[GDI32] Use Gdi Flush for SetViewportOrgEx.
[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 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