xref: /reactos/win32ss/gdi/gdi32/objects/coord.c (revision 64daf542)
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 #if 0
175     INT i;
176     PDC_ATTR pdcattr;
177 
178     /* Get the DC attribute */
179     pdcattr = GdiGetDcAttr(hdc);
180     if (!pdcattr)
181     {
182         SetLastError(ERROR_INVALID_PARAMETER);
183         return FALSE;
184     }
185 
186     if (pdcattr->flXform & ANY_XFORM_CHANGES)
187     {
188         GdiFixupTransforms(pdcattr);
189     }
190 
191     // FIXME: can this fail on Windows?
192     GdiTransformPoints(&pdcattr->mxDeviceToWorld, lpPoints, lpPoints, nCount);
193 
194     return TRUE;
195 #endif
196     return NtGdiTransformPoints(hdc, lpPoints, lpPoints, nCount, GdiDpToLp);
197 }
198 
199 BOOL
200 WINAPI
201 LPtoDP(
202     _In_ HDC hdc,
203     _Inout_updates_(nCount) LPPOINT lpPoints,
204     _In_ INT nCount)
205 {
206 #if 0
207     INT i;
208     PDC_ATTR pdcattr;
209 
210     /* Get the DC attribute */
211     pdcattr = GdiGetDcAttr(hdc);
212     if (!pdcattr)
213     {
214         SetLastError(ERROR_INVALID_PARAMETER);
215         return FALSE;
216     }
217 
218     if (pdcattr->flXform & ANY_XFORM_CHANGES)
219     {
220         GdiFixupTransforms(pdcattr);
221     }
222 
223     // FIXME: can this fail on Windows?
224     GdiTransformPoints(&pdcattr->mxWorldToDevice, lpPoints, lpPoints, nCount);
225 
226     return TRUE;
227 #endif
228     return NtGdiTransformPoints(hdc, lpPoints, lpPoints, nCount, GdiLpToDp);
229 }
230 
231 /*
232  * @implemented
233  *
234  */
235 BOOL
236 WINAPI
237 GetCurrentPositionEx(
238     _In_ HDC hdc,
239     _Out_ LPPOINT lpPoint)
240 {
241     PDC_ATTR pdcattr;
242 
243     /* Get the DC attribute */
244     pdcattr = GdiGetDcAttr(hdc);
245     if ((pdcattr == NULL) || (lpPoint == NULL))
246     {
247         SetLastError(ERROR_INVALID_PARAMETER);
248         return FALSE;
249     }
250 
251     if (pdcattr->ulDirty_ & DIRTY_PTLCURRENT) // have a hit!
252     {
253         lpPoint->x = pdcattr->ptfxCurrent.x;
254         lpPoint->y = pdcattr->ptfxCurrent.y;
255         DPtoLP(hdc, lpPoint, 1);          // reconvert back.
256         pdcattr->ptlCurrent.x = lpPoint->x; // save it
257         pdcattr->ptlCurrent.y = lpPoint->y;
258         pdcattr->ulDirty_ &= ~DIRTY_PTLCURRENT; // clear bit
259     }
260     else
261     {
262         lpPoint->x = pdcattr->ptlCurrent.x;
263         lpPoint->y = pdcattr->ptlCurrent.y;
264     }
265 
266     return TRUE;
267 }
268 
269 /*
270  * @implemented
271  */
272 BOOL
273 WINAPI
274 GetWorldTransform(
275     _In_ HDC hdc,
276     _Out_ LPXFORM pxform)
277 {
278 #if 0
279     PDC_ATTR pdcattr;
280 
281     pdcattr = GdiGetDcAttr(hdc);
282     if (!pdcattr)
283     {
284         SetLastError(ERROR_INVALID_HANDLE);
285         return FALSE;
286     }
287 
288     if (pdcattr->flXform & ANY_XFORM_INVALID)
289     {
290         GdiFixupTransforms(pdcattr);
291     }
292 
293     MatrixToXForm(pxform, &pdcattr->mxWorldToDevice);
294 #endif
295     return NtGdiGetTransform(hdc, GdiWorldSpaceToPageSpace, pxform);
296 }
297 
298 
299 BOOL
300 WINAPI
301 SetWorldTransform(
302     _In_ HDC hdc,
303     _Out_ CONST XFORM *pxform)
304 {
305     return ModifyWorldTransform(hdc, pxform, MWT_SET);
306 }
307 
308 
309 BOOL
310 WINAPI
311 ModifyWorldTransform(
312     _In_ HDC hdc,
313     _In_opt_ CONST XFORM *pxform,
314     _In_ DWORD dwMode)
315 {
316     PDC_ATTR pdcattr;
317 
318     if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE)
319         return FALSE;
320 
321     if (dwMode == MWT_SET)
322     {
323        HANDLE_METADC(BOOL, SetWorldTransform, FALSE, hdc, pxform);
324     }
325     else
326     {
327        HANDLE_METADC(BOOL, ModifyWorldTransform, FALSE, hdc, pxform, dwMode);
328     }
329 
330     /* Get the DC attribute */
331     pdcattr = GdiGetDcAttr(hdc);
332     if (pdcattr == NULL)
333     {
334         SetLastError(ERROR_INVALID_PARAMETER);
335         return FALSE;
336     }
337 
338     /* Check that graphics mode is GM_ADVANCED */
339     if (pdcattr->iGraphicsMode != GM_ADVANCED)
340         return FALSE;
341 
342     /* Call win32k to do the work */
343     return NtGdiModifyWorldTransform(hdc, (LPXFORM)pxform, dwMode);
344 }
345 
346 BOOL
347 WINAPI
348 GetViewportExtEx(
349     _In_ HDC hdc,
350     _Out_ LPSIZE lpSize)
351 {
352     PDC_ATTR pdcattr;
353 
354     /* Get the DC attribute */
355     pdcattr = GdiGetDcAttr(hdc);
356     if (pdcattr == NULL)
357     {
358         /* Do not set LastError here! */
359         return FALSE;
360     }
361 
362     /* Check if we need to update values */
363     if ((pdcattr->flXform & PAGE_EXTENTS_CHANGED) &&
364         (pdcattr->iMapMode == MM_ISOTROPIC))
365     {
366         /* Call win32k to do the work */
367         return NtGdiGetDCPoint(hdc, GdiGetViewPortExt, (PPOINTL)lpSize);
368     }
369 
370     /* Nothing to calculate, return the current extension */
371     lpSize->cx = pdcattr->szlViewportExt.cx;
372     lpSize->cy = pdcattr->szlViewportExt.cy;
373 
374     return TRUE;
375 }
376 
377 
378 BOOL
379 WINAPI
380 GetViewportOrgEx(
381     _In_ HDC hdc,
382     _Out_ LPPOINT lpPoint)
383 {
384     PDC_ATTR pdcattr;
385 
386     /* Get the DC attribute */
387     pdcattr = GdiGetDcAttr(hdc);
388     if (pdcattr == NULL)
389     {
390         /* Do not set LastError here! */
391         return FALSE;
392     }
393 
394     /* Get the current viewport org */
395     lpPoint->x = pdcattr->ptlViewportOrg.x;
396     lpPoint->y = pdcattr->ptlViewportOrg.y;
397 
398     /* Handle right-to-left layout */
399     if (pdcattr->dwLayout & LAYOUT_RTL)
400         lpPoint->x = -lpPoint->x;
401 
402     return TRUE;
403 }
404 
405 
406 BOOL
407 WINAPI
408 GetWindowExtEx(
409     _In_ HDC hdc,
410     _Out_ LPSIZE lpSize)
411 {
412     PDC_ATTR pdcattr;
413 
414     /* Get the DC attribute */
415     pdcattr = GdiGetDcAttr(hdc);
416     if (pdcattr == NULL)
417     {
418         /* Do not set LastError here! */
419         return FALSE;
420     }
421 
422     /* Get the current window extension */
423     lpSize->cx = pdcattr->szlWindowExt.cx;
424     lpSize->cy = pdcattr->szlWindowExt.cy;
425 
426     /* Handle right-to-left layout */
427     if (pdcattr->dwLayout & LAYOUT_RTL)
428         lpSize->cx = -lpSize->cx;
429 
430     return TRUE;
431 }
432 
433 
434 BOOL
435 WINAPI
436 GetWindowOrgEx(
437     _In_ HDC hdc,
438     _Out_ LPPOINT lpPoint)
439 {
440     PDC_ATTR pdcattr;
441 
442     /* Get the DC attribute */
443     pdcattr = GdiGetDcAttr(hdc);
444     if (pdcattr == NULL)
445     {
446         /* Do not set LastError here! */
447         return FALSE;
448     }
449 
450     /* Get the current window origin */
451     lpPoint->x = pdcattr->ptlWindowOrg.x;
452     lpPoint->y = pdcattr->ptlWindowOrg.y;
453 
454     return TRUE;
455 }
456 
457 /*
458  * @unimplemented
459  */
460 BOOL
461 WINAPI
462 SetViewportExtEx(
463     _In_ HDC hdc,
464     _In_ int nXExtent,
465     _In_ int nYExtent,
466     _Out_opt_ LPSIZE lpSize)
467 {
468     PDC_ATTR pdcattr;
469 
470     HANDLE_METADC(BOOL, SetViewportExtEx, FALSE, hdc, nXExtent, nYExtent, lpSize);
471 
472     /* Get the DC attribute */
473     pdcattr = GdiGetDcAttr(hdc);
474     if (pdcattr == NULL)
475     {
476         SetLastError(ERROR_INVALID_PARAMETER);
477         return FALSE;
478     }
479 
480     /* Check if the caller wants the old extension */
481     if (lpSize)
482     {
483         /* Return the current viewport extension */
484         lpSize->cx = pdcattr->szlViewportExt.cx;
485         lpSize->cy = pdcattr->szlViewportExt.cy;
486     }
487 
488     /* Check for trivial case */
489     if ((pdcattr->szlViewportExt.cx == nXExtent) &&
490         (pdcattr->szlViewportExt.cy == nYExtent))
491         return TRUE;
492 
493     /* Only change viewport extension if we are in iso or aniso mode */
494     if ((pdcattr->iMapMode == MM_ISOTROPIC) ||
495         (pdcattr->iMapMode == MM_ANISOTROPIC))
496     {
497         if (NtCurrentTeb()->GdiTebBatch.HDC == hdc)
498         {
499             if (pdcattr->ulDirty_ & DC_FONTTEXT_DIRTY)
500             {
501                 NtGdiFlush(); // Sync up pdcattr from Kernel space.
502                 pdcattr->ulDirty_ &= ~(DC_MODE_DIRTY|DC_FONTTEXT_DIRTY);
503             }
504         }
505 
506         /* Set the new viewport extension */
507         pdcattr->szlViewportExt.cx = nXExtent;
508         pdcattr->szlViewportExt.cy = nYExtent;
509 
510         /* Handle right-to-left layout */
511         if (pdcattr->dwLayout & LAYOUT_RTL)
512             NtGdiMirrorWindowOrg(hdc);
513 
514         /* Update xform flags */
515         pdcattr->flXform |= (PAGE_EXTENTS_CHANGED|INVALIDATE_ATTRIBUTES|DEVICE_TO_WORLD_INVALID);
516     }
517 
518     return TRUE;
519 }
520 
521 /*
522  * @unimplemented
523  */
524 BOOL
525 WINAPI
526 SetWindowOrgEx(
527     _In_ HDC hdc,
528     _In_ int X,
529     _In_ int Y,
530     _Out_opt_ LPPOINT lpPoint)
531 {
532     PDC_ATTR pdcattr;
533 
534     HANDLE_METADC(BOOL, SetWindowOrgEx, FALSE, hdc, X, Y, lpPoint);
535 
536     /* Get the DC attribute */
537     pdcattr = GdiGetDcAttr(hdc);
538     if (pdcattr == NULL)
539     {
540         /* Do not set LastError here! */
541         return FALSE;
542     }
543 #if 0
544     if (lpPoint)
545     {
546         lpPoint->x = pdcattr->ptlWindowOrg.x;
547         lpPoint->y = pdcattr->ptlWindowOrg.y;
548     }
549 
550     if ((pdcattr->ptlWindowOrg.x == X) && (pdcattr->ptlWindowOrg.y == Y))
551         return TRUE;
552 
553     if (NtCurrentTeb()->GdiTebBatch.HDC == (ULONG)hdc)
554     {
555         if (pdcattr->ulDirty_ & DC_FONTTEXT_DIRTY)
556         {
557             NtGdiFlush(); // Sync up pdcattr from Kernel space.
558             pdcattr->ulDirty_ &= ~(DC_MODE_DIRTY|DC_FONTTEXT_DIRTY);
559         }
560     }
561 
562     pdcattr->ptlWindowOrg.x = X;
563     pdcattr->lWindowOrgx    = X;
564     pdcattr->ptlWindowOrg.y = Y;
565     if (pdcattr->dwLayout & LAYOUT_RTL) NtGdiMirrorWindowOrg(hdc);
566     pdcattr->flXform |= (PAGE_XLATE_CHANGED|DEVICE_TO_WORLD_INVALID);
567     return TRUE;
568 #endif
569     return NtGdiSetWindowOrgEx(hdc, X, Y, lpPoint);
570 }
571 
572 /*
573  * @unimplemented
574  */
575 BOOL
576 WINAPI
577 SetWindowExtEx(
578     _In_ HDC hdc,
579     _In_ INT nXExtent,
580     _In_ INT nYExtent,
581     _Out_opt_ LPSIZE lpSize)
582 {
583     PDC_ATTR pdcattr;
584 
585     HANDLE_METADC(BOOL, SetWindowExtEx, FALSE, hdc, nXExtent, nYExtent, lpSize);
586 
587     /* Get the DC attr */
588     pdcattr = GdiGetDcAttr(hdc);
589     if (!pdcattr)
590     {
591         /* Set the error value and return failure */
592         SetLastError(ERROR_INVALID_PARAMETER);
593         return FALSE;
594     }
595 
596     /* Check if the caller wants the old extension */
597     if (lpSize)
598     {
599         /* Return the current window extension */
600         lpSize->cx = pdcattr->szlWindowExt.cx;
601         lpSize->cy = pdcattr->szlWindowExt.cy;
602 
603         /* Handle right-to-left layout */
604         if (pdcattr->dwLayout & LAYOUT_RTL)
605             lpSize->cx = -lpSize->cx;
606     }
607 
608     if (pdcattr->dwLayout & LAYOUT_RTL)
609     {
610         NtGdiMirrorWindowOrg(hdc);
611         pdcattr->flXform |= (PAGE_EXTENTS_CHANGED|INVALIDATE_ATTRIBUTES|DEVICE_TO_WORLD_INVALID);
612     }
613     else if ((pdcattr->iMapMode == MM_ISOTROPIC) ||
614              (pdcattr->iMapMode == MM_ANISOTROPIC))
615     {
616         if ((pdcattr->szlWindowExt.cx == nXExtent) &&
617             (pdcattr->szlWindowExt.cy == nYExtent))
618             return TRUE;
619 
620         if ((!nXExtent) || (!nYExtent))
621             return FALSE;
622 
623         if (NtCurrentTeb()->GdiTebBatch.HDC == hdc)
624         {
625             if (pdcattr->ulDirty_ & DC_FONTTEXT_DIRTY)
626             {
627                 NtGdiFlush(); // Sync up Dc_Attr from Kernel space.
628                 pdcattr->ulDirty_ &= ~(DC_MODE_DIRTY|DC_FONTTEXT_DIRTY);
629             }
630         }
631 
632         pdcattr->szlWindowExt.cx = nXExtent;
633         pdcattr->szlWindowExt.cy = nYExtent;
634         if (pdcattr->dwLayout & LAYOUT_RTL)
635             NtGdiMirrorWindowOrg(hdc);
636 
637         pdcattr->flXform |= (PAGE_EXTENTS_CHANGED|INVALIDATE_ATTRIBUTES|DEVICE_TO_WORLD_INVALID);
638     }
639 
640     return TRUE;
641 }
642 
643 /*
644  * @unimplemented
645  */
646 BOOL
647 WINAPI
648 SetViewportOrgEx(
649     _In_ HDC hdc,
650     _In_ int X,
651     _In_ int Y,
652     _Out_opt_ LPPOINT lpPoint)
653 {
654     PDC_ATTR pdcattr;
655 
656     HANDLE_METADC(BOOL, SetViewportOrgEx, FALSE, hdc, X, Y, lpPoint);
657 
658     /* Get the DC attribute */
659     pdcattr = GdiGetDcAttr(hdc);
660     if (!pdcattr)
661     {
662         /* Do not set LastError here! */
663         return FALSE;
664     }
665 
666 #if 0
667     if (lpPoint)
668     {
669         lpPoint->x = pdcattr->ptlViewportOrg.x;
670         lpPoint->y = pdcattr->ptlViewportOrg.y;
671         if (pdcattr->dwLayout & LAYOUT_RTL) lpPoint->x = -lpPoint->x;
672     }
673     pdcattr->flXform |= (PAGE_XLATE_CHANGED|DEVICE_TO_WORLD_INVALID);
674     if (pdcattr->dwLayout & LAYOUT_RTL) X = -X;
675     pdcattr->ptlViewportOrg.x = X;
676     pdcattr->ptlViewportOrg.y = Y;
677     return TRUE;
678 #endif
679     return NtGdiSetViewportOrgEx(hdc,X,Y,lpPoint);
680 }
681 
682 /*
683  * @implemented
684  */
685 BOOL
686 WINAPI
687 ScaleViewportExtEx(
688     _In_ HDC hdc,
689     _In_ INT xNum,
690     _In_ INT xDenom,
691     _In_ INT yNum,
692     _In_ INT yDenom,
693     _Out_ LPSIZE lpSize)
694 {
695     HANDLE_METADC(BOOL, ScaleViewportExtEx, FALSE, hdc, xNum, xDenom, yNum, yDenom, lpSize);
696 
697     if (!GdiGetDcAttr(hdc))
698     {
699         SetLastError(ERROR_INVALID_PARAMETER);
700         return FALSE;
701     }
702 
703     return NtGdiScaleViewportExtEx(hdc, xNum, xDenom, yNum, yDenom, lpSize);
704 }
705 
706 /*
707  * @implemented
708  */
709 BOOL
710 WINAPI
711 ScaleWindowExtEx(
712     _In_ HDC hdc,
713     _In_ INT xNum,
714     _In_ INT xDenom,
715     _In_ INT yNum,
716     _In_ INT yDenom,
717     _Out_ LPSIZE lpSize)
718 {
719     HANDLE_METADC(BOOL, ScaleWindowExtEx, FALSE, hdc, xNum, xDenom, yNum, yDenom, lpSize);
720 
721     if (!GdiGetDcAttr(hdc))
722     {
723         SetLastError(ERROR_INVALID_PARAMETER);
724         return FALSE;
725     }
726 
727     return NtGdiScaleWindowExtEx(hdc, xNum, xDenom, yNum, yDenom, lpSize);
728 }
729 
730 /*
731  * @implemented
732  */
733 DWORD
734 WINAPI
735 GetLayout(
736     _In_ HDC hdc)
737 {
738     PDC_ATTR pdcattr;
739 
740     /* METADC16 is not supported in this API */
741     if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE)
742     {
743         return GDI_ERROR;
744     }
745 
746     /* Get the DC attribute */
747     pdcattr = GdiGetDcAttr(hdc);
748     if (!pdcattr)
749     {
750         /* Set the error value and return failure */
751         SetLastError(ERROR_INVALID_PARAMETER);
752         return GDI_ERROR;
753     }
754 
755     /* Return the layout */
756     return pdcattr->dwLayout;
757 }
758 
759 
760 /*
761  * @implemented
762  */
763 DWORD
764 WINAPI
765 SetLayout(
766     _In_ HDC hdc,
767     _In_ DWORD dwLayout)
768 {
769     HANDLE_METADC(DWORD, SetLayout, GDI_ERROR, hdc, dwLayout);
770 
771     if (!GdiGetDcAttr(hdc))
772     {
773         SetLastError(ERROR_INVALID_PARAMETER);
774         return GDI_ERROR;
775     }
776 
777     return NtGdiSetLayout(hdc, -1, dwLayout);
778 }
779 
780 /*
781  * @implemented
782  */
783 DWORD
784 WINAPI
785 SetLayoutWidth(
786     _In_ HDC hdc,
787     _In_ LONG wox,
788     _In_ DWORD dwLayout)
789 {
790     /* Only normal DCs are handled here */
791     if (GDI_HANDLE_GET_TYPE(hdc) != GDILoObjType_LO_DC_TYPE)
792     {
793         return GDI_ERROR;
794     }
795 
796     if (!GdiGetDcAttr(hdc))
797     {
798         SetLastError(ERROR_INVALID_PARAMETER);
799         return GDI_ERROR;
800     }
801 
802     return NtGdiSetLayout(hdc, wox, dwLayout);
803 }
804 
805 /*
806  * @implemented
807  */
808 BOOL
809 WINAPI
810 GetDCOrgEx(
811     _In_ HDC hdc,
812     _Out_ LPPOINT lpPoint)
813 {
814     return NtGdiGetDCPoint(hdc, GdiGetDCOrg, (PPOINTL)lpPoint);
815 }
816 
817 
818 /*
819  * @implemented
820  */
821 LONG
822 WINAPI
823 GetDCOrg(
824     _In_ HDC hdc)
825 {
826     POINT pt;
827 
828     /* Call the new API */
829     if (!GetDCOrgEx(hdc, &pt))
830         return 0;
831 
832     /* Return the point in the old way */
833     return(MAKELONG(pt.x, pt.y));
834 }
835 
836 
837 /*
838  * @implemented
839  *
840  */
841 BOOL
842 WINAPI
843 OffsetViewportOrgEx(
844     _In_ HDC hdc,
845     _In_ int nXOffset,
846     _In_ int nYOffset,
847     _Out_opt_ LPPOINT lpPoint)
848 {
849     //PDC_ATTR pdcattr;
850 
851     HANDLE_METADC(BOOL, OffsetViewportOrgEx, FALSE, hdc, nXOffset, nYOffset, lpPoint);
852 #if 0
853 
854     /* Get the DC attribute */
855     pdcattr = GdiGetDcAttr(hdc);
856     if (!pdcattr)
857     {
858         /* Do not set LastError here! */
859         return FALSE;
860     }
861 
862     if (lpPoint)
863     {
864         *lpPoint = (POINT)pdcattr->ptlViewportOrg;
865         if ( pdcattr->dwLayout & LAYOUT_RTL) lpPoint->x = -lpPoint->x;
866     }
867 
868     if ( nXOffset || nYOffset != nXOffset )
869     {
870         if (NtCurrentTeb()->GdiTebBatch.HDC == (ULONG)hdc)
871         {
872             if (pdcattr->ulDirty_ & DC_MODE_DIRTY)
873             {
874                 NtGdiFlush();
875                 pdcattr->ulDirty_ &= ~DC_MODE_DIRTY;
876             }
877         }
878 
879         pdcattr->flXform |= (PAGE_XLATE_CHANGED|DEVICE_TO_WORLD_INVALID);
880         if (pdcattr->dwLayout & LAYOUT_RTL) nXOffset = -nXOffset;
881         pdcattr->ptlViewportOrg.x += nXOffset;
882         pdcattr->ptlViewportOrg.y += nYOffset;
883     }
884     return TRUE;
885 #endif
886     return  NtGdiOffsetViewportOrgEx(hdc, nXOffset, nYOffset, lpPoint);
887 }
888 
889 /*
890  * @implemented
891  *
892  */
893 BOOL
894 WINAPI
895 OffsetWindowOrgEx(
896     _In_ HDC hdc,
897     _In_ int nXOffset,
898     _In_ int nYOffset,
899     _Out_opt_ LPPOINT lpPoint)
900 {
901     //PDC_ATTR pdcattr;
902 
903     HANDLE_METADC(BOOL, OffsetWindowOrgEx, FALSE, hdc, nXOffset, nYOffset, lpPoint);
904 
905 #if 0
906     /* Get the DC attribute */
907     pdcattr = GdiGetDcAttr(hdc);
908     if (!pdcattr)
909     {
910         /* Do not set LastError here! */
911         return FALSE;
912     }
913 
914     if ( lpPoint )
915     {
916         *lpPoint   = (POINT)pdcattr->ptlWindowOrg;
917         lpPoint->x = pdcattr->lWindowOrgx;
918     }
919 
920     if ( nXOffset || nYOffset != nXOffset )
921     {
922         if (NtCurrentTeb()->GdiTebBatch.HDC == (ULONG)hdc)
923         {
924             if (pdcattr->ulDirty_ & DC_MODE_DIRTY)
925             {
926                 NtGdiFlush();
927                 pdcattr->ulDirty_ &= ~DC_MODE_DIRTY;
928             }
929         }
930 
931         pdcattr->flXform |= (PAGE_XLATE_CHANGED|DEVICE_TO_WORLD_INVALID);
932         pdcattr->ptlWindowOrg.x += nXOffset;
933         pdcattr->ptlWindowOrg.y += nYOffset;
934         pdcattr->lWindowOrgx += nXOffset;
935     }
936     return TRUE;
937 #endif
938     return NtGdiOffsetWindowOrgEx(hdc, nXOffset, nYOffset, lpPoint);
939 }
940 
941