From f8f669b8958e02649d3acdbec9b1cf5b17d9487a Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 14 Jul 2022 22:51:13 -0400 Subject: [PATCH 1/8] Add some tests for the listlistmodel --- testsuite/gtk/listlistmodel.c | 126 ++++++++++++++++++++++++++++++++++ testsuite/gtk/meson.build | 1 + 2 files changed, 127 insertions(+) create mode 100644 testsuite/gtk/listlistmodel.c diff --git a/testsuite/gtk/listlistmodel.c b/testsuite/gtk/listlistmodel.c new file mode 100644 index 0000000000..7d1f25aa35 --- /dev/null +++ b/testsuite/gtk/listlistmodel.c @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2022, Red Hat, Inc. + * + * 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 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 . + */ + +#include + +#include + +static GQuark changes_quark; + +static void +items_changed_cb (GListModel *model, + guint position, + guint removed, + guint added) +{ + GString *changes; + + g_assert_true (removed != 0 || added != 0); + + changes = g_object_get_qdata (G_OBJECT (model), changes_quark); + + if (changes->len) + g_string_append (changes, ", "); + + if (removed == 1 && added == 0) + { + g_string_append_printf (changes, "-%u", position); + } + else if (removed == 0 && added == 1) + { + g_string_append_printf (changes, "+%u", position); + } + else + { + g_string_append_printf (changes, "%u", position); + if (removed > 0) + g_string_append_printf (changes, "-%u", removed); + if (added > 0) + g_string_append_printf (changes, "+%u", added); + } +} + +#define assert_changes(model, expected) G_STMT_START{ \ + GString *changes = g_object_get_qdata (G_OBJECT (model), changes_quark); \ + if (!g_str_equal (changes->str, expected)) \ + g_assertion_message_cmpstr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \ + #model " == " #expected, changes->str, "==", expected); \ + g_string_set_size (changes, 0); \ +}G_STMT_END + +static void +free_changes (gpointer data) +{ + GString *s = data; + + g_string_free (s, TRUE); +} + +static void +test_list_list_model (void) +{ + GtkWidget *box; + GListModel *model; + GtkWidget *a, *b; + GObject *item; + guint n_items; + + box = g_object_ref_sink (gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0)); + + model = gtk_widget_observe_children (box); + g_assert_true (g_list_model_get_item_type (model) == G_TYPE_OBJECT); + + g_assert_true (g_list_model_get_n_items (model) == 0); + g_assert_true (g_list_model_get_item (model, 0) == NULL); + + g_object_set_qdata_full (G_OBJECT (model), changes_quark, g_string_new (""), free_changes); + + g_signal_connect (model, "items-changed", G_CALLBACK (items_changed_cb), NULL); + a = gtk_label_new ("a"); + b = gtk_label_new ("b"); + gtk_box_append (GTK_BOX (box), a); + gtk_box_append (GTK_BOX (box), b); + + item = g_list_model_get_item (model, 0); + g_assert_true (GTK_WIDGET (item) == a); + g_object_unref (item); + item = g_list_model_get_item (model, 1); + g_assert_true (GTK_WIDGET (item) == b); + g_object_unref (item); + + assert_changes (model, "+0, +1"); + + g_object_get (model, "n-items", &n_items, NULL); + g_assert_true (n_items == 2); + + g_object_unref (model); + g_object_unref (box); +} + +int +main (int argc, char *argv[]) +{ + (g_test_init) (&argc, &argv, NULL); + gtk_init (); + setlocale (LC_ALL, "C"); + + changes_quark = g_quark_from_static_string ("What did I see? Can I believe what I saw?"); + + g_test_add_func ("/listlistmodel/change", test_list_list_model); + + return g_test_run (); +} diff --git a/testsuite/gtk/meson.build b/testsuite/gtk/meson.build index fcf85ce509..4dd9e494fe 100644 --- a/testsuite/gtk/meson.build +++ b/testsuite/gtk/meson.build @@ -54,6 +54,7 @@ tests = [ { 'name': 'icontheme' }, { 'name': 'label' }, { 'name': 'listbox' }, + { 'name': 'listlistmodel' }, { 'name': 'main' }, { 'name': 'maplistmodel' }, { 'name': 'multiselection' }, From 42042e6811107e16446df84d3102b6b75080c336 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 14 Jul 2022 23:32:00 -0400 Subject: [PATCH 2/8] Add some tests for GtkNoSelection --- testsuite/gtk/meson.build | 1 + testsuite/gtk/noselection.c | 553 ++++++++++++++++++++++++++++++++++++ 2 files changed, 554 insertions(+) create mode 100644 testsuite/gtk/noselection.c diff --git a/testsuite/gtk/meson.build b/testsuite/gtk/meson.build index 4dd9e494fe..05800c22d5 100644 --- a/testsuite/gtk/meson.build +++ b/testsuite/gtk/meson.build @@ -58,6 +58,7 @@ tests = [ { 'name': 'main' }, { 'name': 'maplistmodel' }, { 'name': 'multiselection' }, + { 'name': 'noselection' }, { 'name': 'notify' }, { 'name': 'no-gtk-init' }, { 'name': 'object' }, diff --git a/testsuite/gtk/noselection.c b/testsuite/gtk/noselection.c new file mode 100644 index 0000000000..59e0526035 --- /dev/null +++ b/testsuite/gtk/noselection.c @@ -0,0 +1,553 @@ +/* + * Copyright (C) 2022, Red Hat, Inc. + * Authors: Matthias Clasen + * + * 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 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 . + */ + +#include + +#include + +static GQuark number_quark; +static GQuark changes_quark; +static GQuark selection_quark; + +static guint +get (GListModel *model, + guint position) +{ + guint number; + GObject *object = g_list_model_get_item (model, position); + g_assert_nonnull (object); + number = GPOINTER_TO_UINT (g_object_get_qdata (object, number_quark)); + g_object_unref (object); + return number; +} + +static char * +model_to_string (GListModel *model) +{ + GString *string = g_string_new (NULL); + guint i; + + for (i = 0; i < g_list_model_get_n_items (model); i++) + { + if (i > 0) + g_string_append (string, " "); + g_string_append_printf (string, "%u", get (model, i)); + } + + return g_string_free (string, FALSE); +} + +static char * +selection_to_string (GListModel *model) +{ + GString *string = g_string_new (NULL); + guint i; + + for (i = 0; i < g_list_model_get_n_items (model); i++) + { + if (!gtk_selection_model_is_selected (GTK_SELECTION_MODEL (model), i)) + continue; + + if (string->len > 0) + g_string_append (string, " "); + g_string_append_printf (string, "%u", get (model, i)); + } + + return g_string_free (string, FALSE); +} + +static GListStore * +new_store (guint start, + guint end, + guint step); + +static GObject * +make_object (guint number) +{ + GObject *object; + + /* 0 cannot be differentiated from NULL, so don't use it */ + g_assert_cmpint (number, !=, 0); + + object = g_object_new (G_TYPE_OBJECT, NULL); + g_object_set_qdata (object, number_quark, GUINT_TO_POINTER (number)); + + return object; +} + +static void +splice (GListStore *store, + guint pos, + guint removed, + guint *numbers, + guint added) +{ + GObject **objects = g_newa (GObject *, added); + guint i; + + for (i = 0; i < added; i++) + objects[i] = make_object (numbers[i]); + + g_list_store_splice (store, pos, removed, (gpointer *) objects, added); + + for (i = 0; i < added; i++) + g_object_unref (objects[i]); +} + +static void +add (GListStore *store, + guint number) +{ + GObject *object = make_object (number); + g_list_store_append (store, object); + g_object_unref (object); +} + +static void +insert (GListStore *store, + guint position, + guint number) +{ + GObject *object = make_object (number); + g_list_store_insert (store, position, object); + g_object_unref (object); +} + +#define assert_model(model, expected) G_STMT_START{ \ + char *s = model_to_string (G_LIST_MODEL (model)); \ + if (!g_str_equal (s, expected)) \ + g_assertion_message_cmpstr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \ + #model " == " #expected, s, "==", expected); \ + g_free (s); \ +}G_STMT_END + +#define ignore_changes(model) G_STMT_START{ \ + GString *changes = g_object_get_qdata (G_OBJECT (model), changes_quark); \ + g_string_set_size (changes, 0); \ +}G_STMT_END + +#define assert_changes(model, expected) G_STMT_START{ \ + GString *changes = g_object_get_qdata (G_OBJECT (model), changes_quark); \ + if (!g_str_equal (changes->str, expected)) \ + g_assertion_message_cmpstr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \ + #model " == " #expected, changes->str, "==", expected); \ + g_string_set_size (changes, 0); \ +}G_STMT_END + +#define assert_selection(model, expected) G_STMT_START{ \ + char *s = selection_to_string (G_LIST_MODEL (model)); \ + if (!g_str_equal (s, expected)) \ + g_assertion_message_cmpstr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \ + #model " == " #expected, s, "==", expected); \ + g_free (s); \ +}G_STMT_END + +#define assert_selection_changes(model, expected) G_STMT_START{ \ + GString *changes = g_object_get_qdata (G_OBJECT (model), selection_quark); \ + if (!g_str_equal (changes->str, expected)) \ + g_assertion_message_cmpstr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, \ + #model " == " #expected, changes->str, "==", expected); \ + g_string_set_size (changes, 0); \ +}G_STMT_END + +#define ignore_selection_changes(model) G_STMT_START{ \ + GString *changes = g_object_get_qdata (G_OBJECT (model), selection_quark); \ + g_string_set_size (changes, 0); \ +}G_STMT_END + +static GListStore * +new_empty_store (void) +{ + return g_list_store_new (G_TYPE_OBJECT); +} + +static GListStore * +new_store (guint start, + guint end, + guint step) +{ + GListStore *store = new_empty_store (); + guint i; + + for (i = start; i <= end; i += step) + add (store, i); + + return store; +} + +static void +items_changed (GListModel *model, + guint position, + guint removed, + guint added, + GString *changes) +{ + g_assert_true (removed != 0 || added != 0); + + if (changes->len) + g_string_append (changes, ", "); + + if (removed == 1 && added == 0) + { + g_string_append_printf (changes, "-%u", position); + } + else if (removed == 0 && added == 1) + { + g_string_append_printf (changes, "+%u", position); + } + else + { + g_string_append_printf (changes, "%u", position); + if (removed > 0) + g_string_append_printf (changes, "-%u", removed); + if (added > 0) + g_string_append_printf (changes, "+%u", added); + } +} + +static void +notify_n_items (GObject *object, + GParamSpec *pspec, + GString *changes) +{ + g_string_append_c (changes, '*'); +} + +static void +selection_changed (GListModel *model, + guint position, + guint n_items, + GString *changes) +{ + if (changes->len) + g_string_append (changes, ", "); + + g_string_append_printf (changes, "%u:%u", position, n_items); +} + +static void +free_changes (gpointer data) +{ + GString *changes = data; + + /* all changes must have been checked via assert_changes() before */ + g_assert_cmpstr (changes->str, ==, ""); + + g_string_free (changes, TRUE); +} + +static GtkSelectionModel * +new_model (GListStore *store, gboolean autoselect, gboolean can_unselect) +{ + GtkSelectionModel *result; + GString *changes; + + result = GTK_SELECTION_MODEL (gtk_no_selection_new (g_object_ref (G_LIST_MODEL (store)))); + + changes = g_string_new (""); + g_object_set_qdata_full (G_OBJECT(result), changes_quark, changes, free_changes); + g_signal_connect (result, "items-changed", G_CALLBACK (items_changed), changes); + g_signal_connect (result, "notify::n-items", G_CALLBACK (notify_n_items), changes); + + changes = g_string_new (""); + g_object_set_qdata_full (G_OBJECT(result), selection_quark, changes, free_changes); + g_signal_connect (result, "selection-changed", G_CALLBACK (selection_changed), changes); + + return result; +} + +static void +test_create (void) +{ + GtkSelectionModel *selection; + GListStore *store; + + if (glib_check_version (2, 59, 0) != NULL) + { + g_test_skip ("g_list_store_get_item() has overflow issues before GLIB 2.59.0"); + return; + } + + store = new_store (1, 5, 2); + selection = new_model (store, FALSE, FALSE); + + assert_model (selection, "1 3 5"); + assert_changes (selection, ""); + assert_selection (selection, ""); + assert_selection_changes (selection, ""); + + g_object_unref (store); + + assert_model (selection, "1 3 5"); + assert_changes (selection, ""); + assert_selection (selection, ""); + assert_selection_changes (selection, ""); + + g_object_unref (selection); +} + +static void +test_create_empty (void) +{ + GtkSingleSelection *selection; + + selection = gtk_single_selection_new (NULL); + g_assert_cmpint (g_list_model_get_n_items (G_LIST_MODEL (selection)), ==, 0); + + g_object_unref (selection); +} + +static void +test_changes (void) +{ + GtkSelectionModel *selection; + GListStore *store; + + if (glib_check_version (2, 58, 0) != NULL) + { + g_test_skip ("g_list_store_splice() is broken before GLIB 2.58.0"); + return; + } + + store = new_store (1, 5, 1); + selection = new_model (store, FALSE, FALSE); + assert_model (selection, "1 2 3 4 5"); + assert_changes (selection, ""); + assert_selection (selection, ""); + assert_selection_changes (selection, ""); + + g_list_store_remove (store, 3); + assert_model (selection, "1 2 3 5"); + assert_changes (selection, "-3*"); + assert_selection (selection, ""); + assert_selection_changes (selection, ""); + + insert (store, 3, 99); + assert_model (selection, "1 2 3 99 5"); + assert_changes (selection, "+3*"); + assert_selection (selection, ""); + assert_selection_changes (selection, ""); + + splice (store, 3, 2, (guint[]) { 97 }, 1); + assert_model (selection, "1 2 3 97"); + assert_changes (selection, "3-2+1*"); + assert_selection (selection, ""); + assert_selection_changes (selection, ""); + + g_object_unref (selection); + g_object_unref (store); +} + +static void +test_selection (void) +{ + GtkSelectionModel *selection; + GListStore *store; + gboolean ret; + + if (glib_check_version (2, 59, 0) != NULL) + { + g_test_skip ("g_list_store_get_item() has overflow issues before GLIB 2.59.0"); + return; + } + + store = new_store (1, 5, 1); + selection = new_model (store, TRUE, FALSE); + assert_selection (selection, ""); + assert_selection_changes (selection, ""); + + ret = gtk_selection_model_select_item (selection, 3, FALSE); + g_assert_false (ret); + assert_selection (selection, ""); + assert_selection_changes (selection, ""); + + ret = gtk_selection_model_unselect_item (selection, 3); + g_assert_false (ret); + assert_selection (selection, ""); + assert_selection_changes (selection, ""); + + ret = gtk_selection_model_select_item (selection, 1, FALSE); + g_assert_false (ret); + assert_selection (selection, ""); + assert_selection_changes (selection, ""); + + ret = gtk_selection_model_select_range (selection, 3, 2, FALSE); + g_assert_false (ret); + assert_selection (selection, ""); + assert_selection_changes (selection, ""); + + ret = gtk_selection_model_unselect_range (selection, 4, 2); + g_assert_false (ret); + assert_selection (selection, ""); + assert_selection_changes (selection, ""); + + ret = gtk_selection_model_select_all (selection); + g_assert_false (ret); + assert_selection (selection, ""); + assert_selection_changes (selection, ""); + + ret = gtk_selection_model_unselect_all (selection); + g_assert_false (ret); + assert_selection (selection, ""); + assert_selection_changes (selection, ""); + + g_object_unref (store); + g_object_unref (selection); +} + +static void +check_get_selection (GtkSelectionModel *selection) +{ + GtkBitset *set; + guint i, n_items; + + set = gtk_selection_model_get_selection (selection); + + n_items = g_list_model_get_n_items (G_LIST_MODEL (selection)); + if (n_items == 0) + { + g_assert_true (gtk_bitset_is_empty (set)); + } + else + { + for (i = 0; i < n_items; i++) + { + g_assert_cmpint (gtk_bitset_contains (set, i), ==, gtk_selection_model_is_selected (selection, i)); + } + + /* check that out-of-range has no bits set */ + g_assert_cmpint (gtk_bitset_get_maximum (set), <, g_list_model_get_n_items (G_LIST_MODEL (selection))); + } + + gtk_bitset_unref (set); +} + +static void +test_query_range (void) +{ + GtkSelectionModel *selection; + GListStore *store; + + store = new_store (1, 5, 1); + selection = new_model (store, TRUE, TRUE); + check_get_selection (selection); + + gtk_selection_model_unselect_item (selection, 0); + check_get_selection (selection); + + gtk_selection_model_select_item (selection, 2, TRUE); + check_get_selection (selection); + + gtk_selection_model_select_item (selection, 4, TRUE); + check_get_selection (selection); + + ignore_selection_changes (selection); + + g_object_unref (store); + g_object_unref (selection); +} + +static void +test_set_model (void) +{ + GtkSelectionModel *selection; + GListStore *store; + GListModel *m1, *m2; + + store = new_store (1, 5, 1); + m1 = G_LIST_MODEL (store); + m2 = G_LIST_MODEL (gtk_slice_list_model_new (g_object_ref (m1), 0, 3)); + selection = new_model (store, TRUE, TRUE); + assert_selection (selection, ""); + assert_selection_changes (selection, ""); + + /* we retain the selected item across model changes */ + gtk_no_selection_set_model (GTK_NO_SELECTION (selection), m2); + assert_changes (selection, "0-5+3*"); + assert_selection (selection, ""); + assert_selection_changes (selection, ""); + + gtk_no_selection_set_model (GTK_NO_SELECTION (selection), m1); + assert_changes (selection, "0-3+5*"); + assert_selection (selection, ""); + assert_selection_changes (selection, ""); + + gtk_no_selection_set_model (GTK_NO_SELECTION (selection), m2); + assert_changes (selection, "0-5+3*"); + assert_selection (selection, ""); + assert_selection_changes (selection, ""); + + /* we retain no selected item across model changes */ + gtk_no_selection_set_model (GTK_NO_SELECTION (selection), m1); + assert_changes (selection, "0-3+5*"); + assert_selection (selection, ""); + assert_selection_changes (selection, ""); + + gtk_no_selection_set_model (GTK_NO_SELECTION (selection), m1); + assert_changes (selection, ""); + assert_selection (selection, ""); + assert_selection_changes (selection, ""); + + g_object_unref (m2); + g_object_unref (m1); + g_object_unref (selection); +} + +static void +test_empty (void) +{ + GtkNoSelection *selection; + GListStore *store; + + selection = gtk_no_selection_new (NULL); + + g_assert_cmpuint (g_list_model_get_n_items (G_LIST_MODEL (selection)), ==, 0); + g_assert_null (g_list_model_get_item (G_LIST_MODEL (selection), 11)); + g_assert_true (g_list_model_get_item_type (G_LIST_MODEL (selection)) == G_TYPE_OBJECT); + g_assert_null (gtk_no_selection_get_model (GTK_NO_SELECTION (selection))); + + store = g_list_store_new (G_TYPE_OBJECT); + gtk_no_selection_set_model (selection, G_LIST_MODEL (store)); + g_object_unref (store); + + g_assert_cmpuint (g_list_model_get_n_items (G_LIST_MODEL (selection)), ==, 0); + g_assert_null (g_list_model_get_item (G_LIST_MODEL (selection), 11)); + + g_object_unref (selection); +} + +int +main (int argc, char *argv[]) +{ + (g_test_init) (&argc, &argv, NULL); + setlocale (LC_ALL, "C"); + + number_quark = g_quark_from_static_string ("Hell and fire was spawned to be released."); + changes_quark = g_quark_from_static_string ("What did I see? Can I believe what I saw?"); + selection_quark = g_quark_from_static_string ("Mana mana, badibidibi"); + + g_test_add_func ("/noselection/create", test_create); + g_test_add_func ("/noselection/create-empty", test_create_empty); + g_test_add_func ("/noselection/selection", test_selection); + g_test_add_func ("/noselection/query-range", test_query_range); + g_test_add_func ("/noselection/changes", test_changes); + g_test_add_func ("/noselection/set-model", test_set_model); + g_test_add_func ("/noselection/empty", test_empty); + + return g_test_run (); +} From 2cbb955e49d3765edc027f18ac924e36f727b38c Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 15 Jul 2022 07:15:07 -0400 Subject: [PATCH 3/8] rendernodeparser: Cosmetics --- gsk/gskrendernodeparser.c | 44 +++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/gsk/gskrendernodeparser.c b/gsk/gskrendernodeparser.c index 7e5a74db0c..25943ec305 100644 --- a/gsk/gskrendernodeparser.c +++ b/gsk/gskrendernodeparser.c @@ -982,7 +982,7 @@ parse_color_node (GtkCssParser *parser) { "color", parse_color, NULL, &color }, }; - parse_declarations (parser, declarations, G_N_ELEMENTS(declarations)); + parse_declarations (parser, declarations, G_N_ELEMENTS (declarations)); return gsk_color_node_new (&color, &bounds); } @@ -1003,7 +1003,7 @@ parse_linear_gradient_node_internal (GtkCssParser *parser, }; GskRenderNode *result; - parse_declarations (parser, declarations, G_N_ELEMENTS(declarations)); + parse_declarations (parser, declarations, G_N_ELEMENTS (declarations)); if (stops == NULL) { GskColorStop from = { 0.0, GDK_RGBA("AAFF00") }; @@ -1058,7 +1058,7 @@ parse_radial_gradient_node_internal (GtkCssParser *parser, }; GskRenderNode *result; - parse_declarations (parser, declarations, G_N_ELEMENTS(declarations)); + parse_declarations (parser, declarations, G_N_ELEMENTS (declarations)); if (stops == NULL) { GskColorStop from = { 0.0, GDK_RGBA("AAFF00") }; @@ -1108,7 +1108,7 @@ parse_conic_gradient_node (GtkCssParser *parser) }; GskRenderNode *result; - parse_declarations (parser, declarations, G_N_ELEMENTS(declarations)); + parse_declarations (parser, declarations, G_N_ELEMENTS (declarations)); if (stops == NULL) { GskColorStop from = { 0.0, GDK_RGBA("AAFF00") }; @@ -1142,7 +1142,7 @@ parse_inset_shadow_node (GtkCssParser *parser) { "blur", parse_double, NULL, &blur } }; - parse_declarations (parser, declarations, G_N_ELEMENTS(declarations)); + parse_declarations (parser, declarations, G_N_ELEMENTS (declarations)); return gsk_inset_shadow_node_new (&outline, &color, dx, dy, spread, blur); } @@ -1325,7 +1325,7 @@ parse_glshader_node (GtkCssParser *parser) GBytes *args = NULL; int len, i; - parse_declarations (parser, declarations, G_N_ELEMENTS(declarations)); + parse_declarations (parser, declarations, G_N_ELEMENTS (declarations)); for (len = 0; len < 4; len++) { @@ -1362,7 +1362,7 @@ parse_border_node (GtkCssParser *parser) { "colors", parse_colors4, NULL, &colors } }; - parse_declarations (parser, declarations, G_N_ELEMENTS(declarations)); + parse_declarations (parser, declarations, G_N_ELEMENTS (declarations)); return gsk_border_node_new (&outline, widths, colors); } @@ -1378,7 +1378,7 @@ parse_texture_node (GtkCssParser *parser) }; GskRenderNode *node; - parse_declarations (parser, declarations, G_N_ELEMENTS(declarations)); + parse_declarations (parser, declarations, G_N_ELEMENTS (declarations)); if (texture == NULL) texture = create_default_texture (); @@ -1402,7 +1402,7 @@ parse_cairo_node (GtkCssParser *parser) }; GskRenderNode *node; - parse_declarations (parser, declarations, G_N_ELEMENTS(declarations)); + parse_declarations (parser, declarations, G_N_ELEMENTS (declarations)); node = gsk_cairo_node_new (&bounds); @@ -1447,7 +1447,7 @@ parse_outset_shadow_node (GtkCssParser *parser) { "blur", parse_double, NULL, &blur } }; - parse_declarations (parser, declarations, G_N_ELEMENTS(declarations)); + parse_declarations (parser, declarations, G_N_ELEMENTS (declarations)); return gsk_outset_shadow_node_new (&outline, &color, dx, dy, spread, blur); } @@ -1463,7 +1463,7 @@ parse_transform_node (GtkCssParser *parser) }; GskRenderNode *result; - parse_declarations (parser, declarations, G_N_ELEMENTS(declarations)); + parse_declarations (parser, declarations, G_N_ELEMENTS (declarations)); if (child == NULL) child = create_default_render_node (); @@ -1490,7 +1490,7 @@ parse_opacity_node (GtkCssParser *parser) }; GskRenderNode *result; - parse_declarations (parser, declarations, G_N_ELEMENTS(declarations)); + parse_declarations (parser, declarations, G_N_ELEMENTS (declarations)); if (child == NULL) child = create_default_render_node (); @@ -1517,7 +1517,7 @@ parse_color_matrix_node (GtkCssParser *parser) graphene_vec4_init (&offset, 0, 0, 0, 0); - parse_declarations (parser, declarations, G_N_ELEMENTS(declarations)); + parse_declarations (parser, declarations, G_N_ELEMENTS (declarations)); if (child == NULL) child = create_default_render_node (); @@ -1544,7 +1544,7 @@ parse_cross_fade_node (GtkCssParser *parser) }; GskRenderNode *result; - parse_declarations (parser, declarations, G_N_ELEMENTS(declarations)); + parse_declarations (parser, declarations, G_N_ELEMENTS (declarations)); if (start == NULL) start = gsk_color_node_new (&GDK_RGBA("AAFF00"), &GRAPHENE_RECT_INIT (0, 0, 50, 50)); if (end == NULL) @@ -1571,7 +1571,7 @@ parse_blend_node (GtkCssParser *parser) }; GskRenderNode *result; - parse_declarations (parser, declarations, G_N_ELEMENTS(declarations)); + parse_declarations (parser, declarations, G_N_ELEMENTS (declarations)); if (bottom == NULL) bottom = gsk_color_node_new (&GDK_RGBA("AAFF00"), &GRAPHENE_RECT_INIT (0, 0, 50, 50)); if (top == NULL) @@ -1599,7 +1599,7 @@ parse_repeat_node (GtkCssParser *parser) GskRenderNode *result; guint parse_result; - parse_result = parse_declarations (parser, declarations, G_N_ELEMENTS(declarations)); + parse_result = parse_declarations (parser, declarations, G_N_ELEMENTS (declarations)); if (child == NULL) child = create_default_render_node (); @@ -1663,7 +1663,7 @@ parse_text_node (GtkCssParser *parser) }; GskRenderNode *result; - parse_declarations (parser, declarations, G_N_ELEMENTS(declarations)); + parse_declarations (parser, declarations, G_N_ELEMENTS (declarations)); if (font == NULL) { @@ -1721,7 +1721,7 @@ parse_blur_node (GtkCssParser *parser) }; GskRenderNode *result; - parse_declarations (parser, declarations, G_N_ELEMENTS(declarations)); + parse_declarations (parser, declarations, G_N_ELEMENTS (declarations)); if (child == NULL) child = create_default_render_node (); @@ -1743,7 +1743,7 @@ parse_clip_node (GtkCssParser *parser) }; GskRenderNode *result; - parse_declarations (parser, declarations, G_N_ELEMENTS(declarations)); + parse_declarations (parser, declarations, G_N_ELEMENTS (declarations)); if (child == NULL) child = create_default_render_node (); @@ -1768,7 +1768,7 @@ parse_rounded_clip_node (GtkCssParser *parser) }; GskRenderNode *result; - parse_declarations (parser, declarations, G_N_ELEMENTS(declarations)); + parse_declarations (parser, declarations, G_N_ELEMENTS (declarations)); if (child == NULL) child = create_default_render_node (); @@ -1790,7 +1790,7 @@ parse_shadow_node (GtkCssParser *parser) }; GskRenderNode *result; - parse_declarations (parser, declarations, G_N_ELEMENTS(declarations)); + parse_declarations (parser, declarations, G_N_ELEMENTS (declarations)); if (child == NULL) child = create_default_render_node (); @@ -1819,7 +1819,7 @@ parse_debug_node (GtkCssParser *parser) }; GskRenderNode *result; - parse_declarations (parser, declarations, G_N_ELEMENTS(declarations)); + parse_declarations (parser, declarations, G_N_ELEMENTS (declarations)); if (child == NULL) child = create_default_render_node (); From 69336fa5f182b4ede201e0553afc9444c88f00d8 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 15 Jul 2022 07:42:35 -0400 Subject: [PATCH 4/8] node-editor: Make the help more helpful I struggled to remember how newlines vs strings work in this format, so put it in the docs. --- demos/node-editor/node-format.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/demos/node-editor/node-format.md b/demos/node-editor/node-format.md index cc457f1a20..9664090274 100644 --- a/demos/node-editor/node-format.md +++ b/demos/node-editor/node-format.md @@ -13,6 +13,8 @@ Each node has its own `` and supports a custom set of properties, eac When serializing and the value of a property equals the default value, this value will not be serialized. Serialization aims to produce an output as small as possible. +To embed newlines in strings, use \A. To break a long string into multiple lines, escape the newline with a \. + # Nodes ### container From 35e6a2fdb83c17a2ce27c6deb442d7efe28b7fec Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 15 Jul 2022 08:36:35 -0400 Subject: [PATCH 5/8] node-editor: Sort help better Move the gshader section where it belongs. --- demos/node-editor/node-format.md | 34 ++++++++++++++++---------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/demos/node-editor/node-format.md b/demos/node-editor/node-format.md index 9664090274..ca9417f7d0 100644 --- a/demos/node-editor/node-format.md +++ b/demos/node-editor/node-format.md @@ -137,6 +137,23 @@ Creates a node like `gsk_cross_fade_node_new()` with the given properties. Creates a node like `gsk_debug_node_new()` with the given properties. +### glshader + +| property | syntax | default | printed | +| ---------- | ------------------ | ---------------------- | ----------- | +| bounds | `` | 50 | always | +| sourcecode | `` | "" | always | +| args | `` | none | non-default | +| child1 | `` | none | non-default | +| child2 | `` | none | non-default | +| child3 | `` | none | non-default | +| child4 | `` | none | non-default | + +Creates a GLShader node. The `sourcecode` must be a GLSL fragment shader. +The `args` must match the uniforms of simple types declared in that shader, +in order and comma-separated. The `child` properties must match the sampler +uniforms in the shader. + ### inset-shadow | property | syntax | default | printed | @@ -288,20 +305,3 @@ representation for this texture is `url("data:image/png;base64,iVBORw0KGgoAAAANS | transform| `` | none | non-default | Creates a node like `gsk_transform_node_new()` with the given properties. - -### glshader - -| property | syntax | default | printed | -| ---------- | ------------------ | ---------------------- | ----------- | -| bounds | `` | 50 | always | -| sourcecode | `` | "" | always | -| args | `` | none | non-default | -| child1 | `` | none | non-default | -| child2 | `` | none | non-default | -| child3 | `` | none | non-default | -| child4 | `` | none | non-default | - -Creates a GLShader node. The `sourcecode` must be a GLSL fragment shader. -The `args` must match the uniforms of simple types declared in that shader, -in order and comma-separated. The `child` properties must match the sampler -uniforms in the shader. From 7ebc5454f4d31e01e2a34c4fbbcaa4d21b9edbc9 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 15 Jul 2022 10:24:41 -0400 Subject: [PATCH 6/8] Drop an unused function --- gsk/gskprivate.c | 20 -------------------- gsk/gskprivate.h | 2 -- 2 files changed, 22 deletions(-) diff --git a/gsk/gskprivate.c b/gsk/gskprivate.c index d9e1c3e30f..8404b9dbc6 100644 --- a/gsk/gskprivate.c +++ b/gsk/gskprivate.c @@ -15,23 +15,3 @@ gsk_ensure_resources (void) g_once (®ister_resources_once, register_resources, NULL); } - -int -pango_glyph_string_num_glyphs (PangoGlyphString *glyphs) -{ - int i, count; - - count = 0; - for (i = 0; i < glyphs->num_glyphs; i++) - { - PangoGlyphInfo *gi = &glyphs->glyphs[i]; - if (gi->glyph != PANGO_GLYPH_EMPTY) - { - if (!(gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG)) - count++; - } - } - - return count; -} - diff --git a/gsk/gskprivate.h b/gsk/gskprivate.h index 77c0fe2bf6..a8b92b4b18 100644 --- a/gsk/gskprivate.h +++ b/gsk/gskprivate.h @@ -8,8 +8,6 @@ G_BEGIN_DECLS void gsk_ensure_resources (void); -int pango_glyph_string_num_glyphs (PangoGlyphString *glyphs) G_GNUC_PURE; - typedef struct _GskVulkanRender GskVulkanRender; typedef struct _GskVulkanRenderPass GskVulkanRenderPass; From a4c6517d069d8d5e72fcf66ee37b6d863cd52b56 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 15 Jul 2022 14:40:55 -0400 Subject: [PATCH 7/8] glshader: Add preconditions Add preconditions to many of the glshader uniform apis. --- gsk/gskglshader.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/gsk/gskglshader.c b/gsk/gskglshader.c index 7823651b8b..b8d5566d29 100644 --- a/gsk/gskglshader.c +++ b/gsk/gskglshader.c @@ -162,6 +162,7 @@ uniform_type_from_glsl (const char *str) return GSK_GL_UNIFORM_TYPE_NONE; } +#ifdef G_ENABLE_DEBUG static const char * uniform_type_name (GskGLUniformType type) { @@ -194,6 +195,7 @@ uniform_type_name (GskGLUniformType type) return NULL; } } +#endif static int uniform_type_size (GskGLUniformType type) @@ -397,6 +399,7 @@ gsk_gl_shader_constructed (GObject *object) shader->n_textures = max_texture_seen; +#ifdef G_ENABLE_DEBUG if (GSK_DEBUG_CHECK(SHADERS)) { GString *s; @@ -414,6 +417,7 @@ gsk_gl_shader_constructed (GObject *object) s->str); g_string_free (s, TRUE); } +#endif } #define SPACE_RE "[ \\t]+" // Don't use \s, we don't want to match newlines @@ -631,6 +635,7 @@ gsk_gl_shader_get_uniform_name (GskGLShader *shader, int idx) { g_return_val_if_fail (GSK_IS_GL_SHADER (shader), NULL); + g_return_val_if_fail (0 <= idx && idx < shader->uniforms->len, NULL); return g_array_index (shader->uniforms, GskGLUniform, idx).name; } @@ -675,6 +680,7 @@ gsk_gl_shader_get_uniform_type (GskGLShader *shader, int idx) { g_return_val_if_fail (GSK_IS_GL_SHADER (shader), 0); + g_return_val_if_fail (0 <= idx && idx < shader->uniforms->len, 0); return g_array_index (shader->uniforms, GskGLUniform, idx).type; } @@ -693,6 +699,7 @@ gsk_gl_shader_get_uniform_offset (GskGLShader *shader, int idx) { g_return_val_if_fail (GSK_IS_GL_SHADER (shader), 0); + g_return_val_if_fail (0 <= idx && idx < shader->uniforms->len, 0); return g_array_index (shader->uniforms, GskGLUniform, idx).offset; } From 5064a8eac02d9bb0ce7aea82ed6ca53d58eedc32 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 15 Jul 2022 09:42:45 -0400 Subject: [PATCH 8/8] gsk: Improve test coverage --- testsuite/gsk/diff.c | 9 ++ testsuite/gsk/meson.build | 32 ++++- testsuite/gsk/misc.c | 96 +++++++++++++++ testsuite/gsk/nodeparser/conic-gradient.node | 6 + .../gsk/nodeparser/conic-gradient.ref.node | 6 + testsuite/gsk/nodeparser/debug-fail.errors | 2 + testsuite/gsk/nodeparser/debug-fail.node | 8 ++ testsuite/gsk/nodeparser/debug-fail.ref.node | 5 + testsuite/gsk/nodeparser/glshader.errors | 1 + testsuite/gsk/nodeparser/glshader.node | 11 ++ testsuite/gsk/nodeparser/glshader.ref.node | 11 ++ testsuite/gsk/nodeparser/gradient-fail.errors | 1 + testsuite/gsk/nodeparser/gradient-fail.node | 4 + .../gsk/nodeparser/gradient-fail.ref.node | 6 + testsuite/gsk/nodeparser/radial-gradient.node | 9 ++ .../gsk/nodeparser/radial-gradient.ref.node | 9 ++ .../nodeparser/repeating-linear-gradient.node | 6 + .../repeating-linear-gradient.ref.node | 6 + .../nodeparser/repeating-radial-gradient.node | 9 ++ .../repeating-radial-gradient.ref.node | 9 ++ testsuite/gsk/nodeparser/shadow-fail.errors | 9 ++ testsuite/gsk/nodeparser/shadow-fail.node | 4 + testsuite/gsk/nodeparser/shadow-fail.ref.node | 7 ++ testsuite/gsk/nodeparser/text-fail.errors | 3 + testsuite/gsk/nodeparser/text-fail.node | 8 ++ testsuite/gsk/nodeparser/text-fail.ref.node | 4 + testsuite/gsk/nodeparser/texture-fail.errors | 1 + testsuite/gsk/nodeparser/texture-fail.node | 3 + .../gsk/nodeparser/texture-fail.ref.node | 6 + .../gsk/nodeparser/transform-fail.errors | 1 + testsuite/gsk/nodeparser/transform-fail.node | 3 + .../gsk/nodeparser/transform-fail.ref.node | 6 + testsuite/gsk/rounded-rect.c | 48 ++++++++ testsuite/gsk/shader.c | 55 +++++++++ testsuite/gsk/transform.c | 112 ++++++++++++++++++ 35 files changed, 515 insertions(+), 1 deletion(-) create mode 100644 testsuite/gsk/misc.c create mode 100644 testsuite/gsk/nodeparser/conic-gradient.node create mode 100644 testsuite/gsk/nodeparser/conic-gradient.ref.node create mode 100644 testsuite/gsk/nodeparser/debug-fail.errors create mode 100644 testsuite/gsk/nodeparser/debug-fail.node create mode 100644 testsuite/gsk/nodeparser/debug-fail.ref.node create mode 100644 testsuite/gsk/nodeparser/glshader.errors create mode 100644 testsuite/gsk/nodeparser/glshader.node create mode 100644 testsuite/gsk/nodeparser/glshader.ref.node create mode 100644 testsuite/gsk/nodeparser/gradient-fail.errors create mode 100644 testsuite/gsk/nodeparser/gradient-fail.node create mode 100644 testsuite/gsk/nodeparser/gradient-fail.ref.node create mode 100644 testsuite/gsk/nodeparser/radial-gradient.node create mode 100644 testsuite/gsk/nodeparser/radial-gradient.ref.node create mode 100644 testsuite/gsk/nodeparser/repeating-linear-gradient.node create mode 100644 testsuite/gsk/nodeparser/repeating-linear-gradient.ref.node create mode 100644 testsuite/gsk/nodeparser/repeating-radial-gradient.node create mode 100644 testsuite/gsk/nodeparser/repeating-radial-gradient.ref.node create mode 100644 testsuite/gsk/nodeparser/shadow-fail.errors create mode 100644 testsuite/gsk/nodeparser/shadow-fail.node create mode 100644 testsuite/gsk/nodeparser/shadow-fail.ref.node create mode 100644 testsuite/gsk/nodeparser/text-fail.errors create mode 100644 testsuite/gsk/nodeparser/text-fail.node create mode 100644 testsuite/gsk/nodeparser/text-fail.ref.node create mode 100644 testsuite/gsk/nodeparser/texture-fail.errors create mode 100644 testsuite/gsk/nodeparser/texture-fail.node create mode 100644 testsuite/gsk/nodeparser/texture-fail.ref.node create mode 100644 testsuite/gsk/nodeparser/transform-fail.errors create mode 100644 testsuite/gsk/nodeparser/transform-fail.node create mode 100644 testsuite/gsk/nodeparser/transform-fail.ref.node diff --git a/testsuite/gsk/diff.c b/testsuite/gsk/diff.c index 2bc34ebec6..28ee4ff1f8 100644 --- a/testsuite/gsk/diff.c +++ b/testsuite/gsk/diff.c @@ -25,6 +25,7 @@ test_can_diff_basic (void) { GskRenderNode *container1, *container2; GskRenderNode *color1, *color2; + GskRenderNode *debug1, *debug2; color1 = gsk_color_node_new (&(GdkRGBA){0, 1, 0, 1 }, &GRAPHENE_RECT_INIT (0, 0, 10, 10)); color2 = gsk_color_node_new (&(GdkRGBA){1, 1, 0, 1 }, &GRAPHENE_RECT_INIT (0, 0, 10, 10)); @@ -32,10 +33,15 @@ test_can_diff_basic (void) container1 = gsk_container_node_new (&color1, 1); container2 = gsk_container_node_new (&color2, 1); + debug1 = gsk_debug_node_new (color1, g_strdup ("Debug node!")); + debug2 = gsk_debug_node_new (color2, g_strdup ("Debug node!")); + /* We can diff two color nodes */ g_assert_true (gsk_render_node_can_diff (color1, color2)); /* We can diff two container nodes */ g_assert_true (gsk_render_node_can_diff (container1, container2)); + /* We can diff two debug nodes */ + g_assert_true (gsk_render_node_can_diff (debug1, debug2)); /* We can diff container nodes against anything else */ g_assert_true (gsk_render_node_can_diff (container1, color2)); g_assert_true (gsk_render_node_can_diff (color1, container2)); @@ -45,6 +51,9 @@ test_can_diff_basic (void) gsk_render_node_unref (container1); gsk_render_node_unref (container2); + + gsk_render_node_unref (debug1); + gsk_render_node_unref (debug2); } static void diff --git a/testsuite/gsk/meson.build b/testsuite/gsk/meson.build index 317f6a6670..82fe0d5dfc 100644 --- a/testsuite/gsk/meson.build +++ b/testsuite/gsk/meson.build @@ -129,6 +129,8 @@ node_parser_tests = [ 'blend.node', 'border.node', 'color.node', + 'conic-gradient.node', + 'conic-gradient.ref.node', 'crash1.errors', 'crash1.node', 'crash1.ref.node', @@ -141,6 +143,9 @@ node_parser_tests = [ 'crash4.node', 'crash4.ref.node', 'debug.node', + 'debug-fail.node', + 'debug-fail.ref.node', + 'debug-fail.errors', 'empty-blend.node', 'empty-blend.ref.node', 'empty-blur.node', @@ -181,9 +186,33 @@ node_parser_tests = [ 'empty-texture.ref.node', 'empty-transform.node', 'empty-transform.ref.node', + 'glshader.node', + 'glshader.ref.node', + 'glshader.errors', + 'gradient-fail.node', + 'gradient-fail.ref.node', + 'gradient-fail.errors', + 'radial-gradient.node', + 'radial-gradient.ref.node', + 'repeating-linear-gradient.node', + 'repeating-linear-gradient.ref.node', + 'repeating-radial-gradient.node', + 'repeating-radial-gradient.ref.node', 'rounded-rect.node', 'shadow.node', + 'shadow-fail.node', + 'shadow-fail.ref.node', + 'shadow-fail.errors', 'testswitch.node', + 'text-fail.node', + 'text-fail.ref.node', + 'text-fail.errors', + 'texture-fail.node', + 'texture-fail.ref.node', + 'texture-fail.ref.errors', + 'transform-fail.node', + 'transform-fail.ref.node', + 'transform-fail.errors', 'widgetfactory.node', ] @@ -205,7 +234,6 @@ foreach test : node_parser_tests endforeach tests = [ - ['rounded-rect'], ['transform'], ['shader'], ] @@ -242,6 +270,8 @@ endforeach internal_tests = [ [ 'diff' ], [ 'half-float' ], + ['rounded-rect'], + ['misc'], ] foreach t : internal_tests diff --git a/testsuite/gsk/misc.c b/testsuite/gsk/misc.c new file mode 100644 index 0000000000..7b4af1cf28 --- /dev/null +++ b/testsuite/gsk/misc.c @@ -0,0 +1,96 @@ +#include +#include "gsk/gskrendernodeprivate.h" + +static void +test_rendernode_gvalue (void) +{ + GValue value = G_VALUE_INIT; + GskRenderNode *node, *node2; + + g_assert_false (GSK_VALUE_HOLDS_RENDER_NODE (&value)); + g_value_init (&value, GSK_TYPE_RENDER_NODE); + g_assert_true (GSK_VALUE_HOLDS_RENDER_NODE (&value)); + + node = gsk_value_get_render_node (&value); + g_assert_null (node); + + node = gsk_color_node_new (&(GdkRGBA){0,1,1,1}, &GRAPHENE_RECT_INIT (0, 0, 50, 50)); + gsk_value_set_render_node (&value, node); + + node2 = gsk_value_dup_render_node (&value); + g_assert_true (node == node2); + + g_value_reset (&value); + gsk_value_take_render_node (&value, node); + + g_value_unset (&value); +} + +static void +test_bordernode_uniform (void) +{ + GskRenderNode *node; + GskRoundedRect rect; + GdkRGBA colors[4] = { + { 0, 0, 0, 1 }, + { 0, 0, 0, 1 }, + { 0, 0, 0, 1 }, + { 0, 0, 0, 1 }, + }; + + gsk_rounded_rect_init (&rect, + &GRAPHENE_RECT_INIT (0, 0, 50, 50), + &GRAPHENE_SIZE_INIT (10, 10), + &GRAPHENE_SIZE_INIT (10, 10), + &GRAPHENE_SIZE_INIT (10, 10), + &GRAPHENE_SIZE_INIT (10, 10)); + + node = gsk_border_node_new (&rect, (const float[]){ 1, 1, 1, 1}, colors); + + g_assert_true (gsk_border_node_get_uniform (node)); + g_assert_true (gsk_border_node_get_uniform_color (node)); + + gsk_render_node_unref (node); + + node = gsk_border_node_new (&rect, (const float[]){ 1, 2, 3, 4}, colors); + + g_assert_false (gsk_border_node_get_uniform (node)); + g_assert_true (gsk_border_node_get_uniform_color (node)); + + gsk_render_node_unref (node); +} + +#define DEG_TO_RAD(x) ((x) * (G_PI / 180.f)) + +static void +test_conic_gradient_angle (void) +{ + GskRenderNode *node; + GskColorStop stops[] = { + { 0.f, (GdkRGBA) { 0, 0, 0, 1} }, + { 1.f, (GdkRGBA) { 1, 0, 1, 1} }, + }; + + node = gsk_conic_gradient_node_new (&GRAPHENE_RECT_INIT (0, 0, 50, 50), + &GRAPHENE_POINT_INIT (10, 20), + 33.f, + stops, + G_N_ELEMENTS (stops)); + + g_assert_cmpfloat_with_epsilon (gsk_conic_gradient_node_get_angle (node), DEG_TO_RAD (90.f - 33.f), 0.001); + + gsk_render_node_unref (node); +} + +int +main (int argc, char *argv[]) +{ + (g_test_init) (&argc, &argv, NULL); + gtk_init (); + + g_test_add_func ("/rendernode/gvalue", test_rendernode_gvalue); + g_test_add_func ("/rendernode/border/uniform", test_bordernode_uniform); + g_test_add_func ("/rendernode/conic-gradient/angle", test_conic_gradient_angle); + + return g_test_run (); +} diff --git a/testsuite/gsk/nodeparser/conic-gradient.node b/testsuite/gsk/nodeparser/conic-gradient.node new file mode 100644 index 0000000000..d42bfbbf47 --- /dev/null +++ b/testsuite/gsk/nodeparser/conic-gradient.node @@ -0,0 +1,6 @@ +conic-gradient { + bounds: 0 0 50 50; + center: 20 30; + rotation: 25; + stops: 0 #444, 0.2 #0F0, 1 #F0A; +} \ No newline at end of file diff --git a/testsuite/gsk/nodeparser/conic-gradient.ref.node b/testsuite/gsk/nodeparser/conic-gradient.ref.node new file mode 100644 index 0000000000..dce5e637b5 --- /dev/null +++ b/testsuite/gsk/nodeparser/conic-gradient.ref.node @@ -0,0 +1,6 @@ +conic-gradient { + bounds: 0 0 50 50; + center: 20 30; + rotation: 25; + stops: 0 rgb(68,68,68), 0.2 rgb(0,255,0), 1 rgb(255,0,170); +} diff --git a/testsuite/gsk/nodeparser/debug-fail.errors b/testsuite/gsk/nodeparser/debug-fail.errors new file mode 100644 index 0000000000..e8b664c7d9 --- /dev/null +++ b/testsuite/gsk/nodeparser/debug-fail.errors @@ -0,0 +1,2 @@ +:5:10-11: error: GTK_CSS_PARSER_WARNING_SYNTAX +:6:8-9: error: GTK_CSS_PARSER_WARNING_SYNTAX diff --git a/testsuite/gsk/nodeparser/debug-fail.node b/testsuite/gsk/nodeparser/debug-fail.node new file mode 100644 index 0000000000..3ad439296e --- /dev/null +++ b/testsuite/gsk/nodeparser/debug-fail.node @@ -0,0 +1,8 @@ +debug { + message: "I'm a debug node."; + child: container { + } + message: "With repeating message and child."; + child: container { + } +} diff --git a/testsuite/gsk/nodeparser/debug-fail.ref.node b/testsuite/gsk/nodeparser/debug-fail.ref.node new file mode 100644 index 0000000000..c59d7b7743 --- /dev/null +++ b/testsuite/gsk/nodeparser/debug-fail.ref.node @@ -0,0 +1,5 @@ +debug { + message: "With repeating message and child."; + child: container { + } +} diff --git a/testsuite/gsk/nodeparser/glshader.errors b/testsuite/gsk/nodeparser/glshader.errors new file mode 100644 index 0000000000..f345ed1ef5 --- /dev/null +++ b/testsuite/gsk/nodeparser/glshader.errors @@ -0,0 +1 @@ +:10:43-47: error: GTK_CSS_PARSER_ERROR_SYNTAX diff --git a/testsuite/gsk/nodeparser/glshader.node b/testsuite/gsk/nodeparser/glshader.node new file mode 100644 index 0000000000..0e6be6e0a1 --- /dev/null +++ b/testsuite/gsk/nodeparser/glshader.node @@ -0,0 +1,11 @@ +glshader { + bounds: 0 0 50 50; + sourcecode: "uniform vec3 iResolution;\A\ +uniform vec4 another;\A\ +uniform vec2 point;\A\ +uniform int iii;\A\ +uniform uint uuu;\A\ +uniform bool bbb;\A\ +uniform float num;"; + args: 10 20 30, 1 2 3 4, -1 -2, 0, 100, true, 3.1415; +} diff --git a/testsuite/gsk/nodeparser/glshader.ref.node b/testsuite/gsk/nodeparser/glshader.ref.node new file mode 100644 index 0000000000..3fbec15acb --- /dev/null +++ b/testsuite/gsk/nodeparser/glshader.ref.node @@ -0,0 +1,11 @@ +glshader { + bounds: 0 0 50 50; + sourcecode: "uniform vec3 iResolution;\A\ +uniform vec4 another;\A\ +uniform vec2 point;\A\ +uniform int iii;\A\ +uniform uint uuu;\A\ +uniform bool bbb;\A\ +uniform float num;"; + args: 10 20 30, 1 2 3 4, -1 -2, 0, 100, 0, 0; +} diff --git a/testsuite/gsk/nodeparser/gradient-fail.errors b/testsuite/gsk/nodeparser/gradient-fail.errors new file mode 100644 index 0000000000..052224ba76 --- /dev/null +++ b/testsuite/gsk/nodeparser/gradient-fail.errors @@ -0,0 +1 @@ +:3:8-9: error: GTK_CSS_PARSER_WARNING_SYNTAX diff --git a/testsuite/gsk/nodeparser/gradient-fail.node b/testsuite/gsk/nodeparser/gradient-fail.node new file mode 100644 index 0000000000..c9b57fc3be --- /dev/null +++ b/testsuite/gsk/nodeparser/gradient-fail.node @@ -0,0 +1,4 @@ +repeating-linear-gradient { + stops: 0 #FF0, 0.25 #F0A, 1 #0FF; + stops: 0 #FF0, 0.25 #F0A, 1 #0FF; +} diff --git a/testsuite/gsk/nodeparser/gradient-fail.ref.node b/testsuite/gsk/nodeparser/gradient-fail.ref.node new file mode 100644 index 0000000000..9352158ba4 --- /dev/null +++ b/testsuite/gsk/nodeparser/gradient-fail.ref.node @@ -0,0 +1,6 @@ +repeating-linear-gradient { + bounds: 0 0 50 50; + start: 0 0; + end: 0 50; + stops: 0 rgb(255,255,0), 0.25 rgb(255,0,170), 1 rgb(0,255,255); +} diff --git a/testsuite/gsk/nodeparser/radial-gradient.node b/testsuite/gsk/nodeparser/radial-gradient.node new file mode 100644 index 0000000000..cd34ee2be0 --- /dev/null +++ b/testsuite/gsk/nodeparser/radial-gradient.node @@ -0,0 +1,9 @@ +radial-gradient { + bounds: 0 0 50 50; + center: 20 20; + hradius: 10; + vradius: 20; + start: 0.25; + end: 0.75; + stops: 0 #FF0, 0.5 #ABC, 1 #F0F; +} \ No newline at end of file diff --git a/testsuite/gsk/nodeparser/radial-gradient.ref.node b/testsuite/gsk/nodeparser/radial-gradient.ref.node new file mode 100644 index 0000000000..538ac522a5 --- /dev/null +++ b/testsuite/gsk/nodeparser/radial-gradient.ref.node @@ -0,0 +1,9 @@ +radial-gradient { + bounds: 0 0 50 50; + center: 20 20; + hradius: 10; + vradius: 20; + start: 0.25; + end: 0.75; + stops: 0 rgb(255,255,0), 0.5 rgb(170,187,204), 1 rgb(255,0,255); +} diff --git a/testsuite/gsk/nodeparser/repeating-linear-gradient.node b/testsuite/gsk/nodeparser/repeating-linear-gradient.node new file mode 100644 index 0000000000..f8ed50e58a --- /dev/null +++ b/testsuite/gsk/nodeparser/repeating-linear-gradient.node @@ -0,0 +1,6 @@ +repeating-linear-gradient { + bounds: 0 0 50 50; + start: 50 0; + end: 25 25; + stops: 0 #FF0, 0.25 #F0A, 1 #0FF; +} \ No newline at end of file diff --git a/testsuite/gsk/nodeparser/repeating-linear-gradient.ref.node b/testsuite/gsk/nodeparser/repeating-linear-gradient.ref.node new file mode 100644 index 0000000000..4985680ef0 --- /dev/null +++ b/testsuite/gsk/nodeparser/repeating-linear-gradient.ref.node @@ -0,0 +1,6 @@ +repeating-linear-gradient { + bounds: 0 0 50 50; + start: 50 0; + end: 25 25; + stops: 0 rgb(255,255,0), 0.25 rgb(255,0,170), 1 rgb(0,255,255); +} diff --git a/testsuite/gsk/nodeparser/repeating-radial-gradient.node b/testsuite/gsk/nodeparser/repeating-radial-gradient.node new file mode 100644 index 0000000000..5415d1e839 --- /dev/null +++ b/testsuite/gsk/nodeparser/repeating-radial-gradient.node @@ -0,0 +1,9 @@ +repeating-radial-gradient { + bounds: 0 0 50 50; + center: 20 30; + hradius: 30; + vradius: 20; + start: 0.25; + end: 0.75; + stops: 0 #F0F, 1 #0F0; +} \ No newline at end of file diff --git a/testsuite/gsk/nodeparser/repeating-radial-gradient.ref.node b/testsuite/gsk/nodeparser/repeating-radial-gradient.ref.node new file mode 100644 index 0000000000..4aa3eeed8d --- /dev/null +++ b/testsuite/gsk/nodeparser/repeating-radial-gradient.ref.node @@ -0,0 +1,9 @@ +repeating-radial-gradient { + bounds: 0 0 50 50; + center: 20 30; + hradius: 30; + vradius: 20; + start: 0.25; + end: 0.75; + stops: 0 rgb(255,0,255), 1 rgb(0,255,0); +} diff --git a/testsuite/gsk/nodeparser/shadow-fail.errors b/testsuite/gsk/nodeparser/shadow-fail.errors new file mode 100644 index 0000000000..bb77a372fc --- /dev/null +++ b/testsuite/gsk/nodeparser/shadow-fail.errors @@ -0,0 +1,9 @@ +:2:11-13: error: GTK_CSS_PARSER_ERROR_SYNTAX +:2:11-13: error: GTK_CSS_PARSER_ERROR_UNKNOWN_VALUE +:2:13-14: error: GTK_CSS_PARSER_ERROR_SYNTAX +:2:13-14: error: GTK_CSS_PARSER_ERROR_UNKNOWN_VALUE +:3:9-10: error: GTK_CSS_PARSER_WARNING_SYNTAX +:3:11-13: error: GTK_CSS_PARSER_ERROR_SYNTAX +:3:11-13: error: GTK_CSS_PARSER_ERROR_UNKNOWN_VALUE +:3:13-14: error: GTK_CSS_PARSER_ERROR_SYNTAX +:3:13-14: error: GTK_CSS_PARSER_ERROR_UNKNOWN_VALUE diff --git a/testsuite/gsk/nodeparser/shadow-fail.node b/testsuite/gsk/nodeparser/shadow-fail.node new file mode 100644 index 0000000000..5b851e7eb1 --- /dev/null +++ b/testsuite/gsk/nodeparser/shadow-fail.node @@ -0,0 +1,4 @@ +shadow { + shadows: 22; + shadows: 22; +} diff --git a/testsuite/gsk/nodeparser/shadow-fail.ref.node b/testsuite/gsk/nodeparser/shadow-fail.ref.node new file mode 100644 index 0000000000..77e42196fb --- /dev/null +++ b/testsuite/gsk/nodeparser/shadow-fail.ref.node @@ -0,0 +1,7 @@ +shadow { + shadows: rgb(0,0,0) 22 0, rgb(0,0,0) 22 0; + child: color { + bounds: 0 0 50 50; + color: rgb(255,0,204); + } +} diff --git a/testsuite/gsk/nodeparser/text-fail.errors b/testsuite/gsk/nodeparser/text-fail.errors new file mode 100644 index 0000000000..1df16b5cff --- /dev/null +++ b/testsuite/gsk/nodeparser/text-fail.errors @@ -0,0 +1,3 @@ +:4:7-8: error: GTK_CSS_PARSER_WARNING_SYNTAX +:6:9-10: error: GTK_CSS_PARSER_WARNING_SYNTAX +:8:1-2: error: GTK_CSS_PARSER_ERROR_UNKNOWN_VALUE diff --git a/testsuite/gsk/nodeparser/text-fail.node b/testsuite/gsk/nodeparser/text-fail.node new file mode 100644 index 0000000000..cbbf594fd4 --- /dev/null +++ b/testsuite/gsk/nodeparser/text-fail.node @@ -0,0 +1,8 @@ +text { + color: rgb(50,50,50); + font: ""; + font: ""; + glyphs: "N"; + glyphs: "N"; + offset: 0 32.0186; +} diff --git a/testsuite/gsk/nodeparser/text-fail.ref.node b/testsuite/gsk/nodeparser/text-fail.ref.node new file mode 100644 index 0000000000..404fb1b892 --- /dev/null +++ b/testsuite/gsk/nodeparser/text-fail.ref.node @@ -0,0 +1,4 @@ +color { + bounds: 0 0 50 50; + color: rgb(255,0,204); +} diff --git a/testsuite/gsk/nodeparser/texture-fail.errors b/testsuite/gsk/nodeparser/texture-fail.errors new file mode 100644 index 0000000000..cc436f0e71 --- /dev/null +++ b/testsuite/gsk/nodeparser/texture-fail.errors @@ -0,0 +1 @@ +:2:12-14: error: GTK_CSS_PARSER_ERROR_SYNTAX diff --git a/testsuite/gsk/nodeparser/texture-fail.node b/testsuite/gsk/nodeparser/texture-fail.node new file mode 100644 index 0000000000..996ada6181 --- /dev/null +++ b/testsuite/gsk/nodeparser/texture-fail.node @@ -0,0 +1,3 @@ +texture { + texture: 22; +} diff --git a/testsuite/gsk/nodeparser/texture-fail.ref.node b/testsuite/gsk/nodeparser/texture-fail.ref.node new file mode 100644 index 0000000000..b8027cb332 --- /dev/null +++ b/testsuite/gsk/nodeparser/texture-fail.ref.node @@ -0,0 +1,6 @@ +texture { + bounds: 0 0 50 50; + texture: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAKUlEQVQYlWP8z3DmPwMaYGQwYUQX\ +Y0IXwAUGUCGGoxkYGBiweXAoeAYAz44F3e3U1xUAAAAASUVORK5CYII=\ +"); +} diff --git a/testsuite/gsk/nodeparser/transform-fail.errors b/testsuite/gsk/nodeparser/transform-fail.errors new file mode 100644 index 0000000000..a951d27419 --- /dev/null +++ b/testsuite/gsk/nodeparser/transform-fail.errors @@ -0,0 +1 @@ +:2:14-16: error: GTK_CSS_PARSER_ERROR_SYNTAX diff --git a/testsuite/gsk/nodeparser/transform-fail.node b/testsuite/gsk/nodeparser/transform-fail.node new file mode 100644 index 0000000000..676dde3755 --- /dev/null +++ b/testsuite/gsk/nodeparser/transform-fail.node @@ -0,0 +1,3 @@ +transform { + transform: 22; +} \ No newline at end of file diff --git a/testsuite/gsk/nodeparser/transform-fail.ref.node b/testsuite/gsk/nodeparser/transform-fail.ref.node new file mode 100644 index 0000000000..8a63720daa --- /dev/null +++ b/testsuite/gsk/nodeparser/transform-fail.ref.node @@ -0,0 +1,6 @@ +transform { + child: color { + bounds: 0 0 50 50; + color: rgb(255,0,204); + } +} diff --git a/testsuite/gsk/rounded-rect.c b/testsuite/gsk/rounded-rect.c index 78bae68ab2..0127d1cb54 100644 --- a/testsuite/gsk/rounded-rect.c +++ b/testsuite/gsk/rounded-rect.c @@ -20,6 +20,7 @@ #include "config.h" #include +#include static void test_contains_rect (void) @@ -114,6 +115,51 @@ test_contains_point (void) g_assert_true (gsk_rounded_rect_contains_point (&rect, &GRAPHENE_POINT_INIT (10, 95))); } +static void +test_is_circular (void) +{ + GskRoundedRect rect; + + gsk_rounded_rect_init (&rect, + &GRAPHENE_RECT_INIT (0, 0, 100, 100), + &GRAPHENE_SIZE_INIT (0, 0), + &GRAPHENE_SIZE_INIT (10, 10), + &GRAPHENE_SIZE_INIT (10, 20), + &GRAPHENE_SIZE_INIT (20, 10)); + + g_assert_false (gsk_rounded_rect_is_circular (&rect)); + + gsk_rounded_rect_init (&rect, + &GRAPHENE_RECT_INIT (0, 0, 100, 100), + &GRAPHENE_SIZE_INIT (0, 0), + &GRAPHENE_SIZE_INIT (10, 10), + &GRAPHENE_SIZE_INIT (20, 20), + &GRAPHENE_SIZE_INIT (30, 30)); + + g_assert_true (gsk_rounded_rect_is_circular (&rect)); +} + +static void +test_to_float (void) +{ + GskRoundedRect rect; + float flt[12]; + + gsk_rounded_rect_init (&rect, + &GRAPHENE_RECT_INIT (0, 11, 22, 33), + &GRAPHENE_SIZE_INIT (4, 5), + &GRAPHENE_SIZE_INIT (6, 7), + &GRAPHENE_SIZE_INIT (8, 9), + &GRAPHENE_SIZE_INIT (10, 11)); + + gsk_rounded_rect_to_float (&rect, flt); + g_assert_true (flt[0] == 0. && flt[1] == 11. && flt[2] == 22. && flt[3] == 33.); + g_assert_true (flt[4] == 4. && flt[5] == 6.); + g_assert_true (flt[6] == 8. && flt[7] == 10.); + g_assert_true (flt[8] == 5. && flt[9] == 7.); + g_assert_true (flt[10] == 9. && flt[11] == 11.); +} + int main (int argc, char *argv[]) @@ -123,6 +169,8 @@ main (int argc, g_test_add_func ("/rounded-rect/contains-rect", test_contains_rect); g_test_add_func ("/rounded-rect/intersects-rect", test_intersects_rect); g_test_add_func ("/rounded-rect/contains-point", test_contains_point); + g_test_add_func ("/rounded-rect/is-circular", test_is_circular); + g_test_add_func ("/rounded-rect/to-float", test_to_float); return g_test_run (); } diff --git a/testsuite/gsk/shader.c b/testsuite/gsk/shader.c index 555acb0869..4bc4f0245b 100644 --- a/testsuite/gsk/shader.c +++ b/testsuite/gsk/shader.c @@ -76,6 +76,7 @@ test_create_simple (void) { GBytes *bytes; GskGLShader *shader; + GBytes *source; bytes = g_bytes_new_static (shader1, sizeof (shader1)); shader = gsk_gl_shader_new_from_bytes (bytes); @@ -100,19 +101,48 @@ test_create_simple (void) g_assert_cmpstr (gsk_gl_shader_get_uniform_name (shader, 7), ==, "test5"); g_assert_cmpint (gsk_gl_shader_get_uniform_type (shader, 7), ==, GSK_GL_UNIFORM_TYPE_VEC4); + g_assert_cmpint (gsk_gl_shader_find_uniform_by_name (shader, "progress"), ==, 0); + g_assert_cmpint (gsk_gl_shader_find_uniform_by_name (shader, "dots"), ==, 1); + g_assert_cmpint (gsk_gl_shader_find_uniform_by_name (shader, "center"), ==, 2); + g_assert_cmpint (gsk_gl_shader_find_uniform_by_name (shader, "test1"), ==, 3); + g_assert_cmpint (gsk_gl_shader_find_uniform_by_name (shader, "test2"), ==, 4); + g_assert_cmpint (gsk_gl_shader_find_uniform_by_name (shader, "test3"), ==, 5); + g_assert_cmpint (gsk_gl_shader_find_uniform_by_name (shader, "test4"), ==, 6); + g_assert_cmpint (gsk_gl_shader_find_uniform_by_name (shader, "test5"), ==, 7); + g_assert_cmpint (gsk_gl_shader_find_uniform_by_name (shader, "nosucharg"), ==, -1); + + g_assert_cmpint (gsk_gl_shader_get_uniform_offset (shader, 0), ==, 0); + g_assert_cmpint (gsk_gl_shader_get_uniform_offset (shader, 1), >, 0); + g_assert_cmpint (gsk_gl_shader_get_uniform_offset (shader, 2), >, 0); + g_assert_cmpint (gsk_gl_shader_get_uniform_offset (shader, 3), >, 0); + g_assert_cmpint (gsk_gl_shader_get_uniform_offset (shader, 4), >, 0); + g_assert_cmpint (gsk_gl_shader_get_uniform_offset (shader, 5), >, 0); + g_assert_cmpint (gsk_gl_shader_get_uniform_offset (shader, 6), >, 0); + g_assert_cmpint (gsk_gl_shader_get_uniform_offset (shader, 7), >, 0); + + g_assert_null (gsk_gl_shader_get_resource (shader)); + + g_object_get (shader, "source", &source, NULL); + g_assert_true (g_bytes_equal (source, bytes)); + g_object_unref (shader); g_bytes_unref (bytes); + g_bytes_unref (source); } static void test_create_data (void) { GBytes *bytes; + GBytes *bytes2; GskGLShader *shader; GskShaderArgsBuilder *builder; + GskShaderArgsBuilder *builder2; graphene_vec2_t v2, vv2; graphene_vec3_t v3, vv3; graphene_vec4_t v4, vv4; + GskRenderNode *node; + GskRenderNode *children[2]; bytes = g_bytes_new_static (shader1, sizeof (shader1)); shader = gsk_gl_shader_new_from_bytes (bytes); @@ -150,6 +180,31 @@ test_create_data (void) gsk_gl_shader_get_arg_vec4 (shader, bytes, 7, &vv4); g_assert_true (graphene_vec4_equal (&v4, &vv4)); + children[0] = gsk_color_node_new (&(GdkRGBA){0,0,0,1}, &GRAPHENE_RECT_INIT (0, 0, 50, 50)); + children[1] = gsk_color_node_new (&(GdkRGBA){1,0,0,1}, &GRAPHENE_RECT_INIT (0, 0, 50, 50)); + node = gsk_gl_shader_node_new (shader, + &GRAPHENE_RECT_INIT (0, 0, 50, 50), + bytes, + children, + 2); + + g_assert_true (gsk_gl_shader_node_get_shader (node) == shader); + g_assert_cmpuint (gsk_gl_shader_node_get_n_children (node), ==, 2); + g_assert_true (gsk_gl_shader_node_get_child (node, 0) == children[0]); + g_assert_true (gsk_gl_shader_node_get_child (node, 1) == children[1]); + + gsk_render_node_unref (children[0]); + gsk_render_node_unref (children[1]); + gsk_render_node_unref (node); + + builder2 = gsk_shader_args_builder_new (shader, bytes); + gsk_shader_args_builder_ref (builder2); + bytes2 = gsk_shader_args_builder_free_to_args (builder2); + gsk_shader_args_builder_unref (builder2); + + g_assert_true (g_bytes_equal (bytes, bytes2)); + + g_bytes_unref (bytes2); g_bytes_unref (bytes); gsk_shader_args_builder_unref (builder); diff --git a/testsuite/gsk/transform.c b/testsuite/gsk/transform.c index ec2b138761..1300dedf6a 100644 --- a/testsuite/gsk/transform.c +++ b/testsuite/gsk/transform.c @@ -655,6 +655,19 @@ test_to_2d (void) g_assert_cmpfloat (yy, ==, 1); g_assert_cmpfloat (dx, ==, 0.0); g_assert_cmpfloat (dy, ==, 0.0); + + transform = gsk_transform_translate (NULL, &GRAPHENE_POINT_INIT (10.0, 5.0)); + transform = gsk_transform_rotate (transform, 33.0); + + gsk_transform_to_2d (transform, &xx, &yx, &xy, &yy, &dx, &dy); + gsk_transform_unref (transform); + + g_assert_cmpfloat (xx, ==, 0.838670552f); + g_assert_cmpfloat (yx, ==, 0.544639051f); + g_assert_cmpfloat (xy, ==, -0.544639051f); + g_assert_cmpfloat (yy, ==, 0.838670552f); + g_assert_cmpfloat (dx, ==, 10.f); + g_assert_cmpfloat (dy, ==, 5.f); } static void @@ -735,6 +748,101 @@ test_transform_point (void) gsk_transform_unref (t2); } +static void +test_skew_transform (void) +{ + GskTransform *t1, *t2, *t3; + char *string; + gboolean res; + GskTransform *x; + + t1 = gsk_transform_skew (NULL, 30, 60); + t2 = gsk_transform_skew (NULL, 0, 30); + t3 = gsk_transform_skew (NULL, 0, -30); + + g_assert_true (gsk_transform_get_category (t1) == GSK_TRANSFORM_CATEGORY_2D); + g_assert_true (gsk_transform_get_category (t2) == GSK_TRANSFORM_CATEGORY_2D); + g_assert_false (gsk_transform_equal (t1, t2)); + + t2 = gsk_transform_invert (t2); + graphene_assert_fuzzy_transform_equal (t2, t3, EPSILON); + + string = gsk_transform_to_string (t1); + res = gsk_transform_parse (string, &x); + g_assert_true (res); + g_assert_true (gsk_transform_equal (t1, x)); + + gsk_transform_unref (t1); + gsk_transform_unref (t2); + gsk_transform_unref (t3); + g_free (string); + gsk_transform_unref (x); +} + +static void +test_perspective_transform (void) +{ + GskTransform *t1, *t2; + + t1 = gsk_transform_perspective (NULL, 1000); + t2 = gsk_transform_perspective (NULL, 300); + + g_assert_true (gsk_transform_get_category (t1) == GSK_TRANSFORM_CATEGORY_ANY); + g_assert_true (gsk_transform_get_category (t2) == GSK_TRANSFORM_CATEGORY_ANY); + g_assert_false (gsk_transform_equal (t1, t2)); + + t2 = gsk_transform_perspective (t2, 700); + + g_assert_true (gsk_transform_equal (t1, t2)); + + gsk_transform_unref (t1); + gsk_transform_unref (t2); +} + +static void +test_rotate_transform (void) +{ + GskTransform *t1, *t2, *t3; + + t1 = gsk_transform_rotate (NULL, 60); + t2 = gsk_transform_rotate (NULL, 20); + + g_assert_true (gsk_transform_get_category (t1) == GSK_TRANSFORM_CATEGORY_2D); + g_assert_true (gsk_transform_get_category (t2) == GSK_TRANSFORM_CATEGORY_2D); + g_assert_false (gsk_transform_equal (t1, t2)); + + t2 = gsk_transform_rotate (t2, 40); + g_assert_true (gsk_transform_equal (t1, t2)); + + t1 = gsk_transform_invert (t1); + t3 = gsk_transform_rotate (NULL, -60); + g_assert_true (gsk_transform_equal (t1, t3)); + + gsk_transform_unref (t1); + gsk_transform_unref (t2); + gsk_transform_unref (t3); +} + +static void +test_rotate3d_transform (void) +{ + GskTransform *t1, *t2; + graphene_vec3_t vec; + + t1 = gsk_transform_rotate_3d (NULL, 60, graphene_vec3_init (&vec, 1, 2, 3)); + t2 = gsk_transform_rotate_3d (NULL, -60, graphene_vec3_init (&vec, 1, 2, 3)); + + g_assert_true (gsk_transform_get_category (t1) == GSK_TRANSFORM_CATEGORY_3D); + g_assert_true (gsk_transform_get_category (t2) == GSK_TRANSFORM_CATEGORY_3D); + g_assert_false (gsk_transform_equal (t1, t2)); + + t2 = gsk_transform_invert (t2); + g_assert_true (gsk_transform_equal (t1, t2)); + + gsk_transform_unref (t1); + gsk_transform_unref (t2); +} + int main (int argc, char *argv[]) @@ -753,6 +861,10 @@ main (int argc, g_test_add_func ("/transform/point", test_transform_point); g_test_add_func ("/transform/to-2d", test_to_2d); g_test_add_func ("/transform/to-2d-components", test_to_2d_components); + g_test_add_func ("/transform/skew", test_skew_transform); + g_test_add_func ("/transform/perspective", test_perspective_transform); + g_test_add_func ("/transform/rotate", test_rotate_transform); + g_test_add_func ("/transform/rotate3d", test_rotate3d_transform); return g_test_run (); }