fix build for --disable-gtk-doc
[swfdec.git] / swfdec / swfdec_blur_filter.c
blob662a09d32d27d3ec0cebe4639b1e8f17134636d3
1 /* Swfdec
2 * Copyright (C) 2008 Benjamin Otte <otte@gnome.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301 USA
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
24 #include "swfdec_blur_filter.h"
26 #include <math.h>
28 #include "swfdec_debug.h"
30 G_DEFINE_TYPE (SwfdecBlurFilter, swfdec_blur_filter, SWFDEC_TYPE_FILTER)
32 static void
33 swfdec_blur_filter_clone (SwfdecFilter *dfilter, SwfdecFilter *sfilter)
35 SwfdecBlurFilter *dest = SWFDEC_BLUR_FILTER (dfilter);
36 SwfdecBlurFilter *source = SWFDEC_BLUR_FILTER (sfilter);
38 dest->x = source->x;
39 dest->y = source->y;
40 dest->quality = source->quality;
43 static void
44 swfdec_blur_filter_create_convolution_matrix (SwfdecBlurFilter *blur,
45 double xscale, double yscale)
47 guint x, y, w, h;
48 double div, blurx, blury;
50 if (blur->matrix && xscale == blur->xscale && yscale == blur->yscale)
51 return;
53 blurx = MAX (blur->x * xscale, 1);
54 blury = MAX (blur->y * yscale, 1);
55 w = ceil ((blurx - 1) / 2);
56 w = w * 2 + 1;
57 h = ceil ((blury - 1) / 2);
58 h = h * 2 + 1;
60 blur->matrix = swfdec_convolution_matrix_new (w, h);
61 blur->xscale = xscale;
62 blur->yscale = yscale;
64 div = 1.0 / (blurx * blury);
65 for (y = 0; y < h; y++) {
66 double val = div;
67 if (y == 0 || y == w - 1) {
68 val *= (1 - (h - MAX (blury, 1)) / 2);
70 for (x = 0; x < w; x++) {
71 if (x == 0 || x == w - 1) {
72 swfdec_convolution_matrix_set (blur->matrix, x, y,
73 val * (1 - (w - MAX (blurx, 1)) / 2));
74 } else {
75 swfdec_convolution_matrix_set (blur->matrix, x, y, val);
81 static void
82 swfdec_blur_filter_get_rectangle (SwfdecFilter *filter, SwfdecRectangle *dest,
83 double xscale, double yscale, const SwfdecRectangle *source)
85 SwfdecBlurFilter *blur = SWFDEC_BLUR_FILTER (filter);
86 double blurx, blury;
87 guint w, h;
89 blurx = MAX (blur->x * xscale, 1);
90 blury = MAX (blur->y * yscale, 1);
91 w = ceil ((blurx - 1) / 2);
92 w *= blur->quality;
93 h = ceil ((blury - 1) / 2);
94 h *= blur->quality;
96 dest->x = source->x - w;
97 dest->y = source->y - h;
98 dest->width = source->width + 2 * w;
99 dest->height = source->height + 2 * h;
102 static cairo_pattern_t *
103 swfdec_blur_filter_apply (SwfdecFilter *filter, cairo_pattern_t *pattern,
104 double xscale, double yscale, const SwfdecRectangle *rect)
106 SwfdecBlurFilter *blur = SWFDEC_BLUR_FILTER (filter);
107 cairo_surface_t *a, *b;
108 guint i, j, x, y;
109 guint8 *adata, *bdata;
110 guint astride, bstride;
111 cairo_t *cr;
113 if (blur->x <= 1.0 && blur->y <= 1.0)
114 return cairo_pattern_reference (pattern);
116 swfdec_blur_filter_create_convolution_matrix (blur, xscale, yscale);
117 x = swfdec_convolution_matrix_get_width (blur->matrix) / 2;
118 y = swfdec_convolution_matrix_get_height (blur->matrix) / 2;
120 /* FIXME: make this work in a single pass (requires smarter matrix construction) */
121 a = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
122 rect->width + 2 * x * blur->quality,
123 rect->height + 2 * y * blur->quality);
124 cairo_surface_set_device_offset (a,
125 - (double) rect->x + x * blur->quality, - (double) rect->y + y * blur->quality);
126 b = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
127 rect->width + 2 * x * blur->quality,
128 rect->height + 2 * y * blur->quality);
129 cairo_surface_set_device_offset (b,
130 - (double) rect->x + x * blur->quality, - (double) rect->y + y * blur->quality);
132 cr = cairo_create (b);
133 cairo_set_source (cr, pattern);
134 cairo_rectangle (cr, rect->x, rect->y, rect->width, rect->height);
135 cairo_fill (cr);
136 cairo_destroy (cr);
137 cairo_surface_flush (b);
139 adata = cairo_image_surface_get_data (a);
140 astride = cairo_image_surface_get_stride (a);
141 bdata = cairo_image_surface_get_data (b);
142 bstride = cairo_image_surface_get_stride (b);
143 for (i = 1, j = blur->quality - 1; i <= blur->quality; i++, j--) {
144 swfdec_convolution_matrix_apply (blur->matrix,
145 rect->width + 2 * x * i, rect->height + 2 * y * i,
146 adata + 4 * x * j + astride * y * j, astride,
147 bdata + 4 * x * j + bstride * y * j, bstride);
148 i++;
149 j--;
150 if (i > blur->quality) {
151 cairo_surface_destroy (b);
152 goto out;
154 swfdec_convolution_matrix_apply (blur->matrix,
155 rect->width + 2 * x * i, rect->height + 2 * y * i,
156 bdata + 4 * x * j + bstride * y * j, bstride,
157 adata + 4 * x * j + astride * y * j, astride);
160 cairo_surface_destroy (a);
161 a = b;
162 out:
163 cairo_surface_mark_dirty (a);
164 pattern = cairo_pattern_create_for_surface (a);
165 cairo_surface_destroy (a);
167 return pattern;
170 static void
171 swfdec_blur_filter_dispose (GObject *object)
173 SwfdecBlurFilter *blur = SWFDEC_BLUR_FILTER (object);
175 if (blur->matrix) {
176 swfdec_convolution_matrix_free (blur->matrix);
177 blur->matrix = NULL;
180 G_OBJECT_CLASS (swfdec_blur_filter_parent_class)->dispose (object);
183 static void
184 swfdec_blur_filter_class_init (SwfdecBlurFilterClass *klass)
186 GObjectClass *object_class = G_OBJECT_CLASS (klass);
187 SwfdecFilterClass *filter_class = SWFDEC_FILTER_CLASS (klass);
189 object_class->dispose = swfdec_blur_filter_dispose;
191 filter_class->clone = swfdec_blur_filter_clone;
192 filter_class->get_rectangle = swfdec_blur_filter_get_rectangle;
193 filter_class->apply = swfdec_blur_filter_apply;
196 static void
197 swfdec_blur_filter_init (SwfdecBlurFilter *filter)
199 filter->x = 4;
200 filter->y = 4;
201 filter->quality = 1;
204 void
205 swfdec_blur_filter_invalidate (SwfdecBlurFilter *blur)
207 g_return_if_fail (SWFDEC_IS_BLUR_FILTER (blur));
209 if (blur->matrix) {
210 swfdec_convolution_matrix_free (blur->matrix);
211 blur->matrix = NULL;