~keith-penguin/kdegames/trunk

« back to all changes in this revision

Viewing changes to kmines/renderer.cpp

  • Committer: Keith Worrell
  • Date: 2009-03-18 05:35:28 UTC
  • Revision ID: keith.worrell@gmail.com-20090318053528-mx6x9c0ngmg0kg6p
imported project

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    Copyright 2007 Dmitry Suzdalev <dimsuz@gmail.com>
 
3
 
 
4
    This program is free software; you can redistribute it and/or modify
 
5
    it under the terms of the GNU General Public License as published by
 
6
    the Free Software Foundation; either version 2 of the License, or
 
7
    (at your option) any later version.
 
8
 
 
9
    This program is distributed in the hope that it will be useful,
 
10
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
    GNU General Public License for more details.
 
13
 
 
14
    You should have received a copy of the GNU General Public License
 
15
    along with this program; if not, write to the Free Software
 
16
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 
17
*/
 
18
 
 
19
#include "renderer.h"
 
20
 
 
21
#include <QPainter>
 
22
 
 
23
#include <KSvgRenderer>
 
24
#include <KGameTheme>
 
25
#include <kpixmapcache.h>
 
26
 
 
27
#include "settings.h"
 
28
 
 
29
QString KMinesRenderer::elementToSvgId( SvgElement e ) const
 
30
{
 
31
    switch(e)
 
32
    {
 
33
        case KMinesRenderer::CellUp:
 
34
            return "cell_up";
 
35
        case KMinesRenderer::CellDown:
 
36
            return "cell_down";
 
37
        case KMinesRenderer::Flag:
 
38
            return "flag";
 
39
        case KMinesRenderer::Question:
 
40
            return "question";
 
41
        case KMinesRenderer::Digit1:
 
42
            return "arabicOne";
 
43
        case KMinesRenderer::Digit2:
 
44
            return "arabicTwo";
 
45
        case KMinesRenderer::Digit3:
 
46
            return "arabicThree";
 
47
        case KMinesRenderer::Digit4:
 
48
            return "arabicFour";
 
49
        case KMinesRenderer::Digit5:
 
50
            return "arabicFive";
 
51
        case KMinesRenderer::Digit6:
 
52
            return "arabicSix";
 
53
        case KMinesRenderer::Digit7:
 
54
            return "arabicSeven";
 
55
        case KMinesRenderer::Digit8:
 
56
            return "arabicEight";
 
57
        case KMinesRenderer::Mine:
 
58
            return "mine";
 
59
        case KMinesRenderer::ExplodedMine:
 
60
            return QString(); // dummy. shouldn't be called
 
61
        case KMinesRenderer::Explosion:
 
62
            return "explosion";
 
63
        case KMinesRenderer::Error:
 
64
            return "error";
 
65
        case KMinesRenderer::Hint:
 
66
            return "hint";
 
67
        case KMinesRenderer::BorderEdgeNorth:
 
68
            return "border.edge.north";
 
69
        case KMinesRenderer::BorderEdgeSouth:
 
70
            return "border.edge.south";
 
71
        case KMinesRenderer::BorderEdgeEast:
 
72
            return "border.edge.east";
 
73
        case KMinesRenderer::BorderEdgeWest:
 
74
            return "border.edge.west";
 
75
        case KMinesRenderer::BorderOutsideCornerNE:
 
76
            return "border.outsideCorner.ne";
 
77
        case KMinesRenderer::BorderOutsideCornerNW:
 
78
            return "border.outsideCorner.nw";
 
79
        case KMinesRenderer::BorderOutsideCornerSW:
 
80
            return "border.outsideCorner.sw";
 
81
        case KMinesRenderer::BorderOutsideCornerSE:
 
82
            return "border.outsideCorner.se";
 
83
        case KMinesRenderer::NumElements:
 
84
            return QString();
 
85
    }
 
86
    return QString();
 
87
}
 
88
 
 
89
KMinesRenderer* KMinesRenderer::self()
 
90
{
 
91
    static KMinesRenderer instance;
 
92
    return &instance;
 
93
}
 
94
 
 
95
KMinesRenderer::KMinesRenderer()
 
96
    : m_cellSize(0)
 
