File indexing completed on 2024-12-22 04:15:46

0001 /*
0002  *  SPDX-FileCopyrightText: 2002 Patrick Julien <freak@codepimps.org>
0003  *  SPDX-FileCopyrightText: 2005 C. Boemann <cbo@boemann.dk>
0004  *
0005  *  SPDX-License-Identifier: GPL-2.0-or-later
0006  */
0007 
0008 #include "kis_kra_load_visitor.h"
0009 #include "kis_kra_tags.h"
0010 #include "flake/kis_shape_layer.h"
0011 #include "flake/KisReferenceImagesLayer.h"
0012 #include "KisReferenceImage.h"
0013 #include <KisImportExportManager.h>
0014 
0015 #include <QRect>
0016 #include <QBuffer>
0017 #include <QByteArray>
0018 #include <QMessageBox>
0019 #include <QApplication>
0020 
0021 #include <KoMD5Generator.h>
0022 #include <KoColorSpaceRegistry.h>
0023 #include <KoColorProfile.h>
0024 #include <KoFileDialog.h>
0025 #include <KoStore.h>
0026 #include <KoColorSpace.h>
0027 #include <KoShapeControllerBase.h>
0028 #include <KisGlobalResourcesInterface.h>
0029 
0030 // kritaimage
0031 #include "kis_colorize_dom_utils.h"
0032 #include "kis_dom_utils.h"
0033 #include "kis_filter_registry.h"
0034 #include "kis_generator_registry.h"
0035 #include "kis_paint_device_frames_interface.h"
0036 #include "kis_raster_keyframe_channel.h"
0037 #include "kis_shape_selection.h"
0038 #include "kis_transform_mask_params_factory_registry.h"
0039 #include <filter/kis_filter_configuration.h>
0040 #include <generator/kis_generator_layer.h>
0041 #include <kis_adjustment_layer.h>
0042 #include <kis_clone_layer.h>
0043 #include <kis_datamanager.h>
0044 #include <kis_filter_mask.h>
0045 #include <kis_group_layer.h>
0046 #include <kis_image.h>
0047 #include <kis_layer.h>
0048 #include <kis_meta_data_backend_registry.h>
0049 #include <kis_meta_data_store.h>
0050 #include <kis_node_visitor.h>
0051 #include <kis_paint_layer.h>
0052 #include <kis_pixel_selection.h>
0053 #include <kis_selection.h>
0054 #include <kis_selection_mask.h>
0055 #include <kis_transform_mask.h>
0056 #include <kis_transform_mask_params_interface.h>
0057 #include <kis_transparency_mask.h>
0058 #include <kis_types.h>
0059 #include <lazybrush/kis_colorize_mask.h>
0060 #include <lazybrush/kis_lazy_fill_tools.h>
0061 
0062 using namespace KRA;
0063 
0064 QString expandEncodedDirectory(const QString& _intern)
0065 {
0066 
0067     QString intern = _intern;
0068 
0069     QString result;
0070     int pos;
0071     while ((pos = intern.indexOf('/')) != -1) {
0072         if (QChar(intern.at(0)).isDigit())
0073             result += "part";
0074         result += intern.left(pos + 1);   // copy numbers (or "pictures") + "/"
0075         intern = intern.mid(pos + 1);   // remove the dir we just processed
0076     }
0077 
0078     if (!intern.isEmpty() && QChar(intern.at(0)).isDigit())
0079         result += "part";
0080     result += intern;
0081 
0082     return result;
0083 }
0084 
0085 
0086 KisKraLoadVisitor::KisKraLoadVisitor(KisImageSP image,
0087                                      KoStore *store,
0088                                      KoShapeControllerBase *shapeController,
0089                                      QMap<KisNode *, QString> &layerFilenames,
0090                                      QMap<KisNode *, QString> &keyframeFilenames,
0091                                      const QString & name,
0092                                      int syntaxVersion)
0093     : KisNodeVisitor()
0094     , m_image(image)
0095     , m_store(store)
0096     , m_external(false)
0097     , m_layerFilenames(layerFilenames)
0098     , m_keyframeFilenames(keyframeFilenames)
0099     , m_name(name)
0100     , m_shapeController(shapeController)
0101 {
0102     m_store->pushDirectory();
0103 
0104     if (!m_store->enterDirectory(m_name)) {
0105         QStringList directories = m_store->directoryList();
0106         dbgKrita << directories;
0107         if (directories.size() > 0) {
0108             dbgFile << "Could not locate the directory, maybe some encoding issue? Grab the first directory, that'll be the image one." << m_name << directories;
0109             m_name = directories.first();
0110         }
0111         else {
0112             dbgFile << "Could not enter directory" << m_name << ", probably an old-style file with 'part' added.";
0113             m_name = expandEncodedDirectory(m_name);
0114         }
0115     }
0116     else {
0117         m_store->popDirectory();
0118     }
0119     m_syntaxVersion = syntaxVersion;
0120 }
0121 
0122 void KisKraLoadVisitor::setExternalUri(const QString &uri)
0123 {
0124     m_external = true;
0125     m_uri = uri;
0126 }
0127 
0128 bool KisKraLoadVisitor::visit(KisExternalLayer * layer)
0129 {
0130     bool result = false;
0131 
0132     if (auto *referencesLayer = dynamic_cast<KisReferenceImagesLayer*>(layer)) {
0133         Q_FOREACH(KoShape *shape, referencesLayer->shapes()) {
0134             auto *reference = dynamic_cast<KisReferenceImage*>(shape);
0135             KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(reference, false);
0136 
0137             while (!reference->loadImage(m_store)) {
0138                 if (reference->embed()) {
0139                     m_errorMessages << i18n("Could not load embedded reference image %1 ", reference->internalFile());
0140                     break;
0141                 } else {
0142                     QString msg = i18nc(
0143                         "@info",
0144                         "A reference image linked to an external file could not be loaded.\n\n"
0145                         "Path: %1\n\n"
0146                         "Do you want to select another location?", reference->filename());
0147 
0148                     // qApp->activeWindow() doesn't work here
0149                     int locateManually = QMessageBox::warning(qApp->activeWindow(), i18nc("@title:window", "File not found"), msg, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
0150 
0151                     QString url;
0152                     if (locateManually == QMessageBox::Yes) {
0153                         KoFileDialog dialog(0, KoFileDialog::OpenFile, "OpenDocument");
0154                         dialog.setMimeTypeFilters(KisImportExportManager::supportedMimeTypes(KisImportExportManager::Import));
0155                         url = dialog.filename();
0156                     }
0157 
0158                     if (url.isEmpty()) {
0159                         break;
0160                     } else {
0161                         reference->setFilename(url);
0162                         reference->setEmbed(false);
0163                     }
0164                 }
0165             }
0166         }
0167     } else if (KisShapeLayer *shapeLayer = dynamic_cast<KisShapeLayer*>(layer)) {
0168         loadNodeKeyframes(shapeLayer);
0169 
0170         if (!loadMetaData(layer)) {
0171             return false;
0172         }
0173 
0174         QStringList vectorWarnings;
0175 
0176         m_store->pushDirectory();
0177         m_store->enterDirectory(getLocation(layer, DOT_SHAPE_LAYER)) ;
0178         result =  shapeLayer->loadLayer(m_store, &vectorWarnings);
0179         m_store->popDirectory();
0180 
0181         m_warningMessages << vectorWarnings;
0182     }
0183 
0184     result = visitAll(layer) && result;
0185     return result;
0186 }
0187 
0188 bool KisKraLoadVisitor::visit(KisPaintLayer *layer)
0189 {
0190     loadNodeKeyframes(layer);
0191 
0192     if (!loadPaintDevice(layer->paintDevice(), getLocation(layer))) {
0193         return false;
0194     }
0195     if (!loadProfile(layer->paintDevice(), getLocation(layer, DOT_ICC))) {
0196         return false;
0197     }
0198     if (!loadMetaData(layer)) {
0199         return false;
0200     }
0201 
0202     if (m_syntaxVersion == 1) {
0203         // Check whether there is a file with a .mask extension in the
0204         // layer directory, if so, it's an old-style transparency mask
0205         // that should be converted.
0206         QString location = getLocation(layer, ".mask");
0207 
0208         if (m_store->open(location)) {
0209 
0210             KisSelectionSP selection = KisSelectionSP(new KisSelection());
0211             KisPixelSelectionSP pixelSelection = selection->pixelSelection();
0212             if (!pixelSelection->read(m_store->device())) {
0213                 pixelSelection->disconnect();
0214             } else {
0215                 KisTransparencyMask* mask = new KisTransparencyMask(m_image, i18n("Transparency Mask"));
0216                 mask->setSelection(selection);
0217                 m_image->addNode(mask, layer, layer->firstChild());
0218             }
0219             m_store->close();
0220         }
0221     }
0222     bool result = visitAll(layer);
0223     return result;
0224 }
0225 
0226 bool KisKraLoadVisitor::visit(KisGroupLayer *layer)
0227 {
0228     loadNodeKeyframes(layer);
0229 
0230     if (*layer->colorSpace() != *m_image->colorSpace()) {
0231         layer->resetCache(m_image->colorSpace());
0232     }
0233 
0234     if (!loadMetaData(layer)) {
0235         return false;
0236     }
0237 
0238     bool result = visitAll(layer);
0239     return result;
0240 }
0241 
0242 bool KisKraLoadVisitor::visit(KisAdjustmentLayer* layer)
0243 {
0244     loadNodeKeyframes(layer);
0245 
0246     // Adjustmentlayers are tricky: there's the 1.x style and the 2.x
0247     // style, which has selections with selection components
0248     bool result = true;
0249     if (m_syntaxVersion == 1) {
0250         KisSelectionSP selection = new KisSelection();
0251         KisPixelSelectionSP pixelSelection = selection->pixelSelection();
0252         result = loadPaintDevice(pixelSelection, getLocation(layer, ".selection"));
0253         layer->setInternalSelection(selection);
0254     } else if (m_syntaxVersion == 2) {
0255         result = loadSelection(getLocation(layer), layer->internalSelection());
0256 
0257     } else {
0258         // We use the default, empty selection
0259     }
0260 
0261     if (!result) {
0262         m_warningMessages.append(i18nc("Warning during loading a kra file with a filter layer",
0263                                        "Selection on layer %s couldn't be loaded. It will be replaced by an empty selection.", layer->name()));
0264         // otherwise ignore and just use what is there already
0265         // (most probably an empty selection)
0266     }
0267 
0268     if (!loadMetaData(layer)) {
0269         return false;
0270     }
0271 
0272     KisFilterSP filter = KisFilterRegistry::instance()->value(layer->filter()->name());
0273     KisFilterConfigurationSP  kfc = filter->factoryConfiguration(KisGlobalResourcesInterface::instance());
0274 
0275     loadFilterConfiguration(kfc, getLocation(layer, DOT_FILTERCONFIG));
0276     fixOldFilterConfigurations(kfc);
0277     kfc->createLocalResourcesSnapshot();
0278 
0279     layer->setFilter(kfc);
0280 
0281     result = visitAll(layer);
0282     return result;
0283 }
0284 
0285 bool KisKraLoadVisitor::visit(KisGeneratorLayer *layer)
0286 {
0287     if (!loadMetaData(layer)) {
0288         return false;
0289     }
0290     bool result = true;
0291 
0292     loadNodeKeyframes(layer);
0293     result = loadSelection(getLocation(layer), layer->internalSelection());
0294 
0295     KisGeneratorSP filter = KisGeneratorRegistry::instance()->value(layer->filter()->name());
0296     KisFilterConfigurationSP  kfc = filter->factoryConfiguration(KisGlobalResourcesInterface::instance());
0297 
0298     result = loadFilterConfiguration(kfc, getLocation(layer, DOT_FILTERCONFIG));
0299     kfc->createLocalResourcesSnapshot();
0300 
0301     layer->setFilter(kfc);
0302 
0303     result = visitAll(layer);
0304     return result;
0305 }
0306 
0307 bool KisKraLoadVisitor::visit(KisCloneLayer *layer)
0308 {
0309     if (!loadMetaData(layer)) {
0310         return false;
0311     }
0312 
0313     // the layer might have already been lazily initialized
0314     // from the mask loading code
0315     if (layer->copyFrom()) {
0316         return true;
0317     }
0318 
0319     KisNodeSP srcNode = layer->copyFromInfo().findNode(m_image->rootLayer());
0320     if (!srcNode.isNull()) {
0321         KisLayerSP srcLayer = qobject_cast<KisLayer*>(srcNode.data());
0322         Q_ASSERT(srcLayer);
0323 
0324         layer->setCopyFrom(srcLayer);
0325     } else {
0326         m_warningMessages.append(i18nc("Loading a .kra file", "The file contains a clone layer that has an incorrect source node id. "
0327                                                               "This layer will be converted into a paint layer."));
0328     }
0329 
0330     // Clone layers have no data except for their masks
0331     bool result = visitAll(layer);
0332     return result;
0333 }
0334 
0335 void KisKraLoadVisitor::initSelectionForMask(KisMask *mask)
0336 {
0337     KisLayer *cloneLayer = dynamic_cast<KisCloneLayer*>(mask->parent().data());
0338     if (cloneLayer) {
0339         // the clone layers should be initialized out of order
0340         // and lazily, because their original() is still not
0341         // initialized
0342         cloneLayer->accept(*this);
0343     }
0344 
0345     KisLayer *parentLayer = qobject_cast<KisLayer*>(mask->parent().data());
0346     // the KisKraLoader must have already set the parent for us
0347     Q_ASSERT(parentLayer);
0348     mask->initSelection(parentLayer);
0349 }
0350 
0351 bool KisKraLoadVisitor::visit(KisFilterMask *mask)
0352 {
0353     initSelectionForMask(mask);
0354 
0355     loadNodeKeyframes(mask);
0356 
0357     bool result = true;
0358     result = loadSelection(getLocation(mask), mask->selection());
0359 
0360     KisFilterSP filter = KisFilterRegistry::instance()->value(mask->filter()->name());
0361     KisFilterConfigurationSP  kfc = filter->factoryConfiguration(KisGlobalResourcesInterface::instance());
0362     result = loadFilterConfiguration(kfc, getLocation(mask, DOT_FILTERCONFIG));
0363     fixOldFilterConfigurations(kfc);
0364     kfc->createLocalResourcesSnapshot();
0365 
0366     mask->setFilter(kfc);
0367 
0368     return result;
0369 }
0370 
0371 bool KisKraLoadVisitor::visit(KisTransformMask *mask)
0372 {
0373     QString location = getLocation(mask, DOT_TRANSFORMCONFIG);
0374     if (m_store->hasFile(location)) {
0375         QByteArray data;
0376         m_store->open(location);
0377         data = m_store->read(m_store->size());
0378         m_store->close();
0379         if (!data.isEmpty()) {
0380             QDomDocument doc;
0381             doc.setContent(data);
0382 
0383             QDomElement rootElement = doc.documentElement();
0384 
0385             QDomElement main;
0386 
0387             if (!KisDomUtils::findOnlyElement(rootElement, "main", &main/*, &m_errorMessages*/)) {
0388                 return false;
0389             }
0390 
0391             QString id = main.attribute("id", "not-valid");
0392 
0393             // backward compatibility
0394             if (id == "animatedtransformparams") {
0395                 id = "tooltransformparams";
0396             }
0397             if (id == "not-valid") {
0398                 m_errorMessages << i18n("Could not load \"id\" of the transform mask");
0399                 return false;
0400             }
0401 
0402             QDomElement data;
0403 
0404             if (!KisDomUtils::findOnlyElement(rootElement, "data", &data, &m_errorMessages)) {
0405                 return false;
0406             }
0407 
0408             KisTransformMaskParamsInterfaceSP params =
0409                 KisTransformMaskParamsFactoryRegistry::instance()->createParams(id, data);
0410 
0411             if (!params) {
0412                 m_errorMessages << i18n("Could not create transform mask params");
0413                 return false;
0414             }
0415 
0416             mask->setTransformParams(params);
0417 
0418             loadNodeKeyframes(mask);
0419 
0420             return true;
0421         }
0422     }
0423 
0424     return false;
0425 }
0426 
0427 bool KisKraLoadVisitor::visit(KisTransparencyMask *mask)
0428 {
0429     initSelectionForMask(mask);
0430 
0431     loadNodeKeyframes(mask);
0432 
0433     return loadSelection(getLocation(mask), mask->selection());
0434 }
0435 
0436 bool KisKraLoadVisitor::visit(KisSelectionMask *mask)
0437 {
0438     initSelectionForMask(mask);
0439     return loadSelection(getLocation(mask), mask->selection());
0440 }
0441 
0442 bool KisKraLoadVisitor::visit(KisColorizeMask *mask)
0443 {
0444     m_store->pushDirectory();
0445     QString location = getLocation(mask, DOT_COLORIZE_MASK);
0446     m_store->enterDirectory(location) ;
0447 
0448     QByteArray data;
0449     if (!m_store->extractFile("content.xml", data))
0450         return false;
0451 
0452     QDomDocument doc;
0453     if (!doc.setContent(data))
0454         return false;
0455 
0456     QVector<KisLazyFillTools::KeyStroke> strokes;
0457     if (!KisDomUtils::loadValue(doc.documentElement(),
0458                                 COLORIZE_KEYSTROKES_SECTION,
0459                                 &strokes,
0460                                 mask->colorSpace(),
0461                                 QPoint(mask->x(), mask->y()))) {
0462         return false;
0463     }
0464 
0465     int i = 0;
0466     Q_FOREACH (const KisLazyFillTools::KeyStroke &stroke, strokes) {
0467         const QString fileName = QString("%1_%2").arg(COLORIZE_KEYSTROKE).arg(i++);
0468         loadPaintDevice(stroke.dev, fileName);
0469     }
0470 
0471     mask->setKeyStrokesDirect(QList<KisLazyFillTools::KeyStroke>::fromVector(strokes));
0472 
0473     loadPaintDevice(mask->coloringProjection(), COLORIZE_COLORING_DEVICE);
0474 
0475     const KoColorProfile *profile =
0476         loadProfile(getLocation(mask, DOT_ICC), mask->colorSpace()->colorModelId().id(), mask->colorSpace()->colorDepthId().id());
0477 
0478     if (!profile) {
0479         KisNodeSP parent = mask->parent();
0480         KIS_SAFE_ASSERT_RECOVER(parent) {
0481             parent = m_image->root();
0482         }
0483 
0484         if (parent->colorSpace()->colorModelId() == mask->colorSpace()->colorModelId() &&
0485             parent->colorSpace()->colorDepthId() == mask->colorSpace()->colorDepthId()) {
0486 
0487             profile = parent->colorSpace()->profile();
0488         }
0489     }
0490 
0491     if (!profile) {
0492         if (m_image->colorSpace()->colorModelId() == mask->colorSpace()->colorModelId() &&
0493             m_image->colorSpace()->colorDepthId() == mask->colorSpace()->colorDepthId()) {
0494 
0495             profile = m_image->colorSpace()->profile();
0496         }
0497     }
0498 
0499     if (profile) {
0500         mask->setProfile(profile, 0);
0501     }
0502 
0503     mask->resetCache();
0504 
0505     m_store->popDirectory();
0506     return true;
0507 }
0508 
0509 QStringList KisKraLoadVisitor::errorMessages() const
0510 {
0511     return m_errorMessages;
0512 }
0513 
0514 QStringList KisKraLoadVisitor::warningMessages() const
0515 {
0516     return m_warningMessages;
0517 }
0518 
0519 struct SimpleDevicePolicy
0520 {
0521     bool read(KisPaintDeviceSP dev, QIODevice *stream) {
0522         return dev->read(stream);
0523     }
0524 
0525     void setDefaultPixel(KisPaintDeviceSP dev, const KoColor &defaultPixel) const {
0526         return dev->setDefaultPixel(defaultPixel);
0527     }
0528 };
0529 
0530 struct FramedDevicePolicy
0531 {
0532     FramedDevicePolicy(int frameId)
0533         :  m_frameId(frameId) {}
0534 
0535     bool read(KisPaintDeviceSP dev, QIODevice *stream) {
0536         return dev->framesInterface()->readFrame(stream, m_frameId);
0537     }
0538 
0539     void setDefaultPixel(KisPaintDeviceSP dev, const KoColor &defaultPixel) const {
0540         return dev->framesInterface()->setFrameDefaultPixel(defaultPixel, m_frameId);
0541     }
0542 
0543     int m_frameId;
0544 };
0545 
0546 bool KisKraLoadVisitor::loadPaintDevice(KisPaintDeviceSP device, const QString& location)
0547 {
0548     // Layer data
0549     KisPaintDeviceFramesInterface *frameInterface = device->framesInterface();
0550     QList<int> frames;
0551 
0552     if (frameInterface) {
0553         frames = device->framesInterface()->frames();
0554     }
0555 
0556     if (!frameInterface || frames.count() <= 1) {
0557         return loadPaintDeviceFrame(device, location, SimpleDevicePolicy());
0558     } else {
0559         KisRasterKeyframeChannel *keyframeChannel = device->keyframeChannel();
0560 
0561         for (int i = 0; i < frames.count(); i++) {
0562             int id = frames[i];
0563             if (keyframeChannel->frameFilename(id).isEmpty()) {
0564                 m_warningMessages << i18n("Could not find keyframe pixel data for frame %1 in %2.", id, location);
0565             }
0566             else {
0567                 Q_ASSERT(!keyframeChannel->frameFilename(id).isEmpty());
0568                 QString frameFilename = getLocation(keyframeChannel->frameFilename(id));
0569                 Q_ASSERT(!frameFilename.isEmpty());
0570 
0571                 if (!loadPaintDeviceFrame(device, frameFilename, FramedDevicePolicy(id))) {
0572                     m_warningMessages << i18n("Could not load keyframe pixel data for frame %1 in %2.", id, location);
0573                 }
0574             }
0575         }
0576     }
0577 
0578     return true;
0579 }
0580 
0581 template<class DevicePolicy>
0582 bool KisKraLoadVisitor::loadPaintDeviceFrame(KisPaintDeviceSP device, const QString &location, DevicePolicy policy)
0583 {
0584     {
0585         const int pixelSize = device->colorSpace()->pixelSize();
0586         KoColor color = KoColor::createTransparent(device->colorSpace());
0587 
0588         if (m_store->open(location + ".defaultpixel")) {
0589             if (m_store->size() == pixelSize) {
0590                 m_store->read((char*)color.data(), pixelSize);
0591             }
0592 
0593             m_store->close();
0594         }
0595 
0596         policy.setDefaultPixel(device, color);
0597     }
0598 
0599     if (m_store->open(location)) {
0600         if (!policy.read(device, m_store->device())) {
0601             m_warningMessages << i18n("Could not read pixel data: %1.", location);
0602             device->disconnect();
0603             m_store->close();
0604             return true;
0605         }
0606         m_store->close();
0607     } else {
0608         m_warningMessages << i18n("Could not load pixel data: %1.", location);
0609         return true;
0610     }
0611 
0612     return true;
0613 }
0614 
0615 
0616 bool KisKraLoadVisitor::loadProfile(KisPaintDeviceSP device, const QString& location)
0617 {
0618     const KoColorProfile *profile = loadProfile(location, device->colorSpace()->colorModelId().id(), device->colorSpace()->colorDepthId().id());
0619 
0620     if (profile) {
0621         // TODO: check result!
0622         device->setProfile(profile, 0);
0623     } else {
0624         m_warningMessages << i18n("Could not load profile: %1.", location);
0625     }
0626 
0627     return true;
0628 }
0629 
0630 const KoColorProfile *KisKraLoadVisitor::loadProfile(const QString &location, const QString &colorModelId, const QString &colorDepthId)
0631 {
0632     const KoColorProfile *result = 0;
0633 
0634     if (m_store->hasFile(location)) {
0635         m_store->open(location);
0636         QByteArray data;
0637         data.resize(m_store->size());
0638         dbgFile << "Data to load: " << m_store->size() << " from " << location << " with color space " << colorModelId << colorDepthId;
0639         int read = m_store->read(data.data(), m_store->size());
0640         dbgFile << "Profile size: " << data.size() << " " << m_store->atEnd() << " " << m_store->device()->bytesAvailable() << " " << read;
0641         m_store->close();
0642 
0643         QString hash = KoMD5Generator::generateHash(data);
0644 
0645         if (m_profileCache.contains(hash)) {
0646             result = m_profileCache[hash];
0647         }
0648         else {
0649             // Create a colorspace with the embedded profile
0650             const KoColorProfile *profile = KoColorSpaceRegistry::instance()->createColorProfile(colorModelId, colorDepthId, data);
0651             m_profileCache[hash] = profile;
0652             result = profile;
0653         }
0654     }
0655 
0656     return result;
0657 }
0658 
0659 bool KisKraLoadVisitor::loadFilterConfiguration(KisFilterConfigurationSP kfc, const QString& location)
0660 {
0661     if (m_store->hasFile(location)) {
0662         QByteArray data;
0663         m_store->open(location);
0664         data = m_store->read(m_store->size());
0665         m_store->close();
0666         if (!data.isEmpty()) {
0667             QDomDocument doc;
0668             doc.setContent(data);
0669             QDomElement e = doc.documentElement();
0670             if (e.tagName() == "filterconfig") {
0671                 kfc->fromLegacyXML(e);
0672             } else {
0673                 kfc->fromXML(e);
0674             }
0675             loadDeprecatedFilter(kfc);
0676             return true;
0677         }
0678     }
0679     m_warningMessages << i18n("Could not filter configuration %1.", location);
0680     return true;
0681 }
0682 
0683 void KisKraLoadVisitor::fixOldFilterConfigurations(KisFilterConfigurationSP kfc)
0684 {
0685     KisFilterSP filter = KisFilterRegistry::instance()->value(kfc->name());
0686     KIS_SAFE_ASSERT_RECOVER_RETURN(filter);
0687 
0688     if (!filter->configurationAllowedForMask(kfc)) {
0689         filter->fixLoadedFilterConfigurationForMasks(kfc);
0690     }
0691 
0692     KIS_SAFE_ASSERT_RECOVER_NOOP(filter->configurationAllowedForMask(kfc));
0693 }
0694 
0695 bool KisKraLoadVisitor::loadMetaData(KisNode* node)
0696 {
0697     KisLayer* layer = qobject_cast<KisLayer*>(node);
0698     if (!layer) return true;
0699 
0700     KisMetaData::IOBackend *backend = KisMetadataBackendRegistry::instance()->get("xmp");
0701 
0702     if (!backend || !backend->supportLoading()) {
0703         if (backend)
0704             dbgFile << "Backend " << backend->id() << " does not support loading.";
0705         else
0706             dbgFile << "Could not load the XMP backend at all";
0707         return true;
0708     }
0709 
0710     QString location = getLocation(node, QString(".") + backend->id() +  DOT_METADATA);
0711     dbgFile << "going to load " << backend->id() << ", " << backend->name() << " from " << location;
0712 
0713     if (m_store->hasFile(location)) {
0714         QByteArray data;
0715         m_store->open(location);
0716         data = m_store->read(m_store->size());
0717         m_store->close();
0718         QBuffer buffer(&data);
0719         if (!backend->loadFrom(layer->metaData(), &buffer)) {
0720             m_warningMessages << i18n("Could not load metadata for layer %1.", layer->name());
0721         }
0722     }
0723     return true;
0724 }
0725 
0726 bool KisKraLoadVisitor::loadSelection(const QString& location, KisSelectionSP dstSelection)
0727 {
0728     // by default the selection is expected to be fully transparent
0729     {
0730         KisPixelSelectionSP pixelSelection = dstSelection->pixelSelection();
0731         KoColor transparent = KoColor::createTransparent(pixelSelection->colorSpace());
0732         pixelSelection->setDefaultPixel(transparent);
0733     }
0734 
0735     bool result = true;
0736 
0737     // Shape selection
0738     QString shapeSelectionLocation = location + DOT_SHAPE_SELECTION;
0739     if (m_store->hasFile(shapeSelectionLocation + "/content.svg") ||
0740         m_store->hasFile(shapeSelectionLocation + "/content.xml")) {
0741 
0742         m_store->pushDirectory();
0743         m_store->enterDirectory(shapeSelectionLocation) ;
0744 
0745         KisShapeSelection* shapeSelection = new KisShapeSelection(m_shapeController, dstSelection);
0746         dstSelection->convertToVectorSelectionNoUndo(shapeSelection);
0747         result = shapeSelection->loadSelection(m_store, m_image->bounds());
0748 
0749         /**
0750          * We need to explicitly call updateProjection() here, because
0751          * KisUpdateSelectionJob that is put into the queue will not update
0752          * actual layers that own this selection. In normal situation,
0753          * the setDirty() call is done explicitly while painting.
0754          *
0755          * TODO: consider adding a proper setDirty() call to
0756          *       KisUpdateSelectionJob. Though it doesn't seem to be needed
0757          *       until we allow modifying vector selections on non-selection
0758          *       masks.
0759          */
0760         dstSelection->updateProjection();
0761         m_store->popDirectory();
0762         if (!result) {
0763             m_warningMessages << i18n("Could not load vector selection %1.", location);
0764         }
0765     } else {
0766         /**
0767          * NOTE: since loading a vector selection discards all the contents
0768          * of a raster projection by reincarnating the paint device, there is
0769          * no need to load pixel selection in case any vector selection
0770          * is present.
0771          */
0772 
0773         // Pixel selection
0774         QString pixelSelectionLocation = location + DOT_PIXEL_SELECTION;
0775         if (m_store->hasFile(pixelSelectionLocation)) {
0776             KisPixelSelectionSP pixelSelection = dstSelection->pixelSelection();
0777             result = loadPaintDevice(pixelSelection, pixelSelectionLocation);
0778             if (!result) {
0779                 m_warningMessages << i18n("Could not load raster selection %1.", location);
0780             }
0781             pixelSelection->invalidateOutlineCache();
0782         }
0783     }
0784 
0785     return true;
0786 }
0787 
0788 QString KisKraLoadVisitor::getLocation(KisNode* node, const QString& suffix)
0789 {
0790     return getLocation(m_layerFilenames[node], suffix);
0791 }
0792 
0793 QString KisKraLoadVisitor::getLocation(const QString &filename, const QString& suffix)
0794 {
0795     QString location = m_external ? QString() : m_uri;
0796     location += m_name + LAYER_PATH + filename + suffix;
0797     return location;
0798 }
0799 
0800 void KisKraLoadVisitor::loadNodeKeyframes(KisNode *node)
0801 {
0802     if (!m_keyframeFilenames.contains(node)) return;
0803 
0804     node->enableAnimation();
0805 
0806     const QString &location = getLocation(m_keyframeFilenames[node]);
0807 
0808     if (!m_store->open(location)) {
0809         m_errorMessages << i18n("Could not load keyframes from %1.", location);
0810         return;
0811     }
0812 
0813     QString errorMsg;
0814     int errorLine;
0815     int errorColumn;
0816 
0817     QDomDocument dom;
0818     bool ok = dom.setContent(m_store->device(), &errorMsg, &errorLine, &errorColumn);
0819     m_store->close();
0820 
0821 
0822     if (!ok) {
0823         m_errorMessages << i18n("parsing error in the keyframe file %1 at line %2, column %3\nError message: %4", location, errorLine, errorColumn, i18n(errorMsg.toUtf8()));
0824         return;
0825     }
0826 
0827     QDomElement root = dom.firstChildElement();
0828 
0829     for (QDomElement child = root.firstChildElement(); !child.isNull(); child = child.nextSiblingElement()) {
0830         if (child.nodeName().toUpper() == "CHANNEL") {
0831             QString id = child.attribute("name");
0832 
0833             KisKeyframeChannel *channel = node->getKeyframeChannel(id, true);
0834 
0835             if (!channel) {
0836                 m_warningMessages << i18n("unknown keyframe channel type: %1 in %2", id, location);
0837                 continue;
0838             }
0839 
0840             channel->loadXML(child);
0841         }
0842     }
0843 }
0844 
0845 void KisKraLoadVisitor::loadDeprecatedFilter(KisFilterConfigurationSP cfg)
0846 {
0847     if (cfg->getString("legacy") == "left edge detections") {
0848         cfg->setProperty("horizRadius", 1);
0849         cfg->setProperty("vertRadius", 1);
0850         cfg->setProperty("type", "prewitt");
0851         cfg->setProperty("output", "yFall");
0852         cfg->setProperty("lockAspect", true);
0853         cfg->setProperty("transparency", false);
0854     } else if (cfg->getString("legacy") == "right edge detections") {
0855         cfg->setProperty("horizRadius", 1);
0856         cfg->setProperty("vertRadius", 1);
0857         cfg->setProperty("type", "prewitt");
0858         cfg->setProperty("output", "yGrowth");
0859         cfg->setProperty("lockAspect", true);
0860         cfg->setProperty("transparency", false);
0861     } else if (cfg->getString("legacy") == "top edge detections") {
0862         cfg->setProperty("horizRadius", 1);
0863         cfg->setProperty("vertRadius", 1);
0864         cfg->setProperty("type", "prewitt");
0865         cfg->setProperty("output", "xGrowth");
0866         cfg->setProperty("lockAspect", true);
0867         cfg->setProperty("transparency", false);
0868     } else if (cfg->getString("legacy") == "bottom edge detections") {
0869         cfg->setProperty("horizRadius", 1);
0870         cfg->setProperty("vertRadius", 1);
0871         cfg->setProperty("type", "prewitt");
0872         cfg->setProperty("output", "xFall");
0873         cfg->setProperty("lockAspect", true);
0874         cfg->setProperty("transparency", false);
0875     }
0876 }