]> Pileus Git - ~andy/gtk/blobdiff - modules/engines/pixbuf/pixbuf-render.c
pixbuf-engine: replace call to gdk_draw_pixbuf() with Cairo equivalent
[~andy/gtk] / modules / engines / pixbuf / pixbuf-render.c
index 03ec06083407d733926e97210c9571a6f8171a5b..d074f64c912f61320dd762fe733386873696bc78 100644 (file)
@@ -43,6 +43,12 @@ bilinear_gradient (GdkPixbuf    *src,
   GdkPixbuf *result;
   int i, j, k;
 
+  if (src_x == 0 || src_y == 0)
+    {
+      g_warning ("invalid source position for bilinear gradient");
+      return NULL;
+    }
+
   p1 = src_pixels + (src_y - 1) * src_rowstride + (src_x - 1) * n_channels;
   p2 = p1 + n_channels;
   p3 = src_pixels + src_y * src_rowstride + (src_x - 1) * n_channels;
@@ -50,6 +56,13 @@ bilinear_gradient (GdkPixbuf    *src,
 
   result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, n_channels == 4, 8,
                           width, height);
+
+  if (result == NULL)
+    {
+      g_warning ("failed to create a %dx%d pixbuf", width, height);
+      return NULL;
+    }
+
   dest_rowstride = gdk_pixbuf_get_rowstride (result);
   dest_pixels = gdk_pixbuf_get_pixels (result);
 
@@ -96,8 +109,21 @@ horizontal_gradient (GdkPixbuf    *src,
   GdkPixbuf *result;
   int i, j, k;
 
+  if (src_x == 0)
+    {
+      g_warning ("invalid source position for horizontal gradient");
+      return NULL;
+    }
+
   result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, n_channels == 4, 8,
                           width, height);
+
+  if (result == NULL)
+    {
+      g_warning ("failed to create a %dx%d pixbuf", width, height);
+      return NULL;
+    }
+
   dest_rowstride = gdk_pixbuf_get_rowstride (result);
   dest_pixels = gdk_pixbuf_get_pixels (result);
 
@@ -145,11 +171,24 @@ vertical_gradient (GdkPixbuf    *src,
   GdkPixbuf *result;
   int i, j;
 
+  if (src_y == 0)
+    {
+      g_warning ("invalid source position for vertical gradient");
+      return NULL;
+    }
+
   top_pixels = src_pixels + (src_y - 1) * src_rowstride + (src_x) * n_channels;
   bottom_pixels = top_pixels + src_rowstride;
 
   result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, n_channels == 4, 8,
                           width, height);
+
+  if (result == NULL)
+    {
+      g_warning ("failed to create a %dx%d pixbuf", width, height);
+      return NULL;
+    }
+
   dest_rowstride = gdk_pixbuf_get_rowstride (result);
   dest_pixels = gdk_pixbuf_get_pixels (result);
 
@@ -191,6 +230,13 @@ replicate_single (GdkPixbuf    *src,
 
   result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, n_channels == 4, 8,
                           width, height);
+
+  if (result == NULL)
+    {
+      g_warning ("failed to create a %dx%d pixbuf", width, height);
+      return NULL;
+    }
+
   dest_rowstride = gdk_pixbuf_get_rowstride (result);
   dest_pixels = gdk_pixbuf_get_pixels (result);
   
@@ -229,6 +275,13 @@ replicate_rows (GdkPixbuf    *src,
 
   result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, n_channels == 4, 8,
                           width, height);
+
+  if (result == NULL)
+    {
+      g_warning ("failed to create a %dx%d pixbuf", width, height);
+      return NULL;
+    }
+
   dest_rowstride = gdk_pixbuf_get_rowstride (result);
   dest_pixels = gdk_pixbuf_get_pixels (result);
 
@@ -255,6 +308,13 @@ replicate_cols (GdkPixbuf    *src,
 
   result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, n_channels == 4, 8,
                           width, height);
+
+  if (result == NULL)
+    {
+      g_warning ("failed to create a %dx%d pixbuf", width, height);
+      return NULL;
+    }
+
   dest_rowstride = gdk_pixbuf_get_rowstride (result);
   dest_pixels = gdk_pixbuf_get_pixels (result);
 
@@ -304,7 +364,7 @@ pixbuf_render (GdkPixbuf    *src,
               gint          dest_width,
               gint          dest_height)
 {
-  GdkPixbuf *tmp_pixbuf;
+  GdkPixbuf *tmp_pixbuf = NULL;
   GdkRectangle rect;
   int x_offset, y_offset;
   gboolean has_alpha = gdk_pixbuf_get_has_alpha (src);
@@ -382,7 +442,7 @@ pixbuf_render (GdkPixbuf    *src,
       x_offset = rect.x - dest_x;
       y_offset = rect.y - dest_y;
     }
-  else 
+  else if (src_width > 0 && src_height > 0)
     {
       double x_scale = (double)dest_width / src_width;
       double y_scale = (double)dest_height / src_height;
@@ -415,22 +475,30 @@ pixbuf_render (GdkPixbuf    *src,
       y_offset = 0;
     }
 
-  if (mask)
+  if (tmp_pixbuf)
     {
-      gdk_pixbuf_render_threshold_alpha (tmp_pixbuf, mask,
-                                        x_offset, y_offset,
-                                        rect.x, rect.y,
-                                        rect.width, rect.height,
-                                        128);
-    }
+      cairo_t *cr;
+      
+      cr = gdk_cairo_create (window);
+      if (mask)
+       {
+         gdk_pixbuf_render_threshold_alpha (tmp_pixbuf, mask,
+                                            x_offset, y_offset,
+                                            rect.x, rect.y,
+                                            rect.width, rect.height,
+                                            128);
+       }
 
-  gdk_draw_pixbuf (window, NULL, tmp_pixbuf,
-                  x_offset, y_offset,
-                  rect.x, rect.y,
-                  rect.width, rect.height,
-                  GDK_RGB_DITHER_NORMAL,
-                  0, 0);
-  g_object_unref (tmp_pixbuf);
+      gdk_cairo_set_source_pixbuf (cr, 
+                                   tmp_pixbuf,
+                                   -x_offset + rect.x, 
+                                   -y_offset + rect.y);
+      gdk_cairo_rectangle (cr, &rect);
+      cairo_fill (cr);
+
+      cairo_destroy (cr);
+      g_object_unref (tmp_pixbuf);
+    }
 }
 
 ThemePixbuf *
@@ -466,8 +534,7 @@ theme_pixbuf_set_filename (ThemePixbuf *theme_pb,
       theme_pb->pixbuf = NULL;
     }
 
-  if (theme_pb->filename)
-    g_free (theme_pb->filename);
+  g_free (theme_pb->filename);
 
   if (filename)
     theme_pb->filename = g_strdup (filename);
@@ -637,7 +704,7 @@ theme_pixbuf_set_stretch (ThemePixbuf *theme_pb,
     theme_pixbuf_compute_hints (theme_pb);
 }
 
-GdkPixbuf *
+static GdkPixbuf *
 pixbuf_cache_value_new (gchar *filename)
 {
   GError *err = NULL;
@@ -696,6 +763,9 @@ theme_pixbuf_render (ThemePixbuf  *theme_pb,
 
   if (theme_pb->stretch)
     {
+      if (component_mask & COMPONENT_ALL)
+       component_mask = (COMPONENT_ALL - 1) & ~component_mask;
+
       src_x[0] = 0;
       src_x[1] = theme_pb->border_left;
       src_x[2] = pixbuf_width - theme_pb->border_right;
@@ -711,13 +781,24 @@ theme_pixbuf_render (ThemePixbuf  *theme_pb,
       dest_x[2] = x + width - theme_pb->border_right;
       dest_x[3] = x + width;
 
+      if (dest_x[1] > dest_x[2])
+       {
+         component_mask &= ~(COMPONENT_NORTH | COMPONENT_SOUTH | COMPONENT_CENTER);
+         dest_x[1] = dest_x[2] = (dest_x[1] + dest_x[2]) / 2;
+       }
+
       dest_y[0] = y;
       dest_y[1] = y + theme_pb->border_top;
       dest_y[2] = y + height - theme_pb->border_bottom;
       dest_y[3] = y + height;
 
-      if (component_mask & COMPONENT_ALL)
-       component_mask = (COMPONENT_ALL - 1) & ~component_mask;
+      if (dest_y[1] > dest_y[2])
+       {
+         component_mask &= ~(COMPONENT_EAST | COMPONENT_WEST | COMPONENT_CENTER);
+         dest_y[1] = dest_y[2] = (dest_y[1] + dest_y[2]) / 2;
+       }
+
+
 
 #define RENDER_COMPONENT(X1,X2,Y1,Y2)                                           \
         pixbuf_render (pixbuf, theme_pb->hints[Y1][X1], window, mask, clip_rect, \
@@ -768,35 +849,19 @@ theme_pixbuf_render (ThemePixbuf  *theme_pb,
        }
       else
        {
-         GdkPixmap *tmp_pixmap;
-         GdkGC *tmp_gc;
-         GdkGCValues gc_values;
-
-         tmp_pixmap = gdk_pixmap_new (window,
-                                      pixbuf_width,
-                                      pixbuf_height,
-                                      -1);
-         tmp_gc = gdk_gc_new (tmp_pixmap);
-         gdk_draw_pixbuf (tmp_pixmap, tmp_gc, pixbuf,
-                          0, 0, 
-                          0, 0,
-                          pixbuf_width, pixbuf_height,
-                          GDK_RGB_DITHER_NORMAL,
-                          0, 0);
-         g_object_unref (tmp_gc);
-
-         gc_values.fill = GDK_TILED;
-         gc_values.tile = tmp_pixmap;
-         tmp_gc = gdk_gc_new_with_values (window,
-                                          &gc_values, GDK_GC_FILL | GDK_GC_TILE);
+          cairo_t *cr = gdk_cairo_create (window);
+
+          gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
+          cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT);
+
          if (clip_rect)
-           gdk_draw_rectangle (window, tmp_gc, TRUE,
-                               clip_rect->x, clip_rect->y, clip_rect->width, clip_rect->height);
+           gdk_cairo_rectangle (cr, clip_rect);
          else
-           gdk_draw_rectangle (window, tmp_gc, TRUE, x, y, width, height);
+           cairo_rectangle (cr, x, y, width, height);
          
-         g_object_unref (tmp_gc);
-         g_object_unref (tmp_pixmap);
+          cairo_fill (cr);
+
+          cairo_destroy (cr);
        }
     }
 }