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

0001 /*
0002  *  SPDX-FileCopyrightText: 2002 Patrick Julien <freak@codepimps.org>
0003  *  SPDX-FileCopyrightText: 2005 C. Boemann <cbo@boemann.dk>
0004  *
0005  *  SPDX-License-Identifier: GPL-2.0-or-later
0006  */
0007 
0008 #include "kis_adjustment_layer.h"
0009 
0010 #include <klocalizedstring.h>
0011 #include "kis_debug.h"
0012 
0013 #include <KoIcon.h>
0014 #include <kis_icon.h>
0015 #include <KoCompositeOpRegistry.h>
0016 
0017 #include "kis_image.h"
0018 #include "kis_selection.h"
0019 #include "filter/kis_filter_configuration.h"
0020 #include "filter/kis_filter_registry.h"
0021 #include "filter/kis_filter.h"
0022 #include "kis_node_visitor.h"
0023 #include "kis_processing_visitor.h"
0024 
0025 
0026 KisAdjustmentLayer::KisAdjustmentLayer(KisImageWSP image,
0027                                        const QString &name,
0028                                        KisFilterConfigurationSP kfc,
0029                                        KisSelectionSP selection)
0030     : KisSelectionBasedLayer(image.data(), name, selection, kfc)
0031 {
0032     // by default Adjustment Layers have a copy composition,
0033     // which is more natural for users
0034     // https://bugs.kde.org/show_bug.cgi?id=324505
0035     // https://bugs.kde.org/show_bug.cgi?id=294122
0036     // demand the opposite from each other...
0037     //
0038     // also see a comment in KisLayerUtils::mergeMultipleLayersImpl()
0039 
0040     setCompositeOpId(COMPOSITE_COPY);
0041     setUseSelectionInProjection(false);
0042 }
0043 
0044 KisAdjustmentLayer::KisAdjustmentLayer(const KisAdjustmentLayer& rhs)
0045         : KisSelectionBasedLayer(rhs)
0046 {
0047 }
0048 
0049 
0050 KisAdjustmentLayer::~KisAdjustmentLayer()
0051 {
0052 }
0053 
0054 void KisAdjustmentLayer::setFilter(KisFilterConfigurationSP filterConfig, bool checkCompareConfig)
0055 {
0056     filterConfig->setChannelFlags(channelFlags());
0057     KisSelectionBasedLayer::setFilter(filterConfig, checkCompareConfig);
0058 }
0059 
0060 QRect KisAdjustmentLayer::incomingChangeRect(const QRect &rect) const
0061 {
0062     KisFilterConfigurationSP filterConfig = filter();
0063 
0064     QRect filteredRect = rect;
0065 
0066     if (filterConfig) {
0067         KisFilterSP filter = KisFilterRegistry::instance()->value(filterConfig->name());
0068         filteredRect = filter->changedRect(rect, filterConfig.data(), projection()->defaultBounds()->currentLevelOfDetail());
0069     }
0070 
0071     /**
0072      * After the change in the blending using
0073      * setUseSelectionInProjection(false) we should *not* crop the
0074      * change rect of the layer, because we pass contents through.
0075      *
0076      * //filteredRect = cropChangeRectBySelection(filteredRect);
0077      */
0078 
0079     return filteredRect;
0080 }
0081 
0082 QRect KisAdjustmentLayer::needRect(const QRect& rect, PositionToFilthy pos) const
0083 {
0084     Q_UNUSED(pos);
0085 
0086     KisFilterConfigurationSP filterConfig = filter();
0087     if (!filterConfig) return rect;
0088     KisFilterSP filter = KisFilterRegistry::instance()->value(filterConfig->name());
0089 
0090     /**
0091      * If we need some additional pixels even outside of a selection
0092      * for accurate layer filtering, we'll get them!
0093      * And no KisSelectionBasedLayer::needRect will prevent us
0094      * from doing this! ;)
0095      * That's why simply we do not call
0096      * KisSelectionBasedLayer::needRect here :)
0097      */
0098     QRect needRect = rect;
0099     needRect |= needRectForOriginal(needRect);
0100     needRect = filter->neededRect(needRect, filterConfig.data(), projection()->defaultBounds()->currentLevelOfDetail());
0101     return needRect;
0102 }
0103 
0104 bool KisAdjustmentLayer::accept(KisNodeVisitor & v)
0105 {
0106     return v.visit(this);
0107 }
0108 
0109 void KisAdjustmentLayer::accept(KisProcessingVisitor &visitor, KisUndoAdapter *undoAdapter)
0110 {
0111     return visitor.visit(this, undoAdapter);
0112 }
0113 
0114 QIcon KisAdjustmentLayer::icon() const
0115 {
0116     return KisIconUtils::loadIcon("filterLayer");
0117 }
0118 
0119 KisBaseNode::PropertyList KisAdjustmentLayer::sectionModelProperties() const
0120 {
0121     KisFilterConfigurationSP filterConfig = filter();
0122     KisBaseNode::PropertyList l = KisLayer::sectionModelProperties();
0123     if (filterConfig)
0124         l << KisBaseNode::Property(KoID("filter", i18nc("property of a filter layer, noun", "Filter")), KisFilterRegistry::instance()->value(filterConfig->name())->name());
0125 
0126     return l;
0127 }
0128 
0129 void KisAdjustmentLayer::setChannelFlags(const QBitArray & channelFlags)
0130 {
0131     KisFilterConfigurationSP filterConfig = filter();
0132 
0133     if (filterConfig) {
0134         filterConfig->setChannelFlags(channelFlags);
0135     }
0136     KisLayer::setChannelFlags(channelFlags);
0137 }
0138