[gtk/wip/otte/transform] transform: Add perspective()
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/otte/transform] transform: Add perspective()
- Date: Tue, 5 Mar 2019 18:02:33 +0000 (UTC)
commit d7f66679aae8d1c4ad1dc3599d9b1e0199082a02
Author: Benjamin Otte <otte redhat com>
Date: Tue Mar 5 09:27:30 2019 +0100
transform: Add perspective()
This commit adds gsk_transform_perspective() as well ass support for
perspective() in the CSS syntax.
docs/reference/gsk/gsk4-sections.txt | 1 +
gsk/gsktransform.c | 114 +++++++++++++++++++++++++++++++
gsk/gsktransform.h | 3 +
gtk/gtkcsstransformvalue.c | 129 +++++++++++++++++++++++++++++------
testsuite/gtk/transform.c | 4 ++
5 files changed, 232 insertions(+), 19 deletions(-)
---
diff --git a/docs/reference/gsk/gsk4-sections.txt b/docs/reference/gsk/gsk4-sections.txt
index 980be45b99..c66c32cfcb 100644
--- a/docs/reference/gsk/gsk4-sections.txt
+++ b/docs/reference/gsk/gsk4-sections.txt
@@ -171,6 +171,7 @@ gsk_transform_rotate
gsk_transform_rotate_3d
gsk_transform_scale
gsk_transform_scale_3d
+gsk_transform_perspective
<SUBSECTION>
gsk_transform_equal
<SUBSECTION>
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,
diff --git a/gtk/gtkcsstransformvalue.c b/gtk/gtkcsstransformvalue.c
index 83aadfcf37..51e9a06fdc 100644
--- a/gtk/gtkcsstransformvalue.c
+++ b/gtk/gtkcsstransformvalue.c
@@ -35,7 +35,8 @@ typedef enum {
GTK_CSS_TRANSFORM_SCALE,
GTK_CSS_TRANSFORM_SKEW,
GTK_CSS_TRANSFORM_SKEW_X,
- GTK_CSS_TRANSFORM_SKEW_Y
+ GTK_CSS_TRANSFORM_SKEW_Y,
+ GTK_CSS_TRANSFORM_PERSPECTIVE
} GtkCssTransformType;
union _GtkCssTransform {
@@ -66,6 +67,10 @@ union _GtkCssTransform {
GtkCssTransformType type;
GtkCssValue *skew;
} skew_x, skew_y;
+ struct {
+ GtkCssTransformType type;
+ GtkCssValue *depth;
+ } perspective;
};
struct _GtkCssValue {
@@ -110,6 +115,9 @@ gtk_css_transform_clear (GtkCssTransform *transform)
case GTK_CSS_TRANSFORM_SKEW_Y:
_gtk_css_value_unref (transform->skew_y.skew);
break;
+ case GTK_CSS_TRANSFORM_PERSPECTIVE:
+ _gtk_css_value_unref (transform->perspective.depth);
+ break;
case GTK_CSS_TRANSFORM_NONE:
default:
g_assert_not_reached ();
@@ -117,7 +125,7 @@ gtk_css_transform_clear (GtkCssTransform *transform)
}
}
-static void
+static gboolean
gtk_css_transform_init_identity (GtkCssTransform *transform,
GtkCssTransformType type)
{
@@ -152,13 +160,18 @@ gtk_css_transform_init_identity (GtkCssTransform *transform,
case GTK_CSS_TRANSFORM_SKEW_Y:
transform->skew_y.skew = _gtk_css_number_value_new (0, GTK_CSS_DEG);
break;
+ case GTK_CSS_TRANSFORM_PERSPECTIVE:
+ return FALSE;
+
case GTK_CSS_TRANSFORM_NONE:
default:
g_assert_not_reached ();
- break;
+ return FALSE;
}
transform->type = type;
+
+ return TRUE;
}
static GskTransform *
@@ -198,7 +211,7 @@ gtk_css_transform_apply (const GtkCssTransform *transform,
_gtk_css_number_value_get (transform->scale.x, 1),
_gtk_css_number_value_get (transform->scale.y, 1),
_gtk_css_number_value_get (transform->scale.z, 1));
- break;
+
case GTK_CSS_TRANSFORM_SKEW:
graphene_matrix_init_skew (&skew,
_gtk_css_number_value_get (transform->skew.x, 100) / 180.0f * G_PI,
@@ -217,6 +230,10 @@ gtk_css_transform_apply (const GtkCssTransform *transform,
_gtk_css_number_value_get (transform->skew_y.skew, 100) / 180.0f * G_PI);
return gsk_transform_matrix (next, &skew);
+ case GTK_CSS_TRANSFORM_PERSPECTIVE:
+ return gsk_transform_perspective (next,
+ _gtk_css_number_value_get (transform->perspective.depth, 100));
+
case GTK_CSS_TRANSFORM_NONE:
default:
g_assert_not_reached ();
@@ -303,6 +320,9 @@ gtk_css_transform_compute (GtkCssTransform *dest,
case GTK_CSS_TRANSFORM_SKEW_Y:
dest->skew_y.skew = _gtk_css_value_compute (src->skew_y.skew, property_id, provider, style,
parent_style);
return dest->skew_y.skew == src->skew_y.skew;
+ case GTK_CSS_TRANSFORM_PERSPECTIVE:
+ dest->perspective.depth = _gtk_css_value_compute (src->perspective.depth, property_id, provider,
style, parent_style);
+ return dest->perspective.depth == src->perspective.depth;
case GTK_CSS_TRANSFORM_NONE:
default:
g_assert_not_reached ();
@@ -389,6 +409,8 @@ gtk_css_transform_equal (const GtkCssTransform *transform1,
return _gtk_css_value_equal (transform1->skew_x.skew, transform2->skew_x.skew);
case GTK_CSS_TRANSFORM_SKEW_Y:
return _gtk_css_value_equal (transform1->skew_y.skew, transform2->skew_y.skew);
+ case GTK_CSS_TRANSFORM_PERSPECTIVE:
+ return _gtk_css_value_equal (transform1->perspective.depth, transform2->perspective.depth);
case GTK_CSS_TRANSFORM_NONE:
default:
g_assert_not_reached ();
@@ -416,7 +438,8 @@ gtk_css_value_transform_equal (const GtkCssValue *value1,
{
GtkCssTransform transform;
- gtk_css_transform_init_identity (&transform, larger->transforms[i].type);
+ if (!gtk_css_transform_init_identity (&transform, larger->transforms[i].type))
+ return FALSE;
if (!gtk_css_transform_equal (&larger->transforms[i], &transform))
{
@@ -430,6 +453,38 @@ gtk_css_value_transform_equal (const GtkCssValue *value1,
return TRUE;
}
+static void
+gtk_css_transform_transition_default (GtkCssTransform *result,
+ const GtkCssTransform *start,
+ const GtkCssTransform *end,
+ guint property_id,
+ double progress)
+{
+ graphene_matrix_t start_mat, end_mat;
+ GskTransform *trans;
+
+ result->type = GTK_CSS_TRANSFORM_MATRIX;
+
+ if (start)
+ trans = gtk_css_transform_apply (start, NULL);
+ else
+ trans = NULL;
+ gsk_transform_to_matrix (trans, &start_mat);
+ gsk_transform_unref (trans);
+
+ if (end)
+ trans = gtk_css_transform_apply (end, NULL);
+ else
+ trans = NULL;
+ gsk_transform_to_matrix (trans, &end_mat);
+ gsk_transform_unref (trans);
+
+ graphene_matrix_interpolate (&start_mat,
+ &end_mat,
+ progress,
+ &result->matrix.matrix);
+}
+
static void
gtk_css_transform_transition (GtkCssTransform *result,
const GtkCssTransform *start,
@@ -473,6 +528,9 @@ gtk_css_transform_transition (GtkCssTransform *result,
case GTK_CSS_TRANSFORM_SKEW_Y:
result->skew_y.skew = _gtk_css_value_transition (start->skew_y.skew, end->skew_y.skew, property_id,
progress);
break;
+ case GTK_CSS_TRANSFORM_PERSPECTIVE:
+ gtk_css_transform_transition_default (result, start, end, property_id, progress);
+ break;
case GTK_CSS_TRANSFORM_NONE:
default:
g_assert_not_reached ();
@@ -546,25 +604,45 @@ gtk_css_value_transform_transition (GtkCssValue *start,
{
GtkCssTransform transform;
- gtk_css_transform_init_identity (&transform, start->transforms[i].type);
- gtk_css_transform_transition (&result->transforms[i],
- &start->transforms[i],
- &transform,
- property_id,
- progress);
- gtk_css_transform_clear (&transform);
+ if (gtk_css_transform_init_identity (&transform, start->transforms[i].type))
+ {
+ gtk_css_transform_transition (&result->transforms[i],
+ &start->transforms[i],
+ &transform,
+ property_id,
+ progress);
+ gtk_css_transform_clear (&transform);
+ }
+ else
+ {
+ gtk_css_transform_transition_default (&result->transforms[i],
+ &start->transforms[i],
+ NULL,
+ property_id,
+ progress);
+ }
}
for (; i < end->n_transforms; i++)
{
GtkCssTransform transform;
- gtk_css_transform_init_identity (&transform, end->transforms[i].type);
- gtk_css_transform_transition (&result->transforms[i],
- &transform,
- &end->transforms[i],
- property_id,
- progress);
- gtk_css_transform_clear (&transform);
+ if (gtk_css_transform_init_identity (&transform, end->transforms[i].type))
+ {
+ gtk_css_transform_transition (&result->transforms[i],
+ &transform,
+ &end->transforms[i],
+ property_id,
+ progress);
+ gtk_css_transform_clear (&transform);
+ }
+ else
+ {
+ gtk_css_transform_transition_default (&result->transforms[i],
+ NULL,
+ &end->transforms[i],
+ property_id,
+ progress);
+ }
}
g_assert (i == MAX (start->n_transforms, end->n_transforms));
@@ -678,6 +756,11 @@ gtk_css_transform_print (const GtkCssTransform *transform,
_gtk_css_value_print (transform->skew_y.skew, string);
g_string_append (string, ")");
break;
+ case GTK_CSS_TRANSFORM_PERSPECTIVE:
+ g_string_append (string, "perspective(");
+ _gtk_css_value_print (transform->perspective.depth, string);
+ g_string_append (string, ")");
+ break;
case GTK_CSS_TRANSFORM_NONE:
default:
g_assert_not_reached ();
@@ -1046,6 +1129,14 @@ gtk_css_transform_parse (GtkCssTransform *transform,
if (transform->skew_y.skew == NULL)
return FALSE;
}
+ else if (_gtk_css_parser_try (parser, "perspective(", TRUE))
+ {
+ transform->type = GTK_CSS_TRANSFORM_PERSPECTIVE;
+
+ transform->perspective.depth = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_LENGTH);
+ if (transform->perspective.depth == NULL)
+ return FALSE;
+ }
else
{
_gtk_css_parser_error (parser, "unknown syntax for transform");
diff --git a/testsuite/gtk/transform.c b/testsuite/gtk/transform.c
index b3db0881cf..6026463b90 100644
--- a/testsuite/gtk/transform.c
+++ b/testsuite/gtk/transform.c
@@ -85,6 +85,7 @@ static struct {
{ GSK_TRANSFORM_CATEGORY_3D },
{ GSK_TRANSFORM_CATEGORY_2D_AFFINE },
{ GSK_TRANSFORM_CATEGORY_3D },
+ { GSK_TRANSFORM_CATEGORY_ANY },
};
static GskTransform *
@@ -117,6 +118,9 @@ apply_test_transform (GskTransform *transform,
case 7:
return gsk_transform_scale_3d (transform, 2, 3, 5);
+ case 8:
+ return gsk_transform_perspective (transform, 5);
+
default:
g_assert_not_reached ();
return NULL;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]