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 }