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