1 /** 2 * @file gdiplusmatrix.h 3 * Copyright 2012, 2013 MinGW.org project 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 * DEALINGS IN THE SOFTWARE. 23 */ 24 /* Created by Markus Koenig <markus@stber-koenig.de> */ 25 #ifndef __GDIPLUS_MATRIX_H 26 #define __GDIPLUS_MATRIX_H 27 #pragma GCC system_header 28 #include <_mingw.h> 29 30 /* 31 * GDI+ Matrix class 32 */ 33 34 #ifndef __cplusplus 35 #error "A C++ compiler is required to include gdiplusmatrix.h." 36 #endif 37 38 #define GDIP_MATRIX_PI \ 39 3.1415926535897932384626433832795028841971693993751058209749445923078164 40 41 class Matrix: public GdiplusBase 42 { 43 friend class Graphics; 44 friend class GraphicsPath; 45 friend class LinearGradientBrush; 46 friend class PathGradientBrush; 47 friend class Pen; 48 friend class Region; 49 friend class TextureBrush; 50 51 public: Matrix()52 Matrix(): nativeMatrix(NULL), lastStatus(Ok) 53 { 54 lastStatus = DllExports::GdipCreateMatrix(&nativeMatrix); 55 } Matrix(REAL m11,REAL m12,REAL m21,REAL m22,REAL dx,REAL dy)56 Matrix(REAL m11, REAL m12, REAL m21, REAL m22, REAL dx, REAL dy): 57 nativeMatrix(NULL), lastStatus(Ok) 58 { 59 lastStatus = DllExports::GdipCreateMatrix2( 60 m11, m12, m21, m22, dx, dy, 61 &nativeMatrix); 62 } Matrix(const RectF & rect,const PointF * dstplg)63 Matrix(const RectF& rect, const PointF *dstplg): 64 nativeMatrix(NULL), lastStatus(Ok) 65 { 66 lastStatus = DllExports::GdipCreateMatrix3( 67 &rect, dstplg, &nativeMatrix); 68 } Matrix(const Rect & rect,const Point * dstplg)69 Matrix(const Rect& rect, const Point *dstplg): 70 nativeMatrix(NULL), lastStatus(Ok) 71 { 72 lastStatus = DllExports::GdipCreateMatrix3I( 73 &rect, dstplg, &nativeMatrix); 74 } ~Matrix()75 ~Matrix() 76 { 77 DllExports::GdipDeleteMatrix(nativeMatrix); 78 } Clone()79 Matrix* Clone() const 80 { 81 GpMatrix *cloneMatrix = NULL; 82 Status status = updateStatus(DllExports::GdipCloneMatrix( 83 nativeMatrix, &cloneMatrix)); 84 if (status == Ok) { 85 Matrix *result = new Matrix(cloneMatrix, lastStatus); 86 if (!result) { 87 DllExports::GdipDeleteMatrix(cloneMatrix); 88 lastStatus = OutOfMemory; 89 } 90 return result; 91 } else { 92 return NULL; 93 } 94 } 95 Equals(const Matrix * matrix)96 BOOL Equals(const Matrix *matrix) const 97 { 98 BOOL result; 99 updateStatus(DllExports::GdipIsMatrixEqual( 100 nativeMatrix, 101 matrix ? matrix->nativeMatrix : NULL, &result)); 102 return result; 103 } GetElements(REAL * m)104 Status GetElements(REAL *m) const 105 { 106 return updateStatus(DllExports::GdipGetMatrixElements( 107 nativeMatrix, m)); 108 } GetLastStatus()109 Status GetLastStatus() const 110 { 111 Status result = lastStatus; 112 lastStatus = Ok; 113 return result; 114 } Invert()115 Status Invert() 116 { 117 return updateStatus(DllExports::GdipInvertMatrix(nativeMatrix)); 118 } IsIdentity()119 BOOL IsIdentity() const 120 { 121 BOOL result; 122 updateStatus(DllExports::GdipIsMatrixIdentity( 123 nativeMatrix, &result)); 124 return result; 125 } IsInvertible()126 BOOL IsInvertible() const 127 { 128 BOOL result; 129 updateStatus(DllExports::GdipIsMatrixInvertible( 130 nativeMatrix, &result)); 131 return result; 132 } 133 Status Multiply(const Matrix *matrix, 134 MatrixOrder order = MatrixOrderPrepend) 135 { 136 return updateStatus(DllExports::GdipMultiplyMatrix( 137 nativeMatrix, 138 matrix ? matrix->nativeMatrix : NULL, order)); 139 } OffsetX()140 REAL OffsetX() const 141 { 142 REAL m[6]; 143 updateStatus(DllExports::GdipGetMatrixElements(nativeMatrix, m)); 144 return m[4]; 145 } OffsetY()146 REAL OffsetY() const 147 { 148 REAL m[6]; 149 updateStatus(DllExports::GdipGetMatrixElements(nativeMatrix, m)); 150 return m[5]; 151 } Reset()152 Status Reset() 153 { 154 return updateStatus(DllExports::GdipSetMatrixElements( 155 nativeMatrix, 156 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f)); 157 } 158 Status Rotate(REAL angle, MatrixOrder order = MatrixOrderPrepend) 159 { 160 return updateStatus(DllExports::GdipRotateMatrix( 161 nativeMatrix, angle, order)); 162 } 163 Status RotateAt(REAL angle, const PointF& center, 164 MatrixOrder order = MatrixOrderPrepend) 165 { 166 REAL angleRadian = angle * GDIP_MATRIX_PI / 180.0f; 167 REAL cosAngle = ::cos(angleRadian); 168 REAL sinAngle = ::sin(angleRadian); 169 REAL x = center.X; 170 REAL y = center.Y; 171 172 Matrix matrix2(cosAngle, sinAngle, -sinAngle, cosAngle, 173 x * (1.0f-cosAngle) + y * sinAngle, 174 -x * sinAngle + y * (1.0f-cosAngle)); 175 Status status = matrix2.GetLastStatus(); 176 if (status == Ok) { 177 return Multiply(&matrix2, order); 178 } else { 179 return lastStatus = status; 180 } 181 } 182 Status Scale(REAL scaleX, REAL scaleY, 183 MatrixOrder order = MatrixOrderPrepend) 184 { 185 return updateStatus(DllExports::GdipScaleMatrix( 186 nativeMatrix, scaleX, scaleY, order)); 187 } SetElements(REAL m11,REAL m12,REAL m21,REAL m22,REAL dx,REAL dy)188 Status SetElements(REAL m11, REAL m12, REAL m21, REAL m22, 189 REAL dx, REAL dy) 190 { 191 return updateStatus(DllExports::GdipSetMatrixElements( 192 nativeMatrix, m11, m12, m21, m22, dx, dy)); 193 } 194 Status Shear(REAL shearX, REAL shearY, 195 MatrixOrder order = MatrixOrderPrepend) 196 { 197 return updateStatus(DllExports::GdipShearMatrix( 198 nativeMatrix, shearX, shearY, order)); 199 } 200 Status TransformPoints(PointF *pts, INT count = 1) const 201 { 202 return updateStatus(DllExports::GdipTransformMatrixPoints( 203 nativeMatrix, pts, count)); 204 } 205 Status TransformPoints(Point *pts, INT count = 1) const 206 { 207 return updateStatus(DllExports::GdipTransformMatrixPointsI( 208 nativeMatrix, pts, count)); 209 } 210 Status TransformVectors(PointF *pts, INT count = 1) const 211 { 212 return updateStatus(DllExports::GdipVectorTransformMatrixPoints( 213 nativeMatrix, pts, count)); 214 } 215 Status TransformVectors(Point *pts, INT count = 1) const 216 { 217 return updateStatus(DllExports::GdipVectorTransformMatrixPointsI( 218 nativeMatrix, pts, count)); 219 } 220 Status Translate(REAL offsetX, REAL offsetY, 221 MatrixOrder order = MatrixOrderPrepend) 222 { 223 return updateStatus(DllExports::GdipTranslateMatrix( 224 nativeMatrix, offsetX, offsetY, order)); 225 } 226 227 private: Matrix(GpMatrix * matrix,Status status)228 Matrix(GpMatrix *matrix, Status status): 229 nativeMatrix(matrix), lastStatus(status) {} 230 Matrix(const Matrix&); 231 Matrix& operator=(const Matrix&); 232 updateStatus(Status newStatus)233 Status updateStatus(Status newStatus) const 234 { 235 if (newStatus != Ok) lastStatus = newStatus; 236 return newStatus; 237 } 238 239 GpMatrix *nativeMatrix; 240 mutable Status lastStatus; 241 }; 242 243 #undef GDIP_MATRIX_PI 244 245 #endif /* __GDIPLUS_MATRIX_H */ 246