[gtk/wip/otte/lottie: 32/42] path: Change semantics of gtk_path_builder_add_segment()
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/otte/lottie: 32/42] path: Change semantics of gtk_path_builder_add_segment()
- Date: Sun, 27 Dec 2020 14:38:29 +0000 (UTC)
commit 893a1dcf88d384777e668107ad58e3cfda5ba0de
Author: Benjamin Otte <otte redhat com>
Date: Thu Dec 17 06:55:54 2020 +0100
path: Change semantics of gtk_path_builder_add_segment()
Allow start >= end to mean that the path continues at the beginning
after reaching the end until it reaches the point at @end.
gsk/gskcontour.c | 28 ++++++++++-----
gsk/gskcontourprivate.h | 1 +
gsk/gskpathmeasure.c | 93 ++++++++++++++++++++++++++++++++++---------------
testsuite/gsk/path.c | 23 +++++++++---
4 files changed, 103 insertions(+), 42 deletions(-)
---
diff --git a/gsk/gskcontour.c b/gsk/gskcontour.c
index 075482c9a5..adaaa25bde 100644
--- a/gsk/gskcontour.c
+++ b/gsk/gskcontour.c
@@ -76,6 +76,7 @@ struct _GskContourClass
void (* add_segment) (const GskContour *contour,
GskPathBuilder *builder,
gpointer measure_data,
+ gboolean emit_move_to,
float start,
float end);
int (* get_winding) (const GskContour *contour,
@@ -395,6 +396,7 @@ static void
gsk_rect_contour_add_segment (const GskContour *contour,
GskPathBuilder *builder,
gpointer measure_data,
+ gboolean emit_move_to,
float start,
float end)
{
@@ -404,7 +406,8 @@ gsk_rect_contour_add_segment (const GskContour *contour,
if (start < w)
{
- gsk_path_builder_move_to (builder, self->x + start * (w / self->width), self->y);
+ if (emit_move_to)
+ gsk_path_builder_move_to (builder, self->x + start * (w / self->width), self->y);
if (end <= w)
{
gsk_path_builder_line_to (builder, self->x + end * (w / self->width), self->y);
@@ -417,7 +420,7 @@ gsk_rect_contour_add_segment (const GskContour *contour,
if (start < h)
{
- if (start >= 0)
+ if (start >= 0 && emit_move_to)
gsk_path_builder_move_to (builder, self->x + self->width, self->y + start * (h / self->height));
if (end <= h)
{
@@ -431,7 +434,7 @@ gsk_rect_contour_add_segment (const GskContour *contour,
if (start < w)
{
- if (start >= 0)
+ if (start >= 0 && emit_move_to)
gsk_path_builder_move_to (builder, self->x + (w - start) * (w / self->width), self->y +
self->height);
if (end <= w)
{
@@ -445,7 +448,7 @@ gsk_rect_contour_add_segment (const GskContour *contour,
if (start < h)
{
- if (start >= 0)
+ if (start >= 0 && emit_move_to)
gsk_path_builder_move_to (builder, self->x, self->y + (h - start) * (h / self->height));
if (end <= h)
{
@@ -776,6 +779,7 @@ static void
gsk_circle_contour_add_segment (const GskContour *contour,
GskPathBuilder *builder,
gpointer measure_data,
+ gboolean emit_move_to,
float start,
float end)
{
@@ -784,6 +788,8 @@ gsk_circle_contour_add_segment (const GskContour *contour,
float length = self->radius * DEG_TO_RAD (delta);
GskContour *segment;
+ if (!emit_move_to)
+ g_warning ("FIXME: somebody needs to decompose contours into segments differently");
segment = gsk_circle_contour_new (&self->center, self->radius,
self->start_angle + start/length * delta,
self->start_angle + end/length * delta);
@@ -1340,6 +1346,7 @@ static void
gsk_standard_contour_add_segment (const GskContour *contour,
GskPathBuilder *builder,
gpointer measure_data,
+ gboolean emit_move_to,
float start,
float end)
{
@@ -1391,7 +1398,8 @@ gsk_standard_contour_add_segment (const GskContour *contour,
{
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);
+ if (emit_move_to)
+ gsk_path_builder_move_to (builder, start_point->x, start_point->y);
gsk_curve_builder_to (&cut, builder);
return;
}
@@ -1399,12 +1407,13 @@ gsk_standard_contour_add_segment (const GskContour *contour,
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 (emit_move_to)
+ gsk_path_builder_move_to (builder, start_point->x, start_point->y);
gsk_curve_builder_to (&cut, builder);
i = start_measure->op + 1;
}
- else
- i = 0;
+ else
+ i = emit_move_to ? 0 : 1;
for (; i < (end_measure ? end_measure->op : self->n_ops - 1); i++)
{
@@ -1718,10 +1727,11 @@ void
gsk_contour_add_segment (const GskContour *self,
GskPathBuilder *builder,
gpointer measure_data,
+ gboolean emit_move_to,
float start,
float end)
{
- self->klass->add_segment (self, builder, measure_data, start, end);
+ self->klass->add_segment (self, builder, measure_data, emit_move_to, start, end);
}
int
diff --git a/gsk/gskcontourprivate.h b/gsk/gskcontourprivate.h
index d9d80b898d..927205fdac 100644
--- a/gsk/gskcontourprivate.h
+++ b/gsk/gskcontourprivate.h
@@ -90,6 +90,7 @@ int gsk_contour_get_winding (const GskContou
void gsk_contour_add_segment (const GskContour *self,
GskPathBuilder *builder,
gpointer measure_data,
+ gboolean emit_move_to,
float start,
float end);
gboolean gsk_contour_get_stroke_bounds (const GskContour *self,
diff --git a/gsk/gskpathmeasure.c b/gsk/gskpathmeasure.c
index 873afe5399..2c9590adc5 100644
--- a/gsk/gskpathmeasure.c
+++ b/gsk/gskpathmeasure.c
@@ -530,6 +530,44 @@ gsk_path_measure_in_fill (GskPathMeasure *self,
}
}
+static void
+gsk_path_builder_add_segment_chunk (GskPathBuilder *self,
+ GskPathMeasure *measure,
+ gboolean emit_move_to,
+ float start,
+ float end)
+{
+ g_assert (start < end);
+
+ for (gsize i = measure->first; i < measure->last; i++)
+ {
+ if (measure->measures[i].length < start)
+ {
+ start -= measure->measures[i].length;
+ end -= measure->measures[i].length;
+ }
+ else if (start > 0 || end < measure->measures[i].length)
+ {
+ float len = MIN (end, measure->measures[i].length);
+ gsk_contour_add_segment (gsk_path_get_contour (measure->path, i),
+ self,
+ measure->measures[i].contour_data,
+ emit_move_to,
+ start,
+ len);
+ end -= len;
+ start = 0;
+ if (end <= 0)
+ break;
+ }
+ else
+ {
+ end -= measure->measures[i].length;
+ gsk_path_builder_add_contour (self, gsk_contour_dup (gsk_path_get_contour (measure->path, i)));
+ }
+ emit_move_to = TRUE;
+ }
+}
/**
* gsk_path_builder_add_segment:
@@ -538,14 +576,17 @@ gsk_path_measure_in_fill (GskPathMeasure *self,
* @start: start distance into the path
* @end: end distance into the path
*
- * Adds to @self the segment of @measure inbetween @start and @end.
+ * Adds to @self the segment of @measure from @start to @end.
*
* The distances are given relative to the length of @measure's path,
* from 0 for the beginning of the path to
* gsk_path_measure_get_length() for the end of the path. The values
* will be clamped to that range.
*
- * If @start >= @end after clamping, no path will be added.
+ * If @start >= @end after clamping, the path will first add the segment
+ * from @start to the end of the path, and then add the segment from
+ * the beginning to @end. If the path is closed, these segments will
+ * be connected.
**/
void
gsk_path_builder_add_segment (GskPathBuilder *self,
@@ -553,41 +594,35 @@ gsk_path_builder_add_segment (GskPathBuilder *self,
float start,
float end)
{
- gsize i;
-
g_return_if_fail (self != NULL);
g_return_if_fail (measure != NULL);
start = gsk_path_measure_clamp_distance (measure, start);
end = gsk_path_measure_clamp_distance (measure, end);
- if (start >= end)
- return;
- for (i = measure->first; i < measure->last; i++)
+ if (start < end)
{
- if (measure->measures[i].length < start)
- {
- start -= measure->measures[i].length;
- end -= measure->measures[i].length;
- }
- else if (start > 0 || end < measure->measures[i].length)
- {
- float len = MIN (end, measure->measures[i].length);
- gsk_contour_add_segment (gsk_path_get_contour (measure->path, i),
- self,
- measure->measures[i].contour_data,
- start,
- len);
- end -= len;
- start = 0;
- if (end <= 0)
- break;
- }
+ gsk_path_builder_add_segment_chunk (self, measure, TRUE, start, end);
+ }
+ else
+ {
+ /* If the path is closed, we can connect the 2 subpaths. */
+ gboolean closed = gsk_path_measure_is_closed (measure);
+ gboolean need_move_to = !closed;
+
+ if (start < measure->length)
+ gsk_path_builder_add_segment_chunk (self, measure,
+ TRUE,
+ start, measure->length);
else
- {
- end -= measure->measures[i].length;
- gsk_path_builder_add_contour (self, gsk_contour_dup (gsk_path_get_contour (measure->path, i)));
- }
+ need_move_to = TRUE;
+
+ if (end > 0)
+ gsk_path_builder_add_segment_chunk (self, measure,
+ need_move_to,
+ 0, end);
+ if (start == end && closed)
+ gsk_path_builder_close (self);
}
}
diff --git a/testsuite/gsk/path.c b/testsuite/gsk/path.c
index 90b9ec922b..0f5d1e670a 100644
--- a/testsuite/gsk/path.c
+++ b/testsuite/gsk/path.c
@@ -609,7 +609,10 @@ test_segment_start (void)
path1 = gsk_path_builder_free_to_path (builder);
measure1 = gsk_path_measure_new (path1);
- g_assert_cmpfloat_with_epsilon (seg_length, gsk_path_measure_get_length (measure1), epsilon);
+ if (seg_length == 0)
+ g_assert_cmpfloat_with_epsilon (gsk_path_measure_get_length (measure), gsk_path_measure_get_length
(measure1), epsilon);
+ else
+ g_assert_cmpfloat_with_epsilon (seg_length, gsk_path_measure_get_length (measure1), epsilon);
gsk_path_measure_unref (measure1);
gsk_path_unref (path1);
@@ -642,7 +645,10 @@ test_segment_end (void)
path1 = gsk_path_builder_free_to_path (builder);
measure1 = gsk_path_measure_new (path1);
- g_assert_cmpfloat_with_epsilon (seg_length, gsk_path_measure_get_length (measure1), epsilon);
+ if (seg_length == 0)
+ g_assert_cmpfloat_with_epsilon (gsk_path_measure_get_length (measure), gsk_path_measure_get_length
(measure1), epsilon);
+ else
+ g_assert_cmpfloat_with_epsilon (seg_length, gsk_path_measure_get_length (measure1), epsilon);
gsk_path_measure_unref (measure1);
gsk_path_unref (path1);
@@ -655,8 +661,8 @@ test_segment_end (void)
static void
test_segment_chunk (void)
{
- GskPath *path, *path1;
- GskPathMeasure *measure, *measure1;
+ GskPath *path, *path1, *path2;
+ GskPathMeasure *measure, *measure1, *measure2;
GskPathBuilder *builder;
float epsilon, length;
guint i;
@@ -677,6 +683,15 @@ test_segment_chunk (void)
g_assert_cmpfloat_with_epsilon (length / 2, gsk_path_measure_get_length (measure1), epsilon);
+ builder = gsk_path_builder_new ();
+ gsk_path_builder_add_segment (builder, measure, seg_start + length / 2, seg_start);
+ path2 = gsk_path_builder_free_to_path (builder);
+ measure2 = gsk_path_measure_new (path2);
+
+ g_assert_cmpfloat_with_epsilon (length / 2, gsk_path_measure_get_length (measure2), epsilon);
+
+ gsk_path_measure_unref (measure2);
+ gsk_path_unref (path2);
gsk_path_measure_unref (measure1);
gsk_path_unref (path1);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]