KIconThemes

ksvg2icns.cpp
1 /*
2  SPDX-FileCopyrightText: 2014 Harald Fernengel <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5 */
6 
7 /* This tool converts an svg to a Mac OS X icns file.
8  * Note: Requires the 'iconutil' Mac OS X binary
9  */
10 
11 #include <QCommandLineParser>
12 #include <QFileInfo>
13 #include <QProcess>
14 #include <QTemporaryDir>
15 
16 #include <QGuiApplication>
17 #include <QPainter>
18 #include <QSvgRenderer>
19 
20 #include "../../../kiconthemes_version.h"
21 
22 #include <stdio.h>
23 
24 #define EXIT_ON_ERROR(isOk, ...) \
25  do { \
26  if (!(isOk)) { \
27  fprintf(stderr, __VA_ARGS__); \
28  return 1; \
29  } \
30  } while (false);
31 
32 static bool writeImage(QSvgRenderer &svg, int size, const QString &outFile1, const QString &outFile2 = QString())
33 {
34  QImage out(size, size, QImage::Format_ARGB32);
35  out.fill(Qt::transparent);
36 
37  QPainter painter(&out);
39  svg.render(&painter);
40  painter.end();
41 
42  if (!out.save(outFile1)) {
43  fprintf(stderr, "Unable to write %s\n", qPrintable(outFile1));
44  return false;
45  }
46  if (!outFile2.isEmpty() && !out.save(outFile2)) {
47  fprintf(stderr, "Unable to write %s\n", qPrintable(outFile2));
48  return false;
49  }
50 
51  return true;
52 }
53 
54 int main(int argc, char *argv[])
55 {
56  QGuiApplication app(argc, argv);
57 
58  app.setApplicationName(QStringLiteral("ksvg2icns"));
59  app.setApplicationVersion(QStringLiteral(KICONTHEMES_VERSION_STRING));
60  QCommandLineParser parser;
61  parser.setApplicationDescription(app.translate("main", "Creates an icns file from an svg image"));
62  parser.addPositionalArgument("iconname", app.translate("main", "The svg icon to convert"));
63  parser.addHelpOption();
64 
65  parser.process(app);
66  if (parser.positionalArguments().isEmpty()) {
67  parser.showHelp();
68  return 1;
69  }
70 
71  bool isOk;
72 
73  // create a temporary dir to create an iconset
74  QTemporaryDir tmpDir(QDir::tempPath() + QStringLiteral("/ksvg2icns"));
75 
76  isOk = tmpDir.isValid();
77  EXIT_ON_ERROR(isOk, "Unable to create temporary directory\n");
78 
79  const QString outPath = tmpDir.filePath(QStringLiteral("out.iconset"));
80 
81  isOk = QDir(tmpDir.path()).mkpath(outPath);
82  EXIT_ON_ERROR(isOk, "Unable to create out.iconset directory\n");
83 
84  const QStringList &args = app.arguments();
85  EXIT_ON_ERROR(args.size() == 2,
86  "Usage: %s svg-image\n",
87  qPrintable(args.value(0)));
88 
89  const QString &svgFileName = args.at(1);
90 
91  // open the actual svg file
92  QSvgRenderer svg;
93  isOk = svg.load(svgFileName);
94  EXIT_ON_ERROR(isOk, "Unable to load %s\n", qPrintable(svgFileName));
95 
96  // The sizes are from:
97  // https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Optimizing/Optimizing.html
98 
99  struct OutFiles
100  {
101  int size;
102  QString out1;
103  QString out2;
104  };
105 
106  // create the pngs in various resolutions
107  const OutFiles outFiles[] = {
108  { 1024, outPath + QStringLiteral("/[email protected]"), QString() },
109  { 512, outPath + QStringLiteral("/icon_512x512.png"), outPath + QStringLiteral("/[email protected]") },
110  { 256, outPath + QStringLiteral("/icon_256x256.png"), outPath + QStringLiteral("/[email protected]") },
111  { 128, outPath + QStringLiteral("/icon_128x128.png"), QString() },
112  { 64, outPath + QStringLiteral("/[email protected]"), QString() },
113  { 32, outPath + QStringLiteral("/icon_32x32.png"), outPath + QStringLiteral("/[email protected]") },
114  { 16, outPath + QStringLiteral("/icon_16x16.png"), QString() }
115  };
116 
117  for (const OutFiles &outFile : outFiles) {
118  isOk = writeImage(svg, outFile.size, outFile.out1, outFile.out2);
119  if (!isOk) {
120  return 1;
121  }
122  }
123 
124  // convert the iconset to icns using the "iconutil" command
125 
126  const QString outIcns = QFileInfo(svgFileName).baseName() + QStringLiteral(".icns");
127 
128  const QStringList utilArgs = QStringList()
129  << "-c" << "icns"
130  << "-o" << outIcns
131  << outPath;
132 
133  QProcess iconUtil;
134 
135  iconUtil.start(QStringLiteral("iconutil"), utilArgs, QIODevice::ReadOnly);
136  isOk = iconUtil.waitForFinished(-1);
137  EXIT_ON_ERROR(isOk, "Unable to launch iconutil: %s\n", qPrintable(iconUtil.errorString()));
138 
139  EXIT_ON_ERROR(iconUtil.exitStatus() == QProcess::NormalExit, "iconutil crashed!\n");
140  EXIT_ON_ERROR(iconUtil.exitCode() == 0, "iconutil returned %d\n", iconUtil.exitCode());
141 
142  return 0;
143 }
QStringList positionalArguments() const const
void render(QPainter *painter)
KIOCORE_EXPORT MkpathJob * mkpath(const QUrl &url, const QUrl &baseUrl=QUrl(), JobFlags flags=DefaultFlags)
QString errorString() const const
const T & at(int i) const const
void addPositionalArgument(const QString &name, const QString &description, const QString &syntax)
int size() const const
T value(int i) const const
bool load(const QString &filename)
QString tempPath()
bool isEmpty() const const
QCommandLineOption addHelpOption()
void setApplicationDescription(const QString &description)
void process(const QStringList &arguments)
void showHelp(int exitCode)
KeepAspectRatio
void setAspectRatioMode(Qt::AspectRatioMode mode)
transparent
QString baseName() const const
QProcess::ExitStatus exitStatus() const const
int exitCode() const const
void start(const QString &program, const QStringList &arguments, QIODevice::OpenMode mode)
bool waitForFinished(int msecs)
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Fri Nov 27 2020 22:43:02 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.