1 // This file is part of VSTGUI. It is subject to the license terms
2 // in the LICENSE file found in the top-level directory of this
3 // distribution and at http://github.com/steinbergmedia/vstgui/LICENSE
4
5 #ifndef __cgraphicstransform__
6 #define __cgraphicstransform__
7
8 #include "cpoint.h"
9 #include "crect.h"
10
11 #ifndef M_PI
12 #define M_PI 3.14159265358979323846264338327950288
13 #endif
14
15 namespace VSTGUI {
16
radians(double degrees)17 static inline double radians (double degrees) { return degrees * M_PI / 180; }
18
19 //-----------------------------------------------------------------------------
20 /// @brief Graphics Transform Matrix
21 /// @ingroup new_in_4_0
22 //-----------------------------------------------------------------------------
23 struct CGraphicsTransform
24 {
25 double m11 {1.};
26 double m12 {0.};
27 double m21 {0.};
28 double m22 {1.};
29 double dx {0.};
30 double dy {0.};
31
32 CGraphicsTransform () = default;
CGraphicsTransformCGraphicsTransform33 CGraphicsTransform (double _m11, double _m12, double _m21, double _m22, double _dx, double _dy)
34 : m11 (_m11), m12 (_m12), m21 (_m21), m22 (_m22), dx (_dx), dy (_dy)
35 {}
36
translateCGraphicsTransform37 CGraphicsTransform& translate (double x, double y)
38 {
39 *this = CGraphicsTransform (1, 0, 0, 1, x, y) * this;
40 return *this;
41 }
42
translateCGraphicsTransform43 CGraphicsTransform& translate (const CPoint& p)
44 {
45 return translate (p.x, p.y);
46 }
47
scaleCGraphicsTransform48 CGraphicsTransform& scale (double x, double y)
49 {
50 *this = CGraphicsTransform (x, 0., 0., y, 0., 0.) * this;
51 return *this;
52 }
53
scaleCGraphicsTransform54 CGraphicsTransform& scale (const CPoint& p)
55 {
56 return scale (p.x, p.y);
57 }
58
rotateCGraphicsTransform59 CGraphicsTransform& rotate (double angle)
60 {
61 angle = radians (angle);
62 *this = CGraphicsTransform (cos (angle), -sin (angle), sin (angle), cos (angle), 0, 0) * this;
63 return *this;
64 }
65
rotateCGraphicsTransform66 CGraphicsTransform& rotate (double angle, const CPoint& center)
67 {
68 return translate (-center.x, -center.y).rotate (angle).translate (center.x, center.y);
69 }
70
skewXCGraphicsTransform71 CGraphicsTransform& skewX (double angle)
72 {
73 *this = CGraphicsTransform (1, std::tan (radians (angle)), 0, 1, 0, 0) * *this;
74 return *this;
75 }
76
skewYCGraphicsTransform77 CGraphicsTransform& skewY (double angle)
78 {
79 *this = CGraphicsTransform (1, 0, std::tan (radians (angle)), 1, 0, 0) * *this;
80 return *this;
81 }
82
isInvariantCGraphicsTransform83 bool isInvariant () const
84 {
85 return *this == CGraphicsTransform ();
86 }
87
transformCGraphicsTransform88 void transform (CCoord& x, CCoord& y) const
89 {
90 CCoord x2 = m11*x + m12*y + dx;
91 CCoord y2 = m21*x + m22*y + dy;
92 x = x2;
93 y = y2;
94 }
95
transformCGraphicsTransform96 void transform (CCoord& left, CCoord& right, CCoord& top, CCoord& bottom) const
97 {
98 transform (left, top);
99 transform (right, bottom);
100 }
101
transformCGraphicsTransform102 CPoint& transform (CPoint& p) const
103 {
104 transform (p.x, p.y);
105 return p;
106 }
107
transformCGraphicsTransform108 CRect& transform (CRect& r) const
109 {
110 transform (r.left, r.right, r.top, r.bottom);
111 return r;
112 }
113
inverseCGraphicsTransform114 CGraphicsTransform inverse () const
115 {
116 CGraphicsTransform result;
117 const double denominator = m11 * m22 - m12 * m21;
118 if (denominator != 0)
119 {
120 result.m11 = m22 / denominator;
121 result.m12 = -m12 / denominator;
122 result.m21 = -m21 / denominator;
123 result.m22 = m11 / denominator;
124 result.dx = ((m12 * dy) - (m22 * dx)) / denominator;
125 result.dy = ((m21 * dx) - (m11 * dy)) / denominator;
126 }
127 return result;
128 }
129
130 CGraphicsTransform operator* (const CGraphicsTransform& t) const
131 {
132 CGraphicsTransform result;
133 result.m11 = (m11 * t.m11) + (m12 * t.m21);
134 result.m21 = (m21 * t.m11) + (m22 * t.m21);
135 result.dx = (m11 * t.dx) + (m12 * t.dy) + dx;
136 result.m12 = (m11 * t.m12) + (m12 * t.m22);
137 result.m22 = (m21 * t.m12) + (m22 * t.m22);
138 result.dy = (m21 * t.dx) + (m22 * t.dy) + dy;
139 return result;
140 }
141
142 CGraphicsTransform operator* (const CGraphicsTransform* t) const { return *this * *t; }
143
144 bool operator== (const CGraphicsTransform& t) const
145 {
146 return m11 == t.m11 && m12 == t.m12 && m21 == t.m21 && m22 == t.m22 && dx == t.dx && dy == t.dy;
147 }
148
149 bool operator!= (const CGraphicsTransform& t) const
150 {
151 return m11 != t.m11 || m12 != t.m12 || m21 != t.m21 || m22 != t.m22 || dx != t.dx || dy != t.dy;
152 }
153 };
154
155
156 }
157
158 #endif // __cgraphicstransform__
159