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