spline: Use Skia's tolerance checks
This avoids measuring being too far off (it's still off, but it's less than a percent now.
This commit is contained in:
@@ -25,8 +25,8 @@
|
|||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
/* Same as Cairo, so looks like a good value. ¯\_(ツ)_/¯ */
|
/* Same as Skia, so looks like a good value. ¯\_(ツ)_/¯ */
|
||||||
#define GSK_PATH_TOLERANCE_DEFAULT (0.1)
|
#define GSK_PATH_TOLERANCE_DEFAULT (0.5)
|
||||||
|
|
||||||
gsize gsk_path_get_n_contours (GskPath *path);
|
gsize gsk_path_get_n_contours (GskPath *path);
|
||||||
gboolean gsk_path_foreach_with_tolerance (GskPath *self,
|
gboolean gsk_path_foreach_with_tolerance (GskPath *self,
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ typedef struct
|
|||||||
{
|
{
|
||||||
graphene_point_t last_point;
|
graphene_point_t last_point;
|
||||||
float last_progress;
|
float last_progress;
|
||||||
float tolerance_squared;
|
float tolerance;
|
||||||
GskSplineAddPointFunc func;
|
GskSplineAddPointFunc func;
|
||||||
gpointer user_data;
|
gpointer user_data;
|
||||||
} GskCubicDecomposition;
|
} GskCubicDecomposition;
|
||||||
@@ -103,6 +103,7 @@ gsk_spline_split_cubic (const graphene_point_t pts[4],
|
|||||||
memcpy (result2, (graphene_point_t[4]) { final, bccd, cd, pts[3] }, sizeof (graphene_point_t[4]));
|
memcpy (result2, (graphene_point_t[4]) { final, bccd, cd, pts[3] }, sizeof (graphene_point_t[4]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* Return an upper bound on the error (squared) that could result from
|
/* Return an upper bound on the error (squared) that could result from
|
||||||
* approximating a spline as a line segment connecting the two endpoints. */
|
* approximating a spline as a line segment connecting the two endpoints. */
|
||||||
static float
|
static float
|
||||||
@@ -180,6 +181,25 @@ gsk_spline_error_squared (const graphene_point_t pts[4])
|
|||||||
else
|
else
|
||||||
return cerr;
|
return cerr;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* taken from Skia, including the very descriptive name */
|
||||||
|
static gboolean
|
||||||
|
gsk_spline_cubic_too_curvy (const graphene_point_t pts[4],
|
||||||
|
float tolerance)
|
||||||
|
{
|
||||||
|
graphene_point_t p;
|
||||||
|
|
||||||
|
graphene_point_interpolate (&pts[0], &pts[3], 1.0f / 3, &p);
|
||||||
|
if (ABS (p.x - pts[1].x) + ABS (p.y - pts[1].y) > tolerance)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
graphene_point_interpolate (&pts[0], &pts[3], 2.0f / 3, &p);
|
||||||
|
if (ABS (p.x - pts[2].x) + ABS (p.y - pts[2].y) > tolerance)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gsk_spline_decompose_into (GskCubicDecomposition *decomp,
|
gsk_spline_decompose_into (GskCubicDecomposition *decomp,
|
||||||
@@ -188,7 +208,7 @@ gsk_spline_decompose_into (GskCubicDecomposition *decomp,
|
|||||||
{
|
{
|
||||||
graphene_point_t left[4], right[4];
|
graphene_point_t left[4], right[4];
|
||||||
|
|
||||||
if (gsk_spline_error_squared (pts) < decomp->tolerance_squared)
|
if (!gsk_spline_cubic_too_curvy (pts, decomp->tolerance) || progress < 1 / 1024.f)
|
||||||
{
|
{
|
||||||
gsk_spline_decompose_add_point (decomp, &pts[3], progress);
|
gsk_spline_decompose_add_point (decomp, &pts[3], progress);
|
||||||
return;
|
return;
|
||||||
@@ -206,7 +226,7 @@ gsk_spline_decompose_cubic (const graphene_point_t pts[4],
|
|||||||
GskSplineAddPointFunc add_point_func,
|
GskSplineAddPointFunc add_point_func,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GskCubicDecomposition decomp = { pts[0], 0.0f, tolerance * tolerance, add_point_func, user_data };
|
GskCubicDecomposition decomp = { pts[0], 0.0f, tolerance, add_point_func, user_data };
|
||||||
|
|
||||||
gsk_spline_decompose_into (&decomp, pts, 1.0f);
|
gsk_spline_decompose_into (&decomp, pts, 1.0f);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user