[mutter] clutter/clone: Build scale factor for transformation during allocation



commit 6ea0f8facc0c88a56aacb0a70372a2644c687340
Author: Jonas Dreßler <verdre v0yd nl>
Date:   Fri Mar 20 23:51:05 2020 +0100

    clutter/clone: Build scale factor for transformation during allocation
    
    For ClutterClones we need to apply a scale to the texture of the clone
    to ensure the painted texture of the source actor actually fits the
    allocation of the clone. We're doing this using the transformation
    matrix instead of using the scale_x/scale_y properties of ClutterActor
    to allow users to scale ClutterClones using that API independently.
    
    Now it's quite a bad idea to get the allocation boxes for calculating
    that scale using clutter_actor_get_allocation_box(), since that method
    will internally do an immediate relayout of the stage in case the actor
    isn't allocated. Another side effect of that approach is that it makes
    it impossible to invalidate the transform (which will be needed when we
    start caching those matrices) properly.
    
    So since we eventually allocate both the source actor and the clone
    ourselves anyway, we can simply use the allocation box inside
    clutter_clone_allocate() (which is definitely updated and valid at that
    point) to calculate the scale factor.
    
    https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1181

 clutter/clutter/clutter-clone.c | 42 ++++++++++++++++++++++++-----------------
 1 file changed, 25 insertions(+), 17 deletions(-)
---
diff --git a/clutter/clutter/clutter-clone.c b/clutter/clutter/clutter-clone.c
index 6b534e69bd..fe34359d8e 100644
--- a/clutter/clutter/clutter-clone.c
+++ b/clutter/clutter/clutter-clone.c
@@ -52,6 +52,8 @@
 struct _ClutterClonePrivate
 {
   ClutterActor *clone_source;
+  float x_scale, y_scale;
+
   gulong source_destroy_id;
 };
 
@@ -122,8 +124,6 @@ static void
 clutter_clone_apply_transform (ClutterActor *self, CoglMatrix *matrix)
 {
   ClutterClonePrivate *priv = CLUTTER_CLONE (self)->priv;
-  ClutterActorBox box, source_box;
-  gfloat x_scale, y_scale;
 
   /* First chain up and apply all the standard ClutterActor
    * transformations... */
@@ -134,21 +134,7 @@ clutter_clone_apply_transform (ClutterActor *self, CoglMatrix *matrix)
   if (priv->clone_source == NULL)
     return;
 
-  /* get our allocated size */
-  clutter_actor_get_allocation_box (self, &box);
-
-  /* and get the allocated size of the source */
-  clutter_actor_get_allocation_box (priv->clone_source, &source_box);
-
-  /* We need to scale what the clone-source actor paints to fill our own
-   * allocation...
-   */
-  x_scale = clutter_actor_box_get_width (&box)
-          / clutter_actor_box_get_width (&source_box);
-  y_scale = clutter_actor_box_get_height (&box)
-          / clutter_actor_box_get_height (&source_box);
-
-  cogl_matrix_scale (matrix, x_scale, y_scale, 1.f);
+  cogl_matrix_scale (matrix, priv->x_scale, priv->y_scale, 1.f);
 }
 
 static void
@@ -244,6 +230,8 @@ clutter_clone_allocate (ClutterActor           *self,
 {
   ClutterClonePrivate *priv = CLUTTER_CLONE (self)->priv;
   ClutterActorClass *parent_class;
+  ClutterActorBox source_box;
+  float x_scale, y_scale;
 
   /* chain up */
   parent_class = CLUTTER_ACTOR_CLASS (clutter_clone_parent_class);
@@ -259,6 +247,23 @@ clutter_clone_allocate (ClutterActor           *self,
       !clutter_actor_has_allocation (priv->clone_source))
     clutter_actor_allocate_preferred_size (priv->clone_source);
 
+  clutter_actor_get_allocation_box (priv->clone_source, &source_box);
+
+  /* We need to scale what the clone-source actor paints to fill our own
+   * allocation...
+   */
+  x_scale = clutter_actor_box_get_width (box)
+          / clutter_actor_box_get_width (&source_box);
+  y_scale = clutter_actor_box_get_height (box)
+          / clutter_actor_box_get_height (&source_box);
+
+  if (!G_APPROX_VALUE (priv->x_scale, x_scale, FLT_EPSILON) ||
+      !G_APPROX_VALUE (priv->y_scale, y_scale, FLT_EPSILON))
+    {
+      priv->x_scale = x_scale;
+      priv->y_scale = y_scale;
+    }
+
 #if 0
   /* XXX - this is wrong: ClutterClone cannot clone unparented
    * actors, as it will break all invariants
@@ -364,6 +369,9 @@ static void
 clutter_clone_init (ClutterClone *self)
 {
   self->priv = clutter_clone_get_instance_private (self);
+
+  self->priv->x_scale = 1.f;
+  self->priv->y_scale = 1.f;
 }
 
 /**


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]