gdi32: Use NtGdiModifyWorldTransform for ModifyWorldTransform.
[wine.git] / dlls / gdi32 / mapping.c
blobd30d98b8592d7cb48a9806d319c6c080587cfb5a
1 /*
2 * GDI mapping mode functions
4 * Copyright 1993 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "wingdi.h"
26 #include "ntgdi_private.h"
27 #include "wine/debug.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(dc);
32 static SIZE get_dc_virtual_size( DC *dc )
34 SIZE ret = dc->attr->virtual_size;
36 if (!ret.cx)
38 ret.cx = GetDeviceCaps( dc->hSelf, HORZSIZE );
39 ret.cy = GetDeviceCaps( dc->hSelf, VERTSIZE );
41 return ret;
44 static SIZE get_dc_virtual_res( DC *dc )
46 SIZE ret = dc->attr->virtual_res;
48 if (!ret.cx)
50 ret.cx = GetDeviceCaps( dc->hSelf, HORZRES );
51 ret.cy = GetDeviceCaps( dc->hSelf, VERTRES );
53 return ret;
56 /***********************************************************************
57 * MAPPING_FixIsotropic
59 * Fix viewport extensions for isotropic mode.
61 static void MAPPING_FixIsotropic( DC * dc )
63 SIZE virtual_size = get_dc_virtual_size( dc );
64 SIZE virtual_res = get_dc_virtual_res( dc );
65 double xdim = fabs((double)dc->attr->vport_ext.cx * virtual_size.cx /
66 (virtual_res.cx * dc->attr->wnd_ext.cx));
67 double ydim = fabs((double)dc->attr->vport_ext.cy * virtual_size.cy /
68 (virtual_res.cy * dc->attr->wnd_ext.cy));
70 if (xdim > ydim)
72 INT mincx = (dc->attr->vport_ext.cx >= 0) ? 1 : -1;
73 dc->attr->vport_ext.cx = floor(dc->attr->vport_ext.cx * ydim / xdim + 0.5);
74 if (!dc->attr->vport_ext.cx) dc->attr->vport_ext.cx = mincx;
76 else
78 INT mincy = (dc->attr->vport_ext.cy >= 0) ? 1 : -1;
79 dc->attr->vport_ext.cy = floor(dc->attr->vport_ext.cy * xdim / ydim + 0.5);
80 if (!dc->attr->vport_ext.cy) dc->attr->vport_ext.cy = mincy;
85 BOOL set_map_mode( DC *dc, int mode )
87 SIZE virtual_size, virtual_res;
89 if (mode == dc->attr->map_mode && (mode == MM_ISOTROPIC || mode == MM_ANISOTROPIC))
90 return TRUE;
92 virtual_size = get_dc_virtual_size( dc );
93 virtual_res = get_dc_virtual_res( dc );
94 switch (mode)
96 case MM_TEXT:
97 dc->attr->wnd_ext.cx = 1;
98 dc->attr->wnd_ext.cy = 1;
99 dc->attr->vport_ext.cx = 1;
100 dc->attr->vport_ext.cy = 1;
101 break;
102 case MM_LOMETRIC:
103 case MM_ISOTROPIC:
104 dc->attr->wnd_ext.cx = virtual_size.cx * 10;
105 dc->attr->wnd_ext.cy = virtual_size.cy * 10;
106 dc->attr->vport_ext.cx = virtual_res.cx;
107 dc->attr->vport_ext.cy = -virtual_res.cy;
108 break;
109 case MM_HIMETRIC:
110 dc->attr->wnd_ext.cx = virtual_size.cx * 100;
111 dc->attr->wnd_ext.cy = virtual_size.cy * 100;
112 dc->attr->vport_ext.cx = virtual_res.cx;
113 dc->attr->vport_ext.cy = -virtual_res.cy;
114 break;
115 case MM_LOENGLISH:
116 dc->attr->wnd_ext.cx = MulDiv(1000, virtual_size.cx, 254);
117 dc->attr->wnd_ext.cy = MulDiv(1000, virtual_size.cy, 254);
118 dc->attr->vport_ext.cx = virtual_res.cx;
119 dc->attr->vport_ext.cy = -virtual_res.cy;
120 break;
121 case MM_HIENGLISH:
122 dc->attr->wnd_ext.cx = MulDiv(10000, virtual_size.cx, 254);
123 dc->attr->wnd_ext.cy = MulDiv(10000, virtual_size.cy, 254);
124 dc->attr->vport_ext.cx = virtual_res.cx;
125 dc->attr->vport_ext.cy = -virtual_res.cy;
126 break;
127 case MM_TWIPS:
128 dc->attr->wnd_ext.cx = MulDiv(14400, virtual_size.cx, 254);
129 dc->attr->wnd_ext.cy = MulDiv(14400, virtual_size.cy, 254);
130 dc->attr->vport_ext.cx = virtual_res.cx;
131 dc->attr->vport_ext.cy = -virtual_res.cy;
132 break;
133 case MM_ANISOTROPIC:
134 break;
135 default:
136 return FALSE;
138 /* RTL layout is always MM_ANISOTROPIC */
139 if (!(dc->attr->layout & LAYOUT_RTL)) dc->attr->map_mode = mode;
140 DC_UpdateXforms( dc );
141 return TRUE;
144 BOOL CDECL nulldrv_ModifyWorldTransform( PHYSDEV dev, const XFORM *xform, DWORD mode )
146 return TRUE;
149 BOOL CDECL nulldrv_SetWorldTransform( PHYSDEV dev, const XFORM *xform )
151 DC *dc = get_nulldrv_dc( dev );
153 dc->xformWorld2Wnd = *xform;
154 DC_UpdateXforms( dc );
155 return TRUE;
158 /***********************************************************************
159 * dp_to_lp
161 * Internal version of DPtoLP that takes a DC *.
163 BOOL dp_to_lp( DC *dc, POINT *points, INT count )
165 if (dc->vport2WorldValid)
167 while (count--)
169 double x = points->x;
170 double y = points->y;
171 points->x = floor( x * dc->xformVport2World.eM11 +
172 y * dc->xformVport2World.eM21 +
173 dc->xformVport2World.eDx + 0.5 );
174 points->y = floor( x * dc->xformVport2World.eM12 +
175 y * dc->xformVport2World.eM22 +
176 dc->xformVport2World.eDy + 0.5 );
177 points++;
180 return (count < 0);
183 /***********************************************************************
184 * NtGdiTransformPoints (win32u.@)
186 BOOL WINAPI NtGdiTransformPoints( HDC hdc, const POINT *points_in, POINT *points_out,
187 INT count, UINT mode )
189 DC *dc = get_dc_ptr( hdc );
190 int i = 0;
191 BOOL ret = FALSE;
193 if (!dc) return FALSE;
195 switch (mode)
197 case NtGdiLPtoDP:
198 for (i = 0; i < count; i++)
200 double x = points_in[i].x;
201 double y = points_in[i].y;
202 points_out[i].x = floor( x * dc->xformWorld2Vport.eM11 +
203 y * dc->xformWorld2Vport.eM21 +
204 dc->xformWorld2Vport.eDx + 0.5 );
205 points_out[i].y = floor( x * dc->xformWorld2Vport.eM12 +
206 y * dc->xformWorld2Vport.eM22 +
207 dc->xformWorld2Vport.eDy + 0.5 );
209 ret = TRUE;
210 break;
212 case NtGdiDPtoLP:
213 if (!dc->vport2WorldValid) break;
214 for (i = 0; i < count; i++)
216 double x = points_in[i].x;
217 double y = points_in[i].y;
218 points_out[i].x = floor( x * dc->xformVport2World.eM11 +
219 y * dc->xformVport2World.eM21 +
220 dc->xformVport2World.eDx + 0.5 );
221 points_out[i].y = floor( x * dc->xformVport2World.eM12 +
222 y * dc->xformVport2World.eM22 +
223 dc->xformVport2World.eDy + 0.5 );
225 ret = TRUE;
226 break;
228 default:
229 WARN( "invalid mode %x\n", mode );
230 break;
233 release_dc_ptr( dc );
234 return ret;
238 /***********************************************************************
239 * lp_to_dp
241 * Internal version of LPtoDP that takes a DC *.
243 void lp_to_dp( DC *dc, POINT *points, INT count )
245 while (count--)
247 double x = points->x;
248 double y = points->y;
249 points->x = floor( x * dc->xformWorld2Vport.eM11 +
250 y * dc->xformWorld2Vport.eM21 +
251 dc->xformWorld2Vport.eDx + 0.5 );
252 points->y = floor( x * dc->xformWorld2Vport.eM12 +
253 y * dc->xformWorld2Vport.eM22 +
254 dc->xformWorld2Vport.eDy + 0.5 );
255 points++;
260 /***********************************************************************
261 * NtGdiComputeXformCoefficients (win32u.@)
263 BOOL WINAPI NtGdiComputeXformCoefficients( HDC hdc )
265 DC *dc;
267 if (!(dc = get_dc_ptr( hdc ))) return FALSE;
268 if (dc->attr->map_mode == MM_ISOTROPIC) MAPPING_FixIsotropic( dc );
269 DC_UpdateXforms( dc );
270 release_dc_ptr( dc );
271 return TRUE;
275 /***********************************************************************
276 * NtGdiScaleViewportExtEx (win32u.@)
278 BOOL WINAPI NtGdiScaleViewportExtEx( HDC hdc, INT x_num, INT x_denom,
279 INT y_num, INT y_denom, SIZE *size )
281 DC *dc;
283 if ((!(dc = get_dc_ptr( hdc )))) return FALSE;
285 if (size) *size = dc->attr->vport_ext;
287 if (dc->attr->map_mode == MM_ISOTROPIC || dc->attr->map_mode == MM_ANISOTROPIC)
289 if (!x_num || !x_denom || !y_num || !y_denom)
291 release_dc_ptr( dc );
292 return FALSE;
295 dc->attr->vport_ext.cx = (dc->attr->vport_ext.cx * x_num) / x_denom;
296 dc->attr->vport_ext.cy = (dc->attr->vport_ext.cy * y_num) / y_denom;
297 if (dc->attr->vport_ext.cx == 0) dc->attr->vport_ext.cx = 1;
298 if (dc->attr->vport_ext.cy == 0) dc->attr->vport_ext.cy = 1;
299 if (dc->attr->map_mode == MM_ISOTROPIC) MAPPING_FixIsotropic( dc );
300 DC_UpdateXforms( dc );
303 release_dc_ptr( dc );
304 return TRUE;
308 /***********************************************************************
309 * NtGdiScaleWindowExtEx (win32u.@)
311 BOOL WINAPI NtGdiScaleWindowExtEx( HDC hdc, INT x_num, INT x_denom,
312 INT y_num, INT y_denom, SIZE *size )
314 DC *dc;
316 if ((!(dc = get_dc_ptr( hdc )))) return FALSE;
318 if (size) *size = dc->attr->wnd_ext;
320 if (dc->attr->map_mode == MM_ISOTROPIC || dc->attr->map_mode == MM_ANISOTROPIC)
322 if (!x_num || !x_denom || !y_num || !y_denom)
324 release_dc_ptr( dc );
325 return FALSE;
328 dc->attr->wnd_ext.cx = (dc->attr->wnd_ext.cx * x_num) / x_denom;
329 dc->attr->wnd_ext.cy = (dc->attr->wnd_ext.cy * y_num) / y_denom;
330 if (dc->attr->wnd_ext.cx == 0) dc->attr->wnd_ext.cx = 1;
331 if (dc->attr->wnd_ext.cy == 0) dc->attr->wnd_ext.cy = 1;
332 if (dc->attr->map_mode == MM_ISOTROPIC) MAPPING_FixIsotropic( dc );
333 DC_UpdateXforms( dc );
336 release_dc_ptr( dc );
337 return TRUE;
341 /****************************************************************************
342 * NtGdiModifyWorldTransform (win32u.@)
344 BOOL WINAPI NtGdiModifyWorldTransform( HDC hdc, const XFORM *xform, DWORD mode )
346 BOOL ret = FALSE;
347 DC *dc;
349 if (!xform && mode != MWT_IDENTITY) return FALSE;
350 if ((dc = get_dc_ptr( hdc )))
352 switch (mode)
354 case MWT_IDENTITY:
355 dc->xformWorld2Wnd.eM11 = 1.0f;
356 dc->xformWorld2Wnd.eM12 = 0.0f;
357 dc->xformWorld2Wnd.eM21 = 0.0f;
358 dc->xformWorld2Wnd.eM22 = 1.0f;
359 dc->xformWorld2Wnd.eDx = 0.0f;
360 dc->xformWorld2Wnd.eDy = 0.0f;
361 ret = TRUE;
362 break;
363 case MWT_LEFTMULTIPLY:
364 ret = CombineTransform( &dc->xformWorld2Wnd, xform, &dc->xformWorld2Wnd );
365 break;
366 case MWT_RIGHTMULTIPLY:
367 ret = CombineTransform( &dc->xformWorld2Wnd, &dc->xformWorld2Wnd, xform );
368 break;
370 if (ret) DC_UpdateXforms( dc );
371 release_dc_ptr( dc );
373 return ret;
377 /***********************************************************************
378 * SetWorldTransform (GDI32.@)
380 BOOL WINAPI SetWorldTransform( HDC hdc, const XFORM *xform )
382 BOOL ret = FALSE;
383 DC *dc;
385 if (!xform) return FALSE;
386 /* The transform must conform to (eM11 * eM22 != eM12 * eM21) requirement */
387 if (xform->eM11 * xform->eM22 == xform->eM12 * xform->eM21) return FALSE;
389 TRACE("eM11 %f eM12 %f eM21 %f eM22 %f eDx %f eDy %f\n",
390 xform->eM11, xform->eM12, xform->eM21, xform->eM22, xform->eDx, xform->eDy);
392 if ((dc = get_dc_ptr( hdc )))
394 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetWorldTransform );
395 if (dc->attr->graphics_mode == GM_ADVANCED)
396 ret = physdev->funcs->pSetWorldTransform( physdev, xform );
397 release_dc_ptr( dc );
399 return ret;
403 /***********************************************************************
404 * NtGdiSetVirtualResolution (win32u.@)
406 * Undocumented on msdn.
408 * Changes the values of screen size in pixels and millimeters used by
409 * the mapping mode functions.
411 * PARAMS
412 * hdc [I] Device context
413 * horz_res [I] Width in pixels (equivalent to HORZRES device cap).
414 * vert_res [I] Height in pixels (equivalent to VERTRES device cap).
415 * horz_size [I] Width in mm (equivalent to HORZSIZE device cap).
416 * vert_size [I] Height in mm (equivalent to VERTSIZE device cap).
418 * RETURNS
419 * TRUE if successful.
420 * FALSE if any (but not all) of the last four params are zero.
422 * NOTES
423 * This doesn't change the values returned by GetDeviceCaps, just the
424 * scaling of the mapping modes.
426 * Calling with the last four params equal to zero sets the values
427 * back to their defaults obtained by calls to GetDeviceCaps.
429 BOOL WINAPI NtGdiSetVirtualResolution( HDC hdc, DWORD horz_res, DWORD vert_res,
430 DWORD horz_size, DWORD vert_size )
432 DC * dc;
433 TRACE("(%p %d %d %d %d)\n", hdc, horz_res, vert_res, horz_size, vert_size);
435 if (!horz_res || !vert_res || !horz_size || !vert_size)
437 /* they must be all zero */
438 if (horz_res || vert_res || horz_size || vert_size) return FALSE;
441 dc = get_dc_ptr( hdc );
442 if (!dc) return FALSE;
444 dc->attr->virtual_res.cx = horz_res;
445 dc->attr->virtual_res.cy = vert_res;
446 dc->attr->virtual_size.cx = horz_size;
447 dc->attr->virtual_size.cy = vert_size;
449 release_dc_ptr( dc );
450 return TRUE;