8#include <private/qsgcurveprocessor_p.h>
9#include <private/qquickshape_p.h>
10#include <private/qquadpath_p.h>
11#include <private/qquickitem_p.h>
12#include <private/qquickimagebase_p_p.h>
14#include <QtCore/qloggingcategory.h>
15#include <QtCore/qdir.h>
37 if (m_resultStream && m_array && !m_array->isEmpty())
38 *m_resultStream << *m_array <<
Qt::endl;
44 : m_array(std::exchange(
other.m_array,
nullptr))
45 , m_stream(std::exchange(
other.m_stream,
nullptr))
46 , m_resultStream(std::exchange(
other.m_resultStream,
nullptr))
50 std::swap(m_resultStream,
other.m_resultStream);
51 std::swap(m_stream,
other.m_stream);
52 std::swap(m_array,
other.m_array);
75 , outputFileName(outFileName)
82 if (!outputFileName.
isEmpty()) {
83 QFile outFile(outputFileName);
89 if (lcQuickVectorImage().isDebugEnabled()) {
97 m_shapeTypeName =
name.toLatin1();
112 return m_commentString;
118 if (!
info.nodeId.isEmpty())
119 stream() <<
"objectName: \"" <<
info.nodeId <<
"\"";
120 if (!
info.isDefaultTransform) {
121 auto sx =
info.transform.m11();
122 auto sy =
info.transform.m22();
123 auto x =
info.transform.m31();
124 auto y =
info.transform.m32();
126 stream() <<
"transform: Translate { " <<
"x: " <<
x <<
"; y: " <<
y <<
" }";
128 stream() <<
"transform: Scale { xScale: " << sx <<
"; yScale: " << sy <<
" }";
132 stream() <<
"transform: [ Matrix4x4 { matrix: Qt.matrix4x4 (";
134 const auto *
data =
m.data();
135 for (
int i = 0;
i < 4;
i++) {
143 if (!
info.isDefaultOpacity) {
161 const QFileInfo outputFileInfo(outputFileName);
162 const QDir outputDir(outputFileInfo.absolutePath());
166 if (!m_retainFilePaths ||
info.externalFileReference.isEmpty()) {
167 filePath = m_assetFileDirectory;
169 filePath = outputDir.absolutePath();
174 QDir fileDir(filePath);
175 if (!fileDir.exists()) {
177 qCWarning(lcQuickVectorImage) <<
"Failed to create image resource directory:" << filePath;
185 if (!
info.image.save(filePath))
186 qCWarning(lcQuickVectorImage) <<
"Unabled to save image resource" << filePath;
187 qCDebug(lcQuickVectorImage) <<
"Saving copy of IMAGE" << filePath;
189 filePath =
info.externalFileReference;
203 stream() <<
"source: \"" << outputDir.relativeFilePath(assetFileInfo.absoluteFilePath()) <<
"\"";
216 if (!
info.isDefaultTransform)
217 qWarning() <<
"Skipped transform for node" <<
info.nodeId <<
"type" <<
info.typeName <<
"(this is not supposed to happen)";
220 m_inShapeItem =
true;
221 stream() << shapeName() <<
" {";
228 stream() <<
"preferredRendererType: Shape.CurveRenderer";
233 m_inShapeItem =
false;
241 stream() <<
"fillGradient: LinearGradient {";
244 QRectF gradRect(linGrad->start(), linGrad->finalStop());
247 stream() <<
"x1: " << logRect.left();
248 stream() <<
"y1: " << logRect.top();
249 stream() <<
"x2: " << logRect.right();
250 stream() <<
"y2: " << logRect.bottom();
251 for (
auto &stop : linGrad->stops())
252 stream() <<
"GradientStop { position: " << stop.
first <<
"; color: \"" << stop.second.
name(
QColor::HexArgb) <<
"\" }";
257 stream() <<
"fillGradient: RadialGradient {";
260 stream() <<
"centerX: " << radGrad->center().x();
261 stream() <<
"centerY: " << radGrad->center().y();
262 stream() <<
"centerRadius: " << radGrad->radius();
263 stream() <<
"focalX:" << radGrad->focalPoint().x();
264 stream() <<
"focalY:" << radGrad->focalPoint().y();
265 for (
auto &stop : radGrad->stops())
266 stream() <<
"GradientStop { position: " << stop.
first <<
"; color: \"" << stop.second.
name(
QColor::HexArgb) <<
"\" }";
287 stream() <<
"ShapePath {";
289 if (!
info.nodeId.isEmpty()) {
290 switch (pathSelector) {
292 stream() <<
"objectName: \"svg_fill_path:" <<
info.nodeId <<
"\"";
295 stream() <<
"objectName: \"svg_stroke_path:" <<
info.nodeId <<
"\"";
298 stream() <<
"objectName: \"svg_path:" <<
info.nodeId <<
"\"";
304 stream() <<
"strokeColor: \"transparent\"";
307 stream() <<
"strokeWidth: " <<
info.strokeStyle.width;
310 stream() <<
"miterLimit: " <<
info.strokeStyle.miterLimit;
311 if (
info.strokeStyle.dashArray.length() != 0) {
312 stream() <<
"strokeStyle: " <<
"ShapePath.DashLine";
314 stream() <<
"dashOffset: " <<
info.strokeStyle.dashOffset;
319 stream() <<
"fillColor: \"transparent\"";
326 stream() <<
"fillRule: ShapePath.WindingFill";
328 stream() <<
"fillRule: ShapePath.OddEvenFill";
333 if (!hintStr.isEmpty())
338 stream() <<
"PathSvg { path: \"" << svgPathString <<
"\" }";
349 stream() <<
"// Missing Implementation for SVG Node: " <<
info.typeName;
350 stream() <<
"// Adding an empty Item and skipping";
366 if (!
info.isTextArea)
367 stream() <<
"Item { id: textAlignItem_" <<
counter <<
"; x: " <<
info.position.x() <<
"; y: " <<
info.position.y() <<
"}";
373 if (
info.isTextArea) {
376 if (
info.size.width() > 0)
378 if (
info.size.height() > 0)
380 stream() <<
"wrapMode: Text.Wrap";
384 stream() <<
"anchors.baseline: textAlignItem_" <<
counter <<
".top";
385 switch (
info.alignment) {
393 qCDebug(lcQuickVectorImage) <<
"Unexpected text alignment" <<
info.alignment;
398 stream() <<
"anchors." << hAlign <<
": textAlignItem_" <<
counter <<
".left";
403 stream() <<
"textFormat:" << (
info.needsRichText ?
"Text.RichText" :
"Text.StyledText");
407 stream() <<
"text: \"" <<
s <<
"\"";
408 stream() <<
"font.family: \"" <<
info.font.family() <<
"\"";
409 if (
info.font.pixelSize() > 0)
410 stream() <<
"font.pixelSize:" <<
info.font.pixelSize();
411 else if (
info.font.pointSize() > 0)
412 stream() <<
"font.pixelSize:" <<
info.font.pointSizeF();
413 if (
info.font.underline())
414 stream() <<
"font.underline: true";
416 stream() <<
"font.weight: " << int(
info.font.weight());
417 if (
info.font.italic())
418 stream() <<
"font.italic: true";
422 stream() <<
"style: Text.Outline";
455 if (!
info.forceSeparatePaths &&
info.isPathContainer) {
456 stream() << shapeName() <<
" {";
459 stream() <<
"preferredRendererType: Shape.CurveRenderer";
462 m_inShapeItem =
true;
467 if (!
info.viewBox.isEmpty()) {
469 stream() <<
"transform: [";
473 stream() <<
"Translate { x: " << -
info.viewBox.x() <<
"; y: " << -
info.viewBox.y() <<
" },";
474 stream() <<
"Scale { xScale: width / " <<
info.viewBox.width() <<
"; yScale: height / " <<
info.viewBox.height() <<
" }";
485 m_inShapeItem =
false;
497 if (comments.isEmpty()) {
498 stream() <<
"// Generated from SVG";
500 for (
const auto &comment : comments)
501 stream() <<
"// " << comment;
504 stream() <<
"import QtQuick";
509 double w =
info.size.width();
510 double h =
info.size.height();
512 stream() <<
"implicitWidth: " <<
w;
514 stream() <<
"implicitHeight: " <<
h;
523 if (comments.isEmpty())
524 stream() <<
"// Generated from SVG";
526 for (
const auto &comment : comments)
527 stream() <<
"// " << comment;
529 stream() <<
"import QtQuick";
534 double w =
info.size.width();
535 double h =
info.size.height();
537 stream() <<
"implicitWidth: " <<
w;
539 stream() <<
"implicitHeight: " <<
h;
541 if (!
info.viewBox.isEmpty()) {
542 stream() <<
"transform: [";
546 stream() <<
"Translate { x: " << -
info.viewBox.x() <<
"; y: " << -
info.viewBox.y() <<
" },";
547 stream() <<
"Scale { xScale: width / " <<
info.viewBox.width() <<
"; yScale: height / " <<
info.viewBox.height() <<
" }";
555 m_inShapeItem =
false;
561QString QQuickQmlGenerator::indent()
573const char *QQuickQmlGenerator::shapeName()
const
GeneratorStream(QTextStream *result)
GeneratorStream & operator=(GeneratorStream &&other) noexcept
GeneratorStream(GeneratorStream &&other) noexcept
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
The QColor class provides colors based on RGB, HSV or CMYK values.
Type type() const
Returns the type of gradient.
\inheaderfile QIODevice \inmodule QtCore
The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
Qt::FillRule fillRule() const
Returns the painter path's currently set fill rule.
void optimizePaths(const PathNodeInfo &info)
QQuickVectorImageGenerator::GeneratorFlags m_flags
bool isNodeVisible(const NodeInfo &info)
void outputShapePath(const PathNodeInfo &info, const QPainterPath *path, const QQuadPath *quadPath, QQuickVectorImageGenerator::PathSelector pathSelector, const QRectF &boundingRect) override
bool generateRootNode(const StructureNodeInfo &info) override
void setCommentString(const QString commentString)
void generateNode(const NodeInfo &info) override
void generateImageNode(const ImageNodeInfo &info) override
void generateNodeBase(const NodeInfo &info) override
QString shapeTypeName() const
void setShapeTypeName(const QString &name)
QString commentString() const
bool generateStructureNode(const StructureNodeInfo &info) override
QQuickQmlGenerator(const QString fileName, QQuickVectorImageGenerator::GeneratorFlags flags, const QString &outFileName)
void generateUseNode(const UseNodeInfo &info) override
void generatePath(const PathNodeInfo &info) override
bool generateDefsNode(const NodeInfo &info) override
void generateTextNode(const TextNodeInfo &info) override
\inmodule QtCore\reentrant
\macro QT_RESTRICTED_CAST_FROM_ASCII
QString & fill(QChar c, qsizetype size=-1)
Sets every character in the string to character ch.
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QStringList split(const QString &sep, Qt::SplitBehavior behavior=Qt::KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Splits the string into substrings wherever sep occurs, and returns the list of those strings.
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
constexpr QColor Transparent
QString strokeJoinStyleString(Qt::PenJoinStyle strokeJoinStyle)
QString strokeCapStyleString(Qt::PenCapStyle strokeCapStyle)
QRectF mapToQtLogicalMode(const QRectF &objModeRect, const QRectF &boundingRect)
QString listString(QList< T > list)
QString pathHintString(const QQuadPath &qp)
QString toSvgString(const QPainterPath &path)
Combined button and popup list for selecting options.
QTextStream & endl(QTextStream &stream)
Writes '\n' to the stream and flushes the stream.
bool qFuzzyIsNull(qfloat16 f) noexcept
#define qCWarning(category,...)
#define qCDebug(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
GLint GLint GLint GLint GLint x
[0]
GLfloat GLfloat GLfloat w
[0]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLfloat GLfloat GLfloat GLfloat h
static const QRectF boundingRect(const QPointF *points, int pointCount)
const GeneratorStream & operator<<(const GeneratorStream &str, T val)
QLatin1StringView QLatin1String
#define QStringLiteral(str)
static bool translate(xcb_connection_t *connection, xcb_window_t child, xcb_window_t parent, int *x, int *y)
\inmodule QtCore \reentrant