don't discard iframe children.
[kdelibs.git] / khtml / misc / imagefilter.cpp
blob0d4be664fb808c39f446b59e4a3b7397ac0ad481
1 /*
2 This file is a part of the KDE project
4 Copyright © 2006 Zack Rusin <zack@kde.org>
5 Copyright © 2006-2007, 2008 Fredrik Höglund <fredrik@kde.org>
7 The stack blur algorithm was invented by Mario Klingemann <mario@quasimondo.com>
9 This implementation is based on the version in Anti-Grain Geometry Version 2.4,
10 Copyright © 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
12 Redistribution and use in source and binary forms, with or without
13 modification, are permitted provided that the following conditions
14 are met:
16 1. Redistributions of source code must retain the above copyright
17 notice, this list of conditions and the following disclaimer.
18 2. Redistributions in binary form must reproduce the above copyright
19 notice, this list of conditions and the following disclaimer in the
20 documentation and/or other materials provided with the distribution.
22 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include <QPainter>
35 #include <QImage>
36 #include <QColor>
37 #include <QDebug>
39 #include <cmath>
40 #include <string.h>
42 #include "imagefilter.h"
44 using namespace khtml;
46 static const quint32 stack_blur8_mul[255] =
48 512,512,456,512,328,456,335,512,405,328,271,456,388,335,292,512,
49 454,405,364,328,298,271,496,456,420,388,360,335,312,292,273,512,
50 482,454,428,405,383,364,345,328,312,298,284,271,259,496,475,456,
51 437,420,404,388,374,360,347,335,323,312,302,292,282,273,265,512,
52 497,482,468,454,441,428,417,405,394,383,373,364,354,345,337,328,
53 320,312,305,298,291,284,278,271,265,259,507,496,485,475,465,456,
54 446,437,428,420,412,404,396,388,381,374,367,360,354,347,341,335,
55 329,323,318,312,307,302,297,292,287,282,278,273,269,265,261,512,
56 505,497,489,482,475,468,461,454,447,441,435,428,422,417,411,405,
57 399,394,389,383,378,373,368,364,359,354,350,345,341,337,332,328,
58 324,320,316,312,309,305,301,298,294,291,287,284,281,278,274,271,
59 268,265,262,259,257,507,501,496,491,485,480,475,470,465,460,456,
60 451,446,442,437,433,428,424,420,416,412,408,404,400,396,392,388,
61 385,381,377,374,370,367,363,360,357,354,350,347,344,341,338,335,
62 332,329,326,323,320,318,315,312,310,307,304,302,299,297,294,292,
63 289,287,285,282,280,278,275,273,271,269,267,265,263,261,259
66 static const quint32 stack_blur8_shr[255] =
68 9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17,
69 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19,
70 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20,
71 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21,
72 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
73 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22,
74 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
75 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23,
76 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
77 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
78 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
79 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
80 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
81 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
82 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
83 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24
86 inline static void blurHorizontal(QImage &image, unsigned int *stack, int div, int radius)
88 int stackindex;
89 int stackstart;
91 quint32 * const pixels = reinterpret_cast<quint32 *>(image.bits());
92 quint32 pixel;
94 int w = image.width();
95 int h = image.height();
96 int wm = w - 1;
98 unsigned int mul_sum = stack_blur8_mul[radius];
99 unsigned int shr_sum = stack_blur8_shr[radius];
101 unsigned int sum, sum_in, sum_out;
103 for (int y = 0; y < h; y++)
105 sum = 0;
106 sum_in = 0;
107 sum_out = 0;
109 const int yw = y * w;
110 pixel = pixels[yw];
111 for (int i = 0; i <= radius; i++)
113 stack[i] = qAlpha(pixel);
115 sum += stack[i] * (i + 1);
116 sum_out += stack[i];
119 for (int i = 1; i <= radius; i++)
121 pixel = pixels[yw + qMin(i, wm)];
123 unsigned int *stackpix = &stack[i + radius];
124 *stackpix = qAlpha(pixel);
126 sum += *stackpix * (radius + 1 - i);
127 sum_in += *stackpix;
130 stackindex = radius;
131 for (int x = 0, i = yw; x < w; x++)
133 pixels[i++] = (((sum * mul_sum) >> shr_sum) << 24) & 0xff000000;
135 sum -= sum_out;
137 stackstart = stackindex + div - radius;
138 if (stackstart >= div)
139 stackstart -= div;
141 unsigned int *stackpix = &stack[stackstart];
143 sum_out -= *stackpix;
145 pixel = pixels[yw + qMin(x + radius + 1, wm)];
147 *stackpix = qAlpha(pixel);
149 sum_in += *stackpix;
150 sum += sum_in;
152 if (++stackindex >= div)
153 stackindex = 0;
155 stackpix = &stack[stackindex];
157 sum_out += *stackpix;
158 sum_in -= *stackpix;
159 } // for (x = 0, ...)
160 } // for (y = 0, ...)
163 inline static void blurVertical(QImage &image, unsigned int *stack, int div, int radius)
165 int stackindex;
166 int stackstart;
168 quint32 * const pixels = reinterpret_cast<quint32 *>(image.bits());
169 quint32 pixel;
171 int w = image.width();
172 int h = image.height();
173 int hm = h - 1;
175 int mul_sum = stack_blur8_mul[radius];
176 int shr_sum = stack_blur8_shr[radius];
178 unsigned int sum, sum_in, sum_out;
180 for (int x = 0; x < w; x++)
182 sum = 0;
183 sum_in = 0;
184 sum_out = 0;
186 pixel = pixels[x];
187 for (int i = 0; i <= radius; i++)
189 stack[i] = qAlpha(pixel);
191 sum += stack[i] * (i + 1);
192 sum_out += stack[i];
195 for (int i = 1; i <= radius; i++)
197 pixel = pixels[qMin(i, hm) * w + x];
199 unsigned int *stackpix = &stack[i + radius];
200 *stackpix = qAlpha(pixel);
202 sum += *stackpix * (radius + 1 - i);
203 sum_in += *stackpix;
206 stackindex = radius;
207 for (int y = 0, i = x; y < h; y++, i += w)
209 pixels[i] = (((sum * mul_sum) >> shr_sum) << 24) & 0xff000000;
211 sum -= sum_out;
213 stackstart = stackindex + div - radius;
214 if (stackstart >= div)
215 stackstart -= div;
217 unsigned int *stackpix = &stack[stackstart];
219 sum_out -= *stackpix;
221 pixel = pixels[qMin(y + radius + 1, hm) * w + x];
223 *stackpix = qAlpha(pixel);
225 sum_in += *stackpix;
226 sum += sum_in;
228 if (++stackindex >= div)
229 stackindex = 0;
231 stackpix = &stack[stackindex];
233 sum_out += *stackpix;
234 sum_in -= *stackpix;
235 } // for (y = 0, ...)
236 } // for (x = 0, ...)
239 static void stackBlur(QImage &image, float radius)
241 radius = qRound(radius);
243 int div = int(radius * 2) + 1;
244 unsigned int *stack = new unsigned int[div];
246 blurHorizontal(image, stack, div, radius);
247 blurVertical(image, stack, div, radius);
249 delete [] stack;
252 void ImageFilter::shadowBlur(QImage &image, float radius, const QColor &color)
254 if (radius < 0)
255 return;
257 if (radius > 0)
258 stackBlur(image, radius);
260 // Correct the color and opacity of the shadow
261 QPainter p(&image);
262 p.setCompositionMode(QPainter::CompositionMode_SourceIn);
263 p.fillRect(image.rect(), color);
266 // kate: space-indent on; indent-width 4; replace-tabs on;