Qt 4.8
qsvgiconengine.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the plugins of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 #include "qsvgiconengine.h"
42 
43 #ifndef QT_NO_SVGRENDERER
44 
45 #include "qpainter.h"
46 #include "qpixmap.h"
47 #include "qsvgrenderer.h"
48 #include "qpixmapcache.h"
49 #include "qstyle.h"
50 #include "qapplication.h"
51 #include "qstyleoption.h"
52 #include "qfileinfo.h"
53 #include <QAtomicInt>
54 #include "qdebug.h"
55 
57 
59 {
60 public:
62  : svgBuffers(0), addedPixmaps(0)
63  { stepSerialNum(); }
64 
66  { delete addedPixmaps; delete svgBuffers; }
67 
68  static int hashKey(QIcon::Mode mode, QIcon::State state)
69  { return (((mode)<<4)|state); }
70 
71  QString pmcKey(const QSize &size, QIcon::Mode mode, QIcon::State state)
72  { return QLatin1String("$qt_svgicon_")
74  + QString::number((((((size.width()<<11)|size.height())<<11)|mode)<<4)|state, 16); }
75 
78 
79  void loadDataForModeAndState(QSvgRenderer *renderer, QIcon::Mode mode, QIcon::State state);
80 
84  int serialNum;
86 };
87 
89 
90 static inline int pmKey(const QSize &size, QIcon::Mode mode, QIcon::State state)
91 {
92  return ((((((size.width()<<11)|size.height())<<11)|mode)<<4)|state);
93 }
94 
97 {
98 }
99 
101  : QIconEngineV2(other), d(new QSvgIconEnginePrivate)
102 {
103  d->svgFiles = other.d->svgFiles;
104  if (other.d->svgBuffers)
106  if (other.d->addedPixmaps)
108 }
109 
110 
112 {
113 }
114 
115 
117  QIcon::State state)
118 {
119  if (d->addedPixmaps) {
120  QPixmap pm = d->addedPixmaps->value(d->hashKey(mode, state));
121  if (!pm.isNull() && pm.size() == size)
122  return size;
123  }
124 
125  QPixmap pm = pixmap(size, mode, state);
126  if (pm.isNull())
127  return QSize();
128  return pm.size();
129 }
130 
132 {
133  QByteArray buf;
134  if (svgBuffers) {
135  buf = svgBuffers->value(hashKey(mode, state));
136  if (buf.isEmpty())
137  buf = svgBuffers->value(hashKey(QIcon::Normal, QIcon::Off));
138  }
139  if (!buf.isEmpty()) {
140 #ifndef QT_NO_COMPRESS
141  buf = qUncompress(buf);
142 #endif
143  renderer->load(buf);
144  } else {
145  QString svgFile = svgFiles.value(hashKey(mode, state));
146  if (svgFile.isEmpty())
147  svgFile = svgFiles.value(hashKey(QIcon::Normal, QIcon::Off));
148  if (!svgFile.isEmpty())
149  renderer->load(svgFile);
150  }
151 }
152 
154  QIcon::State state)
155 {
156  QPixmap pm;
157 
158  QString pmckey(d->pmcKey(size, mode, state));
159  if (QPixmapCache::find(pmckey, pm))
160  return pm;
161 
162  if (d->addedPixmaps) {
163  pm = d->addedPixmaps->value(d->hashKey(mode, state));
164  if (!pm.isNull() && pm.size() == size)
165  return pm;
166  }
167 
168  QSvgRenderer renderer;
169  d->loadDataForModeAndState(&renderer, mode, state);
170  if (!renderer.isValid())
171  return pm;
172 
173  QSize actualSize = renderer.defaultSize();
174  if (!actualSize.isNull())
175  actualSize.scale(size, Qt::KeepAspectRatio);
176 
178  img.fill(0x00000000);
179  QPainter p(&img);
180  renderer.render(&p);
181  p.end();
182  pm = QPixmap::fromImage(img);
183  QStyleOption opt(0);
185  QPixmap generated = QApplication::style()->generatedIconPixmap(mode, pm, &opt);
186  if (!generated.isNull())
187  pm = generated;
188 
189  if (!pm.isNull())
190  QPixmapCache::insert(pmckey, pm);
191 
192  return pm;
193 }
194 
195 
197  QIcon::State state)
198 {
199  if (!d->addedPixmaps)
201  d->stepSerialNum();
202  d->addedPixmaps->insert(d->hashKey(mode, state), pixmap);
203 }
204 
205 
207  QIcon::Mode mode, QIcon::State state)
208 {
209  if (!fileName.isEmpty()) {
210  QString abs = fileName;
211  if (fileName.at(0) != QLatin1Char(':'))
212  abs = QFileInfo(fileName).absoluteFilePath();
213  if (abs.endsWith(QLatin1String(".svg"), Qt::CaseInsensitive)
214 #ifndef QT_NO_COMPRESS
215  || abs.endsWith(QLatin1String(".svgz"), Qt::CaseInsensitive)
216  || abs.endsWith(QLatin1String(".svg.gz"), Qt::CaseInsensitive))
217 #endif
218  {
219  QSvgRenderer renderer(abs);
220  if (renderer.isValid()) {
221  d->stepSerialNum();
222  d->svgFiles.insert(d->hashKey(mode, state), abs);
223  }
224  } else {
225  QPixmap pm(abs);
226  if (!pm.isNull())
227  addPixmap(pm, mode, state);
228  }
229  }
230 }
231 
232 void QSvgIconEngine::paint(QPainter *painter, const QRect &rect,
233  QIcon::Mode mode, QIcon::State state)
234 {
235  painter->drawPixmap(rect, pixmap(rect.size(), mode, state));
236 }
237 
239 {
240  return QLatin1String("svg");
241 }
242 
244 {
245  return new QSvgIconEngine(*this);
246 }
247 
248 
250 {
251  d = new QSvgIconEnginePrivate;
253 
254  if (in.version() >= QDataStream::Qt_4_4) {
255  int isCompressed;
256  QHash<int, QString> fileNames; // For memoryoptimization later
257  in >> fileNames >> isCompressed >> *d->svgBuffers;
258 #ifndef QT_NO_COMPRESS
259  if (!isCompressed) {
260  foreach(int key, d->svgBuffers->keys())
261  d->svgBuffers->insert(key, qCompress(d->svgBuffers->value(key)));
262  }
263 #else
264  if (isCompressed) {
265  qWarning("QSvgIconEngine: Can not decompress SVG data");
266  d->svgBuffers->clear();
267  }
268 #endif
269  int hasAddedPixmaps;
270  in >> hasAddedPixmaps;
271  if (hasAddedPixmaps) {
273  in >> *d->addedPixmaps;
274  }
275  }
276  else {
277  QPixmap pixmap;
279  uint mode;
280  uint state;
281  int num_entries;
282 
283  in >> data;
284  if (!data.isEmpty()) {
285 #ifndef QT_NO_COMPRESS
286  data = qUncompress(data);
287 #endif
288  if (!data.isEmpty())
290  }
291  in >> num_entries;
292  for (int i=0; i<num_entries; ++i) {
293  if (in.atEnd())
294  return false;
295  in >> pixmap;
296  in >> mode;
297  in >> state;
298  // The pm list written by 4.3 is buggy and/or useless, so ignore.
299  //addPixmap(pixmap, QIcon::Mode(mode), QIcon::State(state));
300  }
301  }
302 
303  return true;
304 }
305 
306 
308 {
309  if (out.version() >= QDataStream::Qt_4_4) {
310  int isCompressed = 0;
311 #ifndef QT_NO_COMPRESS
312  isCompressed = 1;
313 #endif
314  QHash<int, QByteArray> svgBuffers;
315  if (d->svgBuffers)
316  svgBuffers = *d->svgBuffers;
317  foreach(int key, d->svgFiles.keys()) {
318  QByteArray buf;
319  QFile f(d->svgFiles.value(key));
320  if (f.open(QIODevice::ReadOnly))
321  buf = f.readAll();
322 #ifndef QT_NO_COMPRESS
323  buf = qCompress(buf);
324 #endif
325  svgBuffers.insert(key, buf);
326  }
327  out << d->svgFiles << isCompressed << svgBuffers;
328  if (d->addedPixmaps)
329  out << (int)1 << *d->addedPixmaps;
330  else
331  out << (int)0;
332  }
333  else {
334  QByteArray buf;
335  if (d->svgBuffers)
337  if (buf.isEmpty()) {
339  if (!svgFile.isEmpty()) {
340  QFile f(svgFile);
341  if (f.open(QIODevice::ReadOnly))
342  buf = f.readAll();
343  }
344  }
345 #ifndef QT_NO_COMPRESS
346  buf = qCompress(buf);
347 #endif
348  out << buf;
349  // 4.3 has buggy handling of added pixmaps, so don't write any
350  out << (int)0;
351  }
352  return true;
353 }
354 
356 
357 #endif // QT_NO_SVGRENDERER
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: qstring.cpp:6448
virtual QPixmap generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *opt) const =0
Returns a copy of the given pixmap, styled to conform to the specified iconMode and taking into accou...
QString key() const
Returns a key that identifies this icon engine.
The QPainter class performs low-level painting on widgets and other paint devices.
Definition: qpainter.h:86
double d
Definition: qnumeric_p.h:62
static int pmKey(const QSize &size, QIcon::Mode mode, QIcon::State state)
static QPixmap fromImage(const QImage &image, Qt::ImageConversionFlags flags=Qt::AutoColor)
Converts the given image to a pixmap using the specified flags to control the conversion.
Definition: qpixmap.cpp:2197
QString pmcKey(const QSize &size, QIcon::Mode mode, QIcon::State state)
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
QSize size() const
Returns the size of the pixmap.
Definition: qpixmap.cpp:661
void clear()
Removes all items from the hash.
Definition: qhash.h:574
QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state)
Returns the actual size of the icon the engine provides for the requested size, mode and state...
const QChar at(int i) const
Returns the character at the given index position in the string.
Definition: qstring.h:698
Q_CORE_EXPORT QByteArray qUncompress(const uchar *data, int nbytes)
The QAtomicInt class provides platform-independent atomic operations on integers. ...
Definition: qatomic.h:55
bool open(OpenMode flags)
Opens the file using OpenMode mode, returning true if successful; otherwise false.
Definition: qfile.cpp:1064
static QAtomicInt lastSerialNum
bool atEnd() const
Returns true if the I/O device has reached the end position (end of the stream or file) or if there i...
void fill(uint pixel)
Fills the entire image with the given pixelValue.
Definition: qimage.cpp:2032
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
State
This enum describes the state for which a pixmap is intended to be used.
Definition: qicon.h:64
QString absoluteFilePath() const
Returns an absolute path including the file name.
Definition: qfileinfo.cpp:534
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
static QPalette palette()
Returns the application palette.
static QStyle * style()
Returns the application&#39;s style object.
The QString class provides a Unicode character string.
Definition: qstring.h:83
bool read(QDataStream &in)
Reads icon engine contents from the QDataStream in.
void addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon::State state)
Called by QIcon::addPixmap().
const T value(const Key &key) const
Returns the value associated with the key.
Definition: qhash.h:606
static QPixmap * find(const QString &key)
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition: qhash.h:753
static int hashKey(QIcon::Mode mode, QIcon::State state)
int width() const
Returns the width.
Definition: qsize.h:126
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
The QStyleOption class stores the parameters used by QStyle functions.
Definition: qstyleoption.h:67
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
bool isValid() const
Returns true if there is a valid current document; otherwise returns false.
QSize size() const
Returns the size of the rectangle.
Definition: qrect.h:309
Mode
This enum type describes the mode for which a pixmap is intended to be used.
Definition: qicon.h:63
Q_CORE_EXPORT void qWarning(const char *,...)
The QImage class provides a hardware-independent image representation that allows direct access to th...
Definition: qimage.h:87
static const char * data(const QByteArray &arr)
unsigned int uint
Definition: qglobal.h:996
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal...
Definition: qstring.h:654
QSize defaultSize() const
Returns the default size of the document contents.
QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state)
Returns the icon as a pixmap with the required size, mode, and state.
void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state)
Uses the given painter to paint the icon with the required mode and state into the rectangle rect...
The QIconEngineV2 class provides an abstract base class for QIcon renderers.
Definition: qiconengine.h:73
int version() const
Returns the version number of the data serialization format.
Definition: qdatastream.h:212
int fetchAndAddRelaxed(int valueToAdd)
Atomic fetch-and-add.
QPalette palette
the palette that should be used when painting the control
Definition: qstyleoption.h:92
Q_CORE_EXPORT QByteArray qCompress(const uchar *data, int nbytes, int compressionLevel=-1)
QIconEngineV2 * clone() const
Returns a clone of this icon engine.
QString & append(QChar c)
Definition: qstring.cpp:1777
The QSvgRenderer class is used to draw the contents of SVG files onto paint devices.
Definition: qsvgrenderer.h:64
The QFile class provides an interface for reading from and writing to files.
Definition: qfile.h:65
The QSharedData class is a base class for shared data objects.
Definition: qshareddata.h:56
QHash< int, QPixmap > * addedPixmaps
void loadDataForModeAndState(QSvgRenderer *renderer, QIcon::Mode mode, QIcon::State state)
static bool insert(const QString &key, const QPixmap &pixmap)
Inserts a copy of the pixmap pixmap associated with the key into the cache.
void render(QPainter *p)
Renders the current document, or the current frame of an animated document, using the given painter...
bool load(const QString &filename)
Loads the SVG file specified by filename, returning true if the content was successfully parsed; othe...
int height() const
Returns the height.
Definition: qsize.h:129
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
QByteArray readAll()
Reads all available data from the device, and returns it as a QByteArray.
Definition: qiodevice.cpp:1025
QHash< int, QString > svgFiles
void addFile(const QString &fileName, const QSize &size, QIcon::Mode mode, QIcon::State state)
Called by QIcon::addFile().
The QPixmap class is an off-screen image representation that can be used as a paint device...
Definition: qpixmap.h:71
void scale(int w, int h, Qt::AspectRatioMode mode)
Scales the size to a rectangle with the given width and height, according to the specified mode: ...
Definition: qsize.h:138
bool isNull() const
Returns true if both the width and height is 0; otherwise returns false.
Definition: qsize.h:117
void drawPixmap(const QRectF &targetRect, const QPixmap &pixmap, const QRectF &sourceRect)
Draws the rectangular portion source of the given pixmap into the given target in the paint device...
Definition: qpainter.cpp:5619
bool isEmpty() const
Returns true if the byte array has size 0; otherwise returns false.
Definition: qbytearray.h:421
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:53
The QDataStream class provides serialization of binary data to a QIODevice.
Definition: qdatastream.h:71
QSharedDataPointer< QSvgIconEnginePrivate > d
bool isNull() const
Returns true if this is a null pixmap; otherwise returns false.
Definition: qpixmap.cpp:615
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
Definition: qstring.cpp:3796
The QFileInfo class provides system-independent file information.
Definition: qfileinfo.h:60
QHash< int, QByteArray > * svgBuffers
static QString fileName(const QString &fileUrl)
QList< Key > keys() const
Returns a list containing all the keys in the hash, in an arbitrary order.
Definition: qhash.h:648
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
bool end()
Ends painting.
Definition: qpainter.cpp:1929
bool write(QDataStream &out) const
Writes the contents of this engine to the QDataStream out.