Krita Source Code Documentation
Loading...
Searching...
No Matches
particle_brush.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2010 Lukáš Tvrdý <lukast.dev@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7#include "particle_brush.h"
8
9#include "kis_paint_device.h"
11
12#include <KoColorSpace.h>
13#include <KoColor.h>
14
15#include <kis_global.h>
16
17#include <math.h>
18
19const qreal TIME = 0.000030;
20
25
29
30
37
38void ParticleBrush::setInitialPosition(const QPointF &pos)
39{
40 for (int i = 0; i < m_properties->particleCount; i++) {
41 m_particlePos[i] = pos;
42 m_particleNextPos[i] = pos;
44 }
45}
46
47
48void ParticleBrush::paintParticle(KisRandomAccessorSP accWrite, const KoColorSpace * cs, const QPointF &pos, const KoColor& color, qreal weight, bool respectOpacity)
49{
50 // opacity top left, right, bottom left, right
51 KoColor myColor(color);
52 quint8 opacity = respectOpacity ? myColor.opacityU8() : OPACITY_OPAQUE_U8;
53
54 int ipx = floor(pos.x());
55 int ipy = floor(pos.y());
56 qreal fx = pos.x() - ipx;
57 qreal fy = pos.y() - ipy;
58
59 quint8 btl = qRound((1.0 - fx) * (1.0 - fy) * opacity * weight);
60 quint8 btr = qRound((fx) * (1.0 - fy) * opacity * weight);
61 quint8 bbl = qRound((1.0 - fx) * (fy) * opacity * weight);
62 quint8 bbr = qRound((fx) * (fy) * opacity * weight);
63
64 accWrite->moveTo(ipx , ipy);
65 myColor.setOpacity(quint8(kisBoundFast<quint16>(OPACITY_TRANSPARENT_U8, btl + cs->opacityU8(accWrite->rawData()), OPACITY_OPAQUE_U8)));
66 memcpy(accWrite->rawData(), myColor.data(), cs->pixelSize());
67
68 accWrite->moveTo(ipx + 1, ipy);
69 myColor.setOpacity(quint8(kisBoundFast<quint16>(OPACITY_TRANSPARENT_U8, btr + cs->opacityU8(accWrite->rawData()), OPACITY_OPAQUE_U8)));
70 memcpy(accWrite->rawData(), myColor.data(), cs->pixelSize());
71
72 accWrite->moveTo(ipx, ipy + 1);
73 myColor.setOpacity(quint8(kisBoundFast<quint16>(OPACITY_TRANSPARENT_U8, bbl + cs->opacityU8(accWrite->rawData()), OPACITY_OPAQUE_U8)));
74 memcpy(accWrite->rawData(), myColor.data(), cs->pixelSize());
75
76 accWrite->moveTo(ipx + 1, ipy + 1);
77 myColor.setOpacity(quint8(kisBoundFast<quint16>(OPACITY_TRANSPARENT_U8, bbr + cs->opacityU8(accWrite->rawData()), OPACITY_OPAQUE_U8)));
78 memcpy(accWrite->rawData(), myColor.data(), cs->pixelSize());
79}
80
81
82
83
84void ParticleBrush::draw(KisPaintDeviceSP dab, const KoColor& color, const QPointF &pos)
85{
87 const KoColorSpace * cs = dab->colorSpace();
88
89 QRect boundingRect;
90
92 boundingRect = dab->defaultBounds()->bounds();
93 }
94
95 for (int i = 0; i < m_properties->particleIterations; i++) {
96 for (int j = 0; j < m_properties->particleCount; j++) {
97 /*
98 m_time = 0.01;
99 QPointF temp = m_position;
100 QPointF dist = m_position - m_oldPosition;
101 m_position = m_position + (dist + (m_acceleration*m_time*m_time));
102 m_oldPosition = temp;
103 */
104
105 /*
106 QPointF dist = info.pos() - m_position;
107 dist *= 0.3; // scale
108 dist *= 10; // force
109 m_oldPosition += dist;
110 m_oldPosition *= 0.989;
111 m_position = m_position + m_oldPosition * m_time * m_time;
112 */
113
114
115 QPointF dist = pos - m_particlePos[j];
116 dist.setX(dist.x() * m_properties->particleScaleX);
117 dist.setY(dist.y() * m_properties->particleScaleY);
118 dist = dist * m_acceleration[j];
122
132 // If scale is negative, position can easily jump into infinity
133 // and then it won't be caught by contains();
134 // and then it will be passed to the lockless hashtable
135 // and then it will crash.
136 // Hence better to catch infinity here and just not paint anything.
137 QPointF pointF = m_particlePos[j];
138
139 const qint32 max = 2147483600;
140 const qint32 min = -max;
141 bool nearInfinity = pointF.x() < min || pointF.x () > max || pointF.y() < min || pointF.y() > max;
142 bool inside = boundingRect.contains(m_particlePos[j].toPoint());
143
144 if (boundingRect.isEmpty() || (inside && !nearInfinity)) {
145 paintParticle(accessor, cs, m_particlePos[j], color, m_properties->particleWeight, true);
146 }
147
148 }//for j
149 }//for i
150}
151
152
153
const quint8 OPACITY_TRANSPARENT_U8
const quint8 OPACITY_OPAQUE_U8
virtual quint8 * rawData()=0
virtual QRect bounds() const =0
const KoColorSpace * colorSpace() const
KisDefaultBoundsBaseSP defaultBounds() const
KisRandomAccessorSP createRandomAccessorNG()
virtual void moveTo(qint32 x, qint32 y)=0
virtual quint32 pixelSize() const =0
virtual quint8 opacityU8(const quint8 *pixel) const =0
void setOpacity(quint8 alpha)
Definition KoColor.cpp:333
quint8 * data()
Definition KoColor.h:144
quint8 opacityU8() const
Definition KoColor.cpp:341
QVector< qreal > m_acceleration
KisParticleOpOptionData * m_properties
QVector< QPointF > m_particleNextPos
QVector< QPointF > m_particlePos
void draw(KisPaintDeviceSP dab, const KoColor &color, const QPointF &pos)
void setInitialPosition(const QPointF &pos)
void paintParticle(KisRandomAccessorSP writeAccessor, const KoColorSpace *cs, const QPointF &pos, const KoColor &color, qreal weight, bool respectOpacity)
const qreal TIME