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 "gdi_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
->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
->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
->vportExtX
* virtual_size
.cx
/ (virtual_res
.cx
* dc
->wndExtX
));
66 double ydim
= fabs((double)dc
->vportExtY
* virtual_size
.cy
/ (virtual_res
.cy
* dc
->wndExtY
));
70 INT mincx
= (dc
->vportExtX
>= 0) ? 1 : -1;
71 dc
->vportExtX
= floor(dc
->vportExtX
* ydim
/ xdim
+ 0.5);
72 if (!dc
->vportExtX
) dc
->vportExtX
= mincx
;
76 INT mincy
= (dc
->vportExtY
>= 0) ? 1 : -1;
77 dc
->vportExtY
= floor(dc
->vportExtY
* xdim
/ ydim
+ 0.5);
78 if (!dc
->vportExtY
) dc
->vportExtY
= mincy
;
83 /***********************************************************************
84 * null driver fallback implementations
87 BOOL
nulldrv_OffsetViewportOrgEx( PHYSDEV dev
, INT x
, INT y
, POINT
*pt
)
89 DC
*dc
= get_nulldrv_dc( dev
);
93 pt
->x
= dc
->vportOrgX
;
94 pt
->y
= dc
->vportOrgY
;
98 DC_UpdateXforms( dc
);
102 BOOL
nulldrv_OffsetWindowOrgEx( PHYSDEV dev
, INT x
, INT y
, POINT
*pt
)
104 DC
*dc
= get_nulldrv_dc( dev
);
113 DC_UpdateXforms( dc
);
117 BOOL
nulldrv_ScaleViewportExtEx( PHYSDEV dev
, INT x_num
, INT x_denom
, INT y_num
, INT y_denom
, SIZE
*size
)
119 DC
*dc
= get_nulldrv_dc( dev
);
123 size
->cx
= dc
->vportExtX
;
124 size
->cy
= dc
->vportExtY
;
126 if (dc
->MapMode
!= MM_ISOTROPIC
&& dc
->MapMode
!= MM_ANISOTROPIC
) return TRUE
;
127 if (!x_num
|| !x_denom
|| !y_num
|| !y_denom
) return FALSE
;
129 dc
->vportExtX
= (dc
->vportExtX
* x_num
) / x_denom
;
130 dc
->vportExtY
= (dc
->vportExtY
* y_num
) / y_denom
;
131 if (dc
->vportExtX
== 0) dc
->vportExtX
= 1;
132 if (dc
->vportExtY
== 0) dc
->vportExtY
= 1;
133 if (dc
->MapMode
== MM_ISOTROPIC
) MAPPING_FixIsotropic( dc
);
134 DC_UpdateXforms( dc
);
138 BOOL
nulldrv_ScaleWindowExtEx( PHYSDEV dev
, INT x_num
, INT x_denom
, INT y_num
, INT y_denom
, SIZE
*size
)
140 DC
*dc
= get_nulldrv_dc( dev
);
144 size
->cx
= dc
->wndExtX
;
145 size
->cy
= dc
->wndExtY
;
147 if (dc
->MapMode
!= MM_ISOTROPIC
&& dc
->MapMode
!= MM_ANISOTROPIC
) return TRUE
;
148 if (!x_num
|| !x_denom
|| !y_num
|| !y_denom
) return FALSE
;
150 dc
->wndExtX
= (dc
->wndExtX
* x_num
) / x_denom
;
151 dc
->wndExtY
= (dc
->wndExtY
* y_num
) / y_denom
;
152 if (dc
->wndExtX
== 0) dc
->wndExtX
= 1;
153 if (dc
->wndExtY
== 0) dc
->wndExtY
= 1;
154 if (dc
->MapMode
== MM_ISOTROPIC
) MAPPING_FixIsotropic( dc
);
155 DC_UpdateXforms( dc
);
159 INT
nulldrv_SetMapMode( PHYSDEV dev
, INT mode
)
161 DC
*dc
= get_nulldrv_dc( dev
);
162 INT ret
= dc
->MapMode
;
163 SIZE virtual_size
, virtual_res
;
165 if (mode
== dc
->MapMode
&& (mode
== MM_ISOTROPIC
|| mode
== MM_ANISOTROPIC
)) return ret
;
167 virtual_size
= get_dc_virtual_size( dc
);
168 virtual_res
= get_dc_virtual_res( dc
);
179 dc
->wndExtX
= virtual_size
.cx
* 10;
180 dc
->wndExtY
= virtual_size
.cy
* 10;
181 dc
->vportExtX
= virtual_res
.cx
;
182 dc
->vportExtY
= -virtual_res
.cy
;
185 dc
->wndExtX
= virtual_size
.cx
* 100;
186 dc
->wndExtY
= virtual_size
.cy
* 100;
187 dc
->vportExtX
= virtual_res
.cx
;
188 dc
->vportExtY
= -virtual_res
.cy
;
191 dc
->wndExtX
= MulDiv(1000, virtual_size
.cx
, 254);
192 dc
->wndExtY
= MulDiv(1000, virtual_size
.cy
, 254);
193 dc
->vportExtX
= virtual_res
.cx
;
194 dc
->vportExtY
= -virtual_res
.cy
;
197 dc
->wndExtX
= MulDiv(10000, virtual_size
.cx
, 254);
198 dc
->wndExtY
= MulDiv(10000, virtual_size
.cy
, 254);
199 dc
->vportExtX
= virtual_res
.cx
;
200 dc
->vportExtY
= -virtual_res
.cy
;
203 dc
->wndExtX
= MulDiv(14400, virtual_size
.cx
, 254);
204 dc
->wndExtY
= MulDiv(14400, virtual_size
.cy
, 254);
205 dc
->vportExtX
= virtual_res
.cx
;
206 dc
->vportExtY
= -virtual_res
.cy
;
213 /* RTL layout is always MM_ANISOTROPIC */
214 if (!(dc
->layout
& LAYOUT_RTL
)) dc
->MapMode
= mode
;
215 DC_UpdateXforms( dc
);
219 BOOL
nulldrv_SetViewportExtEx( PHYSDEV dev
, INT cx
, INT cy
, SIZE
*size
)
221 DC
*dc
= get_nulldrv_dc( dev
);
225 size
->cx
= dc
->vportExtX
;
226 size
->cy
= dc
->vportExtY
;
228 if (dc
->MapMode
!= MM_ISOTROPIC
&& dc
->MapMode
!= MM_ANISOTROPIC
) return TRUE
;
229 if (!cx
|| !cy
) return FALSE
;
232 if (dc
->MapMode
== MM_ISOTROPIC
) MAPPING_FixIsotropic( dc
);
233 DC_UpdateXforms( dc
);
237 BOOL
nulldrv_SetViewportOrgEx( PHYSDEV dev
, INT x
, INT y
, POINT
*pt
)
239 DC
*dc
= get_nulldrv_dc( dev
);
243 pt
->x
= dc
->vportOrgX
;
244 pt
->y
= dc
->vportOrgY
;
248 DC_UpdateXforms( dc
);
252 BOOL
nulldrv_SetWindowExtEx( PHYSDEV dev
, INT cx
, INT cy
, SIZE
*size
)
254 DC
*dc
= get_nulldrv_dc( dev
);
258 size
->cx
= dc
->wndExtX
;
259 size
->cy
= dc
->wndExtY
;
261 if (dc
->MapMode
!= MM_ISOTROPIC
&& dc
->MapMode
!= MM_ANISOTROPIC
) return TRUE
;
262 if (!cx
|| !cy
) return FALSE
;
265 /* The API docs say that you should call SetWindowExtEx before
266 SetViewportExtEx. This advice does not imply that Windows
267 doesn't ensure the isotropic mapping after SetWindowExtEx! */
268 if (dc
->MapMode
== MM_ISOTROPIC
) MAPPING_FixIsotropic( dc
);
269 DC_UpdateXforms( dc
);
273 BOOL
nulldrv_SetWindowOrgEx( PHYSDEV dev
, INT x
, INT y
, POINT
*pt
)
275 DC
*dc
= get_nulldrv_dc( dev
);
284 DC_UpdateXforms( dc
);
288 BOOL
nulldrv_ModifyWorldTransform( PHYSDEV dev
, const XFORM
*xform
, DWORD mode
)
290 DC
*dc
= get_nulldrv_dc( dev
);
295 dc
->xformWorld2Wnd
.eM11
= 1.0f
;
296 dc
->xformWorld2Wnd
.eM12
= 0.0f
;
297 dc
->xformWorld2Wnd
.eM21
= 0.0f
;
298 dc
->xformWorld2Wnd
.eM22
= 1.0f
;
299 dc
->xformWorld2Wnd
.eDx
= 0.0f
;
300 dc
->xformWorld2Wnd
.eDy
= 0.0f
;
302 case MWT_LEFTMULTIPLY
:
303 CombineTransform( &dc
->xformWorld2Wnd
, xform
, &dc
->xformWorld2Wnd
);
305 case MWT_RIGHTMULTIPLY
:
306 CombineTransform( &dc
->xformWorld2Wnd
, &dc
->xformWorld2Wnd
, xform
);
311 DC_UpdateXforms( dc
);
315 BOOL
nulldrv_SetWorldTransform( PHYSDEV dev
, const XFORM
*xform
)
317 DC
*dc
= get_nulldrv_dc( dev
);
319 dc
->xformWorld2Wnd
= *xform
;
320 DC_UpdateXforms( dc
);
324 /***********************************************************************
327 BOOL WINAPI
DPtoLP( HDC hdc
, LPPOINT points
, INT count
)
329 DC
* dc
= get_dc_ptr( hdc
);
330 if (!dc
) return FALSE
;
332 if (dc
->vport2WorldValid
)
336 double x
= points
->x
;
337 double y
= points
->y
;
338 points
->x
= floor( x
* dc
->xformVport2World
.eM11
+
339 y
* dc
->xformVport2World
.eM21
+
340 dc
->xformVport2World
.eDx
+ 0.5 );
341 points
->y
= floor( x
* dc
->xformVport2World
.eM12
+
342 y
* dc
->xformVport2World
.eM22
+
343 dc
->xformVport2World
.eDy
+ 0.5 );
347 release_dc_ptr( dc
);
352 /***********************************************************************
355 BOOL WINAPI
LPtoDP( HDC hdc
, LPPOINT points
, INT count
)
357 DC
* dc
= get_dc_ptr( hdc
);
358 if (!dc
) return FALSE
;
362 double x
= points
->x
;
363 double y
= points
->y
;
364 points
->x
= floor( x
* dc
->xformWorld2Vport
.eM11
+
365 y
* dc
->xformWorld2Vport
.eM21
+
366 dc
->xformWorld2Vport
.eDx
+ 0.5 );
367 points
->y
= floor( x
* dc
->xformWorld2Vport
.eM12
+
368 y
* dc
->xformWorld2Vport
.eM22
+
369 dc
->xformWorld2Vport
.eDy
+ 0.5 );
372 release_dc_ptr( dc
);
377 /***********************************************************************
378 * SetMapMode (GDI32.@)
380 INT WINAPI
SetMapMode( HDC hdc
, INT mode
)
383 DC
* dc
= get_dc_ptr( hdc
);
385 TRACE("%p %d\n", hdc
, mode
);
389 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetMapMode
);
390 ret
= physdev
->funcs
->pSetMapMode( physdev
, mode
);
391 release_dc_ptr( dc
);
397 /***********************************************************************
398 * SetViewportExtEx (GDI32.@)
400 BOOL WINAPI
SetViewportExtEx( HDC hdc
, INT x
, INT y
, LPSIZE size
)
403 DC
* dc
= get_dc_ptr( hdc
);
407 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetViewportExtEx
);
408 ret
= physdev
->funcs
->pSetViewportExtEx( physdev
, x
, y
, size
);
409 release_dc_ptr( dc
);
415 /***********************************************************************
416 * SetViewportOrgEx (GDI32.@)
418 BOOL WINAPI
SetViewportOrgEx( HDC hdc
, INT x
, INT y
, LPPOINT pt
)
421 DC
* dc
= get_dc_ptr( hdc
);
425 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetViewportOrgEx
);
426 ret
= physdev
->funcs
->pSetViewportOrgEx( physdev
, x
, y
, pt
);
427 release_dc_ptr( dc
);
433 /***********************************************************************
434 * SetWindowExtEx (GDI32.@)
436 BOOL WINAPI
SetWindowExtEx( HDC hdc
, INT x
, INT y
, LPSIZE size
)
439 DC
* dc
= get_dc_ptr( hdc
);
443 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetWindowExtEx
);
444 ret
= physdev
->funcs
->pSetWindowExtEx( physdev
, x
, y
, size
);
445 release_dc_ptr( dc
);
451 /***********************************************************************
452 * SetWindowOrgEx (GDI32.@)
454 BOOL WINAPI
SetWindowOrgEx( HDC hdc
, INT x
, INT y
, LPPOINT pt
)
457 DC
* dc
= get_dc_ptr( hdc
);
461 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetWindowOrgEx
);
462 ret
= physdev
->funcs
->pSetWindowOrgEx( physdev
, x
, y
, pt
);
463 release_dc_ptr( dc
);
469 /***********************************************************************
470 * OffsetViewportOrgEx (GDI32.@)
472 BOOL WINAPI
OffsetViewportOrgEx( HDC hdc
, INT x
, INT y
, LPPOINT pt
)
475 DC
* dc
= get_dc_ptr( hdc
);
479 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pOffsetViewportOrgEx
);
480 ret
= physdev
->funcs
->pOffsetViewportOrgEx( physdev
, x
, y
, pt
);
481 release_dc_ptr( dc
);
487 /***********************************************************************
488 * OffsetWindowOrgEx (GDI32.@)
490 BOOL WINAPI
OffsetWindowOrgEx( HDC hdc
, INT x
, INT y
, LPPOINT pt
)
493 DC
* dc
= get_dc_ptr( hdc
);
497 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pOffsetWindowOrgEx
);
498 ret
= physdev
->funcs
->pOffsetWindowOrgEx( physdev
, x
, y
, pt
);
499 release_dc_ptr( dc
);
505 /***********************************************************************
506 * ScaleViewportExtEx (GDI32.@)
508 BOOL WINAPI
ScaleViewportExtEx( HDC hdc
, INT xNum
, INT xDenom
,
509 INT yNum
, INT yDenom
, LPSIZE size
)
512 DC
* dc
= get_dc_ptr( hdc
);
516 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pScaleViewportExtEx
);
517 ret
= physdev
->funcs
->pScaleViewportExtEx( physdev
, xNum
, xDenom
, yNum
, yDenom
, size
);
518 release_dc_ptr( dc
);
524 /***********************************************************************
525 * ScaleWindowExtEx (GDI32.@)
527 BOOL WINAPI
ScaleWindowExtEx( HDC hdc
, INT xNum
, INT xDenom
,
528 INT yNum
, INT yDenom
, LPSIZE size
)
531 DC
* dc
= get_dc_ptr( hdc
);
535 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pScaleWindowExtEx
);
536 ret
= physdev
->funcs
->pScaleWindowExtEx( physdev
, xNum
, xDenom
, yNum
, yDenom
, size
);
537 release_dc_ptr( dc
);
543 /****************************************************************************
544 * ModifyWorldTransform (GDI32.@)
546 BOOL WINAPI
ModifyWorldTransform( HDC hdc
, const XFORM
*xform
, DWORD mode
)
551 if (!xform
&& mode
!= MWT_IDENTITY
) return FALSE
;
552 if ((dc
= get_dc_ptr( hdc
)))
554 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pModifyWorldTransform
);
555 if (dc
->GraphicsMode
== GM_ADVANCED
)
556 ret
= physdev
->funcs
->pModifyWorldTransform( physdev
, xform
, mode
);
557 release_dc_ptr( dc
);
563 /***********************************************************************
564 * SetWorldTransform (GDI32.@)
566 BOOL WINAPI
SetWorldTransform( HDC hdc
, const XFORM
*xform
)
571 if (!xform
) return FALSE
;
572 /* The transform must conform to (eM11 * eM22 != eM12 * eM21) requirement */
573 if (xform
->eM11
* xform
->eM22
== xform
->eM12
* xform
->eM21
) return FALSE
;
575 TRACE("eM11 %f eM12 %f eM21 %f eM22 %f eDx %f eDy %f\n",
576 xform
->eM11
, xform
->eM12
, xform
->eM21
, xform
->eM22
, xform
->eDx
, xform
->eDy
);
578 if ((dc
= get_dc_ptr( hdc
)))
580 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetWorldTransform
);
581 if (dc
->GraphicsMode
== GM_ADVANCED
)
582 ret
= physdev
->funcs
->pSetWorldTransform( physdev
, xform
);
583 release_dc_ptr( dc
);
589 /***********************************************************************
590 * SetVirtualResolution (GDI32.@)
592 * Undocumented on msdn.
594 * Changes the values of screen size in pixels and millimeters used by
595 * the mapping mode functions.
598 * hdc [I] Device context
599 * horz_res [I] Width in pixels (equivalent to HORZRES device cap).
600 * vert_res [I] Height in pixels (equivalent to VERTRES device cap).
601 * horz_size [I] Width in mm (equivalent to HORZSIZE device cap).
602 * vert_size [I] Height in mm (equivalent to VERTSIZE device cap).
605 * TRUE if successful.
606 * FALSE if any (but not all) of the last four params are zero.
609 * This doesn't change the values returned by GetDeviceCaps, just the
610 * scaling of the mapping modes.
612 * Calling with the last four params equal to zero sets the values
613 * back to their defaults obtained by calls to GetDeviceCaps.
615 BOOL WINAPI
SetVirtualResolution(HDC hdc
, DWORD horz_res
, DWORD vert_res
,
616 DWORD horz_size
, DWORD vert_size
)
619 TRACE("(%p %d %d %d %d)\n", hdc
, horz_res
, vert_res
, horz_size
, vert_size
);
621 if (!horz_res
|| !vert_res
|| !horz_size
|| !vert_size
)
623 /* they must be all zero */
624 if (horz_res
|| vert_res
|| horz_size
|| vert_size
) return FALSE
;
627 dc
= get_dc_ptr( hdc
);
628 if (!dc
) return FALSE
;
630 dc
->virtual_res
.cx
= horz_res
;
631 dc
->virtual_res
.cy
= vert_res
;
632 dc
->virtual_size
.cx
= horz_size
;
633 dc
->virtual_size
.cy
= vert_size
;
635 release_dc_ptr( dc
);