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
)
40 ULONG xdim
= EngMulDiv(dc
->Dc_Attr
.szlViewportExt
.cx
, dc
->GDIInfo
->ulHorzSize
, dc
->GDIInfo
->ulHorzRes
) / dc
->Dc_Attr
.szlWindowExt
.cx
;
41 ULONG ydim
= EngMulDiv(dc
->Dc_Attr
.szlViewportExt
.cy
, dc
->GDIInfo
->ulVertSize
, dc
->GDIInfo
->ulVertRes
) / dc
->Dc_Attr
.szlWindowExt
.cy
;
45 dc
->Dc_Attr
.szlViewportExt
.cx
= dc
->Dc_Attr
.szlViewportExt
.cx
* abs(ydim
/ xdim
);
46 if (!dc
->Dc_Attr
.szlViewportExt
.cx
) dc
->Dc_Attr
.szlViewportExt
.cx
= 1;
50 dc
->Dc_Attr
.szlViewportExt
.cy
= dc
->Dc_Attr
.szlViewportExt
.cy
* abs(xdim
/ ydim
);
51 if (!dc
->Dc_Attr
.szlViewportExt
.cy
) dc
->Dc_Attr
.szlViewportExt
.cy
= 1;
56 IntGdiCombineTransform(LPXFORM XFormResult
,
60 /* Check for illegal parameters */
61 if (!XFormResult
|| !xform1
|| !xform2
)
66 /* Create the result in a temporary XFORM, since xformResult may be
67 * equal to xform1 or xform2 */
68 XFormResult
->eM11
= xform1
->eM11
* xform2
->eM11
+ xform1
->eM12
* xform2
->eM21
;
69 XFormResult
->eM12
= xform1
->eM11
* xform2
->eM12
+ xform1
->eM12
* xform2
->eM22
;
70 XFormResult
->eM21
= xform1
->eM21
* xform2
->eM11
+ xform1
->eM22
* xform2
->eM21
;
71 XFormResult
->eM22
= xform1
->eM21
* xform2
->eM12
+ xform1
->eM22
* xform2
->eM22
;
72 XFormResult
->eDx
= xform1
->eDx
* xform2
->eM11
+ xform1
->eDy
* xform2
->eM21
+ xform2
->eDx
;
73 XFormResult
->eDy
= xform1
->eDx
* xform2
->eM12
+ xform1
->eDy
* xform2
->eM22
+ xform2
->eDy
;
78 BOOL STDCALL
NtGdiCombineTransform(LPXFORM UnsafeXFormResult
,
79 CONST LPXFORM Unsafexform1
,
80 CONST LPXFORM Unsafexform2
)
83 XFORM xform1
= {0}, xform2
= {0};
84 NTSTATUS Status
= STATUS_SUCCESS
;
89 ProbeForWrite(UnsafeXFormResult
,
92 ProbeForRead(Unsafexform1
,
95 ProbeForRead(Unsafexform2
,
98 xform1
= *Unsafexform1
;
99 xform2
= *Unsafexform2
;
103 Status
= _SEH_GetExceptionCode();
107 if(!NT_SUCCESS(Status
))
109 SetLastNtError(Status
);
113 Ret
= IntGdiCombineTransform(&xformTemp
, &xform1
, &xform2
);
115 /* Copy the result to xformResult */
118 /* pointer was already probed! */
119 *UnsafeXFormResult
= xformTemp
;
123 Status
= _SEH_GetExceptionCode();
127 if(!NT_SUCCESS(Status
))
129 SetLastNtError(Status
);
137 CoordDPtoLP(PDC Dc
, LPPOINT Point
)
142 Point
->x
= x
* Dc
->w
.xformVport2World
.eM11
+
143 y
* Dc
->w
.xformVport2World
.eM21
+ Dc
->w
.xformVport2World
.eDx
;
144 Point
->y
= x
* Dc
->w
.xformVport2World
.eM12
+
145 y
* Dc
->w
.xformVport2World
.eM22
+ Dc
->w
.xformVport2World
.eDy
;
150 IntDPtoLP ( PDC dc
, LPPOINT Points
, INT Count
)
156 for ( i
= 0; i
< Count
; i
++ )
157 CoordDPtoLP ( dc
, &Points
[i
] );
161 * Converts points from device coordinates into logical coordinates. Conversion depends on the mapping mode,
162 * world transfrom, viewport origin settings for the given device context.
163 * \param hDC device context.
164 * \param Points an array of POINT structures (in/out).
165 * \param Count number of elements in the array of POINT structures.
166 * \return TRUE if success.
170 LPPOINT UnsafePoints
,
174 NTSTATUS Status
= STATUS_SUCCESS
;
181 SetLastWin32Error(ERROR_INVALID_HANDLE
);
185 if (!UnsafePoints
|| Count
<= 0)
188 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
192 Size
= Count
* sizeof(POINT
);
194 Points
= (LPPOINT
)ExAllocatePoolWithTag(PagedPool
, Size
, TAG_COORD
);
198 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
204 ProbeForWrite(UnsafePoints
,
207 RtlCopyMemory(Points
,
213 Status
= _SEH_GetExceptionCode();
217 if(!NT_SUCCESS(Status
))
221 SetLastNtError(Status
);
225 IntDPtoLP(dc
, Points
, Count
);
229 /* pointer was already probed! */
230 RtlCopyMemory(UnsafePoints
,
236 Status
= _SEH_GetExceptionCode();
240 if(!NT_SUCCESS(Status
))
244 SetLastNtError(Status
);
255 IntGetGraphicsMode ( PDC dc
)
258 return dc
->Dc_Attr
.iGraphicsMode
;
263 IntGdiModifyWorldTransform(PDC pDc
,
264 CONST LPXFORM lpXForm
,
267 ASSERT(pDc
&& lpXForm
);
272 pDc
->w
.xformWorld2Wnd
.eM11
= 1.0f
;
273 pDc
->w
.xformWorld2Wnd
.eM12
= 0.0f
;
274 pDc
->w
.xformWorld2Wnd
.eM21
= 0.0f
;
275 pDc
->w
.xformWorld2Wnd
.eM22
= 1.0f
;
276 pDc
->w
.xformWorld2Wnd
.eDx
= 0.0f
;
277 pDc
->w
.xformWorld2Wnd
.eDy
= 0.0f
;
280 case MWT_LEFTMULTIPLY
:
281 IntGdiCombineTransform(&pDc
->w
.xformWorld2Wnd
, lpXForm
, &pDc
->w
.xformWorld2Wnd
);
284 case MWT_RIGHTMULTIPLY
:
285 IntGdiCombineTransform(&pDc
->w
.xformWorld2Wnd
, &pDc
->w
.xformWorld2Wnd
, lpXForm
);
289 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
293 DC_UpdateXforms(pDc
);
300 NtGdiGetGraphicsMode ( HDC hDC
)
303 int GraphicsMode
; // default to failure
305 dc
= DC_LockDc ( hDC
);
308 SetLastWin32Error(ERROR_INVALID_HANDLE
);
312 GraphicsMode
= dc
->Dc_Attr
.iGraphicsMode
;
320 NtGdiGetWorldTransform(HDC hDC
,
324 NTSTATUS Status
= STATUS_SUCCESS
;
326 dc
= DC_LockDc ( hDC
);
329 SetLastWin32Error(ERROR_INVALID_HANDLE
);
335 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
344 *XForm
= dc
->w
.xformWorld2Wnd
;
348 Status
= _SEH_GetExceptionCode();
353 return NT_SUCCESS(Status
);
358 CoordLPtoDP ( PDC Dc
, LPPOINT Point
)
367 Point
->x
= x
* Dc
->w
.xformWorld2Vport
.eM11
+
368 y
* Dc
->w
.xformWorld2Vport
.eM21
+ Dc
->w
.xformWorld2Vport
.eDx
;
369 Point
->y
= x
* Dc
->w
.xformWorld2Vport
.eM12
+
370 y
* Dc
->w
.xformWorld2Vport
.eM22
+ Dc
->w
.xformWorld2Vport
.eDy
;
375 IntLPtoDP ( PDC dc
, LPPOINT Points
, INT Count
)
381 for ( i
= 0; i
< Count
; i
++ )
382 CoordLPtoDP ( dc
, &Points
[i
] );
386 * Converts points from logical coordinates into device coordinates. Conversion depends on the mapping mode,
387 * world transfrom, viewport origin settings for the given device context.
388 * \param hDC device context.
389 * \param Points an array of POINT structures (in/out).
390 * \param Count number of elements in the array of POINT structures.
391 * \return TRUE if success.
394 NtGdiLPtoDP ( HDC hDC
, LPPOINT UnsafePoints
, INT Count
)
397 NTSTATUS Status
= STATUS_SUCCESS
;
404 SetLastWin32Error(ERROR_INVALID_HANDLE
);
408 if (!UnsafePoints
|| Count
<= 0)
411 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
415 Size
= Count
* sizeof(POINT
);
417 Points
= (LPPOINT
)ExAllocatePoolWithTag(PagedPool
, Size
, TAG_COORD
);
421 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
427 ProbeForWrite(UnsafePoints
,
430 RtlCopyMemory(Points
,
436 Status
= _SEH_GetExceptionCode();
440 if(!NT_SUCCESS(Status
))
444 SetLastNtError(Status
);
448 IntLPtoDP(dc
, Points
, Count
);
452 /* pointer was already probed! */
453 RtlCopyMemory(UnsafePoints
,
459 Status
= _SEH_GetExceptionCode();
463 if(!NT_SUCCESS(Status
))
467 SetLastNtError(Status
);
479 NtGdiTransformPoints( HDC hdc
,
491 NtGdiModifyWorldTransform(HDC hDC
,
492 CONST LPXFORM UnsafeXForm
,
501 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
508 SetLastWin32Error(ERROR_INVALID_HANDLE
);
514 ProbeForRead(UnsafeXForm
, sizeof(XFORM
), 1);
515 RtlCopyMemory(&SafeXForm
, UnsafeXForm
, sizeof(XFORM
));
517 Ret
= IntGdiModifyWorldTransform(dc
, &SafeXForm
, Mode
);
521 SetLastNtError(_SEH_GetExceptionCode());
531 NtGdiOffsetViewportOrgEx(HDC hDC
,
537 NTSTATUS Status
= STATUS_SUCCESS
;
539 dc
= DC_LockDc ( hDC
);
542 SetLastWin32Error(ERROR_INVALID_HANDLE
);
550 ProbeForWrite(UnsafePoint
,
553 UnsafePoint
->x
= dc
->Dc_Attr
.ptlViewportOrg
.x
;
554 UnsafePoint
->y
= dc
->Dc_Attr
.ptlViewportOrg
.y
;
558 Status
= _SEH_GetExceptionCode();
562 if ( !NT_SUCCESS(Status
) )
564 SetLastNtError(Status
);
570 dc
->Dc_Attr
.ptlViewportOrg
.x
+= XOffset
;
571 dc
->Dc_Attr
.ptlViewportOrg
.y
+= YOffset
;
580 NtGdiOffsetWindowOrgEx(HDC hDC
,
590 SetLastWin32Error(ERROR_INVALID_HANDLE
);
596 NTSTATUS Status
= STATUS_SUCCESS
;
603 Point
->x
= dc
->Dc_Attr
.ptlWindowOrg
.x
;
604 Point
->y
= dc
->Dc_Attr
.ptlWindowOrg
.y
;
608 Status
= _SEH_GetExceptionCode();
612 if(!NT_SUCCESS(Status
))
614 SetLastNtError(Status
);
620 dc
->Dc_Attr
.ptlWindowOrg
.x
+= XOffset
;
621 dc
->Dc_Attr
.ptlWindowOrg
.y
+= YOffset
;
631 NtGdiScaleViewportExtEx(HDC hDC
,
644 NtGdiScaleWindowExtEx(HDC hDC
,
657 NtGdiSetGraphicsMode(HDC hDC
,
663 dc
= DC_LockDc (hDC
);
666 SetLastWin32Error(ERROR_INVALID_HANDLE
);
670 /* One would think that setting the graphics mode to GM_COMPATIBLE
671 * would also reset the world transformation matrix to the unity
672 * matrix. However, in Windows, this is not the case. This doesn't
673 * make a lot of sense to me, but that's the way it is.
676 if ((Mode
!= GM_COMPATIBLE
) && (Mode
!= GM_ADVANCED
))
679 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
683 ret
= dc
->Dc_Attr
.iGraphicsMode
;
684 dc
->Dc_Attr
.iGraphicsMode
= Mode
;
691 NtGdiSetMapMode(HDC hDC
,
700 SetLastWin32Error(ERROR_INVALID_HANDLE
);
704 PrevMapMode
= dc
->Dc_Attr
.iMapMode
;
706 if (MapMode
!= dc
->Dc_Attr
.iMapMode
|| (MapMode
!= MM_ISOTROPIC
&& MapMode
!= MM_ANISOTROPIC
))
708 dc
->Dc_Attr
.iMapMode
= MapMode
;
713 dc
->Dc_Attr
.szlWindowExt
.cx
= 1;
714 dc
->Dc_Attr
.szlWindowExt
.cy
= 1;
715 dc
->Dc_Attr
.szlViewportExt
.cx
= 1;
716 dc
->Dc_Attr
.szlViewportExt
.cy
= 1;
721 dc
->Dc_Attr
.szlWindowExt
.cx
= dc
->GDIInfo
->ulHorzSize
* 10;
722 dc
->Dc_Attr
.szlWindowExt
.cy
= dc
->GDIInfo
->ulVertSize
* 10;
723 dc
->Dc_Attr
.szlViewportExt
.cx
= dc
->GDIInfo
->ulHorzRes
;
724 dc
->Dc_Attr
.szlViewportExt
.cy
= -dc
->GDIInfo
->ulVertRes
;
728 dc
->Dc_Attr
.szlWindowExt
.cx
= dc
->GDIInfo
->ulHorzSize
* 100;
729 dc
->Dc_Attr
.szlWindowExt
.cy
= dc
->GDIInfo
->ulVertSize
* 100;
730 dc
->Dc_Attr
.szlViewportExt
.cx
= dc
->GDIInfo
->ulHorzRes
;
731 dc
->Dc_Attr
.szlViewportExt
.cy
= -dc
->GDIInfo
->ulVertRes
;
735 dc
->Dc_Attr
.szlWindowExt
.cx
= EngMulDiv(1000, dc
->GDIInfo
->ulHorzSize
, 254);
736 dc
->Dc_Attr
.szlWindowExt
.cy
= EngMulDiv(1000, dc
->GDIInfo
->ulVertSize
, 254);
737 dc
->Dc_Attr
.szlViewportExt
.cx
= dc
->GDIInfo
->ulHorzRes
;
738 dc
->Dc_Attr
.szlViewportExt
.cy
= -dc
->GDIInfo
->ulVertRes
;
742 dc
->Dc_Attr
.szlWindowExt
.cx
= EngMulDiv(10000, dc
->GDIInfo
->ulHorzSize
, 254);
743 dc
->Dc_Attr
.szlWindowExt
.cy
= EngMulDiv(10000, dc
->GDIInfo
->ulVertSize
, 254);
744 dc
->Dc_Attr
.szlViewportExt
.cx
= dc
->GDIInfo
->ulHorzRes
;
745 dc
->Dc_Attr
.szlViewportExt
.cy
= -dc
->GDIInfo
->ulVertRes
;
749 dc
->Dc_Attr
.szlWindowExt
.cx
= EngMulDiv(14400, dc
->GDIInfo
->ulHorzSize
, 254);
750 dc
->Dc_Attr
.szlWindowExt
.cy
= EngMulDiv(14400, dc
->GDIInfo
->ulVertSize
, 254);
751 dc
->Dc_Attr
.szlViewportExt
.cx
= dc
->GDIInfo
->ulHorzRes
;
752 dc
->Dc_Attr
.szlViewportExt
.cy
= -dc
->GDIInfo
->ulVertRes
;
769 NtGdiSetViewportExtEx(HDC hDC
,
779 SetLastWin32Error(ERROR_INVALID_HANDLE
);
783 switch (dc
->Dc_Attr
.iMapMode
)
795 // Here we should (probably) check that SetWindowExtEx *really* has
802 NTSTATUS Status
= STATUS_SUCCESS
;
809 Size
->cx
= dc
->Dc_Attr
.szlViewportExt
.cx
;
810 Size
->cy
= dc
->Dc_Attr
.szlViewportExt
.cy
;
812 dc
->Dc_Attr
.szlViewportExt
.cx
= XExtent
;
813 dc
->Dc_Attr
.szlViewportExt
.cy
= YExtent
;
815 if (dc
->Dc_Attr
.iMapMode
== MM_ISOTROPIC
)
816 IntFixIsotropicMapping(dc
);
820 Status
= _SEH_GetExceptionCode();
824 if(!NT_SUCCESS(Status
))
826 SetLastNtError(Status
);
841 NtGdiSetViewportOrgEx(HDC hDC
,
851 SetLastWin32Error(ERROR_INVALID_HANDLE
);
857 NTSTATUS Status
= STATUS_SUCCESS
;
864 Point
->x
= dc
->Dc_Attr
.ptlViewportOrg
.x
;
865 Point
->y
= dc
->Dc_Attr
.ptlViewportOrg
.y
;
869 Status
= _SEH_GetExceptionCode();
873 if(!NT_SUCCESS(Status
))
875 SetLastNtError(Status
);
881 dc
->Dc_Attr
.ptlViewportOrg
.x
= X
;
882 dc
->Dc_Attr
.ptlViewportOrg
.y
= Y
;
892 NtGdiSetWindowExtEx(HDC hDC
,
902 SetLastWin32Error(ERROR_INVALID_HANDLE
);
906 switch (dc
->Dc_Attr
.iMapMode
)
920 NTSTATUS Status
= STATUS_SUCCESS
;
927 Size
->cx
= dc
->Dc_Attr
.szlWindowExt
.cx
;
928 Size
->cy
= dc
->Dc_Attr
.szlWindowExt
.cy
;
932 Status
= _SEH_GetExceptionCode();
936 if(!NT_SUCCESS(Status
))
938 SetLastNtError(Status
);
944 dc
->Dc_Attr
.szlWindowExt
.cx
= XExtent
;
945 dc
->Dc_Attr
.szlWindowExt
.cy
= YExtent
;
955 NtGdiSetWindowOrgEx(HDC hDC
,
965 SetLastWin32Error(ERROR_INVALID_HANDLE
);
971 NTSTATUS Status
= STATUS_SUCCESS
;
978 Point
->x
= dc
->Dc_Attr
.ptlWindowOrg
.x
;
979 Point
->y
= dc
->Dc_Attr
.ptlWindowOrg
.y
;
983 Status
= _SEH_GetExceptionCode();
987 if(!NT_SUCCESS(Status
))
989 SetLastNtError(Status
);
995 dc
->Dc_Attr
.ptlWindowOrg
.x
= X
;
996 dc
->Dc_Attr
.ptlWindowOrg
.y
= Y
;
1006 NtGdiSetWorldTransform(HDC hDC
,
1007 CONST LPXFORM XForm
)
1010 NTSTATUS Status
= STATUS_SUCCESS
;
1012 dc
= DC_LockDc (hDC
);
1015 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1022 /* Win doesn't set LastError */
1026 /* Check that graphics mode is GM_ADVANCED */
1027 if ( dc
->Dc_Attr
.iGraphicsMode
!= GM_ADVANCED
)
1038 dc
->w
.xformWorld2Wnd
= *XForm
;
1042 Status
= _SEH_GetExceptionCode();
1046 if(!NT_SUCCESS(Status
))
1052 DC_UpdateXforms(dc
);