Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_layer.cc
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2002 Patrick Julien <freak@codepimps.org>
3 * SPDX-FileCopyrightText: 2005 C. Boemann <cbo@boemann.dk>
4 * SPDX-FileCopyrightText: 2009 Dmitry Kazakov <dimula73@gmail.com>
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9#include "kis_layer.h"
10
11
12#include <klocalizedstring.h>
13#include <QImage>
14#include <QBitArray>
15#include <QStack>
16#include <QReadWriteLock>
17#include <QReadLocker>
18#include <QWriteLocker>
19
20#include <KoIcon.h>
21#include <kis_icon.h>
22#include <KoProperties.h>
24#include <KoColorSpace.h>
25
26#include "kis_debug.h"
27#include "kis_image.h"
28
29#include "kis_painter.h"
30#include "kis_mask.h"
31#include "kis_effect_mask.h"
32#include "kis_filter_mask.h"
33#include "kis_selection_mask.h"
34#include "kis_meta_data_store.h"
35#include "kis_selection.h"
36#include "kis_paint_layer.h"
38
39#include "kis_clone_layer.h"
40
41#include "kis_psd_layer_style.h"
44
45#include "krita_utils.h"
47#include "kis_layer_utils.h"
48#include "kis_projection_leaf.h"
50
51
53public:
54 void addClone(KisCloneLayerWSP cloneLayer) {
55 m_clonesList.append(cloneLayer);
56 }
57
58 void removeClone(KisCloneLayerWSP cloneLayer) {
59 m_clonesList.removeOne(cloneLayer);
60 }
61
62 void setDirty(const QRect &rect, bool dontInvalidateFrames) {
63 Q_FOREACH (KisCloneLayerSP clone, m_clonesList) {
64 if (clone) {
65 clone->setDirtyOriginal(rect, dontInvalidateFrames);
66 }
67 }
68 }
69
71 return m_clonesList;
72 }
73
74 bool hasClones() const {
75 return !m_clonesList.isEmpty();
76 }
77
78private:
80};
81
83public:
85 : m_parent(parent)
86 {
87 }
88
90 QReadLocker readLock(&m_lock);
91
93 readLock.unlock();
94
95 QWriteLocker writeLock(&m_lock);
97 KoProperties properties;
98 properties.setProperty("active", true);
99 properties.setProperty("visible", true);
100 QList<KisNodeSP> masks = m_parent->childNodes(QStringList("KisSelectionMask"), properties);
101
102 // return the first visible mask
103 Q_FOREACH (KisNodeSP mask, masks) {
104 if (mask) {
105 m_selectionMask = dynamic_cast<KisSelectionMask*>(mask.data());
106 break;
107 }
108 }
110 }
111
112 // return under write lock
113 return m_selectionMask;
114 }
115
116 // return under read lock
117 return m_selectionMask;
118 }
119
121 QReadLocker readLock(&m_lock);
122
124 readLock.unlock();
125
126 QWriteLocker writeLock(&m_lock);
130 }
131
132 // return under write lock
133 return m_effectMasks;
134 }
135
136 // return under read lock
137 return m_effectMasks;
138 }
139
140 void setDirty()
141 {
142 QWriteLocker l(&m_lock);
144 m_isEffectMasksValid = false;
145 m_selectionMask = 0;
147 }
148
149private:
151
152 QReadWriteLock m_lock;
153
158};
159
179
180
181KisLayer::KisLayer(KisImageWSP image, const QString &name, quint8 opacity)
182 : KisNode(image)
183 , m_d(new Private(this))
184{
185 setName(name);
187 m_d->metaDataStore = new KisMetaData::Store();
188 m_d->projectionPlane = toQShared(new KisLayerProjectionPlane(this));
189 m_d->safeProjection = new KisSafeNodeProjectionStore();
190 m_d->safeProjection->setImage(image);
191}
192
194 : KisNode(rhs)
195 , m_d(new Private(this))
196{
197 if (this != &rhs) {
198 m_d->metaDataStore = new KisMetaData::Store(*rhs.m_d->metaDataStore);
199 m_d->channelFlags = rhs.m_d->channelFlags;
200
201 setName(rhs.name());
202 m_d->projectionPlane = toQShared(new KisLayerProjectionPlane(this));
203 m_d->safeProjection = new KisSafeNodeProjectionStore(*rhs.m_d->safeProjection);
204 m_d->safeProjection->setImage(image());
205
206 if (rhs.m_d->layerStyle) {
207 m_d->layerStyle = rhs.m_d->layerStyle->clone().dynamicCast<KisPSDLayerStyle>();
208
209 if (rhs.m_d->layerStyleProjectionPlane) {
210 m_d->layerStyleProjectionPlane = toQShared(
211 new KisLayerStyleProjectionPlane(*rhs.m_d->layerStyleProjectionPlane,
212 this,
213 m_d->layerStyle));
214 }
215 }
216 }
217}
218
220{
221 delete m_d->metaDataStore;
222 delete m_d;
223}
224
231
233{
241 KisNodeSP parentNode = parent();
242 if (!parentNode) return 0;
243
244 if (!parentNode->colorSpace()) return 0;
245 const KoCompositeOp* op = parentNode->colorSpace()->compositeOp(compositeOpId());
246 return op ? op : parentNode->colorSpace()->compositeOp(COMPOSITE_OVER);
247}
248
250{
251 return m_d->layerStyle;
252}
253
255{
256 if (layerStyle) {
257 KIS_SAFE_ASSERT_RECOVER_NOOP(layerStyle->hasLocalResourcesSnapshot());
258
259 m_d->layerStyle = layerStyle;
260
261 KisLayerStyleProjectionPlaneSP plane = !layerStyle->isEmpty() ?
264
265 m_d->layerStyleProjectionPlane = plane;
266 } else {
267 m_d->layerStyleProjectionPlane.clear();
268 m_d->layerStyle.clear();
269 }
270}
271
273{
275 l << KisBaseNode::Property(KoID("opacity", i18n("Opacity")), i18n("%1%", percentOpacity()));
276
277 const KoCompositeOp * compositeOp = this->compositeOp();
278
279 if (compositeOp) {
280 l << KisBaseNode::Property(KoID("compositeop", i18n("Blending Mode")), compositeOp->description());
281 }
282
283 if (m_d->layerStyle && !m_d->layerStyle->isEmpty()) {
285 }
286
288
289 if (colorOverlayMask()) {
290 // Use an immutable property (with a string value), to hide it in the layer properties dialog.
292 }
293
294 return l;
295}
296
298{
300
301 Q_FOREACH (const KisBaseNode::Property &property, properties) {
302 if (property.id == KisLayerPropertiesIcons::inheritAlpha.id()) {
303 disableAlphaChannel(property.state.toBool());
304 }
305
306 if (property.id == KisLayerPropertiesIcons::layerStyle.id()) {
307 if (m_d->layerStyle &&
308 m_d->layerStyle->isEnabled() != property.state.toBool()) {
309
310 m_d->layerStyle->setEnabled(property.state.toBool());
311
314 }
315 }
316 }
317}
318
320{
321 QBitArray newChannelFlags = m_d->channelFlags;
322
323 if(newChannelFlags.isEmpty())
324 newChannelFlags = colorSpace()->channelFlags(true, true);
325
326 if(disable)
327 newChannelFlags &= colorSpace()->channelFlags(true, false);
328 else
329 newChannelFlags |= colorSpace()->channelFlags(false, true);
330
331 setChannelFlags(newChannelFlags);
332}
333
335{
337 QBitArray flags = colorSpace()->channelFlags(false, true) & m_d->channelFlags;
338 return flags.count(true) == 0 && !m_d->channelFlags.isEmpty();
339}
340
341
342void KisLayer::setChannelFlags(const QBitArray & channelFlags)
343{
344 Q_ASSERT(channelFlags.isEmpty() ||((quint32)channelFlags.count() == colorSpace()->channelCount()));
345
347 this->channelFlags())) {
348 return;
349 }
350
351 if (!channelFlags.isEmpty() &&
352 channelFlags == QBitArray(channelFlags.size(), true)) {
353
354 m_d->channelFlags.clear();
355 } else {
356 m_d->channelFlags = channelFlags;
357 }
358
361}
362
363QBitArray & KisLayer::channelFlags() const
364{
365 return m_d->channelFlags;
366}
367
369{
370 return nodeProperties().boolProperty("temporary", false);
371}
372
374{
375 setNodeProperty("temporary", t);
376}
377
379{
380 // we own the projection device, so we should take care about it
382 if (projection && projection != original()) {
384 }
385 m_d->safeProjection->setImage(image);
386
388}
389
391{
392 return
393 this->compositeOpId() == otherLayer->compositeOpId() &&
394 this->opacity() == otherLayer->opacity() &&
395 this->channelFlags() == otherLayer->channelFlags() &&
396 !this->layerStyle() && !otherLayer->layerStyle() &&
397 (this->colorSpace() == otherLayer->colorSpace() ||
398 *this->colorSpace() == *otherLayer->colorSpace());
399}
400
402{
403 Q_UNUSED(layers);
404 return nullptr;
405}
406
408{
409 const bool keepBlendingOptions = canMergeAndKeepBlendOptions(prevLayer);
410
411 KisLayerSP newLayer = new KisPaintLayer(image(), prevLayer->name(), OPACITY_OPAQUE_U8);
412
413 if (keepBlendingOptions) {
414 newLayer->setCompositeOpId(compositeOpId());
415 newLayer->setOpacity(opacity());
416 newLayer->setChannelFlags(channelFlags());
417 }
418
419 return newLayer;
420}
421
422void KisLayer::fillMergedLayerTemplate(KisLayerSP dstLayer, KisLayerSP prevLayer, bool skipPaintingThisLayer)
423{
424 const bool keepBlendingOptions = canMergeAndKeepBlendOptions(prevLayer);
425
426 QRect layerProjectionExtent = this->projection()->extent();
427 QRect prevLayerProjectionExtent = prevLayer->projection()->extent();
428 bool alphaDisabled = this->alphaChannelDisabled();
429 bool prevAlphaDisabled = prevLayer->alphaChannelDisabled();
430
431 KisPaintDeviceSP mergedDevice = dstLayer->paintDevice();
432
433 if (!keepBlendingOptions) {
434 KisPainter gc(mergedDevice);
435
436 KisImageSP imageSP = image().toStrongRef();
437 if (!imageSP) {
438 return;
439 }
440
441 //Copy the pixels of previous layer with their actual alpha value
442 prevLayer->disableAlphaChannel(false);
443
444 prevLayer->projectionPlane()->apply(&gc, prevLayerProjectionExtent | imageSP->bounds());
445
446 //Restore the previous prevLayer disableAlpha status for correct undo/redo
447 prevLayer->disableAlphaChannel(prevAlphaDisabled);
448
449 if (!skipPaintingThisLayer) {
450 //Paint the pixels of the current layer, using their actual alpha value
451 if (alphaDisabled == prevAlphaDisabled) {
452 this->disableAlphaChannel(false);
453 }
454
455 this->projectionPlane()->apply(&gc, layerProjectionExtent | imageSP->bounds());
456
457 //Restore the layer disableAlpha status for correct undo/redo
458 this->disableAlphaChannel(alphaDisabled);
459 }
460 }
461 else {
462 //Copy prevLayer
463 KisPaintDeviceSP srcDev = prevLayer->projection();
464 mergedDevice->makeCloneFrom(srcDev, srcDev->extent());
465
466 if (!skipPaintingThisLayer) {
467 //Paint layer on the copy
468 KisPainter gc(mergedDevice);
469 gc.bitBlt(layerProjectionExtent.topLeft(), this->projection(), layerProjectionExtent);
470 }
471 }
472}
473
475{
476 m_d->clonesList.addClone(clone);
477}
478
480{
481 m_d->clonesList.removeClone(clone);
482}
483
485{
486 return m_d->clonesList.registeredClones();
487}
488
490{
491 return m_d->clonesList.hasClones();
492}
493
494void KisLayer::updateClones(const QRect &rect, bool dontInvalidateFrames)
495{
496 m_d->clonesList.setDirty(rect, dontInvalidateFrames);
497}
498
500{
501 m_d->masksCache.setDirty();
502}
503
505{
506 return m_d->masksCache.selectionMask();
507}
508
510{
512
513 if (mask) {
514 return mask->selection();
515 }
516
517 KisImageSP image = this->image();
518 if (image) {
519 return image->globalSelection();
520 }
521 return KisSelectionSP();
522}
523
526
528{
529 return m_d->masksCache.effectMasks();
530}
531
533{
534 if (lastNode.isNull()) {
535 return effectMasks();
536 } else {
537 // happens rarely.
538 return searchEffectMasks(lastNode);
539 }
540}
541
543{
545
547
548 KisProjectionLeafSP child = projectionLeaf()->firstChild();
549 while (child) {
550 if (child->node() == lastNode) break;
551
553 KIS_SAFE_ASSERT_RECOVER_NOOP(child->node());
554
555 if (child->visible()) {
556 KisEffectMaskSP mask = dynamic_cast<KisEffectMask*>(const_cast<KisNode*>(child->node().data()));
557 if (mask) {
558 masks.append(mask);
559 }
560 }
561
562 child = child->nextSibling();
563 }
564
565 return masks;
566}
567
569{
570 return !m_d->masksCache.effectMasks().isEmpty();
571}
572
574{
575 if (hasEffectMasks()) {
576 // Iterate the masks in reverse, the last element is on top of the stack.
577 auto allMasks = effectMasks();
578 for (auto iter = allMasks.rbegin(); iter != allMasks.rend(); ++iter) {
579 if ((*iter)->inherits("KisFilterMask")) {
580 KisFilterMaskSP filterMask = qobject_cast<KisFilterMask*>((*iter).data());
581 if (filterMask->filter()->name() == "fastcoloroverlay") {
582 return filterMask;
583 }
584 }
585 }
586 }
587 return nullptr;
588}
589
591 const QRect &requestedRect,
592 bool &rectVariesFlag) const
593{
594 rectVariesFlag = false;
595
596 QRect prevChangeRect = requestedRect;
597
602 QRect changeRect = requestedRect;
603
604 Q_FOREACH (const KisEffectMaskSP& mask, masks) {
605 changeRect = mask->changeRect(prevChangeRect);
606
607 if (changeRect != prevChangeRect)
608 rectVariesFlag = true;
609
610 prevChangeRect = changeRect;
611 }
612
613 return changeRect;
614}
615
617 const QRect &changeRect,
618 QStack<QRect> &applyRects,
619 bool &rectVariesFlag) const
620{
621 rectVariesFlag = false;
622
623 QRect prevNeedRect = changeRect;
624 QRect needRect;
625
626 for (qint32 i = masks.size() - 1; i >= 0; i--) {
627 applyRects.push(prevNeedRect);
628
629 needRect = masks[i]->needRect(prevNeedRect);
630
631 if (prevNeedRect != needRect)
632 rectVariesFlag = true;
633
634 prevNeedRect = needRect;
635 }
636
637 return needRect;
638}
639
641 KisNodeSP filthy,
642 KisNodeSP parent)
643{
644 if (parent == filthy || parent != filthy->parent()) {
646 }
647
648 if (nodeInQuestion == filthy) {
649 return KisNode::N_FILTHY;
650 }
651
652 KisNodeSP node = nodeInQuestion->prevSibling();
653 while (node) {
654 if (node == filthy) {
656 }
657 node = node->prevSibling();
658 }
659
661}
662
664 KisPaintDeviceSP destination,
665 const QRect &requestedRect,
666 KisNodeSP filthyNode,
667 KisNodeSP lastNode,
668 KisRenderPassFlags flags) const
669{
670 Q_ASSERT(source);
671 Q_ASSERT(destination);
672
673 QList<KisEffectMaskSP> masks = effectMasks(lastNode);
674 QRect changeRect;
675 QRect needRect;
676
677 if (masks.isEmpty()) {
678 changeRect = requestedRect;
679 if (source != destination) {
680 copyOriginalToProjection(source, destination, requestedRect);
681 }
682 } else {
683 QStack<QRect> applyRects;
684 bool changeRectVaries;
685 bool needRectVaries;
686
691 changeRectVaries = false;
692 changeRect = requestedRect;
693 //changeRect = masksChangeRect(masks, requestedRect,
694 // changeRectVaries);
695
697 applyRects, needRectVaries);
698
699 if (!changeRectVaries && !needRectVaries) {
706 Q_ASSERT(needRect == requestedRect);
707
708 if (source != destination) {
710 }
711
712 Q_FOREACH (const KisEffectMaskSP& mask, masks) {
713 const QRect maskApplyRect = applyRects.pop();
714 const QRect maskNeedRect =
715 applyRects.isEmpty() ? needRect : applyRects.top();
716
717 PositionToFilthy maskPosition = calculatePositionToFilthy(mask, filthyNode, const_cast<KisLayer*>(this));
718 mask->apply(destination, maskApplyRect, maskNeedRect, maskPosition, flags);
719 }
720 Q_ASSERT(applyRects.isEmpty());
721 } else {
728 KisPaintDeviceSP tempDevice = new KisPaintDevice(colorSpace());
729 tempDevice->prepareClone(source);
731
732 QRect maskApplyRect = applyRects.pop();
733 QRect maskNeedRect = needRect;
734
735 Q_FOREACH (const KisEffectMaskSP& mask, masks) {
736 PositionToFilthy maskPosition = calculatePositionToFilthy(mask, filthyNode, const_cast<KisLayer*>(this));
737 mask->apply(tempDevice, maskApplyRect, maskNeedRect, maskPosition, flags);
738
739 if (!applyRects.isEmpty()) {
740 maskNeedRect = maskApplyRect;
741 maskApplyRect = applyRects.pop();
742 }
743 }
744 Q_ASSERT(applyRects.isEmpty());
745
746 KisPainter::copyAreaOptimized(changeRect.topLeft(), tempDevice, destination, changeRect);
747 }
748 }
749
750 return changeRect;
751}
752
753QRect KisLayer::updateProjection(const QRect& rect, KisNodeSP filthyNode, KisRenderPassFlags flags)
754{
755 QRect updatedRect = rect;
756 KisPaintDeviceSP originalDevice = original();
757 if (!rect.isValid() ||
758 (!visible() && !isIsolatedRoot() && !hasClones()) ||
759 !originalDevice) return QRect();
760
761 if (!needProjection() && !hasEffectMasks()) {
762 m_d->safeProjection->releaseDevice();
763 } else {
764
765 if (!updatedRect.isEmpty()) {
766 KisPaintDeviceSP projection = m_d->safeProjection->getDeviceLazy(originalDevice);
767 updatedRect = applyMasks(originalDevice, projection,
768 updatedRect, filthyNode, 0, flags);
769 }
770 }
771
772 return updatedRect;
773}
774
775QRect KisLayer::partialChangeRect(KisNodeSP lastNode, const QRect& rect)
776{
777 bool changeRectVaries = false;
780 changeRectVaries);
781
782 return changeRect;
783}
784
788void KisLayer::buildProjectionUpToNode(KisPaintDeviceSP projection, KisNodeSP lastNode, const QRect& rect)
789{
790 QRect changeRect = partialChangeRect(lastNode, rect);
791
792 KisPaintDeviceSP originalDevice = original();
793
795
796 if (!changeRect.isEmpty()) {
797 applyMasks(originalDevice, projection,
799 }
800}
801
803{
804 return false;
805}
806
808 KisPaintDeviceSP projection,
809 const QRect& rect) const
810{
812}
813
815{
816 return m_d->layerStyleProjectionPlane ?
817 KisAbstractProjectionPlaneSP(m_d->layerStyleProjectionPlane) :
819}
820
822{
823 return m_d->projectionPlane;
824}
825
827{
828 KisPaintDeviceSP originalDevice = original();
829
830 return needProjection() || hasEffectMasks() ?
831 m_d->safeProjection->getDeviceLazy(originalDevice) : originalDevice;
832}
833
834QRect KisLayer::userVisibleBoundsImpl(bool exactBounds) const
835{
836 QRect changeRect = exactBounds ? this->exactBounds() : this->extent();
837
841
842 bool changeRectVaries;
844 changeRect = masksChangeRect(effectMasks(), changeRect, changeRectVaries);
845
846 return changeRect;
847}
848
849
851{
852 return userVisibleBoundsImpl(true);
853}
854
856{
857 return userVisibleBoundsImpl(false);
858}
859
864
865QRect KisLayer::changeRect(const QRect &rect, PositionToFilthy pos) const
866{
867 QRect changeRect = rect;
869
870 if(pos == KisNode::N_FILTHY) {
871 QRect projectionToBeUpdated = amortizedProjectionRectForCleanupInChangePass() & changeRect;
872
873 bool changeRectVaries;
875 changeRect = masksChangeRect(effectMasks(), changeRect, changeRectVaries);
876
884 if (!projectionToBeUpdated.isEmpty() &&
885 !changeRect.contains(projectionToBeUpdated)) {
886
887 changeRect |= projectionToBeUpdated;
888 }
889 }
890
891 // TODO: string comparison: optimize!
892 if (pos != KisNode::N_FILTHY &&
895
896 changeRect |= rect;
897 }
898
899 return changeRect;
900}
901
903{
904 if (dynamic_cast<KisMask*>(changedChildNode.data())) {
906 }
907}
908
909QRect KisLayer::incomingChangeRect(const QRect &rect) const
910{
911 return rect;
912}
913
914QRect KisLayer::outgoingChangeRect(const QRect &rect) const
915{
916 return rect;
917}
918
919QRect KisLayer::needRectForOriginal(const QRect &rect) const
920{
921 QRect needRect = rect;
922
923 const QList<KisEffectMaskSP> masks = effectMasks();
924
925 if (!masks.isEmpty()) {
926 QStack<QRect> applyRects;
927 bool needRectVaries;
928
929 needRect = masksNeedRect(masks, rect,
930 applyRects, needRectVaries);
931 }
932
933 return needRect;
934}
935
936QImage KisLayer::createThumbnail(qint32 w, qint32 h, Qt::AspectRatioMode aspectRatioMode, KisThumbnailBoundsMode boundsMode)
937{
938 if (w == 0 || h == 0) {
939 return QImage();
940 }
941
942 KisPaintDeviceSP originalDevice = original();
943
944 return originalDevice
945 ? originalDevice->createThumbnail(w, h, aspectRatioMode, boundsMode)
946 : QImage();
947}
948
950{
951 KisPaintDeviceSP originalDevice = original();
952 return originalDevice ? originalDevice->sequenceNumber() : -1;
953}
954
955QImage KisLayer::createThumbnailForFrame(qint32 w, qint32 h, int time, Qt::AspectRatioMode aspectRatioMode, KisThumbnailBoundsMode boundsMode)
956{
957 if (w == 0 || h == 0) {
958 return QImage();
959 }
960
961 KisPaintDeviceSP originalDevice = original();
962 if (originalDevice ) {
963 KisRasterKeyframeChannel *channel = originalDevice->keyframeChannel();
964
965 if (channel) {
966 KisPaintDeviceSP targetDevice = new KisPaintDevice(colorSpace());
967 KisRasterKeyframeSP keyframe = channel->activeKeyframeAt<KisRasterKeyframe>(time);
968 keyframe->writeFrameToDevice(targetDevice);
969 return targetDevice->createThumbnail(w, h, aspectRatioMode, boundsMode);
970 }
971 }
972
973 return createThumbnail(w, h, aspectRatioMode, boundsMode);
974}
975
976qint32 KisLayer::x() const
977{
978 KisPaintDeviceSP originalDevice = original();
979 return originalDevice ? originalDevice->x() : 0;
980}
981qint32 KisLayer::y() const
982{
983 KisPaintDeviceSP originalDevice = original();
984 return originalDevice ? originalDevice->y() : 0;
985}
986void KisLayer::setX(qint32 x)
987{
988 KisPaintDeviceSP originalDevice = original();
989 if (originalDevice)
990 originalDevice->setX(x);
991}
992void KisLayer::setY(qint32 y)
993{
994 KisPaintDeviceSP originalDevice = original();
995 if (originalDevice)
996 originalDevice->setY(y);
997}
998
999QRect KisLayer::layerExtentImpl(bool needExactBounds) const
1000{
1001 QRect additionalMaskExtent = QRect();
1003
1004 Q_FOREACH(KisEffectMaskSP mask, effectMasks) {
1005 additionalMaskExtent |= mask->nonDependentExtent();
1006 }
1007
1008 KisPaintDeviceSP originalDevice = original();
1009 QRect layerExtent;
1010
1011 if (originalDevice) {
1012 layerExtent = needExactBounds ?
1013 originalDevice->exactBounds() :
1014 originalDevice->extent();
1015 }
1016
1017 QRect additionalCompositeOpExtent;
1018 if (compositeOpId() == COMPOSITE_COPY ||
1021
1022 additionalCompositeOpExtent = originalDevice->defaultBounds()->bounds();
1023 }
1024
1025 return layerExtent | additionalMaskExtent | additionalCompositeOpExtent;
1026}
1027
1028QRect KisLayer::extent() const
1029{
1030 return layerExtentImpl(false);
1031}
1032
1034{
1035 return layerExtentImpl(true);
1036}
1037
1039{
1040 return qobject_cast<KisLayer*>(parent().data());
1041}
1042
1044{
1045 return m_d->metaDataStore;
1046}
1047
KisMagneticGraph::vertex_descriptor source(typename KisMagneticGraph::edge_descriptor e, KisMagneticGraph g)
QList< QString > QStringList
const quint8 OPACITY_OPAQUE_U8
const QString COMPOSITE_OVER
const QString COMPOSITE_COPY
const QString COMPOSITE_DESTINATION_ATOP
const QString COMPOSITE_DESTINATION_IN
void setDirty(const QRect &rect, bool dontInvalidateFrames)
Definition kis_layer.cc:62
bool hasClones() const
Definition kis_layer.cc:74
const QList< KisCloneLayerWSP > registeredClones() const
Definition kis_layer.cc:70
QList< KisCloneLayerWSP > m_clonesList
Definition kis_layer.cc:79
void addClone(KisCloneLayerWSP cloneLayer)
Definition kis_layer.cc:54
void removeClone(KisCloneLayerWSP cloneLayer)
Definition kis_layer.cc:58
virtual QRect bounds() const =0
KisSelectionSP globalSelection() const
Definition kis_image.cc:695
QRect bounds() const override
KisKeyframeSP activeKeyframeAt(int time) const
KisLayerMasksCache(KisLayer *parent)
Definition kis_layer.cc:84
KisSelectionMaskSP m_selectionMask
Definition kis_layer.cc:156
KisSelectionMaskSP selectionMask()
Definition kis_layer.cc:89
QReadWriteLock m_lock
Definition kis_layer.cc:152
QList< KisEffectMaskSP > m_effectMasks
Definition kis_layer.cc:157
QList< KisEffectMaskSP > effectMasks()
Definition kis_layer.cc:120
KisLayer * m_parent
Definition kis_layer.cc:150
static KisBaseNode::Property getProperty(const KoID &id, bool state)
KisRasterKeyframeChannel * keyframeChannel() const
void setX(qint32 x)
int sequenceNumber() const
void setDefaultBounds(KisDefaultBoundsBaseSP bounds)
QImage createThumbnail(qint32 maxw, qint32 maxh, KisThumbnailBoundsMode boundsMode=KisThumbnailBoundsMode::Precise, qreal oversample=1, KoColorConversionTransformation::Intent renderingIntent=KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::ConversionFlags conversionFlags=KoColorConversionTransformation::internalConversionFlags())
QRect exactBounds() const
QRect extent() const
const KoColorSpace * colorSpace() const
QRect exactBoundsAmortized() const
KisDefaultBoundsBaseSP defaultBounds() const
void prepareClone(KisPaintDeviceSP src)
void setY(qint32 y)
void makeCloneFrom(KisPaintDeviceSP src, const QRect &rect)
static void copyAreaOptimized(const QPoint &dstPt, KisPaintDeviceSP src, KisPaintDeviceSP dst, const QRect &originalSrcRect)
void bitBlt(qint32 dstX, qint32 dstY, const KisPaintDeviceSP srcDev, qint32 srcX, qint32 srcY, qint32 srcWidth, qint32 srcHeight)
The KisRasterKeyframeChannel is a concrete KisKeyframeChannel subclass that stores and manages KisRas...
The KisRasterKeyframe class is a concrete subclass of KisKeyframe that wraps a physical raster image ...
bool isNull() const
KisSharedPtr< T > toStrongRef() const
toStrongRef returns a KisSharedPtr which may be dereferenced.
QBitArray channelFlags(bool color=true, bool alpha=false) const
const KoCompositeOp * compositeOp(const QString &id, const KoColorSpace *srcSpace=nullptr) const
Definition KoID.h:30
QString id() const
Definition KoID.cpp:63
bool boolProperty(const QString &name, bool defaultValue=false) const
void setProperty(const QString &name, const QVariant &value)
#define KIS_ASSERT_RECOVER_RETURN_VALUE(cond, val)
Definition kis_assert.h:85
#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 KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:130
KisNode::PositionToFilthy calculatePositionToFilthy(KisNodeSP nodeInQuestion, KisNodeSP filthy, KisNodeSP parent)
Definition kis_layer.cc:640
QSharedPointer< KisLayerStyleProjectionPlane > KisLayerStyleProjectionPlaneSP
QSharedPointer< T > toQShared(T *ptr)
KisThumbnailBoundsMode
Definition kis_types.h:336
KisSharedPtr< KisSelection > KisSelectionSP
Definition kis_types.h:149
QSharedPointer< KisAbstractProjectionPlane > KisAbstractProjectionPlaneSP
Definition kis_types.h:288
bool compareChannelFlags(QBitArray f1, QBitArray f2)
void setNodeProperty(const QString &name, const QVariant &value)
quint8 percentOpacity() const
bool isIsolatedRoot() const
const QString & compositeOpId() const
void setOpacity(quint8 val)
const KoProperties & nodeProperties() const
KoProperties properties
void setName(const QString &name)
virtual const KoColorSpace * colorSpace() const =0
KisImageWSP image
virtual KisPaintDeviceSP paintDevice() const =0
virtual PropertyList sectionModelProperties() const
QString name() const
void setCompositeOpId(const QString &compositeOpId)
quint8 opacity() const
virtual bool visible(bool recursive=false) const
virtual void setSectionModelProperties(const PropertyList &properties)
KisPaintDeviceSP projection() const override
Definition kis_layer.cc:826
void setImage(KisImageWSP image) override
Definition kis_layer.cc:378
qint32 y() const override
Definition kis_layer.cc:981
void disableAlphaChannel(bool disable)
Definition kis_layer.cc:319
virtual void fillMergedLayerTemplate(KisLayerSP dstLayer, KisLayerSP prevLayer, bool skipPaintingThisLayer=false)
Definition kis_layer.cc:422
virtual QRect outgoingChangeRect(const QRect &rect) const
Definition kis_layer.cc:914
virtual QRect amortizedProjectionRectForCleanupInChangePass() const
Definition kis_layer.cc:860
QRect looseUserVisibleBounds() const
Definition kis_layer.cc:855
virtual KisLayerSP createMergedLayerTemplate(KisLayerSP prevLayer)
Definition kis_layer.cc:407
Private *const m_d
Definition kis_layer.h:450
void childNodeChanged(KisNodeSP changedChildNode) override
Definition kis_layer.cc:902
QImage createThumbnailForFrame(qint32 w, qint32 h, int time, Qt::AspectRatioMode aspectRatioMode, KisThumbnailBoundsMode boundsMode) override
Definition kis_layer.cc:955
QRect needRectForOriginal(const QRect &rect) const
Definition kis_layer.cc:919
QList< KisEffectMaskSP > effectMasks() const
Definition kis_layer.cc:527
KisMetaData::Store * metaData()
KisCloneLayersList clonesList
Definition kis_layer.cc:169
bool canMergeAndKeepBlendOptions(KisLayerSP otherLayer)
Definition kis_layer.cc:390
bool hasEffectMasks() const
Definition kis_layer.cc:568
QRect exactBounds() const override
QRect updateProjection(const QRect &rect, KisNodeSP filthyNode, KisRenderPassFlags flags)
Definition kis_layer.cc:753
void registerClone(KisCloneLayerWSP clone)
Definition kis_layer.cc:474
QBitArray channelFlags
Definition kis_layer.cc:167
QRect masksChangeRect(const QList< KisEffectMaskSP > &masks, const QRect &requestedRect, bool &rectVariesFlag) const
Definition kis_layer.cc:590
KisLayerMasksCache masksCache
Definition kis_layer.cc:177
int thumbnailSeqNo() const override
Definition kis_layer.cc:949
virtual KisLayerProjectionPlaneSP internalProjectionPlane() const
Definition kis_layer.cc:821
virtual KisSelectionMaskSP selectionMask() const
Definition kis_layer.cc:504
QRect tightUserVisibleBounds() const
Definition kis_layer.cc:850
~KisLayer() override
Definition kis_layer.cc:219
const KoCompositeOp * compositeOp() const override
returns the layer's composite op for the colorspace of the layer's parent.
Definition kis_layer.cc:232
virtual QRect incomingChangeRect(const QRect &rect) const
Definition kis_layer.cc:909
bool alphaChannelDisabled() const
Definition kis_layer.cc:334
void buildProjectionUpToNode(KisPaintDeviceSP projection, KisNodeSP lastNode, const QRect &rect)
Definition kis_layer.cc:788
qint32 x() const override
Definition kis_layer.cc:976
KisPSDLayerStyleSP layerStyle
Definition kis_layer.cc:171
QRect partialChangeRect(KisNodeSP lastNode, const QRect &rect)
Definition kis_layer.cc:775
QRect extent() const override
QRect changeRect(const QRect &rect, PositionToFilthy pos=N_FILTHY) const override
Definition kis_layer.cc:865
Private(KisLayer *q)
Definition kis_layer.cc:162
QRect applyMasks(const KisPaintDeviceSP source, KisPaintDeviceSP destination, const QRect &requestedRect, KisNodeSP filthyNode, KisNodeSP lastNode, KisRenderPassFlags flags) const
Definition kis_layer.cc:663
const QList< KisCloneLayerWSP > registeredClones() const
Definition kis_layer.cc:484
friend class KisLayerProjectionPlane
Definition kis_layer.h:440
bool temporary() const
Definition kis_layer.cc:368
void notifyChildMaskChanged()
Definition kis_layer.cc:499
virtual KisLayerSP tryCreateInternallyMergedLayerFromMutipleLayers(QList< KisLayerSP > layers)
Definition kis_layer.cc:401
QRect masksNeedRect(const QList< KisEffectMaskSP > &masks, const QRect &changeRect, QStack< QRect > &applyRects, bool &rectVariesFlag) const
Definition kis_layer.cc:616
QRect layerExtentImpl(bool exactBounds) const
Definition kis_layer.cc:999
KisLayerStyleProjectionPlaneSP layerStyleProjectionPlane
Definition kis_layer.cc:172
QList< KisEffectMaskSP > searchEffectMasks(KisNodeSP lastNode) const
Definition kis_layer.cc:542
QRect userVisibleBoundsImpl(bool exactBounds) const
Definition kis_layer.cc:834
QImage createThumbnail(qint32 w, qint32 h, Qt::AspectRatioMode aspectRatioMode, KisThumbnailBoundsMode boundsMode) override
Definition kis_layer.cc:936
const KoColorSpace * colorSpace() const override
returns the image's colorSpace or null, if there is no image
Definition kis_layer.cc:225
void setX(qint32 x) override
Definition kis_layer.cc:986
KisFilterMaskSP colorOverlayMask() const
Definition kis_layer.cc:573
void setSectionModelProperties(const KisBaseNode::PropertyList &properties) override
Definition kis_layer.cc:297
virtual void setChannelFlags(const QBitArray &channelFlags)
Definition kis_layer.cc:342
void unregisterClone(KisCloneLayerWSP clone)
Definition kis_layer.cc:479
void updateClones(const QRect &rect, bool dontInvalidateFrames)
Definition kis_layer.cc:494
KisLayerSP parentLayer() const
virtual KisSelectionSP selection() const
Definition kis_layer.cc:509
KisPaintDeviceSP original() const override=0
virtual void copyOriginalToProjection(const KisPaintDeviceSP original, KisPaintDeviceSP projection, const QRect &rect) const
Definition kis_layer.cc:807
void setTemporary(bool t)
Definition kis_layer.cc:373
bool hasClones() const
Definition kis_layer.cc:489
KisBaseNode::PropertyList sectionModelProperties() const override
Definition kis_layer.cc:272
void setLayerStyle(KisPSDLayerStyleSP layerStyle)
Definition kis_layer.cc:254
KisSafeNodeProjectionStoreSP safeProjection
Definition kis_layer.cc:175
void setY(qint32 y) override
Definition kis_layer.cc:992
KisLayerProjectionPlaneSP projectionPlane
Definition kis_layer.cc:174
virtual bool needProjection() const
Definition kis_layer.cc:802
KisSelectionSP selection
Definition kis_mask.cc:44
void baseNodeInvalidateAllFramesCallback() override
Definition kis_node.cpp:337
KisNodeSP prevSibling() const
Definition kis_node.cpp:402
friend class KisLayer
Definition kis_node.h:383
void baseNodeChangedCallback() override
Definition kis_node.cpp:329
QList< KisNodeSP > childNodes(const QStringList &nodeTypes, const KoProperties &properties) const
Definition kis_node.cpp:439
void setImage(KisImageWSP newImage) override
Definition kis_node.cpp:254
KisProjectionLeafSP projectionLeaf
Definition kis_node.cpp:93
virtual QRect needRect(const QRect &rect, PositionToFilthy pos=N_FILTHY) const
Definition kis_node.cpp:218
virtual KisNodeSP clone() const =0
PositionToFilthy
Definition kis_node.h:58
@ N_ABOVE_FILTHY
Definition kis_node.h:59
@ N_FILTHY
Definition kis_node.h:61
@ N_FILTHY_PROJECTION
Definition kis_node.h:60
@ N_BELOW_FILTHY
Definition kis_node.h:62
KisNodeWSP parent
Definition kis_node.cpp:86
The KisPSDLayerStyle class implements loading, saving and applying the PSD layer effects.
static KoColorSpaceRegistry * instance()