134 lines
4.3 KiB
JavaScript
134 lines
4.3 KiB
JavaScript
|
#! /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));
|
||
|
});
|
||
|
});
|