From c4a21708ed186640f4db381dc800febdbc85941e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 25 May 2018 17:12:07 +0200 Subject: Provide presets for QGradient MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Similar to Qt::GlobalColor, the presets allow the user to create brushes based on predefined gradients, quickly getting pretty pixels on screen. The presets are based on the linear gradients from WebGradients, a free collection of gradients, hosted at https://webgradients.com/. The few radial and blended gradient presets have been excluded. Change-Id: I1ce8f2210a6045c9edb8829ab3eddcc313549127 Reviewed-by: Tor Arne Vestbø --- util/gradientgen/.gitignore | 2 + util/gradientgen/gradientgen.js | 123 +++++++++++++++++++++++++ util/gradientgen/package-lock.json | 183 +++++++++++++++++++++++++++++++++++++ util/gradientgen/package.json | 13 +++ util/gradientgen/tobinaryjson.cpp | 54 +++++++++++ util/gradientgen/tobinaryjson.pro | 4 + 6 files changed, 379 insertions(+) create mode 100644 util/gradientgen/.gitignore create mode 100755 util/gradientgen/gradientgen.js create mode 100644 util/gradientgen/package-lock.json create mode 100644 util/gradientgen/package.json create mode 100644 util/gradientgen/tobinaryjson.cpp create mode 100644 util/gradientgen/tobinaryjson.pro (limited to 'util') diff --git a/util/gradientgen/.gitignore b/util/gradientgen/.gitignore new file mode 100644 index 0000000000..1a8e824bee --- /dev/null +++ b/util/gradientgen/.gitignore @@ -0,0 +1,2 @@ +node_modules +tobinaryjson diff --git a/util/gradientgen/gradientgen.js b/util/gradientgen/gradientgen.js new file mode 100755 index 0000000000..ff256d16d6 --- /dev/null +++ b/util/gradientgen/gradientgen.js @@ -0,0 +1,123 @@ +#! /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] "); + process.exit(1); +} + +const filename = process.argv[argc - 1]; +const mode = argc > 3 ? process.argv[argc - 2] : ''; + +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 = [] + args.slice(1).forEach((arg, index) => { + let [color, stop = !index ? '0%' : '100%'] = arg; + stop = parseInt(stop) / 100; + color = parseColor(color).hex; + color = parseInt(color.slice(1), 16) + stops.push({ color, stop }) + }); + + gradients[gradients.length - 1] = { start, end, stops }; + }); + + enums.push(name); + + if (mode == 'enums') + console.log(`${name} = ${gradients.length},`) + }); + + // Done walking declarations + if (mode != 'enums') + console.log(JSON.stringify(gradients, undefined, 4)); + }); +}); diff --git a/util/gradientgen/package-lock.json b/util/gradientgen/package-lock.json new file mode 100644 index 0000000000..77939b7fe3 --- /dev/null +++ b/util/gradientgen/package-lock.json @@ -0,0 +1,183 @@ +{ + "name": "gradientgen", + "version": "0.0.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, + "complex.js": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/complex.js/-/complex.js-2.0.4.tgz", + "integrity": "sha512-Syl95HpxUTS0QjwNxencZsKukgh1zdS9uXeXX2Us0pHaqBR6kiZZi0AkZ9VpZFwHJyVIUVzI4EumjWdXP3fy6w==" + }, + "decimal.js": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-9.0.1.tgz", + "integrity": "sha512-2h0iKbJwnImBk4TGk7CG1xadoA0g3LDPlQhQzbZ221zvG0p2YVUedbKIPsOZXKZGx6YmZMJKYOalpCMxSdDqTQ==" + }, + "escape-latex": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-latex/-/escape-latex-1.0.3.tgz", + "integrity": "sha512-GfKaG/7FOKdIdciylIzgaShBTPjdGQ5LJ2EcKLKXPLpcMO1MvCEVotkhydEShwCINRacZr2r3fk5A1PwZ4e5sA==" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "fraction.js": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.0.4.tgz", + "integrity": "sha512-aK/oGatyYLTtXRHjfEsytX5fieeR5H4s8sLorzcT12taFS+dbMZejnvm9gRa8mZAPwci24ucjq9epDyaq5u8Iw==" + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=" + }, + "javascript-natural-sort": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz", + "integrity": "sha1-+eIwPUUH9tdDVac2ZNFED7Wg71k=" + }, + "js-base64": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.3.tgz", + "integrity": "sha512-H7ErYLM34CvDMto3GbD6xD0JLUGYXR3QTcH6B/tr4Hi/QpSThnCsIp+Sy5FRTw3B0d6py4HcNkW7nO/wdtGWEw==" + }, + "lodash": { + "version": "4.17.10", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.10.tgz", + "integrity": "sha512-UejweD1pDoXu+AD825lWwp4ZGtSwgnpZxb3JDViD7StjQz+Nb/6l093lx4OQ0foGWNRoc19mWy7BzL+UAK2iVg==" + }, + "mathjs": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/mathjs/-/mathjs-4.2.2.tgz", + "integrity": "sha512-AKrRfTeGrCBqYN1TYEpLIwrfZh9rKu9lH4n7K0MwTiYqN5crJ7BKh/TnErFvbUmyRVQDv87UjSfNTqeO0JA0JQ==", + "requires": { + "complex.js": "2.0.4", + "decimal.js": "9.0.1", + "escape-latex": "1.0.3", + "fraction.js": "4.0.4", + "javascript-natural-sort": "0.7.1", + "seed-random": "2.2.0", + "tiny-emitter": "2.0.2", + "typed-function": "1.0.3" + } + }, + "parse-color": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-color/-/parse-color-1.0.0.tgz", + "integrity": "sha1-e3SLlag/A/FqlPU15S1/PZRlhhk=", + "requires": { + "color-convert": "0.5.3" + }, + "dependencies": { + "color-convert": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz", + "integrity": "sha1-vbbGnOZg+t/+CwAHzER+G59ygr0=" + } + } + }, + "postcss": { + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", + "requires": { + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "postcss-minify-gradients": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-1.0.5.tgz", + "integrity": "sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE=", + "requires": { + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" + } + }, + "postcss-value-parser": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.0.tgz", + "integrity": "sha1-h/OPnxj3dKSrTIojL1xc6IcqnRU=" + }, + "seed-random": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/seed-random/-/seed-random-2.2.0.tgz", + "integrity": "sha1-KpsZ4lCoFwmSMaW5mk2vgLf77VQ=" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "requires": { + "has-flag": "1.0.0" + } + }, + "tiny-emitter": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.0.2.tgz", + "integrity": "sha512-2NM0auVBGft5tee/OxP4PI3d8WItkDM+fPnaRAVo6xTDI2knbz9eC5ArWGqtGlYqiH3RU5yMpdyTTO7MguC4ow==" + }, + "typed-function": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-function/-/typed-function-1.0.3.tgz", + "integrity": "sha512-sVC/1pm70oELDFMdYtFXMFqyawenLoaDiAXA3QvOAwKF/WvFNTSJN23cY2lFNL8iP0kh3T0PPKewrboO8XUVGQ==" + } + } +} diff --git a/util/gradientgen/package.json b/util/gradientgen/package.json new file mode 100644 index 0000000000..35c324b8cc --- /dev/null +++ b/util/gradientgen/package.json @@ -0,0 +1,13 @@ +{ + "name": "gradientgen", + "version": "0.0.1", + "description": "Generates gradient presets for QGradient", + "main": "gradientgen.js", + "dependencies": { + "lodash": "^4.17.10", + "mathjs": "^4.2.2", + "parse-color": "^1.0.0", + "postcss-minify-gradients": "^1.0.5", + "postcss-value-parser": "^3.3.0" + } +} diff --git a/util/gradientgen/tobinaryjson.cpp b/util/gradientgen/tobinaryjson.cpp new file mode 100644 index 0000000000..65fe07f4b8 --- /dev/null +++ b/util/gradientgen/tobinaryjson.cpp @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include + +#include +#include + +using namespace std; + +int main() +{ + QByteArray json; + while (!cin.eof()) { + char arr[1024]; + cin.read(arr, sizeof(arr)); + json.append(arr, cin.gcount()); + } + + QJsonParseError error; + QJsonDocument document = QJsonDocument::fromJson(json, &error); + if (document.isNull()) { + qDebug() << "error:" << qPrintable(error.errorString()) << "at offset" << error.offset; + return 1; + } + + QByteArray binaryJson = document.toBinaryData(); + cout.write(binaryJson.constData(), binaryJson.size()); +} diff --git a/util/gradientgen/tobinaryjson.pro b/util/gradientgen/tobinaryjson.pro new file mode 100644 index 0000000000..8ed3509278 --- /dev/null +++ b/util/gradientgen/tobinaryjson.pro @@ -0,0 +1,4 @@ +SOURCES += tobinaryjson.cpp +QT = core +CONFIG += console +CONFIG -= app_bundle -- cgit v1.2.3