#include "gdiplus.h"
#include "gdiplus_private.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(gdiplus);
/* Multiplies two matrices of the form
*
memcpy(out, temp, 6 * sizeof(REAL));
}
+static REAL matrix_det(GDIPCONST GpMatrix *matrix)
+{
+ return matrix->matrix[0]*matrix->matrix[3] - matrix->matrix[1]*matrix->matrix[2];
+}
+
GpStatus WINGDIPAPI GdipCreateMatrix2(REAL m11, REAL m12, REAL m21, REAL m22,
REAL dx, REAL dy, GpMatrix **matrix)
{
+ TRACE("(%.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %p)\n", m11, m12, m21, m22, dx, dy, matrix);
+
if(!matrix)
return InvalidParameter;
GpStatus WINGDIPAPI GdipCreateMatrix3(GDIPCONST GpRectF *rect,
GDIPCONST GpPointF *pt, GpMatrix **matrix)
{
+ TRACE("(%p, %p, %p)\n", rect, pt, matrix);
+
if(!matrix)
return InvalidParameter;
GpRectF rectF;
GpPointF ptF;
+ TRACE("(%p, %p, %p)\n", rect, pt, matrix);
+
rectF.X = (REAL)rect->X;
rectF.Y = (REAL)rect->Y;
rectF.Width = (REAL)rect->Width;
GpStatus WINGDIPAPI GdipCloneMatrix(GpMatrix *matrix, GpMatrix **clone)
{
+ TRACE("(%p, %p)\n", matrix, clone);
+
if(!matrix || !clone)
return InvalidParameter;
GpStatus WINGDIPAPI GdipCreateMatrix(GpMatrix **matrix)
{
+ TRACE("(%p)\n", matrix);
+
if(!matrix)
return InvalidParameter;
GpStatus WINGDIPAPI GdipDeleteMatrix(GpMatrix *matrix)
{
+ TRACE("(%p)\n", matrix);
+
if(!matrix)
return InvalidParameter;
GpStatus WINGDIPAPI GdipGetMatrixElements(GDIPCONST GpMatrix *matrix,
REAL *out)
{
+ TRACE("(%p, %p)\n", matrix, out);
+
if(!matrix || !out)
return InvalidParameter;
return Ok;
}
-GpStatus WINGDIPAPI GdipMultiplyMatrix(GpMatrix *matrix, GpMatrix* matrix2,
+GpStatus WINGDIPAPI GdipInvertMatrix(GpMatrix *matrix)
+{
+ GpMatrix copy;
+ REAL det;
+ BOOL invertible;
+
+ TRACE("(%p)\n", matrix);
+
+ if(!matrix)
+ return InvalidParameter;
+
+ GdipIsMatrixInvertible(matrix, &invertible);
+ if(!invertible)
+ return InvalidParameter;
+
+ det = matrix_det(matrix);
+
+ copy = *matrix;
+ /* store result */
+ matrix->matrix[0] = copy.matrix[3] / det;
+ matrix->matrix[1] = -copy.matrix[1] / det;
+ matrix->matrix[2] = -copy.matrix[2] / det;
+ matrix->matrix[3] = copy.matrix[0] / det;
+ matrix->matrix[4] = (copy.matrix[2]*copy.matrix[5]-copy.matrix[3]*copy.matrix[4]) / det;
+ matrix->matrix[5] = -(copy.matrix[0]*copy.matrix[5]-copy.matrix[1]*copy.matrix[4]) / det;
+
+ return Ok;
+}
+
+GpStatus WINGDIPAPI GdipIsMatrixInvertible(GDIPCONST GpMatrix *matrix, BOOL *result)
+{
+ TRACE("(%p, %p)\n", matrix, result);
+
+ if(!matrix || !result)
+ return InvalidParameter;
+
+ *result = (fabs(matrix_det(matrix)) >= 1e-5);
+
+ return Ok;
+}
+
+GpStatus WINGDIPAPI GdipMultiplyMatrix(GpMatrix *matrix, GDIPCONST GpMatrix* matrix2,
GpMatrixOrder order)
{
+ TRACE("(%p, %p, %d)\n", matrix, matrix2, order);
+
if(!matrix || !matrix2)
return InvalidParameter;
{
REAL cos_theta, sin_theta, rotate[6];
+ TRACE("(%p, %.2f, %d)\n", matrix, angle, order);
+
if(!matrix)
return InvalidParameter;
{
REAL scale[6];
+ TRACE("(%p, %.2f, %.2f, %d)\n", matrix, scaleX, scaleY, order);
+
if(!matrix)
return InvalidParameter;
GpStatus WINGDIPAPI GdipSetMatrixElements(GpMatrix *matrix, REAL m11, REAL m12,
REAL m21, REAL m22, REAL dx, REAL dy)
{
+ TRACE("(%p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f)\n", matrix, m11, m12,
+ m21, m22, dx, dy);
+
if(!matrix)
return InvalidParameter;
return Ok;
}
+GpStatus WINGDIPAPI GdipShearMatrix(GpMatrix *matrix, REAL shearX, REAL shearY,
+ GpMatrixOrder order)
+{
+ REAL shear[6];
+
+ TRACE("(%p, %.2f, %.2f, %d)\n", matrix, shearX, shearY, order);
+
+ if(!matrix)
+ return InvalidParameter;
+
+ /* prepare transformation matrix */
+ shear[0] = 1.0;
+ shear[1] = shearY;
+ shear[2] = shearX;
+ shear[3] = 1.0;
+ shear[4] = 0.0;
+ shear[5] = 0.0;
+
+ if(order == MatrixOrderAppend)
+ matrix_multiply(matrix->matrix, shear, matrix->matrix);
+ else
+ matrix_multiply(shear, matrix->matrix, matrix->matrix);
+
+ return Ok;
+}
+
GpStatus WINGDIPAPI GdipTransformMatrixPoints(GpMatrix *matrix, GpPointF *pts,
INT count)
{
REAL x, y;
INT i;
- if(!matrix || !pts)
+ TRACE("(%p, %p, %d)\n", matrix, pts, count);
+
+ if(!matrix || !pts || count <= 0)
return InvalidParameter;
for(i = 0; i < count; i++)
GpStatus ret;
INT i;
+ TRACE("(%p, %p, %d)\n", matrix, pts, count);
+
+ if(count <= 0)
+ return InvalidParameter;
+
ptsF = GdipAlloc(sizeof(GpPointF) * count);
if(!ptsF)
return OutOfMemory;
{
REAL translate[6];
+ TRACE("(%p, %.2f, %.2f, %d)\n", matrix, offsetX, offsetY, order);
+
if(!matrix)
return InvalidParameter;
REAL x, y;
INT i;
- if(!matrix || !pts)
+ TRACE("(%p, %p, %d)\n", matrix, pts, count);
+
+ if(!matrix || !pts || count <= 0)
return InvalidParameter;
for(i = 0; i < count; i++)
GpStatus ret;
INT i;
+ TRACE("(%p, %p, %d)\n", matrix, pts, count);
+
+ if(count <= 0)
+ return InvalidParameter;
+
ptsF = GdipAlloc(sizeof(GpPointF) * count);
if(!ptsF)
return OutOfMemory;
GpStatus WINGDIPAPI GdipIsMatrixEqual(GDIPCONST GpMatrix *matrix, GDIPCONST GpMatrix *matrix2,
BOOL *result)
{
+ TRACE("(%p, %p, %p)\n", matrix, matrix2, result);
+
if(!matrix || !matrix2 || !result)
return InvalidParameter;
/* based on single array member of GpMatrix */
return Ok;
}
+
+GpStatus WINGDIPAPI GdipIsMatrixIdentity(GDIPCONST GpMatrix *matrix, BOOL *result)
+{
+ GpMatrix *e;
+ GpStatus ret;
+ BOOL isIdentity;
+
+ TRACE("(%p, %p)\n", matrix, result);
+
+ if(!matrix || !result)
+ return InvalidParameter;
+
+ ret = GdipCreateMatrix(&e);
+ if(ret != Ok) return ret;
+
+ ret = GdipIsMatrixEqual(matrix, e, &isIdentity);
+ if(ret == Ok)
+ *result = isIdentity;
+
+ GdipFree(e);
+
+ return ret;
+}