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
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
;
38 ret
.cx
= GetDeviceCaps( dc
->hSelf
, HORZSIZE
);
39 ret
.cy
= GetDeviceCaps( dc
->hSelf
, VERTSIZE
);
44 static SIZE
get_dc_virtual_res( DC
*dc
)
46 SIZE ret
= dc
->attr
->virtual_res
;
50 ret
.cx
= GetDeviceCaps( dc
->hSelf
, HORZRES
);
51 ret
.cy
= GetDeviceCaps( dc
->hSelf
, VERTRES
);
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
));
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
;
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
))
92 virtual_size
= get_dc_virtual_size( dc
);
93 virtual_res
= get_dc_virtual_res( dc
);
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;
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
;
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
;
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
;
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
;
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
;
138 /* RTL layout is always MM_ANISOTROPIC */
139 if (!(dc
->attr
->layout
& LAYOUT_RTL
)) dc
->attr
->map_mode
= mode
;
140 DC_UpdateXforms( dc
);
144 BOOL CDECL
nulldrv_ModifyWorldTransform( PHYSDEV dev
, const XFORM
*xform
, DWORD mode
)
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
);
158 /***********************************************************************
161 * Internal version of DPtoLP that takes a DC *.
163 BOOL
dp_to_lp( DC
*dc
, POINT
*points
, INT count
)
165 if (dc
->vport2WorldValid
)
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 );
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
);
193 if (!dc
) return FALSE
;
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 );
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 );
229 WARN( "invalid mode %x\n", mode
);
233 release_dc_ptr( dc
);
238 /***********************************************************************
241 * Internal version of LPtoDP that takes a DC *.
243 void lp_to_dp( DC
*dc
, POINT
*points
, INT 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 );
260 /***********************************************************************
261 * NtGdiComputeXformCoefficients (win32u.@)
263 BOOL WINAPI
NtGdiComputeXformCoefficients( HDC hdc
)
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
);
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
)
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
);
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
);
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
)
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
);
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
);
341 /****************************************************************************
342 * NtGdiModifyWorldTransform (win32u.@)
344 BOOL WINAPI
NtGdiModifyWorldTransform( HDC hdc
, const XFORM
*xform
, DWORD mode
)
349 if (!xform
&& mode
!= MWT_IDENTITY
) return FALSE
;
350 if ((dc
= get_dc_ptr( hdc
)))
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
;
363 case MWT_LEFTMULTIPLY
:
364 ret
= CombineTransform( &dc
->xformWorld2Wnd
, xform
, &dc
->xformWorld2Wnd
);
366 case MWT_RIGHTMULTIPLY
:
367 ret
= CombineTransform( &dc
->xformWorld2Wnd
, &dc
->xformWorld2Wnd
, xform
);
370 ret
= dc
->attr
->graphics_mode
== GM_ADVANCED
&&
371 xform
->eM11
* xform
->eM22
!= xform
->eM12
* xform
->eM21
;
372 if (ret
) dc
->xformWorld2Wnd
= *xform
;
375 if (ret
) DC_UpdateXforms( dc
);
376 release_dc_ptr( dc
);
382 /***********************************************************************
383 * SetWorldTransform (GDI32.@)
385 BOOL WINAPI
SetWorldTransform( HDC hdc
, const XFORM
*xform
)
390 if (!xform
) return FALSE
;
391 /* The transform must conform to (eM11 * eM22 != eM12 * eM21) requirement */
392 if (xform
->eM11
* xform
->eM22
== xform
->eM12
* xform
->eM21
) return FALSE
;
394 TRACE("eM11 %f eM12 %f eM21 %f eM22 %f eDx %f eDy %f\n",
395 xform
->eM11
, xform
->eM12
, xform
->eM21
, xform
->eM22
, xform
->eDx
, xform
->eDy
);
397 if ((dc
= get_dc_ptr( hdc
)))
399 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetWorldTransform
);
400 if (dc
->attr
->graphics_mode
== GM_ADVANCED
)
401 ret
= physdev
->funcs
->pSetWorldTransform( physdev
, xform
);
402 release_dc_ptr( dc
);
408 /***********************************************************************
409 * NtGdiSetVirtualResolution (win32u.@)
411 * Undocumented on msdn.
413 * Changes the values of screen size in pixels and millimeters used by
414 * the mapping mode functions.
417 * hdc [I] Device context
418 * horz_res [I] Width in pixels (equivalent to HORZRES device cap).
419 * vert_res [I] Height in pixels (equivalent to VERTRES device cap).
420 * horz_size [I] Width in mm (equivalent to HORZSIZE device cap).
421 * vert_size [I] Height in mm (equivalent to VERTSIZE device cap).
424 * TRUE if successful.
425 * FALSE if any (but not all) of the last four params are zero.
428 * This doesn't change the values returned by GetDeviceCaps, just the
429 * scaling of the mapping modes.
431 * Calling with the last four params equal to zero sets the values
432 * back to their defaults obtained by calls to GetDeviceCaps.
434 BOOL WINAPI
NtGdiSetVirtualResolution( HDC hdc
, DWORD horz_res
, DWORD vert_res
,
435 DWORD horz_size
, DWORD vert_size
)
438 TRACE("(%p %d %d %d %d)\n", hdc
, horz_res
, vert_res
, horz_size
, vert_size
);
440 if (!horz_res
|| !vert_res
|| !horz_size
|| !vert_size
)
442 /* they must be all zero */
443 if (horz_res
|| vert_res
|| horz_size
|| vert_size
) return FALSE
;
446 dc
= get_dc_ptr( hdc
);
447 if (!dc
) return FALSE
;
449 dc
->attr
->virtual_res
.cx
= horz_res
;
450 dc
->attr
->virtual_res
.cy
= vert_res
;
451 dc
->attr
->virtual_size
.cx
= horz_size
;
452 dc
->attr
->virtual_size
.cy
= vert_size
;
454 release_dc_ptr( dc
);