diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2011-06-26 00:41:16 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2011-06-26 00:41:16 +0000 |
commit | 698569f8428ca088f764d704034a1330517b98c0 (patch) | |
tree | bf45be6946ebbbee9cce5a5bcf838f4c952d87e6 /chalk/plugins/tools/tool_perspectivetransform | |
parent | 2785103a6bd4de55bd26d79e34d0fdd4b329a73a (diff) | |
download | koffice-698569f8428ca088f764d704034a1330517b98c0.tar.gz koffice-698569f8428ca088f764d704034a1330517b98c0.zip |
Finish rebranding of Krita as Chalk
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/koffice@1238363 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'chalk/plugins/tools/tool_perspectivetransform')
8 files changed, 1138 insertions, 0 deletions
diff --git a/chalk/plugins/tools/tool_perspectivetransform/Makefile.am b/chalk/plugins/tools/tool_perspectivetransform/Makefile.am new file mode 100644 index 00000000..416bdcc3 --- /dev/null +++ b/chalk/plugins/tools/tool_perspectivetransform/Makefile.am @@ -0,0 +1,35 @@ +kde_services_DATA = chalktoolperspectivetransform.desktop + +# all_includes must remain last! +INCLUDES = -I$(srcdir)/../../../sdk \ + -I$(srcdir)/../../../core \ + -I$(srcdir)/../../../chalkcolor/ \ + -I$(srcdir)/../../../ui \ + -I$/../../../ui \ + $(KOFFICE_INCLUDES) \ + $(all_includes) + +chalktoolperspectivetransform_la_SOURCES = \ + tool_perspectivetransform.cc \ + kis_tool_perspectivetransform.cc + +# Install this plugin in the KDE modules directory +kde_module_LTLIBRARIES = chalktoolperspectivetransform.la + +noinst_HEADERS = \ + tool_perspectivetransform.h \ + kis_tool_perspectivetransform.h + +chalktoolperspectivetransform_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) $(LIB_QT) -lkdecore -lkdeui -lkjs -lkdefx -lkio -lkparts -L../../../../chalk/chalkcolor/.libs -lchalkcolor -L../../../../chalk/core/.libs -lchalkimage \ + -L../../../../chalk/ui/.libs -lchalkui +chalktoolperspectivetransform_la_LIBADD = ../../../libchalkcommon.la + +chalktoolperspectivetransform_la_METASOURCES = AUTO + +KDE_OPTIONS = nofinal + +chalkpics_DATA = \ + tool_perspectivetransform.png + +chalkpicsdir = $(kde_datadir)/chalk/pics + diff --git a/chalk/plugins/tools/tool_perspectivetransform/chalktoolperspectivetransform.desktop b/chalk/plugins/tools/tool_perspectivetransform/chalktoolperspectivetransform.desktop new file mode 100644 index 00000000..860efc69 --- /dev/null +++ b/chalk/plugins/tools/tool_perspectivetransform/chalktoolperspectivetransform.desktop @@ -0,0 +1,37 @@ +[Desktop Entry] +Icon= +Name=Perspective transform Tool +Name[bg]=Инструмент трансформиране +Name[ca]=Eina de transformació de perspectiva +Name[da]=Perspectivetransformeringsværktøj +Name[de]=Perspektive-Transformationswerkzeug +Name[el]=Εργαλείο προοπτικού μετασχηματισμού +Name[eo]=Perspektivŝanĝo-ilo +Name[es]=Herramienta Transformar perspectiva +Name[et]=Perspektiivteisenduse tööriist +Name[fa]=ابزار تبدیل بُعدنما +Name[fr]=Outils de transformation de perspective +Name[fy]=Perspeksje oerset ark +Name[hu]=Perspektívaátalakító eszköz +Name[it]=Strumento di trasformazione della prospettiva +Name[ja]=視点変更ツール +Name[km]=ឧបករណ៍ប្លែងយថាទស្សន៍ +Name[nb]=Verktøy for perspektivtransformasjon +Name[nds]=Warktüüch för't Kiekwinkeltopassen +Name[ne]=दृश्यात्मक रूपान्तरण उपकरण +Name[nl]=Perspectiefrooster-gereedschap +Name[pl]=Narzędzie zmiany perspektywy +Name[pt]=Ferramenta de Transformação em Perspectiva +Name[pt_BR]=Ferramentas de Transformação em Perspectiva +Name[ru]=Перспектива +Name[sk]=Perspektívna transformácia +Name[sl]=Orodje za transformacijo perspektive +Name[sr]=Алати за трансформацију перспективе +Name[sr@Latn]=Alati za transformaciju perspektive +Name[sv]=Perspektivtransformverktyg +Name[uk]=Засіб перспективи +Name[zh_TW]=透視轉換工具 +ServiceTypes=Chalk/Tool +Type=Service +X-KDE-Library=chalktoolperspectivetransform +X-Chalk-Version=2 diff --git a/chalk/plugins/tools/tool_perspectivetransform/kis_tool_perspectivetransform.cc b/chalk/plugins/tools/tool_perspectivetransform/kis_tool_perspectivetransform.cc new file mode 100644 index 00000000..809d1a7d --- /dev/null +++ b/chalk/plugins/tools/tool_perspectivetransform/kis_tool_perspectivetransform.cc @@ -0,0 +1,742 @@ +/* + * kis_tool_transform.cc -- part of Chalk + * + * Copyright (c) 2006 Cyrille Berger <[email protected]> + * + * Based on the transform tool from : + * Copyright (c) 2004 Boudewijn Rempt <[email protected]> + * Copyright (c) 2005 Casper Boemann <[email protected]> + * + * 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; version 2 of the License. + * + * 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 "kis_tool_perspectivetransform.h" + + +#include <tqpainter.h> +#include <tqpen.h> +#include <tqpushbutton.h> +#include <tqobject.h> +#include <tqlabel.h> +#include <tqcombobox.h> +#include <tqapplication.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_perspectivetransform_worker.h> + +//#include "wdg_tool_transform.h" +#include "kis_canvas.h" +#include "kis_canvas_painter.h" + +namespace { + class PerspectiveTransformCmd : public KisSelectedTransaction { + typedef KisSelectedTransaction super; + + public: + PerspectiveTransformCmd(KisToolPerspectiveTransform *tool, KisPaintDeviceSP device, KisPaintDeviceSP origDevice, KisPoint topleft, KisPoint topright, KisPoint bottomleft, KisPoint bottomright, KisSelectionSP origSel, TQRect initialRect); + virtual ~PerspectiveTransformCmd(); + + public: + virtual void execute(); + virtual void unexecute(); + void transformArgs(KisPoint &topleft, KisPoint &topright, KisPoint &bottomleft, KisPoint& bottomright) const; + KisSelectionSP origSelection(TQRect& initialRect) const; + KisPaintDeviceSP theDevice(); + KisPaintDeviceSP origDevice(); + + private: + TQRect m_initialRect; + KisPoint m_topleft, m_topright, m_bottomleft, m_bottomright; + KisToolPerspectiveTransform *m_tool; + KisSelectionSP m_origSelection; + KisPaintDeviceSP m_device; + KisPaintDeviceSP m_origDevice; + }; + + PerspectiveTransformCmd::PerspectiveTransformCmd(KisToolPerspectiveTransform *tool, KisPaintDeviceSP device, KisPaintDeviceSP origDevice, KisPoint topleft, KisPoint topright, KisPoint bottomleft, KisPoint bottomright, KisSelectionSP origSel, TQRect initialRect) : + super(i18n("Perspective Transform"), device), m_initialRect(initialRect) + , m_topleft(topleft), m_topright(topright), m_bottomleft(bottomleft), m_bottomright(bottomright) + , m_tool(tool), m_origSelection(origSel), m_device(device), m_origDevice(origDevice) + { + } + + PerspectiveTransformCmd::~PerspectiveTransformCmd() + { + } + + void PerspectiveTransformCmd::transformArgs(KisPoint &topleft, KisPoint &topright, KisPoint &bottomleft, KisPoint& bottomright) const + { + topleft = m_topleft; + topright = m_topright; + bottomleft = m_bottomleft; + bottomright = m_bottomright; + } + + KisSelectionSP PerspectiveTransformCmd::origSelection(TQRect& initialRect) const + { + initialRect = m_initialRect; + return m_origSelection; + } + + void PerspectiveTransformCmd::execute() + { + super::execute(); + } + + void PerspectiveTransformCmd::unexecute() + { + super::unexecute(); + } + + KisPaintDeviceSP PerspectiveTransformCmd::theDevice() + { + return m_device; + } + + KisPaintDeviceSP PerspectiveTransformCmd::origDevice() + { + return m_origDevice; + } +} + +KisToolPerspectiveTransform::KisToolPerspectiveTransform() + : super(i18n("Perspective Transform")) +{ + setName("tool_perspectivetransform"); + setCursor(KisCursor::selectCursor()); + m_subject = 0; + m_origDevice = 0; + m_origSelection = 0; + m_handleHalfSize = 8; + m_handleSize = 2 * m_handleHalfSize; + m_handleSelected = NOHANDLE; +} + +KisToolPerspectiveTransform::~KisToolPerspectiveTransform() +{ +} + +void KisToolPerspectiveTransform::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(), TQT_SIGNAL(sigLayerActivated(KisLayerSP)), this, TQT_SLOT(slotLayerActivated(KisLayerSP))); +} + +void KisToolPerspectiveTransform::activate() +{ + super::activate(); + m_currentSelectedPoint = 0; + 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); + + PerspectiveTransformCmd * cmd=0; + + if(m_subject->currentImg()->undoAdapter()->presentCommand()) + cmd = dynamic_cast<PerspectiveTransformCmd*>(m_subject->currentImg()->undoAdapter()->presentCommand()); + + // One of our commands is on top + if(cmd &&cmd->theDevice() == m_subject->currentImg()->activeDevice()) + { + m_interractionMode = EDITRECTINTERRACTION; + // and it even has the same device + // We should ask for tool args and orig selection + m_origDevice = cmd->origDevice(); + cmd->transformArgs(m_topleft, m_topright, m_bottomleft, m_bottomright); + m_origSelection = cmd->origSelection(m_initialRect); + paintOutline(); + } + else + { + m_interractionMode = DRAWRECTINTERRACTION; + m_points.clear(); + initHandles(); + } + } + connect(m_subject->currentImg(), TQT_SIGNAL(sigLayerActivated(KisLayerSP)), this, TQT_SLOT(slotLayerActivated(KisLayerSP))); +} + +void KisToolPerspectiveTransform::initHandles() +{ +// TQ_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()); + m_initialRect = sel->selectedExactRect(); + } + else { + m_initialRect = dev->exactBounds(); + } + m_topleft = KisPoint(m_initialRect.topLeft()); + m_topright = KisPoint(m_initialRect.topRight()); + m_bottomleft = KisPoint(m_initialRect.bottomLeft()); + m_bottomright = KisPoint(m_initialRect.bottomRight()); + + m_subject->canvasController() ->updateCanvas(); +} + +void KisToolPerspectiveTransform::paint(KisCanvasPainter& gc) +{ + paintOutline(gc, TQRect()); +} + +void KisToolPerspectiveTransform::paint(KisCanvasPainter& gc, const TQRect& rc) +{ + paintOutline(gc, rc); +} + +bool KisToolPerspectiveTransform::mouseNear(const TQPoint& mousep, const TQPoint point) +{ + return (TQRect( (point.x() - m_handleHalfSize), (point.y() - m_handleHalfSize), m_handleSize, m_handleSize).tqcontains(mousep) ); +} + +void KisToolPerspectiveTransform::buttonPress(KisButtonPressEvent *event) +{ + if (m_subject) { + switch(m_interractionMode) + { + case DRAWRECTINTERRACTION: + { + if (m_points.isEmpty()) + { + m_dragging = false; + m_dragStart = event->pos(); + m_dragEnd = event->pos(); + m_points.append(m_dragStart); + paintOutline(); + } else { + m_dragging = true; + m_dragStart = m_dragEnd; + m_dragEnd = event->pos(); + paintOutline(); + } + } + case EDITRECTINTERRACTION: + { + KisImageSP img = m_subject->currentImg(); + + if (img && img->activeDevice() && event->button() == Qt::LeftButton) { + m_actualyMoveWhileSelected = false; + m_dragEnd = event->pos(); + KisCanvasController *controller = m_subject->canvasController(); + TQPoint mousep = controller->windowToView( event->pos().roundTQPoint() ); + if( mouseNear( mousep, controller->windowToView(m_topleft.roundTQPoint() ) ) ) + { + kdDebug() << " PRESS TOPLEFT HANDLE " << endl; + m_currentSelectedPoint = &m_topleft; + } + else if( mouseNear( mousep, controller->windowToView(m_topright.roundTQPoint() ) ) ) + { + kdDebug() << " PRESS TOPRIGHT HANDLE " << endl; + m_currentSelectedPoint = &m_topright; + } + else if( mouseNear( mousep, controller->windowToView(m_bottomleft.roundTQPoint() ) ) ) + { + kdDebug() << " PRESS BOTTOMLEFT HANDLE " << endl; + m_currentSelectedPoint = &m_bottomleft; + } + else if( mouseNear( mousep, controller->windowToView(m_bottomright.roundTQPoint() ) ) ) + { + kdDebug() << " PRESS BOTTOMRIGHT HANDLE " << endl; + m_currentSelectedPoint = &m_bottomright; + } else if( mouseNear( mousep, controller->windowToView(KisPoint((m_topleft+m_topright)*0.5).roundTQPoint() ) ) ) + { + kdDebug() << " PRESS TOP HANDLE " << endl; + m_handleSelected = TOPHANDLE; + }else if( mouseNear( mousep, controller->windowToView(KisPoint((m_topleft+m_bottomleft)*0.5).roundTQPoint() ) ) ) + { + kdDebug() << " PRESS LEFT HANDLE " << endl; + m_handleSelected = LEFTHANDLE; + }else if( mouseNear( mousep, controller->windowToView(KisPoint((m_bottomleft+m_bottomright)*0.5).roundTQPoint() ) ) ) + { + kdDebug() << " PRESS BOTTOM HANDLE " << endl; + m_handleSelected = BOTTOMHANDLE; + }else if( mouseNear( mousep, controller->windowToView(KisPoint((m_bottomright+m_topright)*0.5).roundTQPoint() ) ) ) + { + kdDebug() << " PRESS RIGHT HANDLE " << endl; + m_handleSelected = RIGHTHANDLE; + }else if( mouseNear( mousep, controller->windowToView(KisPoint((m_topleft+m_bottomleft + m_bottomright+m_topright)*0.25).roundTQPoint() ) ) ) + { + kdDebug() << " PRESS MIDDLE HANDLE " << endl; + m_handleSelected = MIDDLEHANDLE; + } + } + } + } + } +} + +void KisToolPerspectiveTransform::move(KisMoveEvent *event) +{ + switch(m_interractionMode) + { + case DRAWRECTINTERRACTION: + { + if (m_dragging) { + // erase old lines on canvas + paintOutline(); + // get current mouse position + m_dragEnd = event->pos(); + // draw new lines on canvas + paintOutline(); + } + } + + case EDITRECTINTERRACTION: + { + if(m_currentSelectedPoint) + { + paintOutline(); + KisPoint translate = event->pos() - m_dragEnd; + m_dragEnd = event->pos(); + *m_currentSelectedPoint += translate;; + paintOutline(); + m_actualyMoveWhileSelected = true; + } + else if(m_handleSelected == TOPHANDLE || m_handleSelected == LEFTHANDLE || m_handleSelected == BOTTOMHANDLE || m_handleSelected == RIGHTHANDLE) + { + paintOutline(); + + KisPoint translate = event->pos() - m_dragEnd; + m_dragEnd = event->pos(); + + double matrixFrom[3][3]; + double* b = KisPerspectiveMath::computeMatrixTransfoToPerspective(m_topleft, m_topright, m_bottomleft, m_bottomright, m_initialRect); + for(int i = 0; i < 3; i++) + { + for(int j = 0; j < 3; j++) + { + matrixFrom[i][j] = b[3*i+j]; + } + } + delete b; + + KisPoint topLeft = KisPerspectiveMath::matProd(matrixFrom, KisPoint(m_initialRect.topLeft()) ); + KisPoint topRight = KisPerspectiveMath::matProd(matrixFrom, KisPoint(m_initialRect.topRight()) ); + KisPoint bottomLeft = KisPerspectiveMath::matProd(matrixFrom, KisPoint(m_initialRect.bottomLeft()) ); + KisPoint bottomRight = KisPerspectiveMath::matProd(matrixFrom, KisPoint(m_initialRect.bottomRight()) ); + TQRect dstRect = m_initialRect; + switch(m_handleSelected) + { + case TOPHANDLE: + dstRect.setTop( static_cast<int>( dstRect.top() + translate.y() ) ) ; + break; + case LEFTHANDLE: + dstRect.setLeft( static_cast<int>( dstRect.left() + translate.x() ) ); + break; + case BOTTOMHANDLE: + dstRect.setBottom( static_cast<int>( dstRect.bottom() + translate.y() ) ); + break; + case RIGHTHANDLE: + dstRect.setRight( static_cast<int>( dstRect.right() + translate.x() ) ); + break; + case MIDDLEHANDLE: + case NOHANDLE: + kdDebug() << "Should NOT happen" << endl; + } + double matrixTo[3][3]; + b = KisPerspectiveMath::computeMatrixTransfoToPerspective(topLeft, topRight, bottomLeft, bottomRight, dstRect ); + for(int i = 0; i < 3; i++) + { + for(int j = 0; j < 3; j++) + { + matrixTo[i][j] = b[3*i+j]; + } + } + delete b; + m_topleft = KisPerspectiveMath::matProd(matrixTo, KisPoint(m_initialRect.topLeft())); + m_topright = KisPerspectiveMath::matProd(matrixTo, KisPoint(m_initialRect.topRight())); + m_bottomleft = KisPerspectiveMath::matProd(matrixTo, KisPoint(m_initialRect.bottomLeft())); + m_bottomright = KisPerspectiveMath::matProd(matrixTo, KisPoint(m_initialRect.bottomRight())); + + paintOutline(); + m_actualyMoveWhileSelected = true; + } else if (m_handleSelected == MIDDLEHANDLE) { + paintOutline(); + KisPoint translate = event->pos() - m_dragEnd; + m_dragEnd = event->pos(); + m_topleft += translate; + m_topright += translate; + m_bottomleft += translate; + m_bottomright += translate; + paintOutline(); + m_actualyMoveWhileSelected = true; + } + } + }; +} + +void KisToolPerspectiveTransform::buttonRelease(KisButtonReleaseEvent * event) +{ + KisImageSP img = m_subject->currentImg(); + + if (!img) + return; + if( event->button() == Qt::LeftButton) + { + switch(m_interractionMode) + { + case DRAWRECTINTERRACTION: + { + if (m_dragging && event->button() == Qt::LeftButton) { + paintOutline(); + m_dragging = false; + m_points.append (m_dragEnd); + if( m_points.size() == 4) + { + // from the points, select which is topleft ? topright ? bottomright ? and bottomleft ? + m_topleft = m_points[0]; + m_topright = m_points[1]; + m_bottomleft = m_points[3]; + m_bottomright = m_points[2]; + double matrix[3][3]; + double* b = KisPerspectiveMath::computeMatrixTransfoToPerspective(m_topleft, m_topright, m_bottomleft, m_bottomright, m_initialRect ); + for(int i = 0; i < 3; i++) + { + for(int j = 0; j < 3; j++) + { + kdDebug() << "sol[" << 3*i+j << "]=" << b[3*i+j] << endl; + matrix[i][j] = b[3*i+j]; + } + } + m_topleft = KisPerspectiveMath::matProd(matrix, KisPoint(m_initialRect.topLeft())); + m_topright = KisPerspectiveMath::matProd(matrix, KisPoint(m_initialRect.topRight())); + m_bottomleft = KisPerspectiveMath::matProd(matrix, KisPoint(m_initialRect.bottomLeft())); + m_bottomright = KisPerspectiveMath::matProd(matrix, KisPoint(m_initialRect.bottomRight())); + m_interractionMode = EDITRECTINTERRACTION; + paintOutline(); + TQApplication::setOverrideCursor(KisCursor::waitCursor()); + transform(); + TQApplication::restoreOverrideCursor(); + } else { + paintOutline(); + } + } + } + break; + case EDITRECTINTERRACTION: + { + if(m_currentSelectedPoint ) + { + m_currentSelectedPoint = 0; + if(m_actualyMoveWhileSelected) + { + paintOutline(); + TQApplication::setOverrideCursor(KisCursor::waitCursor()); + transform(); + TQApplication::restoreOverrideCursor(); + } + } + if(m_handleSelected != NOHANDLE) + { + m_handleSelected = NOHANDLE; + if(m_actualyMoveWhileSelected) + { +// paintOutline(); + TQApplication::setOverrideCursor(KisCursor::waitCursor()); + transform(); + TQApplication::restoreOverrideCursor(); + } + } + } + break; + } + } +} + +void KisToolPerspectiveTransform::paintOutline() +{ + if (m_subject) { + KisCanvasController *controller = m_subject->canvasController(); + KisCanvas *canvas = controller->kiscanvas(); + KisCanvasPainter gc(canvas); + TQRect rc; + + paintOutline(gc, rc); + } +} + +void KisToolPerspectiveTransform::paintOutline(KisCanvasPainter& gc, const TQRect&) +{ + if (m_subject) { + KisCanvasController *controller = m_subject->canvasController(); + RasterOp op = gc.rasterOp(); + TQPen old = gc.pen(); + TQPen pen(TQt::SolidLine); + pen.setWidth(1); + Q_ASSERT(controller); + + switch(m_interractionMode) + { + case DRAWRECTINTERRACTION: + { + kdDebug() << "DRAWRECTINTERRACTION paintOutline " << m_points.size() << endl; + KisPoint start, end; + TQPoint startPos; + TQPoint endPos; + for (KisPointVector::iterator it = m_points.begin(); it != m_points.end(); ++it) { + + if (it == m_points.begin()) + { + start = (*it); + } else { + end = (*it); + + startPos = controller->windowToView(start.floorTQPoint()); + endPos = controller->windowToView(end.floorTQPoint()); + + gc.drawLine(startPos, endPos); + + start = end; + } + } + } + break; + case EDITRECTINTERRACTION: + { + TQPoint topleft = controller->windowToView(m_topleft ).roundTQPoint(); + TQPoint topright = controller->windowToView(m_topright).roundTQPoint(); + TQPoint bottomleft = controller->windowToView(m_bottomleft).roundTQPoint(); + TQPoint bottomright = controller->windowToView(m_bottomright).roundTQPoint(); + + gc.setRasterOp(TQt::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.drawRect((bottomleft.x()+bottomright.x()+topleft.x()+topright.x())/4-4, (bottomleft.y()+bottomright.y()+topleft.y()+topright.y())/4-4, 8, 8); + } + break; + } + gc.setRasterOp(op); + gc.setPen(old); + } +} + +void KisToolPerspectiveTransform::transform() +{ + KisImageSP img = m_subject->currentImg(); + + if (!img || !img->activeDevice()) + return; + + KisProgressDisplayInterface *progress = m_subject->progressDisplay(); + + // This mementoes the current state of the active device. + PerspectiveTransformCmd * transaction = new PerspectiveTransformCmd(this, img->activeDevice(), m_origDevice, + m_topleft, m_topright, m_bottomleft, m_bottomright, m_origSelection, m_initialRect); + + // Copy the original state back. + TQRect 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) + { + TQRect 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. + KisPerspectiveTransformWorker t(img->activeDevice(),m_topleft, m_topright, m_bottomleft, m_bottomright, progress); + 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 KisToolPerspectiveTransform::notifyCommandAdded( KCommand * command) +{ + PerspectiveTransformCmd * cmd = dynamic_cast<PerspectiveTransformCmd*>(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 KisToolPerspectiveTransform::notifyCommandExecuted( KCommand * command) +{ + Q_UNUSED(command); + PerspectiveTransformCmd * cmd=0; + if(m_subject->currentImg()->undoAdapter()->presentCommand()) + cmd = dynamic_cast<PerspectiveTransformCmd*>(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 + m_origDevice = cmd->origDevice(); + cmd->transformArgs(m_topleft, m_topright, m_bottomleft, m_bottomright); + m_origSelection = cmd->origSelection(m_initialRect); + m_subject->canvasController() ->updateCanvas(); + } +} + +void KisToolPerspectiveTransform::slotLayerActivated(KisLayerSP) +{ + activate(); +} + + +TQWidget* KisToolPerspectiveTransform::createOptionWidget(TQWidget* /*tqparent*/) +{ +#if 0 + m_optWidget = new WdgToolPerspectiveTransform(tqparent); + 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, TQT_SIGNAL(activated(const KisID &)), + this, TQT_SLOT(slotSetFilter(const KisID &))); + + KisID filterID = m_optWidget->cmbFilter->currentItem(); + m_filter = KisFilterStrategyRegistry::instance()->get(filterID); + +/* + connect(m_optWidget->intStartX, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(setStartX(int))); + connect(m_optWidget->intStartY, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(setStartY(int))); + connect(m_optWidget->intEndX, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(setEndX(int))); + connect(m_optWidget->intEndY, TQT_SIGNAL(valueChanged(int)), this, TQT_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(); +#endif + return 0; +} + +TQWidget* KisToolPerspectiveTransform::optionWidget() +{ + return 0; +} + +void KisToolPerspectiveTransform::setup(KActionCollection *collection) +{ + m_action = static_cast<KRadioAction *>(collection->action(name())); + + if (m_action == 0) { + m_action = new KRadioAction(i18n("&Perspective Transform"), + "tool_perspectivetransform", + 0, + this, + TQT_SLOT(activate()), + collection, + name()); + Q_CHECK_PTR(m_action); + m_action->setToolTip(i18n("Perspective transform a layer or a selection")); + m_action->setExclusiveGroup("tools"); + m_ownAction = true; + } +} + +#include "kis_tool_perspectivetransform.moc" diff --git a/chalk/plugins/tools/tool_perspectivetransform/kis_tool_perspectivetransform.h b/chalk/plugins/tools/tool_perspectivetransform/kis_tool_perspectivetransform.h new file mode 100644 index 00000000..5d637ae5 --- /dev/null +++ b/chalk/plugins/tools/tool_perspectivetransform/kis_tool_perspectivetransform.h @@ -0,0 +1,131 @@ +/* + * kis_tool_transform.h - part of Chalk + * + * Copyright (c) 2006 Cyrille Berger <[email protected]> + * + * Based on the transform tool from : + * Copyright (c) 2004 Boudewijn Rempt <[email protected]> + * Copyright (c) 2005 Casper Boemann <[email protected]> + * + * 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; version 2 of the License. + * + * 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_PERSPECTIVETRANSFORM_H_ +#define KIS_TOOL_PERSPECTIVETRANSFORM_H_ + +#include <tqpoint.h> + +#include <kis_layer.h> +#include <kis_point.h> +#include <kis_tool_non_paint.h> +#include <kis_tool_factory.h> +#include <kis_undo_adapter.h> +#include <kis_perspective_math.h> + +class KisTransaction; +class WdgToolPerspectiveTransform; +class KisID; +class KisFilterStrategy; + +/** + * PerspectiveTransform tool + * + */ +class KisToolPerspectiveTransform : public KisToolNonPaint, KisCommandHistoryListener { + + typedef KisToolNonPaint super; + Q_OBJECT + TQ_OBJECT + enum InterractionMode { DRAWRECTINTERRACTION, EDITRECTINTERRACTION }; + enum HandleSelected { NOHANDLE, TOPHANDLE, BOTTOMHANDLE, RIGHTHANDLE, LEFTHANDLE, MIDDLEHANDLE }; +public: + KisToolPerspectiveTransform(); + virtual ~KisToolPerspectiveTransform(); + + virtual TQWidget* createOptionWidget(TQWidget* tqparent); + virtual TQWidget* optionWidget(); + + virtual void setup(KActionCollection *collection); + virtual enumToolType toolType() { return TOOL_TRANSFORM; } + virtual TQ_UINT32 priority() { return 4; } + virtual void paint(KisCanvasPainter& gc); + virtual void paint(KisCanvasPainter& gc, const TQRect& rc); + virtual void buttonPress(KisButtonPressEvent *e); + virtual void move(KisMoveEvent *e); + virtual void buttonRelease(KisButtonReleaseEvent *e); + void paintOutline(); + +public: + + void notifyCommandAdded(KCommand *); + void notifyCommandExecuted(KCommand *); + +public: + virtual void deactivate(); + +private: + + bool mouseNear(const TQPoint& mousep, const TQPoint point); + void paintOutline(KisCanvasPainter& gc, const TQRect& rc); + void transform(); + void initHandles(); + +private slots: + void slotLayerActivated(KisLayerSP); + +protected slots: + virtual void activate(); + +private: + bool m_dragging; + InterractionMode m_interractionMode; + TQRect m_initialRect; + KisPoint m_dragStart, m_dragEnd; + KisPoint m_topleft, m_topright, m_bottomleft, m_bottomright; + KisPoint* m_currentSelectedPoint; + bool m_actualyMoveWhileSelected; + + WdgToolPerspectiveTransform *m_optWidget; + + KisPaintDeviceSP m_origDevice; + KisSelectionSP m_origSelection; + int m_handleHalfSize, m_handleSize; + + // The following variables are used in during the draw rect interraction mode + typedef TQValueVector<KisPoint> KisPointVector; + KisPointVector m_points; + // The following variables are used when moving a middle handle + HandleSelected m_handleSelected; + +}; + +class KisToolPerspectiveTransformFactory : public KisToolFactory { + typedef KisToolFactory super; + +public: + KisToolPerspectiveTransformFactory() : super() {}; + virtual ~KisToolPerspectiveTransformFactory(){}; + + virtual KisTool * createTool(KActionCollection * ac) { + KisTool * t = new KisToolPerspectiveTransform(); + Q_CHECK_PTR(t); + t->setup(ac); return t; + } + virtual KisID id() { return KisID("perspective transform", i18n("Perspective transform Tool")); } +}; + + + +#endif // KIS_TOOL_TRANSFORM_H_ + diff --git a/chalk/plugins/tools/tool_perspectivetransform/tool_perspectivetransform.cc b/chalk/plugins/tools/tool_perspectivetransform/tool_perspectivetransform.cc new file mode 100644 index 00000000..2c3c85d4 --- /dev/null +++ b/chalk/plugins/tools/tool_perspectivetransform/tool_perspectivetransform.cc @@ -0,0 +1,63 @@ +/* + * tool_perspectivetransform.cc -- Part of Chalk + * + * Copyright (c) 2006 Cyrille Berger <[email protected]> + * + * 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 <tqpoint.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_perspectivetransform.h" +#include "kis_tool_perspectivetransform.h" + + +typedef KGenericFactory<ToolPerspectiveTransform> ToolPerspectiveTransformFactory; +K_EXPORT_COMPONENT_FACTORY( chalktoolperspectivetransform, ToolPerspectiveTransformFactory( "chalk" ) ) + + +ToolPerspectiveTransform::ToolPerspectiveTransform(TQObject *tqparent, const char *name, const TQStringList &) + : KParts::Plugin(tqparent, name) +{ + setInstance(ToolPerspectiveTransformFactory::instance()); + + if ( tqparent->inherits("KisToolRegistry") ) + { + kdDebug() << " add perspective transform tool to the registry" << endl; + KisToolRegistry * r = dynamic_cast<KisToolRegistry*>(tqparent); + r->add(new KisToolPerspectiveTransformFactory()); + } + +} + +ToolPerspectiveTransform::~ToolPerspectiveTransform() +{ +} + +#include "tool_perspectivetransform.moc" diff --git a/chalk/plugins/tools/tool_perspectivetransform/tool_perspectivetransform.h b/chalk/plugins/tools/tool_perspectivetransform/tool_perspectivetransform.h new file mode 100644 index 00000000..1cbeadee --- /dev/null +++ b/chalk/plugins/tools/tool_perspectivetransform/tool_perspectivetransform.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2006 Cyrille Berger <[email protected]> + * + * 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_PERSPECTIVE_TRANSFORM_H_ +#define TOOL_PERSPECTIVE_TRANSFORM_H_ + +#include <kparts/plugin.h> + +class KisView; + +/** + * A module that provides a tool for doinge perspective transformation. + */ +class ToolPerspectiveTransform : public KParts::Plugin +{ + Q_OBJECT + TQ_OBJECT +public: + ToolPerspectiveTransform(TQObject *tqparent, const char *name, const TQStringList &); + virtual ~ToolPerspectiveTransform(); + +private: + + KisView * m_view; + +}; + +#endif // TOOL_PERSPECTIVE_TRANSFORM_H_ diff --git a/chalk/plugins/tools/tool_perspectivetransform/tool_perspectivetransform.png b/chalk/plugins/tools/tool_perspectivetransform/tool_perspectivetransform.png Binary files differnew file mode 100644 index 00000000..c64d09eb --- /dev/null +++ b/chalk/plugins/tools/tool_perspectivetransform/tool_perspectivetransform.png diff --git a/chalk/plugins/tools/tool_perspectivetransform/tool_perspectivetransform.svg b/chalk/plugins/tools/tool_perspectivetransform/tool_perspectivetransform.svg new file mode 100644 index 00000000..3dd79413 --- /dev/null +++ b/chalk/plugins/tools/tool_perspectivetransform/tool_perspectivetransform.svg @@ -0,0 +1,87 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://web.resource.org/cc/" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="22" + height="22" + id="svg2" + sodipodi:version="0.32" + inkscape:version="0.43" + version="1.0" + sodipodi:docbase="/home/cyrille/koffice-1.6/chalk/plugins/tools/tool_perspectivegrid" + sodipodi:docname="tool_perspectivegrid.svg" + inkscape:export-filename="/home/cyrille/koffice-1.6/chalk/plugins/tools/tool_perspectivegrid/tool_perspectivegrid.png" + inkscape:export-xdpi="90" + inkscape:export-ydpi="90"> + <defs + id="defs4" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="9.8597476" + inkscape:cx="12.855376" + inkscape:cy="7.6671075" + inkscape:document-units="px" + inkscape:current-layer="layer1" + inkscape:window-width="749" + inkscape:window-height="540" + inkscape:window-x="424" + inkscape:window-y="433" /> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1"> + <path + style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#909090;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 4.8682788,20.580085 C 6.5924609,1.3098151 6.7953058,1.5126601 6.7953058,1.5126601 L 6.7953058,1.5126601 L 6.7953058,1.5126601" + id="path2183" /> + <path + style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#909090;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 11.359317,18.551636 C 10.446515,2.3240399 10.446515,2.3240399 10.446515,2.3240399 L 10.446515,2.3240399 L 10.446515,2.3240399" + id="path2185" /> + <path + style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#909090;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 17.444666,17.131721 C 13.894879,3.1354197 13.894879,3.1354197 13.894879,3.1354197" + id="path2187" /> + <path + style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#909090;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 2.7384068,4.7581793 C 17.647511,6.5837838 17.546088,6.5837838 17.546088,6.5837838" + id="path2191" /> + <path + style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#909090;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 2.0284495,10.742105 C 18.256045,9.7278805 18.86458,9.1193456 18.86458,9.1193456" + id="path2193" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#909090;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 1.0142247,17.131721 C 20.08165,12.56771 20.08165,12.364865 20.08165,12.364865" + id="path2195" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 3.1440967,0.59985768 L 16.531864,3.6425319 L 21.70441,15.813228 L 0.50711235,21.594309 L 3.1440967,0.59985768 z " + id="rect1307" + sodipodi:nodetypes="ccccc" /> + </g> +</svg> |