File indexing completed on 2024-12-22 04:31:08
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 }