Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_clone_layer.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2007 Boudewijn Rempt <boud@valdyas.org>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7#include "kis_clone_layer.h"
8
9#include <kis_debug.h>
10#include <klocalizedstring.h>
11
12#include <KoIcon.h>
13#include <kis_icon.h>
14
15#include <KoColorSpace.h>
17
18#include "kis_default_bounds.h"
19#include "kis_paint_device.h"
20#include "kis_image.h"
21#include "kis_painter.h"
22#include "kis_node_visitor.h"
24#include "kis_paint_layer.h"
25
26#include <QStack>
27#include <kis_effect_mask.h>
29
30
45
46KisCloneLayer::KisCloneLayer(KisLayerSP from, KisImageWSP image, const QString &name, quint8 opacity)
47 : KisLayer(image, name, opacity)
48 , m_d(new Private(new KisDefaultBounds(image)))
49{
50 KisImageSP imageSP = image.toStrongRef();
51 if (!imageSP) {
52 return;
53 }
54 m_d->fallback = new KisPaintDevice(this,
55 imageSP->colorSpace(),
56 new KisDefaultBounds(imageSP));
57 m_d->copyFrom = from;
58 m_d->type = COPY_PROJECTION;
59
60 // When loading the layer we copy from might not exist yet
61 if (m_d->copyFrom) {
62 m_d->copyFrom->registerClone(this);
63 }
64}
65
67 : KisLayer(rhs)
68 , m_d(new Private(new KisDefaultBounds(rhs.image())))
69{
70 m_d->fallback = new KisPaintDevice(this,
71 rhs.m_d->fallback->colorSpace(),
72 new KisDefaultBounds(rhs.image()));
73 m_d->copyFrom = rhs.copyFrom();
74 m_d->type = rhs.copyType();
75 m_d->offset = rhs.m_d->offset;
76
77 if (m_d->copyFrom) {
78 m_d->copyFrom->registerClone(this);
79 }
80}
81
83{
84 if (m_d->copyFrom) {
85 m_d->copyFrom->unregisterClone(this);
86 }
87 delete m_d;
88}
89
91{
92 KisPaintDeviceSP newOriginal = new KisPaintDevice(*original());
93 KisPaintLayerSP newLayer = new KisPaintLayer(image(), name(), opacity(), newOriginal);
94 newLayer->setX(newLayer->x() + x());
95 newLayer->setY(newLayer->y() + y());
98
99 return newLayer;
100}
101
103{
104 m_d->fallback->setDefaultBounds(new KisDefaultBounds(image));
105 m_d->offset.setDefaultBounds(new KisDefaultBounds(image));
107}
108
110{
111 return node->inherits("KisMask");
112}
113
115{
116 return 0;
117}
118
120{
121 if (!m_d->copyFrom || !m_d->copyFrom->projection()) return m_d->fallback;
122 KisPaintDeviceSP retval;
123 switch (m_d->type) {
124 case COPY_PROJECTION:
125 retval = m_d->copyFrom->projection();
126 break;
127
128 case COPY_ORIGINAL:
129 default:
130 retval = m_d->copyFrom->original();
131 }
132
133 return retval;
134}
135
137{
138 return m_d->offset->x() || m_d->offset->y();
139}
140
142{
143 return m_d->copyFrom ? m_d->copyFrom->colorSpace() : m_d->fallback->colorSpace();
144}
145
147 KisPaintDeviceSP projection,
148 const QRect& rect) const
149{
150 QRect copyRect = rect;
151 copyRect.translate(-m_d->offset->x(), -m_d->offset->y());
152
154}
155
156void KisCloneLayer::setDirtyOriginal(const QRect &rect, bool dontInvalidateFrames)
157{
162 if (!visible(true)) return;
163
170 if (!dontInvalidateFrames) {
172 } else {
174 }
175}
176
178{
179 KisImageSP imageSP = image().toStrongRef();
180 if (!imageSP) {
181 return;
182 }
187 if (value && visible(true)) {
188 KisLayer::setDirty(imageSP->bounds());
189 }
191}
192
193QRect KisCloneLayer::needRectOnSourceForMasks(const QRect &rc) const
194{
195 QStack<QRect> applyRects_unused;
196 bool rectVariesFlag;
197
199 if (effectMasks.isEmpty()) return QRect();
200
201 QRect needRect = this->masksNeedRect(effectMasks,
202 rc,
203 applyRects_unused,
204 rectVariesFlag);
205
206 if (needRect.isEmpty() ||
207 (!rectVariesFlag && needRect == rc)) {
208
209 return QRect();
210 }
211
212 return needRect;
213}
214
215qint32 KisCloneLayer::x() const
216{
217 return m_d->offset->x();
218}
219qint32 KisCloneLayer::y() const
220{
221 return m_d->offset->y();
222}
224{
225 m_d->offset->setX(x);
226}
228{
229 m_d->offset->setY(y);
230}
231
233{
234 QRect rect = original()->extent();
235
236 // HINT: no offset now. See a comment in setDirtyOriginal()
237 return rect | projection()->extent();
238}
239
241{
242 QRect rect = original()->exactBounds();
243
244 // HINT: no offset now. See a comment in setDirtyOriginal()
245 return rect | projection()->exactBounds();
246}
247
248QRect KisCloneLayer::accessRect(const QRect &rect, PositionToFilthy pos) const
249{
250 QRect resultRect = rect;
251
252 if(pos & (N_FILTHY_PROJECTION | N_FILTHY)) {
253 if (m_d->offset->x() || m_d->offset->y()) {
254 resultRect |= rect.translated(-m_d->offset->x(), -m_d->offset->y());
255 }
256
262 resultRect |= needRectOnSourceForMasks(rect);
263 }
264
265 return resultRect;
266}
267
269{
270 return rect.translated(m_d->offset->x(), m_d->offset->y());
271}
272
274{
275 return v.visit(this);
276}
277
279{
280 return visitor.visit(this, undoAdapter);
281}
282
284{
285 if (m_d->copyFrom) {
286 m_d->copyFrom->unregisterClone(this);
287 }
288
289 m_d->copyFrom = fromLayer;
290
291 if (m_d->copyFrom) {
292 m_d->copyFrom->registerClone(this);
293 }
294}
295
297{
298 return m_d->copyFrom;
299}
300
302{
303 m_d->type = type;
304}
305
307{
308 return m_d->type;
309}
310
312{
313 return m_d->copyFrom ? KisNodeUuidInfo(m_d->copyFrom) : m_d->copyFromInfo;
314}
315
317{
318 Q_ASSERT(!m_d->copyFrom);
319 m_d->copyFromInfo = info;
320}
321
323{
324 return KisIconUtils::loadIcon("cloneLayer");
325}
326
328{
330 if (m_d->copyFrom)
331 l << KisBaseNode::Property(KoID("copy_from", i18n("Copy From")), m_d->copyFrom->name());
332
333 return l;
334}
335
337{
339 m_d->offset.syncLodCache();
340}
341
float value(const T *src, size_t ch)
qreal v
const KoColorSpace * colorSpace() const
QRect bounds() const override
QRect exactBounds() const
QRect extent() const
static void copyAreaOptimized(const QPoint &dstPt, KisPaintDeviceSP src, KisPaintDeviceSP dst, const QRect &originalSrcRect)
virtual void visit(KisNode *node, KisUndoAdapter *undoAdapter)=0
KisSharedPtr< T > toStrongRef() const
toStrongRef returns a KisSharedPtr which may be dereferenced.
Definition KoID.h:30
CopyLayerType
@ COPY_ORIGINAL
@ COPY_PROJECTION
QIcon loadIcon(const QString &name)
const QString & compositeOpId() const
void mergeNodeProperties(const KoProperties &properties)
const KoProperties & nodeProperties() const
virtual void notifyParentVisibilityChanged(bool value)
KisImageWSP image
QString name() const
void setCompositeOpId(const QString &compositeOpId)
quint8 opacity() const
virtual bool visible(bool recursive=false) const
void setCopyType(CopyLayerType type)
const KoColorSpace * colorSpace() const override
void syncLodCache() override
void copyOriginalToProjection(const KisPaintDeviceSP original, KisPaintDeviceSP projection, const QRect &rect) const override
bool needProjection() const override
void setCopyFromInfo(KisNodeUuidInfo info)
void setY(qint32) override
KisPaintDeviceSP paintDevice() const override
bool accept(KisNodeVisitor &) override
void setCopyFrom(KisLayerSP layer)
void setX(qint32) override
QRect extent() const override
Returns an approximation of where the bounds on actual data are in this layer.
qint32 y() const override
CopyLayerType type
qint32 x() const override
Private(KisDefaultBoundsBaseSP defaultBounds)
void notifyParentVisibilityChanged(bool value) override
bool allowAsChild(KisNodeSP) const override
QRect outgoingChangeRect(const QRect &rect) const override
KisPaintDeviceSP original() const override
Private *const m_d
KisLayerSP copyFrom
KisNodeUuidInfo copyFromInfo
QRect exactBounds() const override
Returns the exact bounds of where the actual data resides in this layer.
KisLayerSP reincarnateAsPaintLayer() const
~KisCloneLayer() override
void setDirtyOriginal(const QRect &rect, bool dontInvalidateFrames)
void setImage(KisImageWSP image) override
QRect accessRect(const QRect &rect, PositionToFilthy pos) const override
QIcon icon() const override
KisPaintDeviceSP fallback
KisLodCapableLayerOffset offset
CopyLayerType copyType() const
KisBaseNode::PropertyList sectionModelProperties() const override
QRect needRectOnSourceForMasks(const QRect &rc) const
KisCloneLayer(KisLayerSP from, KisImageWSP image, const QString &name, quint8 opacity)
KisPaintDeviceSP projection() const override
Definition kis_layer.cc:820
void setImage(KisImageWSP image) override
Definition kis_layer.cc:378
qint32 y() const override
Definition kis_layer.cc:978
QList< KisEffectMaskSP > effectMasks() const
Definition kis_layer.cc:521
qint32 x() const override
Definition kis_layer.cc:973
QRect masksNeedRect(const QList< KisEffectMaskSP > &masks, const QRect &changeRect, QStack< QRect > &applyRects, bool &rectVariesFlag) const
Definition kis_layer.cc:610
void setX(qint32 x) override
Definition kis_layer.cc:983
KisBaseNode::PropertyList sectionModelProperties() const override
Definition kis_layer.cc:272
void setY(qint32 y) override
Definition kis_layer.cc:989
void setDirtyDontResetAnimationCache()
Definition kis_node.cpp:599
virtual QRect needRect(const QRect &rect, PositionToFilthy pos=N_FILTHY) const
Definition kis_node.cpp:218
PositionToFilthy
Definition kis_node.h:58
@ N_FILTHY
Definition kis_node.h:61
@ N_FILTHY_PROJECTION
Definition kis_node.h:60
virtual void syncLodCache()
Definition kis_node.cpp:677
virtual void setDirty()
Definition kis_node.cpp:577