[gtk+/wip/css-blur: 1/5] Add code for blurring (original code from Unico, copyright fine for Gtk+)
- From: Andrea Cimitan <acimitan src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/css-blur: 1/5] Add code for blurring (original code from Unico, copyright fine for Gtk+)
- Date: Mon, 16 Apr 2012 17:35:35 +0000 (UTC)
commit 7bdfe7c79376238ba0e8551f0f08c4e6c74cb3e0
Author: Andrea Cimitan <andrea cimitan canonical com>
Date: Fri Apr 13 11:59:26 2012 +0200
Add code for blurring (original code from Unico, copyright fine for Gtk+)
gtk/Makefile.am | 4 +
gtk/gtkcairoblur.c | 65 +++++++++++
gtk/gtkcairoblur.h | 37 ++++++
gtk/gtkcairoblurexponential.c | 255 +++++++++++++++++++++++++++++++++++++++++
gtk/gtkcairoblurexponential.h | 41 +++++++
5 files changed, 402 insertions(+), 0 deletions(-)
---
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index 1f45028..9490a6f 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -416,6 +416,8 @@ gtk_private_h_sources = \
gtkboxprivate.h \
gtkbuilderprivate.h \
gtkbuttonprivate.h \
+ gtkcairoblur.h \
+ gtkcairoblurexponential.h \
gtkcellareaboxcontextprivate.h \
gtkcolorswatchprivate.h \
gtkcoloreditorprivate.h \
@@ -587,6 +589,8 @@ gtk_base_c_sources = \
gtkbuilderparser.c \
gtkbuilder-menus.c \
gtkbutton.c \
+ gtkcairoblur.c \
+ gtkcairoblurexponential.c \
gtkcalendar.c \
gtkcellarea.c \
gtkcellareabox.c \
diff --git a/gtk/gtkcairoblur.c b/gtk/gtkcairoblur.c
new file mode 100644
index 0000000..b690ed9
--- /dev/null
+++ b/gtk/gtkcairoblur.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2012 Canonical Ltd
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * Authored by Andrea Cimitan <andrea cimitan canonical com>
+ * Original code from Mirco Mueller <mirco mueller canonical com>
+ *
+ */
+
+#include "gtkcairoblur.h"
+#include "gtkcairoblurexponential.h"
+
+/*
+ * _gtk_cairo_blur_surface:
+ * @surface: a cairo image surface.
+ * @radius: the blur radius.
+ *
+ * Blurs the cairo image surface at the given radius.
+ *
+ */
+void
+_gtk_cairo_blur_surface (cairo_surface_t* surface,
+ guint radius)
+{
+ cairo_format_t format;
+
+ g_return_if_fail (surface != NULL);
+
+ if (cairo_surface_get_type (surface) != CAIRO_SURFACE_TYPE_IMAGE)
+ {
+ g_debug ("_gtk_cairo_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 ("_gtk_cairo_blur_apply(): unsupported image-format");
+ return;
+ }
+
+ if (radius == 0)
+ return;
+
+ /* Now do the real work.
+ * This call performs the blur:
+ * call (and write) a different function to perform a different blur. */
+ _surface_exponential_blur (surface, radius);
+}
diff --git a/gtk/gtkcairoblur.h b/gtk/gtkcairoblur.h
new file mode 100644
index 0000000..0b93bb5
--- /dev/null
+++ b/gtk/gtkcairoblur.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2012 Canonical Ltd
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * Authored by Andrea Cimitan <andrea cimitan canonical com>
+ * Original code from Mirco Mueller <mirco mueller canonical com>
+ *
+ */
+
+#ifndef _GTK_CAIRO_BLUR_H
+#define _GTK_CAIRO_BLUR_H
+
+#include <glib.h>
+#include <cairo.h>
+
+G_BEGIN_DECLS
+
+void _gtk_cairo_blur_surface (cairo_surface_t* surface,
+ guint radius);
+
+G_END_DECLS
+
+#endif /* _GTK_CAIRO_BLUR_H */
diff --git a/gtk/gtkcairoblurexponential.c b/gtk/gtkcairoblurexponential.c
new file mode 100644
index 0000000..6242e18
--- /dev/null
+++ b/gtk/gtkcairoblurexponential.c
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2012 Canonical Ltd
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * Authored by Andrea Cimitan <andrea cimitan canonical com>
+ * Original code from Mirco Mueller <mirco mueller canonical com>
+ *
+ * Notes:
+ * based on exponential-blur algorithm by Jani Huhtanen
+ *
+ */
+
+#include <math.h>
+
+#include <glib.h>
+#include <cairo.h>
+
+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);
+}
+
+/*
+ * _expblur:
+ * @pixels: image data
+ * @width: image width
+ * @height: image height
+ * @channels: image channels
+ * @radius: kernel radius
+ * @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
+ *
+ * Performs an in-place blur of image data 'pixels'
+ * with kernel of approximate radius 'radius'.
+ *
+ * Blurs with two sided exponential impulse response.
+ *
+ */
+static 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);
+}
+
+/*
+ * _surface_exponential_blur:
+ * @surface: a cairo image surface
+ * @radius: blur radius to apply
+ *
+ * Blurs a cairo image surface.
+ *
+ */
+void
+_surface_exponential_blur (cairo_surface_t* surface,
+ guint radius)
+{
+ cairo_format_t format;
+ guchar* pixels;
+ guint width;
+ guint height;
+
+ /* 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:
+ break;
+ }
+
+ /* Inform cairo we altered the surfaces contents. */
+ cairo_surface_mark_dirty (surface);
+}
diff --git a/gtk/gtkcairoblurexponential.h b/gtk/gtkcairoblurexponential.h
new file mode 100644
index 0000000..efb7a37
--- /dev/null
+++ b/gtk/gtkcairoblurexponential.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2012 Canonical Ltd
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * Authored by Andrea Cimitan <andrea cimitan canonical com>
+ * Original code from Mirco Mueller <mirco mueller canonical com>
+ *
+ * Notes:
+ * based on exponential-blur algorithm by Jani Huhtanen
+ *
+ */
+
+#ifndef _GTK_CAIRO_BLUR_EXPONENTIAL_H
+#define _GTK_CAIRO_BLUR_EXPONENTIAL_H
+
+#include <glib.h>
+#include <cairo.h>
+
+G_BEGIN_DECLS
+
+void _surface_exponential_blur (cairo_surface_t* surface,
+ guint radius);
+
+G_END_DECLS
+
+#endif // _GTK_CAIRO_BLUR_EXPONENTIAL_H
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]