xref: /reactos/win32ss/gdi/ntgdi/coord.c (revision 405ce532)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * COPYRIGHT:        GNU GPL, See COPYING in the top level directory
3c2c66affSColin Finck  * PROJECT:          ReactOS kernel
4c2c66affSColin Finck  * PURPOSE:          Coordinate systems
5c2c66affSColin Finck  * FILE:             win32ss/gdi/ntgdi/coord.c
68bdfdd5cSKatayama Hirofumi MZ  * PROGRAMERS:       Timo Kreuzer (timo.kreuzer@rectos.org)
78bdfdd5cSKatayama Hirofumi MZ  *                   Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
8c2c66affSColin Finck  */
9c2c66affSColin Finck 
10c2c66affSColin Finck /* Coordinate translation overview
11c2c66affSColin Finck  * -------------------------------
12c2c66affSColin Finck  *
13c2c66affSColin Finck  * Windows uses 3 different coordinate systems, referred to as world space,
14c2c66affSColin Finck  * page space and device space.
15c2c66affSColin Finck  *
16c2c66affSColin Finck  * Device space:
17c2c66affSColin Finck  * This is the coordinate system of the physical device that displays the
18c2c66affSColin Finck  * graphics. One unit matches one pixel of the surface. The coordinate system
19c2c66affSColin Finck  * is always orthogonal.
20c2c66affSColin Finck  *
21c2c66affSColin Finck  * Page space:
22c2c66affSColin Finck  * This is the coordinate system on the screen or on the paper layout for
23c2c66affSColin Finck  * printer devices. The coordinate system is also orthogonal but one unit
24c2c66affSColin Finck  * does not necessarily match one pixel. Instead there are different mapping
25c2c66affSColin Finck  * modes that can be set using SetMapMode() that specify how page space units
26c2c66affSColin Finck  * are transformed into device space units. These mapping modes are:
27c2c66affSColin Finck  * - MM_TEXT: One unit matches one unit in device space (one pixel)
28c2c66affSColin Finck  * - MM_TWIPS One unit matches 1/20 point (1/1440 inch)
29c2c66affSColin Finck  * - MM_LOMETRIC: One unit matches 0.1 millimeter
30c2c66affSColin Finck  * - MM_HIMETRIC: One unit matches 0.01 millimeter
31c2c66affSColin Finck  * - MM_LOENGLISH: One unit matches 0.01 inch
32c2c66affSColin Finck  * - MM_HIENGLISH: One unit matches 0.001 inch
33c2c66affSColin Finck  * - MM_ISOTROPIC:
34c2c66affSColin Finck  * - MM_ANISOTROPIC:
35c2c66affSColin Finck  * If the mapping mode is either MM_ISOTROPIC or MM_ANISOTROPIC, the actual
36c2c66affSColin Finck  * transformation is calculated from the window and viewport extension.
37c2c66affSColin Finck  * The window extension can be set using SetWindowExtEx() and describes the
38c2c66affSColin Finck  * extents of an arbitrary window (not to confuse with the gui element!) in
39c2c66affSColin Finck  * page space coordinates.
40c2c66affSColin Finck  * The viewport extension can be set using SetViewportExtEx() and describes
41c2c66affSColin Finck  * the extent of the same window in device space coordinates. If the mapping
42c2c66affSColin Finck  * mode is MM_ISOTROPIC one of the viewport extensions can be adjusted by GDI
43c2c66affSColin Finck  * to make sure the mapping stays isotropic, i.e. that it has the same x/y
44c2c66affSColin Finck  * ratio as the window extension.
45c2c66affSColin Finck  *
46c2c66affSColin Finck  * World space:
47c2c66affSColin Finck  * World space is the coordinate system that is used for all GDI drawing
48c2c66affSColin Finck  * operations. The metrics of this coordinate system depend on the DCs
49c2c66affSColin Finck  * graphics mode, which can be set using SetGraphicsMode().
50c2c66affSColin Finck  * If the graphics mode is GM_COMPATIBLE, world space is identical to page
51c2c66affSColin Finck  * space and no additional transformation is applied.
52c2c66affSColin Finck  * If the graphics mode is GM_ADVANCED, an arbitrary coordinate transformation
53c2c66affSColin Finck  * can be set using SetWorldTransform(), which is applied to transform world
54c2c66affSColin Finck  * space coordinates into page space coordinates.
55c2c66affSColin Finck  *
56c2c66affSColin Finck  * User mode data:
57c2c66affSColin Finck  * All coordinate translation data is stored in the DC attribute, so the values
58c2c66affSColin Finck  * might be invalid. This has to be taken into account. Values might also be
59c2c66affSColin Finck  * zero, so when a division is made, the value has to be read first and then
60c2c66affSColin Finck  * checked! This is true for both integer and floating point values, even if
61c2c66affSColin Finck  * we cannot get floating point exceptions on x86, we can get them on all other
62c2c66affSColin Finck  * architectures that use the FPU directly instead of emulation.
63c2c66affSColin Finck  * The result of all operations might be completely random and invalid, if it was
64c2c66affSColin Finck  * messed with in an illegal way in user mode. This is not a problem, since the
65c2c66affSColin Finck  * result of coordinate transformations are never expected to be "valid" values.
66c2c66affSColin Finck  * In the worst case, the drawing operation draws rubbish into the DC.
67c2c66affSColin Finck  */
68c2c66affSColin Finck 
69c2c66affSColin Finck /* INCLUDES ******************************************************************/
70c2c66affSColin Finck 
71c2c66affSColin Finck #include <win32k.h>
72c2c66affSColin Finck 
73c2c66affSColin Finck #define NDEBUG
74c2c66affSColin Finck #include <debug.h>
75c2c66affSColin Finck C_ASSERT(sizeof(XFORML) == sizeof(XFORM));
76c2c66affSColin Finck 
77c2c66affSColin Finck 
78c2c66affSColin Finck /* GLOBALS *******************************************************************/
79c2c66affSColin Finck 
80c2c66affSColin Finck const MATRIX gmxIdentity =
81c2c66affSColin Finck {
82c2c66affSColin Finck     FLOATOBJ_1, FLOATOBJ_0,
83c2c66affSColin Finck     FLOATOBJ_0, FLOATOBJ_1,
84c2c66affSColin Finck     FLOATOBJ_0, FLOATOBJ_0,
85c2c66affSColin Finck     0, 0, XFORM_NO_TRANSLATION|XFORM_FORMAT_LTOL|XFORM_UNITY|XFORM_SCALE
86c2c66affSColin Finck };
87c2c66affSColin Finck 
88c2c66affSColin Finck 
89c2c66affSColin Finck /* FUNCTIONS *****************************************************************/
90c2c66affSColin Finck 
91c2c66affSColin Finck VOID
92c2c66affSColin Finck FASTCALL
DC_vFixIsotropicMapping(PDC pdc)93c2c66affSColin Finck DC_vFixIsotropicMapping(PDC pdc)
94c2c66affSColin Finck {
95c2c66affSColin Finck     PDC_ATTR pdcattr;
96c2c66affSColin Finck     LONG64 fx, fy;
97c2c66affSColin Finck     LONG s;
98c2c66affSColin Finck     SIZEL szlWindowExt, szlViewportExt;
99c2c66affSColin Finck     ASSERT(pdc->pdcattr->iMapMode == MM_ISOTROPIC);
100c2c66affSColin Finck 
101c2c66affSColin Finck     /* Get a pointer to the DC_ATTR */
102c2c66affSColin Finck     pdcattr = pdc->pdcattr;
103c2c66affSColin Finck 
104c2c66affSColin Finck     /* Read the extents, we rely on non-null values */
105c2c66affSColin Finck     szlWindowExt = pdcattr->szlWindowExt;
106c2c66affSColin Finck     szlViewportExt = pdcattr->szlViewportExt;
107c2c66affSColin Finck 
108c2c66affSColin Finck     /* Check if all values are valid */
109c2c66affSColin Finck     if ((szlWindowExt.cx == 0) || (szlWindowExt.cy == 0) ||
110c2c66affSColin Finck         (szlViewportExt.cx == 0) || (szlViewportExt.cy == 0))
111c2c66affSColin Finck     {
112c2c66affSColin Finck         /* Someone put rubbish into the fields, just ignore it. */
113c2c66affSColin Finck         return;
114c2c66affSColin Finck     }
115c2c66affSColin Finck 
116c2c66affSColin Finck     fx = abs((LONG64)szlWindowExt.cx * szlViewportExt.cy);
117c2c66affSColin Finck     fy = abs((LONG64)szlWindowExt.cy * szlViewportExt.cx);
118c2c66affSColin Finck 
119c2c66affSColin Finck     if (fx < fy)
120c2c66affSColin Finck     {
121c2c66affSColin Finck         s = (szlWindowExt.cy ^ szlViewportExt.cx) > 0 ? 1 : -1;
122c2c66affSColin Finck         pdcattr->szlViewportExt.cx = (LONG)(fx * s / szlWindowExt.cy);
123c2c66affSColin Finck     }
124c2c66affSColin Finck     else if (fx > fy)
125c2c66affSColin Finck     {
126c2c66affSColin Finck         s = (szlWindowExt.cx ^ szlViewportExt.cy) > 0 ? 1 : -1;
127c2c66affSColin Finck         pdcattr->szlViewportExt.cy = (LONG)(fy * s / szlWindowExt.cx);
128c2c66affSColin Finck     }
129c2c66affSColin Finck 
130c2c66affSColin Finck     /* Reset the flag */
131c2c66affSColin Finck     pdc->pdcattr->flXform &= ~PAGE_EXTENTS_CHANGED;
132c2c66affSColin Finck }
133c2c66affSColin Finck 
134c2c66affSColin Finck VOID
135c2c66affSColin Finck FASTCALL
DC_vGetPageToDevice(PDC pdc,MATRIX * pmx)136c2c66affSColin Finck DC_vGetPageToDevice(PDC pdc, MATRIX *pmx)
137c2c66affSColin Finck {
138c2c66affSColin Finck     PDC_ATTR pdcattr = pdc->pdcattr;
139c2c66affSColin Finck     PSIZEL pszlViewPortExt;
140c2c66affSColin Finck     SIZEL szlWindowExt;
141c2c66affSColin Finck 
142c2c66affSColin Finck     /* Get the viewport extension */
143c2c66affSColin Finck     pszlViewPortExt = DC_pszlViewportExt(pdc);
144c2c66affSColin Finck 
145c2c66affSColin Finck     /* Copy the window extension, so no one can mess with it */
146c2c66affSColin Finck     szlWindowExt = pdcattr->szlWindowExt;
147c2c66affSColin Finck 
148c2c66affSColin Finck     /* No shearing / rotation */
149c2c66affSColin Finck     FLOATOBJ_SetLong(&pmx->efM12, 0);
150c2c66affSColin Finck     FLOATOBJ_SetLong(&pmx->efM21, 0);
151c2c66affSColin Finck 
152c2c66affSColin Finck     /* Calculate scaling */
153c2c66affSColin Finck     if (szlWindowExt.cx != 0)
154c2c66affSColin Finck     {
155c2c66affSColin Finck         FLOATOBJ_SetLong(&pmx->efM11, pszlViewPortExt->cx);
156c2c66affSColin Finck         FLOATOBJ_DivLong(&pmx->efM11, szlWindowExt.cx);
157c2c66affSColin Finck     }
158c2c66affSColin Finck     else
159c2c66affSColin Finck         FLOATOBJ_SetLong(&pmx->efM11, 1);
160c2c66affSColin Finck 
161c2c66affSColin Finck     if (szlWindowExt.cy != 0)
162c2c66affSColin Finck     {
163c2c66affSColin Finck         FLOATOBJ_SetLong(&pmx->efM22, pszlViewPortExt->cy);
164c2c66affSColin Finck         FLOATOBJ_DivLong(&pmx->efM22, szlWindowExt.cy);
165c2c66affSColin Finck     }
166c2c66affSColin Finck     else
167c2c66affSColin Finck         FLOATOBJ_SetLong(&pmx->efM22, 1);
168c2c66affSColin Finck 
169c2c66affSColin Finck     /* Calculate x offset */
170c2c66affSColin Finck     FLOATOBJ_SetLong(&pmx->efDx, -pdcattr->ptlWindowOrg.x);
171c2c66affSColin Finck     FLOATOBJ_Mul(&pmx->efDx, &pmx->efM11);
172c2c66affSColin Finck     FLOATOBJ_AddLong(&pmx->efDx, pdcattr->ptlViewportOrg.x);
173c2c66affSColin Finck 
174c2c66affSColin Finck     /* Calculate y offset */
175c2c66affSColin Finck     FLOATOBJ_SetLong(&pmx->efDy, -pdcattr->ptlWindowOrg.y);
176c2c66affSColin Finck     FLOATOBJ_Mul(&pmx->efDy, &pmx->efM22);
177c2c66affSColin Finck     FLOATOBJ_AddLong(&pmx->efDy, pdcattr->ptlViewportOrg.y);
178c2c66affSColin Finck }
179c2c66affSColin Finck 
180c2c66affSColin Finck VOID
181c2c66affSColin Finck FASTCALL
DC_vUpdateWorldToDevice(PDC pdc)182c2c66affSColin Finck DC_vUpdateWorldToDevice(PDC pdc)
183c2c66affSColin Finck {
184c2c66affSColin Finck     XFORMOBJ xoPageToDevice, xoWorldToPage, xoWorldToDevice;
185c2c66affSColin Finck     MATRIX mxPageToDevice;
186c2c66affSColin Finck 
187c2c66affSColin Finck     // FIXME: make sure world-to-page is valid!
188c2c66affSColin Finck 
189c2c66affSColin Finck     /* Construct a transformation to do the page-to-device conversion */
190c2c66affSColin Finck     DC_vGetPageToDevice(pdc, &mxPageToDevice);
191c2c66affSColin Finck     XFORMOBJ_vInit(&xoPageToDevice, &mxPageToDevice);
192c2c66affSColin Finck 
193c2c66affSColin Finck     /* Recalculate the world-to-device xform */
194c2c66affSColin Finck     XFORMOBJ_vInit(&xoWorldToPage, &pdc->pdcattr->mxWorldToPage);
195c2c66affSColin Finck     XFORMOBJ_vInit(&xoWorldToDevice, &pdc->pdcattr->mxWorldToDevice);
196c2c66affSColin Finck     XFORMOBJ_iCombine(&xoWorldToDevice, &xoWorldToPage, &xoPageToDevice);
197c2c66affSColin Finck 
198c2c66affSColin Finck     /* Reset the flags */
1998bdfdd5cSKatayama Hirofumi MZ     pdc->pdcattr->flXform &= ~WORLD_XFORM_CHANGED;
200c2c66affSColin Finck }
201c2c66affSColin Finck 
202c2c66affSColin Finck VOID
203c2c66affSColin Finck FASTCALL
DC_vUpdateDeviceToWorld(PDC pdc)204c2c66affSColin Finck DC_vUpdateDeviceToWorld(PDC pdc)
205c2c66affSColin Finck {
206c2c66affSColin Finck     XFORMOBJ xoWorldToDevice, xoDeviceToWorld;
207c2c66affSColin Finck     PMATRIX pmxWorldToDevice;
208c2c66affSColin Finck 
209c2c66affSColin Finck     /* Get the world-to-device translation */
210c2c66affSColin Finck     pmxWorldToDevice = DC_pmxWorldToDevice(pdc);
211c2c66affSColin Finck     XFORMOBJ_vInit(&xoWorldToDevice, pmxWorldToDevice);
212c2c66affSColin Finck 
213c2c66affSColin Finck     /* Create inverse of world-to-device transformation */
214c2c66affSColin Finck     XFORMOBJ_vInit(&xoDeviceToWorld, &pdc->pdcattr->mxDeviceToWorld);
215c2c66affSColin Finck     if (XFORMOBJ_iInverse(&xoDeviceToWorld, &xoWorldToDevice) == DDI_ERROR)
216c2c66affSColin Finck     {
2178bdfdd5cSKatayama Hirofumi MZ         MX_Set0(&pdc->pdcattr->mxDeviceToWorld);
218c2c66affSColin Finck         return;
219c2c66affSColin Finck     }
220c2c66affSColin Finck 
221c2c66affSColin Finck     /* Reset the flag */
222c2c66affSColin Finck     pdc->pdcattr->flXform &= ~DEVICE_TO_WORLD_INVALID;
223c2c66affSColin Finck }
224c2c66affSColin Finck 
225c2c66affSColin Finck BOOL
226c2c66affSColin Finck NTAPI
GreCombineTransform(XFORML * pxformDest,XFORML * pxform1,XFORML * pxform2)227c2c66affSColin Finck GreCombineTransform(
228c2c66affSColin Finck     XFORML *pxformDest,
229c2c66affSColin Finck     XFORML *pxform1,
230c2c66affSColin Finck     XFORML *pxform2)
231c2c66affSColin Finck {
232c2c66affSColin Finck     MATRIX mxDest, mx1, mx2;
233c2c66affSColin Finck     XFORMOBJ xoDest, xo1, xo2;
234c2c66affSColin Finck 
235c2c66affSColin Finck     /* Check for illegal parameters */
236c2c66affSColin Finck     if (!pxformDest || !pxform1 || !pxform2) return FALSE;
237c2c66affSColin Finck 
238c2c66affSColin Finck     /* Initialize XFORMOBJs */
239c2c66affSColin Finck     XFORMOBJ_vInit(&xoDest, &mxDest);
240c2c66affSColin Finck     XFORMOBJ_vInit(&xo1, &mx1);
241c2c66affSColin Finck     XFORMOBJ_vInit(&xo2, &mx2);
242c2c66affSColin Finck 
243c2c66affSColin Finck     /* Convert the XFORMLs into XFORMOBJs */
244c2c66affSColin Finck     XFORMOBJ_iSetXform(&xo1, pxform1);
245c2c66affSColin Finck     XFORMOBJ_iSetXform(&xo2, pxform2);
246c2c66affSColin Finck 
247c2c66affSColin Finck     /* Combine them */
248c2c66affSColin Finck     XFORMOBJ_iCombine(&xoDest, &xo1, &xo2);
249c2c66affSColin Finck 
250c2c66affSColin Finck     /* Translate back into XFORML */
251c2c66affSColin Finck     XFORMOBJ_iGetXform(&xoDest, pxformDest);
252c2c66affSColin Finck 
253c2c66affSColin Finck     return TRUE;
254c2c66affSColin Finck }
255c2c66affSColin Finck 
256c2c66affSColin Finck BOOL
257c2c66affSColin Finck APIENTRY
NtGdiCombineTransform(LPXFORM UnsafeXFormResult,LPXFORM Unsafexform1,LPXFORM Unsafexform2)258c2c66affSColin Finck NtGdiCombineTransform(
259c2c66affSColin Finck     LPXFORM UnsafeXFormResult,
260c2c66affSColin Finck     LPXFORM Unsafexform1,
261c2c66affSColin Finck     LPXFORM Unsafexform2)
262c2c66affSColin Finck {
263c2c66affSColin Finck     BOOL Ret;
264c2c66affSColin Finck 
265c2c66affSColin Finck     _SEH2_TRY
266c2c66affSColin Finck     {
267c2c66affSColin Finck         ProbeForWrite(UnsafeXFormResult, sizeof(XFORM), 1);
268c2c66affSColin Finck         ProbeForRead(Unsafexform1, sizeof(XFORM), 1);
269c2c66affSColin Finck         ProbeForRead(Unsafexform2, sizeof(XFORM), 1);
270c2c66affSColin Finck         Ret = GreCombineTransform((XFORML*)UnsafeXFormResult,
271c2c66affSColin Finck                                   (XFORML*)Unsafexform1,
272c2c66affSColin Finck                                   (XFORML*)Unsafexform2);
273c2c66affSColin Finck     }
274c2c66affSColin Finck     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
275c2c66affSColin Finck     {
276c2c66affSColin Finck         Ret = FALSE;
277c2c66affSColin Finck     }
278c2c66affSColin Finck     _SEH2_END;
279c2c66affSColin Finck 
280c2c66affSColin Finck     return Ret;
281c2c66affSColin Finck }
282c2c66affSColin Finck 
283c2c66affSColin Finck // FIXME: Should be XFORML and use XFORMOBJ functions directly
284c2c66affSColin Finck BOOL
285c2c66affSColin Finck APIENTRY
NtGdiGetTransform(HDC hdc,DWORD iXform,LPXFORM pXForm)286c2c66affSColin Finck NtGdiGetTransform(
287c2c66affSColin Finck     HDC hdc,
288c2c66affSColin Finck     DWORD iXform,
289c2c66affSColin Finck     LPXFORM pXForm)
290c2c66affSColin Finck {
291c2c66affSColin Finck     PDC pdc;
292c2c66affSColin Finck     BOOL ret = TRUE;
293c2c66affSColin Finck     MATRIX mxPageToDevice;
294c2c66affSColin Finck     XFORMOBJ xo;
295c2c66affSColin Finck     PMATRIX pmx;
296c2c66affSColin Finck 
297c2c66affSColin Finck     if (!pXForm)
298c2c66affSColin Finck     {
299c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_PARAMETER);
300c2c66affSColin Finck         return FALSE;
301c2c66affSColin Finck     }
302c2c66affSColin Finck 
303c2c66affSColin Finck     pdc = DC_LockDc(hdc);
304c2c66affSColin Finck     if (!pdc)
305c2c66affSColin Finck     {
306c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_HANDLE);
307c2c66affSColin Finck         return FALSE;
308c2c66affSColin Finck     }
309c2c66affSColin Finck 
310c2c66affSColin Finck     switch (iXform)
311c2c66affSColin Finck     {
312c2c66affSColin Finck         case GdiWorldSpaceToPageSpace:
313c2c66affSColin Finck             pmx = DC_pmxWorldToPage(pdc);
314c2c66affSColin Finck             break;
315c2c66affSColin Finck 
316c2c66affSColin Finck         case GdiWorldSpaceToDeviceSpace:
317c2c66affSColin Finck             pmx = DC_pmxWorldToDevice(pdc);
318c2c66affSColin Finck             break;
319c2c66affSColin Finck 
320c2c66affSColin Finck         case GdiDeviceSpaceToWorldSpace:
321c2c66affSColin Finck             pmx = DC_pmxDeviceToWorld(pdc);
322c2c66affSColin Finck             break;
323c2c66affSColin Finck 
324c2c66affSColin Finck         case GdiPageSpaceToDeviceSpace:
325c2c66affSColin Finck             DC_vGetPageToDevice(pdc, &mxPageToDevice);
326c2c66affSColin Finck             pmx = &mxPageToDevice;
327c2c66affSColin Finck             break;
328c2c66affSColin Finck 
329c2c66affSColin Finck         default:
330c2c66affSColin Finck             DPRINT1("Unknown transform %lu\n", iXform);
331c2c66affSColin Finck             ret = FALSE;
332c2c66affSColin Finck             goto leave;
333c2c66affSColin Finck     }
334c2c66affSColin Finck 
335c2c66affSColin Finck     /* Initialize an XFORMOBJ */
336c2c66affSColin Finck     XFORMOBJ_vInit(&xo, pmx);
337c2c66affSColin Finck 
338c2c66affSColin Finck     _SEH2_TRY
339c2c66affSColin Finck     {
340c2c66affSColin Finck         ProbeForWrite(pXForm, sizeof(XFORML), 1);
341c2c66affSColin Finck         XFORMOBJ_iGetXform(&xo, (XFORML*)pXForm);
342c2c66affSColin Finck     }
343c2c66affSColin Finck     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
344c2c66affSColin Finck     {
345c2c66affSColin Finck         ret = FALSE;
346c2c66affSColin Finck     }
347c2c66affSColin Finck     _SEH2_END;
348c2c66affSColin Finck 
349c2c66affSColin Finck leave:
350c2c66affSColin Finck     DC_UnlockDc(pdc);
351c2c66affSColin Finck     return ret;
352c2c66affSColin Finck }
353c2c66affSColin Finck 
354c2c66affSColin Finck 
355c2c66affSColin Finck /*!
356c2c66affSColin Finck  * Converts points from logical coordinates into device coordinates.
357c2c66affSColin Finck  * Conversion depends on the mapping mode,
358c2c66affSColin Finck  * world transfrom, viewport origin settings for the given device context.
359c2c66affSColin Finck  * \param	hDC		device context.
360c2c66affSColin Finck  * \param	Points	an array of POINT structures (in/out).
361c2c66affSColin Finck  * \param	Count	number of elements in the array of POINT structures.
362c2c66affSColin Finck  * \return  TRUE if success, FALSE otherwise.
363c2c66affSColin Finck */
364c2c66affSColin Finck BOOL
365c2c66affSColin Finck APIENTRY
NtGdiTransformPoints(HDC hDC,PPOINT UnsafePtsIn,PPOINT UnsafePtOut,INT Count,INT iMode)366c2c66affSColin Finck NtGdiTransformPoints(
367c2c66affSColin Finck     HDC hDC,
368c2c66affSColin Finck     PPOINT UnsafePtsIn,
369c2c66affSColin Finck     PPOINT UnsafePtOut,
370c2c66affSColin Finck     INT Count,
371c2c66affSColin Finck     INT iMode)
372c2c66affSColin Finck {
373c2c66affSColin Finck     PDC pdc;
374c2c66affSColin Finck     LPPOINT Points;
375c2c66affSColin Finck     ULONG Size;
376c2c66affSColin Finck     BOOL ret = TRUE;
377c2c66affSColin Finck 
378c2c66affSColin Finck     if (Count <= 0)
379c2c66affSColin Finck         return TRUE;
380c2c66affSColin Finck 
3818bdfdd5cSKatayama Hirofumi MZ     if (!UnsafePtsIn || !UnsafePtOut)
3828bdfdd5cSKatayama Hirofumi MZ     {
3838bdfdd5cSKatayama Hirofumi MZ         return FALSE;
3848bdfdd5cSKatayama Hirofumi MZ     }
3858bdfdd5cSKatayama Hirofumi MZ 
386c2c66affSColin Finck     pdc = DC_LockDc(hDC);
387c2c66affSColin Finck     if (!pdc)
388c2c66affSColin Finck     {
389c2c66affSColin Finck         return FALSE;
390c2c66affSColin Finck     }
391c2c66affSColin Finck 
392c2c66affSColin Finck     Size = Count * sizeof(POINT);
393c2c66affSColin Finck 
394c2c66affSColin Finck     // FIXME: It would be wise to have a small stack buffer as optimization
395c2c66affSColin Finck     Points = ExAllocatePoolWithTag(PagedPool, Size, GDITAG_TEMP);
396c2c66affSColin Finck     if (!Points)
397c2c66affSColin Finck     {
398c2c66affSColin Finck         DC_UnlockDc(pdc);
399c2c66affSColin Finck         EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
400c2c66affSColin Finck         return FALSE;
401c2c66affSColin Finck     }
402c2c66affSColin Finck 
403c2c66affSColin Finck     _SEH2_TRY
404c2c66affSColin Finck     {
405c2c66affSColin Finck         ProbeForWrite(UnsafePtOut, Size, 1);
406c2c66affSColin Finck         ProbeForRead(UnsafePtsIn, Size, 1);
407c2c66affSColin Finck         RtlCopyMemory(Points, UnsafePtsIn, Size);
408c2c66affSColin Finck     }
409c2c66affSColin Finck     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
410c2c66affSColin Finck     {
411c2c66affSColin Finck         /* Do not set last error */
412c2c66affSColin Finck         _SEH2_YIELD(goto leave;)
413c2c66affSColin Finck     }
414c2c66affSColin Finck     _SEH2_END;
415c2c66affSColin Finck 
416c2c66affSColin Finck     switch (iMode)
417c2c66affSColin Finck     {
418c2c66affSColin Finck         case GdiDpToLp:
419*405ce532SJérôme Gardou             ret = INTERNAL_APPLY_MATRIX(DC_pmxDeviceToWorld(pdc), Points, Count);
420c2c66affSColin Finck             break;
421c2c66affSColin Finck 
422c2c66affSColin Finck         case GdiLpToDp:
423*405ce532SJérôme Gardou             ret = INTERNAL_APPLY_MATRIX(DC_pmxWorldToDevice(pdc), Points, Count);
424c2c66affSColin Finck             break;
425c2c66affSColin Finck 
426c2c66affSColin Finck         case 2: // Not supported yet. Need testing.
427c2c66affSColin Finck         default:
428c2c66affSColin Finck         {
429c2c66affSColin Finck             EngSetLastError(ERROR_INVALID_PARAMETER);
430c2c66affSColin Finck             ret = FALSE;
431c2c66affSColin Finck             goto leave;
432c2c66affSColin Finck         }
433c2c66affSColin Finck     }
434c2c66affSColin Finck 
435*405ce532SJérôme Gardou     if (ret)
436*405ce532SJérôme Gardou     {
437c2c66affSColin Finck         _SEH2_TRY
438c2c66affSColin Finck         {
439c2c66affSColin Finck             /* Pointer was already probed! */
440c2c66affSColin Finck             RtlCopyMemory(UnsafePtOut, Points, Size);
441c2c66affSColin Finck         }
442c2c66affSColin Finck         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
443c2c66affSColin Finck         {
444c2c66affSColin Finck             /* Do not set last error */
445*405ce532SJérôme Gardou             ret = FALSE;
446c2c66affSColin Finck         }
447c2c66affSColin Finck         _SEH2_END;
448*405ce532SJérôme Gardou     }
449c2c66affSColin Finck 
450c2c66affSColin Finck //
451c2c66affSColin Finck // If we are getting called that means User XForms is a mess!
452c2c66affSColin Finck //
453c2c66affSColin Finck leave:
454c2c66affSColin Finck     DC_UnlockDc(pdc);
455c2c66affSColin Finck     ExFreePoolWithTag(Points, GDITAG_TEMP);
456c2c66affSColin Finck     return ret;
457c2c66affSColin Finck }
458c2c66affSColin Finck 
459c2c66affSColin Finck BOOL
460c2c66affSColin Finck NTAPI
GreModifyWorldTransform(PDC pdc,const XFORML * pxform,DWORD dwMode)461c2c66affSColin Finck GreModifyWorldTransform(
462c2c66affSColin Finck     PDC pdc,
463c2c66affSColin Finck     const XFORML *pxform,
464c2c66affSColin Finck     DWORD dwMode)
465c2c66affSColin Finck {
466c2c66affSColin Finck     MATRIX mxSrc;
467c2c66affSColin Finck     XFORMOBJ xoSrc, xoDC;
468c2c66affSColin Finck 
469c2c66affSColin Finck     switch (dwMode)
470c2c66affSColin Finck     {
471c2c66affSColin Finck         case MWT_IDENTITY:
472c2c66affSColin Finck             pdc->pdcattr->mxWorldToPage = gmxIdentity;
473c2c66affSColin Finck             break;
474c2c66affSColin Finck 
475c2c66affSColin Finck         case MWT_LEFTMULTIPLY:
476c2c66affSColin Finck             XFORMOBJ_vInit(&xoDC, &pdc->pdcattr->mxWorldToPage);
477c2c66affSColin Finck             XFORMOBJ_vInit(&xoSrc, &mxSrc);
478c2c66affSColin Finck             if (XFORMOBJ_iSetXform(&xoSrc, pxform) == DDI_ERROR)
479c2c66affSColin Finck                 return FALSE;
480c2c66affSColin Finck             XFORMOBJ_iCombine(&xoDC, &xoSrc, &xoDC);
481c2c66affSColin Finck             break;
482c2c66affSColin Finck 
483c2c66affSColin Finck         case MWT_RIGHTMULTIPLY:
484c2c66affSColin Finck             XFORMOBJ_vInit(&xoDC, &pdc->pdcattr->mxWorldToPage);
485c2c66affSColin Finck             XFORMOBJ_vInit(&xoSrc, &mxSrc);
486c2c66affSColin Finck             if (XFORMOBJ_iSetXform(&xoSrc, pxform) == DDI_ERROR)
487c2c66affSColin Finck                 return FALSE;
488c2c66affSColin Finck             XFORMOBJ_iCombine(&xoDC, &xoDC, &xoSrc);
489c2c66affSColin Finck             break;
490c2c66affSColin Finck 
491d85023c9Sjimtabor         case MWT_SET:
492c2c66affSColin Finck             XFORMOBJ_vInit(&xoDC, &pdc->pdcattr->mxWorldToPage);
493c2c66affSColin Finck             if (XFORMOBJ_iSetXform(&xoDC, pxform) == DDI_ERROR)
494c2c66affSColin Finck                 return FALSE;
495c2c66affSColin Finck             break;
496c2c66affSColin Finck 
497c2c66affSColin Finck         default:
498c2c66affSColin Finck             return FALSE;
499c2c66affSColin Finck     }
500c2c66affSColin Finck 
501c2c66affSColin Finck     /*Set invalidation flags */
502c2c66affSColin Finck     pdc->pdcattr->flXform |= WORLD_XFORM_CHANGED|DEVICE_TO_WORLD_INVALID;
503c2c66affSColin Finck 
504c2c66affSColin Finck     return TRUE;
505c2c66affSColin Finck }
506c2c66affSColin Finck 
507c2c66affSColin Finck BOOL
508c2c66affSColin Finck APIENTRY
NtGdiModifyWorldTransform(HDC hdc,LPXFORM pxformUnsafe,DWORD dwMode)509c2c66affSColin Finck NtGdiModifyWorldTransform(
510c2c66affSColin Finck     HDC hdc,
511c2c66affSColin Finck     LPXFORM pxformUnsafe,
512c2c66affSColin Finck     DWORD dwMode)
513c2c66affSColin Finck {
514c2c66affSColin Finck     PDC pdc;
515c2c66affSColin Finck     XFORML xformSafe;
516c2c66affSColin Finck     BOOL Ret = TRUE;
517c2c66affSColin Finck 
518c2c66affSColin Finck     pdc = DC_LockDc(hdc);
519c2c66affSColin Finck     if (!pdc)
520c2c66affSColin Finck     {
521c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_HANDLE);
522c2c66affSColin Finck         return FALSE;
523c2c66affSColin Finck     }
524c2c66affSColin Finck 
525c2c66affSColin Finck     /* The xform is permitted to be NULL for MWT_IDENTITY.
526c2c66affSColin Finck      * However, if it is not NULL, then it must be valid even
527c2c66affSColin Finck      * though it is not used. */
528c2c66affSColin Finck     if ((dwMode != MWT_IDENTITY) && (pxformUnsafe == NULL))
529c2c66affSColin Finck     {
530c2c66affSColin Finck         DC_UnlockDc(pdc);
531c2c66affSColin Finck         return FALSE;
532c2c66affSColin Finck     }
533c2c66affSColin Finck 
534c2c66affSColin Finck     if (pxformUnsafe != NULL)
535c2c66affSColin Finck     {
536c2c66affSColin Finck         _SEH2_TRY
537c2c66affSColin Finck         {
538c2c66affSColin Finck             ProbeForRead(pxformUnsafe, sizeof(XFORML), 1);
539c2c66affSColin Finck             RtlCopyMemory(&xformSafe, pxformUnsafe, sizeof(XFORML));
540c2c66affSColin Finck         }
541c2c66affSColin Finck         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
542c2c66affSColin Finck         {
543c2c66affSColin Finck             Ret = FALSE;
544c2c66affSColin Finck         }
545c2c66affSColin Finck         _SEH2_END;
546c2c66affSColin Finck     }
547c2c66affSColin Finck 
548c2c66affSColin Finck     /* Safe to handle kernel mode data. */
549c2c66affSColin Finck     if (Ret) Ret = GreModifyWorldTransform(pdc, &xformSafe, dwMode);
550c2c66affSColin Finck     DC_UnlockDc(pdc);
551c2c66affSColin Finck     return Ret;
552c2c66affSColin Finck }
553c2c66affSColin Finck 
554c2c66affSColin Finck BOOL
555c2c66affSColin Finck APIENTRY
NtGdiOffsetViewportOrgEx(HDC hDC,int XOffset,int YOffset,LPPOINT UnsafePoint)556c2c66affSColin Finck NtGdiOffsetViewportOrgEx(
557c2c66affSColin Finck     HDC hDC,
558c2c66affSColin Finck     int XOffset,
559c2c66affSColin Finck     int YOffset,
560c2c66affSColin Finck     LPPOINT UnsafePoint)
561c2c66affSColin Finck {
562c2c66affSColin Finck     PDC      dc;
563c2c66affSColin Finck     PDC_ATTR pdcattr;
564c2c66affSColin Finck     NTSTATUS Status = STATUS_SUCCESS;
565c2c66affSColin Finck 
566c2c66affSColin Finck     dc = DC_LockDc(hDC);
567c2c66affSColin Finck     if (!dc)
568c2c66affSColin Finck     {
569c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_HANDLE);
570c2c66affSColin Finck         return FALSE;
571c2c66affSColin Finck     }
572c2c66affSColin Finck     pdcattr = dc->pdcattr;
573c2c66affSColin Finck 
574c2c66affSColin Finck     if (UnsafePoint)
575c2c66affSColin Finck     {
576c2c66affSColin Finck         _SEH2_TRY
577c2c66affSColin Finck         {
578c2c66affSColin Finck             ProbeForWrite(UnsafePoint, sizeof(POINT), 1);
579c2c66affSColin Finck             UnsafePoint->x = pdcattr->ptlViewportOrg.x;
580c2c66affSColin Finck             UnsafePoint->y = pdcattr->ptlViewportOrg.y;
581c2c66affSColin Finck             if (pdcattr->dwLayout & LAYOUT_RTL)
582c2c66affSColin Finck             {
583c2c66affSColin Finck                 UnsafePoint->x = -UnsafePoint->x;
584c2c66affSColin Finck             }
585c2c66affSColin Finck         }
586c2c66affSColin Finck         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
587c2c66affSColin Finck         {
588c2c66affSColin Finck             Status = _SEH2_GetExceptionCode();
589c2c66affSColin Finck         }
590c2c66affSColin Finck         _SEH2_END;
591c2c66affSColin Finck 
592c2c66affSColin Finck         if (!NT_SUCCESS(Status))
593c2c66affSColin Finck         {
594c2c66affSColin Finck             SetLastNtError(Status);
595c2c66affSColin Finck             DC_UnlockDc(dc);
596c2c66affSColin Finck             return FALSE;
597c2c66affSColin Finck         }
598c2c66affSColin Finck     }
599c2c66affSColin Finck 
600c2c66affSColin Finck     if (pdcattr->dwLayout & LAYOUT_RTL)
601c2c66affSColin Finck     {
602c2c66affSColin Finck         XOffset = -XOffset;
603c2c66affSColin Finck     }
604c2c66affSColin Finck     pdcattr->ptlViewportOrg.x += XOffset;
605c2c66affSColin Finck     pdcattr->ptlViewportOrg.y += YOffset;
606f7bc0543SKatayama Hirofumi MZ     pdcattr->flXform |= PAGE_XLATE_CHANGED | WORLD_XFORM_CHANGED | DEVICE_TO_WORLD_INVALID;
607c2c66affSColin Finck 
608c2c66affSColin Finck     DC_UnlockDc(dc);
609c2c66affSColin Finck 
610c2c66affSColin Finck     return TRUE;
611c2c66affSColin Finck }
612c2c66affSColin Finck 
613c2c66affSColin Finck BOOL
614c2c66affSColin Finck APIENTRY
NtGdiOffsetWindowOrgEx(HDC hDC,int XOffset,int YOffset,LPPOINT Point)615c2c66affSColin Finck NtGdiOffsetWindowOrgEx(
616c2c66affSColin Finck     HDC hDC,
617c2c66affSColin Finck     int XOffset,
618c2c66affSColin Finck     int YOffset,
619c2c66affSColin Finck     LPPOINT Point)
620c2c66affSColin Finck {
621c2c66affSColin Finck     PDC dc;
622c2c66affSColin Finck     PDC_ATTR pdcattr;
623c2c66affSColin Finck 
624c2c66affSColin Finck     dc = DC_LockDc(hDC);
625c2c66affSColin Finck     if (!dc)
626c2c66affSColin Finck     {
627c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_HANDLE);
628c2c66affSColin Finck         return FALSE;
629c2c66affSColin Finck     }
630c2c66affSColin Finck     pdcattr = dc->pdcattr;
631c2c66affSColin Finck 
632c2c66affSColin Finck     if (Point)
633c2c66affSColin Finck     {
634c2c66affSColin Finck         NTSTATUS Status = STATUS_SUCCESS;
635c2c66affSColin Finck 
636c2c66affSColin Finck         _SEH2_TRY
637c2c66affSColin Finck         {
638c2c66affSColin Finck             ProbeForWrite(Point, sizeof(POINT), 1);
639c2c66affSColin Finck             Point->x = pdcattr->ptlWindowOrg.x;
640c2c66affSColin Finck             Point->y = pdcattr->ptlWindowOrg.y;
641c2c66affSColin Finck         }
642c2c66affSColin Finck         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
643c2c66affSColin Finck         {
644c2c66affSColin Finck             Status = _SEH2_GetExceptionCode();
645c2c66affSColin Finck         }
646c2c66affSColin Finck         _SEH2_END;
647c2c66affSColin Finck 
648c2c66affSColin Finck         if (!NT_SUCCESS(Status))
649c2c66affSColin Finck         {
650c2c66affSColin Finck             SetLastNtError(Status);
651c2c66affSColin Finck             DC_UnlockDc(dc);
652c2c66affSColin Finck             return FALSE;
653c2c66affSColin Finck         }
654c2c66affSColin Finck     }
655c2c66affSColin Finck 
656c2c66affSColin Finck     pdcattr->ptlWindowOrg.x += XOffset;
657c2c66affSColin Finck     pdcattr->ptlWindowOrg.y += YOffset;
658f7bc0543SKatayama Hirofumi MZ     pdcattr->flXform |= PAGE_XLATE_CHANGED | WORLD_XFORM_CHANGED | DEVICE_TO_WORLD_INVALID;
659c2c66affSColin Finck 
660c2c66affSColin Finck     DC_UnlockDc(dc);
661c2c66affSColin Finck 
662c2c66affSColin Finck     return TRUE;
663c2c66affSColin Finck }
664c2c66affSColin Finck 
665c2c66affSColin Finck BOOL
666c2c66affSColin Finck APIENTRY
NtGdiScaleViewportExtEx(HDC hDC,int Xnum,int Xdenom,int Ynum,int Ydenom,LPSIZE pSize)667c2c66affSColin Finck NtGdiScaleViewportExtEx(
668c2c66affSColin Finck     HDC hDC,
669c2c66affSColin Finck     int Xnum,
670c2c66affSColin Finck     int Xdenom,
671c2c66affSColin Finck     int Ynum,
672c2c66affSColin Finck     int Ydenom,
673c2c66affSColin Finck     LPSIZE pSize)
674c2c66affSColin Finck {
675c2c66affSColin Finck     PDC pDC;
676c2c66affSColin Finck     PDC_ATTR pdcattr;
677c2c66affSColin Finck     BOOL Ret = FALSE;
678c2c66affSColin Finck     LONG X, Y;
679c2c66affSColin Finck 
680c2c66affSColin Finck     pDC = DC_LockDc(hDC);
681c2c66affSColin Finck     if (!pDC)
682c2c66affSColin Finck     {
683c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_HANDLE);
684c2c66affSColin Finck         return FALSE;
685c2c66affSColin Finck     }
686c2c66affSColin Finck     pdcattr = pDC->pdcattr;
687c2c66affSColin Finck 
688c2c66affSColin Finck     if (pdcattr->iMapMode > MM_TWIPS)
689c2c66affSColin Finck     {
690c2c66affSColin Finck         if (Xdenom && Ydenom)
691c2c66affSColin Finck         {
692c2c66affSColin Finck             DC_pszlViewportExt(pDC);
693c2c66affSColin Finck             X = Xnum * pdcattr->szlViewportExt.cx / Xdenom;
694c2c66affSColin Finck             if (X)
695c2c66affSColin Finck             {
696c2c66affSColin Finck                 Y = Ynum * pdcattr->szlViewportExt.cy / Ydenom;
697c2c66affSColin Finck                 if (Y)
698c2c66affSColin Finck                 {
699c2c66affSColin Finck                     pdcattr->szlViewportExt.cx = X;
700c2c66affSColin Finck                     pdcattr->szlViewportExt.cy = Y;
701c2c66affSColin Finck                     pdcattr->flXform |= PAGE_XLATE_CHANGED;
702c2c66affSColin Finck 
703c2c66affSColin Finck                     IntMirrorWindowOrg(pDC);
704c2c66affSColin Finck 
705c2c66affSColin Finck                     pdcattr->flXform |= (PAGE_EXTENTS_CHANGED |
706c2c66affSColin Finck                                          INVALIDATE_ATTRIBUTES |
707f7bc0543SKatayama Hirofumi MZ                                          WORLD_XFORM_CHANGED |
708c2c66affSColin Finck                                          DEVICE_TO_WORLD_INVALID);
709c2c66affSColin Finck 
710c2c66affSColin Finck                     if (pdcattr->iMapMode == MM_ISOTROPIC)
711c2c66affSColin Finck                     {
712c2c66affSColin Finck                         DC_vFixIsotropicMapping(pDC);
713c2c66affSColin Finck                     }
714c2c66affSColin Finck 
715c2c66affSColin Finck                     Ret = TRUE;
716c2c66affSColin Finck                 }
717c2c66affSColin Finck             }
718c2c66affSColin Finck         }
719c2c66affSColin Finck     }
720c2c66affSColin Finck     else
721c2c66affSColin Finck         Ret = TRUE;
722c2c66affSColin Finck 
723c2c66affSColin Finck     if (pSize)
724c2c66affSColin Finck     {
725c2c66affSColin Finck         _SEH2_TRY
726c2c66affSColin Finck         {
727c2c66affSColin Finck             ProbeForWrite(pSize, sizeof(SIZE), 1);
728c2c66affSColin Finck 
729c2c66affSColin Finck             pSize->cx = pdcattr->szlViewportExt.cx;
730c2c66affSColin Finck             pSize->cy = pdcattr->szlViewportExt.cy;
731c2c66affSColin Finck         }
732c2c66affSColin Finck         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
733c2c66affSColin Finck         {
734c2c66affSColin Finck             SetLastNtError(_SEH2_GetExceptionCode());
735c2c66affSColin Finck             Ret = FALSE;
736c2c66affSColin Finck         }
737c2c66affSColin Finck         _SEH2_END;
738c2c66affSColin Finck     }
739c2c66affSColin Finck 
740c2c66affSColin Finck     DC_UnlockDc(pDC);
741c2c66affSColin Finck     return Ret;
742c2c66affSColin Finck }
743c2c66affSColin Finck 
744c2c66affSColin Finck BOOL
745c2c66affSColin Finck APIENTRY
NtGdiScaleWindowExtEx(HDC hDC,int Xnum,int Xdenom,int Ynum,int Ydenom,LPSIZE pSize)746c2c66affSColin Finck NtGdiScaleWindowExtEx(
747c2c66affSColin Finck     HDC hDC,
748c2c66affSColin Finck     int Xnum,
749c2c66affSColin Finck     int Xdenom,
750c2c66affSColin Finck     int Ynum,
751c2c66affSColin Finck     int Ydenom,
752c2c66affSColin Finck     LPSIZE pSize)
753c2c66affSColin Finck {
754c2c66affSColin Finck     PDC pDC;
755c2c66affSColin Finck     PDC_ATTR pdcattr;
756c2c66affSColin Finck     BOOL Ret = FALSE;
757c2c66affSColin Finck     LONG X, Y;
758c2c66affSColin Finck 
759c2c66affSColin Finck     pDC = DC_LockDc(hDC);
760c2c66affSColin Finck     if (!pDC)
761c2c66affSColin Finck     {
762c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_HANDLE);
763c2c66affSColin Finck         return FALSE;
764c2c66affSColin Finck     }
765c2c66affSColin Finck     pdcattr = pDC->pdcattr;
766c2c66affSColin Finck 
767c2c66affSColin Finck     if (pSize)
768c2c66affSColin Finck     {
769c2c66affSColin Finck         NTSTATUS Status = STATUS_SUCCESS;
770c2c66affSColin Finck 
771c2c66affSColin Finck         _SEH2_TRY
772c2c66affSColin Finck         {
773c2c66affSColin Finck             ProbeForWrite(pSize, sizeof(SIZE), 1);
774c2c66affSColin Finck 
775c2c66affSColin Finck             X = pdcattr->szlWindowExt.cx;
776c2c66affSColin Finck             if (pdcattr->dwLayout & LAYOUT_RTL) X = -X;
777c2c66affSColin Finck             pSize->cx = X;
778c2c66affSColin Finck             pSize->cy = pdcattr->szlWindowExt.cy;
779c2c66affSColin Finck         }
780c2c66affSColin Finck         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
781c2c66affSColin Finck         {
782c2c66affSColin Finck             Status = _SEH2_GetExceptionCode();
783c2c66affSColin Finck         }
784c2c66affSColin Finck         _SEH2_END;
785c2c66affSColin Finck 
786c2c66affSColin Finck         if (!NT_SUCCESS(Status))
787c2c66affSColin Finck         {
788c2c66affSColin Finck             SetLastNtError(Status);
789c2c66affSColin Finck             DC_UnlockDc(pDC);
790c2c66affSColin Finck             return FALSE;
791c2c66affSColin Finck         }
792c2c66affSColin Finck     }
793c2c66affSColin Finck 
794c2c66affSColin Finck     if (pdcattr->iMapMode > MM_TWIPS)
795c2c66affSColin Finck     {
796c2c66affSColin Finck         if (Xdenom && Ydenom)
797c2c66affSColin Finck         {
798c2c66affSColin Finck             X = Xnum * pdcattr->szlWindowExt.cx / Xdenom;
799c2c66affSColin Finck             if (X)
800c2c66affSColin Finck             {
801c2c66affSColin Finck                 Y = Ynum * pdcattr->szlWindowExt.cy / Ydenom;
802c2c66affSColin Finck                 if (Y)
803c2c66affSColin Finck                 {
804c2c66affSColin Finck                     pdcattr->szlWindowExt.cx = X;
805c2c66affSColin Finck                     pdcattr->szlWindowExt.cy = Y;
806c2c66affSColin Finck 
807c2c66affSColin Finck                     IntMirrorWindowOrg(pDC);
808c2c66affSColin Finck 
809f7bc0543SKatayama Hirofumi MZ                     pdcattr->flXform |= (PAGE_EXTENTS_CHANGED |
810f7bc0543SKatayama Hirofumi MZ                                          INVALIDATE_ATTRIBUTES |
811f7bc0543SKatayama Hirofumi MZ                                          WORLD_XFORM_CHANGED |
812f7bc0543SKatayama Hirofumi MZ                                          DEVICE_TO_WORLD_INVALID);
813c2c66affSColin Finck 
814c2c66affSColin Finck                     Ret = TRUE;
815c2c66affSColin Finck                 }
816c2c66affSColin Finck             }
817c2c66affSColin Finck         }
818c2c66affSColin Finck     }
819c2c66affSColin Finck     else
820c2c66affSColin Finck         Ret = TRUE;
821c2c66affSColin Finck 
822c2c66affSColin Finck     DC_UnlockDc(pDC);
823c2c66affSColin Finck     return Ret;
824c2c66affSColin Finck }
825c2c66affSColin Finck 
826c2c66affSColin Finck int
827c2c66affSColin Finck APIENTRY
IntGdiSetMapMode(PDC dc,int MapMode)828c2c66affSColin Finck IntGdiSetMapMode(
829c2c66affSColin Finck     PDC dc,
830c2c66affSColin Finck     int MapMode)
831c2c66affSColin Finck {
832c2c66affSColin Finck     INT iPrevMapMode;
833c2c66affSColin Finck     FLONG flXform;
834c2c66affSColin Finck     PDC_ATTR pdcattr = dc->pdcattr;
835c2c66affSColin Finck 
8368bdfdd5cSKatayama Hirofumi MZ     if (MapMode == pdcattr->iMapMode)
8378bdfdd5cSKatayama Hirofumi MZ         return MapMode;
8388bdfdd5cSKatayama Hirofumi MZ 
839c2c66affSColin Finck     flXform = pdcattr->flXform & ~(ISO_OR_ANISO_MAP_MODE|PTOD_EFM22_NEGATIVE|
840c2c66affSColin Finck         PTOD_EFM11_NEGATIVE|POSITIVE_Y_IS_UP|PAGE_TO_DEVICE_SCALE_IDENTITY|
841c2c66affSColin Finck         PAGE_TO_DEVICE_IDENTITY);
842c2c66affSColin Finck 
843c2c66affSColin Finck     switch (MapMode)
844c2c66affSColin Finck     {
845c2c66affSColin Finck         case MM_TEXT:
846c2c66affSColin Finck             pdcattr->szlWindowExt.cx = 1;
847c2c66affSColin Finck             pdcattr->szlWindowExt.cy = 1;
848c2c66affSColin Finck             pdcattr->szlViewportExt.cx = 1;
849c2c66affSColin Finck             pdcattr->szlViewportExt.cy = 1;
850c2c66affSColin Finck             flXform |= PAGE_TO_DEVICE_SCALE_IDENTITY;
851c2c66affSColin Finck             break;
852c2c66affSColin Finck 
853c2c66affSColin Finck         case MM_ISOTROPIC:
854c2c66affSColin Finck             flXform |= ISO_OR_ANISO_MAP_MODE;
855c2c66affSColin Finck             /* Fall through */
856c2c66affSColin Finck 
857c2c66affSColin Finck         case MM_LOMETRIC:
858c2c66affSColin Finck             pdcattr->szlWindowExt.cx = pdcattr->szlVirtualDeviceMm.cx * 10;
859c2c66affSColin Finck             pdcattr->szlWindowExt.cy = pdcattr->szlVirtualDeviceMm.cy * 10;
860c2c66affSColin Finck             pdcattr->szlViewportExt.cx =  pdcattr->szlVirtualDevicePixel.cx;
861c2c66affSColin Finck             pdcattr->szlViewportExt.cy = -pdcattr->szlVirtualDevicePixel.cy;
862c2c66affSColin Finck             break;
863c2c66affSColin Finck 
864c2c66affSColin Finck         case MM_HIMETRIC:
865c2c66affSColin Finck             pdcattr->szlWindowExt.cx = pdcattr->szlVirtualDeviceMm.cx * 100;
866c2c66affSColin Finck             pdcattr->szlWindowExt.cy = pdcattr->szlVirtualDeviceMm.cy * 100;
867c2c66affSColin Finck             pdcattr->szlViewportExt.cx =  pdcattr->szlVirtualDevicePixel.cx;
868c2c66affSColin Finck             pdcattr->szlViewportExt.cy = -pdcattr->szlVirtualDevicePixel.cy;
869c2c66affSColin Finck             break;
870c2c66affSColin Finck 
871c2c66affSColin Finck         case MM_LOENGLISH:
872*405ce532SJérôme Gardou             pdcattr->szlWindowExt.cx = EngMulDiv(1000, pdcattr->szlVirtualDeviceMm.cx, 254);
873*405ce532SJérôme Gardou             pdcattr->szlWindowExt.cy = EngMulDiv(1000, pdcattr->szlVirtualDeviceMm.cy, 254);
874c2c66affSColin Finck             pdcattr->szlViewportExt.cx =  pdcattr->szlVirtualDevicePixel.cx;
875c2c66affSColin Finck             pdcattr->szlViewportExt.cy = -pdcattr->szlVirtualDevicePixel.cy;
876c2c66affSColin Finck             break;
877c2c66affSColin Finck 
878c2c66affSColin Finck         case MM_HIENGLISH:
879*405ce532SJérôme Gardou             pdcattr->szlWindowExt.cx = EngMulDiv(10000, pdcattr->szlVirtualDeviceMm.cx, 254);
880*405ce532SJérôme Gardou             pdcattr->szlWindowExt.cy = EngMulDiv(10000, pdcattr->szlVirtualDeviceMm.cy, 254);
881c2c66affSColin Finck             pdcattr->szlViewportExt.cx =  pdcattr->szlVirtualDevicePixel.cx;
882c2c66affSColin Finck             pdcattr->szlViewportExt.cy = -pdcattr->szlVirtualDevicePixel.cy;
883c2c66affSColin Finck             break;
884c2c66affSColin Finck 
885c2c66affSColin Finck         case MM_TWIPS:
886*405ce532SJérôme Gardou             pdcattr->szlWindowExt.cx = EngMulDiv(14400, pdcattr->szlVirtualDeviceMm.cx, 254);
887*405ce532SJérôme Gardou             pdcattr->szlWindowExt.cy = EngMulDiv(14400, pdcattr->szlVirtualDeviceMm.cy, 254);
888c2c66affSColin Finck             pdcattr->szlViewportExt.cx =  pdcattr->szlVirtualDevicePixel.cx;
889c2c66affSColin Finck             pdcattr->szlViewportExt.cy = -pdcattr->szlVirtualDevicePixel.cy;
890c2c66affSColin Finck             break;
891c2c66affSColin Finck 
892c2c66affSColin Finck         case MM_ANISOTROPIC:
893c2c66affSColin Finck             flXform &= ~(PAGE_TO_DEVICE_IDENTITY|POSITIVE_Y_IS_UP);
894c2c66affSColin Finck             flXform |= ISO_OR_ANISO_MAP_MODE;
895c2c66affSColin Finck             break;
896c2c66affSColin Finck 
897c2c66affSColin Finck         default:
898c2c66affSColin Finck             return 0;
899c2c66affSColin Finck     }
900c2c66affSColin Finck 
901c2c66affSColin Finck     /* Save the old map mode and set the new one */
902c2c66affSColin Finck     iPrevMapMode = pdcattr->iMapMode;
903c2c66affSColin Finck     pdcattr->iMapMode = MapMode;
904c2c66affSColin Finck 
905c2c66affSColin Finck     /* Update xform flags */
906c2c66affSColin Finck     pdcattr->flXform = flXform | (PAGE_XLATE_CHANGED | PAGE_EXTENTS_CHANGED |
907f7bc0543SKatayama Hirofumi MZ                                   INVALIDATE_ATTRIBUTES | DEVICE_TO_PAGE_INVALID |
908f7bc0543SKatayama Hirofumi MZ                                   WORLD_XFORM_CHANGED | DEVICE_TO_WORLD_INVALID);
909c2c66affSColin Finck 
910c2c66affSColin Finck     return iPrevMapMode;
911c2c66affSColin Finck }
912c2c66affSColin Finck 
913c2c66affSColin Finck BOOL
914c2c66affSColin Finck FASTCALL
GreSetViewportOrgEx(HDC hDC,int X,int Y,LPPOINT Point)915c2c66affSColin Finck GreSetViewportOrgEx(
916c2c66affSColin Finck     HDC hDC,
917c2c66affSColin Finck     int X,
918c2c66affSColin Finck     int Y,
919c2c66affSColin Finck     LPPOINT Point)
920c2c66affSColin Finck {
921c2c66affSColin Finck     PDC dc;
922c2c66affSColin Finck     PDC_ATTR pdcattr;
923c2c66affSColin Finck 
924c2c66affSColin Finck     dc = DC_LockDc(hDC);
925c2c66affSColin Finck     if (!dc)
926c2c66affSColin Finck     {
927c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_HANDLE);
928c2c66affSColin Finck         return FALSE;
929c2c66affSColin Finck     }
930c2c66affSColin Finck     pdcattr = dc->pdcattr;
931c2c66affSColin Finck 
932c2c66affSColin Finck     if (Point)
933c2c66affSColin Finck     {
934c2c66affSColin Finck        Point->x = pdcattr->ptlViewportOrg.x;
935c2c66affSColin Finck        Point->y = pdcattr->ptlViewportOrg.y;
936c2c66affSColin Finck     }
937c2c66affSColin Finck 
938c2c66affSColin Finck     pdcattr->ptlViewportOrg.x = X;
939c2c66affSColin Finck     pdcattr->ptlViewportOrg.y = Y;
940f7bc0543SKatayama Hirofumi MZ     pdcattr->flXform |= PAGE_XLATE_CHANGED | WORLD_XFORM_CHANGED | DEVICE_TO_WORLD_INVALID;
941c2c66affSColin Finck 
942c2c66affSColin Finck     DC_UnlockDc(dc);
943c2c66affSColin Finck     return TRUE;
944c2c66affSColin Finck }
945c2c66affSColin Finck 
946c2c66affSColin Finck BOOL
947c2c66affSColin Finck APIENTRY
NtGdiSetViewportOrgEx(HDC hDC,int X,int Y,LPPOINT Point)948c2c66affSColin Finck NtGdiSetViewportOrgEx(
949c2c66affSColin Finck     HDC hDC,
950c2c66affSColin Finck     int X,
951c2c66affSColin Finck     int Y,
952c2c66affSColin Finck     LPPOINT Point)
953c2c66affSColin Finck {
954c2c66affSColin Finck     PDC dc;
955c2c66affSColin Finck     PDC_ATTR pdcattr;
956c2c66affSColin Finck 
957c2c66affSColin Finck     dc = DC_LockDc(hDC);
958c2c66affSColin Finck     if (!dc)
959c2c66affSColin Finck     {
960c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_HANDLE);
961c2c66affSColin Finck         return FALSE;
962c2c66affSColin Finck     }
963c2c66affSColin Finck     pdcattr = dc->pdcattr;
964c2c66affSColin Finck 
965c2c66affSColin Finck     if (Point)
966c2c66affSColin Finck     {
967c2c66affSColin Finck         NTSTATUS Status = STATUS_SUCCESS;
968c2c66affSColin Finck 
969c2c66affSColin Finck         _SEH2_TRY
970c2c66affSColin Finck         {
971c2c66affSColin Finck             ProbeForWrite(Point, sizeof(POINT), 1);
972c2c66affSColin Finck             Point->x = pdcattr->ptlViewportOrg.x;
973c2c66affSColin Finck             Point->y = pdcattr->ptlViewportOrg.y;
974c2c66affSColin Finck         }
975c2c66affSColin Finck         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
976c2c66affSColin Finck         {
977c2c66affSColin Finck             Status = _SEH2_GetExceptionCode();
978c2c66affSColin Finck         }
979c2c66affSColin Finck         _SEH2_END;
980c2c66affSColin Finck 
981c2c66affSColin Finck         if (!NT_SUCCESS(Status))
982c2c66affSColin Finck         {
983c2c66affSColin Finck             SetLastNtError(Status);
984c2c66affSColin Finck             DC_UnlockDc(dc);
985c2c66affSColin Finck             return FALSE;
986c2c66affSColin Finck         }
987c2c66affSColin Finck     }
988c2c66affSColin Finck 
989c2c66affSColin Finck     pdcattr->ptlViewportOrg.x = X;
990c2c66affSColin Finck     pdcattr->ptlViewportOrg.y = Y;
991f7bc0543SKatayama Hirofumi MZ     pdcattr->flXform |= PAGE_XLATE_CHANGED | WORLD_XFORM_CHANGED | DEVICE_TO_WORLD_INVALID;
992c2c66affSColin Finck 
993c2c66affSColin Finck     DC_UnlockDc(dc);
994c2c66affSColin Finck 
995c2c66affSColin Finck     return TRUE;
996c2c66affSColin Finck }
997c2c66affSColin Finck 
998c2c66affSColin Finck BOOL
999c2c66affSColin Finck APIENTRY
NtGdiSetWindowOrgEx(HDC hDC,int X,int Y,LPPOINT Point)1000c2c66affSColin Finck NtGdiSetWindowOrgEx(
1001c2c66affSColin Finck     HDC hDC,
1002c2c66affSColin Finck     int X,
1003c2c66affSColin Finck     int Y,
1004c2c66affSColin Finck     LPPOINT Point)
1005c2c66affSColin Finck {
1006c2c66affSColin Finck     PDC dc;
1007c2c66affSColin Finck     PDC_ATTR pdcattr;
1008c2c66affSColin Finck 
1009c2c66affSColin Finck     dc = DC_LockDc(hDC);
1010c2c66affSColin Finck     if (!dc)
1011c2c66affSColin Finck     {
1012c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_HANDLE);
1013c2c66affSColin Finck         return FALSE;
1014c2c66affSColin Finck     }
1015c2c66affSColin Finck     pdcattr = dc->pdcattr;
1016c2c66affSColin Finck 
1017c2c66affSColin Finck     if (Point)
1018c2c66affSColin Finck     {
1019c2c66affSColin Finck         NTSTATUS Status = STATUS_SUCCESS;
1020c2c66affSColin Finck 
1021c2c66affSColin Finck         _SEH2_TRY
1022c2c66affSColin Finck         {
1023c2c66affSColin Finck             ProbeForWrite(Point, sizeof(POINT), 1);
1024c2c66affSColin Finck             Point->x = pdcattr->ptlWindowOrg.x;
1025c2c66affSColin Finck             Point->y = pdcattr->ptlWindowOrg.y;
1026c2c66affSColin Finck         }
1027c2c66affSColin Finck         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1028c2c66affSColin Finck         {
1029c2c66affSColin Finck             Status = _SEH2_GetExceptionCode();
1030c2c66affSColin Finck         }
1031c2c66affSColin Finck         _SEH2_END;
1032c2c66affSColin Finck 
1033c2c66affSColin Finck         if (!NT_SUCCESS(Status))
1034c2c66affSColin Finck         {
1035c2c66affSColin Finck             SetLastNtError(Status);
1036c2c66affSColin Finck             DC_UnlockDc(dc);
1037c2c66affSColin Finck             return FALSE;
1038c2c66affSColin Finck         }
1039c2c66affSColin Finck     }
1040c2c66affSColin Finck 
1041c2c66affSColin Finck     pdcattr->ptlWindowOrg.x = X;
1042c2c66affSColin Finck     pdcattr->ptlWindowOrg.y = Y;
1043f7bc0543SKatayama Hirofumi MZ     pdcattr->flXform |= PAGE_XLATE_CHANGED | WORLD_XFORM_CHANGED | DEVICE_TO_WORLD_INVALID;
1044c2c66affSColin Finck 
1045c2c66affSColin Finck     DC_UnlockDc(dc);
1046c2c66affSColin Finck 
1047c2c66affSColin Finck     return TRUE;
1048c2c66affSColin Finck }
1049c2c66affSColin Finck 
1050c2c66affSColin Finck //
1051c2c66affSColin Finck // Mirror Window function.
1052c2c66affSColin Finck //
1053c2c66affSColin Finck VOID
1054c2c66affSColin Finck FASTCALL
IntMirrorWindowOrg(PDC dc)1055c2c66affSColin Finck IntMirrorWindowOrg(PDC dc)
1056c2c66affSColin Finck {
1057c2c66affSColin Finck     PDC_ATTR pdcattr;
1058c2c66affSColin Finck     LONG X, cx;
1059c2c66affSColin Finck 
1060c2c66affSColin Finck     pdcattr = dc->pdcattr;
1061c2c66affSColin Finck 
1062c2c66affSColin Finck     if (!(pdcattr->dwLayout & LAYOUT_RTL))
1063c2c66affSColin Finck     {
1064c2c66affSColin Finck         pdcattr->ptlWindowOrg.x = pdcattr->lWindowOrgx; // Flip it back.
1065c2c66affSColin Finck         return;
1066c2c66affSColin Finck     }
1067c2c66affSColin Finck 
1068c2c66affSColin Finck     /* Copy the window extension, so no one can mess with it */
1069c2c66affSColin Finck     cx = pdcattr->szlViewportExt.cx;
1070c2c66affSColin Finck     if (cx == 0) return;
1071c2c66affSColin Finck     //
1072c2c66affSColin Finck     // WOrgx = wox - (Width - 1) * WExtx / VExtx
1073c2c66affSColin Finck     //
1074c2c66affSColin Finck     X = (dc->erclWindow.right - dc->erclWindow.left) - 1; // Get device width - 1
1075c2c66affSColin Finck 
1076c2c66affSColin Finck     X = (X * pdcattr->szlWindowExt.cx) / cx;
1077c2c66affSColin Finck 
1078c2c66affSColin Finck     pdcattr->ptlWindowOrg.x = pdcattr->lWindowOrgx - X; // Now set the inverted win origion.
1079f7bc0543SKatayama Hirofumi MZ     pdcattr->flXform |= PAGE_XLATE_CHANGED | WORLD_XFORM_CHANGED | DEVICE_TO_WORLD_INVALID;
1080c2c66affSColin Finck 
1081c2c66affSColin Finck     return;
1082c2c66affSColin Finck }
1083c2c66affSColin Finck 
1084c2c66affSColin Finck VOID
1085c2c66affSColin Finck NTAPI
DC_vSetLayout(IN PDC pdc,IN LONG wox,IN DWORD dwLayout)1086c2c66affSColin Finck DC_vSetLayout(
1087c2c66affSColin Finck     IN PDC pdc,
1088c2c66affSColin Finck     IN LONG wox,
1089c2c66affSColin Finck     IN DWORD dwLayout)
1090c2c66affSColin Finck {
1091c2c66affSColin Finck     PDC_ATTR pdcattr = pdc->pdcattr;
1092c2c66affSColin Finck 
1093c2c66affSColin Finck     pdcattr->dwLayout = dwLayout;
1094c2c66affSColin Finck 
1095c2c66affSColin Finck     if (!(dwLayout & LAYOUT_ORIENTATIONMASK)) return;
1096c2c66affSColin Finck 
1097c2c66affSColin Finck     if (dwLayout & LAYOUT_RTL)
1098c2c66affSColin Finck     {
1099c2c66affSColin Finck         pdcattr->iMapMode = MM_ANISOTROPIC;
1100c2c66affSColin Finck     }
1101c2c66affSColin Finck 
1102c2c66affSColin Finck     //pdcattr->szlWindowExt.cy = -pdcattr->szlWindowExt.cy;
1103c2c66affSColin Finck     //pdcattr->ptlWindowOrg.x  = -pdcattr->ptlWindowOrg.x;
1104c2c66affSColin Finck 
1105c2c66affSColin Finck     //if (wox == -1)
1106c2c66affSColin Finck     //    IntMirrorWindowOrg(pdc);
1107c2c66affSColin Finck     //else
1108c2c66affSColin Finck     //    pdcattr->ptlWindowOrg.x = wox - pdcattr->ptlWindowOrg.x;
1109c2c66affSColin Finck 
1110c2c66affSColin Finck     if (!(pdcattr->flTextAlign & TA_CENTER)) pdcattr->flTextAlign |= TA_RIGHT;
1111c2c66affSColin Finck 
1112c2c66affSColin Finck     if (pdc->dclevel.flPath & DCPATH_CLOCKWISE)
1113c2c66affSColin Finck         pdc->dclevel.flPath &= ~DCPATH_CLOCKWISE;
1114c2c66affSColin Finck     else
1115c2c66affSColin Finck         pdc->dclevel.flPath |= DCPATH_CLOCKWISE;
1116c2c66affSColin Finck 
1117c2c66affSColin Finck     pdcattr->flXform |= (PAGE_EXTENTS_CHANGED |
1118c2c66affSColin Finck                          INVALIDATE_ATTRIBUTES |
1119f7bc0543SKatayama Hirofumi MZ                          WORLD_XFORM_CHANGED |
1120c2c66affSColin Finck                          DEVICE_TO_WORLD_INVALID);
1121c2c66affSColin Finck }
1122c2c66affSColin Finck 
1123c2c66affSColin Finck // NtGdiSetLayout
1124c2c66affSColin Finck //
1125c2c66affSColin Finck // The default is left to right. This function changes it to right to left, which
1126c2c66affSColin Finck // is the standard in Arabic and Hebrew cultures.
1127c2c66affSColin Finck //
1128c2c66affSColin Finck /*
1129c2c66affSColin Finck  * @implemented
1130c2c66affSColin Finck  */
1131c2c66affSColin Finck DWORD
1132c2c66affSColin Finck APIENTRY
NtGdiSetLayout(IN HDC hdc,IN LONG wox,IN DWORD dwLayout)1133c2c66affSColin Finck NtGdiSetLayout(
1134c2c66affSColin Finck     IN HDC hdc,
1135c2c66affSColin Finck     IN LONG wox,
1136c2c66affSColin Finck     IN DWORD dwLayout)
1137c2c66affSColin Finck {
1138c2c66affSColin Finck     PDC pdc;
1139c2c66affSColin Finck     DWORD dwOldLayout;
1140c2c66affSColin Finck 
1141c2c66affSColin Finck     pdc = DC_LockDc(hdc);
1142c2c66affSColin Finck     if (!pdc)
1143c2c66affSColin Finck     {
1144c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_HANDLE);
1145c2c66affSColin Finck         return GDI_ERROR;
1146c2c66affSColin Finck     }
1147c2c66affSColin Finck 
1148c2c66affSColin Finck     dwOldLayout = pdc->pdcattr->dwLayout;
1149c2c66affSColin Finck     DC_vSetLayout(pdc, wox, dwLayout);
1150c2c66affSColin Finck 
1151c2c66affSColin Finck     DC_UnlockDc(pdc);
1152c2c66affSColin Finck     return dwOldLayout;
1153c2c66affSColin Finck }
1154c2c66affSColin Finck 
1155c2c66affSColin Finck /*
1156c2c66affSColin Finck  * @implemented
1157c2c66affSColin Finck  */
1158c2c66affSColin Finck LONG
1159c2c66affSColin Finck APIENTRY
NtGdiGetDeviceWidth(IN HDC hdc)1160c2c66affSColin Finck NtGdiGetDeviceWidth(
1161c2c66affSColin Finck     IN HDC hdc)
1162c2c66affSColin Finck {
1163c2c66affSColin Finck     PDC dc;
1164c2c66affSColin Finck     LONG Ret;
1165c2c66affSColin Finck     dc = DC_LockDc(hdc);
1166c2c66affSColin Finck     if (!dc)
1167c2c66affSColin Finck     {
1168c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_HANDLE);
1169c2c66affSColin Finck         return 0;
1170c2c66affSColin Finck     }
1171c2c66affSColin Finck     Ret = dc->erclWindow.right - dc->erclWindow.left;
1172c2c66affSColin Finck     DC_UnlockDc(dc);
1173c2c66affSColin Finck     return Ret;
1174c2c66affSColin Finck }
1175c2c66affSColin Finck 
1176c2c66affSColin Finck /*
1177c2c66affSColin Finck  * @implemented
1178c2c66affSColin Finck  */
1179c2c66affSColin Finck BOOL
1180c2c66affSColin Finck APIENTRY
NtGdiMirrorWindowOrg(IN HDC hdc)1181c2c66affSColin Finck NtGdiMirrorWindowOrg(
1182c2c66affSColin Finck     IN HDC hdc)
1183c2c66affSColin Finck {
1184c2c66affSColin Finck     PDC dc;
1185c2c66affSColin Finck     dc = DC_LockDc(hdc);
1186c2c66affSColin Finck     if (!dc)
1187c2c66affSColin Finck     {
1188c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_HANDLE);
1189c2c66affSColin Finck         return FALSE;
1190c2c66affSColin Finck     }
1191c2c66affSColin Finck     IntMirrorWindowOrg(dc);
1192c2c66affSColin Finck     DC_UnlockDc(dc);
1193c2c66affSColin Finck     return TRUE;
1194c2c66affSColin Finck }
1195c2c66affSColin Finck 
1196c2c66affSColin Finck /*
1197c2c66affSColin Finck  * @implemented
1198c2c66affSColin Finck  */
1199c2c66affSColin Finck BOOL
1200c2c66affSColin Finck APIENTRY
NtGdiSetSizeDevice(IN HDC hdc,IN INT cxVirtualDevice,IN INT cyVirtualDevice)1201c2c66affSColin Finck NtGdiSetSizeDevice(
1202c2c66affSColin Finck     IN HDC hdc,
1203c2c66affSColin Finck     IN INT cxVirtualDevice,
1204c2c66affSColin Finck     IN INT cyVirtualDevice)
1205c2c66affSColin Finck {
1206c2c66affSColin Finck     PDC dc;
1207c2c66affSColin Finck     PDC_ATTR pdcattr;
1208c2c66affSColin Finck 
1209c2c66affSColin Finck     if (!cxVirtualDevice || !cyVirtualDevice)
1210c2c66affSColin Finck     {
1211c2c66affSColin Finck         return FALSE;
1212c2c66affSColin Finck     }
1213c2c66affSColin Finck 
1214c2c66affSColin Finck     dc = DC_LockDc(hdc);
1215c2c66affSColin Finck     if (!dc) return FALSE;
1216c2c66affSColin Finck 
1217c2c66affSColin Finck     pdcattr = dc->pdcattr;
1218c2c66affSColin Finck 
1219c2c66affSColin Finck     pdcattr->szlVirtualDeviceSize.cx = cxVirtualDevice;
1220c2c66affSColin Finck     pdcattr->szlVirtualDeviceSize.cy = cyVirtualDevice;
1221c2c66affSColin Finck 
1222c2c66affSColin Finck     DC_UnlockDc(dc);
1223c2c66affSColin Finck 
1224c2c66affSColin Finck     return TRUE;
1225c2c66affSColin Finck }
1226c2c66affSColin Finck 
1227c2c66affSColin Finck /*
1228c2c66affSColin Finck  * @implemented
1229c2c66affSColin Finck  */
1230c2c66affSColin Finck BOOL
1231c2c66affSColin Finck APIENTRY
NtGdiSetVirtualResolution(IN HDC hdc,IN INT cxVirtualDevicePixel,IN INT cyVirtualDevicePixel,IN INT cxVirtualDeviceMm,IN INT cyVirtualDeviceMm)1232c2c66affSColin Finck NtGdiSetVirtualResolution(
1233c2c66affSColin Finck     IN HDC hdc,
1234c2c66affSColin Finck     IN INT cxVirtualDevicePixel,
1235c2c66affSColin Finck     IN INT cyVirtualDevicePixel,
1236c2c66affSColin Finck     IN INT cxVirtualDeviceMm,
1237c2c66affSColin Finck     IN INT cyVirtualDeviceMm)
1238c2c66affSColin Finck {
1239c2c66affSColin Finck     PDC dc;
1240c2c66affSColin Finck     PDC_ATTR pdcattr;
1241c2c66affSColin Finck 
1242c2c66affSColin Finck     /* Check parameters (all zeroes resets to real resolution) */
1243c2c66affSColin Finck     if (cxVirtualDevicePixel == 0 && cyVirtualDevicePixel == 0 &&
1244c2c66affSColin Finck         cxVirtualDeviceMm == 0 && cyVirtualDeviceMm == 0)
1245c2c66affSColin Finck     {
1246c2c66affSColin Finck         cxVirtualDevicePixel = NtGdiGetDeviceCaps(hdc, HORZRES);
1247c2c66affSColin Finck         cyVirtualDevicePixel = NtGdiGetDeviceCaps(hdc, VERTRES);
1248c2c66affSColin Finck         cxVirtualDeviceMm = NtGdiGetDeviceCaps(hdc, HORZSIZE);
1249c2c66affSColin Finck         cyVirtualDeviceMm = NtGdiGetDeviceCaps(hdc, VERTSIZE);
1250c2c66affSColin Finck     }
1251c2c66affSColin Finck     else if (cxVirtualDevicePixel == 0 || cyVirtualDevicePixel == 0 ||
1252c2c66affSColin Finck              cxVirtualDeviceMm == 0 || cyVirtualDeviceMm == 0)
1253c2c66affSColin Finck     {
1254c2c66affSColin Finck         return FALSE;
1255c2c66affSColin Finck     }
1256c2c66affSColin Finck 
1257c2c66affSColin Finck     dc = DC_LockDc(hdc);
1258c2c66affSColin Finck     if (!dc) return FALSE;
1259c2c66affSColin Finck 
1260c2c66affSColin Finck     pdcattr = dc->pdcattr;
1261c2c66affSColin Finck 
1262c2c66affSColin Finck     pdcattr->szlVirtualDevicePixel.cx = cxVirtualDevicePixel;
1263c2c66affSColin Finck     pdcattr->szlVirtualDevicePixel.cy = cyVirtualDevicePixel;
1264c2c66affSColin Finck     pdcattr->szlVirtualDeviceMm.cx = cxVirtualDeviceMm;
1265c2c66affSColin Finck     pdcattr->szlVirtualDeviceMm.cy = cyVirtualDeviceMm;
1266c2c66affSColin Finck 
1267c2c66affSColin Finck //    DC_vUpdateXforms(dc);
1268c2c66affSColin Finck     DC_UnlockDc(dc);
1269c2c66affSColin Finck     return TRUE;
1270c2c66affSColin Finck }
1271c2c66affSColin Finck 
1272c2c66affSColin Finck static
1273c2c66affSColin Finck VOID FASTCALL
DC_vGetAspectRatioFilter(PDC pDC,LPSIZE AspectRatio)1274c2c66affSColin Finck DC_vGetAspectRatioFilter(PDC pDC, LPSIZE AspectRatio)
1275c2c66affSColin Finck {
1276c2c66affSColin Finck     if (pDC->pdcattr->flFontMapper & 1) // TRUE assume 1.
1277c2c66affSColin Finck     {
1278c2c66affSColin Finck         // "This specifies that Windows should only match fonts that have the
1279c2c66affSColin Finck         // same aspect ratio as the display.", Programming Windows, Fifth Ed.
1280c2c66affSColin Finck         AspectRatio->cx = pDC->ppdev->gdiinfo.ulLogPixelsX;
1281c2c66affSColin Finck         AspectRatio->cy = pDC->ppdev->gdiinfo.ulLogPixelsY;
1282c2c66affSColin Finck     }
1283c2c66affSColin Finck     else
1284c2c66affSColin Finck     {
1285c2c66affSColin Finck         AspectRatio->cx = 0;
1286c2c66affSColin Finck         AspectRatio->cy = 0;
1287c2c66affSColin Finck     }
1288c2c66affSColin Finck }
1289c2c66affSColin Finck 
1290c2c66affSColin Finck BOOL APIENTRY
GreGetDCPoint(HDC hDC,UINT iPoint,PPOINTL Point)1291c2c66affSColin Finck GreGetDCPoint(
1292c2c66affSColin Finck     HDC hDC,
1293c2c66affSColin Finck     UINT iPoint,
1294c2c66affSColin Finck     PPOINTL Point)
1295c2c66affSColin Finck {
1296c2c66affSColin Finck     BOOL Ret = TRUE;
1297c2c66affSColin Finck     DC *pdc;
1298c2c66affSColin Finck     SIZE Size;
1299c2c66affSColin Finck     PSIZEL pszlViewportExt;
1300c2c66affSColin Finck 
1301c2c66affSColin Finck     if (!Point)
1302c2c66affSColin Finck     {
1303c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_PARAMETER);
1304c2c66affSColin Finck         return FALSE;
1305c2c66affSColin Finck     }
1306c2c66affSColin Finck 
1307c2c66affSColin Finck     pdc = DC_LockDc(hDC);
1308c2c66affSColin Finck     if (!pdc)
1309c2c66affSColin Finck     {
1310c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_HANDLE);
1311c2c66affSColin Finck         return FALSE;
1312c2c66affSColin Finck     }
1313c2c66affSColin Finck 
1314c2c66affSColin Finck     switch (iPoint)
1315c2c66affSColin Finck     {
1316c2c66affSColin Finck         case GdiGetViewPortExt:
1317c2c66affSColin Finck             pszlViewportExt = DC_pszlViewportExt(pdc);
1318c2c66affSColin Finck             Point->x = pszlViewportExt->cx;
1319c2c66affSColin Finck             Point->y = pszlViewportExt->cy;
1320c2c66affSColin Finck             break;
1321c2c66affSColin Finck 
1322c2c66affSColin Finck         case GdiGetWindowExt:
1323c2c66affSColin Finck             Point->x = pdc->pdcattr->szlWindowExt.cx;
1324c2c66affSColin Finck             Point->y = pdc->pdcattr->szlWindowExt.cy;
1325c2c66affSColin Finck             break;
1326c2c66affSColin Finck 
1327c2c66affSColin Finck         case GdiGetViewPortOrg:
1328c2c66affSColin Finck             *Point = pdc->pdcattr->ptlViewportOrg;
1329c2c66affSColin Finck             break;
1330c2c66affSColin Finck 
1331c2c66affSColin Finck         case GdiGetWindowOrg:
1332c2c66affSColin Finck             *Point = pdc->pdcattr->ptlWindowOrg;
1333c2c66affSColin Finck             break;
1334c2c66affSColin Finck 
1335c2c66affSColin Finck         case GdiGetDCOrg:
1336c2c66affSColin Finck             *Point = pdc->ptlDCOrig;
1337c2c66affSColin Finck             break;
1338c2c66affSColin Finck 
1339c2c66affSColin Finck         case GdiGetAspectRatioFilter:
1340c2c66affSColin Finck             DC_vGetAspectRatioFilter(pdc, &Size);
1341c2c66affSColin Finck             Point->x = Size.cx;
1342c2c66affSColin Finck             Point->y = Size.cy;
1343c2c66affSColin Finck             break;
1344c2c66affSColin Finck 
1345c2c66affSColin Finck         default:
1346c2c66affSColin Finck             EngSetLastError(ERROR_INVALID_PARAMETER);
1347c2c66affSColin Finck             Ret = FALSE;
1348c2c66affSColin Finck             break;
1349c2c66affSColin Finck     }
1350c2c66affSColin Finck 
1351c2c66affSColin Finck     DC_UnlockDc(pdc);
1352c2c66affSColin Finck     return Ret;
1353c2c66affSColin Finck }
1354c2c66affSColin Finck 
1355c2c66affSColin Finck BOOL
1356c2c66affSColin Finck WINAPI
GreSetDCOrg(_In_ HDC hdc,_In_ LONG x,_In_ LONG y,_In_opt_ PRECTL Rect)1357c2c66affSColin Finck GreSetDCOrg(
1358c2c66affSColin Finck     _In_ HDC hdc,
1359c2c66affSColin Finck     _In_ LONG x,
1360c2c66affSColin Finck     _In_ LONG y,
1361c2c66affSColin Finck     _In_opt_ PRECTL Rect)
1362c2c66affSColin Finck {
1363c2c66affSColin Finck     PDC dc;
1364c2c66affSColin Finck 
1365c2c66affSColin Finck     dc = DC_LockDc(hdc);
1366c2c66affSColin Finck     if (!dc) return FALSE;
1367c2c66affSColin Finck 
1368c2c66affSColin Finck     /* Set DC Origin */
1369c2c66affSColin Finck     dc->ptlDCOrig.x = x;
1370c2c66affSColin Finck     dc->ptlDCOrig.y = y;
1371c2c66affSColin Finck 
1372c2c66affSColin Finck     /* Recalculate Fill Origin */
1373c2c66affSColin Finck     dc->ptlFillOrigin.x = dc->dclevel.ptlBrushOrigin.x + x;
1374c2c66affSColin Finck     dc->ptlFillOrigin.y = dc->dclevel.ptlBrushOrigin.y + y;
1375c2c66affSColin Finck 
1376c2c66affSColin Finck     /* Set DC Window Rectangle */
1377c2c66affSColin Finck     if (Rect)
1378c2c66affSColin Finck         dc->erclWindow = *Rect;
1379c2c66affSColin Finck 
1380c2c66affSColin Finck     DC_UnlockDc(dc);
1381c2c66affSColin Finck     return TRUE;
1382c2c66affSColin Finck }
1383c2c66affSColin Finck 
1384c2c66affSColin Finck BOOL
1385c2c66affSColin Finck WINAPI
GreGetDCOrgEx(_In_ HDC hdc,_Out_ PPOINTL Point,_Out_ PRECTL Rect)1386c2c66affSColin Finck GreGetDCOrgEx(
1387c2c66affSColin Finck     _In_ HDC hdc,
1388c2c66affSColin Finck     _Out_ PPOINTL Point,
1389c2c66affSColin Finck     _Out_ PRECTL Rect)
1390c2c66affSColin Finck {
1391c2c66affSColin Finck     PDC dc;
1392c2c66affSColin Finck 
1393c2c66affSColin Finck     dc = DC_LockDc(hdc);
1394c2c66affSColin Finck     if (!dc) return FALSE;
1395c2c66affSColin Finck 
1396c2c66affSColin Finck     /* Retrieve DC Window Rectangle without a check */
1397c2c66affSColin Finck     *Rect = dc->erclWindow;
1398c2c66affSColin Finck 
1399c2c66affSColin Finck     DC_UnlockDc(dc);
1400c2c66affSColin Finck 
1401c2c66affSColin Finck     /* Use default call for DC Origin and parameter checking */
1402c2c66affSColin Finck     return GreGetDCPoint( hdc, GdiGetDCOrg, Point);
1403c2c66affSColin Finck }
1404c2c66affSColin Finck 
1405c2c66affSColin Finck BOOL
1406c2c66affSColin Finck WINAPI
GreGetWindowExtEx(_In_ HDC hdc,_Out_ LPSIZE lpSize)1407c2c66affSColin Finck GreGetWindowExtEx(
1408c2c66affSColin Finck     _In_ HDC hdc,
1409c2c66affSColin Finck     _Out_ LPSIZE lpSize)
1410c2c66affSColin Finck {
1411c2c66affSColin Finck     return GreGetDCPoint(hdc, GdiGetWindowExt, (PPOINTL)lpSize);
1412c2c66affSColin Finck }
1413c2c66affSColin Finck 
1414c2c66affSColin Finck BOOL
1415c2c66affSColin Finck WINAPI
GreGetViewportExtEx(_In_ HDC hdc,_Out_ LPSIZE lpSize)1416c2c66affSColin Finck GreGetViewportExtEx(
1417c2c66affSColin Finck     _In_ HDC hdc,
1418c2c66affSColin Finck     _Out_ LPSIZE lpSize)
1419c2c66affSColin Finck {
1420c2c66affSColin Finck     return GreGetDCPoint(hdc, GdiGetViewPortExt, (PPOINTL)lpSize);
1421c2c66affSColin Finck }
1422c2c66affSColin Finck 
1423c2c66affSColin Finck BOOL APIENTRY
NtGdiGetDCPoint(HDC hDC,UINT iPoint,PPOINTL Point)1424c2c66affSColin Finck NtGdiGetDCPoint(
1425c2c66affSColin Finck     HDC hDC,
1426c2c66affSColin Finck     UINT iPoint,
1427c2c66affSColin Finck     PPOINTL Point)
1428c2c66affSColin Finck {
1429c2c66affSColin Finck     BOOL Ret;
1430c2c66affSColin Finck     POINTL SafePoint;
1431c2c66affSColin Finck 
1432c2c66affSColin Finck     if (!Point)
1433c2c66affSColin Finck     {
1434c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_PARAMETER);
1435c2c66affSColin Finck         return FALSE;
1436c2c66affSColin Finck     }
1437c2c66affSColin Finck 
1438c2c66affSColin Finck     Ret = GreGetDCPoint(hDC, iPoint, &SafePoint);
1439c2c66affSColin Finck     if (Ret)
1440c2c66affSColin Finck     {
1441c2c66affSColin Finck         _SEH2_TRY
1442c2c66affSColin Finck         {
1443c2c66affSColin Finck             ProbeForWrite(Point, sizeof(POINT), 1);
1444c2c66affSColin Finck             *Point = SafePoint;
1445c2c66affSColin Finck         }
1446c2c66affSColin Finck         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1447c2c66affSColin Finck         {
1448c2c66affSColin Finck             Ret = FALSE;
1449c2c66affSColin Finck         }
1450c2c66affSColin Finck         _SEH2_END;
1451c2c66affSColin Finck     }
1452c2c66affSColin Finck 
1453c2c66affSColin Finck     return Ret;
1454c2c66affSColin Finck }
1455c2c66affSColin Finck 
1456c2c66affSColin Finck /* EOF */
1457