You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
212 lines
7.5 KiB
212 lines
7.5 KiB
/* |
|
* 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); |
|
} |
|
|
|
}
|
|
|