File indexing completed on 2024-05-19 04:26:57

0001 /*
0002  *  SPDX-FileCopyrightText: 2016 Boudewijn Rempt <boud@valdyas.org>
0003  *
0004  *  SPDX-License-Identifier: LGPL-2.0-or-later
0005  */
0006 #include <QUrl>
0007 #include <QScopedPointer>
0008 #include <QUuid>
0009 
0010 #include <KoColorSpace.h>
0011 #include <KoColorSpaceRegistry.h>
0012 #include <KoColorTransformation.h>
0013 
0014 #include <KisDocument.h>
0015 #include <KisMimeDatabase.h>
0016 #include <KisPart.h>
0017 #include <kis_image.h>
0018 #include <kis_types.h>
0019 #include <kis_node.h>
0020 #include <kis_paint_layer.h>
0021 #include <kis_group_layer.h>
0022 #include <kis_file_layer.h>
0023 #include <kis_adjustment_layer.h>
0024 #include <kis_generator_layer.h>
0025 #include <kis_clone_layer.h>
0026 #include <kis_shape_layer.h>
0027 #include <KisReferenceImagesLayer.h>
0028 #include <kis_transparency_mask.h>
0029 #include <kis_filter_mask.h>
0030 #include <kis_transform_mask.h>
0031 #include <kis_selection_mask.h>
0032 #include <lazybrush/kis_colorize_mask.h>
0033 #include <kis_layer.h>
0034 #include <kis_meta_data_merge_strategy.h>
0035 #include <kis_meta_data_merge_strategy_registry.h>
0036 #include <kis_filter_strategy.h>
0037 #include <commands/kis_node_compositeop_command.h>
0038 #include <commands/kis_image_layer_add_command.h>
0039 #include <commands/kis_image_layer_remove_command.h>
0040 #include <commands_new/kis_set_layer_style_command.h>
0041 #include <kis_processing_applicator.h>
0042 #include <kis_asl_layer_style_serializer.h>
0043 
0044 #include <kis_raster_keyframe_channel.h>
0045 #include <kis_keyframe.h>
0046 #include "kis_selection.h"
0047 
0048 #include "InfoObject.h"
0049 #include "Krita.h"
0050 #include "Node.h"
0051 #include "Channel.h"
0052 #include "Filter.h"
0053 #include "Selection.h"
0054 
0055 #include "GroupLayer.h"
0056 #include "CloneLayer.h"
0057 #include "FilterLayer.h"
0058 #include "FillLayer.h"
0059 #include "FileLayer.h"
0060 #include "VectorLayer.h"
0061 #include "FilterMask.h"
0062 #include "SelectionMask.h"
0063 #include "TransparencyMask.h"
0064 #include "TransformMask.h"
0065 #include "ColorizeMask.h"
0066 
0067 #include "LibKisUtils.h"
0068 #include <kis_layer_utils.h>
0069 
0070 struct Node::Private {
0071     Private() {}
0072     KisImageWSP image;
0073     KisNodeSP node;
0074 };
0075 
0076 Node::Node(KisImageSP image, KisNodeSP node, QObject *parent)
0077     : QObject(parent)
0078     , d(new Private)
0079 {
0080     d->image = image;
0081     d->node = node;
0082 }
0083 
0084 Node *Node::createNode(KisImageSP image, KisNodeSP node, QObject *parent)
0085 {
0086     if (node.isNull()) {
0087         return 0;
0088     }
0089     if (node->inherits("KisGroupLayer")) {
0090         return new GroupLayer(dynamic_cast<KisGroupLayer*>(node.data()));
0091     }
0092     else if (node->inherits("KisCloneLayer")) {
0093         return new CloneLayer(dynamic_cast<KisCloneLayer*>(node.data()));
0094     }
0095     else if (node->inherits("KisFileLayer")) {
0096         return new FileLayer(dynamic_cast<KisFileLayer*>(node.data()));
0097     }
0098     else if (node->inherits("KisAdjustmentLayer")) {
0099         return new FilterLayer(dynamic_cast<KisAdjustmentLayer*>(node.data()));
0100     }
0101     else if (node->inherits("KisGeneratorLayer")) {
0102         return new FillLayer(dynamic_cast<KisGeneratorLayer*>(node.data()));
0103     }
0104     else if (node->inherits("KisShapeLayer")) {
0105         return new VectorLayer(dynamic_cast<KisShapeLayer*>(node.data()));
0106     }
0107     else if (node->inherits("KisFilterMask")) {
0108         return new FilterMask(image, dynamic_cast<KisFilterMask*>(node.data()));
0109     }
0110     else if (node->inherits("KisSelectionMask")) {
0111         return new SelectionMask(image, dynamic_cast<KisSelectionMask*>(node.data()));
0112     }
0113     else if (node->inherits("KisTransparencyMask")) {
0114         return new TransparencyMask(image, dynamic_cast<KisTransparencyMask*>(node.data()));
0115     }
0116     else if (node->inherits("KisTransformMask")) {
0117         return new TransformMask(image, dynamic_cast<KisTransformMask*>(node.data()));
0118     }
0119     else if (node->inherits("KisColorizeMask")) {
0120         return new ColorizeMask(image, dynamic_cast<KisColorizeMask*>(node.data()));
0121     }
0122     else {
0123         return new Node(image, node, parent);
0124     }
0125 }
0126 
0127 Node::~Node()
0128 {
0129     delete d;
0130 }
0131 
0132 bool Node::operator==(const Node &other) const
0133 {
0134     return (d->node == other.d->node
0135             && d->image == other.d->image);
0136 }
0137 
0138 bool Node::operator!=(const Node &other) const
0139 {
0140     return !(operator==(other));
0141 }
0142 
0143 Node *Node::clone() const
0144 {
0145     KisNodeSP clone = d->node->clone();
0146     Node *node = Node::createNode(0, clone);
0147     return node;
0148 }
0149 
0150 
0151 bool Node::alphaLocked() const
0152 {
0153     if (!d->node) return false;
0154     KisPaintLayerSP paintLayer = qobject_cast<KisPaintLayer*>(d->node.data());
0155     if (paintLayer) {
0156         return paintLayer->alphaLocked();
0157     }
0158     return false;
0159 }
0160 
0161 void Node::setAlphaLocked(bool value)
0162 {
0163     if (!d->node) return;
0164     KisPaintLayerSP paintLayer = qobject_cast<KisPaintLayer*>(d->node.data());
0165     if (paintLayer) {
0166         paintLayer->setAlphaLocked(value);
0167     }
0168 }
0169 
0170 
0171 QString Node::blendingMode() const
0172 {
0173     if (!d->node) return QString();
0174 
0175     return d->node->compositeOpId();
0176 }
0177 
0178 void Node::setBlendingMode(QString value)
0179 {
0180     if (!d->node) return;
0181 
0182     KUndo2Command *cmd = new KisNodeCompositeOpCommand(d->node,
0183                                                        value);
0184 
0185     KisProcessingApplicator::runSingleCommandStroke(d->image, cmd);
0186     d->image->waitForDone();
0187 }
0188 
0189 
0190 QList<Channel*> Node::channels() const
0191 {
0192     QList<Channel*> channels;
0193 
0194     if (!d->node) return channels;
0195     if (!d->node->inherits("KisLayer")) return channels;
0196 
0197     Q_FOREACH(KoChannelInfo *info, d->node->colorSpace()->channels()) {
0198         Channel *channel = new Channel(d->node, info);
0199         channels << channel;
0200     }
0201 
0202     return channels;
0203 }
0204 
0205 QList<Node*> Node::childNodes() const
0206 {
0207     QList<Node*> nodes;
0208     if (d->node) {
0209         KisNodeList nodeList;
0210         int childCount = d->node->childCount();
0211         for (int i = 0; i < childCount; ++i) {
0212             nodeList << d->node->at(i);
0213         }
0214         nodes = LibKisUtils::createNodeList(nodeList, d->image);
0215     }
0216     return nodes;
0217 }
0218 
0219 QList<Node*> Node::findChildNodes(const QString &name, bool recursive, bool partialMatch, const QString &type, int colorLabelIndex) const
0220 {
0221     if (!d->node) return {};
0222 
0223     QList<Node*> nodes;
0224     KisNodeList nodeList = KisLayerUtils::findNodesByName(d->node, name, recursive, partialMatch);
0225 
0226     if (!type.isEmpty()) {
0227         for (int i = nodeList.size() - 1; i >= 0; i--) {
0228             if ((type == "paintlayer" && !qobject_cast<const KisPaintLayer*>(nodeList.at(i))) ||
0229                 (type == "vectorlayer" && !qobject_cast<const KisShapeLayer*>(nodeList.at(i))) ||
0230                 (type == "grouplayer" && !qobject_cast<const KisGroupLayer*>(nodeList.at(i))) ||
0231                 (type == "filelayer" && !qobject_cast<const KisFileLayer*>(nodeList.at(i))) ||
0232                 (type == "filterlayer" && !qobject_cast<const KisAdjustmentLayer*>(nodeList.at(i))) ||
0233                 (type == "filllayer" && !qobject_cast<const KisGeneratorLayer*>(nodeList.at(i))) ||
0234                 (type == "clonelayer" && !qobject_cast<const KisCloneLayer*>(nodeList.at(i))) ||
0235                 (type == "transformmask" && !qobject_cast<const KisTransformMask*>(nodeList.at(i))) ||
0236                 (type == "referenceimageslayer" && !qobject_cast<const KisReferenceImagesLayer*>(nodeList.at(i))) ||
0237                 (type == "transparencymask" && !qobject_cast<const KisTransformMask*>(nodeList.at(i))) ||
0238                 (type == "filtermask" && !qobject_cast<const KisFilterMask*>(nodeList.at(i))) ||
0239                 (type == "selectionmask" && !qobject_cast<const KisSelectionMask*>(nodeList.at(i))) ||
0240                 (type == "colorizemask" && !qobject_cast<const KisColorizeMask*>(nodeList.at(i)))
0241             ) {
0242                 nodeList.removeAt(i);
0243             }
0244         }
0245     }
0246 
0247     if (colorLabelIndex > 0) {
0248         for (int i = nodeList.size() - 1; i >= 0; i--) {
0249             if (nodeList.at(i)->colorLabelIndex() != colorLabelIndex) {
0250                 nodeList.removeAt(i);
0251             }
0252         }
0253     }
0254 
0255     return LibKisUtils::createNodeList(nodeList, d->image);
0256 }
0257 
0258 bool Node::addChildNode(Node *child, Node *above)
0259 {
0260     if (!d->node) return false;
0261 
0262     KUndo2Command *cmd = 0;
0263 
0264     if (above) {
0265         cmd = new KisImageLayerAddCommand(d->image, child->node(), d->node, above->node());
0266     } else {
0267         cmd = new KisImageLayerAddCommand(d->image, child->node(), d->node, d->node->childCount());
0268     }
0269 
0270     KisProcessingApplicator::runSingleCommandStroke(d->image, cmd);
0271     d->image->waitForDone();
0272 
0273     return true;
0274 }
0275 
0276 bool Node::removeChildNode(Node *child)
0277 {
0278     if (!d->node) return false;
0279     return child->remove();
0280 }
0281 
0282 void Node::setChildNodes(QList<Node*> nodes)
0283 {
0284     if (!d->node) return;
0285     KisNodeSP node = d->node->firstChild();
0286     while (node) {
0287         d->image->removeNode(node);
0288         node = node->nextSibling();
0289     }
0290     Q_FOREACH(Node *node, nodes) {
0291         d->image->addNode(node->node(), d->node);
0292     }
0293 }
0294 
0295 int Node::colorLabel() const
0296 {
0297     if (!d->node) return 0;
0298     return d->node->colorLabelIndex();
0299 }
0300 
0301 void Node::setColorLabel(int index)
0302 {
0303     if (!d->node) return;
0304     d->node->setColorLabelIndex(index);
0305 }
0306 
0307 QString Node::colorDepth() const
0308 {
0309     if (!d->node) return "";
0310     if (!d->node->projection()) return d->node->colorSpace()->colorDepthId().id();
0311     return d->node->projection()->colorSpace()->colorDepthId().id();
0312 }
0313 
0314 QString Node::colorModel() const
0315 {
0316     if (!d->node) return "";
0317     if (!d->node->projection()) return d->node->colorSpace()->colorModelId().id();
0318     return d->node->projection()->colorSpace()->colorModelId().id();
0319 }
0320 
0321 
0322 QString Node::colorProfile() const
0323 {
0324     if (!d->node) return "";
0325     if (!d->node->projection()) return d->node->colorSpace()->profile()->name();
0326     return d->node->projection()->colorSpace()->profile()->name();
0327 }
0328 
0329 bool Node::setColorProfile(const QString &colorProfile)
0330 {
0331     if (!d->node) return false;
0332     if (!d->node->inherits("KisLayer")) return false;
0333     KisLayer *layer = qobject_cast<KisLayer*>(d->node.data());
0334     const KoColorProfile *profile = KoColorSpaceRegistry::instance()->profileByName(colorProfile);
0335     bool result = d->image->assignLayerProfile(layer, profile);
0336     d->image->waitForDone();
0337     return result;
0338 }
0339 
0340 bool Node::setColorSpace(const QString &colorModel, const QString &colorDepth, const QString &colorProfile)
0341 {
0342     if (!d->node) return false;
0343     if (!d->node->inherits("KisLayer")) return false;
0344     const KoColorProfile *profile = KoColorSpaceRegistry::instance()->profileByName(colorProfile);
0345     if (!profile) return false;
0346     const KoColorSpace *dstCs = KoColorSpaceRegistry::instance()->colorSpace(colorModel,
0347                                                                              colorDepth,
0348                                                                              profile);
0349     d->image->convertLayerColorSpace(d->node, dstCs, KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags());
0350     d->image->waitForDone();
0351     return true;
0352 }
0353 
0354 bool Node::animated() const
0355 {
0356     if (!d->node) return false;
0357     return d->node->isAnimated();
0358 }
0359 
0360 void Node::enableAnimation() const
0361 {
0362     if (!d->node) return;
0363     d->node->enableAnimation();
0364 }
0365 
0366 void Node::setPinnedToTimeline(bool pinned) const
0367 {
0368     if (!d->node) return;
0369     d->node->setPinnedToTimeline(pinned);
0370 }
0371 
0372 bool Node::isPinnedToTimeline() const
0373 {
0374     if (!d->node) return false;
0375     return d->node->isPinnedToTimeline();
0376 }
0377 
0378 bool Node::collapsed() const
0379 {
0380     if (!d->node) return false;
0381     return d->node->collapsed();
0382 }
0383 
0384 void Node::setCollapsed(bool collapsed)
0385 {
0386     if (!d->node) return;
0387     d->node->setCollapsed(collapsed);
0388 }
0389 
0390 bool Node::inheritAlpha() const
0391 {
0392     if (!d->node) return false;
0393     if (!d->node->inherits("KisLayer")) return false;
0394     return qobject_cast<const KisLayer*>(d->node)->alphaChannelDisabled();
0395 }
0396 
0397 void Node::setInheritAlpha(bool value)
0398 {
0399     if (!d->node) return;
0400     if (!d->node->inherits("KisLayer")) return;
0401     const_cast<KisLayer*>(qobject_cast<const KisLayer*>(d->node))->disableAlphaChannel(value);
0402 }
0403 
0404 bool Node::locked() const
0405 {
0406     if (!d->node) return false;
0407     return d->node->userLocked();
0408 }
0409 
0410 void Node::setLocked(bool value)
0411 {
0412     if (!d->node) return;
0413     d->node->setUserLocked(value);
0414 }
0415 
0416 bool Node::hasExtents()
0417 {
0418     return !d->node->extent().isEmpty();
0419 }
0420 
0421 QString Node::name() const
0422 {
0423     if (!d->node) return QString();
0424     return d->node->name();
0425 }
0426 
0427 void Node::setName(QString name)
0428 {
0429     if (!d->node) return;
0430     d->node->setName(name);
0431 }
0432 
0433 
0434 int Node::opacity() const
0435 {
0436     if (!d->node) return 0;
0437     return d->node->opacity();
0438 }
0439 
0440 void Node::setOpacity(int value)
0441 {
0442     if (!d->node) return;
0443     if (value < 0) value = 0;
0444     if (value > 255) value = 255;
0445     d->node->setOpacity(value);
0446 }
0447 
0448 
0449 Node* Node::parentNode() const
0450 {
0451     if (!d->node) return 0;
0452     if (!d->node->parent()) return 0;
0453     return Node::createNode(d->image, d->node->parent());
0454 }
0455 
0456 QString Node::type() const
0457 {
0458     if (!d->node) return QString();
0459     if (qobject_cast<const KisPaintLayer*>(d->node)) {
0460         return "paintlayer";
0461     }
0462     else if (qobject_cast<const KisGroupLayer*>(d->node)) {
0463         return "grouplayer";
0464     }
0465     if (qobject_cast<const KisFileLayer*>(d->node)) {
0466         return "filelayer";
0467     }
0468     if (qobject_cast<const KisAdjustmentLayer*>(d->node)) {
0469         return "filterlayer";
0470     }
0471     if (qobject_cast<const KisGeneratorLayer*>(d->node)) {
0472         return "filllayer";
0473     }
0474     if (qobject_cast<const KisCloneLayer*>(d->node)) {
0475         return "clonelayer";
0476     }
0477     if (qobject_cast<const KisReferenceImagesLayer*>(d->node)) {
0478         return "referenceimageslayer";
0479     }
0480     if (qobject_cast<const KisShapeLayer*>(d->node)) {
0481         return "vectorlayer";
0482     }
0483     if (qobject_cast<const KisTransparencyMask*>(d->node)) {
0484         return "transparencymask";
0485     }
0486     if (qobject_cast<const KisFilterMask*>(d->node)) {
0487         return "filtermask";
0488     }
0489     if (qobject_cast<const KisTransformMask*>(d->node)) {
0490         return "transformmask";
0491     }
0492     if (qobject_cast<const KisSelectionMask*>(d->node)) {
0493         return "selectionmask";
0494     }
0495     if (qobject_cast<const KisColorizeMask*>(d->node)) {
0496         return "colorizemask";
0497     }
0498     return QString();
0499 }
0500 
0501 QIcon Node::icon() const
0502 {
0503     QIcon icon;
0504     if (d->node) {
0505         icon = d->node->icon();
0506     }
0507     return icon;
0508 }
0509 
0510 bool Node::visible() const
0511 {
0512     if (!d->node) return false;
0513     return d->node->visible();
0514 }
0515 
0516 bool Node::hasKeyframeAtTime(int frameNumber)
0517 {
0518     if (!d->node || !d->node->isAnimated()) return false;
0519 
0520     KisRasterKeyframeChannel *rkc = dynamic_cast<KisRasterKeyframeChannel*>(d->node->getKeyframeChannel(KisKeyframeChannel::Raster.id()));
0521     if (!rkc) return false;
0522 
0523     KisKeyframeSP currentKeyframe = rkc->keyframeAt(frameNumber);
0524 
0525     if (!currentKeyframe) {
0526         return false;
0527     }
0528 
0529     return true;
0530 }
0531 
0532 void Node::setVisible(bool visible)
0533 {
0534     if (!d->node) return;
0535     d->node->setVisible(visible);
0536 }
0537 
0538 
0539 QByteArray Node::pixelData(int x, int y, int w, int h) const
0540 {
0541     QByteArray ba;
0542 
0543     if (!d->node) return ba;
0544 
0545     KisPaintDeviceSP dev = d->node->paintDevice();
0546     if (!dev) return ba;
0547 
0548     ba.resize(w * h * dev->pixelSize());
0549     dev->readBytes(reinterpret_cast<quint8*>(ba.data()), x, y, w, h);
0550     return ba;
0551 }
0552 
0553 QByteArray Node::pixelDataAtTime(int x, int y, int w, int h, int time) const
0554 {
0555     QByteArray ba;
0556 
0557     if (!d->node || !d->node->isAnimated()) return ba;
0558 
0559     //
0560     KisRasterKeyframeChannel *rkc = dynamic_cast<KisRasterKeyframeChannel*>(d->node->getKeyframeChannel(KisKeyframeChannel::Raster.id()));
0561     if (!rkc) return ba;
0562     KisRasterKeyframeSP frame = rkc->keyframeAt<KisRasterKeyframe>(time);
0563     if (!frame) return ba;
0564     KisPaintDeviceSP dev = new KisPaintDevice(*d->node->paintDevice(), KritaUtils::DeviceCopyMode::CopySnapshot);
0565     if (!dev) return ba;
0566 
0567     frame->writeFrameToDevice(dev);
0568 
0569     ba.resize(w * h * dev->pixelSize());
0570     dev->readBytes(reinterpret_cast<quint8*>(ba.data()), x, y, w, h);
0571     return ba;
0572 }
0573 
0574 
0575 QByteArray Node::projectionPixelData(int x, int y, int w, int h) const
0576 {
0577     QByteArray ba;
0578 
0579     if (!d->node) return ba;
0580 
0581     KisPaintDeviceSP dev;
0582     if (const KisColorizeMask *mask = qobject_cast<const KisColorizeMask*>(d->node)) {
0583 
0584         dev = mask->coloringProjection();
0585     } else {
0586         dev = d->node->projection();
0587     }
0588     if (!dev) return ba;
0589 
0590     ba.resize(w * h * dev->pixelSize());
0591     dev->readBytes(reinterpret_cast<quint8*>(ba.data()), x, y, w, h);
0592     return ba;
0593 }
0594 
0595 bool Node::setPixelData(QByteArray value, int x, int y, int w, int h)
0596 {
0597     if (!d->node) return false;
0598     KisPaintDeviceSP dev = d->node->paintDevice();
0599     if (!dev) return false;
0600     if (value.length() <  w * h * (int)dev->colorSpace()->pixelSize()) {
0601         qWarning() << "Node::setPixelData: not enough data to write to the paint device";
0602         return false;
0603     }
0604     dev->writeBytes((const quint8*)value.constData(), x, y, w, h);
0605     return true;
0606 }
0607 
0608 QRect Node::bounds() const
0609 {
0610     if (!d->node) return QRect();
0611     return d->node->exactBounds();
0612 }
0613 
0614 void Node::move(int x, int y)
0615 {
0616     if (!d->node) return;
0617     d->node->setX(x);
0618     d->node->setY(y);
0619 }
0620 
0621 QPoint Node::position() const
0622 {
0623     if (!d->node) return QPoint();
0624     return QPoint(d->node->x(), d->node->y());
0625 }
0626 
0627 bool Node::remove()
0628 {
0629     if (!d->node) return false;
0630     if (!d->node->parent()) return false;
0631 
0632     KUndo2Command *cmd = new KisImageLayerRemoveCommand(d->image, d->node);
0633 
0634     KisProcessingApplicator::runSingleCommandStroke(d->image, cmd);
0635     d->image->waitForDone();
0636 
0637     return true;
0638 }
0639 
0640 Node* Node::duplicate()
0641 {
0642     if (!d->node) return 0;
0643     return Node::createNode(d->image, d->node->clone());
0644 }
0645 
0646 bool Node::save(const QString &filename, double xRes, double yRes, const InfoObject &exportConfiguration, const QRect &exportRect)
0647 {
0648     if (!d->node) return false;
0649     if (filename.isEmpty()) return false;
0650 
0651     KisPaintDeviceSP projection = d->node->projection();
0652     QRect bounds = (exportRect.isEmpty())? d->node->exactBounds() : exportRect;
0653 
0654     QString mimeType = KisMimeDatabase::mimeTypeForFile(filename, false);
0655     QScopedPointer<KisDocument> doc(KisPart::instance()->createDocument());
0656 
0657     KisImageSP dst = new KisImage(doc->createUndoStore(),
0658                                   bounds.right(),
0659                                   bounds.bottom(),
0660                                   projection->compositionSourceColorSpace(),
0661                                   d->node->name());
0662     dst->setResolution(xRes, yRes);
0663     doc->setFileBatchMode(Krita::instance()->batchmode());
0664     doc->setCurrentImage(dst);
0665     KisPaintLayer* paintLayer = new KisPaintLayer(dst, "paint device", d->node->opacity());
0666     paintLayer->paintDevice()->makeCloneFrom(projection, bounds);
0667     dst->addNode(paintLayer, dst->rootLayer(), KisLayerSP(0));
0668     dst->cropImage(bounds);
0669     dst->initialRefreshGraph();
0670 
0671     bool r = doc->exportDocumentSync(filename, mimeType.toLatin1(), exportConfiguration.configuration());
0672     if (!r) {
0673         qWarning() << doc->errorMessage();
0674     }
0675     return r;
0676 }
0677 
0678 Node* Node::mergeDown()
0679 {
0680     if (!d->node) return 0;
0681     if (!qobject_cast<KisLayer*>(d->node.data())) return 0;
0682     if (!d->node->prevSibling()) return 0;
0683 
0684     d->image->mergeDown(qobject_cast<KisLayer*>(d->node.data()), KisMetaData::MergeStrategyRegistry::instance()->get("Drop"));
0685     d->image->waitForDone();
0686 
0687     return Node::createNode(d->image, d->node->prevSibling());
0688 }
0689 
0690 void Node::scaleNode(QPointF origin, int width, int height, QString strategy)
0691 {
0692     if (!d->node) return;
0693     if (!qobject_cast<KisLayer*>(d->node.data())) return;
0694     if (!d->node->parent()) return;
0695 
0696     KisFilterStrategy *actualStrategy = KisFilterStrategyRegistry::instance()->get(strategy);
0697     if (!actualStrategy) actualStrategy = KisFilterStrategyRegistry::instance()->get("Bicubic");
0698 
0699     const QRect bounds(d->node->exactBounds());
0700 
0701     d->image->scaleNode(d->node,
0702                         origin,
0703                         qreal(width) / bounds.width(),
0704                         qreal(height) / bounds.height(),
0705                         actualStrategy, 0);
0706     d->image->waitForDone();
0707 }
0708 
0709 void Node::rotateNode(double radians)
0710 {
0711     if (!d->node) return;
0712     if (!qobject_cast<KisLayer*>(d->node.data())) return;
0713     if (!d->node->parent()) return;
0714 
0715     d->image->rotateNode(d->node, radians, 0);
0716     d->image->waitForDone();
0717 }
0718 
0719 void Node::cropNode(int x, int y, int w, int h)
0720 {
0721     if (!d->node) return;
0722     if (!qobject_cast<KisLayer*>(d->node.data())) return;
0723     if (!d->node->parent()) return;
0724 
0725     QRect rect = QRect(x, y, w, h);
0726     d->image->cropNode(d->node, rect);
0727     d->image->waitForDone();
0728 }
0729 
0730 void Node::shearNode(double angleX, double angleY)
0731 {
0732     if (!d->node) return;
0733     if (!qobject_cast<KisLayer*>(d->node.data())) return;
0734     if (!d->node->parent()) return;
0735 
0736     d->image->shearNode(d->node, angleX, angleY, 0);
0737     d->image->waitForDone();
0738 }
0739 
0740 QImage Node::thumbnail(int w, int h)
0741 {
0742     if (!d->node) return QImage();
0743     return d->node->createThumbnail(w, h);
0744 }
0745 
0746 QString Node::layerStyleToAsl()
0747 {
0748     if (!d->node) return QString();
0749 
0750     KisLayer *layer = qobject_cast<KisLayer*>(d->node.data());
0751 
0752     if (!layer) return QString();
0753 
0754     KisPSDLayerStyleSP layerStyle = layer->layerStyle();
0755 
0756     if (!layerStyle) return QString();
0757 
0758     KisAslLayerStyleSerializer serializer;
0759 
0760     serializer.setStyles(QVector<KisPSDLayerStyleSP>() << layerStyle);
0761 
0762     return serializer.formPsdXmlDocument().toString();
0763 }
0764 
0765 bool Node::setLayerStyleFromAsl(const QString &asl)
0766 {
0767     if (!d->node) return false;
0768 
0769     KisLayer *layer = qobject_cast<KisLayer*>(d->node.data());
0770 
0771     if (!layer) return false;
0772 
0773     QDomDocument aslDoc;
0774 
0775     if (!aslDoc.setContent(asl)) {
0776         qWarning() << "ASL string format is invalid!";
0777         return false;
0778     }
0779 
0780     KisAslLayerStyleSerializer serializer;
0781 
0782     serializer.registerPSDPattern(aslDoc);
0783     serializer.readFromPSDXML(aslDoc);
0784 
0785     if (serializer.styles().size() != 1) return false;
0786 
0787     KisPSDLayerStyleSP newStyle = serializer.styles().first();
0788     KUndo2Command *cmd = new KisSetLayerStyleCommand(layer, layer->layerStyle(), newStyle);
0789 
0790     KisProcessingApplicator::runSingleCommandStroke(d->image, cmd);
0791     d->image->waitForDone();
0792 
0793     return true;
0794 }
0795 
0796 int Node::index() const
0797 {
0798     if (!d->node) return -1;
0799     if (!d->node->parent()) return -1;
0800 
0801     return d->node->parent()->index(d->node);
0802 }
0803 
0804 QUuid Node::uniqueId() const
0805 {
0806     if (!d->node) return QUuid();
0807     return d->node->uuid();
0808 }
0809 
0810 KisPaintDeviceSP Node::paintDevice() const
0811 {
0812     return d->node->paintDevice();
0813 }
0814 
0815 KisImageSP Node::image() const
0816 {
0817     return d->image;
0818 }
0819 
0820 KisNodeSP Node::node() const
0821 {
0822     return d->node;
0823 }