[gtk/wip/otte/lottie: 12/17] path: Change data structure for standard path
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/otte/lottie: 12/17] path: Change data structure for standard path
- Date: Tue, 17 Nov 2020 00:18:25 +0000 (UTC)
commit 12dad94553248d6671db3be0d6d6086d602fafbe
Author: Benjamin Otte <otte redhat com>
Date: Sun Nov 15 15:58:59 2020 +0100
path: Change data structure for standard path
Instead of the Cairo method and imitating cairo_path_data_t, use the
Skia method and keep points and operations separate.
That way we get a points array that includes the starting point -
because it's always the end point of the previous operation.
gsk/gskpath.c | 232 ++++++++++++++++++++++++++++++----------------------------
1 file changed, 119 insertions(+), 113 deletions(-)
---
diff --git a/gsk/gskpath.c b/gsk/gskpath.c
index c2e52d3199..b446f1fd69 100644
--- a/gsk/gskpath.c
+++ b/gsk/gskpath.c
@@ -161,43 +161,37 @@ gsk_rect_contour_init (GskContour *contour,
typedef enum
{
- GSK_PATH_VERB_MOVE,
- GSK_PATH_VERB_CLOSE,
- GSK_PATH_VERB_LINE,
- GSK_PATH_VERB_CURVE,
-} GskPathVerb;
+ GSK_PATH_MOVE,
+ GSK_PATH_CLOSE,
+ GSK_PATH_LINE,
+ GSK_PATH_CURVE,
+} GskPathOperation;
-typedef union {
- GskPathVerb verb;
- graphene_point_t point;
-} GskStandardPoint;
+typedef struct _GskStandardOperation GskStandardOperation;
+
+struct _GskStandardOperation {
+ GskPathOperation op;
+ gsize point; /* index into points array of the start point (last point of previous op) */
+};
typedef struct _GskStandardContour GskStandardContour;
struct _GskStandardContour
{
GskContour contour;
+ gsize n_ops;
gsize n_points;
- GskStandardPoint path[];
+ graphene_point_t *points;
+ GskStandardOperation ops[];
};
static gsize
-gsk_path_verb_n_elements (GskPathVerb verb)
+gsk_standard_contour_compute_size (gsize n_ops,
+ gsize n_points)
{
- switch (verb)
- {
- case GSK_PATH_VERB_MOVE:
- case GSK_PATH_VERB_LINE:
- case GSK_PATH_VERB_CLOSE:
- return 2;
-
- case GSK_PATH_VERB_CURVE:
- return 4;
-
- default:
- g_assert_not_reached();
- return 0;
- }
+ return sizeof (GskStandardContour)
+ + sizeof (GskStandardOperation) * n_ops
+ + sizeof (graphene_point_t) * n_points;
}
static gsize
@@ -205,7 +199,7 @@ gsk_standard_contour_get_size (const GskContour *contour)
{
const GskStandardContour *self = (const GskStandardContour *) contour;
- return sizeof (GskStandardContour) + sizeof (GskStandardPoint) * self->n_points;
+ return gsk_standard_contour_compute_size (self->n_ops, self->n_points);
}
static void
@@ -215,27 +209,29 @@ gsk_standard_contour_print (const GskContour *contour,
const GskStandardContour *self = (const GskStandardContour *) contour;
gsize i;
- for (i = 0; i < self->n_points; i += gsk_path_verb_n_elements (self->path[i].verb))
+ for (i = 0; i < self->n_ops; i ++)
{
- switch (self->path[i].verb)
+ graphene_point_t *pt = &self->points [self->ops[i].point];
+
+ switch (self->ops[i].op)
{
- case GSK_PATH_VERB_MOVE:
- g_string_append_printf (string, "M %g %g", self->path[i + 1].point.x, self->path[i + 1].point.y);
+ case GSK_PATH_MOVE:
+ g_string_append_printf (string, "M %g %g", pt[0].x, pt[0].y);
break;
- case GSK_PATH_VERB_CLOSE:
+ case GSK_PATH_CLOSE:
g_string_append (string, " Z");
break;
- case GSK_PATH_VERB_LINE:
- g_string_append_printf (string, " L %g %g", self->path[i + 1].point.x, self->path[i + 1].point.y);
+ case GSK_PATH_LINE:
+ g_string_append_printf (string, " L %g %g", pt[1].x, pt[1].y);
break;
- case GSK_PATH_VERB_CURVE:
+ case GSK_PATH_CURVE:
g_string_append_printf (string, " C %g %g, %g %g, %g %g",
- self->path[i + 1].point.x, self->path[i + 1].point.y,
- self->path[i + 2].point.x, self->path[i + 2].point.y,
- self->path[i + 3].point.x, self->path[i + 3].point.y);
+ pt[1].x, pt[1].y,
+ pt[2].x, pt[2].y,
+ pt[3].x, pt[3].y);
break;
default:
@@ -254,27 +250,26 @@ gsk_standard_contour_to_cairo (const GskContour *contour,
cairo_new_sub_path (cr);
- for (i = 0; i < self->n_points; i += gsk_path_verb_n_elements (self->path[i].verb))
+ for (i = 0; i < self->n_ops; i ++)
{
- switch (self->path[i].verb)
+ graphene_point_t *pt = &self->points [self->ops[i].point];
+
+ switch (self->ops[i].op)
{
- case GSK_PATH_VERB_MOVE:
- cairo_move_to (cr, self->path[i + 1].point.x, self->path[i + 1].point.y);
+ case GSK_PATH_MOVE:
+ cairo_move_to (cr, pt[0].x, pt[0].y);
break;
- case GSK_PATH_VERB_CLOSE:
+ case GSK_PATH_CLOSE:
cairo_close_path (cr);
break;
- case GSK_PATH_VERB_LINE:
- cairo_line_to (cr, self->path[i + 1].point.x, self->path[i + 1].point.y);
+ case GSK_PATH_LINE:
+ cairo_line_to (cr, pt[1].x, pt[1].y);
break;
- case GSK_PATH_VERB_CURVE:
- cairo_curve_to (cr,
- self->path[i + 1].point.x, self->path[i + 1].point.y,
- self->path[i + 2].point.x, self->path[i + 2].point.y,
- self->path[i + 3].point.x, self->path[i + 3].point.y);
+ case GSK_PATH_CURVE:
+ cairo_curve_to (cr, pt[1].x, pt[1].y, pt[2].x, pt[2].y, pt[3].x, pt[3].y);
break;
default:
@@ -316,33 +311,16 @@ gsk_standard_contour_get_bounds (const GskContour *contour,
const GskStandardContour *self = (const GskStandardContour *) contour;
gsize i;
- for (i = 0; i < self->n_points; i += gsk_path_verb_n_elements (self->path[i].verb))
- {
- switch (self->path[i].verb)
- {
- case GSK_PATH_VERB_MOVE:
- graphene_rect_init (bounds,
- self->path[i + 1].point.x, self->path[i + 1].point.y,
- 0, 0);
- break;
-
- case GSK_PATH_VERB_CLOSE:
- break;
-
- case GSK_PATH_VERB_LINE:
- rect_add_point (bounds, &self->path[i + 1].point);
- break;
+ if (self->n_points == 0)
+ return FALSE;
- case GSK_PATH_VERB_CURVE:
- rect_add_point (bounds, &self->path[i + 1].point);
- rect_add_point (bounds, &self->path[i + 2].point);
- rect_add_point (bounds, &self->path[i + 3].point);
- break;
+ graphene_rect_init (bounds,
+ self->points[0].x, self->points[0].y,
+ 0, 0);
- default:
- g_assert_not_reached();
- return FALSE;
- }
+ for (i = 1; i < self->n_points; i ++)
+ {
+ rect_add_point (bounds, &self->points[i]);
}
return bounds->size.width > 0 && bounds->size.height > 0;
@@ -358,10 +336,25 @@ static const GskContourClass GSK_STANDARD_CONTOUR_CLASS =
gsk_standard_contour_get_bounds
};
+/* You must ensure the contour has enough size allocated,
+ * see gsk_standard_contour_compute_size()
+ */
static void
-gsk_standard_contour_init (GskContour *contour)
+gsk_standard_contour_init (GskContour *contour,
+ const GskStandardOperation *ops,
+ gsize n_ops,
+ const graphene_point_t *points,
+ gsize n_points)
{
- contour->klass = &GSK_STANDARD_CONTOUR_CLASS;
+ GskStandardContour *self = (GskStandardContour *) contour;
+
+ self->contour.klass = &GSK_STANDARD_CONTOUR_CLASS;
+
+ self->n_ops = n_ops;
+ memcpy (self->ops, ops, sizeof (GskStandardOperation) * n_ops);
+ self->n_points = n_points;
+ self->points = (graphene_point_t *) &self->ops[n_ops];
+ memcpy (self->points, points, sizeof (graphene_point_t) * n_points);
}
/* PATH */
@@ -672,8 +665,10 @@ struct _GskPathBuilder
{
int ref_count;
- GSList *contours;
- GskStandardContour *current;
+ GSList *contours; /* (reverse) list of already recorded contours */
+
+ GArray *ops; /* operations for current contour - size == 0 means no current contour */
+ GArray *points; /* points for the operations */
};
G_DEFINE_BOXED_TYPE (GskPathBuilder,
@@ -699,6 +694,8 @@ gsk_path_builder_new (void)
builder = g_slice_new0 (GskPathBuilder);
builder->ref_count = 1;
+ builder->ops = g_array_new (FALSE, FALSE, sizeof (GskStandardOperation));
+ builder->points = g_array_new (FALSE, FALSE, sizeof (graphene_point_t));
return builder;
}
@@ -726,28 +723,37 @@ gsk_path_builder_ref (GskPathBuilder *builder)
}
static void
-gsk_path_builder_append_current (GskPathBuilder *builder,
- gsize n_points,
- GskStandardPoint *points)
+gsk_path_builder_append_current (GskPathBuilder *builder,
+ GskPathOperation op,
+ gsize n_points,
+ const graphene_point_t *points)
{
- gsize size;
-
- g_assert (builder->current);
+ g_assert (builder->ops->len > 0);
+ g_assert (builder->points->len > 0);
+ g_assert (n_points > 0);
- size = sizeof (GskStandardContour) + sizeof (GskStandardPoint) * builder->current->n_points;
- builder->current = g_realloc (builder->current, size + sizeof (GskStandardPoint) * n_points);
- memcpy ((guint8 *) builder->current + size, points, sizeof (GskStandardPoint) * n_points);
- builder->current->n_points += n_points;
+ g_array_append_vals (builder->ops, &(GskStandardOperation) { op, builder->points->len - 1 }, 1);
+ g_array_append_vals (builder->points, points, n_points);
}
static void
gsk_path_builder_end_current (GskPathBuilder *builder)
{
- if (builder->current == NULL)
+ GskContour *contour;
+
+ if (builder->ops->len == 0)
return;
- builder->contours = g_slist_prepend (builder->contours, builder->current);
- builder->current = NULL;
+ contour = g_malloc0 (gsk_standard_contour_compute_size (builder->ops->len, builder->points->len));
+ gsk_standard_contour_init (contour,
+ (GskStandardOperation *) builder->ops->data,
+ builder->ops->len,
+ (graphene_point_t *) builder->points->data,
+ builder->points->len);
+ builder->contours = g_slist_prepend (builder->contours, contour);
+
+ g_array_set_size (builder->ops, 0);
+ g_array_set_size (builder->points, 0);
}
static void
@@ -777,6 +783,8 @@ gsk_path_builder_unref (GskPathBuilder *builder)
return;
gsk_path_builder_clear (builder);
+ g_array_unref (builder->ops);
+ g_array_unref (builder->points);
g_slice_free (GskPathBuilder, builder);
}
@@ -901,18 +909,12 @@ gsk_path_builder_move_to (GskPathBuilder *builder,
float x,
float y)
{
- gsize size;
-
g_return_if_fail (builder != NULL);
gsk_path_builder_end_current (builder);
- size = GSK_STANDARD_CONTOUR_CLASS.struct_size + 2 * sizeof (GskStandardPoint);
- builder->current = g_malloc0 (size);
- gsk_standard_contour_init ((GskContour *) builder->current);
- builder->current->n_points = 2;
- builder->current->path[0].verb = GSK_PATH_VERB_MOVE;
- builder->current->path[1].point = GRAPHENE_POINT_INIT (x, y);
+ g_array_append_vals (builder->ops, &(GskStandardOperation) { GSK_PATH_MOVE, 0 }, 1);
+ g_array_append_val (builder->points, GRAPHENE_POINT_INIT(x, y));
}
void
@@ -922,15 +924,16 @@ gsk_path_builder_line_to (GskPathBuilder *builder,
{
g_return_if_fail (builder != NULL);
- if (builder->current == NULL)
+ if (builder->ops->len == 0)
{
gsk_path_builder_move_to (builder, x, y);
return;
}
- gsk_path_builder_append_current (builder, 2, (GskStandardPoint[2]) {
- { .verb = GSK_PATH_VERB_LINE },
- { .point = GRAPHENE_POINT_INIT (x, y) }
+ gsk_path_builder_append_current (builder,
+ GSK_PATH_LINE,
+ 1, (graphene_point_t[1]) {
+ GRAPHENE_POINT_INIT (x, y)
});
}
@@ -945,14 +948,15 @@ gsk_path_builder_curve_to (GskPathBuilder *builder,
{
g_return_if_fail (builder != NULL);
- if (builder->current == NULL)
+ if (builder->ops->len == 0)
gsk_path_builder_move_to (builder, x1, y1);
- gsk_path_builder_append_current (builder, 4, (GskStandardPoint[4]) {
- { .verb = GSK_PATH_VERB_CURVE },
- { .point = GRAPHENE_POINT_INIT (x1, y1) },
- { .point = GRAPHENE_POINT_INIT (x2, y2) },
- { .point = GRAPHENE_POINT_INIT (x3, y3) }
+ gsk_path_builder_append_current (builder,
+ GSK_PATH_CURVE,
+ 3, (graphene_point_t[3]) {
+ GRAPHENE_POINT_INIT (x1, y1),
+ GRAPHENE_POINT_INIT (x2, y2),
+ GRAPHENE_POINT_INIT (x3, y3)
});
}
@@ -961,13 +965,15 @@ gsk_path_builder_close (GskPathBuilder *builder)
{
g_return_if_fail (builder != NULL);
- if (builder->current == NULL)
+ if (builder->ops->len == 0)
return;
- gsk_path_builder_append_current (builder, 2, (GskStandardPoint[2]) {
- { .verb = GSK_PATH_VERB_CLOSE },
- { .point = builder->current->path[1].point },
+ gsk_path_builder_append_current (builder,
+ GSK_PATH_LINE,
+ 1, (graphene_point_t[1]) {
+ g_array_index (builder->points, graphene_point_t, 0)
});
+
gsk_path_builder_end_current (builder);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]