Here is a third and I hope final version of the spline flattening
patch, incorporating the latest version of David Bevan's cubic spline
flattening routine.
Notes:
1. As with the previous versions, it solves the bug in flattening
s-shaped curves (cubic with control points on both sides of the chord).
2. I have incorporated David's latest code as is. However, I have
expanded his comments, most importantly (i) by giving the reference to
Hain's paper in full rather than as a tinyurl, so as to make it easier
to find elsewhere if it is moved or if the tinyurl service is
discontinued, and (ii) by incorporating a detailed explanation he
provided of the calculation of L.
3. It may be thought advisable to split the patch into two: one for
cubics, which is essential because it fixes a bug, and one for conics,
which is not essential but gives some speed improvement and simpler
code. I leave that up to Werner.
Graham
diff --git a/C:\\DOCUME~1\\Graham\\LOCALS~1\\Temp\\ftgrays_c8f5b9.c
b/C:\\DOCUME~1\\Graham\\LOCALS~1\\Temp\\ftgrays_f4f03b.c
index 0b94143..a3a7a31 100644
--- a/C:\\DOCUME~1\\Graham\\LOCALS~1\\Temp\\ftgrays_c8f5b9.c
+++ b/C:\\DOCUME~1\\Graham\\LOCALS~1\\Temp\\ftgrays_f4f03b.c
@@ -90,6 +90,9 @@
#undef FT_COMPONENT
#define FT_COMPONENT trace_smooth
+/* The maximum distance of a curve from the chord, in 64ths of a pixel; */
+/* used when flattening curves. */
+#define FT_MAX_CURVE_DEVIATION 16
#ifdef _STANDALONE_
@@ -354,8 +357,6 @@ typedef ptrdiff_t FT_PtrDist;
int band_size;
int band_shoot;
-int conic_level;
-int cubic_level;
ft_jmp_buf jump_buffer;
@@ -888,31 +889,18 @@ typedef ptrdiff_t FT_PtrDist;
if ( dx dy )
dx = dy;
-level = 1;
-dx = dx / ras.conic_level;
-while ( dx 0 )
+if ( dx = FT_MAX_CURVE_DEVIATION )
{
- dx = 2;
- level++;
+ gray_render_line( RAS_VAR_ UPSCALE( to-x ), UPSCALE( to-y ) );
+ return;
}
-/* a shortcut to speed things up */
-if ( level = 1 )
+level = 1;
+dx /= FT_MAX_CURVE_DEVIATION;
+while ( dx 1 )
{
- /* we compute the mid-point directly in order to avoid */
- /* calling gray_split_conic() */
- TPos to_x, to_y, mid_x, mid_y;
-
-
- to_x = UPSCALE( to-x );
- to_y = UPSCALE( to-y );
- mid_x = ( ras.x + to_x + 2 * UPSCALE( control-x ) ) / 4;
- mid_y = ( ras.y + to_y + 2 * UPSCALE( control-y ) ) / 4;
-
- gray_render_line( RAS_VAR_ mid_x, mid_y );
- gray_render_line( RAS_VAR_ to_x, to_y );
-
- return;
+ dx = 2;
+ level++;
}
arc = ras.bez_stack;
@@ -957,21 +945,9 @@ typedef ptrdiff_t FT_PtrDist;
}
Draw:
- {
-TPos to_x, to_y, mid_x, mid_y;
-
-
-to_x = arc[0].x;
-to_y = arc[0].y;
-mid_x = ( ras.x + to_x + 2 * arc[1].x ) / 4;
-mid_y = ( ras.y + to_y + 2 * arc[1].y ) / 4;
-
-gray_render_line( RAS_VAR_ mid_x, mid_y );
-gray_render_line( RAS_VAR_ to_x, to_y );
-
-top--;
-arc -= 2;
- }
+ gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
+ top--;
+ arc -= 2;
}
return;
@@ -1011,55 +987,8 @@ typedef ptrdiff_t FT_PtrDist;
const FT_Vector* control2,
const FT_Vector* to )
{
-int top, level;
-int*levels;
FT_Vector* arc;
-int mid_x = ( DOWNSCALE( ras.x ) + to-x +
- 3 * (control1-x + control2-x ) ) / 8;
-int mid_y = ( DOWNSCALE( ras.y ) + to-y +
- 3 * (control1-y + control2-y ) ) / 8;
-TPosdx = DOWNSCALE( ras.x ) + to-x - ( mid_x 1 );
-TPosdy = DOWNSCALE( ras.y ) + to-y - ( mid_y 1 );
-
-if ( dx 0 )
- dx = -dx;
-if ( dy 0 )
- dy = -dy;
-if ( dx dy )
- dx = dy;
-
-level = 1;
-dx /= ras.cubic_level;
-while ( dx 0 )
-{
- dx = 2;
- level++;
-}
-
-if ( level = 1 )
-{
- TPos to_x, to_y;
-
-
- to_x = UPSCALE( to-x );
- to_y = UPSCALE( to-y );
-
- /* Recalculation of midpoint is needed only if */
- /* UPSCALE and DOWNSCALE have any effect. */
-
-#if ( PIXEL_BITS != 6 )
- mid_x = ( ras.x + to_x +
-3 * UPSCALE( control1-x + control2-x ) ) / 8;
- mid_y = ( ras.y + to_y +
-3 * UPSCALE( control1-y + control2-y ) ) / 8;
-#endif
-
- gray_render_line( RAS_VAR_ mid_x, mid_y );
- gray_render_line( RAS_VAR_ to_x, to_y );
-
- return;
-}
arc = ras.bez_stack;
arc[0].x = UPSCALE( to-x );
@@ -1071,60 +1000,98 @@ typedef ptrdiff_t FT_PtrDist;
arc[3].x = ras.x;
arc[3].y = ras.y;
-levels= ras.lev_stack;
-top = 0;
-levels[0] = level;
-
-while ( top = 0 )
+for (;;)
{
- level = levels[top];
- if ( level 1 )
- {
-