* let's not bother with the blur here quite yet; let's do it Right(tm) later in an image effects lib, and when we can actually operate on the backing store

* if there is not -pressed element, still paint something proper

svn path=/trunk/KDE/kdebase/workspace/lib/plasma/; revision=672363
This commit is contained in:
Aaron J. Seigo 2007-06-06 20:48:06 +00:00
parent a043e502f3
commit a80c5349e4

View File

@ -28,244 +28,6 @@
namespace Plasma
{
// Stack Blur Algorithm by Mario Klingemann <mario@quasimondo.com>
void fastbluralpha(QImage &img, int radius)
{
if (radius < 1) {
return;
}
QRgb *pix = (QRgb*)img.bits();
int w = img.width();
int h = img.height();
int wm = w-1;
int hm = h-1;
int wh = w*h;
int div = radius+radius+1;
int *r = new int[wh];
int *g = new int[wh];
int *b = new int[wh];
int *a = new int[wh];
int rsum, gsum, bsum, asum, x, y, i, yp, yi, yw;
QRgb p;
int *vmin = new int[qMax(w,h)];
int divsum = (div+1)>>1;
divsum *= divsum;
int *dv = new int[256*divsum];
for (i=0; i < 256*divsum; ++i) {
dv[i] = (i/divsum);
}
yw = yi = 0;
int **stack = new int*[div];
for(int i = 0; i < div; ++i) {
stack[i] = new int[4];
}
int stackpointer;
int stackstart;
int *sir;
int rbs;
int r1 = radius+1;
int routsum, goutsum, boutsum, aoutsum;
int rinsum, ginsum, binsum, ainsum;
for (y = 0; y < h; ++y){
rinsum = ginsum = binsum = ainsum
= routsum = goutsum = boutsum = aoutsum
= rsum = gsum = bsum = asum = 0;
for(i =- radius; i <= radius; ++i) {
p = pix[yi+qMin(wm,qMax(i,0))];
sir = stack[i+radius];
sir[0] = qRed(p);
sir[1] = qGreen(p);
sir[2] = qBlue(p);
sir[3] = qAlpha(p);
rbs = r1-abs(i);
rsum += sir[0]*rbs;
gsum += sir[1]*rbs;
bsum += sir[2]*rbs;
asum += sir[3]*rbs;
if (i > 0){
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
ainsum += sir[3];
} else {
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
aoutsum += sir[3];
}
}
stackpointer = radius;
for (x=0; x < w; ++x) {
r[yi] = dv[rsum];
g[yi] = dv[gsum];
b[yi] = dv[bsum];
a[yi] = dv[asum];
rsum -= routsum;
gsum -= goutsum;
bsum -= boutsum;
asum -= aoutsum;
stackstart = stackpointer-radius+div;
sir = stack[stackstart%div];
routsum -= sir[0];
goutsum -= sir[1];
boutsum -= sir[2];
aoutsum -= sir[3];
if (y == 0) {
vmin[x] = qMin(x+radius+1,wm);
}
p = pix[yw+vmin[x]];
sir[0] = qRed(p);
sir[1] = qGreen(p);
sir[2] = qBlue(p);
sir[3] = qAlpha(p);
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
ainsum += sir[3];
rsum += rinsum;
gsum += ginsum;
bsum += binsum;
asum += ainsum;
stackpointer = (stackpointer+1)%div;
sir = stack[(stackpointer)%div];
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
aoutsum += sir[3];
rinsum -= sir[0];
ginsum -= sir[1];
binsum -= sir[2];
ainsum -= sir[3];
++yi;
}
yw += w;
}
for (x=0; x < w; ++x){
rinsum = ginsum = binsum = ainsum
= routsum = goutsum = boutsum = aoutsum
= rsum = gsum = bsum = asum = 0;
yp =- radius * w;
for(i=-radius; i <= radius; ++i) {
yi=qMax(0,yp)+x;
sir = stack[i+radius];
sir[0] = r[yi];
sir[1] = g[yi];
sir[2] = b[yi];
sir[3] = a[yi];
rbs = r1-abs(i);
rsum += r[yi]*rbs;
gsum += g[yi]*rbs;
bsum += b[yi]*rbs;
asum += a[yi]*rbs;
if (i > 0) {
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
ainsum += sir[3];
} else {
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
aoutsum += sir[3];
}
if (i < hm){
yp += w;
}
}
yi = x;
stackpointer = radius;
for (y=0; y < h; ++y){
pix[yi] = qRgba(dv[rsum], dv[gsum], dv[bsum], dv[asum]);
rsum -= routsum;
gsum -= goutsum;
bsum -= boutsum;
asum -= aoutsum;
stackstart = stackpointer-radius+div;
sir = stack[stackstart%div];
routsum -= sir[0];
goutsum -= sir[1];
boutsum -= sir[2];
aoutsum -= sir[3];
if (x==0){
vmin[y] = qMin(y+r1,hm)*w;
}
p = x+vmin[y];
sir[0] = r[p];
sir[1] = g[p];
sir[2] = b[p];
sir[3] = a[p];
rinsum += sir[0];
ginsum += sir[1];
binsum += sir[2];
ainsum += sir[3];
rsum += rinsum;
gsum += ginsum;
bsum += binsum;
asum += ainsum;
stackpointer = (stackpointer+1)%div;
sir = stack[stackpointer];
routsum += sir[0];
goutsum += sir[1];
boutsum += sir[2];
aoutsum += sir[3];
rinsum -= sir[0];
ginsum -= sir[1];
binsum -= sir[2];
ainsum -= sir[3];
yi += w;
}
}
delete [] r;
delete [] g;
delete [] b;
delete [] a;
delete [] vmin;
delete [] dv;
}
class Icon::Private
{
@ -375,23 +137,14 @@ void Icon::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWid
case Private::PressedState:
if (d->svgElements & Private::SvgBackgroundPressed) {
element = "background-pressed";
} else if (d->svgElements & Private::SvgBackgroundHover) {
element = "background-hover";
}
break;
}
if (!element.isEmpty()) {
painter->save();
if (element == "background-pressed") {
QImage img(sizeHint().width(), sizeHint().height(), QImage::Format_ARGB32);
img.fill(qRgba(0,0,0,0));
QPainter p(&img);
d->svg.paint(&p, 0, 0, element);
fastbluralpha(img, 2);
painter->drawImage(QPointF(0,0), img);
} else {
d->svg.paint(painter, 0, 0, element);
}
painter->restore();
d->svg.paint(painter, 0, 0, element);
element = QString();
}
@ -434,6 +187,8 @@ void Icon::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWid
case Private::PressedState:
if (d->svgElements & Private::SvgForegroundPressed) {
element = "foreground-pressed";
} else if (d->svgElements & Private::SvgForegroundHover) {
element = "foreground-hover";
}
break;
}