Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenxformobj.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS win32 kernel mode subsystem 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: subsystems/win32/win32k/objects/xformobj.c 00005 * PURPOSE: XFORMOBJ API 00006 * PROGRAMMER: Timo Kreuzer 00007 */ 00008 00011 #include <win32k.h> 00012 #define NDEBUG 00013 #include <debug.h> 00014 00015 C_ASSERT(sizeof(FIX) == sizeof(LONG)); 00016 #define FIX2LONG(x) ((x) >> 4) 00017 #define LONG2FIX(x) ((x) << 4) 00018 00019 #define FLOATOBJ_Equal _FLOATOBJ_Equal 00020 #define FLOATOBJ_GetLong _FLOATOBJ_GetLong 00021 #define FLOATOBJ_GetFix _FLOATOBJ_GetFix 00022 #define FLOATOBJ_IsLong _FLOATOBJ_IsLong 00023 #define FLOATOBJ_Equal0 _FLOATOBJ_Equal0 00024 #define FLOATOBJ_Equal1 _FLOATOBJ_Equal1 00025 00028 /* 00029 * Inline helper to calculate pfo1 * pfo2 + pfo3 * pfo4 00030 */ 00031 FORCEINLINE 00032 VOID 00033 MulAdd( 00034 PFLOATOBJ pfoDest, 00035 PFLOATOBJ pfo1, 00036 PFLOATOBJ pfo2, 00037 PFLOATOBJ pfo3, 00038 PFLOATOBJ pfo4) 00039 { 00040 FLOATOBJ foTmp; 00041 00042 *pfoDest = *pfo1; 00043 FLOATOBJ_Mul(pfoDest, pfo2); 00044 foTmp = *pfo3; 00045 FLOATOBJ_Mul(&foTmp, pfo4); 00046 FLOATOBJ_Add(pfoDest, &foTmp); 00047 } 00048 00049 /* 00050 * Inline helper to calculate pfo1 * l2 + pfo3 * l4 00051 */ 00052 FORCEINLINE 00053 VOID 00054 MulAddLong( 00055 PFLOATOBJ pfoDest, 00056 PFLOATOBJ pfo1, 00057 LONG l2, 00058 PFLOATOBJ pfo3, 00059 LONG l4) 00060 { 00061 FLOATOBJ foTmp; 00062 00063 *pfoDest = *pfo1; 00064 FLOATOBJ_MulLong(pfoDest, l2); 00065 foTmp = *pfo3; 00066 FLOATOBJ_MulLong(&foTmp, l4); 00067 FLOATOBJ_Add(pfoDest, &foTmp); 00068 } 00069 00070 /* 00071 * Inline helper to calculate pfo1 * pfo2 - pfo3 * pfo4 00072 */ 00073 FORCEINLINE 00074 VOID 00075 MulSub( 00076 PFLOATOBJ pfoDest, 00077 PFLOATOBJ pfo1, 00078 PFLOATOBJ pfo2, 00079 PFLOATOBJ pfo3, 00080 PFLOATOBJ pfo4) 00081 { 00082 FLOATOBJ foTmp; 00083 00084 *pfoDest = *pfo1; 00085 FLOATOBJ_Mul(pfoDest, pfo2); 00086 foTmp = *pfo3; 00087 FLOATOBJ_Mul(&foTmp, pfo4); 00088 FLOATOBJ_Sub(pfoDest, &foTmp); 00089 } 00090 00091 /* 00092 * Inline helper to get the complexity hint from flAccel 00093 */ 00094 FORCEINLINE 00095 ULONG 00096 HintFromAccel(ULONG flAccel) 00097 { 00098 switch (flAccel & (XFORM_SCALE|XFORM_UNITY|XFORM_NO_TRANSLATION)) 00099 { 00100 case (XFORM_SCALE|XFORM_UNITY|XFORM_NO_TRANSLATION): 00101 return GX_IDENTITY; 00102 case (XFORM_SCALE|XFORM_UNITY): 00103 return GX_OFFSET; 00104 case XFORM_SCALE: 00105 return GX_SCALE; 00106 default: 00107 return GX_GENERAL; 00108 } 00109 } 00110 00113 ULONG 00114 NTAPI 00115 XFORMOBJ_UpdateAccel( 00116 IN XFORMOBJ *pxo) 00117 { 00118 PMATRIX pmx = XFORMOBJ_pmx(pxo); 00119 00120 /* Copy Dx and Dy to FIX format */ 00121 pmx->fxDx = FLOATOBJ_GetFix(&pmx->efDx); 00122 pmx->fxDy = FLOATOBJ_GetFix(&pmx->efDy); 00123 00124 pmx->flAccel = 0; 00125 00126 if (FLOATOBJ_Equal0(&pmx->efDx) && 00127 FLOATOBJ_Equal0(&pmx->efDy)) 00128 { 00129 pmx->flAccel |= XFORM_NO_TRANSLATION; 00130 } 00131 00132 if (FLOATOBJ_Equal0(&pmx->efM12) && 00133 FLOATOBJ_Equal0(&pmx->efM21)) 00134 { 00135 pmx->flAccel |= XFORM_SCALE; 00136 } 00137 00138 if (FLOATOBJ_Equal1(&pmx->efM11) && 00139 FLOATOBJ_Equal1(&pmx->efM22)) 00140 { 00141 pmx->flAccel |= XFORM_UNITY; 00142 } 00143 00144 if (FLOATOBJ_IsLong(&pmx->efM11) && FLOATOBJ_IsLong(&pmx->efM12) && 00145 FLOATOBJ_IsLong(&pmx->efM21) && FLOATOBJ_IsLong(&pmx->efM22)) 00146 { 00147 pmx->flAccel |= XFORM_INTEGER; 00148 } 00149 00150 return HintFromAccel(pmx->flAccel); 00151 } 00152 00153 00154 ULONG 00155 NTAPI 00156 XFORMOBJ_iSetXform( 00157 OUT XFORMOBJ *pxo, 00158 IN const XFORML *pxform) 00159 { 00160 PMATRIX pmx = XFORMOBJ_pmx(pxo); 00161 00162 /* Check parameters */ 00163 if (!pxo || !pxform) return DDI_ERROR; 00164 00165 /* Check if the xform is valid */ 00166 if ((pxform->eM11 == 0) || (pxform->eM22 == 0)) return DDI_ERROR; 00167 00168 /* Copy members */ 00169 FLOATOBJ_SetFloat(&pmx->efM11, pxform->eM11); 00170 FLOATOBJ_SetFloat(&pmx->efM12, pxform->eM12); 00171 FLOATOBJ_SetFloat(&pmx->efM21, pxform->eM21); 00172 FLOATOBJ_SetFloat(&pmx->efM22, pxform->eM22); 00173 FLOATOBJ_SetFloat(&pmx->efDx, pxform->eDx); 00174 FLOATOBJ_SetFloat(&pmx->efDy, pxform->eDy); 00175 00176 /* Update accelerators and return complexity */ 00177 return XFORMOBJ_UpdateAccel(pxo); 00178 } 00179 00180 00181 /* 00182 * Multiplies pxo1 with pxo2 and stores the result in pxo. 00183 * returns complexity hint 00184 * | efM11 efM12 0 | 00185 * | efM21 efM22 0 | 00186 * | efDx efDy 1 | 00187 */ 00188 ULONG 00189 NTAPI 00190 XFORMOBJ_iCombine( 00191 IN XFORMOBJ *pxo, 00192 IN XFORMOBJ *pxo1, 00193 IN XFORMOBJ *pxo2) 00194 { 00195 MATRIX mx; 00196 PMATRIX pmx, pmx1, pmx2; 00197 00198 pmx = XFORMOBJ_pmx(pxo); 00199 pmx1 =XFORMOBJ_pmx(pxo1); 00200 pmx2 = XFORMOBJ_pmx(pxo2); 00201 00202 /* Do a 3 x 3 matrix multiplication with mx as destinantion */ 00203 MulAdd(&mx.efM11, &pmx1->efM11, &pmx2->efM11, &pmx1->efM12, &pmx2->efM21); 00204 MulAdd(&mx.efM12, &pmx1->efM11, &pmx2->efM12, &pmx1->efM12, &pmx2->efM22); 00205 MulAdd(&mx.efM21, &pmx1->efM21, &pmx2->efM11, &pmx1->efM22, &pmx2->efM21); 00206 MulAdd(&mx.efM22, &pmx1->efM21, &pmx2->efM12, &pmx1->efM22, &pmx2->efM22); 00207 MulAdd(&mx.efDx, &pmx1->efDx, &pmx2->efM11, &pmx1->efDy, &pmx2->efM21); 00208 FLOATOBJ_Add(&mx.efDx, &pmx2->efDx); 00209 MulAdd(&mx.efDy, &pmx1->efDx, &pmx2->efM12, &pmx1->efDy, &pmx2->efM22); 00210 FLOATOBJ_Add(&mx.efDy, &pmx2->efDy); 00211 00212 /* Copy back */ 00213 *pmx = mx; 00214 00215 /* Update accelerators and return complexity */ 00216 return XFORMOBJ_UpdateAccel(pxo); 00217 } 00218 00219 00220 ULONG 00221 NTAPI 00222 XFORMOBJ_iCombineXform( 00223 IN XFORMOBJ *pxo, 00224 IN XFORMOBJ *pxo1, 00225 IN XFORML *pxform, 00226 IN BOOL bLeftMultiply) 00227 { 00228 MATRIX mx; 00229 XFORMOBJ xo2; 00230 00231 XFORMOBJ_vInit(&xo2, &mx); 00232 XFORMOBJ_iSetXform(&xo2, pxform); 00233 00234 if (bLeftMultiply) 00235 { 00236 return XFORMOBJ_iCombine(pxo, &xo2, pxo1); 00237 } 00238 else 00239 { 00240 return XFORMOBJ_iCombine(pxo, pxo1, &xo2); 00241 } 00242 } 00243 00244 /* 00245 * A^-1 = adj(A) / det(AT) 00246 * A^-1 = 1/(a*d - b*c) * (a22,-a12,a21,-a11) 00247 */ 00248 ULONG 00249 NTAPI 00250 XFORMOBJ_iInverse( 00251 OUT XFORMOBJ *pxoDst, 00252 IN XFORMOBJ *pxoSrc) 00253 { 00254 PMATRIX pmxDst, pmxSrc; 00255 FLOATOBJ foDet; 00256 XFORM xformSrc; 00257 union 00258 { 00259 FLOAT Float; 00260 LONG Long; 00261 } eDet; 00262 00263 pmxDst = XFORMOBJ_pmx(pxoDst); 00264 pmxSrc = XFORMOBJ_pmx(pxoSrc); 00265 00266 XFORMOBJ_iGetXform(pxoSrc, (XFORML*)&xformSrc); 00267 00268 /* det = M11 * M22 - M12 * M21 */ 00269 MulSub(&foDet, &pmxSrc->efM11, &pmxSrc->efM22, &pmxSrc->efM12, &pmxSrc->efM21); 00270 00271 if (FLOATOBJ_Equal0(&foDet)) 00272 { 00273 /* Determinant is 0! */ 00274 return DDI_ERROR; 00275 } 00276 00277 eDet.Long = FLOATOBJ_GetFloat(&foDet); 00278 00279 /* Calculate adj(A) / det(A) */ 00280 pmxDst->efM11 = pmxSrc->efM22; 00281 FLOATOBJ_Div(&pmxDst->efM11, &foDet); 00282 pmxDst->efM22 = pmxSrc->efM11; 00283 FLOATOBJ_Div(&pmxDst->efM22, &foDet); 00284 00285 /* The other 2 are negative, negate foDet for that */ 00286 FLOATOBJ_Neg(&foDet); 00287 pmxDst->efM12 = pmxSrc->efM12; 00288 FLOATOBJ_Div(&pmxDst->efM12, &foDet); 00289 pmxDst->efM21 = pmxSrc->efM21; 00290 FLOATOBJ_Div(&pmxDst->efM21, &foDet); 00291 00292 /* Update accelerators and return complexity */ 00293 return XFORMOBJ_UpdateAccel(pxoDst); 00294 } 00295 00296 00297 BOOL 00298 NTAPI 00299 XFORMOBJ_bXformFixPoints( 00300 IN XFORMOBJ *pxo, 00301 IN ULONG cPoints, 00302 IN PPOINTL pptIn, 00303 OUT PPOINTL pptOut) 00304 { 00305 PMATRIX pmx; 00306 INT i; 00307 FLOATOBJ fo1, fo2; 00308 FLONG flAccel; 00309 00310 pmx = XFORMOBJ_pmx(pxo); 00311 flAccel = pmx->flAccel; 00312 00313 if ((flAccel & (XFORM_SCALE|XFORM_UNITY)) == (XFORM_SCALE|XFORM_UNITY)) 00314 { 00315 /* Identity transformation, nothing todo */ 00316 } 00317 else if (flAccel & XFORM_INTEGER) 00318 { 00319 if (flAccel & XFORM_UNITY) 00320 { 00321 /* 1-scale integer transform */ 00322 i = cPoints - 1; 00323 do 00324 { 00325 LONG x = pptIn[i].x + pptIn[i].y * FLOATOBJ_GetLong(&pmx->efM21); 00326 LONG y = pptIn[i].y + pptIn[i].x * FLOATOBJ_GetLong(&pmx->efM12); 00327 pptOut[i].y = y; 00328 pptOut[i].x = x; 00329 } 00330 while (--i >= 0); 00331 } 00332 else if (flAccel & XFORM_SCALE) 00333 { 00334 /* Diagonal integer transform */ 00335 i = cPoints - 1; 00336 do 00337 { 00338 pptOut[i].x = pptIn[i].x * FLOATOBJ_GetLong(&pmx->efM11); 00339 pptOut[i].y = pptIn[i].y * FLOATOBJ_GetLong(&pmx->efM22); 00340 } 00341 while (--i >= 0); 00342 } 00343 else 00344 { 00345 /* Full integer transform */ 00346 i = cPoints - 1; 00347 do 00348 { 00349 LONG x; 00350 x = pptIn[i].x * FLOATOBJ_GetLong(&pmx->efM11); 00351 x += pptIn[i].y * FLOATOBJ_GetLong(&pmx->efM21); 00352 pptOut[i].y = pptIn[i].y * FLOATOBJ_GetLong(&pmx->efM22); 00353 pptOut[i].y += pptIn[i].x * FLOATOBJ_GetLong(&pmx->efM12); 00354 pptOut[i].x = x; 00355 } 00356 while (--i >= 0); 00357 } 00358 } 00359 else if (flAccel & XFORM_UNITY) 00360 { 00361 /* 1-scale transform */ 00362 i = cPoints - 1; 00363 do 00364 { 00365 fo1 = pmx->efM21; 00366 FLOATOBJ_MulLong(&fo1, pptIn[i].y); 00367 fo2 = pmx->efM12; 00368 FLOATOBJ_MulLong(&fo2, pptIn[i].x); 00369 pptOut[i].x = pptIn[i].x + FLOATOBJ_GetLong(&fo1); 00370 pptOut[i].y = pptIn[i].y + FLOATOBJ_GetLong(&fo2); 00371 } 00372 while (--i >= 0); 00373 } 00374 else if (flAccel & XFORM_SCALE) 00375 { 00376 /* Diagonal float transform */ 00377 i = cPoints - 1; 00378 do 00379 { 00380 fo1 = pmx->efM11; 00381 FLOATOBJ_MulLong(&fo1, pptIn[i].x); 00382 pptOut[i].x = FLOATOBJ_GetLong(&fo1); 00383 fo2 = pmx->efM22; 00384 FLOATOBJ_MulLong(&fo2, pptIn[i].y); 00385 pptOut[i].y = FLOATOBJ_GetLong(&fo2); 00386 } 00387 while (--i >= 0); 00388 } 00389 else 00390 { 00391 /* Full float transform */ 00392 i = cPoints - 1; 00393 do 00394 { 00395 MulAddLong(&fo1, &pmx->efM11, pptIn[i].x, &pmx->efM21, pptIn[i].y); 00396 MulAddLong(&fo2, &pmx->efM12, pptIn[i].x, &pmx->efM22, pptIn[i].y); 00397 pptOut[i].x = FLOATOBJ_GetLong(&fo1); 00398 pptOut[i].y = FLOATOBJ_GetLong(&fo2); 00399 } 00400 while (--i >= 0); 00401 } 00402 00403 if (!(pmx->flAccel & XFORM_NO_TRANSLATION)) 00404 { 00405 /* Translate points */ 00406 i = cPoints - 1; 00407 do 00408 { 00409 pptOut[i].x += pmx->fxDx; 00410 pptOut[i].y += pmx->fxDy; 00411 } 00412 while (--i >= 0); 00413 } 00414 00415 return TRUE; 00416 } 00417 00420 // www.osr.com/ddk/graphics/gdifncs_0s2v.htm 00421 ULONG 00422 APIENTRY 00423 XFORMOBJ_iGetXform( 00424 IN XFORMOBJ *pxo, 00425 OUT XFORML *pxform) 00426 { 00427 PMATRIX pmx = XFORMOBJ_pmx(pxo); 00428 00429 /* Check parameters */ 00430 if (!pxo || !pxform) 00431 { 00432 return DDI_ERROR; 00433 } 00434 00435 /* Copy members */ 00436 pxform->eM11 = FLOATOBJ_GetFloat(&pmx->efM11); 00437 pxform->eM12 = FLOATOBJ_GetFloat(&pmx->efM12); 00438 pxform->eM21 = FLOATOBJ_GetFloat(&pmx->efM21); 00439 pxform->eM22 = FLOATOBJ_GetFloat(&pmx->efM22); 00440 pxform->eDx = FLOATOBJ_GetFloat(&pmx->efDx); 00441 pxform->eDy = FLOATOBJ_GetFloat(&pmx->efDy); 00442 00443 /* Return complexity hint */ 00444 return HintFromAccel(pmx->flAccel); 00445 } 00446 00447 00448 // www.osr.com/ddk/graphics/gdifncs_5ig7.htm 00449 ULONG 00450 APIENTRY 00451 XFORMOBJ_iGetFloatObjXform( 00452 IN XFORMOBJ *pxo, 00453 OUT FLOATOBJ_XFORM *pxfo) 00454 { 00455 PMATRIX pmx = XFORMOBJ_pmx(pxo); 00456 00457 /* Check parameters */ 00458 if (!pxo || !pxfo) 00459 { 00460 return DDI_ERROR; 00461 } 00462 00463 /* Copy members */ 00464 pxfo->eM11 = pmx->efM11; 00465 pxfo->eM12 = pmx->efM12; 00466 pxfo->eM21 = pmx->efM21; 00467 pxfo->eM22 = pmx->efM22; 00468 pxfo->eDx = pmx->efDx; 00469 pxfo->eDy = pmx->efDy; 00470 00471 /* Return complexity hint */ 00472 return HintFromAccel(pmx->flAccel); 00473 } 00474 00475 00476 // www.osr.com/ddk/graphics/gdifncs_027b.htm 00477 BOOL 00478 APIENTRY 00479 XFORMOBJ_bApplyXform( 00480 IN XFORMOBJ *pxo, 00481 IN ULONG iMode, 00482 IN ULONG cPoints, 00483 IN PVOID pvIn, 00484 OUT PVOID pvOut) 00485 { 00486 MATRIX mx; 00487 XFORMOBJ xoInv; 00488 POINTL *pptl; 00489 INT i; 00490 00491 /* Check parameters */ 00492 if (!pxo || !pvIn || !pvOut || cPoints < 1) 00493 { 00494 return FALSE; 00495 } 00496 00497 /* Use inverse xform? */ 00498 if (iMode == XF_INV_FXTOL || iMode == XF_INV_LTOL) 00499 { 00500 XFORMOBJ_vInit(&xoInv, &mx); 00501 if (XFORMOBJ_iInverse(&xoInv, pxo) == DDI_ERROR) 00502 { 00503 return FALSE; 00504 } 00505 pxo = &xoInv; 00506 } 00507 00508 /* Convert POINTL to POINTFIX? */ 00509 if (iMode == XF_LTOFX || iMode == XF_LTOL || iMode == XF_INV_LTOL) 00510 { 00511 pptl = pvIn; 00512 for (i = cPoints - 1; i >= 0; i--) 00513 { 00514 pptl[i].x = LONG2FIX(pptl[i].x); 00515 pptl[i].y = LONG2FIX(pptl[i].y); 00516 } 00517 } 00518 00519 /* Do the actual fixpoint transformation */ 00520 if (!XFORMOBJ_bXformFixPoints(pxo, cPoints, pvIn, pvOut)) 00521 { 00522 return FALSE; 00523 } 00524 00525 /* Convert POINTFIX to POINTL? */ 00526 if (iMode == XF_INV_FXTOL || iMode == XF_INV_LTOL || iMode == XF_LTOL) 00527 { 00528 pptl = pvOut; 00529 for (i = cPoints - 1; i >= 0; i--) 00530 { 00531 pptl[i].x = FIX2LONG(pptl[i].x); 00532 pptl[i].y = FIX2LONG(pptl[i].y); 00533 } 00534 } 00535 00536 return TRUE; 00537 } 00538 00539 /* EOF */ Generated on Sun May 27 2012 04:38:27 for ReactOS by
1.7.6.1
|