diff --git a/ChangeLog b/ChangeLog index 380a407ed..ad28fcd8c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2002-08-20 David Turner + + * src/pshinter/pshalgo1.c, src/pshinter/pshalog2.c, + src/pshinter/pshglob.c, src/pshinter/pshrec.c, + src/autohint/ahmodule.c: removing compiler warnings with + DEBUG_HINTER defined (only used in development builds anyway) + + * src/pshinter/pshalgo3.h, src/pshinter/pshalgo3.c: removing + compiler warnings, and improving the support of local extrema + and stem edge points + + * test/gview.c: small updates to the hinting debugger + * Jamfile: small updates + 2002-08-18 Arkadiusz Miskiewicz * builds/unix/install.mk (install, uninstall): Add $(DESTDIR) to diff --git a/src/autohint/ahmodule.c b/src/autohint/ahmodule.c index 5da456b1c..8c148af36 100644 --- a/src/autohint/ahmodule.c +++ b/src/autohint/ahmodule.c @@ -25,9 +25,9 @@ #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; + AH_Hinter* ah_debug_hinter = NULL; + FT_Bool ah_debug_disable_horz = 0; + FT_Bool ah_debug_disable_vert = 0; #endif typedef struct FT_AutoHinterRec_ diff --git a/src/pshinter/pshalgo1.c b/src/pshinter/pshalgo1.c index bc73baf46..7f4d7e8ad 100644 --- a/src/pshinter/pshalgo1.c +++ b/src/pshinter/pshalgo1.c @@ -25,8 +25,8 @@ #define FT_COMPONENT trace_pshalgo1 #ifdef DEBUG_HINTER - extern PSH1_Hint_Table ps1_debug_hint_table = 0; - extern PSH1_HintFunc ps1_debug_hint_func = 0; + PSH1_Hint_Table ps1_debug_hint_table = 0; + PSH1_HintFunc ps1_debug_hint_func = 0; #endif diff --git a/src/pshinter/pshalgo2.c b/src/pshinter/pshalgo2.c index d42658932..8de30a4d6 100644 --- a/src/pshinter/pshalgo2.c +++ b/src/pshinter/pshalgo2.c @@ -25,9 +25,9 @@ #define FT_COMPONENT trace_pshalgo2 #ifdef DEBUG_HINTER - extern PSH2_Hint_Table ps2_debug_hint_table = 0; - extern PSH2_HintFunc ps2_debug_hint_func = 0; - extern PSH2_Glyph ps2_debug_glyph = 0; + PSH2_Hint_Table ps2_debug_hint_table = 0; + PSH2_HintFunc ps2_debug_hint_func = 0; + PSH2_Glyph ps2_debug_glyph = 0; #endif diff --git a/src/pshinter/pshalgo3.c b/src/pshinter/pshalgo3.c index 3eb081f1a..ccf5bc2d0 100644 --- a/src/pshinter/pshalgo3.c +++ b/src/pshinter/pshalgo3.c @@ -27,15 +27,16 @@ #ifdef DEBUG_HINTER - extern PSH3_Hint_Table ps3_debug_hint_table = 0; - extern PSH3_HintFunc ps3_debug_hint_func = 0; - extern PSH3_Glyph ps3_debug_glyph = 0; + PSH3_Hint_Table ps3_debug_hint_table = 0; + PSH3_HintFunc ps3_debug_hint_func = 0; + PSH3_Glyph ps3_debug_glyph = 0; #endif #undef SNAP_STEMS #undef ONLY_ALIGN_Y +#define COMPUTE_INFLEXS /*************************************************************************/ /*************************************************************************/ @@ -51,7 +52,7 @@ PSH3_Hint hint2 ) { return ( hint1->org_pos + hint1->org_len >= hint2->org_pos && - hint2->org_pos + hint2->org_len >= hint1->org_pos ); + hint2->org_pos + hint2->org_len >= hint1->org_pos ); } @@ -427,7 +428,7 @@ hint->cur_len = fit_len; /* check blue zones for horizontal stems */ - align.align = PSH_BLUE_ALIGN_NONE; + align.align = PSH_BLUE_ALIGN_NONE; align.align_bot = align.align_top = 0; if ( dimension == 1 ) @@ -469,9 +470,9 @@ if ( !psh3_hint_is_fitted( parent ) ) psh3_hint_align( parent, globals, dimension, hint_flags ); - par_org_center = parent->org_pos + ( parent->org_len / 2 ); - par_cur_center = parent->cur_pos + ( parent->cur_len / 2 ); - cur_org_center = hint->org_pos + ( hint->org_len / 2 ); + par_org_center = parent->org_pos + ( parent->org_len >> 1 ); + par_cur_center = parent->cur_pos + ( parent->cur_len >> 1 ); + cur_org_center = hint->org_pos + ( hint->org_len >> 1 ); cur_delta = FT_MulFix( cur_org_center - par_org_center, scale ); pos = par_cur_center + cur_delta - ( len >> 1 ); @@ -480,7 +481,7 @@ if ( ( hint_flags & FT_HINT_NO_INTEGER_STEM ) == 0 ) { /* normal processing */ - if ( ( fit_len / 64 ) & 1 ) + if ( fit_len & 64 ) { /* odd number of pixels */ fit_center = ( ( pos + ( len >> 1 ) ) & -64 ) + 32; @@ -663,39 +664,107 @@ /*************************************************************************/ /*************************************************************************/ - static int - psh3_point_is_extremum( PSH3_Point point ) +#ifdef COMPUTE_INFLEXS + /* compute all inflex points in a given glyph */ + static void + psh3_glyph_compute_inflections( PSH3_Glyph glyph ) { - PSH3_Point before = point; - PSH3_Point after = point; - FT_Pos d_before; - FT_Pos d_after; + FT_UInt n; - - do + for ( n = 0; n < glyph->num_contours; n++ ) { - before = before->prev; - if ( before == point ) - return 0; + PSH3_Point first, start, end, before, after; + FT_Angle angle_in, angle_seg, angle_out; + FT_Angle diff_in, diff_out; + FT_Int finished = 0; - d_before = before->org_u - point->org_u; + /* we need at least 4 points to create an inflection point */ + if ( glyph->contours[n].count < 4 ) + continue; - } while ( d_before == 0 ); + /* compute first segment in contour */ + first = glyph->contours[n].start; - do - { - after = after->next; - if ( after == point ) - return 0; + start = end = first; + do + { + end = end->next; + if ( end == first ) + goto Skip; + } + while ( PSH3_POINT_EQUAL_ORG( end, first ) ); - d_after = after->org_u - point->org_u; + angle_seg = PSH3_POINT_ANGLE( start, end ); - } while ( d_after == 0 ); + /* extend the segment start whenever possible */ + before = start; + do + { + do + { + start = before; + before = before->prev; + if ( before == first ) + goto Skip; + } + while ( PSH3_POINT_EQUAL_ORG( before, start ) ); - return ( ( d_before > 0 && d_after > 0 ) || - ( d_before < 0 && d_after < 0 ) ); + angle_in = PSH3_POINT_ANGLE( before, start ); + } + while ( angle_in == angle_seg ); + + first = start; + diff_in = FT_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 ( PSH3_POINT_EQUAL_ORG( end, after ) ); + + angle_out = PSH3_POINT_ANGLE( end, after ); + } + while ( angle_out == angle_seg ); + + diff_out = FT_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 + { + psh3_point_set_inflex( start ); + start = start->next; + } + while ( start != end ); + + psh3_point_set_inflex( start ); + } + + start = end; + end = after; + angle_seg = angle_out; + diff_in = diff_out; + } + while ( !finished ); + + Skip: + ; + } } - +#endif /* COMPUTE_INFLEXS */ static void psh3_glyph_done( PSH3_Glyph glyph ) @@ -742,6 +811,81 @@ } + /* load outline point coordinates into hinter glyph */ + static void + psh3_glyph_load_points( PSH3_Glyph glyph, + FT_Int dimension ) + { + FT_Vector* vec = glyph->outline->points; + PSH3_Point point = glyph->points; + FT_UInt count = glyph->num_points; + + + for ( ; count > 0; count--, point++, vec++ ) + { + point->flags2 = 0; + point->hint = NULL; + if ( dimension == 0 ) + { + point->org_u = vec->x; + point->org_v = vec->y; + } + else + { + point->org_u = vec->y; + point->org_v = vec->x; + } + +#ifdef DEBUG_HINTER + point->org_x = vec->x; + point->org_y = vec->y; +#endif + + } + } + + + /* save hinted point coordinates back to outline */ + static void + psh3_glyph_save_points( PSH3_Glyph glyph, + FT_Int dimension ) + { + FT_UInt n; + PSH3_Point point = glyph->points; + FT_Vector* vec = glyph->outline->points; + char* tags = glyph->outline->tags; + + + for ( n = 0; n < glyph->num_points; n++ ) + { + if ( dimension == 0 ) + vec[n].x = point->cur_u; + else + vec[n].y = point->cur_u; + + if ( psh3_point_is_strong( point ) ) + tags[n] |= (char)( ( dimension == 0 ) ? 32 : 64 ); + +#ifdef DEBUG_HINTER + + if ( dimension == 0 ) + { + point->cur_x = point->cur_u; + point->flags_x = point->flags2 | point->flags; + } + else + { + point->cur_y = point->cur_u; + point->flags_y = point->flags2 | point->flags; + } + +#endif + + point++; + } + } + + static FT_Error psh3_glyph_init( PSH3_Glyph glyph, FT_Outline* outline, @@ -866,6 +1010,11 @@ glyph->outline = outline; glyph->globals = globals; +#ifdef COMPUTE_INFLEXS + psh3_glyph_load_points( glyph, 0 ); + psh3_glyph_compute_inflections( glyph ); +#endif /* COMPUTE_INFLEXS */ + /* now deal with hints tables */ error = psh3_hint_table_init( &glyph->hint_tables [0], &ps_hints->dimension[0].hints, @@ -888,78 +1037,133 @@ } - /* load outline point coordinates into hinter glyph */ + + + /* compute all extrema in a glyph for a given dimension */ static void - psh3_glyph_load_points( PSH3_Glyph glyph, - FT_Int dimension ) + psh3_glyph_compute_extrema( PSH3_Glyph glyph ) { - FT_Vector* vec = glyph->outline->points; - PSH3_Point point = glyph->points; - FT_UInt count = glyph->num_points; + FT_UInt first = 0, next, n; + PSH3_Point points = glyph->points; + PSH3_Contour contour = glyph->contours; - - for ( ; count > 0; count--, point++, vec++ ) + /* first of all, compute all local extrema */ + for ( n = 0; n < glyph->num_contours; n++ ) { - point->flags &= PSH3_POINT_OFF | PSH3_POINT_SMOOTH; - point->hint = 0; - if ( dimension == 0 ) - point->org_u = vec->x; - else - point->org_u = vec->y; + PSH3_Point first = glyph->contours[n].start; + PSH3_Point point, before, after; -#ifdef DEBUG_HINTER - point->org_x = vec->x; - point->org_y = vec->y; -#endif + point = first; + before = point; + after = point; + do + { + before = before->prev; + if ( before == first ) + goto Skip; + + } while ( before->org_u == point->org_u ); + + first = point = before->next; + + for (;;) + { + after = point; + do + { + after = after->next; + if ( after == first ) + goto Next; + } + while ( after->org_u == point->org_u ); + + if ( before->org_u < point->org_u ) + { + if ( after->org_u < point->org_u ) + { + /* local maximum */ + goto Extremum; + } + } + else /* before->org_u > point->org_u */ + { + if ( after->org_u > point->org_u ) + { + /* local minimum */ + Extremum: + do + { + psh3_point_set_extremum( point ); + point = point->next; + } + while ( point != after ); + } + } + + before = after->prev; + point = after; + + } /* for */ + + Next: + ; } - } - - - /* save hinted point coordinates back to outline */ - static void - psh3_glyph_save_points( PSH3_Glyph glyph, - FT_Int dimension ) - { - FT_UInt n; - PSH3_Point point = glyph->points; - FT_Vector* vec = glyph->outline->points; - char* tags = glyph->outline->tags; - + /* for each extrema, determine its direction along the */ + /* orthogonal axis */ for ( n = 0; n < glyph->num_points; n++ ) { - if ( dimension == 0 ) - vec[n].x = point->cur_u; - else - vec[n].y = point->cur_u; + PSH3_Point point, before, after; - if ( psh3_point_is_strong( point ) ) - tags[n] |= (char)( ( dimension == 0 ) ? 32 : 64 ); - -#ifdef DEBUG_HINTER - - if ( dimension == 0 ) + point = &glyph->points[n]; + if ( psh3_point_is_extremum( point ) ) { - point->cur_x = point->cur_u; - point->flags_x = point->flags; - } - else - { - point->cur_y = point->cur_u; - point->flags_y = point->flags; + PSH3_Point before = point; + PSH3_Point after = point; + + do + { + before = before->prev; + if ( before == point ) + goto Skip; + } + while ( before->org_v == point->org_v ); + + do + { + after = after->next; + if ( after == point ) + goto Skip; + } + while ( after->org_v == point->org_v ); } -#endif - - point++; + if ( before->org_v < point->org_v && + after->org_v > point->org_v ) + { + psh3_point_set_positive( point ); + } + else if ( before->org_v > point->org_v && + after->org_v < point->org_v ) + { + psh3_point_set_negative( point ); + } + Skip: + ; } } -#define PSH3_STRONG_THRESHOLD 10 +#define PSH3_STRONG_THRESHOLD 30 + + + /* major_dir is the direction for points on the bottom/left of the stem; + * Points on the top/right of the stem will have a direction of + * -major_dir. + */ static void psh3_hint_table_find_strong_point( PSH3_Hint_Table table, PSH3_Point point, @@ -967,47 +1171,97 @@ { PSH3_Hint* sort = table->sort; FT_UInt num_hints = table->num_hints; + FT_Int point_dir = 0; + FT_UInt flag; + if ( PSH3_DIR_COMPARE( point->dir_in, major_dir ) ) + point_dir = point->dir_in; - for ( ; num_hints > 0; num_hints--, sort++ ) + else if ( PSH3_DIR_COMPARE( point->dir_out, major_dir ) ) + point_dir = point->dir_out; + + if ( point_dir ) { - PSH3_Hint hint = sort[0]; + FT_UInt flag; - - if ( ABS( point->dir_in ) == major_dir || - ABS( point->dir_out ) == major_dir ) + for ( ; num_hints > 0; num_hints--, sort++ ) { - FT_Pos d; + PSH3_Hint hint = sort[0]; + FT_Pos d; - - d = point->org_u - hint->org_pos; - if ( ABS( d ) < PSH3_STRONG_THRESHOLD ) + if ( point_dir == major_dir ) { - Is_Strong: - psh3_point_set_strong( point ); - point->hint = hint; - break; + flag = PSH3_POINT_EDGE_MIN; + d = point->org_u - hint->org_pos; + if ( ABS( d ) < PSH3_STRONG_THRESHOLD ) + { + Is_Strong: + psh3_point_set_strong( point ); + point->flags2 |= flag; + point->hint = hint; + break; + } + } + else if ( point_dir == -major_dir ) + { + flag = PSH3_POINT_EDGE_MAX; + d = point->org_u - hint->org_pos - hint->org_len; + if ( ABS( d ) < PSH3_STRONG_THRESHOLD ) + goto Is_Strong; + } + } + } +#if 1 + else if ( psh3_point_is_extremum( point ) ) + { + /* treat extrema as special cases for stem edge alignment */ + FT_UInt min_flag, max_flag; + + if ( major_dir == PSH3_DIR_HORIZONTAL ) + { + min_flag = PSH3_POINT_POSITIVE; + max_flag = PSH3_POINT_NEGATIVE; + } + else + { + min_flag = PSH3_POINT_NEGATIVE; + max_flag = PSH3_POINT_POSITIVE; + } + + for ( ; num_hints > 0; num_hints--, sort++ ) + { + PSH3_Hint hint = sort[0]; + FT_Pos d, flag; + + if ( point->flags2 & min_flag ) + { + flag = PSH3_POINT_EDGE_MIN; + d = point->org_u - hint->org_pos; + if ( ABS( d ) < PSH3_STRONG_THRESHOLD ) + { + Is_Strong2: + point->flags2 |= flag; + point->hint = hint; + psh3_point_set_strong( point ); + break; + } + } + else if ( point->flags2 & max_flag ) + { + flag = PSH3_POINT_EDGE_MAX; + d = point->org_u - hint->org_pos - hint->org_len; + if ( ABS( d ) < PSH3_STRONG_THRESHOLD ) + goto Is_Strong2; } - d -= hint->org_len; - if ( ABS( d ) < PSH3_STRONG_THRESHOLD ) - goto Is_Strong; + if ( point->org_u >= hint->org_pos && + point->org_u <= hint->org_pos + hint->org_len ) + { + point->hint = hint; + } } - -#if 1 - - if ( point->org_u >= hint->org_pos && - point->org_u <= hint->org_pos + hint->org_len && - psh3_point_is_extremum( point ) ) - { - /* attach to hint, but don't mark as strong */ - point->hint = hint; - break; - } - -#endif - } +#endif } @@ -1023,8 +1277,8 @@ PS_Mask mask = table->hint_masks->masks; FT_UInt num_masks = table->hint_masks->num_masks; FT_UInt first = 0; - FT_Int major_dir = dimension == 0 ? PSH3_DIR_UP - : PSH3_DIR_RIGHT; + FT_Int major_dir = dimension == 0 ? PSH3_DIR_VERTICAL + : PSH3_DIR_HORIZONTAL; /* process secondary hints to "selected" points */ @@ -1107,22 +1361,31 @@ { FT_Pos delta; - - delta = point->org_u - hint->org_pos; - - if ( delta <= 0 ) - point->cur_u = hint->cur_pos + FT_MulFix( delta, scale ); - - else if ( delta >= hint->org_len ) - point->cur_u = hint->cur_pos + hint->cur_len + - FT_MulFix( delta - hint->org_len, scale ); - - else if ( hint->org_len > 0 ) - point->cur_u = hint->cur_pos + - FT_MulDiv( delta, hint->cur_len, hint->org_len ); - else + if ( psh3_point_is_edge_min( point ) ) + { point->cur_u = hint->cur_pos; + } + else if ( psh3_point_is_edge_max( point ) ) + { + point->cur_u = hint->cur_pos + hint->cur_len; + } + else + { + delta = point->org_u - hint->org_pos; + if ( delta <= 0 ) + point->cur_u = hint->cur_pos + FT_MulFix( delta, scale ); + + else if ( delta >= hint->org_len ) + point->cur_u = hint->cur_pos + hint->cur_len + + FT_MulFix( delta - hint->org_len, scale ); + + else if ( hint->org_len > 0 ) + point->cur_u = hint->cur_pos + + FT_MulDiv( delta, hint->cur_len, hint->org_len ); + else + point->cur_u = hint->cur_pos; + } psh3_point_set_fitted( point ); } } @@ -1435,6 +1698,9 @@ { /* load outline coordinates into glyph */ psh3_glyph_load_points( glyph, dimension ); + + /* compute local extrema */ + psh3_glyph_compute_extrema( glyph ); /* compute aligned stem/hints positions */ psh3_hint_table_align_hints( &glyph->hint_tables[dimension], diff --git a/src/pshinter/pshalgo3.h b/src/pshinter/pshalgo3.h index 913e29822..f5479ff94 100644 --- a/src/pshinter/pshalgo3.h +++ b/src/pshinter/pshalgo3.h @@ -28,8 +28,10 @@ FT_BEGIN_HEADER + /* handle to Hint structure */ typedef struct PSH3_HintRec_* PSH3_Hint; - + + /* hint bit-flags */ typedef enum { PSH3_HINT_GHOST = PS_HINT_FLAG_GHOST, @@ -48,7 +50,7 @@ FT_BEGIN_HEADER #define psh3_hint_deactivate( x ) (x)->flags &= ~PSH3_HINT_ACTIVE #define psh3_hint_set_fitted( x ) (x)->flags |= PSH3_HINT_FITTED - + /* hint structure */ typedef struct PSH3_HintRec_ { FT_Int org_pos; @@ -83,7 +85,7 @@ FT_BEGIN_HEADER PSH3_Hint* sort; PSH3_Hint* sort_global; FT_UInt num_zones; - PSH3_Zone zones; + PSH3_ZoneRec* zones; PSH3_Zone zone; PS_Mask_Table hint_masks; PS_Mask_Table counter_masks; @@ -97,20 +99,65 @@ FT_BEGIN_HEADER enum { PSH3_DIR_NONE = 4, - PSH3_DIR_UP = 1, - PSH3_DIR_DOWN = -1, + PSH3_DIR_UP = -1, + PSH3_DIR_DOWN = 1, PSH3_DIR_LEFT = -2, PSH3_DIR_RIGHT = 2 }; +#define PSH3_DIR_HORIZONTAL 2 +#define PSH3_DIR_VERTICAL 1 + +#define PSH3_DIR_COMPARE(d1,d2) ( (d1) == (d2) || (d1) == -(d2) ) +#define PSH3_DIR_IS_HORIZONTAL(d) PSH3_DIR_COMPARE(d,PSH3_DIR_HORIZONTAL) +#define PSH3_DIR_IS_VERTICAL(d) PSH3_DIR_COMPARE(d,PSH3_DIR_VERTICAL) + + + /* the following bit-flags are computed once by the glyph */ + /* analyzer, for both dimensions */ enum { - PSH3_POINT_OFF = 1, /* point is off the curve */ - PSH3_POINT_STRONG = 2, /* point is strong */ - PSH3_POINT_SMOOTH = 4, /* point is smooth */ - PSH3_POINT_FITTED = 8 /* point is already fitted */ + PSH3_POINT_OFF = 1, /* point is off the curve */ + PSH3_POINT_SMOOTH = 2, /* point is smooth */ + PSH3_POINT_INFLEX = 4 /* point is inflection */ }; +#define psh3_point_is_smooth( p ) ( (p)->flags & PSH3_POINT_SMOOTH ) +#define psh3_point_is_off( p ) ( (p)->flags & PSH3_POINT_OFF ) +#define psh3_point_is_inflection( p ) ( (p)->flags & PSH3_POINT_INFLEX ) + +#define psh3_point_set_smooth( p ) (p)->flags |= PSH3_POINT_SMOOTH +#define psh3_point_set_off( p ) (p)->flags |= PSH3_POINT_OFF +#define psh3_point_set_inflex( p ) (p)->flags |= PSH3_POINT_INFLEX + + /* the following bit-flags are re-computed for each dimension */ + enum + { + PSH3_POINT_STRONG = 16, /* point is strong */ + PSH3_POINT_FITTED = 32, /* point is already fitted */ + PSH3_POINT_EXTREMUM = 64, /* point is local extremum */ + PSH3_POINT_POSITIVE = 128, /* extremum has positive contour flow */ + PSH3_POINT_NEGATIVE = 256, /* extremum has negative contour flow */ + PSH3_POINT_EDGE_MIN = 512, /* point is aligned to left/bottom stem edge */ + PSH3_POINT_EDGE_MAX = 1024 /* point is aligned to top/right stem edge */ + }; + +#define psh3_point_is_strong( p ) ( (p)->flags2 & PSH3_POINT_STRONG ) +#define psh3_point_is_fitted( p ) ( (p)->flags2 & PSH3_POINT_FITTED ) +#define psh3_point_is_extremum( p ) ( (p)->flags2 & PSH3_POINT_EXTREMUM ) +#define psh3_point_is_positive( p ) ( (p)->flags2 & PSH3_POINT_POSITIVE ) +#define psh3_point_is_negative( p ) ( (p)->flags2 & PSH3_POINT_NEGATIVE ) +#define psh3_point_is_edge_min( p ) ( (p)->flags2 & PSH3_POINT_EDGE_MIN ) +#define psh3_point_is_edge_max( p ) ( (p)->flags2 & PSH3_POINT_EDGE_MAX ) + +#define psh3_point_set_strong( p ) (p)->flags2 |= PSH3_POINT_STRONG +#define psh3_point_set_fitted( p ) (p)->flags2 |= PSH3_POINT_FITTED +#define psh3_point_set_extremum( p ) (p)->flags2 |= PSH3_POINT_EXTREMUM +#define psh3_point_set_positive( p ) (p)->flags2 |= PSH3_POINT_POSITIVE +#define psh3_point_set_negative( p ) (p)->flags2 |= PSH3_POINT_NEGATIVE +#define psh3_point_set_edge_min( p ) (p)->flags2 |= PSH3_POINT_EDGE_MIN +#define psh3_point_set_edge_max( p ) (p)->flags2 |= PSH3_POINT_EDGE_MAX + typedef struct PSH3_PointRec_ { @@ -118,12 +165,14 @@ FT_BEGIN_HEADER PSH3_Point next; PSH3_Contour contour; FT_UInt flags; + FT_UInt flags2; FT_Char dir_in; FT_Char dir_out; FT_Angle angle_in; FT_Angle angle_out; PSH3_Hint hint; FT_Pos org_u; + FT_Pos org_v; FT_Pos cur_u; #ifdef DEBUG_HINTER FT_Pos org_x; @@ -137,14 +186,11 @@ FT_BEGIN_HEADER } PSH3_PointRec; -#define psh3_point_is_strong( p ) ( (p)->flags & PSH3_POINT_STRONG ) -#define psh3_point_is_fitted( p ) ( (p)->flags & PSH3_POINT_FITTED ) -#define psh3_point_is_smooth( p ) ( (p)->flags & PSH3_POINT_SMOOTH ) - -#define psh3_point_set_strong( p ) (p)->flags |= PSH3_POINT_STRONG -#define psh3_point_set_fitted( p ) (p)->flags |= PSH3_POINT_FITTED -#define psh3_point_set_smooth( p ) (p)->flags |= PSH3_POINT_SMOOTH +#define PSH3_POINT_EQUAL_ORG(a,b) ( (a)->org_u == (b)->org_u && \ + (a)->org_v == (b)->org_v ) +#define PSH3_POINT_ANGLE(a,b) FT_Atan2( (b)->org_u - (a)->org_u, \ + (b)->org_v - (a)->org_v ) typedef struct PSH3_ContourRec_ { diff --git a/src/pshinter/pshglob.c b/src/pshinter/pshglob.c index e5464e4aa..e5ead5451 100644 --- a/src/pshinter/pshglob.c +++ b/src/pshinter/pshglob.c @@ -23,7 +23,7 @@ #include "pshglob.h" #ifdef DEBUG_HINTER - extern PSH_Globals ps_debug_globals = 0; + PSH_Globals ps_debug_globals = 0; #endif diff --git a/src/pshinter/pshrec.c b/src/pshinter/pshrec.c index 93a34e10e..21ced1e29 100644 --- a/src/pshinter/pshrec.c +++ b/src/pshinter/pshrec.c @@ -27,9 +27,9 @@ #define FT_COMPONENT trace_pshrec #ifdef DEBUG_HINTER - extern PS_Hints ps_debug_hints = 0; - extern int ps_debug_no_horz_hints = 0; - extern int ps_debug_no_vert_hints = 0; + PS_Hints ps_debug_hints = 0; + int ps_debug_no_horz_hints = 0; + int ps_debug_no_vert_hints = 0; #endif diff --git a/tests/Jamfile b/tests/Jamfile index 2635cbdac..0470922de 100644 --- a/tests/Jamfile +++ b/tests/Jamfile @@ -7,28 +7,35 @@ test_programs = gview ; SubDirHdrs [ FT2_SubDir .. nirvana include ] ; -NV_TOP = [ FT2_SubDir .. .. nirvana ] ; +NV_TOP = [ FT2_SubDir .. .. nirvana ] ; -NIRVANA_LINKLIBS = $(NV_TOP)\\objs\\nirvana$(SUFLIB) ; +NIRVANA_LINKLIBS = $(NV_TOP)/objs/libnirvana$(SUFLIB) ; { local t ; - + for t in $(test_programs) { Main $(t) : $(t).c ; - + LinkLibraries $(t) : $(FT2_LIB) ; - - if $(TOOLSET) = MINGW + + if $(WIN) { - LINKKLIBS on $(t)$(SUFEXE) = "-luser32 -lgdi32" ; + if $(TOOLSET) = MINGW + { + LINKKLIBS on $(t)$(SUFEXE) = "-luser32 -lgdi32" ; + } + else + { + LINKLIBS on $(t)$(SUFEXE) = user32.lib gdi32.lib ; + } } else { - LINKLIBS on $(t)$(SUFEXE) = user32.lib gdi32.lib ; + LINKLIBS on $(t)$(SUFEXE) = -L/usr/X11R6/lib -lX11 -lm ; } - + NEEDLIBS on $(t)$(SUFEXE) += $(NIRVANA_LINKLIBS) ; } } diff --git a/tests/gview.c b/tests/gview.c index dcdf506cf..36d10e407 100644 --- a/tests/gview.c +++ b/tests/gview.c @@ -9,6 +9,7 @@ #include <../src/pshinter/pshrec.h> #include <../src/pshinter/pshalgo1.h> #include <../src/pshinter/pshalgo2.h> +#include <../src/pshinter/pshalgo3.h> #include <../src/autohint/ahtypes.h> @@ -610,6 +611,155 @@ ps2_draw_control_points( void ) } } + /************************************************************************/ + /************************************************************************/ + /***** *****/ + /***** POSTSCRIPT HINTER ALGORITHM 3 ROUTINES *****/ + /***** *****/ + /************************************************************************/ + /************************************************************************/ + +#include <../src/pshinter/pshalgo3.h> + +static void +draw_ps3_hint( PSH3_Hint hint, FT_Bool vertical ) +{ + int x1, x2; + NV_Vector v; + + if ( pshint_vertical != vertical ) + { + if (vertical) + pshint_cpos = 40; + else + pshint_cpos = 10; + + pshint_vertical = vertical; + } + + if (!vertical) + { + if ( !option_show_vert_hints ) + return; + + v.x = hint->cur_pos; + v.y = 0; + nv_vector_transform( &v, &size_transform ); + x1 = (int)(v.x + 0.5); + + v.x = hint->cur_pos + hint->cur_len; + v.y = 0; + nv_vector_transform( &v, &size_transform ); + x2 = (int)(v.x + 0.5); + + nv_pixmap_fill_rect( target, x1, 0, 1, target->height, + psh3_hint_is_ghost(hint) + ? GHOST_HINT_COLOR : STEM_HINT_COLOR ); + + if ( psh3_hint_is_ghost(hint) ) + { + x1 --; + x2 = x1 + 2; + } + else + nv_pixmap_fill_rect( target, x2, 0, 1, target->height, + psh3_hint_is_ghost(hint) + ? GHOST_HINT_COLOR : STEM_HINT_COLOR ); + + nv_pixmap_fill_rect( target, x1, pshint_cpos, x2+1-x1, 1, + STEM_JOIN_COLOR ); + } + else + { + if (!option_show_horz_hints) + return; + + v.y = hint->cur_pos; + v.x = 0; + nv_vector_transform( &v, &size_transform ); + x1 = (int)(v.y + 0.5); + + v.y = hint->cur_pos + hint->cur_len; + v.x = 0; + nv_vector_transform( &v, &size_transform ); + x2 = (int)(v.y + 0.5); + + nv_pixmap_fill_rect( target, 0, x1, target->width, 1, + psh3_hint_is_ghost(hint) + ? GHOST_HINT_COLOR : STEM_HINT_COLOR ); + + if ( psh3_hint_is_ghost(hint) ) + { + x1 --; + x2 = x1 + 2; + } + else + nv_pixmap_fill_rect( target, 0, x2, target->width, 1, + psh3_hint_is_ghost(hint) + ? GHOST_HINT_COLOR : STEM_HINT_COLOR ); + + nv_pixmap_fill_rect( target, pshint_cpos, x2, 1, x1+1-x2, + STEM_JOIN_COLOR ); + } + +#if 0 + printf( "[%7.3f %7.3f] %c\n", hint->cur_pos/64.0, (hint->cur_pos+hint->cur_len)/64.0, vertical ? 'v' : 'h' ); +#endif + + pshint_cpos += 10; +} + + +static void +ps3_draw_control_points( void ) +{ + if ( ps3_debug_glyph ) + { + PSH3_Glyph glyph = ps3_debug_glyph; + PSH3_Point point = glyph->points; + FT_UInt count = glyph->num_points; + NV_Transform transform, *trans = &transform; + NV_Path vert_rect; + NV_Path horz_rect; + NV_Path dot, circle; + + for ( ; count > 0; count--, point++ ) + { + NV_Vector vec; + + vec.x = point->cur_x; + vec.y = point->cur_y; + nv_vector_transform( &vec, &size_transform ); + + nv_transform_set_translate( trans, vec.x, vec.y ); + + if ( option_show_smooth && !psh3_point_is_smooth(point) ) + { + nv_painter_set_color( painter, SMOOTH_COLOR, 256 ); + nv_painter_fill_path( painter, trans, 0, symbol_circle ); + } + + if (option_show_horz_hints) + { + if ( point->flags_y & PSH3_POINT_STRONG ) + { + nv_painter_set_color( painter, STRONG_COLOR, 256 ); + nv_painter_fill_path( painter, trans, 0, symbol_rect_h ); + } + } + + if (option_show_vert_hints) + { + if ( point->flags_x & PSH3_POINT_STRONG ) + { + nv_painter_set_color( painter, STRONG_COLOR, 256 ); + nv_painter_fill_path( painter, trans, 0, symbol_rect_v ); + } + } + } + } +} + static void ps_print_hints( void ) @@ -742,7 +892,7 @@ ah_draw_edges( void ) if ( option_show_edges ) { - /* draw verticla edges */ + /* draw vertical edges */ if ( option_show_vert_hints ) { count = glyph->num_vedges; @@ -956,12 +1106,11 @@ draw_glyph( int glyph_index ) ps1_debug_hint_func = option_show_ps_hints ? draw_ps1_hint : 0; ps2_debug_hint_func = option_show_ps_hints ? draw_ps2_hint : 0; + ps3_debug_hint_func = option_show_ps_hints ? draw_ps3_hint : 0; ah_debug_hinter = NULL; - error = FT_Load_Glyph( face, glyph_index, option_hinting - ? FT_LOAD_NO_BITMAP - : FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING ); + error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_BITMAP ); if (error) Panic( "could not load glyph" ); if ( face->glyph->format != ft_glyph_format_outline ) @@ -1182,6 +1331,9 @@ handle_event( NVV_EventRec* ev ) TOGGLE_OPTION( option_show_blues, "blue zones display" ); case NVV_KEY('h'): + ps_debug_no_horz_hints = option_hinting; + ps_debug_no_vert_hints = option_hinting; + TOGGLE_OPTION( option_hinting, "hinting" ) case NVV_KEY('H'): @@ -1302,7 +1454,7 @@ int main( int argc, char** argv ) draw_ps_blue_zones(); draw_glyph( glyph_index ); - ps2_draw_control_points(); + ps3_draw_control_points(); nvv_surface_refresh( surface, NULL );