1 /*
2  * Copyright © 2018 Benjamin Otte
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16  *
17  * Authors: Benjamin Otte <otte@gnome.org>
18  */
19 
20 #include "config.h"
21 
22 #include "gtkrendernodepaintableprivate.h"
23 
24 #include "gtksnapshot.h"
25 
26 struct _GtkRenderNodePaintable
27 {
28   GObject parent_instance;
29 
30   GskRenderNode *node;
31   graphene_rect_t bounds;
32 };
33 
34 struct _GtkRenderNodePaintableClass
35 {
36   GObjectClass parent_class;
37 };
38 
39 static void
gtk_render_node_paintable_paintable_snapshot(GdkPaintable * paintable,GdkSnapshot * snapshot,double width,double height)40 gtk_render_node_paintable_paintable_snapshot (GdkPaintable *paintable,
41                                               GdkSnapshot  *snapshot,
42                                               double        width,
43                                               double        height)
44 {
45   GtkRenderNodePaintable *self = GTK_RENDER_NODE_PAINTABLE (paintable);
46 
47   if (self->bounds.size.width <= 0 ||
48       self->bounds.size.height <= 0)
49     return;
50 
51   gtk_snapshot_save (snapshot);
52 
53   gtk_snapshot_scale (snapshot,
54                       width / (self->bounds.size.width),
55                       height / (self->bounds.size.height));
56   gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (-self->bounds.origin.x, -self->bounds.origin.y));
57 
58   gtk_snapshot_push_clip (snapshot, &self->bounds);
59 
60   gtk_snapshot_append_node (snapshot, self->node);
61   //gtk_snapshot_append_color (snapshot, &(GdkRGBA) { 1, 0, 0, 1 }, &self->bounds);
62 
63   gtk_snapshot_pop (snapshot);
64 
65   gtk_snapshot_restore (snapshot);
66 }
67 
68 static GdkPaintableFlags
gtk_render_node_paintable_paintable_get_flags(GdkPaintable * paintable)69 gtk_render_node_paintable_paintable_get_flags (GdkPaintable *paintable)
70 {
71   return GDK_PAINTABLE_STATIC_CONTENTS | GDK_PAINTABLE_STATIC_SIZE;
72 }
73 
74 static int
gtk_render_node_paintable_paintable_get_intrinsic_width(GdkPaintable * paintable)75 gtk_render_node_paintable_paintable_get_intrinsic_width (GdkPaintable *paintable)
76 {
77   GtkRenderNodePaintable *self = GTK_RENDER_NODE_PAINTABLE (paintable);
78 
79   return ceilf (self->bounds.size.width);
80 }
81 
82 static int
gtk_render_node_paintable_paintable_get_intrinsic_height(GdkPaintable * paintable)83 gtk_render_node_paintable_paintable_get_intrinsic_height (GdkPaintable *paintable)
84 {
85   GtkRenderNodePaintable *self = GTK_RENDER_NODE_PAINTABLE (paintable);
86 
87   return ceilf (self->bounds.size.height);
88 }
89 
90 static void
gtk_render_node_paintable_paintable_init(GdkPaintableInterface * iface)91 gtk_render_node_paintable_paintable_init (GdkPaintableInterface *iface)
92 {
93   iface->snapshot = gtk_render_node_paintable_paintable_snapshot;
94   iface->get_flags = gtk_render_node_paintable_paintable_get_flags;
95   iface->get_intrinsic_width = gtk_render_node_paintable_paintable_get_intrinsic_width;
96   iface->get_intrinsic_height = gtk_render_node_paintable_paintable_get_intrinsic_height;
97 }
98 
99 G_DEFINE_TYPE_EXTENDED (GtkRenderNodePaintable, gtk_render_node_paintable, G_TYPE_OBJECT, 0,
100                         G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
101                                                gtk_render_node_paintable_paintable_init))
102 
103 static void
gtk_render_node_paintable_dispose(GObject * object)104 gtk_render_node_paintable_dispose (GObject *object)
105 {
106   GtkRenderNodePaintable *self = GTK_RENDER_NODE_PAINTABLE (object);
107 
108   g_clear_pointer (&self->node, gsk_render_node_unref);
109 
110   G_OBJECT_CLASS (gtk_render_node_paintable_parent_class)->dispose (object);
111 }
112 
113 static void
gtk_render_node_paintable_class_init(GtkRenderNodePaintableClass * klass)114 gtk_render_node_paintable_class_init (GtkRenderNodePaintableClass *klass)
115 {
116   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
117 
118   gobject_class->dispose = gtk_render_node_paintable_dispose;
119 }
120 
121 static void
gtk_render_node_paintable_init(GtkRenderNodePaintable * self)122 gtk_render_node_paintable_init (GtkRenderNodePaintable *self)
123 {
124 }
125 
126 GdkPaintable *
gtk_render_node_paintable_new(GskRenderNode * node,const graphene_rect_t * bounds)127 gtk_render_node_paintable_new (GskRenderNode         *node,
128                                const graphene_rect_t *bounds)
129 {
130   GtkRenderNodePaintable *self;
131 
132   g_return_val_if_fail (GSK_IS_RENDER_NODE (node), NULL);
133   g_return_val_if_fail (bounds != NULL, NULL);
134 
135   self = g_object_new (GTK_TYPE_RENDER_NODE_PAINTABLE, NULL);
136 
137   self->node = gsk_render_node_ref (node);
138   self->bounds = *bounds;
139 
140   return GDK_PAINTABLE (self);
141 }
142 
143 GskRenderNode *
gtk_render_node_paintable_get_render_node(GtkRenderNodePaintable * self)144 gtk_render_node_paintable_get_render_node (GtkRenderNodePaintable *self)
145 {
146   g_return_val_if_fail (GTK_IS_RENDER_NODE_PAINTABLE (self), NULL);
147 
148   return self->node;
149 }
150