97
{
 
98
    m_renderer = new KSvgRenderer();
 
99
    m_cache = new KPixmapCache("kmines-cache");
 
100
    m_cache->setCacheLimit(3*1024);
 
101
 
 
102
    if(!loadTheme( Settings::theme() ))
 
103
        kDebug() << "Failed to load any game theme!";
 
104
}
 
105
 
 
106
bool KMinesRenderer::loadTheme( const QString& themeName )
 
107
{
 
108
    // variable saying whether to discard old cache upon successful new theme loading
 
109
    // we won't discard it if m_currentTheme is empty meaning that
 
110
    // this is the first time loadTheme() is called
 
111
    // (i.e. during startup) as we want to pick the cache from disc
 
112
    bool discardCache = !m_currentTheme.isEmpty();
 
113
 
 
114
    if( !m_currentTheme.isEmpty() && m_currentTheme == themeName )
 
115
    {
 
116
        kDebug() << "Notice: not loading the same theme";
 
117
        return true; // this is not an error
 
118
    }
 
119
 
 
120
    m_currentTheme = themeName;
 
121
 
 
122
    KGameTheme theme;
 
123
    if ( themeName.isEmpty() || !theme.load( themeName ) )
 
124
    {
 
125
        kDebug()<< "Failed to load theme" << Settings::theme();
 
126
        kDebug() << "Trying to load default";
 
127
        if(!theme.loadDefault())
 
128
            return false;
 
129
        // in this case we need to discard any previously cached theme:
 
130
        // we loading default
 
131
        discardCache = true;
 
132
        // set it to something - not be empty - so we
 
133
        // do discard cache on next loadTheme
 
134
        // (see discardCache above)
 
135
        m_currentTheme = "default";
 
136
        Settings::setTheme("themes/default.desktop");
 
137
    }
 
138
 
 
139
    bool res = m_renderer->load( theme.graphics() );
 
140
    kDebug() << "loading" << theme.graphics();
 
141
    if ( !res )
 
142
        return false;
 
143
 
 
144
    if(discardCache)
 
145
    {
 
146
        kDebug() << "discarding cache";
 
147
        m_cache->discard();
 
148
    }
 
149
 
 
150
    return true;
 
151
}
 
152
 
 
153
QPixmap KMinesRenderer::backgroundPixmap( const QSize& size ) const
 
154
{
 
155
    QPixmap bkgnd;
 
156
    QString cacheName = QString("mainWidget%1x%2").arg(size.width()).arg(size.height());
 
157
    if(!m_cache->find( cacheName, bkgnd ))
 
158
    {
 
159
        kDebug() << "re-rendering bkgnd";
 
160
        bkgnd = QPixmap(size);
 
161
        bkgnd.fill(Qt::transparent);
 
162
        QPainter p(&bkgnd);
 
163
        m_renderer->render(&p, "mainWidget");
 
164
        p.end();
 
165
        m_cache->insert(cacheName, bkgnd);
 
166
        kDebug() << "cache size:" << m_cache->size() << "kb";
 
167
    }
 
168
    return bkgnd;
 
169
}
 
170
 
 
171
KMinesRenderer::~KMinesRenderer()
 
172
{
 
173
    delete m_renderer;
 
174
    delete m_cache;
 
175
}
 
176
 
 
177
#define RENDER_SVG_ELEMENT(SVG_ID)                      \
 
178
    p.begin( &pix );                                    \
 
179
    m_renderer->render( &p, elementToSvgId(SVG_ID) );   \
 
180
    p.end();
 
181
 
 
182
QPixmap KMinesRenderer::pixmapForCellState( KMinesState::CellState state ) const
 
