summaryrefslogtreecommitdiffstats
path: root/util/gradientgen/gradientgen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'util/gradientgen/gradientgen.cpp')
-rw-r--r--util/gradientgen/gradientgen.cpp299
1 files changed, 299 insertions, 0 deletions
diff --git a/util/gradientgen/gradientgen.cpp b/util/gradientgen/gradientgen.cpp
new file mode 100644
index 0000000000..5dc0b53b9d
--- /dev/null
+++ b/util/gradientgen/gradientgen.cpp
@@ -0,0 +1,299 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2019 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the utils of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <iostream>
+#include <string>
+#include <algorithm>
+
+#include <QByteArray>
+#include <QVector>
+#include <QJsonDocument>
+#include <QJsonArray>
+#include <QJsonObject>
+#include <QJsonValue>
+#include <QDebug>
+
+#include <QColor>
+
+using namespace std;
+
+static const char LICENSE_HEADER[] =
+R"(/****************************************************************************
+**
+** Copyright (C) 2019 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/)";
+
+class Printer {
+ Q_DISABLE_COPY_MOVE(Printer)
+public:
+ Printer() = default;
+
+ class Indenter
+ {
+ Q_DISABLE_COPY_MOVE(Indenter)
+ Printer &p;
+ public:
+ Indenter(Printer &p) : p(p) { p.indent(); }
+ ~Indenter() { p.deindent(); }
+ };
+
+ ~Printer()
+ {
+ cout << flush;
+ }
+
+ void printLine(const QString &str) const
+ {
+ printLine(qPrintable(str));
+ }
+
+ void printLine(const char *str = nullptr) const
+ {
+ if (str)
+ cout << m_indentString << str << '\n';
+ else
+ cout << '\n';
+ }
+
+ void indent()
+ {
+ m_indent += 4;
+ m_indentString = std::string(m_indent, ' ');
+ }
+
+ void deindent()
+ {
+ m_indent -= 4;
+ m_indentString = std::string(m_indent, ' ');
+ }
+
+private:
+ int m_indent = 0;
+ std::string m_indentString;
+};
+
+// like QGradientStop, but with a plain int as second field
+struct GradientStop
+{
+ double position;
+ int color;
+
+ static bool sortByPosition(GradientStop s1, GradientStop s2)
+ {
+ return s1.position < s2.position;
+ }
+};
+
+static void printGradientStops(Printer &p, const QJsonArray &presets)
+{
+ const QString presetCaseString("case QGradient::%1:");
+ const QString presetStopColorString("QColor(%1, %2, %3, %4)");
+ const QString presetStopString("QGradientStop(%1, %2), ");
+
+ const auto presetStopToGradientStop = [](const QJsonValue &presetStop)
+ {
+ const double position = presetStop[QLatin1String("position")].toDouble();
+ const int color = presetStop[QLatin1String("color")].toInt();
+
+ return GradientStop{position, color};
+ };
+
+ for (const QJsonValue &presetValue : presets) {
+ if (!presetValue.isObject())
+ continue;
+
+ QJsonObject preset = presetValue.toObject();
+
+ // print the case label
+ const QString presetName = preset[QLatin1String("name")].toString();
+ p.printLine(presetCaseString.arg(presetName));
+
+ Printer::Indenter i(p);
+
+ // convert the json array of stops to QGradientStop objects
+ const QJsonArray stops = preset[QLatin1String("stops")].toArray();
+ Q_ASSERT(!stops.isEmpty());
+
+ QVector<GradientStop> gradientStops;
+ gradientStops.reserve(stops.size());
+ std::transform(stops.cbegin(),
+ stops.cend(),
+ std::back_inserter(gradientStops),
+ presetStopToGradientStop);
+
+ // stops should be sorted, but just in case...
+ std::sort(gradientStops.begin(), gradientStops.end(),
+ &GradientStop::sortByPosition);
+
+ Q_ASSERT(gradientStops.size() == stops.size());
+
+ // convert to strings
+ QString result;
+ result.reserve(result.size() + gradientStops.size() * (presetStopString.size() + 20));
+ result += "return Q_ARRAY_LITERAL(QGradientStop, ";
+
+ for (const GradientStop &stop : qAsConst(gradientStops)) {
+ // gradientgen.js does not output the alpha channel, so hardcode full alpha here
+ Q_ASSERT(qAlpha(stop.color) == 0);
+
+ const QString colorString = presetStopColorString
+ .arg(qRed(stop.color))
+ .arg(qGreen(stop.color))
+ .arg(qBlue(stop.color))
+ .arg(255);
+ result += presetStopString.arg(stop.position).arg(colorString);
+ }
+
+ result.chop(2);
+ result += ");";
+ p.printLine(result);
+ }
+
+ // Add an entry for NumPresets, to silence warnings about switches over enumerations
+ p.printLine(presetCaseString.arg("NumPresets"));
+ {
+ Printer::Indenter i(p);
+ p.printLine("Q_UNREACHABLE();");
+ }
+}
+
+static void printGradientData(Printer &p, const QJsonArray &presets)
+{
+ const QString formatString("{ { %1, %2, %3, %4 } },");
+
+ for (const QJsonValue &presetValue : presets) {
+ if (!presetValue.isObject()) {
+ p.printLine("{ { 0, 0, 0, 0 } },");
+ } else {
+ QJsonObject preset = presetValue.toObject();
+ const QJsonValue start = preset[QLatin1String("start")];
+ const QJsonValue end = preset[QLatin1String("end")];
+
+ p.printLine(formatString
+ .arg(start[QLatin1String("x")].toDouble())
+ .arg(start[QLatin1String("y")].toDouble())
+ .arg(end[QLatin1String("x")].toDouble())
+ .arg(end[QLatin1String("y")].toDouble()));
+ }
+ }
+}
+
+int main()
+{
+ QByteArray json;
+ while (!cin.eof()) {
+ char arr[1024];
+ cin.read(arr, sizeof(arr));
+ json.append(arr, cin.gcount());
+ }
+
+ QJsonParseError error;
+ QJsonDocument jsonDocument = QJsonDocument::fromJson(json, &error);
+ if (jsonDocument.isNull())
+ qFatal("Error: %s at offset %d", qPrintable(error.errorString()), error.offset);
+
+ if (!jsonDocument.isArray())
+ qFatal("Error: expected a document with a JSON array");
+
+ QJsonArray presets = jsonDocument.array();
+
+ Printer p;
+
+ p.printLine(LICENSE_HEADER);
+ p.printLine();
+ p.printLine("// This file is auto-generated by gradientgen. DO NOT EDIT!");
+ p.printLine();
+
+ p.printLine("static QArrayDataPointerRef<QGradientStop> qt_preset_gradient_stops(QGradient::Preset preset)");
+ p.printLine("{");
+ {
+ Printer::Indenter i(p);
+ p.printLine("Q_ASSERT(preset < QGradient::NumPresets);");
+ p.printLine("switch (preset) {");
+ printGradientStops(p, presets);
+ p.printLine("}");
+ p.printLine("Q_UNREACHABLE();");
+ p.printLine("return {};");
+ }
+ p.printLine("}");
+ p.printLine();
+
+ p.printLine("static Q_CONSTEXPR QGradient::QGradientData qt_preset_gradient_data[] = {");
+ {
+ Printer::Indenter i(p);
+ printGradientData(p, presets);
+ }
+ p.printLine("};");
+ p.printLine();
+
+ p.printLine("static void *qt_preset_gradient_dummy()");
+ p.printLine("{");
+ {
+ Printer::Indenter i(p);
+ p.printLine("union {void *p; uint i;};");
+ p.printLine("p = 0;");
+ p.printLine("i |= uint(QGradient::ObjectMode);");
+ p.printLine("return p;");
+ }
+ p.printLine("}");
+}