summaryrefslogtreecommitdiffstats
path: root/util/gradientgen/gradientgen.js
diff options
context:
space:
mode:
Diffstat (limited to 'util/gradientgen/gradientgen.js')
-rwxr-xr-xutil/gradientgen/gradientgen.js133
1 files changed, 133 insertions, 0 deletions
diff --git a/util/gradientgen/gradientgen.js b/util/gradientgen/gradientgen.js
new file mode 100755
index 0000000000..434f05b2bb
--- /dev/null
+++ b/util/gradientgen/gradientgen.js
@@ -0,0 +1,133 @@
+#! /usr/bin/env node
+
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** 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$
+**
+****************************************************************************/
+
+const _ = require('lodash');
+const fs = require('fs');
+
+const postcss = require('postcss');
+const minifyGradients = require('postcss-minify-gradients');
+const valueParser = require('postcss-value-parser');
+const parseColor = require('parse-color');
+const math = require('mathjs');
+
+const argc = process.argv.length;
+if (argc < 3) {
+ console.log("usage: gradientgen [mode] <filename>");
+ process.exit(1);
+}
+
+const filename = process.argv[argc - 1];
+const mode = argc > 3 ? process.argv[argc - 2] : 'json';
+
+fs.readFile(filename, (err, css) => {
+ postcss([minifyGradients]).process(css)
+ .then(result => {
+ let enums = [];
+ let gradients = [];
+
+ result.root.walkRules(rule => {
+ gradients.push(null); // Placeholder
+
+ const name = _.startCase(rule.selector).replace(/\s/g, '');
+ if (enums.indexOf(name) >= 0)
+ return; // Duplicate entry
+
+ // We can only support single gradient declarations
+ if (rule.nodes.length > 1)
+ return;
+
+ valueParser(rule.nodes[0].value).walk(node => {
+ if (node.type !== 'function')
+ return;
+
+ if (node.value !== 'linear-gradient')
+ return;
+
+ const args = node.nodes.reduce((args, arg) => {
+ if (arg.type === 'div')
+ args.push([]);
+ else if (arg.type !== 'space')
+ args[args.length - 1].push(arg.value);
+ return args;
+ }, [[]]);
+
+ let angle = valueParser.unit(args[0][0]);
+ if (angle.unit !== 'deg')
+ return;
+
+ angle = parseInt(angle.number);
+ if (angle < 0)
+ angle += 360;
+
+ // Angle is in degrees, but we need radians
+ const radians = angle * math.pi / 180;
+
+ const gradientLine = (math.abs(math.sin(radians)) + math.abs(math.cos(radians)));
+ const cathetus = fn => math.round(fn(radians - math.pi / 2) * gradientLine / 2, 10);
+
+ const x = cathetus(math.cos);
+ const y = cathetus(math.sin);
+
+ const start = { x: 0.5 - x, y: 0.5 - y };
+ const end = { x: 0.5 + x, y: 0.5 + y };
+
+ let stops = []
+
+ let lastPosition = 0;
+ args.slice(1).forEach((arg, index) => {
+ let [color, position = !index ? '0%' : '100%'] = arg;
+ position = parseInt(position) / 100;
+ if (position < lastPosition)
+ position = lastPosition;
+ lastPosition = position;
+ color = parseColor(color).hex;
+ color = parseInt(color.slice(1), 16)
+ stops.push({ color, position })
+ });
+
+ gradients[gradients.length - 1] = { start, end, stops };
+ });
+
+ if (!gradients[gradients.length - 1])
+ return; // Not supported
+
+ enums.push(name);
+
+ if (mode == 'debug')
+ console.log(name, args, gradients[gradients.length - 1])
+ else if (mode == 'enums')
+ console.log(`${name} = ${gradients.length},`)
+ });
+
+ // Done walking declarations
+ if (mode == 'json')
+ console.log(JSON.stringify(gradients, undefined, 4));
+ });
+});