KIconThemes

ksvg2icns.cpp
1 /******************************************************************************
2  * Copyright 2014 Harald Fernengel <[email protected]> *
3  * *
4  * This program is free software; you can redistribute it and/or *
5  * modify it under the terms of the GNU Lesser General Public *
6  * *
7  * License as published by the Free Software Foundation; either *
8  * version 2.1 of the License, or (at your option) version 3, or any *
9  * later version accepted by the membership of KDE e.V. (or its *
10  * successor approved by the membership of KDE e.V.), which shall *
11  * act as a proxy defined in Section 6 of version 3 of the license. *
12  * *
13  * This library is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
16  * Lesser General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU Lesser General Public *
19  * License along with this library. If not, see *
20  * <http://www.gnu.org/licenses/>. *
21  * *
22  ******************************************************************************/
23 
24 /* This tool converts an svg to a Mac OS X icns file.
25  * Note: Requires the 'iconutil' Mac OS X binary
26  */
27 
28 #include <QCommandLineParser>
29 #include <QFileInfo>
30 #include <QProcess>
31 #include <QTemporaryDir>
32 
33 #include <QGuiApplication>
34 #include <QPainter>
35 #include <QSvgRenderer>
36 
37 #include "../../../kiconthemes_version.h"
38 
39 #include <stdio.h>
40 
41 #define EXIT_ON_ERROR(isOk, ...) \
42  do { \
43  if (!(isOk)) { \
44  fprintf(stderr, __VA_ARGS__); \
45  return 1; \
46  } \
47  } while (false);
48 
49 static bool writeImage(QSvgRenderer &svg, int size, const QString &outFile1, const QString &outFile2 = QString())
50 {
51  QImage out(size, size, QImage::Format_ARGB32);
52  out.fill(Qt::transparent);
53 
54  QPainter painter(&out);
55  svg.render(&painter);
56  painter.end();
57 
58  if (!out.save(outFile1)) {
59  fprintf(stderr, "Unable to write %s\n", qPrintable(outFile1));
60  return false;
61  }
62  if (!outFile2.isEmpty() && !out.save(outFile2)) {
63  fprintf(stderr, "Unable to write %s\n", qPrintable(outFile2));
64  return false;
65  }
66 
67  return true;
68 }
69 
70 int main(int argc, char *argv[])
71 {
72  QGuiApplication app(argc, argv);
73 
74  app.setApplicationName(QStringLiteral("ksvg2icns"));
75  app.setApplicationVersion(QStringLiteral(KICONTHEMES_VERSION_STRING));
76  QCommandLineParser parser;
77  parser.setApplicationDescription(app.translate("main", "Creates an icns file from an svg image"));
78  parser.addPositionalArgument("iconname", app.translate("main", "The svg icon to convert"));
79  parser.addHelpOption();
80 
81  parser.process(app);
82  if (parser.positionalArguments().isEmpty()) {
83  parser.showHelp();
84  return 1;
85  }
86 
87  bool isOk;
88 
89  // create a temporary dir to create an iconset
90  QTemporaryDir tmpDir(QDir::tempPath() + QStringLiteral("/ksvg2icns"));
91 
92  isOk = tmpDir.isValid();
93  EXIT_ON_ERROR(isOk, "Unable to create temporary directory\n");
94 
95  const QString outPath = tmpDir.filePath(QStringLiteral("out.iconset"));
96 
97  isOk = QDir(tmpDir.path()).mkpath(outPath);
98  EXIT_ON_ERROR(isOk, "Unable to create out.iconset directory\n");
99 
100  const QStringList &args = app.arguments();
101  EXIT_ON_ERROR(args.size() == 2,
102  "Usage: %s svg-image\n",
103  qPrintable(args.value(0)));
104 
105  const QString &svgFileName = args.at(1);
106 
107  // open the actual svg file
108  QSvgRenderer svg;
109  isOk = svg.load(svgFileName);
110  EXIT_ON_ERROR(isOk, "Unable to load %s\n", qPrintable(svgFileName));
111 
112  // The sizes are from:
113  // https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Optimizing/Optimizing.html
114 
115  struct OutFiles
116  {
117  int size;
118  QString out1;
119  QString out2;
120  };
121 
122  // create the pngs in various resolutions
123  const OutFiles outFiles[] = {
124  { 1024, outPath + QStringLiteral("/[email protected]"), QString() },
125  { 512, outPath + QStringLiteral("/icon_512x512.png"), outPath + QStringLiteral("/[email protected]") },
126  { 256, outPath + QStringLiteral("/icon_256x256.png"), outPath + QStringLiteral("/[email protected]") },
127  { 128, outPath + QStringLiteral("/icon_128x128.png"), QString() },
128  { 64, outPath + QStringLiteral("/[email protected]"), QString() },
129  { 32, outPath + QStringLiteral("/icon_32x32.png"), outPath + QStringLiteral("/[email protected]") },
130  { 16, outPath + QStringLiteral("/icon_16x16.png"), QString() }
131  };
132 
133  for (const OutFiles &outFile : outFiles) {
134  isOk = writeImage(svg, outFile.size, outFile.out1, outFile.out2);
135  if (!isOk) {
136  return 1;
137  }
138  }
139 
140  // convert the iconset to icns using the "iconutil" command
141 
142  const QString outIcns = QFileInfo(svgFileName).baseName() + QStringLiteral(".icns");
143 
144  const QStringList utilArgs = QStringList()
145  << "-c" << "icns"
146  << "-o" << outIcns
147  << outPath;
148 
149  QProcess iconUtil;
150 
151  iconUtil.start(QStringLiteral("iconutil"), utilArgs, QIODevice::ReadOnly);
152  isOk = iconUtil.waitForFinished(-1);
153  EXIT_ON_ERROR(isOk, "Unable to launch iconutil: %s\n", qPrintable(iconUtil.errorString()));
154 
155  EXIT_ON_ERROR(iconUtil.exitStatus() == QProcess::NormalExit, "iconutil crashed!\n");
156  EXIT_ON_ERROR(iconUtil.exitCode() == 0, "iconutil returned %d\n", iconUtil.exitCode());
157 
158  return 0;
159 }
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)
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 Tue Aug 4 2020 22:40:45 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.