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 }