From 5acff562b40291402ef9a9c7977690824027804e Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Fri, 23 Jan 2009 15:57:20 +0000 Subject: [PATCH] [test-anchors] Add tests for the rotation centers The rotation centers are now tested in a similar way to the anchor point and scale centers. The notification handling code has been simplified a bit to handle the increased amount of properties. --- tests/conform/test-anchors.c | 376 ++++++++++++++++++++++++++++++----- 1 file changed, 325 insertions(+), 51 deletions(-) diff --git a/tests/conform/test-anchors.c b/tests/conform/test-anchors.c index 214ae88c3..f0211241f 100644 --- a/tests/conform/test-anchors.c +++ b/tests/conform/test-anchors.c @@ -1,16 +1,24 @@ #include #include +#include #include "test-conform-common.h" -#define NOTIFY_ANCHOR_X 1 -#define NOTIFY_ANCHOR_Y 2 -#define NOTIFY_ANCHOR_GRAVITY 4 -#define NOTIFY_SCALE_X 8 -#define NOTIFY_SCALE_Y 16 -#define NOTIFY_SCALE_CENTER_X 32 -#define NOTIFY_SCALE_CENTER_Y 64 -#define NOTIFY_SCALE_GRAVITY 128 +#define NOTIFY_ANCHOR_X (1 << 0) +#define NOTIFY_ANCHOR_Y (1 << 1) +#define NOTIFY_ANCHOR_GRAVITY (1 << 2) +#define NOTIFY_SCALE_X (1 << 3) +#define NOTIFY_SCALE_Y (1 << 4) +#define NOTIFY_SCALE_CENTER_X (1 << 5) +#define NOTIFY_SCALE_CENTER_Y (1 << 6) +#define NOTIFY_SCALE_GRAVITY (1 << 7) +#define NOTIFY_ROTATION_ANGLE_X (1 << 8) +#define NOTIFY_ROTATION_ANGLE_Y (1 << 9) +#define NOTIFY_ROTATION_ANGLE_Z (1 << 10) +#define NOTIFY_ROTATION_CENTER_X (1 << 11) +#define NOTIFY_ROTATION_CENTER_Y (1 << 12) +#define NOTIFY_ROTATION_CENTER_Z (1 << 13) +#define NOTIFY_ROTATION_CENTER_Z_GRAVITY (1 << 14) #define RECT_WIDTH 100 #define RECT_HEIGHT 80 @@ -42,22 +50,42 @@ static const struct { CLUTTER_GRAVITY_CENTER, RECT_WIDTH / 2, RECT_HEIGHT / 2 } }; -#define make_notify_cb(func, flag) \ - static void \ - func (GObject *object, GParamSpec *pspec, TestState *state) \ - { \ - g_assert ((state->notifications & (flag)) == 0); \ - state->notifications |= (flag); \ - } +static const char * const +properties[] = + { "anchor-x", + "anchor-y", + "anchor-gravity", + "scale-x", + "scale-y", + "scale-center-x", + "scale-center-y", + "scale-gravity", + "rotation-angle-x", + "rotation-angle-y", + "rotation-angle-z", + "rotation-center-x", + "rotation-center-y", + "rotation-center-z", + "rotation-center-z-gravity" }; -make_notify_cb (anchor_x_cb, NOTIFY_ANCHOR_X); -make_notify_cb (anchor_y_cb, NOTIFY_ANCHOR_Y); -make_notify_cb (anchor_gravity_cb, NOTIFY_ANCHOR_GRAVITY); -make_notify_cb (scale_x_cb, NOTIFY_SCALE_X); -make_notify_cb (scale_y_cb, NOTIFY_SCALE_Y); -make_notify_cb (scale_center_x_cb, NOTIFY_SCALE_CENTER_X); -make_notify_cb (scale_center_y_cb, NOTIFY_SCALE_CENTER_Y); -make_notify_cb (scale_gravity_cb, NOTIFY_SCALE_GRAVITY); +static void +notify_cb (GObject *object, GParamSpec *pspec, TestState *state) +{ + int i; + int new_flags = 0; + int flag = 1; + + for (i = 0; i < G_N_ELEMENTS (properties); i++) + { + if (!strcmp (properties[i], pspec->name)) + new_flags |= flag; + flag <<= 1; + } + + g_assert ((new_flags & state->notifications) == 0); + + state->notifications |= new_flags; +} #define assert_notifications(flags) \ do \ @@ -75,19 +103,34 @@ make_notify_cb (scale_gravity_cb, NOTIFY_SCALE_GRAVITY); ClutterVertex verts[4]; \ clutter_actor_get_abs_allocation_vertices ((state)->rect, verts); \ check_coords ((state), (x_1), (y_1), (x_2), (y_2), verts); \ - g_assert (abs ((x_1) - CLUTTER_UNITS_TO_DEVICE (verts[0].x)) \ - <= POSITION_TOLERANCE); \ - g_assert (abs ((y_1) - CLUTTER_UNITS_TO_DEVICE (verts[0].y)) \ - <= POSITION_TOLERANCE); \ - g_assert (abs ((x_2) - CLUTTER_UNITS_TO_DEVICE (verts[3].x)) \ - <= POSITION_TOLERANCE); \ - g_assert (abs ((y_2) - CLUTTER_UNITS_TO_DEVICE (verts[3].y)) \ - <= POSITION_TOLERANCE); \ + g_assert (approx_equal ((x_1), \ + CLUTTER_UNITS_TO_DEVICE (verts[0].x))); \ + g_assert (approx_equal ((y_1), \ + CLUTTER_UNITS_TO_DEVICE (verts[0].y))); \ + g_assert (approx_equal ((x_2), \ + CLUTTER_UNITS_TO_DEVICE (verts[3].x))); \ + g_assert (approx_equal ((y_2), \ + CLUTTER_UNITS_TO_DEVICE (verts[3].y))); \ } while (0) #define assert_position(state, x, y) \ assert_coords((state), (x), (y), (x) + RECT_WIDTH, (y) + RECT_HEIGHT) +#define assert_vertex_and_free(v, xc, yc, zc) \ + do \ + { \ + g_assert (approx_equal (CLUTTER_UNITS_TO_DEVICE (v->x), xc) \ + && approx_equal (CLUTTER_UNITS_TO_DEVICE (v->y), yc) \ + && approx_equal (CLUTTER_UNITS_TO_DEVICE (v->z), zc)); \ + g_boxed_free (CLUTTER_TYPE_VERTEX, v); \ + } while (0) + +static inline gboolean +approx_equal (int a, int b) +{ + return abs (a - b) <= POSITION_TOLERANCE; +} + static void check_coords (TestState *state, gint x_1, gint y_1, gint x_2, gint y_2, @@ -100,10 +143,10 @@ check_coords (TestState *state, CLUTTER_UNITS_TO_DEVICE (verts[0].y), CLUTTER_UNITS_TO_DEVICE (verts[3].x), CLUTTER_UNITS_TO_DEVICE (verts[3].y), - abs (x_1 - verts[0].x) <= POSITION_TOLERANCE - && abs (y_1 - verts[0].y) <= POSITION_TOLERANCE - && abs (x_2 - verts[3].x) <= POSITION_TOLERANCE - && abs (y_2 - verts[3].y) <= POSITION_TOLERANCE + approx_equal (x_1, CLUTTER_UNITS_TO_DEVICE (verts[0].x)) + && approx_equal (y_1, CLUTTER_UNITS_TO_DEVICE (verts[0].y)) + && approx_equal (x_2, CLUTTER_UNITS_TO_DEVICE (verts[3].x)) + && approx_equal (y_2, CLUTTER_UNITS_TO_DEVICE (verts[3].y)) ? "yes" : "NO"); } @@ -360,6 +403,250 @@ test_scale_center (TestState *state) assert_coords (state, 100 + 10 - 10 * 4, 200 + 20 - 20 * 2, 100 + 10 + (RECT_WIDTH - 10) * 4, 200 + 20 + (RECT_HEIGHT - 20) * 2); + + /* Put the scale back to normal */ + clutter_actor_set_scale_full (rect, 1, 1, 0, 0); + assert_notifications (NOTIFY_SCALE_X | NOTIFY_SCALE_Y + | NOTIFY_SCALE_CENTER_X | NOTIFY_SCALE_CENTER_Y); +} + +static void +test_rotate_center (TestState *state) +{ + ClutterActor *rect = state->rect; + gdouble angle_x, angle_y, angle_z; + ClutterVertex *center_x, *center_y, *center_z; + ClutterGravity z_center_gravity; + guint stage_width, stage_height; + gint rect_x, rect_y; + int i; + + /* Position the rectangle at the center of the stage so that + rotations by 90° along the X or Y axis will cause the actor to be + appear as a flat line. This makes verifying the transformations + easier */ + clutter_actor_get_size (clutter_actor_get_stage (rect), + &stage_width, &stage_height); + rect_x = stage_width / 2; + rect_y = stage_height / 2; + clutter_actor_set_position (rect, rect_x, rect_y); + + /* Assert the default settings */ + g_assert (clutter_actor_get_x (rect) == rect_x); + g_assert (clutter_actor_get_y (rect) == rect_y); + g_assert (clutter_actor_get_width (rect) == RECT_WIDTH); + g_assert (clutter_actor_get_height (rect) == RECT_HEIGHT); + g_object_get (rect, + "rotation-angle-x", &angle_x, + "rotation-angle-y", &angle_y, + "rotation-angle-z", &angle_z, + "rotation-center-x", ¢er_x, + "rotation-center-y", ¢er_y, + "rotation-center-z", ¢er_z, + "rotation-center-z-gravity", &z_center_gravity, + NULL); + g_assert (angle_x == 0.0); + g_assert (angle_y == 0.0); + g_assert (angle_z == 0.0); + assert_vertex_and_free (center_x, 0, 0, 0); + assert_vertex_and_free (center_y, 0, 0, 0); + assert_vertex_and_free (center_z, 0, 0, 0); + g_assert (z_center_gravity == CLUTTER_GRAVITY_NONE); + + /* Change each of the rotation angles without affecting the center + point */ + for (i = CLUTTER_X_AXIS; i <= CLUTTER_Z_AXIS; i++) + { + char prop_name[] = "rotation-angle- "; + prop_name[sizeof (prop_name) - 2] = i - CLUTTER_X_AXIS + 'x'; + + if (g_test_verbose ()) + g_print ("Setting %s to 90 degrees\n", prop_name); + + g_object_set (rect, prop_name, 90.0, NULL); + assert_notifications (NOTIFY_ROTATION_ANGLE_X << (i - CLUTTER_X_AXIS)); + + g_assert (clutter_actor_get_x (rect) == rect_x); + g_assert (clutter_actor_get_y (rect) == rect_y); + g_assert (clutter_actor_get_width (rect) == RECT_WIDTH); + g_assert (clutter_actor_get_height (rect) == RECT_HEIGHT); + g_object_get (rect, + "rotation-angle-x", &angle_x, + "rotation-angle-y", &angle_y, + "rotation-angle-z", &angle_z, + "rotation-center-x", ¢er_x, + "rotation-center-y", ¢er_y, + "rotation-center-z", ¢er_z, + "rotation-center-z-gravity", &z_center_gravity, + NULL); + if (i == CLUTTER_X_AXIS) + { + g_assert (angle_x == 90.0); + assert_coords (state, rect_x, rect_y, + CLUTTER_UNITS_TO_DEVICE (verts[3].x), rect_y); + } + else + g_assert (angle_x == 0.0); + if (i == CLUTTER_Y_AXIS) + { + g_assert (angle_y == 90.0); + assert_coords (state, rect_x, rect_y, + rect_x, CLUTTER_UNITS_TO_DEVICE (verts[3].y)); + } + else + g_assert (angle_y == 0.0); + if (i == CLUTTER_Z_AXIS) + { + g_assert (angle_z == 90.0); + assert_coords (state, rect_x, rect_y, + rect_x - RECT_HEIGHT, rect_y + RECT_WIDTH); + } + else + g_assert (angle_z == 0.0); + assert_vertex_and_free (center_x, 0, 0, 0); + assert_vertex_and_free (center_y, 0, 0, 0); + assert_vertex_and_free (center_z, 0, 0, 0); + g_assert (z_center_gravity == CLUTTER_GRAVITY_NONE); + + g_object_set (rect, prop_name, 0.0, NULL); + assert_notifications (NOTIFY_ROTATION_ANGLE_X << (i - CLUTTER_X_AXIS)); + } + + clutter_actor_set_position (rect, rect_x -= 10, rect_y -= 20); + + /* Same test but also change the center position */ + for (i = CLUTTER_X_AXIS; i <= CLUTTER_Z_AXIS; i++) + { + char prop_name[] = "rotation-angle- "; + prop_name[sizeof (prop_name) - 2] = i - CLUTTER_X_AXIS + 'x'; + + if (g_test_verbose ()) + g_print ("Setting %s to 90 degrees with center 10,20,0\n", prop_name); + + clutter_actor_set_rotation (rect, i, 90.0, 10, 20, 0); + assert_notifications ((NOTIFY_ROTATION_ANGLE_X << (i - CLUTTER_X_AXIS)) + | (NOTIFY_ROTATION_CENTER_X + << (i - CLUTTER_X_AXIS))); + + g_assert (clutter_actor_get_x (rect) == rect_x); + g_assert (clutter_actor_get_y (rect) == rect_y); + g_assert (clutter_actor_get_width (rect) == RECT_WIDTH); + g_assert (clutter_actor_get_height (rect) == RECT_HEIGHT); + g_object_get (rect, + "rotation-angle-x", &angle_x, + "rotation-angle-y", &angle_y, + "rotation-angle-z", &angle_z, + "rotation-center-x", ¢er_x, + "rotation-center-y", ¢er_y, + "rotation-center-z", ¢er_z, + "rotation-center-z-gravity", &z_center_gravity, + NULL); + if (i == CLUTTER_X_AXIS) + { + g_assert (angle_x == 90.0); + assert_coords (state, + CLUTTER_UNITS_TO_DEVICE (verts[0].x), rect_y + 20, + CLUTTER_UNITS_TO_DEVICE (verts[3].x), rect_y + 20); + assert_vertex_and_free (center_x, 10, 20, 0); + } + else + { + g_assert (angle_x == 0.0); + assert_vertex_and_free (center_x, 0, 0, 0); + } + if (i == CLUTTER_Y_AXIS) + { + g_assert (angle_y == 90.0); + assert_coords (state, + rect_x + 10, CLUTTER_UNITS_TO_DEVICE (verts[0].y), + rect_x + 10, CLUTTER_UNITS_TO_DEVICE (verts[3].y)); + assert_vertex_and_free (center_y, 10, 20, 0); + } + else + { + g_assert (angle_y == 0.0); + assert_vertex_and_free (center_y, 0, 0, 0); + } + if (i == CLUTTER_Z_AXIS) + { + g_assert (angle_z == 90.0); + assert_coords (state, + rect_x + 10 + 20, + rect_y + 20 - 10, + rect_x + 10 + 20 - RECT_HEIGHT, + rect_y + 20 + RECT_WIDTH - 10); + assert_vertex_and_free (center_z, 10, 20, 0); + } + else + { + g_assert (angle_z == 0.0); + assert_vertex_and_free (center_z, 0, 0, 0); + } + g_assert (z_center_gravity == CLUTTER_GRAVITY_NONE); + + clutter_actor_set_rotation (rect, i, 0, 0, 0, 0); + assert_notifications ((NOTIFY_ROTATION_ANGLE_X << (i - CLUTTER_X_AXIS)) + | (NOTIFY_ROTATION_CENTER_X + << (i - CLUTTER_X_AXIS))); + + } + + /* Try rotating the z with all of the gravities */ + for (i = 0; i < G_N_ELEMENTS (gravities); i++) + { + if (g_test_verbose ()) + { + GEnumClass *gravity_class = g_type_class_ref (CLUTTER_TYPE_GRAVITY); + GEnumValue *value = g_enum_get_value (gravity_class, + gravities[i].gravity); + g_print ("Setting z rotation to 90 degrees with center at %s\n", + value ? value->value_name : "?"); + g_type_class_unref (gravity_class); + } + + clutter_actor_set_z_rotation_from_gravity (rect, 90, + gravities[i].gravity); + assert_notifications (NOTIFY_ROTATION_ANGLE_Z + | NOTIFY_ROTATION_CENTER_Z + | NOTIFY_ROTATION_CENTER_Z_GRAVITY); + + g_assert (clutter_actor_get_x (rect) == rect_x); + g_assert (clutter_actor_get_y (rect) == rect_y); + g_assert (clutter_actor_get_width (rect) == RECT_WIDTH); + g_assert (clutter_actor_get_height (rect) == RECT_HEIGHT); + g_object_get (rect, + "rotation-angle-x", &angle_x, + "rotation-angle-y", &angle_y, + "rotation-angle-z", &angle_z, + "rotation-center-x", ¢er_x, + "rotation-center-y", ¢er_y, + "rotation-center-z", ¢er_z, + "rotation-center-z-gravity", &z_center_gravity, + NULL); + g_assert (angle_x == 0.0); + g_assert (angle_y == 0.0); + g_assert (angle_z == 90.0); + assert_vertex_and_free (center_x, 0, 0, 0); + assert_vertex_and_free (center_y, 0, 0, 0); + assert_vertex_and_free (center_z, + gravities[i].x_pos, gravities[i].y_pos, 0); + assert_coords (state, + rect_x + gravities[i].x_pos + gravities[i].y_pos, + rect_y + gravities[i].y_pos - gravities[i].x_pos, + rect_x + gravities[i].x_pos + gravities[i].y_pos + - RECT_HEIGHT, + rect_y + gravities[i].y_pos + RECT_WIDTH + - gravities[i].x_pos); + g_assert (z_center_gravity == gravities[i].gravity); + g_assert (clutter_actor_get_z_rotation_gravity (rect) + == gravities[i].gravity); + + /* Put the rotation back */ + clutter_actor_set_z_rotation_from_gravity (rect, 0, CLUTTER_GRAVITY_NONE); + assert_notifications (NOTIFY_ROTATION_ANGLE_Z + | NOTIFY_ROTATION_CENTER_Z + | NOTIFY_ROTATION_CENTER_Z_GRAVITY); + } } static gboolean @@ -367,6 +654,7 @@ idle_cb (gpointer data) { test_anchor_point (data); test_scale_center (data); + test_rotate_center (data); clutter_main_quit (); @@ -389,22 +677,8 @@ test_anchors (TestConformSimpleFixture *fixture, /* Record notifications on the actor properties */ state.notifications = 0; - g_signal_connect (state.rect, "notify::anchor-x", - G_CALLBACK (anchor_x_cb), &state); - g_signal_connect (state.rect, "notify::anchor-y", - G_CALLBACK (anchor_y_cb), &state); - g_signal_connect (state.rect, "notify::anchor-gravity", - G_CALLBACK (anchor_gravity_cb), &state); - g_signal_connect (state.rect, "notify::scale-x", - G_CALLBACK (scale_x_cb), &state); - g_signal_connect (state.rect, "notify::scale-y", - G_CALLBACK (scale_y_cb), &state); - g_signal_connect (state.rect, "notify::scale-center-x", - G_CALLBACK (scale_center_x_cb), &state); - g_signal_connect (state.rect, "notify::scale-center-y", - G_CALLBACK (scale_center_y_cb), &state); - g_signal_connect (state.rect, "notify::scale-gravity", - G_CALLBACK (scale_gravity_cb), &state); + g_signal_connect (state.rect, "notify", + G_CALLBACK (notify_cb), &state); /* Run the tests in a low priority idle function so that we can be sure the stage is correctly setup */