urlmon: Support BINDINFO_OPTIONS_DISABLEAUTOREDIRECTS in BindProtocol object.
[wine.git] / dlls / gdi32 / mapping.c
blob28b12bc48cc448d512e7845b9d4eb7f04f081873
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 "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;
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->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->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));
68 if (xdim > ydim)
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;
74 else
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 nulldrv_OffsetViewportOrgEx( PHYSDEV dev, INT x, INT y, POINT *pt )
89 DC *dc = get_nulldrv_dc( dev );
91 if (pt)
92 *pt = dc->vport_org;
94 dc->vport_org.x += x;
95 dc->vport_org.y += y;
96 DC_UpdateXforms( dc );
97 return TRUE;
100 BOOL nulldrv_OffsetWindowOrgEx( PHYSDEV dev, INT x, INT y, POINT *pt )
102 DC *dc = get_nulldrv_dc( dev );
104 if (pt)
105 *pt = dc->wnd_org;
107 dc->wnd_org.x += x;
108 dc->wnd_org.y += y;
109 DC_UpdateXforms( dc );
110 return TRUE;
113 BOOL 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 );
117 if (size)
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 );
129 return TRUE;
132 BOOL 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 );
136 if (size)
137 *size = dc->wnd_ext;
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 );
148 return TRUE;
151 INT 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 );
161 switch (mode)
163 case MM_TEXT:
164 dc->wnd_ext.cx = 1;
165 dc->wnd_ext.cy = 1;
166 dc->vport_ext.cx = 1;
167 dc->vport_ext.cy = 1;
168 break;
169 case MM_LOMETRIC:
170 case MM_ISOTROPIC:
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;
175 break;
176 case MM_HIMETRIC:
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;
181 break;
182 case MM_LOENGLISH:
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;
187 break;
188 case MM_HIENGLISH:
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;
193 break;
194 case MM_TWIPS:
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;
199 break;
200 case MM_ANISOTROPIC:
201 break;
202 default:
203 return 0;
205 /* RTL layout is always MM_ANISOTROPIC */
206 if (!(dc->layout & LAYOUT_RTL)) dc->MapMode = mode;
207 DC_UpdateXforms( dc );
208 return ret;
211 BOOL nulldrv_SetViewportExtEx( PHYSDEV dev, INT cx, INT cy, SIZE *size )
213 DC *dc = get_nulldrv_dc( dev );
215 if (size)
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 );
224 return TRUE;
227 BOOL nulldrv_SetViewportOrgEx( PHYSDEV dev, INT x, INT y, POINT *pt )
229 DC *dc = get_nulldrv_dc( dev );
231 if (pt)
232 *pt = dc->vport_org;
234 dc->vport_org.x = x;
235 dc->vport_org.y = y;
236 DC_UpdateXforms( dc );
237 return TRUE;
240 BOOL nulldrv_SetWindowExtEx( PHYSDEV dev, INT cx, INT cy, SIZE *size )
242 DC *dc = get_nulldrv_dc( dev );
244 if (size)
245 *size = dc->wnd_ext;
247 if (dc->MapMode != MM_ISOTROPIC && dc->MapMode != MM_ANISOTROPIC) return TRUE;
248 if (!cx || !cy) return FALSE;
249 dc->wnd_ext.cx = cx;
250 dc->wnd_ext.cy = cy;
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 );
256 return TRUE;
259 BOOL nulldrv_SetWindowOrgEx( PHYSDEV dev, INT x, INT y, POINT *pt )
261 DC *dc = get_nulldrv_dc( dev );
263 if (pt)
264 *pt = dc->wnd_org;
266 dc->wnd_org.x = x;
267 dc->wnd_org.y = y;
268 DC_UpdateXforms( dc );
269 return TRUE;
272 BOOL nulldrv_ModifyWorldTransform( PHYSDEV dev, const XFORM *xform, DWORD mode )
274 DC *dc = get_nulldrv_dc( dev );
276 switch (mode)
278 case MWT_IDENTITY:
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;
285 break;
286 case MWT_LEFTMULTIPLY:
287 CombineTransform( &dc->xformWorld2Wnd, xform, &dc->xformWorld2Wnd );
288 break;
289 case MWT_RIGHTMULTIPLY:
290 CombineTransform( &dc->xformWorld2Wnd, &dc->xformWorld2Wnd, xform );
291 break;
292 default:
293 return FALSE;
295 DC_UpdateXforms( dc );
296 return TRUE;
299 BOOL nulldrv_SetWorldTransform( PHYSDEV dev, const XFORM *xform )
301 DC *dc = get_nulldrv_dc( dev );
303 dc->xformWorld2Wnd = *xform;
304 DC_UpdateXforms( dc );
305 return TRUE;
308 /***********************************************************************
309 * dp_to_lp
311 * Internal version of DPtoLP that takes a DC *.
313 BOOL dp_to_lp( DC *dc, POINT *points, INT count )
315 if (dc->vport2WorldValid)
317 while (count--)
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 );
327 points++;
330 return (count < 0);
333 /***********************************************************************
334 * DPtoLP (GDI32.@)
336 BOOL WINAPI DPtoLP( HDC hdc, POINT *points, INT count )
338 DC * dc = get_dc_ptr( hdc );
339 BOOL ret;
341 if (!dc) return FALSE;
343 ret = dp_to_lp( dc, points, count );
345 release_dc_ptr( dc );
346 return ret;
350 /***********************************************************************
351 * lp_to_dp
353 * Internal version of LPtoDP that takes a DC *.
355 void lp_to_dp( DC *dc, POINT *points, INT count )
357 while (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 );
367 points++;
371 /***********************************************************************
372 * LPtoDP (GDI32.@)
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 );
382 return TRUE;
386 /***********************************************************************
387 * SetMapMode (GDI32.@)
389 INT WINAPI SetMapMode( HDC hdc, INT mode )
391 INT ret = 0;
392 DC * dc = get_dc_ptr( hdc );
394 TRACE("%p %d\n", hdc, mode );
396 if (dc)
398 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetMapMode );
399 ret = physdev->funcs->pSetMapMode( physdev, mode );
400 release_dc_ptr( dc );
402 return ret;
406 /***********************************************************************
407 * SetViewportExtEx (GDI32.@)
409 BOOL WINAPI SetViewportExtEx( HDC hdc, INT x, INT y, LPSIZE size )
411 BOOL ret = FALSE;
412 DC * dc = get_dc_ptr( hdc );
414 if (dc)
416 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetViewportExtEx );
417 ret = physdev->funcs->pSetViewportExtEx( physdev, x, y, size );
418 release_dc_ptr( dc );
420 return ret;
424 /***********************************************************************
425 * SetViewportOrgEx (GDI32.@)
427 BOOL WINAPI SetViewportOrgEx( HDC hdc, INT x, INT y, LPPOINT pt )
429 BOOL ret = FALSE;
430 DC * dc = get_dc_ptr( hdc );
432 if (dc)
434 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetViewportOrgEx );
435 ret = physdev->funcs->pSetViewportOrgEx( physdev, x, y, pt );
436 release_dc_ptr( dc );
438 return ret;
442 /***********************************************************************
443 * SetWindowExtEx (GDI32.@)
445 BOOL WINAPI SetWindowExtEx( HDC hdc, INT x, INT y, LPSIZE size )
447 BOOL ret = FALSE;
448 DC * dc = get_dc_ptr( hdc );
450 if (dc)
452 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetWindowExtEx );
453 ret = physdev->funcs->pSetWindowExtEx( physdev, x, y, size );
454 release_dc_ptr( dc );
456 return ret;
460 /***********************************************************************
461 * SetWindowOrgEx (GDI32.@)
463 BOOL WINAPI SetWindowOrgEx( HDC hdc, INT x, INT y, LPPOINT pt )
465 BOOL ret = FALSE;
466 DC * dc = get_dc_ptr( hdc );
468 if (dc)
470 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetWindowOrgEx );
471 ret = physdev->funcs->pSetWindowOrgEx( physdev, x, y, pt );
472 release_dc_ptr( dc );
474 return ret;
478 /***********************************************************************
479 * OffsetViewportOrgEx (GDI32.@)
481 BOOL WINAPI OffsetViewportOrgEx( HDC hdc, INT x, INT y, LPPOINT pt)
483 BOOL ret = FALSE;
484 DC * dc = get_dc_ptr( hdc );
486 if (dc)
488 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pOffsetViewportOrgEx );
489 ret = physdev->funcs->pOffsetViewportOrgEx( physdev, x, y, pt );
490 release_dc_ptr( dc );
492 return ret;
496 /***********************************************************************
497 * OffsetWindowOrgEx (GDI32.@)
499 BOOL WINAPI OffsetWindowOrgEx( HDC hdc, INT x, INT y, LPPOINT pt )
501 BOOL ret = FALSE;
502 DC * dc = get_dc_ptr( hdc );
504 if (dc)
506 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pOffsetWindowOrgEx );
507 ret = physdev->funcs->pOffsetWindowOrgEx( physdev, x, y, pt );
508 release_dc_ptr( dc );
510 return ret;
514 /***********************************************************************
515 * ScaleViewportExtEx (GDI32.@)
517 BOOL WINAPI ScaleViewportExtEx( HDC hdc, INT xNum, INT xDenom,
518 INT yNum, INT yDenom, LPSIZE size )
520 BOOL ret = FALSE;
521 DC * dc = get_dc_ptr( hdc );
523 if (dc)
525 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pScaleViewportExtEx );
526 ret = physdev->funcs->pScaleViewportExtEx( physdev, xNum, xDenom, yNum, yDenom, size );
527 release_dc_ptr( dc );
529 return ret;
533 /***********************************************************************
534 * ScaleWindowExtEx (GDI32.@)
536 BOOL WINAPI ScaleWindowExtEx( HDC hdc, INT xNum, INT xDenom,
537 INT yNum, INT yDenom, LPSIZE size )
539 BOOL ret = FALSE;
540 DC * dc = get_dc_ptr( hdc );
542 if (dc)
544 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pScaleWindowExtEx );
545 ret = physdev->funcs->pScaleWindowExtEx( physdev, xNum, xDenom, yNum, yDenom, size );
546 release_dc_ptr( dc );
548 return ret;
552 /****************************************************************************
553 * ModifyWorldTransform (GDI32.@)
555 BOOL WINAPI ModifyWorldTransform( HDC hdc, const XFORM *xform, DWORD mode )
557 BOOL ret = FALSE;
558 DC *dc;
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 );
568 return ret;
572 /***********************************************************************
573 * SetWorldTransform (GDI32.@)
575 BOOL WINAPI SetWorldTransform( HDC hdc, const XFORM *xform )
577 BOOL ret = FALSE;
578 DC *dc;
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 );
594 return ret;
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.
606 * PARAMS
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).
613 * RETURNS
614 * TRUE if successful.
615 * FALSE if any (but not all) of the last four params are zero.
617 * NOTES
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)
627 DC * dc;
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 );
645 return TRUE;