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
This commit is contained in:
Jonas Dreßler 2020-03-20 23:51:05 +01:00 committed by Georges Basile Stavracas Neto
parent 0c1e5b4ee5
commit 6ea0f8facc

View File

@ -52,6 +52,8 @@
struct _ClutterClonePrivate struct _ClutterClonePrivate
{ {
ClutterActor *clone_source; ClutterActor *clone_source;
float x_scale, y_scale;
gulong source_destroy_id; gulong source_destroy_id;
}; };
@ -122,8 +124,6 @@ static void
clutter_clone_apply_transform (ClutterActor *self, CoglMatrix *matrix) clutter_clone_apply_transform (ClutterActor *self, CoglMatrix *matrix)
{ {
ClutterClonePrivate *priv = CLUTTER_CLONE (self)->priv; ClutterClonePrivate *priv = CLUTTER_CLONE (self)->priv;
ClutterActorBox box, source_box;
gfloat x_scale, y_scale;
/* First chain up and apply all the standard ClutterActor /* First chain up and apply all the standard ClutterActor
* transformations... */ * transformations... */
@ -134,21 +134,7 @@ clutter_clone_apply_transform (ClutterActor *self, CoglMatrix *matrix)
if (priv->clone_source == NULL) if (priv->clone_source == NULL)
return; return;
/* get our allocated size */ cogl_matrix_scale (matrix, priv->x_scale, priv->y_scale, 1.f);
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);
} }
static void static void
@ -244,6 +230,8 @@ clutter_clone_allocate (ClutterActor *self,
{ {
ClutterClonePrivate *priv = CLUTTER_CLONE (self)->priv; ClutterClonePrivate *priv = CLUTTER_CLONE (self)->priv;
ClutterActorClass *parent_class; ClutterActorClass *parent_class;
ClutterActorBox source_box;
float x_scale, y_scale;
/* chain up */ /* chain up */
parent_class = CLUTTER_ACTOR_CLASS (clutter_clone_parent_class); 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_has_allocation (priv->clone_source))
clutter_actor_allocate_preferred_size (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 #if 0
/* XXX - this is wrong: ClutterClone cannot clone unparented /* XXX - this is wrong: ClutterClone cannot clone unparented
* actors, as it will break all invariants * actors, as it will break all invariants
@ -364,6 +369,9 @@ static void
clutter_clone_init (ClutterClone *self) clutter_clone_init (ClutterClone *self)
{ {
self->priv = clutter_clone_get_instance_private (self); self->priv = clutter_clone_get_instance_private (self);
self->priv->x_scale = 1.f;
self->priv->y_scale = 1.f;
} }
/** /**