1 /*
2 * PROJECT: ReactOS win32 kernel mode subsystem
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: win32ss/gdi/ntgdi/xformobj.c
5 * PURPOSE: XFORMOBJ API
6 * PROGRAMMERS: Timo Kreuzer
7 * Katayama Hirofumi MZ
8 */
9
10 /** Includes ******************************************************************/
11
12 #include <win32k.h>
13 #define NDEBUG
14 #include <debug.h>
15
16 #define DOES_VALUE_OVERFLOW_LONG(x) \
17 (((__int64)((long)(x))) != (x))
18
19 /** Inline helper functions ***************************************************/
20
21 /*
22 * Inline helper to calculate pfo1 * pfo2 + pfo3 * pfo4
23 */
24 FORCEINLINE
25 VOID
MulAdd(PFLOATOBJ pfoDest,PFLOATOBJ pfo1,PFLOATOBJ pfo2,PFLOATOBJ pfo3,PFLOATOBJ pfo4)26 MulAdd(
27 PFLOATOBJ pfoDest,
28 PFLOATOBJ pfo1,
29 PFLOATOBJ pfo2,
30 PFLOATOBJ pfo3,
31 PFLOATOBJ pfo4)
32 {
33 FLOATOBJ foTmp;
34
35 *pfoDest = *pfo1;
36 FLOATOBJ_Mul(pfoDest, pfo2);
37 foTmp = *pfo3;
38 FLOATOBJ_Mul(&foTmp, pfo4);
39 FLOATOBJ_Add(pfoDest, &foTmp);
40 }
41
42 /*
43 * Inline helper to calculate pfo1 * l2 + pfo3 * l4
44 */
45 FORCEINLINE
46 VOID
MulAddLong(PFLOATOBJ pfoDest,PFLOATOBJ pfo1,LONG l2,PFLOATOBJ pfo3,LONG l4)47 MulAddLong(
48 PFLOATOBJ pfoDest,
49 PFLOATOBJ pfo1,
50 LONG l2,
51 PFLOATOBJ pfo3,
52 LONG l4)
53 {
54 FLOATOBJ foTmp;
55
56 *pfoDest = *pfo1;
57 FLOATOBJ_MulLong(pfoDest, l2);
58 foTmp = *pfo3;
59 FLOATOBJ_MulLong(&foTmp, l4);
60 FLOATOBJ_Add(pfoDest, &foTmp);
61 }
62
63 /*
64 * Inline helper to calculate pfo1 * pfo2 - pfo3 * pfo4
65 */
66 FORCEINLINE
67 VOID
MulSub(PFLOATOBJ pfoDest,PFLOATOBJ pfo1,PFLOATOBJ pfo2,PFLOATOBJ pfo3,PFLOATOBJ pfo4)68 MulSub(
69 PFLOATOBJ pfoDest,
70 PFLOATOBJ pfo1,
71 PFLOATOBJ pfo2,
72 PFLOATOBJ pfo3,
73 PFLOATOBJ pfo4)
74 {
75 FLOATOBJ foTmp;
76
77 *pfoDest = *pfo1;
78 FLOATOBJ_Mul(pfoDest, pfo2);
79 foTmp = *pfo3;
80 FLOATOBJ_Mul(&foTmp, pfo4);
81 FLOATOBJ_Sub(pfoDest, &foTmp);
82 }
83
84 /*
85 * Inline helper to get the complexity hint from flAccel
86 */
87 FORCEINLINE
88 ULONG
HintFromAccel(ULONG flAccel)89 HintFromAccel(ULONG flAccel)
90 {
91 switch (flAccel & (XFORM_SCALE|XFORM_UNITY|XFORM_NO_TRANSLATION))
92 {
93 case (XFORM_SCALE|XFORM_UNITY|XFORM_NO_TRANSLATION):
94 return GX_IDENTITY;
95 case (XFORM_SCALE|XFORM_UNITY):
96 return GX_OFFSET;
97 case XFORM_SCALE:
98 return GX_SCALE;
99 default:
100 return GX_GENERAL;
101 }
102 }
103
104 /** Internal functions ********************************************************/
105
106 ULONG
107 FASTCALL
MX_UpdateAccel(IN OUT PMATRIX pmx)108 MX_UpdateAccel(IN OUT PMATRIX pmx)
109 {
110 /* Copy Dx and Dy to FIX format */
111 pmx->fxDx = FLOATOBJ_GetFix(&pmx->efDx);
112 pmx->fxDy = FLOATOBJ_GetFix(&pmx->efDy);
113
114 pmx->flAccel = 0;
115
116 if (FLOATOBJ_Equal0(&pmx->efDx) &&
117 FLOATOBJ_Equal0(&pmx->efDy))
118 {
119 pmx->flAccel |= XFORM_NO_TRANSLATION;
120 }
121
122 if (FLOATOBJ_Equal0(&pmx->efM12) &&
123 FLOATOBJ_Equal0(&pmx->efM21))
124 {
125 pmx->flAccel |= XFORM_SCALE;
126 }
127
128 if (FLOATOBJ_Equal1(&pmx->efM11) &&
129 FLOATOBJ_Equal1(&pmx->efM22))
130 {
131 pmx->flAccel |= XFORM_UNITY;
132 }
133
134 if (FLOATOBJ_IsLong(&pmx->efM11) && FLOATOBJ_IsLong(&pmx->efM12) &&
135 FLOATOBJ_IsLong(&pmx->efM21) && FLOATOBJ_IsLong(&pmx->efM22))
136 {
137 pmx->flAccel |= XFORM_INTEGER;
138 }
139
140 return HintFromAccel(pmx->flAccel);
141 }
142
143 ULONG
144 NTAPI
XFORMOBJ_UpdateAccel(IN OUT XFORMOBJ * pxo)145 XFORMOBJ_UpdateAccel(
146 IN OUT XFORMOBJ *pxo)
147 {
148 PMATRIX pmx = XFORMOBJ_pmx(pxo);
149
150 return MX_UpdateAccel(pmx);
151 }
152
153
154 ULONG
155 NTAPI
XFORMOBJ_iSetXform(IN OUT XFORMOBJ * pxo,IN const XFORML * pxform)156 XFORMOBJ_iSetXform(
157 IN OUT XFORMOBJ *pxo,
158 IN const XFORML *pxform)
159 {
160 PMATRIX pmx;
161 MATRIX mxTemp;
162 ULONG Hint;
163
164 /* Check parameters */
165 if (!pxo || !pxform) return DDI_ERROR;
166
167 /* Copy members */
168 FLOATOBJ_SetFloat(&mxTemp.efM11, pxform->eM11);
169 FLOATOBJ_SetFloat(&mxTemp.efM12, pxform->eM12);
170 FLOATOBJ_SetFloat(&mxTemp.efM21, pxform->eM21);
171 FLOATOBJ_SetFloat(&mxTemp.efM22, pxform->eM22);
172 FLOATOBJ_SetFloat(&mxTemp.efDx, pxform->eDx);
173 FLOATOBJ_SetFloat(&mxTemp.efDy, pxform->eDy);
174
175 /* Update accelerators and return complexity */
176 Hint = MX_UpdateAccel(&mxTemp);
177
178 /* Check whether det = (M11 * M22 - M12 * M21) is non-zero */
179 if (Hint == GX_SCALE)
180 {
181 if (FLOATOBJ_Equal0(&mxTemp.efM11) || FLOATOBJ_Equal0(&mxTemp.efM22))
182 {
183 return DDI_ERROR;
184 }
185 }
186 else if (Hint == GX_GENERAL)
187 {
188 if (!MX_IsInvertible(&mxTemp))
189 {
190 return DDI_ERROR;
191 }
192 }
193
194 /* Store */
195 pmx = XFORMOBJ_pmx(pxo);
196 *pmx = mxTemp;
197
198 return Hint;
199 }
200
201
202 /*
203 * Multiplies pxo1 with pxo2 and stores the result in pxo.
204 * returns complexity hint
205 * | efM11 efM12 0 |
206 * | efM21 efM22 0 |
207 * | efDx efDy 1 |
208 */
209 ULONG
210 NTAPI
XFORMOBJ_iCombine(IN OUT XFORMOBJ * pxo,IN XFORMOBJ * pxo1,IN XFORMOBJ * pxo2)211 XFORMOBJ_iCombine(
212 IN OUT XFORMOBJ *pxo,
213 IN XFORMOBJ *pxo1,
214 IN XFORMOBJ *pxo2)
215 {
216 MATRIX mx;
217 PMATRIX pmx, pmx1, pmx2;
218
219 /* Get the source matrices */
220 pmx1 = XFORMOBJ_pmx(pxo1);
221 pmx2 = XFORMOBJ_pmx(pxo2);
222
223 /* Do a 3 x 3 matrix multiplication with mx as destinantion */
224 MulAdd(&mx.efM11, &pmx1->efM11, &pmx2->efM11, &pmx1->efM12, &pmx2->efM21);
225 MulAdd(&mx.efM12, &pmx1->efM11, &pmx2->efM12, &pmx1->efM12, &pmx2->efM22);
226 MulAdd(&mx.efM21, &pmx1->efM21, &pmx2->efM11, &pmx1->efM22, &pmx2->efM21);
227 MulAdd(&mx.efM22, &pmx1->efM21, &pmx2->efM12, &pmx1->efM22, &pmx2->efM22);
228 MulAdd(&mx.efDx, &pmx1->efDx, &pmx2->efM11, &pmx1->efDy, &pmx2->efM21);
229 FLOATOBJ_Add(&mx.efDx, &pmx2->efDx);
230 MulAdd(&mx.efDy, &pmx1->efDx, &pmx2->efM12, &pmx1->efDy, &pmx2->efM22);
231 FLOATOBJ_Add(&mx.efDy, &pmx2->efDy);
232
233 /* Copy back */
234 pmx = XFORMOBJ_pmx(pxo);
235 *pmx = mx;
236
237 /* Update accelerators and return complexity */
238 return XFORMOBJ_UpdateAccel(pxo);
239 }
240
241
242 ULONG
243 NTAPI
XFORMOBJ_iCombineXform(IN OUT XFORMOBJ * pxo,IN XFORMOBJ * pxo1,IN XFORML * pxform,IN BOOL bLeftMultiply)244 XFORMOBJ_iCombineXform(
245 IN OUT XFORMOBJ *pxo,
246 IN XFORMOBJ *pxo1,
247 IN XFORML *pxform,
248 IN BOOL bLeftMultiply)
249 {
250 MATRIX mx;
251 XFORMOBJ xo2;
252
253 XFORMOBJ_vInit(&xo2, &mx);
254 XFORMOBJ_iSetXform(&xo2, pxform);
255
256 if (bLeftMultiply)
257 {
258 return XFORMOBJ_iCombine(pxo, &xo2, pxo1);
259 }
260 else
261 {
262 return XFORMOBJ_iCombine(pxo, pxo1, &xo2);
263 }
264 }
265
266 BOOL FASTCALL
MX_IsInvertible(IN PMATRIX pmx)267 MX_IsInvertible(IN PMATRIX pmx)
268 {
269 FLOATOBJ foDet;
270 MulSub(&foDet, &pmx->efM11, &pmx->efM22, &pmx->efM12, &pmx->efM21);
271 return !FLOATOBJ_Equal0(&foDet);
272 }
273
274 VOID FASTCALL
MX_Set0(OUT PMATRIX pmx)275 MX_Set0(OUT PMATRIX pmx)
276 {
277 FLOATOBJ_Set0(&pmx->efM11);
278 FLOATOBJ_Set0(&pmx->efM12);
279 FLOATOBJ_Set0(&pmx->efM21);
280 FLOATOBJ_Set0(&pmx->efM22);
281 FLOATOBJ_Set0(&pmx->efDx);
282 FLOATOBJ_Set0(&pmx->efDy);
283 }
284
285 /*
286 * A^-1 = adj(A) / det(AT)
287 * A^-1 = 1/(a*d - b*c) * (a22,-a12,a21,-a11)
288 */
289 ULONG
290 NTAPI
XFORMOBJ_iInverse(OUT XFORMOBJ * pxoDst,IN XFORMOBJ * pxoSrc)291 XFORMOBJ_iInverse(
292 OUT XFORMOBJ *pxoDst,
293 IN XFORMOBJ *pxoSrc)
294 {
295 PMATRIX pmxDst, pmxSrc;
296 FLOATOBJ foDet;
297 XFORM xformSrc;
298
299 pmxDst = XFORMOBJ_pmx(pxoDst);
300 pmxSrc = XFORMOBJ_pmx(pxoSrc);
301
302 XFORMOBJ_iGetXform(pxoSrc, (XFORML*)&xformSrc);
303
304 /* det = M11 * M22 - M12 * M21 */
305 MulSub(&foDet, &pmxSrc->efM11, &pmxSrc->efM22, &pmxSrc->efM12, &pmxSrc->efM21);
306
307 if (FLOATOBJ_Equal0(&foDet))
308 {
309 /* Determinant is 0! */
310 return DDI_ERROR;
311 }
312
313 /* Calculate adj(A) / det(A) */
314 pmxDst->efM11 = pmxSrc->efM22;
315 FLOATOBJ_Div(&pmxDst->efM11, &foDet);
316 pmxDst->efM22 = pmxSrc->efM11;
317 FLOATOBJ_Div(&pmxDst->efM22, &foDet);
318
319 /* The other 2 are negative, negate foDet for that */
320 FLOATOBJ_Neg(&foDet);
321 pmxDst->efM12 = pmxSrc->efM12;
322 FLOATOBJ_Div(&pmxDst->efM12, &foDet);
323 pmxDst->efM21 = pmxSrc->efM21;
324 FLOATOBJ_Div(&pmxDst->efM21, &foDet);
325
326 /* Calculate the inverted x shift: Dx' = -Dx * M11' - Dy * M21' */
327 pmxDst->efDx = pmxSrc->efDx;
328 FLOATOBJ_Neg(&pmxDst->efDx);
329 MulSub(&pmxDst->efDx, &pmxDst->efDx, &pmxDst->efM11, &pmxSrc->efDy, &pmxDst->efM21);
330
331 /* Calculate the inverted y shift: Dy' = -Dy * M22' - Dx * M12' */
332 pmxDst->efDy = pmxSrc->efDy;
333 FLOATOBJ_Neg(&pmxDst->efDy);
334 MulSub(&pmxDst->efDy, &pmxDst->efDy, &pmxDst->efM22, &pmxSrc->efDx, &pmxDst->efM12);
335
336 /* Update accelerators and return complexity */
337 return XFORMOBJ_UpdateAccel(pxoDst);
338 }
339
340
341 /*!
342 * \brief Transforms fix-point coordinates in an array of POINTL structures using
343 * the transformation matrix from the XFORMOBJ.
344 *
345 * \param pxo - Pointer to the XFORMOBJ
346 *
347 * \param cPoints - Number of coordinates to transform
348 *
349 * \param pptIn - Pointer to an array of POINTL structures containing the
350 * source coordinates.
351 *
352 * \param pptOut - Pointer to an array of POINTL structures, receiving the
353 * transformed coordinates. Can be the same as pptIn.
354 *
355 * \return TRUE if the operation was successful, FALSE if any of the calculations
356 * caused an integer overflow.
357 *
358 * \note If the function returns FALSE, it might still have written to the
359 * output buffer. If pptIn and pptOut are equal, the source coordinates
360 * might have been partly overwritten!
361 */
362 static
363 BOOL
364 NTAPI
XFORMOBJ_bXformFixPoints(_In_ XFORMOBJ * pxo,_In_ ULONG cPoints,_In_reads_ (cPoints)PPOINTL pptIn,_Out_writes_ (cPoints)PPOINTL pptOut)365 XFORMOBJ_bXformFixPoints(
366 _In_ XFORMOBJ *pxo,
367 _In_ ULONG cPoints,
368 _In_reads_(cPoints) PPOINTL pptIn,
369 _Out_writes_(cPoints) PPOINTL pptOut)
370 {
371 PMATRIX pmx;
372 INT i;
373 FLOATOBJ fo1, fo2;
374 FLONG flAccel;
375 LONG lM11, lM12, lM21, lM22, lTemp;
376 register LONGLONG llx, lly;
377
378 pmx = XFORMOBJ_pmx(pxo);
379 flAccel = pmx->flAccel;
380
381 if ((flAccel & (XFORM_SCALE|XFORM_UNITY)) == (XFORM_SCALE|XFORM_UNITY))
382 {
383 /* Identity transformation */
384 RtlCopyMemory(pptOut, pptIn, cPoints * sizeof(POINTL));
385 }
386 else if (flAccel & XFORM_INTEGER)
387 {
388 if (flAccel & XFORM_UNITY)
389 {
390 /* 1-scale integer transform, get the off-diagonal elements */
391 if (!FLOATOBJ_bConvertToLong(&pmx->efM12, &lM12) ||
392 !FLOATOBJ_bConvertToLong(&pmx->efM21, &lM21))
393 {
394 NT_ASSERT(FALSE);
395 return FALSE;
396 }
397
398 i = cPoints - 1;
399 do
400 {
401 /* Calculate x in 64 bit and check for overflow */
402 llx = Int32x32To64(pptIn[i].y, lM21) + pptIn[i].x;
403 if (DOES_VALUE_OVERFLOW_LONG(llx))
404 {
405 return FALSE;
406 }
407
408 /* Calculate y in 64 bit and check for overflow */
409 lly = Int32x32To64(pptIn[i].x, lM12) + pptIn[i].y;
410 if (DOES_VALUE_OVERFLOW_LONG(lly))
411 {
412 return FALSE;
413 }
414
415 /* Write back the results */
416 pptOut[i].x = (LONG)llx;
417 pptOut[i].y = (LONG)lly;
418 }
419 while (--i >= 0);
420 }
421 else if (flAccel & XFORM_SCALE)
422 {
423 /* Diagonal integer transform, get the diagonal elements */
424 if (!FLOATOBJ_bConvertToLong(&pmx->efM11, &lM11) ||
425 !FLOATOBJ_bConvertToLong(&pmx->efM22, &lM22))
426 {
427 NT_ASSERT(FALSE);
428 return FALSE;
429 }
430
431 i = cPoints - 1;
432 do
433 {
434 /* Calculate x in 64 bit and check for overflow */
435 llx = Int32x32To64(pptIn[i].x, lM11);
436 if (DOES_VALUE_OVERFLOW_LONG(llx))
437 {
438 return FALSE;
439 }
440
441 /* Calculate y in 64 bit and check for overflow */
442 lly = Int32x32To64(pptIn[i].y, lM22);
443 if (DOES_VALUE_OVERFLOW_LONG(lly))
444 {
445 return FALSE;
446 }
447
448 /* Write back the results */
449 pptOut[i].x = (LONG)llx;
450 pptOut[i].y = (LONG)lly;
451 }
452 while (--i >= 0);
453 }
454 else
455 {
456 /* Full integer transform */
457 if (!FLOATOBJ_bConvertToLong(&pmx->efM11, &lM11) ||
458 !FLOATOBJ_bConvertToLong(&pmx->efM12, &lM12) ||
459 !FLOATOBJ_bConvertToLong(&pmx->efM21, &lM21) ||
460 !FLOATOBJ_bConvertToLong(&pmx->efM22, &lM22))
461 {
462 NT_ASSERT(FALSE);
463 return FALSE;
464 }
465
466 i = cPoints - 1;
467 do
468 {
469 /* Calculate x in 64 bit and check for overflow */
470 llx = Int32x32To64(pptIn[i].x, lM11);
471 llx += Int32x32To64(pptIn[i].y, lM21);
472 if (DOES_VALUE_OVERFLOW_LONG(llx))
473 {
474 return FALSE;
475 }
476
477 /* Calculate y in 64 bit and check for overflow */
478 lly = Int32x32To64(pptIn[i].y, lM22);
479 lly += Int32x32To64(pptIn[i].x, lM12);
480 if (DOES_VALUE_OVERFLOW_LONG(lly))
481 {
482 return FALSE;
483 }
484
485 /* Write back the results */
486 pptOut[i].x = (LONG)llx;
487 pptOut[i].y = (LONG)lly;
488 }
489 while (--i >= 0);
490 }
491 }
492 else if (flAccel & XFORM_UNITY)
493 {
494 /* 1-scale transform */
495 i = cPoints - 1;
496 do
497 {
498 /* Calculate x in 64 bit and check for overflow */
499 fo1 = pmx->efM21;
500 FLOATOBJ_MulLong(&fo1, pptIn[i].y);
501 if (!FLOATOBJ_bConvertToLong(&fo1, &lTemp))
502 {
503 return FALSE;
504 }
505 llx = (LONGLONG)pptIn[i].x + lTemp;
506 if (DOES_VALUE_OVERFLOW_LONG(llx))
507 {
508 return FALSE;
509 }
510
511 /* Calculate y in 64 bit and check for overflow */
512 fo2 = pmx->efM12;
513 FLOATOBJ_MulLong(&fo2, pptIn[i].x);
514 if (!FLOATOBJ_bConvertToLong(&fo2, &lTemp))
515 {
516 return FALSE;
517 }
518 lly = (LONGLONG)pptIn[i].y + lTemp;
519 if (DOES_VALUE_OVERFLOW_LONG(lly))
520 {
521 return FALSE;
522 }
523
524 /* Write back the results */
525 pptOut[i].x = (LONG)llx;
526 pptOut[i].y = (LONG)lly;
527 }
528 while (--i >= 0);
529 }
530 else if (flAccel & XFORM_SCALE)
531 {
532 /* Diagonal float transform */
533 i = cPoints - 1;
534 do
535 {
536 fo1 = pmx->efM11;
537 FLOATOBJ_MulLong(&fo1, pptIn[i].x);
538 if (!FLOATOBJ_bConvertToLong(&fo1, &pptOut[i].x))
539 {
540 return FALSE;
541 }
542
543 fo2 = pmx->efM22;
544 FLOATOBJ_MulLong(&fo2, pptIn[i].y);
545 if (!FLOATOBJ_bConvertToLong(&fo2, &pptOut[i].y))
546 {
547 return FALSE;
548 }
549 }
550 while (--i >= 0);
551 }
552 else
553 {
554 /* Full float transform */
555 i = cPoints - 1;
556 do
557 {
558 /* Calculate x as FLOATOBJ */
559 MulAddLong(&fo1, &pmx->efM11, pptIn[i].x, &pmx->efM21, pptIn[i].y);
560
561 /* Calculate y as FLOATOBJ */
562 MulAddLong(&fo2, &pmx->efM12, pptIn[i].x, &pmx->efM22, pptIn[i].y);
563
564 if (!FLOATOBJ_bConvertToLong(&fo1, &pptOut[i].x))
565 {
566 return FALSE;
567 }
568
569 if (!FLOATOBJ_bConvertToLong(&fo2, &pptOut[i].y))
570 {
571 return FALSE;
572 }
573 }
574 while (--i >= 0);
575 }
576
577 if (!(pmx->flAccel & XFORM_NO_TRANSLATION))
578 {
579 /* Translate points */
580 i = cPoints - 1;
581 do
582 {
583 llx = (LONGLONG)pptOut[i].x + pmx->fxDx;
584 if (DOES_VALUE_OVERFLOW_LONG(llx))
585 {
586 return FALSE;
587 }
588 pptOut[i].x = (LONG)llx;
589
590 lly = (LONGLONG)pptOut[i].y + pmx->fxDy;
591 if (DOES_VALUE_OVERFLOW_LONG(lly))
592 {
593 return FALSE;
594 }
595 pptOut[i].y = (LONG)lly;
596 }
597 while (--i >= 0);
598 }
599
600 return TRUE;
601 }
602
603 /** Public functions **********************************************************/
604
605 // www.osr.com/ddk/graphics/gdifncs_0s2v.htm
606 ULONG
607 APIENTRY
XFORMOBJ_iGetXform(IN XFORMOBJ * pxo,OUT XFORML * pxform)608 XFORMOBJ_iGetXform(
609 IN XFORMOBJ *pxo,
610 OUT XFORML *pxform)
611 {
612 PMATRIX pmx = XFORMOBJ_pmx(pxo);
613
614 /* Check parameters */
615 if (!pxo || !pxform)
616 {
617 return DDI_ERROR;
618 }
619
620 /* Copy members */
621 pxform->eM11 = FLOATOBJ_GetFloat(&pmx->efM11);
622 pxform->eM12 = FLOATOBJ_GetFloat(&pmx->efM12);
623 pxform->eM21 = FLOATOBJ_GetFloat(&pmx->efM21);
624 pxform->eM22 = FLOATOBJ_GetFloat(&pmx->efM22);
625 pxform->eDx = FLOATOBJ_GetFloat(&pmx->efDx);
626 pxform->eDy = FLOATOBJ_GetFloat(&pmx->efDy);
627
628 /* Return complexity hint */
629 return HintFromAccel(pmx->flAccel);
630 }
631
632
633 // www.osr.com/ddk/graphics/gdifncs_5ig7.htm
634 ULONG
635 APIENTRY
XFORMOBJ_iGetFloatObjXform(IN XFORMOBJ * pxo,OUT FLOATOBJ_XFORM * pxfo)636 XFORMOBJ_iGetFloatObjXform(
637 IN XFORMOBJ *pxo,
638 OUT FLOATOBJ_XFORM *pxfo)
639 {
640 PMATRIX pmx = XFORMOBJ_pmx(pxo);
641
642 /* Check parameters */
643 if (!pxo || !pxfo)
644 {
645 return DDI_ERROR;
646 }
647
648 /* Copy members */
649 pxfo->eM11 = pmx->efM11;
650 pxfo->eM12 = pmx->efM12;
651 pxfo->eM21 = pmx->efM21;
652 pxfo->eM22 = pmx->efM22;
653 pxfo->eDx = pmx->efDx;
654 pxfo->eDy = pmx->efDy;
655
656 /* Return complexity hint */
657 return HintFromAccel(pmx->flAccel);
658 }
659
660
661 // www.osr.com/ddk/graphics/gdifncs_027b.htm
662 BOOL
663 APIENTRY
XFORMOBJ_bApplyXform(IN XFORMOBJ * pxo,IN ULONG iMode,IN ULONG cPoints,IN PVOID pvIn,OUT PVOID pvOut)664 XFORMOBJ_bApplyXform(
665 IN XFORMOBJ *pxo,
666 IN ULONG iMode,
667 IN ULONG cPoints,
668 IN PVOID pvIn,
669 OUT PVOID pvOut)
670 {
671 MATRIX mx;
672 XFORMOBJ xoInv;
673 PPOINTL pptlIn, pptlOut;
674 INT i;
675
676 /* Check parameters */
677 if (!pxo || !pvIn || !pvOut || cPoints < 1)
678 {
679 return FALSE;
680 }
681
682 /* Use inverse xform? */
683 if (iMode == XF_INV_FXTOL || iMode == XF_INV_LTOL)
684 {
685 XFORMOBJ_vInit(&xoInv, &mx);
686 if (XFORMOBJ_iInverse(&xoInv, pxo) == DDI_ERROR)
687 {
688 return FALSE;
689 }
690 pxo = &xoInv;
691 }
692
693 /* Convert POINTL to POINTFIX? */
694 if (iMode == XF_LTOFX || iMode == XF_LTOL || iMode == XF_INV_LTOL)
695 {
696 pptlIn = pvIn;
697 pptlOut = pvOut;
698 for (i = cPoints - 1; i >= 0; i--)
699 {
700 pptlOut[i].x = LONG2FIX(pptlIn[i].x);
701 pptlOut[i].y = LONG2FIX(pptlIn[i].y);
702 }
703
704 /* The input is in the out buffer now! */
705 pvIn = pvOut;
706 }
707
708 /* Do the actual fixpoint transformation */
709 if (!XFORMOBJ_bXformFixPoints(pxo, cPoints, pvIn, pvOut))
710 {
711 return FALSE;
712 }
713
714 /* Convert POINTFIX to POINTL? */
715 if (iMode == XF_INV_FXTOL || iMode == XF_INV_LTOL || iMode == XF_LTOL)
716 {
717 pptlOut = pvOut;
718 for (i = cPoints - 1; i >= 0; i--)
719 {
720 pptlOut[i].x = FIX2LONG(pptlOut[i].x);
721 pptlOut[i].y = FIX2LONG(pptlOut[i].y);
722 }
723 }
724
725 return TRUE;
726 }
727
728 /* EOF */
729