get rid of PaintUtils
the only one using it was PlasmaCore.IconItem, move the transition() function there
This commit is contained in:
parent
8df5da1c50
commit
99bab1825e
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -1 +0,0 @@
|
||||
#include "../../plasma/abstracttoolbox.h"
|
@ -1 +0,0 @@
|
||||
#include "../../plasma/paintutils.h"
|
@ -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
|
||||
|
@ -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
|
@ -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
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user