[krita/krita/4.0] libs/ui: Fix copy-pasting pixel data from animated layers
Boudewijn Rempt
null at kde.org
Wed May 2 11:54:31 UTC 2018
Git commit a4df42f88c2e9dd01e83110270ba5bfdf939d408 by Boudewijn Rempt, on behalf of Dmitry Kazakov.
Committed on 02/05/2018 at 11:54.
Pushed by rempt into branch 'krita/4.0'.
Fix copy-pasting pixel data from animated layers
Now when you copy-paste animated frame data, it is pasted into
exactly the same time range position. It means that if you later
merge down this data back to the original layer, you will not get
a data loss. The data will be merged exactly into the position where
it has been taken from.
BUG:364162
CC:kimageshop at kde.org
(cherry picked from commit 39ec1d47a59425969814dc840209ec2433bdd133)
M +18 -2 libs/ui/actions/KisPasteActionFactory.cpp
M +17 -3 libs/ui/actions/kis_selection_action_factories.cpp
M +30 -3 libs/ui/kis_clipboard.cc
M +4 -1 libs/ui/kis_clipboard.h
https://commits.kde.org/krita/a4df42f88c2e9dd01e83110270ba5bfdf939d408
diff --git a/libs/ui/actions/KisPasteActionFactory.cpp b/libs/ui/actions/KisPasteActionFactory.cpp
index 08e95446a1a..d2e9dea045a 100644
--- a/libs/ui/actions/KisPasteActionFactory.cpp
+++ b/libs/ui/actions/KisPasteActionFactory.cpp
@@ -39,6 +39,9 @@
#include "kis_algebra_2d.h"
#include <KoShapeMoveCommand.h>
#include <KoShapeReorderCommand.h>
+#include "kis_time_range.h"
+#include "kis_keyframe_channel.h"
+#include "kis_raster_keyframe_channel.h"
namespace {
QPointF getFittingOffset(QList<KoShape*> shapes,
@@ -194,8 +197,9 @@ void KisPasteActionFactory::run(bool pasteAtCursorPosition, KisViewManager *view
return;
}
+ KisTimeRange range;
const QRect fittingBounds = pasteAtCursorPosition ? QRect() : image->bounds();
- KisPaintDeviceSP clip = KisClipboard::instance()->clip(fittingBounds, true);
+ KisPaintDeviceSP clip = KisClipboard::instance()->clip(fittingBounds, true, &range);
if (clip) {
if (pasteAtCursorPosition) {
@@ -209,10 +213,22 @@ void KisPasteActionFactory::run(bool pasteAtCursorPosition, KisViewManager *view
}
KisImportCatcher::adaptClipToImageColorSpace(clip, image);
- KisPaintLayer *newLayer = new KisPaintLayer(image.data(), image->nextLayerName() + i18n("(pasted)"), OPACITY_OPAQUE_U8, clip);
+ KisPaintLayerSP newLayer = new KisPaintLayer(image.data(),
+ image->nextLayerName() + i18n("(pasted)"),
+ OPACITY_OPAQUE_U8);
KisNodeSP aboveNode = view->activeLayer();
KisNodeSP parentNode = aboveNode ? aboveNode->parent() : image->root();
+ if (range.isValid()) {
+ newLayer->enableAnimation();
+ KisKeyframeChannel *channel = newLayer->getKeyframeChannel(KisKeyframeChannel::Content.id(), true);
+ KisRasterKeyframeChannel *rasterChannel = dynamic_cast<KisRasterKeyframeChannel*>(channel);
+ rasterChannel->importFrame(range.start(), clip, 0);
+ rasterChannel->addKeyframe(range.end() + 1, 0);
+ } else {
+ newLayer->paintDevice()->makeCloneFromRough(clip, clip->extent());
+ }
+
KUndo2Command *cmd = new KisImageLayerAddCommand(image, newLayer, parentNode, aboveNode);
KisProcessingApplicator *ap = beginAction(view, cmd->text());
ap->applyCommand(cmd, KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::NORMAL);
diff --git a/libs/ui/actions/kis_selection_action_factories.cpp b/libs/ui/actions/kis_selection_action_factories.cpp
index 6fb605e286e..9116fcfeb4f 100644
--- a/libs/ui/actions/kis_selection_action_factories.cpp
+++ b/libs/ui/actions/kis_selection_action_factories.cpp
@@ -61,6 +61,9 @@
#include "KisPart.h"
#include "kis_shape_layer.h"
#include <kis_shape_controller.h>
+#include "kis_image_animation_interface.h"
+#include "kis_time_range.h"
+#include "kis_keyframe_channel.h"
#include <processing/fill_processing_visitor.h>
@@ -71,7 +74,10 @@
namespace ActionHelper {
- void copyFromDevice(KisViewManager *view, KisPaintDeviceSP device, bool makeSharpClip = false)
+ void copyFromDevice(KisViewManager *view,
+ KisPaintDeviceSP device,
+ bool makeSharpClip = false,
+ const KisTimeRange &range = KisTimeRange())
{
KisImageWSP image = view->image();
if (!image) return;
@@ -126,7 +132,7 @@ namespace ActionHelper {
}
}
- KisClipboard::instance()->setClip(clip, rc.topLeft());
+ KisClipboard::instance()->setClip(clip, rc.topLeft(), range);
}
}
@@ -303,7 +309,15 @@ void KisCutCopyActionFactory::run(bool willCut, bool makeSharpClip, KisViewManag
return;
}
- ActionHelper::copyFromDevice(view, dev, makeSharpClip);
+ KisTimeRange range;
+
+ KisKeyframeChannel *channel = node->getKeyframeChannel(KisKeyframeChannel::Content.id());
+ if (channel) {
+ const int currentTime = image->animationInterface()->currentTime();
+ range = channel->affectedFrames(currentTime);
+ }
+
+ ActionHelper::copyFromDevice(view, dev, makeSharpClip, range);
}
if (willCut) {
diff --git a/libs/ui/kis_clipboard.cc b/libs/ui/kis_clipboard.cc
index 83a771e407a..6db87cdae6e 100644
--- a/libs/ui/kis_clipboard.cc
+++ b/libs/ui/kis_clipboard.cc
@@ -43,6 +43,7 @@
#include <kis_annotation.h>
#include <kis_node.h>
#include <kis_image.h>
+#include <kis_time_range.h>
// local
#include "kis_config.h"
@@ -76,7 +77,7 @@ KisClipboard* KisClipboard::instance()
return s_instance;
}
-void KisClipboard::setClip(KisPaintDeviceSP dev, const QPoint& topLeft)
+void KisClipboard::setClip(KisPaintDeviceSP dev, const QPoint& topLeft, const KisTimeRange &range)
{
if (!dev)
return;
@@ -91,7 +92,6 @@ void KisClipboard::setClip(KisPaintDeviceSP dev, const QPoint& topLeft)
Q_ASSERT(store);
Q_ASSERT(!store->bad());
-
// Layer data
if (store->open("layerdata")) {
if (!dev->write(writer)) {
@@ -103,6 +103,12 @@ void KisClipboard::setClip(KisPaintDeviceSP dev, const QPoint& topLeft)
store->close();
}
+ // copied frame time limits
+ if (range.isValid() && store->open("timeRange")) {
+ store->write(QString("%1 %2").arg(range.start()).arg(range.end()).toLatin1());
+ store->close();
+ }
+
// Coordinates
if (store->open("topLeft")) {
store->write(QString("%1 %2").arg(topLeft.x()).arg(topLeft.y()).toLatin1());
@@ -163,10 +169,19 @@ void KisClipboard::setClip(KisPaintDeviceSP dev, const QPoint& topLeft)
}
-KisPaintDeviceSP KisClipboard::clip(const QRect &imageBounds, bool showPopup)
+void KisClipboard::setClip(KisPaintDeviceSP dev, const QPoint& topLeft)
+{
+ setClip(dev, topLeft, KisTimeRange());
+}
+
+KisPaintDeviceSP KisClipboard::clip(const QRect &imageBounds, bool showPopup, KisTimeRange *clipRange)
{
QByteArray mimeType("application/x-krita-selection");
+ if (clipRange) {
+ *clipRange = KisTimeRange();
+ }
+
QClipboard *cb = QApplication::clipboard();
const QMimeData *cbData = cb->mimeData();
@@ -239,6 +254,18 @@ KisPaintDeviceSP KisClipboard::clip(const QRect &imageBounds, bool showPopup)
clip->setX(clip->x() + diff.x());
clip->setY(clip->y() + diff.y());
}
+
+ if (store->hasFile("timeRange") && clipRange) {
+ store->open("timeRange");
+ QString str = store->read(store->size());
+ store->close();
+ QStringList list = str.split(' ');
+ if (list.size() == 2) {
+ KisTimeRange range(list[0].toInt(), list[1].toInt(), true);
+ *clipRange = range;
+ qDebug() << "Pasted time range" << range;
+ }
+ }
}
}
diff --git a/libs/ui/kis_clipboard.h b/libs/ui/kis_clipboard.h
index 81bd0381303..12fe86a9a3d 100644
--- a/libs/ui/kis_clipboard.h
+++ b/libs/ui/kis_clipboard.h
@@ -27,6 +27,7 @@
class QRect;
class QMimeData;
+class KisTimeRange;
class KisBlockUntilOperationsFinishedMediator;
enum enumPasteBehaviour {
@@ -61,10 +62,12 @@ public:
*/
void setClip(KisPaintDeviceSP dev, const QPoint& topLeft);
+ void setClip(KisPaintDeviceSP dev, const QPoint& topLeft, const KisTimeRange &range);
+
/**
* Get the contents of the clipboard in the form of a paint device.
*/
- KisPaintDeviceSP clip(const QRect &imageBounds, bool showPopup);
+ KisPaintDeviceSP clip(const QRect &imageBounds, bool showPopup, KisTimeRange *clipRange = 0);
bool hasClip() const;
More information about the kimageshop
mailing list