From 31c0a833d670da95733109267d0a2a69a9a27bc4 Mon Sep 17 00:00:00 2001 From: Anuj Verma Date: Sat, 16 Oct 2021 10:02:30 +0530 Subject: [PATCH] [sdf] Fixed corner checks and improved performance. * src/sdf/ftsdf.c (sdf_generate_bounding_box): Always check for corner if two distance (for different curves) are very close. * src/sdf/ftsdf.c (sdf_conic_to): Added check to figure out if the conic can be treated as a line (which happens if the control point coincide with any end-point). Also, replace tabs `\t` with spaces. --- src/sdf/ftsdf.c | 63 +++++++++++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 23 deletions(-) diff --git a/src/sdf/ftsdf.c b/src/sdf/ftsdf.c index 0f9dffecf..8f58a2a0f 100644 --- a/src/sdf/ftsdf.c +++ b/src/sdf/ftsdf.c @@ -738,6 +738,18 @@ contour = shape->contours; + /* If the control point coincide with any of the end point */ + /* then it's a line and should be treated as one to avoid */ + /* unnecessary complexity later in the algorithm. */ + if ( ( contour->last_pos.x == control_1->x && + contour->last_pos.y == control_1->y ) || + ( control_1->x == to->x && + control_1->y == to->y ) ) + { + sdf_line_to( to, user ); + goto Exit; + } + FT_CALL( sdf_edge_new( memory, &edge ) ); edge->edge_type = SDF_EDGE_CONIC; @@ -1160,9 +1172,9 @@ /* we check the deviation of the bezier and stop if it is */ /* lower than a pre-defined `threhold` value. */ if ( FT_ABS( 2 * cpos[0].x - 3 * cpos[1].x + cpos[3].x ) < threshold && - FT_ABS( 2 * cpos[0].y - 3 * cpos[1].y + cpos[3].y ) < threshold && + FT_ABS( 2 * cpos[0].y - 3 * cpos[1].y + cpos[3].y ) < threshold && FT_ABS( cpos[0].x - 3 * cpos[2].x + 2 * cpos[3].x ) < threshold && - FT_ABS( cpos[0].y - 3 * cpos[2].y + 2 * cpos[3].y ) < threshold ) + FT_ABS( cpos[0].y - 3 * cpos[2].y + 2 * cpos[3].y ) < threshold ) { split_cubic( cpos ); goto Append; @@ -1264,29 +1276,29 @@ /* Subdivide the curve and add it to the list. */ { FT_26D6_Vec ctrls[3]; - FT_26D6 dx, dy; - FT_UInt num_splits; + FT_26D6 dx, dy; + FT_UInt num_splits; ctrls[0] = edge->start_pos; ctrls[1] = edge->control_a; ctrls[2] = edge->end_pos; - dx = FT_ABS( ctrls[2].x + ctrls[0].x - 2 * ctrls[1].x ); - dy = FT_ABS( ctrls[2].y + ctrls[0].y - 2 * ctrls[1].y ); + dx = FT_ABS( ctrls[2].x + ctrls[0].x - 2 * ctrls[1].x ); + dy = FT_ABS( ctrls[2].y + ctrls[0].y - 2 * ctrls[1].y ); if ( dx < dy ) - dx = dy; + dx = dy; - /* Here we calculate the number of necessary bisections. Each */ - /* bisection reduces the deviation by exactly 4-fold, hence */ - /* we bisect the bezier until the deviation becomes less than */ - /* 1/8th of a pixel. For more details check `ftgrays.c`. */ - num_splits = 1; - while ( dx > ONE_PIXEL / 8 ) - { - dx >>= 2; - num_splits <<= 1; - } + /* Here we calculate the number of necessary bisections. Each */ + /* bisection reduces the deviation by exactly 4-fold, hence */ + /* we bisect the bezier until the deviation becomes less than */ + /* 1/8th of a pixel. For more details check `ftgrays.c`. */ + num_splits = 1; + while ( dx > ONE_PIXEL / 8 ) + { + dx >>= 2; + num_splits <<= 1; + } error = split_sdf_conic( memory, ctrls, num_splits, &new_edges ); } @@ -3316,6 +3328,7 @@ FT_26D6_Vec grid_point = zero_vector; SDF_Signed_Distance dist = max_sdf; FT_UInt index = 0; + FT_16D16 diff = 0; if ( x < 0 || x >= width ) @@ -3343,7 +3356,7 @@ if ( dist.distance > sp_sq ) continue; - /* square_root the values and fit in a 6.10 fixed-point */ + /* square_root the values if required */ if ( USE_SQUARED_DISTANCES ) dist.distance = square_root( dist.distance ); @@ -3355,11 +3368,15 @@ /* check whether the pixel is set or not */ if ( dists[index].sign == 0 ) dists[index] = dist; - else if ( dists[index].distance > dist.distance ) - dists[index] = dist; - else if ( FT_ABS( dists[index].distance - dist.distance ) - < CORNER_CHECK_EPSILON ) - dists[index] = resolve_corner( dists[index], dist ); + else + { + diff = FT_ABS( dists[index].distance - dist.distance ); + + if ( diff <= CORNER_CHECK_EPSILON ) + dists[index] = resolve_corner( dists[index], dist ); + else if ( dists[index].distance > dist.distance ) + dists[index] = dist; + } } }