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