1 /*
2  *  Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
3  *  Copyright (c) 2005 C. Boemann <cbo@boemann.dk>
4  *  Copyright (c) 2007-2008 Boudewijn Rempt <boud@valdyas.org>
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  */
20 
21 #include "kis_kra_save_visitor.h"
22 #include "kis_kra_tags.h"
23 
24 #include <QBuffer>
25 #include <QByteArray>
26 
27 #include <KoColorProfile.h>
28 #include <KoStore.h>
29 #include <KoColorSpace.h>
30 
31 #include <filter/kis_filter_configuration.h>
32 #include <generator/kis_generator_layer.h>
33 #include <kis_adjustment_layer.h>
34 #include <kis_annotation.h>
35 #include <kis_group_layer.h>
36 #include <kis_image.h>
37 #include <kis_layer.h>
38 #include <kis_paint_layer.h>
39 #include <kis_selection.h>
40 #include <kis_shape_layer.h>
41 #include <KisReferenceImagesLayer.h>
42 #include <KisReferenceImage.h>
43 #include <kis_file_layer.h>
44 #include <kis_clone_layer.h>
45 #include <kis_mask.h>
46 #include <kis_filter_mask.h>
47 #include <kis_transform_mask.h>
48 #include <kis_transform_mask_params_interface.h>
49 #include <kis_transparency_mask.h>
50 #include <kis_selection_mask.h>
51 #include "lazybrush/kis_colorize_mask.h"
52 #include <kis_selection_component.h>
53 #include <kis_pixel_selection.h>
54 #include <kis_meta_data_store.h>
55 #include <kis_meta_data_io_backend.h>
56 
57 #include "kis_config.h"
58 #include "kis_store_paintdevice_writer.h"
59 #include "flake/kis_shape_selection.h"
60 
61 #include "kis_raster_keyframe_channel.h"
62 #include "kis_paint_device_frames_interface.h"
63 
64 #include "lazybrush/kis_lazy_fill_tools.h"
65 #include <KoStoreDevice.h>
66 #include "kis_colorize_dom_utils.h"
67 #include "kis_dom_utils.h"
68 
69 
70 using namespace KRA;
71 
KisKraSaveVisitor(KoStore * store,const QString & name,QMap<const KisNode *,QString> nodeFileNames)72 KisKraSaveVisitor::KisKraSaveVisitor(KoStore *store, const QString & name, QMap<const KisNode*, QString> nodeFileNames)
73     : KisNodeVisitor()
74     , m_store(store)
75     , m_external(false)
76     , m_name(name)
77     , m_nodeFileNames(nodeFileNames)
78     , m_writer(new KisStorePaintDeviceWriter(store))
79 {
80 }
81 
~KisKraSaveVisitor()82 KisKraSaveVisitor::~KisKraSaveVisitor()
83 {
84     delete m_writer;
85 }
86 
setExternalUri(const QString & uri)87 void KisKraSaveVisitor::setExternalUri(const QString &uri)
88 {
89     m_external = true;
90     m_uri = uri;
91 }
92 
visit(KisExternalLayer * layer)93 bool KisKraSaveVisitor::visit(KisExternalLayer * layer)
94 {
95     bool result = false;
96     if (auto* referencesLayer = dynamic_cast<KisReferenceImagesLayer*>(layer)) {
97         result = true;
98         QList <KoShape *> shapes = referencesLayer->shapes();
99         std::sort(shapes.begin(), shapes.end(), KoShape::compareShapeZIndex);
100         Q_FOREACH(KoShape *shape, shapes) {
101             auto *reference = dynamic_cast<KisReferenceImage*>(shape);
102             KIS_ASSERT_RECOVER_RETURN_VALUE(reference, false);
103             bool saved = reference->saveImage(m_store);
104             if (!saved) {
105                 m_errorMessages << i18n("Failed to save reference image %1.", reference->internalFile());
106                 result = false;
107             }
108         }
109     }
110     else if (KisShapeLayer *shapeLayer = dynamic_cast<KisShapeLayer*>(layer)) {
111         if (!saveMetaData(layer)) {
112             m_errorMessages << i18n("Failed to save the metadata for layer %1.", layer->name());
113             return false;
114         }
115         m_store->pushDirectory();
116         QString location = getLocation(layer, DOT_SHAPE_LAYER);
117         result = m_store->enterDirectory(location);
118         if (!result) {
119             m_errorMessages << i18n("Failed to open %1.", location);
120         }
121         else {
122             result = shapeLayer->saveLayer(m_store);
123             m_store->popDirectory();
124         }
125     }
126     else if (KisFileLayer *fileLayer = dynamic_cast<KisFileLayer*>(layer)) {
127         Q_UNUSED(fileLayer); // We don't save data for file layers, but we still want to save the masks.
128         result = true;
129     }
130     return result && visitAllInverse(layer);
131 }
132 
visit(KisPaintLayer * layer)133 bool KisKraSaveVisitor::visit(KisPaintLayer *layer)
134 {
135     if (!savePaintDevice(layer->paintDevice(), getLocation(layer))) {
136         m_errorMessages << i18n("Failed to save the pixel data for layer %1.", layer->name());
137         return false;
138     }
139     if (!saveAnnotations(layer)) {
140         m_errorMessages << i18n("Failed to save the annotations for layer %1.", layer->name());
141         return false;
142     }
143     if (!saveMetaData(layer)) {
144         m_errorMessages << i18n("Failed to save the metadata for layer %1.", layer->name());
145         return false;
146     }
147     return visitAllInverse(layer);
148 }
149 
visit(KisGroupLayer * layer)150 bool KisKraSaveVisitor::visit(KisGroupLayer *layer)
151 {
152     if (!saveMetaData(layer)) {
153         m_errorMessages << i18n("Failed to save the metadata for layer %1.", layer->name());
154         return false;
155     }
156     return visitAllInverse(layer);
157 }
158 
visit(KisAdjustmentLayer * layer)159 bool KisKraSaveVisitor::visit(KisAdjustmentLayer* layer)
160 {
161     if (!layer->filter()) {
162         m_errorMessages << i18n("Failed to save the filter layer %1: it has no filter.", layer->name());
163         return false;
164     }
165     if (!saveSelection(layer)) {
166         m_errorMessages << i18n("Failed to save the selection for filter layer %1.", layer->name());
167         return false;
168     }
169     if (!saveFilterConfiguration(layer)) {
170         m_errorMessages << i18n("Failed to save the filter configuration for filter layer %1.", layer->name());
171         return false;
172     }
173     if (!saveMetaData(layer)) {
174         m_errorMessages << i18n("Failed to save the metadata for layer %1.", layer->name());
175         return false;
176     }
177     return visitAllInverse(layer);
178 }
179 
visit(KisGeneratorLayer * layer)180 bool KisKraSaveVisitor::visit(KisGeneratorLayer * layer)
181 {
182     if (!saveSelection(layer)) {
183         m_errorMessages << i18n("Failed to save the selection for layer %1.", layer->name());
184         return false;
185     }
186     if (!saveFilterConfiguration(layer)) {
187         m_errorMessages << i18n("Failed to save the generator configuration for layer %1.", layer->name());
188         return false;
189     }
190     if (!saveMetaData(layer)) {
191         m_errorMessages << i18n("Failed to save the metadata for layer %1.", layer->name());
192         return false;
193     }
194     return visitAllInverse(layer);
195 }
196 
visit(KisCloneLayer * layer)197 bool KisKraSaveVisitor::visit(KisCloneLayer *layer)
198 {
199     // Clone layers do not have a profile
200     if (!saveMetaData(layer)) {
201         m_errorMessages << i18n("Failed to save the metadata for layer %1.", layer->name());
202         return false;
203     }
204     return visitAllInverse(layer);
205 }
206 
visit(KisFilterMask * mask)207 bool KisKraSaveVisitor::visit(KisFilterMask *mask)
208 {
209     if (!mask->filter()) {
210         m_errorMessages << i18n("Failed to save filter mask %1. It has no filter.", mask->name());
211         return false;
212     }
213     if (!saveSelection(mask)) {
214         m_errorMessages << i18n("Failed to save the selection for filter mask %1.", mask->name());
215         return false;
216     }
217     if (!saveFilterConfiguration(mask)) {
218         m_errorMessages << i18n("Failed to save the filter configuration for filter mask %1.", mask->name());
219         return false;
220     }
221     return true;
222 }
223 
visit(KisTransformMask * mask)224 bool KisKraSaveVisitor::visit(KisTransformMask *mask)
225 {
226     QDomDocument doc("transform_params");
227 
228     QDomElement root = doc.createElement("transform_params");
229 
230     QDomElement main = doc.createElement("main");
231     main.setAttribute("id", mask->transformParams()->id());
232 
233     QDomElement data = doc.createElement("data");
234     mask->transformParams()->toXML(&data);
235 
236     doc.appendChild(root);
237     root.appendChild(main);
238     root.appendChild(data);
239 
240     QString location = getLocation(mask, DOT_TRANSFORMCONFIG);
241     if (m_store->open(location)) {
242         QByteArray a = doc.toByteArray();
243         bool retval = m_store->write(a) == a.size();
244 
245         if (!retval) {
246             warnFile << "Could not write transform mask configuration";
247         }
248         if (!m_store->close()) {
249             warnFile << "Could not close store after writing transform mask configuration";
250             retval = false;
251         }
252         return retval;
253     }
254     return false;
255 }
256 
visit(KisTransparencyMask * mask)257 bool KisKraSaveVisitor::visit(KisTransparencyMask *mask)
258 {
259     if (!saveSelection(mask)) {
260         m_errorMessages << i18n("Failed to save the selection for transparency mask %1.", mask->name());
261         return false;
262     }
263     return true;
264 }
265 
visit(KisSelectionMask * mask)266 bool KisKraSaveVisitor::visit(KisSelectionMask *mask)
267 {
268     if (!saveSelection(mask)) {
269         m_errorMessages << i18n("Failed to save the selection for local selection %1.", mask->name());
270         return false;
271     }
272     return true;
273 }
274 
visit(KisColorizeMask * mask)275 bool KisKraSaveVisitor::visit(KisColorizeMask *mask)
276 {
277     m_store->pushDirectory();
278     QString location = getLocation(mask, DOT_COLORIZE_MASK);
279     bool result = m_store->enterDirectory(location);
280 
281     if (!result) {
282         m_errorMessages << i18n("Failed to open %1.", location);
283         return false;
284     }
285 
286     if (!m_store->open("content.xml"))
287         return false;
288 
289     KoStoreDevice storeDev(m_store);
290 
291     QDomDocument doc("doc");
292     QDomElement root = doc.createElement("colorize");
293     doc.appendChild(root);
294     KisDomUtils::saveValue(&root, COLORIZE_KEYSTROKES_SECTION, QVector<KisLazyFillTools::KeyStroke>::fromList(mask->fetchKeyStrokesDirect()));
295 
296     QTextStream stream(&storeDev);
297     stream << doc;
298 
299     if (!m_store->close())
300         return false;
301 
302     int i = 0;
303     Q_FOREACH (const KisLazyFillTools::KeyStroke &stroke, mask->fetchKeyStrokesDirect()) {
304         const QString fileName = QString("%1_%2").arg(COLORIZE_KEYSTROKE).arg(i++);
305         savePaintDevice(stroke.dev, fileName);
306     }
307 
308     savePaintDevice(mask->coloringProjection(), COLORIZE_COLORING_DEVICE);
309     saveIccProfile(mask, mask->colorSpace()->profile());
310 
311     m_store->popDirectory();
312 
313     return true;
314 }
315 
errorMessages() const316 QStringList KisKraSaveVisitor::errorMessages() const
317 {
318     return m_errorMessages;
319 }
320 
321 struct SimpleDevicePolicy
322 {
writeSimpleDevicePolicy323     bool write(KisPaintDeviceSP dev, KisPaintDeviceWriter &store) {
324         return dev->write(store);
325     }
326 
defaultPixelSimpleDevicePolicy327     KoColor defaultPixel(KisPaintDeviceSP dev) const {
328         return dev->defaultPixel();
329     }
330 };
331 
332 struct FramedDevicePolicy
333 {
FramedDevicePolicyFramedDevicePolicy334     FramedDevicePolicy(int frameId)
335         :  m_frameId(frameId) {}
336 
writeFramedDevicePolicy337     bool write(KisPaintDeviceSP dev, KisPaintDeviceWriter &store) {
338         return dev->framesInterface()->writeFrame(store, m_frameId);
339     }
340 
defaultPixelFramedDevicePolicy341     KoColor defaultPixel(KisPaintDeviceSP dev) const {
342         return dev->framesInterface()->frameDefaultPixel(m_frameId);
343     }
344 
345     int m_frameId;
346 };
347 
savePaintDevice(KisPaintDeviceSP device,QString location)348 bool KisKraSaveVisitor::savePaintDevice(KisPaintDeviceSP device,
349                                         QString location)
350 {
351     // Layer data
352     KisConfig cfg(true);
353     m_store->setCompressionEnabled(cfg.compressKra());
354 
355     KisPaintDeviceFramesInterface *frameInterface = device->framesInterface();
356     QList<int> frames;
357 
358     if (frameInterface) {
359         frames = frameInterface->frames();
360     }
361 
362     if (!frameInterface || frames.count() <= 1) {
363         savePaintDeviceFrame(device, location, SimpleDevicePolicy());
364     } else {
365         KisRasterKeyframeChannel *keyframeChannel = device->keyframeChannel();
366 
367         for (int i = 0; i < frames.count(); i++) {
368             int id = frames[i];
369 
370             QString frameFilename = getLocation(keyframeChannel->frameFilename(id));
371             Q_ASSERT(!frameFilename.isEmpty());
372 
373             if (!savePaintDeviceFrame(device, frameFilename, FramedDevicePolicy(id))) {
374                 return false;
375             }
376         }
377     }
378 
379     m_store->setCompressionEnabled(true);
380     return true;
381 }
382 
383 
384 template<class DevicePolicy>
savePaintDeviceFrame(KisPaintDeviceSP device,QString location,DevicePolicy policy)385 bool KisKraSaveVisitor::savePaintDeviceFrame(KisPaintDeviceSP device, QString location, DevicePolicy policy)
386 {
387     if (m_store->open(location)) {
388         if (!policy.write(device, *m_writer)) {
389             device->disconnect();
390             m_store->close();
391             return false;
392         }
393 
394         m_store->close();
395     }
396     if (m_store->open(location + ".defaultpixel")) {
397         m_store->write((char*)policy.defaultPixel(device).data(), device->colorSpace()->pixelSize());
398         m_store->close();
399     }
400 
401     return true;
402 }
403 
saveAnnotations(KisLayer * layer)404 bool KisKraSaveVisitor::saveAnnotations(KisLayer* layer)
405 {
406     if (!layer) return false;
407     if (!layer->paintDevice()) return false;
408     if (!layer->paintDevice()->colorSpace()) return false;
409 
410     if (layer->paintDevice()->colorSpace()->profile()) {
411         return saveIccProfile(layer, layer->paintDevice()->colorSpace()->profile());
412     }
413     return true;
414 
415 }
416 
saveIccProfile(KisNode * node,const KoColorProfile * profile)417 bool KisKraSaveVisitor::saveIccProfile(KisNode *node, const KoColorProfile *profile)
418 {
419     if (profile) {
420         KisAnnotationSP annotation;
421         if (profile) {
422             QByteArray profileRawData = profile->rawData();
423             if (!profileRawData.isEmpty()) {
424                 if (profile->type() == "icc") {
425                     annotation = new KisAnnotation(ICC, profile->name(), profile->rawData());
426                 } else {
427                     annotation = new KisAnnotation(PROFILE, profile->name(), profile->rawData());
428                 }
429             }
430         }
431 
432         if (annotation) {
433             // save layer profile
434             if (m_store->open(getLocation(node, DOT_ICC))) {
435                 m_store->write(annotation->annotation());
436                 m_store->close();
437             } else {
438                 return false;
439             }
440         }
441     }
442     return true;
443 }
444 
saveSelection(KisNode * node)445 bool KisKraSaveVisitor::saveSelection(KisNode* node)
446 {
447     KisSelectionSP selection;
448     if (node->inherits("KisMask")) {
449         selection = static_cast<KisMask*>(node)->selection();
450     } else if (node->inherits("KisAdjustmentLayer")) {
451         selection = static_cast<KisAdjustmentLayer*>(node)->internalSelection();
452     } else if (node->inherits("KisGeneratorLayer")) {
453         selection = static_cast<KisGeneratorLayer*>(node)->internalSelection();
454     } else {
455         return false;
456     }
457 
458     bool retval = true;
459 
460     if (selection->hasNonEmptyPixelSelection()) {
461         KisPaintDeviceSP dev = selection->pixelSelection();
462         if (!savePaintDevice(dev, getLocation(node, DOT_PIXEL_SELECTION))) {
463             m_errorMessages << i18n("Failed to save the pixel selection data for layer %1.", node->name());
464             retval = false;
465         }
466     }
467     if (selection->hasNonEmptyShapeSelection()) {
468         m_store->pushDirectory();
469         retval = m_store->enterDirectory(getLocation(node, DOT_SHAPE_SELECTION));
470         if (retval) {
471             KisShapeSelection* shapeSelection = dynamic_cast<KisShapeSelection*>(selection->shapeSelection());
472             if (!shapeSelection) {
473                 retval = false;
474             }
475 
476             if (retval && !shapeSelection->saveSelection(m_store)) {
477                 m_errorMessages << i18n("Failed to save the vector selection data for layer %1.", node->name());
478                 retval = false;
479             }
480         }
481         m_store->popDirectory();
482     }
483     return retval;
484 }
485 
saveFilterConfiguration(KisNode * node)486 bool KisKraSaveVisitor::saveFilterConfiguration(KisNode* node)
487 {
488     KisNodeFilterInterface *filterInterface =
489             dynamic_cast<KisNodeFilterInterface*>(node);
490 
491     KisFilterConfigurationSP filter;
492 
493     if (filterInterface) {
494         filter = filterInterface->filter();
495     }
496 
497     bool retval = false;
498 
499     if (filter) {
500         QString location = getLocation(node, DOT_FILTERCONFIG);
501         if (m_store->open(location)) {
502             QString s = filter->toXML();
503             retval = (m_store->write(s.toUtf8(), qstrlen(s.toUtf8())) == qstrlen(s.toUtf8())); m_store->close();
504         }
505     }
506     return retval;
507 }
508 
saveMetaData(KisNode * node)509 bool KisKraSaveVisitor::saveMetaData(KisNode* node)
510 {
511     if (!node->inherits("KisLayer")) return true;
512 
513     KisMetaData::Store* metadata = (static_cast<KisLayer*>(node))->metaData();
514     if (metadata->isEmpty()) return true;
515 
516     // Serialize all the types of metadata there are
517     KisMetaData::IOBackend* backend = KisMetaData::IOBackendRegistry::instance()->get("xmp");
518     if (!backend->supportSaving()) {
519         dbgFile << "Backend " << backend->id() << " does not support saving.";
520         return false;
521     }
522 
523     QString location = getLocation(node, QString(".") + backend->id() +  DOT_METADATA);
524     dbgFile << "going to save " << backend->id() << ", " << backend->name() << " to " << location;
525 
526     QBuffer buffer;
527     // not that the metadata backends every return anything but true...
528     bool retval = backend->saveTo(metadata, &buffer);
529 
530     if (!retval) {
531         m_errorMessages << i18n("The metadata backend failed to save the metadata for %1", node->name());
532     }
533     else {
534         QByteArray data = buffer.data();
535         dbgFile << "\t information size is" << data.size();
536 
537         if (data.size() > 0 && m_store->open(location)) {
538             retval = m_store->write(data,  data.size());
539             m_store->close();
540         }
541         if (!retval) {
542             m_errorMessages << i18n("Could not write for %1 metadata to the file.", node->name());
543         }
544     }
545     return retval;
546 }
547 
getLocation(KisNode * node,const QString & suffix)548 QString KisKraSaveVisitor::getLocation(KisNode* node, const QString& suffix)
549 {
550 
551     Q_ASSERT(m_nodeFileNames.contains(node));
552     return getLocation(m_nodeFileNames[node], suffix);
553 }
554 
getLocation(const QString & filename,const QString & suffix)555 QString KisKraSaveVisitor::getLocation(const QString &filename, const QString& suffix)
556 {
557     QString location = m_external ? QString() : m_uri;
558     location += m_name + LAYER_PATH + filename + suffix;
559     return location;
560 }
561