File indexing completed on 2025-02-23 04:08:58

0001 /*
0002  *  SPDX-FileCopyrightText: 2010 Dmitry Kazakov <dimula73@gmail.com>
0003  *  SPDX-FileCopyrightText: 2011 Silvio Heinrich <plassy@web.de>
0004  *
0005  *  SPDX-License-Identifier: GPL-2.0-or-later
0006  */
0007 
0008 #ifndef KIS_COORDINATES_CONVERTER_H
0009 #define KIS_COORDINATES_CONVERTER_H
0010 
0011 #include <QTransform>
0012 #include <KoZoomHandler.h>
0013 
0014 #include "kritaui_export.h"
0015 #include "kis_types.h"
0016 
0017 #define EPSILON 1e-6
0018 
0019 #define SCALE_LESS_THAN(scX, scY, value)                        \
0020     (scX < (value) - EPSILON && scY < (value) - EPSILON)
0021 #define SCALE_MORE_OR_EQUAL_TO(scX, scY, value)                 \
0022     (scX > (value) - EPSILON && scY > (value) - EPSILON)
0023 
0024 namespace _Private
0025 {
0026     template<class T> struct Traits
0027     {
0028         typedef T Result;
0029         static T map(const QTransform& transform, const T& obj)  { return transform.map(obj); }
0030     };
0031 
0032     template<> struct Traits<QRectF>
0033     {
0034         typedef QRectF Result;
0035         static QRectF map(const QTransform& transform, const QRectF& rc)  { return transform.mapRect(rc); }
0036     };
0037 
0038     template<> struct Traits<QRect>:    public Traits<QRectF>    { };
0039     template<> struct Traits<QPoint>:   public Traits<QPointF>   { };
0040     template<> struct Traits<QPolygon>: public Traits<QPolygonF> { };
0041     template<> struct Traits<QLine>:    public Traits<QLineF>    { };
0042 }
0043 
0044 class KRITAUI_EXPORT KisCoordinatesConverter: public KoZoomHandler
0045 {
0046 public:
0047     KisCoordinatesConverter();
0048     ~KisCoordinatesConverter() override;
0049 
0050     QSizeF getCanvasWidgetSize() const;
0051 
0052     void setCanvasWidgetSize(QSizeF size);
0053     void setDevicePixelRatio(qreal value);
0054     void setImage(KisImageWSP image);
0055     void setDocumentOffset(const QPointF &offset);
0056 
0057     qreal devicePixelRatio() const;
0058     QPoint documentOffset() const;
0059     qreal rotationAngle() const;
0060 
0061     // Use the begin/end interface to rotate the canvas in one transformation.
0062     // This method is more accurate and doesn't amplify numerical errors from very small angles.
0063     void beginRotation();
0064     void endRotation();
0065 
0066     void enableNatureGestureFlag();
0067 
0068     QPoint rotate(QPointF center, qreal angle);
0069     QPoint mirror(QPointF center, bool mirrorXAxis, bool mirrorYAxis);
0070     bool xAxisMirrored() const;
0071     bool yAxisMirrored() const;
0072     QPoint resetRotation(QPointF center);
0073 
0074     void setZoom(qreal zoom) override;
0075 
0076     /**
0077      * A composition of to scale methods: zoom level + image resolution
0078      */
0079     qreal effectiveZoom() const;
0080     qreal effectivePhysicalZoom() const;
0081 
0082     template<class T> typename _Private::Traits<T>::Result
0083     imageToViewport(const T& obj) const { return _Private::Traits<T>::map(imageToViewportTransform(), obj); }
0084     template<class T> typename _Private::Traits<T>::Result
0085     viewportToImage(const T& obj) const { return _Private::Traits<T>::map(imageToViewportTransform().inverted(), obj); }
0086 
0087     template<class T> typename _Private::Traits<T>::Result
0088     flakeToWidget(const T& obj) const { return _Private::Traits<T>::map(flakeToWidgetTransform(), obj); }
0089     template<class T> typename _Private::Traits<T>::Result
0090     widgetToFlake(const T& obj) const { return _Private::Traits<T>::map(flakeToWidgetTransform().inverted(), obj); }
0091 
0092     template<class T> typename _Private::Traits<T>::Result
0093     widgetToViewport(const T& obj) const { return _Private::Traits<T>::map(viewportToWidgetTransform().inverted(), obj); }
0094     template<class T> typename _Private::Traits<T>::Result
0095     viewportToWidget(const T& obj) const { return _Private::Traits<T>::map(viewportToWidgetTransform(), obj); }
0096 
0097     template<class T> typename _Private::Traits<T>::Result
0098     documentToWidget(const T& obj) const { return _Private::Traits<T>::map(documentToWidgetTransform(), obj); }
0099     template<class T> typename _Private::Traits<T>::Result
0100     widgetToDocument(const T& obj) const { return _Private::Traits<T>::map(documentToWidgetTransform().inverted(), obj); }
0101 
0102     template<class T> typename _Private::Traits<T>::Result
0103     imageToDocument(const T& obj) const { return _Private::Traits<T>::map(imageToDocumentTransform(), obj); }
0104     template<class T> typename _Private::Traits<T>::Result
0105     documentToImage(const T& obj) const { return _Private::Traits<T>::map(imageToDocumentTransform().inverted(), obj); }
0106 
0107     template<class T> typename _Private::Traits<T>::Result
0108     documentToFlake(const T& obj) const { return _Private::Traits<T>::map(documentToFlakeTransform(), obj); }
0109     template<class T> typename _Private::Traits<T>::Result
0110     flakeToDocument(const T& obj) const { return _Private::Traits<T>::map(documentToFlakeTransform().inverted(), obj); }
0111 
0112     template<class T> typename _Private::Traits<T>::Result
0113     imageToWidget(const T& obj) const { return _Private::Traits<T>::map(imageToWidgetTransform(), obj); }
0114     template<class T> typename _Private::Traits<T>::Result
0115     widgetToImage(const T& obj) const { return _Private::Traits<T>::map(imageToWidgetTransform().inverted(), obj); }
0116 
0117     QTransform imageToWidgetTransform() const;
0118     QTransform imageToDocumentTransform() const;
0119     QTransform documentToFlakeTransform() const;
0120     QTransform imageToViewportTransform() const;
0121     QTransform viewportToWidgetTransform() const;
0122     QTransform flakeToWidgetTransform() const;
0123     QTransform documentToWidgetTransform() const;
0124 
0125     void getQPainterCheckersInfo(QTransform *transform,
0126                                  QPointF *brushOrigin,
0127                                  QPolygonF *polygon,
0128                                  const bool scrollCheckers) const;
0129 
0130     void getOpenGLCheckersInfo(const QRectF &viewportRect,
0131                                QTransform *textureTransform,
0132                                QTransform *modelTransform,
0133                                QRectF *textureRect,
0134                                QRectF *modelRect,
0135                                const bool scrollCheckers) const;
0136 
0137     QPointF imageCenterInWidgetPixel() const;
0138     QRectF imageRectInWidgetPixels() const;
0139     QRectF imageRectInViewportPixels() const;
0140     QSizeF imageSizeInFlakePixels() const;
0141     QRectF widgetRectInFlakePixels() const;
0142     QRectF widgetRectInImagePixels() const;
0143     QRect imageRectInImagePixels() const;
0144     QRectF imageRectInDocumentPixels() const;
0145 
0146     QPointF flakeCenterPoint() const;
0147     QPointF widgetCenterPoint() const;
0148 
0149     void imageScale(qreal *scaleX, qreal *scaleY) const;
0150     void imagePhysicalScale(qreal *scaleX, qreal *scaleY) const;
0151 
0152     QPointF snapToDevicePixel(const QPointF &point) const;
0153 
0154 public:
0155     // overrides from KoViewConverter
0156     QTransform viewToWidget() const override;
0157     QTransform widgetToView() const override;
0158 
0159 private:
0160     friend class KisZoomAndPanTest;
0161 
0162     QPointF centeringCorrection() const;
0163     void correctOffsetToTransformation();
0164     void correctTransformationToOffset();
0165     void recalculateTransformations();
0166 
0167 private:
0168     struct Private;
0169     Private * const m_d;
0170 };
0171 
0172 #endif /* KIS_COORDINATES_CONVERTER_H */