File indexing completed on 2024-05-26 04:33:32
0001 /* 0002 * SPDX-FileCopyrightText: 2002 Patrick Julien <freak@codepimps.org> 0003 * SPDX-FileCopyrightText: 2005 C. Boemann <cbo@boemann.dk> 0004 * SPDX-FileCopyrightText: 2007-2008 Boudewijn Rempt <boud@valdyas.org> 0005 * 0006 * SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include "kis_kra_save_visitor.h" 0010 #include "kis_kra_tags.h" 0011 0012 #include <QBuffer> 0013 #include <QByteArray> 0014 0015 #include <KoColorProfile.h> 0016 #include <KoStore.h> 0017 #include <KoColorSpace.h> 0018 0019 #include "lazybrush/kis_colorize_mask.h" 0020 #include <KisReferenceImage.h> 0021 #include <KisReferenceImagesLayer.h> 0022 #include <filter/kis_filter_configuration.h> 0023 #include <generator/kis_generator_layer.h> 0024 #include <kis_adjustment_layer.h> 0025 #include <kis_annotation.h> 0026 #include <kis_clone_layer.h> 0027 #include <kis_file_layer.h> 0028 #include <kis_filter_mask.h> 0029 #include <kis_group_layer.h> 0030 #include <kis_image.h> 0031 #include <kis_layer.h> 0032 #include <kis_mask.h> 0033 #include <kis_meta_data_backend_registry.h> 0034 #include <kis_meta_data_store.h> 0035 #include <kis_paint_layer.h> 0036 #include <kis_pixel_selection.h> 0037 #include <kis_selection.h> 0038 #include <kis_selection_component.h> 0039 #include <kis_selection_mask.h> 0040 #include <kis_shape_layer.h> 0041 #include <kis_transform_mask.h> 0042 #include <kis_transform_mask_params_interface.h> 0043 #include <kis_transparency_mask.h> 0044 0045 #include "kis_config.h" 0046 #include "kis_store_paintdevice_writer.h" 0047 #include "flake/kis_shape_selection.h" 0048 0049 #include "kis_raster_keyframe_channel.h" 0050 #include "kis_paint_device_frames_interface.h" 0051 0052 #include "lazybrush/kis_lazy_fill_tools.h" 0053 #include <KoStoreDevice.h> 0054 #include "kis_colorize_dom_utils.h" 0055 #include "kis_dom_utils.h" 0056 0057 0058 using namespace KRA; 0059 0060 KisKraSaveVisitor::KisKraSaveVisitor(KoStore *store, const QString & name, QMap<const KisNode*, QString> nodeFileNames) 0061 : KisNodeVisitor() 0062 , m_store(store) 0063 , m_external(false) 0064 , m_name(name) 0065 , m_nodeFileNames(nodeFileNames) 0066 , m_writer(new KisStorePaintDeviceWriter(store)) 0067 { 0068 } 0069 0070 KisKraSaveVisitor::~KisKraSaveVisitor() 0071 { 0072 delete m_writer; 0073 } 0074 0075 void KisKraSaveVisitor::setExternalUri(const QString &uri) 0076 { 0077 m_external = true; 0078 m_uri = uri; 0079 } 0080 0081 bool KisKraSaveVisitor::visit(KisExternalLayer * layer) 0082 { 0083 bool result = false; 0084 if (auto* referencesLayer = dynamic_cast<KisReferenceImagesLayer*>(layer)) { 0085 result = true; 0086 QList <KoShape *> shapes = referencesLayer->shapes(); 0087 std::sort(shapes.begin(), shapes.end(), KoShape::compareShapeZIndex); 0088 Q_FOREACH(KoShape *shape, shapes) { 0089 auto *reference = dynamic_cast<KisReferenceImage*>(shape); 0090 KIS_ASSERT_RECOVER_RETURN_VALUE(reference, false); 0091 bool saved = reference->saveImage(m_store); 0092 if (!saved) { 0093 m_errorMessages << i18n("Failed to save reference image %1.", reference->internalFile()); 0094 result = false; 0095 } 0096 } 0097 } 0098 else if (KisShapeLayer *shapeLayer = dynamic_cast<KisShapeLayer*>(layer)) { 0099 if (!saveMetaData(layer)) { 0100 m_errorMessages << i18n("Failed to save the metadata for layer %1.", layer->name()); 0101 return false; 0102 } 0103 m_store->pushDirectory(); 0104 QString location = getLocation(layer, DOT_SHAPE_LAYER); 0105 result = m_store->enterDirectory(location); 0106 if (!result) { 0107 m_errorMessages << i18n("Failed to open %1.", location); 0108 } 0109 else { 0110 result = shapeLayer->saveLayer(m_store); 0111 m_store->popDirectory(); 0112 } 0113 } 0114 else if (KisFileLayer *fileLayer = dynamic_cast<KisFileLayer*>(layer)) { 0115 Q_UNUSED(fileLayer); // We don't save data for file layers, but we still want to save the masks. 0116 result = true; 0117 } 0118 return result && visitAllInverse(layer); 0119 } 0120 0121 bool KisKraSaveVisitor::visit(KisPaintLayer *layer) 0122 { 0123 if (!savePaintDevice(layer->paintDevice(), getLocation(layer))) { 0124 m_errorMessages << i18n("Failed to save the pixel data for layer %1.", layer->name()); 0125 return false; 0126 } 0127 if (!saveAnnotations(layer)) { 0128 m_errorMessages << i18n("Failed to save the annotations for layer %1.", layer->name()); 0129 return false; 0130 } 0131 if (!saveMetaData(layer)) { 0132 m_errorMessages << i18n("Failed to save the metadata for layer %1.", layer->name()); 0133 return false; 0134 } 0135 return visitAllInverse(layer); 0136 } 0137 0138 bool KisKraSaveVisitor::visit(KisGroupLayer *layer) 0139 { 0140 if (!saveMetaData(layer)) { 0141 m_errorMessages << i18n("Failed to save the metadata for layer %1.", layer->name()); 0142 return false; 0143 } 0144 return visitAllInverse(layer); 0145 } 0146 0147 bool KisKraSaveVisitor::visit(KisAdjustmentLayer* layer) 0148 { 0149 if (!layer->filter()) { 0150 m_errorMessages << i18n("Failed to save the filter layer %1: it has no filter.", layer->name()); 0151 return false; 0152 } 0153 if (!saveSelection(layer)) { 0154 m_errorMessages << i18n("Failed to save the selection for filter layer %1.", layer->name()); 0155 return false; 0156 } 0157 if (!saveFilterConfiguration(layer)) { 0158 m_errorMessages << i18n("Failed to save the filter configuration for filter layer %1.", layer->name()); 0159 return false; 0160 } 0161 if (!saveMetaData(layer)) { 0162 m_errorMessages << i18n("Failed to save the metadata for layer %1.", layer->name()); 0163 return false; 0164 } 0165 return visitAllInverse(layer); 0166 } 0167 0168 bool KisKraSaveVisitor::visit(KisGeneratorLayer * layer) 0169 { 0170 if (!saveSelection(layer)) { 0171 m_errorMessages << i18n("Failed to save the selection for layer %1.", layer->name()); 0172 return false; 0173 } 0174 if (!saveFilterConfiguration(layer)) { 0175 m_errorMessages << i18n("Failed to save the generator configuration for layer %1.", layer->name()); 0176 return false; 0177 } 0178 if (!saveMetaData(layer)) { 0179 m_errorMessages << i18n("Failed to save the metadata for layer %1.", layer->name()); 0180 return false; 0181 } 0182 return visitAllInverse(layer); 0183 } 0184 0185 bool KisKraSaveVisitor::visit(KisCloneLayer *layer) 0186 { 0187 // Clone layers do not have a profile 0188 if (!saveMetaData(layer)) { 0189 m_errorMessages << i18n("Failed to save the metadata for layer %1.", layer->name()); 0190 return false; 0191 } 0192 return visitAllInverse(layer); 0193 } 0194 0195 bool KisKraSaveVisitor::visit(KisFilterMask *mask) 0196 { 0197 if (!mask->filter()) { 0198 m_errorMessages << i18n("Failed to save filter mask %1. It has no filter.", mask->name()); 0199 return false; 0200 } 0201 if (!saveSelection(mask)) { 0202 m_errorMessages << i18n("Failed to save the selection for filter mask %1.", mask->name()); 0203 return false; 0204 } 0205 if (!saveFilterConfiguration(mask)) { 0206 m_errorMessages << i18n("Failed to save the filter configuration for filter mask %1.", mask->name()); 0207 return false; 0208 } 0209 return true; 0210 } 0211 0212 bool KisKraSaveVisitor::visit(KisTransformMask *mask) 0213 { 0214 QDomDocument doc("transform_params"); 0215 0216 QDomElement root = doc.createElement("transform_params"); 0217 0218 QDomElement main = doc.createElement("main"); 0219 main.setAttribute("id", mask->transformParams()->id()); 0220 0221 QDomElement data = doc.createElement("data"); 0222 mask->transformParams()->toXML(&data); 0223 0224 doc.appendChild(root); 0225 root.appendChild(main); 0226 root.appendChild(data); 0227 0228 QString location = getLocation(mask, DOT_TRANSFORMCONFIG); 0229 if (m_store->open(location)) { 0230 QByteArray a = doc.toByteArray(); 0231 bool retval = m_store->write(a) == a.size(); 0232 0233 if (!retval) { 0234 warnFile << "Could not write transform mask configuration"; 0235 } 0236 if (!m_store->close()) { 0237 warnFile << "Could not close store after writing transform mask configuration"; 0238 retval = false; 0239 } 0240 return retval; 0241 } 0242 return false; 0243 } 0244 0245 bool KisKraSaveVisitor::visit(KisTransparencyMask *mask) 0246 { 0247 if (!saveSelection(mask)) { 0248 m_errorMessages << i18n("Failed to save the selection for transparency mask %1.", mask->name()); 0249 return false; 0250 } 0251 return true; 0252 } 0253 0254 bool KisKraSaveVisitor::visit(KisSelectionMask *mask) 0255 { 0256 if (!saveSelection(mask)) { 0257 m_errorMessages << i18n("Failed to save the selection for local selection %1.", mask->name()); 0258 return false; 0259 } 0260 return true; 0261 } 0262 0263 bool KisKraSaveVisitor::visit(KisColorizeMask *mask) 0264 { 0265 m_store->pushDirectory(); 0266 QString location = getLocation(mask, DOT_COLORIZE_MASK); 0267 bool result = m_store->enterDirectory(location); 0268 0269 if (!result) { 0270 m_errorMessages << i18n("Failed to open %1.", location); 0271 return false; 0272 } 0273 0274 if (!m_store->open("content.xml")) 0275 return false; 0276 0277 KoStoreDevice storeDev(m_store); 0278 0279 QDomDocument doc("doc"); 0280 QDomElement root = doc.createElement("colorize"); 0281 doc.appendChild(root); 0282 KisDomUtils::saveValue(&root, COLORIZE_KEYSTROKES_SECTION, QVector<KisLazyFillTools::KeyStroke>::fromList(mask->fetchKeyStrokesDirect())); 0283 0284 QTextStream stream(&storeDev); 0285 stream.setCodec("UTF-8"); 0286 stream << doc; 0287 0288 if (!m_store->close()) 0289 return false; 0290 0291 int i = 0; 0292 Q_FOREACH (const KisLazyFillTools::KeyStroke &stroke, mask->fetchKeyStrokesDirect()) { 0293 const QString fileName = QString("%1_%2").arg(COLORIZE_KEYSTROKE).arg(i++); 0294 savePaintDevice(stroke.dev, fileName); 0295 } 0296 0297 savePaintDevice(mask->coloringProjection(), COLORIZE_COLORING_DEVICE); 0298 saveIccProfile(mask, mask->colorSpace()->profile()); 0299 0300 m_store->popDirectory(); 0301 0302 return true; 0303 } 0304 0305 QStringList KisKraSaveVisitor::errorMessages() const 0306 { 0307 return m_errorMessages; 0308 } 0309 0310 struct SimpleDevicePolicy 0311 { 0312 bool write(KisPaintDeviceSP dev, KisPaintDeviceWriter &store) { 0313 return dev->write(store); 0314 } 0315 0316 KoColor defaultPixel(KisPaintDeviceSP dev) const { 0317 return dev->defaultPixel(); 0318 } 0319 }; 0320 0321 struct FramedDevicePolicy 0322 { 0323 FramedDevicePolicy(int frameId) 0324 : m_frameId(frameId) {} 0325 0326 bool write(KisPaintDeviceSP dev, KisPaintDeviceWriter &store) { 0327 return dev->framesInterface()->writeFrame(store, m_frameId); 0328 } 0329 0330 KoColor defaultPixel(KisPaintDeviceSP dev) const { 0331 return dev->framesInterface()->frameDefaultPixel(m_frameId); 0332 } 0333 0334 int m_frameId; 0335 }; 0336 0337 bool KisKraSaveVisitor::savePaintDevice(KisPaintDeviceSP device, 0338 QString location) 0339 { 0340 // Layer data 0341 KisConfig cfg(true); 0342 m_store->setCompressionEnabled(cfg.compressKra()); 0343 0344 KisPaintDeviceFramesInterface *frameInterface = device->framesInterface(); 0345 QList<int> frames; 0346 0347 if (frameInterface) { 0348 frames = frameInterface->frames(); 0349 } 0350 0351 if (!frameInterface || frames.count() <= 1) { 0352 savePaintDeviceFrame(device, location, SimpleDevicePolicy()); 0353 } else { 0354 KisRasterKeyframeChannel *keyframeChannel = device->keyframeChannel(); 0355 0356 for (int i = 0; i < frames.count(); i++) { 0357 int id = frames[i]; 0358 0359 QString frameFilename = getLocation(keyframeChannel->frameFilename(id)); 0360 Q_ASSERT(!frameFilename.isEmpty()); 0361 0362 if (!savePaintDeviceFrame(device, frameFilename, FramedDevicePolicy(id))) { 0363 return false; 0364 } 0365 } 0366 } 0367 0368 m_store->setCompressionEnabled(true); 0369 return true; 0370 } 0371 0372 0373 template<class DevicePolicy> 0374 bool KisKraSaveVisitor::savePaintDeviceFrame(KisPaintDeviceSP device, QString location, DevicePolicy policy) 0375 { 0376 if (m_store->open(location)) { 0377 if (!policy.write(device, *m_writer)) { 0378 device->disconnect(); 0379 m_store->close(); 0380 return false; 0381 } 0382 0383 m_store->close(); 0384 } 0385 if (m_store->open(location + ".defaultpixel")) { 0386 m_store->write((char*)policy.defaultPixel(device).data(), device->colorSpace()->pixelSize()); 0387 m_store->close(); 0388 } 0389 0390 return true; 0391 } 0392 0393 bool KisKraSaveVisitor::saveAnnotations(KisLayer* layer) 0394 { 0395 if (!layer) return false; 0396 if (!layer->paintDevice()) return false; 0397 if (!layer->paintDevice()->colorSpace()) return false; 0398 0399 if (layer->paintDevice()->colorSpace()->profile()) { 0400 return saveIccProfile(layer, layer->paintDevice()->colorSpace()->profile()); 0401 } 0402 return true; 0403 0404 } 0405 0406 bool KisKraSaveVisitor::saveIccProfile(KisNode *node, const KoColorProfile *profile) 0407 { 0408 if (profile) { 0409 KisAnnotationSP annotation; 0410 if (profile) { 0411 QByteArray profileRawData = profile->rawData(); 0412 if (!profileRawData.isEmpty()) { 0413 if (profile->type() == "icc") { 0414 annotation = new KisAnnotation(ICC, profile->name(), profile->rawData()); 0415 } else { 0416 annotation = new KisAnnotation(PROFILE, profile->name(), profile->rawData()); 0417 } 0418 } 0419 } 0420 0421 if (annotation) { 0422 // save layer profile 0423 if (m_store->open(getLocation(node, DOT_ICC))) { 0424 m_store->write(annotation->annotation()); 0425 m_store->close(); 0426 } else { 0427 return false; 0428 } 0429 } 0430 } 0431 return true; 0432 } 0433 0434 bool KisKraSaveVisitor::saveSelection(KisNode* node) 0435 { 0436 KisSelectionSP selection; 0437 if (node->inherits("KisMask")) { 0438 selection = static_cast<KisMask*>(node)->selection(); 0439 } else if (node->inherits("KisAdjustmentLayer")) { 0440 selection = static_cast<KisAdjustmentLayer*>(node)->internalSelection(); 0441 } else if (node->inherits("KisGeneratorLayer")) { 0442 selection = static_cast<KisGeneratorLayer*>(node)->internalSelection(); 0443 } else { 0444 return false; 0445 } 0446 0447 bool retval = true; 0448 0449 if (selection->hasNonEmptyPixelSelection()) { 0450 KisPaintDeviceSP dev = selection->pixelSelection(); 0451 if (!savePaintDevice(dev, getLocation(node, DOT_PIXEL_SELECTION))) { 0452 m_errorMessages << i18n("Failed to save the pixel selection data for layer %1.", node->name()); 0453 retval = false; 0454 } 0455 } 0456 if (selection->hasNonEmptyShapeSelection()) { 0457 m_store->pushDirectory(); 0458 retval = m_store->enterDirectory(getLocation(node, DOT_SHAPE_SELECTION)); 0459 if (retval) { 0460 KisShapeSelection* shapeSelection = dynamic_cast<KisShapeSelection*>(selection->shapeSelection()); 0461 if (!shapeSelection) { 0462 retval = false; 0463 } 0464 0465 if (retval && !shapeSelection->saveSelection(m_store, node->image()->bounds())) { 0466 m_errorMessages << i18n("Failed to save the vector selection data for layer %1.", node->name()); 0467 retval = false; 0468 } 0469 } 0470 m_store->popDirectory(); 0471 } 0472 return retval; 0473 } 0474 0475 bool KisKraSaveVisitor::saveFilterConfiguration(KisNode* node) 0476 { 0477 KisNodeFilterInterface *filterInterface = 0478 dynamic_cast<KisNodeFilterInterface*>(node); 0479 0480 KisFilterConfigurationSP filter; 0481 0482 if (filterInterface) { 0483 filter = filterInterface->filter(); 0484 } 0485 0486 bool retval = false; 0487 0488 if (filter) { 0489 QString location = getLocation(node, DOT_FILTERCONFIG); 0490 if (m_store->open(location)) { 0491 QString s = filter->toXML(); 0492 retval = (m_store->write(s.toUtf8(), qstrlen(s.toUtf8())) == qstrlen(s.toUtf8())); m_store->close(); 0493 } 0494 } 0495 return retval; 0496 } 0497 0498 bool KisKraSaveVisitor::saveMetaData(KisNode* node) 0499 { 0500 if (!node->inherits("KisLayer")) return true; 0501 0502 KisMetaData::Store* metadata = (static_cast<KisLayer*>(node))->metaData(); 0503 if (metadata->isEmpty()) return true; 0504 0505 // Serialize all the types of metadata there are 0506 KisMetaData::IOBackend *backend = KisMetadataBackendRegistry::instance()->get("xmp"); 0507 if (!backend->supportSaving()) { 0508 dbgFile << "Backend " << backend->id() << " does not support saving."; 0509 return false; 0510 } 0511 0512 QString location = getLocation(node, QString(".") + backend->id() + DOT_METADATA); 0513 dbgFile << "going to save " << backend->id() << ", " << backend->name() << " to " << location; 0514 0515 QBuffer buffer; 0516 // not that the metadata backends every return anything but true... 0517 bool retval = backend->saveTo(metadata, &buffer); 0518 0519 if (!retval) { 0520 m_errorMessages << i18n("The metadata backend failed to save the metadata for %1", node->name()); 0521 } 0522 else { 0523 QByteArray data = buffer.data(); 0524 dbgFile << "\t information size is" << data.size(); 0525 0526 if (data.size() > 0 && m_store->open(location)) { 0527 retval = m_store->write(data, data.size()); 0528 m_store->close(); 0529 } 0530 if (!retval) { 0531 m_errorMessages << i18n("Could not write for %1 metadata to the file.", node->name()); 0532 } 0533 } 0534 return retval; 0535 } 0536 0537 QString KisKraSaveVisitor::getLocation(KisNode* node, const QString& suffix) 0538 { 0539 0540 Q_ASSERT(m_nodeFileNames.contains(node)); 0541 return getLocation(m_nodeFileNames[node], suffix); 0542 } 0543 0544 QString KisKraSaveVisitor::getLocation(const QString &filename, const QString& suffix) 0545 { 0546 QString location = m_external ? QString() : m_uri; 0547 location += m_name + LAYER_PATH + filename + suffix; 0548 return location; 0549 }