[gtk/projective-transform: 1/2] gsk: Add some private transform apis
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/projective-transform: 1/2] gsk: Add some private transform apis
- Date: Tue, 1 Sep 2020 13:01:18 +0000 (UTC)
commit 33c064f4f1f11596200eb9fffae37c6867a94f70
Author: Matthias Clasen <mclasen redhat com>
Date: Tue Sep 1 08:36:45 2020 -0400
gsk: Add some private transform apis
Some of the graphene_matrix_transform apis don't work
correctly with projective matrices, so add our own
variants.
gsk/gsktransform.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++
gsk/gsktransformprivate.h | 10 ++++++
2 files changed, 87 insertions(+)
---
diff --git a/gsk/gsktransform.c b/gsk/gsktransform.c
index a1b65ff13f..528b115865 100644
--- a/gsk/gsktransform.c
+++ b/gsk/gsktransform.c
@@ -2165,3 +2165,80 @@ gsk_transform_parse (const char *string,
return result;
}
+
+/* Some of the graphene_matrix_transform apis yield unexpected
+ * results with projective matrices, since they silently drop
+ * the w component, so we provide working alternatives here.
+ */
+void
+gsk_transform_point (const graphene_matrix_t *m,
+ const graphene_point_t *p,
+ graphene_point_t *res)
+{
+ graphene_vec4_t vec4;
+ float w;
+
+ graphene_vec4_init (&vec4, p->x, p->y, 0.0f, 1.0f);
+ graphene_matrix_transform_vec4 (m, &vec4, &vec4);
+
+ w = graphene_vec4_get_w (&vec4);
+ res->x = graphene_vec4_get_x (&vec4) / w;
+ res->y = graphene_vec4_get_y (&vec4) / w;
+}
+
+void
+gsk_transform_point3d (const graphene_matrix_t *m,
+ const graphene_point3d_t *p,
+ graphene_point3d_t *res)
+{
+ graphene_vec4_t vec4;
+ float w;
+
+ graphene_vec4_init (&vec4, p->x, p->y, 0.0f, 1.0f);
+ graphene_matrix_transform_vec4 (m, &vec4, &vec4);
+
+ w = graphene_vec4_get_w (&vec4);
+ res->x = graphene_vec4_get_x (&vec4) / w;
+ res->y = graphene_vec4_get_y (&vec4) / w;
+ res->z = graphene_vec4_get_z (&vec4) / w;
+}
+
+void
+gsk_transform_bounds (const graphene_matrix_t *m,
+ const graphene_rect_t *r,
+ graphene_rect_t *res)
+{
+ graphene_point_t ret[4];
+ float min_x, min_y;
+ float max_x, max_y;
+ graphene_rect_t rr;
+
+ graphene_rect_normalize_r (r, &rr);
+
+#define TRANSFORM_POINT(matrix, rect, corner, out_p) do {\
+ graphene_vec4_t __s; \
+ graphene_point_t __p; \
+ float w; \
+ graphene_rect_get_ ## corner (rect, &__p); \
+ graphene_vec4_init (&__s, __p.x, __p.y, 0.f, 1.f); \
+ graphene_matrix_transform_vec4 (matrix, &__s, &__s); \
+ w = graphene_vec4_get_w (&__s); \
+ out_p.x = graphene_vec4_get_x (&__s) / w; \
+ out_p.y = graphene_vec4_get_y (&__s) / w; } while (0)
+
+ TRANSFORM_POINT (m, &rr, top_left, ret[0]);
+ TRANSFORM_POINT (m, &rr, top_right, ret[1]);
+ TRANSFORM_POINT (m, &rr, bottom_right, ret[2]);
+ TRANSFORM_POINT (m, &rr, bottom_left, ret[3]);
+
+#undef TRANSFORM_POINT
+
+ /* FIXME: graphene doesn't export a fast way to do this */
+ min_x = MIN (MIN (ret[0].x, ret[1].x), MIN (ret[2].x, ret[3].x));
+ min_y = MIN (MIN (ret[0].y, ret[1].y), MIN (ret[2].y, ret[3].y));
+
+ max_x = MAX (MAX (ret[0].x, ret[1].x), MAX (ret[2].x, ret[3].x));
+ max_y = MAX (MAX (ret[0].y, ret[1].y), MAX (ret[2].y, ret[3].y));
+
+ graphene_rect_init (res, min_x, min_y, max_x - min_x, max_y - min_y);
+}
diff --git a/gsk/gsktransformprivate.h b/gsk/gsktransformprivate.h
index 79dfbf03b8..3e110d3c6f 100644
--- a/gsk/gsktransformprivate.h
+++ b/gsk/gsktransformprivate.h
@@ -32,6 +32,16 @@ G_BEGIN_DECLS
gboolean gsk_transform_parser_parse (GtkCssParser *parser,
GskTransform **out_transform);
+void gsk_transform_point (const graphene_matrix_t *m,
+ const graphene_point_t *p,
+ graphene_point_t *res);
+void gsk_transform_point3d (const graphene_matrix_t *m,
+ const graphene_point3d_t *p,
+ graphene_point3d_t *res);
+void gsk_transform_bounds (const graphene_matrix_t *m,
+ const graphene_rect_t *r,
+ graphene_rect_t *res);
+
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]