[krita] libs/ui: Fix copy-pasting pixel data from animated layers

Dmitry Kazakov null at kde.org
Fri Apr 13 11:38:44 UTC 2018


Git commit eca15c47e552827ec9440ac8bcc8140e4c38b601 by Dmitry Kazakov.
Committed on 13/04/2018 at 11:37.
Pushed by dkazakov into branch 'master'.

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

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/eca15c47e552827ec9440ac8bcc8140e4c38b601

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