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// Qt-Security score:significant reason:default
4
5
7
8#ifndef QT_NO_SVGRENDERER
9
10#include "qsvgrenderer.h"
11#include "private/qsvgdocument_p.h"
12#include "qimage.h"
13#include "qpixmap.h"
14#include "qpainter.h"
15#include "qvariant.h"
16#include "qbuffer.h"
17#include "qdebug.h"
18
20
42
43
44bool QSvgIOHandlerPrivate::load(QIODevice *device)
45{
46 if (loadAttempted)
47 return loadStatus;
48 loadAttempted = true;
49 if (q->format().isEmpty())
51
52 // # The SVG renderer doesn't handle trailing, unrelated data, so we must
53 // assume that all available data in the device is to be read.
54 bool res = false;
55 QBuffer *buf = qobject_cast<QBuffer *>(device);
56 if (buf) {
57 const QByteArray &ba = buf->data();
58 res = r.load(QByteArray::fromRawData(ba.constData() + buf->pos(), ba.size() - buf->pos()));
59 buf->seek(ba.size());
60#ifndef QT_NO_COMPRESS
61 } else if (q->format() == "svgz") {
62 res = r.load(device->readAll());
63#endif
64 } else {
65 xmlReader.setDevice(device);
66 res = r.load(&xmlReader);
67 }
68
69 if (res) {
70 defaultSize = r.defaultSize();
71 loadStatus = true;
72 }
73
74 return loadStatus;
75}
76
77
83
84
86{
87 delete d;
88}
89
91{
92 if (!device())
93 return false;
94 if (d->loadStatus && !d->readDone)
95 return true; // Will happen if we have been asked for the size
96
97 bool isCompressed = false;
98 if (QSvgDocument::isLikelySvg(device(), &isCompressed)) {
99 setFormat(isCompressed ? "svgz" : "svg");
100 return true;
101 }
102 return false;
103}
104
105bool QSvgIOHandler::read(QImage *image)
106{
107 if (!d->readDone && d->load(device())) {
108 bool xform = (d->clipRect.isValid() || d->scaledSize.isValid() || d->scaledClipRect.isValid());
109 QSize finalSize = d->defaultSize;
110 QRectF bounds;
111 if (xform && !d->defaultSize.isEmpty()) {
112 bounds = QRectF(QPointF(0,0), QSizeF(d->defaultSize));
113 QPoint tr1, tr2;
114 QSizeF sc(1, 1);
115 if (d->clipRect.isValid()) {
116 tr1 = -d->clipRect.topLeft();
117 finalSize = d->clipRect.size();
118 }
119 if (d->scaledSize.isValid()) {
120 sc = QSizeF(qreal(d->scaledSize.width()) / finalSize.width(),
121 qreal(d->scaledSize.height()) / finalSize.height());
122 finalSize = d->scaledSize;
123 }
124 if (d->scaledClipRect.isValid()) {
125 tr2 = -d->scaledClipRect.topLeft();
126 finalSize = d->scaledClipRect.size();
127 }
128 QTransform t;
129 t.translate(tr2.x(), tr2.y());
130 t.scale(sc.width(), sc.height());
131 t.translate(tr1.x(), tr1.y());
132 bounds = t.mapRect(bounds);
133 }
134 if (finalSize.isEmpty()) {
135 *image = QImage();
136 } else {
137 if (qMax(finalSize.width(), finalSize.height()) > 0xffff)
138 return false; // Assume corrupted file
139 if (!QImageIOHandler::allocateImage(finalSize, QImage::Format_ARGB32_Premultiplied, image))
140 return false;
141 image->fill(d->backColor.rgba());
142 QPainter p(image);
143 d->r.render(&p, bounds);
144 p.end();
145 }
146 d->readDone = true;
147 return true;
148 }
149
150 return false;
151}
152
153
154QVariant QSvgIOHandler::option(ImageOption option) const
155{
156 switch(option) {
157 case ImageFormat:
158 return QImage::Format_ARGB32_Premultiplied;
159 break;
160 case Size:
162 return d->defaultSize;
163 break;
164 case ClipRect:
165 return d->clipRect;
166 break;
167 case ScaledSize:
168 return d->scaledSize;
169 break;
170 case ScaledClipRect:
171 return d->scaledClipRect;
172 break;
173 case BackgroundColor:
174 return d->backColor;
175 break;
176 default:
177 break;
178 }
179 return QVariant();
180}
181
182
183void QSvgIOHandler::setOption(ImageOption option, const QVariant & value)
184{
185 switch(option) {
186 case ClipRect:
187 d->clipRect = value.toRect();
188 break;
189 case ScaledSize:
190 d->scaledSize = value.toSize();
191 break;
192 case ScaledClipRect:
193 d->scaledClipRect = value.toRect();
194 break;
195 case BackgroundColor:
196 d->backColor = value.value<QColor>();
197 break;
198 default:
199 break;
200 }
201}
202
203
204bool QSvgIOHandler::supportsOption(ImageOption option) const
205{
206 switch(option)
207 {
208 case ImageFormat:
209 case Size:
210 case ClipRect:
211 case ScaledSize:
212 case ScaledClipRect:
213 case BackgroundColor:
214 return true;
215 default:
216 break;
217 }
218 return false;
219}
220
221
222bool QSvgIOHandler::canRead(QIODevice *device)
223{
224 return QSvgDocument::isLikelySvg(device);
225}
226
227QT_END_NAMESPACE
228
229#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:30
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,...
QVariant option(ImageOption option) const override
Returns the value assigned to option as a QVariant.
bool read(QImage *image) override
Read an image from the device, and stores it in image.
bool supportsOption(ImageOption option) const override
Returns true if the QImageIOHandler supports the option option; otherwise returns false.
void setOption(ImageOption option, const QVariant &value) override
Sets the option option with the value value.
static bool canRead(QIODevice *device)
Combined button and popup list for selecting options.