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