Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmatrix.c
Go to the documentation of this file.
00001 /* 00002 * Copyright (C) 2007 Google (Evan Stade) 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2.1 of the License, or (at your option) any later version. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public 00015 * License along with this library; if not, write to the Free Software 00016 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00017 */ 00018 00019 #include <stdarg.h> 00020 #include <math.h> 00021 00022 #include "windef.h" 00023 #include "winbase.h" 00024 #include "wingdi.h" 00025 00026 #include "objbase.h" 00027 00028 #include "gdiplus.h" 00029 #include "gdiplus_private.h" 00030 #include "wine/debug.h" 00031 00032 WINE_DEFAULT_DEBUG_CHANNEL(gdiplus); 00033 00034 /* Multiplies two matrices of the form 00035 * 00036 * idx:0 idx:1 0 00037 * idx:2 idx:3 0 00038 * idx:4 idx:5 1 00039 * 00040 * and puts the output in out. 00041 * */ 00042 static void matrix_multiply(GDIPCONST REAL * left, GDIPCONST REAL * right, REAL * out) 00043 { 00044 REAL temp[6]; 00045 int i, odd; 00046 00047 for(i = 0; i < 6; i++){ 00048 odd = i % 2; 00049 temp[i] = left[i - odd] * right[odd] + left[i - odd + 1] * right[odd + 2] + 00050 (i >= 4 ? right[odd + 4] : 0.0); 00051 } 00052 00053 memcpy(out, temp, 6 * sizeof(REAL)); 00054 } 00055 00056 static REAL matrix_det(GDIPCONST GpMatrix *matrix) 00057 { 00058 return matrix->matrix[0]*matrix->matrix[3] - matrix->matrix[1]*matrix->matrix[2]; 00059 } 00060 00061 GpStatus WINGDIPAPI GdipCreateMatrix2(REAL m11, REAL m12, REAL m21, REAL m22, 00062 REAL dx, REAL dy, GpMatrix **matrix) 00063 { 00064 TRACE("(%.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %p)\n", m11, m12, m21, m22, dx, dy, matrix); 00065 00066 if(!matrix) 00067 return InvalidParameter; 00068 00069 *matrix = GdipAlloc(sizeof(GpMatrix)); 00070 if(!*matrix) return OutOfMemory; 00071 00072 /* first row */ 00073 (*matrix)->matrix[0] = m11; 00074 (*matrix)->matrix[1] = m12; 00075 /* second row */ 00076 (*matrix)->matrix[2] = m21; 00077 (*matrix)->matrix[3] = m22; 00078 /* third row */ 00079 (*matrix)->matrix[4] = dx; 00080 (*matrix)->matrix[5] = dy; 00081 00082 return Ok; 00083 } 00084 00085 GpStatus WINGDIPAPI GdipCreateMatrix3(GDIPCONST GpRectF *rect, 00086 GDIPCONST GpPointF *pt, GpMatrix **matrix) 00087 { 00088 REAL m11, m12, m21, m22, dx, dy; 00089 TRACE("(%p, %p, %p)\n", rect, pt, matrix); 00090 00091 if(!matrix || !pt) 00092 return InvalidParameter; 00093 00094 m11 = (pt[1].X - pt[0].X) / rect->Width; 00095 m21 = (pt[2].X - pt[0].X) / rect->Height; 00096 dx = pt[0].X - m11 * rect->X - m21 * rect->Y; 00097 m12 = (pt[1].Y - pt[0].Y) / rect->Width; 00098 m22 = (pt[2].Y - pt[0].Y) / rect->Height; 00099 dy = pt[0].Y - m12 * rect->X - m22 * rect->Y; 00100 00101 return GdipCreateMatrix2(m11, m12, m21, m22, dx, dy, matrix); 00102 } 00103 00104 GpStatus WINGDIPAPI GdipCreateMatrix3I(GDIPCONST GpRect *rect, GDIPCONST GpPoint *pt, 00105 GpMatrix **matrix) 00106 { 00107 GpRectF rectF; 00108 GpPointF ptF[3]; 00109 int i; 00110 00111 TRACE("(%p, %p, %p)\n", rect, pt, matrix); 00112 00113 rectF.X = (REAL)rect->X; 00114 rectF.Y = (REAL)rect->Y; 00115 rectF.Width = (REAL)rect->Width; 00116 rectF.Height = (REAL)rect->Height; 00117 00118 for (i = 0; i < 3; i++) { 00119 ptF[i].X = (REAL)pt[i].X; 00120 ptF[i].Y = (REAL)pt[i].Y; 00121 } 00122 return GdipCreateMatrix3(&rectF, ptF, matrix); 00123 } 00124 00125 GpStatus WINGDIPAPI GdipCloneMatrix(GpMatrix *matrix, GpMatrix **clone) 00126 { 00127 TRACE("(%p, %p)\n", matrix, clone); 00128 00129 if(!matrix || !clone) 00130 return InvalidParameter; 00131 00132 *clone = GdipAlloc(sizeof(GpMatrix)); 00133 if(!*clone) return OutOfMemory; 00134 00135 **clone = *matrix; 00136 00137 return Ok; 00138 } 00139 00140 GpStatus WINGDIPAPI GdipCreateMatrix(GpMatrix **matrix) 00141 { 00142 TRACE("(%p)\n", matrix); 00143 00144 if(!matrix) 00145 return InvalidParameter; 00146 00147 *matrix = GdipAlloc(sizeof(GpMatrix)); 00148 if(!*matrix) return OutOfMemory; 00149 00150 (*matrix)->matrix[0] = 1.0; 00151 (*matrix)->matrix[1] = 0.0; 00152 (*matrix)->matrix[2] = 0.0; 00153 (*matrix)->matrix[3] = 1.0; 00154 (*matrix)->matrix[4] = 0.0; 00155 (*matrix)->matrix[5] = 0.0; 00156 00157 return Ok; 00158 } 00159 00160 GpStatus WINGDIPAPI GdipDeleteMatrix(GpMatrix *matrix) 00161 { 00162 TRACE("(%p)\n", matrix); 00163 00164 if(!matrix) 00165 return InvalidParameter; 00166 00167 GdipFree(matrix); 00168 00169 return Ok; 00170 } 00171 00172 GpStatus WINGDIPAPI GdipGetMatrixElements(GDIPCONST GpMatrix *matrix, 00173 REAL *out) 00174 { 00175 TRACE("(%p, %p)\n", matrix, out); 00176 00177 if(!matrix || !out) 00178 return InvalidParameter; 00179 00180 memcpy(out, matrix->matrix, sizeof(matrix->matrix)); 00181 00182 return Ok; 00183 } 00184 00185 GpStatus WINGDIPAPI GdipInvertMatrix(GpMatrix *matrix) 00186 { 00187 GpMatrix copy; 00188 REAL det; 00189 BOOL invertible; 00190 00191 TRACE("(%p)\n", matrix); 00192 00193 if(!matrix) 00194 return InvalidParameter; 00195 00196 GdipIsMatrixInvertible(matrix, &invertible); 00197 if(!invertible) 00198 return InvalidParameter; 00199 00200 det = matrix_det(matrix); 00201 00202 copy = *matrix; 00203 /* store result */ 00204 matrix->matrix[0] = copy.matrix[3] / det; 00205 matrix->matrix[1] = -copy.matrix[1] / det; 00206 matrix->matrix[2] = -copy.matrix[2] / det; 00207 matrix->matrix[3] = copy.matrix[0] / det; 00208 matrix->matrix[4] = (copy.matrix[2]*copy.matrix[5]-copy.matrix[3]*copy.matrix[4]) / det; 00209 matrix->matrix[5] = -(copy.matrix[0]*copy.matrix[5]-copy.matrix[1]*copy.matrix[4]) / det; 00210 00211 return Ok; 00212 } 00213 00214 GpStatus WINGDIPAPI GdipIsMatrixInvertible(GDIPCONST GpMatrix *matrix, BOOL *result) 00215 { 00216 TRACE("(%p, %p)\n", matrix, result); 00217 00218 if(!matrix || !result) 00219 return InvalidParameter; 00220 00221 *result = (fabs(matrix_det(matrix)) >= 1e-5); 00222 00223 return Ok; 00224 } 00225 00226 GpStatus WINGDIPAPI GdipMultiplyMatrix(GpMatrix *matrix, GDIPCONST GpMatrix* matrix2, 00227 GpMatrixOrder order) 00228 { 00229 TRACE("(%p, %p, %d)\n", matrix, matrix2, order); 00230 00231 if(!matrix || !matrix2) 00232 return InvalidParameter; 00233 00234 if(order == MatrixOrderAppend) 00235 matrix_multiply(matrix->matrix, matrix2->matrix, matrix->matrix); 00236 else if (order == MatrixOrderPrepend) 00237 matrix_multiply(matrix2->matrix, matrix->matrix, matrix->matrix); 00238 else 00239 return InvalidParameter; 00240 00241 return Ok; 00242 } 00243 00244 GpStatus WINGDIPAPI GdipRotateMatrix(GpMatrix *matrix, REAL angle, 00245 GpMatrixOrder order) 00246 { 00247 REAL cos_theta, sin_theta, rotate[6]; 00248 00249 TRACE("(%p, %.2f, %d)\n", matrix, angle, order); 00250 00251 if(!matrix) 00252 return InvalidParameter; 00253 00254 angle = deg2rad(angle); 00255 cos_theta = cos(angle); 00256 sin_theta = sin(angle); 00257 00258 rotate[0] = cos_theta; 00259 rotate[1] = sin_theta; 00260 rotate[2] = -sin_theta; 00261 rotate[3] = cos_theta; 00262 rotate[4] = 0.0; 00263 rotate[5] = 0.0; 00264 00265 if(order == MatrixOrderAppend) 00266 matrix_multiply(matrix->matrix, rotate, matrix->matrix); 00267 else if (order == MatrixOrderPrepend) 00268 matrix_multiply(rotate, matrix->matrix, matrix->matrix); 00269 else 00270 return InvalidParameter; 00271 00272 return Ok; 00273 } 00274 00275 GpStatus WINGDIPAPI GdipScaleMatrix(GpMatrix *matrix, REAL scaleX, REAL scaleY, 00276 GpMatrixOrder order) 00277 { 00278 REAL scale[6]; 00279 00280 TRACE("(%p, %.2f, %.2f, %d)\n", matrix, scaleX, scaleY, order); 00281 00282 if(!matrix) 00283 return InvalidParameter; 00284 00285 scale[0] = scaleX; 00286 scale[1] = 0.0; 00287 scale[2] = 0.0; 00288 scale[3] = scaleY; 00289 scale[4] = 0.0; 00290 scale[5] = 0.0; 00291 00292 if(order == MatrixOrderAppend) 00293 matrix_multiply(matrix->matrix, scale, matrix->matrix); 00294 else if (order == MatrixOrderPrepend) 00295 matrix_multiply(scale, matrix->matrix, matrix->matrix); 00296 else 00297 return InvalidParameter; 00298 00299 return Ok; 00300 } 00301 00302 GpStatus WINGDIPAPI GdipSetMatrixElements(GpMatrix *matrix, REAL m11, REAL m12, 00303 REAL m21, REAL m22, REAL dx, REAL dy) 00304 { 00305 TRACE("(%p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f)\n", matrix, m11, m12, 00306 m21, m22, dx, dy); 00307 00308 if(!matrix) 00309 return InvalidParameter; 00310 00311 matrix->matrix[0] = m11; 00312 matrix->matrix[1] = m12; 00313 matrix->matrix[2] = m21; 00314 matrix->matrix[3] = m22; 00315 matrix->matrix[4] = dx; 00316 matrix->matrix[5] = dy; 00317 00318 return Ok; 00319 } 00320 00321 GpStatus WINGDIPAPI GdipShearMatrix(GpMatrix *matrix, REAL shearX, REAL shearY, 00322 GpMatrixOrder order) 00323 { 00324 REAL shear[6]; 00325 00326 TRACE("(%p, %.2f, %.2f, %d)\n", matrix, shearX, shearY, order); 00327 00328 if(!matrix) 00329 return InvalidParameter; 00330 00331 /* prepare transformation matrix */ 00332 shear[0] = 1.0; 00333 shear[1] = shearY; 00334 shear[2] = shearX; 00335 shear[3] = 1.0; 00336 shear[4] = 0.0; 00337 shear[5] = 0.0; 00338 00339 if(order == MatrixOrderAppend) 00340 matrix_multiply(matrix->matrix, shear, matrix->matrix); 00341 else if (order == MatrixOrderPrepend) 00342 matrix_multiply(shear, matrix->matrix, matrix->matrix); 00343 else 00344 return InvalidParameter; 00345 00346 return Ok; 00347 } 00348 00349 GpStatus WINGDIPAPI GdipTransformMatrixPoints(GpMatrix *matrix, GpPointF *pts, 00350 INT count) 00351 { 00352 REAL x, y; 00353 INT i; 00354 00355 TRACE("(%p, %p, %d)\n", matrix, pts, count); 00356 00357 if(!matrix || !pts || count <= 0) 00358 return InvalidParameter; 00359 00360 for(i = 0; i < count; i++) 00361 { 00362 x = pts[i].X; 00363 y = pts[i].Y; 00364 00365 pts[i].X = x * matrix->matrix[0] + y * matrix->matrix[2] + matrix->matrix[4]; 00366 pts[i].Y = x * matrix->matrix[1] + y * matrix->matrix[3] + matrix->matrix[5]; 00367 } 00368 00369 return Ok; 00370 } 00371 00372 GpStatus WINGDIPAPI GdipTransformMatrixPointsI(GpMatrix *matrix, GpPoint *pts, INT count) 00373 { 00374 GpPointF *ptsF; 00375 GpStatus ret; 00376 INT i; 00377 00378 TRACE("(%p, %p, %d)\n", matrix, pts, count); 00379 00380 if(count <= 0) 00381 return InvalidParameter; 00382 00383 ptsF = GdipAlloc(sizeof(GpPointF) * count); 00384 if(!ptsF) 00385 return OutOfMemory; 00386 00387 for(i = 0; i < count; i++){ 00388 ptsF[i].X = (REAL)pts[i].X; 00389 ptsF[i].Y = (REAL)pts[i].Y; 00390 } 00391 00392 ret = GdipTransformMatrixPoints(matrix, ptsF, count); 00393 00394 if(ret == Ok) 00395 for(i = 0; i < count; i++){ 00396 pts[i].X = roundr(ptsF[i].X); 00397 pts[i].Y = roundr(ptsF[i].Y); 00398 } 00399 GdipFree(ptsF); 00400 00401 return ret; 00402 } 00403 00404 GpStatus WINGDIPAPI GdipTranslateMatrix(GpMatrix *matrix, REAL offsetX, 00405 REAL offsetY, GpMatrixOrder order) 00406 { 00407 REAL translate[6]; 00408 00409 TRACE("(%p, %.2f, %.2f, %d)\n", matrix, offsetX, offsetY, order); 00410 00411 if(!matrix) 00412 return InvalidParameter; 00413 00414 translate[0] = 1.0; 00415 translate[1] = 0.0; 00416 translate[2] = 0.0; 00417 translate[3] = 1.0; 00418 translate[4] = offsetX; 00419 translate[5] = offsetY; 00420 00421 if(order == MatrixOrderAppend) 00422 matrix_multiply(matrix->matrix, translate, matrix->matrix); 00423 else if (order == MatrixOrderPrepend) 00424 matrix_multiply(translate, matrix->matrix, matrix->matrix); 00425 else 00426 return InvalidParameter; 00427 00428 return Ok; 00429 } 00430 00431 GpStatus WINGDIPAPI GdipVectorTransformMatrixPoints(GpMatrix *matrix, GpPointF *pts, INT count) 00432 { 00433 REAL x, y; 00434 INT i; 00435 00436 TRACE("(%p, %p, %d)\n", matrix, pts, count); 00437 00438 if(!matrix || !pts || count <= 0) 00439 return InvalidParameter; 00440 00441 for(i = 0; i < count; i++) 00442 { 00443 x = pts[i].X; 00444 y = pts[i].Y; 00445 00446 pts[i].X = x * matrix->matrix[0] + y * matrix->matrix[2]; 00447 pts[i].Y = x * matrix->matrix[1] + y * matrix->matrix[3]; 00448 } 00449 00450 return Ok; 00451 } 00452 00453 GpStatus WINGDIPAPI GdipVectorTransformMatrixPointsI(GpMatrix *matrix, GpPoint *pts, INT count) 00454 { 00455 GpPointF *ptsF; 00456 GpStatus ret; 00457 INT i; 00458 00459 TRACE("(%p, %p, %d)\n", matrix, pts, count); 00460 00461 if(count <= 0) 00462 return InvalidParameter; 00463 00464 ptsF = GdipAlloc(sizeof(GpPointF) * count); 00465 if(!ptsF) 00466 return OutOfMemory; 00467 00468 for(i = 0; i < count; i++){ 00469 ptsF[i].X = (REAL)pts[i].X; 00470 ptsF[i].Y = (REAL)pts[i].Y; 00471 } 00472 00473 ret = GdipVectorTransformMatrixPoints(matrix, ptsF, count); 00474 /* store back */ 00475 if(ret == Ok) 00476 for(i = 0; i < count; i++){ 00477 pts[i].X = roundr(ptsF[i].X); 00478 pts[i].Y = roundr(ptsF[i].Y); 00479 } 00480 GdipFree(ptsF); 00481 00482 return ret; 00483 } 00484 00485 GpStatus WINGDIPAPI GdipIsMatrixEqual(GDIPCONST GpMatrix *matrix, GDIPCONST GpMatrix *matrix2, 00486 BOOL *result) 00487 { 00488 TRACE("(%p, %p, %p)\n", matrix, matrix2, result); 00489 00490 if(!matrix || !matrix2 || !result) 00491 return InvalidParameter; 00492 /* based on single array member of GpMatrix */ 00493 *result = (memcmp(matrix->matrix, matrix2->matrix, sizeof(GpMatrix)) == 0); 00494 00495 return Ok; 00496 } 00497 00498 GpStatus WINGDIPAPI GdipIsMatrixIdentity(GDIPCONST GpMatrix *matrix, BOOL *result) 00499 { 00500 GpMatrix *e; 00501 GpStatus ret; 00502 BOOL isIdentity; 00503 00504 TRACE("(%p, %p)\n", matrix, result); 00505 00506 if(!matrix || !result) 00507 return InvalidParameter; 00508 00509 ret = GdipCreateMatrix(&e); 00510 if(ret != Ok) return ret; 00511 00512 ret = GdipIsMatrixEqual(matrix, e, &isIdentity); 00513 if(ret == Ok) 00514 *result = isIdentity; 00515 00516 GdipFree(e); 00517 00518 return ret; 00519 } Generated on Sun May 27 2012 04:19:00 for ReactOS by
1.7.6.1
|