From 8e8bb126d126affb36a2cfe9885f0c62711aa547 Mon Sep 17 00:00:00 2001 From: Alexei Podtelezhnikov Date: Fri, 18 Mar 2016 23:21:59 -0400 Subject: [PATCH] [smooth] Minor refactoring and microoptimizations. * src/smooth/ftgrays.c (gray_render_conic, gray_render_cubic): Move band clipping from here. (gray_conic_to, gray_cubic_to): ... to here. (gray_rander_line, gray_render_scanline): Initialize variables closer to their use. --- ChangeLog | 14 +++- src/smooth/ftgrays.c | 175 +++++++++++++++++++------------------------ 2 files changed, 89 insertions(+), 100 deletions(-) diff --git a/ChangeLog b/ChangeLog index b6f165dfc..c31597db2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,10 +1,20 @@ +2016-03-18 Alexei Podtelezhnikov + + [smooth] Minor refactoring and microoptimizations. + + * src/smooth/ftgrays.c (gray_render_conic, gray_render_cubic): Move + band clipping from here. + (gray_conic_to, gray_cubic_to): ... to here. + (gray_rander_line, gray_render_scanline): Initialize variables closer + to their use. + 2016-03-17 Alexei Podtelezhnikov [smooth] Minor refactoring. * src/smooth/ftgrays.c (gray_render_conic, gray_render_cubic): Move - upscaling from here... - (gray_conic_to, gray_cubic_to):... to here. + upscaling from here. + (gray_conic_to, gray_cubic_to): ... to here. 2016-03-15 Werner Lemberg diff --git a/src/smooth/ftgrays.c b/src/smooth/ftgrays.c index c02c00934..4d3f66484 100644 --- a/src/smooth/ftgrays.c +++ b/src/smooth/ftgrays.c @@ -689,12 +689,8 @@ typedef ptrdiff_t FT_PtrDist; int incr; - dx = x2 - x1; - ex1 = TRUNC( x1 ); ex2 = TRUNC( x2 ); - fx1 = (TCoord)( x1 - SUBPIXELS( ex1 ) ); - fx2 = (TCoord)( x2 - SUBPIXELS( ex2 ) ); /* trivial case. Happens often */ if ( y1 == y2 ) @@ -703,6 +699,9 @@ typedef ptrdiff_t FT_PtrDist; return; } + fx1 = (TCoord)( x1 - SUBPIXELS( ex1 ) ); + fx2 = (TCoord)( x2 - SUBPIXELS( ex2 ) ); + /* everything is located in a single cell. That is easy! */ /* */ if ( ex1 == ex2 ) @@ -716,6 +715,7 @@ typedef ptrdiff_t FT_PtrDist; /* ok, we'll have to render a run of adjacent cells on the same */ /* scanline... */ /* */ + dx = x2 - x1; p = ( ONE_PIXEL - fx1 ) * ( y2 - y1 ); first = ONE_PIXEL; incr = 1; @@ -787,17 +787,15 @@ typedef ptrdiff_t FT_PtrDist; ey1 = TRUNC( ras.y ); ey2 = TRUNC( to_y ); /* if (ey2 >= ras.max_ey) ey2 = ras.max_ey-1; */ - fy1 = (TCoord)( ras.y - SUBPIXELS( ey1 ) ); - fy2 = (TCoord)( to_y - SUBPIXELS( ey2 ) ); - - dx = to_x - ras.x; - dy = to_y - ras.y; /* perform vertical clipping */ if ( ( ey1 >= ras.max_ey && ey2 >= ras.max_ey ) || ( ey1 < ras.min_ey && ey2 < ras.min_ey ) ) goto End; + fy1 = (TCoord)( ras.y - SUBPIXELS( ey1 ) ); + fy2 = (TCoord)( to_y - SUBPIXELS( ey2 ) ); + /* everything is on a single scanline */ if ( ey1 == ey2 ) { @@ -805,6 +803,9 @@ typedef ptrdiff_t FT_PtrDist; goto End; } + dx = to_x - ras.x; + dy = to_y - ras.y; + /* vertical line - avoid calling gray_render_scanline */ incr = 1; @@ -918,8 +919,6 @@ typedef ptrdiff_t FT_PtrDist; TCoord ex1, ex2, ey1, ey2; - ex1 = TRUNC( ras.x ); - ex2 = TRUNC( to_x ); ey1 = TRUNC( ras.y ); ey2 = TRUNC( to_y ); @@ -928,12 +927,15 @@ typedef ptrdiff_t FT_PtrDist; ( ey1 < ras.min_ey && ey2 < ras.min_ey ) ) goto End; - dx = to_x - ras.x; - dy = to_y - ras.y; + ex1 = TRUNC( ras.x ); + ex2 = TRUNC( to_x ); fx1 = ras.x - SUBPIXELS( ex1 ); fy1 = ras.y - SUBPIXELS( ey1 ); + dx = to_x - ras.x; + dy = to_y - ras.y; + if ( ex1 == ex2 && ey1 == ey2 ) /* inside one cell */ ; else if ( dy == 0 ) /* ex1 != ex2 */ /* any horizontal line */ @@ -1066,7 +1068,6 @@ typedef ptrdiff_t FT_PtrDist; gray_render_conic( RAS_ARG ) { TPos dx, dy; - TPos min, max, y; int top, level; int* levels = ras.lev_stack; FT_Vector* arc = ras.bez_stack; @@ -1082,20 +1083,6 @@ typedef ptrdiff_t FT_PtrDist; if ( dx < ONE_PIXEL / 4 ) goto Draw; - /* short-cut the arc that crosses the current band */ - min = max = arc[0].y; - - y = arc[1].y; - if ( y < min ) min = y; - if ( y > max ) max = y; - - y = arc[2].y; - if ( y < min ) min = y; - if ( y > max ) max = y; - - if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey ) - goto Draw; - level = 0; do { @@ -1158,33 +1145,11 @@ typedef ptrdiff_t FT_PtrDist; gray_render_cubic( RAS_ARG ) { FT_Vector* arc = ras.bez_stack; - TPos min, max, y; + TPos dx, dy, dx_, dy_; + TPos dx1, dy1, dx2, dy2; + TPos L, s, s_limit; - /* Short-cut the arc that crosses the current band. */ - min = max = arc[0].y; - - y = arc[1].y; - if ( y < min ) - min = y; - if ( y > max ) - max = y; - - y = arc[2].y; - if ( y < min ) - min = y; - if ( y > max ) - max = y; - - y = arc[3].y; - if ( y < min ) - min = y; - if ( y > max ) - max = y; - - if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey ) - goto Draw; - for (;;) { /* Decide whether to split or draw. See `Rapid Termination */ @@ -1192,64 +1157,53 @@ typedef ptrdiff_t FT_PtrDist; /* F. Hain, at */ /* http://www.cis.southalabama.edu/~hain/general/Publications/Bezier/Camera-ready%20CISST02%202.pdf */ - { - TPos dx, dy, dx_, dy_; - TPos dx1, dy1, dx2, dy2; - TPos L, s, s_limit; - + /* dx and dy are x and y components of the P0-P3 chord vector. */ + dx = dx_ = arc[3].x - arc[0].x; + dy = dy_ = arc[3].y - arc[0].y; - /* dx and dy are x and y components of the P0-P3 chord vector. */ - dx = dx_ = arc[3].x - arc[0].x; - dy = dy_ = arc[3].y - arc[0].y; + L = FT_HYPOT( dx_, dy_ ); - L = FT_HYPOT( dx_, dy_ ); + /* Avoid possible arithmetic overflow below by splitting. */ + if ( L > 32767 ) + goto Split; - /* Avoid possible arithmetic overflow below by splitting. */ - if ( L > 32767 ) - goto Split; + /* Max deviation may be as much as (s/L) * 3/4 (if Hain's v = 1). */ + s_limit = L * (TPos)( ONE_PIXEL / 6 ); - /* Max deviation may be as much as (s/L) * 3/4 (if Hain's v = 1). */ - s_limit = L * (TPos)( ONE_PIXEL / 6 ); + /* s is L * the perpendicular distance from P1 to the line P0-P3. */ + dx1 = arc[1].x - arc[0].x; + dy1 = arc[1].y - arc[0].y; + s = FT_ABS( dy * dx1 - dx * dy1 ); - /* s is L * the perpendicular distance from P1 to the line P0-P3. */ - dx1 = arc[1].x - arc[0].x; - dy1 = arc[1].y - arc[0].y; - s = FT_ABS( dy * dx1 - dx * dy1 ); + if ( s > s_limit ) + goto Split; - if ( s > s_limit ) - goto Split; + /* s is L * the perpendicular distance from P2 to the line P0-P3. */ + dx2 = arc[2].x - arc[0].x; + dy2 = arc[2].y - arc[0].y; + s = FT_ABS( dy * dx2 - dx * dy2 ); - /* s is L * the perpendicular distance from P2 to the line P0-P3. */ - dx2 = arc[2].x - arc[0].x; - dy2 = arc[2].y - arc[0].y; - s = FT_ABS( dy * dx2 - dx * dy2 ); + if ( s > s_limit ) + goto Split; - if ( s > s_limit ) - goto Split; - - /* Split super curvy segments where the off points are so far - from the chord that the angles P0-P1-P3 or P0-P2-P3 become - acute as detected by appropriate dot products. */ - if ( dx1 * ( dx1 - dx ) + dy1 * ( dy1 - dy ) > 0 || - dx2 * ( dx2 - dx ) + dy2 * ( dy2 - dy ) > 0 ) - goto Split; - - /* No reason to split. */ - goto Draw; - } - - Split: - gray_split_cubic( arc ); - arc += 3; - continue; + /* Split super curvy segments where the off points are so far + from the chord that the angles P0-P1-P3 or P0-P2-P3 become + acute as detected by appropriate dot products. */ + if ( dx1 * ( dx1 - dx ) + dy1 * ( dy1 - dy ) > 0 || + dx2 * ( dx2 - dx ) + dy2 * ( dy2 - dy ) > 0 ) + goto Split; - Draw: gray_render_line( RAS_VAR_ arc[0].x, arc[0].y ); if ( arc == ras.bez_stack ) return; arc -= 3; + continue; + + Split: + gray_split_cubic( arc ); + arc += 3; } } @@ -1292,6 +1246,8 @@ typedef ptrdiff_t FT_PtrDist; gray_PWorker worker ) { FT_Vector* arc = ras.bez_stack; + TPos min = SUBPIXELS( ras.min_ey ); + TPos max = SUBPIXELS( ras.max_ey ); arc[0].x = UPSCALE( to->x ); @@ -1301,7 +1257,17 @@ typedef ptrdiff_t FT_PtrDist; arc[2].x = ras.x; arc[2].y = ras.y; - gray_render_conic( RAS_VAR ); + /* only render arc inside the current band */ + if ( ( min <= arc[0].y && arc[0].y < max ) || + ( min <= arc[1].y && arc[1].y < max ) || + ( min <= arc[2].y && arc[2].y < max ) ) + gray_render_conic( RAS_VAR ); + else + { + ras.x = arc[0].x; + ras.y = arc[0].y; + } + return 0; } @@ -1313,6 +1279,8 @@ typedef ptrdiff_t FT_PtrDist; gray_PWorker worker ) { FT_Vector* arc = ras.bez_stack; + TPos min = SUBPIXELS( ras.min_ey ); + TPos max = SUBPIXELS( ras.max_ey ); arc[0].x = UPSCALE( to->x ); @@ -1324,7 +1292,18 @@ typedef ptrdiff_t FT_PtrDist; arc[3].x = ras.x; arc[3].y = ras.y; - gray_render_cubic( RAS_VAR ); + /* only render arc inside the current band */ + if ( ( min <= arc[0].y && arc[0].y < max ) || + ( min <= arc[1].y && arc[1].y < max ) || + ( min <= arc[2].y && arc[2].y < max ) || + ( min <= arc[3].y && arc[3].y < max ) ) + gray_render_cubic( RAS_VAR ); + else + { + ras.x = arc[0].x; + ras.y = arc[0].y; + } + return 0; }