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 /***********************************************************************
33 * MAPPING_FixIsotropic
35 * Fix viewport extensions for isotropic mode.
37 static void MAPPING_FixIsotropic( DC
* dc
)
39 double xdim
= fabs((double)dc
->vportExtX
* dc
->virtual_size
.cx
/
40 (dc
->virtual_res
.cx
* dc
->wndExtX
));
41 double ydim
= fabs((double)dc
->vportExtY
* dc
->virtual_size
.cy
/
42 (dc
->virtual_res
.cy
* dc
->wndExtY
));
46 INT mincx
= (dc
->vportExtX
>= 0) ? 1 : -1;
47 dc
->vportExtX
= floor(dc
->vportExtX
* ydim
/ xdim
+ 0.5);
48 if (!dc
->vportExtX
) dc
->vportExtX
= mincx
;
52 INT mincy
= (dc
->vportExtY
>= 0) ? 1 : -1;
53 dc
->vportExtY
= floor(dc
->vportExtY
* xdim
/ ydim
+ 0.5);
54 if (!dc
->vportExtY
) dc
->vportExtY
= mincy
;
59 /***********************************************************************
60 * null driver fallback implementations
63 BOOL CDECL
nulldrv_OffsetViewportOrgEx( PHYSDEV dev
, INT x
, INT y
, POINT
*pt
)
65 DC
*dc
= get_nulldrv_dc( dev
);
69 pt
->x
= dc
->vportOrgX
;
70 pt
->y
= dc
->vportOrgY
;
74 DC_UpdateXforms( dc
);
78 BOOL CDECL
nulldrv_OffsetWindowOrgEx( PHYSDEV dev
, INT x
, INT y
, POINT
*pt
)
80 DC
*dc
= get_nulldrv_dc( dev
);
89 DC_UpdateXforms( dc
);
93 BOOL CDECL
nulldrv_ScaleViewportExtEx( PHYSDEV dev
, INT x_num
, INT x_denom
, INT y_num
, INT y_denom
,
96 DC
*dc
= get_nulldrv_dc( dev
);
100 size
->cx
= dc
->vportExtX
;
101 size
->cy
= dc
->vportExtY
;
103 if (dc
->MapMode
!= MM_ISOTROPIC
&& dc
->MapMode
!= MM_ANISOTROPIC
) return TRUE
;
104 if (!x_num
|| !x_denom
|| !y_num
|| !y_denom
) return FALSE
;
106 dc
->vportExtX
= (dc
->vportExtX
* x_num
) / x_denom
;
107 dc
->vportExtY
= (dc
->vportExtY
* y_num
) / y_denom
;
108 if (dc
->vportExtX
== 0) dc
->vportExtX
= 1;
109 if (dc
->vportExtY
== 0) dc
->vportExtY
= 1;
110 if (dc
->MapMode
== MM_ISOTROPIC
) MAPPING_FixIsotropic( dc
);
111 DC_UpdateXforms( dc
);
115 BOOL CDECL
nulldrv_ScaleWindowExtEx( PHYSDEV dev
, INT x_num
, INT x_denom
, INT y_num
, INT y_denom
,
118 DC
*dc
= get_nulldrv_dc( dev
);
122 size
->cx
= dc
->wndExtX
;
123 size
->cy
= dc
->wndExtY
;
125 if (dc
->MapMode
!= MM_ISOTROPIC
&& dc
->MapMode
!= MM_ANISOTROPIC
) return TRUE
;
126 if (!x_num
|| !x_denom
|| !y_num
|| !y_denom
) return FALSE
;
128 dc
->wndExtX
= (dc
->wndExtX
* x_num
) / x_denom
;
129 dc
->wndExtY
= (dc
->wndExtY
* y_num
) / y_denom
;
130 if (dc
->wndExtX
== 0) dc
->wndExtX
= 1;
131 if (dc
->wndExtY
== 0) dc
->wndExtY
= 1;
132 if (dc
->MapMode
== MM_ISOTROPIC
) MAPPING_FixIsotropic( dc
);
133 DC_UpdateXforms( dc
);
137 INT CDECL
nulldrv_SetMapMode( PHYSDEV dev
, INT mode
)
139 DC
*dc
= get_nulldrv_dc( dev
);
140 INT ret
= dc
->MapMode
;
141 INT horzSize
, vertSize
, horzRes
, vertRes
;
143 if (mode
== dc
->MapMode
&& (mode
== MM_ISOTROPIC
|| mode
== MM_ANISOTROPIC
)) return ret
;
145 horzSize
= dc
->virtual_size
.cx
;
146 vertSize
= dc
->virtual_size
.cy
;
147 horzRes
= dc
->virtual_res
.cx
;
148 vertRes
= dc
->virtual_res
.cy
;
159 dc
->wndExtX
= horzSize
* 10;
160 dc
->wndExtY
= vertSize
* 10;
161 dc
->vportExtX
= horzRes
;
162 dc
->vportExtY
= -vertRes
;
165 dc
->wndExtX
= horzSize
* 100;
166 dc
->wndExtY
= vertSize
* 100;
167 dc
->vportExtX
= horzRes
;
168 dc
->vportExtY
= -vertRes
;
171 dc
->wndExtX
= MulDiv(1000, horzSize
, 254);
172 dc
->wndExtY
= MulDiv(1000, vertSize
, 254);
173 dc
->vportExtX
= horzRes
;
174 dc
->vportExtY
= -vertRes
;
177 dc
->wndExtX
= MulDiv(10000, horzSize
, 254);
178 dc
->wndExtY
= MulDiv(10000, vertSize
, 254);
179 dc
->vportExtX
= horzRes
;
180 dc
->vportExtY
= -vertRes
;
183 dc
->wndExtX
= MulDiv(14400, horzSize
, 254);
184 dc
->wndExtY
= MulDiv(14400, vertSize
, 254);
185 dc
->vportExtX
= horzRes
;
186 dc
->vportExtY
= -vertRes
;
193 /* RTL layout is always MM_ANISOTROPIC */
194 if (!(dc
->layout
& LAYOUT_RTL
)) dc
->MapMode
= mode
;
195 DC_UpdateXforms( dc
);
199 BOOL CDECL
nulldrv_SetViewportExtEx( PHYSDEV dev
, INT cx
, INT cy
, SIZE
*size
)
201 DC
*dc
= get_nulldrv_dc( dev
);
205 size
->cx
= dc
->vportExtX
;
206 size
->cy
= dc
->vportExtY
;
208 if (dc
->MapMode
!= MM_ISOTROPIC
&& dc
->MapMode
!= MM_ANISOTROPIC
) return TRUE
;
209 if (!cx
|| !cy
) return FALSE
;
212 if (dc
->MapMode
== MM_ISOTROPIC
) MAPPING_FixIsotropic( dc
);
213 DC_UpdateXforms( dc
);
217 BOOL CDECL
nulldrv_SetViewportOrgEx( PHYSDEV dev
, INT x
, INT y
, POINT
*pt
)
219 DC
*dc
= get_nulldrv_dc( dev
);
223 pt
->x
= dc
->vportOrgX
;
224 pt
->y
= dc
->vportOrgY
;
228 DC_UpdateXforms( dc
);
232 BOOL CDECL
nulldrv_SetWindowExtEx( PHYSDEV dev
, INT cx
, INT cy
, SIZE
*size
)
234 DC
*dc
= get_nulldrv_dc( dev
);
238 size
->cx
= dc
->wndExtX
;
239 size
->cy
= dc
->wndExtY
;
241 if (dc
->MapMode
!= MM_ISOTROPIC
&& dc
->MapMode
!= MM_ANISOTROPIC
) return TRUE
;
242 if (!cx
|| !cy
) return FALSE
;
245 /* The API docs say that you should call SetWindowExtEx before
246 SetViewportExtEx. This advice does not imply that Windows
247 doesn't ensure the isotropic mapping after SetWindowExtEx! */
248 if (dc
->MapMode
== MM_ISOTROPIC
) MAPPING_FixIsotropic( dc
);
249 DC_UpdateXforms( dc
);
253 BOOL CDECL
nulldrv_SetWindowOrgEx( PHYSDEV dev
, INT x
, INT y
, POINT
*pt
)
255 DC
*dc
= get_nulldrv_dc( dev
);
264 DC_UpdateXforms( dc
);
268 BOOL CDECL
nulldrv_ModifyWorldTransform( PHYSDEV dev
, const XFORM
*xform
, DWORD mode
)
270 DC
*dc
= get_nulldrv_dc( dev
);
275 dc
->xformWorld2Wnd
.eM11
= 1.0f
;
276 dc
->xformWorld2Wnd
.eM12
= 0.0f
;
277 dc
->xformWorld2Wnd
.eM21
= 0.0f
;
278 dc
->xformWorld2Wnd
.eM22
= 1.0f
;
279 dc
->xformWorld2Wnd
.eDx
= 0.0f
;
280 dc
->xformWorld2Wnd
.eDy
= 0.0f
;
282 case MWT_LEFTMULTIPLY
:
283 CombineTransform( &dc
->xformWorld2Wnd
, xform
, &dc
->xformWorld2Wnd
);
285 case MWT_RIGHTMULTIPLY
:
286 CombineTransform( &dc
->xformWorld2Wnd
, &dc
->xformWorld2Wnd
, xform
);
291 DC_UpdateXforms( dc
);
295 BOOL CDECL
nulldrv_SetWorldTransform( PHYSDEV dev
, const XFORM
*xform
)
297 DC
*dc
= get_nulldrv_dc( dev
);
299 dc
->xformWorld2Wnd
= *xform
;
300 DC_UpdateXforms( dc
);
304 /***********************************************************************
307 BOOL WINAPI
DPtoLP( HDC hdc
, LPPOINT points
, INT count
)
309 DC
* dc
= get_dc_ptr( hdc
);
310 if (!dc
) return FALSE
;
312 if (dc
->vport2WorldValid
)
316 double x
= points
->x
;
317 double y
= points
->y
;
318 points
->x
= floor( x
* dc
->xformVport2World
.eM11
+
319 y
* dc
->xformVport2World
.eM21
+
320 dc
->xformVport2World
.eDx
+ 0.5 );
321 points
->y
= floor( x
* dc
->xformVport2World
.eM12
+
322 y
* dc
->xformVport2World
.eM22
+
323 dc
->xformVport2World
.eDy
+ 0.5 );
327 release_dc_ptr( dc
);
332 /***********************************************************************
335 BOOL WINAPI
LPtoDP( HDC hdc
, LPPOINT points
, INT count
)
337 DC
* dc
= get_dc_ptr( hdc
);
338 if (!dc
) return FALSE
;
342 double x
= points
->x
;
343 double y
= points
->y
;
344 points
->x
= floor( x
* dc
->xformWorld2Vport
.eM11
+
345 y
* dc
->xformWorld2Vport
.eM21
+
346 dc
->xformWorld2Vport
.eDx
+ 0.5 );
347 points
->y
= floor( x
* dc
->xformWorld2Vport
.eM12
+
348 y
* dc
->xformWorld2Vport
.eM22
+
349 dc
->xformWorld2Vport
.eDy
+ 0.5 );
352 release_dc_ptr( dc
);
357 /***********************************************************************
358 * SetMapMode (GDI32.@)
360 INT WINAPI
SetMapMode( HDC hdc
, INT mode
)
363 DC
* dc
= get_dc_ptr( hdc
);
365 TRACE("%p %d\n", hdc
, mode
);
369 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetMapMode
);
370 ret
= physdev
->funcs
->pSetMapMode( physdev
, mode
);
371 release_dc_ptr( dc
);
377 /***********************************************************************
378 * SetViewportExtEx (GDI32.@)
380 BOOL WINAPI
SetViewportExtEx( HDC hdc
, INT x
, INT y
, LPSIZE size
)
383 DC
* dc
= get_dc_ptr( hdc
);
387 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetViewportExtEx
);
388 ret
= physdev
->funcs
->pSetViewportExtEx( physdev
, x
, y
, size
);
389 release_dc_ptr( dc
);
395 /***********************************************************************
396 * SetViewportOrgEx (GDI32.@)
398 BOOL WINAPI
SetViewportOrgEx( HDC hdc
, INT x
, INT y
, LPPOINT pt
)
401 DC
* dc
= get_dc_ptr( hdc
);
405 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetViewportOrgEx
);
406 ret
= physdev
->funcs
->pSetViewportOrgEx( physdev
, x
, y
, pt
);
407 release_dc_ptr( dc
);
413 /***********************************************************************
414 * SetWindowExtEx (GDI32.@)
416 BOOL WINAPI
SetWindowExtEx( HDC hdc
, INT x
, INT y
, LPSIZE size
)
419 DC
* dc
= get_dc_ptr( hdc
);
423 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetWindowExtEx
);
424 ret
= physdev
->funcs
->pSetWindowExtEx( physdev
, x
, y
, size
);
425 release_dc_ptr( dc
);
431 /***********************************************************************
432 * SetWindowOrgEx (GDI32.@)
434 BOOL WINAPI
SetWindowOrgEx( HDC hdc
, INT x
, INT y
, LPPOINT pt
)
437 DC
* dc
= get_dc_ptr( hdc
);
441 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetWindowOrgEx
);
442 ret
= physdev
->funcs
->pSetWindowOrgEx( physdev
, x
, y
, pt
);
443 release_dc_ptr( dc
);
449 /***********************************************************************
450 * OffsetViewportOrgEx (GDI32.@)
452 BOOL WINAPI
OffsetViewportOrgEx( HDC hdc
, INT x
, INT y
, LPPOINT pt
)
455 DC
* dc
= get_dc_ptr( hdc
);
459 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pOffsetViewportOrgEx
);
460 ret
= physdev
->funcs
->pOffsetViewportOrgEx( physdev
, x
, y
, pt
);
461 release_dc_ptr( dc
);
467 /***********************************************************************
468 * OffsetWindowOrgEx (GDI32.@)
470 BOOL WINAPI
OffsetWindowOrgEx( HDC hdc
, INT x
, INT y
, LPPOINT pt
)
473 DC
* dc
= get_dc_ptr( hdc
);
477 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pOffsetWindowOrgEx
);
478 ret
= physdev
->funcs
->pOffsetWindowOrgEx( physdev
, x
, y
, pt
);
479 release_dc_ptr( dc
);
485 /***********************************************************************
486 * ScaleViewportExtEx (GDI32.@)
488 BOOL WINAPI
ScaleViewportExtEx( HDC hdc
, INT xNum
, INT xDenom
,
489 INT yNum
, INT yDenom
, LPSIZE size
)
492 DC
* dc
= get_dc_ptr( hdc
);
496 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pScaleViewportExtEx
);
497 ret
= physdev
->funcs
->pScaleViewportExtEx( physdev
, xNum
, xDenom
, yNum
, yDenom
, size
);
498 release_dc_ptr( dc
);
504 /***********************************************************************
505 * ScaleWindowExtEx (GDI32.@)
507 BOOL WINAPI
ScaleWindowExtEx( HDC hdc
, INT xNum
, INT xDenom
,
508 INT yNum
, INT yDenom
, LPSIZE size
)
511 DC
* dc
= get_dc_ptr( hdc
);
515 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pScaleWindowExtEx
);
516 ret
= physdev
->funcs
->pScaleWindowExtEx( physdev
, xNum
, xDenom
, yNum
, yDenom
, size
);
517 release_dc_ptr( dc
);
523 /****************************************************************************
524 * ModifyWorldTransform (GDI32.@)
526 BOOL WINAPI
ModifyWorldTransform( HDC hdc
, const XFORM
*xform
, DWORD mode
)
531 if (!xform
&& mode
!= MWT_IDENTITY
) return FALSE
;
532 if ((dc
= get_dc_ptr( hdc
)))
534 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pModifyWorldTransform
);
535 if (dc
->GraphicsMode
== GM_ADVANCED
)
536 ret
= physdev
->funcs
->pModifyWorldTransform( physdev
, xform
, mode
);
537 release_dc_ptr( dc
);
543 /***********************************************************************
544 * SetWorldTransform (GDI32.@)
546 BOOL WINAPI
SetWorldTransform( HDC hdc
, const XFORM
*xform
)
551 if (!xform
) return FALSE
;
552 /* The transform must conform to (eM11 * eM22 != eM12 * eM21) requirement */
553 if (xform
->eM11
* xform
->eM22
== xform
->eM12
* xform
->eM21
) return FALSE
;
555 TRACE("eM11 %f eM12 %f eM21 %f eM22 %f eDx %f eDy %f\n",
556 xform
->eM11
, xform
->eM12
, xform
->eM21
, xform
->eM22
, xform
->eDx
, xform
->eDy
);
558 if ((dc
= get_dc_ptr( hdc
)))
560 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetWorldTransform
);
561 if (dc
->GraphicsMode
== GM_ADVANCED
)
562 ret
= physdev
->funcs
->pSetWorldTransform( physdev
, xform
);
563 release_dc_ptr( dc
);
569 /***********************************************************************
570 * SetVirtualResolution (GDI32.@)
572 * Undocumented on msdn.
574 * Changes the values of screen size in pixels and millimeters used by
575 * the mapping mode functions.
578 * hdc [I] Device context
579 * horz_res [I] Width in pixels (equivalent to HORZRES device cap).
580 * vert_res [I] Height in pixels (equivalent to VERTRES device cap).
581 * horz_size [I] Width in mm (equivalent to HORZSIZE device cap).
582 * vert_size [I] Height in mm (equivalent to VERTSIZE device cap).
585 * TRUE if successful.
586 * FALSE if any (but not all) of the last four params are zero.
589 * This doesn't change the values returned by GetDeviceCaps, just the
590 * scaling of the mapping modes.
592 * Calling with the last four params equal to zero sets the values
593 * back to their defaults obtained by calls to GetDeviceCaps.
595 BOOL WINAPI
SetVirtualResolution(HDC hdc
, DWORD horz_res
, DWORD vert_res
,
596 DWORD horz_size
, DWORD vert_size
)
599 TRACE("(%p %d %d %d %d)\n", hdc
, horz_res
, vert_res
, horz_size
, vert_size
);
601 if(horz_res
== 0 && vert_res
== 0 && horz_size
== 0 && vert_size
== 0)
603 horz_res
= GetDeviceCaps(hdc
, HORZRES
);
604 vert_res
= GetDeviceCaps(hdc
, VERTRES
);
605 horz_size
= GetDeviceCaps(hdc
, HORZSIZE
);
606 vert_size
= GetDeviceCaps(hdc
, VERTSIZE
);
608 else if(horz_res
== 0 || vert_res
== 0 || horz_size
== 0 || vert_size
== 0)
611 dc
= get_dc_ptr( hdc
);
612 if (!dc
) return FALSE
;
614 dc
->virtual_res
.cx
= horz_res
;
615 dc
->virtual_res
.cy
= vert_res
;
616 dc
->virtual_size
.cx
= horz_size
;
617 dc
->virtual_size
.cy
= vert_size
;
619 release_dc_ptr( dc
);