File indexing completed on 2024-05-12 15:58:18

0001 /*
0002  *  SPDX-FileCopyrightText: 2005 C. Boemann <cbo@boemann.dk>
0003  *  SPDX-FileCopyrightText: 2007 Boudewijn Rempt <boud@valdyas.org>
0004  *  SPDX-FileCopyrightText: 2009 Dmitry Kazakov <dimula73@gmail.com>
0005  *
0006  *  SPDX-License-Identifier: GPL-2.0-or-later
0007  */
0008 
0009 #include "kis_group_layer.h"
0010 
0011 #include <KoIcon.h>
0012 #include <kis_icon.h>
0013 #include <KoCompositeOpRegistry.h>
0014 #include <KoColorSpace.h>
0015 #include <KoColor.h>
0016 
0017 
0018 #include "kis_node_visitor.h"
0019 #include "kis_processing_visitor.h"
0020 #include "kis_debug.h"
0021 #include "kis_image.h"
0022 #include "kis_paint_device.h"
0023 #include "kis_default_bounds.h"
0024 #include "kis_clone_layer.h"
0025 #include "kis_selection_mask.h"
0026 #include "kis_psd_layer_style.h"
0027 #include "kis_layer_properties_icons.h"
0028 
0029 
0030 struct Q_DECL_HIDDEN KisGroupLayer::Private
0031 {
0032 public:
0033     Private()
0034         : paintDevice(0)
0035         , x(0)
0036         , y(0)
0037         , passThroughMode(false)
0038     {
0039     }
0040 
0041     KisPaintDeviceSP paintDevice;
0042     qint32 x;
0043     qint32 y;
0044     bool passThroughMode;
0045 
0046     std::tuple<KisPaintDeviceSP, bool> originalImpl() const;
0047 };
0048 
0049 KisGroupLayer::KisGroupLayer(KisImageWSP image, const QString &name, quint8 opacity) :
0050     KisLayer(image, name, opacity),
0051     m_d(new Private())
0052 {
0053     resetCache();
0054 }
0055 
0056 KisGroupLayer::KisGroupLayer(const KisGroupLayer &rhs) :
0057     KisLayer(rhs),
0058     m_d(new Private())
0059 {
0060     m_d->paintDevice = new KisPaintDevice(*rhs.m_d->paintDevice.data());
0061     m_d->x = rhs.m_d->x;
0062     m_d->y = rhs.m_d->y;
0063     m_d->paintDevice->setDefaultPixel(const_cast<KisGroupLayer*>(&rhs)->m_d->paintDevice->defaultPixel());
0064     m_d->paintDevice->setProjectionDevice(true);
0065     m_d->passThroughMode = rhs.passThroughMode();
0066 }
0067 
0068 KisGroupLayer::~KisGroupLayer()
0069 {
0070     delete m_d;
0071 }
0072 
0073 bool KisGroupLayer::checkCloneLayer(KisCloneLayerSP clone) const
0074 {
0075     KisNodeSP source = clone->copyFrom();
0076     if (source) {
0077         if(!allowAsChild(source)) return false;
0078 
0079         if (source->inherits("KisGroupLayer")) {
0080             KisNodeSP newParent = const_cast<KisGroupLayer*>(this);
0081             while (newParent) {
0082                 if (newParent == source) {
0083                     return false;
0084                 }
0085                 newParent = newParent->parent();
0086             }
0087         }
0088     }
0089 
0090     return true;
0091 }
0092 
0093 bool KisGroupLayer::checkNodeRecursively(KisNodeSP node) const
0094 {
0095     KisCloneLayerSP cloneLayer = dynamic_cast<KisCloneLayer*>(node.data());
0096     if(cloneLayer) {
0097         return checkCloneLayer(cloneLayer);
0098     }
0099     else if (node->inherits("KisGroupLayer")) {
0100         KisNodeSP child = node->firstChild();
0101         while (child) {
0102             if (!checkNodeRecursively(child)) {
0103                 return false;
0104             }
0105             child = child->nextSibling();
0106         }
0107     }
0108 
0109     return true;
0110 }
0111 
0112 bool KisGroupLayer::allowAsChild(KisNodeSP node) const
0113 {
0114     if (!checkNodeRecursively(node)) return false;
0115 
0116     if (!parent()) {
0117         // We are the root layer, so we need to check
0118         // whether the node that's going to be added is
0119         // a selection mask; that is only allowed if
0120         // there isn't a global selection. See
0121         // BUG:294905
0122 
0123         if (node->inherits("KisSelectionMask")) {
0124             return !qobject_cast<KisSelectionMask*>(node.data())->active() || !selectionMask();
0125         }
0126 
0127         KisImageSP image = this->image();
0128 
0129         if (!image || !image->allowMasksOnRootNode()) {
0130             if (node->inherits("KisMask")) {
0131                 return false;
0132             }
0133         }
0134     }
0135 
0136     return checkNodeRecursively(node);
0137 
0138 }
0139 
0140 const KoColorSpace * KisGroupLayer::colorSpace() const
0141 {
0142     return m_d->paintDevice->colorSpace();
0143 }
0144 
0145 QIcon KisGroupLayer::icon() const
0146 {
0147     return KisIconUtils::loadIcon("groupLayer");
0148 }
0149 
0150 void KisGroupLayer::setImage(KisImageWSP image)
0151 {
0152     m_d->paintDevice->setDefaultBounds(new KisDefaultBounds(image));
0153     KisLayer::setImage(image);
0154 }
0155 
0156 KisLayerSP KisGroupLayer::createMergedLayerTemplate(KisLayerSP prevLayer)
0157 {
0158     KisGroupLayer *prevGroup = dynamic_cast<KisGroupLayer*>(prevLayer.data());
0159 
0160     if (prevGroup && canMergeAndKeepBlendOptions(prevLayer)) {
0161         KisSharedPtr<KisGroupLayer> merged(new KisGroupLayer(*prevGroup));
0162 
0163         KisNodeSP child, cloned;
0164 
0165         for (child = firstChild(); child; child = child->nextSibling()) {
0166             cloned = child->clone();
0167             image()->addNode(cloned, merged);
0168         }
0169 
0170         if (!merged->passThroughMode()) {
0171             image()->refreshGraphAsync(merged);
0172         }
0173 
0174         return merged;
0175     } else
0176         return KisLayer::createMergedLayerTemplate(prevLayer);
0177 }
0178 
0179 void KisGroupLayer::fillMergedLayerTemplate(KisLayerSP dstLayer, KisLayerSP prevLayer)
0180 {
0181     if (!dynamic_cast<KisGroupLayer*>(dstLayer.data())) {
0182         KisLayer::fillMergedLayerTemplate(dstLayer, prevLayer);
0183     }
0184 }
0185 
0186 void KisGroupLayer::resetCache(const KoColorSpace *colorSpace)
0187 {
0188     if (!colorSpace)
0189         colorSpace = image()->colorSpace();
0190 
0191     Q_ASSERT(colorSpace);
0192 
0193     if (!m_d->paintDevice) {
0194 
0195         KisPaintDeviceSP dev = new KisPaintDevice(this, colorSpace, new KisDefaultBounds(image()));
0196         dev->setX(this->x());
0197         dev->setY(this->y());
0198         m_d->paintDevice = dev;
0199         m_d->paintDevice->setProjectionDevice(true);
0200     }
0201     else if(*m_d->paintDevice->colorSpace() != *colorSpace) {
0202 
0203         m_d->paintDevice->clear();
0204         m_d->paintDevice->convertTo(colorSpace);
0205 
0206     } else {
0207 
0208         m_d->paintDevice->clear();
0209     }
0210 }
0211 
0212 KisLayer* KisGroupLayer::onlyMeaningfulChild() const
0213 {
0214     KisNode *child = firstChild().data();
0215     KisLayer *onlyLayer = 0;
0216 
0217     while (child) {
0218         KisLayer *layer = qobject_cast<KisLayer*>(child);
0219         if (layer && !layer->isFakeNode()) {
0220             if (onlyLayer) return 0;
0221             onlyLayer = layer;
0222         }
0223         child = child->nextSibling().data();
0224     }
0225 
0226     return onlyLayer;
0227 }
0228 
0229 KisPaintDeviceSP KisGroupLayer::tryObligeChild() const
0230 {
0231     KisLayer *child = onlyMeaningfulChild();
0232 
0233     if (child) {
0234         KisPaintDeviceSP projection = child->projection();
0235         if (child->channelFlags().isEmpty() &&
0236                 projection &&
0237                 child->visible() &&
0238                 (child->compositeOpId() == COMPOSITE_OVER ||
0239                  child->compositeOpId() == COMPOSITE_ALPHA_DARKEN ||
0240                  child->compositeOpId() == COMPOSITE_COPY) &&
0241                 child->opacity() == OPACITY_OPAQUE_U8 &&
0242                 *projection->colorSpace() == *colorSpace() &&
0243                 !child->layerStyle()) {
0244 
0245             quint8 defaultOpacity =
0246                     m_d->paintDevice->defaultPixel().opacityU8();
0247 
0248             if(defaultOpacity == OPACITY_TRANSPARENT_U8) {
0249                 return projection;
0250             }
0251         }
0252     }
0253 
0254     return 0;
0255 }
0256 
0257 std::tuple<KisPaintDeviceSP, bool> KisGroupLayer::originalImpl() const
0258 {
0259     /**
0260      * We are too lazy! Let's our children work for us.
0261      * Try to use children's paintDevice if it's the only
0262      * one in stack and meets some conditions
0263      */
0264     KisPaintDeviceSP realOriginal = tryObligeChild();
0265     bool ownsOriginal = false;
0266 
0267     if (!realOriginal) {
0268         if (!childCount() && !m_d->paintDevice->extent().isEmpty()) {
0269             m_d->paintDevice->clear();
0270         }
0271         realOriginal = m_d->paintDevice;
0272         ownsOriginal = true;
0273     }
0274 
0275     return std::make_tuple(realOriginal, ownsOriginal);
0276 }
0277 
0278 KisPaintDeviceSP KisGroupLayer::original() const
0279 {
0280     return std::get<0>(originalImpl());
0281 }
0282 
0283 KisPaintDeviceSP KisGroupLayer::lazyDestinationForSubtreeComposition() const
0284 {
0285     KisPaintDeviceSP originalDev;
0286     bool ownsOriginal = false;
0287     std::tie(originalDev, ownsOriginal) = originalImpl();
0288 
0289     return ownsOriginal ? originalDev : nullptr;
0290 }
0291 
0292 QRect KisGroupLayer::amortizedProjectionRectForCleanupInChangePass() const
0293 {
0294     return hasEffectMasks() ? projection()->exactBoundsAmortized() : m_d->paintDevice->exactBoundsAmortized();
0295 }
0296 
0297 KisPaintDeviceSP KisGroupLayer::paintDevice() const
0298 {
0299     return 0;
0300 }
0301 
0302 bool KisGroupLayer::projectionIsValid() const
0303 {
0304     return !tryObligeChild();
0305 }
0306 
0307 void KisGroupLayer::setDefaultProjectionColor(KoColor color)
0308 {
0309     m_d->paintDevice->setDefaultPixel(color);
0310 }
0311 
0312 KoColor KisGroupLayer::defaultProjectionColor() const
0313 {
0314     KoColor color(m_d->paintDevice->defaultPixel(), m_d->paintDevice->colorSpace());
0315     return color;
0316 }
0317 
0318 bool KisGroupLayer::passThroughMode() const
0319 {
0320     return m_d->passThroughMode;
0321 }
0322 
0323 void KisGroupLayer::setPassThroughMode(bool value)
0324 {
0325     if (m_d->passThroughMode == value) return;
0326 
0327     m_d->passThroughMode = value;
0328     if (m_d->passThroughMode) {
0329         resetCache(colorSpace());
0330     }
0331     baseNodeChangedCallback();
0332     baseNodeInvalidateAllFramesCallback();
0333     notifyChildMaskChanged();
0334 }
0335 
0336 KisBaseNode::PropertyList KisGroupLayer::sectionModelProperties() const
0337 {
0338     KisBaseNode::PropertyList l = KisLayer::sectionModelProperties();
0339 
0340     l << KisLayerPropertiesIcons::getProperty(KisLayerPropertiesIcons::passThrough, passThroughMode());
0341 
0342     return l;
0343 }
0344 
0345 void KisGroupLayer::setSectionModelProperties(const KisBaseNode::PropertyList &properties)
0346 {
0347     Q_FOREACH (const KisBaseNode::Property &property, properties) {
0348         if (property.name == i18n("Pass Through")) {
0349             setPassThroughMode(property.state.toBool());
0350         }
0351     }
0352 
0353     KisLayer::setSectionModelProperties(properties);
0354 }
0355 
0356 bool KisGroupLayer::accept(KisNodeVisitor &v)
0357 {
0358     return v.visit(this);
0359 }
0360 
0361 void KisGroupLayer::accept(KisProcessingVisitor &visitor, KisUndoAdapter *undoAdapter)
0362 {
0363     return visitor.visit(this, undoAdapter);
0364 }
0365 
0366 qint32 KisGroupLayer::x() const
0367 {
0368     return m_d->paintDevice ? m_d->paintDevice->x() : m_d->x;
0369 }
0370 
0371 qint32 KisGroupLayer::y() const
0372 {
0373     return m_d->paintDevice ? m_d->paintDevice->y() : m_d->y;
0374 }
0375 
0376 void KisGroupLayer::setX(qint32 x)
0377 {
0378     m_d->x = x;
0379     if(m_d->paintDevice) {
0380         m_d->paintDevice->setX(x);
0381     }
0382 }
0383 
0384 void KisGroupLayer::setY(qint32 y)
0385 {
0386     m_d->y = y;
0387     if(m_d->paintDevice) {
0388         m_d->paintDevice->setY(y);
0389     }
0390 }
0391 
0392 struct ExtentPolicy
0393 {
0394     inline QRect operator() (const KisNode *node) {
0395         return node->extent();
0396     }
0397 };
0398 
0399 struct ExactBoundsPolicy
0400 {
0401     inline QRect operator() (const KisNode *node) {
0402         return node->exactBounds();
0403     }
0404 };
0405 
0406 template <class MetricPolicy>
0407 QRect collectRects(const KisNode *node, MetricPolicy policy)
0408 {
0409     QRect accumulator;
0410 
0411     const KisNode *child = node->firstChild();
0412     while (child) {
0413         if (!qobject_cast<const KisMask*>(child)) {
0414             accumulator |= policy(child);
0415         }
0416         child = child->nextSibling();
0417     }
0418 
0419     return accumulator;
0420 }
0421 
0422 QRect KisGroupLayer::extent() const
0423 {
0424     return m_d->passThroughMode ?
0425         collectRects(this, ExtentPolicy()) :
0426         KisLayer::extent();
0427 }
0428 
0429 QRect KisGroupLayer::exactBounds() const
0430 {
0431     return m_d->passThroughMode ?
0432         collectRects(this, ExactBoundsPolicy()) :
0433         KisLayer::exactBounds();
0434 }