File indexing completed on 2024-12-22 04:31:06

0001 /*************************************************************************
0002  * Copyright (C) 2014 by Hugo Pereira Da Costa <hugo.pereira@free.fr>    *
0003  *                                                                       *
0004  * This program is free software; you can redistribute it and/or modify  *
0005  * it under the terms of the GNU General Public License as published by  *
0006  * the Free Software Foundation; either version 2 of the License, or     *
0007  * (at your option) any later version.                                   *
0008  *                                                                       *
0009  * This program is distributed in the hope that it will be useful,       *
0010  * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0012  * GNU General Public License for more details.                          *
0013  *                                                                       *
0014  * You should have received a copy of the GNU General Public License     *
0015  * along with this program; if not, write to the                         *
0016  * Free Software Foundation, Inc.,                                       *
0017  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA .        *
0018  *************************************************************************/
0019 
0020 #include "tileset.h"
0021 
0022 #include <QPainter>
0023 
0024 //___________________________________________________________
0025 inline bool bits(TileSet::Tiles flags, TileSet::Tiles testFlags)
0026 { return (flags & testFlags) == testFlags; }
0027 
0028 //______________________________________________________________________________________
0029 inline qreal devicePixelRatio( const QPixmap& pixmap )
0030 {
0031     return pixmap.devicePixelRatio();
0032 }
0033 
0034 //______________________________________________________________________________________
0035 inline void setDevicePixelRatio( QPixmap& pixmap, qreal value )
0036 {
0037     return pixmap.setDevicePixelRatio( value );
0038 }
0039 
0040 //______________________________________________________________
0041 void TileSet::initPixmap( PixmapList& pixmaps, const QPixmap &source, int width, int height, const QRect &rect)
0042 {
0043     QSize size( width, height );
0044     if( !( size.isValid() && rect.isValid() ) )
0045     {
0046         pixmaps.append( QPixmap() );
0047 
0048     } else if( size != rect.size() ) {
0049 
0050         const qreal dpiRatio( devicePixelRatio( source ) );
0051         const QRect scaledRect( rect.topLeft()*dpiRatio, rect.size()*dpiRatio );
0052         const QSize scaledSize( size*dpiRatio );
0053         const QPixmap tile( source.copy(scaledRect) );
0054         QPixmap pixmap( scaledSize );
0055 
0056         pixmap.fill(Qt::transparent);
0057         QPainter painter(&pixmap);
0058         painter.drawTiledPixmap(0, 0, scaledSize.width(), scaledSize.height(), tile);
0059         setDevicePixelRatio( pixmap, dpiRatio );
0060         pixmaps.append( pixmap );
0061 
0062     } else {
0063 
0064         const qreal dpiRatio( devicePixelRatio( source ) );
0065         const QRect scaledRect( rect.topLeft()*dpiRatio, rect.size()*dpiRatio );
0066         QPixmap pixmap( source.copy( scaledRect ) );
0067         setDevicePixelRatio( pixmap, dpiRatio );
0068         pixmaps.append( pixmap );
0069 
0070     }
0071 
0072 }
0073 
0074 //______________________________________________________________
0075 TileSet::TileSet():
0076     _w1(0),
0077     _h1(0),
0078     _w3(0),
0079     _h3(0)
0080 { _pixmaps.reserve(9); }
0081 
0082 //______________________________________________________________
0083 TileSet::TileSet(const QPixmap &source, int w1, int h1, int w2, int h2 ):
0084     _w1(w1),
0085     _h1(h1),
0086     _w3(0),
0087     _h3(0)
0088 {
0089     _pixmaps.reserve(9);
0090     if( source.isNull() ) return;
0091 
0092     _w3 = source.width()/devicePixelRatio( source ) - (w1 + w2);
0093     _h3 = source.height()/devicePixelRatio( source ) - (h1 + h2);
0094     int w = w2;
0095     int h = h2;
0096 
0097     // initialise pixmap array
0098     initPixmap( _pixmaps, source, _w1, _h1, QRect(0, 0, _w1, _h1) );
0099     initPixmap( _pixmaps, source, w, _h1, QRect(_w1, 0, w2, _h1) );
0100     initPixmap( _pixmaps, source, _w3, _h1, QRect(_w1+w2, 0, _w3, _h1) );
0101     initPixmap( _pixmaps, source, _w1, h, QRect(0, _h1, _w1, h2) );
0102     initPixmap( _pixmaps, source, w, h, QRect(_w1, _h1, w2, h2) );
0103     initPixmap( _pixmaps, source, _w3, h, QRect(_w1+w2, _h1, _w3, h2) );
0104     initPixmap( _pixmaps, source, _w1, _h3, QRect(0, _h1+h2, _w1, _h3) );
0105     initPixmap( _pixmaps, source, w, _h3, QRect(_w1, _h1+h2, w2, _h3) );
0106     initPixmap( _pixmaps, source, _w3, _h3, QRect(_w1+w2, _h1+h2, _w3, _h3) );
0107 }
0108 
0109 //___________________________________________________________
0110 void TileSet::render(const QRect &constRect, QPainter *painter, Tiles tiles) const
0111 {
0112 
0113     const bool oldHint( painter->testRenderHint( QPainter::SmoothPixmapTransform ) );
0114     painter->setRenderHint( QPainter::SmoothPixmapTransform, true );
0115 
0116     // check initialization
0117     if( _pixmaps.size() < 9 ) return;
0118 
0119     // copy source rect
0120     QRect rect( constRect );
0121 
0122     // get rect dimensions
0123     int x0, y0, w, h;
0124     rect.getRect(&x0, &y0, &w, &h);
0125 
0126     // calculate pixmaps widths
0127     int wLeft(0);
0128     int wRight(0);
0129     if( _w1+_w3 > 0 )
0130     {
0131         qreal wRatio( qreal( _w1 )/qreal( _w1 + _w3 ) );
0132         wLeft = (tiles&Right) ? qMin( _w1, int(w*wRatio) ):_w1;
0133         wRight = (tiles&Left) ? qMin( _w3, int(w*(1.0-wRatio)) ):_w3;
0134     }
0135 
0136     // calculate pixmap heights
0137     int hTop(0);
0138     int hBottom(0);
0139     if( _h1+_h3 > 0 )
0140     {
0141         qreal hRatio( qreal( _h1 )/qreal( _h1 + _h3 ) );
0142         hTop = (tiles&Bottom) ? qMin( _h1, int(h*hRatio) ):_h1;
0143         hBottom = (tiles&Top) ? qMin( _h3, int(h*(1.0-hRatio)) ):_h3;
0144     }
0145 
0146     // calculate corner locations
0147     w -= wLeft + wRight;
0148     h -= hTop + hBottom;
0149     const int x1 = x0 + wLeft;
0150     const int x2 = x1 + w;
0151     const int y1 = y0 + hTop;
0152     const int y2 = y1 + h;
0153 
0154     const int w2 = _pixmaps.at(7).width()/devicePixelRatio( _pixmaps.at(7) );
0155     const int h2 = _pixmaps.at(5).height()/devicePixelRatio( _pixmaps.at(5) );
0156 
0157     // corner
0158     if( bits( tiles, Top|Left) )  painter->drawPixmap(x0, y0, _pixmaps.at(0), 0, 0, wLeft*devicePixelRatio( _pixmaps.at(0) ), hTop*devicePixelRatio( _pixmaps.at(0) ));
0159     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) ) );
0160     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) ));
0161     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) ) );
0162 
0163     // top and bottom
0164     if( w > 0 )
0165     {
0166         if( tiles&Top ) painter->drawPixmap(x1, y0, w, hTop, _pixmaps.at(1), 0, 0, w2*devicePixelRatio( _pixmaps.at(1) ), hTop*devicePixelRatio( _pixmaps.at(1) ) );
0167         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) ) );
0168     }
0169 
0170     // left and right
0171     if( h > 0 )
0172     {
0173         if( tiles&Left ) painter->drawPixmap(x0, y1, wLeft, h, _pixmaps.at(3), 0, 0, wLeft*devicePixelRatio( _pixmaps.at(3) ), h2*devicePixelRatio( _pixmaps.at(3) ) );
0174         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) ) );
0175     }
0176 
0177     // center
0178     if( (tiles&Center) && h > 0 && w > 0 ) painter->drawPixmap(x1, y1, w, h, _pixmaps.at(4));
0179 
0180     // restore
0181     painter->setRenderHint( QPainter::SmoothPixmapTransform, oldHint );
0182 
0183 }