* Saner resizing of the icon when pressed

* Nicer SVG, also fixed the corners, now are pixel perfect
* Prepared the code for the upcoming blur of the wallpaper....

svn path=/trunk/KDE/kdebase/workspace/lib/plasma/; revision=672328
This commit is contained in:
Riccardo Iaconelli 2007-06-06 19:45:00 +00:00
parent cd701724cb
commit a043e502f3

View File

@ -28,6 +28,244 @@
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
{
@ -142,8 +380,18 @@ void Icon::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWid
}
if (!element.isEmpty()) {
//kDebug() << "painting " << element << endl;
d->svg.paint(painter, 0, 0, element);
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();
element = QString();
}
@ -154,8 +402,14 @@ void Icon::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWid
qreal deltaY = (d->size.height() - ih) / 2 ;
if(d->state == Private::PressedState)
{
painter->save();
painter->setRenderHint(QPainter::SmoothPixmapTransform);
painter->scale(0.95, 0.95);
deltaY *= 0.95;
deltaX *= 0.95;
painter->drawPixmap(deltaX + (iw * .025), deltaY + (ih * .025),
d->icon.pixmap(d->iconSize.toSize() * 0.95));
d->icon.pixmap(d->iconSize.toSize()));
painter->restore();
}
else
{