forked from AuroraMiddleware/gtk
Add code for blurring (original code from Unico, copyright fine for Gtk+)
This commit is contained in:
parent
75e746f9ef
commit
43673dafdc
@ -419,6 +419,7 @@ gtk_private_h_sources = \
|
||||
gtkboxprivate.h \
|
||||
gtkbuilderprivate.h \
|
||||
gtkbuttonprivate.h \
|
||||
gtkcairoblurprivate.h \
|
||||
gtkcellareaboxcontextprivate.h \
|
||||
gtkcolorswatchprivate.h \
|
||||
gtkcoloreditorprivate.h \
|
||||
@ -615,6 +616,7 @@ gtk_base_c_sources = \
|
||||
gtkbuilderparser.c \
|
||||
gtkbuilder-menus.c \
|
||||
gtkbutton.c \
|
||||
gtkcairoblur.c \
|
||||
gtkcalendar.c \
|
||||
gtkcellarea.c \
|
||||
gtkcellareabox.c \
|
||||
|
267
gtk/gtkcairoblur.c
Normal file
267
gtk/gtkcairoblur.c
Normal file
@ -0,0 +1,267 @@
|
||||
/*
|
||||
* 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 "gtkcairoblurprivate.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
/*
|
||||
* Notes:
|
||||
* based on exponential-blur algorithm by Jani Huhtanen
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* _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;
|
||||
guchar* pixels;
|
||||
guint width;
|
||||
guint height;
|
||||
|
||||
g_return_if_fail (surface != NULL);
|
||||
g_return_if_fail (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_IMAGE);
|
||||
|
||||
format = cairo_image_surface_get_format (surface);
|
||||
g_return_if_fail (format == CAIRO_FORMAT_A8 ||
|
||||
format == CAIRO_FORMAT_RGB24 ||
|
||||
format == CAIRO_FORMAT_ARGB32);
|
||||
|
||||
if (radius == 0)
|
||||
return;
|
||||
|
||||
/* 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);
|
||||
}
|
37
gtk/gtkcairoblurprivate.h
Normal file
37
gtk/gtkcairoblurprivate.h
Normal file
@ -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 */
|
Loading…
Reference in New Issue
Block a user