Krita Source Code Documentation
Loading...
Searching...
No Matches
Node.cpp
Go to the documentation of this file.
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 <iterator>
11
12#include <KoColorSpace.h>
15
16#include <KisDocument.h>
17#include <KisMimeDatabase.h>
18#include <KisPart.h>
19#include <kis_image.h>
20#include <kis_types.h>
21#include <kis_node.h>
22#include <kis_paint_layer.h>
23#include <kis_group_layer.h>
24#include <kis_file_layer.h>
26#include <kis_generator_layer.h>
27#include <kis_clone_layer.h>
28#include <kis_shape_layer.h>
31#include <kis_filter_mask.h>
32#include <kis_transform_mask.h>
33#include <kis_selection_mask.h>
35#include <kis_layer.h>
38#include <kis_filter_strategy.h>
45
47#include <kis_keyframe.h>
48#include "kis_selection.h"
49
50#include "InfoObject.h"
51#include "Krita.h"
52#include "Node.h"
53#include "Channel.h"
54#include "Filter.h"
55#include "Selection.h"
56
57#include "GroupLayer.h"
58#include "CloneLayer.h"
59#include "FilterLayer.h"
60#include "FillLayer.h"
61#include "FileLayer.h"
62#include "VectorLayer.h"
63#include "FilterMask.h"
64#include "SelectionMask.h"
65#include "TransparencyMask.h"
66#include "TransformMask.h"
67#include "ColorizeMask.h"
68
69#include "LibKisUtils.h"
70#include <kis_layer_utils.h>
71
72#include "PaintingResources.h"
73#include "KisMainWindow.h"
74#include "kis_canvas2.h"
78
79
85
86Node::Node(KisImageSP image, KisNodeSP node, QObject *parent)
87 : QObject(parent)
88 , d(new Private)
89{
90 d->image = image;
91 d->node = node;
92}
93
94Node *Node::createNode(KisImageSP image, KisNodeSP node, QObject *parent)
95{
96 if (node.isNull()) {
97 return 0;
98 }
99 if (node->inherits("KisGroupLayer")) {
100 return new GroupLayer(dynamic_cast<KisGroupLayer*>(node.data()));
101 }
102 else if (node->inherits("KisCloneLayer")) {
103 return new CloneLayer(dynamic_cast<KisCloneLayer*>(node.data()));
104 }
105 else if (node->inherits("KisFileLayer")) {
106 return new FileLayer(dynamic_cast<KisFileLayer*>(node.data()));
107 }
108 else if (node->inherits("KisAdjustmentLayer")) {
109 return new FilterLayer(dynamic_cast<KisAdjustmentLayer*>(node.data()));
110 }
111 else if (node->inherits("KisGeneratorLayer")) {
112 return new FillLayer(dynamic_cast<KisGeneratorLayer*>(node.data()));
113 }
114 else if (node->inherits("KisShapeLayer")) {
115 return new VectorLayer(dynamic_cast<KisShapeLayer*>(node.data()));
116 }
117 else if (node->inherits("KisFilterMask")) {
118 return new FilterMask(image, dynamic_cast<KisFilterMask*>(node.data()));
119 }
120 else if (node->inherits("KisSelectionMask")) {
121 return new SelectionMask(image, dynamic_cast<KisSelectionMask*>(node.data()));
122 }
123 else if (node->inherits("KisTransparencyMask")) {
124 return new TransparencyMask(image, dynamic_cast<KisTransparencyMask*>(node.data()));
125 }
126 else if (node->inherits("KisTransformMask")) {
127 return new TransformMask(image, dynamic_cast<KisTransformMask*>(node.data()));
128 }
129 else if (node->inherits("KisColorizeMask")) {
130 return new ColorizeMask(image, dynamic_cast<KisColorizeMask*>(node.data()));
131 }
132 else {
133 return new Node(image, node, parent);
134 }
135}
136
138{
139 delete d;
140}
141
142bool Node::operator==(const Node &other) const
143{
144 return (d->node == other.d->node
145 && d->image == other.d->image);
146}
147
148bool Node::operator!=(const Node &other) const
149{
150 return !(operator==(other));
151}
152
154{
155 KisNodeSP clone = d->node->clone();
157 return node;
158}
159
160
162{
163 if (!d->node) return false;
164 KisPaintLayerSP paintLayer = qobject_cast<KisPaintLayer*>(d->node.data());
165 if (paintLayer) {
166 return paintLayer->alphaLocked();
167 }
168 return false;
169}
170
172{
173 if (!d->node) return;
174 KisPaintLayerSP paintLayer = qobject_cast<KisPaintLayer*>(d->node.data());
175 if (paintLayer) {
176 paintLayer->setAlphaLocked(value);
177 }
178}
179
180
181QString Node::blendingMode() const
182{
183 if (!d->node) return QString();
184
185 return d->node->compositeOpId();
186}
187
189{
190 if (!d->node) return;
191
193 value);
194
196 d->image->waitForDone();
197}
198
199
201{
203
204 if (!d->node) return channels;
205 if (!d->node->inherits("KisLayer")) return channels;
206
207 Q_FOREACH(KoChannelInfo *info, d->node->colorSpace()->channels()) {
208 Channel *channel = new Channel(d->node, info);
209 channels << channel;
210 }
211
212 return channels;
213}
214
216{
217 QList<Node*> nodes;
218 if (d->node) {
219 KisNodeList nodeList;
220 int childCount = d->node->childCount();
221 for (int i = 0; i < childCount; ++i) {
222 nodeList << d->node->at(i);
223 }
224 nodes = LibKisUtils::createNodeList(nodeList, d->image);
225 }
226 return nodes;
227}
228
229QList<Node*> Node::findChildNodes(const QString &name, bool recursive, bool partialMatch, const QString &type, int colorLabelIndex) const
230{
231 if (!d->node) return {};
232
233 QList<Node*> nodes;
234 KisNodeList nodeList = KisLayerUtils::findNodesByName(d->node, name, recursive, partialMatch);
235
236 if (!type.isEmpty()) {
237 for (int i = nodeList.size() - 1; i >= 0; i--) {
238 if ((type == "paintlayer" && !qobject_cast<const KisPaintLayer*>(nodeList.at(i))) ||
239 (type == "vectorlayer" && !qobject_cast<const KisShapeLayer*>(nodeList.at(i))) ||
240 (type == "grouplayer" && !qobject_cast<const KisGroupLayer*>(nodeList.at(i))) ||
241 (type == "filelayer" && !qobject_cast<const KisFileLayer*>(nodeList.at(i))) ||
242 (type == "filterlayer" && !qobject_cast<const KisAdjustmentLayer*>(nodeList.at(i))) ||
243 (type == "filllayer" && !qobject_cast<const KisGeneratorLayer*>(nodeList.at(i))) ||
244 (type == "clonelayer" && !qobject_cast<const KisCloneLayer*>(nodeList.at(i))) ||
245 (type == "transformmask" && !qobject_cast<const KisTransformMask*>(nodeList.at(i))) ||
246 (type == "referenceimageslayer" && !qobject_cast<const KisReferenceImagesLayer*>(nodeList.at(i))) ||
247 (type == "transparencymask" && !qobject_cast<const KisTransformMask*>(nodeList.at(i))) ||
248 (type == "filtermask" && !qobject_cast<const KisFilterMask*>(nodeList.at(i))) ||
249 (type == "selectionmask" && !qobject_cast<const KisSelectionMask*>(nodeList.at(i))) ||
250 (type == "colorizemask" && !qobject_cast<const KisColorizeMask*>(nodeList.at(i)))
251 ) {
252 nodeList.removeAt(i);
253 }
254 }
255 }
256
257 if (colorLabelIndex > 0) {
258 for (int i = nodeList.size() - 1; i >= 0; i--) {
259 if (nodeList.at(i)->colorLabelIndex() != colorLabelIndex) {
260 nodeList.removeAt(i);
261 }
262 }
263 }
264
265 return LibKisUtils::createNodeList(nodeList, d->image);
266}
267
268bool Node::addChildNode(Node *child, Node *above)
269{
270 if (!d->node) return false;
271
272 KUndo2Command *cmd = 0;
273
274 if (above) {
275 cmd = new KisImageLayerAddCommand(d->image, child->node(), d->node, above->node());
276 } else {
277 cmd = new KisImageLayerAddCommand(d->image, child->node(), d->node, d->node->childCount());
278 }
279
281 d->image->waitForDone();
282
283 return true;
284}
285
287{
288 if (!d->node) return false;
289 return child->remove();
290}
291
293{
294 if (!d->node) return;
295 while (d->node->firstChild()) {
297 }
298 Q_FOREACH(Node *node, nodes) {
299 d->image->addNode(node->node(), d->node);
300 }
301}
302
304{
305 if (!d->node) return 0;
306 return d->node->colorLabelIndex();
307}
308
309void Node::setColorLabel(int index)
310{
311 if (!d->node) return;
313}
314
315QString Node::colorDepth() const
316{
317 if (!d->node) return "";
318 if (!d->node->projection()) return d->node->colorSpace()->colorDepthId().id();
319 return d->node->projection()->colorSpace()->colorDepthId().id();
320}
321
322QString Node::colorModel() const
323{
324 if (!d->node) return "";
325 if (!d->node->projection()) return d->node->colorSpace()->colorModelId().id();
326 return d->node->projection()->colorSpace()->colorModelId().id();
327}
328
329
330QString Node::colorProfile() const
331{
332 if (!d->node) return "";
333 if (!d->node->projection()) return d->node->colorSpace()->profile()->name();
334 return d->node->projection()->colorSpace()->profile()->name();
335}
336
337bool Node::setColorProfile(const QString &colorProfile)
338{
339 if (!d->node) return false;
340 if (!d->node->inherits("KisLayer")) return false;
341 KisLayer *layer = qobject_cast<KisLayer*>(d->node.data());
343 bool result = d->image->assignLayerProfile(layer, profile);
344 d->image->waitForDone();
345 return result;
346}
347
348bool Node::setColorSpace(const QString &colorModel, const QString &colorDepth, const QString &colorProfile)
349{
350 if (!d->node) return false;
351 if (!d->node->inherits("KisLayer")) return false;
353 if (!profile) return false;
356 profile);
358 d->image->waitForDone();
359 return true;
360}
361
362bool Node::animated() const
363{
364 if (!d->node) return false;
365 return d->node->isAnimated();
366}
367
369{
370 if (!d->node) return;
372}
373
374void Node::setPinnedToTimeline(bool pinned) const
375{
376 if (!d->node) return;
377 d->node->setPinnedToTimeline(pinned);
378}
379
381{
382 if (!d->node) return false;
383 return d->node->isPinnedToTimeline();
384}
385
386bool Node::collapsed() const
387{
388 if (!d->node) return false;
389 return d->node->collapsed();
390}
391
392void Node::setCollapsed(bool collapsed)
393{
394 if (!d->node) return;
396}
397
399{
400 if (!d->node) return false;
401 if (!d->node->inherits("KisLayer")) return false;
402 return qobject_cast<const KisLayer*>(d->node)->alphaChannelDisabled();
403}
404
406{
407 if (!d->node) return;
408 if (!d->node->inherits("KisLayer")) return;
409 const_cast<KisLayer*>(qobject_cast<const KisLayer*>(d->node))->disableAlphaChannel(value);
410}
411
412bool Node::locked() const
413{
414 if (!d->node) return false;
415 return d->node->userLocked();
416}
417
419{
420 if (!d->node) return;
422}
423
425{
426 return !d->node->extent().isEmpty();
427}
428
429QString Node::name() const
430{
431 if (!d->node) return QString();
432 return d->node->name();
433}
434
435void Node::setName(QString name)
436{
437 if (!d->node) return;
438 d->node->setName(name);
439}
440
441
442int Node::opacity() const
443{
444 if (!d->node) return 0;
445 return d->node->opacity();
446}
447
449{
450 if (!d->node) return;
451 if (value < 0) value = 0;
452 if (value > 255) value = 255;
454}
455
456
458{
459 if (!d->node) return 0;
460 if (!d->node->parent()) return 0;
461 return Node::createNode(d->image, d->node->parent());
462}
463
464QString Node::type() const
465{
466 if (!d->node) return QString();
467 if (qobject_cast<const KisPaintLayer*>(d->node)) {
468 return "paintlayer";
469 }
470 else if (qobject_cast<const KisGroupLayer*>(d->node)) {
471 return "grouplayer";
472 }
473 if (qobject_cast<const KisFileLayer*>(d->node)) {
474 return "filelayer";
475 }
476 if (qobject_cast<const KisAdjustmentLayer*>(d->node)) {
477 return "filterlayer";
478 }
479 if (qobject_cast<const KisGeneratorLayer*>(d->node)) {
480 return "filllayer";
481 }
482 if (qobject_cast<const KisCloneLayer*>(d->node)) {
483 return "clonelayer";
484 }
485 if (qobject_cast<const KisReferenceImagesLayer*>(d->node)) {
486 return "referenceimageslayer";
487 }
488 if (qobject_cast<const KisShapeLayer*>(d->node)) {
489 return "vectorlayer";
490 }
491 if (qobject_cast<const KisTransparencyMask*>(d->node)) {
492 return "transparencymask";
493 }
494 if (qobject_cast<const KisFilterMask*>(d->node)) {
495 return "filtermask";
496 }
497 if (qobject_cast<const KisTransformMask*>(d->node)) {
498 return "transformmask";
499 }
500 if (qobject_cast<const KisSelectionMask*>(d->node)) {
501 return "selectionmask";
502 }
503 if (qobject_cast<const KisColorizeMask*>(d->node)) {
504 return "colorizemask";
505 }
506 return QString();
507}
508
509QIcon Node::icon() const
510{
511 QIcon icon;
512 if (d->node) {
513 icon = d->node->icon();
514 }
515 return icon;
516}
517
518bool Node::visible() const
519{
520 if (!d->node) return false;
521 return d->node->visible();
522}
523
524bool Node::hasKeyframeAtTime(int frameNumber)
525{
526 if (!d->node || !d->node->isAnimated()) return false;
527
529 if (!rkc) return false;
530
531 KisKeyframeSP currentKeyframe = rkc->keyframeAt(frameNumber);
532
533 if (!currentKeyframe) {
534 return false;
535 }
536
537 return true;
538}
539
540void Node::setVisible(bool visible)
541{
542 if (!d->node) return;
544}
545
546
547QByteArray Node::pixelData(int x, int y, int w, int h) const
548{
549 QByteArray ba;
550
551 if (!d->node) return ba;
552
554 if (!dev) return ba;
555
556 ba.resize(w * h * dev->pixelSize());
557 dev->readBytes(reinterpret_cast<quint8*>(ba.data()), x, y, w, h);
558 return ba;
559}
560
561QByteArray Node::pixelDataAtTime(int x, int y, int w, int h, int time) const
562{
563 QByteArray ba;
564
565 if (!d->node || !d->node->isAnimated()) return ba;
566
567 //
569 if (!rkc) return ba;
571 if (!frame) return ba;
573 if (!dev) return ba;
574
575 frame->writeFrameToDevice(dev);
576
577 ba.resize(w * h * dev->pixelSize());
578 dev->readBytes(reinterpret_cast<quint8*>(ba.data()), x, y, w, h);
579 return ba;
580}
581
582
583QByteArray Node::projectionPixelData(int x, int y, int w, int h) const
584{
585 QByteArray ba;
586
587 if (!d->node) return ba;
588
590 if (const KisColorizeMask *mask = qobject_cast<const KisColorizeMask*>(d->node)) {
591
592 dev = mask->coloringProjection();
593 } else {
594 dev = d->node->projection();
595 }
596 if (!dev) return ba;
597
598 ba.resize(w * h * dev->pixelSize());
599 dev->readBytes(reinterpret_cast<quint8*>(ba.data()), x, y, w, h);
600 return ba;
601}
602
603bool Node::setPixelData(QByteArray value, int x, int y, int w, int h)
604{
605 if (!d->node) return false;
607 if (!dev) return false;
608 if (value.length() < w * h * (int)dev->colorSpace()->pixelSize()) {
609 qWarning() << "Node::setPixelData: not enough data to write to the paint device";
610 return false;
611 }
612 dev->writeBytes((const quint8*)value.constData(), x, y, w, h);
613 return true;
614}
615
616QRect Node::bounds() const
617{
618 if (!d->node) return QRect();
619 return d->node->exactBounds();
620}
621
622void Node::move(int x, int y)
623{
624 if (!d->node) return;
625 d->node->setX(x);
626 d->node->setY(y);
627}
628
629QPoint Node::position() const
630{
631 if (!d->node) return QPoint();
632 return QPoint(d->node->x(), d->node->y());
633}
634
636{
637 if (!d->node) return false;
638 if (!d->node->parent()) return false;
639
641
643 d->image->waitForDone();
644
645 return true;
646}
647
649{
650 if (!d->node) return 0;
651 return Node::createNode(d->image, d->node->clone());
652}
653
654bool Node::save(const QString &filename, double xRes, double yRes, const InfoObject &exportConfiguration, const QRect &exportRect)
655{
656 if (!d->node) return false;
657 if (filename.isEmpty()) return false;
658
659 KisPaintDeviceSP projection = d->node->projection();
660 QRect bounds = (exportRect.isEmpty())? d->node->exactBounds() : exportRect;
661
662 QString mimeType = KisMimeDatabase::mimeTypeForFile(filename, false);
663 QScopedPointer<KisDocument> doc(KisPart::instance()->createDocument());
664
665 KisImageSP dst = new KisImage(doc->createUndoStore(),
666 bounds.right(),
667 bounds.bottom(),
668 projection->compositionSourceColorSpace(),
669 d->node->name());
670 dst->setResolution(xRes, yRes);
671 doc->setFileBatchMode(Krita::instance()->batchmode());
672 doc->setCurrentImage(dst);
673 KisPaintLayer* paintLayer = new KisPaintLayer(dst, "paint device", d->node->opacity());
674 paintLayer->paintDevice()->makeCloneFrom(projection, bounds);
675 dst->addNode(paintLayer, dst->rootLayer(), KisLayerSP(0));
676 dst->cropImage(bounds);
677 dst->initialRefreshGraph();
678
679 bool r = doc->exportDocumentSync(filename, mimeType.toLatin1(), exportConfiguration.configuration());
680 if (!r) {
681 qWarning() << doc->errorMessage();
682 }
683 return r;
684}
685
687{
688 if (!d->node) return 0;
689 if (!qobject_cast<KisLayer*>(d->node.data())) return 0;
690 if (!d->node->prevSibling()) return 0;
691
692 d->image->mergeDown(qobject_cast<KisLayer*>(d->node.data()), KisMetaData::MergeStrategyRegistry::instance()->get("Drop"));
693 d->image->waitForDone();
694
696}
697
698void Node::scaleNode(QPointF origin, int width, int height, QString strategy)
699{
700 if (!d->node) return;
701 if (!qobject_cast<KisLayer*>(d->node.data())) return;
702 if (!d->node->parent()) return;
703
704 KisFilterStrategy *actualStrategy = KisFilterStrategyRegistry::instance()->get(strategy);
705 if (!actualStrategy) actualStrategy = KisFilterStrategyRegistry::instance()->get("Bicubic");
706
707 const QRect bounds(d->node->exactBounds());
708
710 origin,
711 qreal(width) / bounds.width(),
712 qreal(height) / bounds.height(),
713 actualStrategy, 0);
714 d->image->waitForDone();
715}
716
717void Node::rotateNode(double radians)
718{
719 if (!d->node) return;
720 if (!qobject_cast<KisLayer*>(d->node.data())) return;
721 if (!d->node->parent()) return;
722
723 d->image->rotateNode(d->node, radians, 0);
724 d->image->waitForDone();
725}
726
727void Node::cropNode(int x, int y, int w, int h)
728{
729 if (!d->node) return;
730 if (!qobject_cast<KisLayer*>(d->node.data())) return;
731 if (!d->node->parent()) return;
732
733 QRect rect = QRect(x, y, w, h);
734 d->image->cropNode(d->node, rect);
735 d->image->waitForDone();
736}
737
738void Node::shearNode(double angleX, double angleY)
739{
740 if (!d->node) return;
741 if (!qobject_cast<KisLayer*>(d->node.data())) return;
742 if (!d->node->parent()) return;
743
744 d->image->shearNode(d->node, angleX, angleY, 0);
745 d->image->waitForDone();
746}
747
748QImage Node::thumbnail(int w, int h)
749{
750 if (!d->node) return QImage();
751 return d->node->createThumbnail(w, h);
752}
753
755{
756 if (!d->node) return QString();
757
758 KisLayer *layer = qobject_cast<KisLayer*>(d->node.data());
759
760 if (!layer) return QString();
761
762 KisPSDLayerStyleSP layerStyle = layer->layerStyle();
763
764 if (!layerStyle) return QString();
765
767
768 serializer.setStyles(QVector<KisPSDLayerStyleSP>() << layerStyle);
769
770 return serializer.formPsdXmlDocument().toString();
771}
772
773bool Node::setLayerStyleFromAsl(const QString &asl)
774{
775 if (!d->node) return false;
776
777 KisLayer *layer = qobject_cast<KisLayer*>(d->node.data());
778
779 if (!layer) return false;
780
781 QDomDocument aslDoc;
782
783 if (!aslDoc.setContent(asl)) {
784 qWarning() << "ASL string format is invalid!";
785 return false;
786 }
787
789
790 serializer.registerPSDPattern(aslDoc);
791 serializer.readFromPSDXML(aslDoc);
792
793 if (serializer.styles().size() != 1) return false;
794
795 KisPSDLayerStyleSP newStyle = serializer.styles().first();
796 KUndo2Command *cmd = new KisSetLayerStyleCommand(layer, layer->layerStyle(), newStyle);
797
799 d->image->waitForDone();
800
801 return true;
802}
803
804int Node::index() const
805{
806 if (!d->node) return -1;
807 if (!d->node->parent()) return -1;
808
809 return d->node->parent()->index(d->node);
810}
811
812QUuid Node::uniqueId() const
813{
814 if (!d->node) return QUuid();
815 return d->node->uuid();
816}
817
819{
820 return d->node->paintDevice();
821}
822
824{
825 return d->image;
826}
827
829{
830 return d->node;
831}
832
834{
835 // Taken from KisTool:nodePaintAbility().
837 KisCanvas2 *canvas = mainWindow->activeView()->canvasBase();
838 if (canvas->resourceManager()->resource(KoCanvasResource::CurrentPaintOpPreset).isNull()) {
839 return "UNPAINTABLE";
840 }
841
842 if (!d->node) {
843 return "UNPAINTABLE";
844 }
845
846 if (d->node->inherits("KisShapeLayer")) {
847 return "VECTOR";
848 }
849 if (d->node->inherits("KisCloneLayer")) {
850 return "CLONE";
851 }
852 if (d->node->paintDevice()) {
853
854 KisPaintOpPresetSP currentPaintOpPreset = canvas->resourceManager()->resource(KoCanvasResource::CurrentPaintOpPreset).value<KisPaintOpPresetSP>();
855 if (currentPaintOpPreset->paintOp().id() == "mypaintbrush") {
856 const KoColorSpace *colorSpace = d->node->paintDevice()->colorSpace();
857 if (colorSpace->colorModelId() != RGBAColorModelID) {
858 return "MYPAINTBRUSH_UNPAINTABLE";
859 }
860 }
861
862 return "PAINT";
863 }
864
865 return "UNPAINTABLE";
866}
867
868void Node::paintLine(const QPointF pointOne, const QPointF pointTwo, double pressureOne, double pressureTwo, const QString strokeStyle)
869{
870 if (paintAbility() != "PAINT") {
871 dbgScript << "Script attempted to use Node::paintLine() on an unpaintable node, ignoring.";
872 return;
873 }
874
875 KisPaintInformation pointOneInfo;
876 pointOneInfo.setPressure(pressureOne);
877 pointOneInfo.setPos(pointOne);
878
879 KisPaintInformation pointTwoInfo;
880 pointTwoInfo.setPressure(pressureTwo);
881 pointTwoInfo.setPos(pointTwo);
882
884 helper.paintLine(pointOneInfo, pointTwoInfo);
885}
886
887void Node::paintPolylineStroke(const QList<StrokePoint> &points, const QString strokeStyle)
888{
889 if (paintAbility() != "PAINT") {
890 dbgScript << "Script attempted to use Node::paintPolylineStroke() on an unpaintable node, ignoring.";
891 return;
892 }
893
894 if (points.isEmpty()) {
895 return;
896 }
897
898 auto paintInformation = [] (const StrokePoint &point) {
899 return KisPaintInformation(point.position(),
900 point.pressure(),
901 point.xTilt(),
902 point.yTilt(),
903 point.rotation(),
904 point.tangentialPressure(),
905 1.0,
906 point.time(),
907 point.speed());
908 };
909
911
912 KisPaintInformation previous = paintInformation(points.first());
913 if (points.size() == 1) {
914 helper.paintLine(previous, previous);
915 return;
916 }
917
918 for (auto it = std::next(points.cbegin()); it != points.cend(); ++it) {
919 KisPaintInformation current = paintInformation(*it);
920 helper.paintLine(previous, current);
921 previous = current;
922 }
923}
924
925
926void Node::paintRectangle(const QRectF &rect, const QString strokeStyle, const QString fillStyle)
927{
928 if (paintAbility() != "PAINT") {
929 dbgScript << "Script attempted to use Node::paintRectangle() on an unpaintable node, ignoring.";
930 return;
931 }
932
933 // reference class where this stuff is being done. Maybe can use the "facade" like that does for setup?
934 // void KisFigurePaintingToolHelper::paintRect(const QRectF &rect)
935
936 KisFigurePaintingToolHelper helper = PaintingResources::createHelper(d->image, node(), strokeStyle, fillStyle);
937 helper.paintRect(rect);
938}
939
940
941void Node::paintPolygon(const QList<QPointF> listPoint, const QString strokeStyle, const QString fillStyle)
942{
943 if (paintAbility() != "PAINT") {
944 dbgScript << "Script attempted to use Node::paintPolygon() on an unpaintable node, ignoring.";
945 return;
946 }
947
948 // strategy needs points in vPointF format
949 QVector<QPointF> points = points.fromList(listPoint);
950 KisFigurePaintingToolHelper helper = PaintingResources::createHelper(d->image, node(), strokeStyle, fillStyle);
951 helper.paintPolygon(points);
952}
953
954
955void Node::paintEllipse(const QRectF &rect, const QString strokeStyle, const QString fillStyle)
956{
957 if (paintAbility() != "PAINT") {
958 dbgScript << "Script attempted to use Node::paintEllipse() on an unpaintable node, ignoring.";
959 return;
960 }
961
962 KisFigurePaintingToolHelper helper = PaintingResources::createHelper(d->image, node(), strokeStyle, fillStyle);
963 helper.paintEllipse(rect);
964}
965
966
967void Node::paintPath(const QPainterPath &path, const QString strokeStyle, const QString fillStyle)
968{
969 if (paintAbility() != "PAINT") {
970 dbgScript << "Script attempted to use Node::paintPath() on an unpaintable node, ignoring.";
971 return;
972 }
973
974 KisFigurePaintingToolHelper helper = PaintingResources::createHelper(d->image, node(), strokeStyle, fillStyle);
975 helper.paintPainterPath(path);
976}
float value(const T *src, size_t ch)
const KoID RGBAColorModelID("RGBA", ki18n("RGB/Alpha"))
KisPropertiesConfigurationSP configuration() const
configuration gives access to the internal configuration object. Must be used internally in libkis
QVector< KisPSDLayerStyleSP > styles() const
void readFromPSDXML(const QDomDocument &doc)
void registerPSDPattern(const QDomDocument &doc)
void setStyles(const QVector< KisPSDLayerStyleSP > &styles)
void paintPainterPath(const QPainterPath &path)
void paintLine(const KisPaintInformation &pi0, const KisPaintInformation &pi1)
The KisFileLayer class loads a particular file as a layer into the layer stack.
static KisFilterStrategyRegistry * instance()
The command for adding a layer.
void scaleNode(KisNodeSP node, const QPointF &center, qreal scaleX, qreal scaleY, KisFilterStrategy *filterStrategy, KisSelectionSP selection)
start asynchronous operation on scaling a subtree of nodes starting at node
void waitForDone()
KisGroupLayerSP rootLayer() const
void cropNode(KisNodeSP node, const QRect &newRect, const bool activeFrameOnly=false)
start asynchronous operation on cropping a subtree of nodes starting at node
void shearNode(KisNodeSP node, double angleX, double angleY, KisSelectionSP selection)
start asynchronous operation on shearing a subtree of nodes starting at node
void cropImage(const QRect &newRect)
start asynchronous operation on cropping the image
Definition kis_image.cc:896
bool assignLayerProfile(KisNodeSP node, const KoColorProfile *profile)
void initialRefreshGraph()
void mergeDown(KisLayerSP l, const KisMetaData::MergeStrategy *strategy)
void convertLayerColorSpace(KisNodeSP node, const KoColorSpace *dstColorSpace, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags)
void setResolution(double xres, double yres)
void rotateNode(KisNodeSP node, double radians, KisSelectionSP selection)
start asynchronous operation on rotating a subtree of nodes starting at node
static const KoID Raster
KisKeyframeSP keyframeAt(int time) const
Get a keyframe at specified time. Used primarily when the value of a given keyframe is needed.
Main window for Krita.
QPointer< KisView > activeView
static QString mimeTypeForFile(const QString &file, bool checkExistingFiles=true)
Find the mimetype for the given filename. The filename must include a suffix.
The command for setting the composite op.
quint32 pixelSize() const
virtual const KoColorSpace * compositionSourceColorSpace() const
const KoColorSpace * colorSpace() const
void readBytes(quint8 *data, qint32 x, qint32 y, qint32 w, qint32 h) const
void makeCloneFrom(KisPaintDeviceSP src, const QRect &rect)
void writeBytes(const quint8 *data, qint32 x, qint32 y, qint32 w, qint32 h)
void setPos(const QPointF &p)
void setPressure(qreal p)
Set the pressure.
static KisPart * instance()
Definition KisPart.cpp:130
KisMainWindow * currentMainwindow() const
Definition KisPart.cpp:457
static void runSingleCommandStroke(KisImageSP image, KUndo2Command *cmd, KisStrokeJobData::Sequentiality sequentiality=KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::Exclusivity exclusivity=KisStrokeJobData::NORMAL)
runSingleCommandStroke creates a stroke and runs cmd in it. The text() field of cmd is used as a titl...
The KisRasterKeyframeChannel is a concrete KisKeyframeChannel subclass that stores and manages KisRas...
The KisRasterKeyframe class is a concrete subclass of KisKeyframe that wraps a physical raster image ...
bool isNull() const
QPointer< KoCanvasResourceProvider > resourceManager
virtual quint32 pixelSize() const =0
QList< KoChannelInfo * > channels
virtual KoID colorModelId() const =0
virtual KoID colorDepthId() const =0
virtual const KoColorProfile * profile() const =0
T get(const QString &id) const
QString id() const
Definition KoID.cpp:63
static Krita * instance()
instance retrieve the singleton instance of the Application object.
Definition Krita.cpp:396
Definition Node.h:25
bool alphaLocked() const
alphaLocked checks whether the node is a paint layer and returns whether it is alpha locked
Definition Node.cpp:161
void setBlendingMode(QString value)
setBlendingMode set the blending mode of the node to the given value
Definition Node.cpp:188
QList< Node * > childNodes() const
childNodes
Definition Node.cpp:215
void scaleNode(QPointF origin, int width, int height, QString strategy)
scaleNode
Definition Node.cpp:698
void setAlphaLocked(bool value)
setAlphaLocked set the layer to value if the node is paint layer.
Definition Node.cpp:171
void paintPolygon(const QList< QPointF > points, const QString strokeStyle=PaintingResources::defaultStrokeStyle, const QString fillStyle=PaintingResources::defaultFillStyle)
paint a polygon on the canvas. Uses current brush preset
Definition Node.cpp:941
Node * mergeDown()
mergeDown merges the given node with the first visible node underneath this node in the layerstack....
Definition Node.cpp:686
bool operator==(const Node &other) const
Definition Node.cpp:142
void setCollapsed(bool collapsed)
Definition Node.cpp:392
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:200
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:229
void enableAnimation() const
enableAnimation make the current layer animated, so it can have frames.
Definition Node.cpp:368
Node(KisImageSP image, KisNodeSP node, QObject *parent=0)
Definition Node.cpp:86
QString colorDepth() const
Definition Node.cpp:315
void setOpacity(int value)
Definition Node.cpp:448
bool locked() const
locked checks whether the Node is locked. A locked node cannot be changed.
Definition Node.cpp:412
QUuid uniqueId() const
uniqueId uniqueId of the node
Definition Node.cpp:812
QPoint position() const
position returns the position of the paint device of this node. The position is always 0,...
Definition Node.cpp:629
void setPinnedToTimeline(bool pinned) const
Sets whether or not node should be pinned to the Timeline Docker, regardless of selection activity.
Definition Node.cpp:374
void move(int x, int y)
Definition Node.cpp:622
void setChildNodes(QList< Node * > nodes)
setChildNodes this replaces the existing set of child nodes with the new set.
Definition Node.cpp:292
void paintEllipse(const QRectF &rect, const QString strokeStyle=PaintingResources::defaultStrokeStyle, const QString fillStyle=PaintingResources::defaultFillStyle)
paint an ellipse on the canvas. Uses current brush preset
Definition Node.cpp:955
QIcon icon() const
icon
Definition Node.cpp:509
bool visible() const
Definition Node.cpp:518
QString colorModel() const
colorModel retrieve the current color model of this document:
Definition Node.cpp:322
Private *const d
Definition Node.h:737
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. Uses current brush preset
Definition Node.cpp:868
bool operator!=(const Node &other) const
Definition Node.cpp:148
bool hasKeyframeAtTime(int frameNumber)
Definition Node.cpp:524
void shearNode(double angleX, double angleY)
shearNode perform a shear operation on this node.
Definition Node.cpp:738
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:603
friend class FilterMask
Definition Node.h:719
friend class TransparencyMask
Definition Node.h:721
KisNodeSP node() const
Definition Node.cpp:828
bool setColorSpace(const QString &colorModel, const QString &colorDepth, const QString &colorProfile)
setColorSpace convert the node to the given colorspace
Definition Node.cpp:348
virtual QString type() const
type Krita has several types of nodes, split in layers and masks. Group layers can contain other laye...
Definition Node.cpp:464
~Node() override
Definition Node.cpp:137
void paintRectangle(const QRectF &rect, const QString strokeStyle=PaintingResources::defaultStrokeStyle, const QString fillStyle=PaintingResources::defaultFillStyle)
paint a rectangle on the canvas. Uses current brush preset
Definition Node.cpp:926
void setLocked(bool value)
Definition Node.cpp:418
bool animated() const
Krita layers can be animated, i.e., have frames.
Definition Node.cpp:362
bool remove()
remove removes this node from its parent image.
Definition Node.cpp:635
bool inheritAlpha() const
inheritAlpha checks whether this node has the inherits alpha flag set
Definition Node.cpp:398
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:547
void setName(QString name)
Definition Node.cpp:435
KisImageSP image() const
Definition Node.cpp:823
friend class SelectionMask
Definition Node.h:720
bool save(const QString &filename, double xRes, double yRes, const InfoObject &exportConfiguration, const QRect &exportRect=QRect())
save exports the given node with this filename. The extension of the filename determines the filetype...
Definition Node.cpp:654
void cropNode(int x, int y, int w, int h)
cropNode crop this layer.
Definition Node.cpp:727
QString paintAbility()
paintAbility can be used to determine whether this node can be painted on with the current brush pres...
Definition Node.cpp:833
static Node * createNode(KisImageSP image, KisNodeSP node, QObject *parent=0)
Definition Node.cpp:94
void rotateNode(double radians)
rotateNode rotate this layer by the given radians.
Definition Node.cpp:717
int index() const
index the index of the node inside the parent
Definition Node.cpp:804
int opacity() const
Definition Node.cpp:442
bool collapsed() const
Definition Node.cpp:386
bool setLayerStyleFromAsl(const QString &asl)
setLayerStyleFromAsl set a new layer style for this node.
Definition Node.cpp:773
int colorLabel() const
Definition Node.cpp:303
QString blendingMode() const
Definition Node.cpp:181
friend class FilterLayer
Definition Node.h:716
void paintPolylineStroke(const QList< StrokePoint > &points, const QString strokeStyle=PaintingResources::defaultStrokeStyle)
paintPolylineStroke paint one continuous brush stroke with complete input information for every suppl...
Definition Node.cpp:887
QString layerStyleToAsl()
layerStyleToAsl retrieve the current layer's style in ASL format.
Definition Node.cpp:754
friend class FileLayer
Definition Node.h:715
friend class VectorLayer
Definition Node.h:718
bool setColorProfile(const QString &colorProfile)
setColorProfile set the color profile of the image to the given profile. The profile has to be regist...
Definition Node.cpp:337
bool addChildNode(Node *child, Node *above)
addChildNode adds the given node in the list of children.
Definition Node.cpp:268
QImage thumbnail(int w, int h)
thumbnail create a thumbnail of the given dimensions. The thumbnail is sized according to the layer d...
Definition Node.cpp:748
void paintPath(const QPainterPath &path, const QString strokeStyle=PaintingResources::defaultStrokeStyle, const QString fillStyle=PaintingResources::defaultFillStyle)
paint a custom path on the canvas. Uses current brush preset
Definition Node.cpp:967
bool hasExtents()
does the node have any content in it?
Definition Node.cpp:424
friend class FillLayer
Definition Node.h:717
KisPaintDeviceSP paintDevice() const
paintDevice gives access to the internal paint device of this Node
Definition Node.cpp:818
Node * duplicate()
duplicate returns a full copy of the current node. The node is not inserted in the graphic
Definition Node.cpp:648
void setInheritAlpha(bool value)
Definition Node.cpp:405
friend class TransformMask
Definition Node.h:722
bool removeChildNode(Node *child)
removeChildNode removes the given node from the list of children.
Definition Node.cpp:286
QString name() const
Definition Node.cpp:429
Node * parentNode() const
Definition Node.cpp:457
void setVisible(bool visible)
Definition Node.cpp:540
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:583
void setColorLabel(int index)
setColorLabel sets a color label index associated to the layer. The actual color of the label and the...
Definition Node.cpp:309
friend class CloneLayer
Definition Node.h:724
Node * clone() const
clone clone the current node. The node is not associated with any image.
Definition Node.cpp:153
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:561
bool isPinnedToTimeline() const
Definition Node.cpp:380
QRect bounds() const
bounds return the exact bounds of the node's paint device
Definition Node.cpp:616
QString colorProfile() const
Definition Node.cpp:330
friend class GroupLayer
Definition Node.h:714
friend class ColorizeMask
Definition Node.h:723
#define bounds(x, a, b)
#define dbgScript
Definition kis_debug.h:60
KisDocument * createDocument(QList< KisNodeSP > nodes, KisImageSP srcImage, const QRect &copiedBounds)
QList< KisNodeSP > findNodesByName(KisNodeSP root, const QString &name, bool recursive, bool partialMatch)
QList< Node * > createNodeList(KisNodeList kisnodes, KisImageWSP image)
KisFigurePaintingToolHelper createHelper(KisImageWSP image, KisNodeSP node, const QString strokeStyle=defaultStrokeStyle, const QString fillStyle=defaultFillStyle)
void setPinnedToTimeline(bool pinned)
virtual void setUserLocked(bool l)
QUuid uuid() const
virtual KisPaintDeviceSP projection() const =0
const QString & compositeOpId() const
virtual qint32 y() const
void setOpacity(quint8 val)
virtual void setVisible(bool visible, bool loading=false)
bool isPinnedToTimeline() const
KisKeyframeChannel * getKeyframeChannel(const QString &id, bool create)
virtual QRect exactBounds() const
virtual void setX(qint32)
virtual void setY(qint32)
void setColorLabelIndex(int index)
void setName(const QString &name)
void setCollapsed(bool collapsed)
virtual const KoColorSpace * colorSpace() const =0
virtual qint32 x() const
int colorLabelIndex() const
virtual QRect extent() const
bool userLocked() const
bool isAnimated() const
virtual QImage createThumbnail(qint32 w, qint32 h, Qt::AspectRatioMode aspectRatioMode=Qt::IgnoreAspectRatio, KisThumbnailBoundsMode boundsMode=KisThumbnailBoundsMode::Precise)
virtual KisPaintDeviceSP paintDevice() const =0
QString name() const
quint8 opacity() const
virtual bool visible(bool recursive=false) const
void enableAnimation()
virtual QIcon icon() const
KisPSDLayerStyleSP layerStyle
Definition kis_layer.cc:171
bool addNode(KisNodeSP node, KisNodeSP parent=KisNodeSP(), KisNodeAdditionFlags flags=KisNodeAdditionFlag::None)
bool removeNode(KisNodeSP node)
KisNodeSP prevSibling() const
Definition kis_node.cpp:402
KisNodeSP firstChild() const
Definition kis_node.cpp:361
int index(const KisNodeSP node) const
Definition kis_node.cpp:432
virtual KisNodeSP clone() const =0
quint32 childCount() const
Definition kis_node.cpp:414
KisNodeWSP parent
Definition kis_node.cpp:86
KisNodeSP at(quint32 index) const
Definition kis_node.cpp:421
bool alphaLocked() const
KisPaintDeviceSP paintDevice
void setAlphaLocked(bool lock)
const KoColorProfile * profileByName(const QString &name) const
const KoColorSpace * colorSpace(const QString &colorModelId, const QString &colorDepthId, const KoColorProfile *profile)
static KoColorSpaceRegistry * instance()
KisImageWSP image
Definition Node.cpp:82
KisNodeSP node
Definition Node.cpp:83