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
)
42 PDC_ATTR Dc_Attr
= dc
->pDc_Attr
;
43 if(!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
45 xdim
= EngMulDiv(Dc_Attr
->szlViewportExt
.cx
,
46 ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulHorzSize
,
47 ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulHorzRes
) /
48 Dc_Attr
->szlWindowExt
.cx
;
49 ydim
= EngMulDiv(Dc_Attr
->szlViewportExt
.cy
,
50 ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulVertSize
,
51 ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulVertRes
) /
52 Dc_Attr
->szlWindowExt
.cy
;
56 Dc_Attr
->szlViewportExt
.cx
= Dc_Attr
->szlViewportExt
.cx
* abs(ydim
/ xdim
);
57 if (!Dc_Attr
->szlViewportExt
.cx
) Dc_Attr
->szlViewportExt
.cx
= 1;
61 Dc_Attr
->szlViewportExt
.cy
= Dc_Attr
->szlViewportExt
.cy
* abs(xdim
/ ydim
);
62 if (!Dc_Attr
->szlViewportExt
.cy
) Dc_Attr
->szlViewportExt
.cy
= 1;
67 IntGdiCombineTransform(LPXFORM XFormResult
,
71 /* Check for illegal parameters */
72 if (!XFormResult
|| !xform1
|| !xform2
)
77 /* Create the result in a temporary XFORM, since xformResult may be
78 * equal to xform1 or xform2 */
79 XFormResult
->eM11
= xform1
->eM11
* xform2
->eM11
+ xform1
->eM12
* xform2
->eM21
;
80 XFormResult
->eM12
= xform1
->eM11
* xform2
->eM12
+ xform1
->eM12
* xform2
->eM22
;
81 XFormResult
->eM21
= xform1
->eM21
* xform2
->eM11
+ xform1
->eM22
* xform2
->eM21
;
82 XFormResult
->eM22
= xform1
->eM21
* xform2
->eM12
+ xform1
->eM22
* xform2
->eM22
;
83 XFormResult
->eDx
= xform1
->eDx
* xform2
->eM11
+ xform1
->eDy
* xform2
->eM21
+ xform2
->eDx
;
84 XFormResult
->eDy
= xform1
->eDx
* xform2
->eM12
+ xform1
->eDy
* xform2
->eM22
+ xform2
->eDy
;
89 BOOL STDCALL
NtGdiCombineTransform(LPXFORM UnsafeXFormResult
,
94 XFORM xform1
= {0}, xform2
= {0};
95 NTSTATUS Status
= STATUS_SUCCESS
;
100 ProbeForWrite(UnsafeXFormResult
,
103 ProbeForRead(Unsafexform1
,
106 ProbeForRead(Unsafexform2
,
109 xform1
= *Unsafexform1
;
110 xform2
= *Unsafexform2
;
114 Status
= _SEH_GetExceptionCode();
118 if(!NT_SUCCESS(Status
))
120 SetLastNtError(Status
);
124 Ret
= IntGdiCombineTransform(&xformTemp
, &xform1
, &xform2
);
126 /* Copy the result to xformResult */
129 /* pointer was already probed! */
130 *UnsafeXFormResult
= xformTemp
;
134 Status
= _SEH_GetExceptionCode();
138 if(!NT_SUCCESS(Status
))
140 SetLastNtError(Status
);
148 CoordDPtoLP(PDC Dc
, LPPOINT Point
)
153 Point
->x
= x
* Dc
->w
.xformVport2World
.eM11
+
154 y
* Dc
->w
.xformVport2World
.eM21
+ Dc
->w
.xformVport2World
.eDx
;
155 Point
->y
= x
* Dc
->w
.xformVport2World
.eM12
+
156 y
* Dc
->w
.xformVport2World
.eM22
+ Dc
->w
.xformVport2World
.eDy
;
161 IntDPtoLP ( PDC dc
, LPPOINT Points
, INT Count
)
167 for ( i
= 0; i
< Count
; i
++ )
168 CoordDPtoLP ( dc
, &Points
[i
] );
173 IntGetGraphicsMode ( PDC dc
)
177 Dc_Attr
= dc
->pDc_Attr
;
178 if(!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
179 return Dc_Attr
->iGraphicsMode
;
184 IntGdiModifyWorldTransform(PDC pDc
,
185 CONST LPXFORM lpXForm
,
188 ASSERT(pDc
&& lpXForm
);
193 pDc
->w
.xformWorld2Wnd
.eM11
= 1.0f
;
194 pDc
->w
.xformWorld2Wnd
.eM12
= 0.0f
;
195 pDc
->w
.xformWorld2Wnd
.eM21
= 0.0f
;
196 pDc
->w
.xformWorld2Wnd
.eM22
= 1.0f
;
197 pDc
->w
.xformWorld2Wnd
.eDx
= 0.0f
;
198 pDc
->w
.xformWorld2Wnd
.eDy
= 0.0f
;
201 case MWT_LEFTMULTIPLY
:
202 IntGdiCombineTransform(&pDc
->w
.xformWorld2Wnd
, lpXForm
, &pDc
->w
.xformWorld2Wnd
);
205 case MWT_RIGHTMULTIPLY
:
206 IntGdiCombineTransform(&pDc
->w
.xformWorld2Wnd
, &pDc
->w
.xformWorld2Wnd
, lpXForm
);
209 case MWT_MAX
+1: // Must be MWT_SET????
210 pDc
->w
.xformWorld2Wnd
= *lpXForm
; // Do it like Wine.
214 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
217 DC_UpdateXforms(pDc
);
223 NtGdiGetGraphicsMode ( HDC hDC
)
227 int GraphicsMode
; // default to failure
229 dc
= DC_LockDc ( hDC
);
232 SetLastWin32Error(ERROR_INVALID_HANDLE
);
235 Dc_Attr
= dc
->pDc_Attr
;
236 if(!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
237 GraphicsMode
= Dc_Attr
->iGraphicsMode
;
245 NtGdiGetTransform(HDC hDC
,
250 NTSTATUS Status
= STATUS_SUCCESS
;
252 dc
= DC_LockDc ( hDC
);
255 SetLastWin32Error(ERROR_INVALID_HANDLE
);
261 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
272 case GdiWorldSpaceToPageSpace
:
273 *XForm
= dc
->w
.xformWorld2Wnd
;
281 Status
= _SEH_GetExceptionCode();
286 return NT_SUCCESS(Status
);
291 CoordLPtoDP ( PDC Dc
, LPPOINT Point
)
300 Point
->x
= x
* Dc
->w
.xformWorld2Vport
.eM11
+
301 y
* Dc
->w
.xformWorld2Vport
.eM21
+ Dc
->w
.xformWorld2Vport
.eDx
;
302 Point
->y
= x
* Dc
->w
.xformWorld2Vport
.eM12
+
303 y
* Dc
->w
.xformWorld2Vport
.eM22
+ Dc
->w
.xformWorld2Vport
.eDy
;
308 IntLPtoDP ( PDC dc
, LPPOINT Points
, INT Count
)
314 for ( i
= 0; i
< Count
; i
++ )
315 CoordLPtoDP ( dc
, &Points
[i
] );
319 * Converts points from logical coordinates into device coordinates. Conversion depends on the mapping mode,
320 * world transfrom, viewport origin settings for the given device context.
321 * \param hDC device context.
322 * \param Points an array of POINT structures (in/out).
323 * \param Count number of elements in the array of POINT structures.
324 * \return TRUE if success.
328 NtGdiTransformPoints( HDC hDC
,
335 NTSTATUS Status
= STATUS_SUCCESS
;
342 SetLastWin32Error(ERROR_INVALID_HANDLE
);
346 if (!UnsafePtsIn
|| !UnsafePtOut
|| Count
<= 0)
349 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
353 Size
= Count
* sizeof(POINT
);
355 Points
= (LPPOINT
)ExAllocatePoolWithTag(PagedPool
, Size
, TAG_COORD
);
359 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
365 ProbeForWrite(UnsafePtOut
,
368 ProbeForRead(UnsafePtsIn
,
371 RtlCopyMemory(Points
,
377 Status
= _SEH_GetExceptionCode();
381 if(!NT_SUCCESS(Status
))
385 SetLastNtError(Status
);
392 IntDPtoLP(dc
, Points
, Count
);
395 IntLPtoDP(dc
, Points
, Count
);
397 case 2: // Not supported yet. Need testing.
402 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
409 /* pointer was already probed! */
410 RtlCopyMemory(UnsafePtOut
,
416 Status
= _SEH_GetExceptionCode();
420 if(!NT_SUCCESS(Status
))
424 SetLastNtError(Status
);
428 // If we are getting called that means User XForms is a mess!
437 NtGdiModifyWorldTransform(HDC hDC
,
447 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
454 SetLastWin32Error(ERROR_INVALID_HANDLE
);
460 ProbeForRead(UnsafeXForm
, sizeof(XFORM
), 1);
461 RtlCopyMemory(&SafeXForm
, UnsafeXForm
, sizeof(XFORM
));
465 SetLastNtError(_SEH_GetExceptionCode());
469 // Safe to handle kernel mode data.
470 Ret
= IntGdiModifyWorldTransform(dc
, &SafeXForm
, Mode
);
477 NtGdiOffsetViewportOrgEx(HDC hDC
,
484 NTSTATUS Status
= STATUS_SUCCESS
;
486 dc
= DC_LockDc ( hDC
);
489 SetLastWin32Error(ERROR_INVALID_HANDLE
);
492 Dc_Attr
= dc
->pDc_Attr
;
493 if(!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
499 ProbeForWrite(UnsafePoint
,
502 UnsafePoint
->x
= Dc_Attr
->ptlViewportOrg
.x
;
503 UnsafePoint
->y
= Dc_Attr
->ptlViewportOrg
.y
;
507 Status
= _SEH_GetExceptionCode();
511 if ( !NT_SUCCESS(Status
) )
513 SetLastNtError(Status
);
519 Dc_Attr
->ptlViewportOrg
.x
+= XOffset
;
520 Dc_Attr
->ptlViewportOrg
.y
+= YOffset
;
528 NtGdiOffsetWindowOrgEx(HDC hDC
,
539 SetLastWin32Error(ERROR_INVALID_HANDLE
);
542 Dc_Attr
= dc
->pDc_Attr
;
543 if(!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
547 NTSTATUS Status
= STATUS_SUCCESS
;
554 Point
->x
= Dc_Attr
->ptlWindowOrg
.x
;
555 Point
->y
= Dc_Attr
->ptlWindowOrg
.y
;
559 Status
= _SEH_GetExceptionCode();
563 if(!NT_SUCCESS(Status
))
565 SetLastNtError(Status
);
571 Dc_Attr
->ptlWindowOrg
.x
+= XOffset
;
572 Dc_Attr
->ptlWindowOrg
.y
+= YOffset
;
582 NtGdiScaleViewportExtEx(HDC hDC
,
595 NtGdiScaleWindowExtEx(HDC hDC
,
608 NtGdiSetGraphicsMode(HDC hDC
,
615 dc
= DC_LockDc (hDC
);
618 SetLastWin32Error(ERROR_INVALID_HANDLE
);
621 Dc_Attr
= dc
->pDc_Attr
;
622 if(!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
624 /* One would think that setting the graphics mode to GM_COMPATIBLE
625 * would also reset the world transformation matrix to the unity
626 * matrix. However, in Windows, this is not the case. This doesn't
627 * make a lot of sense to me, but that's the way it is.
630 if ((Mode
!= GM_COMPATIBLE
) && (Mode
!= GM_ADVANCED
))
633 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
637 ret
= Dc_Attr
->iGraphicsMode
;
638 Dc_Attr
->iGraphicsMode
= Mode
;
645 IntGdiSetMapMode(PDC dc
,
649 PDC_ATTR Dc_Attr
= dc
->pDc_Attr
;
650 if(!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
652 PrevMapMode
= Dc_Attr
->iMapMode
;
654 if (MapMode
!= Dc_Attr
->iMapMode
|| (MapMode
!= MM_ISOTROPIC
&& MapMode
!= MM_ANISOTROPIC
))
656 Dc_Attr
->iMapMode
= MapMode
;
661 Dc_Attr
->szlWindowExt
.cx
= 1;
662 Dc_Attr
->szlWindowExt
.cy
= 1;
663 Dc_Attr
->szlViewportExt
.cx
= 1;
664 Dc_Attr
->szlViewportExt
.cy
= 1;
669 Dc_Attr
->szlWindowExt
.cx
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulHorzSize
* 10;
670 Dc_Attr
->szlWindowExt
.cy
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulVertSize
* 10;
671 Dc_Attr
->szlViewportExt
.cx
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulHorzRes
;
672 Dc_Attr
->szlViewportExt
.cy
= -((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulVertRes
;
676 Dc_Attr
->szlWindowExt
.cx
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulHorzSize
* 100;
677 Dc_Attr
->szlWindowExt
.cy
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulVertSize
* 100;
678 Dc_Attr
->szlViewportExt
.cx
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulHorzRes
;
679 Dc_Attr
->szlViewportExt
.cy
= -((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulVertRes
;
683 Dc_Attr
->szlWindowExt
.cx
= EngMulDiv(1000, ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulHorzSize
, 254);
684 Dc_Attr
->szlWindowExt
.cy
= EngMulDiv(1000, ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulVertSize
, 254);
685 Dc_Attr
->szlViewportExt
.cx
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulHorzRes
;
686 Dc_Attr
->szlViewportExt
.cy
= -((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulVertRes
;
690 Dc_Attr
->szlWindowExt
.cx
= EngMulDiv(10000, ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulHorzSize
, 254);
691 Dc_Attr
->szlWindowExt
.cy
= EngMulDiv(10000, ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulVertSize
, 254);
692 Dc_Attr
->szlViewportExt
.cx
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulHorzRes
;
693 Dc_Attr
->szlViewportExt
.cy
= -((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulVertRes
;
697 Dc_Attr
->szlWindowExt
.cx
= EngMulDiv(14400, ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulHorzSize
, 254);
698 Dc_Attr
->szlWindowExt
.cy
= EngMulDiv(14400, ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulVertSize
, 254);
699 Dc_Attr
->szlViewportExt
.cx
= ((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulHorzRes
;
700 Dc_Attr
->szlViewportExt
.cy
= -((PGDIDEVICE
)dc
->pPDev
)->GDIInfo
.ulVertRes
;
715 NtGdiSetViewportExtEx(HDC hDC
,
726 SetLastWin32Error(ERROR_INVALID_HANDLE
);
729 Dc_Attr
= dc
->pDc_Attr
;
730 if(!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
732 switch (Dc_Attr
->iMapMode
)
744 // Here we should (probably) check that SetWindowExtEx *really* has
751 NTSTATUS Status
= STATUS_SUCCESS
;
758 Size
->cx
= Dc_Attr
->szlViewportExt
.cx
;
759 Size
->cy
= Dc_Attr
->szlViewportExt
.cy
;
761 Dc_Attr
->szlViewportExt
.cx
= XExtent
;
762 Dc_Attr
->szlViewportExt
.cy
= YExtent
;
764 if (Dc_Attr
->iMapMode
== MM_ISOTROPIC
)
765 IntFixIsotropicMapping(dc
);
769 Status
= _SEH_GetExceptionCode();
773 if(!NT_SUCCESS(Status
))
775 SetLastNtError(Status
);
790 NtGdiSetViewportOrgEx(HDC hDC
,
801 SetLastWin32Error(ERROR_INVALID_HANDLE
);
804 Dc_Attr
= dc
->pDc_Attr
;
805 if(!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
809 NTSTATUS Status
= STATUS_SUCCESS
;
816 Point
->x
= Dc_Attr
->ptlViewportOrg
.x
;
817 Point
->y
= Dc_Attr
->ptlViewportOrg
.y
;
821 Status
= _SEH_GetExceptionCode();
825 if(!NT_SUCCESS(Status
))
827 SetLastNtError(Status
);
833 Dc_Attr
->ptlViewportOrg
.x
= X
;
834 Dc_Attr
->ptlViewportOrg
.y
= Y
;
844 NtGdiSetWindowExtEx(HDC hDC
,
855 SetLastWin32Error(ERROR_INVALID_HANDLE
);
858 Dc_Attr
= dc
->pDc_Attr
;
859 if(!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
861 switch (Dc_Attr
->iMapMode
)
875 NTSTATUS Status
= STATUS_SUCCESS
;
882 Size
->cx
= Dc_Attr
->szlWindowExt
.cx
;
883 Size
->cy
= Dc_Attr
->szlWindowExt
.cy
;
887 Status
= _SEH_GetExceptionCode();
891 if(!NT_SUCCESS(Status
))
893 SetLastNtError(Status
);
899 Dc_Attr
->szlWindowExt
.cx
= XExtent
;
900 Dc_Attr
->szlWindowExt
.cy
= YExtent
;
910 NtGdiSetWindowOrgEx(HDC hDC
,
921 SetLastWin32Error(ERROR_INVALID_HANDLE
);
924 Dc_Attr
= dc
->pDc_Attr
;
925 if(!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
929 NTSTATUS Status
= STATUS_SUCCESS
;
936 Point
->x
= Dc_Attr
->ptlWindowOrg
.x
;
937 Point
->y
= Dc_Attr
->ptlWindowOrg
.y
;
941 Status
= _SEH_GetExceptionCode();
945 if(!NT_SUCCESS(Status
))
947 SetLastNtError(Status
);
953 Dc_Attr
->ptlWindowOrg
.x
= X
;
954 Dc_Attr
->ptlWindowOrg
.y
= Y
;
979 SetLastWin32Error(ERROR_INVALID_HANDLE
);
982 Dc_Attr
= dc
->pDc_Attr
;
983 if(!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
985 Dc_Attr
->dwLayout
= dwLayout
;
986 oLayout
= Dc_Attr
->dwLayout
;
988 if (!(dwLayout
& LAYOUT_ORIENTATIONMASK
))
994 // DC_UpdateXforms(dc);