Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qsvgiohandler.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5
6#ifndef QT_NO_SVGRENDERER
7
8#include "qsvgrenderer.h"
9#include "private/qsvgtinydocument_p.h"
10#include "qimage.h"
11#include "qpixmap.h"
12#include "qpainter.h"
13#include "qvariant.h"
14#include "qbuffer.h"
15#include "qdebug.h"
16
18
40
41
42bool QSvgIOHandlerPrivate::load(QIODevice *device)
43{
44 if (loadAttempted)
45 return loadStatus;
46 loadAttempted = true;
47 if (q->format().isEmpty())
49
50 // # The SVG renderer doesn't handle trailing, unrelated data, so we must
51 // assume that all available data in the device is to be read.
52 bool res = false;
53 QBuffer *buf = qobject_cast<QBuffer *>(device);
54 if (buf) {
55 const QByteArray &ba = buf->data();
56 res = r.load(QByteArray::fromRawData(ba.constData() + buf->pos(), ba.size() - buf->pos()));
57 buf->seek(ba.size());
58#ifndef QT_NO_COMPRESS
59 } else if (q->format() == "svgz") {
60 res = r.load(device->readAll());
61#endif
62 } else {
63 xmlReader.setDevice(device);
64 res = r.load(&xmlReader);
65 }
66
67 if (res) {
68 defaultSize = r.defaultSize();
69 loadStatus = true;
70 }
71
72 return loadStatus;
73}
74
75
81
82
84{
85 delete d;
86}
87
89{
90 if (!device())
91 return false;
92 if (d->loadStatus && !d->readDone)
93 return true; // Will happen if we have been asked for the size
94
95 bool isCompressed = false;
96 if (QSvgTinyDocument::isLikelySvg(device(), &isCompressed)) {
97 setFormat(isCompressed ? "svgz" : "svg");
98 return true;
99 }
100 return false;
101}
102
103bool QSvgIOHandler::read(QImage *image)
104{
105 if (!d->readDone && d->load(device())) {
106 bool xform = (d->clipRect.isValid() || d->scaledSize.isValid() || d->scaledClipRect.isValid());
107 QSize finalSize = d->defaultSize;
108 QRectF bounds;
109 if (xform && !d->defaultSize.isEmpty()) {
110 bounds = QRectF(QPointF(0,0), QSizeF(d->defaultSize));
111 QPoint tr1, tr2;
112 QSizeF sc(1, 1);
113 if (d->clipRect.isValid()) {
114 tr1 = -d->clipRect.topLeft();
115 finalSize = d->clipRect.size();
116 }
117 if (d->scaledSize.isValid()) {
118 sc = QSizeF(qreal(d->scaledSize.width()) / finalSize.width(),
119 qreal(d->scaledSize.height()) / finalSize.height());
120 finalSize = d->scaledSize;
121 }
122 if (d->scaledClipRect.isValid()) {
123 tr2 = -d->scaledClipRect.topLeft();
124 finalSize = d->scaledClipRect.size();
125 }
126 QTransform t;
127 t.translate(tr2.x(), tr2.y());
128 t.scale(sc.width(), sc.height());
129 t.translate(tr1.x(), tr1.y());
130 bounds = t.mapRect(bounds);
131 }
132 if (finalSize.isEmpty()) {
133 *image = QImage();
134 } else {
135 if (qMax(finalSize.width(), finalSize.height()) > 0xffff)
136 return false; // Assume corrupted file
137 if (!QImageIOHandler::allocateImage(finalSize, QImage::Format_ARGB32_Premultiplied, image))
138 return false;
139 image->fill(d->backColor.rgba());
140 QPainter p(image);
141 d->r.render(&p, bounds);
142 p.end();
143 }
144 d->readDone = true;
145 return true;
146 }
147
148 return false;
149}
150
151
152QVariant QSvgIOHandler::option(ImageOption option) const
153{
154 switch(option) {
155 case ImageFormat:
156 return QImage::Format_ARGB32_Premultiplied;
157 break;
158 case Size:
160 return d->defaultSize;
161 break;
162 case ClipRect:
163 return d->clipRect;
164 break;
165 case ScaledSize:
166 return d->scaledSize;
167 break;
168 case ScaledClipRect:
169 return d->scaledClipRect;
170 break;
171 case BackgroundColor:
172 return d->backColor;
173 break;
174 default:
175 break;
176 }
177 return QVariant();
178}
179
180
181void QSvgIOHandler::setOption(ImageOption option, const QVariant & value)
182{
183 switch(option) {
184 case ClipRect:
185 d->clipRect = value.toRect();
186 break;
187 case ScaledSize:
188 d->scaledSize = value.toSize();
189 break;
190 case ScaledClipRect:
191 d->scaledClipRect = value.toRect();
192 break;
193 case BackgroundColor:
194 d->backColor = value.value<QColor>();
195 break;
196 default:
197 break;
198 }
199}
200
201
202bool QSvgIOHandler::supportsOption(ImageOption option) const
203{
204 switch(option)
205 {
206 case ImageFormat:
207 case Size:
208 case ClipRect:
209 case ScaledSize:
210 case ScaledClipRect:
211 case BackgroundColor:
212 return true;
213 default:
214 break;
215 }
216 return false;
217}
218
219
220bool QSvgIOHandler::canRead(QIODevice *device)
221{
222 return QSvgTinyDocument::isLikelySvg(device);
223}
224
225QT_END_NAMESPACE
226
227#endif // QT_NO_SVGRENDERER
QIODevice * device() const
Returns the device currently assigned to QImageReader, or \nullptr if no device has been assigned.
friend class QPainter
\inmodule QtCore\reentrant
Definition qpoint.h:29
bool load(QIODevice *device)
QXmlStreamReader xmlReader
QSvgIOHandlerPrivate(QSvgIOHandler *qq)
bool canRead() const override
Returns true if an image can be read from the device (i.e., the image format is supported,...
bool read(QImage *image) override
Read an image from the device, and stores it in image.
static bool canRead(QIODevice *device)