get rid of PaintUtils

the only one using it was PlasmaCore.IconItem, move the transition() function there
This commit is contained in:
Marco Martin 2013-03-13 12:05:06 +01:00
parent 8df5da1c50
commit 99bab1825e
9 changed files with 131 additions and 850 deletions

View File

@ -19,15 +19,141 @@
#include "iconitem.h"
#include <KIconLoader>
#include <KIconEffect>
#include <QDebug>
#include <QPaintEngine>
#include <QPainter>
#include <QPropertyAnimation>
#include <KIconLoader>
#include <KIconEffect>
#include <plasma/paintutils.h>
#include <plasma/svg.h>
#include <QDebug>
QPixmap transition(const QPixmap &from, const QPixmap &to, qreal amount)
{
if (from.isNull() && to.isNull()) {
return from;
}
if (qFuzzyCompare(amount + 1, qreal(1.0))) {
return from;
}
QRect startRect(from.rect());
QRect targetRect(to.rect());
QSize pixmapSize = startRect.size().expandedTo(targetRect.size());
QRect toRect = QRect(QPoint(0,0), pixmapSize);
targetRect.moveCenter(toRect.center());
startRect.moveCenter(toRect.center());
//paint to in the center of from
QColor color;
color.setAlphaF(amount);
// If the native paint engine supports Porter/Duff compositing and CompositionMode_Plus
QPaintEngine *paintEngine = from.paintEngine();
if (paintEngine &&
paintEngine->hasFeature(QPaintEngine::PorterDuff) &&
paintEngine->hasFeature(QPaintEngine::BlendModes)) {
QPixmap startPixmap(pixmapSize);
startPixmap.fill(Qt::transparent);
QPixmap targetPixmap(pixmapSize);
targetPixmap.fill(Qt::transparent);
QPainter p;
p.begin(&targetPixmap);
p.drawPixmap(targetRect, to);
p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
p.fillRect(targetRect, color);
p.end();
p.begin(&startPixmap);
p.drawPixmap(startRect, from);
p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
p.fillRect(startRect, color);
p.setCompositionMode(QPainter::CompositionMode_Plus);
p.drawPixmap(targetRect, targetPixmap);
p.end();
return startPixmap;
}
#warning Cannot use XRender with QPixmap anymore. Find equivalent with Qt API.
#if 0 // HAVE_X11 && defined(HAVE_XRENDER)
// We have Xrender support
else if (paintEngine && paintEngine->hasFeature(QPaintEngine::PorterDuff)) {
// QX11PaintEngine doesn't implement CompositionMode_Plus in Qt 4.3,
// which we need to be able to do a transition from one pixmap to
// another.
//
// In order to avoid the overhead of converting the pixmaps to images
// and doing the operation entirely in software, this function has a
// specialized path for X11 that uses Xrender directly to do the
// transition. This operation can be fully accelerated in HW.
//
// This specialization can be removed when QX11PaintEngine supports
// CompositionMode_Plus.
QPixmap source(targetPixmap), destination(startPixmap);
source.detach();
destination.detach();
Display *dpy = QX11Info::display();
XRenderPictFormat *format = XRenderFindStandardFormat(dpy, PictStandardA8);
XRenderPictureAttributes pa;
pa.repeat = 1; // RepeatNormal
// Create a 1x1 8 bit repeating alpha picture
Pixmap pixmap = XCreatePixmap(dpy, destination.handle(), 1, 1, 8);
Picture alpha = XRenderCreatePicture(dpy, pixmap, format, CPRepeat, &pa);
XFreePixmap(dpy, pixmap);
// Fill the alpha picture with the opacity value
XRenderColor xcolor;
xcolor.alpha = quint16(0xffff * amount);
XRenderFillRectangle(dpy, PictOpSrc, alpha, &xcolor, 0, 0, 1, 1);
// Reduce the alpha of the destination with 1 - opacity
XRenderComposite(dpy, PictOpOutReverse, alpha, None, destination.x11PictureHandle(),
0, 0, 0, 0, 0, 0, destination.width(), destination.height());
// Add source * opacity to the destination
XRenderComposite(dpy, PictOpAdd, source.x11PictureHandle(), alpha,
destination.x11PictureHandle(),
toRect.x(), toRect.y(), 0, 0, 0, 0, destination.width(), destination.height());
XRenderFreePicture(dpy, alpha);
return destination;
}
#endif
else {
// Fall back to using QRasterPaintEngine to do the transition.
QImage under(pixmapSize, QImage::Format_ARGB32_Premultiplied);
under.fill(Qt::transparent);
QImage over(pixmapSize, QImage::Format_ARGB32_Premultiplied);
over.fill(Qt::transparent);
QPainter p;
p.begin(&over);
p.drawPixmap(targetRect, to);
p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
p.fillRect(over.rect(), color);
p.end();
p.begin(&under);
p.drawPixmap(startRect, from);
p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
p.fillRect(startRect, color);
p.setCompositionMode(QPainter::CompositionMode_Plus);
p.drawImage(toRect.topLeft(), over);
p.end();
return QPixmap::fromImage(under);
}
}
IconItem::IconItem(QQuickItem *parent)
: QQuickPaintedItem(parent),
@ -193,8 +319,8 @@ void IconItem::paint(QPainter *painter)
if (m_animation->state() == QAbstractAnimation::Running) {
QPixmap result = m_iconPixmaps.first();
result = Plasma::PaintUtils::transition(result,
m_iconPixmaps.last(), m_animValue);
result = transition(result,
m_iconPixmaps.last(), m_animValue);
painter->drawPixmap(destRect, result);
//simpler logic for just paint
} else {

View File

@ -111,10 +111,8 @@ set(plasma_LIB_SRCS
#graphics
framesvg.cpp
paintutils.cpp
svg.cpp
theme.cpp
private/effects/halopainter.cpp
private/theme_p.cpp
#scripting
@ -176,7 +174,6 @@ set(plasma_LIB_INCLUDES
datacontainer.h
dataengine.h
pluginloader.h
paintutils.h
framesvg.h
package.h
packagestructure.h

View File

@ -1 +0,0 @@
#include "../../plasma/abstracttoolbox.h"

View File

@ -1 +0,0 @@
#include "../../plasma/paintutils.h"

View File

@ -1,283 +0,0 @@
/*
* Copyright 2005 by Aaron Seigo <aseigo@kde.org>
* Copyright 2008 by Andrew Lake <jamboarder@yahoo.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <paintutils.h>
#include <QImage>
#include <QPainter>
#include <QPaintEngine>
#include <QPixmap>
#include "private/effects/blur.cpp"
#include "private/effects/halopainter_p.h"
#include "svg.h"
namespace Plasma
{
namespace PaintUtils
{
void shadowBlur(QImage &image, int radius, const QColor &color)
{
if (radius < 1) {
return;
}
if (image.isNull()) {
return;
}
expblur<16, 7>(image, radius);
QPainter p(&image);
p.setCompositionMode(QPainter::CompositionMode_SourceIn);
p.fillRect(image.rect(), color);
p.end();
}
QPixmap texturedText(const QString &text, const QFont &font, Plasma::Svg *texture)
{
QFontMetrics fm(font);
//the text will be moved a bit from contentsRect
QRect contentsRect = fm.boundingRect(text).adjusted(0, 0, 2, 2);
contentsRect.moveTo(0,0);
QPixmap pixmap(contentsRect.size());
pixmap.fill(Qt::transparent);
QPainter buffPainter(&pixmap);
buffPainter.setPen(Qt::black);
buffPainter.setFont(font);
buffPainter.drawText(contentsRect, Qt::AlignCenter, text);
buffPainter.setCompositionMode(QPainter::CompositionMode_SourceIn);
texture->paint(&buffPainter, contentsRect, "foreground");
buffPainter.end();
//do the shadow
QImage image(pixmap.size() + QSize(2, 2), QImage::Format_ARGB32_Premultiplied);
image.fill(Qt::transparent);
buffPainter.begin(&image);
buffPainter.setFont(font);
buffPainter.drawText(contentsRect.translated(1, 1), Qt::AlignCenter, text);
buffPainter.setCompositionMode(QPainter::CompositionMode_SourceIn);
texture->paint(&buffPainter, contentsRect.adjusted(-1, -1, 1, 1), "shadow");
buffPainter.end();
expblur<16, 7>(image, 1);
//hole in the shadow
buffPainter.begin(&image);
buffPainter.setCompositionMode(QPainter::CompositionMode_DestinationOut);
buffPainter.setFont(font);
buffPainter.drawText(contentsRect.translated(1, 1), Qt::AlignCenter, text);
buffPainter.end();
QPixmap ret(image.size());
ret.fill(Qt::transparent);
buffPainter.begin(&ret);
buffPainter.setCompositionMode(QPainter::CompositionMode_SourceOver);
buffPainter.drawImage(QPoint(0,0), image);
buffPainter.drawPixmap(QPoint(1,1), pixmap);
buffPainter.end();
return ret;
}
void drawHalo(QPainter *painter, const QRectF &rect)
{
HaloPainter::instance()->drawHalo(painter, rect.toRect());
}
QPainterPath roundedRectangle(const QRectF &rect, qreal radius)
{
QPainterPath path(QPointF(rect.left(), rect.top() + radius));
path.quadTo(rect.left(), rect.top(), rect.left() + radius, rect.top()); // Top left corner
path.lineTo(rect.right() - radius, rect.top()); // Top side
path.quadTo(rect.right(), rect.top(), rect.right(), rect.top() + radius); // Top right corner
path.lineTo(rect.right(), rect.bottom() - radius); // Right side
path.quadTo(rect.right(), rect.bottom(), rect.right() - radius, rect.bottom()); // Bottom right corner
path.lineTo(rect.left() + radius, rect.bottom()); // Bottom side
path.quadTo(rect.left(), rect.bottom(), rect.left(), rect.bottom() - radius); // Bottom left corner
path.closeSubpath();
return path;
}
void centerPixmaps(QPixmap &from, QPixmap &to)
{
if (from.size() == to.size() && from.hasAlphaChannel() && to.hasAlphaChannel()) {
return;
}
QRect fromRect(from.rect());
QRect toRect(to.rect());
QRect actualRect = QRect(QPoint(0,0), fromRect.size().expandedTo(toRect.size()));
fromRect.moveCenter(actualRect.center());
toRect.moveCenter(actualRect.center());
if (from.size() != actualRect.size() || !from.hasAlphaChannel()) {
QPixmap result(actualRect.size());
result.fill(Qt::transparent);
QPainter p(&result);
p.setCompositionMode(QPainter::CompositionMode_Source);
p.drawPixmap(fromRect.topLeft(), from);
p.end();
from = result;
}
if (to.size() != actualRect.size() || !to.hasAlphaChannel()) {
QPixmap result(actualRect.size());
result.fill(Qt::transparent);
QPainter p(&result);
p.setCompositionMode(QPainter::CompositionMode_Source);
p.drawPixmap(toRect.topLeft(), to);
p.end();
to = result;
}
}
QPixmap transition(const QPixmap &from, const QPixmap &to, qreal amount)
{
if (from.isNull() && to.isNull()) {
return from;
}
if (qFuzzyCompare(amount + 1, qreal(1.0))) {
return from;
}
QRect startRect(from.rect());
QRect targetRect(to.rect());
QSize pixmapSize = startRect.size().expandedTo(targetRect.size());
QRect toRect = QRect(QPoint(0,0), pixmapSize);
targetRect.moveCenter(toRect.center());
startRect.moveCenter(toRect.center());
//paint to in the center of from
QColor color;
color.setAlphaF(amount);
// If the native paint engine supports Porter/Duff compositing and CompositionMode_Plus
QPaintEngine *paintEngine = from.paintEngine();
if (paintEngine &&
paintEngine->hasFeature(QPaintEngine::PorterDuff) &&
paintEngine->hasFeature(QPaintEngine::BlendModes)) {
QPixmap startPixmap(pixmapSize);
startPixmap.fill(Qt::transparent);
QPixmap targetPixmap(pixmapSize);
targetPixmap.fill(Qt::transparent);
QPainter p;
p.begin(&targetPixmap);
p.drawPixmap(targetRect, to);
p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
p.fillRect(targetRect, color);
p.end();
p.begin(&startPixmap);
p.drawPixmap(startRect, from);
p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
p.fillRect(startRect, color);
p.setCompositionMode(QPainter::CompositionMode_Plus);
p.drawPixmap(targetRect, targetPixmap);
p.end();
return startPixmap;
}
#warning Cannot use XRender with QPixmap anymore. Find equivalent with Qt API.
#if 0 // HAVE_X11 && defined(HAVE_XRENDER)
// We have Xrender support
else if (paintEngine && paintEngine->hasFeature(QPaintEngine::PorterDuff)) {
// QX11PaintEngine doesn't implement CompositionMode_Plus in Qt 4.3,
// which we need to be able to do a transition from one pixmap to
// another.
//
// In order to avoid the overhead of converting the pixmaps to images
// and doing the operation entirely in software, this function has a
// specialized path for X11 that uses Xrender directly to do the
// transition. This operation can be fully accelerated in HW.
//
// This specialization can be removed when QX11PaintEngine supports
// CompositionMode_Plus.
QPixmap source(targetPixmap), destination(startPixmap);
source.detach();
destination.detach();
Display *dpy = QX11Info::display();
XRenderPictFormat *format = XRenderFindStandardFormat(dpy, PictStandardA8);
XRenderPictureAttributes pa;
pa.repeat = 1; // RepeatNormal
// Create a 1x1 8 bit repeating alpha picture
Pixmap pixmap = XCreatePixmap(dpy, destination.handle(), 1, 1, 8);
Picture alpha = XRenderCreatePicture(dpy, pixmap, format, CPRepeat, &pa);
XFreePixmap(dpy, pixmap);
// Fill the alpha picture with the opacity value
XRenderColor xcolor;
xcolor.alpha = quint16(0xffff * amount);
XRenderFillRectangle(dpy, PictOpSrc, alpha, &xcolor, 0, 0, 1, 1);
// Reduce the alpha of the destination with 1 - opacity
XRenderComposite(dpy, PictOpOutReverse, alpha, None, destination.x11PictureHandle(),
0, 0, 0, 0, 0, 0, destination.width(), destination.height());
// Add source * opacity to the destination
XRenderComposite(dpy, PictOpAdd, source.x11PictureHandle(), alpha,
destination.x11PictureHandle(),
toRect.x(), toRect.y(), 0, 0, 0, 0, destination.width(), destination.height());
XRenderFreePicture(dpy, alpha);
return destination;
}
#endif
else {
// Fall back to using QRasterPaintEngine to do the transition.
QImage under(pixmapSize, QImage::Format_ARGB32_Premultiplied);
under.fill(Qt::transparent);
QImage over(pixmapSize, QImage::Format_ARGB32_Premultiplied);
over.fill(Qt::transparent);
QPainter p;
p.begin(&over);
p.drawPixmap(targetRect, to);
p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
p.fillRect(over.rect(), color);
p.end();
p.begin(&under);
p.drawPixmap(startRect, from);
p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
p.fillRect(startRect, color);
p.setCompositionMode(QPainter::CompositionMode_Plus);
p.drawImage(toRect.topLeft(), over);
p.end();
return QPixmap::fromImage(under);
}
}
} // PaintUtils namespace
} // Plasma namespace

View File

@ -1,73 +0,0 @@
/*
* Copyright 2005 by Aaron Seigo <aseigo@kde.org>
* Copyright 2008 by Andrew Lake <jamboarder@yahoo.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef PLASMA_PAINTUTILS_H
#define PLASMA_PAINTUTILS_H
#include <QApplication>
#include <QPainterPath>
#include <QColor>
#include <plasma/plasma_export.h>
#include "theme.h"
/** @headerfile plasma/paintutils.h <Plasma/PaintUtils> */
namespace Plasma
{
class Svg;
/**
* Namespace for all Image Effects specific to Plasma
**/
namespace PaintUtils
{
/**
* Creates a blurred shadow of the supplied image.
*/
PLASMA_EXPORT void shadowBlur(QImage &image, int radius, const QColor &color);
PLASMA_EXPORT QPixmap texturedText(const QString &text, const QFont &font, Plasma::Svg *texture);
PLASMA_EXPORT void drawHalo(QPainter *painter, const QRectF &rect);
/**
* Returns a nicely rounded rectanglular path for painting.
*/
PLASMA_EXPORT QPainterPath roundedRectangle(const QRectF &rect, qreal radius);
/**
* center two pixmap together in the biggest rectangle
* @since 4.5
*/
PLASMA_EXPORT void centerPixmaps(QPixmap &from, QPixmap &to);
/**
* Blends a pixmap into another
*/
PLASMA_EXPORT QPixmap transition(const QPixmap &from, const QPixmap &to, qreal amount);
} // PaintUtils namespace
} // Plasma namespace
#endif

View File

@ -1,154 +0,0 @@
#ifndef BLUR_CPP
#define BLUR_CPP
/*
* Copyright 2007 Jani Huhtanen <jani.huhtanen@tut.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License version 2 as
* published by the Free Software Foundation
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <cmath>
// Exponential blur, Jani Huhtanen, 2006
//
template<int aprec, int zprec>
static inline void blurinner(unsigned char *bptr, int &zR, int &zG, int &zB, int &zA, int alpha);
template<int aprec,int zprec>
static inline void blurrow(QImage &im, int line, int alpha);
template<int aprec, int zprec>
static inline void blurcol(QImage &im, int col, int alpha);
/*
* expblur(QImage &img, int radius)
*
* In-place blur of image 'img' with kernel
* of approximate radius 'radius'.
*
* Blurs with two sided exponential impulse
* response.
*
* aprec = precision of alpha parameter
* in fixed-point format 0.aprec
*
* zprec = precision of state parameters
* zR,zG,zB and zA in fp format 8.zprec
*/
template<int aprec,int zprec>
void expblur(QImage &img, int radius)
{
if (radius < 1) {
return;
}
img = img.convertToFormat(QImage::Format_ARGB32_Premultiplied);
/* Calculate the alpha such that 90% of
the kernel is within the radius.
(Kernel extends to infinity)
*/
int alpha = (int)((1 << aprec) * (1.0f - std::exp(-2.3f / (radius + 1.f))));
int height = img.height();
int width = img.width();
for (int row=0; row<height; row++) {
blurrow<aprec,zprec>(img, row, alpha);
}
for (int col=0; col<width; col++) {
blurcol<aprec,zprec>(img, col, alpha);
}
return;
}
template<int aprec, int zprec>
static inline void blurinner(unsigned char *bptr, int &zR, int &zG, int &zB, int &zA, int alpha)
{
int R, G, B, A;
R = *bptr;
G = *(bptr + 1);
B = *(bptr + 2);
A = *(bptr + 3);
zR += (alpha * ((R << zprec) - zR)) >> aprec;
zG += (alpha * ((G << zprec) - zG)) >> aprec;
zB += (alpha * ((B << zprec) - zB)) >> aprec;
zA += (alpha * ((A << zprec) - zA)) >> aprec;
*bptr = zR >> zprec;
*(bptr+1) = zG >> zprec;
*(bptr+2) = zB >> zprec;
*(bptr+3) = zA >> zprec;
}
template<int aprec,int zprec>
static inline void blurrow(QImage &im, int line, int alpha)
{
int zR, zG, zB, zA;
QRgb *ptr = (QRgb *)im.scanLine(line);
int width = im.width();
zR = *((unsigned char *)ptr ) << zprec;
zG = *((unsigned char *)ptr + 1) << zprec;
zB = *((unsigned char *)ptr + 2) << zprec;
zA = *((unsigned char *)ptr + 3) << zprec;
for (int index=1; index<width; index++) {
blurinner<aprec,zprec>((unsigned char *)&ptr[index],zR,zG,zB,zA,alpha);
}
for (int index=width-2; index>=0; index--) {
blurinner<aprec,zprec>((unsigned char *)&ptr[index],zR,zG,zB,zA,alpha);
}
}
template<int aprec, int zprec>
static inline void blurcol(QImage &im, int col, int alpha)
{
int zR, zG, zB, zA;
QRgb *ptr = (QRgb *)im.bits();
ptr += col;
int height = im.height();
int width = im.width();
zR = *((unsigned char *)ptr ) << zprec;
zG = *((unsigned char *)ptr + 1) << zprec;
zB = *((unsigned char *)ptr + 2) << zprec;
zA = *((unsigned char *)ptr + 3) << zprec;
for (int index=width; index<(height-1)*width; index+=width) {
blurinner<aprec,zprec>((unsigned char *)&ptr[index], zR, zG, zB, zA, alpha);
}
for (int index=(height-2)*width; index>=0; index-=width) {
blurinner<aprec,zprec>((unsigned char *)&ptr[index], zR, zG, zB, zA, alpha);
}
}
template<class T>
inline const T &qClamp(const T &x, const T &low, const T &high)
{
if (x < low) {
return low;
} else if (x > high) {
return high;
} else {
return x;
}
}
#endif

View File

@ -1,250 +0,0 @@
/*
* Copyright © 2009 Fredrik Höglund <fredrik@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "halopainter_p.h"
#include <QPainter>
#include <cmath>
namespace Plasma
{
static inline qreal gaussian(qreal x, qreal sigma)
{
return (1.0 / std::sqrt(2.0 * M_PI) * sigma)
* std::exp(-((x * x) / (2.0 * sigma * sigma)));
}
static void gaussianBlur(QImage &image, int radius)
{
// The gaussian curve is effectively zero after 3 standard deviations.
qreal sigma = radius / 3.;
int size = radius * 2 + 1;
int center = size / 2;
qreal *kernel = new qreal[size];
qreal total = 0;
// Generate the gaussian kernel
for (int i = 0; i < size; i++) {
kernel[i] = gaussian(i - center, sigma);
total += kernel[i];
}
// Normalize the kernel
for (int i = 0; i < size; i++)
kernel[i] = kernel[i] / total;
quint32 *buf = new quint32[image.width() * image.height()];
memset(buf, 0, image.width() * image.height() * sizeof(quint32));
// Blur the image horizontally
for (int y = 0; y < image.height(); y++)
{
quint32 *src = (quint32*)image.scanLine(y);
quint32 *dst = buf + image.width() * y;
for (int x = 0, start = center; x < center; x++, start--) {
double a = 0;
for (int i = start; i < size; i++)
a += qAlpha(src[x - center + i]) * kernel[i];
dst[x] = qRound(a) << 24;
}
for (int x = center; x < image.width() - center; x++) {
double a = 0;
for (int i = 0; i < size; i++)
a += qAlpha(src[x - center + i]) * kernel[i];
dst[x] = qRound(a) << 24;
}
for (int x = image.width() - center, stop = size - 1; x < image.width(); x++, stop--) {
double a = 0;
for (int i = 0; i < stop; i++)
a += qAlpha(src[x - center + i]) * kernel[i];
dst[x] = qRound(a) << 24;
}
}
// Blur the image vertically
quint32 *src = buf;
quint32 *dst = (quint32*)image.bits();
for (int x = 0; x < image.width(); x++)
{
int di = x;
for (int y = 0, start = center; y < center; y++, start--) {
double a = 0;
int si = (y - center + start) * image.width() + x;
for (int i = start; i < size; i++) {
a += qAlpha(src[si]) * kernel[i];
si += image.width();
}
dst[di] = qRound(a) << 24;
di += image.width();
}
for (int y = center; y < image.height() - center; y++) {
double a = 0;
int si = (y - center) * image.width() + x;
for (int i = 0; i < size; i++) {
a += qAlpha(src[si]) * kernel[i];
si += image.width();
}
dst[di] = qRound(a) << 24;
di += image.width();
}
for (int y = image.height() - center, stop = size - 1; y < image.height(); y++, stop--) {
double a = 0;
int si = (y - center) * image.width() + x;
for (int i = 0; i < stop; i++) {
a += qAlpha(src[si]) * kernel[i];
si += image.width();
}
dst[di] = qRound(a) << 24;
di += image.width();
}
}
delete [] buf;
delete [] kernel;
}
// -----------------------------------------------------------------------
TileSet::TileSet(const QPixmap &pixmap)
{
int tw = pixmap.width() / 3;
int th = pixmap.height();
for (int x = 0; x < 3; x++)
tiles[x] = pixmap.copy(x * tw, 0, tw, th);
}
void TileSet::paint(QPainter *p, const QRect &r)
{
int tw = tiles[Left].width();
int th = tiles[Left].height();
int tw2 = tw * 2;
if (r.width() < tw2) {
int sw = r.width() / 2;
p->drawPixmap(r.x(), r.y(), tiles[Left], 0, 0, sw, tiles[Left].height());
p->drawPixmap(r.x() + sw, r.y(), tiles[Right], tw - sw, 0, sw, tiles[Right].height());
} else {
p->drawPixmap(r.topLeft(), tiles[Left]);
if (r.width() - tw2 > 0)
p->drawTiledPixmap(r.x() + tw, r.y(), r.width() - tw2, th, tiles[Center]);
p->drawPixmap(r.right() - tw + 1, r.y(), tiles[Right]);
}
}
// -----------------------------------------------------------------------
HaloPainter *HaloPainter::s_instance = 0;
HaloPainter::HaloPainter()
: m_tileCache(16), m_haloCache(30)
{
}
HaloPainter::~HaloPainter()
{
}
TileSet *HaloPainter::tiles(int height) const
{
TileSet *tiles = m_tileCache.object(height);
if (!tiles) {
QImage image(64 * 3, height + 16, QImage::Format_ARGB32_Premultiplied);
image.fill(0);
QPainter p(&image);
p.setRenderHint(QPainter::Antialiasing);
p.setPen(Qt::NoPen);
p.setBrush(Qt::white);
p.drawRoundedRect(image.rect().adjusted(8, 8, -8, -8), height, height / 2);
p.end();
gaussianBlur(image, 8);
p.begin(&image);
p.setCompositionMode(QPainter::CompositionMode_SourceIn);
p.fillRect(image.rect(), QColor(255, 255, 255, 255));
p.end();
tiles = new TileSet(QPixmap::fromImage(image));
m_tileCache.insert(height, tiles);
}
return tiles;
}
void HaloPainter::paint(QPainter *painter, const QRect &textRect) const
{
int radius = textRect.height() / 2;
const QRect hr = textRect.adjusted(-8 - radius, -9, 8 + radius, 9);
int key = hr.width() << 16 | hr.height();
QPixmap *pixmap = m_haloCache.object(key);
if (!pixmap) {
TileSet *halo = tiles(hr.height() - 16);
pixmap = new QPixmap(hr.size());
pixmap->fill(Qt::transparent);
QPainter p(pixmap);
p.setCompositionMode(QPainter::CompositionMode_Source);
halo->paint(&p, pixmap->rect());
QLinearGradient g(0, 0, pixmap->width(), 0);
if (hr.width() < 80) {
for (int i = 0; i <= 16; i++) {
g.setColorAt(i / 16., QColor(0, 0, 0, 164 * (1 - std::pow((i - 8) / 8., 2))));
}
} else {
const qreal pixel = 1. / hr.width();
for (int i = 0; i <= 8; i++) {
const QColor color(0, 0, 0, 164 * (1 - std::pow((i - 8) / 8., 2)));
g.setColorAt(i * (pixel * 40) / 8, color);
g.setColorAt(1 - i * (pixel * 40) / 8, color);
}
}
p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
p.fillRect(pixmap->rect(), g);
p.end();
m_haloCache.insert(key, pixmap);
}
painter->drawPixmap(hr.topLeft(), *pixmap);
}
} // namespace Plasma

View File

@ -1,80 +0,0 @@
/*
* Copyright © 2009 Fredrik Höglund <fredrik@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef HALOPAINTER_H
#define HALOPAINTER_H
#include <QCache>
#include <QPixmap>
class QRect;
class QPainter;
namespace Plasma {
class TileSet
{
public:
enum Tile {
Left, Center, Right, NTiles
};
TileSet(const QPixmap &pixmap);
~TileSet() {}
void paint(QPainter *painter, const QRect &rect);
protected:
QPixmap tiles[NTiles];
};
// -----------------------------------------------------------------------
class HaloPainter : public QObject
{
public:
~HaloPainter();
static HaloPainter *instance() {
if (!s_instance) {
s_instance = new HaloPainter;
}
return s_instance;
}
static void drawHalo(QPainter *painter, const QRect &textRect) {
instance()->paint(painter, textRect);
}
private:
HaloPainter();
TileSet *tiles(int height) const;
void paint(QPainter *painter, const QRect &textRect) const;
private:
static HaloPainter *s_instance;
mutable QCache<int, TileSet> m_tileCache;
mutable QCache<int, QPixmap> m_haloCache;
};
} // namespace Plasma
#endif