File indexing completed on 2024-05-26 04:33:16

0001 /*
0002  * KDE. Krita Project.
0003  *
0004  * SPDX-FileCopyrightText: 2020 Deif Lou <ginoba@gmail.com>
0005  * SPDX-FileCopyrightText: 2021 L. E. Segovia <amy@amyspark.me>
0006  *
0007  * SPDX-License-Identifier: GPL-2.0-or-later
0008  */
0009 
0010 #ifndef KISGRADIENTGENERATORCONFIGURATION_H
0011 #define KISGRADIENTGENERATORCONFIGURATION_H
0012 
0013 #include <QString>
0014 #include <QStringList>
0015 
0016 #include <kis_filter_configuration.h>
0017 #include <kis_gradient_painter.h>
0018 #include <KoAbstractGradient.h>
0019 #include <KoStopGradient.h>
0020 #include <KoColorSpaceRegistry.h>
0021 
0022 class KisGradientGeneratorConfiguration;
0023 typedef KisPinnedSharedPtr<KisGradientGeneratorConfiguration> KisGradientGeneratorConfigurationSP;
0024 
0025 class KisGradientGeneratorConfiguration : public KisFilterConfiguration
0026 {
0027 public:
0028     enum CoordinateSystem
0029     {
0030         CoordinateSystemCartesian,
0031         CoordinateSystemPolar
0032     };
0033 
0034     enum SpatialUnits
0035     {
0036         SpatialUnitsPixels,
0037         SpatialUnitsPercentOfWidth,
0038         SpatialUnitsPercentOfHeight,
0039         SpatialUnitsPercentOfLongestSide,
0040         SpatialUnitsPercentOfShortestSide
0041     };
0042 
0043     enum Positioning
0044     {
0045         PositioningAbsolute,
0046         PositioningRelative
0047     };
0048 
0049     enum GradientType
0050     {
0051         GradientTypeStop,
0052         GradientTypeSegment
0053     };
0054 
0055     KisGradientGeneratorConfiguration(qint32 version, KisResourcesInterfaceSP resourcesInterface);
0056     KisGradientGeneratorConfiguration(KisResourcesInterfaceSP resourcesInterface);
0057     KisGradientGeneratorConfiguration(const KisGradientGeneratorConfiguration &rhs);
0058 
0059     virtual KisFilterConfigurationSP clone() const override;
0060 
0061     static inline QString defaultName()
0062     {
0063         return "gradient";
0064     }
0065     
0066     static constexpr qint32 defaultVersion()
0067     {
0068         return 1;
0069     }
0070 
0071     static constexpr KisGradientPainter::enumGradientShape defaultShape()
0072     {
0073         return KisGradientPainter::GradientShapeLinear;
0074     }
0075 
0076     static constexpr KisGradientPainter::enumGradientRepeat defaultRepeat()
0077     {
0078         return KisGradientPainter::GradientRepeatNone;
0079     }
0080 
0081     static constexpr qreal defaultAntiAliasThreshold()
0082     {
0083         return 0.0;
0084     }
0085 
0086     static constexpr bool defaultDither()
0087     {
0088         return false;
0089     }
0090 
0091     static constexpr bool defaultReverse()
0092     {
0093         return false;
0094     }
0095 
0096     static constexpr qreal defaultStartPositionX()
0097     {
0098         return 0.0;
0099     }
0100 
0101     static constexpr qreal defaultStartPositionY()
0102     {
0103         return 50.0;
0104     }
0105     
0106     static constexpr SpatialUnits defaultStartPositionXUnits()
0107     {
0108         return SpatialUnitsPercentOfWidth;
0109     }
0110     
0111     static constexpr SpatialUnits defaultStartPositionYUnits() 
0112     {
0113         return SpatialUnitsPercentOfHeight;
0114     }
0115     
0116     static constexpr CoordinateSystem defaultEndPositionCoordinateSystem()
0117     {
0118         return CoordinateSystemCartesian;
0119     }
0120     
0121     static constexpr qreal defaultEndPositionX()
0122     {
0123         return 100.0;
0124     }
0125     
0126     static constexpr qreal defaultEndPositionY()
0127     {
0128         return 50.0;
0129     }
0130     
0131     static constexpr SpatialUnits defaultEndPositionXUnits()
0132     {
0133         return SpatialUnitsPercentOfWidth;
0134     }
0135     
0136     static constexpr SpatialUnits defaultEndPositionYUnits()
0137     {
0138         return SpatialUnitsPercentOfHeight;
0139     }
0140     
0141     static constexpr Positioning defaultEndPositionXPositioning()
0142     {
0143         return PositioningAbsolute;
0144     }
0145     
0146     static constexpr Positioning defaultEndPositionYPositioning()
0147     {
0148         return PositioningAbsolute;
0149     }
0150     
0151     static constexpr qreal defaultEndPositionAngle()
0152     {
0153         return 0.0;
0154     }
0155     
0156     static constexpr qreal defaultEndPositionDistance()
0157     {
0158         return 100.0;
0159     }
0160     
0161     static constexpr SpatialUnits defaultEndPositionDistanceUnits()
0162     {
0163         return SpatialUnitsPercentOfWidth;
0164     }
0165 
0166     static inline KoAbstractGradientSP defaultGradient()
0167     {
0168         KoStopGradientSP gradient = KoStopGradientSP(new KoStopGradient);
0169         gradient->setStops(
0170             QList<KoGradientStop>()
0171             << KoGradientStop(0.0, KoColor(Qt::black, KoColorSpaceRegistry::instance()->rgb8(0)), FOREGROUNDSTOP)
0172             << KoGradientStop(1.0, KoColor(Qt::white, KoColorSpaceRegistry::instance()->rgb8(0)), BACKGROUNDSTOP)
0173         );
0174         gradient->setName(i18nc("Default gradient name for the gradient generator", "Unnamed"));
0175         gradient->setValid(true);
0176         return gradient;
0177     }
0178 
0179     KisGradientPainter::enumGradientShape shape() const;
0180     KisGradientPainter::enumGradientRepeat repeat() const;
0181     qreal antiAliasThreshold() const;
0182     bool dither() const;
0183     bool reverse() const;
0184     qreal startPositionX() const;
0185     qreal startPositionY() const;
0186     SpatialUnits startPositionXUnits() const;
0187     SpatialUnits startPositionYUnits() const;
0188     CoordinateSystem endPositionCoordinateSystem() const;
0189     qreal endPositionX() const;
0190     qreal endPositionY() const;
0191     SpatialUnits endPositionXUnits() const;
0192     SpatialUnits endPositionYUnits() const;
0193     Positioning endPositionXPositioning() const;
0194     Positioning endPositionYPositioning() const;
0195     qreal endPositionAngle() const;
0196     qreal endPositionDistance() const;
0197     SpatialUnits endPositionDistanceUnits() const;
0198     KoAbstractGradientSP gradient(KoAbstractGradientSP fallbackGradient = nullptr) const;
0199 
0200     QPair<QPointF, QPointF> absoluteCartesianPositionsInPixels(int width, int height) const;
0201 
0202     void setShape(KisGradientPainter::enumGradientShape newShape);
0203     void setRepeat(KisGradientPainter::enumGradientRepeat newRepeat);
0204     void setAntiAliasThreshold(qreal newAntiAliasThreshold);
0205     void setDither(bool newDither);
0206     void setReverse(bool newReverse);
0207     void setStartPositionX(qreal newStartPositionX);
0208     void setStartPositionY(qreal newStartPositionY);
0209     void setStartPositionXUnits(SpatialUnits newStartPositionXUnits);
0210     void setStartPositionYUnits(SpatialUnits newStartPositionYUnits);
0211     void setEndPositionCoordinateSystem(CoordinateSystem newEndPositionCoordinateSystem);
0212     void setEndPositionX(qreal newEndPositionX);
0213     void setEndPositionY(qreal newEndPositionY);
0214     void setEndPositionXUnits(SpatialUnits newEndPositionXUnits);
0215     void setEndPositionYUnits(SpatialUnits newEndPositionYUnits);
0216     void setEndPositionXPositioning(Positioning newEndPositionXPositioning);
0217     void setEndPositionYPositioning(Positioning newEndPositionYPositioning);
0218     void setEndPositionAngle(qreal newEndPositionAngle);
0219     void setEndPositionDistance(qreal newEndPositionDistance);
0220     void setEndPositionDistanceUnits(SpatialUnits newEndPositionDistanceUnits);
0221     void setGradient(KoAbstractGradientSP newGradient);
0222     void setDefaults();
0223 
0224     static inline QString shapeToString(KisGradientPainter::enumGradientShape shape,
0225                                         const QString & defaultShapeString = QString())
0226     {
0227         if (shape == KisGradientPainter::GradientShapeLinear) {
0228             return "linear";
0229         } else if (shape == KisGradientPainter::GradientShapeBiLinear) {
0230             return "bilinear";
0231         } else if (shape == KisGradientPainter::GradientShapeRadial) {
0232             return "radial";
0233         } else if (shape == KisGradientPainter::GradientShapeSquare) {
0234             return "square";
0235         } else if (shape == KisGradientPainter::GradientShapeConical) {
0236             return "conical";
0237         } else if (shape == KisGradientPainter::GradientShapeConicalSymetric) {
0238             return "conical_symetric";
0239         } else if (shape == KisGradientPainter::GradientShapeSpiral) {
0240             return "spiral";
0241         } else if (shape == KisGradientPainter::GradientShapeReverseSpiral) {
0242             return "reverse_spiral";
0243         } else if (shape == KisGradientPainter::GradientShapePolygonal) {
0244             return "polygonal";
0245         }
0246         return defaultShapeString;
0247     }
0248 
0249     static inline KisGradientPainter::enumGradientShape stringToShape(QString const & shapeString,
0250                                                                       KisGradientPainter::enumGradientShape defaultShape = KisGradientPainter::GradientShapeLinear)
0251     {
0252         if (shapeString == "linear") {
0253             return KisGradientPainter::GradientShapeLinear;
0254         } else if (shapeString == "bilinear") {
0255             return KisGradientPainter::GradientShapeBiLinear;
0256         } else if (shapeString == "radial") {
0257             return KisGradientPainter::GradientShapeRadial;
0258         } else if (shapeString == "square") {
0259             return KisGradientPainter::GradientShapeSquare;
0260         } else if (shapeString == "conical") {
0261             return KisGradientPainter::GradientShapeConical;
0262         } else if (shapeString == "conical_symetric") {
0263             return KisGradientPainter::GradientShapeConicalSymetric;
0264         } else if (shapeString == "spiral") {
0265             return KisGradientPainter::GradientShapeSpiral;
0266         } else if (shapeString == "reverse_spiral") {
0267             return KisGradientPainter::GradientShapeReverseSpiral;
0268         } else if (shapeString == "polygonal") {
0269             return KisGradientPainter::GradientShapePolygonal;
0270         }
0271         return defaultShape;
0272     }
0273 
0274     static inline QString repeatToString(KisGradientPainter::enumGradientRepeat repeat,
0275                                          const QString & defaultRepeatString = QString())
0276     {
0277         if (repeat == KisGradientPainter::GradientRepeatNone) {
0278             return "none";
0279         } else if (repeat == KisGradientPainter::GradientRepeatForwards) {
0280             return "forwards";
0281         } else if (repeat == KisGradientPainter::GradientRepeatAlternate) {
0282             return "alternate";
0283         }
0284         return defaultRepeatString;
0285     }
0286 
0287     static inline KisGradientPainter::enumGradientRepeat stringToRepeat(QString const & repeatString,
0288                                                                         KisGradientPainter::enumGradientRepeat defaultRepeat = KisGradientPainter::GradientRepeatNone)
0289     {
0290         if (repeatString == "none") {
0291             return KisGradientPainter::GradientRepeatNone;
0292         } else if (repeatString == "forwards") {
0293             return KisGradientPainter::GradientRepeatForwards;
0294         } else if (repeatString == "alternate") {
0295             return KisGradientPainter::GradientRepeatAlternate;
0296         }
0297         return defaultRepeat;
0298     }
0299 
0300     static inline QString coordinateSystemToString(CoordinateSystem coordinateSystem,
0301                                                    const QString &defaultCoordinateSystemString = QString())
0302     {
0303         if (coordinateSystem == CoordinateSystemCartesian) {
0304             return "cartesian";
0305         } else if (coordinateSystem == CoordinateSystemPolar) {
0306             return "polar";
0307         }
0308         return defaultCoordinateSystemString;
0309     }
0310 
0311     static inline CoordinateSystem stringToCoordinateSystem(QString const & coordinateSystemString,
0312                                                             CoordinateSystem defaultCoordinateSystem = CoordinateSystemCartesian)
0313     {
0314         if (coordinateSystemString == "cartesian") {
0315             return CoordinateSystemCartesian;
0316         } else if (coordinateSystemString == "polar") {
0317             return CoordinateSystemPolar;
0318         }
0319         return defaultCoordinateSystem;
0320     }
0321 
0322     static inline QString spatialUnitsToString(SpatialUnits spatialUnits,
0323                                                const QString &defaultSpatialUnitsString = QString())
0324     {
0325         if (spatialUnits == SpatialUnitsPixels) {
0326             return "pixels";
0327         } else if (spatialUnits == SpatialUnitsPercentOfWidth) {
0328             return "percent_of_width";
0329         } else if (spatialUnits == SpatialUnitsPercentOfHeight) {
0330             return "percent_of_height";
0331         } else if (spatialUnits == SpatialUnitsPercentOfLongestSide) {
0332             return "percent_of_longest_side";
0333         } else if (spatialUnits == SpatialUnitsPercentOfShortestSide) {
0334             return "percent_of_shortest_side";
0335         }
0336         return defaultSpatialUnitsString;
0337     }
0338 
0339     static inline SpatialUnits stringToSpatialUnits(QString const & spatialUnitsString,
0340                                                     SpatialUnits defaultSpatialUnits = SpatialUnitsPixels)
0341     {
0342         if (spatialUnitsString == "pixels") {
0343             return SpatialUnitsPixels;
0344         } else if (spatialUnitsString == "percent_of_width") {
0345             return SpatialUnitsPercentOfWidth;
0346         } else if (spatialUnitsString == "percent_of_height") {
0347             return SpatialUnitsPercentOfHeight;
0348         } else if (spatialUnitsString == "percent_of_longest_side") {
0349             return SpatialUnitsPercentOfLongestSide;
0350         } else if (spatialUnitsString == "percent_of_shortest_side") {
0351             return SpatialUnitsPercentOfShortestSide;
0352         }
0353         return defaultSpatialUnits;
0354     }
0355 
0356     static inline QString positioningToString(Positioning positioning,
0357                                               const QString &defaultPositioningString = QString())
0358     {
0359         if (positioning == PositioningAbsolute) {
0360             return "absolute";
0361         } else if (positioning == PositioningRelative) {
0362             return "relative";
0363         }
0364         return defaultPositioningString;
0365     }
0366 
0367     static inline Positioning stringToPositioning(QString const & positioningString,
0368                                                   Positioning defaultPositioning = PositioningAbsolute)
0369     {
0370         if (positioningString == "absolute") {
0371             return PositioningAbsolute;
0372         } else if (positioningString == "relative") {
0373             return PositioningRelative;
0374         }
0375         return defaultPositioning;
0376     }
0377 
0378 private:
0379     static inline qreal convertUnitsToPixels(qreal x, SpatialUnits sourceUnits, int width, int height)
0380     {
0381         if (sourceUnits == SpatialUnitsPercentOfWidth) {
0382             return x * static_cast<qreal>(width) / 100.0;
0383         } else if (sourceUnits == SpatialUnitsPercentOfHeight) {
0384             return x * static_cast<qreal>(height) / 100.0;
0385         } else if (sourceUnits == SpatialUnitsPercentOfLongestSide) {
0386             return x * static_cast<qreal>(qMax(width, height)) / 100.0;
0387         } else if (sourceUnits == SpatialUnitsPercentOfShortestSide) {
0388             return x * static_cast<qreal>(qMin(width, height)) / 100.0;
0389         }
0390         return x;
0391     }
0392 };
0393 
0394 #endif