when the size changes resize all frames
svn path=/trunk/KDE/kdelibs/; revision=1054744
This commit is contained in:
parent
ebbb89e543
commit
495a00cc59
236
private/effects/halopainter.cpp
Normal file
236
private/effects/halopainter.cpp
Normal file
@ -0,0 +1,236 @@
|
||||
/*
|
||||
* 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>
|
||||
|
||||
|
||||
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);
|
||||
for (int i = 0; i <= 16; i++)
|
||||
g.setColorAt(i / 16., QColor(0, 0, 0, 164 * (1 - std::pow((i - 8) / 8., 2))));
|
||||
p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
|
||||
p.fillRect(pixmap->rect(), g);
|
||||
p.end();
|
||||
|
||||
m_haloCache.insert(key, pixmap);
|
||||
}
|
||||
|
||||
painter->drawPixmap(hr.topLeft(), *pixmap);
|
||||
}
|
||||
|
77
private/effects/halopainter_p.h
Normal file
77
private/effects/halopainter_p.h
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -99,6 +99,9 @@ bool FocusIndicator::eventFilter(QObject *watched, QEvent *event)
|
||||
|
||||
void FocusIndicator::resizeEvent(QGraphicsSceneResizeEvent *event)
|
||||
{
|
||||
m_background->setElementPrefix("hover");
|
||||
m_background->resizeFrame(event->newSize());
|
||||
m_background->setElementPrefix("focus");
|
||||
m_background->resizeFrame(event->newSize());
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user