Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_generator_layer.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2008 Boudewijn Rempt <boud@valdyas.org>
3 * SPDX-FileCopyrightText: 2020 L. E. Segovia <amy@amyspark.me>
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 */
7
8#include <QMutex>
9#include <QMutexLocker>
10
11#include "kis_generator_layer.h"
12
13#include <klocalizedstring.h>
14#include "kis_debug.h"
15
16#include <KoIcon.h>
17#include <kis_icon.h>
18#include "kis_selection.h"
24#include "kis_node_visitor.h"
28
29
30#define UPDATE_DELAY 100 /*ms */
31
46
47
49 const QString &name,
51 KisSelectionSP selection)
52 : KisSelectionBasedLayer(image, name, selection, kfc),
53 m_d(new Private)
54{
55 connect(&m_d->updateSignalCompressor, SIGNAL(timeout()), SLOT(slotDelayedStaticUpdate()));
56}
57
60 m_d(new Private)
61{
62 connect(&m_d->updateSignalCompressor, SIGNAL(timeout()), SLOT(slotDelayedStaticUpdate()));
63}
64
68
69void KisGeneratorLayer::setFilter(KisFilterConfigurationSP filterConfig, bool checkCompareConfig)
70{
71 setFilterWithoutUpdate(filterConfig, checkCompareConfig);
72 m_d->updateSignalCompressor.start();
73}
74
76{
77 if (filter().isNull() || (!checkCompareConfig || !filter()->compareTo(filterConfig.constData()))) {
79 {
80 QMutexLocker locker(&m_d->mutex);
81 m_d->preparedRect = QRect();
82 }
83 }
84}
85
87{
93 if (KisImageSP image = this->image(); image && image->locked()) {
94 m_d->updateSignalCompressor.start();
95 return;
96 }
97
103 KisLayerSP parentLayer(qobject_cast<KisLayer*>(parent().data()));
104 if (!parentLayer) return;
105
107
108 if (image) {
109 if (!m_d->updateCookie) {
110 this->update();
111 } else {
112 m_d->updateSignalCompressor.start();
113 }
114 }
115}
116
118{
119 QMutexLocker locker(&m_d->mutex);
120
121 KisImageSP image = this->image().toStrongRef();
122 const QRect updateRect = extent() | image->bounds();
123
124 if (filterConfig != m_d->preparedForFilter) {
125 locker.unlock();
127 locker.relock();
128 }
129
130 if (m_d->preparedImageBounds != image->bounds()) {
131 m_d->preparedRect = QRect();
132 }
133
134 const QRegion processRegion(QRegion(updateRect) - m_d->preparedRect);
135 if (processRegion.isEmpty())
136 return;
137
138 KisGeneratorSP f = KisGeneratorRegistry::instance()->value(filterConfig->name());
140
141 KisPaintDeviceSP originalDevice = original();
142
143 QSharedPointer<boost::none_t> cookie(new boost::none_t(boost::none));
144
145 auto jobs = KisGeneratorStrokeStrategy::createJobsData(this, cookie, f, originalDevice, processRegion, filterConfig);
146
147 Q_FOREACH (auto job, jobs) {
148 image->addJob(strokeId, job);
149 }
150
151 m_d->updateCookie = cookie;
152 m_d->preparedRect = updateRect;
153 m_d->preparedImageBounds = image->bounds();
154 m_d->preparedForFilter = filterConfig;
155}
156
158{
159 KisFilterConfigurationSP filterConfig = filter();
161
162 requestUpdateJobsWithStroke(strokeId, filterConfig);
163 return m_d->updateCookie;
164}
165
167{
168 KisImageSP image = this->image().toStrongRef();
169
170 KisFilterConfigurationSP filterConfig = filter();
171 KIS_SAFE_ASSERT_RECOVER_RETURN(filterConfig);
172
174
175 KisStrokeId strokeId = image->startStroke(stroke);
176
177 requestUpdateJobsWithStroke(strokeId, filterConfig);
178
179 image->endStroke(strokeId);
180}
181
183{
184 return v.visit(this);
185}
186
188{
189 return visitor.visit(this, undoAdapter);
190}
191
193{
194 return KisIconUtils::loadIcon("fillLayer");
195}
196
198{
199 KisFilterConfigurationSP filterConfig = filter();
200
202 l << KisBaseNode::Property(KoID("generator", i18n("Generator")),
203 KisGeneratorRegistry::instance()->value(filterConfig->name())->name());
204
205 return l;
206}
207
209{
211 {
212 QMutexLocker locker(&m_d->mutex);
213 m_d->preparedRect = QRect();
214 }
215 m_d->updateSignalCompressor.start();
216}
217
219{
221 {
222 QMutexLocker locker(&m_d->mutex);
223 m_d->preparedRect = QRect();
224 }
225 m_d->updateSignalCompressor.start();
226}
227
229{
231 m_d->updateSignalCompressor.start();
232}
233
235{
237 m_d->updateSignalCompressor.stop();
238 m_d->updateCookie.clear();
239
241 }
242}
243
245{
246 return m_d->updateSignalCompressor.isActive();
247}
248
250{
252 {
253 QMutexLocker locker(&m_d->mutex);
254 m_d->preparedRect = QRect();
255 }
256}
257
259{
261 m_d->updateSignalCompressor.start();
262}
263
float value(const T *src, size_t ch)
qreal v
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
static KisGeneratorRegistry * instance()
static QVector< KisStrokeJobData * > createJobsData(const KisGeneratorLayerSP layer, QSharedPointer< boost::none_t > cookie, const KisGeneratorSP f, const KisPaintDeviceSP dev, const QRegion &rc, const KisFilterConfigurationSP filterConfig)
const KoColorSpace * colorSpace() const
void addJob(KisStrokeId id, KisStrokeJobData *data) override
KisStrokeId startStroke(KisStrokeStrategy *strokeStrategy) override
QRect bounds() const override
bool locked() const
Definition kis_image.cc:751
void endStroke(KisStrokeId id) override
virtual KisFilterConfigurationSP filter() const
virtual void setFilter(KisFilterConfigurationSP filterConfig, bool checkCompareConfig=true)
virtual void visit(KisNode *node, KisUndoAdapter *undoAdapter)=0
const T * constData() const
KisSharedPtr< T > toStrongRef() const
toStrongRef returns a KisSharedPtr which may be dereferenced.
const T value(const QString &id) const
Definition KoID.h:30
#define KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(cond, val)
Definition kis_assert.h:129
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128
#define UPDATE_DELAY
QIcon loadIcon(const QString &name)
KisImageWSP image
KisFilterConfigurationSP preparedForFilter
void resetCacheWithoutUpdate(const KoColorSpace *colorSpace)
const QScopedPointer< Private > m_d
void resetCache(const KoColorSpace *colorSpace) override
void setDirtyWithoutUpdate(const QVector< QRect > &rects)
bool accept(KisNodeVisitor &) override
QWeakPointer< boost::none_t > updateCookie
KisGeneratorLayer(KisImageWSP image, const QString &name, KisFilterConfigurationSP kfc, KisSelectionSP selection)
void forceUpdateTimedNode() override
forceUpdateTimedNode forces the node to regenerate its project. The update might be asynchronous,...
void setFilterWithoutUpdate(KisFilterConfigurationSP filterConfig, bool checkCompareConfig=true)
void requestUpdateJobsWithStroke(const KisStrokeId stroke, const KisFilterConfigurationSP configuration)
void setY(qint32 y) override
void setX(qint32 x) override
QWeakPointer< boost::none_t > previewWithStroke(const KisStrokeId stroke)
QIcon icon() const override
bool hasPendingTimedUpdates() const override
void setFilter(KisFilterConfigurationSP filterConfig, bool checkCompareConfig=true) override
KisBaseNode::PropertyList sectionModelProperties() const override
KisThreadSafeSignalCompressor updateSignalCompressor
const KoColorSpace * colorSpace() const override
returns the image's colorSpace or null, if there is no image
Definition kis_layer.cc:225
KisLayerSP parentLayer() const
KisBaseNode::PropertyList sectionModelProperties() const override
Definition kis_layer.cc:272
KisNodeWSP parent
Definition kis_node.cpp:86
Describes base behaviour for selection base classes like KisAdjustmentLayer and KisGeneratorLayer....
virtual void resetCache(const KoColorSpace *colorSpace)
KisPaintDeviceSP original() const override