Krita Source Code Documentation
Loading...
Searching...
No Matches
KisCanvasNavigationActionStrategy.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2026 Dmitry Kazakov <dimula73@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
8
9#include <kis_algebra_2d.h>
10
11namespace
12{
13qreal angleForSnapping(qreal angle)
14{
15 if (angle < 0) {
16 return std::fmod(angle - 2, 45) + 2;
17 } else {
18 return std::fmod(angle + 2, 45) - 2;
19 }
20}
21} // namespace
22
23qreal KisCanvasNavigationActionStrategy::canvasRotationAngleContinuous(qreal currentRelativeRotation, qreal currectCanvasRotation, SnappedRotationData &data)
24{
25 if (!data.previousAngle) {
26 data.previousAngle = currentRelativeRotation;
27 return 0;
28 }
29 qreal rotationAngle = (180 / M_PI) * (currentRelativeRotation - data.previousAngle);
30 data.previousAngle = currentRelativeRotation;
31
32 const qreal canvasAnglePostRotation = currectCanvasRotation + rotationAngle;
33 const qreal snapDelta = angleForSnapping(canvasAnglePostRotation);
34 // we snap the canvas to an angle that is a multiple of 45
35 if (abs(snapDelta) <= 2 && abs(data.accumRotationAngle) <= 2) {
36 // accumulate the relative angle of finger from the point when we started snapping
37 data.accumRotationAngle += rotationAngle;
38 rotationAngle = rotationAngle - snapDelta;
39 } else {
40 // snap the canvas out using the accumulated angle
41 rotationAngle += data.accumRotationAngle;
42 data.accumRotationAngle = 0;
43 }
44
45 return rotationAngle;
46}
47
49{
50 if (!data.initialReferenceAngle) {
51 data.initialReferenceAngle = currentRelativeRotation;
52 return 0;
53 }
54 qreal rotationAngle = 0;
55 const qreal relativeAngle = (180 / M_PI) * (currentRelativeRotation - data.initialReferenceAngle);
56 const qreal rotationThreshold = 15;
57
58 // if the canvas is moved in either direction with an angle greater than the threshold, we rotate the canvas in
59 // that direction by 15°.
60 if (std::abs(relativeAngle) >= rotationThreshold && std::abs(relativeAngle) <= (360 - rotationThreshold)) {
61 // set reference as currentAngle to check if we go beyond the threshold next time
62 data.initialReferenceAngle = currentRelativeRotation;
63
64 if (std::abs(relativeAngle) <= 180) {
65 rotationAngle = KisAlgebra2D::copysign(15.0, relativeAngle);
66 } else {
67 // if we're over 180, it means the canvas has to be rotated in the opposite direction of the current
68 // angle. E.g if the relative angle is +341° then we move the canvas by -15° (because the actual effect
69 // is 341 - 360 = -19° on the original theta).
70 rotationAngle = KisAlgebra2D::copysign(15.0, -relativeAngle);
71 }
72 }
73 return rotationAngle;
74}
75
77 : m_flags(flags)
78{
79}
80
81KisCanvasNavigationActionStrategy::Flags KisCanvasNavigationActionStrategy::flags() const
82{
83 return m_flags;
84}
static qreal canvasRotationAngleContinuous(qreal currentRotationOffset, qreal currectCanvasRotation, SnappedRotationData &data)
static qreal canvasRotationAngleDescrete(qreal currentRotationOffset, SnappedRotationData &data)
#define M_PI
Definition kis_global.h:111
T copysign(T x, T y)