diff options
Diffstat (limited to 'util/gradientgen/gradientgen.js')
-rwxr-xr-x | util/gradientgen/gradientgen.js | 133 |
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)); + }); +}); |