source: trunk/src/plugins/imageformats/svg/qsvgiohandler.cpp@ 890

Last change on this file since 890 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 7.1 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the plugins of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qsvgiohandler.h"
43
44#ifndef QT_NO_SVGRENDERER
45
46#include "qsvgrenderer.h"
47#include "qimage.h"
48#include "qpixmap.h"
49#include "qpainter.h"
50#include "qvariant.h"
51#include "qbuffer.h"
52#include "qdebug.h"
53
54QT_BEGIN_NAMESPACE
55
56class QSvgIOHandlerPrivate
57{
58public:
59 QSvgIOHandlerPrivate(QSvgIOHandler *qq)
60 : q(qq), loaded(false), readDone(false), backColor(Qt::transparent)
61 {}
62
63 bool load(QIODevice *device);
64
65 QSvgIOHandler *q;
66 QSvgRenderer r;
67 QXmlStreamReader xmlReader;
68 QSize defaultSize;
69 QRect clipRect;
70 QSize scaledSize;
71 QRect scaledClipRect;
72 bool loaded;
73 bool readDone;
74 QColor backColor;
75};
76
77
78bool QSvgIOHandlerPrivate::load(QIODevice *device)
79{
80 if (loaded)
81 return true;
82 if (q->format().isEmpty())
83 q->canRead();
84
85 // # The SVG renderer doesn't handle trailing, unrelated data, so we must
86 // assume that all available data in the device is to be read.
87 bool res = false;
88 QBuffer *buf = qobject_cast<QBuffer *>(device);
89 if (buf) {
90 const QByteArray &ba = buf->data();
91 res = r.load(QByteArray::fromRawData(ba.constData() + buf->pos(), ba.size() - buf->pos()));
92 buf->seek(ba.size());
93 } else if (q->format() == "svgz") {
94 res = r.load(device->readAll());
95 } else {
96 xmlReader.setDevice(device);
97 res = r.load(&xmlReader);
98 }
99
100 if (res) {
101 defaultSize = QSize(r.viewBox().width(), r.viewBox().height());
102 loaded = true;
103 }
104
105 return loaded;
106}
107
108
109QSvgIOHandler::QSvgIOHandler()
110 : d(new QSvgIOHandlerPrivate(this))
111{
112
113}
114
115
116QSvgIOHandler::~QSvgIOHandler()
117{
118 delete d;
119}
120
121
122bool QSvgIOHandler::canRead() const
123{
124 if (!device())
125 return false;
126 if (d->loaded && !d->readDone)
127 return true; // Will happen if we have been asked for the size
128
129 QByteArray buf = device()->peek(8);
130 if (buf.startsWith("\x1f\x8b")) {
131 setFormat("svgz");
132 return true;
133 } else if (buf.contains("<?xml") || buf.contains("<svg")) {
134 setFormat("svg");
135 return true;
136 }
137 return false;
138}
139
140
141QByteArray QSvgIOHandler::name() const
142{
143 return "svg";
144}
145
146
147bool QSvgIOHandler::read(QImage *image)
148{
149 if (!d->readDone && d->load(device())) {
150 bool xform = (d->clipRect.isValid() || d->scaledSize.isValid() || d->scaledClipRect.isValid());
151 QSize finalSize = d->defaultSize;
152 QRectF bounds;
153 if (xform && !d->defaultSize.isEmpty()) {
154 bounds = QRectF(QPointF(0,0), QSizeF(d->defaultSize));
155 QPoint tr1, tr2;
156 QSizeF sc(1, 1);
157 if (d->clipRect.isValid()) {
158 tr1 = -d->clipRect.topLeft();
159 finalSize = d->clipRect.size();
160 }
161 if (d->scaledSize.isValid()) {
162 sc = QSizeF(qreal(d->scaledSize.width()) / finalSize.width(),
163 qreal(d->scaledSize.height()) / finalSize.height());
164 finalSize = d->scaledSize;
165 }
166 if (d->scaledClipRect.isValid()) {
167 tr2 = -d->scaledClipRect.topLeft();
168 finalSize = d->scaledClipRect.size();
169 }
170 QTransform t;
171 t.translate(tr2.x(), tr2.y());
172 t.scale(sc.width(), sc.height());
173 t.translate(tr1.x(), tr1.y());
174 bounds = t.mapRect(bounds);
175 }
176 *image = QImage(finalSize, QImage::Format_ARGB32_Premultiplied);
177 if (!finalSize.isEmpty()) {
178 image->fill(d->backColor.rgba());
179 QPainter p(image);
180 d->r.render(&p, bounds);
181 p.end();
182 }
183 d->readDone = true;
184 return true;
185 }
186
187 return false;
188}
189
190
191QVariant QSvgIOHandler::option(ImageOption option) const
192{
193 switch(option) {
194 case ImageFormat:
195 return QImage::Format_ARGB32_Premultiplied;
196 break;
197 case Size:
198 d->load(device());
199 return d->defaultSize;
200 break;
201 case ClipRect:
202 return d->clipRect;
203 break;
204 case ScaledSize:
205 return d->scaledSize;
206 break;
207 case ScaledClipRect:
208 return d->scaledClipRect;
209 break;
210 case BackgroundColor:
211 return d->backColor;
212 break;
213 default:
214 break;
215 }
216 return QVariant();
217}
218
219
220void QSvgIOHandler::setOption(ImageOption option, const QVariant & value)
221{
222 switch(option) {
223 case ClipRect:
224 d->clipRect = value.toRect();
225 break;
226 case ScaledSize:
227 d->scaledSize = value.toSize();
228 break;
229 case ScaledClipRect:
230 d->scaledClipRect = value.toRect();
231 break;
232 case BackgroundColor:
233 d->backColor = value.value<QColor>();
234 break;
235 default:
236 break;
237 }
238}
239
240
241bool QSvgIOHandler::supportsOption(ImageOption option) const
242{
243 switch(option)
244 {
245 case ImageFormat:
246 case Size:
247 case ClipRect:
248 case ScaledSize:
249 case ScaledClipRect:
250 case BackgroundColor:
251 return true;
252 default:
253 break;
254 }
255 return false;
256}
257
258
259bool QSvgIOHandler::canRead(QIODevice *device)
260{
261 QByteArray buf = device->peek(8);
262 return buf.startsWith("\x1f\x8b") || buf.contains("<?xml") || buf.contains("<svg");
263}
264
265QT_END_NAMESPACE
266
267#endif // QT_NO_SVGRENDERER
Note: See TracBrowser for help on using the repository browser.