inspector: Handle icon rendering in snapshots
diff --git a/gtk/inspector/Makefile.inc b/gtk/inspector/Makefile.inc
index 275fe5b..efeeba4 100644
--- a/gtk/inspector/Makefile.inc
+++ b/gtk/inspector/Makefile.inc
@@ -13,6 +13,7 @@
         inspector/gtkrenderoperationbackground.c        \
         inspector/gtkrenderoperationborder.c            \
         inspector/gtkrenderoperationcairo.c             \
+        inspector/gtkrenderoperationicon.c              \
         inspector/gtkrenderoperationoutline.c           \
         inspector/gtkrenderoperationwidget.c            \
 	inspector/gtktreemodelcssnode.c	\
@@ -52,6 +53,7 @@
         inspector/gtkrenderoperationbackground.h        \
         inspector/gtkrenderoperationborder.h            \
         inspector/gtkrenderoperationcairo.h             \
+        inspector/gtkrenderoperationicon.h              \
         inspector/gtkrenderoperationoutline.h           \
         inspector/gtkrenderoperationwidget.h            \
 	inspector/gtktreemodelcssnode.h	\
diff --git a/gtk/inspector/gtkrenderoperationicon.c b/gtk/inspector/gtkrenderoperationicon.c
new file mode 100644
index 0000000..6e4e107
--- /dev/null
+++ b/gtk/inspector/gtkrenderoperationicon.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright © 2015 Benjamin Otte <otte@gnome.org>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte@gnome.org>
+ */
+
+#include "config.h"
+
+#include "gtkrenderoperationicon.h"
+
+#include <math.h>
+
+#include "gtkcssstyleprivate.h"
+#include "gtkrendericonprivate.h"
+
+G_DEFINE_TYPE (GtkRenderOperationIcon, gtk_render_operation_icon, GTK_TYPE_RENDER_OPERATION)
+
+static void
+gtk_render_operation_icon_get_clip (GtkRenderOperation    *operation,
+                                      cairo_rectangle_int_t *clip)
+{
+  GtkRenderOperationIcon *oper = GTK_RENDER_OPERATION_ICON (operation);
+
+  clip->x = 0;
+  clip->y = 0;
+  clip->width = ceil (oper->width);
+  clip->height = ceil (oper->height);
+}
+
+static void
+gtk_render_operation_icon_get_matrix (GtkRenderOperation *operation,
+                                        cairo_matrix_t     *matrix)
+{
+  GtkRenderOperationIcon *oper = GTK_RENDER_OPERATION_ICON (operation);
+
+  cairo_matrix_init_translate (matrix, oper->x, oper->y);
+}
+
+static char *
+gtk_render_operation_icon_describe (GtkRenderOperation *operation)
+{
+  GtkRenderOperationIcon *oper = GTK_RENDER_OPERATION_ICON (operation);
+
+  switch (oper->builtin_type)
+  {
+    default:
+      g_warning ("missing builtin type %u", (guint) oper->builtin_type);
+      /* fall through */
+    case GTK_CSS_IMAGE_BUILTIN_NONE:
+      return g_strdup ("CSS icon");
+    case GTK_CSS_IMAGE_BUILTIN_CHECK:
+      return g_strdup ("CSS check icon (unchecked)");
+    case GTK_CSS_IMAGE_BUILTIN_CHECK_CHECKED:
+      return g_strdup ("CSS check icon (checked)");
+    case GTK_CSS_IMAGE_BUILTIN_CHECK_INCONSISTENT:
+      return g_strdup ("CSS check icon (inconsistent)");
+    case GTK_CSS_IMAGE_BUILTIN_OPTION:
+      return g_strdup ("CSS option icon (unchecked)");
+    case GTK_CSS_IMAGE_BUILTIN_OPTION_CHECKED:
+      return g_strdup ("CSS option icon (checked)");
+    case GTK_CSS_IMAGE_BUILTIN_OPTION_INCONSISTENT:
+      return g_strdup ("CSS option icon (inconsistent)");
+    case GTK_CSS_IMAGE_BUILTIN_ARROW_UP:
+      return g_strdup ("CSS up arrow icon");
+    case GTK_CSS_IMAGE_BUILTIN_ARROW_DOWN:
+      return g_strdup ("CSS down arrow icon");
+    case GTK_CSS_IMAGE_BUILTIN_ARROW_LEFT:
+      return g_strdup ("CSS left arrow icon");
+    case GTK_CSS_IMAGE_BUILTIN_ARROW_RIGHT:
+      return g_strdup ("CSS right arrow icon");
+    case GTK_CSS_IMAGE_BUILTIN_EXPANDER_HORIZONTAL_LEFT:
+      return g_strdup ("CSS horizontal left expander icon");
+    case GTK_CSS_IMAGE_BUILTIN_EXPANDER_VERTICAL_LEFT:
+      return g_strdup ("CSS vertical left expander icon");
+    case GTK_CSS_IMAGE_BUILTIN_EXPANDER_HORIZONTAL_RIGHT:
+      return g_strdup ("CSS horizontal right expander icon");
+    case GTK_CSS_IMAGE_BUILTIN_EXPANDER_VERTICAL_RIGHT:
+      return g_strdup ("CSS vertical right expander icon");
+    case GTK_CSS_IMAGE_BUILTIN_EXPANDER_HORIZONTAL_LEFT_EXPANDED:
+      return g_strdup ("CSS horizontal left expander icon (expanded)");
+    case GTK_CSS_IMAGE_BUILTIN_EXPANDER_VERTICAL_LEFT_EXPANDED:
+      return g_strdup ("CSS vertical left expander icon (expanded)");
+    case GTK_CSS_IMAGE_BUILTIN_EXPANDER_HORIZONTAL_RIGHT_EXPANDED:
+      return g_strdup ("CSS horizontal right expander icon (expanded)");
+    case GTK_CSS_IMAGE_BUILTIN_EXPANDER_VERTICAL_RIGHT_EXPANDED:
+      return g_strdup ("CSS vertical right expander icon (expanded)");
+    case GTK_CSS_IMAGE_BUILTIN_GRIP_TOPLEFT:
+      return g_strdup ("CSS top left grip icon");
+    case GTK_CSS_IMAGE_BUILTIN_GRIP_TOP:
+      return g_strdup ("CSS top grip icon");
+    case GTK_CSS_IMAGE_BUILTIN_GRIP_TOPRIGHT:
+      return g_strdup ("CSS top right grip icon");
+    case GTK_CSS_IMAGE_BUILTIN_GRIP_RIGHT:
+      return g_strdup ("CSS right grip icon");
+    case GTK_CSS_IMAGE_BUILTIN_GRIP_BOTTOMRIGHT:
+      return g_strdup ("CSS bottom right grip icon");
+    case GTK_CSS_IMAGE_BUILTIN_GRIP_BOTTOM:
+      return g_strdup ("CSS bottom grip icon");
+    case GTK_CSS_IMAGE_BUILTIN_GRIP_BOTTOMLEFT:
+      return g_strdup ("CSS bottom left grip icon");
+    case GTK_CSS_IMAGE_BUILTIN_GRIP_LEFT:
+      return g_strdup ("CSS left grip icon");
+    case GTK_CSS_IMAGE_BUILTIN_PANE_SEPARATOR:
+      return g_strdup ("CSS pane separator icon");
+    case GTK_CSS_IMAGE_BUILTIN_HANDLE:
+      return g_strdup ("CSS handle icon");
+    case GTK_CSS_IMAGE_BUILTIN_SPINNER:
+      return g_strdup ("CSS spinner icon");
+  }
+}
+
+static void
+gtk_render_operation_icon_draw (GtkRenderOperation *operation,
+                                  cairo_t            *cr)
+{
+  GtkRenderOperationIcon *oper = GTK_RENDER_OPERATION_ICON (operation);
+
+  gtk_css_style_render_icon (oper->style,
+                             cr,
+                             0, 0, 
+                             oper->width,
+                             oper->height,
+                             oper->builtin_type);
+}
+
+static void
+gtk_render_operation_icon_finalize (GObject *object)
+{
+  GtkRenderOperationIcon *oper = GTK_RENDER_OPERATION_ICON (object);
+
+  g_object_unref (oper->style);
+
+  G_OBJECT_CLASS (gtk_render_operation_icon_parent_class)->finalize (object);
+}
+
+static void
+gtk_render_operation_icon_class_init (GtkRenderOperationIconClass *klass)
+{
+  GtkRenderOperationClass *operation_class = GTK_RENDER_OPERATION_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = gtk_render_operation_icon_finalize;
+
+  operation_class->get_clip = gtk_render_operation_icon_get_clip;
+  operation_class->get_matrix = gtk_render_operation_icon_get_matrix;
+  operation_class->describe = gtk_render_operation_icon_describe;
+  operation_class->draw = gtk_render_operation_icon_draw;
+}
+
+static void
+gtk_render_operation_icon_init (GtkRenderOperationIcon *image)
+{
+}
+
+GtkRenderOperation *
+gtk_render_operation_icon_new (GtkCssStyle            *style,
+                               double                  x,
+                               double                  y,
+                               double                  width,
+                               double                  height,
+                               GtkCssImageBuiltinType  builtin_type)
+{
+  GtkRenderOperationIcon *result;
+
+  g_return_val_if_fail (GTK_IS_CSS_STYLE (style), NULL);
+
+  result = g_object_new (GTK_TYPE_RENDER_OPERATION_ICON, NULL);
+  
+  result->style = g_object_ref (style);
+  result->x = x;
+  result->y = y;
+  result->width = width;
+  result->height = height;
+  result->builtin_type = builtin_type;
+ 
+  return GTK_RENDER_OPERATION (result);
+}
+
diff --git a/gtk/inspector/gtkrenderoperationicon.h b/gtk/inspector/gtkrenderoperationicon.h
new file mode 100644
index 0000000..9adfac7
--- /dev/null
+++ b/gtk/inspector/gtkrenderoperationicon.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright © 2015 Red Hat Inc.
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte@gnome.org>
+ */
+
+#ifndef __GTK_RENDER_OPERATION_ICON_PRIVATE_H__
+#define __GTK_RENDER_OPERATION_ICON_PRIVATE_H__
+
+#include "gtkrenderoperation.h"
+
+#include "gtkcssimagebuiltinprivate.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_RENDER_OPERATION_ICON           (gtk_render_operation_icon_get_type ())
+#define GTK_RENDER_OPERATION_ICON(obj)           (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_RENDER_OPERATION_ICON, GtkRenderOperationIcon))
+#define GTK_RENDER_OPERATION_ICON_CLASS(cls)     (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_RENDER_OPERATION_ICON, GtkRenderOperationIconClass))
+#define GTK_IS_RENDER_OPERATION_ICON(obj)        (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_RENDER_OPERATION_ICON))
+#define GTK_IS_RENDER_OPERATION_ICON_CLASS(obj)  (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_RENDER_OPERATION_ICON))
+#define GTK_RENDER_OPERATION_ICON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_RENDER_OPERATION_ICON, GtkRenderOperationIconClass))
+
+typedef struct _GtkRenderOperationIcon           GtkRenderOperationIcon;
+typedef struct _GtkRenderOperationIconClass      GtkRenderOperationIconClass;
+
+struct _GtkRenderOperationIcon
+{
+  GtkRenderOperation parent;
+  
+  GtkCssStyle             *style;
+  double                   x;
+  double                   y;
+  double                   width;
+  double                   height;
+  GtkCssImageBuiltinType   builtin_type;
+};
+
+struct _GtkRenderOperationIconClass
+{
+  GtkRenderOperationClass parent_class;
+};
+
+GType                   gtk_render_operation_icon_get_type           (void) G_GNUC_CONST;
+
+GtkRenderOperation *    gtk_render_operation_icon_new                (GtkCssStyle            *style,
+                                                                      double                  x,
+                                                                      double                  y,
+                                                                      double                  width,
+                                                                      double                  height,
+                                                                      GtkCssImageBuiltinType  builtin_type);
+
+G_END_DECLS
+
+#endif /* __GTK_RENDER_OPERATION_ICON_PRIVATE_H__ */
diff --git a/gtk/inspector/recordingrenderops.c b/gtk/inspector/recordingrenderops.c
index 509acb8..a30c2d6 100644
--- a/gtk/inspector/recordingrenderops.c
+++ b/gtk/inspector/recordingrenderops.c
@@ -24,6 +24,7 @@
 #include "gtkrenderoperationbackground.h"
 #include "gtkrenderoperationborder.h"
 #include "gtkrenderoperationcairo.h"
