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