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,...
bool read(QImage *image) override
Read an image from the device, and stores it in image.
static bool canRead(QIODevice *device)
Combined button and popup list for selecting options.