summaryrefslogtreecommitdiff
path: root/src/libaudgui/scaled-image.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libaudgui/scaled-image.cc')
-rw-r--r--src/libaudgui/scaled-image.cc116
1 files changed, 116 insertions, 0 deletions
diff --git a/src/libaudgui/scaled-image.cc b/src/libaudgui/scaled-image.cc
new file mode 100644
index 0000000..41c804a
--- /dev/null
+++ b/src/libaudgui/scaled-image.cc
@@ -0,0 +1,116 @@
+/*
+ * scaled-image.c
+ * Copyright 2012-2013 John Lindgren
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions, and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions, and the following disclaimer in the documentation
+ * provided with the distribution.
+ *
+ * This software is provided "as is" and without any warranty, express or
+ * implied. In no event shall the authors be liable for any damages arising from
+ * the use of this software.
+ */
+
+#include <libaudgui/libaudgui-gtk.h>
+
+static GdkPixbuf * get_scaled (GtkWidget * widget, int maxwidth, int maxheight)
+{
+ GdkPixbuf * unscaled = (GdkPixbuf *) g_object_get_data ((GObject *) widget, "pixbuf-unscaled");
+
+ if (! unscaled)
+ return nullptr;
+
+ int width = gdk_pixbuf_get_width (unscaled);
+ int height = gdk_pixbuf_get_height (unscaled);
+
+ if (width > maxwidth || height > maxheight)
+ {
+ if (width * maxheight > height * maxwidth)
+ {
+ height = height * maxwidth / width;
+ width = maxwidth;
+ }
+ else
+ {
+ width = width * maxheight / height;
+ height = maxheight;
+ }
+ }
+
+ GdkPixbuf * scaled = (GdkPixbuf *) g_object_get_data ((GObject *) widget, "pixbuf-scaled");
+
+ if (scaled)
+ {
+ if (gdk_pixbuf_get_width (scaled) == width && gdk_pixbuf_get_height (scaled) == height)
+ return scaled;
+
+ g_object_unref (scaled);
+ }
+
+ scaled = gdk_pixbuf_scale_simple (unscaled, width, height, GDK_INTERP_BILINEAR);
+ g_object_set_data ((GObject *) widget, "pixbuf-scaled", scaled);
+
+ return scaled;
+}
+
+static int expose_cb (GtkWidget * widget, GdkEventExpose * event)
+{
+ GdkRectangle rect;
+ gtk_widget_get_allocation (widget, & rect);
+
+ GdkPixbuf * scaled = get_scaled (widget, rect.width, rect.height);
+
+ if (scaled)
+ {
+ int x = (rect.width - gdk_pixbuf_get_width (scaled)) / 2;
+ int y = (rect.height - gdk_pixbuf_get_height (scaled)) / 2;
+
+ cairo_t * cr = gdk_cairo_create (gtk_widget_get_window (widget));
+ gdk_cairo_set_source_pixbuf (cr, scaled, x, y);
+ cairo_paint (cr);
+ cairo_destroy (cr);
+ }
+
+ return true;
+}
+
+EXPORT void audgui_scaled_image_set (GtkWidget * widget, GdkPixbuf * pixbuf)
+{
+ GdkPixbuf * old;
+
+ if ((old = (GdkPixbuf *) g_object_get_data ((GObject *) widget, "pixbuf-unscaled")))
+ g_object_unref (old);
+ if ((old = (GdkPixbuf *) g_object_get_data ((GObject *) widget, "pixbuf-scaled")))
+ g_object_unref (old);
+
+ if (pixbuf)
+ g_object_ref (pixbuf);
+
+ g_object_set_data ((GObject *) widget, "pixbuf-unscaled", pixbuf);
+ g_object_set_data ((GObject *) widget, "pixbuf-scaled", nullptr);
+
+ gtk_widget_queue_draw (widget);
+}
+
+static void destroy_cb (GtkWidget * widget)
+{
+ audgui_scaled_image_set (widget, nullptr);
+}
+
+EXPORT GtkWidget * audgui_scaled_image_new (GdkPixbuf * pixbuf)
+{
+ GtkWidget * widget = gtk_drawing_area_new ();
+
+ g_signal_connect (widget, "expose-event", (GCallback) expose_cb, nullptr);
+ g_signal_connect (widget, "destroy", (GCallback) destroy_cb, nullptr);
+
+ audgui_scaled_image_set (widget, pixbuf);
+
+ return widget;
+}