2 * PROJECT: ReactOS win32 kernel mode subsystem
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: subsystems/win32/win32k/objects/xformobj.c
5 * PURPOSE: XFORMOBJ api
6 * PROGRAMMER: Timo Kreuzer
9 /** Includes ******************************************************************/
15 C_ASSERT(sizeof(FIX
) == sizeof(LONG
));
16 #define FIX2LONG(x) ((x) >> 4)
17 #define LONG2FIX(x) ((x) << 4)
19 #define FLOATOBJ_Equal _FLOATOBJ_Equal
20 #define FLOATOBJ_GetLong _FLOATOBJ_GetLong
21 #define FLOATOBJ_GetFix _FLOATOBJ_GetFix
22 #define FLOATOBJ_IsLong _FLOATOBJ_IsLong
23 #define FLOATOBJ_Equal0 _FLOATOBJ_Equal0
24 #define FLOATOBJ_Equal1 _FLOATOBJ_Equal1
26 /** Inline helper functions ***************************************************/
29 * Inline helper to calculate pfo1 * pfo2 + pfo3 * pfo4
43 FLOATOBJ_Mul(pfoDest
, pfo2
);
45 FLOATOBJ_Mul(&foTmp
, pfo4
);
46 FLOATOBJ_Add(pfoDest
, &foTmp
);
50 * Inline helper to calculate pfo1 * l2 + pfo3 * l4
64 FLOATOBJ_MulLong(pfoDest
, l2
);
66 FLOATOBJ_MulLong(&foTmp
, l4
);
67 FLOATOBJ_Add(pfoDest
, &foTmp
);
71 * Inline helper to calculate pfo1 * pfo2 - pfo3 * pfo4
85 FLOATOBJ_Mul(pfoDest
, pfo2
);
87 FLOATOBJ_Mul(&foTmp
, pfo4
);
88 FLOATOBJ_Sub(pfoDest
, &foTmp
);
92 * Inline helper to get the complexity hint from flAccel
96 HintFromAccel(ULONG flAccel
)
98 switch (flAccel
& (MX_NOTRANSLATE
| MX_IDENTITYSCALE
| MX_SCALE
))
100 case (MX_SCALE
| MX_IDENTITYSCALE
| MX_NOTRANSLATE
):
102 case (MX_SCALE
| MX_IDENTITYSCALE
):
111 /** Internal functions ********************************************************/
115 XFORMOBJ_UpdateAccel(
118 PMATRIX pmx
= (PMATRIX
)pxo
;
120 /* Copy Dx and Dy to FIX format */
121 pmx
->fxDx
= FLOATOBJ_GetFix(&pmx
->efDx
);
122 pmx
->fxDy
= FLOATOBJ_GetFix(&pmx
->efDy
);
126 if (FLOATOBJ_Equal0(&pmx
->efDx
) &&
127 FLOATOBJ_Equal0(&pmx
->efDy
))
129 pmx
->flAccel
|= MX_NOTRANSLATE
;
132 if (FLOATOBJ_Equal0(&pmx
->efM12
) &&
133 FLOATOBJ_Equal0(&pmx
->efM21
))
135 pmx
->flAccel
|= MX_SCALE
;
138 if (FLOATOBJ_Equal1(&pmx
->efM11
) &&
139 FLOATOBJ_Equal1(&pmx
->efM22
))
141 pmx
->flAccel
|= MX_IDENTITYSCALE
;
144 if (FLOATOBJ_IsLong(&pmx
->efM11
) && FLOATOBJ_IsLong(&pmx
->efM12
) &&
145 FLOATOBJ_IsLong(&pmx
->efM21
) && FLOATOBJ_IsLong(&pmx
->efM22
))
147 pmx
->flAccel
|= MX_INTEGER
;
150 return HintFromAccel(pmx
->flAccel
);
160 PMATRIX pmx
= (PMATRIX
)pxo
;
162 /* Check parameters */
169 FLOATOBJ_SetFloat(&pmx
->efM11
, pxform
->eM11
);
170 FLOATOBJ_SetFloat(&pmx
->efM12
, pxform
->eM12
);
171 FLOATOBJ_SetFloat(&pmx
->efM21
, pxform
->eM21
);
172 FLOATOBJ_SetFloat(&pmx
->efM22
, pxform
->eM22
);
173 FLOATOBJ_SetFloat(&pmx
->efDx
, pxform
->eDx
);
174 FLOATOBJ_SetFloat(&pmx
->efDy
, pxform
->eDy
);
176 /* Update accelerators and return complexity */
177 return XFORMOBJ_UpdateAccel(pxo
);
182 * Multiplies pxo1 with pxo2 and stores the result in pxo.
183 * returns complexity hint
196 PMATRIX pmx
, pmx1
, pmx2
;
199 pmx1
= (PMATRIX
)pxo1
;
200 pmx2
= (PMATRIX
)pxo2
;
202 /* Do a 3 x 3 matrix multiplication with mx as destinantion */
203 MulAdd(&mx
.efM11
, &pmx1
->efM11
, &pmx2
->efM11
, &pmx1
->efM12
, &pmx2
->efM21
);
204 MulAdd(&mx
.efM12
, &pmx1
->efM11
, &pmx2
->efM12
, &pmx1
->efM12
, &pmx2
->efM22
);
205 MulAdd(&mx
.efM21
, &pmx1
->efM21
, &pmx2
->efM11
, &pmx1
->efM22
, &pmx2
->efM21
);
206 MulAdd(&mx
.efM22
, &pmx1
->efM21
, &pmx2
->efM12
, &pmx1
->efM22
, &pmx2
->efM22
);
207 MulAdd(&mx
.efDx
, &pmx1
->efDx
, &pmx2
->efM11
, &pmx1
->efDy
, &pmx2
->efM21
);
208 FLOATOBJ_Add(&mx
.efDx
, &pmx2
->efDx
);
209 MulAdd(&mx
.efDy
, &pmx1
->efDx
, &pmx2
->efM12
, &pmx1
->efDy
, &pmx2
->efM22
);
210 FLOATOBJ_Add(&mx
.efDy
, &pmx2
->efDy
);
215 /* Update accelerators and return complexity */
216 return XFORMOBJ_UpdateAccel(pxo
);
222 XFORMOBJ_iCombineXform(
226 IN BOOL bLeftMultiply
)
229 XFORMOBJ
*pxo2
= (XFORMOBJ
*)&mx
;
231 XFORMOBJ_iSetXform(pxo2
, pxform
);
235 return XFORMOBJ_iCombine(pxo
, pxo2
, pxo1
);
239 return XFORMOBJ_iCombine(pxo
, pxo1
, pxo2
);
244 * A^-1 = adj(A) / det(AT)
245 * A^-1 = 1/(a*d - b*c) * (a22,-a12,a21,-a11)
250 OUT XFORMOBJ
*pxoDst
,
253 PMATRIX pmxDst
, pmxSrc
;
256 pmxDst
= (PMATRIX
)pxoDst
;
257 pmxSrc
= (PMATRIX
)pxoSrc
;
259 /* det = M11 * M22 - M12 * M21 */
260 MulSub(&foDet
, &pmxSrc
->efM11
, &pmxSrc
->efM22
, &pmxSrc
->efM12
, &pmxSrc
->efM21
);
262 if (FLOATOBJ_Equal0(&foDet
))
264 /* Determinant is 0! */
268 /* Calculate adj(A) / det(A) */
269 pmxDst
->efM11
= pmxSrc
->efM22
;
270 FLOATOBJ_Div(&pmxDst
->efM11
, &foDet
);
271 pmxDst
->efM22
= pmxSrc
->efM11
;
272 FLOATOBJ_Div(&pmxDst
->efM22
, &foDet
);
274 /* The other 2 are negative, negate foDet for that */
275 FLOATOBJ_Neg(&foDet
);
276 pmxDst
->efM12
= pmxSrc
->efM21
;
277 FLOATOBJ_Div(&pmxDst
->efM12
, &foDet
);
278 pmxDst
->efM21
= pmxSrc
->efM12
;
279 FLOATOBJ_Div(&pmxDst
->efM22
, &foDet
);
281 /* Update accelerators and return complexity */
282 return XFORMOBJ_UpdateAccel(pxoDst
);
288 XFORMOBJ_bXformFixPoints(
300 flAccel
= pmx
->flAccel
& (MX_INTEGER
|MX_SCALE
|MX_IDENTITYSCALE
);
304 case (MX_SCALE
| MX_IDENTITYSCALE
):
305 case (MX_SCALE
| MX_IDENTITYSCALE
| MX_INTEGER
):
306 /* Identity transformation, nothing todo */
309 case (MX_IDENTITYSCALE
| MX_INTEGER
):
310 /* 1-scale integer transform */
314 LONG x
= pptIn
[i
].x
+ pptIn
[i
].y
* FLOATOBJ_GetLong(&pmx
->efM21
);
315 LONG y
= pptIn
[i
].y
+ pptIn
[i
].x
* FLOATOBJ_GetLong(&pmx
->efM12
);
322 case (MX_SCALE
| MX_INTEGER
):
323 /* Diagonal integer transform */
327 pptOut
[i
].x
= pptIn
[i
].x
* FLOATOBJ_GetLong(&pmx
->efM11
);
328 pptOut
[i
].y
= pptIn
[i
].y
* FLOATOBJ_GetLong(&pmx
->efM22
);
334 /* Full integer transform */
339 x
= pptIn
[i
].x
* FLOATOBJ_GetLong(&pmx
->efM11
);
340 x
+= pptIn
[i
].y
* FLOATOBJ_GetLong(&pmx
->efM21
);
341 pptOut
[i
].y
= pptIn
[i
].y
* FLOATOBJ_GetLong(&pmx
->efM22
);
342 pptOut
[i
].y
+= pptIn
[i
].x
* FLOATOBJ_GetLong(&pmx
->efM12
);
348 case (MX_IDENTITYSCALE
):
349 /* 1-scale transform */
354 FLOATOBJ_MulLong(&fo1
, pptIn
[i
].y
);
356 FLOATOBJ_MulLong(&fo2
, pptIn
[i
].x
);
357 pptOut
[i
].x
= pptIn
[i
].x
+ FLOATOBJ_GetLong(&fo1
);
358 pptOut
[i
].y
= pptIn
[i
].y
+ FLOATOBJ_GetLong(&fo2
);
364 /* Diagonal float transform */
369 FLOATOBJ_MulLong(&fo1
, pptIn
[i
].x
);
370 pptOut
[i
].x
= FLOATOBJ_GetLong(&fo1
);
372 FLOATOBJ_MulLong(&fo2
, pptIn
[i
].y
);
373 pptOut
[i
].y
= FLOATOBJ_GetLong(&fo2
);
379 /* Full float transform */
383 MulAddLong(&fo1
, &pmx
->efM11
, pptIn
[i
].x
, &pmx
->efM21
, pptIn
[i
].y
);
384 MulAddLong(&fo2
, &pmx
->efM12
, pptIn
[i
].x
, &pmx
->efM22
, pptIn
[i
].y
);
385 pptOut
[i
].x
= FLOATOBJ_GetLong(&fo1
);
386 pptOut
[i
].y
= FLOATOBJ_GetLong(&fo2
);
392 if (!(pmx
->flAccel
& MX_NOTRANSLATE
))
394 /* Translate points */
398 // DPRINT1("Translating Points (%d,%d)->(%d,%d)\n", pptOut[i].x, pptOut[i].y, pptOut[i].x + pmx->fxDx, pptOut[i].y + pmx->fxDy);
399 pptOut
[i
].x
+= pmx
->fxDx
;
400 pptOut
[i
].y
+= pmx
->fxDy
;
408 /** Public functions **********************************************************/
410 // www.osr.com/ddk/graphics/gdifncs_0s2v.htm
417 PMATRIX pmx
= (PMATRIX
)pxo
;
419 /* Check parameters */
426 pxform
->eM11
= FLOATOBJ_GetFloat(&pmx
->efM11
);
427 pxform
->eM12
= FLOATOBJ_GetFloat(&pmx
->efM12
);
428 pxform
->eM21
= FLOATOBJ_GetFloat(&pmx
->efM21
);
429 pxform
->eM22
= FLOATOBJ_GetFloat(&pmx
->efM22
);
430 pxform
->eDx
= FLOATOBJ_GetFloat(&pmx
->efDx
);
431 pxform
->eDy
= FLOATOBJ_GetFloat(&pmx
->efDy
);
433 /* Return complexity hint */
434 return HintFromAccel(pmx
->flAccel
);
438 // www.osr.com/ddk/graphics/gdifncs_5ig7.htm
441 XFORMOBJ_iGetFloatObjXform(
443 OUT FLOATOBJ_XFORM
*pxfo
)
445 PMATRIX pmx
= (PMATRIX
)pxo
;
447 /* Check parameters */
454 pxfo
->eM11
= pmx
->efM11
;
455 pxfo
->eM12
= pmx
->efM12
;
456 pxfo
->eM21
= pmx
->efM21
;
457 pxfo
->eM22
= pmx
->efM22
;
458 pxfo
->eDx
= pmx
->efDx
;
459 pxfo
->eDy
= pmx
->efDy
;
461 /* Return complexity hint */
462 return HintFromAccel(pmx
->flAccel
);
466 // www.osr.com/ddk/graphics/gdifncs_027b.htm
469 XFORMOBJ_bApplyXform(
480 /* Check parameters */
481 if (!pxo
|| !pvIn
|| !pvOut
|| cPoints
< 1)
486 /* Use inverse xform? */
487 if (iMode
== XF_INV_FXTOL
|| iMode
== XF_INV_LTOL
)
490 ret
= XFORMOBJ_Inverse((XFORMOBJ
*)&mx
, pxo
);
491 if (ret
== DDI_ERROR
)
495 pxo
= (XFORMOBJ
*)&mx
;
498 /* Convert POINTL to POINTFIX? */
499 if (iMode
== XF_LTOFX
|| iMode
== XF_LTOL
|| iMode
== XF_INV_LTOL
)
502 for (i
= cPoints
- 1; i
>= 0; i
--)
504 pptl
[i
].x
= LONG2FIX(pptl
[i
].x
);
505 pptl
[i
].y
= LONG2FIX(pptl
[i
].y
);
509 /* Do the actual fixpoint transformation */
510 if (!XFORMOBJ_bXformFixPoints(pxo
, cPoints
, pvIn
, pvOut
))
515 /* Convert POINTFIX to POINTL? */
516 if (iMode
== XF_INV_FXTOL
|| iMode
== XF_INV_LTOL
|| iMode
== XF_LTOL
)
519 for (i
= cPoints
- 1; i
>= 0; i
--)
521 pptl
[i
].x
= FIX2LONG(pptl
[i
].x
);
522 pptl
[i
].y
= FIX2LONG(pptl
[i
].y
);