File indexing completed on 2024-06-23 04:27:43

0001 /*
0002  *  SPDX-FileCopyrightText: 2008-2010 Lukáš Tvrdý <lukast.dev@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #ifndef _HAIRY_BRUSH_H_
0008 #define _HAIRY_BRUSH_H_
0009 
0010 #include <QVector>
0011 #include <QList>
0012 #include <QTransform>
0013 
0014 #include <KoColor.h>
0015 
0016 #include "trajectory.h"
0017 #include "bristle.h"
0018 
0019 #include <kis_paint_device.h>
0020 #include <brushengine/kis_paint_information.h>
0021 #include <kis_random_accessor_ng.h>
0022 
0023 class KoCompositeOp;
0024 
0025 
0026 class KisHairyProperties
0027 {
0028 public:
0029     quint16 radius;
0030     quint16 inkAmount;
0031     qreal sigma;
0032     QVector<qreal> inkDepletionCurve;
0033     bool inkDepletionEnabled;
0034     bool isbrushDimension1D;
0035     bool useMousePressure;
0036     bool useSaturation;
0037     bool useOpacity;
0038     bool useWeights;
0039 
0040     bool useSoakInk;
0041     bool connectedPath;
0042     bool antialias;
0043     bool useCompositing;
0044 
0045     quint8 pressureWeight;
0046     quint8 bristleLengthWeight;
0047     quint8 bristleInkAmountWeight;
0048     quint8 inkDepletionWeight;
0049 
0050     qreal shearFactor;
0051     qreal randomFactor;
0052     qreal scaleFactor;
0053     qreal threshold;
0054 
0055 };
0056 
0057 class HairyBrush
0058 {
0059 
0060 public:
0061     HairyBrush();
0062     ~HairyBrush();
0063 
0064     void paintLine(KisPaintDeviceSP dab, KisPaintDeviceSP layer, const KisPaintInformation &pi1, const KisPaintInformation &pi2, qreal scale, qreal rotation);
0065     /// set ink color for the whole bristle shape
0066     void setInkColor(const KoColor &color) {
0067         m_color = color;
0068     }
0069     /// set parameters for the brush engine
0070     void setProperties(KisHairyProperties * properties) {
0071         m_properties = properties;
0072     }
0073     /// set the shape of the bristles according the dab
0074     void fromDabWithDensity(KisFixedPaintDeviceSP dab, qreal density);
0075 
0076 private:
0077     /// paints single bristle
0078     void addBristleInk(Bristle *bristle,const QPointF &pos, const KoColor &color);
0079     /// composite single pixel to dab
0080     void plotPixel(int wx, int wy, const KoColor &color);
0081     /// check the opacity of dab pixel and if the opacity is less than color, it will copy color to dab
0082     void darkenPixel(int wx, int wy, const KoColor &color);
0083     /// paint wu particle by copying the color and setup just the opacity, weight is complementary to opacity of the color
0084     void paintParticle(QPointF pos, const KoColor& color, qreal weight);
0085     /// paint wu particle using composite operation
0086     void paintParticle(QPointF pos, const KoColor& color);
0087     /// similar to sample input color in spray
0088     void colorifyBristles(KisPaintDeviceSP source, QPointF point);
0089 
0090     void repositionBristles(double angle, double slope);
0091     /// compute mouse pressure according distance
0092     double computeMousePressure(double distance);
0093 
0094     /// simulate running out of saturation
0095     void saturationDepletion(Bristle * bristle, KoColor &bristleColor, qreal pressure, qreal inkDepletion);
0096     /// simulate running out of ink through opacity decreasing
0097     void opacityDepletion(Bristle * bristle, KoColor &bristleColor, qreal pressure, qreal inkDepletion);
0098     /// fetch actual ink status according depletion curve
0099     qreal fetchInkDepletion(Bristle * bristle, int inkDepletionSize);
0100 
0101     void initAndCache();
0102 
0103 private:
0104     const KisHairyProperties * m_properties {nullptr};
0105 
0106     QVector<Bristle*> m_bristles;
0107     QTransform m_transform;
0108 
0109     // used for interpolation the path of bristles
0110     Trajectory m_trajectory;
0111     QHash<QString, QVariant> m_params;
0112     // temporary device
0113     KisPaintDeviceSP m_dab;
0114     KisRandomAccessorSP m_dabAccessor;
0115     const KoCompositeOp * m_compositeOp {nullptr};
0116     quint32 m_pixelSize {0};
0117 
0118     int m_counter {0};
0119 
0120     double m_lastAngle {0.0};
0121     double m_oldPressure {1.0};
0122     KoColor m_color;
0123 
0124     int m_saturationId {-1};
0125     KoColorTransformation * m_transfo {nullptr};
0126 
0127     // internal counter counts the calls of paint, the counter is 1 when the first call occurs
0128     inline bool firstStroke() const {
0129         return (m_counter == 1);
0130     }
0131 };
0132 
0133 #endif