summaryrefslogtreecommitdiffstats
path: root/krita/plugins/tools/tool_transform
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-20 01:29:50 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-01-20 01:29:50 +0000
commit8362bf63dea22bbf6736609b0f49c152f975eb63 (patch)
tree0eea3928e39e50fae91d4e68b21b1e6cbae25604 /krita/plugins/tools/tool_transform
downloadkoffice-8362bf63dea22bbf6736609b0f49c152f975eb63.tar.gz
koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.zip
Added old abandoned KDE3 version of koffice
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/koffice@1077364 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'krita/plugins/tools/tool_transform')
-rw-r--r--krita/plugins/tools/tool_transform/Makefile.am36
-rw-r--r--krita/plugins/tools/tool_transform/kis_tool_transform.cc916
-rw-r--r--krita/plugins/tools/tool_transform/kis_tool_transform.h154
-rw-r--r--krita/plugins/tools/tool_transform/kritatooltransform.desktop46
-rw-r--r--krita/plugins/tools/tool_transform/rotate_cursor.xpm29
-rw-r--r--krita/plugins/tools/tool_transform/tool_transform.cc64
-rw-r--r--krita/plugins/tools/tool_transform/tool_transform.h42
-rw-r--r--krita/plugins/tools/tool_transform/tool_transform.pngbin0 -> 457 bytes
-rw-r--r--krita/plugins/tools/tool_transform/wdg_tool_transform.ui243
9 files changed, 1530 insertions, 0 deletions
diff --git a/krita/plugins/tools/tool_transform/Makefile.am b/krita/plugins/tools/tool_transform/Makefile.am
new file mode 100644
index 00000000..8f77620e
--- /dev/null
+++ b/krita/plugins/tools/tool_transform/Makefile.am
@@ -0,0 +1,36 @@
+kde_services_DATA = kritatooltransform.desktop
+
+# all_includes must remain last!
+INCLUDES = -I$(srcdir)/../../../sdk \
+ -I$(srcdir)/../../../core \
+ -I$(srcdir)/../../../kritacolor/ \
+ -I$(srcdir)/../../../ui \
+ -I$/../../../ui \
+ $(KOFFICE_INCLUDES) \
+ $(all_includes)
+
+kritatooltransform_la_SOURCES = \
+ wdg_tool_transform.ui \
+ tool_transform.cc \
+ kis_tool_transform.cc
+
+# Install this plugin in the KDE modules directory
+kde_module_LTLIBRARIES = kritatooltransform.la
+
+noinst_HEADERS = \
+ tool_transform.h \
+ kis_tool_transform.h
+
+kritatooltransform_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
+kritatooltransform_la_LIBADD = ../../../libkritacommon.la
+
+kritatooltransform_la_METASOURCES = AUTO
+
+KDE_OPTIONS = nofinal
+
+kritapics_DATA = \
+ rotate_cursor.xpm \
+ tool_transform.png
+
+kritapicsdir = $(kde_datadir)/krita/pics
+
diff --git a/krita/plugins/tools/tool_transform/kis_tool_transform.cc b/krita/plugins/tools/tool_transform/kis_tool_transform.cc
new file mode 100644
index 00000000..05cdfd44
--- /dev/null
+++ b/krita/plugins/tools/tool_transform/kis_tool_transform.cc
@@ -0,0 +1,916 @@
+/*
+ * kis_tool_transform.cc -- part of Krita
+ *
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ * Copyright (c) 2005 Casper Boemann <cbr@boemann.dk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+#include <qpainter.h>
+#include <qpen.h>
+#include <qpushbutton.h>
+#include <qobject.h>
+#include <qlabel.h>
+#include <qcombobox.h>
+#include <qapplication.h>
+
+#include <kdebug.h>
+#include <kaction.h>
+#include <kcommand.h>
+#include <klocale.h>
+#include <knuminput.h>
+
+#include <kis_global.h>
+#include <kis_painter.h>
+#include <kis_canvas_controller.h>
+#include <kis_canvas_subject.h>
+#include <kis_cursor.h>
+#include <kis_image.h>
+#include <kis_undo_adapter.h>
+#include <kis_selected_transaction.h>
+#include <kis_button_press_event.h>
+#include <kis_button_release_event.h>
+#include <kis_move_event.h>
+#include <kis_selection.h>
+#include <kis_filter_strategy.h>
+#include <kis_cmb_idlist.h>
+#include <kis_id.h>
+#include <kis_tool_controller.h>
+#include <kis_transform_worker.h>
+
+#include "kis_tool_transform.h"
+#include "wdg_tool_transform.h"
+#include "kis_canvas.h"
+#include "kis_canvas_painter.h"
+
+namespace {
+ class TransformCmd : public KisSelectedTransaction {
+ typedef KisSelectedTransaction super;
+
+ public:
+ TransformCmd(KisToolTransform *tool, KisPaintDeviceSP device, KisPaintDeviceSP origDevice, double scaleX, double scaleY, double tX, double tY, double a, KisSelectionSP origSel, QPoint startPos, QPoint endPos);
+ virtual ~TransformCmd();
+
+ public:
+ virtual void execute();
+ virtual void unexecute();
+ void transformArgs(double &sx, double &sy, double &tx, double &ty, double &a);
+ KisSelectionSP origSelection(QPoint &startPos, QPoint &endPos);
+ KisPaintDeviceSP theDevice();
+ KisPaintDeviceSP origDevice();
+
+ private:
+ double m_scaleX;
+ double m_scaleY;
+ double m_translateX;
+ double m_translateY;
+ double m_a;
+ KisToolTransform *m_tool;
+ KisSelectionSP m_origSelection;
+ QPoint m_startPos;
+ QPoint m_endPos;
+ KisPaintDeviceSP m_device;
+ KisPaintDeviceSP m_origDevice;
+ };
+
+ TransformCmd::TransformCmd(KisToolTransform *tool, KisPaintDeviceSP device, KisPaintDeviceSP origDevice, double scaleX, double scaleY, double tX, double tY, double a, KisSelectionSP origSel, QPoint startPos, QPoint endPos) :
+ super(i18n("Transform"), device)
+ , m_scaleX(scaleX)
+ , m_scaleY(scaleY)
+ , m_translateX(tX)
+ , m_translateY(tY)
+ , m_a(a)
+ , m_tool(tool)
+ , m_origSelection(origSel)
+ , m_startPos(startPos)
+ , m_endPos(endPos)
+ , m_device(device)
+ , m_origDevice(origDevice)
+ {
+ }
+
+ TransformCmd::~TransformCmd()
+ {
+ }
+
+ void TransformCmd::transformArgs(double &sx, double &sy, double &tx, double &ty, double &a)
+ {
+ sx = m_scaleX;
+ sy = m_scaleY;
+ tx= m_translateX;
+ ty = m_translateY;
+ a = m_a;
+ }
+
+ KisSelectionSP TransformCmd::origSelection(QPoint &startPos, QPoint &endPos)
+ {
+ startPos = m_startPos;
+ endPos = m_endPos;
+ return m_origSelection;
+ }
+
+ void TransformCmd::execute()
+ {
+ super::execute();
+ }
+
+ void TransformCmd::unexecute()
+ {
+ super::unexecute();
+ }
+
+ KisPaintDeviceSP TransformCmd::theDevice()
+ {
+ return m_device;
+ }
+
+ KisPaintDeviceSP TransformCmd::origDevice()
+ {
+ return m_origDevice;
+ }
+}
+
+KisToolTransform::KisToolTransform()
+ : super(i18n("Transform"))
+ , m_wasPressed( false )
+{
+ setName("tool_transform");
+ setCursor(KisCursor::selectCursor());
+ m_subject = 0;
+ m_selecting = false;
+ m_startPos = QPoint(0, 0);
+ m_endPos = QPoint(0, 0);
+ m_optWidget = 0;
+ m_sizeCursors[0] = KisCursor::sizeVerCursor();
+ m_sizeCursors[1] = KisCursor::sizeBDiagCursor();
+ m_sizeCursors[2] = KisCursor::sizeHorCursor();
+ m_sizeCursors[3] = KisCursor::sizeFDiagCursor();
+ m_sizeCursors[4] = KisCursor::sizeVerCursor();
+ m_sizeCursors[5] = KisCursor::sizeBDiagCursor();
+ m_sizeCursors[6] = KisCursor::sizeHorCursor();
+ m_sizeCursors[7] = KisCursor::sizeFDiagCursor();
+ m_origDevice = 0;
+ m_origSelection = 0;
+
+}
+
+KisToolTransform::~KisToolTransform()
+{
+}
+
+void KisToolTransform::deactivate()
+{
+ if (m_subject && m_subject->undoAdapter()) m_subject->undoAdapter()->removeCommandHistoryListener( this );
+
+ KisImageSP img = m_subject->currentImg();
+ if (!img) return;
+
+ paintOutline();
+
+ disconnect(m_subject->currentImg().data(), SIGNAL(sigLayerActivated(KisLayerSP)), this, SLOT(slotLayerActivated(KisLayerSP)));
+}
+
+void KisToolTransform::activate()
+{
+ if(m_subject && m_subject->currentImg() && m_subject->currentImg()->activeDevice())
+ {
+ //connect(m_subject, commandExecuted(KCommand *c), this, notifyCommandAdded( KCommand * c));
+ m_subject->undoAdapter()->setCommandHistoryListener( this );
+
+ KisToolControllerInterface *controller = m_subject->toolController();
+
+ if (controller)
+ controller->setCurrentTool(this);
+
+ TransformCmd * cmd=0;
+
+ if(m_subject->currentImg()->undoAdapter()->presentCommand())
+ cmd = dynamic_cast<TransformCmd*>(m_subject->currentImg()->undoAdapter()->presentCommand());
+
+ if (cmd == 0) {
+ initHandles();
+ }
+ else
+ {
+ // One of our commands is on top
+ if(cmd->theDevice() == m_subject->currentImg()->activeDevice())
+ {
+ // and it even has the same device
+ // We should ask for tool args and orig selection
+ m_origDevice = cmd->origDevice();
+ cmd->transformArgs(m_scaleX, m_scaleY, m_translateX, m_translateY, m_a);
+ m_origSelection = cmd->origSelection(m_startPos, m_endPos);
+ m_org_cenX = (m_startPos.x() + m_endPos.x()) / 2.0;
+ m_org_cenY = (m_startPos.y() + m_endPos.y()) / 2.0;
+ paintOutline();
+ }
+ else
+ initHandles();
+ }
+ }
+ connect(m_subject->currentImg(), SIGNAL(sigLayerActivated(KisLayerSP)), this, SLOT(slotLayerActivated(KisLayerSP)));
+}
+
+void KisToolTransform::initHandles()
+{
+ Q_INT32 x,y,w,h;
+ KisImageSP img = m_subject->currentImg();
+
+ KisPaintDeviceSP dev = img->activeDevice();
+ if (!dev ) return;
+
+ // Create a lazy copy of the current state
+ m_origDevice = new KisPaintDevice(*dev.data());
+ Q_ASSERT(m_origDevice);
+
+ if(dev->hasSelection())
+ {
+ KisSelectionSP sel = dev->selection();
+ m_origSelection = new KisSelection(*sel.data());
+ QRect r = sel->selectedExactRect();
+ r.rect(&x, &y, &w, &h);
+ }
+ else {
+ dev->exactBounds(x,y,w,h);
+ m_origSelection = 0;
+ }
+ m_startPos = QPoint(x, y);
+ m_endPos = QPoint(x+w-1, y+h-1);
+ m_org_cenX = (m_startPos.x() + m_endPos.x()) / 2.0;
+ m_org_cenY = (m_startPos.y() + m_endPos.y()) / 2.0;
+
+ m_a = 0.0;
+ m_scaleX = 1.0;
+ m_scaleY = 1.0;
+ m_translateX = m_org_cenX;
+ m_translateY = m_org_cenY;
+
+ m_subject->canvasController() ->updateCanvas();
+}
+
+void KisToolTransform::paint(KisCanvasPainter& gc)
+{
+ paintOutline(gc, QRect());
+}
+
+void KisToolTransform::paint(KisCanvasPainter& gc, const QRect& rc)
+{
+ paintOutline(gc, rc);
+}
+
+
+void KisToolTransform::buttonPress(KisButtonPressEvent *e)
+{
+ if (m_subject && e->button() == QMouseEvent::LeftButton) {
+ m_wasPressed = true;
+ }
+
+ if (m_subject) {
+ KisImageSP img = m_subject->currentImg();
+
+ if (img && img->activeDevice() && e->button() == LeftButton) {
+ switch(m_function)
+ {
+ case ROTATE:
+ m_clickoffset = e->pos().floorQPoint()
+ - QPoint(static_cast<int>(m_translateX),static_cast<int>(m_translateY));
+ m_clickangle = -m_a - atan2(m_clickoffset.x(),m_clickoffset.y());
+ m_clickoffset = QPoint(0, 0);
+ break;
+ case MOVE:
+ m_clickoffset = e->pos().floorQPoint()
+ - QPoint(static_cast<int>(m_translateX),static_cast<int>(m_translateY));
+ break;
+ case TOPSCALE:
+ m_clickoffset = e->pos().floorQPoint()
+ - QPoint((m_topleft + m_topright)/2);
+ break;
+ case TOPRIGHTSCALE:
+ m_clickoffset = e->pos().floorQPoint() - m_topright;
+ break;
+ case RIGHTSCALE:
+ m_clickoffset = e->pos().floorQPoint()
+ - QPoint((m_topright + m_bottomright)/2);
+ break;
+ case BOTTOMRIGHTSCALE:
+ m_clickoffset = e->pos().floorQPoint() - m_bottomright;
+ break;
+ case BOTTOMSCALE:
+ m_clickoffset = e->pos().floorQPoint()
+ - QPoint((m_bottomleft + m_bottomright)/2);
+ break;
+ case BOTTOMLEFTSCALE:
+ m_clickoffset = e->pos().floorQPoint() - m_bottomleft;
+ break;
+ case LEFTSCALE:
+ m_clickoffset = e->pos().floorQPoint()
+ - QPoint((m_topleft + m_bottomleft)/2);
+ break;
+ case TOPLEFTSCALE:
+ m_clickoffset = e->pos().floorQPoint() - m_topleft;
+ break;
+ }
+ m_selecting = true;
+ m_actualyMoveWhileSelected = false;
+ }
+ }
+}
+
+int KisToolTransform::det(QPoint v,QPoint w)
+{
+ return v.x()*w.y()-v.y()*w.x();
+}
+int KisToolTransform::distsq(QPoint v,QPoint w)
+{
+ v -= w;
+ return v.x()*v.x() + v.y()*v.y();
+}
+
+void KisToolTransform::setFunctionalCursor()
+{
+ int rotOctant = 8 + int(8.5 + m_a* 4 / M_PI);
+
+ int s;
+ if(m_scaleX*m_scaleY<0)
+ s = -1;
+ else
+ s=1;
+
+ switch(m_function)
+ {
+ case MOVE:
+ setCursor(KisCursor::moveCursor());
+ break;
+ case ROTATE:
+ setCursor(KisCursor::rotateCursor());
+ break;
+ case TOPSCALE:
+ setCursor(m_sizeCursors[(0*s +rotOctant)%8]);
+ break;
+ case TOPRIGHTSCALE:
+ setCursor(m_sizeCursors[(1*s +rotOctant)%8]);
+ break;
+ case RIGHTSCALE:
+ setCursor(m_sizeCursors[(2*s +rotOctant)%8]);
+ break;
+ case BOTTOMRIGHTSCALE:
+ setCursor(m_sizeCursors[(3*s +rotOctant)%8]);
+ break;
+ case BOTTOMSCALE:
+ setCursor(m_sizeCursors[(4*s +rotOctant)%8]);
+ break;
+ case BOTTOMLEFTSCALE:
+ setCursor(m_sizeCursors[(5*s +rotOctant)%8]);
+ break;
+ case LEFTSCALE:
+ setCursor(m_sizeCursors[(6*s +rotOctant)%8]);
+ break;
+ case TOPLEFTSCALE:
+ setCursor(m_sizeCursors[(7*s +rotOctant)%8]);
+ break;
+ }
+}
+
+void KisToolTransform::move(KisMoveEvent *e)
+{
+ if (m_subject) {
+ KisCanvasController *controller = m_subject->canvasController();
+
+ Q_ASSERT(controller);
+ QPoint topleft = m_topleft;
+ QPoint topright = m_topright;
+ QPoint bottomleft = m_bottomleft;
+ QPoint bottomright = m_bottomright;
+
+ QPoint mousePos = e->pos().floorQPoint();
+
+ if (m_subject && m_selecting) {
+ paintOutline();
+ m_actualyMoveWhileSelected = true;
+ mousePos -= m_clickoffset;
+
+ // transform mousePos coords, so it seems like it isn't rotated and centered at 0,0
+ double newX = invrotX(mousePos.x() - m_translateX, mousePos.y() - m_translateY);
+ double newY = invrotY(mousePos.x() - m_translateX, mousePos.y() - m_translateY);
+ double dx=0, dy=0;
+ double oldScaleX = m_scaleX;
+ double oldScaleY = m_scaleY;
+
+ if(m_function == MOVE)
+ {
+ m_translateX += mousePos.x() - m_translateX;
+ m_translateY += mousePos.y() - m_translateY;
+ }
+
+ if(m_function == ROTATE)
+ {
+ m_a = -atan2(mousePos.x() - m_translateX, mousePos.y() - m_translateY)
+ - m_clickangle;
+ }
+
+ if(m_function == TOPSCALE)
+ {
+ dy = (newY - m_scaleY * (m_startPos.y() - m_org_cenY)) / 2;
+ m_scaleY = (newY - dy) / (m_startPos.y() - m_org_cenY);
+
+ // enforce same acpect if shift button is pressed
+ if(e->state() & Qt::ShiftButton)
+ {
+ if(m_scaleX>0) // handle the mirrored cases
+ m_scaleX = fabs(m_scaleY);
+ else
+ m_scaleX = -fabs(m_scaleY);
+ }
+ }
+
+ if(m_function == TOPRIGHTSCALE)
+ {
+ dx = (newX - m_scaleX * (m_endPos.x() - m_org_cenX)) / 2;
+ m_scaleX = (newX - dx) / (m_endPos.x() - m_org_cenX);
+
+ dy = (newY - m_scaleY * (m_startPos.y() - m_org_cenY)) / 2;
+ m_scaleY = (newY - dy) / (m_startPos.y() - m_org_cenY);
+
+ // enforce same aspect if shift button is pressed
+ if(e->state() & Qt::ShiftButton)
+ {
+ if(m_scaleX < m_scaleY)
+ {
+ if(m_scaleX>0) // handle the mirrored cases
+ m_scaleX = fabs(m_scaleY);
+ else
+ m_scaleX = -fabs(m_scaleY);
+ dx = (m_scaleX - oldScaleX) * (m_endPos.x() - m_org_cenX);
+ }
+ else
+ {
+ if(m_scaleY>0) // handle the mirrored cases
+ m_scaleY = fabs(m_scaleX);
+ else
+ m_scaleY = -fabs(m_scaleX);
+ dy = (m_scaleY - oldScaleY) * (m_startPos.y() - m_org_cenY);
+ }
+ }
+ }
+
+ if(m_function == RIGHTSCALE)
+ {
+ dx = (newX - m_scaleX * (m_endPos.x() - m_org_cenX)) / 2;
+ m_scaleX = (newX - dx) / (m_endPos.x() - m_org_cenX);
+
+ // enforce same acpect if shift button is pressed
+ if(e->state() & Qt::ShiftButton)
+ {
+ if(m_scaleY>0) // handle the mirrored cases
+ m_scaleY = fabs(m_scaleX);
+ else
+ m_scaleY = -fabs(m_scaleX);
+ }
+ }
+
+ if(m_function == BOTTOMRIGHTSCALE)
+ {
+ dx = (newX - m_scaleX * (m_endPos.x() - m_org_cenX)) / 2;
+ m_scaleX = (newX - dx) / (m_endPos.x() - m_org_cenX);
+
+ dy = (newY - m_scaleY * (m_endPos.y() - m_org_cenY)) / 2;
+ m_scaleY = (newY - dy) / (m_endPos.y() - m_org_cenY);
+
+ // enforce same acpect if shift button is pressed
+ if(e->state() & Qt::ShiftButton)
+ {
+ if(m_scaleX < m_scaleY)
+ {
+ if(m_scaleX>0) // handle the mirrored cases
+ m_scaleX = fabs(m_scaleY);
+ else
+ m_scaleX = -fabs(m_scaleY);
+ dx = (m_scaleX - oldScaleX) * (m_endPos.x() - m_org_cenX);
+ }
+ else
+ {
+ if(m_scaleY>0) // handle the mirrored cases
+ m_scaleY = fabs(m_scaleX);
+ else
+ m_scaleY = -fabs(m_scaleX);
+ dy = (m_scaleY - oldScaleY) * (m_endPos.y() - m_org_cenY);
+ }
+ }
+ }
+
+ if(m_function == BOTTOMSCALE)
+ {
+ dy = (newY - m_scaleY * (m_endPos.y() - m_org_cenY)) / 2;
+ m_scaleY = (newY - dy) / (m_endPos.y() - m_org_cenY);
+
+ // enforce same acpect if shift button is pressed
+ if(e->state() & Qt::ShiftButton)
+ {
+ if(m_scaleX>0) // handle the mirrored cases
+ m_scaleX = fabs(m_scaleY);
+ else
+ m_scaleX = -fabs(m_scaleY);
+ }
+ }
+
+ if(m_function == BOTTOMLEFTSCALE)
+ {
+ dx = (newX - m_scaleX * (m_startPos.x() - m_org_cenX)) / 2;
+ m_scaleX = (newX - dx) / (m_startPos.x() - m_org_cenX);
+
+ dy = (newY - m_scaleY * (m_endPos.y() - m_org_cenY)) / 2;
+ m_scaleY = (newY - dy) / (m_endPos.y() - m_org_cenY);
+
+ // enforce same acpect if shift button is pressed
+ if(e->state() & Qt::ShiftButton)
+ {
+ if(m_scaleX < m_scaleY)
+ {
+ if(m_scaleX>0) // handle the mirrored cases
+ m_scaleX = fabs(m_scaleY);
+ else
+ m_scaleX = -fabs(m_scaleY);
+ dx = (m_scaleX - oldScaleX) * (m_startPos.x() - m_org_cenX);
+ }
+ else
+ {
+ if(m_scaleY>0) // handle the mirrored cases
+ m_scaleY = fabs(m_scaleX);
+ else
+ m_scaleY = -fabs(m_scaleX);
+ dy = (m_scaleY - oldScaleY) * (m_endPos.y() - m_org_cenY);
+ }
+ }
+ }
+
+ if(m_function == LEFTSCALE)
+ {
+ dx = (newX - m_scaleX * (m_startPos.x() - m_org_cenX)) / 2;
+ m_scaleX = (newX - dx) / (m_startPos.x() - m_org_cenX);
+
+ // enforce same acpect if shift button is pressed
+ if(e->state() & Qt::ShiftButton)
+ {
+ if(m_scaleY>0) // handle the mirrored cases
+ m_scaleY = fabs(m_scaleX);
+ else
+ m_scaleY = -fabs(m_scaleX);
+ }
+ }
+
+ if(m_function == TOPLEFTSCALE)
+ {
+ dx = (newX - m_scaleX * (m_startPos.x() - m_org_cenX)) / 2;
+ m_scaleX = (newX - dx) / (m_startPos.x() - m_org_cenX);
+
+ dy = (newY - m_scaleY * (m_startPos.y() - m_org_cenY)) / 2;
+ m_scaleY = (newY - dy) / (m_startPos.y() - m_org_cenY);
+
+ // enforce same acpect if shift button is pressed
+ if(e->state() & Qt::ShiftButton)
+ {
+ if(m_scaleX < m_scaleY)
+ {
+ if(m_scaleX>0) // handle the mirrored cases
+ m_scaleX = fabs(m_scaleY);
+ else
+ m_scaleX = -fabs(m_scaleY);
+ dx = (m_scaleX - oldScaleX) * (m_startPos.x() - m_org_cenX);
+ }
+ else
+ {
+ if(m_scaleY>0) // handle the mirrored cases
+ m_scaleY = fabs(m_scaleX);
+ else
+ m_scaleY = -fabs(m_scaleX);
+ dy = (m_scaleY - oldScaleY) * (m_startPos.y() - m_org_cenY);
+ }
+ }
+ }
+
+ m_translateX += rotX(dx, dy);
+ m_translateY += rotY(dx, dy);
+
+ paintOutline();
+ }
+ else
+ {
+ if(det(mousePos - topleft, topright - topleft)>0)
+ m_function = ROTATE;
+ else if(det(mousePos - topright, bottomright - topright)>0)
+ m_function = ROTATE;
+ else if(det(mousePos - bottomright, bottomleft - bottomright)>0)
+ m_function = ROTATE;
+ else if(det(mousePos - bottomleft, topleft - bottomleft)>0)
+ m_function = ROTATE;
+ else
+ m_function = MOVE;
+
+ int handleradius = int( 25 / (m_subject->zoomFactor() * m_subject->zoomFactor()) );
+
+ if(distsq(mousePos, (m_topleft + m_topright)/2)<=handleradius)
+ m_function = TOPSCALE;
+ if(distsq(mousePos, m_topright)<=handleradius)
+ m_function = TOPRIGHTSCALE;
+ if(distsq(mousePos, (m_topright + m_bottomright)/2)<=handleradius)
+ m_function = RIGHTSCALE;
+ if(distsq(mousePos, m_bottomright)<=handleradius)
+ m_function = BOTTOMRIGHTSCALE;
+ if(distsq(mousePos, (m_bottomleft + m_bottomright)/2)<=handleradius)
+ m_function = BOTTOMSCALE;
+ if(distsq(mousePos, m_bottomleft)<=handleradius)
+ m_function = BOTTOMLEFTSCALE;
+ if(distsq(mousePos, (m_topleft + m_bottomleft)/2)<=handleradius)
+ m_function = LEFTSCALE;
+ if(distsq(mousePos, m_topleft)<=handleradius)
+ m_function = TOPLEFTSCALE;
+
+ setFunctionalCursor();
+ }
+ }
+}
+
+void KisToolTransform::buttonRelease(KisButtonReleaseEvent *e)
+{
+ if (m_subject && e->button() == QMouseEvent::LeftButton) {
+ if(!m_wasPressed) return;
+ m_wasPressed = false;
+
+ KisImageSP img = m_subject->currentImg();
+
+ if (!img)
+ return;
+
+ m_selecting = false;
+
+ if(m_actualyMoveWhileSelected)
+ {
+ paintOutline();
+ QApplication::setOverrideCursor(KisCursor::waitCursor());
+ transform();
+ QApplication::restoreOverrideCursor();
+ }
+ }
+}
+
+void KisToolTransform::paintOutline()
+{
+ if (m_subject) {
+ KisCanvasController *controller = m_subject->canvasController();
+ KisCanvas *canvas = controller->kiscanvas();
+ KisCanvasPainter gc(canvas);
+ QRect rc;
+
+ paintOutline(gc, rc);
+ }
+}
+
+void KisToolTransform::recalcOutline()
+{
+ double x,y;
+
+ m_sina = sin(m_a);
+ m_cosa = cos(m_a);
+
+ x = (m_startPos.x() - m_org_cenX) * m_scaleX;
+ y = (m_startPos.y() - m_org_cenY) * m_scaleY;
+ m_topleft = QPoint(int(rotX(x,y) + m_translateX+0.5), int(rotY(x,y) + m_translateY+0.5));
+
+ x = (m_endPos.x() - m_org_cenX) * m_scaleX;
+ y = (m_startPos.y() - m_org_cenY) * m_scaleY;
+ m_topright = QPoint(int(rotX(x,y) + m_translateX+0.5), int(rotY(x,y) + m_translateY+0.5));
+
+ x = (m_startPos.x() - m_org_cenX) * m_scaleX;
+ y = (m_endPos.y() - m_org_cenY) * m_scaleY;
+ m_bottomleft = QPoint(int(rotX(x,y) + m_translateX+0.5), int(rotY(x,y) + m_translateY+0.5));
+
+ x = (m_endPos.x() - m_org_cenX) * m_scaleX;
+ y = (m_endPos.y() - m_org_cenY) * m_scaleY;
+ m_bottomright = QPoint(int(rotX(x,y) + m_translateX+0.5), int(rotY(x,y) + m_translateY+0.5));
+}
+
+void KisToolTransform::paintOutline(KisCanvasPainter& gc, const QRect&)
+{
+ if (m_subject) {
+ KisCanvasController *controller = m_subject->canvasController();
+ RasterOp op = gc.rasterOp();
+ QPen old = gc.pen();
+ QPen pen(Qt::SolidLine);
+ pen.setWidth(1);
+ Q_ASSERT(controller);
+
+ recalcOutline();
+ QPoint topleft = controller->windowToView(m_topleft);
+ QPoint topright = controller->windowToView(m_topright);
+ QPoint bottomleft = controller->windowToView(m_bottomleft);
+ QPoint bottomright = controller->windowToView(m_bottomright);
+
+ gc.setRasterOp(Qt::NotROP);
+ gc.setPen(pen);
+ gc.drawRect(topleft.x()-4, topleft.y()-4, 8, 8);
+ gc.drawLine(topleft.x(), topleft.y(), (topleft.x()+topright.x())/2, (topleft.y()+topright.y())/2);
+ gc.drawRect((topleft.x()+topright.x())/2-4, (topleft.y()+topright.y())/2-4, 8, 8);
+ gc.drawLine((topleft.x()+topright.x())/2, (topleft.y()+topright.y())/2, topright.x(), topright.y());
+ gc.drawRect(topright.x()-4, topright.y()-4, 8, 8);
+ gc.drawLine(topright.x(), topright.y(), (topright.x()+bottomright.x())/2, (topright.y()+bottomright.y())/2);
+ gc.drawRect((topright.x()+bottomright.x())/2-4, (topright.y()+bottomright.y())/2-4, 8, 8);
+ gc.drawLine((topright.x()+bottomright.x())/2, (topright.y()+bottomright.y())/2,bottomright.x(), bottomright.y());
+ gc.drawRect(bottomright.x()-4, bottomright.y()-4, 8, 8);
+ gc.drawLine(bottomright.x(), bottomright.y(), (bottomleft.x()+bottomright.x())/2, (bottomleft.y()+bottomright.y())/2);
+ gc.drawRect((bottomleft.x()+bottomright.x())/2-4, (bottomleft.y()+bottomright.y())/2-4, 8, 8);
+ gc.drawLine((bottomleft.x()+bottomright.x())/2, (bottomleft.y()+bottomright.y())/2, bottomleft.x(), bottomleft.y());
+ gc.drawRect(bottomleft.x()-4, bottomleft.y()-4, 8, 8);
+ gc.drawLine(bottomleft.x(), bottomleft.y(), (topleft.x()+bottomleft.x())/2, (topleft.y()+bottomleft.y())/2);
+ gc.drawRect((topleft.x()+bottomleft.x())/2-4, (topleft.y()+bottomleft.y())/2-4, 8, 8);
+ gc.drawLine((topleft.x()+bottomleft.x())/2, (topleft.y()+bottomleft.y())/2, topleft.x(), topleft.y());
+ gc.setRasterOp(op);
+ gc.setPen(old);
+ }
+}
+
+void KisToolTransform::transform()
+{
+
+ KisImageSP img = m_subject->currentImg();
+
+ if (!img || !img->activeDevice())
+ return;
+
+ double tx = m_translateX - rotX(m_org_cenX * m_scaleX, m_org_cenY * m_scaleY);
+ double ty = m_translateY - rotY(m_org_cenX * m_scaleX, m_org_cenY * m_scaleY);
+ KisProgressDisplayInterface *progress = m_subject->progressDisplay();
+
+ // This mementoes the current state of the active device.
+ TransformCmd * transaction = new TransformCmd(this, img->activeDevice(), m_origDevice,
+ m_scaleX, m_scaleY, m_translateX, m_translateY, m_a, m_origSelection, m_startPos, m_endPos);
+
+ // Copy the original state back.
+ QRect rc = m_origDevice->extent();
+ rc = rc.normalize();
+ img->activeDevice()->clear();
+ KisPainter gc(img->activeDevice());
+ gc.bitBlt(rc.x(), rc.y(), COMPOSITE_COPY, m_origDevice, rc.x(), rc.y(), rc.width(), rc.height());
+ gc.end();
+
+ // Also restore the original selection.
+ if(m_origSelection)
+ {
+ //QRect rc = m_origSelection->extent();
+ QRect rc = m_origSelection->selectedRect();
+ rc = rc.normalize();
+ img->activeDevice()->selection()->clear();
+ KisPainter sgc(img->activeDevice()->selection().data());
+ sgc.bitBlt(rc.x(), rc.y(), COMPOSITE_COPY, m_origSelection.data(), rc.x(), rc.y(), rc.width(), rc.height());
+ sgc.end();
+ }
+ else
+ if(img->activeDevice()->hasSelection())
+ img->activeDevice()->selection()->clear();
+
+ // Perform the transform. Since we copied the original state back, this doesn't degrade
+ // after many tweaks. Since we started the transaction before the copy back, the memento
+ // has the previous state.
+ KisTransformWorker t(img->activeDevice(), m_scaleX, m_scaleY, 0, 0, m_a, int(tx), int(ty), progress, m_filter);
+ t.run();
+
+ // If canceled, go back to the memento
+ if(t.isCanceled())
+ {
+ transaction->unexecute();
+ delete transaction;
+ return;
+ }
+
+ img->activeDevice()->setDirty(rc); // XXX: This is not enough - should union with new extent
+
+ // Else add the command -- this will have the memento from the previous state,
+ // and the transformed state from the original device we cached in our activated()
+ // method.
+ if (transaction) {
+ if (img->undo())
+ img->undoAdapter()->addCommand(transaction);
+ else
+ delete transaction;
+ }
+}
+
+void KisToolTransform::notifyCommandAdded( KCommand * command)
+{
+ TransformCmd * cmd = dynamic_cast<TransformCmd*>(command);
+ if (cmd == 0) {
+ // The last added command wasn't one of ours;
+ // we should reset to the new state of the canvas.
+ // In effect we should treat this as if the tool has been just activated
+ initHandles();
+ }
+}
+
+void KisToolTransform::notifyCommandExecuted( KCommand * command)
+{
+ Q_UNUSED(command);
+ TransformCmd * cmd=0;
+
+ if(m_subject->currentImg()->undoAdapter()->presentCommand())
+ cmd = dynamic_cast<TransformCmd*>(m_subject->currentImg()->undoAdapter()->presentCommand());
+
+ if (cmd == 0) {
+ // The command now on the top of the stack isn't one of ours
+ // We should treat this as if the tool has been just activated
+ initHandles();
+ }
+ else
+ {
+ // One of our commands is now on top
+ // We should ask for tool args and orig selection
+ cmd->transformArgs(m_scaleX, m_scaleY, m_translateX, m_translateY, m_a);
+ m_origSelection = cmd->origSelection(m_startPos, m_endPos);
+ m_origDevice = cmd->origDevice();
+ m_org_cenX = (m_startPos.x() + m_endPos.x()) / 2.0;
+ m_org_cenY = (m_startPos.y() + m_endPos.y()) / 2.0;
+ m_subject->canvasController() ->updateCanvas();
+ }
+}
+
+void KisToolTransform::slotSetFilter(const KisID &filterID)
+{
+ m_filter = KisFilterStrategyRegistry::instance()->get(filterID);
+}
+
+void KisToolTransform::slotLayerActivated(KisLayerSP)
+{
+ activate();
+}
+
+
+QWidget* KisToolTransform::createOptionWidget(QWidget* parent)
+{
+
+ m_optWidget = new WdgToolTransform(parent);
+ Q_CHECK_PTR(m_optWidget);
+
+ m_optWidget->cmbFilter->clear();
+ m_optWidget->cmbFilter->setIDList(KisFilterStrategyRegistry::instance()->listKeys());
+
+ m_optWidget->cmbFilter->setCurrentText("Mitchell");
+ connect(m_optWidget->cmbFilter, SIGNAL(activated(const KisID &)),
+ this, SLOT(slotSetFilter(const KisID &)));
+
+ KisID filterID = m_optWidget->cmbFilter->currentItem();
+ m_filter = KisFilterStrategyRegistry::instance()->get(filterID);
+
+/*
+ connect(m_optWidget->intStartX, SIGNAL(valueChanged(int)), this, SLOT(setStartX(int)));
+ connect(m_optWidget->intStartY, SIGNAL(valueChanged(int)), this, SLOT(setStartY(int)));
+ connect(m_optWidget->intEndX, SIGNAL(valueChanged(int)), this, SLOT(setEndX(int)));
+ connect(m_optWidget->intEndY, SIGNAL(valueChanged(int)), this, SLOT(setEndY(int)));
+*/
+ m_optWidget->intStartX->hide();
+ m_optWidget->intStartY->hide();
+ m_optWidget->intEndX->hide();
+ m_optWidget->intEndY->hide();
+ m_optWidget->textLabel1->hide();
+ m_optWidget->textLabel2->hide();
+ m_optWidget->textLabel3->hide();
+ m_optWidget->textLabel4->hide();
+ return m_optWidget;
+}
+
+QWidget* KisToolTransform::optionWidget()
+{
+ return m_optWidget;
+}
+
+void KisToolTransform::setup(KActionCollection *collection)
+{
+ m_action = static_cast<KRadioAction *>(collection->action(name()));
+
+ if (m_action == 0) {
+ m_action = new KRadioAction(i18n("&Transform"),
+ "tool_transform",
+ 0,
+ this,
+ SLOT(activate()),
+ collection,
+ name());
+ Q_CHECK_PTR(m_action);
+ m_action->setToolTip(i18n("Transform a layer or a selection"));
+ m_action->setExclusiveGroup("tools");
+ m_ownAction = true;
+ }
+}
+
+#include "kis_tool_transform.moc"
diff --git a/krita/plugins/tools/tool_transform/kis_tool_transform.h b/krita/plugins/tools/tool_transform/kis_tool_transform.h
new file mode 100644
index 00000000..9ae4f4da
--- /dev/null
+++ b/krita/plugins/tools/tool_transform/kis_tool_transform.h
@@ -0,0 +1,154 @@
+/*
+ * kis_tool_transform.h - part of Krita
+ *
+ * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org>
+ * Copyright (c) 2005 Casper Boemann <cbr@boemann.dk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KIS_TOOL_TRANSFORM_H_
+#define KIS_TOOL_TRANSFORM_H_
+
+#include <qpoint.h>
+
+#include <kis_tool_non_paint.h>
+#include <kis_tool_factory.h>
+#include <kis_undo_adapter.h>
+#include <kis_layer.h>
+
+class KisTransaction;
+class WdgToolTransform;
+class KisID;
+class KisFilterStrategy;
+
+/**
+ * Transform tool
+ *
+ */
+class KisToolTransform : public KisToolNonPaint, KisCommandHistoryListener {
+
+ typedef KisToolNonPaint super;
+ Q_OBJECT
+
+public:
+ KisToolTransform();
+ virtual ~KisToolTransform();
+
+ virtual QWidget* createOptionWidget(QWidget* parent);
+ virtual QWidget* optionWidget();
+
+ virtual void setup(KActionCollection *collection);
+ virtual enumToolType toolType() { return TOOL_TRANSFORM; }
+ virtual Q_UINT32 priority() { return 3; }
+ virtual void paint(KisCanvasPainter& gc);
+ virtual void paint(KisCanvasPainter& gc, const QRect& rc);
+ virtual void buttonPress(KisButtonPressEvent *e);
+ virtual void move(KisMoveEvent *e);
+ virtual void buttonRelease(KisButtonReleaseEvent *e);
+ void setScaleX(double sx) { m_scaleX = sx; }
+ void setScaleY(double sy) { m_scaleY = sy; }
+ void setTranslateX(double tx) { m_translateX = tx; }
+ void setTranslateY(double ty) { m_translateY = ty; }
+ void setAngle(double a) { m_a = a; }
+ void paintOutline();
+
+public:
+
+ void notifyCommandAdded(KCommand *);
+ void notifyCommandExecuted(KCommand *);
+
+public:
+ virtual void deactivate();
+
+private:
+
+ void paintOutline(KisCanvasPainter& gc, const QRect& rc);
+ void transform();
+ void recalcOutline();
+ double rotX(double x, double y) { return m_cosa*x - m_sina*y;};
+ double rotY(double x, double y) { return m_sina*x + m_cosa*y;};
+ double invrotX(double x, double y) { return m_cosa*x + m_sina*y;};
+ double invrotY(double x, double y) { return -m_sina*x + m_cosa*y;};
+ int det(QPoint v,QPoint w);
+ int distsq(QPoint v,QPoint w);
+ void setFunctionalCursor();
+ void initHandles();
+
+private slots:
+
+ void slotLayerActivated(KisLayerSP);
+ void slotSetFilter(const KisID &);
+ void setStartX(int x) { m_startPos.setX(x); }
+ void setStartY(int y) { m_startPos.setY(y); }
+ void setEndX(int x) { m_endPos.setX(x); }
+ void setEndY(int y) { m_endPos.setY(y); }
+
+protected slots:
+ virtual void activate();
+
+private:
+ enum function {ROTATE,MOVE,TOPLEFTSCALE,TOPSCALE,TOPRIGHTSCALE,RIGHTSCALE,
+ BOTTOMRIGHTSCALE, BOTTOMSCALE,BOTTOMLEFTSCALE, LEFTSCALE};
+ QCursor m_sizeCursors[8];
+ function m_function;
+ QPoint m_startPos;
+ QPoint m_endPos;
+ bool m_selecting;
+ bool m_actualyMoveWhileSelected;
+ QPoint m_topleft;
+ QPoint m_topright;
+ QPoint m_bottomleft;
+ QPoint m_bottomright;
+ double m_scaleX;
+ double m_scaleY;
+ double m_translateX;
+ double m_translateY;
+ QPoint m_clickoffset;
+ double m_org_cenX;
+ double m_org_cenY;
+ double m_cosa;
+ double m_sina;
+ double m_a;
+ double m_clickangle;
+ KisFilterStrategy *m_filter;
+
+ WdgToolTransform *m_optWidget;
+
+ KisPaintDeviceSP m_origDevice;
+ KisSelectionSP m_origSelection;
+
+ bool m_wasPressed;
+};
+
+class KisToolTransformFactory : public KisToolFactory {
+ typedef KisToolFactory super;
+
+public:
+ KisToolTransformFactory() : super() {};
+ virtual ~KisToolTransformFactory(){};
+
+ virtual KisTool * createTool(KActionCollection * ac) {
+ KisTool * t = new KisToolTransform();
+ Q_CHECK_PTR(t);
+ t->setup(ac); return t;
+ }
+ virtual KisID id() { return KisID("transform", i18n("Transform Tool")); }
+};
+
+
+
+#endif // KIS_TOOL_TRANSFORM_H_
+
diff --git a/krita/plugins/tools/tool_transform/kritatooltransform.desktop b/krita/plugins/tools/tool_transform/kritatooltransform.desktop
new file mode 100644
index 00000000..bff56123
--- /dev/null
+++ b/krita/plugins/tools/tool_transform/kritatooltransform.desktop
@@ -0,0 +1,46 @@
+[Desktop Entry]
+Name=Transform Tool
+Name[bg]=Инструмент за трансформиране
+Name[br]=Ostilh treuzfurmiñ
+Name[ca]=Eina de transformació
+Name[cy]=Erfyn Trawsffurfio
+Name[da]=Transformeringsværktøj
+Name[de]=Transformation-Werkzeug
+Name[el]=Εργαλείο μετασχηματισμού
+Name[eo]=Transform-ilo
+Name[es]=Herramienta para transformar
+Name[et]=Transformeermistööriist
+Name[fa]=ابزار تبدیل
+Name[fr]=Outil transformation
+Name[fy]=ferfoarmingsark
+Name[ga]=Uirlis Trasfhoirmithe
+Name[gl]=Ferramenta de Transformación
+Name[hu]=Átalakító eszköz
+Name[is]=Ummyndunartól
+Name[it]=Strumento di trasformazione
+Name[ja]=変換ツール
+Name[km]=ឧបករណ៍​ប្លែង
+Name[lt]=Transformavimo įrankis
+Name[lv]=Transformāciju rīks
+Name[nb]=Transformeringsverktøy
+Name[nds]=Ümwanneln-Warktüüch
+Name[ne]=रूपान्तरण उपकरण
+Name[nl]=Vervormgereedschap
+Name[pl]=Narzędzie przekształcania
+Name[pt]=Ferramenta de Transformação
+Name[pt_BR]=Ferramenta de Transformação
+Name[ru]=Преобразование
+Name[sk]=Transformácia
+Name[sl]=Orodje za pretvorbo
+Name[sr]=Алат за трансформацију
+Name[sr@Latn]=Alat za transformaciju
+Name[sv]=Transformeringsverktyg
+Name[uk]=Засіб перетворення
+Name[uz]=Aylantirish asbobi
+Name[uz@cyrillic]=Айлантириш асбоби
+Name[zh_CN]=变形工具
+Name[zh_TW]=變形工具
+ServiceTypes=Krita/Tool
+Type=Service
+X-KDE-Library=kritatooltransform
+X-Krita-Version=2
diff --git a/krita/plugins/tools/tool_transform/rotate_cursor.xpm b/krita/plugins/tools/tool_transform/rotate_cursor.xpm
new file mode 100644
index 00000000..f3860232
--- /dev/null
+++ b/krita/plugins/tools/tool_transform/rotate_cursor.xpm
@@ -0,0 +1,29 @@
+/* XPM */
+static char *rotate_cursor[]={
+"22 22 4 1",
+"b c None",
+". c None",
+"a c #000000",
+"# c #ffffff",
+"......................",
+"......................",
+"....##...#####........",
+"....#a###aaaaa##......",
+"....#aaaabbbbbaa#.....",
+"....#aaa#.....bba#....",
+"....#aaaa#......ba#...",
+"....######......bba#..",
+".................ba#..",
+"..bbb.............ba#.",
+"..#ab.............ba#.",
+"..#ab.............ba#.",
+"..#ab.............ba#.",
+"..#ab.............ba#.",
+"...#ab............bbb.",
+"...#ab.......######...",
+"....#ab......#aaaa#...",
+".....#abbb....#aaa#...",
+"......#aabbbb#aaaa#...",
+".......##aaaaa###a#...",
+".........#####...##...",
+"......................"};
diff --git a/krita/plugins/tools/tool_transform/tool_transform.cc b/krita/plugins/tools/tool_transform/tool_transform.cc
new file mode 100644
index 00000000..e8c77aa7
--- /dev/null
+++ b/krita/plugins/tools/tool_transform/tool_transform.cc
@@ -0,0 +1,64 @@
+/*
+ * tool_transform.cc -- Part of Krita
+ *
+ * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#include <stdlib.h>
+#include <vector>
+
+#include <qpoint.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kinstance.h>
+#include <kmessagebox.h>
+#include <kstandarddirs.h>
+#include <kdebug.h>
+#include <kgenericfactory.h>
+
+#include <kis_global.h>
+#include <kis_types.h>
+#include <kis_tool_registry.h>
+
+#include "tool_transform.h"
+#include "kis_tool_transform.h"
+
+
+typedef KGenericFactory<ToolTransform> ToolTransformFactory;
+K_EXPORT_COMPONENT_FACTORY( kritatooltransform, ToolTransformFactory( "krita" ) )
+
+
+ToolTransform::ToolTransform(QObject *parent, const char *name, const QStringList &)
+ : KParts::Plugin(parent, name)
+{
+ setInstance(ToolTransformFactory::instance());
+
+ if ( parent->inherits("KisToolRegistry") )
+ {
+ KisToolRegistry * r = dynamic_cast<KisToolRegistry*>(parent);
+ KisToolTransformFactory * f = new KisToolTransformFactory();
+ Q_CHECK_PTR(f);
+ r->add(f);
+ }
+
+}
+
+ToolTransform::~ToolTransform()
+{
+}
+
+#include "tool_transform.moc"
diff --git a/krita/plugins/tools/tool_transform/tool_transform.h b/krita/plugins/tools/tool_transform/tool_transform.h
new file mode 100644
index 00000000..42eba788
--- /dev/null
+++ b/krita/plugins/tools/tool_transform/tool_transform.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef TOOL_TRANSFORM_H_
+#define TOOL_TRANSFORM_H_
+
+#include <kparts/plugin.h>
+
+class KisView;
+
+/**
+ * A module that provides a transform tool.
+ */
+class ToolTransform : public KParts::Plugin
+{
+ Q_OBJECT
+public:
+ ToolTransform(QObject *parent, const char *name, const QStringList &);
+ virtual ~ToolTransform();
+
+private:
+
+ KisView * m_view;
+
+};
+
+#endif // TOOL_TRANSFORM_H_
diff --git a/krita/plugins/tools/tool_transform/tool_transform.png b/krita/plugins/tools/tool_transform/tool_transform.png
new file mode 100644
index 00000000..47e58869
--- /dev/null
+++ b/krita/plugins/tools/tool_transform/tool_transform.png
Binary files differ
diff --git a/krita/plugins/tools/tool_transform/wdg_tool_transform.ui b/krita/plugins/tools/tool_transform/wdg_tool_transform.ui
new file mode 100644
index 00000000..b9307451
--- /dev/null
+++ b/krita/plugins/tools/tool_transform/wdg_tool_transform.ui
@@ -0,0 +1,243 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>WdgToolTransform</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>WdgToolTransform</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>377</width>
+ <height>91</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Transform</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>3</number>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>layout11</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout7</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Move X:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>isbX</cstring>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox">
+ <property name="name">
+ <cstring>intStartX</cstring>
+ </property>
+ <property name="maxValue">
+ <number>1000000000</number>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Scale X:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>isbWidth</cstring>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox">
+ <property name="name">
+ <cstring>intEndX</cstring>
+ </property>
+ <property name="maxValue">
+ <number>1000000000</number>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout8</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout3</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Move Y:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>isbY</cstring>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox">
+ <property name="name">
+ <cstring>intStartY</cstring>
+ </property>
+ <property name="maxValue">
+ <number>1000000000</number>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel4</cstring>
+ </property>
+ <property name="text">
+ <string>Scale Y:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>isbHeight</cstring>
+ </property>
+ </widget>
+ <widget class="KIntSpinBox">
+ <property name="name">
+ <cstring>intEndY</cstring>
+ </property>
+ <property name="maxValue">
+ <number>1000000000</number>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>Filter:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignVCenter|AlignRight</set>
+ </property>
+ </widget>
+ <widget class="KisCmbIDList" row="1" column="1">
+ <property name="name">
+ <cstring>cmbFilter</cstring>
+ </property>
+ </widget>
+ <spacer row="2" column="0">
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>21</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>KisCmbIDList</class>
+ <header location="local">kis_cmb_idlist.h</header>
+ <sizehint>
+ <width>1</width>
+ <height>24</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="PNG" length="870">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b0000032d49444154388db59531681c4714863f892dde8004b320c32e3870020b74458a6b0f5458e581c016a809a8496b42208454098604d2c4904a6954a410511ae752085b858c1208dc35221244b00119f60ac12ee860062c980719708a95a248f129459cd7cceeccf0edb76fff61a706830197d5ed765ff3166a30184c4d5d829fed3c7bdd5e6ce3bda71a5738ef301802e1d6d179477152303c1842bc822797a64fbf7b4a9a43be00ada817cb0e12011c2611205ccd73755f9c087c6b19bef0d7c100f5b8267d07caf10fe8ab9210156320fc01be16aa5a11043307f30b20a21041019985f48ef2f7fa0becc68e80475fd584e831b396f210f67795c3831a4940a3228925bb27f4d652ba4b01a199b73342f3981be0ca57745042ac30c632d853b6373d44b056c8ef0922508d94d14be59b2f4aeaf58cd5751069e06f3436890114332b9487d0bf80f61e64dc5f813c3790045453f67703fd4d4f7f6b4496b5597e689044af194f5f5e841800210478bee3d1a8f41e64acbe0f69ae6852e1cf0ccf7f74f4d652defbc042226c6f55e8f89f91bb6e9c387c9d521c9558db988a3416fe3c67e32b4779ec7167f0e8939ce19ea7fc5d298a80c875f03563930855ed2081bc05e91d5014ef53363eaf288e3d6285ee520a338e76c7a251a94e41e30470d3631004a262672e3eca59cec6978ef2b889979d11f2bb904af3be92081a416e28dfe831983920b1142345d5b0ff2234a6334276d7321ad53c795c511ca654a5a251996f19b83d158ef602b45a423d52f67703abeb29ee4ce9de4fc93378f218462f6b3efdb042cf3d59666977a0aa6fe9310888d25b13342afd4dcffeaee3d147399da540ab13f8f8b39c2cb3f8710d11ba2b96f9c57fcd7180287497a03ecde86f8dd8fe1a867b9ef6bb1612a84a871f6bd35b94e217a53832589970f2dcd85d9c7d4580d57521cbdaf4bfaf288e95e268d4ec8e60e72ccb0f2dbffea454e71e8d29f57882717152509482a48d8924b0bc12e82ee51445a03a6da079cbd0eec0fc22142b06620e89a3fc8d3783870743d814d2bc8994aa6ff286472e764902e5a96f72bbd3b4c37b280e95aa9e604c84e1cf978b37c74935797d7ae2ca7fac6968fe51ff0bf86dc30783c1d49f0baa9bb819e612310000000049454e44ae426082</data>
+ </image>
+</images>
+<tabstops>
+ <tabstop>intStartX</tabstop>
+ <tabstop>intStartY</tabstop>
+ <tabstop>intEndX</tabstop>
+ <tabstop>intEndY</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>knuminput.h</includehint>
+ <includehint>kis_cmb_idlist.h</includehint>
+</includehints>
+</UI>