Commit cf368266 authored by Agata Cacko's avatar Agata Cacko

Fix crash opening .kra with incorrect clone source

Before this commit, files created using copying and pasting
clone layers from one file to another would be corrupted
and crash Krita when the user tried to open them.
This commit fixes crashing on opening those files.
After this commit, all clone layers are replaced by
empty paint layers. (Empty, because all data is lost).

CCBUG:414699
parent 0e62d4e2
......@@ -172,6 +172,10 @@ public:
prepareRegion += needRectOnSource;
}
if (srcLayer.isNull()) {
return true;
}
Q_FOREACH (const QRect &rect, prepareRegion.rects()) {
walker.collectRects(srcLayer, rect);
merger.startMerge(walker, false);
......
......@@ -37,6 +37,7 @@
#include <kis_paint_layer.h>
#include <kis_png_converter.h>
#include <KisDocument.h>
#include <kis_clone_layer.h>
static const char CURRENT_DTD_VERSION[] = "2.0";
......@@ -60,6 +61,26 @@ KraConverter::~KraConverter()
delete m_kraLoader;
}
void fixCloneLayers(KisImageSP image, KisNodeSP root)
{
KisNodeSP first = root->firstChild();
KisNodeSP node = first;
while (!node.isNull()) {
if (node->inherits("KisCloneLayer")) {
KisCloneLayer* layer = dynamic_cast<KisCloneLayer*>(node.data());
if (layer && layer->copyFrom().isNull()) {
KisLayerSP reincarnation = layer->reincarnateAsPaintLayer();
image->addNode(reincarnation, node->parent(), node->prevSibling());
image->removeNode(node);
node = reincarnation;
}
} else if (node->childCount() > 0) {
fixCloneLayers(image, node);
}
node = node->nextSibling();
}
}
KisImportExportErrorCode KraConverter::buildImage(QIODevice *io)
{
m_store = KoStore::createStore(io, KoStore::Read, "", KoStore::Zip);
......@@ -69,7 +90,7 @@ KisImportExportErrorCode KraConverter::buildImage(QIODevice *io)
return ImportExportCodes::FileFormatIncorrect;
}
bool success;
bool success = false;
{
if (m_store->hasFile("root") || m_store->hasFile("maindoc.xml")) { // Fallback to "old" file format (maindoc.xml)
KoXmlDocument doc;
......@@ -89,13 +110,16 @@ KisImportExportErrorCode KraConverter::buildImage(QIODevice *io)
if (m_store->hasFile("documentinfo.xml")) {
KoXmlDocument doc;
if (oldLoadAndParse(m_store, "documentinfo.xml", doc).isOk()) {
KisImportExportErrorCode resultHere = oldLoadAndParse(m_store, "documentinfo.xml", doc);
if (resultHere.isOk()) {
m_doc->documentInfo()->load(doc);
}
}
success = completeLoading(m_store);
}
fixCloneLayers(m_image, m_image->root());
return success ? ImportExportCodes::OK : ImportExportCodes::Failure;
}
......@@ -380,6 +404,11 @@ bool KraConverter::completeLoading(KoStore* store)
m_kraLoader->loadBinaryData(store, m_image, m_doc->localFilePath(), true);
m_kraLoader->loadPalettes(store, m_doc);
if (!m_kraLoader->errorMessages().isEmpty()) {
m_doc->setErrorMessage(m_kraLoader->errorMessages().join("\n"));
return false;
}
m_image->unblockUpdates();
if (!m_kraLoader->warningMessages().isEmpty()) {
......@@ -391,6 +420,7 @@ bool KraConverter::completeLoading(KoStore* store)
m_assistants = m_kraLoader->assistants();
return true;
return m_kraLoader->errorMessages().isEmpty();
}
void KraConverter::cancel()
......
......@@ -304,10 +304,15 @@ bool KisKraLoadVisitor::visit(KisCloneLayer *layer)
}
KisNodeSP srcNode = layer->copyFromInfo().findNode(m_image->rootLayer());
KisLayerSP srcLayer = qobject_cast<KisLayer*>(srcNode.data());
Q_ASSERT(srcLayer);
if (!srcNode.isNull()) {
KisLayerSP srcLayer = qobject_cast<KisLayer*>(srcNode.data());
Q_ASSERT(srcLayer);
layer->setCopyFrom(srcLayer);
layer->setCopyFrom(srcLayer);
} else {
m_warningMessages.append(i18nc("Loading a .kra file", "The file contains a clone layer that has an incorrect source node id. "
"This layer will be converted into a paint layer."));
}
// Clone layers have no data except for their masks
bool result = visitAll(layer);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment