[gtk/wip/otte/lottie: 20/42] path: Add gsk_curve_segment()
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/otte/lottie: 20/42] path: Add gsk_curve_segment()
- Date: Sun, 27 Dec 2020 14:38:29 +0000 (UTC)
commit a6d1e9ff3e149588d488b7da9cca39ec4a594d9b
Author: Benjamin Otte <otte redhat com>
Date: Wed Dec 9 03:40:58 2020 +0100
path: Add gsk_curve_segment()
Using split() twice with scaled t values does not work with conics.
gsk/gskcontour.c | 16 ++++-----
gsk/gskcurve.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++
gsk/gskcurveprivate.h | 4 +++
3 files changed, 107 insertions(+), 8 deletions(-)
---
diff --git a/gsk/gskcontour.c b/gsk/gskcontour.c
index aaef60cdb3..e433d8c508 100644
--- a/gsk/gskcontour.c
+++ b/gsk/gskcontour.c
@@ -1334,19 +1334,19 @@ gsk_standard_contour_add_segment (const GskContour *contour,
gsk_curve_init (&curve, self->ops[start_measure->op]);
- gsk_curve_split (&curve, start_progress, NULL, &cut);
- start_point = gsk_curve_get_start_point (&cut);
- gsk_path_builder_move_to (builder, start_point->x, start_point->y);
-
if (end_measure && end_measure->op == start_measure->op)
{
- GskCurve cut2;
-
- gsk_curve_split (&cut, (end_progress - start_progress) / (1 - start_progress), &cut2, NULL);
- gsk_curve_builder_to (&cut2, builder);
+ gsk_curve_segment (&curve, start_progress, end_progress, &cut);
+ start_point = gsk_curve_get_start_point (&cut);
+ gsk_path_builder_move_to (builder, start_point->x, start_point->y);
+ gsk_curve_builder_to (&cut, builder);
return;
}
+ gsk_curve_split (&curve, start_progress, NULL, &cut);
+
+ start_point = gsk_curve_get_start_point (&cut);
+ gsk_path_builder_move_to (builder, start_point->x, start_point->y);
gsk_curve_builder_to (&cut, builder);
i = start_measure->op + 1;
}
diff --git a/gsk/gskcurve.c b/gsk/gskcurve.c
index ed28700b3f..6e0332ab37 100644
--- a/gsk/gskcurve.c
+++ b/gsk/gskcurve.c
@@ -39,6 +39,10 @@ struct _GskCurveClass
float progress,
GskCurve *result1,
GskCurve *result2);
+ void (* segment) (const GskCurve *curve,
+ float start,
+ float end,
+ GskCurve *segment);
gboolean (* decompose) (const GskCurve *curve,
float tolerance,
GskCurveAddLineFunc add_line_func,
@@ -121,6 +125,21 @@ gsk_line_curve_split (const GskCurve *curve,
gsk_line_curve_init_from_points (&end->line, GSK_PATH_LINE, &point, &self->points[1]);
}
+static void
+gsk_line_curve_segment (const GskCurve *curve,
+ float start,
+ float end,
+ GskCurve *segment)
+{
+ const GskLineCurve *self = &curve->line;
+ graphene_point_t start_point, end_point;
+
+ graphene_point_interpolate (&self->points[0], &self->points[1], start, &start_point);
+ graphene_point_interpolate (&self->points[0], &self->points[1], end, &end_point);
+
+ gsk_line_curve_init_from_points (&segment->line, GSK_PATH_LINE, &start_point, &end_point);
+}
+
static gboolean
gsk_line_curve_decompose (const GskCurve *curve,
float tolerance,
@@ -170,6 +189,7 @@ static const GskCurveClass GSK_LINE_CURVE_CLASS = {
gsk_line_curve_get_point,
gsk_line_curve_get_tangent,
gsk_line_curve_split,
+ gsk_line_curve_segment,
gsk_line_curve_decompose,
gsk_line_curve_pathop,
gsk_line_curve_get_start_point,
@@ -273,6 +293,18 @@ gsk_curve_curve_split (const GskCurve *curve,
gsk_curve_curve_init_from_points (&end->curve, (graphene_point_t[4]) { final, bccd, cd, pts[3] });
}
+static void
+gsk_curve_curve_segment (const GskCurve *curve,
+ float start,
+ float end,
+ GskCurve *segment)
+{
+ GskCurve tmp;
+
+ gsk_curve_curve_split (curve, start, NULL, &tmp);
+ gsk_curve_curve_split (&tmp, (end - start) / (1.0f - start), segment, NULL);
+}
+
/* taken from Skia, including the very descriptive name */
static gboolean
gsk_curve_curve_too_curvy (const GskCurveCurve *self,
@@ -370,6 +402,7 @@ static const GskCurveClass GSK_CURVE_CURVE_CLASS = {
gsk_curve_curve_get_point,
gsk_curve_curve_get_tangent,
gsk_curve_curve_split,
+ gsk_curve_curve_segment,
gsk_curve_curve_decompose,
gsk_curve_curve_pathop,
gsk_curve_curve_get_start_point,
@@ -598,6 +631,52 @@ gsk_conic_curve_split (const GskCurve *curve,
gsk_curve_init (end, gsk_pathop_encode (GSK_PATH_CONIC, right));
}
+static void
+gsk_conic_curve_segment (const GskCurve *curve,
+ float start,
+ float end,
+ GskCurve *segment)
+{
+ const GskConicCurve *self = &curve->conic;
+ graphene_point_t start_num, start_denom;
+ graphene_point_t mid_num, mid_denom;
+ graphene_point_t end_num, end_denom;
+ graphene_point_t ctrl_num, ctrl_denom;
+ float mid;
+
+ if (start <= 0.0f)
+ return gsk_conic_curve_split (curve, end, segment, NULL);
+ else if (end >= 1.0f)
+ return gsk_conic_curve_split (curve, start, NULL, segment);
+
+ gsk_conic_curve_ensure_coefficents (self);
+
+ gsk_curve_eval_quad (self->num, start, &start_num);
+ gsk_curve_eval_quad (self->denom, start, &start_denom);
+ mid = (start + end) / 2;
+ gsk_curve_eval_quad (self->num, mid, &mid_num);
+ gsk_curve_eval_quad (self->denom, mid, &mid_denom);
+ gsk_curve_eval_quad (self->num, end, &end_num);
+ gsk_curve_eval_quad (self->denom, end, &end_denom);
+ ctrl_num = GRAPHENE_POINT_INIT (2 * mid_num.x - (start_num.x + end_num.x) / 2,
+ 2 * mid_num.y - (start_num.y + end_num.y) / 2);
+ ctrl_denom = GRAPHENE_POINT_INIT (2 * mid_denom.x - (start_denom.x + end_denom.x) / 2,
+ 2 * mid_denom.y - (start_denom.y + end_denom.y) / 2);
+
+ gsk_conic_curve_init_from_points (&segment->conic,
+ (graphene_point_t[4]) {
+ GRAPHENE_POINT_INIT (start_num.x / start_denom.x,
+ start_num.y / start_denom.y),
+ GRAPHENE_POINT_INIT (ctrl_num.x / ctrl_denom.x,
+ ctrl_num.y / ctrl_denom.y),
+ GRAPHENE_POINT_INIT (ctrl_denom.x / sqrtf (start_denom.x *
end_denom.x),
+ 0),
+ GRAPHENE_POINT_INIT (end_num.x / end_denom.x,
+ end_num.y / end_denom.y)
+ });
+
+}
+
/* taken from Skia, including the very descriptive name */
static gboolean
gsk_conic_curve_too_curvy (const graphene_point_t *start,
@@ -706,6 +785,7 @@ static const GskCurveClass GSK_CONIC_CURVE_CLASS = {
gsk_conic_curve_get_point,
gsk_conic_curve_get_tangent,
gsk_conic_curve_split,
+ gsk_conic_curve_segment,
gsk_conic_curve_decompose,
gsk_conic_curve_pathop,
gsk_conic_curve_get_start_point,
@@ -763,6 +843,21 @@ gsk_curve_split (const GskCurve *curve,
get_class (curve->op)->split (curve, progress, start, end);
}
+void
+gsk_curve_segment (const GskCurve *curve,
+ float start,
+ float end,
+ GskCurve *segment)
+{
+ if (start <= 0 && end >= 1)
+ {
+ *segment = *curve;
+ return;
+ }
+
+ get_class (curve->op)->segment (curve, start, end, segment);
+}
+
gboolean
gsk_curve_decompose (const GskCurve *curve,
float tolerance,
diff --git a/gsk/gskcurveprivate.h b/gsk/gskcurveprivate.h
index 1fd7794836..d01f520f07 100644
--- a/gsk/gskcurveprivate.h
+++ b/gsk/gskcurveprivate.h
@@ -92,6 +92,10 @@ void gsk_curve_split (const GskCurve
float progress,
GskCurve *start,
GskCurve *end);
+void gsk_curve_segment (const GskCurve *curve,
+ float start,
+ float end,
+ GskCurve *segment);
gboolean gsk_curve_decompose (const GskCurve *curve,
float tolerance,
GskCurveAddLineFunc add_line_func,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]