2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * PURPOSE: Coordinate systems
24 * FILE: subsys/win32k/objects/coord.c
28 /* INCLUDES ******************************************************************/
35 /* FUNCTIONS *****************************************************************/
38 IntFixIsotropicMapping(PDC dc
)
43 /* Get a pointer to the DC_ATTR */
44 pdcattr
= dc
->pdcattr
;
46 /* Check if all values are valid */
47 if (pdcattr
->szlWindowExt
.cx
== 0 || pdcattr
->szlWindowExt
.cy
== 0 ||
48 pdcattr
->szlViewportExt
.cx
== 0 || pdcattr
->szlViewportExt
.cy
== 0)
50 /* Don't recalculate */
54 fx
= abs(pdcattr
->szlWindowExt
.cx
* pdcattr
->szlViewportExt
.cy
);
55 fy
= abs(pdcattr
->szlWindowExt
.cy
* pdcattr
->szlViewportExt
.cx
);
59 s
= pdcattr
->szlWindowExt
.cy
* pdcattr
->szlViewportExt
.cx
> 0 ? 1 : -1;
60 pdcattr
->szlViewportExt
.cx
= s
* fx
/ pdcattr
->szlWindowExt
.cy
;
64 s
= pdcattr
->szlWindowExt
.cx
* pdcattr
->szlViewportExt
.cy
> 0 ? 1 : -1;
65 pdcattr
->szlViewportExt
.cy
= s
* fy
/ pdcattr
->szlWindowExt
.cx
;
70 IntGdiCombineTransform(LPXFORM XFormResult
,
75 /* Check for illegal parameters */
76 if (!XFormResult
|| !xform1
|| !xform2
)
81 /* Create the result in a temporary XFORM, since xformResult may be
82 * equal to xform1 or xform2 */
83 xformTemp
.eM11
= xform1
->eM11
* xform2
->eM11
+ xform1
->eM12
* xform2
->eM21
;
84 xformTemp
.eM12
= xform1
->eM11
* xform2
->eM12
+ xform1
->eM12
* xform2
->eM22
;
85 xformTemp
.eM21
= xform1
->eM21
* xform2
->eM11
+ xform1
->eM22
* xform2
->eM21
;
86 xformTemp
.eM22
= xform1
->eM21
* xform2
->eM12
+ xform1
->eM22
* xform2
->eM22
;
87 xformTemp
.eDx
= xform1
->eDx
* xform2
->eM11
+ xform1
->eDy
* xform2
->eM21
+ xform2
->eDx
;
88 xformTemp
.eDy
= xform1
->eDx
* xform2
->eM12
+ xform1
->eDy
* xform2
->eM22
+ xform2
->eDy
;
89 *XFormResult
= xformTemp
;
94 BOOL APIENTRY
NtGdiCombineTransform(LPXFORM UnsafeXFormResult
,
102 ProbeForWrite(UnsafeXFormResult
, sizeof(XFORM
), 1);
103 ProbeForRead(Unsafexform1
, sizeof(XFORM
), 1);
104 ProbeForRead(Unsafexform2
, sizeof(XFORM
), 1);
105 Ret
= IntGdiCombineTransform(UnsafeXFormResult
,
109 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
121 IntGetGraphicsMode(PDC dc
)
125 pdcattr
= dc
->pdcattr
;
126 return pdcattr
->iGraphicsMode
;
131 IntGdiModifyWorldTransform(PDC pDc
,
132 CONST LPXFORM lpXForm
,
136 XFORM xformWorld2Wnd
;
141 xformWorld2Wnd
.eM11
= 1.0f
;
142 xformWorld2Wnd
.eM12
= 0.0f
;
143 xformWorld2Wnd
.eM21
= 0.0f
;
144 xformWorld2Wnd
.eM22
= 1.0f
;
145 xformWorld2Wnd
.eDx
= 0.0f
;
146 xformWorld2Wnd
.eDy
= 0.0f
;
147 XForm2MatrixS(&pDc
->dclevel
.mxWorldToPage
, &xformWorld2Wnd
);
150 case MWT_LEFTMULTIPLY
:
151 MatrixS2XForm(&xformWorld2Wnd
, &pDc
->dclevel
.mxWorldToPage
);
152 IntGdiCombineTransform(&xformWorld2Wnd
, lpXForm
, &xformWorld2Wnd
);
153 XForm2MatrixS(&pDc
->dclevel
.mxWorldToPage
, &xformWorld2Wnd
);
156 case MWT_RIGHTMULTIPLY
:
157 MatrixS2XForm(&xformWorld2Wnd
, &pDc
->dclevel
.mxWorldToPage
);
158 IntGdiCombineTransform(&xformWorld2Wnd
, &xformWorld2Wnd
, lpXForm
);
159 XForm2MatrixS(&pDc
->dclevel
.mxWorldToPage
, &xformWorld2Wnd
);
162 case MWT_MAX
+1: // Must be MWT_SET????
163 XForm2MatrixS(&pDc
->dclevel
.mxWorldToPage
, lpXForm
); // Do it like Wine.
169 DC_UpdateXforms(pDc
);
175 NtGdiGetTransform(HDC hDC
,
180 NTSTATUS Status
= STATUS_SUCCESS
;
185 SetLastWin32Error(ERROR_INVALID_HANDLE
);
191 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
197 ProbeForWrite(XForm
, sizeof(XFORM
), 1);
200 case GdiWorldSpaceToPageSpace
:
201 MatrixS2XForm(XForm
, &dc
->dclevel
.mxWorldToPage
);
207 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
209 Status
= _SEH2_GetExceptionCode();
214 return NT_SUCCESS(Status
);
219 * Converts points from logical coordinates into device coordinates. Conversion depends on the mapping mode,
220 * world transfrom, viewport origin settings for the given device context.
221 * \param hDC device context.
222 * \param Points an array of POINT structures (in/out).
223 * \param Count number of elements in the array of POINT structures.
224 * \return TRUE if success.
228 NtGdiTransformPoints(HDC hDC
,
235 NTSTATUS Status
= STATUS_SUCCESS
;
242 SetLastWin32Error(ERROR_INVALID_HANDLE
);
246 if (!UnsafePtsIn
|| !UnsafePtOut
|| Count
<= 0)
249 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
253 Size
= Count
* sizeof(POINT
);
255 Points
= (LPPOINT
)ExAllocatePoolWithTag(PagedPool
, Size
, TAG_COORD
);
259 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
265 ProbeForWrite(UnsafePtOut
, Size
, 1);
266 ProbeForRead(UnsafePtsIn
, Size
, 1);
267 RtlCopyMemory(Points
, UnsafePtsIn
, Size
);
269 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
271 Status
= _SEH2_GetExceptionCode();
275 if (!NT_SUCCESS(Status
))
278 ExFreePoolWithTag(Points
, TAG_COORD
);
279 SetLastNtError(Status
);
286 IntDPtoLP(dc
, Points
, Count
);
289 IntLPtoDP(dc
, Points
, Count
);
291 case 2: // Not supported yet. Need testing.
295 ExFreePoolWithTag(Points
, TAG_COORD
);
296 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
303 /* pointer was already probed! */
304 RtlCopyMemory(UnsafePtOut
, Points
, Size
);
306 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
308 Status
= _SEH2_GetExceptionCode();
312 if (!NT_SUCCESS(Status
))
315 ExFreePoolWithTag(Points
, TAG_COORD
);
316 SetLastNtError(Status
);
320 // If we are getting called that means User XForms is a mess!
323 ExFreePoolWithTag(Points
, TAG_COORD
);
329 NtGdiModifyWorldTransform(HDC hDC
,
340 SetLastWin32Error(ERROR_INVALID_HANDLE
);
344 // The xform is permitted to be NULL for MWT_IDENTITY.
345 // However, if it is not NULL, then it must be valid even though it is not used.
346 if (UnsafeXForm
!= NULL
|| Mode
!= MWT_IDENTITY
)
350 ProbeForRead(UnsafeXForm
, sizeof(XFORM
), 1);
351 RtlCopyMemory(&SafeXForm
, UnsafeXForm
, sizeof(XFORM
));
353 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
360 // Safe to handle kernel mode data.
361 if (Ret
) Ret
= IntGdiModifyWorldTransform(dc
, &SafeXForm
, Mode
);
368 NtGdiOffsetViewportOrgEx(HDC hDC
,
375 NTSTATUS Status
= STATUS_SUCCESS
;
380 SetLastWin32Error(ERROR_INVALID_HANDLE
);
383 pdcattr
= dc
->pdcattr
;
389 ProbeForWrite(UnsafePoint
, sizeof(POINT
), 1);
390 UnsafePoint
->x
= pdcattr
->ptlViewportOrg
.x
;
391 UnsafePoint
->y
= pdcattr
->ptlViewportOrg
.y
;
392 if (pdcattr
->dwLayout
& LAYOUT_RTL
)
394 UnsafePoint
->x
= -UnsafePoint
->x
;
397 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
399 Status
= _SEH2_GetExceptionCode();
403 if (!NT_SUCCESS(Status
))
405 SetLastNtError(Status
);
411 if (pdcattr
->dwLayout
& LAYOUT_RTL
)
415 pdcattr
->ptlViewportOrg
.x
+= XOffset
;
416 pdcattr
->ptlViewportOrg
.y
+= YOffset
;
425 NtGdiOffsetWindowOrgEx(HDC hDC
,
436 SetLastWin32Error(ERROR_INVALID_HANDLE
);
439 pdcattr
= dc
->pdcattr
;
443 NTSTATUS Status
= STATUS_SUCCESS
;
447 ProbeForWrite(Point
, sizeof(POINT
), 1);
448 Point
->x
= pdcattr
->ptlWindowOrg
.x
;
449 Point
->y
= pdcattr
->ptlWindowOrg
.y
;
451 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
453 Status
= _SEH2_GetExceptionCode();
457 if (!NT_SUCCESS(Status
))
459 SetLastNtError(Status
);
465 pdcattr
->ptlWindowOrg
.x
+= XOffset
;
466 pdcattr
->ptlWindowOrg
.y
+= YOffset
;
476 NtGdiScaleViewportExtEx(HDC hDC
,
488 pDC
= DC_LockDc(hDC
);
491 SetLastWin32Error(ERROR_INVALID_HANDLE
);
494 pdcattr
= pDC
->pdcattr
;
498 NTSTATUS Status
= STATUS_SUCCESS
;
502 ProbeForWrite(pSize
, sizeof(LPSIZE
), 1);
504 pSize
->cx
= pdcattr
->szlViewportExt
.cx
;
505 pSize
->cy
= pdcattr
->szlViewportExt
.cy
;
507 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
509 Status
= _SEH2_GetExceptionCode();
513 if (!NT_SUCCESS(Status
))
515 SetLastNtError(Status
);
521 if (pdcattr
->iMapMode
> MM_TWIPS
)
523 if (Xdenom
&& Ydenom
)
525 X
= Xnum
* pdcattr
->szlViewportExt
.cx
/ Xdenom
;
528 Y
= Ynum
* pdcattr
->szlViewportExt
.cy
/ Ydenom
;
531 pdcattr
->szlViewportExt
.cx
= X
;
532 pdcattr
->szlViewportExt
.cy
= Y
;
534 IntMirrorWindowOrg(pDC
);
536 pdcattr
->flXform
|= (PAGE_EXTENTS_CHANGED
|
537 INVALIDATE_ATTRIBUTES
|
538 DEVICE_TO_WORLD_INVALID
);
540 if (pdcattr
->iMapMode
== MM_ISOTROPIC
)
542 IntFixIsotropicMapping(pDC
);
544 DC_UpdateXforms(pDC
);
560 NtGdiScaleWindowExtEx(HDC hDC
,
572 pDC
= DC_LockDc(hDC
);
575 SetLastWin32Error(ERROR_INVALID_HANDLE
);
578 pdcattr
= pDC
->pdcattr
;
582 NTSTATUS Status
= STATUS_SUCCESS
;
586 ProbeForWrite(pSize
, sizeof(LPSIZE
), 1);
588 X
= pdcattr
->szlWindowExt
.cx
;
589 if (pdcattr
->dwLayout
& LAYOUT_RTL
) X
= -X
;
591 pSize
->cy
= pdcattr
->szlWindowExt
.cy
;
593 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
595 Status
= _SEH2_GetExceptionCode();
599 if (!NT_SUCCESS(Status
))
601 SetLastNtError(Status
);
607 if (pdcattr
->iMapMode
> MM_TWIPS
)
609 if (Xdenom
&& Ydenom
)
611 X
= Xnum
* pdcattr
->szlWindowExt
.cx
/ Xdenom
;
614 Y
= Ynum
* pdcattr
->szlWindowExt
.cy
/ Ydenom
;
617 pdcattr
->szlWindowExt
.cx
= X
;
618 pdcattr
->szlWindowExt
.cy
= Y
;
620 IntMirrorWindowOrg(pDC
);
622 pdcattr
->flXform
|= (PAGE_EXTENTS_CHANGED
|INVALIDATE_ATTRIBUTES
|DEVICE_TO_WORLD_INVALID
);
624 if (pdcattr
->iMapMode
== MM_ISOTROPIC
) IntFixIsotropicMapping(pDC
);
625 DC_UpdateXforms(pDC
);
641 IntGdiSetMapMode(PDC dc
,
645 PDC_ATTR pdcattr
= dc
->pdcattr
;
647 PrevMapMode
= pdcattr
->iMapMode
;
649 pdcattr
->iMapMode
= MapMode
;
654 pdcattr
->szlWindowExt
.cx
= 1;
655 pdcattr
->szlWindowExt
.cy
= 1;
656 pdcattr
->szlViewportExt
.cx
= 1;
657 pdcattr
->szlViewportExt
.cy
= 1;
658 pdcattr
->flXform
&= ~(ISO_OR_ANISO_MAP_MODE
|PTOD_EFM22_NEGATIVE
|
659 PTOD_EFM11_NEGATIVE
|POSITIVE_Y_IS_UP
);
660 pdcattr
->flXform
|= (PAGE_XLATE_CHANGED
|PAGE_TO_DEVICE_SCALE_IDENTITY
|
661 INVALIDATE_ATTRIBUTES
|DEVICE_TO_WORLD_INVALID
);
665 pdcattr
->flXform
|= ISO_OR_ANISO_MAP_MODE
;
669 pdcattr
->szlWindowExt
.cx
= 3600;
670 pdcattr
->szlWindowExt
.cy
= 2700;
671 pdcattr
->szlViewportExt
.cx
= ((PGDIDEVICE
)dc
->ppdev
)->GDIInfo
.ulHorzRes
;
672 pdcattr
->szlViewportExt
.cy
= -((PGDIDEVICE
)dc
->ppdev
)->GDIInfo
.ulVertRes
;
676 pdcattr
->szlWindowExt
.cx
= 36000;
677 pdcattr
->szlWindowExt
.cy
= 27000;
678 pdcattr
->szlViewportExt
.cx
= ((PGDIDEVICE
)dc
->ppdev
)->GDIInfo
.ulHorzRes
;
679 pdcattr
->szlViewportExt
.cy
= -((PGDIDEVICE
)dc
->ppdev
)->GDIInfo
.ulVertRes
;
683 pdcattr
->szlWindowExt
.cx
= 1417;
684 pdcattr
->szlWindowExt
.cy
= 1063;
685 pdcattr
->szlViewportExt
.cx
= ((PGDIDEVICE
)dc
->ppdev
)->GDIInfo
.ulHorzRes
;
686 pdcattr
->szlViewportExt
.cy
= -((PGDIDEVICE
)dc
->ppdev
)->GDIInfo
.ulVertRes
;
690 pdcattr
->szlWindowExt
.cx
= 14173;
691 pdcattr
->szlWindowExt
.cy
= 10630;
692 pdcattr
->szlViewportExt
.cx
= ((PGDIDEVICE
)dc
->ppdev
)->GDIInfo
.ulHorzRes
;
693 pdcattr
->szlViewportExt
.cy
= -((PGDIDEVICE
)dc
->ppdev
)->GDIInfo
.ulVertRes
;
697 pdcattr
->szlWindowExt
.cx
= 20409;
698 pdcattr
->szlWindowExt
.cy
= 15307;
699 pdcattr
->szlViewportExt
.cx
= ((PGDIDEVICE
)dc
->ppdev
)->GDIInfo
.ulHorzRes
;
700 pdcattr
->szlViewportExt
.cy
= -((PGDIDEVICE
)dc
->ppdev
)->GDIInfo
.ulVertRes
;
704 pdcattr
->flXform
&= ~(PAGE_TO_DEVICE_IDENTITY
|POSITIVE_Y_IS_UP
);
705 pdcattr
->flXform
|= ISO_OR_ANISO_MAP_MODE
;
708 pdcattr
->iMapMode
= PrevMapMode
;
719 NtGdiSetViewportOrgEx(HDC hDC
,
730 SetLastWin32Error(ERROR_INVALID_HANDLE
);
733 pdcattr
= dc
->pdcattr
;
737 NTSTATUS Status
= STATUS_SUCCESS
;
741 ProbeForWrite(Point
, sizeof(POINT
), 1);
742 Point
->x
= pdcattr
->ptlViewportOrg
.x
;
743 Point
->y
= pdcattr
->ptlViewportOrg
.y
;
745 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
747 Status
= _SEH2_GetExceptionCode();
751 if (!NT_SUCCESS(Status
))
753 SetLastNtError(Status
);
759 pdcattr
->ptlViewportOrg
.x
= X
;
760 pdcattr
->ptlViewportOrg
.y
= Y
;
770 NtGdiSetWindowOrgEx(HDC hDC
,
781 SetLastWin32Error(ERROR_INVALID_HANDLE
);
784 pdcattr
= dc
->pdcattr
;
788 NTSTATUS Status
= STATUS_SUCCESS
;
792 ProbeForWrite(Point
, sizeof(POINT
), 1);
793 Point
->x
= pdcattr
->ptlWindowOrg
.x
;
794 Point
->y
= pdcattr
->ptlWindowOrg
.y
;
796 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
798 Status
= _SEH2_GetExceptionCode();
802 if (!NT_SUCCESS(Status
))
804 SetLastNtError(Status
);
810 pdcattr
->ptlWindowOrg
.x
= X
;
811 pdcattr
->ptlWindowOrg
.y
= Y
;
820 // Mirror Window function.
824 IntMirrorWindowOrg(PDC dc
)
829 pdcattr
= dc
->pdcattr
;
831 if (!(pdcattr
->dwLayout
& LAYOUT_RTL
))
833 pdcattr
->ptlWindowOrg
.x
= pdcattr
->lWindowOrgx
; // Flip it back.
836 if (!pdcattr
->szlViewportExt
.cx
) return;
838 // WOrgx = wox - (Width - 1) * WExtx / VExtx
840 X
= (dc
->erclWindow
.right
- dc
->erclWindow
.left
) - 1; // Get device width - 1
842 X
= (X
* pdcattr
->szlWindowExt
.cx
) / pdcattr
->szlViewportExt
.cx
;
844 pdcattr
->ptlWindowOrg
.x
= pdcattr
->lWindowOrgx
- X
; // Now set the inverted win origion.
851 // The default is left to right. This function changes it to right to left, which
852 // is the standard in Arabic and Hebrew cultures.
871 SetLastWin32Error(ERROR_INVALID_HANDLE
);
874 pdcattr
= dc
->pdcattr
;
876 pdcattr
->dwLayout
= dwLayout
;
877 oLayout
= pdcattr
->dwLayout
;
879 if (!(dwLayout
& LAYOUT_ORIENTATIONMASK
))
885 if (dwLayout
& LAYOUT_RTL
)
887 pdcattr
->iMapMode
= MM_ANISOTROPIC
;
890 pdcattr
->szlWindowExt
.cy
= -pdcattr
->szlWindowExt
.cy
;
891 pdcattr
->ptlWindowOrg
.x
= -pdcattr
->ptlWindowOrg
.x
;
894 IntMirrorWindowOrg(dc
);
896 pdcattr
->ptlWindowOrg
.x
= wox
- pdcattr
->ptlWindowOrg
.x
;
898 if (!(pdcattr
->flTextAlign
& TA_CENTER
)) pdcattr
->flTextAlign
|= TA_RIGHT
;
900 if (dc
->dclevel
.flPath
& DCPATH_CLOCKWISE
)
901 dc
->dclevel
.flPath
&= ~DCPATH_CLOCKWISE
;
903 dc
->dclevel
.flPath
|= DCPATH_CLOCKWISE
;
905 pdcattr
->flXform
|= (PAGE_EXTENTS_CHANGED
|
906 INVALIDATE_ATTRIBUTES
|
907 DEVICE_TO_WORLD_INVALID
);
909 // DC_UpdateXforms(dc);
927 SetLastWin32Error(ERROR_INVALID_HANDLE
);
930 Ret
= dc
->erclWindow
.right
- dc
->erclWindow
.left
;
940 NtGdiMirrorWindowOrg(
947 SetLastWin32Error(ERROR_INVALID_HANDLE
);
950 IntMirrorWindowOrg(dc
);
962 IN INT cxVirtualDevice
,
963 IN INT cyVirtualDevice
)
968 if (!cxVirtualDevice
|| !cyVirtualDevice
)
974 if (!dc
) return FALSE
;
976 pdcattr
= dc
->pdcattr
;
978 pdcattr
->szlVirtualDeviceSize
.cx
= cxVirtualDevice
;
979 pdcattr
->szlVirtualDeviceSize
.cy
= cyVirtualDevice
;
981 // DC_UpdateXforms(dc);
992 NtGdiSetVirtualResolution(
994 IN INT cxVirtualDevicePixel
,
995 IN INT cyVirtualDevicePixel
,
996 IN INT cxVirtualDeviceMm
,
997 IN INT cyVirtualDeviceMm
)
1002 // Need test types for zeros and non zeros
1004 dc
= DC_LockDc(hdc
);
1005 if (!dc
) return FALSE
;
1007 pdcattr
= dc
->pdcattr
;
1009 pdcattr
->szlVirtualDevicePixel
.cx
= cxVirtualDevicePixel
;
1010 pdcattr
->szlVirtualDevicePixel
.cy
= cyVirtualDevicePixel
;
1011 pdcattr
->szlVirtualDeviceMm
.cx
= cxVirtualDeviceMm
;
1012 pdcattr
->szlVirtualDeviceMm
.cy
= cyVirtualDeviceMm
;
1014 // DC_UpdateXforms(dc);