summaryrefslogtreecommitdiff
path: root/gsk
diff options
context:
space:
mode:
Diffstat (limited to 'gsk')
-rw-r--r--gsk/gsktransform.c114
-rw-r--r--gsk/gsktransform.h3
2 files changed, 117 insertions, 0 deletions
diff --git a/gsk/gsktransform.c b/gsk/gsktransform.c
index b434d4cb31..a4da1cfad3 100644
--- a/gsk/gsktransform.c
+++ b/gsk/gsktransform.c
@@ -1095,6 +1095,120 @@ gsk_transform_scale_3d (GskTransform *next,
return &result->parent;
}
+/*** PERSPECTIVE ***/
+
+typedef struct _GskPerspectiveTransform GskPerspectiveTransform;
+
+struct _GskPerspectiveTransform
+{
+ GskTransform parent;
+
+ float depth;
+};
+
+static void
+gsk_perspective_transform_finalize (GskTransform *self)
+{
+}
+
+static void
+gsk_perspective_transform_to_matrix (GskTransform *transform,
+ graphene_matrix_t *out_matrix)
+{
+ GskPerspectiveTransform *self = (GskPerspectiveTransform *) transform;
+ float f[16] = { 1.f, 0.f, 0.f, 0.f,
+ 0.f, 1.f, 0.f, 0.f,
+ 0.f, 0.f, 1.f, -1.f / self->depth,
+ 0.f, 0.f, 0.f, 1.f };
+
+ graphene_matrix_init_from_float (out_matrix, f);
+}
+
+
+static GskTransform *
+gsk_perspective_transform_apply (GskTransform *transform,
+ GskTransform *apply_to)
+{
+ GskPerspectiveTransform *self = (GskPerspectiveTransform *) transform;
+
+ return gsk_transform_perspective (apply_to, self->depth);
+}
+
+static GskTransform *
+gsk_perspective_transform_invert (GskTransform *transform,
+ GskTransform *next)
+{
+ GskPerspectiveTransform *self = (GskPerspectiveTransform *) transform;
+
+ return gsk_transform_perspective (next, - self->depth);
+}
+
+static gboolean
+gsk_perspective_transform_equal (GskTransform *first_transform,
+ GskTransform *second_transform)
+{
+ GskPerspectiveTransform *first = (GskPerspectiveTransform *) first_transform;
+ GskPerspectiveTransform *second = (GskPerspectiveTransform *) second_transform;
+
+ return first->depth == second->depth;
+}
+
+static void
+gsk_perspective_transform_print (GskTransform *transform,
+ GString *string)
+{
+ GskPerspectiveTransform *self = (GskPerspectiveTransform *) transform;
+
+ g_string_append (string, "perspective(");
+ string_append_double (string, self->depth);
+ g_string_append (string, ")");
+}
+
+static const GskTransformClass GSK_PERSPECTIVE_TRANSFORM_CLASS =
+{
+ sizeof (GskPerspectiveTransform),
+ "GskPerspectiveTransform",
+ gsk_perspective_transform_finalize,
+ gsk_perspective_transform_to_matrix,
+ NULL,
+ NULL,
+ NULL,
+ gsk_perspective_transform_print,
+ gsk_perspective_transform_apply,
+ gsk_perspective_transform_invert,
+ gsk_perspective_transform_equal,
+};
+
+/**
+ * gsk_transform_perspective:
+ * @next: (allow-none): the next transform
+ * @depth: distance of the z=0 plane. Lower values give a more
+ * flattened pyramid and therefore a more pronounced
+ * perspective effect.
+ *
+ * Applies a perspective projection transform. This transform
+ * scales points in X and Y based on their Z value, scaling
+ * points with positive Z values away from the origin, and
+ * those with negative Z values towards the origin. Points
+ * on the z=0 plane are unchanged.
+ *
+ * Returns: The new matrix
+ **/
+GskTransform *
+gsk_transform_perspective (GskTransform *next,
+ float depth)
+{
+ GskPerspectiveTransform *result;
+
+ result = gsk_transform_alloc (&GSK_PERSPECTIVE_TRANSFORM_CLASS,
+ GSK_TRANSFORM_CATEGORY_ANY,
+ next);
+
+ result->depth = depth;
+
+ return &result->parent;
+}
+
/*** PUBLIC API ***/
static void
diff --git a/gsk/gsktransform.h b/gsk/gsktransform.h
index 19552a0add..6cbe3659f2 100644
--- a/gsk/gsktransform.h
+++ b/gsk/gsktransform.h
@@ -105,6 +105,9 @@ GskTransform * gsk_transform_scale_3d (GskTransform
float factor_x,
float factor_y,
float factor_z);
+GDK_AVAILABLE_IN_ALL
+GskTransform * gsk_transform_perspective (GskTransform *next,
+ float depth);
GDK_AVAILABLE_IN_ALL
void gsk_transform_transform_bounds (GskTransform *self,