183
{
 
184
    QPainter p;
 
185
    switch(state)
 
186
    {
 
187
        case KMinesState::Released:
 
188
        {
 
189
            QPixmap pix;
 
190
            QString cacheName = elementToSvgId(CellUp)+QString::number(m_cellSize);
 
191
            if(!m_cache->find(cacheName, pix))
 
192
            {
 
193
//                kDebug() << "putting" << cacheName << "to cache";
 
194
                pix = QPixmap(m_cellSize, m_cellSize);
 
195
                pix.fill( Qt::transparent);
 
196
                RENDER_SVG_ELEMENT(CellUp);
 
197
                m_cache->insert(cacheName, pix);
 
198
            }
 
199
            return pix;
 
200
        }
 
201
        case KMinesState::Pressed:
 
202
        case KMinesState::Revealed:// i.e. revealed & digit=0 case
 
203
        {
 
204
            QPixmap pix;
 
205
            QString cacheName = elementToSvgId(CellDown)+QString::number(m_cellSize);
 
206
            if(!m_cache->find(cacheName, pix))
 
207
            {
 
208
//                kDebug() << "putting" << cacheName << "to cache";
 
209
                pix = QPixmap(m_cellSize, m_cellSize);
 
210
                pix.fill( Qt::transparent);
 
211
                RENDER_SVG_ELEMENT(CellDown);
 
212
                m_cache->insert(cacheName, pix);
 
213
            }
 
214
            return pix;
 
215
        }
 
216
        case KMinesState::Questioned:
 
217
        {
 
218
            QPixmap pix;
 
219
            QString cacheName = elementToSvgId(Question)+QString::number(m_cellSize);
 
220
            if(!m_cache->find(cacheName, pix))
 
221
            {
 
222
//                kDebug() << "putting" << cacheName << "to cache";
 
223
                // question (on top of cellup)
 
224
                pix = pixmapForCellState( KMinesState::Released );
 
225
                RENDER_SVG_ELEMENT(Question);
 
226
                m_cache->insert(cacheName, pix);
 
227
            }
 
228
            return pix;
 
229
        }
 
230
        case KMinesState::Flagged:
 
231
        {
 
232
            QPixmap pix;
 
233
            QString cacheName = elementToSvgId(Flag)+QString::number(m_cellSize);
 
234
            if(!m_cache->find(cacheName, pix))
 
235
            {
 
236
                // flag (on top of cellup)
 
237
//                kDebug() << "putting" << cacheName << "to cache";
 
238
                pix = pixmapForCellState( KMinesState::Released );
 
239
                RENDER_SVG_ELEMENT(Flag);
 
240
                m_cache->insert(cacheName, pix);
 
241
            }
 
242
            return pix;
 
243
        }
 
244
        case KMinesState::Error:
 
245
        {
 
246
            QPixmap pix;
 
247
            QString cacheName = elementToSvgId(Error)+QString::number(m_cellSize);
 
248
            if(!m_cache->find(cacheName, pix))
 
249
            {
 
250
//                kDebug() << "putting" << cacheName << "to cache";
 
251
                // flag (on top of mine)
 
252
                pix = pixmapMine();
 
253
                RENDER_SVG_ELEMENT(Error);
 
254
                m_cache->insert(cacheName, pix);
 
255
            }
 
256
            return pix;
 
257
        }
 
258
        case KMinesState::Hint:
 
259
        {
 
260
            QPixmap pix;
 
261
            QString cacheName = elementToSvgId(Hint)+QString::number(m_cellSize);
 
262
            if(!m_cache->find(cacheName, pix))
 
263
            {
 
264
//                kDebug() << "putting" << cacheName << "to cache";
 
265
                // hint (on top of cellup)
 
266
                pix = pixmapForCellState( KMinesState::Released );
 
267
                RENDER_SVG_ELEMENT(Hint);
 
268
                m_cache->insert(cacheName, pix);
 
269
            }
 
270
            return pix;
 
271
        }
 
272
        // no default! this way we'll get compiler warnings if
 
273
        // something is forgotten
 
274
    }
 
275
    return QPixmap();
 
276
}
 
277
 
 
278
QPixmap KMinesRenderer::pixmapForDigitElement( int digit ) const
 
279
{
 
280
    KMinesRenderer::SvgElement e;
 
281
    if(digit == 1)
 
282
        e = KMinesRenderer::Digit1;
 
283
    else if(digit == 2)
 
284
        e = KMinesRenderer::Digit2;
 
285
    else if(digit == 3)
 
286
        e = KMinesRenderer::Digit3;
 
287
    else if(digit == 4)
 
288
        e = KMinesRenderer::Digit4;
 
289
    else if(digit == 5)
 
290
        e = KMinesRenderer::Digit5;
 
291
    else if(digit == 6)
 
292
        e = KMinesRenderer::Digit6;
 
293
    else if(digit == 7)
 
294
        e = KMinesRenderer::Digit7;
 
295
    else if(digit == 8)
 
296
        e = KMinesRenderer::Digit8;
 
297
    else
 
298
        return QPixmap();
 
299
 
 
300
    QPainter p;
 
301
    QPixmap pix;
 
302
    QString cacheName = elementToSvgId(e)+QString::number(m_cellSize);
 
303
    if(!m_cache->find(cacheName, pix))
 
304
    {
 
305
//        kDebug() << "putting" << cacheName << "to cache";
 
306
        // digit (on top of celldown)
 
307
        pix = pixmapForCellState( KMinesState::Pressed );
 
308
        RENDER_SVG_ELEMENT(e);
 
309
        m_cache->insert(cacheName, pix);
 
310
    }
 
311
    return pix;
 
312
}
 
