Git commit e30395b251684b8cfdbbcce6606d9e2b0edb30e1 by Dmitry Kazakov. Committed on 31/01/2013 at 16:16. Pushed by dkazakov into branch 'master'. Added an ability to transform layers recursively with a Transform Tool Now the transform tool supports transforming of a group of layers or masks recursively in a single pass. You can use it for transforming a set of layers grouped into a Group Layer or just transform a single layer with all its masks (e.g. with transparency masks). This option is enabled by default, but you can disable it by switching a small button in the transform tool configuration docker. This button has a icon of a small spider (the tool "crawls" through the layers :) ) [0]. It would be cool, if someone tested it a bit ;) [0] - you can suggest any other icon for this, actually =) BUG:297927,314176 CCMAIL:kimageshop@kde.org M +5 -4 krita/image/kis_processing_visitor.cpp M +4 -2 krita/image/kis_processing_visitor.h M +1 -0 krita/plugins/tools/tool_transform2/CMakeLists.txt M +56 -40 krita/plugins/tools/tool_transform2/kis_tool_transform.cc M +5 -5 krita/plugins/tools/tool_transform2/kis_tool_transform.h M +11 -0 krita/plugins/tools/tool_transform2/kis_tool_transform_config_widget.cpp M +3 -0 krita/plugins/tools/tool_transform2/kis_tool_transform_config_widget.h A +- -- krita/plugins/tools/tool_transform2/krita_tool_transform_recursive.png M +96 -44 krita/plugins/tools/tool_transform2/strokes/transform_stroke_strategy.cpp M +31 -15 krita/plugins/tools/tool_transform2/strokes/transform_stroke_strategy.h M +35 -16 krita/plugins/tools/tool_transform2/wdg_tool_transform.ui http://commits.kde.org/calligra/e30395b251684b8cfdbbcce6606d9e2b0edb30e1 diff --git a/krita/image/kis_processing_visitor.cpp b/krita/image/kis_processing_visitor.cpp index 00e1993..5761544 100644 --- a/krita/image/kis_processing_visitor.cpp +++ b/krita/image/kis_processing_visitor.cpp @@ -30,23 +30,24 @@ KisProcessingVisitor::ProgressHelper::ProgressHelper(const KisNode *node) if(progressProxy) { m_progressUpdater = new KoProgressUpdater(progressProxy); m_progressUpdater->start(); - m_updater = m_progressUpdater->startSubtask(); m_progressUpdater->moveToThread(node->thread()); } else { m_progressUpdater = 0; - m_updater = 0; } } KisProcessingVisitor::ProgressHelper::~ProgressHelper() { - m_progressUpdater->deleteLater(); + if (m_progressUpdater) { + m_progressUpdater->deleteLater(); + } } KoUpdater* KisProcessingVisitor::ProgressHelper::updater() const { - return m_updater; + QMutexLocker l(&m_progressMutex); + return m_progressUpdater ? m_progressUpdater->startSubtask() : 0; } diff --git a/krita/image/kis_processing_visitor.h b/krita/image/kis_processing_visitor.h index 9984d3c..dc3aef2 100644 --- a/krita/image/kis_processing_visitor.h +++ b/krita/image/kis_processing_visitor.h @@ -22,6 +22,8 @@ #include "krita_export.h" #include "kis_shared.h" +#include + class KisNode; class KoUpdater; class KoProgressUpdater; @@ -57,7 +59,7 @@ public: virtual void visit(KisTransparencyMask *mask, KisUndoAdapter *undoAdapter) = 0; virtual void visit(KisSelectionMask *mask, KisUndoAdapter *undoAdapter) = 0; -protected: +public: class ProgressHelper { public: ProgressHelper(const KisNode *node); @@ -66,7 +68,7 @@ protected: KoUpdater* updater() const; private: KoProgressUpdater *m_progressUpdater; - KoUpdater *m_updater; + mutable QMutex m_progressMutex; }; }; diff --git a/krita/plugins/tools/tool_transform2/CMakeLists.txt b/krita/plugins/tools/tool_transform2/CMakeLists.txt index 598c009..7a6c19b 100644 --- a/krita/plugins/tools/tool_transform2/CMakeLists.txt +++ b/krita/plugins/tools/tool_transform2/CMakeLists.txt @@ -25,5 +25,6 @@ install(TARGETS kritatooltransform DESTINATION ${PLUGIN_INSTALL_DIR}) install( FILES rotate_cursor.xpm krita_tool_transform.png + krita_tool_transform_recursive.png DESTINATION ${DATA_INSTALL_DIR}/krita/pics) install( FILES kritatooltransform.desktop DESTINATION ${SERVICES_INSTALL_DIR}) diff --git a/krita/plugins/tools/tool_transform2/kis_tool_transform.cc b/krita/plugins/tools/tool_transform2/kis_tool_transform.cc index 63300c2..7e14215 100644 --- a/krita/plugins/tools/tool_transform2/kis_tool_transform.cc +++ b/krita/plugins/tools/tool_transform2/kis_tool_transform.cc @@ -859,11 +859,11 @@ void KisToolTransform::mousePressEvent(KoPointerEvent *event) KisImageWSP kisimage = image(); - if (!currentNode() || !currentNode()->paintDevice()) + if (!currentNode()) return; setMode(KisTool::PAINT_MODE); - if (kisimage && currentNode()->paintDevice() && event->button() == Qt::LeftButton) { + if (kisimage && event->button() == Qt::LeftButton) { QPointF mousePos = QPointF(event->point.x() * kisimage->xRes(), event->point.y() * kisimage->yRes()); if (!m_strokeId) { startStroke(m_currentArgs.mode()); @@ -1932,8 +1932,7 @@ void KisToolTransform::updateSelectionPath() if (selection) { selectionOutline = selection->outline(); } else { - KisPaintDeviceSP dev = currentNode()->paintDevice(); - selectionOutline << dev->exactBounds(); + selectionOutline << m_selectedPortionCache->exactBounds(); } const KisCoordinatesConverter *converter = m_canvas->coordinatesConverter(); @@ -1946,32 +1945,16 @@ void KisToolTransform::updateSelectionPath() } } -void KisToolTransform::initThumbnailImage() +void KisToolTransform::initThumbnailImage(KisPaintDeviceSP previewDevice) { m_transform = QTransform(); m_origImg = QImage(); m_currImg = QImage(); - - KisPaintDeviceSP dev; - KisSelectionSP selection = currentSelection(); - - if (!currentNode() || !(dev = currentNode()->paintDevice())) { - return; - } - - QRect srcRect(m_transaction.originalRect().toAlignedRect()); - - if (selection) { - m_selectedPortionCache = new KisPaintDevice(dev->colorSpace()); - KisPainter gc(m_selectedPortionCache); - gc.setSelection(selection); - gc.bitBlt(srcRect.topLeft(), dev, srcRect); - } else { - m_selectedPortionCache = new KisPaintDevice(*dev); - } + m_selectedPortionCache = previewDevice; const int maxSize = 2000; + QRect srcRect(m_transaction.originalRect().toAlignedRect()); int x, y, w, h; srcRect.getRect(&x, &y, &w, &h); @@ -2039,7 +2022,7 @@ void KisToolTransform::startStroke(ToolTransformArgs::TransformMode mode) KisPaintDeviceSP dev; - if (!currentNode() || !(dev = currentNode()->paintDevice())) { + if (!currentNode()) { return; } @@ -2058,25 +2041,25 @@ void KisToolTransform::startStroke(ToolTransformArgs::TransformMode mode) return; } - KisSelectionSP selection = currentSelection(); + m_optWidget->setRecursiveOptionEnabled(false); + m_workRecursively = m_optWidget->workRecursively() || + !currentNode()->paintDevice(); + + TransformStrokeStrategy *strategy = new TransformStrokeStrategy(currentNode(), currentSelection(), image()->postExecutionUndoAdapter(), image()->undoAdapter()); + KisPaintDeviceSP previewDevice = strategy->previewDevice(); - QRectF originalRect; - originalRect = selection ? - selection->selectedExactRect() : dev->exactBounds(); + KisSelectionSP selection = currentSelection(); + QRect srcRect = selection ? selection->selectedExactRect() : previewDevice->exactBounds(); - m_transaction = TransformTransactionProperties(originalRect, &m_currentArgs); + m_transaction = TransformTransactionProperties(srcRect, &m_currentArgs); - initThumbnailImage(); + initThumbnailImage(previewDevice); updateSelectionPath(); initTransformMode(mode); - KisStrokeStrategy *strategy = new TransformStrokeStrategy(currentNode(), currentSelection(), m_selectedPortionCache, image()->postExecutionUndoAdapter(), image()->undoAdapter()); - m_strokeId = image()->startStroke(strategy); - - image()->addJob(m_strokeId, - new TransformStrokeStrategy::ClearSelectionData()); + clearDevices(currentNode(), m_workRecursively); Q_ASSERT(m_changesTracker.isEmpty()); commitChanges(); @@ -2087,15 +2070,13 @@ void KisToolTransform::endStroke() if (!m_strokeId) return; if (!m_currentArgs.isIdentity()) { - image()->addJob(m_strokeId, - new TransformStrokeStrategy::TransformData( - TransformStrokeStrategy::TransformData::PAINT_DEVICE, - m_currentArgs)); + transformDevices(currentNode(), m_workRecursively); image()->addJob(m_strokeId, new TransformStrokeStrategy::TransformData( TransformStrokeStrategy::TransformData::SELECTION, - m_currentArgs)); + m_currentArgs, + currentNode())); image()->endStroke(m_strokeId); } else { @@ -2104,6 +2085,7 @@ void KisToolTransform::endStroke() m_strokeId.clear(); m_changesTracker.reset(); + m_optWidget->setRecursiveOptionEnabled(true); } void KisToolTransform::cancelStroke() @@ -2113,6 +2095,7 @@ void KisToolTransform::cancelStroke() image()->cancelStroke(m_strokeId); m_strokeId.clear(); m_changesTracker.reset(); + m_optWidget->setRecursiveOptionEnabled(true); } void KisToolTransform::commitChanges() @@ -2128,6 +2111,39 @@ void KisToolTransform::slotTrackerChangedConfig() updateOptionWidget(); } +void KisToolTransform::clearDevices(KisNodeSP node, bool recursive) +{ + if (recursive) { + // simple tail-recursive iteration + KisNodeSP prevNode = node->lastChild(); + while(prevNode) { + clearDevices(prevNode, recursive); + prevNode = prevNode->prevSibling(); + } + } + + image()->addJob(m_strokeId, + new TransformStrokeStrategy::ClearSelectionData(node)); +} + +void KisToolTransform::transformDevices(KisNodeSP node, bool recursive) +{ + if (recursive) { + // simple tail-recursive iteration + KisNodeSP prevNode = node->lastChild(); + while(prevNode) { + transformDevices(prevNode, recursive); + prevNode = prevNode->prevSibling(); + } + } + + image()->addJob(m_strokeId, + new TransformStrokeStrategy::TransformData( + TransformStrokeStrategy::TransformData::PAINT_DEVICE, + m_currentArgs, + node)); +} + QWidget* KisToolTransform::createOptionWidget() { m_optWidget = new KisToolTransformConfigWidget(&m_transaction, m_canvas, 0); Q_CHECK_PTR(m_optWidget); diff --git a/krita/plugins/tools/tool_transform2/kis_tool_transform.h b/krita/plugins/tools/tool_transform2/kis_tool_transform.h index 9e6fca9..16e043c 100644 --- a/krita/plugins/tools/tool_transform2/kis_tool_transform.h +++ b/krita/plugins/tools/tool_transform2/kis_tool_transform.h @@ -97,6 +97,9 @@ protected: void requestStrokeCancellation(); private: + void clearDevices(KisNodeSP node, bool recursive); + void transformDevices(KisNodeSP node, bool recursive); + void startStroke(ToolTransformArgs::TransformMode mode); void endStroke(); void cancelStroke(); @@ -271,13 +274,9 @@ private: void initTransformMode(ToolTransformArgs::TransformMode mode); - void initThumbnailImage(); + void initThumbnailImage(KisPaintDeviceSP previewDevice); void updateSelectionPath(); void updateApplyResetAvailability(); - void transformDevice(KisPaintDeviceSP device, - KoUpdaterPtr warpUpdater, - KoUpdaterPtr affineUpdater, - KoUpdaterPtr perspectiveUpdater); private: enum function {ROTATE = 0, MOVE, RIGHTSCALE, TOPRIGHTSCALE, TOPSCALE, TOPLEFTSCALE, @@ -311,6 +310,7 @@ private: QImage m_currImg; // origImg transformed using m_transform KisPaintDeviceSP m_selectedPortionCache; KisStrokeId m_strokeId; + bool m_workRecursively; QPainterPath m_selectionPath; // original (unscaled) selection outline, used for painting decorations diff --git a/krita/plugins/tools/tool_transform2/kis_tool_transform_config_widget.cpp b/krita/plugins/tools/tool_transform2/kis_tool_transform_config_widget.cpp index c98556b..3e65c72 100644 --- a/krita/plugins/tools/tool_transform2/kis_tool_transform_config_widget.cpp +++ b/krita/plugins/tools/tool_transform2/kis_tool_transform_config_widget.cpp @@ -39,6 +39,7 @@ KisToolTransformConfigWidget::KisToolTransformConfigWidget(TransformTransactionP { setupUi(this); showDecorationsBox->setIcon(koIcon("krita_tool_transform")); + chkWorkRecursively->setIcon(koIcon("krita_tool_transform_recursive.png")); label_shearX->setPixmap(koIcon("shear_horizontal").pixmap(16, 16)); label_shearY->setPixmap(koIcon("shear_vertical").pixmap(16, 16)); @@ -272,6 +273,16 @@ void KisToolTransformConfigWidget::resetRotationCenterButtons() } } +void KisToolTransformConfigWidget::setRecursiveOptionEnabled(bool value) +{ + chkWorkRecursively->setEnabled(value); +} + +bool KisToolTransformConfigWidget::workRecursively() const +{ + return chkWorkRecursively->isChecked();; +} + void KisToolTransformConfigWidget::setTooBigLabelVisible(bool value) { tooBigLabelWidget->setVisible(value); diff --git a/krita/plugins/tools/tool_transform2/kis_tool_transform_config_widget.h b/krita/plugins/tools/tool_transform2/kis_tool_transform_config_widget.h index 2d3b0b6..f905fc9 100644 --- a/krita/plugins/tools/tool_transform2/kis_tool_transform_config_widget.h +++ b/krita/plugins/tools/tool_transform2/kis_tool_transform_config_widget.h @@ -39,6 +39,9 @@ public: void setTooBigLabelVisible(bool value); bool showDecorations() const; + bool workRecursively() const; + void setRecursiveOptionEnabled(bool value); + public slots: void updateConfig(const ToolTransformArgs &config); diff --git a/krita/plugins/tools/tool_transform2/krita_tool_transform_recursive.png b/krita/plugins/tools/tool_transform2/krita_tool_transform_recursive.png new file mode 100644 index 0000000..b5d5c73 Binary files /dev/null and b/krita/plugins/tools/tool_transform2/krita_tool_transform_recursive.png differ diff --git a/krita/plugins/tools/tool_transform2/strokes/transform_stroke_strategy.cpp b/krita/plugins/tools/tool_transform2/strokes/transform_stroke_strategy.cpp index 7e5b20e..0e9d13d 100644 --- a/krita/plugins/tools/tool_transform2/strokes/transform_stroke_strategy.cpp +++ b/krita/plugins/tools/tool_transform2/strokes/transform_stroke_strategy.cpp @@ -32,26 +32,79 @@ #include -TransformStrokeStrategy::TransformStrokeStrategy(KisNodeSP node, +TransformStrokeStrategy::TransformStrokeStrategy(KisNodeSP rootNode, KisSelectionSP selection, - KisPaintDeviceSP selectedPortionCache, KisPostExecutionUndoAdapter *undoAdapter, KisUndoAdapter *legacyUndoAdapter) : KisStrokeStrategyUndoCommandBased(i18n("Transform Stroke"), false, undoAdapter), - m_node(node), m_selection(selection), - m_selectedPortionCache(selectedPortionCache), - m_legacyUndoAdapter(legacyUndoAdapter), - m_progressUpdater(0) + m_legacyUndoAdapter(legacyUndoAdapter) { - Q_ASSERT(m_node); + if (rootNode->childCount() || !rootNode->paintDevice()) { + m_previewDevice = createDeviceCache(rootNode->projection()); + } else { + m_previewDevice = createDeviceCache(rootNode->paintDevice()); + putDeviceCache(rootNode->paintDevice(), m_previewDevice); + } + + Q_ASSERT(m_previewDevice); } TransformStrokeStrategy::~TransformStrokeStrategy() { - if (m_progressUpdater) { - m_progressUpdater->deleteLater(); +} + +KisPaintDeviceSP TransformStrokeStrategy::previewDevice() const +{ + return m_previewDevice; +} + +KisPaintDeviceSP TransformStrokeStrategy::createDeviceCache(KisPaintDeviceSP dev) +{ + KisPaintDeviceSP cache; + + if (m_selection) { + QRect srcRect = m_selection->selectedExactRect(); + + cache = new KisPaintDevice(dev->colorSpace()); + KisPainter gc(cache); + gc.setSelection(m_selection); + gc.bitBlt(srcRect.topLeft(), dev, srcRect); + } else { + cache = new KisPaintDevice(*dev); } + + return cache; +} + +bool TransformStrokeStrategy::haveDeviceInCache(KisPaintDeviceSP src) +{ + QMutexLocker l(&m_devicesCacheMutex); + return m_devicesCacheHash.contains(src.data()); +} + +void TransformStrokeStrategy::putDeviceCache(KisPaintDeviceSP src, KisPaintDeviceSP cache) +{ + QMutexLocker l(&m_devicesCacheMutex); + m_devicesCacheHash.insert(src.data(), cache); +} + +KisPaintDeviceSP TransformStrokeStrategy::getDeviceCache(KisPaintDeviceSP src) +{ + QMutexLocker l(&m_devicesCacheMutex); + KisPaintDeviceSP cache = m_devicesCacheHash.value(src.data()); + if (!cache) { + qWarning() << "WARNING: Transform Stroke: the device is absent in cache!"; + } + + return cache; +} + +bool TransformStrokeStrategy::checkBelongsToSelection(KisPaintDeviceSP device) const +{ + return m_selection && + (device == m_selection->pixelSelection().data() || + device == m_selection->projection().data()); } void TransformStrokeStrategy::doStrokeCallback(KisStrokeJobData *data) @@ -61,20 +114,25 @@ void TransformStrokeStrategy::doStrokeCallback(KisStrokeJobData *data) if(td) { if (td->destination == TransformData::PAINT_DEVICE) { - QRect oldExtent = m_node->extent(); + QRect oldExtent = td->node->extent(); + KisPaintDeviceSP device = td->node->paintDevice(); - KisPaintDeviceSP device = m_node->paintDevice(); + if (device && !checkBelongsToSelection(device)) { + KisPaintDeviceSP cachedPortion = getDeviceCache(device); + Q_ASSERT(cachedPortion); - KisTransaction transaction("Transform Device", device); + KisTransaction transaction("Transform Device", device); - transformAndMergeDevice(td->config, m_selectedPortionCache, - device); + KisProcessingVisitor::ProgressHelper helper(td->node); + transformAndMergeDevice(td->config, cachedPortion, + device, &helper); - runAndSaveCommand(KUndo2CommandSP(transaction.endAndTake()), - KisStrokeJobData::CONCURRENT, - KisStrokeJobData::NORMAL); + runAndSaveCommand(KUndo2CommandSP(transaction.endAndTake()), + KisStrokeJobData::CONCURRENT, + KisStrokeJobData::NORMAL); - m_node->setDirty(oldExtent | m_node->extent()); + td->node->setDirty(oldExtent | td->node->extent()); + } } else if (m_selection) { // FIXME: do it undoable m_selection->flatten(); @@ -82,8 +140,10 @@ void TransformStrokeStrategy::doStrokeCallback(KisStrokeJobData *data) KisSelectionTransaction transaction("Transform Selection", m_legacyUndoAdapter, m_selection); + KisProcessingVisitor::ProgressHelper helper(td->node); transformDevice(td->config, - m_selection->pixelSelection()); + m_selection->pixelSelection(), + &helper); runAndSaveCommand(KUndo2CommandSP(transaction.endAndTake()), KisStrokeJobData::CONCURRENT, @@ -92,17 +152,20 @@ void TransformStrokeStrategy::doStrokeCallback(KisStrokeJobData *data) m_legacyUndoAdapter->emitSelectionChanged(); } } else if (csd) { - clearSelection(); + KisPaintDeviceSP device = csd->node->paintDevice(); + if (device && !checkBelongsToSelection(device)) { + if (!haveDeviceInCache(device)) { + putDeviceCache(device, createDeviceCache(device)); + } + clearSelection(device); + } } else { KisStrokeStrategyUndoCommandBased::doStrokeCallback(data); } } -void TransformStrokeStrategy::clearSelection() +void TransformStrokeStrategy::clearSelection(KisPaintDeviceSP device) { - KisPaintDeviceSP device = m_node->paintDevice(); - Q_ASSERT(device); - KisTransaction transaction("Clear Selection", device); if (m_selection) { device->clearSelection(m_selection); @@ -118,11 +181,12 @@ void TransformStrokeStrategy::clearSelection() void TransformStrokeStrategy::transformAndMergeDevice(const ToolTransformArgs &config, KisPaintDeviceSP src, - KisPaintDeviceSP dst) + KisPaintDeviceSP dst, + KisProcessingVisitor::ProgressHelper *helper) { - KoUpdaterPtr mergeUpdater = src != dst ? fetchUpdater() : 0; + KoUpdaterPtr mergeUpdater = src != dst ? helper->updater() : 0; - transformDevice(config, src); + transformDevice(config, src, helper); if (src != dst) { QRect mergeRect = src->extent(); KisPainter painter(dst); @@ -132,24 +196,12 @@ void TransformStrokeStrategy::transformAndMergeDevice(const ToolTransformArgs &c } } -KoUpdaterPtr TransformStrokeStrategy::fetchUpdater() -{ - QMutexLocker l(&m_progressMutex); - - if (!m_progressUpdater) { - KisNodeProgressProxy *progressProxy = m_node->nodeProgressProxy(); - m_progressUpdater = new KoProgressUpdater(progressProxy); - m_progressUpdater->moveToThread(m_node->thread()); - } - - return m_progressUpdater->startSubtask(); -} - void TransformStrokeStrategy::transformDevice(const ToolTransformArgs &config, - KisPaintDeviceSP device) + KisPaintDeviceSP device, + KisProcessingVisitor::ProgressHelper *helper) { if (config.mode() == ToolTransformArgs::WARP) { - KoUpdaterPtr updater = fetchUpdater(); + KoUpdaterPtr updater = helper->updater(); KisWarpTransformWorker worker(config.warpType(), device, @@ -178,8 +230,8 @@ void TransformStrokeStrategy::transformDevice(const ToolTransformArgs &config, QPointF translation = config.transformedCenter() - transformedCenter.toPointF(); - KoUpdaterPtr updater1 = fetchUpdater(); - KoUpdaterPtr updater2 = fetchUpdater(); + KoUpdaterPtr updater1 = helper->updater(); + KoUpdaterPtr updater2 = helper->updater(); KisTransformWorker transformWorker(device, config.scaleX(), config.scaleY(), diff --git a/krita/plugins/tools/tool_transform2/strokes/transform_stroke_strategy.h b/krita/plugins/tools/tool_transform2/strokes/transform_stroke_strategy.h index 7eb5bf0..c56857e 100644 --- a/krita/plugins/tools/tool_transform2/strokes/transform_stroke_strategy.h +++ b/krita/plugins/tools/tool_transform2/strokes/transform_stroke_strategy.h @@ -24,6 +24,7 @@ #include "kis_stroke_strategy_undo_command_based.h" #include "kis_types.h" #include "tool_transform_args.h" +#include class KisUndoAdapter; @@ -42,56 +43,71 @@ public: }; public: - TransformData(Destination _destination, const ToolTransformArgs &_config) + TransformData(Destination _destination, const ToolTransformArgs &_config, KisNodeSP _node) : KisStrokeJobData(CONCURRENT, NORMAL), destination(_destination), - config(_config) + config(_config), + node(_node) { } Destination destination; ToolTransformArgs config; + KisNodeSP node; }; class KDE_EXPORT ClearSelectionData : public KisStrokeJobData { public: - ClearSelectionData() - : KisStrokeJobData(SEQUENTIAL, NORMAL) + ClearSelectionData(KisNodeSP _node) + : KisStrokeJobData(SEQUENTIAL, NORMAL), + node(_node) { } + KisNodeSP node; }; public: - TransformStrokeStrategy(KisNodeSP node, + TransformStrokeStrategy(KisNodeSP rootNode, KisSelectionSP selection, - KisPaintDeviceSP selectedPortionCache, KisPostExecutionUndoAdapter *undoAdapter, KisUndoAdapter *legacyUndoAdapter); ~TransformStrokeStrategy(); + KisPaintDeviceSP previewDevice() const; + void doStrokeCallback(KisStrokeJobData *data); private: - KoUpdaterPtr fetchUpdater(); + KoUpdaterPtr fetchUpdater(KisNodeSP node); void transformAndMergeDevice(const ToolTransformArgs &config, KisPaintDeviceSP src, - KisPaintDeviceSP dst); + KisPaintDeviceSP dst, + KisProcessingVisitor::ProgressHelper *helper); void transformDevice(const ToolTransformArgs &config, - KisPaintDeviceSP device); + KisPaintDeviceSP device, + KisProcessingVisitor::ProgressHelper *helper); + + void clearSelection(KisPaintDeviceSP device); + //void transformDevice(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisProcessingVisitor::ProgressHelper *helper); + + bool checkBelongsToSelection(KisPaintDeviceSP device) const; - void clearSelection(); - void transformDevice(KisPaintDeviceSP src, KisPaintDeviceSP dst); + KisPaintDeviceSP createDeviceCache(KisPaintDeviceSP src); + + bool haveDeviceInCache(KisPaintDeviceSP src); + void putDeviceCache(KisPaintDeviceSP src, KisPaintDeviceSP cache); + KisPaintDeviceSP getDeviceCache(KisPaintDeviceSP src); private: - KisNodeSP m_node; KisSelectionSP m_selection; - KisPaintDeviceSP m_selectedPortionCache; KisUndoAdapter *m_legacyUndoAdapter; - QMutex m_progressMutex; - KoProgressUpdater *m_progressUpdater; + QMutex m_devicesCacheMutex; + QHash m_devicesCacheHash; + + KisPaintDeviceSP m_previewDevice; }; #endif /* __TRANSFORM_STROKE_STRATEGY_H */ diff --git a/krita/plugins/tools/tool_transform2/wdg_tool_transform.ui b/krita/plugins/tools/tool_transform2/wdg_tool_transform.ui index 9b8519c..17254be 100644 --- a/krita/plugins/tools/tool_transform2/wdg_tool_transform.ui +++ b/krita/plugins/tools/tool_transform2/wdg_tool_transform.ui @@ -6,8 +6,8 @@ 0 0 - 225 - 258 + 294 + 266 @@ -38,17 +38,8 @@ Qt::LeftToRight - - 0 - - - 0 - - - 0 - @@ -56,7 +47,7 @@ - 0 + 13 20 @@ -125,7 +116,7 @@ - 0 + 13 20 @@ -1105,7 +1096,7 @@ big! - 40 + 32 16777215 @@ -1124,14 +1115,42 @@ big! + + + + 0 + 0 + + + + + 32 + 16777215 + + + + Work Recursively + + + + + + true + + + true + + + + Qt::Horizontal - 0 - 10 + 13 + 13 _______________________________________________ kimageshop mailing list kimageshop@kde.org https://mail.kde.org/mailman/listinfo/kimageshop