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 }