Commit f1452472 authored by Dmitry Kazakov's avatar Dmitry Kazakov

Add a workaround for loading broken files with negative frame ids

Summary: CCBUG:395378

Test Plan:
Try to load the file attached to this bugreport:
https://bugs.kde.org/show_bug.cgi?id=395378

Every layer in the file should have two frames (in random order). At least one
of the frames should have sane pixel data

Reviewers: #krita, rempt, jounip

Tags: #krita

Differential Revision: https://phabricator.kde.org/D13562
parent 37386604
......@@ -46,12 +46,14 @@ struct KisKeyframeChannel::Private
node = newParentNode;
id = rhs.id;
defaultBounds = rhs.defaultBounds;
haveBrokenFrameTimeBug = rhs.haveBrokenFrameTimeBug;
}
KeyframesMap keys;
KisNodeWSP node;
KoID id;
KisDefaultBoundsBaseSP defaultBounds;
bool haveBrokenFrameTimeBug = false;
};
KisKeyframeChannel::KisKeyframeChannel(const KoID &id, KisDefaultBoundsBaseSP defaultBounds)
......@@ -516,6 +518,7 @@ void KisKeyframeChannel::loadXML(const QDomElement &channelNode)
if (keyframeNode.nodeName().toUpper() != "KEYFRAME") continue;
KisKeyframeSP keyframe = loadKeyframe(keyframeNode);
KIS_SAFE_ASSERT_RECOVER(keyframe) { continue; }
if (keyframeNode.hasAttribute("color-label")) {
keyframe->setColorLabel(keyframeNode.attribute("color-label").toUInt());
......@@ -608,6 +611,33 @@ void KisKeyframeChannel::requestUpdate(const KisTimeRange &range, const QRect &r
}
}
void KisKeyframeChannel::workaroundBrokenFrameTimeBug(int *time)
{
/**
* Between Krita 4.1 and 4.4 Krita had a bug which resulted in creating frames
* with negative time stamp. The bug has been fixed, but there might be some files
* still in the wild.
*
* TODO: remove this workaround in Krita 5.0, when no such file are left :)
*/
if (*time < 0) {
qWarning() << "WARNING: Loading a file with negative animation frames!";
qWarning() << " The file has been saved with a buggy version of Krita.";
qWarning() << " All the frames with negative ids will be dropped!";
qWarning() << " " << ppVar(this->id()) << ppVar(*time);
m_d->haveBrokenFrameTimeBug = true;
*time = 0;
}
if (m_d->haveBrokenFrameTimeBug) {
while (keyframeAt(*time)) {
(*time)++;
}
}
}
int KisKeyframeChannel::currentTime() const
{
return m_d->defaultBounds->currentTime();
......
......@@ -147,6 +147,7 @@ protected:
virtual KisKeyframeSP loadKeyframe(const QDomElement &keyframeNode) = 0;
virtual void saveKeyframe(KisKeyframeSP keyframe, QDomElement keyframeElement, const QString &layerFilename) = 0;
void workaroundBrokenFrameTimeBug(int *time);
private:
KisKeyframeSP replaceKeyframeAt(int time, KisKeyframeSP newKeyframe);
......
......@@ -260,7 +260,8 @@ void KisRasterKeyframeChannel::saveKeyframe(KisKeyframeSP keyframe, QDomElement
KisKeyframeSP KisRasterKeyframeChannel::loadKeyframe(const QDomElement &keyframeNode)
{
int time = keyframeNode.attribute("time").toUInt();
int time = keyframeNode.attribute("time").toInt();
workaroundBrokenFrameTimeBug(&time);
QPoint offset;
KisDomUtils::loadValue(keyframeNode, "offset", &offset);
......@@ -271,7 +272,7 @@ KisKeyframeSP KisRasterKeyframeChannel::loadKeyframe(const QDomElement &keyframe
if (m_d->frameFilenames.isEmpty()) {
// First keyframe loaded: use the existing frame
Q_ASSERT(keyframeCount() == 1);
KIS_SAFE_ASSERT_RECOVER_NOOP(keyframeCount() == 1);
keyframe = constKeys().begin().value();
// Remove from keys. It will get reinserted with new time once we return
......
......@@ -442,7 +442,9 @@ void KisScalarKeyframeChannel::saveKeyframe(KisKeyframeSP keyframe, QDomElement
KisKeyframeSP KisScalarKeyframeChannel::loadKeyframe(const QDomElement &keyframeNode)
{
int time = keyframeNode.toElement().attribute("time").toUInt();
int time = keyframeNode.toElement().attribute("time").toInt();
workaroundBrokenFrameTimeBug(&time);
qreal value = KisDomUtils::toDouble(keyframeNode.toElement().attribute("value"));
KUndo2Command tempParentCommand;
......
......@@ -106,7 +106,9 @@ KisKeyframeSP KisTransformArgsKeyframeChannel::loadKeyframe(const QDomElement &k
ToolTransformArgs args;
args.fromXML(keyframeNode);
int time = keyframeNode.attribute("time").toUInt();
int time = keyframeNode.attribute("time").toInt();
workaroundBrokenFrameTimeBug(&time);
KisTransformArgsKeyframe *keyframe = new KisTransformArgsKeyframe(this, time, args);
return toQShared(keyframe);
......
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