From 219d0efcc67fff6f40fb22b1a6ae437bc32dc53e Mon Sep 17 00:00:00 2001 From: Emanuele Aina Date: Fri, 14 Dec 2012 17:05:26 +0000 Subject: [PATCH] actor: rollback pivot translation even on explicit transforms When setting an explicit transform with clutter_actor_set_transform() and a non (0,0) pivot-point, clutter_actor_apply_transform() will fail to roll back the pivot-point translation done before multiplying the transformation matrix due to the "out:" label being slightly misplaced in clutter_actor_real_apply_transform(). This works properly: clutter_actor_set_pivot_point (actor, 0.5, 0.5); clutter_actor_set_rotation_angle (actor, CLUTTER_Z_AXIS, 30); This results in the actor being moved to the pivot-point position: clutter_actor_set_pivot_point (actor, 0.5, 0.5); clutter_matrix_init_identity(&matrix); cogl_matrix_rotate (&matrix, 30, 0, 0, 1.0); clutter_actor_set_transform (actor, &matrix); This also add a conformance test checking that even when using a pivot-point, no matter how a rotation is set the resulting transformation matrix will be the same. https://bugzilla.gnome.org/show_bug.cgi?id=690214 --- clutter/clutter-actor.c | 2 +- tests/conform/actor-invariants.c | 40 +++++++++++++++++++++++++++++++ tests/conform/test-conform-main.c | 1 + 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c index 55861bb80..36552bbc3 100644 --- a/clutter/clutter-actor.c +++ b/clutter/clutter-actor.c @@ -3072,11 +3072,11 @@ clutter_actor_real_apply_transform (ClutterActor *self, cogl_matrix_translate (transform, -x, -y, -z); } +out: /* roll back the pivot translation */ if (pivot_x != 0.f || pivot_y != 0.f || info->pivot_z != 0.f) cogl_matrix_translate (transform, -pivot_x, -pivot_y, -info->pivot_z); -out: priv->transform_valid = TRUE; } diff --git a/tests/conform/actor-invariants.c b/tests/conform/actor-invariants.c index 893dfa499..a9e21eeb8 100644 --- a/tests/conform/actor-invariants.c +++ b/tests/conform/actor-invariants.c @@ -442,3 +442,43 @@ default_stage (TestConformSimpleFixture *fixture, g_assert (CLUTTER_ACTOR_IS_REALIZED (def_stage)); } + +void +actor_pivot_transformation (TestConformSimpleFixture *fixture, + gconstpointer data) +{ + ClutterActor *stage, *actor_implicit, *actor_explicit; + ClutterMatrix transform, result_implicit, result_explicit; + ClutterActorBox allocation = CLUTTER_ACTOR_BOX_INIT (0, 0, 90, 30); + gfloat angle = 30; + + stage = clutter_stage_new (); + + actor_implicit = clutter_actor_new (); + actor_explicit = clutter_actor_new (); + + clutter_actor_add_child (stage, actor_implicit); + clutter_actor_add_child (stage, actor_explicit); + + /* Fake allocation or pivot-point will not have any effect */ + clutter_actor_allocate (actor_implicit, &allocation, CLUTTER_ALLOCATION_NONE); + clutter_actor_allocate (actor_explicit, &allocation, CLUTTER_ALLOCATION_NONE); + + clutter_actor_set_pivot_point (actor_implicit, 0.5, 0.5); + clutter_actor_set_pivot_point (actor_explicit, 0.5, 0.5); + + /* Implict transformation */ + clutter_actor_set_rotation_angle (actor_implicit, CLUTTER_Z_AXIS, angle); + + /* Explict transformation */ + clutter_matrix_init_identity(&transform); + cogl_matrix_rotate (&transform, angle, 0, 0, 1.0); + clutter_actor_set_transform (actor_explicit, &transform); + + clutter_actor_get_transform (actor_implicit, &result_implicit); + clutter_actor_get_transform (actor_explicit, &result_explicit); + + clutter_actor_destroy (stage); + + g_assert (cogl_matrix_equal (&result_implicit, &result_explicit)); +} diff --git a/tests/conform/test-conform-main.c b/tests/conform/test-conform-main.c index f57a5893c..077a62ddc 100644 --- a/tests/conform/test-conform-main.c +++ b/tests/conform/test-conform-main.c @@ -162,6 +162,7 @@ main (int argc, char **argv) TEST_CONFORM_SIMPLE ("/actor/invariants", clone_no_map); TEST_CONFORM_SIMPLE ("/actor/invariants", actor_contains); TEST_CONFORM_SIMPLE ("/actor/invariants", default_stage); + TEST_CONFORM_SIMPLE ("/actor/invariants", actor_pivot_transformation); TEST_CONFORM_SIMPLE ("/actor/opacity", opacity_label); TEST_CONFORM_SIMPLE ("/actor/opacity", opacity_rectangle);