+#include "gtkrenderoperationicon.h"
 #include "gtkrenderoperationoutline.h"
 #include "gtkrenderoperationwidget.h"
 #include "gtkwidget.h"
@@ -162,6 +163,26 @@
   g_object_unref (oper);
 }
 
+static void
+gtk_recording_render_ops_draw_icon (GtkRenderOps           *ops,
+                                    GtkCssStyle            *style,
+                                    cairo_t                *cr,
+                                    gdouble                 x,
+                                    gdouble                 y,
+                                    gdouble                 width,
+                                    gdouble                 height,
+                                    GtkCssImageBuiltinType  builtin_type)
+{
+  GtkRecordingRenderOps *record = GTK_RECORDING_RENDER_OPS (ops);
+  GtkRenderOperation *oper;
+
+  gtk_recording_render_ops_save_snapshot (record, cr);
+
+  oper = gtk_render_operation_icon_new (style, x, y, width, height, builtin_type);
+  gtk_render_operation_widget_add_operation (record->widgets->data, oper);
+  g_object_unref (oper);
+}
+
 static cairo_t *
 gtk_recording_render_ops_begin_draw_widget (GtkRenderOps *ops,
                                             GtkWidget    *widget,
@@ -218,6 +239,7 @@
   ops_class->draw_background = gtk_recording_render_ops_draw_background;
   ops_class->draw_border = gtk_recording_render_ops_draw_border;
   ops_class->draw_outline = gtk_recording_render_ops_draw_outline;
+  ops_class->draw_icon = gtk_recording_render_ops_draw_icon;
 }
 
 static void