From 7fdcc58532174c8406378d3b6885e60c31a07ad5 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Mon, 26 Mar 2018 04:37:01 +0200 Subject: [PATCH] snapshot: Add gtk_snapshot_to_paintable() This is intended for DND icons --- docs/reference/gtk/gtk4-sections.txt | 2 + gtk/gtkrendernodepaintable.c | 146 +++++++++++++++++++++++++++ gtk/gtkrendernodepaintableprivate.h | 35 +++++++ gtk/gtksnapshot.c | 46 +++++++++ gtk/gtksnapshot.h | 4 + gtk/meson.build | 1 + 6 files changed, 234 insertions(+) create mode 100644 gtk/gtkrendernodepaintable.c create mode 100644 gtk/gtkrendernodepaintableprivate.h diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt index 374124bc9a..64603bc925 100644 --- a/docs/reference/gtk/gtk4-sections.txt +++ b/docs/reference/gtk/gtk4-sections.txt @@ -4171,7 +4171,9 @@ gtk_snapshot_new gtk_snapshot_ref gtk_snapshot_unref gtk_snapshot_to_node +gtk_snapshot_to_paintable gtk_snapshot_free_to_node +gtk_snapshot_free_to_paintable gtk_snapshot_get_renderer gtk_snapshot_get_record_names gtk_snapshot_push diff --git a/gtk/gtkrendernodepaintable.c b/gtk/gtkrendernodepaintable.c new file mode 100644 index 0000000000..18c36a7a8c --- /dev/null +++ b/gtk/gtkrendernodepaintable.c @@ -0,0 +1,146 @@ +/* + * Copyright © 2018 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 . + * + * Authors: Benjamin Otte + */ + +#include "config.h" + +#include "gtkrendernodepaintableprivate.h" + +#include "gtksnapshot.h" + +struct _GtkRenderNodePaintable +{ + GObject parent_instance; + + GskRenderNode *node; +}; + +struct _GtkRenderNodePaintableClass +{ + GObjectClass parent_class; +}; + +static void +gtk_render_node_paintable_paintable_snapshot (GdkPaintable *paintable, + GdkSnapshot *snapshot, + double width, + double height) +{ + GtkRenderNodePaintable *self = GTK_RENDER_NODE_PAINTABLE (paintable); + graphene_rect_t node_bounds; + + gsk_render_node_get_bounds (self->node, &node_bounds); + + if (node_bounds.origin.x + node_bounds.size.width != width || + node_bounds.origin.y + node_bounds.size.height != height) + { + graphene_matrix_t transform; + + graphene_matrix_init_scale (&transform, + width / (node_bounds.origin.x + node_bounds.size.width), + height / (node_bounds.origin.y + node_bounds.size.height), + 1.0); + gtk_snapshot_push_transform (snapshot, + &transform, + "RenderNodeScaleToFit"); + gtk_snapshot_append_node (snapshot, self->node); + gtk_snapshot_pop (snapshot); + } + else + { + gtk_snapshot_append_node (snapshot, self->node); + } +} + +static GdkPaintableFlags +gtk_render_node_paintable_paintable_get_flags (GdkPaintable *paintable) +{ + return GDK_PAINTABLE_STATIC_CONTENTS | GDK_PAINTABLE_STATIC_SIZE; +} + +static int +gtk_render_node_paintable_paintable_get_intrinsic_width (GdkPaintable *paintable) +{ + GtkRenderNodePaintable *self = GTK_RENDER_NODE_PAINTABLE (paintable); + graphene_rect_t node_bounds; + + gsk_render_node_get_bounds (self->node, &node_bounds); + + return node_bounds.origin.x + node_bounds.size.width; +} + +static int +gtk_render_node_paintable_paintable_get_intrinsic_height (GdkPaintable *paintable) +{ + GtkRenderNodePaintable *self = GTK_RENDER_NODE_PAINTABLE (paintable); + graphene_rect_t node_bounds; + + gsk_render_node_get_bounds (self->node, &node_bounds); + + return node_bounds.origin.y + node_bounds.size.height; +} + +static void +gtk_render_node_paintable_paintable_init (GdkPaintableInterface *iface) +{ + iface->snapshot = gtk_render_node_paintable_paintable_snapshot; + iface->get_flags = gtk_render_node_paintable_paintable_get_flags; + iface->get_intrinsic_width = gtk_render_node_paintable_paintable_get_intrinsic_width; + iface->get_intrinsic_height = gtk_render_node_paintable_paintable_get_intrinsic_height; +} + +G_DEFINE_TYPE_EXTENDED (GtkRenderNodePaintable, gtk_render_node_paintable, G_TYPE_OBJECT, 0, + G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE, + gtk_render_node_paintable_paintable_init)) + +static void +gtk_render_node_paintable_dispose (GObject *object) +{ + GtkRenderNodePaintable *self = GTK_RENDER_NODE_PAINTABLE (object); + + g_clear_pointer (&self->node, gsk_render_node_unref); + + G_OBJECT_CLASS (gtk_render_node_paintable_parent_class)->dispose (object); +} + +static void +gtk_render_node_paintable_class_init (GtkRenderNodePaintableClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->dispose = gtk_render_node_paintable_dispose; +} + +static void +gtk_render_node_paintable_init (GtkRenderNodePaintable *self) +{ +} + +GdkPaintable * +gtk_render_node_paintable_new (GskRenderNode *node) +{ + GtkRenderNodePaintable *self; + + g_return_val_if_fail (GSK_IS_RENDER_NODE (node), NULL); + + self = g_object_new (GTK_TYPE_RENDER_NODE_PAINTABLE, NULL); + + self->node = gsk_render_node_ref (node); + + return GDK_PAINTABLE (self); +} diff --git a/gtk/gtkrendernodepaintableprivate.h b/gtk/gtkrendernodepaintableprivate.h new file mode 100644 index 0000000000..1eba80ec3f --- /dev/null +++ b/gtk/gtkrendernodepaintableprivate.h @@ -0,0 +1,35 @@ +/* + * Copyright © 2018 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 . + * + * Authors: Benjamin Otte + */ + +#ifndef __GTK_RENDER_NODE_PAINTABLE_H__ +#define __GTK_RENDER_NODE_PAINTABLE_H__ + +#include + +G_BEGIN_DECLS + +#define GTK_TYPE_RENDER_NODE_PAINTABLE (gtk_render_node_paintable_get_type ()) + +G_DECLARE_FINAL_TYPE (GtkRenderNodePaintable, gtk_render_node_paintable, GTK, RENDER_NODE_PAINTABLE, GObject) + +GdkPaintable * gtk_render_node_paintable_new (GskRenderNode *node); + +G_END_DECLS + +#endif /* __GTK_RENDER_NODE_PAINTABLE_H__ */ diff --git a/gtk/gtksnapshot.c b/gtk/gtksnapshot.c index 609a0c6473..2fe1e783e2 100644 --- a/gtk/gtksnapshot.c +++ b/gtk/gtksnapshot.c @@ -25,6 +25,7 @@ #include "gtkrenderbackgroundprivate.h" #include "gtkrenderborderprivate.h" #include "gtkrendericonprivate.h" +#include "gtkrendernodepaintableprivate.h" #include "gtkstylecontextprivate.h" #include "gsk/gskrendernodeprivate.h" @@ -222,6 +223,26 @@ gtk_snapshot_free_to_node (GtkSnapshot *snapshot) return result; } +/** + * gtk_snapshot_free_to_paintable: (skip) + * @snapshot: (transfer full): a #GtkSnapshot + * + * Returns a paintable for the node that was + * constructed by @snapshot and frees @snapshot. + * + * Returns: a newly-created #GdkPaintable + */ +GdkPaintable * +gtk_snapshot_free_to_paintable (GtkSnapshot *snapshot) +{ + GdkPaintable *result; + + result = gtk_snapshot_to_paintable (snapshot); + g_object_unref (snapshot); + + return result; +} + /** * gtk_snapshot_push: * @snapshot: a #GtkSnapshot @@ -1268,6 +1289,31 @@ gtk_snapshot_to_node (GtkSnapshot *snapshot) return result; } +/** + * gtk_snapshot_to_paintable: + * @snapshot: a #GtkSnapshot + * + * Returns a paintable encapsulating the render node + * that was constructed by @snapshot. After calling + * this function, it is no longer possible to add more + * nodes to @snapshot. The only function that should be + * called after this is gtk_snapshot_unref(). + * + * Returns: a new #GdkPaintable + */ +GdkPaintable * +gtk_snapshot_to_paintable (GtkSnapshot *snapshot) +{ + GskRenderNode *node; + GdkPaintable *paintable; + + node = gtk_snapshot_to_node (snapshot); + paintable = gtk_render_node_paintable_new (node); + gsk_render_node_unref (node); + + return paintable; +} + /** * gtk_snapshot_pop: * @snapshot: a #GtkSnapshot diff --git a/gtk/gtksnapshot.h b/gtk/gtksnapshot.h index db9d4e6d78..add8cdd0b5 100644 --- a/gtk/gtksnapshot.h +++ b/gtk/gtksnapshot.h @@ -58,9 +58,13 @@ GtkSnapshot * gtk_snapshot_new (gboolean ...) G_GNUC_PRINTF (3, 4); GDK_AVAILABLE_IN_ALL GskRenderNode * gtk_snapshot_free_to_node (GtkSnapshot *snapshot); +GDK_AVAILABLE_IN_ALL +GdkPaintable * gtk_snapshot_free_to_paintable (GtkSnapshot *snapshot); GDK_AVAILABLE_IN_ALL GskRenderNode * gtk_snapshot_to_node (GtkSnapshot *snapshot); +GDK_AVAILABLE_IN_ALL +GdkPaintable * gtk_snapshot_to_paintable (GtkSnapshot *snapshot); GDK_AVAILABLE_IN_ALL gboolean gtk_snapshot_get_record_names (GtkSnapshot *snapshot); diff --git a/gtk/meson.build b/gtk/meson.build index c06b5aa075..a0b3932d57 100644 --- a/gtk/meson.build +++ b/gtk/meson.build @@ -291,6 +291,7 @@ gtk_public_sources = files([ 'gtkrenderbackground.c', 'gtkrenderborder.c', 'gtkrendericon.c', + 'gtkrendernodepaintable.c', 'gtkrevealer.c', 'gtkroundedbox.c', 'gtkscale.c', -- 2.30.2