1 /*****************************************************************************
2  *   Copyright 2007 Matthew Woehlke <mw_triad@users.sourceforge.net>         *
3  *   Copyright 2008 Long Huynh Huu <long.upcase@gmail.com>                   *
4  *   Copyright 2008 - 2010 Craig Drummond <craig.p.drummond@gmail.com>       *
5  *   Copyright 2013 - 2015 Yichao Yu <yyc1992@gmail.com>                     *
6  *                                                                           *
7  *   This program is free software; you can redistribute it and/or modify    *
8  *   it under the terms of the GNU Lesser General Public License as          *
9  *   published by the Free Software Foundation; either version 2.1 of the    *
10  *   License, or (at your option) version 3, or any later version accepted   *
11  *   by the membership of KDE e.V. (or its successor approved by the         *
12  *   membership of KDE e.V.), which shall act as a proxy defined in          *
13  *   Section 6 of version 3 of the license.                                  *
14  *                                                                           *
15  *   This program is distributed in the hope that it will be useful,         *
16  *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
17  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU       *
18  *   Lesser General Public License for more details.                         *
19  *                                                                           *
20  *   You should have received a copy of the GNU Lesser General Public        *
21  *   License along with this library. If not,                                *
22  *   see <http://www.gnu.org/licenses/>.                                     *
23  *****************************************************************************/
24 
25 #include "tileset.h"
26 
27 #include <kdeversion.h>
28 
29 #include <QPainter>
30 
31 void
initPixmap(int s,const QPixmap & pix,int w,int h,const QRect & region)32 TileSet::initPixmap(int s, const QPixmap &pix, int w, int h,
33                     const QRect &region)
34 {
35     if (w != region.width() || h != region.height()) {
36         QPixmap tile = pix.copy(region);
37         _pixmap[s] = QPixmap(w, h);
38         _pixmap[s].fill(QColor(0, 0, 0, 0));
39         QPainter p(&_pixmap[s]);
40         p.drawTiledPixmap(0, 0, w, h, tile);
41     } else {
42         _pixmap[s] = pix.copy(region);
43     }
44 }
45 
TileSet()46 TileSet::TileSet()
47     : _w1(0), _h1(0), _w3(0), _h3(0)
48 {
49 }
50 
TileSet(const QPixmap & pix,int w1,int h1,int w2,int h2)51 TileSet::TileSet(const QPixmap &pix, int w1, int h1, int w2, int h2)
52     : _w1(w1), _h1(h1), _w3(0), _h3(0)
53 {
54     if (pix.isNull())
55         return;
56 
57     _w3 = pix.width() - (w1 + w2);
58     _h3 = pix.height() - (h1 + h2);
59     int w = w2;
60     while (w < 32 && w2 > 0)
61         w += w2;
62     int h = h2;
63     while (h < 32 && h2 > 0)
64         h += h2;
65 
66     // initialise pixmap array
67     _pixmap.resize(9);
68     initPixmap(0, pix, _w1, _h1, QRect(0, 0, _w1, _h1));
69     initPixmap(1, pix, w, _h1, QRect(_w1, 0, w2, _h1));
70     initPixmap(2, pix, _w3, _h1, QRect(_w1 + w2, 0, _w3, _h1));
71     initPixmap(3, pix, _w1, h, QRect(0, _h1, _w1, h2));
72     initPixmap(4, pix, w, h, QRect(_w1, _h1, w2, h2));
73     initPixmap(5, pix, _w3, h, QRect(_w1 + w2, _h1, _w3, h2));
74     initPixmap(6, pix, _w1, _h3, QRect(0, _h1 + h2, _w1, _h3));
75     initPixmap(7, pix, w, _h3, QRect(_w1, _h1 + h2, w2, _h3));
76     initPixmap(8, pix, _w3, _h3, QRect(_w1 + w2, _h1 + h2, _w3, _h3));
77 }
78 
TileSet(const QPixmap & pix,int w1,int h1,int w3,int h3,int x1,int y1,int w2,int h2)79 TileSet::TileSet(const QPixmap &pix, int w1, int h1, int w3, int h3,
80                  int x1, int y1, int w2, int h2)
81     : _w1(w1), _h1(h1), _w3(w3), _h3(h3)
82 {
83     if (pix.isNull())
84         return;
85 
86     int x2 = pix.width() - _w3;
87     int y2 = pix.height() - _h3;
88     int w = w2;
89     while (w < 32 && w2 > 0)
90         w += w2;
91     int h = h2;
92     while (h < 32 && h2 > 0)
93         h += h2;
94 
95     // initialise pixmap array
96     _pixmap.resize(9);
97     initPixmap(0, pix, _w1, _h1, QRect(0, 0, _w1, _h1));
98     initPixmap(1, pix, w, _h1, QRect(x1, 0, w2, _h1));
99     initPixmap(2, pix, _w3, _h1, QRect(x2, 0, _w3, _h1));
100     initPixmap(3, pix, _w1, h, QRect(0, y1, _w1, h2));
101     initPixmap(4, pix, w, h, QRect(x1, y1, w2, h2));
102     initPixmap(5, pix, _w3, h, QRect(x2, y1, _w3, h2));
103     initPixmap(6, pix, _w1, _h3, QRect(0, y2, _w1, _h3));
104     initPixmap(7, pix, w, _h3, QRect(x1, y2, w2, _h3));
105     initPixmap(8, pix, _w3, _h3, QRect(x2, y2, _w3, _h3));
106 }
107 
108 inline bool
bits(TileSet::Tiles flags,TileSet::Tiles testFlags)109 bits(TileSet::Tiles flags, TileSet::Tiles testFlags)
110 {
111     return (flags & testFlags) == testFlags;
112 }
113 
114 void
render(const QRect & r,QPainter * p,Tiles t) const115 TileSet::render(const QRect &r, QPainter *p, Tiles t) const
116 {
117     // check initialization
118     if(_pixmap.size() < 9)
119         return;
120 
121     int x0, y0, w, h;
122     r.getRect(&x0, &y0, &w, &h);
123 
124     // calculate pixmaps widths
125     qreal wRatio(qreal(_w1) / qreal(_w1 + _w3));
126     int wLeft = (t&Right) ? qMin(_w1, int(w * wRatio)) : _w1;
127     int wRight = (t&Left) ? qMin(_w3, int(w * (1.0 - wRatio))) : _w3;
128 
129     // calculate pixmap heights
130     qreal hRatio(qreal(_h1) / qreal(_h1 + _h3));
131     int hTop = (t & Bottom) ? qMin(_h1, int(h * hRatio)) : _h1;
132     int hBottom = (t & Top) ? qMin(_h3, int(h * (1.0 - hRatio))) : _h3;
133 
134     // calculate corner locations
135 
136     // maybe one should make the following two lines depend on
137     // what tilesets are selected. Would be more logical, but would
138     // probably break code all over the place ...
139     w -= wLeft + wRight;
140     h -= hTop + hBottom;
141     int x1 = x0 + wLeft;
142     int x2 = x1 + w;
143     int y1 = y0 + hTop;
144     int y2 = y1 + h;
145 
146     // corner
147     if (bits(t, Top | Left))
148         p->drawPixmap(x0, y0, _pixmap.at(0), 0, 0, wLeft, hTop);
149     if (bits(t, Top | Right))
150         p->drawPixmap(x2, y0, _pixmap.at(2), _w3 - wRight, 0, wRight, hTop);
151     if (bits(t, Bottom | Left))
152         p->drawPixmap(x0, y2, _pixmap.at(6), 0, _h3 - hBottom, wLeft, hBottom);
153     if (bits(t, Bottom | Right))
154         p->drawPixmap(x2, y2, _pixmap.at(8), _w3 - wRight, _h3 - hBottom,
155                       wRight, hBottom);
156 
157     // top and bottom
158     if (w > 0) {
159         if (t & Top)
160             p->drawTiledPixmap(x1, y0, w, hTop, _pixmap.at(1));
161         if (t & Bottom) {
162             p->drawTiledPixmap(x1, y2, w, hBottom, _pixmap.at(7),
163                                0, _h3 - hBottom);
164         }
165     }
166 
167     // left and right
168     if (h > 0) {
169         if (t & Left)
170             p->drawTiledPixmap(x0, y1, wLeft, h, _pixmap.at(3));
171         if (t & Right) {
172             p->drawTiledPixmap(x2, y1, wRight, h, _pixmap.at(5),
173                                _w3 - wRight, 0);
174         }
175     }
176 
177     // center
178     if ((t & Center) && h > 0 && w > 0) {
179         p->drawTiledPixmap(x1, y1, w, h, _pixmap.at(4));
180     }
181 }
182