2008-03-25 17:34:57 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2007 Google (Evan Stade)
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "gdiplus_private.h"
|
|
|
|
|
|
|
|
/* Multiplies two matrices of the form
|
|
|
|
*
|
|
|
|
* idx:0 idx:1 0
|
|
|
|
* idx:2 idx:3 0
|
|
|
|
* idx:4 idx:5 1
|
|
|
|
*
|
|
|
|
* and puts the output in out.
|
|
|
|
* */
|
|
|
|
static void matrix_multiply(GDIPCONST REAL * left, GDIPCONST REAL * right, REAL * out)
|
|
|
|
{
|
|
|
|
REAL temp[6];
|
|
|
|
int i, odd;
|
|
|
|
|
|
|
|
for(i = 0; i < 6; i++){
|
|
|
|
odd = i % 2;
|
|
|
|
temp[i] = left[i - odd] * right[odd] + left[i - odd + 1] * right[odd + 2] +
|
|
|
|
(i >= 4 ? right[odd + 4] : 0.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(out, temp, 6 * sizeof(REAL));
|
|
|
|
}
|
|
|
|
|
2008-08-05 12:23:58 +00:00
|
|
|
static REAL matrix_det(GDIPCONST GpMatrix *matrix)
|
|
|
|
{
|
|
|
|
return matrix->matrix[0]*matrix->matrix[3] - matrix->matrix[1]*matrix->matrix[2];
|
|
|
|
}
|
|
|
|
|
2008-03-25 17:34:57 +00:00
|
|
|
GpStatus WINGDIPAPI GdipCreateMatrix2(REAL m11, REAL m12, REAL m21, REAL m22,
|
|
|
|
REAL dx, REAL dy, GpMatrix **matrix)
|
|
|
|
{
|
2008-09-07 10:32:49 +00:00
|
|
|
TRACE("(%.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %p)\n", m11, m12, m21, m22, dx, dy, matrix);
|
|
|
|
|
2008-03-25 17:34:57 +00:00
|
|
|
if(!matrix)
|
|
|
|
return InvalidParameter;
|
|
|
|
|
2015-11-22 10:10:02 +00:00
|
|
|
*matrix = heap_alloc_zero(sizeof(GpMatrix));
|
2008-03-25 17:34:57 +00:00
|
|
|
if(!*matrix) return OutOfMemory;
|
|
|
|
|
|
|
|
/* first row */
|
|
|
|
(*matrix)->matrix[0] = m11;
|
|
|
|
(*matrix)->matrix[1] = m12;
|
|
|
|
/* second row */
|
|
|
|
(*matrix)->matrix[2] = m21;
|
|
|
|
(*matrix)->matrix[3] = m22;
|
|
|
|
/* third row */
|
|
|
|
(*matrix)->matrix[4] = dx;
|
|
|
|
(*matrix)->matrix[5] = dy;
|
|
|
|
|
|
|
|
return Ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
GpStatus WINGDIPAPI GdipCreateMatrix3(GDIPCONST GpRectF *rect,
|
|
|
|
GDIPCONST GpPointF *pt, GpMatrix **matrix)
|
|
|
|
{
|
2012-03-05 20:17:42 +00:00
|
|
|
REAL m11, m12, m21, m22, dx, dy;
|
2008-09-07 10:32:49 +00:00
|
|
|
TRACE("(%p, %p, %p)\n", rect, pt, matrix);
|
|
|
|
|
Finish the Wine sync. These components are not just rc file changes
atl, comctl32, comdlg32, dwmapi, fusion, gdiplus, jscript, mpr, mshtml, msi, msimtf, msxml3, ole32, oleaut32, riched20, shdocvw, shlwapi, urlmon, usp10, version and windowscodecs
Seems to build and boot. /me hides
svn path=/trunk/; revision=48273
2010-07-26 02:26:04 +00:00
|
|
|
if(!matrix || !pt)
|
2008-03-25 17:34:57 +00:00
|
|
|
return InvalidParameter;
|
|
|
|
|
2012-03-05 20:17:42 +00:00
|
|
|
m11 = (pt[1].X - pt[0].X) / rect->Width;
|
|
|
|
m21 = (pt[2].X - pt[0].X) / rect->Height;
|
|
|
|
dx = pt[0].X - m11 * rect->X - m21 * rect->Y;
|
|
|
|
m12 = (pt[1].Y - pt[0].Y) / rect->Width;
|
|
|
|
m22 = (pt[2].Y - pt[0].Y) / rect->Height;
|
|
|
|
dy = pt[0].Y - m12 * rect->X - m22 * rect->Y;
|
2008-03-25 17:34:57 +00:00
|
|
|
|
2012-03-05 20:17:42 +00:00
|
|
|
return GdipCreateMatrix2(m11, m12, m21, m22, dx, dy, matrix);
|
2008-03-25 17:34:57 +00:00
|
|
|
}
|
|
|
|
|
2008-05-04 19:41:25 +00:00
|
|
|
GpStatus WINGDIPAPI GdipCreateMatrix3I(GDIPCONST GpRect *rect, GDIPCONST GpPoint *pt,
|
|
|
|
GpMatrix **matrix)
|
|
|
|
{
|
|
|
|
GpRectF rectF;
|
2012-03-05 20:17:42 +00:00
|
|
|
GpPointF ptF[3];
|
|
|
|
int i;
|
2008-05-04 19:41:25 +00:00
|
|
|
|
2008-09-07 10:32:49 +00:00
|
|
|
TRACE("(%p, %p, %p)\n", rect, pt, matrix);
|
|
|
|
|
2008-05-04 19:41:25 +00:00
|
|
|
rectF.X = (REAL)rect->X;
|
|
|
|
rectF.Y = (REAL)rect->Y;
|
|
|
|
rectF.Width = (REAL)rect->Width;
|
|
|
|
rectF.Height = (REAL)rect->Height;
|
|
|
|
|
2012-03-05 20:17:42 +00:00
|
|
|
for (i = 0; i < 3; i++) {
|
|
|
|
ptF[i].X = (REAL)pt[i].X;
|
|
|
|
ptF[i].Y = (REAL)pt[i].Y;
|
|
|
|
}
|
|
|
|
return GdipCreateMatrix3(&rectF, ptF, matrix);
|
2008-05-04 19:41:25 +00:00
|
|
|
}
|
|
|
|
|
2008-03-25 17:34:57 +00:00
|
|
|
GpStatus WINGDIPAPI GdipCloneMatrix(GpMatrix *matrix, GpMatrix **clone)
|
|
|
|
{
|
2008-09-07 10:32:49 +00:00
|
|
|
TRACE("(%p, %p)\n", matrix, clone);
|
|
|
|
|
2008-03-25 17:34:57 +00:00
|
|
|
if(!matrix || !clone)
|
|
|
|
return InvalidParameter;
|
|
|
|
|
2015-11-22 10:10:02 +00:00
|
|
|
*clone = heap_alloc_zero(sizeof(GpMatrix));
|
2008-03-25 17:34:57 +00:00
|
|
|
if(!*clone) return OutOfMemory;
|
|
|
|
|
|
|
|
**clone = *matrix;
|
|
|
|
|
|
|
|
return Ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
GpStatus WINGDIPAPI GdipCreateMatrix(GpMatrix **matrix)
|
|
|
|
{
|
2008-09-07 10:32:49 +00:00
|
|
|
TRACE("(%p)\n", matrix);
|
|
|
|
|
2008-03-25 17:34:57 +00:00
|
|
|
if(!matrix)
|
|
|
|
return InvalidParameter;
|
|
|
|
|
2015-11-22 10:10:02 +00:00
|
|
|
*matrix = heap_alloc_zero(sizeof(GpMatrix));
|
2008-03-25 17:34:57 +00:00
|
|
|
if(!*matrix) return OutOfMemory;
|
|
|
|
|
|
|
|
(*matrix)->matrix[0] = 1.0;
|
|
|
|
(*matrix)->matrix[1] = 0.0;
|
|
|
|
(*matrix)->matrix[2] = 0.0;
|
|
|
|
(*matrix)->matrix[3] = 1.0;
|
|
|
|
(*matrix)->matrix[4] = 0.0;
|
|
|
|
(*matrix)->matrix[5] = 0.0;
|
|
|
|
|
|
|
|
return Ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
GpStatus WINGDIPAPI GdipDeleteMatrix(GpMatrix *matrix)
|
|
|
|
{
|
2008-09-07 10:32:49 +00:00
|
|
|
TRACE("(%p)\n", matrix);
|
|
|
|
|
2008-03-25 17:34:57 +00:00
|
|
|
if(!matrix)
|
|
|
|
return InvalidParameter;
|
|
|
|
|
2015-11-22 10:10:02 +00:00
|
|
|
heap_free(matrix);
|
2008-03-25 17:34:57 +00:00
|
|
|
|
|
|
|
return Ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
GpStatus WINGDIPAPI GdipGetMatrixElements(GDIPCONST GpMatrix *matrix,
|
|
|
|
REAL *out)
|
|
|
|
{
|
2008-09-07 10:32:49 +00:00
|
|
|
TRACE("(%p, %p)\n", matrix, out);
|
|
|
|
|
2008-03-25 17:34:57 +00:00
|
|
|
if(!matrix || !out)
|
|
|
|
return InvalidParameter;
|
|
|
|
|
|
|
|
memcpy(out, matrix->matrix, sizeof(matrix->matrix));
|
|
|
|
|
|
|
|
return Ok;
|
|
|
|
}
|
|
|
|
|
2008-08-05 12:23:58 +00:00
|
|
|
GpStatus WINGDIPAPI GdipInvertMatrix(GpMatrix *matrix)
|
|
|
|
{
|
|
|
|
GpMatrix copy;
|
|
|
|
REAL det;
|
|
|
|
BOOL invertible;
|
|
|
|
|
2008-09-07 10:32:49 +00:00
|
|
|
TRACE("(%p)\n", matrix);
|
|
|
|
|
2008-08-05 12:23:58 +00:00
|
|
|
if(!matrix)
|
|
|
|
return InvalidParameter;
|
|
|
|
|
|
|
|
GdipIsMatrixInvertible(matrix, &invertible);
|
|
|
|
if(!invertible)
|
|
|
|
return InvalidParameter;
|
|
|
|
|
2017-09-17 12:34:15 +00:00
|
|
|
/* optimize inverting simple scaling and translation matrices */
|
|
|
|
if(matrix->matrix[1] == 0 && matrix->matrix[2] == 0)
|
|
|
|
{
|
|
|
|
matrix->matrix[4] = -matrix->matrix[4] / matrix->matrix[0];
|
|
|
|
matrix->matrix[5] = -matrix->matrix[5] / matrix->matrix[3];
|
|
|
|
matrix->matrix[0] = 1 / matrix->matrix[0];
|
|
|
|
matrix->matrix[3] = 1 / matrix->matrix[3];
|
|
|
|
|
|
|
|
return Ok;
|
|
|
|
}
|
|
|
|
|
2008-08-05 12:23:58 +00:00
|
|
|
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)
|
|
|
|
{
|
2008-09-07 10:32:49 +00:00
|
|
|
TRACE("(%p, %p)\n", matrix, result);
|
|
|
|
|
2008-08-05 12:23:58 +00:00
|
|
|
if(!matrix || !result)
|
|
|
|
return InvalidParameter;
|
|
|
|
|
2017-09-17 12:34:15 +00:00
|
|
|
if(matrix->matrix[1] == 0 && matrix->matrix[2] == 0)
|
|
|
|
*result = matrix->matrix[0] != 0 && matrix->matrix[3] != 0;
|
|
|
|
else
|
|
|
|
*result = (fabs(matrix_det(matrix)) >= 1e-5);
|
2008-08-05 12:23:58 +00:00
|
|
|
|
|
|
|
return Ok;
|
|
|
|
}
|
|
|
|
|
2008-12-06 09:26:01 +00:00
|
|
|
GpStatus WINGDIPAPI GdipMultiplyMatrix(GpMatrix *matrix, GDIPCONST GpMatrix* matrix2,
|
2008-03-25 17:34:57 +00:00
|
|
|
GpMatrixOrder order)
|
|
|
|
{
|
2008-09-07 10:32:49 +00:00
|
|
|
TRACE("(%p, %p, %d)\n", matrix, matrix2, order);
|
|
|
|
|
2008-03-25 17:34:57 +00:00
|
|
|
if(!matrix || !matrix2)
|
|
|
|
return InvalidParameter;
|
|
|
|
|
|
|
|
if(order == MatrixOrderAppend)
|
|
|
|
matrix_multiply(matrix->matrix, matrix2->matrix, matrix->matrix);
|
2012-03-05 20:17:42 +00:00
|
|
|
else if (order == MatrixOrderPrepend)
|
2008-03-25 17:34:57 +00:00
|
|
|
matrix_multiply(matrix2->matrix, matrix->matrix, matrix->matrix);
|
2012-03-05 20:17:42 +00:00
|
|
|
else
|
|
|
|
return InvalidParameter;
|
2008-03-25 17:34:57 +00:00
|
|
|
|
|
|
|
return Ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
GpStatus WINGDIPAPI GdipRotateMatrix(GpMatrix *matrix, REAL angle,
|
|
|
|
GpMatrixOrder order)
|
|
|
|
{
|
|
|
|
REAL cos_theta, sin_theta, rotate[6];
|
|
|
|
|
2008-09-07 10:32:49 +00:00
|
|
|
TRACE("(%p, %.2f, %d)\n", matrix, angle, order);
|
|
|
|
|
2008-03-25 17:34:57 +00:00
|
|
|
if(!matrix)
|
|
|
|
return InvalidParameter;
|
|
|
|
|
|
|
|
angle = deg2rad(angle);
|
|
|
|
cos_theta = cos(angle);
|
|
|
|
sin_theta = sin(angle);
|
|
|
|
|
|
|
|
rotate[0] = cos_theta;
|
|
|
|
rotate[1] = sin_theta;
|
|
|
|
rotate[2] = -sin_theta;
|
|
|
|
rotate[3] = cos_theta;
|
|
|
|
rotate[4] = 0.0;
|
|
|
|
rotate[5] = 0.0;
|
|
|
|
|
|
|
|
if(order == MatrixOrderAppend)
|
|
|
|
matrix_multiply(matrix->matrix, rotate, matrix->matrix);
|
2012-03-05 20:17:42 +00:00
|
|
|
else if (order == MatrixOrderPrepend)
|
2008-03-25 17:34:57 +00:00
|
|
|
matrix_multiply(rotate, matrix->matrix, matrix->matrix);
|
2012-03-05 20:17:42 +00:00
|
|
|
else
|
|
|
|
return InvalidParameter;
|
2008-03-25 17:34:57 +00:00
|
|
|
|
|
|
|
return Ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
GpStatus WINGDIPAPI GdipScaleMatrix(GpMatrix *matrix, REAL scaleX, REAL scaleY,
|
|
|
|
GpMatrixOrder order)
|
|
|
|
{
|
|
|
|
REAL scale[6];
|
|
|
|
|
2008-09-07 10:32:49 +00:00
|
|
|
TRACE("(%p, %.2f, %.2f, %d)\n", matrix, scaleX, scaleY, order);
|
|
|
|
|
2008-03-25 17:34:57 +00:00
|
|
|
if(!matrix)
|
|
|
|
return InvalidParameter;
|
|
|
|
|
|
|
|
scale[0] = scaleX;
|
|
|
|
scale[1] = 0.0;
|
|
|
|
scale[2] = 0.0;
|
|
|
|
scale[3] = scaleY;
|
|
|
|
scale[4] = 0.0;
|
|
|
|
scale[5] = 0.0;
|
|
|
|
|
|
|
|
if(order == MatrixOrderAppend)
|
|
|
|
matrix_multiply(matrix->matrix, scale, matrix->matrix);
|
2012-03-05 20:17:42 +00:00
|
|
|
else if (order == MatrixOrderPrepend)
|
2008-03-25 17:34:57 +00:00
|
|
|
matrix_multiply(scale, matrix->matrix, matrix->matrix);
|
2012-03-05 20:17:42 +00:00
|
|
|
else
|
|
|
|
return InvalidParameter;
|
2008-03-25 17:34:57 +00:00
|
|
|
|
|
|
|
return Ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
GpStatus WINGDIPAPI GdipSetMatrixElements(GpMatrix *matrix, REAL m11, REAL m12,
|
|
|
|
REAL m21, REAL m22, REAL dx, REAL dy)
|
|
|
|
{
|
2008-09-07 10:32:49 +00:00
|
|
|
TRACE("(%p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f)\n", matrix, m11, m12,
|
|
|
|
m21, m22, dx, dy);
|
|
|
|
|
2008-03-25 17:34:57 +00:00
|
|
|
if(!matrix)
|
|
|
|
return InvalidParameter;
|
|
|
|
|
|
|
|
matrix->matrix[0] = m11;
|
|
|
|
matrix->matrix[1] = m12;
|
|
|
|
matrix->matrix[2] = m21;
|
|
|
|
matrix->matrix[3] = m22;
|
|
|
|
matrix->matrix[4] = dx;
|
|
|
|
matrix->matrix[5] = dy;
|
|
|
|
|
|
|
|
return Ok;
|
|
|
|
}
|
|
|
|
|
2008-08-05 12:23:58 +00:00
|
|
|
GpStatus WINGDIPAPI GdipShearMatrix(GpMatrix *matrix, REAL shearX, REAL shearY,
|
|
|
|
GpMatrixOrder order)
|
|
|
|
{
|
|
|
|
REAL shear[6];
|
|
|
|
|
2008-09-07 10:32:49 +00:00
|
|
|
TRACE("(%p, %.2f, %.2f, %d)\n", matrix, shearX, shearY, order);
|
|
|
|
|
2008-08-05 12:23:58 +00:00
|
|
|
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);
|
2012-03-05 20:17:42 +00:00
|
|
|
else if (order == MatrixOrderPrepend)
|
2008-08-05 12:23:58 +00:00
|
|
|
matrix_multiply(shear, matrix->matrix, matrix->matrix);
|
2012-03-05 20:17:42 +00:00
|
|
|
else
|
|
|
|
return InvalidParameter;
|
2008-08-05 12:23:58 +00:00
|
|
|
|
|
|
|
return Ok;
|
|
|
|
}
|
|
|
|
|
2008-03-25 17:34:57 +00:00
|
|
|
GpStatus WINGDIPAPI GdipTransformMatrixPoints(GpMatrix *matrix, GpPointF *pts,
|
|
|
|
INT count)
|
|
|
|
{
|
|
|
|
REAL x, y;
|
|
|
|
INT i;
|
|
|
|
|
2008-09-07 10:32:49 +00:00
|
|
|
TRACE("(%p, %p, %d)\n", matrix, pts, count);
|
|
|
|
|
2008-06-01 13:14:02 +00:00
|
|
|
if(!matrix || !pts || count <= 0)
|
2008-03-25 17:34:57 +00:00
|
|
|
return InvalidParameter;
|
|
|
|
|
|
|
|
for(i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
x = pts[i].X;
|
|
|
|
y = pts[i].Y;
|
|
|
|
|
|
|
|
pts[i].X = x * matrix->matrix[0] + y * matrix->matrix[2] + matrix->matrix[4];
|
|
|
|
pts[i].Y = x * matrix->matrix[1] + y * matrix->matrix[3] + matrix->matrix[5];
|
|
|
|
}
|
|
|
|
|
|
|
|
return Ok;
|
|
|
|
}
|
|
|
|
|
2008-05-04 19:41:25 +00:00
|
|
|
GpStatus WINGDIPAPI GdipTransformMatrixPointsI(GpMatrix *matrix, GpPoint *pts, INT count)
|
|
|
|
{
|
|
|
|
GpPointF *ptsF;
|
|
|
|
GpStatus ret;
|
|
|
|
INT i;
|
|
|
|
|
2008-09-07 10:32:49 +00:00
|
|
|
TRACE("(%p, %p, %d)\n", matrix, pts, count);
|
|
|
|
|
2008-06-01 13:14:02 +00:00
|
|
|
if(count <= 0)
|
|
|
|
return InvalidParameter;
|
|
|
|
|
2015-11-22 10:10:02 +00:00
|
|
|
ptsF = heap_alloc_zero(sizeof(GpPointF) * count);
|
2008-05-04 19:41:25 +00:00
|
|
|
if(!ptsF)
|
|
|
|
return OutOfMemory;
|
|
|
|
|
|
|
|
for(i = 0; i < count; i++){
|
|
|
|
ptsF[i].X = (REAL)pts[i].X;
|
|
|
|
ptsF[i].Y = (REAL)pts[i].Y;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = GdipTransformMatrixPoints(matrix, ptsF, count);
|
|
|
|
|
|
|
|
if(ret == Ok)
|
|
|
|
for(i = 0; i < count; i++){
|
2012-12-11 21:40:15 +00:00
|
|
|
pts[i].X = gdip_round(ptsF[i].X);
|
|
|
|
pts[i].Y = gdip_round(ptsF[i].Y);
|
2008-05-04 19:41:25 +00:00
|
|
|
}
|
2015-11-22 10:10:02 +00:00
|
|
|
heap_free(ptsF);
|
2008-05-04 19:41:25 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2008-03-25 17:34:57 +00:00
|
|
|
GpStatus WINGDIPAPI GdipTranslateMatrix(GpMatrix *matrix, REAL offsetX,
|
|
|
|
REAL offsetY, GpMatrixOrder order)
|
|
|
|
{
|
|
|
|
REAL translate[6];
|
|
|
|
|
2008-09-07 10:32:49 +00:00
|
|
|
TRACE("(%p, %.2f, %.2f, %d)\n", matrix, offsetX, offsetY, order);
|
|
|
|
|
2008-03-25 17:34:57 +00:00
|
|
|
if(!matrix)
|
|
|
|
return InvalidParameter;
|
|
|
|
|
|
|
|
translate[0] = 1.0;
|
|
|
|
translate[1] = 0.0;
|
|
|
|
translate[2] = 0.0;
|
|
|
|
translate[3] = 1.0;
|
|
|
|
translate[4] = offsetX;
|
|
|
|
translate[5] = offsetY;
|
|
|
|
|
|
|
|
if(order == MatrixOrderAppend)
|
|
|
|
matrix_multiply(matrix->matrix, translate, matrix->matrix);
|
2012-03-05 20:17:42 +00:00
|
|
|
else if (order == MatrixOrderPrepend)
|
2008-03-25 17:34:57 +00:00
|
|
|
matrix_multiply(translate, matrix->matrix, matrix->matrix);
|
2012-03-05 20:17:42 +00:00
|
|
|
else
|
|
|
|
return InvalidParameter;
|
2008-03-25 17:34:57 +00:00
|
|
|
|
|
|
|
return Ok;
|
|
|
|
}
|
2008-05-04 19:41:25 +00:00
|
|
|
|
|
|
|
GpStatus WINGDIPAPI GdipVectorTransformMatrixPoints(GpMatrix *matrix, GpPointF *pts, INT count)
|
|
|
|
{
|
|
|
|
REAL x, y;
|
|
|
|
INT i;
|
|
|
|
|
2008-09-07 10:32:49 +00:00
|
|
|
TRACE("(%p, %p, %d)\n", matrix, pts, count);
|
|
|
|
|
2008-06-01 13:14:02 +00:00
|
|
|
if(!matrix || !pts || count <= 0)
|
2008-05-04 19:41:25 +00:00
|
|
|
return InvalidParameter;
|
|
|
|
|
|
|
|
for(i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
x = pts[i].X;
|
|
|
|
y = pts[i].Y;
|
|
|
|
|
|
|
|
pts[i].X = x * matrix->matrix[0] + y * matrix->matrix[2];
|
|
|
|
pts[i].Y = x * matrix->matrix[1] + y * matrix->matrix[3];
|
|
|
|
}
|
|
|
|
|
|
|
|
return Ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
GpStatus WINGDIPAPI GdipVectorTransformMatrixPointsI(GpMatrix *matrix, GpPoint *pts, INT count)
|
|
|
|
{
|
|
|
|
GpPointF *ptsF;
|
|
|
|
GpStatus ret;
|
|
|
|
INT i;
|
|
|
|
|
2008-09-07 10:32:49 +00:00
|
|
|
TRACE("(%p, %p, %d)\n", matrix, pts, count);
|
|
|
|
|
2008-06-01 13:14:02 +00:00
|
|
|
if(count <= 0)
|
|
|
|
return InvalidParameter;
|
|
|
|
|
2015-11-22 10:10:02 +00:00
|
|
|
ptsF = heap_alloc_zero(sizeof(GpPointF) * count);
|
2008-05-04 19:41:25 +00:00
|
|
|
if(!ptsF)
|
|
|
|
return OutOfMemory;
|
|
|
|
|
|
|
|
for(i = 0; i < count; i++){
|
|
|
|
ptsF[i].X = (REAL)pts[i].X;
|
|
|
|
ptsF[i].Y = (REAL)pts[i].Y;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = GdipVectorTransformMatrixPoints(matrix, ptsF, count);
|
|
|
|
/* store back */
|
|
|
|
if(ret == Ok)
|
|
|
|
for(i = 0; i < count; i++){
|
2012-12-11 21:40:15 +00:00
|
|
|
pts[i].X = gdip_round(ptsF[i].X);
|
|
|
|
pts[i].Y = gdip_round(ptsF[i].Y);
|
2008-05-04 19:41:25 +00:00
|
|
|
}
|
2015-11-22 10:10:02 +00:00
|
|
|
heap_free(ptsF);
|
2008-05-04 19:41:25 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
GpStatus WINGDIPAPI GdipIsMatrixEqual(GDIPCONST GpMatrix *matrix, GDIPCONST GpMatrix *matrix2,
|
|
|
|
BOOL *result)
|
|
|
|
{
|
2008-09-07 10:32:49 +00:00
|
|
|
TRACE("(%p, %p, %p)\n", matrix, matrix2, result);
|
|
|
|
|
2008-05-04 19:41:25 +00:00
|
|
|
if(!matrix || !matrix2 || !result)
|
|
|
|
return InvalidParameter;
|
|
|
|
/* based on single array member of GpMatrix */
|
|
|
|
*result = (memcmp(matrix->matrix, matrix2->matrix, sizeof(GpMatrix)) == 0);
|
|
|
|
|
|
|
|
return Ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
GpStatus WINGDIPAPI GdipIsMatrixIdentity(GDIPCONST GpMatrix *matrix, BOOL *result)
|
|
|
|
{
|
2016-11-17 22:35:44 +00:00
|
|
|
static const GpMatrix identity =
|
|
|
|
{
|
|
|
|
{ 1.0, 0.0,
|
|
|
|
0.0, 1.0,
|
|
|
|
0.0, 0.0 }
|
|
|
|
};
|
2008-05-04 19:41:25 +00:00
|
|
|
|
2008-09-07 10:32:49 +00:00
|
|
|
TRACE("(%p, %p)\n", matrix, result);
|
|
|
|
|
2008-05-04 19:41:25 +00:00
|
|
|
if(!matrix || !result)
|
|
|
|
return InvalidParameter;
|
|
|
|
|
2016-11-17 22:35:44 +00:00
|
|
|
return GdipIsMatrixEqual(matrix, &identity, result);
|
2008-05-04 19:41:25 +00:00
|
|
|
}
|