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(
261 pdc
= DC_LockDc(hDC
);
264 EngSetLastError(ERROR_INVALID_HANDLE
);
268 if (!UnsafePtsIn
|| !UnsafePtOut
|| Count
<= 0)
271 EngSetLastError(ERROR_INVALID_PARAMETER
);
275 Size
= Count
* sizeof(POINT
);
277 // FIXME: It would be wise to have a small stack buffer as optimization
278 Points
= ExAllocatePoolWithTag(PagedPool
, Size
, GDITAG_TEMP
);
282 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
288 ProbeForWrite(UnsafePtOut
, Size
, 1);
289 ProbeForRead(UnsafePtsIn
, Size
, 1);
290 RtlCopyMemory(Points
, UnsafePtsIn
, Size
);
292 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
294 SetLastNtError(_SEH2_GetExceptionCode());
296 _SEH2_YIELD(goto leave
;)
303 IntDPtoLP(pdc
, Points
, Count
);
307 IntLPtoDP(pdc
, Points
, Count
);
310 case 2: // Not supported yet. Need testing.
313 EngSetLastError(ERROR_INVALID_PARAMETER
);
321 /* pointer was already probed! */
322 RtlCopyMemory(UnsafePtOut
, Points
, Size
);
324 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
326 SetLastNtError(_SEH2_GetExceptionCode());
332 // If we are getting called that means User XForms is a mess!
336 ExFreePoolWithTag(Points
, GDITAG_TEMP
);
340 // FIXME: Don't use floating point in the kernel
343 IntGdiModifyWorldTransform(
345 CONST LPXFORM lpXForm
,
348 XFORM xformWorld2Wnd
;
354 xformWorld2Wnd
.eM11
= 1.0f
;
355 xformWorld2Wnd
.eM12
= 0.0f
;
356 xformWorld2Wnd
.eM21
= 0.0f
;
357 xformWorld2Wnd
.eM22
= 1.0f
;
358 xformWorld2Wnd
.eDx
= 0.0f
;
359 xformWorld2Wnd
.eDy
= 0.0f
;
360 XForm2MatrixS(&pDc
->dclevel
.mxWorldToPage
, &xformWorld2Wnd
);
363 case MWT_LEFTMULTIPLY
:
364 MatrixS2XForm(&xformWorld2Wnd
, &pDc
->dclevel
.mxWorldToPage
);
365 IntGdiCombineTransform(&xformWorld2Wnd
, lpXForm
, &xformWorld2Wnd
);
366 XForm2MatrixS(&pDc
->dclevel
.mxWorldToPage
, &xformWorld2Wnd
);
369 case MWT_RIGHTMULTIPLY
:
370 MatrixS2XForm(&xformWorld2Wnd
, &pDc
->dclevel
.mxWorldToPage
);
371 IntGdiCombineTransform(&xformWorld2Wnd
, &xformWorld2Wnd
, lpXForm
);
372 XForm2MatrixS(&pDc
->dclevel
.mxWorldToPage
, &xformWorld2Wnd
);
375 case MWT_MAX
+1: // Must be MWT_SET????
376 XForm2MatrixS(&pDc
->dclevel
.mxWorldToPage
, lpXForm
); // Do it like Wine.
382 DC_UpdateXforms(pDc
);
388 NtGdiModifyWorldTransform(
394 XFORM SafeXForm
; //FIXME: use XFORML
400 EngSetLastError(ERROR_INVALID_HANDLE
);
404 // The xform is permitted to be NULL for MWT_IDENTITY.
405 // However, if it is not NULL, then it must be valid even though it is not used.
406 if (UnsafeXForm
!= NULL
|| Mode
!= MWT_IDENTITY
)
410 ProbeForRead(UnsafeXForm
, sizeof(XFORM
), 1);
411 RtlCopyMemory(&SafeXForm
, UnsafeXForm
, sizeof(XFORM
));
413 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
420 // Safe to handle kernel mode data.
421 if (Ret
) Ret
= IntGdiModifyWorldTransform(dc
, &SafeXForm
, Mode
);
428 NtGdiOffsetViewportOrgEx(
436 NTSTATUS Status
= STATUS_SUCCESS
;
441 EngSetLastError(ERROR_INVALID_HANDLE
);
444 pdcattr
= dc
->pdcattr
;
450 ProbeForWrite(UnsafePoint
, sizeof(POINT
), 1);
451 UnsafePoint
->x
= pdcattr
->ptlViewportOrg
.x
;
452 UnsafePoint
->y
= pdcattr
->ptlViewportOrg
.y
;
453 if (pdcattr
->dwLayout
& LAYOUT_RTL
)
455 UnsafePoint
->x
= -UnsafePoint
->x
;
458 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
460 Status
= _SEH2_GetExceptionCode();
464 if (!NT_SUCCESS(Status
))
466 SetLastNtError(Status
);
472 if (pdcattr
->dwLayout
& LAYOUT_RTL
)
476 pdcattr
->ptlViewportOrg
.x
+= XOffset
;
477 pdcattr
->ptlViewportOrg
.y
+= YOffset
;
486 NtGdiOffsetWindowOrgEx(
498 EngSetLastError(ERROR_INVALID_HANDLE
);
501 pdcattr
= dc
->pdcattr
;
505 NTSTATUS Status
= STATUS_SUCCESS
;
509 ProbeForWrite(Point
, sizeof(POINT
), 1);
510 Point
->x
= pdcattr
->ptlWindowOrg
.x
;
511 Point
->y
= pdcattr
->ptlWindowOrg
.y
;
513 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
515 Status
= _SEH2_GetExceptionCode();
519 if (!NT_SUCCESS(Status
))
521 SetLastNtError(Status
);
527 pdcattr
->ptlWindowOrg
.x
+= XOffset
;
528 pdcattr
->ptlWindowOrg
.y
+= YOffset
;
538 NtGdiScaleViewportExtEx(
551 pDC
= DC_LockDc(hDC
);
554 EngSetLastError(ERROR_INVALID_HANDLE
);
557 pdcattr
= pDC
->pdcattr
;
559 if (pdcattr
->iMapMode
> MM_TWIPS
)
561 if (Xdenom
&& Ydenom
)
563 X
= Xnum
* pdcattr
->szlViewportExt
.cx
/ Xdenom
;
566 Y
= Ynum
* pdcattr
->szlViewportExt
.cy
/ Ydenom
;
569 pdcattr
->szlViewportExt
.cx
= X
;
570 pdcattr
->szlViewportExt
.cy
= Y
;
572 IntMirrorWindowOrg(pDC
);
574 pdcattr
->flXform
|= (PAGE_EXTENTS_CHANGED
|
575 INVALIDATE_ATTRIBUTES
|
576 DEVICE_TO_WORLD_INVALID
);
578 if (pdcattr
->iMapMode
== MM_ISOTROPIC
)
580 IntFixIsotropicMapping(pDC
);
582 DC_UpdateXforms(pDC
);
596 ProbeForWrite(pSize
, sizeof(LPSIZE
), 1);
598 pSize
->cx
= pdcattr
->szlViewportExt
.cx
;
599 pSize
->cy
= pdcattr
->szlViewportExt
.cy
;
601 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
603 SetLastNtError(_SEH2_GetExceptionCode());
615 NtGdiScaleWindowExtEx(
628 pDC
= DC_LockDc(hDC
);
631 EngSetLastError(ERROR_INVALID_HANDLE
);
634 pdcattr
= pDC
->pdcattr
;
638 NTSTATUS Status
= STATUS_SUCCESS
;
642 ProbeForWrite(pSize
, sizeof(LPSIZE
), 1);
644 X
= pdcattr
->szlWindowExt
.cx
;
645 if (pdcattr
->dwLayout
& LAYOUT_RTL
) X
= -X
;
647 pSize
->cy
= pdcattr
->szlWindowExt
.cy
;
649 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
651 Status
= _SEH2_GetExceptionCode();
655 if (!NT_SUCCESS(Status
))
657 SetLastNtError(Status
);
663 if (pdcattr
->iMapMode
> MM_TWIPS
)
665 if (Xdenom
&& Ydenom
)
667 X
= Xnum
* pdcattr
->szlWindowExt
.cx
/ Xdenom
;
670 Y
= Ynum
* pdcattr
->szlWindowExt
.cy
/ Ydenom
;
673 pdcattr
->szlWindowExt
.cx
= X
;
674 pdcattr
->szlWindowExt
.cy
= Y
;
676 IntMirrorWindowOrg(pDC
);
678 pdcattr
->flXform
|= (PAGE_EXTENTS_CHANGED
|INVALIDATE_ATTRIBUTES
|DEVICE_TO_WORLD_INVALID
);
680 if (pdcattr
->iMapMode
== MM_ISOTROPIC
) IntFixIsotropicMapping(pDC
);
681 DC_UpdateXforms(pDC
);
702 PDC_ATTR pdcattr
= dc
->pdcattr
;
704 PrevMapMode
= pdcattr
->iMapMode
;
706 pdcattr
->iMapMode
= MapMode
;
711 pdcattr
->szlWindowExt
.cx
= 1;
712 pdcattr
->szlWindowExt
.cy
= 1;
713 pdcattr
->szlViewportExt
.cx
= 1;
714 pdcattr
->szlViewportExt
.cy
= 1;
715 pdcattr
->flXform
&= ~(ISO_OR_ANISO_MAP_MODE
|PTOD_EFM22_NEGATIVE
|
716 PTOD_EFM11_NEGATIVE
|POSITIVE_Y_IS_UP
);
717 pdcattr
->flXform
|= (PAGE_XLATE_CHANGED
|PAGE_TO_DEVICE_SCALE_IDENTITY
|
718 INVALIDATE_ATTRIBUTES
|DEVICE_TO_WORLD_INVALID
);
722 pdcattr
->flXform
|= ISO_OR_ANISO_MAP_MODE
;
726 pdcattr
->szlWindowExt
.cx
= pdcattr
->szlVirtualDeviceMm
.cx
* 10;
727 pdcattr
->szlWindowExt
.cy
= pdcattr
->szlVirtualDeviceMm
.cy
* 10;
728 pdcattr
->szlViewportExt
.cx
= pdcattr
->szlVirtualDevicePixel
.cx
;
729 pdcattr
->szlViewportExt
.cy
= -pdcattr
->szlVirtualDevicePixel
.cy
;
733 pdcattr
->szlWindowExt
.cx
= pdcattr
->szlVirtualDeviceMm
.cx
* 100;
734 pdcattr
->szlWindowExt
.cy
= pdcattr
->szlVirtualDeviceMm
.cy
* 100;
735 pdcattr
->szlViewportExt
.cx
= pdcattr
->szlVirtualDevicePixel
.cx
;
736 pdcattr
->szlViewportExt
.cy
= -pdcattr
->szlVirtualDevicePixel
.cy
;
740 pdcattr
->szlWindowExt
.cx
= MulDiv(1000, pdcattr
->szlVirtualDeviceMm
.cx
, 254);
741 pdcattr
->szlWindowExt
.cy
= MulDiv(1000, pdcattr
->szlVirtualDeviceMm
.cy
, 254);
742 pdcattr
->szlViewportExt
.cx
= pdcattr
->szlVirtualDevicePixel
.cx
;
743 pdcattr
->szlViewportExt
.cy
= -pdcattr
->szlVirtualDevicePixel
.cy
;
747 pdcattr
->szlWindowExt
.cx
= MulDiv(10000, pdcattr
->szlVirtualDeviceMm
.cx
, 254);
748 pdcattr
->szlWindowExt
.cy
= MulDiv(10000, pdcattr
->szlVirtualDeviceMm
.cy
, 254);
749 pdcattr
->szlViewportExt
.cx
= pdcattr
->szlVirtualDevicePixel
.cx
;
750 pdcattr
->szlViewportExt
.cy
= -pdcattr
->szlVirtualDevicePixel
.cy
;
754 pdcattr
->szlWindowExt
.cx
= MulDiv(14400, pdcattr
->szlVirtualDeviceMm
.cx
, 254);
755 pdcattr
->szlWindowExt
.cy
= MulDiv(14400, pdcattr
->szlVirtualDeviceMm
.cy
, 254);
756 pdcattr
->szlViewportExt
.cx
= pdcattr
->szlVirtualDevicePixel
.cx
;
757 pdcattr
->szlViewportExt
.cy
= -pdcattr
->szlVirtualDevicePixel
.cy
;
761 pdcattr
->flXform
&= ~(PAGE_TO_DEVICE_IDENTITY
|POSITIVE_Y_IS_UP
);
762 pdcattr
->flXform
|= ISO_OR_ANISO_MAP_MODE
;
766 pdcattr
->iMapMode
= PrevMapMode
;
777 NtGdiSetViewportOrgEx(
789 EngSetLastError(ERROR_INVALID_HANDLE
);
792 pdcattr
= dc
->pdcattr
;
796 NTSTATUS Status
= STATUS_SUCCESS
;
800 ProbeForWrite(Point
, sizeof(POINT
), 1);
801 Point
->x
= pdcattr
->ptlViewportOrg
.x
;
802 Point
->y
= pdcattr
->ptlViewportOrg
.y
;
804 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
806 Status
= _SEH2_GetExceptionCode();
810 if (!NT_SUCCESS(Status
))
812 SetLastNtError(Status
);
818 pdcattr
->ptlViewportOrg
.x
= X
;
819 pdcattr
->ptlViewportOrg
.y
= Y
;
841 EngSetLastError(ERROR_INVALID_HANDLE
);
844 pdcattr
= dc
->pdcattr
;
848 NTSTATUS Status
= STATUS_SUCCESS
;
852 ProbeForWrite(Point
, sizeof(POINT
), 1);
853 Point
->x
= pdcattr
->ptlWindowOrg
.x
;
854 Point
->y
= pdcattr
->ptlWindowOrg
.y
;
856 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
858 Status
= _SEH2_GetExceptionCode();
862 if (!NT_SUCCESS(Status
))
864 SetLastNtError(Status
);
870 pdcattr
->ptlWindowOrg
.x
= X
;
871 pdcattr
->ptlWindowOrg
.y
= Y
;
880 // Mirror Window function.
884 IntMirrorWindowOrg(PDC dc
)
889 pdcattr
= dc
->pdcattr
;
891 if (!(pdcattr
->dwLayout
& LAYOUT_RTL
))
893 pdcattr
->ptlWindowOrg
.x
= pdcattr
->lWindowOrgx
; // Flip it back.
896 if (!pdcattr
->szlViewportExt
.cx
) return;
898 // WOrgx = wox - (Width - 1) * WExtx / VExtx
900 X
= (dc
->erclWindow
.right
- dc
->erclWindow
.left
) - 1; // Get device width - 1
902 X
= (X
* pdcattr
->szlWindowExt
.cx
) / pdcattr
->szlViewportExt
.cx
;
904 pdcattr
->ptlWindowOrg
.x
= pdcattr
->lWindowOrgx
- X
; // Now set the inverted win origion.
916 PDC_ATTR pdcattr
= pdc
->pdcattr
;
918 pdcattr
->dwLayout
= dwLayout
;
920 if (!(dwLayout
& LAYOUT_ORIENTATIONMASK
)) return;
922 if (dwLayout
& LAYOUT_RTL
)
924 pdcattr
->iMapMode
= MM_ANISOTROPIC
;
927 pdcattr
->szlWindowExt
.cy
= -pdcattr
->szlWindowExt
.cy
;
928 pdcattr
->ptlWindowOrg
.x
= -pdcattr
->ptlWindowOrg
.x
;
931 IntMirrorWindowOrg(pdc
);
933 pdcattr
->ptlWindowOrg
.x
= wox
- pdcattr
->ptlWindowOrg
.x
;
935 if (!(pdcattr
->flTextAlign
& TA_CENTER
)) pdcattr
->flTextAlign
|= TA_RIGHT
;
937 if (pdc
->dclevel
.flPath
& DCPATH_CLOCKWISE
)
938 pdc
->dclevel
.flPath
&= ~DCPATH_CLOCKWISE
;
940 pdc
->dclevel
.flPath
|= DCPATH_CLOCKWISE
;
942 pdcattr
->flXform
|= (PAGE_EXTENTS_CHANGED
|
943 INVALIDATE_ATTRIBUTES
|
944 DEVICE_TO_WORLD_INVALID
);
946 // DC_UpdateXforms(pdc);
951 // The default is left to right. This function changes it to right to left, which
952 // is the standard in Arabic and Hebrew cultures.
968 pdc
= DC_LockDc(hdc
);
971 EngSetLastError(ERROR_INVALID_HANDLE
);
974 pdcattr
= pdc
->pdcattr
;
976 oLayout
= pdcattr
->dwLayout
;
977 DC_vSetLayout(pdc
, wox
, dwLayout
);
996 EngSetLastError(ERROR_INVALID_HANDLE
);
999 Ret
= dc
->erclWindow
.right
- dc
->erclWindow
.left
;
1009 NtGdiMirrorWindowOrg(
1013 dc
= DC_LockDc(hdc
);
1016 EngSetLastError(ERROR_INVALID_HANDLE
);
1019 IntMirrorWindowOrg(dc
);
1031 IN INT cxVirtualDevice
,
1032 IN INT cyVirtualDevice
)
1037 if (!cxVirtualDevice
|| !cyVirtualDevice
)
1042 dc
= DC_LockDc(hdc
);
1043 if (!dc
) return FALSE
;
1045 pdcattr
= dc
->pdcattr
;
1047 pdcattr
->szlVirtualDeviceSize
.cx
= cxVirtualDevice
;
1048 pdcattr
->szlVirtualDeviceSize
.cy
= cyVirtualDevice
;
1050 // DC_UpdateXforms(dc);
1061 NtGdiSetVirtualResolution(
1063 IN INT cxVirtualDevicePixel
,
1064 IN INT cyVirtualDevicePixel
,
1065 IN INT cxVirtualDeviceMm
,
1066 IN INT cyVirtualDeviceMm
)
1071 /* Check parameters (all zeroes resets to real resolution) */
1072 if (cxVirtualDevicePixel
== 0 && cyVirtualDevicePixel
== 0 &&
1073 cxVirtualDeviceMm
== 0 && cyVirtualDeviceMm
== 0)
1075 cxVirtualDevicePixel
= NtGdiGetDeviceCaps(hdc
, HORZRES
);
1076 cyVirtualDevicePixel
= NtGdiGetDeviceCaps(hdc
, VERTRES
);
1077 cxVirtualDeviceMm
= NtGdiGetDeviceCaps(hdc
, HORZSIZE
);
1078 cyVirtualDeviceMm
= NtGdiGetDeviceCaps(hdc
, VERTSIZE
);
1080 else if (cxVirtualDevicePixel
== 0 || cyVirtualDevicePixel
== 0 ||
1081 cxVirtualDeviceMm
== 0 || cyVirtualDeviceMm
== 0)
1086 dc
= DC_LockDc(hdc
);
1087 if (!dc
) return FALSE
;
1089 pdcattr
= dc
->pdcattr
;
1091 pdcattr
->szlVirtualDevicePixel
.cx
= cxVirtualDevicePixel
;
1092 pdcattr
->szlVirtualDevicePixel
.cy
= cyVirtualDevicePixel
;
1093 pdcattr
->szlVirtualDeviceMm
.cx
= cxVirtualDeviceMm
;
1094 pdcattr
->szlVirtualDeviceMm
.cy
= cyVirtualDeviceMm
;
1096 // DC_UpdateXforms(dc);
1102 // FIXME: Don't use floating point in the kernel!
1104 DC_InvertXform(const XFORM
*xformSrc
,
1109 determinant
= xformSrc
->eM11
*xformSrc
->eM22
- xformSrc
->eM12
*xformSrc
->eM21
;
1110 if (determinant
> -1e-12 && determinant
< 1e-12)
1115 xformDest
->eM11
= xformSrc
->eM22
/ determinant
;
1116 xformDest
->eM12
= -xformSrc
->eM12
/ determinant
;
1117 xformDest
->eM21
= -xformSrc
->eM21
/ determinant
;
1118 xformDest
->eM22
= xformSrc
->eM11
/ determinant
;
1119 xformDest
->eDx
= -xformSrc
->eDx
* xformDest
->eM11
- xformSrc
->eDy
* xformDest
->eM21
;
1120 xformDest
->eDy
= -xformSrc
->eDx
* xformDest
->eM12
- xformSrc
->eDy
* xformDest
->eM22
;
1126 IntCalcFillOrigin(PDC pdc
)
1128 pdc
->ptlFillOrigin
.x
= pdc
->dclevel
.ptlBrushOrigin
.x
+ pdc
->ptlDCOrig
.x
;
1129 pdc
->ptlFillOrigin
.y
= pdc
->dclevel
.ptlBrushOrigin
.y
+ pdc
->ptlDCOrig
.y
;
1131 return pdc
->ptlFillOrigin
.y
;
1136 IntptlBrushOrigin(PDC pdc
, LONG x
, LONG y
)
1138 pdc
->dclevel
.ptlBrushOrigin
.x
= x
;
1139 pdc
->dclevel
.ptlBrushOrigin
.y
= y
;
1140 IntCalcFillOrigin(pdc
);
1141 return &pdc
->dclevel
.ptlBrushOrigin
;
1146 DC_vGetAspectRatioFilter(PDC pDC
, LPSIZE AspectRatio
)
1148 if (pDC
->pdcattr
->flFontMapper
& 1) // TRUE assume 1.
1150 // "This specifies that Windows should only match fonts that have the
1151 // same aspect ratio as the display.", Programming Windows, Fifth Ed.
1152 AspectRatio
->cx
= pDC
->ppdev
->gdiinfo
.ulLogPixelsX
;
1153 AspectRatio
->cy
= pDC
->ppdev
->gdiinfo
.ulLogPixelsY
;
1157 AspectRatio
->cx
= 0;
1158 AspectRatio
->cy
= 0;
1172 NTSTATUS Status
= STATUS_SUCCESS
;
1176 EngSetLastError(ERROR_INVALID_PARAMETER
);
1180 pdc
= DC_LockDc(hDC
);
1183 EngSetLastError(ERROR_INVALID_HANDLE
);
1189 case GdiGetViewPortExt
:
1190 DC_vUpdateViewportExt(pdc
);
1191 SafePoint
.x
= pdc
->pdcattr
->szlViewportExt
.cx
;
1192 SafePoint
.y
= pdc
->pdcattr
->szlViewportExt
.cy
;
1195 case GdiGetWindowExt
:
1196 SafePoint
.x
= pdc
->pdcattr
->szlWindowExt
.cx
;
1197 SafePoint
.y
= pdc
->pdcattr
->szlWindowExt
.cy
;
1200 case GdiGetViewPortOrg
:
1201 SafePoint
= pdc
->pdcattr
->ptlViewportOrg
;
1204 case GdiGetWindowOrg
:
1205 SafePoint
= pdc
->pdcattr
->ptlWindowOrg
;
1209 SafePoint
= pdc
->ptlDCOrig
;
1212 case GdiGetAspectRatioFilter
:
1213 DC_vGetAspectRatioFilter(pdc
, &Size
);
1214 SafePoint
.x
= Size
.cx
;
1215 SafePoint
.y
= Size
.cy
;
1219 EngSetLastError(ERROR_INVALID_PARAMETER
);
1228 ProbeForWrite(Point
, sizeof(POINT
), 1);
1231 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1233 Status
= _SEH2_GetExceptionCode();
1237 if (!NT_SUCCESS(Status
))
1239 SetLastNtError(Status
);