[murrine] Added blur capabilities and menustyle = 2.
- From: Andrea Cimitan <acimitan src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [murrine] Added blur capabilities and menustyle = 2.
- Date: Thu, 5 Aug 2010 17:21:43 +0000 (UTC)
commit fd9b854f14ea45c8efaca016e802d2d80ab83c0c
Author: Andrea Cimitan <andrea cimitan gmail com>
Date: Thu Aug 5 18:21:11 2010 +0100
Added blur capabilities and menustyle = 2.
CREDITS | 2 +
Makefile.am | 10 ++-
NEWS | 1 +
src/exponential-blur.c | 299 ++++++++++++++++++++++++++++++++++++++++
src/exponential-blur.h | 42 ++++++
src/gaussian-blur.c | 172 +++++++++++++++++++++++
src/gaussian-blur.h | 42 ++++++
src/murrine_draw.c | 29 ++++-
src/murrine_draw_rgba.c | 27 ++++-
src/raico-blur.c | 184 +++++++++++++++++++++++++
src/raico-blur.h | 73 ++++++++++
src/stack-blur.c | 346 +++++++++++++++++++++++++++++++++++++++++++++++
src/stack-blur.h | 42 ++++++
13 files changed, 1266 insertions(+), 3 deletions(-)
---
diff --git a/CREDITS b/CREDITS
index a80111f..ceb3b64 100644
--- a/CREDITS
+++ b/CREDITS
@@ -1,5 +1,7 @@
Cimi's thanks:
+Mirco Mueller - for his amazing blur functions :)
+
Doug Whitely - for the permission to edit his theme and for the little help.
Oliver Tobin - for his support to refine my theme.
diff --git a/Makefile.am b/Makefile.am
index 9b58109..cd7162d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -24,7 +24,15 @@ libmurrine_la_SOURCES = \
./src/murrine_draw.c \
./src/murrine_draw_rgba.c \
./src/murrine_draw.h \
- ./src/murrine_types.h
+ ./src/murrine_types.h \
+ ./src/exponential-blur.c \
+ ./src/exponential-blur.h \
+ ./src/gaussian-blur.c \
+ ./src/gaussian-blur.h \
+ ./src/raico-blur.c \
+ ./src/raico-blur.h \
+ ./src/stack-blur.c \
+ ./src/stack-blur.h
libmurrine_la_LDFLAGS = -module -avoid-version -no-undefined
libmurrine_la_LIBADD = $(GTK_LIBS)
diff --git a/NEWS b/NEWS
index e6e8eaa..a0b459c 100644
--- a/NEWS
+++ b/NEWS
@@ -45,6 +45,7 @@ Changes in this release:
- New option: trough_shades = { 1.0, 1.0 } to draw a gradient on
the trough of GtkScrollbar and GtkProgressBar.
- Changed option: listviewstyle = 2 for a solid line.
+- Changed option: menustyle = 2 for glow on the sides of the menu.
- Changed option: reliefstyle = 3 for a gradient on shadow.
reliefstyle = 4 for a stronger shadow.
- Changed option: stepperstyle = 2 for squared steppers with a rounded slider.
diff --git a/src/exponential-blur.c b/src/exponential-blur.c
new file mode 100644
index 0000000..ea6b085
--- /dev/null
+++ b/src/exponential-blur.c
@@ -0,0 +1,299 @@
+////////////////////////////////////////////////////////////////////////////////
+//3456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
+// 10 20 30 40 50 60 70 80
+//
+// raico-blur
+//
+// exponential-blur.c - implements exponential-blur function
+//
+// Copyright 2009 Canonical Ltd.
+//
+// Authors:
+// Mirco "MacSlow" Mueller <mirco mueller canonical com>
+// Jason Smith <jason smith canonical com>
+//
+// Notes:
+// based on exponential-blur algorithm by Jani Huhtanen
+//
+// This program is free software: you can redistribute it and/or modify it
+// under the terms of the GNU General Public License version 3, as published
+// by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranties of
+// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+// PURPOSE. See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// FIXME: not working yet, unfinished
+
+#include <math.h>
+
+#include "exponential-blur.h"
+
+static inline void
+_blurinner (guchar* pixel,
+ gint *zR,
+ gint *zG,
+ gint *zB,
+ gint *zA,
+ gint alpha,
+ gint aprec,
+ gint zprec);
+
+static inline void
+_blurrow (guchar* pixels,
+ gint width,
+ gint height,
+ gint channels,
+ gint line,
+ gint alpha,
+ gint aprec,
+ gint zprec);
+
+static inline void
+_blurcol (guchar* pixels,
+ gint width,
+ gint height,
+ gint channels,
+ gint col,
+ gint alpha,
+ gint aprec,
+ gint zprec);
+
+void
+_expblur (guchar* pixels,
+ gint width,
+ gint height,
+ gint channels,
+ gint radius,
+ gint aprec,
+ gint zprec);
+
+void
+surface_exponential_blur (cairo_surface_t* surface,
+ guint radius)
+{
+ guchar* pixels;
+ guint width;
+ guint height;
+ cairo_format_t format;
+
+ // sanity checks are done in raico-blur.c
+
+ // before we mess with the surface execute any pending drawing
+ cairo_surface_flush (surface);
+
+ pixels = cairo_image_surface_get_data (surface);
+ width = cairo_image_surface_get_width (surface);
+ height = cairo_image_surface_get_height (surface);
+ format = cairo_image_surface_get_format (surface);
+
+ switch (format)
+ {
+ case CAIRO_FORMAT_ARGB32:
+ _expblur (pixels, width, height, 4, radius, 16, 7);
+ break;
+
+ case CAIRO_FORMAT_RGB24:
+ _expblur (pixels, width, height, 3, radius, 16, 7);
+ break;
+
+ case CAIRO_FORMAT_A8:
+ _expblur (pixels, width, height, 1, radius, 16, 7);
+ break;
+
+ default :
+ // do nothing
+ break;
+ }
+
+ // inform cairo we altered the surfaces contents
+ cairo_surface_mark_dirty (surface);
+}
+
+//
+// pixels image-data
+// width image-width
+// height image-height
+// channels image-channels
+//
+// in-place blur of image 'img' with kernel of approximate radius 'radius'
+//
+// blurs with two sided exponential impulse response
+//
+// aprec = precision of alpha parameter in fixed-point format 0.aprec
+//
+// zprec = precision of state parameters zR,zG,zB and zA in fp format 8.zprec
+//
+void
+_expblur (guchar* pixels,
+ gint width,
+ gint height,
+ gint channels,
+ gint radius,
+ gint aprec,
+ gint zprec)
+{
+ gint alpha;
+ gint row = 0;
+ gint col = 0;
+
+ if (radius < 1)
+ return;
+
+ // calculate the alpha such that 90% of
+ // the kernel is within the radius.
+ // (Kernel extends to infinity)
+ alpha = (gint) ((1 << aprec) * (1.0f - expf (-2.3f / (radius + 1.f))));
+
+ for (; row < height; row++)
+ _blurrow (pixels,
+ width,
+ height,
+ channels,
+ row,
+ alpha,
+ aprec,
+ zprec);
+
+ for(; col < width; col++)
+ _blurcol (pixels,
+ width,
+ height,
+ channels,
+ col,
+ alpha,
+ aprec,
+ zprec);
+
+ return;
+}
+
+static inline void
+_blurinner (guchar* pixel,
+ gint *zR,
+ gint *zG,
+ gint *zB,
+ gint *zA,
+ gint alpha,
+ gint aprec,
+ gint zprec)
+{
+ gint R;
+ gint G;
+ gint B;
+ guchar A;
+
+ R = *pixel;
+ G = *(pixel + 1);
+ B = *(pixel + 2);
+ A = *(pixel + 3);
+
+ *zR += (alpha * ((R << zprec) - *zR)) >> aprec;
+ *zG += (alpha * ((G << zprec) - *zG)) >> aprec;
+ *zB += (alpha * ((B << zprec) - *zB)) >> aprec;
+ *zA += (alpha * ((A << zprec) - *zA)) >> aprec;
+
+ *pixel = *zR >> zprec;
+ *(pixel + 1) = *zG >> zprec;
+ *(pixel + 2) = *zB >> zprec;
+ *(pixel + 3) = *zA >> zprec;
+}
+
+static inline void
+_blurrow (guchar* pixels,
+ gint width,
+ gint height,
+ gint channels,
+ gint line,
+ gint alpha,
+ gint aprec,
+ gint zprec)
+{
+ gint zR;
+ gint zG;
+ gint zB;
+ gint zA;
+ gint index;
+ guchar* scanline;
+
+ scanline = &(pixels[line * width * channels]);
+
+ zR = *scanline << zprec;
+ zG = *(scanline + 1) << zprec;
+ zB = *(scanline + 2) << zprec;
+ zA = *(scanline + 3) << zprec;
+
+ for (index = 0; index < width; index ++)
+ _blurinner (&scanline[index * channels],
+ &zR,
+ &zG,
+ &zB,
+ &zA,
+ alpha,
+ aprec,
+ zprec);
+
+ for (index = width - 2; index >= 0; index--)
+ _blurinner (&scanline[index * channels],
+ &zR,
+ &zG,
+ &zB,
+ &zA,
+ alpha,
+ aprec,
+ zprec);
+}
+
+static inline void
+_blurcol (guchar* pixels,
+ gint width,
+ gint height,
+ gint channels,
+ gint x,
+ gint alpha,
+ gint aprec,
+ gint zprec)
+{
+ gint zR;
+ gint zG;
+ gint zB;
+ gint zA;
+ gint index;
+ guchar* ptr;
+
+ ptr = pixels;
+
+ ptr += x * channels;
+
+ zR = *((guchar*) ptr ) << zprec;
+ zG = *((guchar*) ptr + 1) << zprec;
+ zB = *((guchar*) ptr + 2) << zprec;
+ zA = *((guchar*) ptr + 3) << zprec;
+
+ for (index = width; index < (height - 1) * width; index += width)
+ _blurinner ((guchar*) &ptr[index * channels],
+ &zR,
+ &zG,
+ &zB,
+ &zA,
+ alpha,
+ aprec,
+ zprec);
+
+ for (index = (height - 2) * width; index >= 0; index -= width)
+ _blurinner ((guchar*) &ptr[index * channels],
+ &zR,
+ &zG,
+ &zB,
+ &zA,
+ alpha,
+ aprec,
+ zprec);
+}
+
diff --git a/src/exponential-blur.h b/src/exponential-blur.h
new file mode 100644
index 0000000..203fd0a
--- /dev/null
+++ b/src/exponential-blur.h
@@ -0,0 +1,42 @@
+////////////////////////////////////////////////////////////////////////////////
+//3456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
+// 10 20 30 40 50 60 70 80
+//
+// raico-blur
+//
+// exponential-blur.h - implements exponential-blur function
+//
+// Copyright 2009 Canonical Ltd.
+//
+// Authors:
+// Mirco "MacSlow" Mueller <mirco mueller canonical com>
+//
+// Notes:
+// based on exponential-blur algorithm by Jani Huhtanen
+//
+// This program is free software: you can redistribute it and/or modify it
+// under the terms of the GNU General Public License version 3, as published
+// by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranties of
+// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+// PURPOSE. See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+#ifndef _EXPONENTIAL_BLUR_H
+#define _EXPONENTIAL_BLUR_H
+
+#include <glib.h>
+#include <cairo.h>
+
+void
+surface_exponential_blur (cairo_surface_t* surface,
+ guint radius);
+
+#endif // _EXPONENTIAL_BLUR_H
+
diff --git a/src/gaussian-blur.c b/src/gaussian-blur.c
new file mode 100644
index 0000000..7694ebc
--- /dev/null
+++ b/src/gaussian-blur.c
@@ -0,0 +1,172 @@
+////////////////////////////////////////////////////////////////////////////////
+//3456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
+// 10 20 30 40 50 60 70 80
+//
+// raico-blur
+//
+// gaussian-blur.c - implements gaussian-blur function
+//
+// Copyright 2009 Canonical Ltd.
+//
+// Authors:
+// Mirco "MacSlow" Mueller <mirco mueller canonical com>
+//
+// Notes:
+// based on filters in libpixman
+//
+// This program is free software: you can redistribute it and/or modify it
+// under the terms of the GNU General Public License version 3, as published
+// by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranties of
+// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+// PURPOSE. See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+#include <math.h>
+#include <pixman.h>
+
+#include "gaussian-blur.h"
+
+pixman_fixed_t*
+create_gaussian_blur_kernel (gint radius,
+ gdouble sigma,
+ gint* length)
+{
+ const gdouble scale2 = 2.0f * sigma * sigma;
+ const gdouble scale1 = 1.0f / (G_PI * scale2);
+ const gint size = 2 * radius + 1;
+ const gint n_params = size * size;
+ pixman_fixed_t* params;
+ gdouble* tmp;
+ gdouble sum;
+ gint x;
+ gint y;
+ gint i;
+
+ tmp = g_newa (double, n_params);
+
+ // caluclate gaussian kernel in floating point format
+ for (i = 0, sum = 0, x = -radius; x <= radius; ++x) {
+ for (y = -radius; y <= radius; ++y, ++i) {
+ const gdouble u = x * x;
+ const gdouble v = y * y;
+
+ tmp[i] = scale1 * exp (-(u+v)/scale2);
+
+ sum += tmp[i];
+ }
+ }
+
+ // normalize gaussian kernel and convert to fixed point format
+ params = g_new (pixman_fixed_t, n_params + 2);
+
+ params[0] = pixman_int_to_fixed (size);
+ params[1] = pixman_int_to_fixed (size);
+
+ for (i = 0; i < n_params; ++i)
+ params[2 + i] = pixman_double_to_fixed (tmp[i] / sum);
+
+ if (length)
+ *length = n_params + 2;
+
+ return params;
+}
+
+void
+_blur_image_surface (cairo_surface_t* surface,
+ gint radius,
+ gdouble sigma /* pass 0.0f for auto-calculation */)
+{
+ pixman_fixed_t* params = NULL;
+ gint n_params;
+ pixman_image_t* src;
+ gint w;
+ gint h;
+ gint s;
+ gpointer p;
+ gdouble radiusf;
+
+ radiusf = fabs (radius) + 1.0f;
+ if (sigma == 0.0f)
+ sigma = sqrt (-(radiusf * radiusf) / (2.0f * log (1.0f / 255.0f)));
+
+ w = cairo_image_surface_get_width (surface);
+ h = cairo_image_surface_get_height (surface);
+ s = cairo_image_surface_get_stride (surface);
+
+ // create pixman image for cairo image surface
+ p = cairo_image_surface_get_data (surface);
+ src = pixman_image_create_bits (PIXMAN_a8r8g8b8, w, h, p, s);
+
+ // attach gaussian kernel to pixman image
+ params = create_gaussian_blur_kernel (radius, sigma, &n_params);
+ pixman_image_set_filter (src,
+ PIXMAN_FILTER_CONVOLUTION,
+ params,
+ n_params);
+ g_free (params);
+
+ // render blured image to new pixman image
+ pixman_image_composite (PIXMAN_OP_SRC,
+ src,
+ NULL,
+ src,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ w,
+ h);
+ pixman_image_unref (src);
+}
+
+void
+surface_gaussian_blur (cairo_surface_t* surface,
+ guint radius)
+{
+ guchar* pixels;
+ guint width;
+ guint height;
+ cairo_format_t format;
+
+ // sanity checks are done in raico-blur.c
+
+ // before we mess with the surface execute any pending drawing
+ cairo_surface_flush (surface);
+
+ pixels = cairo_image_surface_get_data (surface);
+ width = cairo_image_surface_get_width (surface);
+ height = cairo_image_surface_get_height (surface);
+ format = cairo_image_surface_get_format (surface);
+
+ switch (format)
+ {
+ case CAIRO_FORMAT_ARGB32:
+ _blur_image_surface (surface, radius, 0.0f);
+ break;
+
+ case CAIRO_FORMAT_RGB24:
+ // do nothing, for now
+ break;
+
+ case CAIRO_FORMAT_A8:
+ // do nothing, for now
+ break;
+
+ default :
+ // do nothing
+ break;
+ }
+
+ // inform cairo we altered the surfaces contents
+ cairo_surface_mark_dirty (surface);
+}
+
diff --git a/src/gaussian-blur.h b/src/gaussian-blur.h
new file mode 100644
index 0000000..e06f352
--- /dev/null
+++ b/src/gaussian-blur.h
@@ -0,0 +1,42 @@
+////////////////////////////////////////////////////////////////////////////////
+//3456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
+// 10 20 30 40 50 60 70 80
+//
+// notify-osd
+//
+// gaussian-blur.h - implements gaussian-blur function
+//
+// Copyright 2009 Canonical Ltd.
+//
+// Authors:
+// Mirco "MacSlow" Mueller <mirco mueller canonical com>
+//
+// Notes:
+// based on filters in libpixman
+//
+// This program is free software: you can redistribute it and/or modify it
+// under the terms of the GNU General Public License version 3, as published
+// by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranties of
+// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+// PURPOSE. See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+#ifndef _GAUSSIAN_BLUR_H
+#define _GAUSSIAN_BLUR_H
+
+#include <glib.h>
+#include <cairo.h>
+
+void
+surface_gaussian_blur (cairo_surface_t* surface,
+ guint radius);
+
+#endif // _GAUSSIAN_BLUR_H
+
diff --git a/src/murrine_draw.c b/src/murrine_draw.c
index bac84e3..b4a62e6 100644
--- a/src/murrine_draw.c
+++ b/src/murrine_draw.c
@@ -25,6 +25,7 @@
#include "murrine_types.h"
#include "support.h"
#include "cairo-support.h"
+#include "raico-blur.h"
static void
murrine_draw_inset (cairo_t *cr,
@@ -2272,7 +2273,7 @@ murrine_draw_menu_frame (cairo_t *cr,
int x, int y, int width, int height,
int menustyle)
{
- const MurrineRGB *border = &colors->shade[5];
+ const MurrineRGB *border = &colors->shade[menustyle == 2 ? 2 : 5];
cairo_translate (cr, x, y);
@@ -2280,6 +2281,7 @@ murrine_draw_menu_frame (cairo_t *cr,
cairo_rectangle (cr, 0.5, 0.5, width-1, height-1);
cairo_stroke (cr);
+
if (menustyle == 1)
{
MurrineRGB *fill = (MurrineRGB*)&colors->spot[1];
@@ -2293,6 +2295,31 @@ murrine_draw_menu_frame (cairo_t *cr,
murrine_set_color_rgb (cr, fill);
cairo_fill (cr);
}
+
+ if (menustyle == 2)
+ {
+ raico_blur_t* blur = NULL;
+ cairo_t *cr_surface;
+ cairo_surface_t *surface;
+
+ MurrineRGB fill;
+ murrine_shade (&colors->bg[0], 0.1, &fill);
+
+ /* draw glow */
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width+40, height+40);
+ cr_surface = cairo_create (surface);
+ blur = raico_blur_create (RAICO_BLUR_QUALITY_LOW);
+ raico_blur_set_radius (blur, 20);
+ cairo_set_line_width (cr_surface, 4.0);
+ cairo_rectangle (cr_surface, 20, 15, width, height+5);
+ murrine_set_color_rgb (cr_surface, &fill);
+ cairo_stroke (cr_surface);
+ raico_blur_apply (blur, surface);
+ cairo_set_source_surface (cr, surface, -20, -20);
+ cairo_paint (cr);
+ cairo_surface_destroy (surface);
+ cairo_destroy (cr_surface);
+ }
}
static void
diff --git a/src/murrine_draw_rgba.c b/src/murrine_draw_rgba.c
index 04e20dc..c283247 100644
--- a/src/murrine_draw_rgba.c
+++ b/src/murrine_draw_rgba.c
@@ -2225,7 +2225,7 @@ murrine_rgba_draw_menu_frame (cairo_t *cr,
int x, int y, int width, int height,
int menustyle)
{
- const MurrineRGB *border = &colors->shade[5];
+ const MurrineRGB *border = &colors->shade[menustyle == 2 ? 2 : 5];
uint8 corners = (menustyle == 1 ? MRN_CORNER_BOTTOMRIGHT :
MRN_CORNER_BOTTOMLEFT | MRN_CORNER_BOTTOMRIGHT);
@@ -2256,6 +2256,31 @@ murrine_rgba_draw_menu_frame (cairo_t *cr,
murrine_set_color_rgb (cr, fill);
cairo_fill (cr);
}
+
+ if (menustyle == 2)
+ {
+ raico_blur_t* blur = NULL;
+ cairo_t *cr_surface;
+ cairo_surface_t *surface;
+
+ MurrineRGB fill;
+ murrine_shade (&colors->bg[0], 0.1, &fill);
+
+ /* draw glow */
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width+40, height+40);
+ cr_surface = cairo_create (surface);
+ blur = raico_blur_create (RAICO_BLUR_QUALITY_LOW);
+ raico_blur_set_radius (blur, 20);
+ cairo_set_line_width (cr_surface, 4.0);
+ cairo_rectangle (cr_surface, 20, 15, width, height+5);
+ murrine_set_color_rgb (cr_surface, &fill);
+ cairo_stroke (cr_surface);
+ raico_blur_apply (blur, surface);
+ cairo_set_source_surface (cr, surface, -20, -20);
+ cairo_paint (cr);
+ cairo_surface_destroy (surface);
+ cairo_destroy (cr_surface);
+ }
}
static void
diff --git a/src/raico-blur.c b/src/raico-blur.c
new file mode 100644
index 0000000..2fdc08f
--- /dev/null
+++ b/src/raico-blur.c
@@ -0,0 +1,184 @@
+////////////////////////////////////////////////////////////////////////////////
+//3456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
+// 10 20 30 40 50 60 70 80
+//
+// notify-osd
+//
+// raico-blur.c - implements public API for blurring cairo image-surfaces
+//
+// Copyright 2009 Canonical Ltd.
+//
+// Authors:
+// Mirco "MacSlow" Mueller <mirco mueller canonical com>
+//
+// This program is free software: you can redistribute it and/or modify it
+// under the terms of the GNU General Public License version 3, as published
+// by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranties of
+// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+// PURPOSE. See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+#include "raico-blur.h"
+#include "exponential-blur.h"
+#include "stack-blur.h"
+#include "gaussian-blur.h"
+
+struct _raico_blur_private_t
+{
+ raico_blur_quality_t quality; // low, medium, high
+ guint radius; // blur-radius
+};
+
+raico_blur_t*
+raico_blur_create (raico_blur_quality_t quality)
+{
+ raico_blur_t* blur = NULL;
+ raico_blur_private_t* priv = NULL;
+
+ blur = g_new0 (raico_blur_t, 1);
+ if (!blur)
+ {
+ g_debug ("raico_blur_create(): could not allocate blur struct");
+ return NULL;
+ }
+
+ priv = g_new0 (raico_blur_private_t, 1);
+ if (!priv)
+ {
+ g_debug ("raico_blur_create(): could not allocate priv struct");
+ g_free ((gpointer) blur);
+ return NULL;
+ }
+
+ priv->quality = quality;
+ priv->radius = 0;
+
+ blur->priv = priv;
+
+ return blur;
+}
+
+raico_blur_quality_t
+raico_blur_get_quality (raico_blur_t* blur)
+{
+ g_assert (blur != NULL);
+
+ return blur->priv->quality;
+}
+
+void
+raico_blur_set_quality (raico_blur_t* blur,
+ raico_blur_quality_t quality)
+{
+ if (!blur)
+ {
+ g_debug ("raico_blur_set_quality(): NULL blur-pointer passed");
+ return;
+ }
+
+ blur->priv->quality = quality;
+}
+
+guint
+raico_blur_get_radius (raico_blur_t* blur)
+{
+ g_assert (blur != NULL);
+
+ return blur->priv->radius;
+}
+
+void
+raico_blur_set_radius (raico_blur_t* blur,
+ guint radius)
+{
+ if (!blur)
+ {
+ g_debug ("raico_blur_set_radius(): NULL blur-pointer passed");
+ return;
+ }
+
+ blur->priv->radius = radius;
+}
+
+void
+raico_blur_apply (raico_blur_t* blur,
+ cairo_surface_t* surface)
+{
+ cairo_format_t format;
+
+ // sanity checks
+ if (!blur)
+ {
+ g_debug ("raico_blur_apply(): NULL blur-pointer passed");
+ return;
+ }
+
+ if (!surface)
+ {
+ g_debug ("raico_blur_apply(): NULL surface-pointer passed");
+ return;
+ }
+
+ if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS)
+ {
+ g_debug ("raico_blur_apply(): invalid surface status");
+ return;
+ }
+
+ if (cairo_surface_get_type (surface) != CAIRO_SURFACE_TYPE_IMAGE)
+ {
+ g_debug ("raico_blur_apply(): non-image surface passed");
+ return;
+ }
+
+ format = cairo_image_surface_get_format (surface);
+ if (format != CAIRO_FORMAT_A8 &&
+ format != CAIRO_FORMAT_RGB24 &&
+ format != CAIRO_FORMAT_ARGB32)
+ {
+ g_debug ("raico_blur_apply(): unsupported image-format");
+ return;
+ }
+
+ // stupid, but you never know
+ if (blur->priv->radius == 0)
+ return;
+
+ // now do the real work
+ switch (blur->priv->quality)
+ {
+ case RAICO_BLUR_QUALITY_LOW:
+ surface_exponential_blur (surface, blur->priv->radius);
+ break;
+
+ case RAICO_BLUR_QUALITY_MEDIUM:
+ //surface_stack_blur (surface, blur->priv->radius);
+ surface_gaussian_blur (surface, blur->priv->radius);
+ break;
+
+ case RAICO_BLUR_QUALITY_HIGH:
+ surface_gaussian_blur (surface, blur->priv->radius);
+ break;
+ }
+}
+
+void
+raico_blur_destroy (raico_blur_t* blur)
+{
+ if (!blur)
+ {
+ g_debug ("raico_blur_destroy(): invalid blur-pointer passed");
+ return;
+ }
+
+ g_free ((gpointer) blur->priv);
+ g_free ((gpointer) blur);
+}
+
diff --git a/src/raico-blur.h b/src/raico-blur.h
new file mode 100644
index 0000000..c1d743e
--- /dev/null
+++ b/src/raico-blur.h
@@ -0,0 +1,73 @@
+////////////////////////////////////////////////////////////////////////////////
+//3456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
+// 10 20 30 40 50 60 70 80
+//
+// notify-osd
+//
+// raico-blur.h - implements public API for blurring cairo image-surfaces
+//
+// Copyright 2009 Canonical Ltd.
+//
+// Authors:
+// Mirco "MacSlow" Mueller <mirco mueller canonical com>
+//
+// This program is free software: you can redistribute it and/or modify it
+// under the terms of the GNU General Public License version 3, as published
+// by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranties of
+// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+// PURPOSE. See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+#ifndef _RAICO_BLUR_H
+#define _RAICO_BLUR_H
+
+#include <glib.h>
+#include <cairo.h>
+
+typedef enum _raico_blur_quality_t
+{
+ RAICO_BLUR_QUALITY_LOW = 0, // low quality, but fast, maybe interactive
+ RAICO_BLUR_QUALITY_MEDIUM, // compromise between speed and quality
+ RAICO_BLUR_QUALITY_HIGH // quality before speed
+} raico_blur_quality_t;
+
+typedef struct _raico_blur_private_t raico_blur_private_t;
+
+typedef struct _raico_blur_t
+{
+ raico_blur_private_t* priv;
+} raico_blur_t;
+
+raico_blur_t*
+raico_blur_create (raico_blur_quality_t quality);
+
+raico_blur_quality_t
+raico_blur_get_quality (raico_blur_t* blur);
+
+void
+raico_blur_set_quality (raico_blur_t* blur,
+ raico_blur_quality_t quality);
+
+guint
+raico_blur_get_radius (raico_blur_t* blur);
+
+void
+raico_blur_set_radius (raico_blur_t* blur,
+ guint radius);
+
+void
+raico_blur_apply (raico_blur_t* blur,
+ cairo_surface_t* surface);
+
+void
+raico_blur_destroy (raico_blur_t* blur);
+
+#endif // _RAICO_BLUR_H
+
diff --git a/src/stack-blur.c b/src/stack-blur.c
new file mode 100644
index 0000000..fe3bce3
--- /dev/null
+++ b/src/stack-blur.c
@@ -0,0 +1,346 @@
+////////////////////////////////////////////////////////////////////////////////
+//3456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
+// 10 20 30 40 50 60 70 80
+//
+// raico-blur
+//
+// stack-blur.c - implements stack-blur function
+//
+// Copyright 2009 Canonical Ltd.
+//
+// Authors:
+// Mirco "MacSlow" Mueller <mirco mueller canonical com>
+//
+// Notes:
+// based on stack-blur algorithm by Mario Klingemann <mario quasimondo com>
+//
+// This program is free software: you can redistribute it and/or modify it
+// under the terms of the GNU General Public License version 3, as published
+// by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranties of
+// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+// PURPOSE. See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+// FIXME: not working yet, unfinished
+
+#include <math.h>
+#include <stdlib.h>
+
+#include "stack-blur.h"
+
+void
+surface_stack_blur (cairo_surface_t* surface,
+ guint radius)
+{
+ guchar* pixels;
+ guint width;
+ guint height;
+ cairo_format_t format;
+
+ // sanity checks are done in raico-blur.c
+
+ // before we mess with the surface execute any pending drawing
+ cairo_surface_flush (surface);
+
+ pixels = cairo_image_surface_get_data (surface);
+ width = cairo_image_surface_get_width (surface);
+ height = cairo_image_surface_get_height (surface);
+ format = cairo_image_surface_get_format (surface);
+
+ switch (format)
+ {
+ case CAIRO_FORMAT_ARGB32:{
+
+ gint w = width;
+ gint h = height;
+ gint wm = w - 1;
+ gint hm = h - 1;
+ gint wh = w * h;
+ gint div = radius + radius + 1;
+
+ if (radius < 1)
+ break;
+
+ gint* r = (gint*) g_malloc0 (wh);
+ gint* g = (gint*) g_malloc0 (wh);
+ gint* b = (gint*) g_malloc0 (wh);
+ gint* a = (gint*) g_malloc0 (wh);
+
+ gint rsum;
+ gint gsum;
+ gint bsum;
+ gint asum;
+ gint x;
+ gint y;
+ gint i;
+ gint yp;
+ gint yi;
+ gint yw;
+ gint* dv = NULL;
+
+ gint* vmin = (gint*) g_malloc0 (MAX (w, h));
+
+ gint divsum = (div + 1) >> 1;
+ divsum *= divsum;
+ dv = (gint*) g_malloc0 (256 * divsum);
+ g_assert (dv != NULL);
+
+ for (i = 0; i < 256 * divsum; ++i)
+ dv[i] = (i / divsum);
+
+ yw = yi = 0;
+
+ gint** stack = (gint**) g_malloc0 (div);
+
+ for (i = 0; i < div; ++i)
+ stack[i] = (gint*) g_malloc0 (4);
+
+ gint stackpointer;
+ gint stackstart;
+ gint* sir;
+ gint rbs;
+ gint r1 = radius + 1;
+ gint routsum;
+ gint goutsum;
+ gint boutsum;
+ gint aoutsum;
+ gint rinsum;
+ gint ginsum;
+ gint binsum;
+ gint ainsum;
+
+ for (y = 0; y < h; ++y)
+ {
+ rinsum = ginsum = binsum = ainsum = routsum = goutsum = boutsum = aoutsum = rsum = gsum = bsum = asum = 0;
+
+ for(i =- radius; i <= radius; ++i)
+ {
+ sir = stack[i + radius];
+ sir[0] = pixels[yi + MIN (wm, MAX (i, 0)) + 0];
+ sir[1] = pixels[yi + MIN (wm, MAX (i, 0)) + 1];
+ sir[2] = pixels[yi + MIN (wm, MAX (i, 0)) + 2];
+ sir[3] = pixels[yi + MIN (wm, MAX (i, 0)) + 3];
+
+ rbs = r1 - abs (i);
+ rsum += sir[0] * rbs;
+ gsum += sir[1] * rbs;
+ bsum += sir[2] * rbs;
+ asum += sir[3] * rbs;
+
+ if (i > 0)
+ {
+ rinsum += sir[0];
+ ginsum += sir[1];
+ binsum += sir[2];
+ ainsum += sir[3];
+ }
+ else
+ {
+ routsum += sir[0];
+ goutsum += sir[1];
+ boutsum += sir[2];
+ aoutsum += sir[3];
+ }
+ }
+
+ stackpointer = radius;
+
+ for (x = 0; x < w; ++x)
+ {
+ r[yi] = dv[rsum];
+ g[yi] = dv[gsum];
+ b[yi] = dv[bsum];
+ a[yi] = dv[asum];
+
+ rsum -= routsum;
+ gsum -= goutsum;
+ bsum -= boutsum;
+ asum -= aoutsum;
+
+ stackstart = stackpointer - radius + div;
+ sir = stack[stackstart % div];
+
+ routsum -= sir[0];
+ goutsum -= sir[1];
+ boutsum -= sir[2];
+ aoutsum -= sir[3];
+
+ if (y == 0)
+ vmin[x] = MIN (x + radius + 1, wm);
+
+ sir[0] = pixels[yw + vmin[x] + 0];
+ sir[1] = pixels[yw + vmin[x] + 1];
+ sir[2] = pixels[yw + vmin[x] + 2];
+ sir[3] = pixels[yw + vmin[x] + 3];
+
+ rinsum += sir[0];
+ ginsum += sir[1];
+ binsum += sir[2];
+ ainsum += sir[3];
+
+ rsum += rinsum;
+ gsum += ginsum;
+ bsum += binsum;
+ asum += ainsum;
+
+ stackpointer = (stackpointer + 1) % div;
+ sir = stack[(stackpointer) % div];
+
+ routsum += sir[0];
+ goutsum += sir[1];
+ boutsum += sir[2];
+ aoutsum += sir[3];
+
+ rinsum -= sir[0];
+ ginsum -= sir[1];
+ binsum -= sir[2];
+ ainsum -= sir[3];
+
+ ++yi;
+ }
+
+ yw += w;
+
+ }
+
+ for (x = 0; x < w; ++x)
+ {
+ rinsum = ginsum = binsum = ainsum = routsum = goutsum = boutsum = aoutsum = rsum = gsum = bsum = asum = 0;
+
+ yp =- radius * w;
+
+ for (i =- radius; i <= radius; ++i)
+ {
+ yi = MAX (0, yp) + x;
+
+ sir = stack[i + radius];
+
+ sir[0] = r[yi];
+ sir[1] = g[yi];
+ sir[2] = b[yi];
+ sir[3] = a[yi];
+
+ rbs = r1 - abs (i);
+
+ rsum += r[yi] * rbs;
+ gsum += g[yi] * rbs;
+ bsum += b[yi] * rbs;
+ asum += a[yi] * rbs;
+
+ if (i > 0)
+ {
+ rinsum += sir[0];
+ ginsum += sir[1];
+ binsum += sir[2];
+ ainsum += sir[3];
+ }
+ else
+ {
+ routsum += sir[0];
+ goutsum += sir[1];
+ boutsum += sir[2];
+ aoutsum += sir[3];
+ }
+
+ if (i < hm)
+ yp += w;
+ }
+
+ yi = x;
+ stackpointer = radius;
+
+ for (y = 0; y < h; ++y)
+ {
+ pixels[yi + 0] = dv[rsum];
+ pixels[yi + 1] = dv[gsum];
+ pixels[yi + 2] = dv[bsum];
+ pixels[yi + 3] = dv[asum];
+
+ rsum -= routsum;
+ gsum -= goutsum;
+ bsum -= boutsum;
+ asum -= aoutsum;
+
+ stackstart = stackpointer - radius + div;
+ sir = stack[stackstart % div];
+
+ routsum -= sir[0];
+ goutsum -= sir[1];
+ boutsum -= sir[2];
+ aoutsum -= sir[3];
+
+ if (x == 0)
+ vmin[y] = MIN (y + r1, hm) * w;
+
+ gint pixel = x + vmin[y];
+
+ sir[0] = r[pixel];
+ sir[1] = g[pixel];
+ sir[2] = b[pixel];
+ sir[3] = a[pixel];
+
+ rinsum += sir[0];
+ ginsum += sir[1];
+ binsum += sir[2];
+ ainsum += sir[3];
+
+ rsum += rinsum;
+ gsum += ginsum;
+ bsum += binsum;
+ asum += ainsum;
+
+ stackpointer = (stackpointer + 1) % div;
+ sir = stack[stackpointer];
+
+ routsum += sir[0];
+ goutsum += sir[1];
+ boutsum += sir[2];
+ aoutsum += sir[3];
+
+ rinsum -= sir[0];
+ ginsum -= sir[1];
+ binsum -= sir[2];
+ ainsum -= sir[3];
+
+ yi += w;
+ }
+ }
+
+ g_free ((gpointer) r);
+ g_free ((gpointer) g);
+ g_free ((gpointer) b);
+ g_free ((gpointer) a);
+ g_free ((gpointer) vmin);
+ g_free ((gpointer) dv);
+
+ for (i = 0; i < div; ++i)
+ g_free ((gpointer) stack[i]);
+
+ g_free ((gpointer) stack);
+ }
+ break;
+
+ case CAIRO_FORMAT_RGB24:
+ // do nothing, for the moment
+ break;
+
+ case CAIRO_FORMAT_A8:
+ // do nothing, for the moment
+ break;
+
+ default :
+ // really do nothing
+ break;
+ }
+
+ // inform cairo we altered the surfaces contents
+ cairo_surface_mark_dirty (surface);
+}
+
diff --git a/src/stack-blur.h b/src/stack-blur.h
new file mode 100644
index 0000000..2cb12b3
--- /dev/null
+++ b/src/stack-blur.h
@@ -0,0 +1,42 @@
+////////////////////////////////////////////////////////////////////////////////
+//3456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
+// 10 20 30 40 50 60 70 80
+//
+// notify-osd
+//
+// stack-blur.h - implements stack-blur function
+//
+// Copyright 2009 Canonical Ltd.
+//
+// Authors:
+// Mirco "MacSlow" Mueller <mirco mueller canonical com>
+//
+// Notes:
+// based on stack-blur algorithm by Mario Klingemann <mario quasimondo com>
+//
+// This program is free software: you can redistribute it and/or modify it
+// under the terms of the GNU General Public License version 3, as published
+// by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranties of
+// MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+// PURPOSE. See the GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+#ifndef _STACK_BLUR_H
+#define _STACK_BLUR_H
+
+#include <glib.h>
+#include <cairo.h>
+
+void
+surface_stack_blur (cairo_surface_t* surface,
+ guint radius);
+
+#endif // _STACK_BLUR_H
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]