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

KDE's Doxygen guidelines are available online.