xref: /reactos/win32ss/gdi/gdi32/objects/coord.c (revision 8a978a17)
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  * @implemented
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  * @implemented
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  * @implemented
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  * @implemented
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     //// HACK : XP+ doesn't do this. See CORE-16656 & CORE-16644.
673     if (NtCurrentTeb()->GdiTebBatch.HDC == hdc)
674     {
675         if (pdcattr->ulDirty_ & DC_MODE_DIRTY)
676         {
677             NtGdiFlush();
678             pdcattr->ulDirty_ &= ~DC_MODE_DIRTY;
679         }
680     }
681     ////
682     if (lpPoint)
683     {
684         lpPoint->x = pdcattr->ptlViewportOrg.x;
685         lpPoint->y = pdcattr->ptlViewportOrg.y;
686         if (pdcattr->dwLayout & LAYOUT_RTL) lpPoint->x = -lpPoint->x;
687     }
688     pdcattr->flXform |= (PAGE_XLATE_CHANGED|WORLD_XFORM_CHANGED|DEVICE_TO_WORLD_INVALID);
689     if (pdcattr->dwLayout & LAYOUT_RTL) X = -X;
690     pdcattr->ptlViewportOrg.x = X;
691     pdcattr->ptlViewportOrg.y = Y;
692     return TRUE;
693 
694 //    return NtGdiSetViewportOrgEx(hdc,X,Y,lpPoint);
695 }
696 
697 /*
698  * @implemented
699  */
700 BOOL
701 WINAPI
702 ScaleViewportExtEx(
703     _In_ HDC hdc,
704     _In_ INT xNum,
705     _In_ INT xDenom,
706     _In_ INT yNum,
707     _In_ INT yDenom,
708     _Out_ LPSIZE lpSize)
709 {
710     HANDLE_METADC(BOOL, ScaleViewportExtEx, FALSE, hdc, xNum, xDenom, yNum, yDenom, lpSize);
711 
712     if (!GdiGetDcAttr(hdc))
713     {
714         SetLastError(ERROR_INVALID_PARAMETER);
715         return FALSE;
716     }
717 
718     return NtGdiScaleViewportExtEx(hdc, xNum, xDenom, yNum, yDenom, lpSize);
719 }
720 
721 /*
722  * @implemented
723  */
724 BOOL
725 WINAPI
726 ScaleWindowExtEx(
727     _In_ HDC hdc,
728     _In_ INT xNum,
729     _In_ INT xDenom,
730     _In_ INT yNum,
731     _In_ INT yDenom,
732     _Out_ LPSIZE lpSize)
733 {
734     HANDLE_METADC(BOOL, ScaleWindowExtEx, FALSE, hdc, xNum, xDenom, yNum, yDenom, lpSize);
735 
736     if (!GdiGetDcAttr(hdc))
737     {
738         SetLastError(ERROR_INVALID_PARAMETER);
739         return FALSE;
740     }
741 
742     return NtGdiScaleWindowExtEx(hdc, xNum, xDenom, yNum, yDenom, lpSize);
743 }
744 
745 /*
746  * @implemented
747  */
748 DWORD
749 WINAPI
750 GetLayout(
751     _In_ HDC hdc)
752 {
753     PDC_ATTR pdcattr;
754 
755     /* METADC16 is not supported in this API */
756     if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE)
757     {
758         return GDI_ERROR;
759     }
760 
761     /* Get the DC attribute */
762     pdcattr = GdiGetDcAttr(hdc);
763     if (!pdcattr)
764     {
765         /* Set the error value and return failure */
766         SetLastError(ERROR_INVALID_PARAMETER);
767         return GDI_ERROR;
768     }
769 
770     /* Return the layout */
771     return pdcattr->dwLayout;
772 }
773 
774 
775 /*
776  * @implemented
777  */
778 DWORD
779 WINAPI
780 SetLayout(
781     _In_ HDC hdc,
782     _In_ DWORD dwLayout)
783 {
784     HANDLE_METADC(DWORD, SetLayout, GDI_ERROR, hdc, dwLayout);
785 
786     if (!GdiGetDcAttr(hdc))
787     {
788         SetLastError(ERROR_INVALID_PARAMETER);
789         return GDI_ERROR;
790     }
791 
792     return NtGdiSetLayout(hdc, -1, dwLayout);
793 }
794 
795 /*
796  * @implemented
797  */
798 DWORD
799 WINAPI
800 SetLayoutWidth(
801     _In_ HDC hdc,
802     _In_ LONG wox,
803     _In_ DWORD dwLayout)
804 {
805     /* Only normal DCs are handled here */
806     if (GDI_HANDLE_GET_TYPE(hdc) != GDILoObjType_LO_DC_TYPE)
807     {
808         return GDI_ERROR;
809     }
810 
811     if (!GdiGetDcAttr(hdc))
812     {
813         SetLastError(ERROR_INVALID_PARAMETER);
814         return GDI_ERROR;
815     }
816 
817     return NtGdiSetLayout(hdc, wox, dwLayout);
818 }
819 
820 /*
821  * @implemented
822  */
823 BOOL
824 WINAPI
825 GetDCOrgEx(
826     _In_ HDC hdc,
827     _Out_ LPPOINT lpPoint)
828 {
829     return NtGdiGetDCPoint(hdc, GdiGetDCOrg, (PPOINTL)lpPoint);
830 }
831 
832 
833 /*
834  * @implemented
835  */
836 LONG
837 WINAPI
838 GetDCOrg(
839     _In_ HDC hdc)
840 {
841     POINT pt;
842 
843     /* Call the new API */
844     if (!GetDCOrgEx(hdc, &pt))
845         return 0;
846 
847     /* Return the point in the old way */
848     return(MAKELONG(pt.x, pt.y));
849 }
850 
851 
852 /*
853  * @implemented
854  *
855  */
856 BOOL
857 WINAPI
858 OffsetViewportOrgEx(
859     _In_ HDC hdc,
860     _In_ int nXOffset,
861     _In_ int nYOffset,
862     _Out_opt_ LPPOINT lpPoint)
863 {
864     PDC_ATTR pdcattr;
865 
866     HANDLE_METADC(BOOL, OffsetViewportOrgEx, FALSE, hdc, nXOffset, nYOffset, lpPoint);
867 
868     /* Get the DC attribute */
869     pdcattr = GdiGetDcAttr(hdc);
870     if (!pdcattr)
871     {
872         /* Do not set LastError here! */
873         return FALSE;
874     }
875 
876     if (lpPoint)
877     {
878         *lpPoint = pdcattr->ptlViewportOrg;
879         if ( pdcattr->dwLayout & LAYOUT_RTL) lpPoint->x = -lpPoint->x;
880     }
881 
882     if ( nXOffset || nYOffset != nXOffset )
883     {
884         if (NtCurrentTeb()->GdiTebBatch.HDC == hdc)
885         {
886             if (pdcattr->ulDirty_ & DC_MODE_DIRTY)
887             {
888                 NtGdiFlush();
889                 pdcattr->ulDirty_ &= ~DC_MODE_DIRTY;
890             }
891         }
892 
893         pdcattr->flXform |= (PAGE_XLATE_CHANGED|WORLD_XFORM_CHANGED|DEVICE_TO_WORLD_INVALID);
894         if (pdcattr->dwLayout & LAYOUT_RTL) nXOffset = -nXOffset;
895         pdcattr->ptlViewportOrg.x += nXOffset;
896         pdcattr->ptlViewportOrg.y += nYOffset;
897     }
898     return TRUE;
899 
900 //    return  NtGdiOffsetViewportOrgEx(hdc, nXOffset, nYOffset, lpPoint);
901 }
902 
903 /*
904  * @implemented
905  *
906  */
907 BOOL
908 WINAPI
909 OffsetWindowOrgEx(
910     _In_ HDC hdc,
911     _In_ int nXOffset,
912     _In_ int nYOffset,
913     _Out_opt_ LPPOINT lpPoint)
914 {
915     PDC_ATTR pdcattr;
916 
917     HANDLE_METADC(BOOL, OffsetWindowOrgEx, FALSE, hdc, nXOffset, nYOffset, lpPoint);
918 
919     /* Get the DC attribute */
920     pdcattr = GdiGetDcAttr(hdc);
921     if (!pdcattr)
922     {
923         /* Do not set LastError here! */
924         return FALSE;
925     }
926 
927     if ( lpPoint )
928     {
929         *lpPoint   = pdcattr->ptlWindowOrg;
930         //lpPoint->x = pdcattr->lWindowOrgx;
931     }
932 
933     if ( nXOffset || nYOffset != nXOffset )
934     {
935         if (NtCurrentTeb()->GdiTebBatch.HDC == hdc)
936         {
937             if (pdcattr->ulDirty_ & DC_MODE_DIRTY)
938             {
939                 NtGdiFlush();
940                 pdcattr->ulDirty_ &= ~DC_MODE_DIRTY;
941             }
942         }
943 
944         pdcattr->flXform |= (PAGE_XLATE_CHANGED|WORLD_XFORM_CHANGED|DEVICE_TO_WORLD_INVALID);
945         pdcattr->ptlWindowOrg.x += nXOffset;
946         pdcattr->ptlWindowOrg.y += nYOffset;
947         pdcattr->lWindowOrgx += nXOffset;
948     }
949     return TRUE;
950 
951 //    return NtGdiOffsetWindowOrgEx(hdc, nXOffset, nYOffset, lpPoint);
952 }
953 
954