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 along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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
;
69 // FIXME: don't use floating point in the kernel! use XFORMOBJ function
71 IntGdiCombineTransform(
77 /* Check for illegal parameters */
78 if (!XFormResult
|| !xform1
|| !xform2
)
83 /* Create the result in a temporary XFORM, since xformResult may be
84 * equal to xform1 or xform2 */
85 xformTemp
.eM11
= xform1
->eM11
* xform2
->eM11
+ xform1
->eM12
* xform2
->eM21
;
86 xformTemp
.eM12
= xform1
->eM11
* xform2
->eM12
+ xform1
->eM12
* xform2
->eM22
;
87 xformTemp
.eM21
= xform1
->eM21
* xform2
->eM11
+ xform1
->eM22
* xform2
->eM21
;
88 xformTemp
.eM22
= xform1
->eM21
* xform2
->eM12
+ xform1
->eM22
* xform2
->eM22
;
89 xformTemp
.eDx
= xform1
->eDx
* xform2
->eM11
+ xform1
->eDy
* xform2
->eM21
+ xform2
->eDx
;
90 xformTemp
.eDy
= xform1
->eDx
* xform2
->eM12
+ xform1
->eDy
* xform2
->eM22
+ xform2
->eDy
;
91 *XFormResult
= xformTemp
;
96 // FIXME: should be XFORML and use XFORMOBJ functions
97 BOOL APIENTRY
NtGdiCombineTransform(
98 LPXFORM UnsafeXFormResult
,
100 LPXFORM Unsafexform2
)
106 ProbeForWrite(UnsafeXFormResult
, sizeof(XFORM
), 1);
107 ProbeForRead(Unsafexform1
, sizeof(XFORM
), 1);
108 ProbeForRead(Unsafexform2
, sizeof(XFORM
), 1);
109 Ret
= IntGdiCombineTransform(UnsafeXFormResult
,
113 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
122 // FIXME: Don't use floating point in the kernel
125 IntGdiModifyWorldTransform(
127 CONST LPXFORM lpXForm
,
130 XFORM xformWorld2Wnd
;
136 xformWorld2Wnd
.eM11
= 1.0f
;
137 xformWorld2Wnd
.eM12
= 0.0f
;
138 xformWorld2Wnd
.eM21
= 0.0f
;
139 xformWorld2Wnd
.eM22
= 1.0f
;
140 xformWorld2Wnd
.eDx
= 0.0f
;
141 xformWorld2Wnd
.eDy
= 0.0f
;
142 XForm2MatrixS(&pDc
->dclevel
.mxWorldToPage
, &xformWorld2Wnd
);
145 case MWT_LEFTMULTIPLY
:
146 MatrixS2XForm(&xformWorld2Wnd
, &pDc
->dclevel
.mxWorldToPage
);
147 IntGdiCombineTransform(&xformWorld2Wnd
, lpXForm
, &xformWorld2Wnd
);
148 XForm2MatrixS(&pDc
->dclevel
.mxWorldToPage
, &xformWorld2Wnd
);
151 case MWT_RIGHTMULTIPLY
:
152 MatrixS2XForm(&xformWorld2Wnd
, &pDc
->dclevel
.mxWorldToPage
);
153 IntGdiCombineTransform(&xformWorld2Wnd
, &xformWorld2Wnd
, lpXForm
);
154 XForm2MatrixS(&pDc
->dclevel
.mxWorldToPage
, &xformWorld2Wnd
);
157 case MWT_MAX
+1: // Must be MWT_SET????
158 XForm2MatrixS(&pDc
->dclevel
.mxWorldToPage
, lpXForm
); // Do it like Wine.
164 DC_UpdateXforms(pDc
);
168 // FIXME: Don't use floating point in the kernel!
169 void IntWindowToViewPort(PDC_ATTR pdcattr
, LPXFORM xformWnd2Vport
)
171 FLOAT scaleX
, scaleY
;
173 scaleX
= (pdcattr
->szlWindowExt
.cx
? (FLOAT
)pdcattr
->szlViewportExt
.cx
/ (FLOAT
)pdcattr
->szlWindowExt
.cx
: 0.0f
);
174 scaleY
= (pdcattr
->szlWindowExt
.cy
? (FLOAT
)pdcattr
->szlViewportExt
.cy
/ (FLOAT
)pdcattr
->szlWindowExt
.cy
: 0.0f
);
175 xformWnd2Vport
->eM11
= scaleX
;
176 xformWnd2Vport
->eM12
= 0.0;
177 xformWnd2Vport
->eM21
= 0.0;
178 xformWnd2Vport
->eM22
= scaleY
;
179 xformWnd2Vport
->eDx
= (FLOAT
)pdcattr
->ptlViewportOrg
.x
- scaleX
* (FLOAT
)pdcattr
->ptlWindowOrg
.x
;
180 xformWnd2Vport
->eDy
= (FLOAT
)pdcattr
->ptlViewportOrg
.y
- scaleY
* (FLOAT
)pdcattr
->ptlWindowOrg
.y
;
183 // FIXME: Should be XFORML and use XFORMOBJ functions directly
192 NTSTATUS Status
= STATUS_SUCCESS
;
197 SetLastWin32Error(ERROR_INVALID_HANDLE
);
203 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
209 ProbeForWrite(XForm
, sizeof(XFORM
), 1);
212 case GdiWorldSpaceToPageSpace
:
213 MatrixS2XForm(XForm
, &dc
->dclevel
.mxWorldToPage
);
216 case GdiWorldSpaceToDeviceSpace
:
217 MatrixS2XForm(XForm
, &dc
->dclevel
.mxWorldToDevice
);
220 case GdiPageSpaceToDeviceSpace
:
221 IntWindowToViewPort(dc
->pdcattr
, XForm
);
224 case GdiDeviceSpaceToWorldSpace
:
225 MatrixS2XForm(XForm
, &dc
->dclevel
.mxDeviceToWorld
);
229 DPRINT1("Unknown transform %lu\n", iXform
);
230 Status
= STATUS_INVALID_PARAMETER
;
234 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
236 Status
= _SEH2_GetExceptionCode();
241 return NT_SUCCESS(Status
);
246 * Converts points from logical coordinates into device coordinates. Conversion depends on the mapping mode,
247 * world transfrom, viewport origin settings for the given device context.
248 * \param hDC device context.
249 * \param Points an array of POINT structures (in/out).
250 * \param Count number of elements in the array of POINT structures.
251 * \return TRUE if success.
255 NtGdiTransformPoints(
263 NTSTATUS Status
= STATUS_SUCCESS
;
270 SetLastWin32Error(ERROR_INVALID_HANDLE
);
274 if (!UnsafePtsIn
|| !UnsafePtOut
|| Count
<= 0)
277 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
281 Size
= Count
* sizeof(POINT
);
283 // FIXME: It would be wise to have a small stack buffer as optimization
284 Points
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_COORD
);
288 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
294 ProbeForWrite(UnsafePtOut
, Size
, 1);
295 ProbeForRead(UnsafePtsIn
, Size
, 1);
296 RtlCopyMemory(Points
, UnsafePtsIn
, Size
);
298 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
300 Status
= _SEH2_GetExceptionCode();
304 if (!NT_SUCCESS(Status
))
307 ExFreePoolWithTag(Points
, TAG_COORD
);
308 SetLastNtError(Status
);
315 IntDPtoLP(dc
, Points
, Count
);
319 IntLPtoDP(dc
, Points
, Count
);
322 case 2: // Not supported yet. Need testing.
326 ExFreePoolWithTag(Points
, TAG_COORD
);
327 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
334 /* pointer was already probed! */
335 RtlCopyMemory(UnsafePtOut
, Points
, Size
);
337 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
339 Status
= _SEH2_GetExceptionCode();
343 if (!NT_SUCCESS(Status
))
346 ExFreePoolWithTag(Points
, TAG_COORD
);
347 SetLastNtError(Status
);
351 // If we are getting called that means User XForms is a mess!
354 ExFreePoolWithTag(Points
, TAG_COORD
);
360 NtGdiModifyWorldTransform(
372 SetLastWin32Error(ERROR_INVALID_HANDLE
);
376 // The xform is permitted to be NULL for MWT_IDENTITY.
377 // However, if it is not NULL, then it must be valid even though it is not used.
378 if (UnsafeXForm
!= NULL
|| Mode
!= MWT_IDENTITY
)
382 ProbeForRead(UnsafeXForm
, sizeof(XFORM
), 1);
383 RtlCopyMemory(&SafeXForm
, UnsafeXForm
, sizeof(XFORM
));
385 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
392 // Safe to handle kernel mode data.
393 if (Ret
) Ret
= IntGdiModifyWorldTransform(dc
, &SafeXForm
, Mode
);
400 NtGdiOffsetViewportOrgEx(
408 NTSTATUS Status
= STATUS_SUCCESS
;
413 SetLastWin32Error(ERROR_INVALID_HANDLE
);
416 pdcattr
= dc
->pdcattr
;
422 ProbeForWrite(UnsafePoint
, sizeof(POINT
), 1);
423 UnsafePoint
->x
= pdcattr
->ptlViewportOrg
.x
;
424 UnsafePoint
->y
= pdcattr
->ptlViewportOrg
.y
;
425 if (pdcattr
->dwLayout
& LAYOUT_RTL
)
427 UnsafePoint
->x
= -UnsafePoint
->x
;
430 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
432 Status
= _SEH2_GetExceptionCode();
436 if (!NT_SUCCESS(Status
))
438 SetLastNtError(Status
);
444 if (pdcattr
->dwLayout
& LAYOUT_RTL
)
448 pdcattr
->ptlViewportOrg
.x
+= XOffset
;
449 pdcattr
->ptlViewportOrg
.y
+= YOffset
;
458 NtGdiOffsetWindowOrgEx(
470 SetLastWin32Error(ERROR_INVALID_HANDLE
);
473 pdcattr
= dc
->pdcattr
;
477 NTSTATUS Status
= STATUS_SUCCESS
;
481 ProbeForWrite(Point
, sizeof(POINT
), 1);
482 Point
->x
= pdcattr
->ptlWindowOrg
.x
;
483 Point
->y
= pdcattr
->ptlWindowOrg
.y
;
485 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
487 Status
= _SEH2_GetExceptionCode();
491 if (!NT_SUCCESS(Status
))
493 SetLastNtError(Status
);
499 pdcattr
->ptlWindowOrg
.x
+= XOffset
;
500 pdcattr
->ptlWindowOrg
.y
+= YOffset
;
510 NtGdiScaleViewportExtEx(
523 pDC
= DC_LockDc(hDC
);
526 SetLastWin32Error(ERROR_INVALID_HANDLE
);
529 pdcattr
= pDC
->pdcattr
;
533 NTSTATUS Status
= STATUS_SUCCESS
;
537 ProbeForWrite(pSize
, sizeof(LPSIZE
), 1);
539 pSize
->cx
= pdcattr
->szlViewportExt
.cx
;
540 pSize
->cy
= pdcattr
->szlViewportExt
.cy
;
542 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
544 Status
= _SEH2_GetExceptionCode();
548 if (!NT_SUCCESS(Status
))
550 SetLastNtError(Status
);
556 if (pdcattr
->iMapMode
> MM_TWIPS
)
558 if (Xdenom
&& Ydenom
)
560 X
= Xnum
* pdcattr
->szlViewportExt
.cx
/ Xdenom
;
563 Y
= Ynum
* pdcattr
->szlViewportExt
.cy
/ Ydenom
;
566 pdcattr
->szlViewportExt
.cx
= X
;
567 pdcattr
->szlViewportExt
.cy
= Y
;
569 IntMirrorWindowOrg(pDC
);
571 pdcattr
->flXform
|= (PAGE_EXTENTS_CHANGED
|
572 INVALIDATE_ATTRIBUTES
|
573 DEVICE_TO_WORLD_INVALID
);
575 if (pdcattr
->iMapMode
== MM_ISOTROPIC
)
577 IntFixIsotropicMapping(pDC
);
579 DC_UpdateXforms(pDC
);
595 NtGdiScaleWindowExtEx(
608 pDC
= DC_LockDc(hDC
);
611 SetLastWin32Error(ERROR_INVALID_HANDLE
);
614 pdcattr
= pDC
->pdcattr
;
618 NTSTATUS Status
= STATUS_SUCCESS
;
622 ProbeForWrite(pSize
, sizeof(LPSIZE
), 1);
624 X
= pdcattr
->szlWindowExt
.cx
;
625 if (pdcattr
->dwLayout
& LAYOUT_RTL
) X
= -X
;
627 pSize
->cy
= pdcattr
->szlWindowExt
.cy
;
629 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
631 Status
= _SEH2_GetExceptionCode();
635 if (!NT_SUCCESS(Status
))
637 SetLastNtError(Status
);
643 if (pdcattr
->iMapMode
> MM_TWIPS
)
645 if (Xdenom
&& Ydenom
)
647 X
= Xnum
* pdcattr
->szlWindowExt
.cx
/ Xdenom
;
650 Y
= Ynum
* pdcattr
->szlWindowExt
.cy
/ Ydenom
;
653 pdcattr
->szlWindowExt
.cx
= X
;
654 pdcattr
->szlWindowExt
.cy
= Y
;
656 IntMirrorWindowOrg(pDC
);
658 pdcattr
->flXform
|= (PAGE_EXTENTS_CHANGED
|INVALIDATE_ATTRIBUTES
|DEVICE_TO_WORLD_INVALID
);
660 if (pdcattr
->iMapMode
== MM_ISOTROPIC
) IntFixIsotropicMapping(pDC
);
661 DC_UpdateXforms(pDC
);
682 PDC_ATTR pdcattr
= dc
->pdcattr
;
684 PrevMapMode
= pdcattr
->iMapMode
;
686 pdcattr
->iMapMode
= MapMode
;
691 pdcattr
->szlWindowExt
.cx
= 1;
692 pdcattr
->szlWindowExt
.cy
= 1;
693 pdcattr
->szlViewportExt
.cx
= 1;
694 pdcattr
->szlViewportExt
.cy
= 1;
695 pdcattr
->flXform
&= ~(ISO_OR_ANISO_MAP_MODE
|PTOD_EFM22_NEGATIVE
|
696 PTOD_EFM11_NEGATIVE
|POSITIVE_Y_IS_UP
);
697 pdcattr
->flXform
|= (PAGE_XLATE_CHANGED
|PAGE_TO_DEVICE_SCALE_IDENTITY
|
698 INVALIDATE_ATTRIBUTES
|DEVICE_TO_WORLD_INVALID
);
702 pdcattr
->flXform
|= ISO_OR_ANISO_MAP_MODE
;
706 pdcattr
->szlWindowExt
.cx
= pdcattr
->szlVirtualDeviceMm
.cx
* 10;
707 pdcattr
->szlWindowExt
.cy
= pdcattr
->szlVirtualDeviceMm
.cy
* 10;
708 pdcattr
->szlViewportExt
.cx
= pdcattr
->szlVirtualDevicePixel
.cx
;
709 pdcattr
->szlViewportExt
.cy
= -pdcattr
->szlVirtualDevicePixel
.cy
;
713 pdcattr
->szlWindowExt
.cx
= pdcattr
->szlVirtualDeviceMm
.cx
* 100;
714 pdcattr
->szlWindowExt
.cy
= pdcattr
->szlVirtualDeviceMm
.cy
* 100;
715 pdcattr
->szlViewportExt
.cx
= pdcattr
->szlVirtualDevicePixel
.cx
;
716 pdcattr
->szlViewportExt
.cy
= -pdcattr
->szlVirtualDevicePixel
.cy
;
720 pdcattr
->szlWindowExt
.cx
= MulDiv(1000, pdcattr
->szlVirtualDeviceMm
.cx
, 254);
721 pdcattr
->szlWindowExt
.cy
= MulDiv(1000, pdcattr
->szlVirtualDeviceMm
.cy
, 254);
722 pdcattr
->szlViewportExt
.cx
= pdcattr
->szlVirtualDevicePixel
.cx
;
723 pdcattr
->szlViewportExt
.cy
= -pdcattr
->szlVirtualDevicePixel
.cy
;
727 pdcattr
->szlWindowExt
.cx
= MulDiv(10000, pdcattr
->szlVirtualDeviceMm
.cx
, 254);
728 pdcattr
->szlWindowExt
.cy
= MulDiv(10000, pdcattr
->szlVirtualDeviceMm
.cy
, 254);
729 pdcattr
->szlViewportExt
.cx
= pdcattr
->szlVirtualDevicePixel
.cx
;
730 pdcattr
->szlViewportExt
.cy
= -pdcattr
->szlVirtualDevicePixel
.cy
;
734 pdcattr
->szlWindowExt
.cx
= MulDiv(14400, pdcattr
->szlVirtualDeviceMm
.cx
, 254);
735 pdcattr
->szlWindowExt
.cy
= MulDiv(14400, pdcattr
->szlVirtualDeviceMm
.cy
, 254);
736 pdcattr
->szlViewportExt
.cx
= pdcattr
->szlVirtualDevicePixel
.cx
;
737 pdcattr
->szlViewportExt
.cy
= -pdcattr
->szlVirtualDevicePixel
.cy
;
741 pdcattr
->flXform
&= ~(PAGE_TO_DEVICE_IDENTITY
|POSITIVE_Y_IS_UP
);
742 pdcattr
->flXform
|= ISO_OR_ANISO_MAP_MODE
;
746 pdcattr
->iMapMode
= PrevMapMode
;
757 NtGdiSetViewportOrgEx(
769 SetLastWin32Error(ERROR_INVALID_HANDLE
);
772 pdcattr
= dc
->pdcattr
;
776 NTSTATUS Status
= STATUS_SUCCESS
;
780 ProbeForWrite(Point
, sizeof(POINT
), 1);
781 Point
->x
= pdcattr
->ptlViewportOrg
.x
;
782 Point
->y
= pdcattr
->ptlViewportOrg
.y
;
784 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
786 Status
= _SEH2_GetExceptionCode();
790 if (!NT_SUCCESS(Status
))
792 SetLastNtError(Status
);
798 pdcattr
->ptlViewportOrg
.x
= X
;
799 pdcattr
->ptlViewportOrg
.y
= Y
;
821 SetLastWin32Error(ERROR_INVALID_HANDLE
);
824 pdcattr
= dc
->pdcattr
;
828 NTSTATUS Status
= STATUS_SUCCESS
;
832 ProbeForWrite(Point
, sizeof(POINT
), 1);
833 Point
->x
= pdcattr
->ptlWindowOrg
.x
;
834 Point
->y
= pdcattr
->ptlWindowOrg
.y
;
836 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
838 Status
= _SEH2_GetExceptionCode();
842 if (!NT_SUCCESS(Status
))
844 SetLastNtError(Status
);
850 pdcattr
->ptlWindowOrg
.x
= X
;
851 pdcattr
->ptlWindowOrg
.y
= Y
;
860 // Mirror Window function.
864 IntMirrorWindowOrg(PDC dc
)
869 pdcattr
= dc
->pdcattr
;
871 if (!(pdcattr
->dwLayout
& LAYOUT_RTL
))
873 pdcattr
->ptlWindowOrg
.x
= pdcattr
->lWindowOrgx
; // Flip it back.
876 if (!pdcattr
->szlViewportExt
.cx
) return;
878 // WOrgx = wox - (Width - 1) * WExtx / VExtx
880 X
= (dc
->erclWindow
.right
- dc
->erclWindow
.left
) - 1; // Get device width - 1
882 X
= (X
* pdcattr
->szlWindowExt
.cx
) / pdcattr
->szlViewportExt
.cx
;
884 pdcattr
->ptlWindowOrg
.x
= pdcattr
->lWindowOrgx
- X
; // Now set the inverted win origion.
891 // The default is left to right. This function changes it to right to left, which
892 // is the standard in Arabic and Hebrew cultures.
911 SetLastWin32Error(ERROR_INVALID_HANDLE
);
914 pdcattr
= dc
->pdcattr
;
916 pdcattr
->dwLayout
= dwLayout
;
917 oLayout
= pdcattr
->dwLayout
;
919 if (!(dwLayout
& LAYOUT_ORIENTATIONMASK
))
925 if (dwLayout
& LAYOUT_RTL
)
927 pdcattr
->iMapMode
= MM_ANISOTROPIC
;
930 pdcattr
->szlWindowExt
.cy
= -pdcattr
->szlWindowExt
.cy
;
931 pdcattr
->ptlWindowOrg
.x
= -pdcattr
->ptlWindowOrg
.x
;
934 IntMirrorWindowOrg(dc
);
936 pdcattr
->ptlWindowOrg
.x
= wox
- pdcattr
->ptlWindowOrg
.x
;
938 if (!(pdcattr
->flTextAlign
& TA_CENTER
)) pdcattr
->flTextAlign
|= TA_RIGHT
;
940 if (dc
->dclevel
.flPath
& DCPATH_CLOCKWISE
)
941 dc
->dclevel
.flPath
&= ~DCPATH_CLOCKWISE
;
943 dc
->dclevel
.flPath
|= DCPATH_CLOCKWISE
;
945 pdcattr
->flXform
|= (PAGE_EXTENTS_CHANGED
|
946 INVALIDATE_ATTRIBUTES
|
947 DEVICE_TO_WORLD_INVALID
);
949 // DC_UpdateXforms(dc);
967 SetLastWin32Error(ERROR_INVALID_HANDLE
);
970 Ret
= dc
->erclWindow
.right
- dc
->erclWindow
.left
;
980 NtGdiMirrorWindowOrg(
987 SetLastWin32Error(ERROR_INVALID_HANDLE
);
990 IntMirrorWindowOrg(dc
);
1002 IN INT cxVirtualDevice
,
1003 IN INT cyVirtualDevice
)
1008 if (!cxVirtualDevice
|| !cyVirtualDevice
)
1013 dc
= DC_LockDc(hdc
);
1014 if (!dc
) return FALSE
;
1016 pdcattr
= dc
->pdcattr
;
1018 pdcattr
->szlVirtualDeviceSize
.cx
= cxVirtualDevice
;
1019 pdcattr
->szlVirtualDeviceSize
.cy
= cyVirtualDevice
;
1021 // DC_UpdateXforms(dc);
1032 NtGdiSetVirtualResolution(
1034 IN INT cxVirtualDevicePixel
,
1035 IN INT cyVirtualDevicePixel
,
1036 IN INT cxVirtualDeviceMm
,
1037 IN INT cyVirtualDeviceMm
)
1042 /* Check parameters (all zeroes resets to real resolution) */
1043 if (cxVirtualDevicePixel
== 0 && cyVirtualDevicePixel
== 0 &&
1044 cxVirtualDeviceMm
== 0 && cyVirtualDeviceMm
== 0)
1046 cxVirtualDevicePixel
= NtGdiGetDeviceCaps(hdc
, HORZRES
);
1047 cyVirtualDevicePixel
= NtGdiGetDeviceCaps(hdc
, VERTRES
);
1048 cxVirtualDeviceMm
= NtGdiGetDeviceCaps(hdc
, HORZSIZE
);
1049 cyVirtualDeviceMm
= NtGdiGetDeviceCaps(hdc
, VERTSIZE
);
1051 else if (cxVirtualDevicePixel
== 0 || cyVirtualDevicePixel
== 0 ||
1052 cxVirtualDeviceMm
== 0 || cyVirtualDeviceMm
== 0)
1057 dc
= DC_LockDc(hdc
);
1058 if (!dc
) return FALSE
;
1060 pdcattr
= dc
->pdcattr
;
1062 pdcattr
->szlVirtualDevicePixel
.cx
= cxVirtualDevicePixel
;
1063 pdcattr
->szlVirtualDevicePixel
.cy
= cyVirtualDevicePixel
;
1064 pdcattr
->szlVirtualDeviceMm
.cx
= cxVirtualDeviceMm
;
1065 pdcattr
->szlVirtualDeviceMm
.cy
= cyVirtualDeviceMm
;
1067 // DC_UpdateXforms(dc);
1073 // FIXME: Don't use floating point in the kernel!
1075 DC_InvertXform(const XFORM
*xformSrc
,
1080 determinant
= xformSrc
->eM11
*xformSrc
->eM22
- xformSrc
->eM12
*xformSrc
->eM21
;
1081 if (determinant
> -1e-12 && determinant
< 1e-12)
1086 xformDest
->eM11
= xformSrc
->eM22
/ determinant
;
1087 xformDest
->eM12
= -xformSrc
->eM12
/ determinant
;
1088 xformDest
->eM21
= -xformSrc
->eM21
/ determinant
;
1089 xformDest
->eM22
= xformSrc
->eM11
/ determinant
;
1090 xformDest
->eDx
= -xformSrc
->eDx
* xformDest
->eM11
- xformSrc
->eDy
* xformDest
->eM21
;
1091 xformDest
->eDy
= -xformSrc
->eDx
* xformDest
->eM12
- xformSrc
->eDy
* xformDest
->eM22
;
1097 DC_UpdateXforms(PDC dc
)
1099 XFORM xformWnd2Vport
;
1100 PDC_ATTR pdcattr
= dc
->pdcattr
;
1101 XFORM xformWorld2Vport
, xformWorld2Wnd
, xformVport2World
;
1103 /* Construct a transformation to do the window-to-viewport conversion */
1104 IntWindowToViewPort(pdcattr
, &xformWnd2Vport
);
1106 /* Combine with the world transformation */
1107 MatrixS2XForm(&xformWorld2Vport
, &dc
->dclevel
.mxWorldToDevice
);
1108 MatrixS2XForm(&xformWorld2Wnd
, &dc
->dclevel
.mxWorldToPage
);
1109 IntGdiCombineTransform(&xformWorld2Vport
, &xformWorld2Wnd
, &xformWnd2Vport
);
1111 /* Create inverse of world-to-viewport transformation */
1112 MatrixS2XForm(&xformVport2World
, &dc
->dclevel
.mxDeviceToWorld
);
1113 if (DC_InvertXform(&xformWorld2Vport
, &xformVport2World
))
1115 pdcattr
->flXform
&= ~DEVICE_TO_WORLD_INVALID
;
1119 pdcattr
->flXform
|= DEVICE_TO_WORLD_INVALID
;
1122 /* Update transformation matrices */
1123 XForm2MatrixS(&dc
->dclevel
.mxWorldToDevice
, &xformWorld2Vport
);
1124 XForm2MatrixS(&dc
->dclevel
.mxDeviceToWorld
, &xformVport2World
);
1128 IntCalcFillOrigin(PDC pdc
)
1130 pdc
->ptlFillOrigin
.x
= pdc
->dclevel
.ptlBrushOrigin
.x
+ pdc
->ptlDCOrig
.x
;
1131 pdc
->ptlFillOrigin
.y
= pdc
->dclevel
.ptlBrushOrigin
.y
+ pdc
->ptlDCOrig
.y
;
1133 return pdc
->ptlFillOrigin
.y
;
1138 IntptlBrushOrigin(PDC pdc
, LONG x
, LONG y
)
1140 pdc
->dclevel
.ptlBrushOrigin
.x
= x
;
1141 pdc
->dclevel
.ptlBrushOrigin
.y
= y
;
1142 IntCalcFillOrigin(pdc
);
1143 return &pdc
->dclevel
.ptlBrushOrigin
;
1148 GdiSetDCOrg(HDC hDC
, LONG Left
, LONG Top
, PRECTL prc
)
1152 pdc
= DC_LockDc(hDC
);
1155 pdc
->ptlDCOrig
.x
= Left
;
1156 pdc
->ptlDCOrig
.y
= Top
;
1158 IntCalcFillOrigin(pdc
);
1160 if (prc
) pdc
->erclWindow
= *prc
;
1167 IntGdiGetDCOrg(PDC pDc
, PPOINTL ppt
)
1169 *ppt
= pDc
->ptlDCOrig
;
1175 GdiGetDCOrgEx(HDC hDC
, PPOINTL ppt
, PRECTL prc
)
1179 pdc
= DC_LockDc(hDC
);
1180 if (!pdc
) return FALSE
;
1182 *prc
= pdc
->erclWindow
;
1183 *ppt
= pdc
->ptlDCOrig
;
1191 DC_vGetAspectRatioFilter(PDC pDC
, LPSIZE AspectRatio
)
1193 if (pDC
->pdcattr
->flFontMapper
& 1) // TRUE assume 1.
1195 // "This specifies that Windows should only match fonts that have the
1196 // same aspect ratio as the display.", Programming Windows, Fifth Ed.
1197 AspectRatio
->cx
= pDC
->ppdev
->gdiinfo
.ulLogPixelsX
;
1198 AspectRatio
->cy
= pDC
->ppdev
->gdiinfo
.ulLogPixelsY
;
1202 AspectRatio
->cx
= 0;
1203 AspectRatio
->cy
= 0;
1209 DC_vUpdateViewportExt(PDC pdc
)
1213 /* Get a pointer to the dc attribute */
1214 pdcattr
= pdc
->pdcattr
;
1216 /* Check if we need to recalculate */
1217 if (pdcattr
->flXform
& PAGE_EXTENTS_CHANGED
)
1219 /* Check if we need to do isotropic fixup */
1220 if (pdcattr
->iMapMode
== MM_ISOTROPIC
)
1222 IntFixIsotropicMapping(pdc
);
1225 /* Update xforms, CHECKME: really done here? */
1226 DC_UpdateXforms(pdc
);
1240 NTSTATUS Status
= STATUS_SUCCESS
;
1244 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1248 pdc
= DC_LockDc(hDC
);
1251 SetLastWin32Error(ERROR_INVALID_HANDLE
);
1257 case GdiGetViewPortExt
:
1258 DC_vUpdateViewportExt(pdc
);
1259 SafePoint
.x
= pdc
->pdcattr
->szlViewportExt
.cx
;
1260 SafePoint
.y
= pdc
->pdcattr
->szlViewportExt
.cy
;
1263 case GdiGetWindowExt
:
1264 SafePoint
.x
= pdc
->pdcattr
->szlWindowExt
.cx
;
1265 SafePoint
.y
= pdc
->pdcattr
->szlWindowExt
.cy
;
1268 case GdiGetViewPortOrg
:
1269 SafePoint
= pdc
->pdcattr
->ptlViewportOrg
;
1272 case GdiGetWindowOrg
:
1273 SafePoint
= pdc
->pdcattr
->ptlWindowOrg
;
1277 SafePoint
= pdc
->ptlDCOrig
;
1280 case GdiGetAspectRatioFilter
:
1281 DC_vGetAspectRatioFilter(pdc
, &Size
);
1282 SafePoint
.x
= Size
.cx
;
1283 SafePoint
.y
= Size
.cy
;
1287 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
1296 ProbeForWrite(Point
, sizeof(POINT
), 1);
1299 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1301 Status
= _SEH2_GetExceptionCode();
1305 if (!NT_SUCCESS(Status
))
1307 SetLastNtError(Status
);
1325 return DCB_RESET
; /* bounding rectangle always empty */
1336 return DCB_DISABLE
; /* bounding rectangle always empty */