Krita

Node.cpp
1/*
2 * SPDX-FileCopyrightText: 2016 Boudewijn Rempt <boud@valdyas.org>
3 *
4 * SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6#include <QUrl>
7#include <QScopedPointer>
8#include <QUuid>
9
10#include <KoColorSpace.h>
11#include <KoColorSpaceRegistry.h>
12#include <KoColorTransformation.h>
13
14#include <KisDocument.h>
15#include <KisMimeDatabase.h>
16#include <KisPart.h>
17#include <kis_image.h>
18#include <kis_types.h>
19#include <kis_node.h>
20#include <kis_paint_layer.h>
21#include <kis_group_layer.h>
22#include <kis_file_layer.h>
23#include <kis_adjustment_layer.h>
24#include <kis_generator_layer.h>
25#include <kis_clone_layer.h>
26#include <kis_shape_layer.h>
27#include <KisReferenceImagesLayer.h>
28#include <kis_transparency_mask.h>
29#include <kis_filter_mask.h>
30#include <kis_transform_mask.h>
31#include <kis_selection_mask.h>
32#include <lazybrush/kis_colorize_mask.h>
33#include <kis_layer.h>
34#include <kis_meta_data_merge_strategy.h>
35#include <kis_meta_data_merge_strategy_registry.h>
36#include <kis_filter_strategy.h>
37#include <commands/kis_node_compositeop_command.h>
38#include <commands/kis_image_layer_add_command.h>
39#include <commands/kis_image_layer_remove_command.h>
40#include <commands_new/kis_set_layer_style_command.h>
41#include <kis_processing_applicator.h>
42#include <kis_asl_layer_style_serializer.h>
43
44#include <kis_raster_keyframe_channel.h>
45#include <kis_keyframe.h>
46#include "kis_selection.h"
47
48#include "InfoObject.h"
49#include "Krita.h"
50#include "Node.h"
51#include "Channel.h"
52#include "Filter.h"
53#include "Selection.h"
54
55#include "GroupLayer.h"
56#include "CloneLayer.h"
57#include "FilterLayer.h"
58#include "FillLayer.h"
59#include "FileLayer.h"
60#include "VectorLayer.h"
61#include "FilterMask.h"
62#include "SelectionMask.h"
63#include "TransparencyMask.h"
64#include "TransformMask.h"
65#include "ColorizeMask.h"
66
67#include "LibKisUtils.h"
68#include <kis_layer_utils.h>
69
70#include "PaintingResources.h"
71#include "KisMainWindow.h"
72#include "kis_canvas2.h"
73#include "KoCanvasResourceProvider.h"
74#include <brushengine/kis_paintop_preset.h>
75
76
77struct Node::Private {
78 Private() {}
79 KisImageWSP image;
80 KisNodeSP node;
81};
82
83Node::Node(KisImageSP image, KisNodeSP node, QObject *parent)
84 : QObject(parent)
85 , d(new Private)
86{
87 d->image = image;
88 d->node = node;
89}
90
91Node *Node::createNode(KisImageSP image, KisNodeSP node, QObject *parent)
92{
93 if (node.isNull()) {
94 return 0;
95 }
96 if (node->inherits("KisGroupLayer")) {
97 return new GroupLayer(dynamic_cast<KisGroupLayer*>(node.data()));
98 }
99 else if (node->inherits("KisCloneLayer")) {
100 return new CloneLayer(dynamic_cast<KisCloneLayer*>(node.data()));
101 }
102 else if (node->inherits("KisFileLayer")) {
103 return new FileLayer(dynamic_cast<KisFileLayer*>(node.data()));
104 }
105 else if (node->inherits("KisAdjustmentLayer")) {
106 return new FilterLayer(dynamic_cast<KisAdjustmentLayer*>(node.data()));
107 }
108 else if (node->inherits("KisGeneratorLayer")) {
109 return new FillLayer(dynamic_cast<KisGeneratorLayer*>(node.data()));
110 }
111 else if (node->inherits("KisShapeLayer")) {
112 return new VectorLayer(dynamic_cast<KisShapeLayer*>(node.data()));
113 }
114 else if (node->inherits("KisFilterMask")) {
115 return new FilterMask(image, dynamic_cast<KisFilterMask*>(node.data()));
116 }
117 else if (node->inherits("KisSelectionMask")) {
118 return new SelectionMask(image, dynamic_cast<KisSelectionMask*>(node.data()));
119 }
120 else if (node->inherits("KisTransparencyMask")) {
121 return new TransparencyMask(image, dynamic_cast<KisTransparencyMask*>(node.data()));
122 }
123 else if (node->inherits("KisTransformMask")) {
124 return new TransformMask(image, dynamic_cast<KisTransformMask*>(node.data()));
125 }
126 else if (node->inherits("KisColorizeMask")) {
127 return new ColorizeMask(image, dynamic_cast<KisColorizeMask*>(node.data()));
128 }
129 else {
130 return new Node(image, node, parent);
131 }
132}
133
134Node::~Node()
135{
136 delete d;
137}
138
139bool Node::operator==(const Node &other) const
140{
141 return (d->node == other.d->node
142 && d->image == other.d->image);
143}
144
145bool Node::operator!=(const Node &other) const
146{
147 return !(operator==(other));
148}
149
150Node *Node::clone() const
151{
152 KisNodeSP clone = d->node->clone();
153 Node *node = Node::createNode(0, clone);
154 return node;
155}
156
157
159{
160 if (!d->node) return false;
161 KisPaintLayerSP paintLayer = qobject_cast<KisPaintLayer*>(d->node.data());
162 if (paintLayer) {
163 return paintLayer->alphaLocked();
164 }
165 return false;
166}
167
168void Node::setAlphaLocked(bool value)
169{
170 if (!d->node) return;
171 KisPaintLayerSP paintLayer = qobject_cast<KisPaintLayer*>(d->node.data());
172 if (paintLayer) {
173 paintLayer->setAlphaLocked(value);
174 }
175}
176
177
179{
180 if (!d->node) return QString();
181
182 return d->node->compositeOpId();
183}
184
186{
187 if (!d->node) return;
188
189 KUndo2Command *cmd = new KisNodeCompositeOpCommand(d->node,
190 value);
191
192 KisProcessingApplicator::runSingleCommandStroke(d->image, cmd);
193 d->image->waitForDone();
194}
195
196
198{
200
201 if (!d->node) return channels;
202 if (!d->node->inherits("KisLayer")) return channels;
203
204 Q_FOREACH(KoChannelInfo *info, d->node->colorSpace()->channels()) {
205 Channel *channel = new Channel(d->node, info);
206 channels << channel;
207 }
208
209 return channels;
210}
211
213{
214 QList<Node*> nodes;
215 if (d->node) {
216 KisNodeList nodeList;
217 int childCount = d->node->childCount();
218 for (int i = 0; i < childCount; ++i) {
219 nodeList << d->node->at(i);
220 }
221 nodes = LibKisUtils::createNodeList(nodeList, d->image);
222 }
223 return nodes;
224}
225
226QList<Node*> Node::findChildNodes(const QString &name, bool recursive, bool partialMatch, const QString &type, int colorLabelIndex) const
227{
228 if (!d->node) return {};
229
230 QList<Node*> nodes;
231 KisNodeList nodeList = KisLayerUtils::findNodesByName(d->node, name, recursive, partialMatch);
232
233 if (!type.isEmpty()) {
234 for (int i = nodeList.size() - 1; i >= 0; i--) {
235 if ((type == "paintlayer" && !qobject_cast<const KisPaintLayer*>(nodeList.at(i))) ||
236 (type == "vectorlayer" && !qobject_cast<const KisShapeLayer*>(nodeList.at(i))) ||
237 (type == "grouplayer" && !qobject_cast<const KisGroupLayer*>(nodeList.at(i))) ||
238 (type == "filelayer" && !qobject_cast<const KisFileLayer*>(nodeList.at(i))) ||
239 (type == "filterlayer" && !qobject_cast<const KisAdjustmentLayer*>(nodeList.at(i))) ||
240 (type == "filllayer" && !qobject_cast<const KisGeneratorLayer*>(nodeList.at(i))) ||
241 (type == "clonelayer" && !qobject_cast<const KisCloneLayer*>(nodeList.at(i))) ||
242 (type == "transformmask" && !qobject_cast<const KisTransformMask*>(nodeList.at(i))) ||
243 (type == "referenceimageslayer" && !qobject_cast<const KisReferenceImagesLayer*>(nodeList.at(i))) ||
244 (type == "transparencymask" && !qobject_cast<const KisTransformMask*>(nodeList.at(i))) ||
245 (type == "filtermask" && !qobject_cast<const KisFilterMask*>(nodeList.at(i))) ||
246 (type == "selectionmask" && !qobject_cast<const KisSelectionMask*>(nodeList.at(i))) ||
247 (type == "colorizemask" && !qobject_cast<const KisColorizeMask*>(nodeList.at(i)))
248 ) {
249 nodeList.removeAt(i);
250 }
251 }
252 }
253
254 if (colorLabelIndex > 0) {
255 for (int i = nodeList.size() - 1; i >= 0; i--) {
256 if (nodeList.at(i)->colorLabelIndex() != colorLabelIndex) {
257 nodeList.removeAt(i);
258 }
259 }
260 }
261
262 return LibKisUtils::createNodeList(nodeList, d->image);
263}
264
265bool Node::addChildNode(Node *child, Node *above)
266{
267 if (!d->node) return false;
268
269 KUndo2Command *cmd = 0;
270
271 if (above) {
272 cmd = new KisImageLayerAddCommand(d->image, child->node(), d->node, above->node());
273 } else {
274 cmd = new KisImageLayerAddCommand(d->image, child->node(), d->node, d->node->childCount());
275 }
276
277 KisProcessingApplicator::runSingleCommandStroke(d->image, cmd);
278 d->image->waitForDone();
279
280 return true;
281}
282
283bool Node::removeChildNode(Node *child)
284{
285 if (!d->node) return false;
286 return child->remove();
287}
288
290{
291 if (!d->node) return;
292 KisNodeSP node = d->node->firstChild();
293 while (node) {
294 d->image->removeNode(node);
295 node = node->nextSibling();
296 }
297 Q_FOREACH(Node *node, nodes) {
298 d->image->addNode(node->node(), d->node);
299 }
300}
301
303{
304 if (!d->node) return 0;
305 return d->node->colorLabelIndex();
306}
307
309{
310 if (!d->node) return;
311 d->node->setColorLabelIndex(index);
312}
313
315{
316 if (!d->node) return "";
317 if (!d->node->projection()) return d->node->colorSpace()->colorDepthId().id();
318 return d->node->projection()->colorSpace()->colorDepthId().id();
319}
320
322{
323 if (!d->node) return "";
324 if (!d->node->projection()) return d->node->colorSpace()->colorModelId().id();
325 return d->node->projection()->colorSpace()->colorModelId().id();
326}
327
328
330{
331 if (!d->node) return "";
332 if (!d->node->projection()) return d->node->colorSpace()->profile()->name();
333 return d->node->projection()->colorSpace()->profile()->name();
334}
335
337{
338 if (!d->node) return false;
339 if (!d->node->inherits("KisLayer")) return false;
340 KisLayer *layer = qobject_cast<KisLayer*>(d->node.data());
341 const KoColorProfile *profile = KoColorSpaceRegistry::instance()->profileByName(colorProfile);
342 bool result = d->image->assignLayerProfile(layer, profile);
343 d->image->waitForDone();
344 return result;
345}
346
348{
349 if (!d->node) return false;
350 if (!d->node->inherits("KisLayer")) return false;
351 const KoColorProfile *profile = KoColorSpaceRegistry::instance()->profileByName(colorProfile);
352 if (!profile) return false;
353 const KoColorSpace *dstCs = KoColorSpaceRegistry::instance()->colorSpace(colorModel,
355 profile);
356 d->image->convertLayerColorSpace(d->node, dstCs, KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags());
357 d->image->waitForDone();
358 return true;
359}
360
361bool Node::animated() const
362{
363 if (!d->node) return false;
364 return d->node->isAnimated();
365}
366
368{
369 if (!d->node) return;
370 d->node->enableAnimation();
371}
372
373void Node::setPinnedToTimeline(bool pinned) const
374{
375 if (!d->node) return;
376 d->node->setPinnedToTimeline(pinned);
377}
378
380{
381 if (!d->node) return false;
382 return d->node->isPinnedToTimeline();
383}
384
385bool Node::collapsed() const
386{
387 if (!d->node) return false;
388 return d->node->collapsed();
389}
390
392{
393 if (!d->node) return;
394 d->node->setCollapsed(collapsed);
395}
396
398{
399 if (!d->node) return false;
400 if (!d->node->inherits("KisLayer")) return false;
401 return qobject_cast<const KisLayer*>(d->node)->alphaChannelDisabled();
402}
403
404void Node::setInheritAlpha(bool value)
405{
406 if (!d->node) return;
407 if (!d->node->inherits("KisLayer")) return;
408 const_cast<KisLayer*>(qobject_cast<const KisLayer*>(d->node))->disableAlphaChannel(value);
409}
410
411bool Node::locked() const
412{
413 if (!d->node) return false;
414 return d->node->userLocked();
415}
416
417void Node::setLocked(bool value)
418{
419 if (!d->node) return;
420 d->node->setUserLocked(value);
421}
422
424{
425 return !d->node->extent().isEmpty();
426}
427
429{
430 if (!d->node) return QString();
431 return d->node->name();
432}
433
435{
436 if (!d->node) return;
437 d->node->setName(name);
438}
439
440
441int Node::opacity() const
442{
443 if (!d->node) return 0;
444 return d->node->opacity();
445}
446
447void Node::setOpacity(int value)
448{
449 if (!d->node) return;
450 if (value < 0) value = 0;
451 if (value > 255) value = 255;
452 d->node->setOpacity(value);
453}
454
455
456Node* Node::parentNode() const
457{
458 if (!d->node) return 0;
459 if (!d->node->parent()) return 0;
460 return Node::createNode(d->image, d->node->parent());
461}
462
464{
465 if (!d->node) return QString();
467 return "paintlayer";
468 }
469 else if (qobject_cast<const KisGroupLayer*>(d->node)) {
470 return "grouplayer";
471 }
473 return "filelayer";
474 }
476 return "filterlayer";
477 }
479 return "filllayer";
480 }
482 return "clonelayer";
483 }
485 return "referenceimageslayer";
486 }
488 return "vectorlayer";
489 }
491 return "transparencymask";
492 }
494 return "filtermask";
495 }
497 return "transformmask";
498 }
500 return "selectionmask";
501 }
503 return "colorizemask";
504 }
505 return QString();
506}
507
509{
510 QIcon icon;
511 if (d->node) {
512 icon = d->node->icon();
513 }
514 return icon;
515}
516
517bool Node::visible() const
518{
519 if (!d->node) return false;
520 return d->node->visible();
521}
522
523bool Node::hasKeyframeAtTime(int frameNumber)
524{
525 if (!d->node || !d->node->isAnimated()) return false;
526
527 KisRasterKeyframeChannel *rkc = dynamic_cast<KisRasterKeyframeChannel*>(d->node->getKeyframeChannel(KisKeyframeChannel::Raster.id()));
528 if (!rkc) return false;
529
530 KisKeyframeSP currentKeyframe = rkc->keyframeAt(frameNumber);
531
532 if (!currentKeyframe) {
533 return false;
534 }
535
536 return true;
537}
538
540{
541 if (!d->node) return;
542 d->node->setVisible(visible);
543}
544
545
546QByteArray Node::pixelData(int x, int y, int w, int h) const
547{
548 QByteArray ba;
549
550 if (!d->node) return ba;
551
552 KisPaintDeviceSP dev = d->node->paintDevice();
553 if (!dev) return ba;
554
555 ba.resize(w * h * dev->pixelSize());
556 dev->readBytes(reinterpret_cast<quint8*>(ba.data()), x, y, w, h);
557 return ba;
558}
559
560QByteArray Node::pixelDataAtTime(int x, int y, int w, int h, int time) const
561{
562 QByteArray ba;
563
564 if (!d->node || !d->node->isAnimated()) return ba;
565
566 //
567 KisRasterKeyframeChannel *rkc = dynamic_cast<KisRasterKeyframeChannel*>(d->node->getKeyframeChannel(KisKeyframeChannel::Raster.id()));
568 if (!rkc) return ba;
569 KisRasterKeyframeSP frame = rkc->keyframeAt<KisRasterKeyframe>(time);
570 if (!frame) return ba;
571 KisPaintDeviceSP dev = new KisPaintDevice(*d->node->paintDevice(), KritaUtils::DeviceCopyMode::CopySnapshot);
572 if (!dev) return ba;
573
574 frame->writeFrameToDevice(dev);
575
576 ba.resize(w * h * dev->pixelSize());
577 dev->readBytes(reinterpret_cast<quint8*>(ba.data()), x, y, w, h);
578 return ba;
579}
580
581
582QByteArray Node::projectionPixelData(int x, int y, int w, int h) const
583{
584 QByteArray ba;
585
586 if (!d->node) return ba;
587
588 KisPaintDeviceSP dev;
589 if (const KisColorizeMask *mask = qobject_cast<const KisColorizeMask*>(d->node)) {
590
591 dev = mask->coloringProjection();
592 } else {
593 dev = d->node->projection();
594 }
595 if (!dev) return ba;
596
597 ba.resize(w * h * dev->pixelSize());
598 dev->readBytes(reinterpret_cast<quint8*>(ba.data()), x, y, w, h);
599 return ba;
600}
601
602bool Node::setPixelData(QByteArray value, int x, int y, int w, int h)
603{
604 if (!d->node) return false;
605 KisPaintDeviceSP dev = d->node->paintDevice();
606 if (!dev) return false;
607 if (value.length() < w * h * (int)dev->colorSpace()->pixelSize()) {
608 qWarning() << "Node::setPixelData: not enough data to write to the paint device";
609 return false;
610 }
611 dev->writeBytes((const quint8*)value.constData(), x, y, w, h);
612 return true;
613}
614
616{
617 if (!d->node) return QRect();
618 return d->node->exactBounds();
619}
620
621void Node::move(int x, int y)
622{
623 if (!d->node) return;
624 d->node->setX(x);
625 d->node->setY(y);
626}
627
629{
630 if (!d->node) return QPoint();
631 return QPoint(d->node->x(), d->node->y());
632}
633
635{
636 if (!d->node) return false;
637 if (!d->node->parent()) return false;
638
639 KUndo2Command *cmd = new KisImageLayerRemoveCommand(d->image, d->node);
640
641 KisProcessingApplicator::runSingleCommandStroke(d->image, cmd);
642 d->image->waitForDone();
643
644 return true;
645}
646
648{
649 if (!d->node) return 0;
650 return Node::createNode(d->image, d->node->clone());
651}
652
653bool Node::save(const QString &filename, double xRes, double yRes, const InfoObject &exportConfiguration, const QRect &exportRect)
654{
655 if (!d->node) return false;
656 if (filename.isEmpty()) return false;
657
658 KisPaintDeviceSP projection = d->node->projection();
659 QRect bounds = (exportRect.isEmpty())? d->node->exactBounds() : exportRect;
660
661 QString mimeType = KisMimeDatabase::mimeTypeForFile(filename, false);
662 QScopedPointer<KisDocument> doc(KisPart::instance()->createDocument());
663
664 KisImageSP dst = new KisImage(doc->createUndoStore(),
665 bounds.right(),
666 bounds.bottom(),
667 projection->compositionSourceColorSpace(),
668 d->node->name());
669 dst->setResolution(xRes, yRes);
670 doc->setFileBatchMode(Krita::instance()->batchmode());
671 doc->setCurrentImage(dst);
672 KisPaintLayer* paintLayer = new KisPaintLayer(dst, "paint device", d->node->opacity());
673 paintLayer->paintDevice()->makeCloneFrom(projection, bounds);
674 dst->addNode(paintLayer, dst->rootLayer(), KisLayerSP(0));
675 dst->cropImage(bounds);
676 dst->initialRefreshGraph();
677
678 bool r = doc->exportDocumentSync(filename, mimeType.toLatin1(), exportConfiguration.configuration());
679 if (!r) {
680 qWarning() << doc->errorMessage();
681 }
682 return r;
683}
684
686{
687 if (!d->node) return 0;
688 if (!qobject_cast<KisLayer*>(d->node.data())) return 0;
689 if (!d->node->prevSibling()) return 0;
690
691 d->image->mergeDown(qobject_cast<KisLayer*>(d->node.data()), KisMetaData::MergeStrategyRegistry::instance()->get("Drop"));
692 d->image->waitForDone();
693
694 return Node::createNode(d->image, d->node->prevSibling());
695}
696
697void Node::scaleNode(QPointF origin, int width, int height, QString strategy)
698{
699 if (!d->node) return;
700 if (!qobject_cast<KisLayer*>(d->node.data())) return;
701 if (!d->node->parent()) return;
702
703 KisFilterStrategy *actualStrategy = KisFilterStrategyRegistry::instance()->get(strategy);
704 if (!actualStrategy) actualStrategy = KisFilterStrategyRegistry::instance()->get("Bicubic");
705
706 const QRect bounds(d->node->exactBounds());
707
708 d->image->scaleNode(d->node,
709 origin,
710 qreal(width) / bounds.width(),
711 qreal(height) / bounds.height(),
712 actualStrategy, 0);
713 d->image->waitForDone();
714}
715
716void Node::rotateNode(double radians)
717{
718 if (!d->node) return;
719 if (!qobject_cast<KisLayer*>(d->node.data())) return;
720 if (!d->node->parent()) return;
721
722 d->image->rotateNode(d->node, radians, 0);
723 d->image->waitForDone();
724}
725
726void Node::cropNode(int x, int y, int w, int h)
727{
728 if (!d->node) return;
729 if (!qobject_cast<KisLayer*>(d->node.data())) return;
730 if (!d->node->parent()) return;
731
732 QRect rect = QRect(x, y, w, h);
733 d->image->cropNode(d->node, rect);
734 d->image->waitForDone();
735}
736
737void Node::shearNode(double angleX, double angleY)
738{
739 if (!d->node) return;
740 if (!qobject_cast<KisLayer*>(d->node.data())) return;
741 if (!d->node->parent()) return;
742
743 d->image->shearNode(d->node, angleX, angleY, 0);
744 d->image->waitForDone();
745}
746
748{
749 if (!d->node) return QImage();
750 return d->node->createThumbnail(w, h);
751}
752
754{
755 if (!d->node) return QString();
756
757 KisLayer *layer = qobject_cast<KisLayer*>(d->node.data());
758
759 if (!layer) return QString();
760
761 KisPSDLayerStyleSP layerStyle = layer->layerStyle();
762
763 if (!layerStyle) return QString();
764
765 KisAslLayerStyleSerializer serializer;
766
767 serializer.setStyles(QVector<KisPSDLayerStyleSP>() << layerStyle);
768
769 return serializer.formPsdXmlDocument().toString();
770}
771
773{
774 if (!d->node) return false;
775
776 KisLayer *layer = qobject_cast<KisLayer*>(d->node.data());
777
778 if (!layer) return false;
779
780 QDomDocument aslDoc;
781
782 if (!aslDoc.setContent(asl)) {
783 qWarning() << "ASL string format is invalid!";
784 return false;
785 }
786
787 KisAslLayerStyleSerializer serializer;
788
789 serializer.registerPSDPattern(aslDoc);
790 serializer.readFromPSDXML(aslDoc);
791
792 if (serializer.styles().size() != 1) return false;
793
794 KisPSDLayerStyleSP newStyle = serializer.styles().first();
795 KUndo2Command *cmd = new KisSetLayerStyleCommand(layer, layer->layerStyle(), newStyle);
796
797 KisProcessingApplicator::runSingleCommandStroke(d->image, cmd);
798 d->image->waitForDone();
799
800 return true;
801}
802
803int Node::index() const
804{
805 if (!d->node) return -1;
806 if (!d->node->parent()) return -1;
807
808 return d->node->parent()->index(d->node);
809}
810
812{
813 if (!d->node) return QUuid();
814 return d->node->uuid();
815}
816
817KisPaintDeviceSP Node::paintDevice() const
818{
819 return d->node->paintDevice();
820}
821
822KisImageSP Node::image() const
823{
824 return d->image;
825}
826
827KisNodeSP Node::node() const
828{
829 return d->node;
830}
831
833{
834 // Taken from KisTool:nodePaintAbility().
835 KisMainWindow *mainWindow = KisPart::instance()->currentMainwindow();
836 KisCanvas2 *canvas = mainWindow->activeView()->canvasBase();
837 if (canvas->resourceManager()->resource(KoCanvasResource::CurrentPaintOpPreset).isNull()) {
838 return "UNPAINTABLE";
839 }
840
841 if (!d->node) {
842 return "UNPAINTABLE";
843 }
844
845 if (d->node->inherits("KisShapeLayer")) {
846 return "VECTOR";
847 }
848 if (d->node->inherits("KisCloneLayer")) {
849 return "CLONE";
850 }
851 if (d->node->paintDevice()) {
852
853 KisPaintOpPresetSP currentPaintOpPreset = canvas->resourceManager()->resource(KoCanvasResource::CurrentPaintOpPreset).value<KisPaintOpPresetSP>();
854 if (currentPaintOpPreset->paintOp().id() == "mypaintbrush") {
855 const KoColorSpace *colorSpace = d->node->paintDevice()->colorSpace();
856 if (colorSpace->colorModelId() != RGBAColorModelID) {
857 return "MYPAINTBRUSH_UNPAINTABLE";
858 }
859 }
860
861 return "PAINT";
862 }
863
864 return "UNPAINTABLE";
865}
866
867void Node::paintLine(const QPointF pointOne, const QPointF pointTwo, double pressureOne, double pressureTwo, const QString strokeStyle)
868{
869 if (paintAbility() != "PAINT") {
870 dbgScript << "Script attempted to use Node::paintLine() on an unpaintable node, ignoring.";
871 return;
872 }
873
874 KisPaintInformation pointOneInfo;
875 pointOneInfo.setPressure(pressureOne);
876 pointOneInfo.setPos(pointOne);
877
878 KisPaintInformation pointTwoInfo;
879 pointTwoInfo.setPressure(pressureTwo);
880 pointTwoInfo.setPos(pointTwo);
881
882 KisFigurePaintingToolHelper helper = PaintingResources::createHelper(d->image, node(), strokeStyle);
883 helper.paintLine(pointOneInfo, pointTwoInfo);
884}
885
886
887void Node::paintRectangle(const QRectF &rect, const QString strokeStyle, const QString fillStyle)
888{
889 if (paintAbility() != "PAINT") {
890 dbgScript << "Script attempted to use Node::paintRectangle() on an unpaintable node, ignoring.";
891 return;
892 }
893
894 // reference class where this stuff is being done. Maybe can use the "facade" like that does for setup?
895 // void KisFigurePaintingToolHelper::paintRect(const QRectF &rect)
896
897 KisFigurePaintingToolHelper helper = PaintingResources::createHelper(d->image, node(), strokeStyle, fillStyle);
898 helper.paintRect(rect);
899}
900
901
902void Node::paintPolygon(const QList<QPointF> listPoint, const QString strokeStyle, const QString fillStyle)
903{
904 if (paintAbility() != "PAINT") {
905 dbgScript << "Script attempted to use Node::paintPolygon() on an unpaintable node, ignoring.";
906 return;
907 }
908
909 // strategy needs points in vPointF format
910 QVector<QPointF> points = points.fromList(listPoint);
911 KisFigurePaintingToolHelper helper = PaintingResources::createHelper(d->image, node(), strokeStyle, fillStyle);
912 helper.paintPolygon(points);
913}
914
915
916void Node::paintEllipse(const QRectF &rect, const QString strokeStyle, const QString fillStyle)
917{
918 if (paintAbility() != "PAINT") {
919 dbgScript << "Script attempted to use Node::paintEllipse() on an unpaintable node, ignoring.";
920 return;
921 }
922
923 KisFigurePaintingToolHelper helper = PaintingResources::createHelper(d->image, node(), strokeStyle, fillStyle);
924 helper.paintEllipse(rect);
925}
926
927
928void Node::paintPath(const QPainterPath &path, const QString strokeStyle, const QString fillStyle)
929{
930 if (paintAbility() != "PAINT") {
931 dbgScript << "Script attempted to use Node::paintPath() on an unpaintable node, ignoring.";
932 return;
933 }
934
935 KisFigurePaintingToolHelper helper = PaintingResources::createHelper(d->image, node(), strokeStyle, fillStyle);
936 helper.paintPainterPath(path);
937}
A Channel represents a single channel in a Node.
Definition Channel.h:23
InfoObject wrap a properties map.
Definition InfoObject.h:20
static Krita * instance()
instance retrieve the singleton instance of the Application object.
Definition Krita.cpp:390
Node represents a layer or mask in a Krita image's Node hierarchy.
Definition Node.h:24
bool alphaLocked() const
alphaLocked checks whether the node is a paint layer and returns whether it is alpha locked
Definition Node.cpp:158
void setBlendingMode(QString value)
setBlendingMode set the blending mode of the node to the given value
Definition Node.cpp:185
QList< Node * > childNodes() const
childNodes
Definition Node.cpp:212
void scaleNode(QPointF origin, int width, int height, QString strategy)
scaleNode
Definition Node.cpp:697
void setAlphaLocked(bool value)
setAlphaLocked set the layer to value if the node is paint layer.
Definition Node.cpp:168
void paintPolygon(const QList< QPointF > points, const QString strokeStyle=PaintingResources::defaultStrokeStyle, const QString fillStyle=PaintingResources::defaultFillStyle)
paint a polygon on the canvas.
Definition Node.cpp:902
Node * mergeDown()
mergeDown merges the given node with the first visible node underneath this node in the layerstack.
Definition Node.cpp:685
void setCollapsed(bool collapsed)
Sets the state of the node to the value of.
Definition Node.cpp:391
QList< Channel * > channels() const
channels creates a list of Channel objects that can be used individually to show or hide certain chan...
Definition Node.cpp:197
QList< Node * > findChildNodes(const QString &name=QString(), bool recursive=false, bool partialMatch=false, const QString &type=QString(), int colorLabelIndex=0) const
findChildNodes
Definition Node.cpp:226
void enableAnimation() const
enableAnimation make the current layer animated, so it can have frames.
Definition Node.cpp:367
QString colorDepth() const
colorDepth A string describing the color depth of the image:
Definition Node.cpp:314
void setOpacity(int value)
set the opacity of the Node to the given value.
Definition Node.cpp:447
bool locked() const
locked checks whether the Node is locked.
Definition Node.cpp:411
QUuid uniqueId() const
uniqueId uniqueId of the node
Definition Node.cpp:811
QPoint position() const
position returns the position of the paint device of this node.
Definition Node.cpp:628
void setPinnedToTimeline(bool pinned) const
Sets whether or not node should be pinned to the Timeline Docker, regardless of selection activity.
Definition Node.cpp:373
void move(int x, int y)
move the pixels to the given x, y location in the image coordinate space.
Definition Node.cpp:621
void setChildNodes(QList< Node * > nodes)
setChildNodes this replaces the existing set of child nodes with the new set.
Definition Node.cpp:289
void paintEllipse(const QRectF &rect, const QString strokeStyle=PaintingResources::defaultStrokeStyle, const QString fillStyle=PaintingResources::defaultFillStyle)
paint an ellipse on the canvas.
Definition Node.cpp:916
QIcon icon() const
icon
Definition Node.cpp:508
bool visible() const
Check whether the current Node is visible in the layer stack.
Definition Node.cpp:517
QString colorModel() const
colorModel retrieve the current color model of this document:
Definition Node.cpp:321
void paintLine(const QPointF pointOne, const QPointF pointTwo, double pressureOne=1.0, double pressureTwo=1.0, const QString strokeStyle=PaintingResources::defaultStrokeStyle)
paint a line on the canvas.
Definition Node.cpp:867
bool hasKeyframeAtTime(int frameNumber)
Check to see if frame number on layer is a keyframe.
Definition Node.cpp:523
void shearNode(double angleX, double angleY)
shearNode perform a shear operation on this node.
Definition Node.cpp:737
bool setPixelData(QByteArray value, int x, int y, int w, int h)
setPixelData writes the given bytes, of which there must be enough, into the Node,...
Definition Node.cpp:602
bool setColorSpace(const QString &colorModel, const QString &colorDepth, const QString &colorProfile)
setColorSpace convert the node to the given colorspace
Definition Node.cpp:347
virtual QString type() const
type Krita has several types of nodes, split in layers and masks.
Definition Node.cpp:463
void paintRectangle(const QRectF &rect, const QString strokeStyle=PaintingResources::defaultStrokeStyle, const QString fillStyle=PaintingResources::defaultFillStyle)
paint a rectangle on the canvas.
Definition Node.cpp:887
void setLocked(bool value)
set the Locked flag to the give value
Definition Node.cpp:417
bool animated() const
Krita layers can be animated, i.e., have frames.
Definition Node.cpp:361
bool remove()
remove removes this node from its parent image.
Definition Node.cpp:634
bool inheritAlpha() const
inheritAlpha checks whether this node has the inherits alpha flag set
Definition Node.cpp:397
QByteArray pixelData(int x, int y, int w, int h) const
pixelData reads the given rectangle from the Node's paintable pixels, if those exist,...
Definition Node.cpp:546
void setName(QString name)
rename the Node to the given name
Definition Node.cpp:434
bool save(const QString &filename, double xRes, double yRes, const InfoObject &exportConfiguration, const QRect &exportRect=QRect())
save exports the given node with this filename.
Definition Node.cpp:653
void cropNode(int x, int y, int w, int h)
cropNode crop this layer.
Definition Node.cpp:726
QString paintAbility()
paintAbility can be used to determine whether this node can be painted on with the current brush pres...
Definition Node.cpp:832
void rotateNode(double radians)
rotateNode rotate this layer by the given radians.
Definition Node.cpp:716
int index() const
index the index of the node inside the parent
Definition Node.cpp:803
int opacity() const
return the opacity of the Node.
Definition Node.cpp:441
bool collapsed() const
returns the collapsed state of this node
Definition Node.cpp:385
bool setLayerStyleFromAsl(const QString &asl)
setLayerStyleFromAsl set a new layer style for this node.
Definition Node.cpp:772
int colorLabel() const
Sets a color label index associated to the layer.
Definition Node.cpp:302
QString blendingMode() const
Definition Node.cpp:178
QString layerStyleToAsl()
layerStyleToAsl retrieve the current layer's style in ASL format.
Definition Node.cpp:753
bool setColorProfile(const QString &colorProfile)
setColorProfile set the color profile of the image to the given profile.
Definition Node.cpp:336
bool addChildNode(Node *child, Node *above)
addChildNode adds the given node in the list of children.
Definition Node.cpp:265
QImage thumbnail(int w, int h)
thumbnail create a thumbnail of the given dimensions.
Definition Node.cpp:747
void paintPath(const QPainterPath &path, const QString strokeStyle=PaintingResources::defaultStrokeStyle, const QString fillStyle=PaintingResources::defaultFillStyle)
paint a custom path on the canvas.
Definition Node.cpp:928
bool hasExtents()
does the node have any content in it?
Definition Node.cpp:423
Node * duplicate()
duplicate returns a full copy of the current node.
Definition Node.cpp:647
void setInheritAlpha(bool value)
set the Inherit Alpha flag to the given value
Definition Node.cpp:404
bool removeChildNode(Node *child)
removeChildNode removes the given node from the list of children.
Definition Node.cpp:283
QString name() const
Definition Node.cpp:428
Node * parentNode() const
return the Node that is the parent of the current Node, or 0 if this is the root Node.
Definition Node.cpp:456
void setVisible(bool visible)
Set the visibility of the current node to.
Definition Node.cpp:539
QByteArray projectionPixelData(int x, int y, int w, int h) const
projectionPixelData reads the given rectangle from the Node's projection (that is,...
Definition Node.cpp:582
void setColorLabel(int index)
setColorLabel sets a color label index associated to the layer.
Definition Node.cpp:308
Node * clone() const
clone clone the current node.
Definition Node.cpp:150
QByteArray pixelDataAtTime(int x, int y, int w, int h, int time) const
pixelDataAtTime a basic function to get pixeldata from an animated node at a given time.
Definition Node.cpp:560
bool isPinnedToTimeline() const
Definition Node.cpp:379
QRect bounds() const
bounds return the exact bounds of the node's paint device
Definition Node.cpp:615
QString colorProfile() const
Definition Node.cpp:329
const char * constData() const const
char * data()
qsizetype length() const const
void resize(qsizetype newSize, char c)
ParseResult setContent(QAnyStringView text, ParseOptions options)
QList< T > fromList(const QList< T > &list)
QObject * parent() const const
T qobject_cast(QObject *object)
bool isEmpty() const const
bool isEmpty() const const
QByteArray toLatin1() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Jan 31 2025 12:06:53 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.