313
 
 
314
QPixmap KMinesRenderer::pixmapMine() const
 
315
{
 
316
    QPainter p;
 
317
    QPixmap pix;
 
318
    QString cacheName = elementToSvgId(Mine)+QString::number(m_cellSize);
 
319
    if(!m_cache->find(cacheName, pix))
 
320
    {
 
321
//        kDebug() << "putting" << cacheName << "to cache";
 
322
        // mine (on top of celldown)
 
323
        pix = pixmapForCellState( KMinesState::Pressed );
 
324
        RENDER_SVG_ELEMENT(Mine);
 
325
        m_cache->insert(cacheName, pix);
 
326
    }
 
327
    return pix;
 
328
}
 
329
 
 
330
QPixmap KMinesRenderer::pixmapExplodedMine() const
 
331
{
 
332
    QPainter p;
 
333
    QPixmap pix;
 
334
    QString cacheName = elementToSvgId(Explosion)+QString::number(m_cellSize);
 
335
    if(!m_cache->find(cacheName, pix))
 
336
    {
 
337
//        kDebug() << "putting" << cacheName << "to cache";
 
338
        // mine (on top of celldown)
 
339
        pix = pixmapForCellState( KMinesState::Pressed );
 
340
        RENDER_SVG_ELEMENT(Explosion);
 
341
        RENDER_SVG_ELEMENT(Mine);
 
342
        m_cache->insert(cacheName, pix);
 
343
    }
 
344
    return pix;
 
345
}
 
346
 
 
347
QPixmap KMinesRenderer::pixmapForBorderElement(KMinesState::BorderElement e) const
 
348
{
 
349
    SvgElement svgel = NumElements; // invalid
 
350
    switch(e)
 
351
    {
 
352
        case KMinesState::BorderNorth:
 
353
            svgel = BorderEdgeNorth;
 
354
            break;
 
355
        case KMinesState::BorderSouth:
 
356
            svgel = BorderEdgeSouth;
 
357
            break;
 
358
        case KMinesState::BorderEast:
 
359
            svgel = BorderEdgeEast;
 
360
            break;
 
361
        case KMinesState::BorderWest:
 
362
            svgel = BorderEdgeWest;
 
363
            break;
 
364
        case KMinesState::BorderCornerNW:
 
365
            svgel = BorderOutsideCornerNW;
 
366
            break;
 
367
        case KMinesState::BorderCornerSW:
 
368
            svgel = BorderOutsideCornerSW;
 
369
            break;
 
370
        case KMinesState::BorderCornerNE:
 
371
            svgel = BorderOutsideCornerNE;
 
372
            break;
 
373
        case KMinesState::BorderCornerSE:
 
374
            svgel = BorderOutsideCornerSE;
 
375
            break;
 
376
    }
 
377
 
 
378
    QPainter p;
 
379
    QPixmap pix;
 
380
    QString cacheName = elementToSvgId(svgel)+QString::number(m_cellSize);
 
381
    if(!m_cache->find(cacheName, pix))
 
382
    {
 
383
//        kDebug() << "putting" << cacheName << "to cache";
 
384
        pix = QPixmap(m_cellSize, m_cellSize);
 
385
        pix.fill( Qt::transparent);
 
386
        RENDER_SVG_ELEMENT(svgel);
 
387
        m_cache->insert(cacheName, pix);
 
388
    }
 
389
    return pix;
 
390
}
 
391
 
 
392
void KMinesRenderer::setCellSize( int size )
 
393
{
 
394
    m_cellSize = size;
 
395
}