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ø --- examples/gui/rasterwindow/rasterwindow.cpp | 2 +- src/gui/painting/WEBGRADIENTS_LICENSE.txt | 21 + src/gui/painting/painting.pri | 7 +- src/gui/painting/qbrush.cpp | 70 ++ src/gui/painting/qbrush.h | 174 +++++ src/gui/painting/qpainter.cpp | 31 + src/gui/painting/qpainter.h | 18 + src/gui/painting/qt_attribution.json | 16 +- src/gui/painting/webgradients.binaryjson | Bin 0 -> 49052 bytes src/gui/painting/webgradients.css | 909 ++++++++++++++++++++++++++ tests/auto/gui/painting/qbrush/tst_qbrush.cpp | 21 + 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 + 17 files changed, 1645 insertions(+), 3 deletions(-) create mode 100644 src/gui/painting/WEBGRADIENTS_LICENSE.txt create mode 100644 src/gui/painting/webgradients.binaryjson create mode 100644 src/gui/painting/webgradients.css 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 diff --git a/examples/gui/rasterwindow/rasterwindow.cpp b/examples/gui/rasterwindow/rasterwindow.cpp index e240b7f31c..4dd2ac25ca 100644 --- a/examples/gui/rasterwindow/rasterwindow.cpp +++ b/examples/gui/rasterwindow/rasterwindow.cpp @@ -107,7 +107,7 @@ void RasterWindow::renderNow() QPaintDevice *device = m_backingStore->paintDevice(); QPainter painter(device); - painter.fillRect(0, 0, width(), height(), Qt::white); + painter.fillRect(0, 0, width(), height(), QGradient::NightFade); render(&painter); painter.end(); diff --git a/src/gui/painting/WEBGRADIENTS_LICENSE.txt b/src/gui/painting/WEBGRADIENTS_LICENSE.txt new file mode 100644 index 0000000000..1a4d527a4d --- /dev/null +++ b/src/gui/painting/WEBGRADIENTS_LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 itmeo + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index 29bef14f0c..749cc221ff 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -99,8 +99,13 @@ SOURCES += \ painting/qplatformbackingstore.cpp \ painting/qpathsimplifier.cpp +webgradients.files = painting/webgradients.binaryjson +webgradients.prefix = qgradient +webgradients.base = painting + RESOURCES += \ - painting/qpdf.qrc + painting/qpdf.qrc \ + webgradients darwin { HEADERS += painting/qcoregraphics_p.h diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp index 5c13308d94..c667454cd2 100644 --- a/src/gui/painting/qbrush.cpp +++ b/src/gui/painting/qbrush.cpp @@ -46,9 +46,13 @@ #include "qvariant.h" #include "qline.h" #include "qdebug.h" +#include +#include #include #include "private/qhexstring_p.h" #include +#include +#include QT_BEGIN_NAMESPACE @@ -1330,6 +1334,72 @@ QGradient::QGradient() { } +/*! + \enum QGradient::Preset + \since 5.12 + + This enum specifies a set of predefined presets for QGradient, + based on the gradients from https://webgradients.com/. +*/ + +/*! + \fn QGradient::QGradient(QGradient::Preset preset) + \since 5.12 + + Constructs a gradient based on a predefined \a preset. + + The coordinate mode of the resulting gradient is + QGradient::ObjectBoundingMode, allowing the preset + to be applied to arbitrary object sizes. +*/ +QGradient::QGradient(Preset preset) + : QGradient() +{ + static QHash cachedPresets; + static QMutex cacheMutex; + QMutexLocker locker(&cacheMutex); + if (cachedPresets.contains(preset)) { + const QGradient &cachedPreset = cachedPresets.value(preset); + m_type = cachedPreset.m_type; + m_data = cachedPreset.m_data; + m_stops = cachedPreset.m_stops; + m_spread = cachedPreset.m_spread; + dummy = cachedPreset.dummy; + } else { + static QJsonDocument jsonPresets = []() { + QFile webGradients(QLatin1String(":/qgradient/webgradients.binaryjson")); + webGradients.open(QFile::ReadOnly); + return QJsonDocument::fromBinaryData(webGradients.readAll()); + }(); + + const QJsonValue presetData = jsonPresets[preset - 1]; + if (!presetData.isObject()) + return; + + m_type = LinearGradient; + setCoordinateMode(ObjectBoundingMode); + setSpread(PadSpread); + + const QJsonValue start = presetData[QLatin1Literal("start")]; + const QJsonValue end = presetData[QLatin1Literal("end")]; + m_data.linear.x1 = start[QLatin1Literal("x")].toDouble(); + m_data.linear.y1 = start[QLatin1Literal("y")].toDouble(); + m_data.linear.x2 = end[QLatin1Literal("x")].toDouble(); + m_data.linear.y2 = end[QLatin1Literal("y")].toDouble(); + + for (const QJsonValue &stop : presetData[QLatin1String("stops")].toArray()) { + setColorAt(stop[QLatin1Literal("stop")].toDouble(), + QColor(QRgb(stop[QLatin1Literal("color")].toInt()))); + } + + cachedPresets.insert(preset, *this); + } +} + +QT_END_NAMESPACE +static void initGradientPresets() { Q_INIT_RESOURCE(qmake_webgradients); } +Q_CONSTRUCTOR_FUNCTION(initGradientPresets); +QT_BEGIN_NAMESPACE /*! \enum QGradient::Type diff --git a/src/gui/painting/qbrush.h b/src/gui/painting/qbrush.h index e5cff9cc9b..9023d2f43d 100644 --- a/src/gui/painting/qbrush.h +++ b/src/gui/painting/qbrush.h @@ -203,7 +203,181 @@ public: ComponentInterpolation }; + enum Preset { + WarmFlame = 1, + NightFade = 2, + SpringWarmth = 3, + JuicyPeach = 4, + YoungPassion = 5, + LadyLips = 6, + SunnyMorning = 7, + RainyAshville = 8, + FrozenDreams = 9, + WinterNeva = 10, + DustyGrass = 11, + TemptingAzure = 12, + HeavyRain = 13, + AmyCrisp = 14, + MeanFruit = 15, + DeepBlue = 16, + RipeMalinka = 17, + CloudyKnoxville = 18, + MalibuBeach = 19, + NewLife = 20, + TrueSunset = 21, + MorpheusDen = 22, + RareWind = 23, + NearMoon = 24, + WildApple = 25, + SaintPetersburg = 26, + AriellesSmile = 27, + PlumPlate = 28, + EverlastingSky = 29, + HappyFisher = 30, + Blessing = 31, + SharpeyeEagle = 32, + LadogaBottom = 33, + LemonGate = 34, + ItmeoBranding = 35, + ZeusMiracle = 36, + OldHat = 37, + StarWine = 38, + HappyAcid = 41, + AwesomePine = 42, + NewYork = 43, + ShyRainbow = 44, + MixedHopes = 46, + FlyHigh = 47, + StrongBliss = 48, + FreshMilk = 49, + SnowAgain = 50, + FebruaryInk = 51, + KindSteel = 52, + SoftGrass = 53, + GrownEarly = 54, + SharpBlues = 55, + ShadyWater = 56, + DirtyBeauty = 57, + GreatWhale = 58, + TeenNotebook = 59, + PoliteRumors = 60, + SweetPeriod = 61, + WideMatrix = 62, + SoftCherish = 63, + RedSalvation = 64, + BurningSpring = 65, + NightParty = 66, + SkyGlider = 67, + HeavenPeach = 68, + PurpleDivision = 69, + AquaSplash = 70, + SpikyNaga = 72, + LoveKiss = 73, + CleanMirror = 75, + PremiumDark = 76, + ColdEvening = 77, + CochitiLake = 78, + SummerGames = 79, + PassionateBed = 80, + MountainRock = 81, + DesertHump = 82, + JungleDay = 83, + PhoenixStart = 84, + OctoberSilence = 85, + FarawayRiver = 86, + AlchemistLab = 87, + OverSun = 88, + PremiumWhite = 89, + MarsParty = 90, + EternalConstance = 91, + JapanBlush = 92, + SmilingRain = 93, + CloudyApple = 94, + BigMango = 95, + HealthyWater = 96, + AmourAmour = 97, + RiskyConcrete = 98, + StrongStick = 99, + ViciousStance = 100, + PaloAlto = 101, + HappyMemories = 102, + MidnightBloom = 103, + Crystalline = 104, + PartyBliss = 106, + ConfidentCloud = 107, + LeCocktail = 108, + RiverCity = 109, + FrozenBerry = 110, + ChildCare = 112, + FlyingLemon = 113, + NewRetrowave = 114, + HiddenJaguar = 115, + AboveTheSky = 116, + Nega = 117, + DenseWater = 118, + Seashore = 120, + MarbleWall = 121, + CheerfulCaramel = 122, + NightSky = 123, + MagicLake = 124, + YoungGrass = 125, + ColorfulPeach = 126, + GentleCare = 127, + PlumBath = 128, + HappyUnicorn = 129, + AfricanField = 131, + SolidStone = 132, + OrangeJuice = 133, + GlassWater = 134, + NorthMiracle = 136, + FruitBlend = 137, + MillenniumPine = 138, + HighFlight = 139, + MoleHall = 140, + SpaceShift = 142, + ForestInei = 143, + RoyalGarden = 144, + RichMetal = 145, + JuicyCake = 146, + SmartIndigo = 147, + SandStrike = 148, + NorseBeauty = 149, + AquaGuidance = 150, + SunVeggie = 151, + SeaLord = 152, + BlackSea = 153, + GrassShampoo = 154, + LandingAircraft = 155, + WitchDance = 156, + SleeplessNight = 157, + AngelCare = 158, + CrystalRiver = 159, + SoftLipstick = 160, + SaltMountain = 161, + PerfectWhite = 162, + FreshOasis = 163, + StrictNovember = 164, + MorningSalad = 165, + DeepRelief = 166, + SeaStrike = 167, + NightCall = 168, + SupremeSky = 169, + LightBlue = 170, + MindCrawl = 171, + LilyMeadow = 172, + SugarLollipop = 173, + SweetDessert = 174, + MagicRay = 175, + TeenParty = 176, + FrozenHeat = 177, + GagarinView = 178, + FabledSunset = 179, + PerfectBlue = 180 + }; + Q_ENUM(Preset) + QGradient(); + QGradient(Preset); Type type() const { return m_type; } diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index a37511ff0a..4a18df899e 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -7084,6 +7084,37 @@ void QPainter::fillRect(const QRectF &r, const QColor &color) \since 4.5 */ +/*! + \fn void QPainter::fillRect(int x, int y, int width, int height, QGradient::Preset preset) + + \overload + + Fills the rectangle beginning at (\a{x}, \a{y}) with the given \a + width and \a height, using the given gradient \a preset. + + \since 5.12 +*/ + +/*! + \fn void QPainter::fillRect(const QRect &rectangle, QGradient::Preset preset); + + \overload + + Fills the given \a rectangle with the specified gradient \a preset. + + \since 5.12 +*/ + +/*! + \fn void QPainter::fillRect(const QRectF &rectangle, QGradient::Preset preset); + + \overload + + Fills the given \a rectangle with the specified gradient \a preset. + + \since 5.12 +*/ + /*! Sets the given render \a hint on the painter if \a on is true; otherwise clears the render hint. diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h index 12a9c720a8..482f5fb63d 100644 --- a/src/gui/painting/qpainter.h +++ b/src/gui/painting/qpainter.h @@ -448,6 +448,10 @@ public: inline void fillRect(const QRect &r, Qt::BrushStyle style); inline void fillRect(const QRectF &r, Qt::BrushStyle style); + inline void fillRect(int x, int y, int w, int h, QGradient::Preset preset); + inline void fillRect(const QRect &r, QGradient::Preset preset); + inline void fillRect(const QRectF &r, QGradient::Preset preset); + void eraseRect(const QRectF &); inline void eraseRect(int x, int y, int w, int h); inline void eraseRect(const QRect &); @@ -746,6 +750,20 @@ inline void QPainter::fillRect(const QRectF &r, Qt::BrushStyle style) fillRect(r, QBrush(style)); } +inline void QPainter::fillRect(int x, int y, int w, int h, QGradient::Preset p) +{ + fillRect(QRect(x, y, w, h), QGradient(p)); +} + +inline void QPainter::fillRect(const QRect &r, QGradient::Preset p) +{ + fillRect(r, QGradient(p)); +} + +inline void QPainter::fillRect(const QRectF &r, QGradient::Preset p) +{ + fillRect(r, QGradient(p)); +} inline void QPainter::setBrushOrigin(int x, int y) { diff --git a/src/gui/painting/qt_attribution.json b/src/gui/painting/qt_attribution.json index 06a62d9d66..6aed115d01 100644 --- a/src/gui/painting/qt_attribution.json +++ b/src/gui/painting/qt_attribution.json @@ -27,5 +27,19 @@ "Copyright": "Copyright (C) 2004, 2005 Daniel M. Duley. (C) Carsten Haitzler and various contributors. (C) Willem Monsuwe " - } + }, + { + "Id": "webgradients", + "Name": "WebGradients", + "QDocModule": "qtgui", + "QtUsage": "Used in Qt GUI to provide presets for QGradient.", + "Files": "webgradients.css", + + "Description": "WebGradients is a free collection of 180 linear gradients.", + "Homepage": "https://webgradients.com/", + "License": "MIT License", + "LicenseId": "MIT", + "LicenseFile": "WEBGRADIENTS_LICENSE.txt", + "Copyright": "Copyright (c) 2017 itmeo" + }, ] diff --git a/src/gui/painting/webgradients.binaryjson b/src/gui/painting/webgradients.binaryjson new file mode 100644 index 0000000000..15b798f7ba Binary files /dev/null and b/src/gui/painting/webgradients.binaryjson differ diff --git a/src/gui/painting/webgradients.css b/src/gui/painting/webgradients.css new file mode 100644 index 0000000000..870866bb46 --- /dev/null +++ b/src/gui/painting/webgradients.css @@ -0,0 +1,909 @@ +/*001 Warm Flame*/ +.warm_flame{ + background-image: linear-gradient(45deg, #ff9a9e 0%, #fad0c4 99%, #fad0c4 100%); +} + +/*002 Night Fade*/ +.night_fade{ + background-image: linear-gradient(to top, #a18cd1 0%, #fbc2eb 100%); +} + +/*003 Spring Warmth*/ +.spring_warmth{ + background-image: linear-gradient(to top, #fad0c4 0%, #fad0c4 1%, #ffd1ff 100%); +} + +/*004 Juicy Peach*/ +.juicy_peach{ + background-image: linear-gradient(to right, #ffecd2 0%, #fcb69f 100%); +} + +/*005 Young Passion*/ +.young_passion{ + background-image: linear-gradient(to right, #ff8177 0%, #ff867a 0%, #ff8c7f 21%, #f99185 52%, #cf556c 78%, #b12a5b 100%); +} + +/*006 Lady Lips*/ +.lady_lips{ + background-image: linear-gradient(to top, #ff9a9e 0%, #fecfef 99%, #fecfef 100%); +} + +/*007 Sunny Morning*/ +.sunny_morning{ + background-image: linear-gradient(120deg, #f6d365 0%, #fda085 100%); +} + +/*008 Rainy Ashville*/ +.rainy_ashville{ + background-image: linear-gradient(to top, #fbc2eb 0%, #a6c1ee 100%); +} + +/*009 Frozen Dreams*/ +.frozen_dreams{ + background-image: linear-gradient(to top, #fdcbf1 0%, #fdcbf1 1%, #e6dee9 100%); +} + +/*010 Winter Neva*/ +.winter_neva{ + background-image: linear-gradient(120deg, #a1c4fd 0%, #c2e9fb 100%); +} + +/*011 Dusty Grass*/ +.dusty_grass{ + background-image: linear-gradient(120deg, #d4fc79 0%, #96e6a1 100%); +} + +/*012 Tempting Azure*/ +.tempting_azure{ + background-image: linear-gradient(120deg, #84fab0 0%, #8fd3f4 100%); +} + +/*013 Heavy Rain*/ +.heavy_rain{ + background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%); +} + +/*014 Amy Crisp*/ +.amy_crisp{ + background-image: linear-gradient(120deg, #a6c0fe 0%, #f68084 100%); +} + +/*015 Mean Fruit*/ +.mean_fruit{ + background-image: linear-gradient(120deg, #fccb90 0%, #d57eeb 100%); +} + +/*016 Deep Blue*/ +.deep_blue{ + background-image: linear-gradient(120deg, #e0c3fc 0%, #8ec5fc 100%); +} + +/*017 Ripe Malinka*/ +.ripe_malinka{ + background-image: linear-gradient(120deg, #f093fb 0%, #f5576c 100%); +} + +/*018 Cloudy Knoxville*/ +.cloudy_knoxville{ + background-image: linear-gradient(120deg, #fdfbfb 0%, #ebedee 100%); +} + +/*019 Malibu Beach*/ +.malibu_beach{ + background-image: linear-gradient(to right, #4facfe 0%, #00f2fe 100%); +} + +/*020 New Life*/ +.new_life{ + background-image: linear-gradient(to right, #43e97b 0%, #38f9d7 100%); +} + +/*021 True Sunset*/ +.true_sunset{ + background-image: linear-gradient(to right, #fa709a 0%, #fee140 100%); +} + +/*022 Morpheus Den*/ +.morpheus_den{ + background-image: linear-gradient(to top, #30cfd0 0%, #330867 100%); +} + +/*023 Rare Wind*/ +.rare_wind{ + background-image: linear-gradient(to top, #a8edea 0%, #fed6e3 100%); +} + +/*024 Near Moon*/ +.near_moon{ + background-image: linear-gradient(to top, #5ee7df 0%, #b490ca 100%); +} + +/*025 Wild Apple*/ +.wild_apple{ + background-image: linear-gradient(to top, #d299c2 0%, #fef9d7 100%); +} + +/*026 Saint Petersburg*/ +.saint_petersburg{ + background-image: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); +} + +/*027 Arielle's Smile*/ +.arielles_smile{ + background-image: radial-gradient(circle 248px at center, #16d9e3 0%, #30c7ec 47%, #46aef7 100%); +} + +/*028 Plum Plate*/ +.plum_plate{ + background-image: linear-gradient(135deg, #667eea 0%, #764ba2 100%); +} + +/*029 Everlasting Sky*/ +.everlasting_sky{ + background-image: linear-gradient(135deg, #fdfcfb 0%, #e2d1c3 100%); +} + +/*030 Happy Fisher*/ +.happy_fisher{ + background-image: linear-gradient(120deg, #89f7fe 0%, #66a6ff 100%); +} + +/*031 Blessing*/ +.blessing{ + background-image: linear-gradient(to top, #fddb92 0%, #d1fdff 100%); +} + +/*032 Sharpeye Eagle*/ +.sharpeye_eagle{ + background-image: linear-gradient(to top, #9890e3 0%, #b1f4cf 100%); +} + +/*033 Ladoga Bottom*/ +.ladoga_bottom{ + background-image: linear-gradient(to top, #ebc0fd 0%, #d9ded8 100%); +} + +/*034 Lemon Gate*/ +.lemon_gate{ + background-image: linear-gradient(to top, #96fbc4 0%, #f9f586 100%); +} + +/*035 Itmeo Branding*/ +.itmeo_branding{ + background-image: linear-gradient(180deg, #2af598 0%, #009efd 100%); +} + +/*036 Zeus Miracle*/ +.zeus_miracle{ + background-image: linear-gradient(to top, #cd9cf2 0%, #f6f3ff 100%); +} + +/*037 Old Hat*/ +.old_hat{ + background-image: linear-gradient(to right, #e4afcb 0%, #b8cbb8 0%, #b8cbb8 0%, #e2c58b 30%, #c2ce9c 64%, #7edbdc 100%); +} + +/*038 Star Wine*/ +.star_wine{ + background-image: linear-gradient(to right, #b8cbb8 0%, #b8cbb8 0%, #b465da 0%, #cf6cc9 33%, #ee609c 66%, #ee609c 100%); +} + +/*039 Deep Blue*/ +.deep_blue{ + background-image: linear-gradient(to right, #6a11cb 0%, #2575fc 100%); +} + +/*040 Coup de Grace*/ +.coup_de_grace{ + background: #DCD9D4 linear-gradient(to bottom, rgba(255, 255, 255, 0.50) 0%, rgba(0, 0, 0, 0.50) 100%), radial-gradient(at 50% 0%, rgba(255, 255, 255, 0.10) 0%, rgba(0, 0, 0, 0.50) 50%); + background-blend-mode: soft-light,screen; +} + +/*041 Happy Acid*/ +.happy_acid{ + background-image: linear-gradient(to top, #37ecba 0%, #72afd3 100%); +} + +/*042 Awesome Pine*/ +.awesome_pine{ + background-image: linear-gradient(to top, #ebbba7 0%, #cfc7f8 100%); +} + +/*043 New York*/ +.new_york{ + background-image: linear-gradient(to top, #fff1eb 0%, #ace0f9 100%); +} + +/*044 Shy Rainbow*/ +.shy_rainbow{ + background-image: linear-gradient(to right, #eea2a2 0%, #bbc1bf 19%, #57c6e1 42%, #b49fda 79%, #7ac5d8 100%); +} + +/*045 Loon Crest*/ +.loon_crest{ + background: linear-gradient(to bottom, rgba(255,255,255,0.15) 0%, rgba(0,0,0,0.15) 100%), radial-gradient(at top center, rgba(255,255,255,0.40) 0%, rgba(0,0,0,0.40) 120%) #989898; + background-blend-mode: multiply,multiply; +} + +/*046 Mixed Hopes*/ +.mixed_hopes{ + background-image: linear-gradient(to top, #c471f5 0%, #fa71cd 100%); +} + +/*047 Fly High*/ +.fly_high{ + background-image: linear-gradient(to top, #48c6ef 0%, #6f86d6 100%); +} + +/*048 Strong Bliss*/ +.strong_bliss{ + background-image: linear-gradient(to right, #f78ca0 0%, #f9748f 19%, #fd868c 60%, #fe9a8b 100%); +} + +/*049 Fresh Milk*/ +.fresh_milk{ + background-image: linear-gradient(to top, #feada6 0%, #f5efef 100%); +} + +/*050 Snow Again*/ +.snow_again{ + background-image: linear-gradient(to top, #e6e9f0 0%, #eef1f5 100%); +} + +/*051 February Ink*/ +.february_ink{ + background-image: linear-gradient(to top, #accbee 0%, #e7f0fd 100%); +} + +/*052 Kind Steel*/ +.kind_steel{ + background-image: linear-gradient(-20deg, #e9defa 0%, #fbfcdb 100%); +} + +/*053 Soft Grass*/ +.soft_grass{ + background-image: linear-gradient(to top, #c1dfc4 0%, #deecdd 100%); +} + +/*054 Grown Early*/ +.grown_early{ + background-image: linear-gradient(to top, #0ba360 0%, #3cba92 100%); +} + +/*055 Sharp Blues*/ +.sharp_blues{ + background-image: linear-gradient(to top, #00c6fb 0%, #005bea 100%); +} + +/*056 Shady Water*/ +.shady_water{ + background-image: linear-gradient(to right, #74ebd5 0%, #9face6 100%); +} + +/*057 Dirty Beauty*/ +.dirty_beauty{ + background-image: linear-gradient(to top, #6a85b6 0%, #bac8e0 100%); +} + +/*058 Great Whale*/ +.great_whale{ + background-image: linear-gradient(to top, #a3bded 0%, #6991c7 100%); +} + +/*059 Teen Notebook*/ +.teen_notebook{ + background-image: linear-gradient(to top, #9795f0 0%, #fbc8d4 100%); +} + +/*060 Polite Rumors*/ +.polite_rumors{ + background-image: linear-gradient(to top, #a7a6cb 0%, #8989ba 52%, #8989ba 100%); +} + +/*061 Sweet Period*/ +.sweet_period{ + background-image: linear-gradient(to top, #3f51b1 0%, #5a55ae 13%, #7b5fac 25%, #8f6aae 38%, #a86aa4 50%, #cc6b8e 62%, #f18271 75%, #f3a469 87%, #f7c978 100%); +} + +/*062 Wide Matrix*/ +.wide_matrix{ + background-image: linear-gradient(to top, #fcc5e4 0%, #fda34b 15%, #ff7882 35%, #c8699e 52%, #7046aa 71%, #0c1db8 87%, #020f75 100%); +} + +/*063 Soft Cherish*/ +.soft_cherish{ + background-image: linear-gradient(to top, #dbdcd7 0%, #dddcd7 24%, #e2c9cc 30%, #e7627d 46%, #b8235a 59%, #801357 71%, #3d1635 84%, #1c1a27 100%); +} + +/*064 Red Salvation*/ +.red_salvation{ + background-image: linear-gradient(to top, #f43b47 0%, #453a94 100%); +} + +/*065 Burning Spring*/ +.burning_spring{ + background-image: linear-gradient(to top, #4fb576 0%, #44c489 30%, #28a9ae 46%, #28a2b7 59%, #4c7788 71%, #6c4f63 86%, #432c39 100%); +} + +/*066 Night Party*/ +.night_party{ + background-image: linear-gradient(to top, #0250c5 0%, #d43f8d 100%); +} + +/*067 Sky Glider*/ +.sky_glider{ + background-image: linear-gradient(to top, #88d3ce 0%, #6e45e2 100%); +} + +/*068 Heaven Peach*/ +.heaven_peach{ + background-image: linear-gradient(to top, #d9afd9 0%, #97d9e1 100%); +} + +/*069 Purple Division*/ +.purple_division{ + background-image: linear-gradient(to top, #7028e4 0%, #e5b2ca 100%); +} + +/*070 Aqua Splash*/ +.aqua_splash{ + background-image: linear-gradient(15deg, #13547a 0%, #80d0c7 100%); +} + +/*071 Above Clouds*/ +.above_clouds{ + background-image: linear-gradient(to left, #BDBBBE 0%, #9D9EA3 100%), radial-gradient(88% 271%, rgba(255, 255, 255, 0.25) 0%, rgba(254, 254, 254, 0.25) 1%, rgba(0, 0, 0, 0.25) 100%), radial-gradient(50% 100%, rgba(255, 255, 255, 0.30) 0%, rgba(0, 0, 0, 0.30) 100%); + background-blend-mode: normal, lighten, soft-light; +} + +/*072 Spiky Naga*/ +.spiky_naga{ + background-image: linear-gradient(to top, #505285 0%, #585e92 12%, #65689f 25%, #7474b0 37%, #7e7ebb 50%, #8389c7 62%, #9795d4 75%, #a2a1dc 87%, #b5aee4 100%); +} + +/*073 Love Kiss*/ +.love_kiss{ + background-image: linear-gradient(to top, #ff0844 0%, #ffb199 100%); +} + +/*074 Sharp Glass*/ +.sharp_glass{ + background: #C9CCD3 linear-gradient(-180deg, rgba(255, 255, 255, 0.50) 0%, rgba(0, 0, 0, 0.50) 100%); + background-blend-mode: lighten; +} + +/*075 Clean Mirror*/ +.clean_mirror{ + background-image: linear-gradient(45deg, #93a5cf 0%, #e4efe9 100%); +} + +/*076 Premium Dark*/ +.premium_dark{ + background-image: linear-gradient(to right, #434343 0%, black 100%); +} + +/*077 Cold Evening*/ +.cold_evening{ + background-image: linear-gradient(to top, #0c3483 0%, #a2b6df 100%, #6b8cce 100%, #a2b6df 100%); +} + +/*078 Cochiti Lake*/ +.cochiti_lake{ + background-image: linear-gradient(45deg, #93a5cf 0%, #e4efe9 100%); +} + +/*079 Summer Games*/ +.summer_games{ + background-image: linear-gradient(to right, #92fe9d 0%, #00c9ff 100%); +} + +/*080 Passionate Bed*/ +.passionate_bed{ + background-image: linear-gradient(to right, #ff758c 0%, #ff7eb3 100%); +} + +/*081 Mountain Rock*/ +.mountain_rock{ + background-image: linear-gradient(to right, #868f96 0%, #596164 100%); +} + +/*082 Desert Hump*/ +.desert_hump{ + background-image: linear-gradient(to top, #c79081 0%, #dfa579 100%); +} + +/*083 Jungle Day*/ +.jungle_day{ + background-image: linear-gradient(45deg, #8baaaa 0%, #ae8b9c 100%); +} + +/*084 Phoenix Start*/ +.phoenix_start{ + background-image: linear-gradient(to right, #f83600 0%, #f9d423 100%); +} + +/*085 October Silence*/ +.october_silence{ + background-image: linear-gradient(-20deg, #b721ff 0%, #21d4fd 100%); +} + +/*086 Faraway River*/ +.faraway_river{ + background-image: linear-gradient(-20deg, #6e45e2 0%, #88d3ce 100%); +} + +/*087 Alchemist Lab*/ +.alchemist_lab{ + background-image: linear-gradient(-20deg, #d558c8 0%, #24d292 100%); +} + +/*088 Over Sun*/ +.over_sun{ + background-image: linear-gradient(60deg, #abecd6 0%, #fbed96 100%); +} + +/*089 Premium White*/ +.premium_white{ + background-image: linear-gradient(to top, #d5d4d0 0%, #d5d4d0 1%, #eeeeec 31%, #efeeec 75%, #e9e9e7 100%); +} + +/*090 Mars Party*/ +.mars_party{ + background-image: linear-gradient(to top, #5f72bd 0%, #9b23ea 100%); +} + +/*091 Eternal Constance*/ +.eternal_constance{ + background-image: linear-gradient(to top, #09203f 0%, #537895 100%); +} + +/*092 Japan Blush*/ +.japan_blush{ + background-image: linear-gradient(-20deg, #ddd6f3 0%, #faaca8 100%, #faaca8 100%); +} + +/*093 Smiling Rain*/ +.smiling_rain{ + background-image: linear-gradient(-20deg, #dcb0ed 0%, #99c99c 100%); +} + +/*094 Cloudy Apple*/ +.cloudy_apple{ + background-image: linear-gradient(to top, #f3e7e9 0%, #e3eeff 99%, #e3eeff 100%); +} + +/*095 Big Mango*/ +.big_mango{ + background-image: linear-gradient(to top, #c71d6f 0%, #d09693 100%); +} + +/*096 Healthy Water*/ +.healthy_water{ + background-image: linear-gradient(60deg, #96deda 0%, #50c9c3 100%); +} + +/*097 Amour Amour*/ +.amour_amour{ + background-image: linear-gradient(to top, #f77062 0%, #fe5196 100%); +} + +/*098 Risky Concrete*/ +.risky_concrete{ + background-image: linear-gradient(to top, #c4c5c7 0%, #dcdddf 52%, #ebebeb 100%); +} + +/*099 Strong Stick*/ +.strong_stick{ + background-image: linear-gradient(to right, #a8caba 0%, #5d4157 100%); +} + +/*100 Vicious Stance*/ +.vicious_stance{ + background-image: linear-gradient(60deg, #29323c 0%, #485563 100%); +} + +/*101 Palo Alto*/ +.palo_alto{ + background-image: linear-gradient(-60deg, #16a085 0%, #f4d03f 100%); +} + +/*102 Happy Memories*/ +.happy_memories{ + background-image: linear-gradient(-60deg, #ff5858 0%, #f09819 100%); +} + +/*103 Midnight Bloom*/ +.midnight_bloom{ + background-image: linear-gradient(-20deg, #2b5876 0%, #4e4376 100%); +} + +/*104 Crystalline*/ +.crystalline{ + background-image: linear-gradient(-20deg, #00cdac 0%, #8ddad5 100%); +} + +/*105 Raccoon Back*/ +.raccoon_back{ + background: linear-gradient(-180deg, #BCC5CE 0%, #929EAD 98%), radial-gradient(at top left, rgba(255,255,255,0.30) 0%, rgba(0,0,0,0.30) 100%); + background-blend-mode: screen; +} + +/*106 Party Bliss*/ +.party_bliss{ + background-image: linear-gradient(to top, #4481eb 0%, #04befe 100%); +} + +/*107 Confident Cloud*/ +.confident_cloud{ + background-image: linear-gradient(to top, #dad4ec 0%, #dad4ec 1%, #f3e7e9 100%); +} + +/*108 Le Cocktail*/ +.le_cocktail{ + background-image: linear-gradient(45deg, #874da2 0%, #c43a30 100%); +} + +/*109 River City*/ +.river_city{ + background-image: linear-gradient(to top, #4481eb 0%, #04befe 100%); +} + +/*110 Frozen Berry*/ +.frozen_berry{ + background-image: linear-gradient(to top, #e8198b 0%, #c7eafd 100%); +} + +/*111 Elegance*/ +.elegance{ + background-image: radial-gradient(73% 147%, #EADFDF 59%, #ECE2DF 100%), radial-gradient(91% 146%, rgba(255,255,255,0.50) 47%, rgba(0,0,0,0.50) 100%); + background-blend-mode: screen; +} + +/*112 Child Care*/ +.child_care{ + background-image: linear-gradient(-20deg, #f794a4 0%, #fdd6bd 100%); +} + +/*113 Flying Lemon*/ +.flying_lemon{ + background-image: linear-gradient(60deg, #64b3f4 0%, #c2e59c 100%); +} + +/*114 New Retrowave*/ +.new_retrowave{ + background-image: linear-gradient(to top, #3b41c5 0%, #a981bb 49%, #ffc8a9 100%); +} + +/*115 Hidden Jaguar*/ +.hidden_jaguar{ + background-image: linear-gradient(to top, #0fd850 0%, #f9f047 100%); +} + +/*116 Above The Sky*/ +.above_the_sky{ + background-image: linear-gradient(to top, lightgrey 0%, lightgrey 1%, #e0e0e0 26%, #efefef 48%, #d9d9d9 75%, #bcbcbc 100%); +} + +/*117 Nega*/ +.nega{ + background-image: linear-gradient(45deg, #ee9ca7 0%, #ffdde1 100%); +} + +/*118 Dense Water*/ +.dense_water{ + background-image: linear-gradient(to right, #3ab5b0 0%, #3d99be 31%, #56317a 100%); +} + +/*119 Chemic Aqua*/ +.chemic_aqua{ + background: #CDDCDC radial-gradient(at 50% 100%, rgba(255, 255, 255, 0.50) 0%, rgba(0, 0, 0, 0.50) 100%), linear-gradient(to bottom, rgba(255, 255, 255, 0.25) 0%, rgba(0, 0, 0, 0.25) 100%); + background-blend-mode: screen, overlay; +} + +/*120 Seashore*/ +.seashore{ + background-image: linear-gradient(to top, #209cff 0%, #68e0cf 100%); +} + +/*121 Marble Wall*/ +.marble_wall{ + background-image: linear-gradient(to top, #bdc2e8 0%, #bdc2e8 1%, #e6dee9 100%); +} + +/*122 Cheerful Caramel*/ +.cheerful_caramel{ + background-image: linear-gradient(to top, #e6b980 0%, #eacda3 100%); +} + +/*123 Night Sky*/ +.night_sky{ + background-image: linear-gradient(to top, #1e3c72 0%, #1e3c72 1%, #2a5298 100%); +} + +/*124 Magic Lake*/ +.magic_lake{ + background-image: linear-gradient(to top, #d5dee7 0%, #ffafbd 0%, #c9ffbf 100%); +} + +/*125 Young Grass*/ +.young_grass{ + background-image: linear-gradient(to top, #9be15d 0%, #00e3ae 100%); +} + +/*126 Colorful Peach*/ +.colorful_peach{ + background-image: linear-gradient(to right, #ed6ea0 0%, #ec8c69 100%); +} + +/*127 Gentle Care*/ +.gentle_care{ + background-image: linear-gradient(to right, #ffc3a0 0%, #ffafbd 100%); +} + +/*128 Plum Bath*/ +.plum_bath{ + background-image: linear-gradient(to top, #cc208e 0%, #6713d2 100%); +} + +/*129 Happy Unicorn*/ +.happy_unicorn{ + background-image: linear-gradient(to top, #b3ffab 0%, #12fff7 100%); +} + +/*130 Full Metal*/ +.full_metal{ + background: linear-gradient(to bottom, #D5DEE7 0%, #E8EBF2 50%, #E2E7ED 100%), linear-gradient(to bottom, rgba(0,0,0,0.02) 50%, rgba(255,255,255,0.02) 61%, rgba(0,0,0,0.02) 73%), linear-gradient(33deg, rgba(255,255,255,0.20) 0%, rgba(0,0,0,0.20) 100%); + background-blend-mode: normal,color-burn; +} + +/*131 African Field*/ +.african_field{ + background-image: linear-gradient(to top, #65bd60 0%, #5ac1a8 25%, #3ec6ed 50%, #b7ddb7 75%, #fef381 100%); +} + +/*132 Solid Stone*/ +.solid_stone{ + background-image: linear-gradient(to right, #243949 0%, #517fa4 100%); +} + +/*133 Orange Juice*/ +.orange_juice{ + background-image: linear-gradient(-20deg, #fc6076 0%, #ff9a44 100%); +} + +/*134 Glass Water*/ +.glass_water{ + background-image: linear-gradient(to top, #dfe9f3 0%, white 100%); +} + +/*135 Slick Carbon*/ +.slick_carbon{ + background: linear-gradient(to bottom, #323232 0%, #3F3F3F 40%, #1C1C1C 150%), linear-gradient(to top, rgba(255,255,255,0.40) 0%, rgba(0,0,0,0.25) 200%); + background-blend-mode: multiply; +} + +/*136 North Miracle*/ +.north_miracle{ + background-image: linear-gradient(to right, #00dbde 0%, #fc00ff 100%); +} + +/*137 Fruit Blend*/ +.fruit_blend{ + background-image: linear-gradient(to right, #f9d423 0%, #ff4e50 100%); +} + +/*138 Millennium Pine*/ +.millennium_pine{ + background-image: linear-gradient(to top, #50cc7f 0%, #f5d100 100%); +} + +/*139 High Flight*/ +.high_flight{ + background-image: linear-gradient(to right, #0acffe 0%, #495aff 100%); +} + +/*140 Mole Hall*/ +.mole_hall{ + background-image: linear-gradient(-20deg, #616161 0%, #9bc5c3 100%); +} + +/*141 Earl Gray*/ +.earl_gray{ + background: #E4E4E1 radial-gradient(at top center, rgba(255, 255, 255, 0.03) 0%, rgba(0, 0, 0, 0.03) 100%), linear-gradient(to top, rgba(255, 255, 255, 0.1) 0%, rgba(143, 152, 157, 0.60) 100%); + background-blend-mode: normal, multiply; +} + +/*142 Space Shift*/ +.space_shift{ + background-image: linear-gradient(60deg, #3d3393 0%, #2b76b9 37%, #2cacd1 65%, #35eb93 100%); +} + +/*143 Forest Inei*/ +.forest_inei{ + background-image: linear-gradient(to top, #df89b5 0%, #bfd9fe 100%); +} + +/*144 Royal Garden*/ +.royal_garden{ + background-image: linear-gradient(to right, #ed6ea0 0%, #ec8c69 100%); +} + +/*145 Rich Metal*/ +.rich_metal{ + background-image: linear-gradient(to right, #d7d2cc 0%, #304352 100%); +} + +/*146 Juicy Cake*/ +.juicy_cake{ + background-image: linear-gradient(to top, #e14fad 0%, #f9d423 100%); +} + +/*147 Smart Indigo*/ +.smart_indigo{ + background-image: linear-gradient(to top, #b224ef 0%, #7579ff 100%); +} + +/*148 Sand Strike*/ +.sand_strike{ + background-image: linear-gradient(to right, #c1c161 0%, #c1c161 0%, #d4d4b1 100%); +} + +/*149 Norse Beauty*/ +.norse_beauty{ + background-image: linear-gradient(to right, #ec77ab 0%, #7873f5 100%); +} + +/*150 Aqua Guidance*/ +.aqua_guidance{ + background-image: linear-gradient(to top, #007adf 0%, #00ecbc 100%); +} + +/*151 Sun Veggie*/ +.sun_veggie{ + background-image: linear-gradient(-225deg, #20E2D7 0%, #F9FEA5 100%); +} + +/*152 Sea Lord*/ +.sea_lord{ + background-image: linear-gradient(-225deg, #2CD8D5 0%, #C5C1FF 56%, #FFBAC3 100%); +} + +/*153 Black Sea*/ +.black_sea{ + background-image: linear-gradient(-225deg, #2CD8D5 0%, #6B8DD6 48%, #8E37D7 100%); +} + +/*154 Grass Shampoo*/ +.grass_shampoo{ + background-image: linear-gradient(-225deg, #DFFFCD 0%, #90F9C4 48%, #39F3BB 100%); +} + +/*155 Landing Aircraft*/ +.landing_aircraft{ + background-image: linear-gradient(-225deg, #5D9FFF 0%, #B8DCFF 48%, #6BBBFF 100%); +} + +/*156 Witch Dance*/ +.witch_dance{ + background-image: linear-gradient(-225deg, #A8BFFF 0%, #884D80 100%); +} + +/*157 Sleepless Night*/ +.sleepless_night{ + background-image: linear-gradient(-225deg, #5271C4 0%, #B19FFF 48%, #ECA1FE 100%); +} + +/*158 Angel Care*/ +.angel_care{ + background-image: linear-gradient(-225deg, #FFE29F 0%, #FFA99F 48%, #FF719A 100%); +} + +/*159 Crystal River*/ +.crystal_river{ + background-image: linear-gradient(-225deg, #22E1FF 0%, #1D8FE1 48%, #625EB1 100%); +} + +/*160 Soft Lipstick*/ +.soft_lipstick{ + background-image: linear-gradient(-225deg, #B6CEE8 0%, #F578DC 100%); +} + +/*161 Salt Mountain*/ +.salt_mountain{ + background-image: linear-gradient(-225deg, #FFFEFF 0%, #D7FFFE 100%); +} + +/*162 Perfect White*/ +.perfect_white{ + background-image: linear-gradient(-225deg, #E3FDF5 0%, #FFE6FA 100%); +} + +/*163 Fresh Oasis*/ +.fresh_oasis{ + background-image: linear-gradient(-225deg, #7DE2FC 0%, #B9B6E5 100%); +} + +/*164 Strict November*/ +.strict_november{ + background-image: linear-gradient(-225deg, #CBBACC 0%, #2580B3 100%); +} + +/*165 Morning Salad*/ +.morning_salad{ + background-image: linear-gradient(-225deg, #B7F8DB 0%, #50A7C2 100%); +} + +/*166 Deep Relief*/ +.deep_relief{ + background-image: linear-gradient(-225deg, #7085B6 0%, #87A7D9 50%, #DEF3F8 100%); +} + +/*167 Sea Strike*/ +.sea_strike{ + background-image: linear-gradient(-225deg, #77FFD2 0%, #6297DB 48%, #1EECFF 100%); +} + +/*168 Night Call*/ +.night_call{ + background-image: linear-gradient(-225deg, #AC32E4 0%, #7918F2 48%, #4801FF 100%); +} + +/*169 Supreme Sky*/ +.supreme_sky{ + background-image: linear-gradient(-225deg, #D4FFEC 0%, #57F2CC 48%, #4596FB 100%); +} + +/*170 Light Blue*/ +.light_blue{ + background-image: linear-gradient(-225deg, #9EFBD3 0%, #57E9F2 48%, #45D4FB 100%); +} + +/*171 Mind Crawl*/ +.mind_crawl{ + background-image: linear-gradient(-225deg, #473B7B 0%, #3584A7 51%, #30D2BE 100%); +} + +/*172 Lily Meadow*/ +.lily_meadow{ + background-image: linear-gradient(-225deg, #65379B 0%, #886AEA 53%, #6457C6 100%); +} + +/*173 Sugar Lollipop*/ +.sugar_lollipop{ + background-image: linear-gradient(-225deg, #A445B2 0%, #D41872 52%, #FF0066 100%); +} + +/*174 Sweet Dessert*/ +.sweet_dessert{ + background-image: linear-gradient(-225deg, #7742B2 0%, #F180FF 52%, #FD8BD9 100%); +} + +/*175 Magic Ray*/ +.magic_ray{ + background-image: linear-gradient(-225deg, #FF3CAC 0%, #562B7C 52%, #2B86C5 100%); +} + +/*176 Teen Party*/ +.teen_party{ + background-image: linear-gradient(-225deg, #FF057C 0%, #8D0B93 50%, #321575 100%); +} + +/*177 Frozen Heat*/ +.frozen_heat{ + background-image: linear-gradient(-225deg, #FF057C 0%, #7C64D5 48%, #4CC3FF 100%); +} + +/*178 Gagarin View*/ +.gagarin_view{ + background-image: linear-gradient(-225deg, #69EACB 0%, #EACCF8 48%, #6654F1 100%); +} + +/*179 Fabled Sunset*/ +.fabled_sunset{ + background-image: linear-gradient(-225deg, #231557 0%, #44107A 29%, #FF1361 67%, #FFF800 100%); +} + +/*180 Perfect Blue*/ +.perfect_blue{ + background-image: linear-gradient(-225deg, #3D4E81 0%, #5753C9 48%, #6E7FF3 100%); +} diff --git a/tests/auto/gui/painting/qbrush/tst_qbrush.cpp b/tests/auto/gui/painting/qbrush/tst_qbrush.cpp index a2f7a3aa07..8cb1d92568 100644 --- a/tests/auto/gui/painting/qbrush/tst_qbrush.cpp +++ b/tests/auto/gui/painting/qbrush/tst_qbrush.cpp @@ -58,6 +58,7 @@ private slots: void testQGradientCopyConstructor(); void gradientStops(); + void gradientPresets(); void textures(); @@ -326,6 +327,26 @@ void tst_QBrush::gradientStops() QCOMPARE(gradient.stops().at(0).second, QColor()); } +void tst_QBrush::gradientPresets() +{ + QGradient gradient(QGradient::WarmFlame); + QCOMPARE(gradient.type(), QGradient::LinearGradient); + QCOMPARE(gradient.coordinateMode(), QGradient::ObjectBoundingMode); + + QLinearGradient *lg = static_cast(&gradient); + QCOMPARE(lg->start(), QPointF(0, 1)); + QCOMPARE(lg->finalStop(), QPointF(1, 0)); + + QCOMPARE(lg->stops().size(), 3); + QCOMPARE(lg->stops().at(0), QGradientStop(0, QColor(QLatin1Literal("#ff9a9e")))); + QCOMPARE(lg->stops().at(1), QGradientStop(0.99, QColor(QLatin1Literal("#fad0c4")))); + QCOMPARE(lg->stops().at(2), QGradientStop(1, QColor(QLatin1Literal("#fad0c4")))); + + + QGradient invalidPreset(QGradient::Preset(-1)); + QCOMPARE(invalidPreset.type(), QGradient::NoGradient); +} + void fill(QPaintDevice *pd) { QPainter p(pd); 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