[gtk/path-work-rebased: 28/36] curve: Move some curve apis to gskcurve.c
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/path-work-rebased: 28/36] curve: Move some curve apis to gskcurve.c
- Date: Thu, 7 Apr 2022 03:51:35 +0000 (UTC)
commit 5eb79b3b01b2d4a32fa16413b3ec581f97813a37
Author: Matthias Clasen <mclasen redhat com>
Date: Sun Mar 20 23:08:47 2022 -0400
curve: Move some curve apis to gskcurve.c
Some of this will be reused elsewhere, so move
it out of gskpathstroke.c.
gsk/gskcurve.c | 144 +++++++++++++++++++++++++++++++++++++++++++++++++
gsk/gskcurveprivate.h | 6 +++
gsk/gskpathstroke.c | 145 +-------------------------------------------------
3 files changed, 152 insertions(+), 143 deletions(-)
---
diff --git a/gsk/gskcurve.c b/gsk/gskcurve.c
index 2f1894f297..1a38a6425e 100644
--- a/gsk/gskcurve.c
+++ b/gsk/gskcurve.c
@@ -1802,3 +1802,147 @@ gsk_curve_get_curvature (const GskCurve *curve,
return k;
}
+
+static void
+align_points (const graphene_point_t *p,
+ const graphene_point_t *a,
+ const graphene_point_t *b,
+ graphene_point_t *q,
+ int n)
+{
+ graphene_vec2_t n1;
+ float angle;
+ float s, c;
+
+ get_tangent (a, b, &n1);
+ angle = - atan2 (graphene_vec2_get_y (&n1), graphene_vec2_get_x (&n1));
+ sincosf (angle, &s, &c);
+
+ for (int i = 0; i < n; i++)
+ {
+ q[i].x = (p[i].x - a->x) * c - (p[i].y - a->y) * s;
+ q[i].y = (p[i].x - a->x) * s + (p[i].y - a->y) * c;
+ }
+}
+
+/* find solutions for at^2 + bt + c = 0 */
+static int
+solve_quadratic (float a, float b, float c, float t[2])
+{
+ float d;
+ int n = 0;
+
+ if (fabs (a) > 0.0001)
+ {
+ if (b*b > 4*a*c)
+ {
+ d = sqrt (b*b - 4*a*c);
+ t[n++] = (-b + d)/(2*a);
+ t[n++] = (-b - d)/(2*a);
+ }
+ else
+ {
+ t[n++] = -b / (2*a);
+ }
+ }
+ else if (fabs (b) > 0.0001)
+ {
+ t[n++] = -c / b;
+ }
+
+ return n;
+}
+
+static int
+filter_allowable (float t[3],
+ int n)
+{
+ float g[3];
+ int j = 0;
+
+ for (int i = 0; i < n; i++)
+ if (0 < t[i] && t[i] < 1)
+ g[j++] = t[i];
+ for (int i = 0; i < j; i++)
+ t[i] = g[i];
+ return j;
+}
+
+/* Get the points where the curvature of curve is
+ * zero, or a maximum or minimum, inside the open
+ * interval from 0 to 1.
+ */
+int
+gsk_curve_get_curvature_points (const GskCurve *curve,
+ float t[3])
+{
+ const graphene_point_t *pts = curve->curve.points;
+ graphene_point_t p[4];
+ float a, b, c, d;
+ float x, y, z;
+ int n;
+
+ align_points (pts, &pts[0], &pts[3], p, 4);
+
+ a = p[2].x * p[1].y;
+ b = p[3].x * p[1].y;
+ c = p[1].x * p[2].y;
+ d = p[3].x * p[2].y;
+
+ x = - 3*a + 2*b + 3*c - d;
+ y = 3*a - b - 3*c;
+ z = c - a;
+
+ n = solve_quadratic (x, y, z, t);
+ return filter_allowable (t, n);
+}
+
+/* Find cusps inside the open interval from 0 to 1. According
+ * to Stone & deRose, A Geometric Characterization of Parametric
+ * Cubic curves, a necessary and sufficient condition is that
+ * the first derivative vanishes.
+ */
+int
+gsk_curve_get_cusps (const GskCurve *curve,
+ float t[2])
+{
+ const graphene_point_t *pts = curve->curve.points;
+ graphene_point_t p[3];
+ float ax, bx, cx;
+ float ay, by, cy;
+ float tx[3];
+ int nx;
+ int n = 0;
+
+ if (curve->op != GSK_PATH_CURVE)
+ return 0;
+
+ p[0].x = 3 * (pts[1].x - pts[0].x);
+ p[0].y = 3 * (pts[1].y - pts[0].y);
+ p[1].x = 3 * (pts[2].x - pts[1].x);
+ p[1].y = 3 * (pts[2].y - pts[1].y);
+ p[2].x = 3 * (pts[3].x - pts[2].x);
+ p[2].y = 3 * (pts[3].y - pts[2].y);
+
+ ax = p[0].x - 2 * p[1].x + p[2].x;
+ bx = - 2 * p[0].x + 2 * p[1].x;
+ cx = p[0].x;
+
+ nx = solve_quadratic (ax, bx, cx, tx);
+ nx = filter_allowable (tx, nx);
+
+ ay = p[0].y - 2 * p[1].y + p[2].y;
+ by = - 2 * p[0].y + 2 * p[1].y;
+ cy = p[0].y;
+
+ for (int i = 0; i < nx; i++)
+ {
+ float ti = tx[i];
+
+ if (0 < ti && ti < 1 &&
+ fabs (ay * ti * ti + by * ti + cy) < 0.001)
+ t[n++] = ti;
+ }
+
+ return n;
+}
diff --git a/gsk/gskcurveprivate.h b/gsk/gskcurveprivate.h
index 5af65f6fa9..cacc5eb06a 100644
--- a/gsk/gskcurveprivate.h
+++ b/gsk/gskcurveprivate.h
@@ -149,6 +149,12 @@ float gsk_curve_get_curvature (const GskCurve
float t,
graphene_point_t *center);
+int gsk_curve_get_curvature_points (const GskCurve *curve,
+ float t[3]);
+
+int gsk_curve_get_cusps (const GskCurve *curve,
+ float t[2]);
+
G_END_DECLS
#endif /* __GSK_CURVE_PRIVATE_H__ */
diff --git a/gsk/gskpathstroke.c b/gsk/gskpathstroke.c
index d44e635cd0..1ebe88b46d 100644
--- a/gsk/gskpathstroke.c
+++ b/gsk/gskpathstroke.c
@@ -573,147 +573,6 @@ conic_is_degenerate (const GskCurve *curve)
return FALSE;
}
-static void
-align_points (const graphene_point_t *p,
- const graphene_point_t *a,
- const graphene_point_t *b,
- graphene_point_t *q,
- int n)
-{
- graphene_vec2_t n1;
- float angle;
- float s, c;
-
- get_tangent (a, b, &n1);
- angle = - atan2 (graphene_vec2_get_y (&n1), graphene_vec2_get_x (&n1));
- sincosf (angle, &s, &c);
-
- for (int i = 0; i < n; i++)
- {
- q[i].x = (p[i].x - a->x) * c - (p[i].y - a->y) * s;
- q[i].y = (p[i].x - a->x) * s + (p[i].y - a->y) * c;
- }
-}
-
-/* find solutions for at^2 + bt + c = 0 */
-static int
-solve_quadratic (float a, float b, float c, float t[2])
-{
- float d;
- int n = 0;
-
- if (fabs (a) > 0.0001)
- {
- if (b*b > 4*a*c)
- {
- d = sqrt (b*b - 4*a*c);
- t[n++] = (-b + d)/(2*a);
- t[n++] = (-b - d)/(2*a);
- }
- else
- {
- t[n++] = -b / (2*a);
- }
- }
- else if (fabs (b) > 0.0001)
- {
- t[n++] = -c / b;
- }
-
- return n;
-}
-
-static int
-filter_allowable (float t[3],
- int n)
-{
- float g[3];
- int j = 0;
-
- for (int i = 0; i < n; i++)
- if (0 < t[i] && t[i] < 1)
- g[j++] = t[i];
- for (int i = 0; i < j; i++)
- t[i] = g[i];
- return j;
-}
-
-/* Get the points where the curvature of curve is
- * zero, or a maximum or minimum, inside the open
- * interval from 0 to 1.
- */
-static int
-cubic_curvature_points (const GskCurve *curve,
- float t[3])
-{
- const graphene_point_t *pts = curve->curve.points;
- graphene_point_t p[4];
- float a, b, c, d;
- float x, y, z;
- int n;
-
- align_points (pts, &pts[0], &pts[3], p, 4);
-
- a = p[2].x * p[1].y;
- b = p[3].x * p[1].y;
- c = p[1].x * p[2].y;
- d = p[3].x * p[2].y;
-
- x = - 3*a + 2*b + 3*c - d;
- y = 3*a - b - 3*c;
- z = c - a;
-
- n = solve_quadratic (x, y, z, t);
- return filter_allowable (t, n);
-}
-
-/* Find cusps inside the open interval from 0 to 1. According
- * to Stone & deRose, A Geometric Characterization of Parametric
- * Cubic curves, a necessary and sufficient condition is that
- * the first derivative vanishes.
- */
-static int
-find_cusps (const GskCurve *curve,
- float t[2])
-{
- const graphene_point_t *pts = curve->curve.points;
- graphene_point_t p[3];
- float ax, bx, cx;
- float ay, by, cy;
- float tx[3];
- int nx;
- int n = 0;
-
- p[0].x = 3 * (pts[1].x - pts[0].x);
- p[0].y = 3 * (pts[1].y - pts[0].y);
- p[1].x = 3 * (pts[2].x - pts[1].x);
- p[1].y = 3 * (pts[2].y - pts[1].y);
- p[2].x = 3 * (pts[3].x - pts[2].x);
- p[2].y = 3 * (pts[3].y - pts[2].y);
-
- ax = p[0].x - 2 * p[1].x + p[2].x;
- bx = - 2 * p[0].x + 2 * p[1].x;
- cx = p[0].x;
-
- nx = solve_quadratic (ax, bx, cx, tx);
- nx = filter_allowable (tx, nx);
-
- ay = p[0].y - 2 * p[1].y + p[2].y;
- by = - 2 * p[0].y + 2 * p[1].y;
- cy = p[0].y;
-
- for (int i = 0; i < nx; i++)
- {
- float ti = tx[i];
-
- if (0 < ti && ti < 1 &&
- fabs (ay * ti * ti + by * ti + cy) < 0.001)
- t[n++] = ti;
- }
-
- return n;
-}
-
/* }}} */
/* {{{ Stroke helpers */
@@ -1761,7 +1620,7 @@ subdivide_and_add_curve (const GskCurve *curve,
add_curve_cb (curve, force_round_join, data);
else if (level < MAX_SUBDIVISION && cubic_is_simple (curve))
add_curve_cb (curve, force_round_join, data);
- else if (level == MAX_SUBDIVISION && (n = find_cusps (curve, t)) > 0)
+ else if (level == MAX_SUBDIVISION && (n = gsk_curve_get_cusps (curve, t)) > 0)
{
t[n++] = 0;
t[n++] = 1;
@@ -1783,7 +1642,7 @@ subdivide_and_add_curve (const GskCurve *curve,
if (level == MAX_SUBDIVISION)
{
- n += cubic_curvature_points (curve, &t[n]);
+ n += gsk_curve_get_curvature_points (curve, &t[n]);
qsort (t, n, sizeof (float), cmpfloat);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]