1
/***************************************************************************
2
* kgrtheme.cpp - description *
3
* ------------------- *
4
* begin : Wed Jul 7 2007 *
5
* Copyright 2002 Marco Krüger <grisuji@gmx.de> *
6
* Copyright 2002 Ian Wadham <ianw2@optusnet.com.au> *
7
* Copyright 2007 Luciano Montanaro <mikelima@cirulla.net> *
8
***************************************************************************/
10
/***************************************************************************
12
* This program is free software; you can redistribute it and/or modify *
13
* it under the terms of the GNU General Public License as published by *
14
* the Free Software Foundation; either version 2 of the License, or *
15
* (at your option) any later version. *
17
***************************************************************************/
22
#include <KConfigGroup>
28
KGrTheme::KGrTheme (const QString &systemDataDir) :
29
themeDataDir (systemDataDir + "../theme/"),
34
KConfigGroup group (KGlobal::config(), "Debugging");
36
// Initialize theme lookup table
37
for (int i = 0; i < TileTypeCount; ++i) {
43
KGrTheme::~ KGrTheme()
50
bool KGrTheme::load (const QString& themeFilepath)
52
kDebug() << "New Theme -" << themeFilepath;
53
if (!m_themeFilepath.isEmpty() && (themeFilepath == m_themeFilepath)) {
54
kDebug() << "NO CHANGE OF THEME ...";
55
return true; // No change of theme.
58
KConfig theme (themeFilepath, KConfig::SimpleConfig); // Read graphics config.
59
KConfigGroup group = theme.group ("KDEGameTheme");
61
QString f = group.readEntry ("Set", "");
62
if (f.endsWith (".svg") || f.endsWith (".svgz")) {
63
// Load a SVG theme (KGoldrunner 3+ and KDE 4+).
64
QString path = themeFilepath.left (themeFilepath.lastIndexOf ("/") + 1) + f;
65
if (! path.isEmpty()) {
68
// The theme may have multiple backgrounds, called
69
// background0...backgroundN or just one background, called
70
// background0 or simply background.
71
QString backgroundPattern ("background%1");
73
while (svgSet.elementExists (backgroundPattern.arg (numBackgrounds))) {
76
if (numBackgrounds == 0) {
77
if (svgSet.elementExists ("background")) {
83
f = group.readEntry ("Actors", "default/actors.svg");
84
if (f.endsWith (".svg") || f.endsWith (".svgz"))
86
QString path = themeFilepath.left (themeFilepath.lastIndexOf ("/") + 1) + f;
89
svgActors.load (path);
94
return false; // Not SVG: old XPM themes no longer supported.
97
// Check if the theme asks us to draw a border and set the specified color.
98
themeDrawBorder = group.readEntry ("DrawCanvasBorder", 0);
100
// The border color (default black) is also used as the view's background
101
// color, to soften the ugly look of empty rectangles during repainting.
102
QString themeBorderColor = group.readEntry ("BorderColor", "#000000");
103
if (! themeBorderColor.isEmpty()) {
104
m_borderColor.setNamedColor (themeBorderColor);
107
// If specified, also set the title color.
108
QString themeTextColor = group.readEntry ("TextColor", "");
109
if (! themeTextColor.isEmpty()) {
110
m_textColor.setNamedColor (themeTextColor);
113
// Save the user's selected theme in KDE's config-group data for the game.
114
KConfigGroup gameGroup (KGlobal::config(), "KDEGame");
115
gameGroup.writeEntry ("ThemeFilepath", themeFilepath);
116
gameGroup.sync(); // Ensure that the entry goes to disk.
117
m_themeFilepath = themeFilepath;
125
QPixmap KGrTheme::background (unsigned int width, unsigned int height,
126
unsigned int variant)
128
variant %= numBackgrounds;
132
//for (int i = 0; i < 5; i++) {
133
if ((width != 0) && (height != 0) && (numBackgrounds > 0))
135
if (svgSet.elementExists(QString("background%1").arg(variant)))
137
pixmap = loadGraphic(QSize(width, height), QString("background%1").arg(variant),svgSet);
139
else if (svgSet.elementExists("background"))
141
pixmap = loadGraphic(QSize(width, height), "background",svgSet);
146
qDebug() << "background took" << t.elapsed() << "ms to render";
150
QList<QPixmap> KGrTheme::hero (unsigned int size)
152
QList<QPixmap> frames;
154
for (int i = 1; i <= 36; i++)
156
frames << loadGraphic(QSize(size, size), QString("hero_%1").arg(i), svgActors);
162
QList<QPixmap> KGrTheme::enemy (unsigned int size)
164
QList<QPixmap> frames;
165
for (int i = 1; i <= 36; i++)
167
frames << loadGraphic(QSize(size, size), QString("enemy_%1").arg(i), svgActors);
169
for (int i = 1; i <= 36; i++)
171
frames << loadGraphic(QSize(size, size), QString("gold_enemy_%1").arg(i), svgActors);
177
QList<QPixmap> KGrTheme::tiles (unsigned int size)
181
// Create a list of rendered tiles. The tiles must be appended in the
182
// same order they appear in the TileType enum.
183
// While creating the tiles, count the variants, and fill the offset and
186
QVector< QString > tileNames;
189
// These tiles can never have variants
190
tileNames << "empty" << "hidden_ladder" << "false_brick";
191
foreach (const QString &name, tileNames) {
192
list.append (loadGraphic(QSize(size, size), name, svgSet));
198
// These tiles, used in the game-editor, come from the Actors SVG file
200
tileNames << "hero_1" << "enemy_1";
201
foreach (const QString &name, tileNames) {
202
list.append (loadGraphic(QSize(size, size), name, svgActors));
208
// These tiles can have variants
210
tileNames << "gold" << "bar" << "ladder" << "concrete" << "brick";
211
foreach (const QString &name, tileNames) {
213
QString tileNamePattern = name + "-%1";
214
while (svgSet.elementExists (tileNamePattern.arg (tileCount))) {
215
kDebug() << tileNamePattern.arg(tileCount);
216
list.append (loadGraphic( QSize(size, size), tileNamePattern.arg(tileCount), svgSet));
220
counts[i] = tileCount;
222
list.append (loadGraphic(QSize(size, size), name, svgSet));
225
offsets[i] = offsets[i - 1] + counts[i - 1];
229
// Add SVG versions of blasted bricks.
230
QString brickPattern("brick_%1");
231
for (int j = 1; j <= 9; ++j) {
232
list.append (loadGraphic(QSize(size, size), brickPattern.arg(j), svgSet));
234
offsets[i] = offsets[i - 1] + counts[i - 1];
240
QList< QPixmap > KGrTheme::namedTiles (QList< QString > names,
243
QList< QPixmap > list;
245
foreach (const QString &name, names) {
246
if (svgSet.elementExists (name)) {
247
list.append (loadGraphic(QSize(size, size), name, svgSet));
248
kDebug() << name << "found";
252
kDebug() << name << "NOT found, exiting";
257
kDebug() << "namedTiles() tiles:" << list.size();
262
QList< QPixmap > KGrTheme::displayTiles (unsigned int size)
264
QList< QString > tileNames;
266
tileNames << "display-left" << "display-centre" << "display-right";
268
return namedTiles (tileNames, size);
271
QList< QPixmap > KGrTheme::frameTiles (unsigned int size)
273
QList< QString > tileNames;
275
tileNames << "frame-topleft" << "frame-top" << "frame-topright" <<
276
"frame-left" << "frame-fill" << "frame-right" <<
277
"frame-bottomleft" << "frame-bottom" << "frame-bottomright";
279
return namedTiles (tileNames, size);
282
QPixmap KGrTheme::loadGraphic(const QSize & size, const QString & strName, KSvgRenderer &Svg, double boundsAdjust)
286
kWarning() << "Cannot load graphics until pixmap cache object has been created!";
292
QString strTagName = QString("%1|%2|%3x%4").arg(m_themeFilepath).arg(strName).arg(size.width()).arg(size.height());
294
if (! pixCache->find(strTagName, pix))
296
// kWarning() << "Element" << strName << "Not in cache, rendering from SVG";
297
if (! Svg.elementExists(strName))
299
kWarning() << "Element" << strName << "Not found in SVG document - unable to load!";
304
pix.fill(QColor(0,0,0,0));
307
QRectF bounds(0,0, size.width(), size.height());
308
bounds.adjust(-boundsAdjust, -boundsAdjust, boundsAdjust, boundsAdjust);
309
Svg.render(&p, strName, bounds);
311
pixCache->insert(strTagName, pix);
318
void KGrTheme::createPixCache()
323
QString strCacheName = m_themeFilepath.mid(m_themeFilepath.lastIndexOf('/') + 1);
324
strCacheName = strCacheName.left(strCacheName.indexOf('.'));
325
kWarning() << strCacheName;
327
pixCache = new KPixmapCache(QString("kgoldrunner-pixmap-cache-") + strCacheName);
328
pixCache->setRemoveEntryStrategy(KPixmapCache::RemoveLeastRecentlyUsed);
329
pixCache->setCacheLimit(1024 * 3); // set cache size to 3 MB PER THEME
331
// Check the file modification time of the theme. If it is newer than the pixmap cache
332
// timestamp then we invalidate the entire cache for this theme only.
333
QFileInfo fi(m_themeFilepath);
334
if (fi.lastModified().toTime_t() != pixCache->timestamp())
336
kWarning() << "Pixmap cache for theme '" << strCacheName << "' is outdated; invalidating cache.";
338
pixCache->setTimestamp(fi.lastModified().toTime_t());