diff options
author | Owen Taylor <otaylor@redhat.com> | 2002-01-19 05:39:43 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 2002-01-19 05:39:43 +0000 |
commit | c77a8b918371334e6b24823107a246e66fd62574 (patch) | |
tree | d394fd0725a1796be62db095df3d4a60da90877d /modules | |
parent | 3f100bb8191d8e40cc55dbed3ee0ce3c09d480d5 (diff) | |
download | gtk+-c77a8b918371334e6b24823107a246e66fd62574.tar.gz |
Add an extrodinarily ugly example.
Sat Jan 19 00:32:14 2002 Owen Taylor <otaylor@redhat.com>
* examples/*: Add an extrodinarily ugly example.
* src/pixbuf-draw.c (draw_simple_image): Never shape
the window, even if we are allowed to. Shaping is
ugly -- if the widget isn't NO_WINDOW (most are),
you'll just have to draw it rectangular.
* src/pixbuf-render.c (pixbuf_render): Always use
gdk_pixbuf_render_alpha() with FULL_ALPHA() as the
type.
* pixbuf.h src/pixbuf-render.c (theme_pixbuf_compute_hints): To
speed up scaling, cache whether pixbufs have constant rows
or constant columns.
* src/pixbuf-render.c (pixbuf_render): Speed up scaling
by using the hints from compute_hints().
Diffstat (limited to 'modules')
-rw-r--r-- | modules/engines/pixbuf/ChangeLog | 25 | ||||
-rw-r--r-- | modules/engines/pixbuf/examples/bubble/README | 14 | ||||
-rw-r--r-- | modules/engines/pixbuf/examples/bubble/gtk-2.0/bc-dark.png | bin | 0 -> 63960 bytes | |||
-rw-r--r-- | modules/engines/pixbuf/examples/bubble/gtk-2.0/bc-light.png | bin | 0 -> 24945 bytes | |||
-rw-r--r-- | modules/engines/pixbuf/examples/bubble/gtk-2.0/bc.png | bin | 0 -> 63764 bytes | |||
-rw-r--r-- | modules/engines/pixbuf/examples/bubble/gtk-2.0/bubble-blue.png | bin | 0 -> 836 bytes | |||
-rw-r--r-- | modules/engines/pixbuf/examples/bubble/gtk-2.0/bubble-parts.xcf | bin | 0 -> 6335 bytes | |||
-rw-r--r-- | modules/engines/pixbuf/examples/bubble/gtk-2.0/triangle_background.png | bin | 0 -> 58238 bytes | |||
-rw-r--r-- | modules/engines/pixbuf/pixbuf-draw.c | 18 | ||||
-rw-r--r-- | modules/engines/pixbuf/pixbuf-render.c | 334 | ||||
-rw-r--r-- | modules/engines/pixbuf/pixbuf.h | 6 |
11 files changed, 333 insertions, 64 deletions
diff --git a/modules/engines/pixbuf/ChangeLog b/modules/engines/pixbuf/ChangeLog index 7ee358dd54..72c1bba1da 100644 --- a/modules/engines/pixbuf/ChangeLog +++ b/modules/engines/pixbuf/ChangeLog @@ -1,3 +1,28 @@ +Sat Jan 19 00:32:14 2002 Owen Taylor <otaylor@redhat.com> + + * examples/*: Add an extrodinarily ugly example. + + * src/pixbuf-draw.c (draw_simple_image): Never shape + the window, even if we are allowed to. Shaping is + ugly -- if the widget isn't NO_WINDOW (most are), + you'll just have to draw it rectangular. + + * src/pixbuf-render.c (pixbuf_render): Always use + gdk_pixbuf_render_alpha() with FULL_ALPHA() as the + type. + + * pixbuf.h src/pixbuf-render.c (theme_pixbuf_compute_hints): To + speed up scaling, cache whether pixbufs have constant rows + or constant columns. + + * src/pixbuf-render.c (pixbuf_render): Speed up scaling + by using the hints from compute_hints(). + +Fri Jan 18 20:49:48 2002 Owen Taylor <otaylor@redhat.com> + + * configure.in: Use pkg-config to get the binray version + of GTK+ that we use for an install path. + Fri Jan 18 18:14:11 2002 Owen Taylor <otaylor@redhat.com> * src/pixbuf-draw.c (draw_focus): Fix for changes to draw_focus. diff --git a/modules/engines/pixbuf/examples/bubble/README b/modules/engines/pixbuf/examples/bubble/README new file mode 100644 index 0000000000..46cade49d1 --- /dev/null +++ b/modules/engines/pixbuf/examples/bubble/README @@ -0,0 +1,14 @@ +gtk-2.0/triangle-background.png is copyright Owen Taylor, 1997 +and may be used without restriction as long as this attribution +is reproduced. + +images/bc.pnm images/bc-dark.pnm images/bc-light.png are +from the BrushedMetalClean theme; I believe Tuomas Kuosmanen +and Carsten Haitzler had something to do with the original +BrushedMetal artwork. + +This theme is truly hideous for a reason ... to demonstrate +that alpha-compositing is going on. + +Owen Taylor +19 Jan 2002x
\ No newline at end of file diff --git a/modules/engines/pixbuf/examples/bubble/gtk-2.0/bc-dark.png b/modules/engines/pixbuf/examples/bubble/gtk-2.0/bc-dark.png Binary files differnew file mode 100644 index 0000000000..ab87858cea --- /dev/null +++ b/modules/engines/pixbuf/examples/bubble/gtk-2.0/bc-dark.png diff --git a/modules/engines/pixbuf/examples/bubble/gtk-2.0/bc-light.png b/modules/engines/pixbuf/examples/bubble/gtk-2.0/bc-light.png Binary files differnew file mode 100644 index 0000000000..0c7ecd5d83 --- /dev/null +++ b/modules/engines/pixbuf/examples/bubble/gtk-2.0/bc-light.png diff --git a/modules/engines/pixbuf/examples/bubble/gtk-2.0/bc.png b/modules/engines/pixbuf/examples/bubble/gtk-2.0/bc.png Binary files differnew file mode 100644 index 0000000000..7b7c1da47f --- /dev/null +++ b/modules/engines/pixbuf/examples/bubble/gtk-2.0/bc.png diff --git a/modules/engines/pixbuf/examples/bubble/gtk-2.0/bubble-blue.png b/modules/engines/pixbuf/examples/bubble/gtk-2.0/bubble-blue.png Binary files differnew file mode 100644 index 0000000000..bea78c350f --- /dev/null +++ b/modules/engines/pixbuf/examples/bubble/gtk-2.0/bubble-blue.png diff --git a/modules/engines/pixbuf/examples/bubble/gtk-2.0/bubble-parts.xcf b/modules/engines/pixbuf/examples/bubble/gtk-2.0/bubble-parts.xcf Binary files differnew file mode 100644 index 0000000000..184d75069e --- /dev/null +++ b/modules/engines/pixbuf/examples/bubble/gtk-2.0/bubble-parts.xcf diff --git a/modules/engines/pixbuf/examples/bubble/gtk-2.0/triangle_background.png b/modules/engines/pixbuf/examples/bubble/gtk-2.0/triangle_background.png Binary files differnew file mode 100644 index 0000000000..a4a612d7ba --- /dev/null +++ b/modules/engines/pixbuf/examples/bubble/gtk-2.0/triangle_background.png diff --git a/modules/engines/pixbuf/pixbuf-draw.c b/modules/engines/pixbuf/pixbuf-draw.c index f9687bc006..ab192a446e 100644 --- a/modules/engines/pixbuf/pixbuf-draw.c +++ b/modules/engines/pixbuf/pixbuf-draw.c @@ -127,27 +127,11 @@ draw_simple_image(GtkStyle *style, { if (image->background) { - GdkBitmap *mask = NULL; - - if (image->background->stretch && setbg && - !GDK_IS_PIXMAP (window)) - { - GdkPixbuf *pixbuf = theme_pixbuf_get_pixbuf (image->background); - if (pixbuf && gdk_pixbuf_get_has_alpha (pixbuf)) - mask = gdk_pixmap_new (window, width, height, 1); - } - theme_pixbuf_render (image->background, - window, mask, area, + window, NULL, area, draw_center ? COMPONENT_ALL : COMPONENT_ALL | COMPONENT_CENTER, FALSE, x, y, width, height); - - if (mask) - { - gdk_window_shape_combine_mask (window, mask, 0, 0); - gdk_pixmap_unref (mask); - } } if (image->overlay && draw_center) diff --git a/modules/engines/pixbuf/pixbuf-render.c b/modules/engines/pixbuf/pixbuf-render.c index 7674ff14e0..d50d4c210d 100644 --- a/modules/engines/pixbuf/pixbuf-render.c +++ b/modules/engines/pixbuf/pixbuf-render.c @@ -20,17 +20,139 @@ * Carsten Haitzler <raster@rasterman.com> */ +#include <string.h> + #include "pixbuf.h" #include <gdk-pixbuf/gdk-pixbuf.h> GCache *pixbuf_cache = NULL; +static GdkPixbuf * +replicate_single (GdkPixbuf *src, + gint src_x, + gint src_y, + gint width, + gint height) +{ + guint n_channels = gdk_pixbuf_get_n_channels (src); + guchar *pixels = (gdk_pixbuf_get_pixels (src) + + src_y * gdk_pixbuf_get_rowstride (src) + + src_x * n_channels); + guchar r = *(pixels++); + guchar g = *(pixels++); + guchar b = *(pixels++); + guint dest_rowstride; + guchar *dest_pixels; + guchar a = 0; + GdkPixbuf *result; + int i, j; + + if (n_channels == 4) + a = *(pixels++); + + result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, n_channels == 4, 8, + width, height); + dest_rowstride = gdk_pixbuf_get_rowstride (result); + dest_pixels = gdk_pixbuf_get_pixels (result); + + for (i = 0; i < height; i++) + { + guchar *p = dest_pixels + dest_rowstride *i; + + for (j = 0; j < width; j++) + { + *(p++) = r; + *(p++) = g; + *(p++) = b; + + if (n_channels == 4) + *(p++) = a; + } + } + + return result; +} + +static GdkPixbuf * +replicate_rows (GdkPixbuf *src, + gint src_x, + gint src_y, + gint width, + gint height) +{ + guint n_channels = gdk_pixbuf_get_n_channels (src); + guint src_rowstride = gdk_pixbuf_get_rowstride (src); + guchar *pixels = (gdk_pixbuf_get_pixels (src) + src_y * src_rowstride + src_x * n_channels); + guchar *dest_pixels; + GdkPixbuf *result; + guint dest_rowstride; + int i; + + result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, n_channels == 4, 8, + width, height); + dest_rowstride = gdk_pixbuf_get_rowstride (result); + dest_pixels = gdk_pixbuf_get_pixels (result); + + for (i = 0; i < height; i++) + memcpy (dest_pixels + dest_rowstride * i, pixels, n_channels * width); + + return result; +} + +static GdkPixbuf * +replicate_cols (GdkPixbuf *src, + gint src_x, + gint src_y, + gint width, + gint height) +{ + guint n_channels = gdk_pixbuf_get_n_channels (src); + guint src_rowstride = gdk_pixbuf_get_rowstride (src); + guchar *pixels = (gdk_pixbuf_get_pixels (src) + src_y * src_rowstride + src_x * n_channels); + guchar *dest_pixels; + GdkPixbuf *result; + guint dest_rowstride; + int i, j; + + result = gdk_pixbuf_new (GDK_COLORSPACE_RGB, n_channels == 4, 8, + width, height); + dest_rowstride = gdk_pixbuf_get_rowstride (result); + dest_pixels = gdk_pixbuf_get_pixels (result); + + for (i = 0; i < height; i++) + { + guchar *p = dest_pixels + dest_rowstride * i; + guchar *q = pixels + src_rowstride * i; + + guchar r = *(q++); + guchar g = *(q++); + guchar b = *(q++); + guchar a = 0; + + if (n_channels == 4) + a = *(q++); + + for (j = 0; j < width; j++) + { + *(p++) = r; + *(p++) = g; + *(p++) = b; + + if (n_channels == 4) + *(p++) = a; + } + } + + return result; +} + /* Scale the rectangle (src_x, src_y, src_width, src_height) * onto the rectangle (dest_x, dest_y, dest_width, dest_height) * of the destination, clip by clip_rect and render */ static void pixbuf_render (GdkPixbuf *src, + guint hints, GdkWindow *window, GdkBitmap *mask, GdkRectangle *clip_rect, @@ -65,18 +187,39 @@ pixbuf_render (GdkPixbuf *src, */ if (!mask && clip_rect) { - /* The temporary is necessary only for GDK+-1.2, and not - * for later versions of GDK, where you can have the - * same source and dest for gdk_rectangle_intersect(). - */ - GdkRectangle tmp_rect = rect; - - if (!gdk_rectangle_intersect (clip_rect, &tmp_rect, &rect)) + if (!gdk_rectangle_intersect (clip_rect, &rect, &rect)) return; } - - if (dest_width != src_width || - dest_height != src_height) + + if (dest_width == src_width && dest_height == src_height) + { + tmp_pixbuf = g_object_ref (src); + + x_offset = src_x + rect.x - dest_x; + y_offset = src_y + rect.y - dest_y; + } + else if ((hints & THEME_CONSTANT_COLS) && (hints & THEME_CONSTANT_ROWS)) + { + tmp_pixbuf = replicate_single (src, src_x, src_y, dest_width, dest_height); + + x_offset = rect.x - dest_x; + y_offset = rect.y - dest_y; + } + else if (dest_width == src_width && (hints & THEME_CONSTANT_COLS)) + { + tmp_pixbuf = replicate_rows (src, src_x, src_y, dest_width, dest_height); + + x_offset = rect.x - dest_x; + y_offset = rect.y - dest_y; + } + else if (dest_height == src_height && (hints & THEME_CONSTANT_ROWS)) + { + tmp_pixbuf = replicate_cols (src, src_x, src_y, dest_width, dest_height); + + x_offset = rect.x - dest_x; + y_offset = rect.y - dest_y; + } + else { double x_scale = (double)dest_width / src_width; double y_scale = (double)dest_height / src_height; @@ -108,52 +251,30 @@ pixbuf_render (GdkPixbuf *src, x_offset = 0; y_offset = 0; } - else - { - tmp_pixbuf = src; - gdk_pixbuf_ref (tmp_pixbuf); - - x_offset = src_x + rect.x - dest_x; - y_offset = src_y + rect.y - dest_y; - } if (mask) { - GdkGC *tmp_gc; - gdk_pixbuf_render_threshold_alpha (tmp_pixbuf, mask, x_offset, y_offset, rect.x, rect.y, rect.width, rect.height, 128); - - tmp_gc = gdk_gc_new (window); - if (clip_rect) - gdk_gc_set_clip_rectangle (tmp_gc, clip_rect); - - gdk_pixbuf_render_to_drawable (tmp_pixbuf, window, tmp_gc, - x_offset, y_offset, - rect.x, rect.y, - rect.width, rect.height, - GDK_RGB_DITHER_NORMAL, - 0, 0); - gdk_gc_unref (tmp_gc); } - else - gdk_pixbuf_render_to_drawable_alpha (tmp_pixbuf, window, - x_offset, y_offset, - rect.x, rect.y, - rect.width, rect.height, - GDK_PIXBUF_ALPHA_BILEVEL, 128, - GDK_RGB_DITHER_NORMAL, - 0, 0); + + gdk_pixbuf_render_to_drawable_alpha (tmp_pixbuf, window, + x_offset, y_offset, + rect.x, rect.y, + rect.width, rect.height, + GDK_PIXBUF_ALPHA_FULL, 128, + GDK_RGB_DITHER_NORMAL, + 0, 0); gdk_pixbuf_unref (tmp_pixbuf); } ThemePixbuf * theme_pixbuf_new (void) { - ThemePixbuf *result = g_new (ThemePixbuf, 1); + ThemePixbuf *result = g_new0 (ThemePixbuf, 1); result->filename = NULL; result->pixbuf = NULL; @@ -189,6 +310,116 @@ theme_pixbuf_set_filename (ThemePixbuf *theme_pb, theme_pb->filename = g_strdup (filename); } +static guint +compute_hint (GdkPixbuf *pixbuf, + gint x0, + gint x1, + gint y0, + gint y1) +{ + int i, j; + int hints = THEME_CONSTANT_ROWS | THEME_CONSTANT_COLS; + int n_channels = gdk_pixbuf_get_n_channels (pixbuf); + + guchar *data = gdk_pixbuf_get_pixels (pixbuf); + int rowstride = gdk_pixbuf_get_rowstride (pixbuf); + + if (x0 == x1 || y0 == y1) + return 0; + + for (i = y0; i < y1; i++) + { + guchar *p = data + i * rowstride + x0 * n_channels; + guchar r = *(p++); + guchar g = *(p++); + guchar b = *(p++); + guchar a = 0; + + if (n_channels == 4) + a = *(p++); + + for (j = x0 + 1; j < x1 ; j++) + { + if (r != *(p++) || + g != *(p++) || + b != *(p++) || + (n_channels == 4 && a != *(p++))) + { + hints &= ~THEME_CONSTANT_ROWS; + goto cols; + } + } + } + + cols: + for (i = y0 + 1; i < y1; i++) + { + guchar *base = data + y0 * rowstride + x0 * n_channels; + guchar *p = data + i * rowstride + x0 * n_channels; + + if (memcmp (p, base, n_channels * (x1 - x0)) != 0) + { + hints &= ~THEME_CONSTANT_COLS; + return hints; + } + } + + return hints; +} + +static void +theme_pixbuf_compute_hints (ThemePixbuf *theme_pb) +{ + int i, j; + gint width = gdk_pixbuf_get_width (theme_pb->pixbuf); + gint height = gdk_pixbuf_get_height (theme_pb->pixbuf); + + for (i = 0; i < 3; i++) + { + gint y0, y1; + + switch (i) + { + case 0: + y0 = 0; + y1 = theme_pb->border_top; + break; + case 1: + y0 = theme_pb->border_top; + y1 = height - theme_pb->border_bottom; + break; + default: + y0 = height - theme_pb->border_bottom; + y1 = height; + break; + } + + for (j = 0; j < 3; j++) + { + gint x0, x1; + + switch (j) + { + case 0: + x0 = 0; + x1 = theme_pb->border_left; + break; + case 1: + x0 = theme_pb->border_left; + x1 = width - theme_pb->border_right; + break; + default: + x0 = width - theme_pb->border_right; + x1 = width; + break; + } + + theme_pb->hints[i][j] = compute_hint (theme_pb->pixbuf, x0, x1, y0, y1); + } + } + +} + void theme_pixbuf_set_border (ThemePixbuf *theme_pb, gint left, @@ -200,6 +431,9 @@ theme_pixbuf_set_border (ThemePixbuf *theme_pb, theme_pb->border_right = right; theme_pb->border_top = top; theme_pb->border_bottom = bottom; + + if (theme_pb->pixbuf) + theme_pixbuf_compute_hints (theme_pb); } void @@ -207,6 +441,9 @@ theme_pixbuf_set_stretch (ThemePixbuf *theme_pb, gboolean stretch) { theme_pb->stretch = stretch; + + if (theme_pb->pixbuf) + theme_pixbuf_compute_hints (theme_pb); } GdkPixbuf * @@ -238,6 +475,9 @@ theme_pixbuf_get_pixbuf (ThemePixbuf *theme_pb) g_str_hash, g_direct_hash, g_str_equal); theme_pb->pixbuf = g_cache_insert (pixbuf_cache, theme_pb->filename); + + if (theme_pb->stretch) + theme_pixbuf_compute_hints (theme_pb); } return theme_pb->pixbuf; @@ -288,11 +528,11 @@ theme_pixbuf_render (ThemePixbuf *theme_pb, if (component_mask & COMPONENT_ALL) component_mask = (COMPONENT_ALL - 1) & ~component_mask; -#define RENDER_COMPONENT(X1,X2,Y1,Y2) \ - pixbuf_render (pixbuf, window, mask, clip_rect, \ - src_x[X1], src_y[Y1], \ - src_x[X2] - src_x[X1], src_y[Y2] - src_y[Y1], \ - dest_x[X1], dest_y[Y1], \ +#define RENDER_COMPONENT(X1,X2,Y1,Y2) \ + pixbuf_render (pixbuf, theme_pb->hints[Y1][X1], window, mask, clip_rect, \ + src_x[X1], src_y[Y1], \ + src_x[X2] - src_x[X1], src_y[Y2] - src_y[Y1], \ + dest_x[X1], dest_y[Y1], \ dest_x[X2] - dest_x[X1], dest_y[Y2] - dest_y[Y1]); if (component_mask & COMPONENT_NORTH_WEST) @@ -329,7 +569,7 @@ theme_pixbuf_render (ThemePixbuf *theme_pb, x += (width - pixbuf_width) / 2; y += (height - pixbuf_height) / 2; - pixbuf_render (pixbuf, window, NULL, clip_rect, + pixbuf_render (pixbuf, 0, window, NULL, clip_rect, 0, 0, pixbuf_width, pixbuf_height, x, y, diff --git a/modules/engines/pixbuf/pixbuf.h b/modules/engines/pixbuf/pixbuf.h index 908e0177bc..34dfeb61c0 100644 --- a/modules/engines/pixbuf/pixbuf.h +++ b/modules/engines/pixbuf/pixbuf.h @@ -119,6 +119,11 @@ typedef enum { THEME_MATCH_ARROW_DIRECTION = 1 << 4 } ThemeMatchFlags; +typedef enum { + THEME_CONSTANT_ROWS = 1 << 0, + THEME_CONSTANT_COLS = 1 << 1 +} ThemeRenderHints; + struct _ThemePixbuf { gchar *filename; @@ -128,6 +133,7 @@ struct _ThemePixbuf gint border_right; gint border_bottom; gint border_top; + guint hints[3][3]; }; struct _ThemeMatchData |