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 ®ion)
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