1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
4#include <QGuiApplication>
5#include <QQmlApplicationEngine>
6#include <QCommandLineParser>
7#include <QFile>
8#include <QQuickWindow>
9#include <QQuickItem>
10#include <QtQuickVectorImageGenerator/private/qquickitemgenerator_p.h>
11#include <QtQuickVectorImageGenerator/private/qquickqmlgenerator_p.h>
12#include <QtQuickVectorImageGenerator/private/qquickvectorimageglobal_p.h>
13
14#define ENABLE_GUI
15
16int main(int argc, char *argv[])
17{
18#ifdef ENABLE_GUI
19 QGuiApplication app(argc, argv);
20#else
21 QCoreApplication app(argc, argv);
22#endif
23
24 QCommandLineParser parser;
25 parser.setApplicationDescription("SVG to QML converter");
26 parser.addHelpOption();
27 parser.addPositionalArgument(name: "input", description: QCoreApplication::translate(context: "main", key: "SVG file to read."));
28 parser.addPositionalArgument(name: "output", description: QCoreApplication::translate(context: "main", key: "QML file to write."), syntax: "[output]");
29
30 QCommandLineOption curveRendererOption({ "c", "curve-renderer" },
31 QCoreApplication::translate(context: "main", key: "Use the curve renderer in generated QML."));
32 parser.addOption(commandLineOption: curveRendererOption);
33
34 QCommandLineOption optimizeOption({ "p", "optimize-paths" },
35 QCoreApplication::translate(context: "main", key: "Optimize paths for the curve renderer."));
36 parser.addOption(commandLineOption: optimizeOption);
37
38 QCommandLineOption typeNameOption({ "t", "type-name" },
39 QCoreApplication::translate(context: "main", key: "Use <typename> for Shape."),
40 QCoreApplication::translate(context: "main", key: "typename"));
41 parser.addOption(commandLineOption: typeNameOption);
42
43 QCommandLineOption copyrightOption("copyright-statement",
44 QCoreApplication::translate(context: "main", key: "Add <string> as a comment at the start of the generated file."),
45 QCoreApplication::translate(context: "main", key: "string"));
46 parser.addOption(commandLineOption: copyrightOption);
47
48 QCommandLineOption outlineModeOption("outline-stroke-mode",
49 QCoreApplication::translate(context: "main", key: "Stroke the outline (contour) of the filled shape instead of "
50 "the original path. Also sets optimize-paths."));
51 parser.addOption(commandLineOption: outlineModeOption);
52
53 QCommandLineOption assetOutputDirectoryOption("asset-output-directory",
54 QCoreApplication::translate(context: "main", key: "If the SVG refers to external or embedded files, such as images, these "
55 "will be copied into the same directory as the output QML file by default. "
56 "Set the asset output directory to override the location."),
57 QCoreApplication::translate(context: "main", key: "directory"));
58 parser.addOption(commandLineOption: assetOutputDirectoryOption);
59
60 QCommandLineOption assetOutputPrefixOption("asset-output-prefix",
61 QCoreApplication::translate(context: "main", key: "If the SVG refers to external or embedded files, such as images, these "
62 "will be copied to files with unique identifiers. By default, the files will be prefixed "
63 "with \"svg_asset_\". Set the asset output prefix to override the prefix."),
64 QCoreApplication::translate(context: "main", key: "prefix"));
65 parser.addOption(commandLineOption: assetOutputPrefixOption);
66
67 QCommandLineOption keepPathsOption("keep-external-paths",
68 QCoreApplication::translate(context: "main", key: "Any paths to external files will be retained in the QML output. "
69 "The paths will be reformatted as relative to the output file. If "
70 "this is not enabled, copies of the file will be saved to the asset output "
71 "directory. Embedded data will still be saved to files, even if "
72 "this option is set."));
73 parser.addOption(commandLineOption: keepPathsOption);
74
75 QCommandLineOption untrustedOption("no-assume-trusted-source",
76 QCoreApplication::translate(context: "main", key: "When parsing the SVG, this enables certain checks and restrictions which "
77 "are not enabled by default."));
78 parser.addOption(commandLineOption: untrustedOption);
79
80#ifdef ENABLE_GUI
81 QCommandLineOption guiOption({ "v", "view" },
82 QCoreApplication::translate(context: "main", key: "Display the generated QML in a window. This is the default behavior if no "
83 "output file is specified."));
84 parser.addOption(commandLineOption: guiOption);
85#endif
86 parser.process(app);
87 const QStringList args = parser.positionalArguments();
88 if (args.size() < 1) {
89 parser.showHelp(exitCode: 1);
90 }
91
92 const QString inFileName = args.at(i: 0);
93
94 QString commentString = QLatin1String("Generated from SVG file %1").arg(args: inFileName);
95
96 const auto outFileName = args.size() > 1 ? args.at(i: 1) : QString{};
97 const auto typeName = parser.value(option: typeNameOption);
98 const auto assetOutputDirectory = parser.value(option: assetOutputDirectoryOption);
99 const auto assetOutputPrefix = parser.value(option: assetOutputPrefixOption);
100 const bool keepPaths = parser.isSet(option: keepPathsOption);
101 auto copyrightString = parser.value(option: copyrightOption);
102
103 if (!copyrightString.isEmpty()) {
104 copyrightString = copyrightString.replace(before: "\\n", after: "\n");
105 commentString = copyrightString + u"\n" + commentString;
106 }
107
108 QQuickVectorImageGenerator::GeneratorFlags flags;
109 if (!parser.isSet(option: untrustedOption))
110 flags |= QQuickVectorImageGenerator::GeneratorFlag::AssumeTrustedSource;
111 if (parser.isSet(option: curveRendererOption))
112 flags |= QQuickVectorImageGenerator::GeneratorFlag::CurveRenderer;
113 if (parser.isSet(option: optimizeOption))
114 flags |= QQuickVectorImageGenerator::GeneratorFlag::OptimizePaths;
115 if (parser.isSet(option: outlineModeOption))
116 flags |= (QQuickVectorImageGenerator::GeneratorFlag::OutlineStrokeMode
117 | QQuickVectorImageGenerator::GeneratorFlag::OptimizePaths);
118
119 QQuickQmlGenerator generator(inFileName, flags, outFileName);
120 generator.setShapeTypeName(typeName);
121 generator.setCommentString(commentString);
122 generator.setAssetFileDirectory(assetOutputDirectory);
123 generator.setAssetFilePrefix(assetOutputPrefix);
124 generator.setRetainFilePaths(keepPaths);
125 bool ok = generator.generate() && generator.save();
126
127#ifdef ENABLE_GUI
128 if (ok && (parser.isSet(option: guiOption) || outFileName.isEmpty())) {
129 app.setOrganizationName("QtProject");
130 const QUrl url(QStringLiteral("qrc:/main.qml"));
131 QQmlApplicationEngine engine;
132 QObject::connect(sender: &engine, signal: &QQmlApplicationEngine::objectCreated,
133 context: &app, slot: [&](QObject *obj, const QUrl &objUrl){
134 if (!obj && url == objUrl)
135 QCoreApplication::exit(retcode: -1);
136 if (obj) {
137 auto *containerItem = obj->findChild<QQuickItem*>(QStringLiteral("svg_item"));
138 QQuickItemGenerator generator(inFileName, flags, containerItem, engine.rootContext());
139 generator.generate();
140 }
141 });
142 engine.load(url);
143 return app.exec();
144 }
145#endif
146
147 return ok ? 0 : 1;
148}
149

source code of qtdeclarative/tools/svgtoqml/main.cpp