[gtk/wip/otte/lottie: 56/86] path: Introduce gskpathop
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/otte/lottie: 56/86] path: Introduce gskpathop
- Date: Sun, 27 Dec 2020 20:00:23 +0000 (UTC)
commit 43c010ffc557e187c7888a0402b3a035bc5b2d30
Author: Benjamin Otte <otte redhat com>
Date: Fri Dec 4 17:02:42 2020 +0100
path: Introduce gskpathop
A gskpathop is a pointer to a graphene_point_t* with the low bits used
to encode the GskPathOperation. It's an easy way to introduce API for
operations.
So far it's just used to replace GskStandardOperation.
gsk/gskcontour.c | 112 ++++++++++++++----------------
gsk/gskcontourprivate.h | 16 ++---
gsk/gskpathbuilder.c | 26 +++++--
gsk/gskpathopprivate.h | 178 ++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 256 insertions(+), 76 deletions(-)
---
diff --git a/gsk/gskcontour.c b/gsk/gskcontour.c
index 76595e1145..359356d838 100644
--- a/gsk/gskcontour.c
+++ b/gsk/gskcontour.c
@@ -871,7 +871,7 @@ struct _GskStandardContour
gsize n_ops;
gsize n_points;
graphene_point_t *points;
- GskStandardOperation ops[];
+ gskpathop ops[];
};
static gsize
@@ -879,7 +879,7 @@ gsk_standard_contour_compute_size (gsize n_ops,
gsize n_points)
{
return sizeof (GskStandardContour)
- + sizeof (GskStandardOperation) * n_ops
+ + sizeof (gskpathop) * n_ops
+ sizeof (graphene_point_t) * n_points;
}
@@ -899,30 +899,11 @@ gsk_standard_contour_foreach (const GskContour *contour,
{
const GskStandardContour *self = (const GskStandardContour *) contour;
gsize i;
- const gsize n_points[] = {
- [GSK_PATH_MOVE] = 1,
- [GSK_PATH_CLOSE] = 2,
- [GSK_PATH_LINE] = 2,
- [GSK_PATH_CURVE] = 4
- };
for (i = 0; i < self->n_ops; i ++)
{
- if (self->ops[i].op == GSK_PATH_CONIC)
- {
- graphene_point_t pts[3] = { self->points[self->ops[i].point],
- self->points[self->ops[i].point + 1],
- self->points[self->ops[i].point + 3] };
- float weight = self->points[self->ops[i].point + 2].x;
-
- if (!func (GSK_PATH_CONIC, pts, 3, weight, user_data))
- return FALSE;
- }
- else
- {
- if (!func (self->ops[i].op, &self->points[self->ops[i].point], n_points[self->ops[i].op], 0,
user_data))
- return FALSE;
- }
+ if (!gsk_pathop_foreach (self->ops[i], func, user_data))
+ return FALSE;
}
return TRUE;
@@ -945,9 +926,9 @@ gsk_standard_contour_print (const GskContour *contour,
for (i = 0; i < self->n_ops; i ++)
{
- graphene_point_t *pt = &self->points[self->ops[i].point];
+ const graphene_point_t *pt = gsk_pathop_points (self->ops[i]);
- switch (self->ops[i].op)
+ switch (gsk_pathop_op (self->ops[i]))
{
case GSK_PATH_MOVE:
g_string_append (string, "M ");
@@ -1102,9 +1083,9 @@ gsk_standard_contour_init_measure (const GskContour *contour,
for (i = 1; i < self->n_ops; i ++)
{
- graphene_point_t *pt = &self->points[self->ops[i].point];
+ const graphene_point_t *pt = gsk_pathop_points (self->ops[i]);
- switch (self->ops[i].op)
+ switch (gsk_pathop_op (self->ops[i]))
{
case GSK_PATH_MOVE:
break;
@@ -1184,8 +1165,8 @@ gsk_standard_contour_measure_get_point (GskStandardContour *self,
{
const graphene_point_t *pts;
- pts = &self->points[self->ops[op].point];
- switch (self->ops[op].op)
+ pts = gsk_pathop_points (self->ops[op]);
+ switch (gsk_pathop_op (self->ops[op]))
{
case GSK_PATH_LINE:
case GSK_PATH_CLOSE:
@@ -1229,7 +1210,7 @@ gsk_standard_contour_get_point (const GskContour *contour,
if (array->len == 0)
{
g_assert (distance == 0);
- g_assert (self->ops[0].op == GSK_PATH_MOVE);
+ g_assert (gsk_pathop_op (self->ops[0]) == GSK_PATH_MOVE);
if (pos)
*pos = self->points[0];
if (tangent)
@@ -1266,7 +1247,7 @@ gsk_standard_contour_get_closest_point (const GskContour *contour,
gsize i;
gboolean result = FALSE;
- g_assert (self->ops[0].op == GSK_PATH_MOVE);
+ g_assert (gsk_pathop_op (self->ops[0]) == GSK_PATH_MOVE);
last_point = self->points[0];
if (array->len == 0)
@@ -1338,12 +1319,13 @@ gsk_standard_contour_get_closest_point (const GskContour *contour,
}
static void
-gsk_standard_contour_init (GskContour *contour,
- GskPathFlags flags,
- const GskStandardOperation *ops,
- gsize n_ops,
+gsk_standard_contour_init (GskContour *contour,
+ GskPathFlags flags,
const graphene_point_t *points,
- gsize n_points);
+ gsize n_points,
+ const gskpathop *ops,
+ gsize n_ops,
+ ptrdiff_t offset);
static void
gsk_standard_contour_copy (const GskContour *contour,
@@ -1351,7 +1333,7 @@ gsk_standard_contour_copy (const GskContour *contour,
{
const GskStandardContour *self = (const GskStandardContour *) contour;
- gsk_standard_contour_init (dest, self->flags, self->ops, self->n_ops, self->points, self->n_points);
+ gsk_standard_contour_init (dest, self->flags, self->points, self->n_points, self->ops, self->n_ops, 0);
}
static void
@@ -1400,12 +1382,12 @@ gsk_standard_contour_add_segment (const GskContour *contour,
* taking care that first and last operation might be identical */
if (start_measure)
{
- switch (self->ops[start_measure->op].op)
+ switch (gsk_pathop_op (self->ops[start_measure->op]))
{
case GSK_PATH_CLOSE:
case GSK_PATH_LINE:
{
- graphene_point_t *pts = &self->points[self->ops[start_measure->op].point];
+ const graphene_point_t *pts = gsk_pathop_points (self->ops[start_measure->op]);
graphene_point_t point;
graphene_point_interpolate (&pts[0], &pts[1], start_progress, &point);
@@ -1422,7 +1404,7 @@ gsk_standard_contour_add_segment (const GskContour *contour,
case GSK_PATH_CURVE:
{
- graphene_point_t *pts = &self->points[self->ops[start_measure->op].point];
+ const graphene_point_t *pts = gsk_pathop_points (self->ops[start_measure->op]);
graphene_point_t curve[4], discard[4];
gsk_spline_split_cubic (pts, discard, curve, start_progress);
@@ -1441,7 +1423,7 @@ gsk_standard_contour_add_segment (const GskContour *contour,
case GSK_PATH_CONIC:
{
- graphene_point_t *pts = &self->points[self->ops[start_measure->op].point];
+ const graphene_point_t *pts = gsk_pathop_points (self->ops[start_measure->op]);
graphene_point_t curve[4], discard[4];
gsk_spline_split_conic (pts, discard, curve, start_progress);
@@ -1470,9 +1452,9 @@ gsk_standard_contour_add_segment (const GskContour *contour,
for (; i < (end_measure ? end_measure->op : self->n_ops); i++)
{
- graphene_point_t *pt = &self->points[self->ops[i].point];
+ const graphene_point_t *pt = gsk_pathop_points (self->ops[i]);
- switch (self->ops[i].op)
+ switch (gsk_pathop_op (self->ops[i]))
{
case GSK_PATH_MOVE:
gsk_path_builder_move_to (builder, pt[0].x, pt[0].y);
@@ -1500,12 +1482,12 @@ gsk_standard_contour_add_segment (const GskContour *contour,
/* Add the last partial operation */
if (end_measure)
{
- switch (self->ops[end_measure->op].op)
+ switch (gsk_pathop_op (self->ops[end_measure->op]))
{
case GSK_PATH_CLOSE:
case GSK_PATH_LINE:
{
- graphene_point_t *pts = &self->points[self->ops[end_measure->op].point];
+ const graphene_point_t *pts = gsk_pathop_points (self->ops[end_measure->op]);
graphene_point_t point;
graphene_point_interpolate (&pts[0], &pts[1], end_progress, &point);
@@ -1515,7 +1497,7 @@ gsk_standard_contour_add_segment (const GskContour *contour,
case GSK_PATH_CURVE:
{
- graphene_point_t *pts = &self->points[self->ops[end_measure->op].point];
+ const graphene_point_t *pts = gsk_pathop_points (self->ops[end_measure->op]);
graphene_point_t curve[4], discard[4];
gsk_spline_split_cubic (pts, curve, discard, end_progress);
@@ -1525,7 +1507,7 @@ gsk_standard_contour_add_segment (const GskContour *contour,
case GSK_PATH_CONIC:
{
- graphene_point_t *pts = &self->points[self->ops[end_measure->op].point];
+ const graphene_point_t *pts = gsk_pathop_points (self->ops[end_measure->op]);
graphene_point_t curve[4], discard[4];
gsk_spline_split_conic (pts, curve, discard, end_progress);
@@ -1637,37 +1619,47 @@ static const GskContourClass GSK_STANDARD_CONTOUR_CLASS =
* see gsk_standard_contour_compute_size()
*/
static void
-gsk_standard_contour_init (GskContour *contour,
- GskPathFlags flags,
- const GskStandardOperation *ops,
- gsize n_ops,
- const graphene_point_t *points,
- gsize n_points)
+gsk_standard_contour_init (GskContour *contour,
+ GskPathFlags flags,
+ const graphene_point_t *points,
+ gsize n_points,
+ const gskpathop *ops,
+ gsize n_ops,
+ gssize offset)
+
{
GskStandardContour *self = (GskStandardContour *) contour;
+ gsize i;
self->contour.klass = &GSK_STANDARD_CONTOUR_CLASS;
self->flags = flags;
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);
+
+ offset += self->points - points;
+ for (i = 0; i < n_ops; i++)
+ {
+ self->ops[i] = gsk_pathop_encode (gsk_pathop_op (ops[i]),
+ gsk_pathop_points (ops[i]) + offset);
+ }
}
GskContour *
-gsk_standard_contour_new (GskPathFlags flags,
- const GskStandardOperation *ops,
- gsize n_ops,
- const graphene_point_t *points,
- gsize n_points)
+gsk_standard_contour_new (GskPathFlags flags,
+ const graphene_point_t *points,
+ gsize n_points,
+ const gskpathop *ops,
+ gsize n_ops,
+ gssize offset)
{
GskContour *contour;
contour = g_malloc0 (gsk_standard_contour_compute_size (n_ops, n_points));
- gsk_standard_contour_init (contour, flags, ops, n_ops, points, n_points);
+ gsk_standard_contour_init (contour, flags, points, n_points, ops, n_ops, offset);
return contour;
}
diff --git a/gsk/gskcontourprivate.h b/gsk/gskcontourprivate.h
index 13e54a8e5d..bce0689d17 100644
--- a/gsk/gskcontourprivate.h
+++ b/gsk/gskcontourprivate.h
@@ -23,6 +23,8 @@
#include <gskpath.h>
+#include "gskpathopprivate.h"
+
G_BEGIN_DECLS
typedef enum
@@ -33,23 +35,17 @@ typedef enum
typedef struct _GskContour GskContour;
-typedef struct _GskStandardOperation GskStandardOperation;
-
-struct _GskStandardOperation {
- GskPathOperation op;
- gsize point; /* index into points array of the start point (last point of previous op) */
-};
-
GskContour * gsk_rect_contour_new (const graphene_rect_t *rect);
GskContour * gsk_circle_contour_new (const graphene_point_t *center,
float radius,
float start_angle,
float end_angle);
GskContour * gsk_standard_contour_new (GskPathFlags flags,
- const
GskStandardOperation *ops,
+ const graphene_point_t *points,
+ gsize n_points,
+ const gskpathop *ops,
gsize n_ops,
- const graphene_point_t
*points,
- gsize n_points);
+ gssize offset);
void gsk_contour_copy (GskContour * dest,
const GskContour *src);
diff --git a/gsk/gskpathbuilder.c b/gsk/gskpathbuilder.c
index a28898159f..c5e9533686 100644
--- a/gsk/gskpathbuilder.c
+++ b/gsk/gskpathbuilder.c
@@ -105,7 +105,7 @@ gsk_path_builder_new (void)
builder = g_slice_new0 (GskPathBuilder);
builder->ref_count = 1;
- builder->ops = g_array_new (FALSE, FALSE, sizeof (GskStandardOperation));
+ builder->ops = g_array_new (FALSE, FALSE, sizeof (gskpathop));
builder->points = g_array_new (FALSE, FALSE, sizeof (graphene_point_t));
/* Be explicit here */
@@ -137,6 +137,19 @@ gsk_path_builder_ref (GskPathBuilder *builder)
return builder;
}
+/* We're cheating here. Out pathops are relative to the NULL pointer,
+ * so that we can not care about the points GArray reallocating itself
+ * until we create the contour.
+ * This does however mean that we need to not use gsk_pathop_get_points()
+ * without offsetting the returned pointer.
+ */
+static inline gskpathop
+gsk_pathop_encode_index (GskPathOperation op,
+ gsize index)
+{
+ return gsk_pathop_encode (op, ((graphene_point_t *) NULL) + index);
+}
+
static void
gsk_path_builder_ensure_current (GskPathBuilder *builder)
{
@@ -144,7 +157,7 @@ gsk_path_builder_ensure_current (GskPathBuilder *builder)
return;
builder->flags = GSK_PATH_FLAT;
- g_array_append_vals (builder->ops, &(GskStandardOperation) { GSK_PATH_MOVE, 0 }, 1);
+ g_array_append_vals (builder->ops, (gskpathop[1]) { gsk_pathop_encode_index (GSK_PATH_MOVE, 0) }, 1);
g_array_append_val (builder->points, builder->current_point);
}
@@ -156,7 +169,7 @@ gsk_path_builder_append_current (GskPathBuilder *builder,
{
gsk_path_builder_ensure_current (builder);
- g_array_append_vals (builder->ops, &(GskStandardOperation) { op, builder->points->len - 1 }, 1);
+ g_array_append_vals (builder->ops, (gskpathop[1]) { gsk_pathop_encode_index (op, builder->points->len - 1)
}, 1);
g_array_append_vals (builder->points, points, n_points);
builder->current_point = points[n_points - 1];
@@ -171,10 +184,11 @@ gsk_path_builder_end_current (GskPathBuilder *builder)
return;
contour = gsk_standard_contour_new (builder->flags,
- (GskStandardOperation *) builder->ops->data,
- builder->ops->len,
(graphene_point_t *) builder->points->data,
- builder->points->len);
+ builder->points->len,
+ (gskpathop *) builder->ops->data,
+ builder->ops->len,
+ (graphene_point_t *) builder->points->data - (graphene_point_t *)
NULL);
g_array_set_size (builder->ops, 0);
g_array_set_size (builder->points, 0);
diff --git a/gsk/gskpathopprivate.h b/gsk/gskpathopprivate.h
new file mode 100644
index 0000000000..864e97e2ea
--- /dev/null
+++ b/gsk/gskpathopprivate.h
@@ -0,0 +1,178 @@
+/*
+ * Copyright © 2020 Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte gnome org>
+ */
+
+
+#ifndef __GSK_PATHOP_PRIVATE_H__
+#define __GSK_PATHOP_PRIVATE_H__
+
+#include <gsk/gskpath.h>
+#include <gsk/gskpathbuilder.h>
+
+G_BEGIN_DECLS
+
+typedef gpointer gskpathop;
+
+static inline
+gskpathop gsk_pathop_encode (GskPathOperation op,
+ const graphene_point_t *pts);
+static inline
+const graphene_point_t *gsk_pathop_points (gskpathop pop);
+static inline
+GskPathOperation gsk_pathop_op (gskpathop pop);
+
+static inline
+gboolean gsk_pathop_foreach (gskpathop pop,
+ GskPathForeachFunc func,
+ gpointer user_data);
+
+/* included inline so tests can use them */
+static inline
+void gsk_path_builder_pathop_to (GskPathBuilder *builder,
+ gskpathop op);
+static inline
+void gsk_path_builder_pathop_reverse_to (GskPathBuilder *builder,
+ gskpathop op);
+
+/* IMPLEMENTATION */
+
+#define GSK_PATHOP_OPERATION_MASK (0x7)
+
+static inline gskpathop
+gsk_pathop_encode (GskPathOperation op,
+ const graphene_point_t *pts)
+{
+ /* g_assert (op & GSK_PATHOP_OPERATION_MASK == op); */
+
+ return GSIZE_TO_POINTER (GPOINTER_TO_SIZE (pts) | op);
+}
+
+static inline const graphene_point_t *
+gsk_pathop_points (gskpathop pop)
+{
+ return GSIZE_TO_POINTER (GPOINTER_TO_SIZE (pop) & ~GSK_PATHOP_OPERATION_MASK);
+}
+
+static inline
+GskPathOperation gsk_pathop_op (gskpathop pop)
+{
+ return GPOINTER_TO_SIZE (pop) & GSK_PATHOP_OPERATION_MASK;
+}
+
+static inline gboolean
+gsk_pathop_foreach (gskpathop pop,
+ GskPathForeachFunc func,
+ gpointer user_data)
+{
+ switch (gsk_pathop_op (pop))
+ {
+ case GSK_PATH_MOVE:
+ return func (gsk_pathop_op (pop), gsk_pathop_points (pop), 1, 0, user_data);
+
+ case GSK_PATH_CLOSE:
+ case GSK_PATH_LINE:
+ return func (gsk_pathop_op (pop), gsk_pathop_points (pop), 2, 0, user_data);
+
+ case GSK_PATH_CURVE:
+ return func (gsk_pathop_op (pop), gsk_pathop_points (pop), 4, 0, user_data);
+
+ case GSK_PATH_CONIC:
+ {
+ const graphene_point_t *pts = gsk_pathop_points (pop);
+ return func (gsk_pathop_op (pop), (graphene_point_t[3]) { pts[0], pts[1], pts[3] }, 3, pts[2].x,
user_data);
+ }
+
+ default:
+ g_assert_not_reached ();
+ return TRUE;
+ }
+}
+
+static inline void
+gsk_path_builder_pathop_to (GskPathBuilder *builder,
+ gskpathop op)
+{
+ const graphene_point_t *pts = gsk_pathop_points (op);
+
+ switch (gsk_pathop_op (op))
+ {
+ case GSK_PATH_MOVE:
+ gsk_path_builder_move_to (builder, pts[0].x, pts[0].y);
+ break;
+
+ case GSK_PATH_CLOSE:
+ gsk_path_builder_close (builder);
+ break;
+
+ case GSK_PATH_LINE:
+ gsk_path_builder_line_to (builder, pts[1].x, pts[1].y);
+ break;
+
+ case GSK_PATH_CURVE:
+ gsk_path_builder_curve_to (builder, pts[1].x, pts[1].y, pts[2].x, pts[2].y, pts[3].x, pts[3].y);
+ break;
+
+ case GSK_PATH_CONIC:
+ gsk_path_builder_conic_to (builder, pts[1].x, pts[1].y, pts[3].x, pts[3].y, pts[2].x);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
+static inline void
+gsk_path_builder_pathop_reverse_to (GskPathBuilder *builder,
+ gskpathop op)
+{
+ const graphene_point_t *pts = gsk_pathop_points (op);
+
+ switch (gsk_pathop_op (op))
+ {
+ case GSK_PATH_MOVE:
+ gsk_path_builder_move_to (builder, pts[0].x, pts[0].y);
+ break;
+
+ case GSK_PATH_CLOSE:
+ gsk_path_builder_line_to (builder, pts[0].x, pts[0].y);
+ break;
+
+ case GSK_PATH_LINE:
+ gsk_path_builder_line_to (builder, pts[1].x, pts[1].y);
+ break;
+
+ case GSK_PATH_CURVE:
+ gsk_path_builder_curve_to (builder, pts[2].x, pts[2].y, pts[1].x, pts[1].y, pts[0].x, pts[0].y);
+ break;
+
+ case GSK_PATH_CONIC:
+ gsk_path_builder_conic_to (builder, pts[1].x, pts[1].y, pts[0].x, pts[0].y, pts[2].x);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+}
+
+
+G_END_DECLS
+
+#endif /* __GSK_PATHOP_PRIVATE_H__ */
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]