forked from blue/squawk
146 lines
4.5 KiB
C++
146 lines
4.5 KiB
C++
/*
|
|
* Squawk messenger.
|
|
* Copyright (C) 2019 Yury Gubich <blue@macaw.me>
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, 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 General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "dropshadoweffect.h"
|
|
|
|
PixmapFilter::PixmapFilter(QObject* parent):QObject(parent) {}
|
|
PixmapFilter::~PixmapFilter(){}
|
|
QRectF PixmapFilter::boundingRectFor(const QRectF &rect) const {return rect;}
|
|
|
|
PixmapDropShadowFilter::PixmapDropShadowFilter(QObject *parent):
|
|
PixmapFilter(parent),
|
|
mColor(63, 63, 63, 180),
|
|
mRadius(1),
|
|
mThickness(2),
|
|
top(true),
|
|
right(true),
|
|
bottom(true),
|
|
left(true){}
|
|
|
|
PixmapDropShadowFilter::~PixmapDropShadowFilter() {}
|
|
qreal PixmapDropShadowFilter::blurRadius() const {return mRadius;}
|
|
void PixmapDropShadowFilter::setBlurRadius(qreal radius) {mRadius = radius;}
|
|
QColor PixmapDropShadowFilter::color() const {return mColor;}
|
|
void PixmapDropShadowFilter::setColor(const QColor &color) {mColor = color;}
|
|
qreal PixmapDropShadowFilter::thickness() const {return mThickness;}
|
|
void PixmapDropShadowFilter::setThickness(qreal thickness) {mThickness = thickness;}
|
|
void PixmapDropShadowFilter::setFrame(bool ptop, bool pright, bool pbottom, bool pleft)
|
|
{
|
|
top = ptop;
|
|
right = pright;
|
|
bottom = pbottom;
|
|
left = pleft;
|
|
}
|
|
|
|
void DropShadowEffect::setThickness(qreal thickness)
|
|
{
|
|
if (filter.thickness() == thickness)
|
|
return;
|
|
|
|
filter.setThickness(thickness);
|
|
update();
|
|
}
|
|
|
|
|
|
void PixmapDropShadowFilter::draw(QPainter *p, const QPointF &pos, const QPixmap &px, const QRectF &src) const
|
|
{
|
|
if (px.isNull())
|
|
return;
|
|
|
|
QImage tmp({px.width(), px.height() + int(mThickness)}, QImage::Format_ARGB32_Premultiplied);
|
|
tmp.setDevicePixelRatio(px.devicePixelRatioF());
|
|
tmp.fill(0);
|
|
QPainter tmpPainter(&tmp);
|
|
tmpPainter.setCompositionMode(QPainter::CompositionMode_Source);
|
|
if (top) {
|
|
QRectF shadow(0, 0, px.width(), mThickness);
|
|
tmpPainter.fillRect(shadow, mColor);
|
|
}
|
|
if (right) {
|
|
QRectF shadow(px.width() - mThickness, 0, mThickness, px.height());
|
|
tmpPainter.fillRect(shadow, mColor);
|
|
}
|
|
if (bottom) {
|
|
QRectF shadow(0, px.height() - mThickness, px.width(), mThickness * 2); //i have no idea why, but it leaves some unpainted stripe without some spare space
|
|
tmpPainter.fillRect(shadow, mColor);
|
|
}
|
|
if (left) {
|
|
QRectF shadow(0, 0, mThickness, px.height());
|
|
tmpPainter.fillRect(shadow, mColor);
|
|
}
|
|
|
|
Utils::exponentialblur(tmp, mRadius, false, 0);
|
|
tmpPainter.end();
|
|
|
|
// Draw the actual pixmap...
|
|
p->drawPixmap(pos, px, src);
|
|
|
|
// draw the blurred drop shadow...
|
|
p->drawImage(pos, tmp);
|
|
}
|
|
|
|
qreal DropShadowEffect::blurRadius() const {return filter.blurRadius();}
|
|
void DropShadowEffect::setBlurRadius(qreal blurRadius)
|
|
{
|
|
if (qFuzzyCompare(filter.blurRadius(), blurRadius))
|
|
return;
|
|
|
|
filter.setBlurRadius(blurRadius);
|
|
updateBoundingRect();
|
|
emit blurRadiusChanged(blurRadius);
|
|
}
|
|
|
|
void DropShadowEffect::setFrame(bool top, bool right, bool bottom, bool left)
|
|
{
|
|
filter.setFrame(top, right, bottom, left);
|
|
update();
|
|
}
|
|
|
|
|
|
QColor DropShadowEffect::color() const {return filter.color();}
|
|
void DropShadowEffect::setColor(const QColor &color)
|
|
{
|
|
if (filter.color() == color)
|
|
return;
|
|
|
|
filter.setColor(color);
|
|
update();
|
|
emit colorChanged(color);
|
|
}
|
|
|
|
void DropShadowEffect::draw(QPainter* painter)
|
|
{
|
|
if (filter.blurRadius() <= 0 && filter.thickness() == 0) {
|
|
drawSource(painter);
|
|
return;
|
|
}
|
|
|
|
PixmapPadMode mode = PadToEffectiveBoundingRect;
|
|
|
|
// Draw pixmap in device coordinates to avoid pixmap scaling.
|
|
QPoint offset;
|
|
const QPixmap pixmap = sourcePixmap(Qt::DeviceCoordinates, &offset, mode);
|
|
if (pixmap.isNull())
|
|
return;
|
|
|
|
QTransform restoreTransform = painter->worldTransform();
|
|
painter->setWorldTransform(QTransform());
|
|
filter.draw(painter, offset, pixmap);
|
|
painter->setWorldTransform(restoreTransform);
|
|
}
|