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
->vport_ext
.cx
* virtual_size
.cx
/ (virtual_res
.cx
* dc
->wnd_ext
.cx
));
66 double ydim
= fabs((double)dc
->vport_ext
.cy
* virtual_size
.cy
/ (virtual_res
.cy
* dc
->wnd_ext
.cy
));
70 INT mincx
= (dc
->vport_ext
.cx
>= 0) ? 1 : -1;
71 dc
->vport_ext
.cx
= floor(dc
->vport_ext
.cx
* ydim
/ xdim
+ 0.5);
72 if (!dc
->vport_ext
.cx
) dc
->vport_ext
.cx
= mincx
;
76 INT mincy
= (dc
->vport_ext
.cy
>= 0) ? 1 : -1;
77 dc
->vport_ext
.cy
= floor(dc
->vport_ext
.cy
* xdim
/ ydim
+ 0.5);
78 if (!dc
->vport_ext
.cy
) dc
->vport_ext
.cy
= mincy
;
83 /***********************************************************************
84 * null driver fallback implementations
87 BOOL CDECL
nulldrv_OffsetViewportOrgEx( PHYSDEV dev
, INT x
, INT y
, POINT
*pt
)
89 DC
*dc
= get_nulldrv_dc( dev
);
96 DC_UpdateXforms( dc
);
100 BOOL CDECL
nulldrv_OffsetWindowOrgEx( PHYSDEV dev
, INT x
, INT y
, POINT
*pt
)
102 DC
*dc
= get_nulldrv_dc( dev
);
109 DC_UpdateXforms( dc
);
113 BOOL CDECL
nulldrv_ScaleViewportExtEx( PHYSDEV dev
, INT x_num
, INT x_denom
, INT y_num
, INT y_denom
, SIZE
*size
)
115 DC
*dc
= get_nulldrv_dc( dev
);
118 *size
= dc
->vport_ext
;
120 if (dc
->MapMode
!= MM_ISOTROPIC
&& dc
->MapMode
!= MM_ANISOTROPIC
) return TRUE
;
121 if (!x_num
|| !x_denom
|| !y_num
|| !y_denom
) return FALSE
;
123 dc
->vport_ext
.cx
= (dc
->vport_ext
.cx
* x_num
) / x_denom
;
124 dc
->vport_ext
.cy
= (dc
->vport_ext
.cy
* y_num
) / y_denom
;
125 if (dc
->vport_ext
.cx
== 0) dc
->vport_ext
.cx
= 1;
126 if (dc
->vport_ext
.cy
== 0) dc
->vport_ext
.cy
= 1;
127 if (dc
->MapMode
== MM_ISOTROPIC
) MAPPING_FixIsotropic( dc
);
128 DC_UpdateXforms( dc
);
132 BOOL CDECL
nulldrv_ScaleWindowExtEx( PHYSDEV dev
, INT x_num
, INT x_denom
, INT y_num
, INT y_denom
, SIZE
*size
)
134 DC
*dc
= get_nulldrv_dc( dev
);
139 if (dc
->MapMode
!= MM_ISOTROPIC
&& dc
->MapMode
!= MM_ANISOTROPIC
) return TRUE
;
140 if (!x_num
|| !x_denom
|| !y_num
|| !y_denom
) return FALSE
;
142 dc
->wnd_ext
.cx
= (dc
->wnd_ext
.cx
* x_num
) / x_denom
;
143 dc
->wnd_ext
.cy
= (dc
->wnd_ext
.cy
* y_num
) / y_denom
;
144 if (dc
->wnd_ext
.cx
== 0) dc
->wnd_ext
.cx
= 1;
145 if (dc
->wnd_ext
.cy
== 0) dc
->wnd_ext
.cy
= 1;
146 if (dc
->MapMode
== MM_ISOTROPIC
) MAPPING_FixIsotropic( dc
);
147 DC_UpdateXforms( dc
);
151 INT CDECL
nulldrv_SetMapMode( PHYSDEV dev
, INT mode
)
153 DC
*dc
= get_nulldrv_dc( dev
);
154 INT ret
= dc
->MapMode
;
155 SIZE virtual_size
, virtual_res
;
157 if (mode
== dc
->MapMode
&& (mode
== MM_ISOTROPIC
|| mode
== MM_ANISOTROPIC
)) return ret
;
159 virtual_size
= get_dc_virtual_size( dc
);
160 virtual_res
= get_dc_virtual_res( dc
);
166 dc
->vport_ext
.cx
= 1;
167 dc
->vport_ext
.cy
= 1;
171 dc
->wnd_ext
.cx
= virtual_size
.cx
* 10;
172 dc
->wnd_ext
.cy
= virtual_size
.cy
* 10;
173 dc
->vport_ext
.cx
= virtual_res
.cx
;
174 dc
->vport_ext
.cy
= -virtual_res
.cy
;
177 dc
->wnd_ext
.cx
= virtual_size
.cx
* 100;
178 dc
->wnd_ext
.cy
= virtual_size
.cy
* 100;
179 dc
->vport_ext
.cx
= virtual_res
.cx
;
180 dc
->vport_ext
.cy
= -virtual_res
.cy
;
183 dc
->wnd_ext
.cx
= MulDiv(1000, virtual_size
.cx
, 254);
184 dc
->wnd_ext
.cy
= MulDiv(1000, virtual_size
.cy
, 254);
185 dc
->vport_ext
.cx
= virtual_res
.cx
;
186 dc
->vport_ext
.cy
= -virtual_res
.cy
;
189 dc
->wnd_ext
.cx
= MulDiv(10000, virtual_size
.cx
, 254);
190 dc
->wnd_ext
.cy
= MulDiv(10000, virtual_size
.cy
, 254);
191 dc
->vport_ext
.cx
= virtual_res
.cx
;
192 dc
->vport_ext
.cy
= -virtual_res
.cy
;
195 dc
->wnd_ext
.cx
= MulDiv(14400, virtual_size
.cx
, 254);
196 dc
->wnd_ext
.cy
= MulDiv(14400, virtual_size
.cy
, 254);
197 dc
->vport_ext
.cx
= virtual_res
.cx
;
198 dc
->vport_ext
.cy
= -virtual_res
.cy
;
205 /* RTL layout is always MM_ANISOTROPIC */
206 if (!(dc
->layout
& LAYOUT_RTL
)) dc
->MapMode
= mode
;
207 DC_UpdateXforms( dc
);
211 BOOL CDECL
nulldrv_SetViewportExtEx( PHYSDEV dev
, INT cx
, INT cy
, SIZE
*size
)
213 DC
*dc
= get_nulldrv_dc( dev
);
216 *size
= dc
->vport_ext
;
218 if (dc
->MapMode
!= MM_ISOTROPIC
&& dc
->MapMode
!= MM_ANISOTROPIC
) return TRUE
;
219 if (!cx
|| !cy
) return FALSE
;
220 dc
->vport_ext
.cx
= cx
;
221 dc
->vport_ext
.cy
= cy
;
222 if (dc
->MapMode
== MM_ISOTROPIC
) MAPPING_FixIsotropic( dc
);
223 DC_UpdateXforms( dc
);
227 BOOL CDECL
nulldrv_SetViewportOrgEx( PHYSDEV dev
, INT x
, INT y
, POINT
*pt
)
229 DC
*dc
= get_nulldrv_dc( dev
);
236 DC_UpdateXforms( dc
);
240 BOOL CDECL
nulldrv_SetWindowExtEx( PHYSDEV dev
, INT cx
, INT cy
, SIZE
*size
)
242 DC
*dc
= get_nulldrv_dc( dev
);
247 if (dc
->MapMode
!= MM_ISOTROPIC
&& dc
->MapMode
!= MM_ANISOTROPIC
) return TRUE
;
248 if (!cx
|| !cy
) return FALSE
;
251 /* The API docs say that you should call SetWindowExtEx before
252 SetViewportExtEx. This advice does not imply that Windows
253 doesn't ensure the isotropic mapping after SetWindowExtEx! */
254 if (dc
->MapMode
== MM_ISOTROPIC
) MAPPING_FixIsotropic( dc
);
255 DC_UpdateXforms( dc
);
259 BOOL CDECL
nulldrv_SetWindowOrgEx( PHYSDEV dev
, INT x
, INT y
, POINT
*pt
)
261 DC
*dc
= get_nulldrv_dc( dev
);
268 DC_UpdateXforms( dc
);
272 BOOL CDECL
nulldrv_ModifyWorldTransform( PHYSDEV dev
, const XFORM
*xform
, DWORD mode
)
274 DC
*dc
= get_nulldrv_dc( dev
);
279 dc
->xformWorld2Wnd
.eM11
= 1.0f
;
280 dc
->xformWorld2Wnd
.eM12
= 0.0f
;
281 dc
->xformWorld2Wnd
.eM21
= 0.0f
;
282 dc
->xformWorld2Wnd
.eM22
= 1.0f
;
283 dc
->xformWorld2Wnd
.eDx
= 0.0f
;
284 dc
->xformWorld2Wnd
.eDy
= 0.0f
;
286 case MWT_LEFTMULTIPLY
:
287 CombineTransform( &dc
->xformWorld2Wnd
, xform
, &dc
->xformWorld2Wnd
);
289 case MWT_RIGHTMULTIPLY
:
290 CombineTransform( &dc
->xformWorld2Wnd
, &dc
->xformWorld2Wnd
, xform
);
295 DC_UpdateXforms( dc
);
299 BOOL CDECL
nulldrv_SetWorldTransform( PHYSDEV dev
, const XFORM
*xform
)
301 DC
*dc
= get_nulldrv_dc( dev
);
303 dc
->xformWorld2Wnd
= *xform
;
304 DC_UpdateXforms( dc
);
308 /***********************************************************************
311 * Internal version of DPtoLP that takes a DC *.
313 BOOL
dp_to_lp( DC
*dc
, POINT
*points
, INT count
)
315 if (dc
->vport2WorldValid
)
319 double x
= points
->x
;
320 double y
= points
->y
;
321 points
->x
= floor( x
* dc
->xformVport2World
.eM11
+
322 y
* dc
->xformVport2World
.eM21
+
323 dc
->xformVport2World
.eDx
+ 0.5 );
324 points
->y
= floor( x
* dc
->xformVport2World
.eM12
+
325 y
* dc
->xformVport2World
.eM22
+
326 dc
->xformVport2World
.eDy
+ 0.5 );
333 /***********************************************************************
336 BOOL WINAPI
DPtoLP( HDC hdc
, POINT
*points
, INT count
)
338 DC
* dc
= get_dc_ptr( hdc
);
341 if (!dc
) return FALSE
;
343 ret
= dp_to_lp( dc
, points
, count
);
345 release_dc_ptr( dc
);
350 /***********************************************************************
353 * Internal version of LPtoDP that takes a DC *.
355 void lp_to_dp( DC
*dc
, POINT
*points
, INT count
)
359 double x
= points
->x
;
360 double y
= points
->y
;
361 points
->x
= floor( x
* dc
->xformWorld2Vport
.eM11
+
362 y
* dc
->xformWorld2Vport
.eM21
+
363 dc
->xformWorld2Vport
.eDx
+ 0.5 );
364 points
->y
= floor( x
* dc
->xformWorld2Vport
.eM12
+
365 y
* dc
->xformWorld2Vport
.eM22
+
366 dc
->xformWorld2Vport
.eDy
+ 0.5 );
371 /***********************************************************************
374 BOOL WINAPI
LPtoDP( HDC hdc
, POINT
*points
, INT count
)
376 DC
* dc
= get_dc_ptr( hdc
);
377 if (!dc
) return FALSE
;
379 lp_to_dp( dc
, points
, count
);
381 release_dc_ptr( dc
);
386 /***********************************************************************
387 * SetMapMode (GDI32.@)
389 INT WINAPI
SetMapMode( HDC hdc
, INT mode
)
392 DC
* dc
= get_dc_ptr( hdc
);
394 TRACE("%p %d\n", hdc
, mode
);
398 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetMapMode
);
399 ret
= physdev
->funcs
->pSetMapMode( physdev
, mode
);
400 release_dc_ptr( dc
);
406 /***********************************************************************
407 * SetViewportExtEx (GDI32.@)
409 BOOL WINAPI
SetViewportExtEx( HDC hdc
, INT x
, INT y
, LPSIZE size
)
412 DC
* dc
= get_dc_ptr( hdc
);
416 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetViewportExtEx
);
417 ret
= physdev
->funcs
->pSetViewportExtEx( physdev
, x
, y
, size
);
418 release_dc_ptr( dc
);
424 /***********************************************************************
425 * SetViewportOrgEx (GDI32.@)
427 BOOL WINAPI
SetViewportOrgEx( HDC hdc
, INT x
, INT y
, LPPOINT pt
)
430 DC
* dc
= get_dc_ptr( hdc
);
434 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetViewportOrgEx
);
435 ret
= physdev
->funcs
->pSetViewportOrgEx( physdev
, x
, y
, pt
);
436 release_dc_ptr( dc
);
442 /***********************************************************************
443 * SetWindowExtEx (GDI32.@)
445 BOOL WINAPI
SetWindowExtEx( HDC hdc
, INT x
, INT y
, LPSIZE size
)
448 DC
* dc
= get_dc_ptr( hdc
);
452 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetWindowExtEx
);
453 ret
= physdev
->funcs
->pSetWindowExtEx( physdev
, x
, y
, size
);
454 release_dc_ptr( dc
);
460 /***********************************************************************
461 * SetWindowOrgEx (GDI32.@)
463 BOOL WINAPI
SetWindowOrgEx( HDC hdc
, INT x
, INT y
, LPPOINT pt
)
466 DC
* dc
= get_dc_ptr( hdc
);
470 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetWindowOrgEx
);
471 ret
= physdev
->funcs
->pSetWindowOrgEx( physdev
, x
, y
, pt
);
472 release_dc_ptr( dc
);
478 /***********************************************************************
479 * OffsetViewportOrgEx (GDI32.@)
481 BOOL WINAPI
OffsetViewportOrgEx( HDC hdc
, INT x
, INT y
, LPPOINT pt
)
484 DC
* dc
= get_dc_ptr( hdc
);
488 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pOffsetViewportOrgEx
);
489 ret
= physdev
->funcs
->pOffsetViewportOrgEx( physdev
, x
, y
, pt
);
490 release_dc_ptr( dc
);
496 /***********************************************************************
497 * OffsetWindowOrgEx (GDI32.@)
499 BOOL WINAPI
OffsetWindowOrgEx( HDC hdc
, INT x
, INT y
, LPPOINT pt
)
502 DC
* dc
= get_dc_ptr( hdc
);
506 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pOffsetWindowOrgEx
);
507 ret
= physdev
->funcs
->pOffsetWindowOrgEx( physdev
, x
, y
, pt
);
508 release_dc_ptr( dc
);
514 /***********************************************************************
515 * ScaleViewportExtEx (GDI32.@)
517 BOOL WINAPI
ScaleViewportExtEx( HDC hdc
, INT xNum
, INT xDenom
,
518 INT yNum
, INT yDenom
, LPSIZE size
)
521 DC
* dc
= get_dc_ptr( hdc
);
525 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pScaleViewportExtEx
);
526 ret
= physdev
->funcs
->pScaleViewportExtEx( physdev
, xNum
, xDenom
, yNum
, yDenom
, size
);
527 release_dc_ptr( dc
);
533 /***********************************************************************
534 * ScaleWindowExtEx (GDI32.@)
536 BOOL WINAPI
ScaleWindowExtEx( HDC hdc
, INT xNum
, INT xDenom
,
537 INT yNum
, INT yDenom
, LPSIZE size
)
540 DC
* dc
= get_dc_ptr( hdc
);
544 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pScaleWindowExtEx
);
545 ret
= physdev
->funcs
->pScaleWindowExtEx( physdev
, xNum
, xDenom
, yNum
, yDenom
, size
);
546 release_dc_ptr( dc
);
552 /****************************************************************************
553 * ModifyWorldTransform (GDI32.@)
555 BOOL WINAPI
ModifyWorldTransform( HDC hdc
, const XFORM
*xform
, DWORD mode
)
560 if (!xform
&& mode
!= MWT_IDENTITY
) return FALSE
;
561 if ((dc
= get_dc_ptr( hdc
)))
563 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pModifyWorldTransform
);
564 if (dc
->GraphicsMode
== GM_ADVANCED
)
565 ret
= physdev
->funcs
->pModifyWorldTransform( physdev
, xform
, mode
);
566 release_dc_ptr( dc
);
572 /***********************************************************************
573 * SetWorldTransform (GDI32.@)
575 BOOL WINAPI
SetWorldTransform( HDC hdc
, const XFORM
*xform
)
580 if (!xform
) return FALSE
;
581 /* The transform must conform to (eM11 * eM22 != eM12 * eM21) requirement */
582 if (xform
->eM11
* xform
->eM22
== xform
->eM12
* xform
->eM21
) return FALSE
;
584 TRACE("eM11 %f eM12 %f eM21 %f eM22 %f eDx %f eDy %f\n",
585 xform
->eM11
, xform
->eM12
, xform
->eM21
, xform
->eM22
, xform
->eDx
, xform
->eDy
);
587 if ((dc
= get_dc_ptr( hdc
)))
589 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetWorldTransform
);
590 if (dc
->GraphicsMode
== GM_ADVANCED
)
591 ret
= physdev
->funcs
->pSetWorldTransform( physdev
, xform
);
592 release_dc_ptr( dc
);
598 /***********************************************************************
599 * SetVirtualResolution (GDI32.@)
601 * Undocumented on msdn.
603 * Changes the values of screen size in pixels and millimeters used by
604 * the mapping mode functions.
607 * hdc [I] Device context
608 * horz_res [I] Width in pixels (equivalent to HORZRES device cap).
609 * vert_res [I] Height in pixels (equivalent to VERTRES device cap).
610 * horz_size [I] Width in mm (equivalent to HORZSIZE device cap).
611 * vert_size [I] Height in mm (equivalent to VERTSIZE device cap).
614 * TRUE if successful.
615 * FALSE if any (but not all) of the last four params are zero.
618 * This doesn't change the values returned by GetDeviceCaps, just the
619 * scaling of the mapping modes.
621 * Calling with the last four params equal to zero sets the values
622 * back to their defaults obtained by calls to GetDeviceCaps.
624 BOOL WINAPI
SetVirtualResolution(HDC hdc
, DWORD horz_res
, DWORD vert_res
,
625 DWORD horz_size
, DWORD vert_size
)
628 TRACE("(%p %d %d %d %d)\n", hdc
, horz_res
, vert_res
, horz_size
, vert_size
);
630 if (!horz_res
|| !vert_res
|| !horz_size
|| !vert_size
)
632 /* they must be all zero */
633 if (horz_res
|| vert_res
|| horz_size
|| vert_size
) return FALSE
;
636 dc
= get_dc_ptr( hdc
);
637 if (!dc
) return FALSE
;
639 dc
->virtual_res
.cx
= horz_res
;
640 dc
->virtual_res
.cy
= vert_res
;
641 dc
->virtual_size
.cx
= horz_size
;
642 dc
->virtual_size
.cy
= vert_size
;
644 release_dc_ptr( dc
);