File indexing completed on 2024-06-16 04:17:19

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 _DEFORM_BRUSH_H_
0008 #define _DEFORM_BRUSH_H_
0009 
0010 #include <kis_paint_device.h>
0011 #include <brushengine/kis_paint_information.h>
0012 
0013 #include "KisBrushSizeOptionData.h"
0014 #include "KisDeformOptionData.h"
0015 #include "kis_algebra_2d.h"
0016 
0017 #include <time.h>
0018 
0019 #if defined(_WIN32) || defined(_WIN64)
0020 #define srand48 srand
0021 inline double drand48()
0022 {
0023     return double(rand()) / RAND_MAX;
0024 }
0025 #endif
0026 
0027 
0028 class DeformBase
0029 {
0030 public:
0031     DeformBase() {}
0032     virtual ~DeformBase() {}
0033     virtual void transform(qreal * x, qreal * y, qreal distance, KisRandomSourceSP randomSource) {
0034         Q_UNUSED(x);
0035         Q_UNUSED(y);
0036         Q_UNUSED(distance);
0037         Q_UNUSED(randomSource);
0038     }
0039 };
0040 
0041 /// Inverse weighted inverse scaling - grow&shrink
0042 class DeformScale : public DeformBase
0043 {
0044 
0045 public:
0046     void setFactor(qreal factor) {
0047         m_factor = factor;
0048     }
0049     qreal factor() {
0050         return m_factor;
0051     }
0052     void transform(qreal* x, qreal* y, qreal distance, KisRandomSourceSP randomSource) override {
0053         Q_UNUSED(randomSource);
0054         qreal scaleFactor = KisAlgebra2D::signPZ(m_factor) * (qAbs((1.0 - distance) * m_factor) + distance);
0055         *x = *x / scaleFactor;
0056         *y = *y / scaleFactor;
0057     }
0058 
0059 private:
0060     qreal m_factor {0.0};
0061 };
0062 
0063 /// Inverse weighted rotation - swirlCW&&swirlCWW
0064 class DeformRotation : public DeformBase
0065 {
0066 
0067 public:
0068     void setAlpha(qreal alpha) {
0069         m_alpha = alpha;
0070     }
0071     void transform(qreal* maskX, qreal* maskY, qreal distance, KisRandomSourceSP randomSource) override {
0072         Q_UNUSED(randomSource);
0073         distance = 1.0 - distance;
0074         qreal rotX = cos(-m_alpha * distance) * (*maskX) - sin(-m_alpha * distance) * (*maskY);
0075         qreal rotY = sin(-m_alpha * distance) * (*maskX) + cos(-m_alpha * distance) * (*maskY);
0076 
0077         *maskX = rotX;
0078         *maskY = rotY;
0079     }
0080 
0081 private:
0082     qreal m_alpha {0.0};
0083 };
0084 
0085 /// Inverse move
0086 class DeformMove : public DeformBase
0087 {
0088 public:
0089     void setFactor(qreal factor) {
0090         m_factor = factor;
0091     }
0092     void setDistance(qreal dx, qreal dy) {
0093         m_dx = dx;
0094         m_dy = dy;
0095     }
0096     void transform(qreal* maskX, qreal* maskY, qreal distance, KisRandomSourceSP randomSource) override {
0097         Q_UNUSED(randomSource);
0098         *maskX -= m_dx * m_factor * (1.0 - distance);
0099         *maskY -= m_dy * m_factor * (1.0 - distance);
0100     }
0101 
0102 private:
0103     qreal m_dx {0.0};
0104     qreal m_dy {0.0};
0105     qreal m_factor {0.0};
0106 };
0107 
0108 /// Inverse lens distortion
0109 class DeformLens : public DeformBase
0110 {
0111 public:
0112     void setLensFactor(qreal k1, qreal k2) {
0113         m_k1 = k1;
0114         m_k2 = k2;
0115     }
0116     void setMaxDistance(qreal maxX, qreal maxY) {
0117         m_maxX = maxX;
0118         m_maxY = maxY;
0119     }
0120     void setMode(bool out) {
0121         m_out = out;
0122     }
0123 
0124     void transform(qreal* maskX, qreal* maskY, qreal distance, KisRandomSourceSP randomSource) override {
0125         Q_UNUSED(distance);
0126         Q_UNUSED(randomSource);
0127         //normalize
0128         qreal normX = *maskX / m_maxX;
0129         qreal normY = *maskY / m_maxY;
0130 
0131         qreal radius_2 = normX * normX  + normY * normY;
0132         qreal radius_4 = radius_2 * radius_2;
0133 
0134         if (m_out) {
0135             *maskX = normX * (1.0 + m_k1 * radius_2 + m_k2 * radius_4);
0136             *maskY = normY * (1.0 + m_k1 * radius_2 + m_k2 * radius_4);
0137         }
0138         else {
0139             *maskX = normX / (1.0 + m_k1 * radius_2 + m_k2 * radius_4);
0140             *maskY = normY / (1.0 + m_k1 * radius_2 + m_k2 * radius_4);
0141         }
0142 
0143         *maskX = m_maxX * (*maskX);
0144         *maskY = m_maxY * (*maskY);
0145     }
0146 
0147 private:
0148     qreal m_k1 {0.0}, m_k2 {0.0};
0149     qreal m_maxX {0.0}, m_maxY {0.0};
0150     bool m_out {false};
0151 };
0152 
0153 /// Randomly disturb the pixels
0154 class DeformColor : public DeformBase
0155 {
0156 public:
0157     DeformColor() {
0158     }
0159 
0160     void setFactor(qreal factor) {
0161         m_factor = factor;
0162     }
0163     void transform(qreal* x, qreal* y, qreal distance, KisRandomSourceSP randomSource) override {
0164         Q_UNUSED(distance);
0165         qreal randomX = m_factor * ((randomSource->generateNormalized() * 2.0) - 1.0);
0166         qreal randomY = m_factor * ((randomSource->generateNormalized() * 2.0) - 1.0);
0167         *x += randomX;
0168         *y += randomY;
0169     }
0170 
0171 private:
0172     qreal m_factor {0.0};
0173 };
0174 
0175 
0176 
0177 
0178 
0179 class DeformBrush
0180 {
0181 
0182 public:
0183     DeformBrush();
0184     ~DeformBrush();
0185 
0186     KisFixedPaintDeviceSP paintMask(KisFixedPaintDeviceSP dab, KisPaintDeviceSP layer, KisRandomSourceSP randomSource,
0187                                     qreal scale, qreal rotation, QPointF pos,
0188                                     qreal subPixelX, qreal subPixelY, int dabX, int dabY);
0189 
0190     void setSizeProperties(KisBrushSizeOptionData * properties) {
0191         m_sizeProperties = properties;
0192     }
0193     void setProperties(KisDeformOptionData * properties) {
0194         m_properties = properties;
0195     }
0196     void initDeformAction();
0197     QPointF hotSpot(qreal scale, qreal rotation);
0198 
0199 private:
0200     // return true if can paint
0201     bool setupAction(
0202         DeformModes mode, const QPointF& pos, QTransform const& rotation);
0203     void debugColor(const quint8* data, KoColorSpace * cs);
0204 
0205     qreal maskWidth(qreal scale) {
0206         return m_sizeProperties->brushDiameter * scale;
0207     }
0208 
0209     qreal maskHeight(qreal scale) {
0210         return m_sizeProperties->brushDiameter * m_sizeProperties->brushAspect  * scale;
0211     }
0212 
0213     inline qreal norme(qreal x, qreal y) {
0214         return x * x + y * y;
0215     }
0216 
0217 
0218 private:
0219     KisRandomSubAccessorSP m_srcAcc;
0220     bool m_firstPaint {false};
0221     qreal m_prevX {0.0}, m_prevY {0.0};
0222     int m_counter {1}; // taken from the constructor
0223 
0224     QRectF m_maskRect;
0225 
0226     DeformBase * m_deformAction {0};
0227 
0228     KisDeformOptionData * m_properties {0};
0229     KisBrushSizeOptionData * m_sizeProperties {0};
0230 };
0231 
0232 
0233 #endif