diff options
author | Benjamin Otte <otte@redhat.com> | 2019-03-02 04:39:46 +0100 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2019-03-04 23:41:27 +0100 |
commit | 979e9bec27532c118f4ab7e30d7d59c85a321d5c (patch) | |
tree | 735a752e8ef4a0d97683e5c05005845cdf772cb4 | |
parent | e737b42113daea66bd06611163a9f480c5985c21 (diff) | |
download | gtk+-979e9bec27532c118f4ab7e30d7d59c85a321d5c.tar.gz |
testsuite: Add a transforms test
In particular, check that to_matrix() and to_2d(), to_affine() and
to_translate() return the same values.
This also requires a recent Graphene version or the tests will fail.
-rw-r--r-- | meson.build | 2 | ||||
-rw-r--r-- | testsuite/gtk/meson.build | 1 | ||||
-rw-r--r-- | testsuite/gtk/transform.c | 248 |
3 files changed, 250 insertions, 1 deletions
diff --git a/meson.build b/meson.build index b4063c68d4..5ce18aaa0b 100644 --- a/meson.build +++ b/meson.build @@ -35,7 +35,7 @@ gdk_pixbuf_req = '>= 2.30.0' introspection_req = '>= 1.39.0' wayland_proto_req = '>= 1.12' wayland_req = '>= 1.14.91' -graphene_req = '>= 1.5.1' +graphene_req = '>= 1.8.5' epoxy_req = '>= 1.4' cloudproviders_req = '>= 0.2.5' xkbcommon_req = '>= 0.2.0' diff --git a/testsuite/gtk/meson.build b/testsuite/gtk/meson.build index c02e4ab177..97e5f47fce 100644 --- a/testsuite/gtk/meson.build +++ b/testsuite/gtk/meson.build @@ -52,6 +52,7 @@ tests = [ ['templates'], ['textbuffer'], ['textiter'], + ['transform'], ['treelistmodel'], ['treemodel', ['treemodel.c', 'liststore.c', 'treestore.c', 'filtermodel.c', 'modelrefcount.c', 'sortmodel.c', 'gtktreemodelrefcount.c']], diff --git a/testsuite/gtk/transform.c b/testsuite/gtk/transform.c new file mode 100644 index 0000000000..0d7a8ad9f1 --- /dev/null +++ b/testsuite/gtk/transform.c @@ -0,0 +1,248 @@ +/* + * Copyright © 2019 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + * + * Authors: Benjamin Otte <otte@gnome.org> + */ + +#include "config.h" + +#include <gtk/gtk.h> + +#define EPSILON (1.f / 1024 / 1024) + +/* macros stolen from graphene testsuite, so they get to keep their names */ + +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)) +/* Use typeof on GCC */ +# define graphene_fuzzy_equals(n1,n2,epsilon) \ + G_GNUC_EXTENSION({ \ + __auto_type _n1 = (n1); \ + __auto_type _n2 = (n2); \ + __auto_type _epsilon = (epsilon); \ + ((_n1 > _n2 ? (_n1 - _n2 ) : (_n2 - _n1)) <= _epsilon); \ + }) + +#else +/* fallback for Visual Studio, typeof not supported */ +# define graphene_fuzzy_equals(n1,n2,epsilon) \ + (((n1) > (n2) ? ((n1) - (n2)) : ((n2) - (n1))) <= (epsilon)) + +#endif /* __GNUC__ */ + +#define graphene_assert_fuzzy_matrix_cell_equal(row,col,n1,n2,epsilon) \ + G_STMT_START { \ + if (graphene_fuzzy_equals (n1, n2, epsilon)) ; else { \ + char *s = g_strdup_printf ("[%d][%d]: " #n1 " == " #n2 " (+/- " #epsilon "): (%.7g == %.7g)", \ + row, col, n1, n2); \ + g_assertion_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, s); \ + g_free (s); \ + } \ + } G_STMT_END + +#define graphene_assert_fuzzy_matrix_equal(m1,m2,epsilon) \ + G_STMT_START { \ + unsigned int __i, __j; \ + float __m1[16], __m2[16]; \ + graphene_matrix_to_float ((m1), __m1); \ + graphene_matrix_to_float ((m2), __m2); \ + for (__i = 0; __i < 4; __i++) { \ + for (__j = 0; __j < 4; __j++) { \ + unsigned int __idx = __i * 4 + __j; \ + graphene_assert_fuzzy_matrix_cell_equal (__i, __j, __m1[__idx], __m2[__idx], epsilon); \ + } \ + } \ + } G_STMT_END + +static struct { + GskTransformCategory category; +} test_transforms[] = { + { GSK_TRANSFORM_CATEGORY_IDENTITY }, + { GSK_TRANSFORM_CATEGORY_IDENTITY }, + { GSK_TRANSFORM_CATEGORY_2D_TRANSLATE }, + { GSK_TRANSFORM_CATEGORY_3D }, + { GSK_TRANSFORM_CATEGORY_2D }, + { GSK_TRANSFORM_CATEGORY_3D }, + { GSK_TRANSFORM_CATEGORY_2D_AFFINE }, + { GSK_TRANSFORM_CATEGORY_3D }, +}; + +static GskTransform * +apply_test_transform (GskTransform *transform, + guint i) +{ + switch (i) + { + case 0: + return transform ? transform : gsk_transform_new (); + + case 1: + return gsk_transform_transform (transform, NULL); + + case 2: + return gsk_transform_translate (transform, &GRAPHENE_POINT_INIT (3, 5)); + + case 3: + return gsk_transform_translate_3d (transform, &GRAPHENE_POINT3D_INIT (3, 5, 7)); + + case 4: + return gsk_transform_rotate (transform, 90); + + case 5: + return gsk_transform_rotate_3d (transform, 90, graphene_vec3_y_axis ()); + + case 6: + return gsk_transform_scale (transform, 2, 3); + + case 7: + return gsk_transform_scale_3d (transform, 2, 3, 5); + + default: + g_assert_not_reached (); + return NULL; + } +} + +static GskTransformCategory +categorize_matrix (const graphene_matrix_t *matrix) +{ + if (!graphene_fuzzy_equals (graphene_matrix_get_value (matrix, 0, 3), 0, EPSILON) || + !graphene_fuzzy_equals (graphene_matrix_get_value (matrix, 1, 3), 0, EPSILON) || + !graphene_fuzzy_equals (graphene_matrix_get_value (matrix, 2, 3), 0, EPSILON) || + !graphene_fuzzy_equals (graphene_matrix_get_value (matrix, 3, 3), 1, EPSILON)) + return GSK_TRANSFORM_CATEGORY_ANY; + + if (!graphene_fuzzy_equals (graphene_matrix_get_value (matrix, 0, 2), 0, EPSILON) || + !graphene_fuzzy_equals (graphene_matrix_get_value (matrix, 1, 2), 0, EPSILON) || + !graphene_fuzzy_equals (graphene_matrix_get_value (matrix, 2, 2), 1, EPSILON) || + !graphene_fuzzy_equals (graphene_matrix_get_value (matrix, 3, 2), 0, EPSILON) || + !graphene_fuzzy_equals (graphene_matrix_get_value (matrix, 2, 0), 0, EPSILON) || + !graphene_fuzzy_equals (graphene_matrix_get_value (matrix, 2, 1), 0, EPSILON)) + return GSK_TRANSFORM_CATEGORY_3D; + + if (!graphene_fuzzy_equals (graphene_matrix_get_value (matrix, 0, 1), 0, EPSILON) || + !graphene_fuzzy_equals (graphene_matrix_get_value (matrix, 1, 0), 0, EPSILON)) + return GSK_TRANSFORM_CATEGORY_2D; + + if (!graphene_fuzzy_equals (graphene_matrix_get_value (matrix, 0, 0), 1, EPSILON) || + !graphene_fuzzy_equals (graphene_matrix_get_value (matrix, 1, 1), 1, EPSILON)) + return GSK_TRANSFORM_CATEGORY_2D_AFFINE; + + if (!graphene_fuzzy_equals (graphene_matrix_get_value (matrix, 3, 0), 0, EPSILON) || + !graphene_fuzzy_equals (graphene_matrix_get_value (matrix, 3, 1), 0, EPSILON)) + return GSK_TRANSFORM_CATEGORY_2D_TRANSLATE; + + return GSK_TRANSFORM_CATEGORY_IDENTITY; +} + +static void +check_conversions (GskTransform *transform, + GskTransformCategory expected_category) +{ + graphene_matrix_t matrix, test; + float f[16] = { 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 }; + + g_assert_cmpint (gsk_transform_get_category (transform), ==, expected_category); + gsk_transform_to_matrix (transform, &matrix); + /* we don't insist on getting simplifications right. + * The matrix "scale(2) scale(0.5)" would be categorized as identity, + * but the transform might not do that. + */ + g_assert_cmpint (gsk_transform_get_category (transform), <=, categorize_matrix (&matrix)); + + switch (expected_category) + { + case GSK_TRANSFORM_CATEGORY_UNKNOWN: + case GSK_TRANSFORM_CATEGORY_ANY: + case GSK_TRANSFORM_CATEGORY_3D: + break; + + case GSK_TRANSFORM_CATEGORY_IDENTITY: + case GSK_TRANSFORM_CATEGORY_2D_TRANSLATE: + g_assert (gsk_transform_to_translate (transform, + &f[4 * 3 + 0], &f[4 * 3 + 1])); + graphene_matrix_init_from_float (&test, f); + graphene_assert_fuzzy_matrix_equal (&matrix, &test, EPSILON); + /* fallthrough */ + + case GSK_TRANSFORM_CATEGORY_2D_AFFINE: + g_assert (gsk_transform_to_affine (transform, + &f[4 * 0 + 0], &f[4 * 1 + 1], + &f[4 * 3 + 0], &f[4 * 3 + 1])); + graphene_matrix_init_from_float (&test, f); + graphene_assert_fuzzy_matrix_equal (&matrix, &test, EPSILON); + /* fallthrough */ + + case GSK_TRANSFORM_CATEGORY_2D: + g_assert (gsk_transform_to_2d (transform, + &f[4 * 0 + 0], &f[4 * 0 + 1], + &f[4 * 1 + 0], &f[4 * 1 + 1], + &f[4 * 3 + 0], &f[4 * 3 + 1])); + graphene_matrix_init_from_float (&test, f); + graphene_assert_fuzzy_matrix_equal (&matrix, &test, EPSILON); + break; + } +} + +static void +test_conversions_simple (void) +{ + GskTransform *transform; + guint i; + + for (i = 0; i < G_N_ELEMENTS (test_transforms); i++) + { + transform = apply_test_transform (NULL, i); + check_conversions (transform, test_transforms[i].category); + gsk_transform_unref (transform); + } +} + +static void +test_conversions_transformed (void) +{ + GskTransform *transform; + guint i, j, k; + + for (i = 0; i < G_N_ELEMENTS (test_transforms); i++) + { + for (j = 0; j < G_N_ELEMENTS (test_transforms); j++) + { + for (k = 0; k < G_N_ELEMENTS (test_transforms); k++) + { + transform = apply_test_transform (NULL, i); + transform = apply_test_transform (transform, j); + transform = apply_test_transform (transform, k); + check_conversions (transform, MIN (test_transforms[i].category, MIN (test_transforms[j].category, test_transforms[k].category))); + gsk_transform_unref (transform); + } + } + } +} + +int +main (int argc, + char *argv[]) +{ + gtk_test_init (&argc, &argv, NULL); + + g_test_add_func ("/transform/conversions/simple", test_conversions_simple); + g_test_add_func ("/transform/conversions/transformed", test_conversions_transformed); + + return g_test_run (); +} |