1 /*
2     SPDX-FileCopyrightText: 1997 Mathias Mueller <in5y158@public.uni-hamburg.de>
3     SPDX-FileCopyrightText: 2006 Mauricio Piacentini <mauricio@tabuleiro.com>
4 
5     SPDX-License-Identifier: GPL-2.0-or-later
6 */
7 
8 // own
9 #include "kmahjonggbackground.h"
10 
11 // Qt
12 #include <QFile>
13 #include <QImage>
14 #include <QMap>
15 #include <QPainter>
16 #include <QPixmap>
17 #include <QPixmapCache>
18 #include <QSvgRenderer>
19 
20 // KF
21 #include <KConfig>
22 #include <KConfigGroup>
23 #include <KLocalizedString>
24 
25 // LibKMahjongg
26 #include "libkmahjongg_debug.h"
27 
28 class KMahjonggBackgroundPrivate
29 {
30 public:
KMahjonggBackgroundPrivate()31     KMahjonggBackgroundPrivate()
32         : w(1)
33         , h(1)
34         , graphicsLoaded(false)
35         , isPlain(false)
36         , isTiled(true)
37         , isSVG(false)
38     {
39     }
40 
41     QMap<QString, QString> authorproperties;
42     QString pixmapCacheNameFromElementId(const QString & elementid);
43     QPixmap renderBG(short width, short height);
44 
45     QPixmap backgroundPixmap;
46     QBrush backgroundBrush;
47     QString filename;
48     QString graphicspath;
49     short w;
50     short h;
51 
52     QSvgRenderer svg;
53 
54     bool graphicsLoaded;
55     bool isPlain;
56     bool isTiled;
57     bool isSVG;
58 };
59 
KMahjonggBackground()60 KMahjonggBackground::KMahjonggBackground()
61     : d(new KMahjonggBackgroundPrivate)
62 {
63     static bool _inited = false;
64     if (_inited) {
65         return;
66     }
67     _inited = true;
68 }
69 
70 KMahjonggBackground::~KMahjonggBackground() = default;
71 
loadDefault()72 bool KMahjonggBackground::loadDefault()
73 {
74     // Set default background here.
75     QLatin1String idx("egyptian.desktop");
76 
77     QString bgPath = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kmahjongglib/backgrounds/") + idx);
78     qCDebug(LIBKMAHJONGG_LOG) << "Inside LoadDefault(), located background at" << bgPath;
79     if (bgPath.isEmpty()) {
80         return false;
81     }
82     return load(bgPath, 0, 0);
83 }
84 
85 #define kBGVersionFormat 1
86 
load(const QString & file,short width,short height)87 bool KMahjonggBackground::load(const QString & file, short width, short height)
88 {
89     //qCDebug(LIBKMAHJONGG_LOG) << "Background loading";
90     d->isSVG = false;
91 
92     //qCDebug(LIBKMAHJONGG_LOG) << "Attempting to load .desktop at" << file;
93 
94     // verify if it is a valid file first and if we can open it
95     QFile bgfile(file);
96     if (!bgfile.open(QIODevice::ReadOnly)) {
97         return false;
98     }
99     bgfile.close();
100 
101     KConfig bgconfig(file, KConfig::SimpleConfig);
102     KConfigGroup group = bgconfig.group("KMahjonggBackground");
103 
104     d->authorproperties.insert(QStringLiteral("Name"), group.readEntry("Name")); // Returns translated data
105     d->authorproperties.insert(QStringLiteral("Author"), group.readEntry("Author"));
106     d->authorproperties.insert(QStringLiteral("Description"), group.readEntry("Description"));
107     d->authorproperties.insert(QStringLiteral("AuthorEmail"), group.readEntry("AuthorEmail"));
108     //The "Plain" key is set to 1 by the color_plain background.
109     d->isPlain = group.readEntry("Plain", 0) != 0;
110     d->authorproperties.insert(QStringLiteral("Plain"), d->isPlain ? QStringLiteral("1") : QStringLiteral("0"));
111 
112     //Version control
113     int bgversion = group.readEntry("VersionFormat", 0);
114     //Format is increased when we have incompatible changes, meaning that older clients are not able to use the remaining information safely
115     if (bgversion > kBGVersionFormat) {
116         return false;
117     }
118 
119     if (d->isPlain) {
120         //qCDebug(LIBKMAHJONGG_LOG) << "Using plain background";
121         d->graphicspath.clear();
122         d->filename = file;
123         return true;
124     }
125 
126     QString graphName = group.readEntry("FileName");
127 
128     d->graphicspath = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kmahjongglib/backgrounds/") + graphName);
129 
130     qCDebug(LIBKMAHJONGG_LOG) << "Using background at" << d->graphicspath;
131 
132     if (d->graphicspath.isEmpty()) {
133         return false;
134     }
135 
136     if (group.readEntry("Tiled", 0) != 0) {
137         d->w = group.readEntry("Width", 0);
138         d->h = group.readEntry("Height", 0);
139         d->isTiled = true;
140     } else {
141         d->w = width;
142         d->h = height;
143         d->isTiled = false;
144     }
145     d->graphicsLoaded = false;
146     d->filename = file;
147     return true;
148 }
149 
loadGraphics()150 bool KMahjonggBackground::loadGraphics()
151 {
152     if (d->graphicsLoaded || d->isPlain) {
153         return true;
154     }
155 
156     d->svg.load(d->graphicspath);
157     if (d->svg.isValid()) {
158         d->isSVG = true;
159     } else {
160         //qCDebug(LIBKMAHJONGG_LOG) << "could not load svg";
161         return false;
162     }
163     return true;
164 }
165 
sizeChanged(int newW,int newH)166 void KMahjonggBackground::sizeChanged(int newW, int newH)
167 {
168     //in tiled mode we do not care about the whole field size
169     if (d->isTiled || d->isPlain) {
170         return;
171     }
172 
173     if (newW == d->w && newH == d->h) {
174         return;
175     }
176     d->w = newW;
177     d->h = newH;
178 }
179 
pixmapCacheNameFromElementId(const QString & elementid)180 QString KMahjonggBackgroundPrivate::pixmapCacheNameFromElementId(const QString & elementid)
181 {
182     return authorproperties[QStringLiteral("Name")] + elementid + QStringLiteral("W%1H%2").arg(w).arg(h);
183 }
184 
renderBG(short width,short height)185 QPixmap KMahjonggBackgroundPrivate::renderBG(short width, short height)
186 {
187     QImage qiRend(QSize(width, height), QImage::Format_ARGB32_Premultiplied);
188     qiRend.fill(0);
189 
190     if (svg.isValid()) {
191         QPainter p(&qiRend);
192         svg.render(&p);
193     }
194     return QPixmap::fromImage(qiRend);
195 }
196 
getBackground()197 QBrush & KMahjonggBackground::getBackground()
198 {
199     if (d->isPlain) {
200         d->backgroundBrush = QBrush(QPixmap());
201     } else {
202         if (!QPixmapCache::find(d->pixmapCacheNameFromElementId(d->filename), &d->backgroundPixmap)) {
203             d->backgroundPixmap = d->renderBG(d->w, d->h);
204             QPixmapCache::insert(d->pixmapCacheNameFromElementId(d->filename), d->backgroundPixmap);
205         }
206         d->backgroundBrush = QBrush(d->backgroundPixmap);
207     }
208     return d->backgroundBrush;
209 }
210 
path() const211 QString KMahjonggBackground::path() const
212 {
213     return d->filename;
214 }
215 
authorProperty(const QString & key) const216 QString KMahjonggBackground::authorProperty(const QString & key) const
217 {
218     return d->authorproperties[key];
219 }
220