xref: /reactos/win32ss/gdi/gdi32/objects/coord.c (revision 44b11ad6)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS System Libraries
4  * FILE:            win32ss/gdi/gdi32/objects/coord.c
5  * PURPOSE:         Functions for coordinate transformation
6  * PROGRAMMER:
7  */
8 #include <precomp.h>
9 
10 /* Currently we use a MATRIX inside the DC_ATTR containing the
11    coordinate transformations, while we deal with XFORM structures
12    internally. If we move all coordinate transformation to gdi32,
13    we might as well have an XFORM structure in the DC_ATTR. */
14 void
15 MatrixToXForm(XFORM *pxform, const MATRIX *pmx)
16 {
17     XFORML *pxforml = (XFORML*)pxform;
18     pxforml->eM11 = FOtoF(&pmx->efM11);
19     pxforml->eM12 = FOtoF(&pmx->efM12);
20     pxforml->eM21 = FOtoF(&pmx->efM21);
21     pxforml->eM22 = FOtoF(&pmx->efM22);
22     pxforml->eDx = FOtoF(&pmx->efDx);
23     pxforml->eDy = FOtoF(&pmx->efDy);
24 }
25 
26 void
27 GdiTransformPoints2(
28     _In_ XFORM *pxform,
29     _Out_writes_(nCount) PPOINT pptOut,
30     _In_reads_(nCount) PPOINT pptIn,
31     _In_ ULONG nCount)
32 {
33     ULONG i;
34     FLOAT x, y;
35 
36     for (i = 0; i < nCount; i++)
37     {
38         x = pptIn[i].x * pxform->eM11 + pptIn[i].y * pxform->eM12 + pxform->eDx;
39         pptOut[i].x = _lrintf(x);
40         y = pptIn[i].x * pxform->eM21 + pptIn[i].y * pxform->eM22 + pxform->eDy;
41         pptOut[i].y = _lrintf(y);
42     }
43 }
44 
45 FORCEINLINE
46 void
47 GdiTransformPoints(
48     _In_ MATRIX *pmx,
49     _Out_writes_(nCount) PPOINT pptOut,
50     _In_reads_(nCount) PPOINT pptIn,
51     _In_ ULONG nCount)
52 {
53     XFORM xform;
54 
55     MatrixToXForm(&xform, pmx);
56     GdiTransformPoints2(&xform, pptOut, pptIn, nCount);
57 }
58 
59 #define MAX_OFFSET 4294967041.0
60 #define _fmul(x,y) (((x) == 0) ? 0 : (x) * (y))
61 
62 BOOL
63 WINAPI
64 CombineTransform(
65     _Out_ LPXFORM pxfResult,
66     _In_ const XFORM *pxf1,
67     _In_ const XFORM *pxf2)
68 {
69     XFORM xformTmp;
70 
71     /* Check paramters */
72     if (!pxfResult || !pxf1 || !pxf2) return FALSE;
73 
74     /* Do matrix multiplication, start with scaling elements */
75     xformTmp.eM11 = (pxf1->eM11 * pxf2->eM11) + (pxf1->eM12 * pxf2->eM21);
76     xformTmp.eM22 = (pxf1->eM21 * pxf2->eM12) + (pxf1->eM22 * pxf2->eM22);
77 
78     /* Calculate shear/rotate elements only of they are present */
79     if ((pxf1->eM12 != 0.) || (pxf1->eM21 != 0.) ||
80         (pxf2->eM12 != 0.) || (pxf2->eM21 != 0.))
81     {
82         xformTmp.eM12 = (pxf1->eM11 * pxf2->eM12) + (pxf1->eM12 * pxf2->eM22);
83         xformTmp.eM21 = (pxf1->eM21 * pxf2->eM11) + (pxf1->eM22 * pxf2->eM21);
84     }
85     else
86     {
87         xformTmp.eM12 = 0.;
88         xformTmp.eM21 = 0.;
89     }
90 
91     /* Calculate the offset */
92     xformTmp.eDx = _fmul(pxf1->eDx, pxf2->eM11) + _fmul(pxf1->eDy, pxf2->eM21) + pxf2->eDx;
93     xformTmp.eDy = _fmul(pxf1->eDx, pxf2->eM12) + _fmul(pxf1->eDy, pxf2->eM22) + pxf2->eDy;
94 
95     /* Check for invalid offset ranges */
96     if ((xformTmp.eDx > MAX_OFFSET) || (xformTmp.eDx < -MAX_OFFSET) ||
97         (xformTmp.eDy > MAX_OFFSET) || (xformTmp.eDy < -MAX_OFFSET))
98     {
99         return FALSE;
100     }
101 
102     /* All is ok, return the calculated values */
103     *pxfResult = xformTmp;
104     return TRUE;
105 }
106 
107 
108 /*
109  * @implemented
110  *
111  */
112 int
113 WINAPI
114 GetMapMode(
115     _In_ HDC hdc)
116 {
117     PDC_ATTR pdcattr;
118 
119     /* Get the DC attribute */
120     pdcattr = GdiGetDcAttr(hdc);
121     if (pdcattr == NULL)
122     {
123         SetLastError(ERROR_INVALID_PARAMETER);
124         return 0;
125     }
126 
127     /* Return the map mode */
128     return pdcattr->iMapMode;
129 }
130 
131 /*
132  * @implemented
133  */
134 INT
135 WINAPI
136 SetMapMode(
137     _In_ HDC hdc,
138     _In_ INT iMode)
139 {
140     PDC_ATTR pdcattr;
141 
142     /* Handle METADC16 here, since we don't have a DCATTR. */
143     if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE) \
144     {
145         return GetAndSetDCDWord(hdc, GdiGetSetMapMode, iMode, 0, 0, 0 );
146     }
147 
148     /* Get the DC attribute */
149     pdcattr = GdiGetDcAttr(hdc);
150     if (pdcattr == NULL)
151     {
152         SetLastError(ERROR_INVALID_PARAMETER);
153         return 0;
154     }
155 
156     /* Force change if Isotropic is set for recompute. */
157     if ((iMode != pdcattr->iMapMode) || (iMode == MM_ISOTROPIC))
158     {
159         pdcattr->ulDirty_ &= ~SLOW_WIDTHS;
160         return GetAndSetDCDWord(hdc, GdiGetSetMapMode, iMode, 0, 0, 0 );
161     }
162 
163     return pdcattr->iMapMode;
164 }
165 
166 
167 BOOL
168 WINAPI
169 DPtoLP(
170     _In_ HDC hdc,
171     _Inout_updates_(nCount) LPPOINT lpPoints,
172     _In_ INT nCount)
173 {
174     PDC_ATTR pdcattr;
175     SIZEL sizlView;
176 
177     if (nCount <= 0)
178         return TRUE;
179 
180     if (hdc == NULL)
181     {
182         SetLastError(ERROR_INVALID_PARAMETER);
183         return FALSE;
184     }
185     if (lpPoints == NULL)
186     {
187         return TRUE;
188     }
189 
190     pdcattr = GdiGetDcAttr(hdc);
191     if (pdcattr == NULL)
192         return FALSE;
193 
194     if (pdcattr->iMapMode == MM_ISOTROPIC)
195     {
196         if (NtGdiGetDCPoint(hdc, GdiGetViewPortExt, (PPOINTL)&sizlView))
197         {
198             if (sizlView.cx == 0 || sizlView.cy == 0)
199                 return FALSE;
200         }
201     }
202 
203     return NtGdiTransformPoints(hdc, lpPoints, lpPoints, nCount, GdiDpToLp);
204 }
205 
206 BOOL
207 WINAPI
208 LPtoDP(
209     _In_ HDC hdc,
210     _Inout_updates_(nCount) LPPOINT lpPoints,
211     _In_ INT nCount)
212 {
213     PDC_ATTR pdcattr;
214 
215     if (nCount <= 0)
216         return TRUE;
217 
218     if (hdc == NULL)
219     {
220         SetLastError(ERROR_INVALID_PARAMETER);
221         return FALSE;
222     }
223     if (lpPoints == NULL)
224     {
225         return TRUE;
226     }
227 
228     pdcattr = GdiGetDcAttr(hdc);
229     if (pdcattr == NULL)
230         return FALSE;
231 
232     return NtGdiTransformPoints(hdc, lpPoints, lpPoints, nCount, GdiLpToDp);
233 }
234 
235 /*
236  * @implemented
237  *
238  */
239 BOOL
240 WINAPI
241 GetCurrentPositionEx(
242     _In_ HDC hdc,
243     _Out_ LPPOINT lpPoint)
244 {
245     PDC_ATTR pdcattr;
246 
247     /* Get the DC attribute */
248     pdcattr = GdiGetDcAttr(hdc);
249     if ((pdcattr == NULL) || (lpPoint == NULL))
250     {
251         SetLastError(ERROR_INVALID_PARAMETER);
252         return FALSE;
253     }
254 
255     if (pdcattr->ulDirty_ & DIRTY_PTLCURRENT) // have a hit!
256     {
257         lpPoint->x = pdcattr->ptfxCurrent.x;
258         lpPoint->y = pdcattr->ptfxCurrent.y;
259         DPtoLP(hdc, lpPoint, 1);          // reconvert back.
260         pdcattr->ptlCurrent.x = lpPoint->x; // save it
261         pdcattr->ptlCurrent.y = lpPoint->y;
262         pdcattr->ulDirty_ &= ~DIRTY_PTLCURRENT; // clear bit
263     }
264     else
265     {
266         lpPoint->x = pdcattr->ptlCurrent.x;
267         lpPoint->y = pdcattr->ptlCurrent.y;
268     }
269 
270     return TRUE;
271 }
272 
273 /*
274  * @implemented
275  */
276 BOOL
277 WINAPI
278 GetWorldTransform(
279     _In_ HDC hdc,
280     _Out_ LPXFORM pxform)
281 {
282     PDC_ATTR pdcattr;
283 
284     pdcattr = GdiGetDcAttr(hdc);
285     if (!pdcattr)
286     {
287         SetLastError(ERROR_INVALID_HANDLE);
288         return FALSE;
289     }
290 #if 0
291     if (pdcattr->flXform & ANY_XFORM_INVALID)
292     {
293         GdiFixupTransforms(pdcattr);
294     }
295 
296     MatrixToXForm(pxform, &pdcattr->mxWorldToDevice);
297 #endif
298     return NtGdiGetTransform(hdc, GdiWorldSpaceToPageSpace, pxform);
299 }
300 
301 
302 BOOL
303 WINAPI
304 SetWorldTransform(
305     _In_ HDC hdc,
306     _Out_ CONST XFORM *pxform)
307 {
308     return ModifyWorldTransform(hdc, pxform, MWT_SET);
309 }
310 
311 
312 BOOL
313 WINAPI
314 ModifyWorldTransform(
315     _In_ HDC hdc,
316     _In_opt_ CONST XFORM *pxform,
317     _In_ DWORD dwMode)
318 {
319     PDC_ATTR pdcattr;
320 
321     if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE)
322         return FALSE;
323 
324     if (dwMode == MWT_SET)
325     {
326        HANDLE_METADC(BOOL, SetWorldTransform, FALSE, hdc, pxform);
327     }
328     else
329     {
330        HANDLE_METADC(BOOL, ModifyWorldTransform, FALSE, hdc, pxform, dwMode);
331     }
332 
333     /* Get the DC attribute */
334     pdcattr = GdiGetDcAttr(hdc);
335     if (pdcattr == NULL)
336     {
337         SetLastError(ERROR_INVALID_PARAMETER);
338         return FALSE;
339     }
340 
341     /* Check that graphics mode is GM_ADVANCED */
342     if (pdcattr->iGraphicsMode != GM_ADVANCED)
343         return FALSE;
344 
345     /* Call win32k to do the work */
346     return NtGdiModifyWorldTransform(hdc, (LPXFORM)pxform, dwMode);
347 }
348 
349 BOOL
350 WINAPI
351 GetViewportExtEx(
352     _In_ HDC hdc,
353     _Out_ LPSIZE lpSize)
354 {
355     PDC_ATTR pdcattr;
356 
357     /* Get the DC attribute */
358     pdcattr = GdiGetDcAttr(hdc);
359     if (pdcattr == NULL)
360     {
361         /* Do not set LastError here! */
362         return FALSE;
363     }
364 
365     /* Check if we need to update values */
366     if ((pdcattr->flXform & PAGE_EXTENTS_CHANGED) &&
367         (pdcattr->iMapMode == MM_ISOTROPIC))
368     {
369         /* Call win32k to do the work */
370         return NtGdiGetDCPoint(hdc, GdiGetViewPortExt, (PPOINTL)lpSize);
371     }
372 
373     /* Nothing to calculate, return the current extension */
374     lpSize->cx = pdcattr->szlViewportExt.cx;
375     lpSize->cy = pdcattr->szlViewportExt.cy;
376 
377     return TRUE;
378 }
379 
380 
381 BOOL
382 WINAPI
383 GetViewportOrgEx(
384     _In_ HDC hdc,
385     _Out_ LPPOINT lpPoint)
386 {
387     PDC_ATTR pdcattr;
388 
389     /* Get the DC attribute */
390     pdcattr = GdiGetDcAttr(hdc);
391     if (pdcattr == NULL)
392     {
393         /* Do not set LastError here! */
394         return FALSE;
395     }
396 
397     /* Get the current viewport org */
398     lpPoint->x = pdcattr->ptlViewportOrg.x;
399     lpPoint->y = pdcattr->ptlViewportOrg.y;
400 
401     /* Handle right-to-left layout */
402     if (pdcattr->dwLayout & LAYOUT_RTL)
403         lpPoint->x = -lpPoint->x;
404 
405     return TRUE;
406 }
407 
408 
409 BOOL
410 WINAPI
411 GetWindowExtEx(
412     _In_ HDC hdc,
413     _Out_ LPSIZE lpSize)
414 {
415     PDC_ATTR pdcattr;
416 
417     /* Get the DC attribute */
418     pdcattr = GdiGetDcAttr(hdc);
419     if (pdcattr == NULL)
420     {
421         /* Do not set LastError here! */
422         return FALSE;
423     }
424 
425     /* Get the current window extension */
426     lpSize->cx = pdcattr->szlWindowExt.cx;
427     lpSize->cy = pdcattr->szlWindowExt.cy;
428 
429     /* Handle right-to-left layout */
430     if (pdcattr->dwLayout & LAYOUT_RTL)
431         lpSize->cx = -lpSize->cx;
432 
433     return TRUE;
434 }
435 
436 
437 BOOL
438 WINAPI
439 GetWindowOrgEx(
440     _In_ HDC hdc,
441     _Out_ LPPOINT lpPoint)
442 {
443     PDC_ATTR pdcattr;
444 
445     /* Get the DC attribute */
446     pdcattr = GdiGetDcAttr(hdc);
447     if (pdcattr == NULL)
448     {
449         /* Do not set LastError here! */
450         return FALSE;
451     }
452 
453     /* Get the current window origin */
454     lpPoint->x = pdcattr->ptlWindowOrg.x;
455     lpPoint->y = pdcattr->ptlWindowOrg.y;
456 
457     return TRUE;
458 }
459 
460 /*
461  * @unimplemented
462  */
463 BOOL
464 WINAPI
465 SetViewportExtEx(
466     _In_ HDC hdc,
467     _In_ int nXExtent,
468     _In_ int nYExtent,
469     _Out_opt_ LPSIZE lpSize)
470 {
471     PDC_ATTR pdcattr;
472 
473     HANDLE_METADC(BOOL, SetViewportExtEx, FALSE, hdc, nXExtent, nYExtent, lpSize);
474 
475     /* Get the DC attribute */
476     pdcattr = GdiGetDcAttr(hdc);
477     if (pdcattr == NULL)
478     {
479         SetLastError(ERROR_INVALID_PARAMETER);
480         return FALSE;
481     }
482 
483     /* Check if the caller wants the old extension */
484     if (lpSize)
485     {
486         /* Return the current viewport extension */
487         lpSize->cx = pdcattr->szlViewportExt.cx;
488         lpSize->cy = pdcattr->szlViewportExt.cy;
489     }
490 
491     /* Check for trivial case */
492     if ((pdcattr->szlViewportExt.cx == nXExtent) &&
493         (pdcattr->szlViewportExt.cy == nYExtent))
494         return TRUE;
495 
496     if (nXExtent == 0 || nYExtent == 0)
497         return TRUE;
498 
499     /* Only change viewport extension if we are in iso or aniso mode */
500     if ((pdcattr->iMapMode == MM_ISOTROPIC) ||
501         (pdcattr->iMapMode == MM_ANISOTROPIC))
502     {
503         if (NtCurrentTeb()->GdiTebBatch.HDC == hdc)
504         {
505             if (pdcattr->ulDirty_ & DC_MODE_DIRTY)
506             {
507                 NtGdiFlush(); // Sync up pdcattr from Kernel space.
508                 pdcattr->ulDirty_ &= ~DC_MODE_DIRTY;
509             }
510         }
511 
512         /* Set the new viewport extension */
513         pdcattr->szlViewportExt.cx = nXExtent;
514         pdcattr->szlViewportExt.cy = nYExtent;
515 
516         /* Handle right-to-left layout */
517         if (pdcattr->dwLayout & LAYOUT_RTL)
518             NtGdiMirrorWindowOrg(hdc);
519 
520         /* Update xform flags */
521         pdcattr->flXform |= (PAGE_EXTENTS_CHANGED|INVALIDATE_ATTRIBUTES|DEVICE_TO_WORLD_INVALID);
522     }
523 
524     return TRUE;
525 }
526 
527 /*
528  * @unimplemented
529  */
530 BOOL
531 WINAPI
532 SetWindowOrgEx(
533     _In_ HDC hdc,
534     _In_ int X,
535     _In_ int Y,
536     _Out_opt_ LPPOINT lpPoint)
537 {
538     PDC_ATTR pdcattr;
539 
540     HANDLE_METADC(BOOL, SetWindowOrgEx, FALSE, hdc, X, Y, lpPoint);
541 
542     /* Get the DC attribute */
543     pdcattr = GdiGetDcAttr(hdc);
544     if (pdcattr == NULL)
545     {
546         /* Do not set LastError here! */
547         return FALSE;
548     }
549 
550     if (lpPoint)
551     {
552         lpPoint->x = pdcattr->ptlWindowOrg.x;
553         lpPoint->y = pdcattr->ptlWindowOrg.y;
554     }
555 
556     if ((pdcattr->ptlWindowOrg.x == X) && (pdcattr->ptlWindowOrg.y == Y))
557         return TRUE;
558 
559     if (NtCurrentTeb()->GdiTebBatch.HDC == hdc)
560     {
561         if (pdcattr->ulDirty_ & DC_MODE_DIRTY)
562         {
563             NtGdiFlush(); // Sync up pdcattr from Kernel space.
564             pdcattr->ulDirty_ &= ~DC_MODE_DIRTY;
565         }
566     }
567 
568     pdcattr->ptlWindowOrg.x = X;
569     pdcattr->ptlWindowOrg.y = Y;
570 
571     pdcattr->lWindowOrgx    = X;
572     if (pdcattr->dwLayout & LAYOUT_RTL) NtGdiMirrorWindowOrg(hdc);
573     pdcattr->flXform |= (PAGE_XLATE_CHANGED|WORLD_XFORM_CHANGED|DEVICE_TO_WORLD_INVALID);
574     return TRUE;
575 
576 //    return NtGdiSetWindowOrgEx(hdc, X, Y, lpPoint);
577 }
578 
579 /*
580  * @unimplemented
581  */
582 BOOL
583 WINAPI
584 SetWindowExtEx(
585     _In_ HDC hdc,
586     _In_ INT nXExtent,
587     _In_ INT nYExtent,
588     _Out_opt_ LPSIZE lpSize)
589 {
590     PDC_ATTR pdcattr;
591 
592     HANDLE_METADC(BOOL, SetWindowExtEx, FALSE, hdc, nXExtent, nYExtent, lpSize);
593 
594     /* Get the DC attr */
595     pdcattr = GdiGetDcAttr(hdc);
596     if (!pdcattr)
597     {
598         /* Set the error value and return failure */
599         SetLastError(ERROR_INVALID_PARAMETER);
600         return FALSE;
601     }
602 
603     /* Check if the caller wants the old extension */
604     if (lpSize)
605     {
606         /* Return the current window extension */
607         lpSize->cx = pdcattr->szlWindowExt.cx;
608         lpSize->cy = pdcattr->szlWindowExt.cy;
609 
610         /* Handle right-to-left layout */
611         if (pdcattr->dwLayout & LAYOUT_RTL)
612             lpSize->cx = -lpSize->cx;
613     }
614 
615     if (pdcattr->dwLayout & LAYOUT_RTL)
616     {
617         NtGdiMirrorWindowOrg(hdc);
618         pdcattr->flXform |= (PAGE_EXTENTS_CHANGED|INVALIDATE_ATTRIBUTES|DEVICE_TO_WORLD_INVALID);
619     }
620     else if ((pdcattr->iMapMode == MM_ISOTROPIC) ||
621              (pdcattr->iMapMode == MM_ANISOTROPIC))
622     {
623         if ((pdcattr->szlWindowExt.cx == nXExtent) &&
624             (pdcattr->szlWindowExt.cy == nYExtent))
625             return TRUE;
626 
627         if ((!nXExtent) || (!nYExtent))
628             return FALSE;
629 
630         if (NtCurrentTeb()->GdiTebBatch.HDC == hdc)
631         {
632             if (pdcattr->ulDirty_ & DC_MODE_DIRTY)
633             {
634                 NtGdiFlush(); // Sync up Dc_Attr from Kernel space.
635                 pdcattr->ulDirty_ &= ~DC_MODE_DIRTY;
636             }
637         }
638 
639         pdcattr->szlWindowExt.cx = nXExtent;
640         pdcattr->szlWindowExt.cy = nYExtent;
641         if (pdcattr->dwLayout & LAYOUT_RTL)
642             NtGdiMirrorWindowOrg(hdc);
643 
644         pdcattr->flXform |= (PAGE_EXTENTS_CHANGED|INVALIDATE_ATTRIBUTES|DEVICE_TO_WORLD_INVALID);
645     }
646 
647     return TRUE;
648 }
649 
650 /*
651  * @unimplemented
652  */
653 BOOL
654 WINAPI
655 SetViewportOrgEx(
656     _In_ HDC hdc,
657     _In_ int X,
658     _In_ int Y,
659     _Out_opt_ LPPOINT lpPoint)
660 {
661     PDC_ATTR pdcattr;
662 
663     HANDLE_METADC(BOOL, SetViewportOrgEx, FALSE, hdc, X, Y, lpPoint);
664 
665     /* Get the DC attribute */
666     pdcattr = GdiGetDcAttr(hdc);
667     if (!pdcattr)
668     {
669         /* Do not set LastError here! */
670         return FALSE;
671     }
672 
673     if (lpPoint)
674     {
675         lpPoint->x = pdcattr->ptlViewportOrg.x;
676         lpPoint->y = pdcattr->ptlViewportOrg.y;
677         if (pdcattr->dwLayout & LAYOUT_RTL) lpPoint->x = -lpPoint->x;
678     }
679     pdcattr->flXform |= (PAGE_XLATE_CHANGED|WORLD_XFORM_CHANGED|DEVICE_TO_WORLD_INVALID);
680     if (pdcattr->dwLayout & LAYOUT_RTL) X = -X;
681     pdcattr->ptlViewportOrg.x = X;
682     pdcattr->ptlViewportOrg.y = Y;
683     return TRUE;
684 
685 //    return NtGdiSetViewportOrgEx(hdc,X,Y,lpPoint);
686 }
687 
688 /*
689  * @implemented
690  */
691 BOOL
692 WINAPI
693 ScaleViewportExtEx(
694     _In_ HDC hdc,
695     _In_ INT xNum,
696     _In_ INT xDenom,
697     _In_ INT yNum,
698     _In_ INT yDenom,
699     _Out_ LPSIZE lpSize)
700 {
701     HANDLE_METADC(BOOL, ScaleViewportExtEx, FALSE, hdc, xNum, xDenom, yNum, yDenom, lpSize);
702 
703     if (!GdiGetDcAttr(hdc))
704     {
705         SetLastError(ERROR_INVALID_PARAMETER);
706         return FALSE;
707     }
708 
709     return NtGdiScaleViewportExtEx(hdc, xNum, xDenom, yNum, yDenom, lpSize);
710 }
711 
712 /*
713  * @implemented
714  */
715 BOOL
716 WINAPI
717 ScaleWindowExtEx(
718     _In_ HDC hdc,
719     _In_ INT xNum,
720     _In_ INT xDenom,
721     _In_ INT yNum,
722     _In_ INT yDenom,
723     _Out_ LPSIZE lpSize)
724 {
725     HANDLE_METADC(BOOL, ScaleWindowExtEx, FALSE, hdc, xNum, xDenom, yNum, yDenom, lpSize);
726 
727     if (!GdiGetDcAttr(hdc))
728     {
729         SetLastError(ERROR_INVALID_PARAMETER);
730         return FALSE;
731     }
732 
733     return NtGdiScaleWindowExtEx(hdc, xNum, xDenom, yNum, yDenom, lpSize);
734 }
735 
736 /*
737  * @implemented
738  */
739 DWORD
740 WINAPI
741 GetLayout(
742     _In_ HDC hdc)
743 {
744     PDC_ATTR pdcattr;
745 
746     /* METADC16 is not supported in this API */
747     if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE)
748     {
749         return GDI_ERROR;
750     }
751 
752     /* Get the DC attribute */
753     pdcattr = GdiGetDcAttr(hdc);
754     if (!pdcattr)
755     {
756         /* Set the error value and return failure */
757         SetLastError(ERROR_INVALID_PARAMETER);
758         return GDI_ERROR;
759     }
760 
761     /* Return the layout */
762     return pdcattr->dwLayout;
763 }
764 
765 
766 /*
767  * @implemented
768  */
769 DWORD
770 WINAPI
771 SetLayout(
772     _In_ HDC hdc,
773     _In_ DWORD dwLayout)
774 {
775     HANDLE_METADC(DWORD, SetLayout, GDI_ERROR, hdc, dwLayout);
776 
777     if (!GdiGetDcAttr(hdc))
778     {
779         SetLastError(ERROR_INVALID_PARAMETER);
780         return GDI_ERROR;
781     }
782 
783     return NtGdiSetLayout(hdc, -1, dwLayout);
784 }
785 
786 /*
787  * @implemented
788  */
789 DWORD
790 WINAPI
791 SetLayoutWidth(
792     _In_ HDC hdc,
793     _In_ LONG wox,
794     _In_ DWORD dwLayout)
795 {
796     /* Only normal DCs are handled here */
797     if (GDI_HANDLE_GET_TYPE(hdc) != GDILoObjType_LO_DC_TYPE)
798     {
799         return GDI_ERROR;
800     }
801 
802     if (!GdiGetDcAttr(hdc))
803     {
804         SetLastError(ERROR_INVALID_PARAMETER);
805         return GDI_ERROR;
806     }
807 
808     return NtGdiSetLayout(hdc, wox, dwLayout);
809 }
810 
811 /*
812  * @implemented
813  */
814 BOOL
815 WINAPI
816 GetDCOrgEx(
817     _In_ HDC hdc,
818     _Out_ LPPOINT lpPoint)
819 {
820     return NtGdiGetDCPoint(hdc, GdiGetDCOrg, (PPOINTL)lpPoint);
821 }
822 
823 
824 /*
825  * @implemented
826  */
827 LONG
828 WINAPI
829 GetDCOrg(
830     _In_ HDC hdc)
831 {
832     POINT pt;
833 
834     /* Call the new API */
835     if (!GetDCOrgEx(hdc, &pt))
836         return 0;
837 
838     /* Return the point in the old way */
839     return(MAKELONG(pt.x, pt.y));
840 }
841 
842 
843 /*
844  * @implemented
845  *
846  */
847 BOOL
848 WINAPI
849 OffsetViewportOrgEx(
850     _In_ HDC hdc,
851     _In_ int nXOffset,
852     _In_ int nYOffset,
853     _Out_opt_ LPPOINT lpPoint)
854 {
855     PDC_ATTR pdcattr;
856 
857     HANDLE_METADC(BOOL, OffsetViewportOrgEx, FALSE, hdc, nXOffset, nYOffset, lpPoint);
858 
859     /* Get the DC attribute */
860     pdcattr = GdiGetDcAttr(hdc);
861     if (!pdcattr)
862     {
863         /* Do not set LastError here! */
864         return FALSE;
865     }
866 
867     if (lpPoint)
868     {
869         *lpPoint = pdcattr->ptlViewportOrg;
870         if ( pdcattr->dwLayout & LAYOUT_RTL) lpPoint->x = -lpPoint->x;
871     }
872 
873     if ( nXOffset || nYOffset != nXOffset )
874     {
875         if (NtCurrentTeb()->GdiTebBatch.HDC == hdc)
876         {
877             if (pdcattr->ulDirty_ & DC_MODE_DIRTY)
878             {
879                 NtGdiFlush();
880                 pdcattr->ulDirty_ &= ~DC_MODE_DIRTY;
881             }
882         }
883 
884         pdcattr->flXform |= (PAGE_XLATE_CHANGED|WORLD_XFORM_CHANGED|DEVICE_TO_WORLD_INVALID);
885         if (pdcattr->dwLayout & LAYOUT_RTL) nXOffset = -nXOffset;
886         pdcattr->ptlViewportOrg.x += nXOffset;
887         pdcattr->ptlViewportOrg.y += nYOffset;
888     }
889     return TRUE;
890 
891 //    return  NtGdiOffsetViewportOrgEx(hdc, nXOffset, nYOffset, lpPoint);
892 }
893 
894 /*
895  * @implemented
896  *
897  */
898 BOOL
899 WINAPI
900 OffsetWindowOrgEx(
901     _In_ HDC hdc,
902     _In_ int nXOffset,
903     _In_ int nYOffset,
904     _Out_opt_ LPPOINT lpPoint)
905 {
906     PDC_ATTR pdcattr;
907 
908     HANDLE_METADC(BOOL, OffsetWindowOrgEx, FALSE, hdc, nXOffset, nYOffset, lpPoint);
909 
910     /* Get the DC attribute */
911     pdcattr = GdiGetDcAttr(hdc);
912     if (!pdcattr)
913     {
914         /* Do not set LastError here! */
915         return FALSE;
916     }
917 
918     if ( lpPoint )
919     {
920         *lpPoint   = pdcattr->ptlWindowOrg;
921         //lpPoint->x = pdcattr->lWindowOrgx;
922     }
923 
924     if ( nXOffset || nYOffset != nXOffset )
925     {
926         if (NtCurrentTeb()->GdiTebBatch.HDC == hdc)
927         {
928             if (pdcattr->ulDirty_ & DC_MODE_DIRTY)
929             {
930                 NtGdiFlush();
931                 pdcattr->ulDirty_ &= ~DC_MODE_DIRTY;
932             }
933         }
934 
935         pdcattr->flXform |= (PAGE_XLATE_CHANGED|WORLD_XFORM_CHANGED|DEVICE_TO_WORLD_INVALID);
936         pdcattr->ptlWindowOrg.x += nXOffset;
937         pdcattr->ptlWindowOrg.y += nYOffset;
938         pdcattr->lWindowOrgx += nXOffset;
939     }
940     return TRUE;
941 
942 //    return NtGdiOffsetWindowOrgEx(hdc, nXOffset, nYOffset, lpPoint);
943 }
944 
945