showrendernode.c 6.51 KB
Newer Older
Timm Bäder's avatar
Timm Bäder committed
1
2
#include <gtk/gtk.h>

3
4
5
6
7
8
9
10
11
12
static char *write_to_filename = NULL;
static gboolean compare_node;

static GOptionEntry options[] = {
  { "write", 'o', 0, G_OPTION_ARG_STRING, &write_to_filename, "Write PNG file", NULL },
  { "compare", 'c', 0, G_OPTION_ARG_NONE, &compare_node, "Compare render to render_texture", NULL },
  { NULL }
};


Timm Bäder's avatar
Timm Bäder committed
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

typedef struct _GtkNodeView      GtkNodeView;
typedef struct _GtkNodeViewClass GtkNodeViewClass;

#define GTK_TYPE_NODE_VIEW           (gtk_node_view_get_type ())
#define GTK_NODE_VIEW(obj)           (G_TYPE_CHECK_INSTANCE_CAST(obj, GTK_TYPE_NODE_VIEW, GtkNodeView))
#define GTK_NODE_VIEW_CLASS(cls)     (G_TYPE_CHECK_CLASS_CAST(cls, GTK_TYPE_NODE_VIEW, GtkNodeViewClass))
struct _GtkNodeView
{
  GtkWidget parent_instance;

  GskRenderNode *node;
};

struct _GtkNodeViewClass
{
  GtkWidgetClass parent_class;
};

GType gtk_node_view_get_type (void) G_GNUC_CONST;


G_DEFINE_TYPE(GtkNodeView, gtk_node_view, GTK_TYPE_WIDGET)

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
static void
gtk_node_view_measure (GtkWidget      *widget,
                       GtkOrientation  orientation,
                       int             for_size,
                       int            *minimum,
                       int            *natural,
                       int            *minimum_baseline,
                       int            *natural_baseline)
{
  GtkNodeView *self = GTK_NODE_VIEW (widget);
  graphene_rect_t bounds;


  if (self->node == NULL)
    return;

  gsk_render_node_get_bounds (self->node, &bounds);

  if (orientation == GTK_ORIENTATION_HORIZONTAL)
    {
      *minimum = *natural = bounds.origin.x + bounds.size.width;
    }
  else /* VERTICAL */
    {
      *minimum = *natural = bounds.origin.y + bounds.size.height;
    }
}

Timm Bäder's avatar
Timm Bäder committed
65
66
67
68
69
70
71
72
73
74
75
static void
gtk_node_view_snapshot (GtkWidget   *widget,
                        GtkSnapshot *snapshot)
{
  GtkNodeView *self = GTK_NODE_VIEW (widget);

  if (self->node != NULL)
    {
      gtk_snapshot_push_clip (snapshot,
                              &GRAPHENE_RECT_INIT (
                                0, 0,
Benjamin Otte's avatar
Benjamin Otte committed
76
                                gtk_widget_get_width (widget), gtk_widget_get_height (widget)));
Timm Bäder's avatar
Timm Bäder committed
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
      gtk_snapshot_append_node (snapshot, self->node);
      gtk_snapshot_pop (snapshot);
    }
}

static void
gtk_node_view_finalize (GObject *object)
{
  GtkNodeView *self = GTK_NODE_VIEW (object);

  if (self->node)
    gsk_render_node_unref (self->node);

  G_OBJECT_CLASS (gtk_node_view_parent_class)->finalize (object);
}

static void
gtk_node_view_init (GtkNodeView *self)
{
96
  gtk_widget_set_has_surface (GTK_WIDGET (self), FALSE);
Timm Bäder's avatar
Timm Bäder committed
97
98
99
100
101
102
103
104
105
106
}

static void
gtk_node_view_class_init (GtkNodeViewClass *klass)
{
  GObjectClass   *object_class = G_OBJECT_CLASS (klass);
  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);

  object_class->finalize = gtk_node_view_finalize;

107
  widget_class->measure = gtk_node_view_measure;
Timm Bäder's avatar
Timm Bäder committed
108
109
110
  widget_class->snapshot = gtk_node_view_snapshot;
}

111
112
113
114
115
116
117
118
119
static void
deserialize_error_func (const GtkCssSection *section,
                        const GError        *error,
                        gpointer             user_data)
{
  char *section_str = gtk_css_section_to_string (section);

  g_warning ("Error at %s: %s", section_str, error->message);

120
  g_free (section_str);
121
122
}

