[calligra/krita-animation-pentikainen] krita: Initial port of the Move Tool to LoD framework
Dmitry Kazakov
dimula73 at gmail.com
Fri Sep 4 13:02:04 UTC 2015
Git commit 9402f93d8093b9fa2afcc72583581f9311bc1650 by Dmitry Kazakov.
Committed on 04/09/2015 at 13:01.
Pushed by dkazakov into branch 'krita-animation-pentikainen'.
Initial port of the Move Tool to LoD framework
Known issues:
1) Clone layers are moved incorrectly
2) Shape layers are also moved incorrectly
3) "Move Selection" action is not ported yet, so it is slow.
The rest seem to work fine! :)
CC:kimageshop at kde.org
M +10 -13 krita/image/kis_group_layer.cc
M +4 -6 krita/image/kis_stroke_strategy_undo_command_based.cpp
M +1 -2 krita/image/kis_stroke_strategy_undo_command_based.h
M +4 -3 krita/plugins/tools/defaulttools/kis_tool_move.cc
M +1 -1 krita/plugins/tools/defaulttools/kis_tool_move.h
M +10 -4 krita/plugins/tools/defaulttools/strokes/move_selection_stroke_strategy.cpp
M +1 -0 krita/plugins/tools/defaulttools/strokes/move_selection_stroke_strategy.h
M +71 -7 krita/plugins/tools/defaulttools/strokes/move_stroke_strategy.cpp
M +27 -0 krita/plugins/tools/defaulttools/strokes/move_stroke_strategy.h
http://commits.kde.org/calligra/9402f93d8093b9fa2afcc72583581f9311bc1650
diff --git a/krita/image/kis_group_layer.cc b/krita/image/kis_group_layer.cc
index acefd80..3d8210d 100644
--- a/krita/image/kis_group_layer.cc
+++ b/krita/image/kis_group_layer.cc
@@ -170,15 +170,16 @@ void KisGroupLayer::resetCache(const KoColorSpace *colorSpace)
if (!m_d->paintDevice) {
- m_d->paintDevice = new KisPaintDevice(this, colorSpace, new KisDefaultBounds(image()));
- m_d->paintDevice->setX(m_d->x);
- m_d->paintDevice->setY(m_d->y);
+ KisPaintDeviceSP dev = new KisPaintDevice(this, colorSpace, new KisDefaultBounds(image()));
+ dev->setX(this->x());
+ dev->setY(this->y());
+ m_d->paintDevice = dev;
}
else if(!(*m_d->paintDevice->colorSpace() == *colorSpace)) {
KisPaintDeviceSP dev = new KisPaintDevice(this, colorSpace, new KisDefaultBounds(image()));
- dev->setX(m_d->x);
- dev->setY(m_d->y);
+ dev->setX(this->x());
+ dev->setY(this->y());
quint8* defaultPixel = new quint8[colorSpace->pixelSize()];
m_d->paintDevice->colorSpace()->
@@ -310,31 +311,27 @@ void KisGroupLayer::accept(KisProcessingVisitor &visitor, KisUndoAdapter *undoAd
qint32 KisGroupLayer::x() const
{
- return m_d->x;
+ return m_d->paintDevice ? m_d->paintDevice->x() : m_d->x;
}
qint32 KisGroupLayer::y() const
{
- return m_d->y;
+ return m_d->paintDevice ? m_d->paintDevice->y() : m_d->y;
}
void KisGroupLayer::setX(qint32 x)
{
- qint32 delta = x - m_d->x;
m_d->x = x;
if(m_d->paintDevice) {
- m_d->paintDevice->setX(m_d->paintDevice->x() + delta);
- Q_ASSERT(m_d->paintDevice->x() == m_d->x);
+ m_d->paintDevice->setX(x);
}
}
void KisGroupLayer::setY(qint32 y)
{
- qint32 delta = y - m_d->y;
m_d->y = y;
if(m_d->paintDevice) {
- m_d->paintDevice->setY(m_d->paintDevice->y() + delta);
- Q_ASSERT(m_d->paintDevice->y() == m_d->y);
+ m_d->paintDevice->setY(y);
}
}
diff --git a/krita/image/kis_stroke_strategy_undo_command_based.cpp b/krita/image/kis_stroke_strategy_undo_command_based.cpp
index 20541c2..f8f8cd9 100644
--- a/krita/image/kis_stroke_strategy_undo_command_based.cpp
+++ b/krita/image/kis_stroke_strategy_undo_command_based.cpp
@@ -44,16 +44,14 @@ KisStrokeStrategyUndoCommandBased(const KUndo2MagicString &name,
KisStrokeStrategyUndoCommandBased::
KisStrokeStrategyUndoCommandBased(const KisStrokeStrategyUndoCommandBased &rhs,
- int levelOfDetail)
+ bool suppressUndo)
: KisSimpleStrokeStrategy(rhs),
- m_supportsLevelOfDetail(rhs.m_supportsLevelOfDetail),
+ m_undo(false),
m_initCommand(rhs.m_initCommand),
m_finishCommand(rhs.m_finishCommand),
- m_undoAdapter(rhs.m_undoAdapter)
+ m_undoAdapter(!suppressUndo ? rhs.m_undoAdapter : 0),
+ m_macroCommand(0)
{
- // LOD_MERGE_FIXME:
- Q_UNUSED(levelOfDetail);
-
KIS_ASSERT_RECOVER_NOOP(!rhs.m_macroCommand &&
!rhs.m_undo &&
"After the stroke has been started, no copying must happen");
diff --git a/krita/image/kis_stroke_strategy_undo_command_based.h b/krita/image/kis_stroke_strategy_undo_command_based.h
index af20509..bd9a02f 100644
--- a/krita/image/kis_stroke_strategy_undo_command_based.h
+++ b/krita/image/kis_stroke_strategy_undo_command_based.h
@@ -109,7 +109,7 @@ protected:
KisStrokeJobData::Exclusivity exclusivity);
KisStrokeStrategyUndoCommandBased(const KisStrokeStrategyUndoCommandBased &rhs,
- int levelOfDetail);
+ bool suppressUndo);
virtual void postProcessToplevelCommand(KUndo2Command *command);
@@ -118,7 +118,6 @@ private:
private:
bool m_undo;
- bool m_supportsLevelOfDetail;
KUndo2CommandSP m_initCommand;
KUndo2CommandSP m_finishCommand;
KisPostExecutionUndoAdapter *m_undoAdapter;
diff --git a/krita/plugins/tools/defaulttools/kis_tool_move.cc b/krita/plugins/tools/defaulttools/kis_tool_move.cc
index b692b8c..2b9e908 100644
--- a/krita/plugins/tools/defaulttools/kis_tool_move.cc
+++ b/krita/plugins/tools/defaulttools/kis_tool_move.cc
@@ -144,7 +144,6 @@ void KisToolMove::startAction(KoPointerEvent *event, MoveToolMode mode)
{
QPoint pos = convertToPixelCoord(event).toPoint();
m_dragStart = pos;
- m_lastDragPos = m_dragStart;
m_moveInProgress = true;
emit moveInProgressChanged();
@@ -200,6 +199,7 @@ void KisToolMove::startAction(KoPointerEvent *event, MoveToolMode mode)
m_strokeId = image->startStroke(strategy);
m_currentlyProcessingNode = node;
+ m_accumulatedOffset = QPoint();
}
void KisToolMove::continueAction(KoPointerEvent *event)
@@ -222,14 +222,15 @@ void KisToolMove::endAction(KoPointerEvent *event)
QPoint pos = convertToPixelCoord(event).toPoint();
pos = applyModifiers(event->modifiers(), pos);
drag(pos);
+
+ m_accumulatedOffset += pos - m_dragStart;
}
void KisToolMove::drag(const QPoint& newPos)
{
KisImageWSP image = currentImage();
- QPoint offset = newPos - m_lastDragPos;
- m_lastDragPos = newPos;
+ QPoint offset = m_accumulatedOffset + newPos - m_dragStart;
image->addJob(m_strokeId,
new MoveStrokeStrategy::Data(offset));
diff --git a/krita/plugins/tools/defaulttools/kis_tool_move.h b/krita/plugins/tools/defaulttools/kis_tool_move.h
index eac0e88..367014d 100644
--- a/krita/plugins/tools/defaulttools/kis_tool_move.h
+++ b/krita/plugins/tools/defaulttools/kis_tool_move.h
@@ -104,7 +104,7 @@ private:
MoveToolOptionsWidget* m_optionsWidget;
QPoint m_dragStart;
- QPoint m_lastDragPos;
+ QPoint m_accumulatedOffset;
KisStrokeId m_strokeId;
diff --git a/krita/plugins/tools/defaulttools/strokes/move_selection_stroke_strategy.cpp b/krita/plugins/tools/defaulttools/strokes/move_selection_stroke_strategy.cpp
index e2a737c..76e3e35 100644
--- a/krita/plugins/tools/defaulttools/strokes/move_selection_stroke_strategy.cpp
+++ b/krita/plugins/tools/defaulttools/strokes/move_selection_stroke_strategy.cpp
@@ -69,6 +69,8 @@ void MoveSelectionStrokeStrategy::initStrokeCallback()
indirect->setTemporaryCompositeOp(paintDevice->colorSpace()->compositeOp(COMPOSITE_OVER));
indirect->setTemporaryOpacity(OPACITY_OPAQUE_U8);
+ m_initialDeviceOffset = QPoint(movedDevice->x(), movedDevice->y());
+
m_selection->setVisible(false);
}
@@ -128,11 +130,15 @@ void MoveSelectionStrokeStrategy::doStrokeCallback(KisStrokeJobData *data)
KisPaintDeviceSP movedDevice = indirect->temporaryTarget();
QRegion dirtyRegion = movedDevice->region();
- dirtyRegion |= dirtyRegion.translated(d->offset);
- movedDevice->setX(movedDevice->x() + d->offset.x());
- movedDevice->setY(movedDevice->y() + d->offset.y());
- m_finalOffset += d->offset;
+ QPoint currentDeviceOffset(movedDevice->x(), movedDevice->y());
+ QPoint newDeviceOffset(m_initialDeviceOffset + d->offset);
+
+ dirtyRegion |= dirtyRegion.translated(newDeviceOffset - currentDeviceOffset);
+
+ movedDevice->setX(newDeviceOffset.x());
+ movedDevice->setY(newDeviceOffset.y());
+ m_finalOffset = d->offset;
m_paintLayer->setDirty(dirtyRegion);
} else {
diff --git a/krita/plugins/tools/defaulttools/strokes/move_selection_stroke_strategy.h b/krita/plugins/tools/defaulttools/strokes/move_selection_stroke_strategy.h
index 3682c57..6b2edf2 100644
--- a/krita/plugins/tools/defaulttools/strokes/move_selection_stroke_strategy.h
+++ b/krita/plugins/tools/defaulttools/strokes/move_selection_stroke_strategy.h
@@ -44,6 +44,7 @@ private:
KisSelectionSP m_selection;
KisUpdatesFacade *m_updatesFacade;
QPoint m_finalOffset;
+ QPoint m_initialDeviceOffset;
};
#endif /* __MOVE_SELECTION_STROKE_STRATEGY_H */
diff --git a/krita/plugins/tools/defaulttools/strokes/move_stroke_strategy.cpp b/krita/plugins/tools/defaulttools/strokes/move_stroke_strategy.cpp
index 618a166..c8c53d63 100644
--- a/krita/plugins/tools/defaulttools/strokes/move_stroke_strategy.cpp
+++ b/krita/plugins/tools/defaulttools/strokes/move_stroke_strategy.cpp
@@ -30,20 +30,53 @@ MoveStrokeStrategy::MoveStrokeStrategy(KisNodeSP node,
KisPostExecutionUndoAdapter *undoAdapter)
: KisStrokeStrategyUndoCommandBased(kundo2_i18n("Move"), false, undoAdapter),
m_node(node),
- m_updatesFacade(updatesFacade)
+ m_updatesFacade(updatesFacade),
+ m_undoEnabled(true),
+ m_updatesEnabled(true)
{
setSupportsWrapAroundMode(true);
}
+MoveStrokeStrategy::MoveStrokeStrategy(const MoveStrokeStrategy &rhs, bool suppressUndo)
+ : KisStrokeStrategyUndoCommandBased(rhs, suppressUndo),
+ m_node(rhs.m_node),
+ m_updatesFacade(rhs.m_updatesFacade),
+ m_finalOffset(rhs.m_finalOffset),
+ m_dirtyRect(rhs.m_dirtyRect),
+ m_undoEnabled(rhs.m_undoEnabled),
+ m_updatesEnabled(rhs.m_updatesEnabled)
+{
+}
+
void MoveStrokeStrategy::setNode(KisNodeSP node)
{
Q_ASSERT(!m_node);
m_node = node;
}
+void MoveStrokeStrategy::saveInitialNodeOffsets(KisNodeSP node)
+{
+ m_initialNodeOffsets.insert(node, QPoint(node->x(), node->y()));
+
+ KisNodeSP child = node->firstChild();
+ while(child) {
+ saveInitialNodeOffsets(child);
+ child = child->nextSibling();
+ }
+}
+
+void MoveStrokeStrategy::initStrokeCallback()
+{
+ if (m_node) {
+ saveInitialNodeOffsets(m_node);
+ }
+
+ KisStrokeStrategyUndoCommandBased::initStrokeCallback();
+}
+
void MoveStrokeStrategy::finishStrokeCallback()
{
- if(m_node) {
+ if(m_node && m_undoEnabled) {
KUndo2Command *updateCommand =
new KisUpdateCommand(m_node, m_dirtyRect, m_updatesFacade, true);
@@ -54,6 +87,10 @@ void MoveStrokeStrategy::finishStrokeCallback()
KisStrokeJobData::EXCLUSIVE);
}
+ if (m_node && !m_updatesEnabled) {
+ m_updatesFacade->refreshGraphAsync(m_node, m_dirtyRect);
+ }
+
KisStrokeStrategyUndoCommandBased::finishStrokeCallback();
}
@@ -81,7 +118,7 @@ void MoveStrokeStrategy::doStrokeCallback(KisStrokeJobData *data)
* NOTE: we do not care about threading here, because
* all our jobs are declared sequential
*/
- m_finalOffset += d->offset;
+ m_finalOffset = d->offset;
}
else {
KisStrokeStrategyUndoCommandBased::doStrokeCallback(data);
@@ -93,16 +130,25 @@ void MoveStrokeStrategy::moveAndUpdate(QPoint offset)
QRect dirtyRect = moveNode(m_node, offset);
m_dirtyRect |= dirtyRect;
- m_updatesFacade->refreshGraphAsync(m_node, dirtyRect);
+ if (m_updatesEnabled) {
+ m_updatesFacade->refreshGraphAsync(m_node, dirtyRect);
+ }
}
QRect MoveStrokeStrategy::moveNode(KisNodeSP node, QPoint offset)
{
QRect dirtyRect = node->extent();
- dirtyRect |= dirtyRect.translated(offset);
+ QPoint newOffset = m_initialNodeOffsets[node] + offset;
+
+ /**
+ * Some layers, e.g. clones need an update to change extent(), so
+ * calculate the dirty rect manually
+ */
+ QPoint currentOffset(node->x(), node->y());
+ dirtyRect |= dirtyRect.translated(newOffset - currentOffset);
- node->setX(node->x() + offset.x());
- node->setY(node->y() + offset.y());
+ node->setX(newOffset.x());
+ node->setY(newOffset.y());
KisNodeMoveCommand2::tryNotifySelection(node);
KisNodeSP child = node->firstChild();
@@ -126,3 +172,21 @@ void MoveStrokeStrategy::addMoveCommands(KisNodeSP node, KUndo2Command *parent)
child = child->nextSibling();
}
}
+
+void MoveStrokeStrategy::setUndoEnabled(bool value)
+{
+ m_undoEnabled = value;
+}
+
+void MoveStrokeStrategy::setUpdatesEnabled(bool value)
+{
+ m_updatesEnabled = value;
+}
+
+KisStrokeStrategy* MoveStrokeStrategy::createLodClone(int levelOfDetail)
+{
+ MoveStrokeStrategy *clone = new MoveStrokeStrategy(*this, levelOfDetail > 0);
+ clone->setUndoEnabled(false);
+ this->setUpdatesEnabled(false);
+ return clone;
+}
diff --git a/krita/plugins/tools/defaulttools/strokes/move_stroke_strategy.h b/krita/plugins/tools/defaulttools/strokes/move_stroke_strategy.h
index e962a6a..a0bd3b0 100644
--- a/krita/plugins/tools/defaulttools/strokes/move_stroke_strategy.h
+++ b/krita/plugins/tools/defaulttools/strokes/move_stroke_strategy.h
@@ -19,9 +19,12 @@
#ifndef __MOVE_STROKE_STRATEGY_H
#define __MOVE_STROKE_STRATEGY_H
+#include <QHash>
+
#include "kis_stroke_strategy_undo_command_based.h"
#include "kis_types.h"
#include "kritadefaulttools_export.h"
+#include "kis_lod_transform.h"
class KisUpdatesFacade;
class KisPostExecutionUndoAdapter;
@@ -37,7 +40,20 @@ public:
offset(_offset)
{
}
+
+ KisStrokeJobData* createLodClone(int levelOfDetail) {
+ return new Data(*this, levelOfDetail);
+ }
+
QPoint offset;
+
+ private:
+ Data(const Data &rhs, int levelOfDetail)
+ : KisStrokeJobData(rhs)
+ {
+ KisLodTransform t(levelOfDetail);
+ offset = t.map(rhs.offset);
+ }
};
public:
@@ -54,20 +70,31 @@ public:
void setNode(KisNodeSP node);
+ void initStrokeCallback();
void finishStrokeCallback();
void cancelStrokeCallback();
void doStrokeCallback(KisStrokeJobData *data);
+ KisStrokeStrategy* createLodClone(int levelOfDetail);
+
+private:
+ MoveStrokeStrategy(const MoveStrokeStrategy &rhs, bool suppressUndo);
+ void setUndoEnabled(bool value);
+ void setUpdatesEnabled(bool value);
private:
void moveAndUpdate(QPoint offset);
QRect moveNode(KisNodeSP node, QPoint offset);
void addMoveCommands(KisNodeSP node, KUndo2Command *parent);
+ void saveInitialNodeOffsets(KisNodeSP node);
private:
KisNodeSP m_node;
KisUpdatesFacade *m_updatesFacade;
QPoint m_finalOffset;
QRect m_dirtyRect;
+ bool m_undoEnabled;
+ bool m_updatesEnabled;
+ QHash<KisNodeSP, QPoint> m_initialNodeOffsets;
};
#endif /* __MOVE_STROKE_STRATEGY_H */
More information about the kimageshop
mailing list