• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * gdiplusmatrix.h
3  *
4  * GDI+ Matrix class
5  *
6  * This file is part of the w32api package.
7  *
8  * Contributors:
9  *   Created by Markus Koenig <markus@stber-koenig.de>
10  *
11  * THIS SOFTWARE IS NOT COPYRIGHTED
12  *
13  * This source code is offered for use in the public domain. You may
14  * use, modify or distribute it freely.
15  *
16  * This code is distributed in the hope that it will be useful but
17  * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
18  * DISCLAIMED. This includes but is not limited to warranties of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20  *
21  */
22 
23 #ifndef __GDIPLUS_MATRIX_H
24 #define __GDIPLUS_MATRIX_H
25 #if __GNUC__ >=3
26 #pragma GCC system_header
27 #endif
28 
29 #ifndef __cplusplus
30 #error "A C++ compiler is required to include gdiplusmatrix.h."
31 #endif
32 
33 #define GDIP_MATRIX_PI \
34 	3.1415926535897932384626433832795028841971693993751058209749445923078164
35 
36 class Matrix: public GdiplusBase
37 {
38 	friend class Graphics;
39 	friend class GraphicsPath;
40 	friend class LinearGradientBrush;
41 	friend class PathGradientBrush;
42 	friend class Pen;
43 	friend class Region;
44 	friend class TextureBrush;
45 
46 public:
Matrix()47 	Matrix(): nativeMatrix(NULL), lastStatus(Ok)
48 	{
49 		lastStatus = DllExports::GdipCreateMatrix(&nativeMatrix);
50 	}
Matrix(REAL m11,REAL m12,REAL m21,REAL m22,REAL dx,REAL dy)51 	Matrix(REAL m11, REAL m12, REAL m21, REAL m22, REAL dx, REAL dy):
52 			nativeMatrix(NULL), lastStatus(Ok)
53 	{
54 		lastStatus = DllExports::GdipCreateMatrix2(
55 				m11, m12, m21, m22, dx, dy,
56 				&nativeMatrix);
57 	}
Matrix(const RectF & rect,const PointF * dstplg)58 	Matrix(const RectF& rect, const PointF *dstplg):
59 			nativeMatrix(NULL), lastStatus(Ok)
60 	{
61 		lastStatus = DllExports::GdipCreateMatrix3(
62 				&rect, dstplg, &nativeMatrix);
63 	}
Matrix(const Rect & rect,const Point * dstplg)64 	Matrix(const Rect& rect, const Point *dstplg):
65 			nativeMatrix(NULL), lastStatus(Ok)
66 	{
67 		lastStatus = DllExports::GdipCreateMatrix3I(
68 				&rect, dstplg, &nativeMatrix);
69 	}
~Matrix()70 	~Matrix()
71 	{
72 		DllExports::GdipDeleteMatrix(nativeMatrix);
73 	}
Clone()74 	Matrix* Clone() const
75 	{
76 		GpMatrix *cloneMatrix = NULL;
77 		Status status = updateStatus(DllExports::GdipCloneMatrix(
78 				nativeMatrix, &cloneMatrix));
79 		if (status == Ok) {
80 			Matrix *result = new Matrix(cloneMatrix, lastStatus);
81 			if (!result) {
82 				DllExports::GdipDeleteMatrix(cloneMatrix);
83 				lastStatus = OutOfMemory;
84 			}
85 			return result;
86 		} else {
87 			return NULL;
88 		}
89 	}
90 
Equals(const Matrix * matrix)91 	BOOL Equals(const Matrix *matrix) const
92 	{
93 		BOOL result;
94 		updateStatus(DllExports::GdipIsMatrixEqual(
95 				nativeMatrix,
96 				matrix ? matrix->nativeMatrix : NULL, &result));
97 		return result;
98 	}
GetElements(REAL * m)99 	Status GetElements(REAL *m) const
100 	{
101 		return updateStatus(DllExports::GdipGetMatrixElements(
102 				nativeMatrix, m));
103 	}
GetLastStatus()104 	Status GetLastStatus() const
105 	{
106 		Status result = lastStatus;
107 		lastStatus = Ok;
108 		return result;
109 	}
Invert()110 	Status Invert()
111 	{
112 		return updateStatus(DllExports::GdipInvertMatrix(nativeMatrix));
113 	}
IsIdentity()114 	BOOL IsIdentity() const
115 	{
116 		BOOL result;
117 		updateStatus(DllExports::GdipIsMatrixIdentity(
118 				nativeMatrix, &result));
119 		return result;
120 	}
IsInvertible()121 	BOOL IsInvertible() const
122 	{
123 		BOOL result;
124 		updateStatus(DllExports::GdipIsMatrixInvertible(
125 				nativeMatrix, &result));
126 		return result;
127 	}
128 	Status Multiply(const Matrix *matrix,
129 			MatrixOrder order = MatrixOrderPrepend)
130 	{
131 		return updateStatus(DllExports::GdipMultiplyMatrix(
132 				nativeMatrix,
133 				matrix ? matrix->nativeMatrix : NULL, order));
134 	}
OffsetX()135 	REAL OffsetX() const
136 	{
137 		REAL m[6];
138 		updateStatus(DllExports::GdipGetMatrixElements(nativeMatrix, m));
139 		return m[4];
140 	}
OffsetY()141 	REAL OffsetY() const
142 	{
143 		REAL m[6];
144 		updateStatus(DllExports::GdipGetMatrixElements(nativeMatrix, m));
145 		return m[5];
146 	}
Reset()147 	Status Reset()
148 	{
149 		return updateStatus(DllExports::GdipSetMatrixElements(
150 				nativeMatrix,
151 				1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f));
152 	}
153 	Status Rotate(REAL angle, MatrixOrder order = MatrixOrderPrepend)
154 	{
155 		return updateStatus(DllExports::GdipRotateMatrix(
156 				nativeMatrix, angle, order));
157 	}
158 	Status RotateAt(REAL angle, const PointF& center,
159 			MatrixOrder order = MatrixOrderPrepend)
160 	{
161 		REAL angleRadian = angle * GDIP_MATRIX_PI / 180.0f;
162 		REAL cosAngle = ::cos(angleRadian);
163 		REAL sinAngle = ::sin(angleRadian);
164 		REAL x = center.X;
165 		REAL y = center.Y;
166 
167 		Matrix matrix2(cosAngle, sinAngle, -sinAngle, cosAngle,
168 				x * (1.0f-cosAngle) + y * sinAngle,
169 				-x * sinAngle + y * (1.0f-cosAngle));
170 		Status status = matrix2.GetLastStatus();
171 		if (status == Ok) {
172 			return Multiply(&matrix2, order);
173 		} else {
174 			return lastStatus = status;
175 		}
176 	}
177 	Status Scale(REAL scaleX, REAL scaleY,
178 			MatrixOrder order = MatrixOrderPrepend)
179 	{
180 		return updateStatus(DllExports::GdipScaleMatrix(
181 				nativeMatrix, scaleX, scaleY, order));
182 	}
SetElements(REAL m11,REAL m12,REAL m21,REAL m22,REAL dx,REAL dy)183 	Status SetElements(REAL m11, REAL m12, REAL m21, REAL m22,
184 			REAL dx, REAL dy)
185 	{
186 		return updateStatus(DllExports::GdipSetMatrixElements(
187 				nativeMatrix, m11, m12, m21, m22, dx, dy));
188 	}
189 	Status Shear(REAL shearX, REAL shearY,
190 			MatrixOrder order = MatrixOrderPrepend)
191 	{
192 		return updateStatus(DllExports::GdipShearMatrix(
193 				nativeMatrix, shearX, shearY, order));
194 	}
195 	Status TransformPoints(PointF *pts, INT count = 1) const
196 	{
197 		return updateStatus(DllExports::GdipTransformMatrixPoints(
198 				nativeMatrix, pts, count));
199 	}
200 	Status TransformPoints(Point *pts, INT count = 1) const
201 	{
202 		return updateStatus(DllExports::GdipTransformMatrixPointsI(
203 				nativeMatrix, pts, count));
204 	}
205 	Status TransformVectors(PointF *pts, INT count = 1) const
206 	{
207 		return updateStatus(DllExports::GdipVectorTransformMatrixPoints(
208 				nativeMatrix, pts, count));
209 	}
210 	Status TransformVectors(Point *pts, INT count = 1) const
211 	{
212 		return updateStatus(DllExports::GdipVectorTransformMatrixPointsI(
213 				nativeMatrix, pts, count));
214 	}
215 	Status Translate(REAL offsetX, REAL offsetY,
216 			MatrixOrder order = MatrixOrderPrepend)
217 	{
218 		return updateStatus(DllExports::GdipTranslateMatrix(
219 				nativeMatrix, offsetX, offsetY, order));
220 	}
221 
222 private:
Matrix(GpMatrix * matrix,Status status)223 	Matrix(GpMatrix *matrix, Status status):
224 		nativeMatrix(matrix), lastStatus(status) {}
225 	Matrix(const Matrix&);
226 	Matrix& operator=(const Matrix&);
227 
updateStatus(Status newStatus)228 	Status updateStatus(Status newStatus) const
229 	{
230 		if (newStatus != Ok) lastStatus = newStatus;
231 		return newStatus;
232 	}
233 
234 	GpMatrix *nativeMatrix;
235 	mutable Status lastStatus;
236 };
237 
238 #undef GDIP_MATRIX_PI
239 
240 #endif /* __GDIPLUS_MATRIX_H */
241