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
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
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
308void Node::setColorLabel(int index)
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
336bool Node::setColorProfile(const QString &colorProfile)
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
347bool Node::setColorSpace(const QString &colorModel, const QString &colorDepth, const QString &colorProfile)
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
391void Node::setCollapsed(bool collapsed)
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
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
539void Node::setVisible(bool visible)
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, 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, 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, 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, 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, strokeStyle, fillStyle);
936 helper.paintPainterPath(path);
937}
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: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
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 Nov 29 2024 11:53:16 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.