ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

matrix.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.