Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_kra_loader.cpp
Go to the documentation of this file.
1/* This file is part of the KDE project
2 * SPDX-FileCopyrightText: 2007 Boudewijn Rempt <boud@valdyas.org>
3 *
4 * SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6
7#include "kis_kra_loader.h"
8
9#include <QApplication>
10#include <QStringList>
11
12#include <QMessageBox>
13
14#include <QUrl>
15#include <QBuffer>
16#include <QVersionNumber>
17
18#include <KoStore.h>
20#include <KoColorSpaceEngine.h>
21#include <KoColorProfile.h>
22#include <KoDocumentInfo.h>
23#include <KoFileDialog.h>
25#include <KoStoreDevice.h>
27#include <KoResourceServer.h>
28#include <KisResourceStorage.h>
30#include <KisResourceModel.h>
31
32#include <filter/kis_filter.h>
38#include <kis_annotation.h>
39#include <kis_base_node.h>
40#include <kis_clone_layer.h>
41#include <kis_debug.h>
42#include <kis_assert.h>
44#include <kis_filter_mask.h>
45#include <kis_transform_mask.h>
46#include "kis_hdr_metadata.h"
48#include <kis_group_layer.h>
49#include <kis_image.h>
50#include <kis_layer.h>
51#include <kis_name_server.h>
52#include <kis_paint_layer.h>
53#include <kis_selection.h>
54#include <kis_selection_mask.h>
55#include <kis_shape_layer.h>
58#include <kis_file_layer.h>
59#include <kis_psd_layer_style.h>
64#include "KisReferenceImage.h"
65#include <KoColorSet.h>
66
67#include "KisDocument.h"
68#include "kis_config.h"
69#include "kis_kra_tags.h"
70#include "kis_kra_utils.h"
72#include "kis_dom_utils.h"
74#include "kis_time_span.h"
75#include "kis_grid_config.h"
76#include "kis_guides_config.h"
77#include "kis_image_config.h"
81#include "KisMirrorAxisConfig.h"
83
84/*
85 Color model id comparison through the ages:
86
872.4 2.5 2.6 ideal
88
89ALPHA ALPHA ALPHA ALPHAU8
90
91CMYK CMYK CMYK CMYKAU8
92 CMYKAF32 CMYKAF32
93CMYKA16 CMYKAU16 CMYKAU16
94
95GRAYA GRAYA GRAYA GRAYAU8
96GrayF32 GRAYAF32 GRAYAF32
97GRAYA16 GRAYAU16 GRAYAU16
98
99LABA LABA LABA LABAU16
100 LABAF32 LABAF32
101 LABAU8 LABAU8
102
103RGBA RGBA RGBA RGBAU8
104RGBA16 RGBA16 RGBA16 RGBAU16
105RgbAF32 RGBAF32 RGBAF32
106RgbAF16 RgbAF16 RGBAF16
107
108XYZA16 XYZA16 XYZA16 XYZAU16
109 XYZA8 XYZA8 XYZAU8
110XyzAF16 XyzAF16 XYZAF16
111XyzAF32 XYZAF32 XYZAF32
112
113YCbCrA YCBCRA8 YCBCRA8 YCBCRAU8
114YCbCrAU16 YCBCRAU16 YCBCRAU16
115 YCBCRF32 YCBCRF32
116 */
117
118using namespace KRA;
119
121{
122public:
124 QString imageName; // used to be stored in the image, is now in the documentInfo block
125 QString imageComment; // used to be stored in the image, is now in the documentInfo block
126 QMap<KisNode*, QString> layerFilenames; // temp storage during loading
127 int syntaxVersion; // version of the fileformat we are loading
128 QVersionNumber kritaVersion;
129 vKisNodeSP selectedNodes; // the nodes that were active when saving the document.
130 QMap<QString, QString> assistantsFilenames;
134 QMap<KisNode*, QString> keyframeFilenames;
140};
141
142void convertColorSpaceNames(QString &colorspacename, QString &profileProductName) {
143 if (colorspacename == "Grayscale + Alpha") {
144 colorspacename = "GRAYA";
145 profileProductName.clear();
146 }
147 else if (colorspacename == "RgbAF32") {
148 colorspacename = "RGBAF32";
149 profileProductName.clear();
150 }
151 else if (colorspacename == "RgbAF16") {
152 colorspacename = "RGBAF16";
153 profileProductName.clear();
154 }
155 else if (colorspacename == "CMYKA16") {
156 colorspacename = "CMYKAU16";
157 }
158 else if (colorspacename == "GrayF32") {
159 colorspacename = "GRAYAF32";
160 profileProductName.clear();
161 }
162 else if (colorspacename == "GRAYA16") {
163 colorspacename = "GRAYAU16";
164 }
165 else if (colorspacename == "XyzAF16") {
166 colorspacename = "XYZAF16";
167 profileProductName.clear();
168 }
169 else if (colorspacename == "XyzAF32") {
170 colorspacename = "XYZAF32";
171 profileProductName.clear();
172 }
173 else if (colorspacename == "YCbCrA") {
174 colorspacename = "YCBCRA8";
175 }
176 else if (colorspacename == "YCbCrAU16") {
177 colorspacename = "YCBCRAU16";
178 }
179}
180
181KisKraLoader::KisKraLoader(KisDocument * document, int syntaxVersion, const QVersionNumber &kritaVersion)
182 : m_d(new Private())
183{
184 m_d->document = document;
185 m_d->syntaxVersion = syntaxVersion;
186 m_d->kritaVersion = kritaVersion;
187}
188
189
191{
192 delete m_d;
193}
194
195
196KisImageSP KisKraLoader::loadXML(const QDomElement& imageElement)
197{
198 QString attr;
199 KisImageSP image = 0;
200 qint32 width;
201 qint32 height;
202 QString profileProductName;
203 double xres;
204 double yres;
205 QString colorspacename;
206 const KoColorSpace * cs;
207
208 if ((attr = imageElement.attribute(MIME)) == NATIVE_MIMETYPE) {
209
210 if ((m_d->imageName = imageElement.attribute(NAME)).isNull()) {
211 m_d->errorMessages << i18n("Image does not have a name.");
212 return KisImageSP(0);
213 }
214
215 if ((attr = imageElement.attribute(WIDTH)).isNull()) {
216 m_d->errorMessages << i18n("Image does not specify a width.");
217 return KisImageSP(0);
218 }
219 width = KisDomUtils::toInt(attr);
220
221 if ((attr = imageElement.attribute(HEIGHT)).isNull()) {
222 m_d->errorMessages << i18n("Image does not specify a height.");
223 return KisImageSP(0);
224 }
225
226 height = KisDomUtils::toInt(attr);
227
228 m_d->imageComment = imageElement.attribute(DESCRIPTION);
229
230 xres = 100.0 / 72.0;
231 if (!(attr = imageElement.attribute(X_RESOLUTION)).isNull()) {
232 qreal value = KisDomUtils::toDouble(attr);
233
234 if (value > 0) {
235 xres = value / 72.0;
236 }
237 }
238
239 yres = 100.0 / 72.0;
240 if (!(attr = imageElement.attribute(Y_RESOLUTION)).isNull()) {
241 qreal value = KisDomUtils::toDouble(attr);
242 if (value > 0) {
243 yres = value / 72.0;
244 }
245 }
246
247 if ((colorspacename = imageElement.attribute(COLORSPACE_NAME)).isNull()) {
248 // An old file: take a reasonable default.
249 // Krita didn't support anything else in those
250 // days anyway.
251 colorspacename = "RGBA";
252 }
253
254 profileProductName = imageElement.attribute(PROFILE);
255 // A hack for an old colorspacename
256 convertColorSpaceNames(colorspacename, profileProductName);
257
258 QString colorspaceModel = KoColorSpaceRegistry::instance()->colorSpaceColorModelId(colorspacename).id();
259 QString colorspaceDepth = KoColorSpaceRegistry::instance()->colorSpaceColorDepthId(colorspacename).id();
260
261 if (profileProductName.isNull()) {
262 // no mention of profile so get default profile";
263 cs = KoColorSpaceRegistry::instance()->colorSpace(colorspaceModel, colorspaceDepth, "");
264 } else {
265 cs = KoColorSpaceRegistry::instance()->colorSpace(colorspaceModel, colorspaceDepth, profileProductName);
266 }
267
268 if (cs == 0) {
269 // try once more without the profile
270 cs = KoColorSpaceRegistry::instance()->colorSpace(colorspaceModel, colorspaceDepth, "");
271 if (cs == 0) {
272 m_d->errorMessages << i18n("Image specifies an unsupported color model: %1.", colorspacename);
273 return KisImageSP(0);
274 }
275 }
276 KisProofingConfigurationSP proofingConfig;
277 if (!(attr = imageElement.attribute(PROOFINGPROFILENAME)).isNull()) {
278 // initialize config only if ptofile name is present
279 proofingConfig = KisImageConfig(true).defaultProofingconfiguration();
280 proofingConfig->proofingProfile = attr;
281 }
282 if (proofingConfig && !(attr = imageElement.attribute(PROOFINGMODEL)).isNull()) {
283 proofingConfig->proofingModel = attr;
284 }
285 if (proofingConfig && !(attr = imageElement.attribute(PROOFINGDEPTH)).isNull()) {
286 proofingConfig->proofingDepth = attr;
287 }
288 if (proofingConfig && !(attr = imageElement.attribute(PROOFINGINTENT)).isNull()) {
289 proofingConfig->conversionIntent = (KoColorConversionTransformation::Intent) KisDomUtils::toInt(attr);
290 }
291 if (proofingConfig && !(attr = imageElement.attribute(PROOFINGDISPLAYINTENT)).isNull()) {
292 proofingConfig->displayIntent = (KoColorConversionTransformation::Intent) KisDomUtils::toInt(attr);
293 }
294 if (proofingConfig && !(attr = imageElement.attribute(PROOFINGDISPLAYMODE)).isNull()) {
295 if (attr == "monitor") {
296 proofingConfig->displayMode = KisProofingConfiguration::Monitor;
297 } else if (attr == "paper") {
298 proofingConfig->displayMode = KisProofingConfiguration::Paper;
299 } else {
300 proofingConfig->displayMode = KisProofingConfiguration::Custom;
301 }
302 }
303 if (proofingConfig && !(attr = imageElement.attribute(PROOFINGBLACKPOINTCOMPENSATION)).isNull()) {
304 proofingConfig->useBlackPointCompensationFirstTransform = (attr == "true");
305 }
306
307 if (proofingConfig && !(attr = imageElement.attribute(PROOFINGDISPLAYBLACKPOINTCOMPENSATION)).isNull()) {
308 proofingConfig->displayFlags.setFlag(KoColorConversionTransformation::BlackpointCompensation, attr == "true");
309 }
310
311 if (proofingConfig && !(attr = imageElement.attribute(PROOFINGADAPTATIONSTATE)).isNull()) {
312 const qreal legacyAdaptationState = KisDomUtils::toDouble(attr);
313 proofingConfig->setLegacyAdaptationState(legacyAdaptationState);
314 }
315
316 if (m_d->document) {
317 image = new KisImage(m_d->document->createUndoStore(), width, height, cs, m_d->imageName);
318 }
319 else {
320 image = new KisImage(0, width, height, cs, m_d->imageName);
321 }
322 image->setResolution(xres, yres);
323 loadNodes(imageElement, image, const_cast<KisGroupLayer*>(image->rootLayer().data()));
324
325
326 QDomNode child;
327 for (child = imageElement.lastChild(); !child.isNull(); child = child.previousSibling()) {
328 QDomElement e = child.toElement();
329
330 if(e.tagName() == CANVASPROJECTIONCOLOR) {
331 if (e.hasAttribute(COLORBYTEDATA)) {
332 QByteArray colorData = QByteArray::fromBase64(e.attribute(COLORBYTEDATA).toLatin1());
333 KoColor color((const quint8*)colorData.data(), image->colorSpace());
334 image->setDefaultProjectionColor(color);
335 }
336 }
337
338 if(e.tagName() == COLORHISTORY) {
339 QList<KoColor> colors = loadKoColors(e);
341 }
342
343 if (e.tagName() == HDRMETADATA) {
344 loadHDRMetadata(e, image);
345 }
346
347 if(e.tagName() == GLOBALASSISTANTSCOLOR) {
348 if (e.hasAttribute(SIMPLECOLORDATA)) {
349 QString colorData = e.attribute(SIMPLECOLORDATA);
351 }
352 }
353
354 if (proofingConfig && e.tagName()== PROOFINGWARNINGCOLOR) {
355 QDomDocument dom;
356 QDomNode node = e;
357 dom.appendChild(dom.importNode(node, true));
358 QDomElement eq = dom.firstChildElement();
359 proofingConfig->warningColor = KoColor::fromXML(eq.firstChildElement(), Integer8BitsColorDepthID.id());
360 }
361
362 // COMPATIBILITY -- Load Animation Metadata from OLD KRA files.
363 if (e.tagName().toLower() == "animation") {
365 }
366 }
367
368 if (proofingConfig) {
369 image->setProofingConfiguration(proofingConfig);
370 }
371
372 for (child = imageElement.lastChild(); !child.isNull(); child = child.previousSibling()) {
373 QDomElement e = child.toElement();
374 if (e.tagName() == "compositions") {
375 loadCompositions(e, image);
376 }
377 }
378 }
379
380 QDomNode child;
381 for (child = imageElement.lastChild(); !child.isNull(); child = child.previousSibling()) {
382 QDomElement e = child.toElement();
383 if (e.tagName() == "grid") {
384 loadGrid(e);
385 } else if (e.tagName() == "guides") {
386 loadGuides(e);
387 } else if (e.tagName() == MIRROR_AXIS) {
389 } else if (e.tagName() == "assistants") {
391 } else if (e.tagName() == "audio") {
393 }
394 }
395
396 // reading palettes from XML
397 for (child = imageElement.lastChild(); !child.isNull(); child = child.previousSibling()) {
398 QDomElement e = child.toElement();
399 if (e.tagName() == PALETTES) {
400 for (QDomElement paletteElement = e.lastChildElement(); !paletteElement.isNull();
401 paletteElement = paletteElement.previousSiblingElement()) {
402 QString paletteName = paletteElement.attribute("filename");
403 m_d->paletteFilenames.append(paletteName);
404 }
405 break;
406 }
407 }
408
409 // reading resources from XML
410 for (child = imageElement.lastChild(); !child.isNull(); child = child.previousSibling()) {
411 QDomElement e = child.toElement();
412 if (e.tagName() == RESOURCES) {
413 for (QDomElement resourceElement = e.lastChildElement();
414 !resourceElement.isNull();
415 resourceElement = resourceElement.previousSiblingElement())
416 {
417 KoResourceSignature resourceItem;
418 resourceItem.filename = resourceElement.attribute("filename");
419 resourceItem.md5sum = resourceElement.attribute("md5sum");
420 resourceItem.type = resourceElement.attribute("type");
421 resourceItem.name = resourceElement.attribute("name");
422 m_d->resources.append(resourceItem);
423 }
424 break;
425 }
426 }
427
428 // reading the extra annotations from XML
429 for (child = imageElement.lastChild(); !child.isNull(); child = child.previousSibling()) {
430 QDomElement e = child.toElement();
431 if (e.tagName() == ANNOTATIONS) {
432 for (QDomElement annotationElement = e.firstChildElement();
433 !annotationElement.isNull();
434 annotationElement = annotationElement.nextSiblingElement())
435 {
436 QString type = annotationElement.attribute("type");
437 QString description = annotationElement.attribute("description");
438
439 KisAnnotationSP annotation = new KisAnnotation(type, description, QByteArray());
440 m_d->annotations << annotation;
441 }
442 break;
443 }
444 }
445
446 return image;
447}
448
449void KisKraLoader::loadBinaryData(KoStore * store, KisImageSP image, const QString & uri, bool external)
450{
451 // icc profile: if present, this overrides the profile product name loaded in loadXML.
452 QString location = external ? QString() : uri;
453 location += m_d->imageName + ICC_PATH;
454 if (store->hasFile(location)) {
455 if (store->open(location)) {
456 QByteArray data; data.resize(store->size());
457 bool res = (store->read(data.data(), store->size()) > -1);
458 store->close();
459 if (res) {
460 QString colorspaceModel = image->colorSpace()->colorModelId().id();
461 QString colorspaceDepth = image->colorSpace()->colorDepthId().id();
463 if (profile && profile->valid()) {
464 const KoColorSpace *colorSpace = KoColorSpaceRegistry::instance()->colorSpace(colorspaceModel, colorspaceDepth, profile);
465 image->convertImageProjectionColorSpace(colorSpace);
466 }
467 }
468 }
469 }
470 //load the embed proofing profile, it only needs to be loaded into Krita, not assigned.
471 location = external ? QString() : uri;
472 location += m_d->imageName + ICC_PROOFING_PATH;
473 if (store->hasFile(location)) {
474 if (store->open(location)) {
475 QByteArray proofingData;
476 proofingData.resize(store->size());
477 bool proofingProfileRes = (store->read(proofingData.data(), store->size())>-1);
478 store->close();
479
480 KisProofingConfigurationSP proofingConfig = image->proofingConfiguration();
481 if (!proofingConfig) {
482 proofingConfig = KisImageConfig(true).defaultProofingconfiguration();
483 }
484
485 if (proofingProfileRes) {
486 const KoColorProfile *proofingProfile = KoColorSpaceRegistry::instance()->createColorProfile(proofingConfig->proofingModel, proofingConfig->proofingDepth, proofingData, KisKraLoadVisitor::customProfileNameAliasForKra());
487 if (!proofingProfile || proofingProfile->valid()){
488 warnKrita << "Failed to load a proofing profile!";
489 }
490 }
491 }
492 }
493
494
495 // Load the layers data: if there is a profile associated with a layer it will be set now.
497
498 if (external) {
499 visitor.setExternalUri(uri);
500 }
501
502 image->rootLayer()->accept(visitor);
503 if (!visitor.errorMessages().isEmpty()) {
504 m_d->errorMessages.append(visitor.errorMessages());
505 }
506 if (!visitor.warningMessages().isEmpty()) {
507 m_d->warningMessages.append(visitor.warningMessages());
508 }
509
510 // annotations
511 // exif
512 location = external ? QString() : uri;
513 location += m_d->imageName + EXIF_PATH;
514 if (store->hasFile(location)) {
515 QByteArray data;
516 store->open(location);
517 data = store->read(store->size());
518 store->close();
519 image->addAnnotation(KisAnnotationSP(new KisAnnotation("exif", "", data)));
520 }
521
522
523 // layer styles
524 location = external ? QString() : uri;
525 location += m_d->imageName + LAYER_STYLES_PATH;
526 if (store->hasFile(location)) {
527
529 store->open(location);
530 {
531 KoStoreDevice device(store);
532 device.open(QIODevice::ReadOnly);
533
538 QByteArray buf = device.readAll();
539 QBuffer raDevice(&buf);
540 raDevice.open(QIODevice::ReadOnly);
541 serializer.readFromDevice(raDevice);
542 }
543 store->close();
544
545 if (serializer.isValid()) {
546 const QString resourceLocation = m_d->document->embeddedResourcesStorageId();
547 serializer.assignAllLayerStylesToLayers(image->root(), resourceLocation);
548
549 } else {
550 warnKrita << "WARNING: Couldn't load layer styles library from .kra!";
551 }
552 }
553
554 if (m_d->document && m_d->document->documentInfo()->aboutInfo("title").isNull())
556 if (m_d->document && m_d->document->documentInfo()->aboutInfo("comment").isNull())
558
559 loadAssistants(store, uri, external);
560
561 // Annotations
562 Q_FOREACH(KisAnnotationSP annotation, m_d->annotations) {
563 QByteArray ba;
564 location = external ? QString() : uri;
565 location += m_d->imageName + ANNOTATIONS_PATH + annotation->type();
566 if (store->hasFile(location)) {
567 store->open(location);
568 KoStoreDevice device(store);
569 device.open(QIODevice::ReadOnly);
570 ba = device.readAll();
571 device.close();
572 store->close();
573 annotation->setAnnotation(ba);
574 m_d->document->image()->addAnnotation(annotation);
575 }
576 }
577
578}
579
581{
583 Q_FOREACH (const QString &filename, m_d->paletteFilenames) {
584 KoColorSetSP newPalette(new KoColorSet(filename));
585 store->open(m_d->imageName + PALETTE_PATH + filename);
586
587 QByteArray data = store->read(store->size());
588 if (data.size() > 0) {
589 newPalette->fromByteArray(data, KisGlobalResourcesInterface::instance());
590 store->close();
591 list.append(newPalette);
592 } else {
593 m_d->warningMessages.append(i18nc("Warning message on loading a .kra file", "Embedded palette is empty and cannot be loaded. The name of the palette: %1", filename));
594 }
595 }
596 doc->setPaletteList(list);
597
598 Q_FOREACH(const KoResourceSignature &resourceItem, m_d->resources) {
599 KisResourceModel model(resourceItem.type);
600 if (model.resourcesForMD5(resourceItem.md5sum).isEmpty()) {
601 store->open(RESOURCE_PATH + '/' + resourceItem.type + '/' + resourceItem.filename);
602
603 if (!store->isOpen()) {
604 m_d->warningMessages.append(i18nc("Warning message on loading a .kra file", "Embedded resource cannot be read. The filename of the resource: %1", resourceItem.filename));
605 continue;
606 }
607
610 if (!store->device()->atEnd() && !doc->linkedResourcesStorageId().isEmpty()) {
611 bool result = bool(model.importResource(resourceItem.filename, store->device(), false, doc->linkedResourcesStorageId()));
612 if (!result) {
613 m_d->warningMessages.append(i18nc("Warning message on loading a .kra file", "Embedded resource cannot be imported. The filename of the resource: %1", resourceItem.filename));
614 }
615 }
616
617 store->close();
618 }
619 }
620}
621
623{
624 if (!store->hasFile(m_d->imageName + STORYBOARD_PATH + "index.xml")) return;
625
626 if (store->open(m_d->imageName + STORYBOARD_PATH + "index.xml")) {
627 QByteArray data = store->read(store->size());
628 QDomDocument document;
629 document.setContent(data);
630 store->close();
631
632 QDomElement root = document.documentElement();
633 QDomNode node;
634 for (node = root.lastChild(); !node.isNull(); node = node.previousSibling()) {
635 if (node.isElement()) {
636 QDomElement element = node.toElement();
637 if (element.tagName() == "StoryboardItemList") {
638 loadStoryboardItemList(element);
639 } else if (element.tagName() == "StoryboardCommentList") {
641 }
642 }
643 }
644 }
645}
646
648{
649 if (!store->hasFile(m_d->imageName + ANIMATION_METADATA_PATH + "index.xml")) return;
650
651 if (store->open(m_d->imageName + ANIMATION_METADATA_PATH + "index.xml")) {
652 QByteArray data = store->read(store->size());
653 QDomDocument document;
654 document.setContent(data);
655 store->close();
656
657 QDomElement root = document.documentElement();
658 loadAnimationMetadataFromXML(root, image);
659 }
660}
661
663{
664 if (!store->hasFile(m_d->imageName + AUDIO_PATH + "index.xml")) return;
665
666 if (store->open(m_d->imageName + AUDIO_PATH + "index.xml")) {
667 QByteArray byteData = store->read(store->size());
668 QDomDocument xmlDocument;
669 xmlDocument.setContent(byteData);
670 store->close();
671
672 QDomElement root = xmlDocument.documentElement();
673 loadAudioXML(xmlDocument, root, kisDoc);
674 }
675}
676
677void KisKraLoader::backCompat_loadAudio(const QDomElement& elem, KisDocument *document)
678{
679 QDomDocument dom;
680 dom.appendChild(dom.importNode(elem, true));
681 QDomElement qElement = dom.firstChildElement();
682
683 QString fileName;
684 if (KisDomUtils::loadValue(qElement, "masterChannelPath", &fileName)) {
685 fileName = QDir::toNativeSeparators(fileName);
686
687 QDir baseDirectory = QFileInfo(m_d->document->localFilePath()).absoluteDir();
688 fileName = QDir::cleanPath( baseDirectory.filePath(fileName) );
689
690 QFileInfo info(fileName);
691
692 if (!info.exists()) {
693 KisCursorOverrideHijacker cursorHijacker;
694
695 QString msg = i18nc(
696 "@info",
697 "Audio channel file \"%1\" doesn't exist!\n\n"
698 "Expected path:\n"
699 "%2\n\n"
700 "Do you want to locate it manually?", info.fileName(), info.absoluteFilePath());
701
702 int result = QMessageBox::warning(qApp->activeWindow(), i18nc("@title:window", "File not found"), msg, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
703
704 if (result == QMessageBox::Yes) {
705 info.setFile(KisImportExportManager::askForAudioFileName(info.absolutePath(), 0));
706 }
707 }
708
709 if (info.exists()) {
710 QVector<QFileInfo> clipFiles;
711
712 clipFiles << info;
713
714 document->setAudioTracks(clipFiles);
715 }
716 }
717
718 // Note: Muting has been removed from backCompat due to it no longer being document-specific.
719
720 qreal audioVolume = 1.0;
721 if (KisDomUtils::loadValue(qElement, "audioVolume", &audioVolume)) {
722 document->setAudioVolume(audioVolume);
723 }
724}
725
730
735
740
745
750
755
757{
758 return m_d->imageName;
759}
760
761
762void KisKraLoader::loadAssistants(KoStore *store, const QString &uri, bool external)
763{
764 QString file_path;
765 QString location;
766 QMap<int ,KisPaintingAssistantHandleSP> handleMap;
767 KisPaintingAssistant* assistant = 0;
768 const QColor globalColor = m_d->document->assistantsGlobalColor();
769
770 QMap<QString,QString>::const_iterator loadedAssistant = m_d->assistantsFilenames.constBegin();
771 while (loadedAssistant != m_d->assistantsFilenames.constEnd()){
772 const KisPaintingAssistantFactory* factory = KisPaintingAssistantFactoryRegistry::instance()->get(loadedAssistant.value());
773 if (factory) {
774 assistant = factory->createPaintingAssistant();
775 location = external ? QString() : uri;
776 location += m_d->imageName + ASSISTANTS_PATH;
777 file_path = location + loadedAssistant.key();
778 assistant->loadXml(store, handleMap, file_path);
779 assistant->setAssistantGlobalColorCache(globalColor);
780
781 //If an assistant has too few handles than it should according to it's own setup, just don't load it//
782 if (assistant->handles().size()==assistant->numHandles()){
783 m_d->assistants.append(toQShared(assistant));
784 }
785 }
786 loadedAssistant++;
787 }
788}
789
790void KisKraLoader::loadAnimationMetadataFromXML(const QDomElement &element, KisImageSP image)
791{
792 QDomDocument qDom;
793 QDomNode node = element;
794 qDom.appendChild(qDom.importNode(node, true));
795 QDomElement rootElement = qDom.firstChildElement();
796
797 float framerate;
798 KisTimeSpan range;
799 int currentTime;
800 QString string;
801
803
804 if (KisDomUtils::loadValue(rootElement, "framerate", &framerate)) {
805 animation->setFramerate(framerate);
806 }
807
808 if (KisDomUtils::loadValue(rootElement, "range", &range)) {
809 animation->setDocumentRange(range);
810 }
811
812 if (KisDomUtils::loadValue(rootElement, "currentTime", &currentTime)) {
813 animation->switchCurrentTimeAsync(currentTime);
814 }
815
816 {
817 int initialFrameNumber = -1;
818 QDomElement exportElement = rootElement.firstChildElement("export-settings");
819 if (!exportElement.isNull()) {
820 if (KisDomUtils::loadValue(exportElement, "sequenceFilePath", &string)) {
821 animation->setExportSequenceFilePath(string);
822 }
823
824 if (KisDomUtils::loadValue(exportElement, "sequenceBaseName", &string)) {
825 animation->setExportSequenceBaseName(string);
826 }
827
828 if (KisDomUtils::loadValue(exportElement, "sequenceInitialFrameNumber", &initialFrameNumber)) {
829 animation->setExportInitialFrameNumber(initialFrameNumber);
830 }
831 }
832 }
833
834 animation->setExportSequenceBaseName(string);
835}
836
837KisNodeSP KisKraLoader::loadNodes(const QDomElement& element, KisImageSP image, KisNodeSP parent)
838{
839
840 QDomNode node = element.firstChild();
841 QDomNode child;
842
843 if (!node.isNull()) {
844
845 if (node.isElement()) {
846
847 // See https://bugs.kde.org/show_bug.cgi?id=408963, where there is a selection mask that is a child of the
848 // the projection. That needs to be treated as a global selection, so we keep track of those.
849 vKisNodeSP topLevelSelectionMasks;
850 if (node.nodeName().toUpper() == LAYERS.toUpper() || node.nodeName().toUpper() == MASKS.toUpper()) {
851 for (child = node.lastChild(); !child.isNull(); child = child.previousSibling()) {
852 KisNodeSP node = loadNode(child.toElement(), image);
853
854 if (node && parent.data() == image->rootLayer().data() && node->inherits("KisSelectionMask") && image->rootLayer()->childCount() > 0) {
855 topLevelSelectionMasks << node;
856 continue;
857 }
858
859 if (node ) {
860 image->addNode(node, parent);
861 if (node->inherits("KisLayer") && child.childNodes().count() > 0) {
862 loadNodes(child.toElement(), image, node);
863 }
864 }
865 }
866
867 KisSelectionMaskSP activeSelectionMask;
868 Q_FOREACH (KisNodeSP node, topLevelSelectionMasks) {
869 KisSelectionMask *mask = qobject_cast<KisSelectionMask*>(node.data());
870 if (mask->active()) {
871 if (activeSelectionMask) {
872 m_d->warningMessages << i18n("Two global selection masks in active state found. \"%1\" is kept active, \"%2\" is deactivated", activeSelectionMask->name(), mask->name());
873 mask->setActive(false);
874 KIS_ASSERT(!mask->active());
875 } else {
876 activeSelectionMask = mask;
877 }
878 }
879
880 image->addNode(mask, parent);
881 }
882 }
883 }
884 }
885
886 return parent;
887}
888
890
891KisNodeSP KisKraLoader::loadNode(const QDomElement& element, KisImageSP image)
892{
893 // Nota bene: If you add new properties to layers, you should
894 // ALWAYS define a default value in case the property is not
895 // present in the layer definition: this helps a LOT with backward
896 // compatibility.
897 QString name = element.attribute(NAME, "No Name");
898
899 QUuid id = QUuid(element.attribute(UUID, QUuid().toString()));
900
901 qint32 x = element.attribute(X, "0").toInt();
902 qint32 y = element.attribute(Y, "0").toInt();
903
904 qint32 opacity = element.attribute(OPACITY, QString::number(OPACITY_OPAQUE_U8)).toInt();
905 if (opacity < OPACITY_TRANSPARENT_U8) opacity = OPACITY_TRANSPARENT_U8;
906 if (opacity > OPACITY_OPAQUE_U8) opacity = OPACITY_OPAQUE_U8;
907
908 const KoColorSpace* colorSpace = 0;
909 if ((element.attribute(COLORSPACE_NAME)).isNull()) {
910 dbgFile << "No attribute color space for layer: " << name;
911 colorSpace = image->colorSpace();
912 } else {
913 QString colorspacename = element.attribute(COLORSPACE_NAME);
914 QString profileProductName = element.attribute(PROFILE);
915
916 convertColorSpaceNames(colorspacename, profileProductName);
917
918 QString colorspaceModel = KoColorSpaceRegistry::instance()->colorSpaceColorModelId(colorspacename).id();
919 QString colorspaceDepth = KoColorSpaceRegistry::instance()->colorSpaceColorDepthId(colorspacename).id();
920 dbgFile << "Searching color space: " << colorspacename << colorspaceModel << colorspaceDepth << " for layer: " << name;
921 // use default profile - it will be replaced later in completeLoading
922
923 if (profileProductName.isNull()) {
924 // no mention of profile so get default profile";
925 colorSpace = KoColorSpaceRegistry::instance()->colorSpace(colorspaceModel, colorspaceDepth, "");
926 } else {
927 colorSpace = KoColorSpaceRegistry::instance()->colorSpace(colorspaceModel, colorspaceDepth, profileProductName);
928 }
929
930 dbgFile << "found colorspace" << colorSpace;
931 if (!colorSpace) {
932 m_d->warningMessages << i18n("Layer %1 specifies an unsupported color model: %2.", name, colorspacename);
933 return 0;
934 }
935 }
936
937 const bool visible = element.attribute(VISIBLE, "1") == "0" ? false : true;
938 const bool locked = element.attribute(LOCKED, "0") == "0" ? false : true;
939 const bool collapsed = element.attribute(COLLAPSED, "0") == "0" ? false : true;
940 int colorLabelIndex = element.attribute(COLOR_LABEL, "0").toInt();
942 if (colorLabelIndex >= labels.size()) {
943 colorLabelIndex = labels.size() - 1;
944 }
945
946 // Now find out the layer type and do specific handling
947 QString nodeType;
948
949 if (m_d->syntaxVersion == 1) {
950 nodeType = element.attribute("layertype");
951 if (nodeType.isEmpty()) {
953 }
954 }
955 else {
956 nodeType = element.attribute(NODE_TYPE);
957 }
958
959 if (nodeType.isEmpty()) {
960 m_d->warningMessages << i18n("Layer %1 has an unsupported type.", name);
961 return 0;
962 }
963
964
965
966 KisNodeSP node = 0;
967
968 if (nodeType == PAINT_LAYER)
969 node = loadPaintLayer(element, image, name, colorSpace, opacity);
970 else if (nodeType == GROUP_LAYER)
971 node = loadGroupLayer(element, image, name, colorSpace, opacity);
972 else if (nodeType == ADJUSTMENT_LAYER)
973 node = loadAdjustmentLayer(element, image, name, colorSpace, opacity);
974 else if (nodeType == SHAPE_LAYER)
975 node = loadShapeLayer(element, image, name, colorSpace, opacity);
976 else if (nodeType == GENERATOR_LAYER)
977 node = loadGeneratorLayer(element, image, name, colorSpace, opacity);
978 else if (nodeType == CLONE_LAYER)
979 node = loadCloneLayer(element, image, name, colorSpace, opacity);
980 else if (nodeType == FILTER_MASK)
981 node = loadFilterMask(image, element);
982 else if (nodeType == TRANSFORM_MASK)
983 node = loadTransformMask(image, element);
984 else if (nodeType == TRANSPARENCY_MASK)
985 node = loadTransparencyMask(image, element);
986 else if (nodeType == SELECTION_MASK)
987 node = loadSelectionMask(image, element);
988 else if (nodeType == COLORIZE_MASK)
989 node = loadColorizeMask(image, element, colorSpace);
990 else if (nodeType == FILE_LAYER)
991 node = loadFileLayer(element, image, name, opacity, colorSpace);
993 node = loadReferenceImagesLayer(element, image);
994 else {
995 m_d->warningMessages << i18n("Layer %1 has an unsupported type: %2.", name, nodeType);
996 return 0;
997 }
998
999 // Loading the node went wrong. Return empty node and leave to
1000 // upstream to complain to the user
1001 if (!node) {
1002 m_d->warningMessages << i18n("Failure loading layer %1 of type: %2.", name, nodeType);
1003 return 0;
1004 }
1005
1006 node->setVisible(visible, true);
1007 node->setUserLocked(locked);
1008 node->setCollapsed(collapsed);
1009 node->setColorLabelIndex(colorLabelIndex);
1010 node->setX(x);
1011 node->setY(y);
1012 node->setName(name);
1013
1014 if (! id.isNull()) // if no uuid in file, new one has been generated already
1015 node->setUuid(id);
1016
1017 if (node->inherits("KisLayer") || node->inherits("KisColorizeMask")) {
1018 QString compositeOpName = element.attribute(COMPOSITE_OP, "normal");
1019 node->setCompositeOpId(compositeOpName);
1020
1021 if (m_d->kritaVersion < QVersionNumber(5, 2) &&
1022 colorSpace->colorModelId() == CMYKAColorModelID &&
1023 subtractiveBlendingModesInCmyk().contains(compositeOpName)) {
1024
1026 i18n("Layer \"%1\" has blending mode \"%2\" that has changed its "
1027 "behavior for CMYK color in Krita 5.2. Please check the "
1028 "result and consider enabling legacy \"Additive\" algorithm in "
1029 "Settings->Configure Krita->General->Tools->CMYK blending mode",
1030 name, KoCompositeOpRegistry::instance().getKoID(compositeOpName).name());
1031 }
1032 }
1033
1034 if (node->inherits("KisLayer")) {
1035 KisLayer* layer = qobject_cast<KisLayer*>(node.data());
1036 QBitArray channelFlags = stringToFlags(element.attribute(CHANNEL_FLAGS, ""), colorSpace->channelCount());
1037 layer->setChannelFlags(channelFlags);
1038
1039 if (element.hasAttribute(LAYER_STYLE_UUID)) {
1040 QString uuidString = element.attribute(LAYER_STYLE_UUID);
1041 QUuid uuid(uuidString);
1042 if (!uuid.isNull()) {
1043 KisPSDLayerStyleSP dumbLayerStyle(new KisPSDLayerStyle());
1044 dumbLayerStyle->setUuid(uuid);
1045 layer->setLayerStyle(dumbLayerStyle->cloneWithResourcesSnapshot(KisGlobalResourcesInterface::instance(), 0));
1046 } else {
1047 warnKrita << "WARNING: Layer style for layer" << layer->name() << "contains invalid UUID" << uuidString;
1048 }
1049 }
1050 }
1051
1052 if (node->inherits("KisGroupLayer")) {
1053 if (element.hasAttribute(PASS_THROUGH_MODE)) {
1054 bool value = element.attribute(PASS_THROUGH_MODE, "0") != "0";
1055
1056 KisGroupLayer *group = qobject_cast<KisGroupLayer*>(node.data());
1057 group->setPassThroughMode(value);
1058 }
1059 }
1060
1061 if (node->inherits("KisShapeLayer")) {
1062 if (element.hasAttribute(ANTIALIASED)) {
1063 bool value = element.attribute(ANTIALIASED, "0") != "0";
1064
1065 KisShapeLayer *shapeLayer = qobject_cast<KisShapeLayer*>(node.data());
1066 shapeLayer->setAntialiased(value);
1067 }
1068 }
1069
1070
1071 const bool timelineEnabled = element.attribute(VISIBLE_IN_TIMELINE, "0") == "0" ? false : true;
1072 node->setPinnedToTimeline(timelineEnabled);
1073
1074 if (node->inherits("KisPaintLayer")) {
1075 KisPaintLayer* layer = qobject_cast<KisPaintLayer*>(node.data());
1076 QBitArray channelLockFlags = stringToFlags(element.attribute(CHANNEL_LOCK_FLAGS, ""), colorSpace->channelCount());
1077 layer->setChannelLockFlags(channelLockFlags);
1078
1079 bool onionEnabled = element.attribute(ONION_SKIN_ENABLED, "0") == "0" ? false : true;
1080 layer->setOnionSkinEnabled(onionEnabled);
1081 }
1082
1083 if (element.attribute(FILE_NAME).isNull()) {
1084 m_d->layerFilenames[node.data()] = name;
1085 }
1086 else {
1087 m_d->layerFilenames[node.data()] = element.attribute(FILE_NAME);
1088 }
1089
1090 if (element.hasAttribute("selected") && element.attribute("selected") == "true") {
1091 m_d->selectedNodes.append(node);
1092 }
1093
1094 if (element.hasAttribute(KEYFRAME_FILE)) {
1095 m_d->keyframeFilenames.insert(node.data(), element.attribute(KEYFRAME_FILE));
1096 }
1097
1098 return node;
1099}
1100
1101
1102KisNodeSP KisKraLoader::loadPaintLayer(const QDomElement& element, KisImageSP image,
1103 const QString& name, const KoColorSpace* cs, quint32 opacity)
1104{
1105 Q_UNUSED(element);
1106 KisPaintLayer* layer;
1107
1108 layer = new KisPaintLayer(image, name, opacity, cs);
1109 Q_CHECK_PTR(layer);
1110 return layer;
1111
1112}
1113
1114KisNodeSP KisKraLoader::loadFileLayer(const QDomElement& element, KisImageSP image, const QString& name, quint32 opacity, const KoColorSpace *fallbackColorSpace)
1115{
1116 QString filename = element.attribute("source", QString());
1117 if (filename.isNull()) return 0;
1118 bool scale = (element.attribute("scale", "true") == "true");
1119 int scalingMethod = element.attribute("scalingmethod", "-1").toInt();
1120 if (scalingMethod < 0) {
1121 if (scale) {
1122 scalingMethod = KisFileLayer::ToImagePPI;
1123 }
1124 else {
1125 scalingMethod = KisFileLayer::None;
1126 }
1127 }
1128 QString scalingFilter = element.attribute("scalingfilter", "Bicubic");
1129
1130 QString documentPath;
1131 if (m_d->document) {
1132 documentPath = m_d->document->path();
1133 }
1134 QFileInfo info(documentPath);
1135 QString basePath = info.absolutePath();
1136
1137#ifndef Q_OS_ANDROID
1138 QString fullPath = QDir(basePath).filePath(QDir::cleanPath(filename));
1139#else
1140 QString fullPath = filename;
1141#endif
1142 if (!QFileInfo(fullPath).exists()) {
1143 KisCursorOverrideHijacker cursorHijacker;
1144
1145 QString msg = i18nc(
1146 "@info",
1147 "The file associated to a file layer with the name \"%1\" is not found.\n\n"
1148 "Expected path:\n"
1149 "%2\n\n"
1150 "Do you want to locate it manually?", name, fullPath);
1151
1152 int result = QMessageBox::warning(qApp->activeWindow(), i18nc("@title:window", "File not found"), msg, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
1153
1154 if (result == QMessageBox::Yes) {
1155
1156 KoFileDialog dialog(0, KoFileDialog::OpenFile, "OpenDocument");
1158 dialog.setDefaultDir(basePath);
1159 QString url = dialog.filename();
1160
1161 if (!QFileInfo(basePath).exists()) {
1162 filename = url;
1163 } else {
1164 QDir d(basePath);
1165 filename = d.relativeFilePath(url);
1166 }
1167 }
1168 }
1169
1170 KisLayer *layer = new KisFileLayer(image, basePath, filename, (KisFileLayer::ScalingMethod)scalingMethod, scalingFilter, name, opacity, fallbackColorSpace);
1171 Q_CHECK_PTR(layer);
1172
1173 return layer;
1174}
1175
1176KisNodeSP KisKraLoader::loadGroupLayer(const QDomElement& element, KisImageSP image,
1177 const QString& name, const KoColorSpace* cs, quint32 opacity)
1178{
1179 Q_UNUSED(element);
1180 KisGroupLayer* layer;
1181
1182 layer = new KisGroupLayer(image, name, opacity, cs);
1183 Q_CHECK_PTR(layer);
1184
1185 return layer;
1186
1187}
1188
1190 const QString& name, const KoColorSpace* cs, quint32 opacity)
1191{
1192 // XXX: do something with filterversion?
1193 Q_UNUSED(cs);
1194 QString attr;
1195 KisAdjustmentLayer* layer;
1196 QString filtername;
1197 QString legacy = filtername;
1198
1199 if ((filtername = element.attribute(FILTER_NAME)).isNull()) {
1200 // XXX: Invalid adjustment layer! We should warn about it!
1201 warnFile << "No filter in adjustment layer";
1202 return 0;
1203 }
1204
1205 //get deprecated filters.
1206 if (filtername=="brightnesscontrast") {
1207 legacy = filtername;
1208 filtername = "perchannel";
1209 }
1210 if (filtername=="left edge detections"
1211 || filtername=="right edge detections"
1212 || filtername=="top edge detections"
1213 || filtername=="bottom edge detections") {
1214 legacy = filtername;
1215 filtername = "edge detection";
1216 }
1217
1219 if (!f) {
1220 warnFile << "No filter for filtername" << filtername << "";
1221 return 0; // XXX: We don't have this filter. We should warn about it!
1222 }
1223
1224 KisFilterConfigurationSP kfc = f->defaultConfiguration(KisGlobalResourcesInterface::instance());
1225 kfc->createLocalResourcesSnapshot();
1226 kfc->setProperty("legacy", legacy);
1227 if (legacy=="brightnesscontrast") {
1228 kfc->setProperty("colorModel", cs->colorModelId().id());
1229 }
1230
1231 // We'll load the configuration and the selection later.
1232 layer = new KisAdjustmentLayer(image, name, kfc, 0);
1233 Q_CHECK_PTR(layer);
1234
1235 layer->setOpacity(opacity);
1236
1237 return layer;
1238
1239}
1240
1241
1242KisNodeSP KisKraLoader::loadShapeLayer(const QDomElement& element, KisImageSP image,
1243 const QString& name, const KoColorSpace* cs, quint32 opacity)
1244{
1245
1246 Q_UNUSED(element);
1247 Q_UNUSED(cs);
1248
1249 QString attr;
1250 KoShapeControllerBase * shapeController = 0;
1251 if (m_d->document) {
1252 shapeController = m_d->document->shapeController();
1253 }
1254 KisShapeLayer* layer = new KisShapeLayer(shapeController, image, name, opacity);
1255 Q_CHECK_PTR(layer);
1256
1257 return layer;
1258
1259}
1260
1261
1263 const QString& name, const KoColorSpace* cs, quint32 opacity)
1264{
1265 Q_UNUSED(cs);
1266 // XXX: do something with generator version?
1267 KisGeneratorLayer* layer;
1268 QString generatorname = element.attribute(GENERATOR_NAME);
1269
1270 if (generatorname.isNull()) {
1271 // XXX: Invalid generator layer! We should warn about it!
1272 warnFile << "No generator in generator layer";
1273 return 0;
1274 }
1275
1276 KisGeneratorSP generator = KisGeneratorRegistry::instance()->value(generatorname);
1277 if (!generator) {
1278 warnFile << "No generator for generatorname" << generatorname << "";
1279 return 0; // XXX: We don't have this generator. We should warn about it!
1280 }
1281
1283 kgc->createLocalResourcesSnapshot();
1284
1285 // We'll load the configuration and the selection later.
1286 layer = new KisGeneratorLayer(image, name, kgc, 0);
1287 Q_CHECK_PTR(layer);
1288
1289 layer->setOpacity(opacity);
1290
1291 return layer;
1292
1293}
1294
1295KisNodeSP KisKraLoader::loadCloneLayer(const QDomElement& element, KisImageSP image,
1296 const QString& name, const KoColorSpace* cs, quint32 opacity)
1297{
1298 Q_UNUSED(cs);
1299
1300 KisCloneLayerSP layer = new KisCloneLayer(0, image, name, opacity);
1301
1302 KisNodeUuidInfo info;
1303 if (! (element.attribute(CLONE_FROM_UUID)).isNull()) {
1304 info = KisNodeUuidInfo(QUuid(element.attribute(CLONE_FROM_UUID)));
1305 } else {
1306 if ((element.attribute(CLONE_FROM)).isNull()) {
1307 return 0;
1308 } else {
1309 info = KisNodeUuidInfo(element.attribute(CLONE_FROM));
1310 }
1311 }
1312 layer->setCopyFromInfo(info);
1313
1314 if ((element.attribute(CLONE_TYPE)).isNull()) {
1315 return 0;
1316 } else {
1317 layer->setCopyType((CopyLayerType) element.attribute(CLONE_TYPE).toInt());
1318 }
1319
1320 return layer;
1321}
1322
1323
1324KisNodeSP KisKraLoader::loadFilterMask(KisImageSP image, const QDomElement& element)
1325{
1326 QString attr;
1327 KisFilterMask* mask;
1328 QString filtername;
1329
1330 // XXX: should we check the version?
1331
1332 if ((filtername = element.attribute(FILTER_NAME)).isNull()) {
1333 // XXX: Invalid filter layer! We should warn about it!
1334 warnFile << "No filter in filter layer";
1335 return 0;
1336 }
1337
1339 if (!f) {
1340 warnFile << "No filter for filtername" << filtername << "";
1341 return 0; // XXX: We don't have this filter. We should warn about it!
1342 }
1343
1344 KisFilterConfigurationSP kfc = f->defaultConfiguration(KisGlobalResourcesInterface::instance());
1345 kfc->createLocalResourcesSnapshot();
1346
1347 // We'll load the configuration and the selection later.
1348 mask = new KisFilterMask(image);
1349 mask->setFilter(kfc);
1350 Q_CHECK_PTR(mask);
1351
1352 return mask;
1353}
1354
1355KisNodeSP KisKraLoader::loadTransformMask(KisImageSP image, const QDomElement& element)
1356{
1357 Q_UNUSED(element);
1358
1359 KisTransformMask* mask;
1360
1365 mask = new KisTransformMask(image, "");
1366 Q_CHECK_PTR(mask);
1367
1368 return mask;
1369}
1370
1372{
1373 Q_UNUSED(element);
1374 KisTransparencyMask* mask = new KisTransparencyMask(image, "");
1375 Q_CHECK_PTR(mask);
1376
1377 return mask;
1378}
1379
1380KisNodeSP KisKraLoader::loadSelectionMask(KisImageSP image, const QDomElement& element)
1381{
1382 KisSelectionMaskSP mask = new KisSelectionMask(image);
1383 bool active = element.attribute(ACTIVE, "1") == "0" ? false : true;
1384 mask->setActive(active);
1385 Q_CHECK_PTR(mask);
1386
1387 return mask;
1388}
1389
1390KisNodeSP KisKraLoader::loadColorizeMask(KisImageSP image, const QDomElement& element, const KoColorSpace *colorSpace)
1391{
1392 KisColorizeMaskSP mask = new KisColorizeMask(image, "");
1393 const bool editKeystrokes = element.attribute(COLORIZE_EDIT_KEYSTROKES, "1") == "0" ? false : true;
1394 const bool showColoring = element.attribute(COLORIZE_SHOW_COLORING, "1") == "0" ? false : true;
1395
1399 mask->setSectionModelProperties(props);
1400
1401 const bool useEdgeDetection = KisDomUtils::toInt(element.attribute(COLORIZE_USE_EDGE_DETECTION, "0"));
1402 const qreal edgeDetectionSize = KisDomUtils::toDouble(element.attribute(COLORIZE_EDGE_DETECTION_SIZE, "4"));
1403 const qreal radius = KisDomUtils::toDouble(element.attribute(COLORIZE_FUZZY_RADIUS, "0"));
1404 const int cleanUp = KisDomUtils::toInt(element.attribute(COLORIZE_CLEANUP, "0"));
1405 const bool limitToDevice = KisDomUtils::toInt(element.attribute(COLORIZE_LIMIT_TO_DEVICE, "0"));
1406
1407 mask->setUseEdgeDetection(useEdgeDetection);
1408 mask->setEdgeDetectionSize(edgeDetectionSize);
1409 mask->setFuzzyRadius(radius);
1410 mask->setCleanUpAmount(qreal(cleanUp) / 100.0);
1411 mask->setLimitToDeviceBounds(limitToDevice);
1412
1413 delete mask->setColorSpace(colorSpace);
1414
1415 return mask;
1416}
1417
1418void KisKraLoader::loadCompositions(const QDomElement& elem, KisImageSP image)
1419{
1420 QDomNode child;
1421
1422 for (child = elem.firstChild(); !child.isNull(); child = child.nextSibling()) {
1423
1424 QDomElement e = child.toElement();
1425 QString name = e.attribute("name");
1426 bool exportEnabled = e.attribute("exportEnabled", "1") == "0" ? false : true;
1427
1428 KisLayerCompositionSP composition(new KisLayerComposition(image, name));
1429 composition->setExportEnabled(exportEnabled);
1430
1431 QDomNode value;
1432 for (value = child.lastChild(); !value.isNull(); value = value.previousSibling()) {
1433 QDomElement e = value.toElement();
1434 QUuid uuid(e.attribute("uuid"));
1435 bool visible = e.attribute("visible", "1") == "0" ? false : true;
1436 composition->setVisible(uuid, visible);
1437 bool collapsed = e.attribute("collapsed", "1") == "0" ? false : true;
1438 composition->setCollapsed(uuid, collapsed);
1439 }
1440
1441 image->addComposition(composition);
1442 }
1443}
1444
1445void KisKraLoader::loadAssistantsList(const QDomElement &elem)
1446{
1447 QDomNode child;
1448 for (child = elem.firstChild(); !child.isNull(); child = child.nextSibling()) {
1449 QDomElement e = child.toElement();
1450 QString type = e.attribute("type");
1451 QString file_name = e.attribute("filename");
1452 m_d->assistantsFilenames.insert(file_name,type);
1453 }
1454}
1455
1456void KisKraLoader::loadGrid(const QDomElement& elem)
1457{
1458 QDomDocument dom;
1459 dom.appendChild(dom.importNode(elem, true));
1460 QDomElement domElement = dom.firstChildElement();
1461
1462 KisGridConfig config;
1463 config.loadStaticData();
1464 config.loadDynamicDataFromXml(domElement);
1465 m_d->document->setGridConfig(config);
1466}
1467
1468void KisKraLoader::loadGuides(const QDomElement& elem)
1469{
1470 QDomDocument dom;
1471 dom.appendChild(dom.importNode(elem, true));
1472 QDomElement domElement = dom.firstChildElement();
1473
1474 KisGuidesConfig guides;
1475 guides.loadFromXml(domElement);
1476 m_d->document->setGuidesConfig(guides);
1477}
1478
1479void KisKraLoader::loadMirrorAxis(const QDomElement &elem)
1480{
1481 QDomDocument dom;
1482 dom.appendChild(dom.importNode(elem, true));
1483 QDomElement domElement = dom.firstChildElement();
1484
1485 KisMirrorAxisConfig mirrorAxis;
1486 mirrorAxis.loadFromXml(domElement);
1487 m_d->document->setMirrorAxisConfig(mirrorAxis);
1488}
1489
1490void KisKraLoader::loadStoryboardItemList(const QDomElement& elem)
1491{
1492 QDomNode child;
1493 for (child = elem.firstChild(); !child.isNull(); child = child.nextSibling()) {
1494 QDomElement e = child.toElement();
1495 if (e.tagName() == "storyboarditem") {
1497 item->loadXML(e);
1498 m_d->storyboardItemList.append(item);
1499 }
1500 }
1501}
1502
1503void KisKraLoader::loadStoryboardCommentList(const QDomElement& elem)
1504{
1505 QDomNode child;
1506 for (child = elem.firstChild(); !child.isNull(); child = child.nextSibling()) {
1507 QDomElement e = child.toElement();
1508 if (e.tagName() == "storyboardcomment") {
1509 StoryboardComment comment;
1510 if (e.hasAttribute("visibility")) {
1511 comment.visibility = e.attribute("visibility").toInt();
1512 }
1513 if (e.hasAttribute("name")) {
1514 comment.name = e.attribute("name");
1515 }
1516 m_d->storyboardCommentList.append(comment);
1517 }
1518 }
1519}
1520
1521void KisKraLoader::loadAudioXML(QDomDocument &xmlDoc, QDomElement &xmlElement, KisDocument *kisDoc)
1522{
1523 Q_UNUSED(xmlDoc);
1524 QDomNode audioClip = xmlElement.firstChild();
1525 if (audioClip.nodeName() == "audioClips") {
1526 QDomElement audioClipElement = audioClip.toElement();
1527 QVector<QFileInfo> clipFiles;
1528 qreal volume = 1.0;
1529 QDomNode clip;
1530 for (clip = audioClipElement.firstChild(); !clip.isNull(); clip = clip.nextSibling()) {
1531 QDomElement clipElem = clip.toElement();
1532
1533 if (clipElem.hasAttribute("filePath")) {
1534 QFileInfo f(clipElem.attribute("filePath"));
1535 if (f.exists()) {
1536 clipFiles << f;
1537 }
1538 }
1539
1540 if (clipElem.hasAttribute("volume")) {
1541 volume = clipElem.attribute("volume").toDouble();
1542 }
1543 }
1544
1545 kisDoc->setAudioTracks(clipFiles);
1546 kisDoc->setAudioVolume(volume);
1547 }
1548}
1549
1550void KisKraLoader::loadHDRMetadata(const QDomElement &elem, KisImageSP image)
1551{
1552 QDomElement child;
1553 for (child = elem.firstChildElement(); !child.isNull(); child = child.nextSiblingElement()) {
1554 if (child.tagName() == HDRREFERENCEWHITE) {
1555 double diffWhite = 0.0;
1556 KisDomUtils::loadValue(child, &diffWhite);
1557 image->setHdrReferenceWhiteLightLevel(diffWhite);
1558 }
1559 if (child.tagName() == CONTENTLIGHTLEVEL) {
1561 clli.maxContentLightLevel = KisDomUtils::toDouble(child.attribute(MAXCLL, "0.0"));
1562 clli.maxFrameAverageLightLevel = KisDomUtils::toDouble(child.attribute(MAXFALL, "0.0"));
1563 const QString type = child.attribute(CLLI_CALCTYPE);
1564 if (type == CLLI_CALC_RGB_XYZ_FALLBACK) {
1566 } else if (type == CLLI_CALC_Rec2020) {
1568 } else {
1570 }
1572 }
1573 if (child.tagName() == COLORVOLUME) {
1575 //TODO: Kisdomutils!!!
1576 cv.maxLuminance = KisDomUtils::toDouble(child.attribute(COLORVOLUMEMAXLUMINANCE, "0.0"));
1577 cv.minLuminance = KisDomUtils::toDouble(child.attribute(COLORVOLUMEMINLUMINANCE, "0.0"));
1578
1579 QDomElement red = child.firstChildElement(COLORVOLUMERED);
1580 QDomElement green = child.firstChildElement(COLORVOLUMEGREEN);
1581 QDomElement blue = child.firstChildElement(COLORVOLUMEBLUE);
1582 QDomElement white = child.firstChildElement(COLORVOLUMEWHITE);
1583
1584 QPointF temp;
1585 if (KisDomUtils::loadValue(red, &temp)) {
1586 cv.red.x = temp.x();
1587 cv.red.y = temp.y();
1588 }
1589 if (KisDomUtils::loadValue(green, &temp)) {
1590 cv.green.x = temp.x();
1591 cv.green.y = temp.y();
1592 }
1593 if (KisDomUtils::loadValue(blue, &temp)) {
1594 cv.blue.x = temp.x();
1595 cv.blue.y = temp.y();
1596 }
1597 if (KisDomUtils::loadValue(white, &temp)) {
1598 cv.white.x = temp.x();
1599 cv.white.y = temp.y();
1600 }
1601 image->setColorVolumeInformation(cv);
1602 }
1603 }
1604}
1605
1607{
1610
1611 m_d->document->setReferenceImagesLayer(layer, false);
1612
1613 for (QDomElement child = elem.firstChildElement(); !child.isNull(); child = child.nextSiblingElement()) {
1614 if (child.nodeName().toLower() == "referenceimage") {
1615 auto* reference = KisReferenceImage::fromXml(child);
1616 reference->setZIndex(layer->shapes().size());
1617 layer->addShape(reference);
1618 }
1619 }
1620
1621 return layer;
1622}
1623
1624QList<KoColor> KisKraLoader::loadKoColors(const QDomElement &colorElement) const
1625{
1626 QList<KoColor> colors;
1627 QDomNodeList colorNodes = colorElement.childNodes();
1628 colors.reserve(colorNodes.size());
1629
1630 for (int k = 0; k < colorNodes.size(); k++) {
1631 QDomElement colorElement = colorNodes.at(k).toElement();
1632 KoColor color = KoColor::fromXML(colorElement, Integer16BitsColorDepthID.id());
1633 colors.push_back(color);
1634 }
1635
1636 return colors;
1637}
float value(const T *src, size_t ch)
const KoID Integer8BitsColorDepthID("U8", ki18n("8-bit integer/channel"))
const KoID Integer16BitsColorDepthID("U16", ki18n("16-bit integer/channel"))
const KoID CMYKAColorModelID("CMYKA", ki18n("CMYK/Alpha"))
QStringList subtractiveBlendingModesInCmyk()
the list of blendmodes that perform channel-inversion in CMYK color space
const quint8 OPACITY_TRANSPARENT_U8
const quint8 OPACITY_OPAQUE_U8
const QString DESCRIPTION
char nodeType(const KoPathPoint *point)
A data extension mechanism for Krita.
void assignAllLayerStylesToLayers(KisNodeSP root, const QString &storageLocation)
KisBaseNode::PropertyList sectionModelProperties() const override
void setEdgeDetectionSize(qreal value)
void setLimitToDeviceBounds(bool value)
void setSectionModelProperties(const KisBaseNode::PropertyList &properties) override
void setUseEdgeDetection(bool value)
void setFuzzyRadius(qreal value)
KUndo2Command * setColorSpace(const KoColorSpace *dstColorSpace, KoColorConversionTransformation::Intent renderingIntent=KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::ConversionFlags conversionFlags=KoColorConversionTransformation::internalConversionFlags(), KoUpdater *progressUpdater=nullptr)
void setCleanUpAmount(qreal value)
The KisCursorOverrideHijacker class stores all override cursors in a stack, and resets them back afte...
KisUndoStore * createUndoStore()
KoDocumentInfo * documentInfo() const
KisImageSP image
QString linkedResourcesStorageId() const
KisShapeController * shapeController
void setAudioTracks(QVector< QFileInfo > f)
QString localFilePath() const
void setMirrorAxisConfig(const KisMirrorAxisConfig &config)
void setAssistantsGlobalColor(QColor color)
void setReferenceImagesLayer(KisSharedPtr< KisReferenceImagesLayer > layer, bool updateImage)
QString path() const
void setColorHistoryColors(const QList< KoColor > &colors)
QColor assistantsGlobalColor()
QString embeddedResourcesStorageId() const
void setGridConfig(const KisGridConfig &config)
void setAudioVolume(qreal level)
void setGuidesConfig(const KisGuidesConfig &data)
void setPaletteList(const QList< KoColorSetSP > &paletteList, bool emitSignal=false)
setPaletteList replaces the palettes in the document's local resource storage with the list of palett...
The KisFileLayer class loads a particular file as a layer into the layer stack.
void setFilter(KisFilterConfigurationSP filterConfig, bool checkCompareConfig=true) override
static KisFilterRegistry * instance()
static KisGeneratorRegistry * instance()
static KisResourcesInterfaceSP instance()
bool loadDynamicDataFromXml(const QDomElement &parent)
bool loadFromXml(const QDomElement &parent)
void setExportSequenceBaseName(const QString &baseName)
void switchCurrentTimeAsync(int frameId, SwitchTimeAsyncFlags options=STAO_NONE)
void setDocumentRange(const KisTimeSpan range)
void setExportInitialFrameNumber(const int frameNum)
void setExportSequenceFilePath(const QString &filePath)
KisProofingConfigurationSP defaultProofingconfiguration(bool requestDefault=false)
void setColorVolumeInformation(const std::optional< KisColorVolumeInformation > cvi)
Set the color volume information.
void addAnnotation(KisAnnotationSP annotation)
void setHdrReferenceWhiteLightLevel(const std::optional< double > value)
Set the diffuse white light level, in cd/m²
KisGroupLayerSP rootLayer() const
const KoColorSpace * colorSpace() const
KisImageAnimationInterface * animationInterface() const
void setDefaultProjectionColor(const KoColor &color)
void setProofingConfiguration(KisProofingConfigurationSP proofingConfig)
setProofingConfiguration, this sets the image's proofing configuration, and signals the proofingConfi...
void addComposition(KisLayerCompositionSP composition)
void setRelativeContentLightLevelInformation(const std::optional< KisRelativeContentLightLevelInformation > clli)
void setResolution(double xres, double yres)
void convertImageProjectionColorSpace(const KoColorSpace *dstColorSpace)
KisProofingConfigurationSP proofingConfiguration() const
proofingConfiguration
static QString askForAudioFileName(const QString &defaultDir, QWidget *parent)
static QStringList supportedMimeTypes(Direction direction)
void setExternalUri(const QString &uri)
QStringList warningMessages() const
static QHash< QString, QString > customProfileNameAliasForKra()
QStringList errorMessages() const
KisNodeSP loadFilterMask(KisImageSP image, const QDomElement &elem)
KisImageSP loadXML(const QDomElement &imageElement)
KisNodeSP loadNodes(const QDomElement &element, KisImageSP image, KisNodeSP parent)
void loadAnimationMetadata(KoStore *store, KisImageSP image)
KisNodeSP loadFileLayer(const QDomElement &elem, KisImageSP image, const QString &name, quint32 opacity, const KoColorSpace *fallbackColorSpace)
KisNodeSP loadShapeLayer(const QDomElement &elem, KisImageSP image, const QString &name, const KoColorSpace *cs, quint32 opacity)
void loadAudioXML(QDomDocument &xmlDoc, QDomElement &xmlElement, KisDocument *kisDoc)
void loadCompositions(const QDomElement &elem, KisImageSP image)
KisNodeSP loadColorizeMask(KisImageSP image, const QDomElement &elem, const KoColorSpace *colorSpace)
void loadAssistantsList(const QDomElement &elem)
void loadStoryboardItemList(const QDomElement &elem)
QStringList errorMessages() const
if empty, loading didn't fail...
KisNodeSP loadCloneLayer(const QDomElement &elem, KisImageSP image, const QString &name, const KoColorSpace *cs, quint32 opacity)
KisNodeSP loadGeneratorLayer(const QDomElement &elem, KisImageSP image, const QString &name, const KoColorSpace *cs, quint32 opacity)
void loadStoryboards(KoStore *store, KisDocument *doc)
KisNodeSP loadPaintLayer(const QDomElement &elem, KisImageSP image, const QString &name, const KoColorSpace *cs, quint32 opacity)
QString imageName() const
QStringList warningMessages() const
if not empty, loading didn't fail, but there are problems
void loadGuides(const QDomElement &elem)
void loadGrid(const QDomElement &elem)
KisNodeSP loadNode(const QDomElement &elem, KisImageSP image)
KisKraLoader(KisDocument *document, int syntaxVersion, const QVersionNumber &kritaVersion)
void loadBinaryData(KoStore *store, KisImageSP image, const QString &uri, bool external)
vKisNodeSP selectedNodes() const
void loadResources(KoStore *store, KisDocument *doc)
void loadMirrorAxis(const QDomElement &elem)
void loadAnimationMetadataFromXML(const QDomElement &element, KisImageSP image)
void loadStoryboardCommentList(const QDomElement &elem)
KisNodeSP loadSelectionMask(KisImageSP image, const QDomElement &elem)
StoryboardItemList storyboardItemList() const
KisNodeSP loadTransformMask(KisImageSP image, const QDomElement &elem)
Private *const m_d
KisNodeSP loadGroupLayer(const QDomElement &elem, KisImageSP image, const QString &name, const KoColorSpace *cs, quint32 opacity)
QList< KoColor > loadKoColors(const QDomElement &elem) const
KisNodeSP loadReferenceImagesLayer(const QDomElement &elem, KisImageSP image)
void loadHDRMetadata(const QDomElement &elem, KisImageSP image)
KisNodeSP loadTransparencyMask(KisImageSP image, const QDomElement &elem)
Q_DECL_DEPRECATED void backCompat_loadAudio(const QDomElement &elem, KisDocument *document)
void loadAssistants(KoStore *store, const QString &uri, bool external)
QList< KisPaintingAssistantSP > assistants() const
StoryboardCommentList storyboardCommentList() const
KisNodeSP loadAdjustmentLayer(const QDomElement &elem, KisImageSP image, const QString &name, const KoColorSpace *cs, quint32 opacity)
void loadAudio(KoStore *store, KisDocument *kisDoc)
static void setNodeProperty(KisBaseNode::PropertyList *props, const KoID &id, const QVariant &value)
The KisMirrorAxisConfig class stores configuration for the KisMirrorAxis canvas decoration....
bool loadFromXml(const QDomElement &parent)
loadFromXml() function for KisKraLoader
static KisNodeViewColorScheme * instance()
QVector< QColor > allColorLabels() const
static KisPaintingAssistantFactoryRegistry * instance()
virtual KisPaintingAssistant * createPaintingAssistant() const =0
void setAssistantGlobalColorCache(const QColor &color)
virtual int numHandles() const =0
void loadXml(KoStore *store, QMap< int, KisPaintingAssistantHandleSP > &handleMap, QString path)
const QList< KisPaintingAssistantHandleSP > & handles() const
@ Custom
Let artists configure their own.
@ Paper
Whether to use Paper settings (absolute colorimetric, 0% adaptation.)
@ Monitor
Whether to use monitor rendering intent and flags for the second transform.
static KisReferenceImage * fromXml(const QDomElement &elem)
The KisResourceModel class provides the main access to resources. It is possible to filter the resour...
QVector< KoResourceSP > resourcesForMD5(const QString md5sum) const
KoResourceSP importResource(const QString &filename, QIODevice *device, const bool allowOverwrite, const QString &storageId=QString("")) override
importResource imports a resource from a QIODevice
void setAntialiased(const bool antialiased)
virtual KoID colorModelId() const =0
virtual quint32 channelCount() const =0
virtual KoID colorDepthId() const =0
static KoColor fromXML(const QDomElement &elt, const QString &channelDepthId)
Definition KoColor.cpp:350
static const KoCompositeOpRegistry & instance()
void setAboutInfo(const QString &info, const QString &data)
QString aboutInfo(const QString &info) const
const T value(const QString &id) const
T get(const QString &id) const
QString id() const
Definition KoID.cpp:63
A simple wrapper object for the main information about the resource.
void close() override
bool open(OpenMode m) override
QIODevice * device() const
Definition KoStore.cpp:171
bool close()
Definition KoStore.cpp:156
qint64 size() const
Definition KoStore.cpp:239
bool isOpen() const
Definition KoStore.cpp:150
bool hasFile(const QString &fileName) const
Definition KoStore.cpp:384
bool open(const QString &name)
Definition KoStore.cpp:109
QByteArray read(qint64 max)
Definition KoStore.cpp:181
This class stores a list of StoryboardChild objects and provides functionality to manipulate the list...
This file is part of the Krita application in calligra.
#define KIS_ASSERT(cond)
Definition kis_assert.h:33
CopyLayerType
#define warnFile
Definition kis_debug.h:99
#define warnKrita
Definition kis_debug.h:91
#define dbgFile
Definition kis_debug.h:56
void convertColorSpaceNames(QString &colorspacename, QString &profileProductName)
QSharedPointer< T > toQShared(T *ptr)
KisSharedPtr< KisAnnotation > KisAnnotationSP
Definition kis_types.h:179
KisSharedPtr< KisImage > KisImageSP
Definition kis_types.h:69
const QString COLORIZE_CLEANUP
const QString TRANSPARENCY_MASK
const QString COLORVOLUMEBLUE
const QString COLORIZE_FUZZY_RADIUS
const QString Y
const QString CLLI_CALC_RGB_XYZ_FALLBACK
const QString GENERATOR_NAME
const QString FILTER_NAME
const QString CLLI_CALC_Rec2020
const QString PALETTES
const QString PROOFINGPROFILENAME
const QString COLORHISTORY
const QString CANVASPROJECTIONCOLOR
const QString COLORVOLUMERED
const QString CLONE_FROM
const QString CLONE_TYPE
const QString CLONE_FROM_UUID
const QString COLORBYTEDATA
const QString PROOFINGBLACKPOINTCOMPENSATION
const QString NAME
const QString COLORVOLUMEMAXLUMINANCE
const QString ICC_PROOFING_PATH
const QString VISIBLE
const QString COLORIZE_EDIT_KEYSTROKES
const QString Y_RESOLUTION
const QString HEIGHT
const QString ASSISTANTS_PATH
const QString FILE_LAYER
const QString COLOR_LABEL
const QString OPACITY
const QString PROOFINGDEPTH
const QString ANIMATION_METADATA_PATH
const QString NATIVE_MIMETYPE
const QString LAYER_STYLES_PATH
const QString X_RESOLUTION
const QString STORYBOARD_PATH
const QString X
const QString RESOURCES
const QString FILE_NAME
const QString ANNOTATIONS_PATH
const QString PROOFINGDISPLAYBLACKPOINTCOMPENSATION
const QString PASS_THROUGH_MODE
const QString COLORIZE_EDGE_DETECTION_SIZE
const QString PROOFINGDISPLAYMODE
const QString MAXCLL
const QString HDRREFERENCEWHITE
const QString CONTENTLIGHTLEVEL
const QString COMPOSITE_OP
const QString ICC_PATH
const QString PROOFINGWARNINGCOLOR
const QString KEYFRAME_FILE
const QString COLORVOLUMEGREEN
const QString PAINT_LAYER
const QString COLORVOLUME
const QString PROOFINGDISPLAYINTENT
const QString GROUP_LAYER
const QString VISIBLE_IN_TIMELINE
const QString LOCKED
const QString COLORIZE_MASK
QBitArray stringToFlags(const QString &string, int size=-1, char token='0', bool defaultTrue=true)
const QString NODE_TYPE
const QString WIDTH
const QString EXIF_PATH
const QString MIME
const QString CHANNEL_LOCK_FLAGS
const QString GLOBALASSISTANTSCOLOR
const QString COLLAPSED
const QString ANNOTATIONS
const QString TRANSFORM_MASK
const QString COLORIZE_SHOW_COLORING
const QString COLORVOLUMEWHITE
const QString ONION_SKIN_ENABLED
const QString RESOURCE_PATH
const QString LAYERS
const QString PROOFINGMODEL
const QString AUDIO_PATH
const QString REFERENCE_IMAGES_LAYER
const QString COLORIZE_USE_EDGE_DETECTION
const QString PALETTE_PATH
const QString COLORVOLUMEMINLUMINANCE
const QString PROOFINGINTENT
const QString HDRMETADATA
const QString ANTIALIASED
const QString FILTER_MASK
const QString ACTIVE
const QString MIRROR_AXIS
const QString MAXFALL
const QString SIMPLECOLORDATA
const QString UUID
const QString PROOFINGADAPTATIONSTATE
const QString CLONE_LAYER
const QString SHAPE_LAYER
const QString GENERATOR_LAYER
const QString PROFILE
const QString COLORSPACE_NAME
const QString SELECTION_MASK
const QString COLORIZE_LIMIT_TO_DEVICE
const QString CLLI_CALCTYPE
const QString LAYER_STYLE_UUID
const QString MASKS
const QString CHANNEL_FLAGS
const QString ADJUSTMENT_LAYER
QColor qStringToQColor(QString colorString)
double toDouble(const QString &str, bool *ok=nullptr)
int toInt(const QString &str, bool *ok=nullptr)
bool loadValue(const QDomElement &e, float *v)
void setPinnedToTimeline(bool pinned)
virtual void setUserLocked(bool l)
void setOpacity(quint8 val)
virtual void setVisible(bool visible, bool loading=false)
virtual void setX(qint32)
void setUuid(const QUuid &id)
virtual void setY(qint32)
void setColorLabelIndex(int index)
void setName(const QString &name)
void setCollapsed(bool collapsed)
QString name() const
void setCompositeOpId(const QString &compositeOpId)
virtual KisFilterConfigurationSP defaultConfiguration(KisResourcesInterfaceSP resourcesInterface) const
The KisColorVolumeInformation class is a struct that represents the 'mastering' display....
double maxLuminance
Maximum screen brightness in cd/m²
KoColorimetryUtils::xy blue
xyY location of the blue colorant.
double minLuminance
Minimum screen brightness in cd/m²
KoColorimetryUtils::xy white
xyY location of the whitepoint.
KoColorimetryUtils::xy red
xyY location of the red colorant.
KoColorimetryUtils::xy green
xyY location of the green colorant.
bool accept(KisNodeVisitor &v) override
void setPassThroughMode(bool value)
StoryboardCommentList storyboardCommentList
QList< KisPaintingAssistantSP > assistants
QMap< KisNode *, QString > keyframeFilenames
QVersionNumber kritaVersion
QVector< QString > paletteFilenames
QMap< KisNode *, QString > layerFilenames
StoryboardItemList storyboardItemList
QList< KisAnnotationSP > annotations
QVector< KoResourceSignature > resources
QMap< QString, QString > assistantsFilenames
virtual void setChannelFlags(const QBitArray &channelFlags)
Definition kis_layer.cc:342
void setLayerStyle(KisPSDLayerStyleSP layerStyle)
Definition kis_layer.cc:254
bool addNode(KisNodeSP node, KisNodeSP parent=KisNodeSP(), KisNodeAdditionFlags flags=KisNodeAdditionFlag::None)
QList< KisNodeSP > childNodes(const QStringList &nodeTypes, const KoProperties &properties) const
Definition kis_node.cpp:439
quint32 childCount() const
Definition kis_node.cpp:414
The KisPSDLayerStyle class implements loading, saving and applying the PSD layer effects.
void setChannelLockFlags(const QBitArray &channelFlags)
void setOnionSkinEnabled(bool state)
@ XYZLuminance
Calculate luminance by converting to xyz.
@ Rec2020Component
Calculate luminance by converting to rec2020.
@ RGBComponent
Calculate luminance on the RGB components if possible.
double maxFrameAverageLightLevel
maxFrameAverage MaxFrameAverageLightLevel or MaxFALL is the average of average pixel brightnesses in ...
void setActive(bool active)
virtual bool valid() const =0
const KoColorSpace * colorSpace(const QString &colorModelId, const QString &colorDepthId, const KoColorProfile *profile)
static KoColorSpaceRegistry * instance()
KoID colorSpaceColorDepthId(const QString &_colorSpaceId) const
KoID colorSpaceColorModelId(const QString &_colorSpaceId) const
const KoColorProfile * createColorProfile(const QString &colorModelId, const QString &colorDepthId, const QByteArray &rawData)