1/**************************************************************************\
2*
3* Copyright (c) 1998-2000, Microsoft Corp.  All Rights Reserved.
4*
5* Module Name:
6*
7*   GdiplusMatrix.h
8*
9* Abstract:
10*
11*   GDI+ Matrix class
12*
13\**************************************************************************/
14
15class Matrix : public GdiplusBase
16{
17public:
18    friend class Graphics;
19    friend class GraphicsPath;
20    friend class TextureBrush;
21    friend class LinearGradientBrush;
22    friend class PathGradientBrush;
23    friend class Pen;
24    friend class Region;
25
26    // Default constructor - set to identity matrix
27
28    Matrix()
29    {
30        GpMatrix *matrix = NULL;
31
32        lastResult = DllExports::GdipCreateMatrix(&matrix);
33
34        SetNativeMatrix(matrix);
35    }
36
37    Matrix(IN REAL m11,
38           IN REAL m12,
39           IN REAL m21,
40           IN REAL m22,
41           IN REAL dx,
42           IN REAL dy)
43    {
44        GpMatrix *matrix = NULL;
45
46        lastResult = DllExports::GdipCreateMatrix2(m11, m12, m21, m22,
47                                                      dx, dy, &matrix);
48
49        SetNativeMatrix(matrix);
50    }
51
52    Matrix(IN const RectF& rect,
53           IN const PointF* dstplg)
54    {
55        GpMatrix *matrix = NULL;
56
57        lastResult = DllExports::GdipCreateMatrix3(&rect,
58                                                   dstplg,
59                                                   &matrix);
60
61        SetNativeMatrix(matrix);
62    }
63
64    Matrix(IN const Rect& rect,
65           IN const Point* dstplg)
66    {
67        GpMatrix *matrix = NULL;
68
69        lastResult = DllExports::GdipCreateMatrix3I(&rect,
70                                                    dstplg,
71                                                    &matrix);
72
73        SetNativeMatrix(matrix);
74    }
75
76    ~Matrix()
77    {
78        DllExports::GdipDeleteMatrix(nativeMatrix);
79    }
80
81    Matrix *Clone() const
82    {
83        GpMatrix *cloneMatrix = NULL;
84
85        SetStatus(DllExports::GdipCloneMatrix(nativeMatrix,
86                                                  &cloneMatrix));
87
88        if (lastResult != Ok)
89            return NULL;
90
91        return new Matrix(cloneMatrix);
92    }
93
94    Status GetElements(OUT REAL *m) const
95    {
96        return SetStatus(DllExports::GdipGetMatrixElements(nativeMatrix, m));
97    }
98
99    Status SetElements(IN REAL m11,
100                       IN REAL m12,
101                       IN REAL m21,
102                       IN REAL m22,
103                       IN REAL dx,
104                       IN REAL dy)
105    {
106        return SetStatus(DllExports::GdipSetMatrixElements(nativeMatrix,
107                            m11, m12, m21, m22, dx, dy));
108    }
109
110    REAL OffsetX() const
111    {
112        REAL elements[6];
113
114        if (GetElements(&elements[0]) == Ok)
115            return elements[4];
116        else
117            return 0.0f;
118    }
119
120    REAL OffsetY() const
121    {
122       REAL elements[6];
123
124       if (GetElements(&elements[0]) == Ok)
125           return elements[5];
126       else
127           return 0.0f;
128    }
129
130    Status Reset()
131    {
132        // set identity matrix elements
133        return SetStatus(DllExports::GdipSetMatrixElements(nativeMatrix,
134                                             1.0, 0.0, 0.0, 1.0, 0.0, 0.0));
135    }
136
137    Status Multiply(IN const Matrix *matrix,
138                    IN MatrixOrder order = MatrixOrderPrepend)
139    {
140        return SetStatus(DllExports::GdipMultiplyMatrix(nativeMatrix,
141                                          matrix->nativeMatrix,
142                                          order));
143    }
144
145    Status Translate(IN REAL offsetX,
146                     IN REAL offsetY,
147                     IN MatrixOrder order = MatrixOrderPrepend)
148    {
149        return SetStatus(DllExports::GdipTranslateMatrix(nativeMatrix, offsetX, offsetY, order));
150    }
151
152    Status Scale(IN REAL scaleX,
153                 IN REAL scaleY,
154                 IN MatrixOrder order = MatrixOrderPrepend)
155    {
156        return SetStatus(DllExports::GdipScaleMatrix(nativeMatrix, scaleX, scaleY, order));
157    }
158
159    Status Rotate(IN REAL angle,
160                  IN MatrixOrder order = MatrixOrderPrepend)
161    {
162        return SetStatus(DllExports::GdipRotateMatrix(nativeMatrix, angle, order));
163    }
164
165    Status RotateAt(IN REAL angle,
166                    IN const PointF& center,
167                    IN MatrixOrder order = MatrixOrderPrepend)
168    {
169        if(order == MatrixOrderPrepend)
170        {
171            SetStatus(DllExports::GdipTranslateMatrix(nativeMatrix, center.X, center.Y, order));
172            SetStatus(DllExports::GdipRotateMatrix(nativeMatrix, angle, order));
173            return SetStatus(DllExports::GdipTranslateMatrix(nativeMatrix, - center.X, - center.Y, order));
174        }
175        else
176        {
177            SetStatus(DllExports::GdipTranslateMatrix(nativeMatrix, - center.X, - center.Y, order));
178            SetStatus(DllExports::GdipRotateMatrix(nativeMatrix, angle, order));
179            return SetStatus(DllExports::GdipTranslateMatrix(nativeMatrix, center.X, center.Y, order));
180        }
181    }
182
183    Status Shear(IN REAL shearX,
184                 IN REAL shearY,
185                 IN MatrixOrder order = MatrixOrderPrepend)
186    {
187        return SetStatus(DllExports::GdipShearMatrix(nativeMatrix, shearX, shearY, order));
188    }
189
190    Status Invert()
191    {
192        return SetStatus(DllExports::GdipInvertMatrix(nativeMatrix));
193    }
194
195    // float version
196    Status TransformPoints(IN OUT PointF* pts,
197                           IN INT count = 1) const
198    {
199        return SetStatus(DllExports::GdipTransformMatrixPoints(nativeMatrix, pts, count));
200    }
201
202    Status TransformPoints(IN OUT Point* pts,
203                           IN INT count = 1) const
204    {
205        return SetStatus(DllExports::GdipTransformMatrixPointsI(nativeMatrix,
206                                                                pts,
207                                                                count));
208    }
209
210    Status TransformVectors(IN OUT PointF* pts,
211                            IN INT count = 1) const
212    {
213        return SetStatus(DllExports::GdipVectorTransformMatrixPoints(nativeMatrix, pts, count));
214    }
215
216    Status TransformVectors(IN OUT Point* pts,
217                            IN INT count = 1) const
218    {
219       return SetStatus(DllExports::GdipVectorTransformMatrixPointsI(nativeMatrix,
220                                                                    pts,
221                                                                    count));
222    }
223
224    BOOL IsInvertible() const
225    {
226        BOOL result = FALSE;
227
228        SetStatus(DllExports::GdipIsMatrixInvertible(nativeMatrix, &result));
229
230        return result;
231    }
232
233    BOOL IsIdentity() const
234    {
235       BOOL result = FALSE;
236
237       SetStatus(DllExports::GdipIsMatrixIdentity(nativeMatrix, &result));
238
239       return result;
240    }
241
242    BOOL Equals(IN const Matrix *matrix) const
243    {
244       BOOL result = FALSE;
245
246       SetStatus(DllExports::GdipIsMatrixEqual(nativeMatrix,
247                                                 matrix->nativeMatrix, &result));
248
249       return result;
250    }
251
252    Status GetLastStatus() const
253    {
254        Status lastStatus = lastResult;
255        lastResult = Ok;
256
257        return lastStatus;
258    }
259
260protected:
261
262#ifdef DCR_USE_NEW_250932
263
264private:
265    Matrix(const Matrix &);
266    Matrix& operator=(const Matrix &);
267protected:
268
269#else
270
271    Matrix(const Matrix& matrix)
272    {
273        matrix;
274        SetStatus(NotImplemented);
275        SetNativeMatrix(NULL);
276    }
277
278    Matrix& operator=(const Matrix& matrix)
279    {
280        matrix;
281        SetStatus(NotImplemented);
282        return *this;
283    }
284
285#endif
286
287    Matrix(GpMatrix *nativeMatrix)
288    {
289        lastResult = Ok;
290        SetNativeMatrix(nativeMatrix);
291    }
292
293    VOID SetNativeMatrix(GpMatrix *nativeMatrix)
294    {
295        this->nativeMatrix = nativeMatrix;
296    }
297
298    Status SetStatus(Status status) const
299    {
300        if (status != Ok)
301            return (lastResult = status);
302        else
303            return status;
304    }
305
306protected:
307    GpMatrix *nativeMatrix;
308    mutable Status lastResult;
309};
310