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 const bool keepBlendingOptions = canMergeAndKeepBlendOptions(prevLayer);
404
405 KisLayerSP newLayer = new KisPaintLayer(image(), prevLayer->name(), OPACITY_OPAQUE_U8);
406
407 if (keepBlendingOptions) {
408 newLayer->setCompositeOpId(compositeOpId());
409 newLayer->setOpacity(opacity());
410 newLayer->setChannelFlags(channelFlags());
411 }
412
413 return newLayer;
414}
415
416void KisLayer::fillMergedLayerTemplate(KisLayerSP dstLayer, KisLayerSP prevLayer, bool skipPaintingThisLayer)
417{
418 const bool keepBlendingOptions = canMergeAndKeepBlendOptions(prevLayer);
419
420 QRect layerProjectionExtent = this->projection()->extent();
421 QRect prevLayerProjectionExtent = prevLayer->projection()->extent();
422 bool alphaDisabled = this->alphaChannelDisabled();
423 bool prevAlphaDisabled = prevLayer->alphaChannelDisabled();
424
425 KisPaintDeviceSP mergedDevice = dstLayer->paintDevice();
426
427 if (!keepBlendingOptions) {
428 KisPainter gc(mergedDevice);
429
430 KisImageSP imageSP = image().toStrongRef();
431 if (!imageSP) {
432 return;
433 }
434
435 //Copy the pixels of previous layer with their actual alpha value
436 prevLayer->disableAlphaChannel(false);
437
438 prevLayer->projectionPlane()->apply(&gc, prevLayerProjectionExtent | imageSP->bounds());
439
440 //Restore the previous prevLayer disableAlpha status for correct undo/redo
441 prevLayer->disableAlphaChannel(prevAlphaDisabled);
442
443 if (!skipPaintingThisLayer) {
444 //Paint the pixels of the current layer, using their actual alpha value
445 if (alphaDisabled == prevAlphaDisabled) {
446 this->disableAlphaChannel(false);
447 }
448
449 this->projectionPlane()->apply(&gc, layerProjectionExtent | imageSP->bounds());
450
451 //Restore the layer disableAlpha status for correct undo/redo
452 this->disableAlphaChannel(alphaDisabled);
453 }
454 }
455 else {
456 //Copy prevLayer
457 KisPaintDeviceSP srcDev = prevLayer->projection();
458 mergedDevice->makeCloneFrom(srcDev, srcDev->extent());
459
460 if (!skipPaintingThisLayer) {
461 //Paint layer on the copy
462 KisPainter gc(mergedDevice);
463 gc.bitBlt(layerProjectionExtent.topLeft(), this->projection(), layerProjectionExtent);
464 }
465 }
466}
467
469{
470 m_d->clonesList.addClone(clone);
471}
472
474{
475 m_d->clonesList.removeClone(clone);
476}
477
479{
480 return m_d->clonesList.registeredClones();
481}
482
484{
485 return m_d->clonesList.hasClones();
486}
487
488void KisLayer::updateClones(const QRect &rect, bool dontInvalidateFrames)
489{
490 m_d->clonesList.setDirty(rect, dontInvalidateFrames);
491}
492
494{
495 m_d->masksCache.setDirty();
496}
497
499{
500 return m_d->masksCache.selectionMask();
501}
502
504{
506
507 if (mask) {
508 return mask->selection();
509 }
510
511 KisImageSP image = this->image();
512 if (image) {
513 return image->globalSelection();
514 }
515 return KisSelectionSP();
516}
517
520
522{
523 return m_d->masksCache.effectMasks();
524}
525
527{
528 if (lastNode.isNull()) {
529 return effectMasks();
530 } else {
531 // happens rarely.
532 return searchEffectMasks(lastNode);
533 }
534}
535
537{
539
541
542 KisProjectionLeafSP child = projectionLeaf()->firstChild();
543 while (child) {
544 if (child->node() == lastNode) break;
545
547 KIS_SAFE_ASSERT_RECOVER_NOOP(child->node());
548
549 if (child->visible()) {
550 KisEffectMaskSP mask = dynamic_cast<KisEffectMask*>(const_cast<KisNode*>(child->node().data()));
551 if (mask) {
552 masks.append(mask);
553 }
554 }
555
556 child = child->nextSibling();
557 }
558
559 return masks;
560}
561
563{
564 return !m_d->masksCache.effectMasks().isEmpty();
565}
566
568{
569 if (hasEffectMasks()) {
570 // Iterate the masks in reverse, the last element is on top of the stack.
571 auto allMasks = effectMasks();
572 for (auto iter = allMasks.rbegin(); iter != allMasks.rend(); ++iter) {
573 if ((*iter)->inherits("KisFilterMask")) {
574 KisFilterMaskSP filterMask = qobject_cast<KisFilterMask*>((*iter).data());
575 if (filterMask->filter()->name() == "fastcoloroverlay") {
576 return filterMask;
577 }
578 }
579 }
580 }
581 return nullptr;
582}
583
585 const QRect &requestedRect,
586 bool &rectVariesFlag) const
587{
588 rectVariesFlag = false;
589
590 QRect prevChangeRect = requestedRect;
591
596 QRect changeRect = requestedRect;
597
598 Q_FOREACH (const KisEffectMaskSP& mask, masks) {
599 changeRect = mask->changeRect(prevChangeRect);
600
601 if (changeRect != prevChangeRect)
602 rectVariesFlag = true;
603
604 prevChangeRect = changeRect;
605 }
606
607 return changeRect;
608}
609
611 const QRect &changeRect,
612 QStack<QRect> &applyRects,
613 bool &rectVariesFlag) const
614{
615 rectVariesFlag = false;
616
617 QRect prevNeedRect = changeRect;
618 QRect needRect;
619
620 for (qint32 i = masks.size() - 1; i >= 0; i--) {
621 applyRects.push(prevNeedRect);
622
623 needRect = masks[i]->needRect(prevNeedRect);
624
625 if (prevNeedRect != needRect)
626 rectVariesFlag = true;
627
628 prevNeedRect = needRect;
629 }
630
631 return needRect;
632}
633
635 KisNodeSP filthy,
636 KisNodeSP parent)
637{
638 if (parent == filthy || parent != filthy->parent()) {
640 }
641
642 if (nodeInQuestion == filthy) {
643 return KisNode::N_FILTHY;
644 }
645
646 KisNodeSP node = nodeInQuestion->prevSibling();
647 while (node) {
648 if (node == filthy) {
650 }
651 node = node->prevSibling();
652 }
653
655}
656
658 KisPaintDeviceSP destination,
659 const QRect &requestedRect,
660 KisNodeSP filthyNode,
661 KisNodeSP lastNode,
662 KisRenderPassFlags flags) const
663{
664 Q_ASSERT(source);
665 Q_ASSERT(destination);
666
667 QList<KisEffectMaskSP> masks = effectMasks(lastNode);
668 QRect changeRect;
669 QRect needRect;
670
671 if (masks.isEmpty()) {
672 changeRect = requestedRect;
673 if (source != destination) {
674 copyOriginalToProjection(source, destination, requestedRect);
675 }
676 } else {
677 QStack<QRect> applyRects;
678 bool changeRectVaries;
679 bool needRectVaries;
680
685 changeRectVaries = false;
686 changeRect = requestedRect;
687 //changeRect = masksChangeRect(masks, requestedRect,
688 // changeRectVaries);
689
691 applyRects, needRectVaries);
692
693 if (!changeRectVaries && !needRectVaries) {
700 Q_ASSERT(needRect == requestedRect);
701
702 if (source != destination) {
704 }
705
706 Q_FOREACH (const KisEffectMaskSP& mask, masks) {
707 const QRect maskApplyRect = applyRects.pop();
708 const QRect maskNeedRect =
709 applyRects.isEmpty() ? needRect : applyRects.top();
710
711 PositionToFilthy maskPosition = calculatePositionToFilthy(mask, filthyNode, const_cast<KisLayer*>(this));
712 mask->apply(destination, maskApplyRect, maskNeedRect, maskPosition, flags);
713 }
714 Q_ASSERT(applyRects.isEmpty());
715 } else {
722 KisPaintDeviceSP tempDevice = new KisPaintDevice(colorSpace());
723 tempDevice->prepareClone(source);
725
726 QRect maskApplyRect = applyRects.pop();
727 QRect maskNeedRect = needRect;
728
729 Q_FOREACH (const KisEffectMaskSP& mask, masks) {
730 PositionToFilthy maskPosition = calculatePositionToFilthy(mask, filthyNode, const_cast<KisLayer*>(this));
731 mask->apply(tempDevice, maskApplyRect, maskNeedRect, maskPosition, flags);
732
733 if (!applyRects.isEmpty()) {
734 maskNeedRect = maskApplyRect;
735 maskApplyRect = applyRects.pop();
736 }
737 }
738 Q_ASSERT(applyRects.isEmpty());
739
740 KisPainter::copyAreaOptimized(changeRect.topLeft(), tempDevice, destination, changeRect);
741 }
742 }
743
744 return changeRect;
745}
746
747QRect KisLayer::updateProjection(const QRect& rect, KisNodeSP filthyNode, KisRenderPassFlags flags)
748{
749 QRect updatedRect = rect;
750 KisPaintDeviceSP originalDevice = original();
751 if (!rect.isValid() ||
752 (!visible() && !isIsolatedRoot() && !hasClones()) ||
753 !originalDevice) return QRect();
754
755 if (!needProjection() && !hasEffectMasks()) {
756 m_d->safeProjection->releaseDevice();
757 } else {
758
759 if (!updatedRect.isEmpty()) {
760 KisPaintDeviceSP projection = m_d->safeProjection->getDeviceLazy(originalDevice);
761 updatedRect = applyMasks(originalDevice, projection,
762 updatedRect, filthyNode, 0, flags);
763 }
764 }
765
766 return updatedRect;
767}
768
769QRect KisLayer::partialChangeRect(KisNodeSP lastNode, const QRect& rect)
770{
771 bool changeRectVaries = false;
774 changeRectVaries);
775
776 return changeRect;
777}
778
782void KisLayer::buildProjectionUpToNode(KisPaintDeviceSP projection, KisNodeSP lastNode, const QRect& rect)
783{
784 QRect changeRect = partialChangeRect(lastNode, rect);
785
786 KisPaintDeviceSP originalDevice = original();
787
789
790 if (!changeRect.isEmpty()) {
791 applyMasks(originalDevice, projection,
793 }
794}
795
797{
798 return false;
799}
800
802 KisPaintDeviceSP projection,
803 const QRect& rect) const
804{
806}
807
809{
810 return m_d->layerStyleProjectionPlane ?
811 KisAbstractProjectionPlaneSP(m_d->layerStyleProjectionPlane) :
813}
814
816{
817 return m_d->projectionPlane;
818}
819
821{
822 KisPaintDeviceSP originalDevice = original();
823
824 return needProjection() || hasEffectMasks() ?
825 m_d->safeProjection->getDeviceLazy(originalDevice) : originalDevice;
826}
827
828QRect KisLayer::userVisibleBoundsImpl(bool exactBounds) const
829{
830 QRect changeRect = exactBounds ? this->exactBounds() : this->extent();
831
835
836 bool changeRectVaries;
838 changeRect = masksChangeRect(effectMasks(), changeRect, changeRectVaries);
839
840 return changeRect;
841}
842
843
845{
846 return userVisibleBoundsImpl(true);
847}
848
850{
851 return userVisibleBoundsImpl(false);
852}
853
858
859QRect KisLayer::changeRect(const QRect &rect, PositionToFilthy pos) const
860{
861 QRect changeRect = rect;
863
864 if(pos == KisNode::N_FILTHY) {
865 QRect projectionToBeUpdated = amortizedProjectionRectForCleanupInChangePass() & changeRect;
866
867 bool changeRectVaries;
869 changeRect = masksChangeRect(effectMasks(), changeRect, changeRectVaries);
870
878 if (!projectionToBeUpdated.isEmpty() &&
879 !changeRect.contains(projectionToBeUpdated)) {
880
881 changeRect |= projectionToBeUpdated;
882 }
883 }
884
885 // TODO: string comparison: optimize!
886 if (pos != KisNode::N_FILTHY &&
889
890 changeRect |= rect;
891 }
892
893 return changeRect;
894}
895
897{
898 if (dynamic_cast<KisMask*>(changedChildNode.data())) {
900 }
901}
902
903QRect KisLayer::incomingChangeRect(const QRect &rect) const
904{
905 return rect;
906}
907
908QRect KisLayer::outgoingChangeRect(const QRect &rect) const
909{
910 return rect;
911}
912
913QRect KisLayer::needRectForOriginal(const QRect &rect) const
914{
915 QRect needRect = rect;
916
917 const QList<KisEffectMaskSP> masks = effectMasks();
918
919 if (!masks.isEmpty()) {
920 QStack<QRect> applyRects;
921 bool needRectVaries;
922
923 needRect = masksNeedRect(masks, rect,
924 applyRects, needRectVaries);
925 }
926
927 return needRect;
928}
929
930QImage KisLayer::createThumbnail(qint32 w, qint32 h, Qt::AspectRatioMode aspectRatioMode)
931{
932 if (w == 0 || h == 0) {
933 return QImage();
934 }
935
936 KisPaintDeviceSP originalDevice = original();
937
938 return originalDevice ?
939 originalDevice->createThumbnail(w, h, aspectRatioMode, 1,
942}
943
945{
946 KisPaintDeviceSP originalDevice = original();
947 return originalDevice ? originalDevice->sequenceNumber() : -1;
948}
949
950QImage KisLayer::createThumbnailForFrame(qint32 w, qint32 h, int time, Qt::AspectRatioMode aspectRatioMode)
951{
952 if (w == 0 || h == 0) {
953 return QImage();
954 }
955
956 KisPaintDeviceSP originalDevice = original();
957 if (originalDevice ) {
958 KisRasterKeyframeChannel *channel = originalDevice->keyframeChannel();
959
960 if (channel) {
961 KisPaintDeviceSP targetDevice = new KisPaintDevice(colorSpace());
962 KisRasterKeyframeSP keyframe = channel->activeKeyframeAt<KisRasterKeyframe>(time);
963 keyframe->writeFrameToDevice(targetDevice);
964 return targetDevice->createThumbnail(w, h, aspectRatioMode, 1,
967 }
968 }
969
970 return createThumbnail(w, h);
971}
972
973qint32 KisLayer::x() const
974{
975 KisPaintDeviceSP originalDevice = original();
976 return originalDevice ? originalDevice->x() : 0;
977}
978qint32 KisLayer::y() const
979{
980 KisPaintDeviceSP originalDevice = original();
981 return originalDevice ? originalDevice->y() : 0;
982}
983void KisLayer::setX(qint32 x)
984{
985 KisPaintDeviceSP originalDevice = original();
986 if (originalDevice)
987 originalDevice->setX(x);
988}
989void KisLayer::setY(qint32 y)
990{
991 KisPaintDeviceSP originalDevice = original();
992 if (originalDevice)
993 originalDevice->setY(y);
994}
995
996QRect KisLayer::layerExtentImpl(bool needExactBounds) const
997{
998 QRect additionalMaskExtent = QRect();
1000
1001 Q_FOREACH(KisEffectMaskSP mask, effectMasks) {
1002 additionalMaskExtent |= mask->nonDependentExtent();
1003 }
1004
1005 KisPaintDeviceSP originalDevice = original();
1006 QRect layerExtent;
1007
1008 if (originalDevice) {
1009 layerExtent = needExactBounds ?
1010 originalDevice->exactBounds() :
1011 originalDevice->extent();
1012 }
1013
1014 QRect additionalCompositeOpExtent;
1015 if (compositeOpId() == COMPOSITE_COPY ||
1018
1019 additionalCompositeOpExtent = originalDevice->defaultBounds()->bounds();
1020 }
1021
1022 return layerExtent | additionalMaskExtent | additionalCompositeOpExtent;
1023}
1024
1025QRect KisLayer::extent() const
1026{
1027 return layerExtentImpl(false);
1028}
1029
1031{
1032 return layerExtentImpl(true);
1033}
1034
1036{
1037 return qobject_cast<KisLayer*>(parent().data());
1038}
1039
1041{
1042 return m_d->metaDataStore;
1043}
1044
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, QRect rect, 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:634
QSharedPointer< KisLayerStyleProjectionPlane > KisLayerStyleProjectionPlaneSP
QSharedPointer< T > toQShared(T *ptr)
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)
QImage createThumbnail(qint32 w, qint32 h, Qt::AspectRatioMode aspectRatioMode=Qt::IgnoreAspectRatio) override
Definition kis_layer.cc:930
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
void disableAlphaChannel(bool disable)
Definition kis_layer.cc:319
virtual void fillMergedLayerTemplate(KisLayerSP dstLayer, KisLayerSP prevLayer, bool skipPaintingThisLayer=false)
Definition kis_layer.cc:416
virtual QRect outgoingChangeRect(const QRect &rect) const
Definition kis_layer.cc:908
virtual QRect amortizedProjectionRectForCleanupInChangePass() const
Definition kis_layer.cc:854
QRect looseUserVisibleBounds() const
Definition kis_layer.cc:849
QImage createThumbnailForFrame(qint32 w, qint32 h, int time, Qt::AspectRatioMode aspectRatioMode=Qt::IgnoreAspectRatio) override
Definition kis_layer.cc:950
virtual KisLayerSP createMergedLayerTemplate(KisLayerSP prevLayer)
Definition kis_layer.cc:401
Private *const m_d
Definition kis_layer.h:438
void childNodeChanged(KisNodeSP changedChildNode) override
Definition kis_layer.cc:896
QRect needRectForOriginal(const QRect &rect) const
Definition kis_layer.cc:913
QList< KisEffectMaskSP > effectMasks() const
Definition kis_layer.cc:521
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:562
QRect exactBounds() const override
QRect updateProjection(const QRect &rect, KisNodeSP filthyNode, KisRenderPassFlags flags)
Definition kis_layer.cc:747
void registerClone(KisCloneLayerWSP clone)
Definition kis_layer.cc:468
QBitArray channelFlags
Definition kis_layer.cc:167
QRect masksChangeRect(const QList< KisEffectMaskSP > &masks, const QRect &requestedRect, bool &rectVariesFlag) const
Definition kis_layer.cc:584
KisLayerMasksCache masksCache
Definition kis_layer.cc:177
int thumbnailSeqNo() const override
Definition kis_layer.cc:944
virtual KisLayerProjectionPlaneSP internalProjectionPlane() const
Definition kis_layer.cc:815
virtual KisSelectionMaskSP selectionMask() const
Definition kis_layer.cc:498
QRect tightUserVisibleBounds() const
Definition kis_layer.cc:844
~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:903
bool alphaChannelDisabled() const
Definition kis_layer.cc:334
void buildProjectionUpToNode(KisPaintDeviceSP projection, KisNodeSP lastNode, const QRect &rect)
Definition kis_layer.cc:782
qint32 x() const override
Definition kis_layer.cc:973
KisPSDLayerStyleSP layerStyle
Definition kis_layer.cc:171
QRect partialChangeRect(KisNodeSP lastNode, const QRect &rect)
Definition kis_layer.cc:769
QRect extent() const override
QRect changeRect(const QRect &rect, PositionToFilthy pos=N_FILTHY) const override
Definition kis_layer.cc:859
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:657
const QList< KisCloneLayerWSP > registeredClones() const
Definition kis_layer.cc:478
friend class KisLayerProjectionPlane
Definition kis_layer.h:428
bool temporary() const
Definition kis_layer.cc:368
void notifyChildMaskChanged()
Definition kis_layer.cc:493
QRect masksNeedRect(const QList< KisEffectMaskSP > &masks, const QRect &changeRect, QStack< QRect > &applyRects, bool &rectVariesFlag) const
Definition kis_layer.cc:610
QRect layerExtentImpl(bool exactBounds) const
Definition kis_layer.cc:996
KisLayerStyleProjectionPlaneSP layerStyleProjectionPlane
Definition kis_layer.cc:172
QList< KisEffectMaskSP > searchEffectMasks(KisNodeSP lastNode) const
Definition kis_layer.cc:536
QRect userVisibleBoundsImpl(bool exactBounds) const
Definition kis_layer.cc:828
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:983
KisFilterMaskSP colorOverlayMask() const
Definition kis_layer.cc:567
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:473
void updateClones(const QRect &rect, bool dontInvalidateFrames)
Definition kis_layer.cc:488
KisLayerSP parentLayer() const
virtual KisSelectionSP selection() const
Definition kis_layer.cc:503
KisPaintDeviceSP original() const override=0
virtual void copyOriginalToProjection(const KisPaintDeviceSP original, KisPaintDeviceSP projection, const QRect &rect) const
Definition kis_layer.cc:801
void setTemporary(bool t)
Definition kis_layer.cc:373
bool hasClones() const
Definition kis_layer.cc:483
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:989
KisLayerProjectionPlaneSP projectionPlane
Definition kis_layer.cc:174
virtual bool needProjection() const
Definition kis_layer.cc:796
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()