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