diff --git a/applet.cpp b/applet.cpp index da56c6aa3..5941ba2a1 100644 --- a/applet.cpp +++ b/applet.cpp @@ -46,7 +46,7 @@ #include "plasma/widgets/lineedit.h" #include "plasma/widgets/vboxlayout.h" -//#include "stackblur_shadows.cpp" +#include "shadowblur.cpp" namespace Plasma { @@ -134,19 +134,15 @@ public: } } - void paintBackground(QPainter* p, Applet* q) + void paintBackground(QPainter* p2, Applet* q, const QColor &shadowColor = Qt::black) { //TODO: we should cache this background rather that repaint it over and over + //TODO: get shadow removed from svg QSize contents = contentSize(q).toSize(); const int contentWidth = contents.width(); const int contentHeight = contents.height(); -#if 0 - // this could be used to draw a dynamic shadow - QImage image(w, h, QImage::Format_ARGB32_Premultiplied); - QPainter* p = new QPainter(&image); - p->setCompositionMode(QPainter::CompositionMode_Source); -#endif - p->setRenderHint(QPainter::SmoothPixmapTransform); + + background->resize(); const int topHeight = background->elementSize("top").height(); @@ -166,6 +162,14 @@ public: const int contentTop = 0; const int contentLeft = 0; + QPixmap backgroundPixmap(leftWidth + contentWidth + rightWidth, topHeight + contentHeight + bottomHeight); + backgroundPixmap.fill(Qt::transparent); + QPainter* p = new QPainter(&backgroundPixmap); + p->translate(leftWidth, topHeight); + p->setCompositionMode(QPainter::CompositionMode_Source); + + p->setRenderHint(QPainter::SmoothPixmapTransform); + background->paint(p, QRect(leftOffset, topOffset, leftWidth, topHeight), "topleft"); background->paint(p, QRect(rightOffset, topOffset, rightWidth, topHeight), "topright"); background->paint(p, QRect(leftOffset, bottomOffset, leftWidth, bottomHeight), "bottomleft"); @@ -209,6 +213,16 @@ public: p->drawTiledPixmap(QRect(contentLeft, bottomOffset, contentWidth, bottomHeight), bottom); background->paint(p, QRect(contentLeft, contentTop, contentWidth + 1, contentHeight + 1), "center"); + + QImage shadowImage = backgroundPixmap.toImage(); + shadowBlur(shadowImage, 5); + QPainter* pShadow = new QPainter(&shadowImage); + pShadow->setCompositionMode(QPainter::CompositionMode_SourceAtop); + pShadow->fillRect(0, 0, shadowImage.size().width(), shadowImage.size().height(), QBrush(shadowColor)); + QPixmap shadowPixmap = QPixmap::fromImage(shadowImage); + //p2->setRenderHint(QPainter::SmoothPixmapTransform); + p2->drawPixmap(leftOffset, topOffset, shadowPixmap); + p2->drawPixmap(leftOffset, topOffset, backgroundPixmap); } void paintHover(QPainter* painter, Applet* q) @@ -493,7 +507,7 @@ QColor Applet::color() const // TODO: add more colors for more categories and // maybe read from config? QString c = category(); - int alpha = 200; + int alpha = 100; // Colors taken from Oxygen color palette if (c == "Date and Time") { return QColor(191, 94, 0, alpha); @@ -538,11 +552,21 @@ void Applet::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QW } else if (zoomLevel == scalingFactor(Plasma::GroupZoom)) { // Show Groups + Applet outline //TODO: make pretty. painter->setBrush(QBrush(color(), Qt::SolidPattern)); - painter->drawRoundRect(boundingRect()); - int iconDim = KIconLoader().currentSize(K3Icon::Desktop); - int midX = (boundingRect().width() / 2) - (iconDim / 2); - int midY = (boundingRect().height() / 2) - (iconDim / 2); - KIcon(icon()).paint(painter, midX, midY, iconDim, iconDim); + //painter->drawRoundRect(boundingRect()); + //normal applet + if (d->background) { + d->paintBackground(painter, this, color()); + } + + if (d->failed) { + return; + } + paintInterface(painter, option, QRect(QPoint(0,0), d->contentSize(this).toSize())); + +// int iconDim = KIconLoader().currentSize(K3Icon::Desktop); +// int midX = (boundingRect().width() / 2) - (iconDim / 2); +// int midY = (boundingRect().height() / 2) - (iconDim / 2); +// KIcon(icon()).paint(painter, midX, midY, iconDim, iconDim); }/* else if (zoomLevel == scalingFactor(Plasma::OverviewZoom)) { //Show Groups only } */ } diff --git a/shadowblur.cpp b/shadowblur.cpp new file mode 100644 index 000000000..19388eb1f --- /dev/null +++ b/shadowblur.cpp @@ -0,0 +1,248 @@ +/* + This file is a part of the KDE project + + Copyright © 2006 Zack Rusin + Copyright © 2006-2007 Fredrik Höglund + + The stack blur algorithm was invented by Mario Klingemann + + + This implementation incorporates performance improvements from + Anti-Grain Geometry Version 2.4, + Copyright © Maxim Shemanarev (http://www.antigrain.com) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +static const quint32 stack_blur8_mul[255] = +{ + 512,512,456,512,328,456,335,512,405,328,271,456,388,335,292,512, + 454,405,364,328,298,271,496,456,420,388,360,335,312,292,273,512, + 482,454,428,405,383,364,345,328,312,298,284,271,259,496,475,456, + 437,420,404,388,374,360,347,335,323,312,302,292,282,273,265,512, + 497,482,468,454,441,428,417,405,394,383,373,364,354,345,337,328, + 320,312,305,298,291,284,278,271,265,259,507,496,485,475,465,456, + 446,437,428,420,412,404,396,388,381,374,367,360,354,347,341,335, + 329,323,318,312,307,302,297,292,287,282,278,273,269,265,261,512, + 505,497,489,482,475,468,461,454,447,441,435,428,422,417,411,405, + 399,394,389,383,378,373,368,364,359,354,350,345,341,337,332,328, + 324,320,316,312,309,305,301,298,294,291,287,284,281,278,274,271, + 268,265,262,259,257,507,501,496,491,485,480,475,470,465,460,456, + 451,446,442,437,433,428,424,420,416,412,408,404,400,396,392,388, + 385,381,377,374,370,367,363,360,357,354,350,347,344,341,338,335, + 332,329,326,323,320,318,315,312,310,307,304,302,299,297,294,292, + 289,287,285,282,280,278,275,273,271,269,267,265,263,261,259 +}; + +static const quint32 stack_blur8_shr[255] = +{ + 9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, + 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24 +}; + + +inline static void blurHorizontal(QImage &image, int *stack, int div, int radius) +{ + int stackpointer; + int stackstart; + + quint32 * const pixels = reinterpret_cast(image.bits()); + quint32 pixel; + + int w = image.width(); + int h = image.height(); + int wm = w - 1; + + int mul_sum = stack_blur8_mul[radius]; + int shr_sum = stack_blur8_shr[radius]; + + int sum, sum_in, sum_out; + + for (int y = 0; y < h; y++) + { + sum = 0; + sum_in = 0; + sum_out = 0; + + const int yw = y * w; + pixel = pixels[yw]; + for (int i = 0; i <= radius; i++) + { + stack[i] = qAlpha(pixel); + + sum += stack[i] * (i + 1); + sum_out += stack[i]; + } + + for (int i = 1; i <= radius; i++) + { + pixel = pixels[yw + qMin(i, wm)]; + + int *stackpix = &stack[i + radius]; + *stackpix = qAlpha(pixel); + + sum += *stackpix * (radius + 1 - i); + sum_in += *stackpix; + } + + stackpointer = radius; + for (int x = 0, i = yw; x < w; x++) + { + pixels[i++] = (((sum * mul_sum) >> shr_sum) << 24) & 0xff000000; + + sum -= sum_out; + + stackstart = stackpointer + div - radius; + if (stackstart >= div) + stackstart -= div; + + int *stackpix = &stack[stackstart]; + + sum_out -= *stackpix; + + pixel = pixels[yw + qMin(x + radius + 1, wm)]; + + *stackpix = qAlpha(pixel); + + sum_in += *stackpix; + sum += sum_in; + + if (++stackpointer >= div) + stackpointer = 0; + + stackpix = &stack[stackpointer]; + + sum_out += *stackpix; + sum_in -= *stackpix; + } // for (x = 0, ...) + } // for (y = 0, ...) +} + + +inline static void blurVertical(QImage &image, int *stack, int div, int radius) +{ + quint32 * const pixels = reinterpret_cast(image.bits()); + + int w = image.width(); + int h = image.height(); + int hm = h - 1; + + int mul_sum = stack_blur8_mul[radius]; + int shr_sum = stack_blur8_shr[radius]; + + int sum, sum_in, sum_out; + + int stackpointer; + int stackstart; + + quint32 pixel; + + for (int x = 0; x < w; x++) + { + sum = 0; + sum_in = 0; + sum_out = 0; + + pixel = pixels[x]; + for (int i = 0; i <= radius; i++) + { + stack[i] = qAlpha(pixel); + + sum += stack[i] * (i + 1); + sum_out += stack[i]; + } + + for (int i = 1; i <= radius; i++) + { + pixel = pixels[qMin(i, hm) * w + x]; + + int *stackpix = &stack[i + radius]; + *stackpix = qAlpha(pixel); + + sum += *stackpix * (radius + 1 - i); + sum_in += *stackpix; + } + + stackpointer = radius; + for (int y = 0, i = x; y < h; y++, i += w) + { + pixels[i] = (((sum * mul_sum) >> shr_sum) << 24) & 0xff000000; + + sum -= sum_out; + + stackstart = stackpointer + div - radius; + if (stackstart >= div) + stackstart -= div; + + int *stackpix = &stack[stackstart]; + + sum_out -= *stackpix; + + pixel = pixels[qMin(y + radius + 1, hm) * w + x]; + + *stackpix = qAlpha(pixel); + + sum_in += *stackpix; + sum += sum_in; + + if (++stackpointer >= div) + stackpointer = 0; + + stackpix = &stack[stackpointer]; + + sum_out += *stackpix; + sum_in -= *stackpix; + } // for (y = 0, ...) + } // for (x = 0, ...) +} + + +void shadowBlur(QImage &image, int radius) +{ + if (radius < 1) + return; + + int div = radius * 2 + 1; + int *stack = new int[div]; + + blurHorizontal(image, stack, div, radius); + blurVertical(image, stack, div, radius); + + delete [] stack; +} + +// kate: space-indent on; indent-width 4; replace-tabs on;