ref: fd5770b359bcfb359401c15b1c1bb40381352008
parent: 9723e7e7ae5aba39c444c8aaa10f0a0710a3a0c2
author: David Turner <[email protected]>
date: Mon Aug 19 02:06:44 EDT 2002
- removal of compiler warnings - slight improvements to the Postscript hinter
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2002-08-20 David Turner <[email protected]>
+
+ * 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 <[email protected]>
* builds/unix/install.mk (install, uninstall): Add $(DESTDIR) to
--- 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_
--- 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
--- 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
--- a/src/pshinter/pshalgo3.c
+++ b/src/pshinter/pshalgo3.c
@@ -27,9 +27,9 @@
#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
@@ -36,6 +36,7 @@
#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,40 +664,108 @@
/*************************************************************************/
/*************************************************************************/
- 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 );
- /* 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;
+ 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:
+ ;
+ }
+
+ /* 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 );
+ point = &glyph->points[n];
+ if ( psh3_point_is_extremum( point ) )
+ {
+ PSH3_Point before = point;
+ PSH3_Point after = point;
-#ifdef DEBUG_HINTER
+ do
+ {
+ before = before->prev;
+ if ( before == point )
+ goto Skip;
+ }
+ while ( before->org_v == point->org_v );
- if ( dimension == 0 )
+ do
+ {
+ after = after->next;
+ if ( after == point )
+ goto Skip;
+ }
+ while ( after->org_v == point->org_v );
+ }
+
+ if ( before->org_v < point->org_v &&
+ after->org_v > point->org_v )
{
- point->cur_x = point->cur_u;
- point->flags_x = point->flags;
+ psh3_point_set_positive( point );
}
- else
+ else if ( before->org_v > point->org_v &&
+ after->org_v < point->org_v )
{
- point->cur_y = point->cur_u;
- point->flags_y = point->flags;
+ psh3_point_set_negative( point );
}
-
-#endif
-
- 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;
+ }
}
-
- d -= hint->org_len;
- if ( ABS( d ) < PSH3_STRONG_THRESHOLD )
- goto Is_Strong;
+ 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 ( point->org_u >= hint->org_pos &&
- point->org_u <= hint->org_pos + hint->org_len &&
- psh3_point_is_extremum( point ) )
+ if ( major_dir == PSH3_DIR_HORIZONTAL )
{
- /* attach to hint, but don't mark as strong */
- point->hint = hint;
- break;
+ min_flag = PSH3_POINT_POSITIVE;
+ max_flag = PSH3_POINT_NEGATIVE;
}
+ else
+ {
+ min_flag = PSH3_POINT_NEGATIVE;
+ max_flag = PSH3_POINT_POSITIVE;
+ }
-#endif
+ 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;
+ }
+
+ if ( point->org_u >= hint->org_pos &&
+ point->org_u <= hint->org_pos + hint->org_len )
+ {
+ point->hint = hint;
+ }
+ }
}
+#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;
+ 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;
- delta = point->org_u - hint->org_pos;
+ if ( delta <= 0 )
+ point->cur_u = hint->cur_pos + FT_MulFix( delta, scale );
- 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 ( 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;
-
+ 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],
--- 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 @@
#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 @@
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,21 +99,66 @@
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_
{
PSH3_Point prev;
@@ -118,6 +165,7 @@
PSH3_Point next;
PSH3_Contour contour;
FT_UInt flags;
+ FT_UInt flags2;
FT_Char dir_in;
FT_Char dir_out;
FT_Angle angle_in;
@@ -124,6 +172,7 @@
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 @@
} 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_EQUAL_ORG(a,b) ( (a)->org_u == (b)->org_u && \
+ (a)->org_v == (b)->org_v )
-#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_ANGLE(a,b) FT_Atan2( (b)->org_u - (a)->org_u, \
+ (b)->org_v - (a)->org_v )
typedef struct PSH3_ContourRec_
{
--- 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
--- 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
--- a/tests/Jamfile
+++ b/tests/Jamfile
@@ -7,28 +7,35 @@
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) ;
}
}
--- 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,8 +611,157 @@
}
}
+ /************************************************************************/
+ /************************************************************************/
+ /***** *****/
+ /***** 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 )
{
if ( ps_debug_hints )
@@ -742,7 +892,7 @@
if ( option_show_edges )
{
- /* draw verticla edges */
+ /* draw vertical edges */
if ( option_show_vert_hints )
{
count = glyph->num_vedges;
@@ -956,12 +1106,11 @@
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 @@
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 @@
draw_ps_blue_zones();
draw_glyph( glyph_index );
- ps2_draw_control_points();
+ ps3_draw_control_points();
nvv_surface_refresh( surface, NULL );