Timm Bäder's avatar
Timm Bäder committed
123
124
125
126
127
128
129
130
131
int
main (int argc, char **argv)
{
  GtkWidget *window;
  GtkWidget *nodeview;
  char *contents;
  gsize len;
  GBytes *bytes;
  graphene_rect_t node_bounds;
132
133
  GOptionContext *option_context;
  GError *error = NULL;
Timm Bäder's avatar
Timm Bäder committed
134

135
136
137
138
  option_context = g_option_context_new ("NODE-FILE [-o OUTPUT] [--compare]");
  g_option_context_add_main_entries (option_context, options, NULL);

  if (argc < 2)
Timm Bäder's avatar
Timm Bäder committed
139
    {
140
      printf ("Usage: showrendernode NODEFILE [-o OUTPUT] [--compare]\n");
Timm Bäder's avatar
Timm Bäder committed
141
142
143
      return 0;
    }

144
145
146
147
148
149
150
151
  if (!g_option_context_parse (option_context, &argc, &argv, &error))
    {
      g_printerr ("Option parsing failed: %s\n", error->message);
      return 1;
    }

  g_message ("Compare: %d, write to filename: %s", compare_node, write_to_filename);

Timm Bäder's avatar
Timm Bäder committed
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
  gtk_init ();

  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  nodeview = g_object_new (GTK_TYPE_NODE_VIEW, NULL);

  gtk_window_set_decorated (GTK_WINDOW (window), FALSE);

  g_file_get_contents (argv[1], &contents, &len, &error);
  if (error)
    {
      g_warning ("%s", error->message);
      return -1;
    }

  bytes = g_bytes_new_take (contents, len);
167
  GTK_NODE_VIEW (nodeview)->node = gsk_render_node_deserialize (bytes, deserialize_error_func, NULL);
Timm Bäder's avatar
Timm Bäder committed
168
169
170
171
  g_bytes_unref (bytes);

  if (GTK_NODE_VIEW (nodeview)->node == NULL)
    {
172
      g_critical ("Invalid node file: %s", error->message);
Timm Bäder's avatar
Timm Bäder committed
173
174
175
176
      g_clear_error (&error);
      return -1;
    }

177
178
  if (write_to_filename != NULL)
    {
179
      GdkSurface *window = gdk_surface_new_toplevel (gdk_display_get_default(), 10 , 10);
180
      GskRenderer *renderer = gsk_renderer_new_for_surface (window);
181
182
183
184
185
186
      GdkTexture *texture = gsk_renderer_render_texture (renderer, GTK_NODE_VIEW (nodeview)->node, NULL);

      g_message ("Writing .node file to .png using %s", G_OBJECT_TYPE_NAME (renderer));

      g_assert (texture != NULL);

187
      gdk_texture_save_to_png (texture, write_to_filename);
188
189
190
191
192
193
194
195
196
197
198

      gsk_renderer_unrealize (renderer);

      g_object_unref (texture);
      g_object_unref (renderer);
      g_object_unref (window);
    }

  if (compare_node)
    {
      GtkWidget *box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
199
      GdkSurface *gdk_surface = gdk_surface_new_toplevel (gdk_display_get_default(), 10 , 10);
200
      GskRenderer *renderer = gsk_renderer_new_for_surface (gdk_surface);
201
      GdkTexture *texture = gsk_renderer_render_texture (renderer, GTK_NODE_VIEW (nodeview)->node, NULL);
202
      GtkWidget *image = gtk_image_new_from_paintable (GDK_PAINTABLE (texture));
203

204
205
206
207
      gtk_widget_set_size_request (image,
                                   gdk_texture_get_width (texture),
                                   gdk_texture_get_height (texture));

208
209
210
211
212
213
214
      gtk_container_add (GTK_CONTAINER (box), nodeview);
      gtk_container_add (GTK_CONTAINER (box), image);
      gtk_container_add (GTK_CONTAINER (window), box);

      gsk_renderer_unrealize (renderer);
      g_object_unref (texture);
      g_object_unref (renderer);
215
      g_object_unref (gdk_surface);
216
217
218
219
220
221
    }
  else
    {
      gtk_container_add (GTK_CONTAINER (window), nodeview);
    }

Timm Bäder's avatar
Timm Bäder committed
222
  gsk_render_node_get_bounds (GTK_NODE_VIEW (nodeview)->node, &node_bounds);
223
224
225
  gtk_window_resize (GTK_WINDOW (window),
                     MAX (600, node_bounds.size.width),
                     MAX (500, node_bounds.size.height));
Timm Bäder's avatar
Timm Bäder committed
226

227
  g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
Timm Bäder's avatar
Timm Bäder committed
228
229
230
231
232
  gtk_widget_show (window);
  gtk_main ();

  return 0;
}