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 (at) 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: 47 Matrix(): nativeMatrix(NULL), lastStatus(Ok) 48 { 49 lastStatus = DllExports::GdipCreateMatrix(&nativeMatrix); 50 } 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 } 58 Matrix(const RectF& rect, const PointF *dstplg): 59 nativeMatrix(NULL), lastStatus(Ok) 60 { 61 lastStatus = DllExports::GdipCreateMatrix3( 62 &rect, dstplg, &nativeMatrix); 63 } 64 Matrix(const Rect& rect, const Point *dstplg): 65 nativeMatrix(NULL), lastStatus(Ok) 66 { 67 lastStatus = DllExports::GdipCreateMatrix3I( 68 &rect, dstplg, &nativeMatrix); 69 } 70 ~Matrix() 71 { 72 DllExports::GdipDeleteMatrix(nativeMatrix); 73 } 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 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 } 99 Status GetElements(REAL *m) const 100 { 101 return updateStatus(DllExports::GdipGetMatrixElements( 102 nativeMatrix, m)); 103 } 104 Status GetLastStatus() const 105 { 106 Status result = lastStatus; 107 lastStatus = Ok; 108 return result; 109 } 110 Status Invert() 111 { 112 return updateStatus(DllExports::GdipInvertMatrix(nativeMatrix)); 113 } 114 BOOL IsIdentity() const 115 { 116 BOOL result; 117 updateStatus(DllExports::GdipIsMatrixIdentity( 118 nativeMatrix, &result)); 119 return result; 120 } 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 } 135 REAL OffsetX() const 136 { 137 REAL m[6]; 138 updateStatus(DllExports::GdipGetMatrixElements(nativeMatrix, m)); 139 return m[4]; 140 } 141 REAL OffsetY() const 142 { 143 REAL m[6]; 144 updateStatus(DllExports::GdipGetMatrixElements(nativeMatrix, m)); 145 return m[5]; 146 } 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 } 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: 223 Matrix(GpMatrix *matrix, Status status): 224 nativeMatrix(matrix), lastStatus(status) {} 225 Matrix(const Matrix&); 226 Matrix& operator=(const Matrix&); 227 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