File indexing completed on 2024-05-12 15:59:05

0001 /*
0002  *  SPDX-FileCopyrightText: 2016 Boudewijn Rempt <boud@valdyas.org>
0003  *
0004  *  SPDX-License-Identifier: LGPL-2.0-or-later
0005  */
0006 #include "Filter.h"
0007 
0008 #include <KoCanvasResourceProvider.h>
0009 
0010 #include <kis_canvas_resource_provider.h>
0011 #include <kis_filter.h>
0012 #include <kis_properties_configuration.h>
0013 #include <kis_filter_configuration.h>
0014 #include <kis_filter_manager.h>
0015 #include <kis_filter_registry.h>
0016 #include <KisDocument.h>
0017 #include <kis_paint_device.h>
0018 #include <kis_paint_device_frames_interface.h>
0019 #include <KisPart.h>
0020 #include <KisView.h>
0021 
0022 #include <strokes/kis_filter_stroke_strategy.h>
0023 #include <krita_utils.h>
0024 #include <KisGlobalResourcesInterface.h>
0025 
0026 #include "Krita.h"
0027 #include "Document.h"
0028 #include "InfoObject.h"
0029 #include "Node.h"
0030 
0031 struct Filter::Private {
0032     Private() {}
0033     QString name;
0034     InfoObject *configuration {0};
0035 };
0036 
0037 Filter::Filter()
0038     : QObject(0)
0039     , d(new Private)
0040 {
0041 }
0042 
0043 Filter::~Filter()
0044 {
0045     delete d->configuration;
0046     delete d;
0047 }
0048 
0049 bool Filter::operator==(const Filter &other) const
0050 {
0051     return (d->name == other.d->name
0052             && d->configuration == other.d->configuration);
0053 }
0054 
0055 bool Filter::operator!=(const Filter &other) const
0056 {
0057     return !(operator==(other));
0058 }
0059 
0060 
0061 QString Filter::name() const
0062 {
0063     return d->name;
0064 }
0065 
0066 void Filter::setName(const QString &name)
0067 {
0068     d->name = name;
0069     delete d->configuration;
0070 
0071     KisFilterSP filter = KisFilterRegistry::instance()->value(d->name);
0072     d->configuration = new InfoObject(filter->defaultConfiguration(KisGlobalResourcesInterface::instance()));
0073 }
0074 
0075 InfoObject* Filter::configuration() const
0076 {
0077     return d->configuration;
0078 }
0079 
0080 void Filter::setConfiguration(InfoObject* value)
0081 {
0082     d->configuration = value;
0083 }
0084 
0085 bool Filter::apply(Node *node, int x, int y, int w, int h)
0086 {
0087     if (node->locked()) return false;
0088 
0089     KisFilterSP filter = KisFilterRegistry::instance()->value(d->name);
0090     if (!filter) return false;
0091 
0092     KisPaintDeviceSP dev = node->paintDevice();
0093     if (!dev) return false;
0094 
0095     QRect applyRect = QRect(x, y, w, h);
0096     KisFilterConfigurationSP config = static_cast<KisFilterConfiguration*>(d->configuration->configuration().data());
0097     filter->process(dev, applyRect, config->cloneWithResourcesSnapshot());
0098     return true;
0099 }
0100 
0101 bool Filter::startFilter(Node *node, int x, int y, int w, int h)
0102 {
0103     if (node->locked()) return false;
0104 
0105     KisFilterSP filter = KisFilterRegistry::instance()->value(d->name);
0106     if (!filter) return false;
0107 
0108     KisImageWSP image = node->image();
0109     if (!image) return false;
0110 
0111     KisFilterConfigurationSP filterConfig = static_cast<KisFilterConfiguration*>(d->configuration->configuration().data());
0112 
0113     image->waitForDone();
0114     QRect initialApplyRect = QRect(x, y, w, h);
0115 
0116     QRect applyRect = initialApplyRect;
0117 
0118     KisPaintDeviceSP paintDevice = node->paintDevice();
0119     if (paintDevice && filter->needsTransparentPixels(filterConfig.data(), paintDevice->colorSpace())) {
0120         applyRect |= image->bounds();
0121     }
0122 
0123     KisResourcesSnapshotSP resources = new KisResourcesSnapshot(image, node->node());
0124 
0125     Document *document = Krita::instance()->activeDocument();
0126     if (document && KisPart::instance()->viewCount(document->document()) > 0) {
0127         Q_FOREACH (QPointer<KisView> view, KisPart::instance()->views()) {
0128             if (view && view->document() == document->document()) {
0129                 resources = new KisResourcesSnapshot(image, node->node(), view->resourceProvider()->resourceManager());
0130                 break;
0131             }
0132         }
0133     }
0134     delete document;
0135 
0136     KisStrokeId currentStrokeId = image->startStroke(new KisFilterStrokeStrategy(filter,
0137                                                                                  KisFilterConfigurationSP(filterConfig),
0138                                                                                  resources));
0139 
0140     QRect processRect = filter->changedRect(applyRect, filterConfig.data(), 0);
0141     processRect &= image->bounds();
0142 
0143     image->addJob(currentStrokeId, new KisFilterStrokeStrategy::FilterJobData());
0144 
0145 
0146     image->endStroke(currentStrokeId);
0147     image->waitForDone();
0148 
0149     return true;
0150 }
0151 
0152 KisFilterConfigurationSP Filter::filterConfig()
0153 {
0154     KisFilterConfigurationSP config = KisFilterRegistry::instance()->get(d->name)->factoryConfiguration(KisGlobalResourcesInterface::instance());
0155     Q_FOREACH(const QString property, d->configuration->properties().keys()) {
0156         config->setProperty(property, d->configuration->property(property));
0157     }
0158     return config;
0159 }