Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_projection_leaf.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2015 Dmitry Kazakov <dimula73@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
8
9#include <KoColorSpace.h>
10
11#include "kis_layer.h"
12#include "kis_image.h"
13#include "kis_mask.h"
14#include "kis_group_layer.h"
15#include "kis_selection_mask.h"
17
18#include "krita_utils.h"
19
21#include "kis_async_merger.h"
23#include "kis_clone_layer.h"
24
25
26struct Q_DECL_HIDDEN KisProjectionLeaf::Private
27{
28 Private(KisNode *_node) : node(_node) {}
29
31 bool isTemporaryHidden = false;
32
33 static bool checkPassThrough(const KisNode *node) {
34 const KisGroupLayer *group = qobject_cast<const KisGroupLayer*>(node);
35 return group && group->passThroughMode();
36 }
37
38 static bool isSelectionMask(const KisNode *node) {
39 return qobject_cast<const KisSelectionMask*>(node);
40 }
41
43 while (node && isSelectionMask(node)) {
44 node = node->nextSibling();
45 }
46 return node;
47 }
48
50 while (node && isSelectionMask(node)) {
51 node = node->prevSibling();
52 }
53 return node;
54 }
55
57 return node->parent() && checkPassThrough(node->parent());
58 }
59
61 return checkPassThrough(node);
62 }
63
65 return node && node->graphListener() && node->graphListener()->graphOverlayNode() ?
67 }
68
69 bool isTopmostNode() const {
70 return !skipSelectionMasksForward(node->nextSibling()) &&
71 node->parent() &&
72 !node->parent()->parent();
73 }
74
76 KisNodeSP root = node;
77
78 while (root->parent()) {
79 root = root->parent();
80 }
81
82 return root;
83 }
84
86 KisGroupLayer *group = qobject_cast<KisGroupLayer*>(node.data());
87 if (!group) return;
88
90 }
91};
92
94 : m_d(new Private(node))
95{
96}
97
101
103{
105
106 if (Private::isSelectionMask(m_d->node)) {
107 if (m_d->overlayProjectionLeaf() == this) {
108 node = m_d->findRoot();
109 }
110 } else {
111 node = m_d->node->parent();
112 }
113
114 while (node && Private::checkPassThrough(node)) {
115 node = node->parent();
116 }
117
119}
120
121
123{
125
126 if (!m_d->checkThisPassThrough()) {
127 node = m_d->node->firstChild();
128 node = Private::skipSelectionMasksForward(node);
129 }
130
131 if (!node && isRoot()) {
132 KisProjectionLeafSP overlayLeaf = m_d->overlayProjectionLeaf();
133 if (overlayLeaf) {
134 return overlayLeaf;
135 }
136 }
137
139}
140
142{
144
145 if (isRoot()) {
146 KisProjectionLeafSP overlayLeaf = m_d->overlayProjectionLeaf();
147 if (overlayLeaf) {
148 return overlayLeaf;
149 }
150 }
151
152 if (!m_d->checkThisPassThrough()) {
153 node = m_d->node->lastChild();
154 node = Private::skipSelectionMasksBackward(node);
155 }
156
158}
159
161{
162 if (Private::isSelectionMask(m_d->node)) {
164
165 if (m_d->overlayProjectionLeaf() == this) {
166 KisNodeSP node = m_d->findRoot()->lastChild();
167 node = Private::skipSelectionMasksBackward(node);
168 leaf = node->projectionLeaf();
169 }
170
171 return leaf;
172 }
173
175
176 if (m_d->checkThisPassThrough()) {
177 node = m_d->node->lastChild();
178 node = Private::skipSelectionMasksBackward(node);
179 }
180
181 if (!node) {
182 node = m_d->node->prevSibling();
183 node = Private::skipSelectionMasksBackward(node);
184 }
185
186 const KisProjectionLeaf *leaf = this;
187 while (!node && leaf->m_d->checkParentPassThrough()) {
188 leaf = leaf->node()->parent()->projectionLeaf().data();
189 node = leaf->node()->prevSibling();
190 node = Private::skipSelectionMasksBackward(node);
191 }
192
194}
195
197{
198 if (Private::isSelectionMask(m_d->node)) {
199 return KisProjectionLeafSP();
200 }
201
202 KisProjectionLeafSP overlayLeaf = m_d->overlayProjectionLeaf();
203 if (overlayLeaf && m_d->isTopmostNode()) {
204 return overlayLeaf;
205 }
206
207 KisNodeSP node = m_d->node->nextSibling();
208 node = Private::skipSelectionMasksForward(node);
209
210 while (node && Private::checkPassThrough(node) && node->firstChild()) {
211 node = node->firstChild();
212 node = Private::skipSelectionMasksForward(node);
213 }
214
215 if (!node && m_d->checkParentPassThrough()) {
216 node = m_d->node->parent();
217 node = Private::skipSelectionMasksForward(node);
218 }
219
221}
222
224{
225 return m_d->node;
226}
227
229{
230 return m_d->node->projectionPlane();
231}
232
234{
235 return m_d->node->accept(visitor);
236}
237
239{
240 return m_d->node->original();
241}
242
244{
245 return m_d->node->projection();
246}
247
249{
250 const KisGroupLayer *group = qobject_cast<const KisGroupLayer*>(m_d->node.data());
251 return group ? group->lazyDestinationForSubtreeComposition() : nullptr;
252}
253
255{
256 return (bool)!m_d->node->parent();
257}
258
260{
261 return (bool)qobject_cast<const KisLayer*>(m_d->node.data()) &&
262 !m_d->node->isFakeNode();
263}
264
266{
267 return (bool)qobject_cast<const KisMask*>(m_d->node.data()) &&
268 !m_d->node->isFakeNode();
269}
270
272{
273 return (bool)qobject_cast<const KisGroupLayer*>(m_d->node.data());
274}
275
277{
278 return (bool)qobject_cast<const KisAdjustmentLayer*>(m_d->node.data());
279}
280
282{
283 if (m_d->isTemporaryHidden || isDroppedNode()) return false;
284
285 // TODO: check opacity as well!
286
287 bool hiddenByParentPassThrough = false;
288
289 KisNodeSP node = m_d->node->parent();
290 while (node && node->projectionLeaf()->m_d->checkThisPassThrough()) {
291 hiddenByParentPassThrough |= !node->visible();
292 node = node->parent();
293 }
294
295 return (m_d->node->visible(false) || m_d->node->isIsolatedRoot()) &&
296 !m_d->checkThisPassThrough() &&
297 !hiddenByParentPassThrough;
298}
299
301{
302 quint8 resultOpacity = m_d->node->opacity();
303
304 if (m_d->checkParentPassThrough()) {
305 quint8 parentOpacity = m_d->node->parent()->projectionLeaf()->opacity();
306
307 resultOpacity = KritaUtils::mergeOpacityU8(resultOpacity, parentOpacity);
308 }
309
310 return resultOpacity;
311}
312
314{
315 QBitArray channelFlags;
316
317 KisLayer *layer = qobject_cast<KisLayer*>(m_d->node.data());
318 if (!layer) return channelFlags;
319
320 channelFlags = layer->channelFlags();
321
322 if (m_d->checkParentPassThrough()) {
323 QBitArray parentChannelFlags;
324
325 if (*m_d->node->colorSpace() ==
326 *m_d->node->parent()->colorSpace()) {
327
328 KisLayer *parentLayer = qobject_cast<KisLayer*>(m_d->node->parent().data());
329 parentChannelFlags = parentLayer->channelFlags();
330 }
331
333 }
334
335 return channelFlags;
336}
337
339{
340 return (bool)m_d->node->graphListener();
341}
342
344{
345 KisLayer *layer = qobject_cast<KisLayer*>(m_d->node.data());
346 return layer ? layer->hasClones() : false;
347}
348
350{
351 return dropReason() != NodeAvailable;
352}
353
355{
356 return visible() || hasClones();
357}
358
360{
361 if (qobject_cast<KisMask*>(m_d->node.data()) &&
362 m_d->checkParentPassThrough()) {
363
364 return DropPassThroughMask;
365 }
366
367 KisCloneLayer *cloneLayer = qobject_cast<KisCloneLayer*>(m_d->node.data());
368 if (cloneLayer && cloneLayer->copyFrom()) {
369 KisProjectionLeafSP leaf = cloneLayer->copyFrom()->projectionLeaf();
370
371 if (leaf->m_d->checkThisPassThrough()) {
373 }
374 }
375
376 return NodeAvailable;
377}
378
380{
381 return this == m_d->overlayProjectionLeaf();
382}
383
385{
386 m_d->isTemporaryHidden = value;
387}
388
390{
391 return m_d->isTemporaryHidden;
392}
393
399{
400 if (!m_d->checkThisPassThrough()) return;
401
402 m_d->temporarySetPassThrough(false);
403
404 const QRect updateRect = projection()->defaultBounds()->bounds();
405
406 KisRefreshSubtreeWalker walker(updateRect);
407 walker.collectRects(m_d->node, updateRect);
408
409 KisAsyncMerger merger;
410 merger.startMerge(walker);
411
412 m_d->temporarySetPassThrough(true);
413}
float value(const T *src, size_t ch)
void startMerge(KisBaseRectsWalker &walker, bool notifyClones=true)
void collectRects(KisNodeSP node, const QRect &requestedRect)
virtual QRect bounds() const =0
KisDefaultBoundsBaseSP defaultBounds() const
bool isSelectionMask(KisNodeSP node)
QSharedPointer< KisProjectionLeaf > KisProjectionLeafSP
Definition kis_types.h:292
quint8 mergeOpacityU8(quint8 opacity, quint8 parentOpacity)
QBitArray mergeChannelFlags(const QBitArray &childFlags, const QBitArray &parentFlags)
quint8 opacity() const
virtual bool visible(bool recursive=false) const
KisLayerSP copyFrom
KisPaintDeviceSP lazyDestinationForSubtreeComposition() const
void setPassThroughMode(bool value)
QBitArray channelFlags
Definition kis_layer.cc:167
bool hasClones() const
Definition kis_layer.cc:483
virtual KisNode * graphOverlayNode() const
KisNodeSP prevSibling() const
Definition kis_node.cpp:402
KisNodeSP firstChild() const
Definition kis_node.cpp:361
KisProjectionLeafSP projectionLeaf
Definition kis_node.cpp:93
KisNodeWSP parent
Definition kis_node.cpp:86
KisNodeSP lastChild() const
Definition kis_node.cpp:367
KisNodeSP nextSibling() const
Definition kis_node.cpp:408
KisNodeGraphListener * graphListener
Definition kis_node.cpp:87
static KisNodeSP skipSelectionMasksForward(KisNodeSP node)
KisProjectionLeafSP parent() const
KisAbstractProjectionPlaneSP projectionPlane() const
void explicitlyRegeneratePassThroughProjection()
KisNodeSP findRoot() const
const QScopedPointer< Private > m_d
KisProjectionLeafSP prevSibling() const
static KisNodeSP skipSelectionMasksBackward(KisNodeSP node)
KisPaintDeviceSP original()
KisPaintDeviceSP lazyDestinationForSubtreeComposition()
bool isTemporaryHiddenFromRendering() const
KisProjectionLeafSP nextSibling() const
static bool isSelectionMask(const KisNode *node)
KisProjectionLeaf(KisNode *node)
void temporarySetPassThrough(bool value)
static bool checkPassThrough(const KisNode *node)
void setTemporaryHiddenFromRendering(bool value)
bool accept(KisNodeVisitor &visitor)
QBitArray channelFlags() const
bool isOverlayProjectionLeaf() const
NodeDropReason dropReason() const
KisProjectionLeafSP lastChild() const
KisPaintDeviceSP projection()
KisProjectionLeafSP overlayProjectionLeaf() const
KisProjectionLeafSP firstChild() const