File indexing completed on 2024-04-28 05:26:27
0001 /* 0002 * SPDX-FileCopyrightText: 2014 Hugo Pereira Da Costa <hugo.pereira@free.fr> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "breezetileset.h" 0008 0009 #include <QPainter> 0010 0011 namespace Breeze 0012 { 0013 //___________________________________________________________ 0014 inline bool bits(TileSet::Tiles flags, TileSet::Tiles testFlags) 0015 { 0016 return (flags & testFlags) == testFlags; 0017 } 0018 0019 //______________________________________________________________________________________ 0020 inline qreal devicePixelRatio(const QPixmap &pixmap) 0021 { 0022 return pixmap.devicePixelRatio(); 0023 } 0024 0025 //______________________________________________________________________________________ 0026 inline void setDevicePixelRatio(QPixmap &pixmap, qreal value) 0027 { 0028 return pixmap.setDevicePixelRatio(value); 0029 } 0030 0031 //______________________________________________________________ 0032 void TileSet::initPixmap(PixmapList &pixmaps, const QPixmap &source, int width, int height, const QRect &rect) 0033 { 0034 QSize size(width, height); 0035 if (!(size.isValid() && rect.isValid())) { 0036 pixmaps.append(QPixmap()); 0037 0038 } else if (size != rect.size()) { 0039 const qreal dpiRatio(devicePixelRatio(source)); 0040 const QRect scaledRect(rect.topLeft() * dpiRatio, rect.size() * dpiRatio); 0041 const QSize scaledSize(size * dpiRatio); 0042 const QPixmap tile(source.copy(scaledRect)); 0043 QPixmap pixmap(scaledSize); 0044 0045 pixmap.fill(Qt::transparent); 0046 QPainter painter(&pixmap); 0047 painter.drawTiledPixmap(0, 0, scaledSize.width(), scaledSize.height(), tile); 0048 setDevicePixelRatio(pixmap, dpiRatio); 0049 pixmaps.append(pixmap); 0050 0051 } else { 0052 const qreal dpiRatio(devicePixelRatio(source)); 0053 const QRect scaledRect(rect.topLeft() * dpiRatio, rect.size() * dpiRatio); 0054 QPixmap pixmap(source.copy(scaledRect)); 0055 setDevicePixelRatio(pixmap, dpiRatio); 0056 pixmaps.append(pixmap); 0057 } 0058 } 0059 0060 //______________________________________________________________ 0061 TileSet::TileSet() 0062 : _w1(0) 0063 , _h1(0) 0064 , _w3(0) 0065 , _h3(0) 0066 { 0067 _pixmaps.reserve(9); 0068 } 0069 0070 //______________________________________________________________ 0071 TileSet::TileSet(const QPixmap &source, int w1, int h1, int w2, int h2) 0072 : _w1(w1) 0073 , _h1(h1) 0074 , _w3(0) 0075 , _h3(0) 0076 { 0077 _pixmaps.reserve(9); 0078 if (source.isNull()) { 0079 return; 0080 } 0081 0082 _w3 = source.width() / devicePixelRatio(source) - (w1 + w2); 0083 _h3 = source.height() / devicePixelRatio(source) - (h1 + h2); 0084 int w = w2; 0085 int h = h2; 0086 0087 // initialise pixmap array 0088 initPixmap(_pixmaps, source, _w1, _h1, QRect(0, 0, _w1, _h1)); 0089 initPixmap(_pixmaps, source, w, _h1, QRect(_w1, 0, w2, _h1)); 0090 initPixmap(_pixmaps, source, _w3, _h1, QRect(_w1 + w2, 0, _w3, _h1)); 0091 initPixmap(_pixmaps, source, _w1, h, QRect(0, _h1, _w1, h2)); 0092 initPixmap(_pixmaps, source, w, h, QRect(_w1, _h1, w2, h2)); 0093 initPixmap(_pixmaps, source, _w3, h, QRect(_w1 + w2, _h1, _w3, h2)); 0094 initPixmap(_pixmaps, source, _w1, _h3, QRect(0, _h1 + h2, _w1, _h3)); 0095 initPixmap(_pixmaps, source, w, _h3, QRect(_w1, _h1 + h2, w2, _h3)); 0096 initPixmap(_pixmaps, source, _w3, _h3, QRect(_w1 + w2, _h1 + h2, _w3, _h3)); 0097 } 0098 0099 //___________________________________________________________ 0100 void TileSet::render(const QRect &constRect, QPainter *painter, Tiles tiles) const 0101 { 0102 const bool oldHint(painter->testRenderHint(QPainter::SmoothPixmapTransform)); 0103 painter->setRenderHint(QPainter::SmoothPixmapTransform, true); 0104 0105 // check initialization 0106 if (_pixmaps.size() < 9) { 0107 return; 0108 } 0109 0110 // copy source rect 0111 QRect rect(constRect); 0112 0113 // get rect dimensions 0114 int x0, y0, w, h; 0115 rect.getRect(&x0, &y0, &w, &h); 0116 0117 // calculate pixmaps widths 0118 int wLeft(0); 0119 int wRight(0); 0120 if (_w1 + _w3 > 0) { 0121 qreal wRatio(qreal(_w1) / qreal(_w1 + _w3)); 0122 wLeft = (tiles & Right) ? qMin(_w1, int(w * wRatio)) : _w1; 0123 wRight = (tiles & Left) ? qMin(_w3, int(w * (1.0 - wRatio))) : _w3; 0124 } 0125 0126 // calculate pixmap heights 0127 int hTop(0); 0128 int hBottom(0); 0129 if (_h1 + _h3 > 0) { 0130 qreal hRatio(qreal(_h1) / qreal(_h1 + _h3)); 0131 hTop = (tiles & Bottom) ? qMin(_h1, int(h * hRatio)) : _h1; 0132 hBottom = (tiles & Top) ? qMin(_h3, int(h * (1.0 - hRatio))) : _h3; 0133 } 0134 0135 // calculate corner locations 0136 w -= wLeft + wRight; 0137 h -= hTop + hBottom; 0138 const int x1 = x0 + wLeft; 0139 const int x2 = x1 + w; 0140 const int y1 = y0 + hTop; 0141 const int y2 = y1 + h; 0142 0143 const int w2 = _pixmaps.at(7).width() / devicePixelRatio(_pixmaps.at(7)); 0144 const int h2 = _pixmaps.at(5).height() / devicePixelRatio(_pixmaps.at(5)); 0145 0146 // corner 0147 if (bits(tiles, Top | Left)) { 0148 painter->drawPixmap(x0, y0, _pixmaps.at(0), 0, 0, wLeft * devicePixelRatio(_pixmaps.at(0)), hTop * devicePixelRatio(_pixmaps.at(0))); 0149 } 0150 if (bits(tiles, Top | Right)) { 0151 painter->drawPixmap(x2, 0152 y0, 0153 _pixmaps.at(2), 0154 (_w3 - wRight) * devicePixelRatio(_pixmaps.at(2)), 0155 0, 0156 wRight * devicePixelRatio(_pixmaps.at(2)), 0157 hTop * devicePixelRatio(_pixmaps.at(2))); 0158 } 0159 if (bits(tiles, Bottom | Left)) { 0160 painter->drawPixmap(x0, 0161 y2, 0162 _pixmaps.at(6), 0163 0, 0164 (_h3 - hBottom) * devicePixelRatio(_pixmaps.at(6)), 0165 wLeft * devicePixelRatio(_pixmaps.at(6)), 0166 hBottom * devicePixelRatio(_pixmaps.at(6))); 0167 } 0168 if (bits(tiles, Bottom | Right)) { 0169 painter->drawPixmap(x2, 0170 y2, 0171 _pixmaps.at(8), 0172 (_w3 - wRight) * devicePixelRatio(_pixmaps.at(8)), 0173 (_h3 - hBottom) * devicePixelRatio(_pixmaps.at(8)), 0174 wRight * devicePixelRatio(_pixmaps.at(8)), 0175 hBottom * devicePixelRatio(_pixmaps.at(8))); 0176 } 0177 0178 // top and bottom 0179 if (w > 0) { 0180 if (tiles & Top) { 0181 painter->drawPixmap(x1, y0, w, hTop, _pixmaps.at(1), 0, 0, w2 * devicePixelRatio(_pixmaps.at(1)), hTop * devicePixelRatio(_pixmaps.at(1))); 0182 } 0183 if (tiles & Bottom) { 0184 painter->drawPixmap(x1, 0185 y2, 0186 w, 0187 hBottom, 0188 _pixmaps.at(7), 0189 0, 0190 (_h3 - hBottom) * devicePixelRatio(_pixmaps.at(7)), 0191 w2 * devicePixelRatio(_pixmaps.at(7)), 0192 hBottom * devicePixelRatio(_pixmaps.at(7))); 0193 } 0194 } 0195 0196 // left and right 0197 if (h > 0) { 0198 if (tiles & Left) { 0199 painter->drawPixmap(x0, y1, wLeft, h, _pixmaps.at(3), 0, 0, wLeft * devicePixelRatio(_pixmaps.at(3)), h2 * devicePixelRatio(_pixmaps.at(3))); 0200 } 0201 if (tiles & Right) { 0202 painter->drawPixmap(x2, 0203 y1, 0204 wRight, 0205 h, 0206 _pixmaps.at(5), 0207 (_w3 - wRight) * devicePixelRatio(_pixmaps.at(5)), 0208 0, 0209 wRight * devicePixelRatio(_pixmaps.at(5)), 0210 h2 * devicePixelRatio(_pixmaps.at(5))); 0211 } 0212 } 0213 0214 // center 0215 if ((tiles & Center) && h > 0 && w > 0) { 0216 painter->drawPixmap(x1, y1, w, h, _pixmaps.at(4)); 0217 } 0218 0219 // restore 0220 painter->setRenderHint(QPainter::SmoothPixmapTransform, oldHint); 0221 } 0222 0223 }