diff --git a/gsk/gskdiff.c b/gsk/gskdiff.c index d6390a3808..cd2aa917b8 100644 --- a/gsk/gskdiff.c +++ b/gsk/gskdiff.c @@ -372,7 +372,7 @@ compare (gconstpointer *elem1, if (settings->compare_func (elem1[lim1 - 1], elem2[lim2 - 1], data) != 0) break; - settings-> keep_func (elem1[lim1 - 1], elem2[lim2 - 1], data); + settings->keep_func (elem1[lim1 - 1], elem2[lim2 - 1], data); } /* diff --git a/gsk/gskrendernode.c b/gsk/gskrendernode.c index 00d893be06..fb2ddd3962 100644 --- a/gsk/gskrendernode.c +++ b/gsk/gskrendernode.c @@ -489,10 +489,14 @@ gsk_render_node_can_diff (const GskRenderNode *node1, if (node1 == node2) return TRUE; - if (_gsk_render_node_get_node_type (node1) != _gsk_render_node_get_node_type (node2)) - return FALSE; + if (_gsk_render_node_get_node_type (node1) == _gsk_render_node_get_node_type (node2)) + return GSK_RENDER_NODE_GET_CLASS (node1)->can_diff (node1, node2); - return GSK_RENDER_NODE_GET_CLASS (node1)->can_diff (node1, node2); + if (_gsk_render_node_get_node_type (node1) == GSK_CONTAINER_NODE || + _gsk_render_node_get_node_type (node2) == GSK_CONTAINER_NODE) + return TRUE; + + return FALSE; } static void @@ -544,10 +548,15 @@ gsk_render_node_diff (GskRenderNode *node1, if (node1 == node2) return; - if (_gsk_render_node_get_node_type (node1) != _gsk_render_node_get_node_type (node2)) - return gsk_render_node_diff_impossible (node1, node2, region); + if (_gsk_render_node_get_node_type (node1) == _gsk_render_node_get_node_type (node2)) + return GSK_RENDER_NODE_GET_CLASS (node1)->diff (node1, node2, region); - return GSK_RENDER_NODE_GET_CLASS (node1)->diff (node1, node2, region); + if (_gsk_render_node_get_node_type (node1) == GSK_CONTAINER_NODE) + return gsk_container_node_diff_with (node1, node2, region); + if (_gsk_render_node_get_node_type (node2) == GSK_CONTAINER_NODE) + return gsk_container_node_diff_with (node2, node1, region); + + return gsk_render_node_diff_impossible (node1, node2, region); } /** diff --git a/gsk/gskrendernodeimpl.c b/gsk/gskrendernodeimpl.c index 04e9977a52..d611977acc 100644 --- a/gsk/gskrendernodeimpl.c +++ b/gsk/gskrendernodeimpl.c @@ -2641,6 +2641,36 @@ gsk_container_node_get_diff_settings (void) return settings; } +static gboolean +gsk_render_node_diff_multiple (GskRenderNode **nodes1, + gsize n_nodes1, + GskRenderNode **nodes2, + gsize n_nodes2, + cairo_region_t *region) +{ + return gsk_diff ((gconstpointer *) nodes1, n_nodes1, + (gconstpointer *) nodes2, n_nodes2, + gsk_container_node_get_diff_settings (), + region) == GSK_DIFF_OK; +} + +void +gsk_container_node_diff_with (GskRenderNode *container, + GskRenderNode *other, + cairo_region_t *region) +{ + GskContainerNode *self = (GskContainerNode *) container; + + if (gsk_render_node_diff_multiple (self->children, + self->n_children, + &other, + 1, + region)) + return; + + gsk_render_node_diff_impossible (container, other, region); +} + static void gsk_container_node_diff (GskRenderNode *node1, GskRenderNode *node2, @@ -2649,12 +2679,11 @@ gsk_container_node_diff (GskRenderNode *node1, GskContainerNode *self1 = (GskContainerNode *) node1; GskContainerNode *self2 = (GskContainerNode *) node2; - if (gsk_diff ((gconstpointer *) self1->children, - self1->n_children, - (gconstpointer *) self2->children, - self2->n_children, - gsk_container_node_get_diff_settings (), - region) == GSK_DIFF_OK) + if (gsk_render_node_diff_multiple (self1->children, + self1->n_children, + self2->children, + self2->n_children, + region)) return; gsk_render_node_diff_impossible (node1, node2, region); @@ -2849,19 +2878,18 @@ gsk_transform_node_diff (GskRenderNode *node1, { cairo_region_t *sub; float dx, dy; - gsk_transform_to_translate (self1->transform, &dx, &dy); sub = cairo_region_create (); gsk_render_node_diff (self1->child, self2->child, sub); - cairo_region_translate (sub, floor (dx), floor (dy)); - if (floor (dx) != dx) + cairo_region_translate (sub, floorf (dx), floorf (dy)); + if (floorf (dx) != dx) { cairo_region_t *tmp = cairo_region_copy (sub); cairo_region_translate (tmp, 1, 0); cairo_region_union (sub, tmp); cairo_region_destroy (tmp); } - if (floor (dy) != dy) + if (floorf (dy) != dy) { cairo_region_t *tmp = cairo_region_copy (sub); cairo_region_translate (tmp, 0, 1); diff --git a/gsk/gskrendernodeprivate.h b/gsk/gskrendernodeprivate.h index 07ec707c03..a767daa365 100644 --- a/gsk/gskrendernodeprivate.h +++ b/gsk/gskrendernodeprivate.h @@ -93,6 +93,9 @@ void gsk_render_node_diff (GskRenderNode void gsk_render_node_diff_impossible (GskRenderNode *node1, GskRenderNode *node2, cairo_region_t *region); +void gsk_container_node_diff_with (GskRenderNode *container, + GskRenderNode *other, + cairo_region_t *region); bool gsk_border_node_get_uniform (const GskRenderNode *self); bool gsk_border_node_get_uniform_color (const GskRenderNode *self); diff --git a/gsk/ngl/gsknglrenderjob.c b/gsk/ngl/gsknglrenderjob.c index 38dbe8f27d..026f2be6e7 100644 --- a/gsk/ngl/gsknglrenderjob.c +++ b/gsk/ngl/gsknglrenderjob.c @@ -2672,8 +2672,6 @@ gsk_ngl_render_job_visit_text_node (GskNglRenderJob *job, else c = *color; - //memset (&lookup, 0, sizeof lookup); - lookup.font = (PangoFont *)font; lookup.scale = (guint) (text_scale * 1024); diff --git a/testsuite/gsk/diff.c b/testsuite/gsk/diff.c new file mode 100644 index 0000000000..2bc34ebec6 --- /dev/null +++ b/testsuite/gsk/diff.c @@ -0,0 +1,99 @@ +/* + * Copyright © 2021 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.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 . + * + * Authors: Matthias Clasen + */ + +#include +#include "gsk/gskrendernodeprivate.h" + +static void +test_can_diff_basic (void) +{ + GskRenderNode *container1, *container2; + GskRenderNode *color1, *color2; + + 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)); + + container1 = gsk_container_node_new (&color1, 1); + container2 = gsk_container_node_new (&color2, 1); + + /* 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 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)); + + gsk_render_node_unref (color1); + gsk_render_node_unref (color2); + + gsk_render_node_unref (container1); + gsk_render_node_unref (container2); +} + +static void +test_can_diff_transform (void) +{ + GskRenderNode *color1, *color2; + GskRenderNode *opacity; + GskRenderNode *transform1, *transform2, *transform3, *transform4; + GskTransform *t1, *t2; + + 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)); + opacity = gsk_opacity_node_new (color2, 0.5); + + t1 = gsk_transform_translate (NULL, &GRAPHENE_POINT_INIT (10, 10)); + t2 = gsk_transform_scale (NULL, 2, 1); + + transform1 = gsk_transform_node_new (color1, t1); + transform2 = gsk_transform_node_new (color2, t1); + transform3 = gsk_transform_node_new (color2, t2); + transform4 = gsk_transform_node_new (opacity, t1); + + /* The case we can handle */ + g_assert_true (gsk_render_node_can_diff (transform1, transform2)); + + /* These, we can't */ + g_assert_false (gsk_render_node_can_diff (transform1, transform3)); + g_assert_false (gsk_render_node_can_diff (transform1, transform4)); + + gsk_render_node_unref (color1); + gsk_render_node_unref (color2); + gsk_render_node_unref (opacity); + gsk_render_node_unref (transform1); + gsk_render_node_unref (transform2); + gsk_render_node_unref (transform3); + gsk_render_node_unref (transform4); + + gsk_transform_unref (t1); + gsk_transform_unref (t2); +} + +int +main (int argc, + char *argv[]) +{ + gtk_test_init (&argc, &argv, NULL); + + g_test_add_func ("/node/can-diff/basic", test_can_diff_basic); + g_test_add_func ("/node/can-diff/transform", test_can_diff_transform); + + return g_test_run (); +} diff --git a/testsuite/gsk/meson.build b/testsuite/gsk/meson.build index f78a71fc39..9dc11f2b55 100644 --- a/testsuite/gsk/meson.build +++ b/testsuite/gsk/meson.build @@ -230,3 +230,36 @@ foreach t : tests suite: 'gsk', ) endforeach + +internal_tests = [ + ['diff'] +] + +foreach t : internal_tests + test_name = t.get(0) + test_srcs = ['@0@.c'.format(test_name)] + t.get(1, []) + test_extra_cargs = t.get(2, []) + test_extra_ldflags = t.get(3, []) + + test_exe = executable(test_name, test_srcs, + c_args : test_cargs + test_extra_cargs + common_cflags, + link_args : test_extra_ldflags, + dependencies : libgtk_static_dep, + install: get_option('install-tests'), + install_dir: testexecdir, + ) + + test(test_name, test_exe, + args: [ '--tap', '-k' ], + protocol: 'tap', + env: [ + 'GSK_RENDERER=cairo', + 'GTK_A11Y=test', + 'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()), + 'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir()) + ], + suite: 'gsk', + ) +endforeach + +