Krita Source Code Documentation
Loading...
Searching...
No Matches
ImageShape.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2016 Dmitry Kazakov <dimula73@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7#include "ImageShape.h"
8#include "kis_debug.h"
9
10#include <QPainter>
11#include <SvgLoadingContext.h>
12#include <SvgSavingContext.h>
13#include <SvgUtil.h>
14#include <SvgStyleWriter.h>
15#include <QBuffer>
16#include <KisMimeDatabase.h>
17#include <KoXmlWriter.h>
18#include "kis_dom_utils.h"
19#include <QRegularExpression>
21
22
23struct Q_DECL_HIDDEN ImageShape::Private : public QSharedData
24{
26 Private(const Private &rhs)
27 : QSharedData(),
28 image(rhs.image),
29 ratioParser(rhs.ratioParser ? new SvgUtil::PreserveAspectRatioParser(*rhs.ratioParser) : 0),
30 viewBoxTransform(rhs.viewBoxTransform)
31 {
32 }
33
34 QImage image;
35 QScopedPointer<SvgUtil::PreserveAspectRatioParser> ratioParser;
36 QTransform viewBoxTransform;
37};
38
39
41 : m_d(new Private)
42{
43}
44
46 : KoShape(rhs),
47 m_d(rhs.m_d)
48{
49}
50
54
56{
57 return new ImageShape(*this);
58}
59
60void ImageShape::paint(QPainter &painter) const
61{
62 KisQPainterStateSaver saver(&painter);
63
64 const QRectF myrect(QPointF(), size());
65
66 painter.setRenderHint(QPainter::SmoothPixmapTransform);
67 painter.setClipRect(QRectF(QPointF(), size()), Qt::IntersectClip);
68 painter.setTransform(m_d->viewBoxTransform, true);
69 painter.drawImage(QPoint(), m_d->image);
70}
71
72void ImageShape::setSize(const QSizeF &size)
73{
75}
76
78{
79 const QString uid = context.createUID("image");
80
81 context.shapeWriter().startElement("image");
82 context.shapeWriter().addAttribute("id", uid);
84 context.shapeWriter().addAttribute("width", QString("%1px").arg(KisDomUtils::toString(size().width())));
85 context.shapeWriter().addAttribute("height", QString("%1px").arg(KisDomUtils::toString(size().height())));
86
87 QString aspectString = m_d->ratioParser? m_d->ratioParser->toString(): QString();
88 if (!aspectString.isEmpty()) {
89 context.shapeWriter().addAttribute("preserveAspectRatio", aspectString);
90 }
91
92 QBuffer buffer;
93 buffer.open(QIODevice::WriteOnly);
94 if (m_d->image.save(&buffer, "PNG")) {
95 const QString mimeType = KisMimeDatabase::mimeTypeForSuffix("*.png");
96 context.shapeWriter().addAttribute("xlink:href", "data:"+ mimeType + ";base64," + buffer.data().toBase64());
97 }
98 SvgStyleWriter::saveMetadata(this, context);
99
100 context.shapeWriter().endElement(); // image
101
102 return true;
103}
104
105bool ImageShape::loadSvg(const QDomElement &element, SvgLoadingContext &context)
106{
107 const qreal x = SvgUtil::parseUnitX(context.currentGC(), context.resolvedProperties(), element.attribute("x"));
108 const qreal y = SvgUtil::parseUnitY(context.currentGC(), context.resolvedProperties(), element.attribute("y"));
109 const qreal w = SvgUtil::parseUnitX(context.currentGC(), context.resolvedProperties(), element.attribute("width"));
110 const qreal h = SvgUtil::parseUnitY(context.currentGC(), context.resolvedProperties(), element.attribute("height"));
111
112 setSize(QSizeF(w, h));
113 setPosition(QPointF(x, y));
114
115 if (w == 0.0 || h == 0.0) {
116 setVisible(false);
117 }
118
119 QString fileName = element.attribute("xlink:href");
120
121 QByteArray data;
122
123 if (fileName.startsWith("data:")) {
124
125 QRegularExpression re("data:(.+?);base64,(.+)");
126 QRegularExpressionMatch match = re.match(fileName);
127
128 data = match.captured(2).toLatin1();
129 data = QByteArray::fromBase64(data);
130 } else {
131 data = context.fetchExternalFile(fileName);
132 }
133
134 if (!data.isEmpty()) {
135 QBuffer buffer(&data);
136 m_d->image.load(&buffer, "");
137 }
138
139 const QString aspectString = element.attribute("preserveAspectRatio", "xMidYMid meet");
140 m_d->ratioParser.reset(new SvgUtil::PreserveAspectRatioParser(aspectString));
141
142 if (!m_d->image.isNull()) {
143
144 m_d->viewBoxTransform =
145 QTransform::fromScale(w / m_d->image.width(), h / m_d->image.height());
146
147 SvgUtil::parseAspectRatio(*m_d->ratioParser,
148 QRectF(QPointF(), size()),
149 QRect(QPoint(), m_d->image.size()),
150 &m_d->viewBoxTransform);
151 }
152
153 if (m_d->ratioParser->defer) {
154 // TODO:
155 }
156
157 return true;
158}
159
160void ImageShape::setImage(const QImage &img)
161{
162 if (m_d->image != img) {
163 m_d->image = img;
165 }
166}
167
168QImage ImageShape::image() const
169{
170 return m_d->image;
171}
172
173void ImageShape::setViewBoxTransform(const QTransform &tf)
174{
175 if (m_d->viewBoxTransform != tf) {
176 m_d->viewBoxTransform = tf;
178 }
179}
180
181QTransform ImageShape::viewBoxTransform() const
182{
183 return m_d->viewBoxTransform;
184}
static QString mimeTypeForSuffix(const QString &suffix)
Find the mimetype for a given extension. The extension may have the form "*.xxx" or "xxx".
virtual QSizeF size() const
Get the size of the shape in pt.
Definition KoShape.cpp:740
virtual void shapeChanged(ChangeType type, KoShape *shape=0)
Definition KoShape.cpp:1059
@ ContentChanged
the content of the shape changed e.g. a new image inside a pixmap/text change inside a textshape
Definition KoShape.h:106
@ GenericMatrixChange
used after the matrix was changed without knowing which property explicitly changed
Definition KoShape.h:98
QTransform transformation() const
Returns the shapes local transformation matrix.
Definition KoShape.cpp:383
virtual void setPosition(const QPointF &position)
Set the position of the shape in pt.
Definition KoShape.cpp:267
void setVisible(bool on)
Definition KoShape.cpp:795
virtual void setSize(const QSizeF &size)
Resize the shape.
Definition KoShape.cpp:248
Contains data used for loading svg.
QByteArray fetchExternalFile(const QString &url)
SvgGraphicsContext * currentGC() const
Returns the current graphics context.
KoSvgTextProperties resolvedProperties() const
These are the text properties, completely resolved, ensuring that everything is inherited and the siz...
Context for saving svg files.
QString createUID(const QString &base)
Create a unique id from the specified base text.
QScopedPointer< KoXmlWriter > shapeWriter
static void saveMetadata(const KoShape *shape, SvgSavingContext &context)
static qreal parseUnitX(SvgGraphicsContext *gc, const KoSvgTextProperties &resolved, const QString &unit)
parses a length attribute in x-direction
Definition SvgUtil.cpp:304
static void parseAspectRatio(const PreserveAspectRatioParser &p, const QRectF &elementBounds, const QRectF &viewRect, QTransform *_viewTransform)
Definition SvgUtil.cpp:190
static void writeTransformAttributeLazy(const QString &name, const QTransform &transform, KoXmlWriter &shapeWriter)
Writes a transform as an attribute name iff the transform is not empty.
Definition SvgUtil.cpp:124
static qreal parseUnitY(SvgGraphicsContext *gc, const KoSvgTextProperties &resolved, const QString &unit)
parses a length attribute in y-direction
Definition SvgUtil.cpp:313
QString toString(const QString &value)
QTransform viewBoxTransform
void setImage(const QImage &img)
QImage image
void setViewBoxTransform(const QTransform &tf)
void setSize(const QSizeF &size) override
Resize the shape.
bool loadSvg(const QDomElement &element, SvgLoadingContext &context) override
Loads data from specified svg element.
bool saveSvg(SvgSavingContext &context) override
Saves data utilizing specified svg saving context.
void paint(QPainter &painter) const override
Paint the shape fill The class extending this one is responsible for painting itself....
~ImageShape() override
Private(const Private &rhs)
KoShape * cloneShape() const override
creates a deep copy of the shape or shape's subtree
QScopedPointer< SvgUtil::PreserveAspectRatioParser > ratioParser
QSharedDataPointer< Private > m_d
Definition ImageShape.h:44