gtkcairoblur: Blur a CAIRO_A8 surface instead of a full CAIRO_ARGB32

This is considerably faster to draw and paint.
This commit is contained in:
Jasper St. Pierre 2014-07-28 22:04:05 +02:00
parent 227b4a8620
commit 45bdec84f5
2 changed files with 10 additions and 59 deletions

View File

@ -31,33 +31,16 @@
*/ */
static inline void static inline void
_blurinner (guchar* pixel, _blurinner (guchar* pixel,
gint *zR,
gint *zG,
gint *zB,
gint *zA, gint *zA,
gint alpha, gint alpha,
gint aprec, gint aprec,
gint zprec) gint zprec)
{ {
gint R;
gint G;
gint B;
guchar A; guchar A;
R = *pixel; A = *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; *zA += (alpha * ((A << zprec) - *zA)) >> aprec;
*pixel = *zA >> zprec;
*pixel = *zR >> zprec;
*(pixel + 1) = *zG >> zprec;
*(pixel + 2) = *zB >> zprec;
*(pixel + 3) = *zA >> zprec;
} }
static inline void static inline void
@ -65,41 +48,28 @@ _blurrow (guchar* pixels,
gint width, gint width,
gint height, gint height,
gint rowstride, gint rowstride,
gint channels,
gint line, gint line,
gint alpha, gint alpha,
gint aprec, gint aprec,
gint zprec) gint zprec)
{ {
gint zR;
gint zG;
gint zB;
gint zA; gint zA;
gint index; gint index;
guchar* scanline; guchar* scanline;
scanline = &pixels[line * rowstride]; scanline = &pixels[line * rowstride];
zR = *scanline << zprec; zA = *scanline << zprec;
zG = *(scanline + 1) << zprec;
zB = *(scanline + 2) << zprec;
zA = *(scanline + 3) << zprec;
for (index = 0; index < width; index ++) for (index = 0; index < width; index ++)
_blurinner (&scanline[index * channels], _blurinner (&scanline[index],
&zR,
&zG,
&zB,
&zA, &zA,
alpha, alpha,
aprec, aprec,
zprec); zprec);
for (index = width - 2; index >= 0; index--) for (index = width - 2; index >= 0; index--)
_blurinner (&scanline[index * channels], _blurinner (&scanline[index],
&zR,
&zG,
&zB,
&zA, &zA,
alpha, alpha,
aprec, aprec,
@ -111,33 +81,23 @@ _blurcol (guchar* pixels,
gint width, gint width,
gint height, gint height,
gint rowstride, gint rowstride,
gint channels,
gint x, gint x,
gint alpha, gint alpha,
gint aprec, gint aprec,
gint zprec) gint zprec)
{ {
gint zR;
gint zG;
gint zB;
gint zA; gint zA;
gint index; gint index;
guchar* ptr; guchar* ptr;
ptr = pixels; ptr = pixels;
ptr += x * channels; ptr += x;
zR = *((guchar*) ptr ) << zprec; zA = *ptr << zprec;
zG = *((guchar*) ptr + 1) << zprec;
zB = *((guchar*) ptr + 2) << zprec;
zA = *((guchar*) ptr + 3) << zprec;
for (index = 0; index < height; index++) for (index = 0; index < height; index++)
_blurinner (&ptr[index * rowstride], _blurinner (&ptr[index * rowstride],
&zR,
&zG,
&zB,
&zA, &zA,
alpha, alpha,
aprec, aprec,
@ -145,9 +105,6 @@ _blurcol (guchar* pixels,
for (index = height - 2; index >= 0; index--) for (index = height - 2; index >= 0; index--)
_blurinner (&ptr[index * rowstride], _blurinner (&ptr[index * rowstride],
&zR,
&zG,
&zB,
&zA, &zA,
alpha, alpha,
aprec, aprec,
@ -160,7 +117,6 @@ _blurcol (guchar* pixels,
* @width: image width * @width: image width
* @height: image height * @height: image height
* @rowstride: image rowstride * @rowstride: image rowstride
* @channels: image channels
* @radius: kernel radius * @radius: kernel radius
* @aprec: precision of alpha parameter in fixed-point format 0.aprec * @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 * @zprec: precision of state parameters zR,zG,zB and zA in fp format 8.zprec
@ -176,7 +132,6 @@ _expblur (guchar* pixels,
gint width, gint width,
gint height, gint height,
gint rowstride, gint rowstride,
gint channels,
double radius, double radius,
gint aprec, gint aprec,
gint zprec) gint zprec)
@ -194,7 +149,6 @@ _expblur (guchar* pixels,
width, width,
height, height,
rowstride, rowstride,
channels,
row, row,
alpha, alpha,
aprec, aprec,
@ -205,7 +159,6 @@ _expblur (guchar* pixels,
width, width,
height, height,
rowstride, rowstride,
channels,
col, col,
alpha, alpha,
aprec, aprec,
@ -230,8 +183,7 @@ _gtk_cairo_blur_surface (cairo_surface_t* surface,
g_return_if_fail (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_IMAGE); g_return_if_fail (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_IMAGE);
format = cairo_image_surface_get_format (surface); format = cairo_image_surface_get_format (surface);
g_return_if_fail (format == CAIRO_FORMAT_RGB24 || g_return_if_fail (format == CAIRO_FORMAT_A8);
format == CAIRO_FORMAT_ARGB32);
if (radius == 0) if (radius == 0)
return; return;
@ -243,7 +195,6 @@ _gtk_cairo_blur_surface (cairo_surface_t* surface,
cairo_image_surface_get_width (surface), cairo_image_surface_get_width (surface),
cairo_image_surface_get_height (surface), cairo_image_surface_get_height (surface),
cairo_image_surface_get_stride (surface), cairo_image_surface_get_stride (surface),
4,
radius, radius,
16, 16,
7); 7);

View File

@ -330,7 +330,7 @@ gtk_css_shadow_value_start_drawing (const GtkCssValue *shadow,
clip_radius = _gtk_cairo_blur_compute_pixels (radius); clip_radius = _gtk_cairo_blur_compute_pixels (radius);
/* Create a larger surface to center the blur. */ /* Create a larger surface to center the blur. */
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, surface = cairo_image_surface_create (CAIRO_FORMAT_A8,
clip_rect.width + 2 * clip_radius, clip_rect.width + 2 * clip_radius,
clip_rect.height + 2 * clip_radius); clip_rect.height + 2 * clip_radius);
cairo_surface_set_device_offset (surface, clip_radius - clip_rect.x, clip_radius - clip_rect.y); cairo_surface_set_device_offset (surface, clip_radius - clip_rect.x, clip_radius - clip_rect.y);