Home | History | Annotate | Download | only in gdiplus
      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