summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnuj Verma <anujv@iitbhilai.ac.in>2021-10-16 10:02:30 +0530
committerAnuj Verma <anujv@iitbhilai.ac.in>2021-10-16 10:02:30 +0530
commit31c0a833d670da95733109267d0a2a69a9a27bc4 (patch)
tree5faab7b74213b3a7076089e372476324a8e4cc0d
parent3d3be1dfd160e7fc8b192df1247ce4486c31b898 (diff)
downloadfreetype2-31c0a833d670da95733109267d0a2a69a9a27bc4.tar.gz
[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.
-rw-r--r--src/sdf/ftsdf.c65
1 files changed, 41 insertions, 24 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;
-
- /* 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;
- }
+ 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;
+ }
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;
+ }
}
}