/* * SPDX-FileCopyrightText: 2014 Hugo Pereira Da Costa * * SPDX-License-Identifier: GPL-2.0-or-later */ #include "breezetileset.h" #include 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); } }