1 /*
2     This file is part of Photoflare.
3 
4     Photoflare is free software: you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation, either version 3 of the License, or
7     (at your option) any later version.
8 
9     Photoflare is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13 
14     You should have received a copy of the GNU General Public License
15     along with Photoflare.  If not, see <https://www.gnu.org/licenses/>.
16 */
17 
18 // SmudgeTool - Smudge pixels while dragging the mouse.
19 
20 #include "SmudgeTool.h"
21 #include "PaintWidget.h"
22 
23 #include <QPainter>
24 #include <QImage>
25 #include <QtMath>
26 
27 class SmudgeToolPrivate
28 {
29 public:
SmudgeToolPrivate()30     SmudgeToolPrivate()
31     {
32         primaryPen = QPen(QBrush(), 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
33         pixmap = QPixmap(32,32);
34     }
35     int radius;
36     int pressure;
37     QPoint lastPos;
38     QPen primaryPen;
39     Qt::MouseButton mouseButton;
40     QPixmap pixmap;
41     QImage completeImage;
42 };
43 
SmudgeTool(QObject * parent)44 SmudgeTool::SmudgeTool(QObject *parent)
45     : Tool(parent)
46     , d(new SmudgeToolPrivate){}
47 
~SmudgeTool()48 SmudgeTool::~SmudgeTool()
49 {
50     delete d;
51 }
52 
getCursor()53 QCursor SmudgeTool::getCursor()
54 {
55     int width = d->radius * m_scale;
56     if(width < 5)
57         width = 5;
58     QPixmap pixmap(QSize(width,width));
59     pixmap.fill(Qt::transparent);
60     QPainter painter(&pixmap);
61     QPen pen = QPen(QBrush(), 1, Qt::DashLine);
62     pen.setColor(Qt::gray);
63     painter.setPen(pen);
64 
65     painter.drawEllipse(pixmap.rect());
66     return QCursor(pixmap);
67 }
68 
setRadius(int radius)69 void SmudgeTool::setRadius(int radius)
70 {
71     d->radius = radius;
72     emit cursorChanged(getCursor());
73 }
74 
setPressure(int pressure)75 void SmudgeTool::setPressure(int pressure)
76 {
77     d->pressure = pressure;
78 }
79 
onMousePress(const QPoint & pos,Qt::MouseButton button)80 void SmudgeTool::onMousePress(const QPoint &pos, Qt::MouseButton button)
81 {
82     Q_UNUSED(button);
83     d->lastPos = pos;
84     d->mouseButton = button;
85     const QImage *image = dynamic_cast<QImage*>(m_paintDevice);
86     d->completeImage = *image;
87 }
88 
onMouseMove(const QPoint & pos)89 void SmudgeTool::onMouseMove(const QPoint &pos)
90 {
91     if (m_paintDevice)
92     {
93         float pressure = d->pressure / 20.0f;
94         QImage lastImage = d->completeImage.copy(d->lastPos.x() - d->radius/2, d->lastPos.y() - d->radius/2, d->radius, d->radius);
95         QImage currImage = lastImage.scaled(int(d->radius * pressure), int(d->radius * pressure));
96         QImage pattern(int(d->radius * pressure), int(d->radius * pressure), QImage::Format_ARGB32);
97         pattern.fill(Qt::transparent);
98         int w = pattern.width();
99         for(int i=0; i<w; i++)
100         {
101             for(int j=0; j<w; j++)
102             {
103                 float l = qSqrt( qPow(i-w/2, 2) + qPow(j-w/2, 2) );
104                 if(l <= w/2)
105                 {
106                     pattern.setPixel(i, j, currImage.pixel(i, j));
107                 }
108             }
109         }
110 
111         QPainter painter(m_paintDevice);
112         painter.drawPixmap(pos.x()-int(d->radius * pressure / 2), pos.y()-int(d->radius * pressure / 2), d->pixmap.fromImage(pattern));
113 
114         d->lastPos = pos;
115         emit painted(m_paintDevice);
116 
117         const QImage *image = dynamic_cast<QImage*>(m_paintDevice);
118         d->completeImage = *image;
119     }
120 }
121 
onMouseRelease(const QPoint & pos)122 void SmudgeTool::onMouseRelease(const QPoint &pos)
123 {
124     Q_UNUSED(pos);
125     d->mouseButton = Qt::NoButton;
126     d->completeImage = QImage();
127 }
128 
129