2 * COPYRIGHT: GNU GPL, See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Coordinate systems
5 * FILE: subsys/win32k/objects/coord.c
9 /* INCLUDES ******************************************************************/
16 /* FUNCTIONS *****************************************************************/
19 IntFixIsotropicMapping(PDC pdc
)
24 /* Get a pointer to the DC_ATTR */
25 pdcattr
= pdc
->pdcattr
;
27 /* Check if all values are valid */
28 if (pdcattr
->szlWindowExt
.cx
== 0 || pdcattr
->szlWindowExt
.cy
== 0 ||
29 pdcattr
->szlViewportExt
.cx
== 0 || pdcattr
->szlViewportExt
.cy
== 0)
31 /* Don't recalculate */
35 fx
= abs(pdcattr
->szlWindowExt
.cx
* pdcattr
->szlViewportExt
.cy
);
36 fy
= abs(pdcattr
->szlWindowExt
.cy
* pdcattr
->szlViewportExt
.cx
);
40 s
= pdcattr
->szlWindowExt
.cy
* pdcattr
->szlViewportExt
.cx
> 0 ? 1 : -1;
41 pdcattr
->szlViewportExt
.cx
= s
* fx
/ pdcattr
->szlWindowExt
.cy
;
45 s
= pdcattr
->szlWindowExt
.cx
* pdcattr
->szlViewportExt
.cy
> 0 ? 1 : -1;
46 pdcattr
->szlViewportExt
.cy
= s
* fy
/ pdcattr
->szlWindowExt
.cx
;
50 // FIXME: Don't use floating point in the kernel!
51 void IntWindowToViewPort(PDC_ATTR pdcattr
, LPXFORM xformWnd2Vport
)
55 scaleX
= (pdcattr
->szlWindowExt
.cx
? (FLOAT
)pdcattr
->szlViewportExt
.cx
/ (FLOAT
)pdcattr
->szlWindowExt
.cx
: 0.0f
);
56 scaleY
= (pdcattr
->szlWindowExt
.cy
? (FLOAT
)pdcattr
->szlViewportExt
.cy
/ (FLOAT
)pdcattr
->szlWindowExt
.cy
: 0.0f
);
57 xformWnd2Vport
->eM11
= scaleX
;
58 xformWnd2Vport
->eM12
= 0.0;
59 xformWnd2Vport
->eM21
= 0.0;
60 xformWnd2Vport
->eM22
= scaleY
;
61 xformWnd2Vport
->eDx
= (FLOAT
)pdcattr
->ptlViewportOrg
.x
- scaleX
* (FLOAT
)pdcattr
->ptlWindowOrg
.x
;
62 xformWnd2Vport
->eDy
= (FLOAT
)pdcattr
->ptlViewportOrg
.y
- scaleY
* (FLOAT
)pdcattr
->ptlWindowOrg
.y
;
65 // FIXME: Use XFORMOBJECT!
67 DC_UpdateXforms(PDC dc
)
70 PDC_ATTR pdcattr
= dc
->pdcattr
;
71 XFORM xformWorld2Vport
, xformWorld2Wnd
, xformVport2World
;
73 /* Construct a transformation to do the window-to-viewport conversion */
74 IntWindowToViewPort(pdcattr
, &xformWnd2Vport
);
76 /* Combine with the world transformation */
77 MatrixS2XForm(&xformWorld2Vport
, &dc
->dclevel
.mxWorldToDevice
);
78 MatrixS2XForm(&xformWorld2Wnd
, &dc
->dclevel
.mxWorldToPage
);
79 IntGdiCombineTransform(&xformWorld2Vport
, &xformWorld2Wnd
, &xformWnd2Vport
);
81 /* Create inverse of world-to-viewport transformation */
82 MatrixS2XForm(&xformVport2World
, &dc
->dclevel
.mxDeviceToWorld
);
83 if (DC_InvertXform(&xformWorld2Vport
, &xformVport2World
))
85 pdcattr
->flXform
&= ~DEVICE_TO_WORLD_INVALID
;
89 pdcattr
->flXform
|= DEVICE_TO_WORLD_INVALID
;
92 /* Update transformation matrices */
93 XForm2MatrixS(&dc
->dclevel
.mxWorldToDevice
, &xformWorld2Vport
);
94 XForm2MatrixS(&dc
->dclevel
.mxDeviceToWorld
, &xformVport2World
);
99 DC_vUpdateViewportExt(PDC pdc
)
103 /* Get a pointer to the dc attribute */
104 pdcattr
= pdc
->pdcattr
;
106 /* Check if we need to recalculate */
107 if (pdcattr
->flXform
& PAGE_EXTENTS_CHANGED
)
109 /* Check if we need to do isotropic fixup */
110 if (pdcattr
->iMapMode
== MM_ISOTROPIC
)
112 IntFixIsotropicMapping(pdc
);
115 /* Update xforms, CHECKME: really done here? */
116 DC_UpdateXforms(pdc
);
120 // FIXME: don't use floating point in the kernel! use XFORMOBJ function
122 IntGdiCombineTransform(
129 /* Check for illegal parameters */
130 if (!XFormResult
|| !xform1
|| !xform2
)
135 /* Create the result in a temporary XFORM, since xformResult may be
136 * equal to xform1 or xform2 */
137 xformTemp
.eM11
= xform1
->eM11
* xform2
->eM11
+ xform1
->eM12
* xform2
->eM21
;
138 xformTemp
.eM12
= xform1
->eM11
* xform2
->eM12
+ xform1
->eM12
* xform2
->eM22
;
139 xformTemp
.eM21
= xform1
->eM21
* xform2
->eM11
+ xform1
->eM22
* xform2
->eM21
;
140 xformTemp
.eM22
= xform1
->eM21
* xform2
->eM12
+ xform1
->eM22
* xform2
->eM22
;
141 xformTemp
.eDx
= xform1
->eDx
* xform2
->eM11
+ xform1
->eDy
* xform2
->eM21
+ xform2
->eDx
;
142 xformTemp
.eDy
= xform1
->eDx
* xform2
->eM12
+ xform1
->eDy
* xform2
->eM22
+ xform2
->eDy
;
143 *XFormResult
= xformTemp
;
148 // FIXME: should be XFORML and use XFORMOBJ functions
151 NtGdiCombineTransform(
152 LPXFORM UnsafeXFormResult
,
153 LPXFORM Unsafexform1
,
154 LPXFORM Unsafexform2
)
160 ProbeForWrite(UnsafeXFormResult
, sizeof(XFORM
), 1);
161 ProbeForRead(Unsafexform1
, sizeof(XFORM
), 1);
162 ProbeForRead(Unsafexform2
, sizeof(XFORM
), 1);
163 Ret
= IntGdiCombineTransform(UnsafeXFormResult
,
167 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
176 // FIXME: Should be XFORML and use XFORMOBJ functions directly
185 NTSTATUS Status
= STATUS_SUCCESS
;
189 EngSetLastError(ERROR_INVALID_PARAMETER
);
193 pdc
= DC_LockDc(hDC
);
196 EngSetLastError(ERROR_INVALID_HANDLE
);
202 ProbeForWrite(XForm
, sizeof(XFORM
), 1);
205 case GdiWorldSpaceToPageSpace
:
206 MatrixS2XForm(XForm
, &pdc
->dclevel
.mxWorldToPage
);
209 case GdiWorldSpaceToDeviceSpace
:
210 MatrixS2XForm(XForm
, &pdc
->dclevel
.mxWorldToDevice
);
213 case GdiPageSpaceToDeviceSpace
:
214 IntWindowToViewPort(pdc
->pdcattr
, XForm
);
217 case GdiDeviceSpaceToWorldSpace
:
218 MatrixS2XForm(XForm
, &pdc
->dclevel
.mxDeviceToWorld
);
222 DPRINT1("Unknown transform %lu\n", iXform
);
223 Status
= STATUS_INVALID_PARAMETER
;
227 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
229 Status
= _SEH2_GetExceptionCode();
234 return NT_SUCCESS(Status
);
239 * Converts points from logical coordinates into device coordinates.
240 * Conversion depends on the mapping mode,
241 * world transfrom, viewport origin settings for the given device context.
242 * \param hDC device context.
243 * \param Points an array of POINT structures (in/out).
244 * \param Count number of elements in the array of POINT structures.
245 * \return TRUE if success, FALSE otherwise.
249 NtGdiTransformPoints(
264 pdc
= DC_LockDc(hDC
);
267 EngSetLastError(ERROR_INVALID_PARAMETER
);
271 Size
= Count
* sizeof(POINT
);
273 // FIXME: It would be wise to have a small stack buffer as optimization
274 Points
= ExAllocatePoolWithTag(PagedPool
, Size
, GDITAG_TEMP
);
278 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
284 ProbeForWrite(UnsafePtOut
, Size
, 1);
285 ProbeForRead(UnsafePtsIn
, Size
, 1);
286 RtlCopyMemory(Points
, UnsafePtsIn
, Size
);
288 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
290 /* Do not set last error */
291 _SEH2_YIELD(goto leave
;)
298 IntDPtoLP(pdc
, Points
, Count
);
302 IntLPtoDP(pdc
, Points
, Count
);
305 case 2: // Not supported yet. Need testing.
308 EngSetLastError(ERROR_INVALID_PARAMETER
);
316 /* pointer was already probed! */
317 RtlCopyMemory(UnsafePtOut
, Points
, Size
);
319 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
321 /* Do not set last error */
326 // If we are getting called that means User XForms is a mess!
330 ExFreePoolWithTag(Points
, GDITAG_TEMP
);
334 // FIXME: Don't use floating point in the kernel
337 IntGdiModifyWorldTransform(
339 CONST LPXFORM lpXForm
,
342 XFORM xformWorld2Wnd
;
348 xformWorld2Wnd
.eM11
= 1.0f
;
349 xformWorld2Wnd
.eM12
= 0.0f
;
350 xformWorld2Wnd
.eM21
= 0.0f
;
351 xformWorld2Wnd
.eM22
= 1.0f
;
352 xformWorld2Wnd
.eDx
= 0.0f
;
353 xformWorld2Wnd
.eDy
= 0.0f
;
354 XForm2MatrixS(&pDc
->dclevel
.mxWorldToPage
, &xformWorld2Wnd
);
357 case MWT_LEFTMULTIPLY
:
358 MatrixS2XForm(&xformWorld2Wnd
, &pDc
->dclevel
.mxWorldToPage
);
359 IntGdiCombineTransform(&xformWorld2Wnd
, lpXForm
, &xformWorld2Wnd
);
360 XForm2MatrixS(&pDc
->dclevel
.mxWorldToPage
, &xformWorld2Wnd
);
363 case MWT_RIGHTMULTIPLY
:
364 MatrixS2XForm(&xformWorld2Wnd
, &pDc
->dclevel
.mxWorldToPage
);
365 IntGdiCombineTransform(&xformWorld2Wnd
, &xformWorld2Wnd
, lpXForm
);
366 XForm2MatrixS(&pDc
->dclevel
.mxWorldToPage
, &xformWorld2Wnd
);
369 case MWT_MAX
+1: // Must be MWT_SET????
370 XForm2MatrixS(&pDc
->dclevel
.mxWorldToPage
, lpXForm
); // Do it like Wine.
376 DC_UpdateXforms(pDc
);
382 NtGdiModifyWorldTransform(
388 XFORM SafeXForm
; //FIXME: use XFORML
394 EngSetLastError(ERROR_INVALID_HANDLE
);
398 // The xform is permitted to be NULL for MWT_IDENTITY.
399 // However, if it is not NULL, then it must be valid even though it is not used.
400 if (UnsafeXForm
!= NULL
|| Mode
!= MWT_IDENTITY
)
404 ProbeForRead(UnsafeXForm
, sizeof(XFORM
), 1);
405 RtlCopyMemory(&SafeXForm
, UnsafeXForm
, sizeof(XFORM
));
407 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
414 // Safe to handle kernel mode data.
415 if (Ret
) Ret
= IntGdiModifyWorldTransform(dc
, &SafeXForm
, Mode
);
422 NtGdiOffsetViewportOrgEx(
430 NTSTATUS Status
= STATUS_SUCCESS
;
435 EngSetLastError(ERROR_INVALID_HANDLE
);
438 pdcattr
= dc
->pdcattr
;
444 ProbeForWrite(UnsafePoint
, sizeof(POINT
), 1);
445 UnsafePoint
->x
= pdcattr
->ptlViewportOrg
.x
;
446 UnsafePoint
->y
= pdcattr
->ptlViewportOrg
.y
;
447 if (pdcattr
->dwLayout
& LAYOUT_RTL
)
449 UnsafePoint
->x
= -UnsafePoint
->x
;
452 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
454 Status
= _SEH2_GetExceptionCode();
458 if (!NT_SUCCESS(Status
))
460 SetLastNtError(Status
);
466 if (pdcattr
->dwLayout
& LAYOUT_RTL
)
470 pdcattr
->ptlViewportOrg
.x
+= XOffset
;
471 pdcattr
->ptlViewportOrg
.y
+= YOffset
;
480 NtGdiOffsetWindowOrgEx(
492 EngSetLastError(ERROR_INVALID_HANDLE
);
495 pdcattr
= dc
->pdcattr
;
499 NTSTATUS Status
= STATUS_SUCCESS
;
503 ProbeForWrite(Point
, sizeof(POINT
), 1);
504 Point
->x
= pdcattr
->ptlWindowOrg
.x
;
505 Point
->y
= pdcattr
->ptlWindowOrg
.y
;
507 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
509 Status
= _SEH2_GetExceptionCode();
513 if (!NT_SUCCESS(Status
))
515 SetLastNtError(Status
);
521 pdcattr
->ptlWindowOrg
.x
+= XOffset
;
522 pdcattr
->ptlWindowOrg
.y
+= YOffset
;
532 NtGdiScaleViewportExtEx(
545 pDC
= DC_LockDc(hDC
);
548 EngSetLastError(ERROR_INVALID_HANDLE
);
551 pdcattr
= pDC
->pdcattr
;
553 if (pdcattr
->iMapMode
> MM_TWIPS
)
555 if (Xdenom
&& Ydenom
)
557 X
= Xnum
* pdcattr
->szlViewportExt
.cx
/ Xdenom
;
560 Y
= Ynum
* pdcattr
->szlViewportExt
.cy
/ Ydenom
;
563 pdcattr
->szlViewportExt
.cx
= X
;
564 pdcattr
->szlViewportExt
.cy
= Y
;
566 IntMirrorWindowOrg(pDC
);
568 pdcattr
->flXform
|= (PAGE_EXTENTS_CHANGED
|
569 INVALIDATE_ATTRIBUTES
|
570 DEVICE_TO_WORLD_INVALID
);
572 if (pdcattr
->iMapMode
== MM_ISOTROPIC
)
574 IntFixIsotropicMapping(pDC
);
576 DC_UpdateXforms(pDC
);
590 ProbeForWrite(pSize
, sizeof(LPSIZE
), 1);
592 pSize
->cx
= pdcattr
->szlViewportExt
.cx
;
593 pSize
->cy
= pdcattr
->szlViewportExt
.cy
;
595 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
597 SetLastNtError(_SEH2_GetExceptionCode());
609 NtGdiScaleWindowExtEx(
622 pDC
= DC_LockDc(hDC
);
625 EngSetLastError(ERROR_INVALID_HANDLE
);
628 pdcattr
= pDC
->pdcattr
;
632 NTSTATUS Status
= STATUS_SUCCESS
;
636 ProbeForWrite(pSize
, sizeof(LPSIZE
), 1);
638 X
= pdcattr
->szlWindowExt
.cx
;
639 if (pdcattr
->dwLayout
& LAYOUT_RTL
) X
= -X
;
641 pSize
->cy
= pdcattr
->szlWindowExt
.cy
;
643 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
645 Status
= _SEH2_GetExceptionCode();
649 if (!NT_SUCCESS(Status
))
651 SetLastNtError(Status
);
657 if (pdcattr
->iMapMode
> MM_TWIPS
)
659 if (Xdenom
&& Ydenom
)
661 X
= Xnum
* pdcattr
->szlWindowExt
.cx
/ Xdenom
;
664 Y
= Ynum
* pdcattr
->szlWindowExt
.cy
/ Ydenom
;
667 pdcattr
->szlWindowExt
.cx
= X
;
668 pdcattr
->szlWindowExt
.cy
= Y
;
670 IntMirrorWindowOrg(pDC
);
672 pdcattr
->flXform
|= (PAGE_EXTENTS_CHANGED
|INVALIDATE_ATTRIBUTES
|DEVICE_TO_WORLD_INVALID
);
674 if (pdcattr
->iMapMode
== MM_ISOTROPIC
) IntFixIsotropicMapping(pDC
);
675 DC_UpdateXforms(pDC
);
696 PDC_ATTR pdcattr
= dc
->pdcattr
;
698 PrevMapMode
= pdcattr
->iMapMode
;
700 pdcattr
->iMapMode
= MapMode
;
705 pdcattr
->szlWindowExt
.cx
= 1;
706 pdcattr
->szlWindowExt
.cy
= 1;
707 pdcattr
->szlViewportExt
.cx
= 1;
708 pdcattr
->szlViewportExt
.cy
= 1;
709 pdcattr
->flXform
&= ~(ISO_OR_ANISO_MAP_MODE
|PTOD_EFM22_NEGATIVE
|
710 PTOD_EFM11_NEGATIVE
|POSITIVE_Y_IS_UP
);
711 pdcattr
->flXform
|= (PAGE_XLATE_CHANGED
|PAGE_TO_DEVICE_SCALE_IDENTITY
|
712 INVALIDATE_ATTRIBUTES
|DEVICE_TO_WORLD_INVALID
);
716 pdcattr
->flXform
|= ISO_OR_ANISO_MAP_MODE
;
720 pdcattr
->szlWindowExt
.cx
= pdcattr
->szlVirtualDeviceMm
.cx
* 10;
721 pdcattr
->szlWindowExt
.cy
= pdcattr
->szlVirtualDeviceMm
.cy
* 10;
722 pdcattr
->szlViewportExt
.cx
= pdcattr
->szlVirtualDevicePixel
.cx
;
723 pdcattr
->szlViewportExt
.cy
= -pdcattr
->szlVirtualDevicePixel
.cy
;
727 pdcattr
->szlWindowExt
.cx
= pdcattr
->szlVirtualDeviceMm
.cx
* 100;
728 pdcattr
->szlWindowExt
.cy
= pdcattr
->szlVirtualDeviceMm
.cy
* 100;
729 pdcattr
->szlViewportExt
.cx
= pdcattr
->szlVirtualDevicePixel
.cx
;
730 pdcattr
->szlViewportExt
.cy
= -pdcattr
->szlVirtualDevicePixel
.cy
;
734 pdcattr
->szlWindowExt
.cx
= MulDiv(1000, pdcattr
->szlVirtualDeviceMm
.cx
, 254);
735 pdcattr
->szlWindowExt
.cy
= MulDiv(1000, pdcattr
->szlVirtualDeviceMm
.cy
, 254);
736 pdcattr
->szlViewportExt
.cx
= pdcattr
->szlVirtualDevicePixel
.cx
;
737 pdcattr
->szlViewportExt
.cy
= -pdcattr
->szlVirtualDevicePixel
.cy
;
741 pdcattr
->szlWindowExt
.cx
= MulDiv(10000, pdcattr
->szlVirtualDeviceMm
.cx
, 254);
742 pdcattr
->szlWindowExt
.cy
= MulDiv(10000, pdcattr
->szlVirtualDeviceMm
.cy
, 254);
743 pdcattr
->szlViewportExt
.cx
= pdcattr
->szlVirtualDevicePixel
.cx
;
744 pdcattr
->szlViewportExt
.cy
= -pdcattr
->szlVirtualDevicePixel
.cy
;
748 pdcattr
->szlWindowExt
.cx
= MulDiv(14400, pdcattr
->szlVirtualDeviceMm
.cx
, 254);
749 pdcattr
->szlWindowExt
.cy
= MulDiv(14400, pdcattr
->szlVirtualDeviceMm
.cy
, 254);
750 pdcattr
->szlViewportExt
.cx
= pdcattr
->szlVirtualDevicePixel
.cx
;
751 pdcattr
->szlViewportExt
.cy
= -pdcattr
->szlVirtualDevicePixel
.cy
;
755 pdcattr
->flXform
&= ~(PAGE_TO_DEVICE_IDENTITY
|POSITIVE_Y_IS_UP
);
756 pdcattr
->flXform
|= ISO_OR_ANISO_MAP_MODE
;
760 pdcattr
->iMapMode
= PrevMapMode
;
771 NtGdiSetViewportOrgEx(
783 EngSetLastError(ERROR_INVALID_HANDLE
);
786 pdcattr
= dc
->pdcattr
;
790 NTSTATUS Status
= STATUS_SUCCESS
;
794 ProbeForWrite(Point
, sizeof(POINT
), 1);
795 Point
->x
= pdcattr
->ptlViewportOrg
.x
;
796 Point
->y
= pdcattr
->ptlViewportOrg
.y
;
798 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
800 Status
= _SEH2_GetExceptionCode();
804 if (!NT_SUCCESS(Status
))
806 SetLastNtError(Status
);
812 pdcattr
->ptlViewportOrg
.x
= X
;
813 pdcattr
->ptlViewportOrg
.y
= Y
;
835 EngSetLastError(ERROR_INVALID_HANDLE
);
838 pdcattr
= dc
->pdcattr
;
842 NTSTATUS Status
= STATUS_SUCCESS
;
846 ProbeForWrite(Point
, sizeof(POINT
), 1);
847 Point
->x
= pdcattr
->ptlWindowOrg
.x
;
848 Point
->y
= pdcattr
->ptlWindowOrg
.y
;
850 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
852 Status
= _SEH2_GetExceptionCode();
856 if (!NT_SUCCESS(Status
))
858 SetLastNtError(Status
);
864 pdcattr
->ptlWindowOrg
.x
= X
;
865 pdcattr
->ptlWindowOrg
.y
= Y
;
874 // Mirror Window function.
878 IntMirrorWindowOrg(PDC dc
)
883 pdcattr
= dc
->pdcattr
;
885 if (!(pdcattr
->dwLayout
& LAYOUT_RTL
))
887 pdcattr
->ptlWindowOrg
.x
= pdcattr
->lWindowOrgx
; // Flip it back.
890 if (!pdcattr
->szlViewportExt
.cx
) return;
892 // WOrgx = wox - (Width - 1) * WExtx / VExtx
894 X
= (dc
->erclWindow
.right
- dc
->erclWindow
.left
) - 1; // Get device width - 1
896 X
= (X
* pdcattr
->szlWindowExt
.cx
) / pdcattr
->szlViewportExt
.cx
;
898 pdcattr
->ptlWindowOrg
.x
= pdcattr
->lWindowOrgx
- X
; // Now set the inverted win origion.
910 PDC_ATTR pdcattr
= pdc
->pdcattr
;
912 pdcattr
->dwLayout
= dwLayout
;
914 if (!(dwLayout
& LAYOUT_ORIENTATIONMASK
)) return;
916 if (dwLayout
& LAYOUT_RTL
)
918 pdcattr
->iMapMode
= MM_ANISOTROPIC
;
921 pdcattr
->szlWindowExt
.cy
= -pdcattr
->szlWindowExt
.cy
;
922 pdcattr
->ptlWindowOrg
.x
= -pdcattr
->ptlWindowOrg
.x
;
925 IntMirrorWindowOrg(pdc
);
927 pdcattr
->ptlWindowOrg
.x
= wox
- pdcattr
->ptlWindowOrg
.x
;
929 if (!(pdcattr
->flTextAlign
& TA_CENTER
)) pdcattr
->flTextAlign
|= TA_RIGHT
;
931 if (pdc
->dclevel
.flPath
& DCPATH_CLOCKWISE
)
932 pdc
->dclevel
.flPath
&= ~DCPATH_CLOCKWISE
;
934 pdc
->dclevel
.flPath
|= DCPATH_CLOCKWISE
;
936 pdcattr
->flXform
|= (PAGE_EXTENTS_CHANGED
|
937 INVALIDATE_ATTRIBUTES
|
938 DEVICE_TO_WORLD_INVALID
);
940 // DC_UpdateXforms(pdc);
945 // The default is left to right. This function changes it to right to left, which
946 // is the standard in Arabic and Hebrew cultures.
962 pdc
= DC_LockDc(hdc
);
965 EngSetLastError(ERROR_INVALID_HANDLE
);
968 pdcattr
= pdc
->pdcattr
;
970 oLayout
= pdcattr
->dwLayout
;
971 DC_vSetLayout(pdc
, wox
, dwLayout
);
990 EngSetLastError(ERROR_INVALID_HANDLE
);
993 Ret
= dc
->erclWindow
.right
- dc
->erclWindow
.left
;
1003 NtGdiMirrorWindowOrg(
1007 dc
= DC_LockDc(hdc
);
1010 EngSetLastError(ERROR_INVALID_HANDLE
);
1013 IntMirrorWindowOrg(dc
);
1025 IN INT cxVirtualDevice
,
1026 IN INT cyVirtualDevice
)
1031 if (!cxVirtualDevice
|| !cyVirtualDevice
)
1036 dc
= DC_LockDc(hdc
);
1037 if (!dc
) return FALSE
;
1039 pdcattr
= dc
->pdcattr
;
1041 pdcattr
->szlVirtualDeviceSize
.cx
= cxVirtualDevice
;
1042 pdcattr
->szlVirtualDeviceSize
.cy
= cyVirtualDevice
;
1044 // DC_UpdateXforms(dc);
1055 NtGdiSetVirtualResolution(
1057 IN INT cxVirtualDevicePixel
,
1058 IN INT cyVirtualDevicePixel
,
1059 IN INT cxVirtualDeviceMm
,
1060 IN INT cyVirtualDeviceMm
)
1065 /* Check parameters (all zeroes resets to real resolution) */
1066 if (cxVirtualDevicePixel
== 0 && cyVirtualDevicePixel
== 0 &&
1067 cxVirtualDeviceMm
== 0 && cyVirtualDeviceMm
== 0)
1069 cxVirtualDevicePixel
= NtGdiGetDeviceCaps(hdc
, HORZRES
);
1070 cyVirtualDevicePixel
= NtGdiGetDeviceCaps(hdc
, VERTRES
);
1071 cxVirtualDeviceMm
= NtGdiGetDeviceCaps(hdc
, HORZSIZE
);
1072 cyVirtualDeviceMm
= NtGdiGetDeviceCaps(hdc
, VERTSIZE
);
1074 else if (cxVirtualDevicePixel
== 0 || cyVirtualDevicePixel
== 0 ||
1075 cxVirtualDeviceMm
== 0 || cyVirtualDeviceMm
== 0)
1080 dc
= DC_LockDc(hdc
);
1081 if (!dc
) return FALSE
;
1083 pdcattr
= dc
->pdcattr
;
1085 pdcattr
->szlVirtualDevicePixel
.cx
= cxVirtualDevicePixel
;
1086 pdcattr
->szlVirtualDevicePixel
.cy
= cyVirtualDevicePixel
;
1087 pdcattr
->szlVirtualDeviceMm
.cx
= cxVirtualDeviceMm
;
1088 pdcattr
->szlVirtualDeviceMm
.cy
= cyVirtualDeviceMm
;
1090 // DC_UpdateXforms(dc);
1096 // FIXME: Don't use floating point in the kernel!
1098 DC_InvertXform(const XFORM
*xformSrc
,
1103 determinant
= xformSrc
->eM11
*xformSrc
->eM22
- xformSrc
->eM12
*xformSrc
->eM21
;
1104 if (determinant
> -1e-12 && determinant
< 1e-12)
1109 xformDest
->eM11
= xformSrc
->eM22
/ determinant
;
1110 xformDest
->eM12
= -xformSrc
->eM12
/ determinant
;
1111 xformDest
->eM21
= -xformSrc
->eM21
/ determinant
;
1112 xformDest
->eM22
= xformSrc
->eM11
/ determinant
;
1113 xformDest
->eDx
= -xformSrc
->eDx
* xformDest
->eM11
- xformSrc
->eDy
* xformDest
->eM21
;
1114 xformDest
->eDy
= -xformSrc
->eDx
* xformDest
->eM12
- xformSrc
->eDy
* xformDest
->eM22
;
1120 IntCalcFillOrigin(PDC pdc
)
1122 pdc
->ptlFillOrigin
.x
= pdc
->dclevel
.ptlBrushOrigin
.x
+ pdc
->ptlDCOrig
.x
;
1123 pdc
->ptlFillOrigin
.y
= pdc
->dclevel
.ptlBrushOrigin
.y
+ pdc
->ptlDCOrig
.y
;
1125 return pdc
->ptlFillOrigin
.y
;
1130 IntptlBrushOrigin(PDC pdc
, LONG x
, LONG y
)
1132 pdc
->dclevel
.ptlBrushOrigin
.x
= x
;
1133 pdc
->dclevel
.ptlBrushOrigin
.y
= y
;
1134 IntCalcFillOrigin(pdc
);
1135 return &pdc
->dclevel
.ptlBrushOrigin
;
1140 DC_vGetAspectRatioFilter(PDC pDC
, LPSIZE AspectRatio
)
1142 if (pDC
->pdcattr
->flFontMapper
& 1) // TRUE assume 1.
1144 // "This specifies that Windows should only match fonts that have the
1145 // same aspect ratio as the display.", Programming Windows, Fifth Ed.
1146 AspectRatio
->cx
= pDC
->ppdev
->gdiinfo
.ulLogPixelsX
;
1147 AspectRatio
->cy
= pDC
->ppdev
->gdiinfo
.ulLogPixelsY
;
1151 AspectRatio
->cx
= 0;
1152 AspectRatio
->cy
= 0;
1166 NTSTATUS Status
= STATUS_SUCCESS
;
1170 EngSetLastError(ERROR_INVALID_PARAMETER
);
1174 pdc
= DC_LockDc(hDC
);
1177 EngSetLastError(ERROR_INVALID_HANDLE
);
1183 case GdiGetViewPortExt
:
1184 DC_vUpdateViewportExt(pdc
);
1185 SafePoint
.x
= pdc
->pdcattr
->szlViewportExt
.cx
;
1186 SafePoint
.y
= pdc
->pdcattr
->szlViewportExt
.cy
;
1189 case GdiGetWindowExt
:
1190 SafePoint
.x
= pdc
->pdcattr
->szlWindowExt
.cx
;
1191 SafePoint
.y
= pdc
->pdcattr
->szlWindowExt
.cy
;
1194 case GdiGetViewPortOrg
:
1195 SafePoint
= pdc
->pdcattr
->ptlViewportOrg
;
1198 case GdiGetWindowOrg
:
1199 SafePoint
= pdc
->pdcattr
->ptlWindowOrg
;
1203 SafePoint
= pdc
->ptlDCOrig
;
1206 case GdiGetAspectRatioFilter
:
1207 DC_vGetAspectRatioFilter(pdc
, &Size
);
1208 SafePoint
.x
= Size
.cx
;
1209 SafePoint
.y
= Size
.cy
;
1213 EngSetLastError(ERROR_INVALID_PARAMETER
);
1222 ProbeForWrite(Point
, sizeof(POINT
), 1);
1225 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1227 Status
= _SEH2_GetExceptionCode();
1231 if (!NT_SUCCESS(Status
))
1233 SetLastNtError(Status
);