diff --git a/krita/ui/canvas/kis_coordinates_converter.cpp b/krita/ui/canvas/kis_coordinates_converter.cpp index 08aca3a944..abb824c13d 100644 --- a/krita/ui/canvas/kis_coordinates_converter.cpp +++ b/krita/ui/canvas/kis_coordinates_converter.cpp @@ -1,293 +1,305 @@ /* * Copyright (c) 2010 Dmitry Kazakov * Copyright (c) 2011 Silvio Heinrich * * 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 "kis_coordinates_converter.h" #include #include #include #include struct KisCoordinatesConverter::Private { Private(): isXAxisMirrored(false), isYAxisMirrored(false) { } KisImageWSP image; bool isXAxisMirrored; bool isYAxisMirrored; - QSize canvasWidgetSize; - QPoint documentOffset; - QPoint documentOrigin; + QSizeF canvasWidgetSize; + QPointF documentOffset; + QPointF documentOrigin; + QTransform postprocessingTransform; - QTransform imageToDocument; QTransform documentToFlake; QTransform flakeToPostprocessedFlake; QTransform postprocessedFlakeToWidget; QTransform widgetToViewport; }; void KisCoordinatesConverter::recalculateTransformations() const { if(!m_d->image.isValid()) return; m_d->imageToDocument = QTransform::fromScale(1 / m_d->image->xRes(), 1 / m_d->image->yRes()); qreal zoomX, zoomY; zoom(&zoomX, &zoomY); m_d->documentToFlake = QTransform::fromScale(zoomX, zoomY); // Make new coordinate system not go to negative values QSizeF flakeSize = imageSizeInFlakePixels(); QPointF shift = -m_d->postprocessingTransform.mapRect(QRectF(QPointF(0,0), flakeSize)).topLeft(); m_d->flakeToPostprocessedFlake = m_d->postprocessingTransform * QTransform::fromTranslate(shift.x(), shift.y()); m_d->postprocessedFlakeToWidget = QTransform::fromTranslate(-m_d->documentOffset.x() + m_d->documentOrigin.x(), -m_d->documentOffset.y() + m_d->documentOrigin.y()); QRectF irect = imageRectInWidgetPixels(); QRectF wrect = QRectF(QPoint(0,0), m_d->canvasWidgetSize); QRectF rrect = irect & wrect; QTransform reversedTransform = flakeToWidgetTransform().inverted(); QRectF canvasBounds = reversedTransform.mapRect(rrect); QPointF offset = canvasBounds.topLeft(); m_d->widgetToViewport = reversedTransform * QTransform::fromTranslate(-offset.x(), -offset.y()); // qDebug() << "***********"; // qDebug() << ppVar(m_d->flakeToPostprocessedFlake); // qDebug() << ppVar(m_d->postprocessedFlakeToWidget); // qDebug() << ppVar(m_d->widgetToViewport); // qDebug() << ppVar(documentOrigin()); // qDebug() << ppVar(irect) << ppVar(wrect) << ppVar(rrect); // qDebug() << ppVar(canvasBounds); // qDebug() << ppVar(m_d->widgetToViewport.mapRect(irect)); } KisCoordinatesConverter::KisCoordinatesConverter() : m_d(new Private) { } KisCoordinatesConverter::~KisCoordinatesConverter() { delete m_d; } void KisCoordinatesConverter::setCanvasWidgetSize(QSize size) { m_d->canvasWidgetSize = size; recalculateTransformations(); } void KisCoordinatesConverter::setImage(KisImageWSP image) { m_d->image = image; recalculateTransformations(); } void KisCoordinatesConverter::setDocumentOrigin(const QPoint &origin) { m_d->documentOrigin = origin; recalculateTransformations(); } void KisCoordinatesConverter::setDocumentOffset(const QPoint &offset) { m_d->documentOffset = offset; recalculateTransformations(); } QPoint KisCoordinatesConverter::documentOrigin() const { - return m_d->documentOrigin; + return QPoint(int(m_d->documentOrigin.x()), int(m_d->documentOrigin.y())); } QPoint KisCoordinatesConverter::documentOffset() const { - return m_d->documentOffset; + return QPoint(int(m_d->documentOffset.x()), int(m_d->documentOffset.y())); } void KisCoordinatesConverter::setZoom(qreal zoom) { KoZoomHandler::setZoom(zoom); recalculateTransformations(); } void KisCoordinatesConverter::rotate(qreal angle) { - m_d->postprocessingTransform.rotate(angle); + QTransform rot; + rot.rotate(angle); + + QPointF center = widgetCenterPoint(); + + m_d->postprocessingTransform *= QTransform::fromTranslate(-center.x(),-center.y()); + m_d->postprocessingTransform *= rot; + m_d->postprocessingTransform *= QTransform::fromTranslate(center.x(), center.y()); recalculateTransformations(); } void KisCoordinatesConverter::mirror(bool mirrorXAxis, bool mirrorYAxis) { qreal scaleX = (m_d->isYAxisMirrored ^ mirrorYAxis) ? -1.0 : 1.0; qreal scaleY = (m_d->isXAxisMirrored ^ mirrorXAxis) ? -1.0 : 1.0; m_d->postprocessingTransform.scale(scaleX, scaleY); m_d->isXAxisMirrored = mirrorXAxis; m_d->isYAxisMirrored = mirrorYAxis; recalculateTransformations(); } void KisCoordinatesConverter::resetTransformations() { m_d->postprocessingTransform.reset(); recalculateTransformations(); } QTransform KisCoordinatesConverter::imageToWidgetTransform() const{ return m_d->imageToDocument * m_d->documentToFlake * m_d->flakeToPostprocessedFlake * m_d->postprocessedFlakeToWidget; } QTransform KisCoordinatesConverter::imageToDocumentTransform() const { return m_d->imageToDocument; } QTransform KisCoordinatesConverter::flakeToWidgetTransform() const { return m_d->flakeToPostprocessedFlake * m_d->postprocessedFlakeToWidget; } QTransform KisCoordinatesConverter::documentToWidgetTransform() const { return m_d->documentToFlake * m_d->flakeToPostprocessedFlake * m_d->postprocessedFlakeToWidget; } QTransform KisCoordinatesConverter::viewportToWidgetTransform() const { return m_d->widgetToViewport.inverted(); } QTransform KisCoordinatesConverter::imageToViewportTransform() const { return m_d->imageToDocument * m_d->documentToFlake * m_d->flakeToPostprocessedFlake * m_d->postprocessedFlakeToWidget * m_d->widgetToViewport; } void KisCoordinatesConverter::getQPainterCheckersInfo(QTransform *transform, QPointF *brushOrigin, QPolygonF *polygon) const { KisConfig cfg; if (cfg.scrollCheckers()) { *transform = viewportToWidgetTransform(); *polygon = imageRectInViewportPixels(); *brushOrigin = imageToViewport(QPointF(0,0)); } else { *transform = QTransform(); *polygon = viewportToWidgetTransform().map(imageRectInViewportPixels()); *brushOrigin = QPoint(0,0); } } void KisCoordinatesConverter::getOpenGLCheckersInfo(QTransform *textureTransform, QTransform *modelTransform, QRectF *textureRect, QRectF *modelRect) const { KisConfig cfg; QRectF viewportRect = imageRectInViewportPixels(); if(cfg.scrollCheckers()) { *textureTransform = QTransform(); *textureRect = QRectF(0, 0, viewportRect.width(),viewportRect.height()); } else { *textureTransform = m_d->widgetToViewport.inverted(); *textureRect = viewportRect; } *modelTransform = viewportToWidgetTransform(); *modelRect = viewportRect; } QPointF KisCoordinatesConverter::imageCenterInWidgetPixel() const { if(!m_d->image.isValid()) return QPointF(); QPolygonF poly = imageToWidget(QPolygon(m_d->image->bounds())); return (poly[0] + poly[1] + poly[2] + poly[3]) / 4.0; } // these functions return a bounding rect if the canvas is rotated QRectF KisCoordinatesConverter::imageRectInWidgetPixels() const { if(!m_d->image.isValid()) return QRectF(); return imageToWidget(m_d->image->bounds()); } QRectF KisCoordinatesConverter::imageRectInViewportPixels() const { if(!m_d->image.isValid()) return QRectF(); return imageToViewport(m_d->image->bounds()); } QSizeF KisCoordinatesConverter::imageSizeInFlakePixels() const { if(!m_d->image.isValid()) return QSizeF(); qreal scaleX, scaleY; imageScale(&scaleX, &scaleY); QSize imageSize = m_d->image->size(); return QSizeF(imageSize.width() * scaleX, imageSize.height() * scaleY); } QRectF KisCoordinatesConverter::widgetRectInFlakePixels() const { return widgetToFlake(QRectF(QPoint(0,0), m_d->canvasWidgetSize)); } QPoint KisCoordinatesConverter::shiftFromFlakeCenterPoint(const QPointF &pt) const { QPointF newWidgetCenter = flakeToWidgetTransform().map(pt); QPointF oldWidgetCenter = QPointF(m_d->canvasWidgetSize.width() / 2, m_d->canvasWidgetSize.height() / 2); return (newWidgetCenter - oldWidgetCenter).toPoint(); } QPointF KisCoordinatesConverter::flakeCenterPoint() const { QRectF widgetRect = widgetRectInFlakePixels(); return QPointF(widgetRect.left() + widgetRect.width() / 2, widgetRect.top() + widgetRect.height() / 2); } +QPointF KisCoordinatesConverter::widgetCenterPoint() const +{ + return QPointF(m_d->canvasWidgetSize.width() / 2.0, m_d->canvasWidgetSize.height() / 2.0); +} + void KisCoordinatesConverter::imageScale(qreal *scaleX, qreal *scaleY) const { // get the x and y zoom level of the canvas qreal zoomX, zoomY; zoom(&zoomX, &zoomY); // Get the KisImage resolution qreal resX = m_d->image->xRes(); qreal resY = m_d->image->yRes(); // Compute the scale factors *scaleX = zoomX / resX; *scaleY = zoomY / resY; } diff --git a/krita/ui/canvas/kis_coordinates_converter.h b/krita/ui/canvas/kis_coordinates_converter.h index 10204b5c80..376155b737 100644 --- a/krita/ui/canvas/kis_coordinates_converter.h +++ b/krita/ui/canvas/kis_coordinates_converter.h @@ -1,134 +1,135 @@ /* * Copyright (c) 2010 Dmitry Kazakov * Copyright (c) 2011 Silvio Heinrich * * 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_COORDINATES_CONVERTER_H #define KIS_COORDINATES_CONVERTER_H #include #include #include "krita_export.h" #include "kis_types.h" namespace _Private { template struct Traits { typedef T Result; static T map(const QTransform& transform, const T& obj) { return transform.map(obj); } }; template<> struct Traits { typedef QRectF Result; static QRectF map(const QTransform& transform, const QRectF& rc) { return transform.mapRect(rc); } }; template<> struct Traits: public Traits { }; template<> struct Traits: public Traits { }; template<> struct Traits: public Traits { }; template<> struct Traits: public Traits { }; } class KRITAUI_EXPORT KisCoordinatesConverter: public KoZoomHandler { public: KisCoordinatesConverter(); ~KisCoordinatesConverter(); void setCanvasWidgetSize(QSize size); void setImage(KisImageWSP image); void setDocumentOrigin(const QPoint &origin); void setDocumentOffset(const QPoint &offset); QPoint documentOrigin() const; QPoint documentOffset() const; void rotate(qreal angle); void mirror(bool mirrorXAxis, bool mirrorYAxis); void resetTransformations(); virtual void setZoom(qreal zoom); template typename _Private::Traits::Result imageToViewport(const T& obj) const { return _Private::Traits::map(imageToViewportTransform(), obj); } template typename _Private::Traits::Result viewportToImage(const T& obj) const { return _Private::Traits::map(imageToViewportTransform().inverted(), obj); } template typename _Private::Traits::Result flakeToWidget(const T& obj) const { return _Private::Traits::map(flakeToWidgetTransform(), obj); } template typename _Private::Traits::Result widgetToFlake(const T& obj) const { return _Private::Traits::map(flakeToWidgetTransform().inverted(), obj); } template typename _Private::Traits::Result widgetToViewport(const T& obj) const { return _Private::Traits::map(viewportToWidgetTransform().inverted(), obj); } template typename _Private::Traits::Result viewportToWidget(const T& obj) const { return _Private::Traits::map(viewportToWidgetTransform(), obj); } template typename _Private::Traits::Result documentToWidget(const T& obj) const { return _Private::Traits::map(documentToWidgetTransform(), obj); } template typename _Private::Traits::Result widgetToDocument(const T& obj) const { return _Private::Traits::map(documentToWidgetTransform().inverted(), obj); } template typename _Private::Traits::Result imageToDocument(const T& obj) const { return _Private::Traits::map(imageToDocumentTransform(), obj); } template typename _Private::Traits::Result documentToImage(const T& obj) const { return _Private::Traits::map(imageToDocumentTransform().inverted(), obj); } template typename _Private::Traits::Result imageToWidget(const T& obj) const { return _Private::Traits::map(imageToWidgetTransform(), obj); } template typename _Private::Traits::Result widgetToImage(const T& obj) const { return _Private::Traits::map(imageToWidgetTransform().inverted(), obj); } QTransform imageToWidgetTransform() const; QTransform imageToDocumentTransform() const; QTransform imageToViewportTransform() const; QTransform viewportToWidgetTransform() const; QTransform flakeToWidgetTransform() const; QTransform documentToWidgetTransform() const; void getQPainterCheckersInfo(QTransform *transform, QPointF *brushOrigin, QPolygonF *poligon) const; void getOpenGLCheckersInfo(QTransform *textureTransform, QTransform *modelTransform, QRectF *textureRect, QRectF *modelRect) const; QPointF imageCenterInWidgetPixel() const; QRectF imageRectInWidgetPixels() const; QRectF imageRectInViewportPixels() const; QSizeF imageSizeInFlakePixels() const; QRectF widgetRectInFlakePixels() const; QPoint shiftFromFlakeCenterPoint(const QPointF &pt) const; QPointF flakeCenterPoint() const; + QPointF widgetCenterPoint() const; void imageScale(qreal *scaleX, qreal *scaleY) const; private: void recalculateTransformations() const; private: struct Private; Private * const m_d; }; #endif /* KIS_COORDINATES_CONVERTER_H */