Add gtk_snapshot_push_mask
authorMatthias Clasen <mclasen@redhat.com>
Sat, 11 Feb 2023 15:06:54 +0000 (10:06 -0500)
committerMatthias Clasen <mclasen@redhat.com>
Sun, 12 Feb 2023 13:35:25 +0000 (08:35 -0500)
gtk/gtksnapshot.c
gtk/gtksnapshot.h

index 32686d264b8580fc0b270a0be4a27208da9c0a2c..f64a3cc99f5aa69f261390ca019ec98206c96d4d 100644 (file)
@@ -121,6 +121,9 @@ struct _GtkSnapshotState {
     struct {
       char *message;
     } debug;
+    struct {
+      GskRenderNode *mask_node;
+    } mask;
   } data;
 };
 
@@ -1241,6 +1244,79 @@ gtk_snapshot_push_blend (GtkSnapshot  *snapshot,
                            NULL);
 }
 
+static GskRenderNode *
+gtk_snapshot_collect_mask_source (GtkSnapshot      *snapshot,
+                                  GtkSnapshotState *state,
+                                  GskRenderNode   **nodes,
+                                  guint             n_nodes)
+{
+  GskRenderNode *source_child, *mask_child, *mask_node;
+
+  mask_child = gsk_render_node_ref (state->data.mask.mask_node);
+  source_child = gtk_snapshot_collect_default (snapshot, state, nodes, n_nodes);
+
+  if (source_child == NULL || mask_child == NULL)
+    return NULL;
+
+  mask_node = gsk_mask_node_new (source_child, mask_child);
+
+  gsk_render_node_unref (source_child);
+  gsk_render_node_unref (mask_child);
+
+  return mask_node;
+}
+
+static void
+gtk_snapshot_clear_mask_source (GtkSnapshotState *state)
+{
+  g_clear_pointer (&(state->data.mask.mask_node), gsk_render_node_unref);
+}
+
+static GskRenderNode *
+gtk_snapshot_collect_mask_mask (GtkSnapshot      *snapshot,
+                                GtkSnapshotState *state,
+                                GskRenderNode   **nodes,
+                                guint             n_nodes)
+{
+  GtkSnapshotState *prev_state = gtk_snapshot_get_previous_state (snapshot);
+
+  g_assert (prev_state->collect_func == gtk_snapshot_collect_mask_source);
+
+  prev_state->data.mask.mask_node = gtk_snapshot_collect_default (snapshot, state, nodes, n_nodes);
+
+  return NULL;
+}
+
+/**
+ * gtk_snapshot_push_mask:
+ * @snapshot: a #GtkSnapshot
+ *
+ * Until the first call to [method@Gtk.Snapshot.pop], the
+ * mask image for the mask operation will be recorded.
+ * After that call, the source image will be recorded until
+ * the second call to [method@Gtk.Snapshot.pop].
+ *
+ * Calling this function requires 2 subsequent calls to gtk_snapshot_pop().
+ *
+ * Since: 4.10
+ */
+void
+gtk_snapshot_push_mask (GtkSnapshot *snapshot)
+{
+  GtkSnapshotState *current_state = gtk_snapshot_get_current_state (snapshot);
+  GtkSnapshotState *source_state;
+
+  source_state = gtk_snapshot_push_state (snapshot,
+                                          current_state->transform,
+                                          gtk_snapshot_collect_mask_source,
+                                          gtk_snapshot_clear_mask_source);
+
+  gtk_snapshot_push_state (snapshot,
+                           source_state->transform,
+                           gtk_snapshot_collect_mask_mask,
+                           NULL);
+}
+
 static GskRenderNode *
 gtk_snapshot_collect_cross_fade_end (GtkSnapshot      *snapshot,
                                      GtkSnapshotState *state,
index 66d0d879f15e2d90cb75c3413dfdc8dd4296018f..d1d5c1a757ecd1a161fe3dc5414293b076af2051 100644 (file)
@@ -95,6 +95,9 @@ void            gtk_snapshot_push_shadow                (GtkSnapshot
 GDK_AVAILABLE_IN_ALL
 void            gtk_snapshot_push_blend                 (GtkSnapshot            *snapshot,
                                                          GskBlendMode            blend_mode);
+GDK_AVAILABLE_IN_4_10
+void            gtk_snapshot_push_mask                  (GtkSnapshot            *snapshot);
+
 GDK_AVAILABLE_IN_ALL
 void            gtk_snapshot_push_cross_fade            (GtkSnapshot            *snapshot,
                                                          double                  progress);