[Xfce4-commits] <ristretto:master> Implement image-viewer background-image using cairo
Stephan Arts
noreply at xfce.org
Fri Oct 21 17:38:01 CEST 2011
Updating branch refs/heads/master
to 068a0f1f8cea742416df0bfd33aa6acad3e505e0 (commit)
from c690a16966b8c235221ecfa7194ffc77dc550c1e (commit)
commit 068a0f1f8cea742416df0bfd33aa6acad3e505e0
Author: Stephan Arts <stephan at xfce.org>
Date: Wed Oct 19 22:07:45 2011 +0200
Implement image-viewer background-image using cairo
src/image_viewer.c | 314 +++++++++++++++++++++++-----------------------------
1 files changed, 137 insertions(+), 177 deletions(-)
diff --git a/src/image_viewer.c b/src/image_viewer.c
index e9cca8b..137cc68 100644
--- a/src/image_viewer.c
+++ b/src/image_viewer.c
@@ -37,6 +37,9 @@
#define RSTTO_IMAGE_VIEWER_BUFFER_SIZE 4096
#endif
+#define BACKGROUND_ICON_NAME "ristretto"
+#define BACKGROUND_ICON_SIZE 256
+
#ifndef RSTTO_MAX_SCALE
#define RSTTO_MAX_SCALE 4.0
#endif
@@ -57,6 +60,11 @@ struct _RsttoImageViewerPriv
GdkVisual *visual;
GdkColormap *colormap;
+ GtkIconTheme *icon_theme;
+ GdkPixbuf *bg_icon;
+ GdkColor *bg_color;
+ GdkColor *bg_color_fs;
+
RsttoImageViewerTransaction *transaction;
GdkPixbuf *pixbuf;
GdkPixbuf *dst_pixbuf;
@@ -125,7 +133,7 @@ struct _RsttoImageViewerTransaction
static void
-rstto_image_viewer_init(RsttoImageViewer *);
+rstto_image_viewer_init (GObject *);
static void
rstto_image_viewer_class_init(RsttoImageViewerClass *);
static void
@@ -244,8 +252,11 @@ rstto_image_viewer_get_type (void)
}
static void
-rstto_image_viewer_init(RsttoImageViewer *viewer)
+rstto_image_viewer_init ( GObject *object )
{
+ RsttoImageViewer *viewer = RSTTO_IMAGE_VIEWER (object);
+ GtkWidget *widget = GTK_WIDGET (object);
+
if (default_screen == NULL)
{
default_screen = gdk_screen_get_default();
@@ -259,6 +270,18 @@ rstto_image_viewer_init(RsttoImageViewer *viewer)
viewer->priv->visual = gdk_rgb_get_visual();
viewer->priv->colormap = gdk_colormap_new (viewer->priv->visual, TRUE);
+ viewer->priv->icon_theme = gtk_icon_theme_get_default ();
+ viewer->priv->bg_icon = gtk_icon_theme_load_icon (
+ viewer->priv->icon_theme,
+ BACKGROUND_ICON_NAME,
+ BACKGROUND_ICON_SIZE,
+ 0,
+ NULL);
+ gdk_pixbuf_saturate_and_pixelate (
+ viewer->priv->bg_icon,
+ viewer->priv->bg_icon,
+ 0, FALSE);
+
g_signal_connect (
G_OBJECT(viewer->priv->settings),
"notify::bgcolor",
@@ -346,6 +369,11 @@ rstto_image_viewer_class_init(RsttoImageViewerClass *viewer_class)
static void
rstto_image_viewer_realize(GtkWidget *widget)
{
+ RsttoImageViewer *viewer = RSTTO_IMAGE_VIEWER (widget);
+ GValue val_bg_color = {0, };
+ GValue val_bg_color_override = {0, };
+ GValue val_bg_color_fs = {0, };
+
GdkWindowAttr attributes;
gint attributes_mask;
@@ -354,6 +382,10 @@ rstto_image_viewer_realize(GtkWidget *widget)
GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+ g_value_init (&val_bg_color, GDK_TYPE_COLOR);
+ g_value_init (&val_bg_color_fs, GDK_TYPE_COLOR);
+ g_value_init (&val_bg_color_override, G_TYPE_BOOLEAN);
+
attributes.x = widget->allocation.x;
attributes.y = widget->allocation.y;
attributes.width = widget->allocation.width;
@@ -372,6 +404,18 @@ rstto_image_viewer_realize(GtkWidget *widget)
gdk_window_set_user_data (widget->window, widget);
gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
+
+
+ if (TRUE == g_value_get_boolean (&val_bg_color_override))
+ {
+ viewer->priv->bg_color = g_value_get_boxed (&val_bg_color);
+ }
+ else
+ {
+ viewer->priv->bg_color = &(widget->style->bg[GTK_STATE_NORMAL]);
+ }
+
+ viewer->priv->bg_color_fs = g_value_get_boxed (&val_bg_color_fs);
}
/**
@@ -492,203 +536,86 @@ static void
rstto_image_viewer_paint (GtkWidget *widget)
{
RsttoImageViewer *viewer = RSTTO_IMAGE_VIEWER (widget);
-
GdkColor *bg_color = NULL;
- GValue val_bg_color = {0, }, val_bg_color_override = {0, }, val_bg_color_fs = {0, };
- GdkPixbuf *pixbuf = viewer->priv->dst_pixbuf;
+ cairo_t *ctx = NULL;
+ gdouble bg_scale = 1.0;
- /*
- * Variables used for the selection-box.
- */
- gint box_x, box_y;
- gint box_width, box_height;
-
- /** BELOW THIS LINE THE VARIABLE_NAMES GET MESSY **/
- GdkPixbuf *n_pixbuf = NULL;
- gint x1, x2, y1, y2;
- /** ABOVE THIS LINE THE VARIABLE_NAMES GET MESSY **/
-
- g_value_init (&val_bg_color, GDK_TYPE_COLOR);
- g_value_init (&val_bg_color_fs, GDK_TYPE_COLOR);
- g_value_init (&val_bg_color_override, G_TYPE_BOOLEAN);
-
- g_object_get_property (G_OBJECT(viewer->priv->settings), "bgcolor", &val_bg_color);
- g_object_get_property (G_OBJECT(viewer->priv->settings), "bgcolor-override", &val_bg_color_override);
- g_object_get_property (G_OBJECT(viewer->priv->settings), "bgcolor-fullscreen", &val_bg_color_fs);
-
- /* required for transparent pixbufs... add double buffering to fix flickering*/
if(GTK_WIDGET_REALIZED(widget))
{
-
- /*
- * Create a buffer to draw on
- */
- GdkPixmap *buffer = gdk_pixmap_new(NULL, widget->allocation.width, widget->allocation.height, gdk_drawable_get_depth(widget->window));
- GdkGC *gc = gdk_gc_new(GDK_DRAWABLE(buffer));
-
- /*
- * Determine the background-color and draw the background.
+ /* Create the cairo context */
+ ctx = gdk_cairo_create (widget->window);
+
+ /* Determine if we draw the 'default' background-color,
+ * or the fullscreen-background-color.
*/
-
- if(gdk_window_get_state(gdk_window_get_toplevel(GTK_WIDGET(viewer)->window)) & GDK_WINDOW_STATE_FULLSCREEN)
+ if ( GDK_WINDOW_STATE_FULLSCREEN & gdk_window_get_state (
+ gdk_window_get_toplevel (widget->window) ) )
{
- bg_color = g_value_get_boxed (&val_bg_color_fs);
+ bg_color = viewer->priv->bg_color_fs;
}
- else
+
+ if ( NULL == bg_color )
{
- if (g_value_get_boxed (&val_bg_color) && g_value_get_boolean (&val_bg_color_override))
- {
- bg_color = g_value_get_boxed (&val_bg_color);
- }
- else
- {
- bg_color = &(widget->style->bg[GTK_STATE_NORMAL]);
- }
+ bg_color = viewer->priv->bg_color;
}
-
- gdk_window_set_background (widget->window, bg_color);
-
- gdk_colormap_alloc_color (gdk_gc_get_colormap (gc), bg_color, FALSE, TRUE);
- gdk_gc_set_rgb_bg_color (gc, bg_color);
- gdk_gc_set_foreground (gc, bg_color);
-
- gdk_draw_rectangle(GDK_DRAWABLE(buffer), gc, TRUE, 0, 0, widget->allocation.width, widget->allocation.height);
+
+ /* Paint the background-color */
+ /******************************/
+ gdk_cairo_set_source_color ( ctx, bg_color );
+ cairo_paint (ctx);
- /*
- * Check if there is a source image
- */
- if(pixbuf)
+ /* Check if a file should be rendered */
+ if ( NULL == viewer->priv->file )
{
- /*
- * Draw the image on the background
- */
- x1 = (widget->allocation.width-gdk_pixbuf_get_width(pixbuf))<0?0:(widget->allocation.width-gdk_pixbuf_get_width(pixbuf))/2;
- y1 = (widget->allocation.height-gdk_pixbuf_get_height(pixbuf))<0?0:(widget->allocation.height-gdk_pixbuf_get_height(pixbuf))/2;
- x2 = gdk_pixbuf_get_width(pixbuf);
- y2 = gdk_pixbuf_get_height(pixbuf);
-
- /* We only need to paint a checkered background if the image is transparent */
- if(gdk_pixbuf_get_has_alpha(pixbuf))
- {
- /* TODO: give these variables correct names */
- rstto_image_viewer_paint_checkers (viewer, GDK_DRAWABLE(buffer), gc, x2, y2, x1, y1);
- }
- gdk_draw_pixbuf(GDK_DRAWABLE(buffer),
- NULL,
- pixbuf,
- 0,
- 0,
- x1,
- y1,
- x2,
- y2,
- GDK_RGB_DITHER_NONE,
- 0,0);
-
- if(viewer->priv->motion.state == RSTTO_IMAGE_VIEWER_MOTION_STATE_BOX_ZOOM)
- {
- /*
- * The user can create a selection-box when dragging from four corners.
- * Check if the endpoint is before or after the starting-point,
- * calculate the offset and box-size accordingly.
- *
- * Perform the calculations for the vertical movement.
- */
- if (viewer->priv->motion.y < viewer->priv->motion.current_y)
- {
- box_y = viewer->priv->motion.y;
- box_height = viewer->priv->motion.current_y - box_y;
- }
- else
- {
- box_y = viewer->priv->motion.current_y;
- box_height = viewer->priv->motion.y - box_y;
- }
- /*
- * Above comment applies here aswell, for the horizontal movement.
- */
- if (viewer->priv->motion.x < viewer->priv->motion.current_x)
- {
- box_x = viewer->priv->motion.x;
- box_width = viewer->priv->motion.current_x - box_x;
- }
- else
- {
- box_x = viewer->priv->motion.current_x;
- box_width = viewer->priv->motion.x - box_x;
- }
-
- /*
- * Finally, paint the selection-box.
- */
- rstto_image_viewer_paint_selection (viewer, GDK_DRAWABLE(buffer), gc, box_width, box_height, box_x, box_y);
- }
- }
- else
- {
- /*
- * There is no image, draw the ristretto icon on the background
+ /* If there is no image shown, render the ristretto
+ * logo on the background.
*/
- guint size = 0;
- if ((GTK_WIDGET (viewer)->allocation.width) < (GTK_WIDGET (viewer)->allocation.height))
+
+ /* Calculate the icon-size */
+ /***************************/
+ if (widget->allocation.width < widget->allocation.height)
{
- size = GTK_WIDGET (viewer)->allocation.width;
+ bg_scale = (gdouble)BACKGROUND_ICON_SIZE /
+ (gdouble)widget->allocation.width * 1.2;
}
else
{
- size = GTK_WIDGET (viewer)->allocation.height;
+ bg_scale = (gdouble)BACKGROUND_ICON_SIZE /
+ (gdouble)widget->allocation.height * 1.2;
}
- pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default(),
- "ristretto",
- (size*0.8),
- GTK_ICON_LOOKUP_FORCE_SIZE, NULL);
- if (pixbuf)
- {
- gdk_pixbuf_saturate_and_pixelate (pixbuf, pixbuf, 0, TRUE);
- n_pixbuf = gdk_pixbuf_composite_color_simple (pixbuf, (size*0.8), (size*0.8), GDK_INTERP_BILINEAR, 40, 40, bg_color->pixel, bg_color->pixel);
- g_object_unref (pixbuf);
- pixbuf = n_pixbuf;
-
- x1 = (widget->allocation.width-gdk_pixbuf_get_width(pixbuf))<0?0:(widget->allocation.width-gdk_pixbuf_get_width(pixbuf))/2;
- y1 = (widget->allocation.height-gdk_pixbuf_get_height(pixbuf))<0?0:(widget->allocation.height-gdk_pixbuf_get_height(pixbuf))/2;
- x2 = gdk_pixbuf_get_width(pixbuf);
- y2 = gdk_pixbuf_get_height(pixbuf);
-
- gdk_draw_pixbuf(GDK_DRAWABLE(buffer),
- NULL,
- pixbuf,
- 0,
- 0,
- x1,
- y1,
- x2,
- y2,
- GDK_RGB_DITHER_NONE,
- 0,0);
-
- /* Cleanup pixbuf */
- g_object_unref (pixbuf);
- pixbuf = NULL;
- }
- }
- /*
- * Draw the buffer on the window
- */
+ /* Move the cairo context in position so the
+ * background-image is painted in the center
+ * of the widget.
+ */
+ cairo_translate (
+ ctx,
+ (gdouble)(widget->allocation.width-BACKGROUND_ICON_SIZE/bg_scale)/2.0,
+ (gdouble)(widget->allocation.height-BACKGROUND_ICON_SIZE/bg_scale)/2.0);
- gdk_draw_drawable(GDK_DRAWABLE(widget->window),
- gdk_gc_new(widget->window),
- buffer,
- 0,
- 0,
- 0,
- 0,
- widget->allocation.width,
- widget->allocation.height);
- g_object_unref(buffer);
+ /* Scale the context so the image
+ * fills the same part of the cairo-context
+ */
+ cairo_scale (
+ ctx,
+ 1.0 / bg_scale,
+ 1.0 / bg_scale);
+
+ /* Draw the pixbuf on the cairo-context */
+ /****************************************/
+ gdk_cairo_set_source_pixbuf (
+ ctx,
+ viewer->priv->bg_icon,
+ 0.0,
+ 0.0);
+ cairo_paint_with_alpha (ctx, 0.1);
+ }
+ else
+ {
+ }
}
}
@@ -2281,6 +2208,39 @@ cb_rstto_bgcolor_changed (
gpointer user_data)
{
RsttoImageViewer *viewer = RSTTO_IMAGE_VIEWER (user_data);
+ GtkWidget *widget = GTK_WIDGET (user_data);
+
+ GValue val_bg_color = {0, };
+ GValue val_bg_color_override = {0, };
+ GValue val_bg_color_fs = {0, };
+
+ g_value_init (&val_bg_color, GDK_TYPE_COLOR);
+ g_value_init (&val_bg_color_fs, GDK_TYPE_COLOR);
+ g_value_init (&val_bg_color_override, G_TYPE_BOOLEAN);
+
+ g_object_get_property (
+ G_OBJECT(viewer->priv->settings),
+ "bgcolor",
+ &val_bg_color);
+ g_object_get_property (
+ G_OBJECT(viewer->priv->settings),
+ "bgcolor-override",
+ &val_bg_color_override);
+ g_object_get_property (
+ G_OBJECT(viewer->priv->settings),
+ "bgcolor-fullscreen",
+ &val_bg_color_fs);
+
+ if (TRUE == g_value_get_boolean (&val_bg_color_override))
+ {
+ viewer->priv->bg_color = g_value_get_boxed (&val_bg_color);
+ }
+ else
+ {
+ viewer->priv->bg_color = &(widget->style->bg[GTK_STATE_NORMAL]);
+ }
+ viewer->priv->bg_color_fs = g_value_get_boxed (&val_bg_color_fs);
+
rstto_image_viewer_queued_repaint (viewer, TRUE);
}
More information about the Xfce4-commits
mailing list