aerothemeplasma/KWin/smod_kwin_theme/breeze/kstyle/breezetileset.cpp

224 lines
7.6 KiB
C++

/*
* SPDX-FileCopyrightText: 2014 Hugo Pereira Da Costa <hugo.pereira@free.fr>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "breezetileset.h"
#include <QPainter>
namespace Breeze
{
//___________________________________________________________
inline bool bits(TileSet::Tiles flags, TileSet::Tiles testFlags)
{
return (flags & testFlags) == testFlags;
}
//______________________________________________________________________________________
inline qreal devicePixelRatio(const QPixmap &pixmap)
{
return pixmap.devicePixelRatio();
}
//______________________________________________________________________________________
inline void setDevicePixelRatio(QPixmap &pixmap, qreal value)
{
return pixmap.setDevicePixelRatio(value);
}
//______________________________________________________________
void TileSet::initPixmap(PixmapList &pixmaps, const QPixmap &source, int width, int height, const QRect &rect)
{
QSize size(width, height);
if (!(size.isValid() && rect.isValid())) {
pixmaps.append(QPixmap());
} else if (size != rect.size()) {
const qreal dpiRatio(devicePixelRatio(source));
const QRect scaledRect(rect.topLeft() * dpiRatio, rect.size() * dpiRatio);
const QSize scaledSize(size * dpiRatio);
const QPixmap tile(source.copy(scaledRect));
QPixmap pixmap(scaledSize);
pixmap.fill(Qt::transparent);
QPainter painter(&pixmap);
painter.drawTiledPixmap(0, 0, scaledSize.width(), scaledSize.height(), tile);
setDevicePixelRatio(pixmap, dpiRatio);
pixmaps.append(pixmap);
} else {
const qreal dpiRatio(devicePixelRatio(source));
const QRect scaledRect(rect.topLeft() * dpiRatio, rect.size() * dpiRatio);
QPixmap pixmap(source.copy(scaledRect));
setDevicePixelRatio(pixmap, dpiRatio);
pixmaps.append(pixmap);
}
}
//______________________________________________________________
TileSet::TileSet()
: _w1(0)
, _h1(0)
, _w3(0)
, _h3(0)
{
_pixmaps.reserve(9);
}
//______________________________________________________________
TileSet::TileSet(const QPixmap &source, int w1, int h1, int w2, int h2)
: _w1(w1)
, _h1(h1)
, _w3(0)
, _h3(0)
{
_pixmaps.reserve(9);
if (source.isNull()) {
return;
}
_w3 = source.width() / devicePixelRatio(source) - (w1 + w2);
_h3 = source.height() / devicePixelRatio(source) - (h1 + h2);
int w = w2;
int h = h2;
// initialise pixmap array
initPixmap(_pixmaps, source, _w1, _h1, QRect(0, 0, _w1, _h1));
initPixmap(_pixmaps, source, w, _h1, QRect(_w1, 0, w2, _h1));
initPixmap(_pixmaps, source, _w3, _h1, QRect(_w1 + w2, 0, _w3, _h1));
initPixmap(_pixmaps, source, _w1, h, QRect(0, _h1, _w1, h2));
initPixmap(_pixmaps, source, w, h, QRect(_w1, _h1, w2, h2));
initPixmap(_pixmaps, source, _w3, h, QRect(_w1 + w2, _h1, _w3, h2));
initPixmap(_pixmaps, source, _w1, _h3, QRect(0, _h1 + h2, _w1, _h3));
initPixmap(_pixmaps, source, w, _h3, QRect(_w1, _h1 + h2, w2, _h3));
initPixmap(_pixmaps, source, _w3, _h3, QRect(_w1 + w2, _h1 + h2, _w3, _h3));
}
//___________________________________________________________
void TileSet::render(const QRect &constRect, QPainter *painter, Tiles tiles) const
{
const bool oldHint(painter->testRenderHint(QPainter::SmoothPixmapTransform));
painter->setRenderHint(QPainter::SmoothPixmapTransform, true);
// check initialization
if (_pixmaps.size() < 9) {
return;
}
// copy source rect
QRect rect(constRect);
// get rect dimensions
int x0, y0, w, h;
rect.getRect(&x0, &y0, &w, &h);
// calculate pixmaps widths
int wLeft(0);
int wRight(0);
if (_w1 + _w3 > 0) {
qreal wRatio(qreal(_w1) / qreal(_w1 + _w3));
wLeft = (tiles & Right) ? qMin(_w1, int(w * wRatio)) : _w1;
wRight = (tiles & Left) ? qMin(_w3, int(w * (1.0 - wRatio))) : _w3;
}
// calculate pixmap heights
int hTop(0);
int hBottom(0);
if (_h1 + _h3 > 0) {
qreal hRatio(qreal(_h1) / qreal(_h1 + _h3));
hTop = (tiles & Bottom) ? qMin(_h1, int(h * hRatio)) : _h1;
hBottom = (tiles & Top) ? qMin(_h3, int(h * (1.0 - hRatio))) : _h3;
}
// calculate corner locations
w -= wLeft + wRight;
h -= hTop + hBottom;
const int x1 = x0 + wLeft;
const int x2 = x1 + w;
const int y1 = y0 + hTop;
const int y2 = y1 + h;
const int w2 = _pixmaps.at(7).width() / devicePixelRatio(_pixmaps.at(7));
const int h2 = _pixmaps.at(5).height() / devicePixelRatio(_pixmaps.at(5));
// corner
if (bits(tiles, Top | Left)) {
painter->drawPixmap(x0, y0, _pixmaps.at(0), 0, 0, wLeft * devicePixelRatio(_pixmaps.at(0)), hTop * devicePixelRatio(_pixmaps.at(0)));
}
if (bits(tiles, Top | Right)) {
painter->drawPixmap(x2,
y0,
_pixmaps.at(2),
(_w3 - wRight) * devicePixelRatio(_pixmaps.at(2)),
0,
wRight * devicePixelRatio(_pixmaps.at(2)),
hTop * devicePixelRatio(_pixmaps.at(2)));
}
if (bits(tiles, Bottom | Left)) {
painter->drawPixmap(x0,
y2,
_pixmaps.at(6),
0,
(_h3 - hBottom) * devicePixelRatio(_pixmaps.at(6)),
wLeft * devicePixelRatio(_pixmaps.at(6)),
hBottom * devicePixelRatio(_pixmaps.at(6)));
}
if (bits(tiles, Bottom | Right)) {
painter->drawPixmap(x2,
y2,
_pixmaps.at(8),
(_w3 - wRight) * devicePixelRatio(_pixmaps.at(8)),
(_h3 - hBottom) * devicePixelRatio(_pixmaps.at(8)),
wRight * devicePixelRatio(_pixmaps.at(8)),
hBottom * devicePixelRatio(_pixmaps.at(8)));
}
// top and bottom
if (w > 0) {
if (tiles & Top) {
painter->drawPixmap(x1, y0, w, hTop, _pixmaps.at(1), 0, 0, w2 * devicePixelRatio(_pixmaps.at(1)), hTop * devicePixelRatio(_pixmaps.at(1)));
}
if (tiles & Bottom) {
painter->drawPixmap(x1,
y2,
w,
hBottom,
_pixmaps.at(7),
0,
(_h3 - hBottom) * devicePixelRatio(_pixmaps.at(7)),
w2 * devicePixelRatio(_pixmaps.at(7)),
hBottom * devicePixelRatio(_pixmaps.at(7)));
}
}
// left and right
if (h > 0) {
if (tiles & Left) {
painter->drawPixmap(x0, y1, wLeft, h, _pixmaps.at(3), 0, 0, wLeft * devicePixelRatio(_pixmaps.at(3)), h2 * devicePixelRatio(_pixmaps.at(3)));
}
if (tiles & Right) {
painter->drawPixmap(x2,
y1,
wRight,
h,
_pixmaps.at(5),
(_w3 - wRight) * devicePixelRatio(_pixmaps.at(5)),
0,
wRight * devicePixelRatio(_pixmaps.at(5)),
h2 * devicePixelRatio(_pixmaps.at(5)));
}
}
// center
if ((tiles & Center) && h > 0 && w > 0) {
painter->drawPixmap(x1, y1, w, h, _pixmaps.at(4));
}
// restore
painter->setRenderHint(QPainter::SmoothPixmapTransform, oldHint);
}
}