snapshot: Fix push_repeat () with empty child bounds
authorSergey Bugaev <bugaevc@gmail.com>
Wed, 23 Aug 2023 14:39:44 +0000 (17:39 +0300)
committerMatthias Clasen <mclasen@redhat.com>
Tue, 19 Sep 2023 19:16:25 +0000 (15:16 -0400)
The logic would confuse empty child bounds (in which case nothing should
get rendered) with NULL child bounds (in which case the child node's own
bounds should get used). In fact, if the child bounds are empty, we can
discard the descendant render nodes completely, getting a nice little
optimization.

Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
gtk/gtksnapshot.c

index 4e16b6cb9548041aedd38859f6591c40b07555cb..d837dc4c26a899101c8a2bfb0ad0a3265dab06d8 100644 (file)
@@ -708,6 +708,16 @@ gtk_snapshot_collect_repeat (GtkSnapshot      *snapshot,
   return repeat_node;
 }
 
+static GskRenderNode *
+gtk_snapshot_collect_discard_repeat (GtkSnapshot      *snapshot,
+                                     GtkSnapshotState *state,
+                                     GskRenderNode   **nodes,
+                                     guint             n_nodes)
+{
+  /* Drop the node and return nothing.  */
+  return NULL;
+}
+
 static void
 gtk_graphene_rect_scale_affine (const graphene_rect_t *rect,
                                 float                  scale_x,
@@ -798,17 +808,24 @@ gtk_snapshot_push_repeat (GtkSnapshot           *snapshot,
                           const graphene_rect_t *child_bounds)
 {
   GtkSnapshotState *state;
+  gboolean empty_child_bounds = FALSE;
   graphene_rect_t real_child_bounds = { { 0 } };
   float scale_x, scale_y, dx, dy;
 
   gtk_snapshot_ensure_affine (snapshot, &scale_x, &scale_y, &dx, &dy);
 
   if (child_bounds)
-    gtk_graphene_rect_scale_affine (child_bounds, scale_x, scale_y, dx, dy, &real_child_bounds);
+    {
+      gtk_graphene_rect_scale_affine (child_bounds, scale_x, scale_y, dx, dy, &real_child_bounds);
+      if (real_child_bounds.size.width <= 0 || real_child_bounds.size.height <= 0)
+        empty_child_bounds = TRUE;
+    }
 
   state = gtk_snapshot_push_state (snapshot,
                                    gtk_snapshot_get_current_state (snapshot)->transform,
-                                   gtk_snapshot_collect_repeat,
+                                   empty_child_bounds
+                                   ? gtk_snapshot_collect_discard_repeat
+                                   : gtk_snapshot_collect_repeat,
                                    NULL);
 
   gtk_graphene_rect_scale_affine (bounds, scale_x, scale_y, dx, dy, &state->data.repeat.bounds);