+/*\r
+ * gdiplusmatrix.h\r
+ *\r
+ * GDI+ Matrix class\r
+ *\r
+ * This file is part of the w32api package.\r
+ *\r
+ * Contributors:\r
+ * Created by Markus Koenig <markus@stber-koenig.de>\r
+ *\r
+ * THIS SOFTWARE IS NOT COPYRIGHTED\r
+ *\r
+ * This source code is offered for use in the public domain. You may\r
+ * use, modify or distribute it freely.\r
+ *\r
+ * This code is distributed in the hope that it will be useful but\r
+ * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY\r
+ * DISCLAIMED. This includes but is not limited to warranties of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\r
+ *\r
+ */\r
+\r
+#ifndef __GDIPLUS_MATRIX_H\r
+#define __GDIPLUS_MATRIX_H\r
+#if __GNUC__ >=3\r
+#pragma GCC system_header\r
+#endif\r
+\r
+#ifndef __cplusplus\r
+#error "A C++ compiler is required to include gdiplusmatrix.h."\r
+#endif\r
+\r
+#define GDIP_MATRIX_PI \\r
+ 3.1415926535897932384626433832795028841971693993751058209749445923078164\r
+\r
+class Matrix: public GdiplusBase\r
+{\r
+ friend class Graphics;\r
+ friend class GraphicsPath;\r
+ friend class LinearGradientBrush;\r
+ friend class PathGradientBrush;\r
+ friend class Pen;\r
+ friend class Region;\r
+ friend class TextureBrush;\r
+\r
+public:\r
+ Matrix(): nativeMatrix(NULL), lastStatus(Ok)\r
+ {\r
+ lastStatus = DllExports::GdipCreateMatrix(&nativeMatrix);\r
+ }\r
+ Matrix(REAL m11, REAL m12, REAL m21, REAL m22, REAL dx, REAL dy):\r
+ nativeMatrix(NULL), lastStatus(Ok)\r
+ {\r
+ lastStatus = DllExports::GdipCreateMatrix2(\r
+ m11, m12, m21, m22, dx, dy,\r
+ &nativeMatrix);\r
+ }\r
+ Matrix(const RectF& rect, const PointF *dstplg):\r
+ nativeMatrix(NULL), lastStatus(Ok)\r
+ {\r
+ lastStatus = DllExports::GdipCreateMatrix3(\r
+ &rect, dstplg, &nativeMatrix);\r
+ }\r
+ Matrix(const Rect& rect, const Point *dstplg):\r
+ nativeMatrix(NULL), lastStatus(Ok)\r
+ {\r
+ lastStatus = DllExports::GdipCreateMatrix3I(\r
+ &rect, dstplg, &nativeMatrix);\r
+ }\r
+ ~Matrix()\r
+ {\r
+ DllExports::GdipDeleteMatrix(nativeMatrix);\r
+ }\r
+ Matrix* Clone() const\r
+ {\r
+ GpMatrix *cloneMatrix = NULL;\r
+ Status status = updateStatus(DllExports::GdipCloneMatrix(\r
+ nativeMatrix, &cloneMatrix));\r
+ if (status == Ok) {\r
+ Matrix *result = new Matrix(cloneMatrix, lastStatus);\r
+ if (!result) {\r
+ DllExports::GdipDeleteMatrix(cloneMatrix);\r
+ lastStatus = OutOfMemory;\r
+ }\r
+ return result;\r
+ } else {\r
+ return NULL;\r
+ }\r
+ }\r
+\r
+ BOOL Equals(const Matrix *matrix) const\r
+ {\r
+ BOOL result;\r
+ updateStatus(DllExports::GdipIsMatrixEqual(\r
+ nativeMatrix,\r
+ matrix ? matrix->nativeMatrix : NULL, &result));\r
+ return result;\r
+ }\r
+ Status GetElements(REAL *m) const\r
+ {\r
+ return updateStatus(DllExports::GdipGetMatrixElements(\r
+ nativeMatrix, m));\r
+ }\r
+ Status GetLastStatus() const\r
+ {\r
+ Status result = lastStatus;\r
+ lastStatus = Ok;\r
+ return result;\r
+ }\r
+ Status Invert()\r
+ {\r
+ return updateStatus(DllExports::GdipInvertMatrix(nativeMatrix));\r
+ }\r
+ BOOL IsIdentity() const\r
+ {\r
+ BOOL result;\r
+ updateStatus(DllExports::GdipIsMatrixIdentity(\r
+ nativeMatrix, &result));\r
+ return result;\r
+ }\r
+ BOOL IsInvertible() const\r
+ {\r
+ BOOL result;\r
+ updateStatus(DllExports::GdipIsMatrixInvertible(\r
+ nativeMatrix, &result));\r
+ return result;\r
+ }\r
+ Status Multiply(const Matrix *matrix,\r
+ MatrixOrder order = MatrixOrderPrepend)\r
+ {\r
+ return updateStatus(DllExports::GdipMultiplyMatrix(\r
+ nativeMatrix,\r
+ matrix ? matrix->nativeMatrix : NULL, order));\r
+ }\r
+ REAL OffsetX() const\r
+ {\r
+ REAL m[6];\r
+ updateStatus(DllExports::GdipGetMatrixElements(nativeMatrix, m));\r
+ return m[4];\r
+ }\r
+ REAL OffsetY() const\r
+ {\r
+ REAL m[6];\r
+ updateStatus(DllExports::GdipGetMatrixElements(nativeMatrix, m));\r
+ return m[5];\r
+ }\r
+ Status Reset()\r
+ {\r
+ return updateStatus(DllExports::GdipSetMatrixElements(\r
+ nativeMatrix,\r
+ 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f));\r
+ }\r
+ Status Rotate(REAL angle, MatrixOrder order = MatrixOrderPrepend)\r
+ {\r
+ return updateStatus(DllExports::GdipRotateMatrix(\r
+ nativeMatrix, angle, order));\r
+ }\r
+ Status RotateAt(REAL angle, const PointF& center,\r
+ MatrixOrder order = MatrixOrderPrepend)\r
+ {\r
+ REAL angleRadian = angle * GDIP_MATRIX_PI / 180.0f;\r
+ REAL cosAngle = ::cos(angleRadian);\r
+ REAL sinAngle = ::sin(angleRadian);\r
+ REAL x = center.X;\r
+ REAL y = center.Y;\r
+\r
+ Matrix matrix2(cosAngle, sinAngle, -sinAngle, cosAngle,\r
+ x * (1.0f-cosAngle) + y * sinAngle,\r
+ -x * sinAngle + y * (1.0f-cosAngle));\r
+ Status status = matrix2.GetLastStatus();\r
+ if (status == Ok) {\r
+ return Multiply(&matrix2, order);\r
+ } else {\r
+ return lastStatus = status;\r
+ }\r
+ }\r
+ Status Scale(REAL scaleX, REAL scaleY,\r
+ MatrixOrder order = MatrixOrderPrepend)\r
+ {\r
+ return updateStatus(DllExports::GdipScaleMatrix(\r
+ nativeMatrix, scaleX, scaleY, order));\r
+ }\r
+ Status SetElements(REAL m11, REAL m12, REAL m21, REAL m22,\r
+ REAL dx, REAL dy)\r
+ {\r
+ return updateStatus(DllExports::GdipSetMatrixElements(\r
+ nativeMatrix, m11, m12, m21, m22, dx, dy));\r
+ }\r
+ Status Shear(REAL shearX, REAL shearY,\r
+ MatrixOrder order = MatrixOrderPrepend)\r
+ {\r
+ return updateStatus(DllExports::GdipShearMatrix(\r
+ nativeMatrix, shearX, shearY, order));\r
+ }\r
+ Status TransformPoints(PointF *pts, INT count = 1) const\r
+ {\r
+ return updateStatus(DllExports::GdipTransformMatrixPoints(\r
+ nativeMatrix, pts, count));\r
+ }\r
+ Status TransformPoints(Point *pts, INT count = 1) const\r
+ {\r
+ return updateStatus(DllExports::GdipTransformMatrixPointsI(\r
+ nativeMatrix, pts, count));\r
+ }\r
+ Status TransformVectors(PointF *pts, INT count = 1) const\r
+ {\r
+ return updateStatus(DllExports::GdipVectorTransformMatrixPoints(\r
+ nativeMatrix, pts, count));\r
+ }\r
+ Status TransformVectors(Point *pts, INT count = 1) const\r
+ {\r
+ return updateStatus(DllExports::GdipVectorTransformMatrixPointsI(\r
+ nativeMatrix, pts, count));\r
+ }\r
+ Status Translate(REAL offsetX, REAL offsetY,\r
+ MatrixOrder order = MatrixOrderPrepend)\r
+ {\r
+ return updateStatus(DllExports::GdipTranslateMatrix(\r
+ nativeMatrix, offsetX, offsetY, order));\r
+ }\r
+\r
+private:\r
+ Matrix(GpMatrix *matrix, Status status):\r
+ nativeMatrix(matrix), lastStatus(status) {}\r
+ Matrix(const Matrix&);\r
+ Matrix& operator=(const Matrix&);\r
+\r
+ Status updateStatus(Status newStatus) const\r
+ {\r
+ if (newStatus != Ok) lastStatus = newStatus;\r
+ return newStatus;\r
+ }\r
+\r
+ GpMatrix *nativeMatrix;\r
+ mutable Status lastStatus;\r
+};\r
+\r
+#undef GDIP_MATRIX_PI\r
+\r
+#endif /* __GDIPLUS_MATRIX_H */\r