f2adad31b05967d64373fd15bd491ea83e58fe9a
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
& (XFORM_SCALE
|XFORM_UNITY
|XFORM_NO_TRANSLATION
))
100 case (XFORM_SCALE
|XFORM_UNITY
|XFORM_NO_TRANSLATION
):
102 case (XFORM_SCALE
|XFORM_UNITY
):
111 /** Internal functions ********************************************************/
115 XFORMOBJ_UpdateAccel(
118 PMATRIX pmx
= XFORMOBJ_pmx(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
|= XFORM_NO_TRANSLATION
;
132 if (FLOATOBJ_Equal0(&pmx
->efM12
) &&
133 FLOATOBJ_Equal0(&pmx
->efM21
))
135 pmx
->flAccel
|= XFORM_SCALE
;
138 if (FLOATOBJ_Equal1(&pmx
->efM11
) &&
139 FLOATOBJ_Equal1(&pmx
->efM22
))
141 pmx
->flAccel
|= XFORM_UNITY
;
144 if (FLOATOBJ_IsLong(&pmx
->efM11
) && FLOATOBJ_IsLong(&pmx
->efM12
) &&
145 FLOATOBJ_IsLong(&pmx
->efM21
) && FLOATOBJ_IsLong(&pmx
->efM22
))
147 pmx
->flAccel
|= XFORM_INTEGER
;
150 return HintFromAccel(pmx
->flAccel
);
158 IN
const XFORML
*pxform
)
160 PMATRIX pmx
= XFORMOBJ_pmx(pxo
);
162 /* Check parameters */
163 if (!pxo
|| !pxform
) return DDI_ERROR
;
165 /* Check if the xform is valid */
166 if ((pxform
->eM11
== 0) || (pxform
->eM22
== 0)) return DDI_ERROR
;
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
;
198 pmx
= XFORMOBJ_pmx(pxo
);
199 pmx1
=XFORMOBJ_pmx(pxo1
);
200 pmx2
= XFORMOBJ_pmx(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
)
231 XFORMOBJ_vInit(&xo2
, &mx
);
232 XFORMOBJ_iSetXform(&xo2
, pxform
);
236 return XFORMOBJ_iCombine(pxo
, &xo2
, pxo1
);
240 return XFORMOBJ_iCombine(pxo
, pxo1
, &xo2
);
245 * A^-1 = adj(A) / det(AT)
246 * A^-1 = 1/(a*d - b*c) * (a22,-a12,a21,-a11)
251 OUT XFORMOBJ
*pxoDst
,
254 PMATRIX pmxDst
, pmxSrc
;
258 pmxDst
= XFORMOBJ_pmx(pxoDst
);
259 pmxSrc
= XFORMOBJ_pmx(pxoSrc
);
261 XFORMOBJ_iGetXform(pxoSrc
, (XFORML
*)&xformSrc
);
263 /* det = M11 * M22 - M12 * M21 */
264 MulSub(&foDet
, &pmxSrc
->efM11
, &pmxSrc
->efM22
, &pmxSrc
->efM12
, &pmxSrc
->efM21
);
266 if (FLOATOBJ_Equal0(&foDet
))
268 /* Determinant is 0! */
272 /* Calculate adj(A) / det(A) */
273 pmxDst
->efM11
= pmxSrc
->efM22
;
274 FLOATOBJ_Div(&pmxDst
->efM11
, &foDet
);
275 pmxDst
->efM22
= pmxSrc
->efM11
;
276 FLOATOBJ_Div(&pmxDst
->efM22
, &foDet
);
278 /* The other 2 are negative, negate foDet for that */
279 FLOATOBJ_Neg(&foDet
);
280 pmxDst
->efM12
= pmxSrc
->efM12
;
281 FLOATOBJ_Div(&pmxDst
->efM12
, &foDet
);
282 pmxDst
->efM21
= pmxSrc
->efM21
;
283 FLOATOBJ_Div(&pmxDst
->efM21
, &foDet
);
285 /* Calculate the inverted x shift: Dx' = -Dx * M11' - Dy * M21' */
286 pmxDst
->efDx
= pmxSrc
->efDx
;
287 FLOATOBJ_Neg(&pmxDst
->efDx
);
288 MulSub(&pmxDst
->efDx
, &pmxDst
->efDx
, &pmxDst
->efM11
, &pmxSrc
->efDy
, &pmxDst
->efM21
);
290 /* Calculate the inverted y shift: Dy' = -Dy * M22' - Dx * M12' */
291 pmxDst
->efDy
= pmxSrc
->efDy
;
292 FLOATOBJ_Neg(&pmxDst
->efDy
);
293 MulSub(&pmxDst
->efDy
, &pmxDst
->efDy
, &pmxDst
->efM22
, &pmxSrc
->efDx
, &pmxDst
->efM12
);
295 /* Update accelerators and return complexity */
296 return XFORMOBJ_UpdateAccel(pxoDst
);
302 XFORMOBJ_bXformFixPoints(
313 pmx
= XFORMOBJ_pmx(pxo
);
314 flAccel
= pmx
->flAccel
;
316 if ((flAccel
& (XFORM_SCALE
|XFORM_UNITY
)) == (XFORM_SCALE
|XFORM_UNITY
))
318 /* Identity transformation, nothing todo */
320 else if (flAccel
& XFORM_INTEGER
)
322 if (flAccel
& XFORM_UNITY
)
324 /* 1-scale integer transform */
328 LONG x
= pptIn
[i
].x
+ pptIn
[i
].y
* FLOATOBJ_GetLong(&pmx
->efM21
);
329 LONG y
= pptIn
[i
].y
+ pptIn
[i
].x
* FLOATOBJ_GetLong(&pmx
->efM12
);
335 else if (flAccel
& XFORM_SCALE
)
337 /* Diagonal integer transform */
341 pptOut
[i
].x
= pptIn
[i
].x
* FLOATOBJ_GetLong(&pmx
->efM11
);
342 pptOut
[i
].y
= pptIn
[i
].y
* FLOATOBJ_GetLong(&pmx
->efM22
);
348 /* Full integer transform */
353 x
= pptIn
[i
].x
* FLOATOBJ_GetLong(&pmx
->efM11
);
354 x
+= pptIn
[i
].y
* FLOATOBJ_GetLong(&pmx
->efM21
);
355 pptOut
[i
].y
= pptIn
[i
].y
* FLOATOBJ_GetLong(&pmx
->efM22
);
356 pptOut
[i
].y
+= pptIn
[i
].x
* FLOATOBJ_GetLong(&pmx
->efM12
);
362 else if (flAccel
& XFORM_UNITY
)
364 /* 1-scale transform */
369 FLOATOBJ_MulLong(&fo1
, pptIn
[i
].y
);
371 FLOATOBJ_MulLong(&fo2
, pptIn
[i
].x
);
372 pptOut
[i
].x
= pptIn
[i
].x
+ FLOATOBJ_GetLong(&fo1
);
373 pptOut
[i
].y
= pptIn
[i
].y
+ FLOATOBJ_GetLong(&fo2
);
377 else if (flAccel
& XFORM_SCALE
)
379 /* Diagonal float transform */
384 FLOATOBJ_MulLong(&fo1
, pptIn
[i
].x
);
385 pptOut
[i
].x
= FLOATOBJ_GetLong(&fo1
);
387 FLOATOBJ_MulLong(&fo2
, pptIn
[i
].y
);
388 pptOut
[i
].y
= FLOATOBJ_GetLong(&fo2
);
394 /* Full float transform */
398 MulAddLong(&fo1
, &pmx
->efM11
, pptIn
[i
].x
, &pmx
->efM21
, pptIn
[i
].y
);
399 MulAddLong(&fo2
, &pmx
->efM12
, pptIn
[i
].x
, &pmx
->efM22
, pptIn
[i
].y
);
400 pptOut
[i
].x
= FLOATOBJ_GetLong(&fo1
);
401 pptOut
[i
].y
= FLOATOBJ_GetLong(&fo2
);
406 if (!(pmx
->flAccel
& XFORM_NO_TRANSLATION
))
408 /* Translate points */
412 pptOut
[i
].x
+= pmx
->fxDx
;
413 pptOut
[i
].y
+= pmx
->fxDy
;
421 /** Public functions **********************************************************/
423 // www.osr.com/ddk/graphics/gdifncs_0s2v.htm
430 PMATRIX pmx
= XFORMOBJ_pmx(pxo
);
432 /* Check parameters */
439 pxform
->eM11
= FLOATOBJ_GetFloat(&pmx
->efM11
);
440 pxform
->eM12
= FLOATOBJ_GetFloat(&pmx
->efM12
);
441 pxform
->eM21
= FLOATOBJ_GetFloat(&pmx
->efM21
);
442 pxform
->eM22
= FLOATOBJ_GetFloat(&pmx
->efM22
);
443 pxform
->eDx
= FLOATOBJ_GetFloat(&pmx
->efDx
);
444 pxform
->eDy
= FLOATOBJ_GetFloat(&pmx
->efDy
);
446 /* Return complexity hint */
447 return HintFromAccel(pmx
->flAccel
);
451 // www.osr.com/ddk/graphics/gdifncs_5ig7.htm
454 XFORMOBJ_iGetFloatObjXform(
456 OUT FLOATOBJ_XFORM
*pxfo
)
458 PMATRIX pmx
= XFORMOBJ_pmx(pxo
);
460 /* Check parameters */
467 pxfo
->eM11
= pmx
->efM11
;
468 pxfo
->eM12
= pmx
->efM12
;
469 pxfo
->eM21
= pmx
->efM21
;
470 pxfo
->eM22
= pmx
->efM22
;
471 pxfo
->eDx
= pmx
->efDx
;
472 pxfo
->eDy
= pmx
->efDy
;
474 /* Return complexity hint */
475 return HintFromAccel(pmx
->flAccel
);
479 // www.osr.com/ddk/graphics/gdifncs_027b.htm
482 XFORMOBJ_bApplyXform(
494 /* Check parameters */
495 if (!pxo
|| !pvIn
|| !pvOut
|| cPoints
< 1)
500 /* Use inverse xform? */
501 if (iMode
== XF_INV_FXTOL
|| iMode
== XF_INV_LTOL
)
503 XFORMOBJ_vInit(&xoInv
, &mx
);
504 if (XFORMOBJ_iInverse(&xoInv
, pxo
) == DDI_ERROR
)
511 /* Convert POINTL to POINTFIX? */
512 if (iMode
== XF_LTOFX
|| iMode
== XF_LTOL
|| iMode
== XF_INV_LTOL
)
515 for (i
= cPoints
- 1; i
>= 0; i
--)
517 pptl
[i
].x
= LONG2FIX(pptl
[i
].x
);
518 pptl
[i
].y
= LONG2FIX(pptl
[i
].y
);
522 /* Do the actual fixpoint transformation */
523 if (!XFORMOBJ_bXformFixPoints(pxo
, cPoints
, pvIn
, pvOut
))
528 /* Convert POINTFIX to POINTL? */
529 if (iMode
== XF_INV_FXTOL
|| iMode
== XF_INV_LTOL
|| iMode
== XF_LTOL
)
532 for (i
= cPoints
- 1; i
>= 0; i
--)
534 pptl
[i
].x
= FIX2LONG(pptl
[i
].x
);
535 pptl
[i
].y
= FIX2LONG(pptl
[i
].y
);