riched20: \pard resets the reading direction.
[wine.git] / dlls / gdi32 / mapping.c
blob665042a9e473263c6a42f68cc48dbf6a69ab6039
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->vportExtX * virtual_size.cx / (virtual_res.cx * dc->wndExtX));
66 double ydim = fabs((double)dc->vportExtY * virtual_size.cy / (virtual_res.cy * dc->wndExtY));
68 if (xdim > ydim)
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;
74 else
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 );
91 if (pt)
93 pt->x = dc->vportOrgX;
94 pt->y = dc->vportOrgY;
96 dc->vportOrgX += x;
97 dc->vportOrgY += y;
98 DC_UpdateXforms( dc );
99 return TRUE;
102 BOOL nulldrv_OffsetWindowOrgEx( PHYSDEV dev, INT x, INT y, POINT *pt )
104 DC *dc = get_nulldrv_dc( dev );
106 if (pt)
108 pt->x = dc->wndOrgX;
109 pt->y = dc->wndOrgY;
111 dc->wndOrgX += x;
112 dc->wndOrgY += y;
113 DC_UpdateXforms( dc );
114 return TRUE;
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 );
121 if (size)
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 );
135 return TRUE;
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 );
142 if (size)
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 );
156 return TRUE;
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 );
169 switch (mode)
171 case MM_TEXT:
172 dc->wndExtX = 1;
173 dc->wndExtY = 1;
174 dc->vportExtX = 1;
175 dc->vportExtY = 1;
176 break;
177 case MM_LOMETRIC:
178 case MM_ISOTROPIC:
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;
183 break;
184 case MM_HIMETRIC:
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;
189 break;
190 case MM_LOENGLISH:
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;
195 break;
196 case MM_HIENGLISH:
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;
201 break;
202 case MM_TWIPS:
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;
207 break;
208 case MM_ANISOTROPIC:
209 break;
210 default:
211 return 0;
213 /* RTL layout is always MM_ANISOTROPIC */
214 if (!(dc->layout & LAYOUT_RTL)) dc->MapMode = mode;
215 DC_UpdateXforms( dc );
216 return ret;
219 BOOL nulldrv_SetViewportExtEx( PHYSDEV dev, INT cx, INT cy, SIZE *size )
221 DC *dc = get_nulldrv_dc( dev );
223 if (size)
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;
230 dc->vportExtX = cx;
231 dc->vportExtY = cy;
232 if (dc->MapMode == MM_ISOTROPIC) MAPPING_FixIsotropic( dc );
233 DC_UpdateXforms( dc );
234 return TRUE;
237 BOOL nulldrv_SetViewportOrgEx( PHYSDEV dev, INT x, INT y, POINT *pt )
239 DC *dc = get_nulldrv_dc( dev );
241 if (pt)
243 pt->x = dc->vportOrgX;
244 pt->y = dc->vportOrgY;
246 dc->vportOrgX = x;
247 dc->vportOrgY = y;
248 DC_UpdateXforms( dc );
249 return TRUE;
252 BOOL nulldrv_SetWindowExtEx( PHYSDEV dev, INT cx, INT cy, SIZE *size )
254 DC *dc = get_nulldrv_dc( dev );
256 if (size)
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;
263 dc->wndExtX = cx;
264 dc->wndExtY = cy;
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 );
270 return TRUE;
273 BOOL nulldrv_SetWindowOrgEx( PHYSDEV dev, INT x, INT y, POINT *pt )
275 DC *dc = get_nulldrv_dc( dev );
277 if (pt)
279 pt->x = dc->wndOrgX;
280 pt->y = dc->wndOrgY;
282 dc->wndOrgX = x;
283 dc->wndOrgY = y;
284 DC_UpdateXforms( dc );
285 return TRUE;
288 BOOL nulldrv_ModifyWorldTransform( PHYSDEV dev, const XFORM *xform, DWORD mode )
290 DC *dc = get_nulldrv_dc( dev );
292 switch (mode)
294 case MWT_IDENTITY:
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;
301 break;
302 case MWT_LEFTMULTIPLY:
303 CombineTransform( &dc->xformWorld2Wnd, xform, &dc->xformWorld2Wnd );
304 break;
305 case MWT_RIGHTMULTIPLY:
306 CombineTransform( &dc->xformWorld2Wnd, &dc->xformWorld2Wnd, xform );
307 break;
308 default:
309 return FALSE;
311 DC_UpdateXforms( dc );
312 return TRUE;
315 BOOL nulldrv_SetWorldTransform( PHYSDEV dev, const XFORM *xform )
317 DC *dc = get_nulldrv_dc( dev );
319 dc->xformWorld2Wnd = *xform;
320 DC_UpdateXforms( dc );
321 return TRUE;
324 /***********************************************************************
325 * DPtoLP (GDI32.@)
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)
334 while (count--)
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 );
344 points++;
347 release_dc_ptr( dc );
348 return (count < 0);
352 /***********************************************************************
353 * LPtoDP (GDI32.@)
355 BOOL WINAPI LPtoDP( HDC hdc, LPPOINT points, INT count )
357 DC * dc = get_dc_ptr( hdc );
358 if (!dc) return FALSE;
360 while (count--)
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 );
370 points++;
372 release_dc_ptr( dc );
373 return TRUE;
377 /***********************************************************************
378 * SetMapMode (GDI32.@)
380 INT WINAPI SetMapMode( HDC hdc, INT mode )
382 INT ret = 0;
383 DC * dc = get_dc_ptr( hdc );
385 TRACE("%p %d\n", hdc, mode );
387 if (dc)
389 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetMapMode );
390 ret = physdev->funcs->pSetMapMode( physdev, mode );
391 release_dc_ptr( dc );
393 return ret;
397 /***********************************************************************
398 * SetViewportExtEx (GDI32.@)
400 BOOL WINAPI SetViewportExtEx( HDC hdc, INT x, INT y, LPSIZE size )
402 BOOL ret = FALSE;
403 DC * dc = get_dc_ptr( hdc );
405 if (dc)
407 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetViewportExtEx );
408 ret = physdev->funcs->pSetViewportExtEx( physdev, x, y, size );
409 release_dc_ptr( dc );
411 return ret;
415 /***********************************************************************
416 * SetViewportOrgEx (GDI32.@)
418 BOOL WINAPI SetViewportOrgEx( HDC hdc, INT x, INT y, LPPOINT pt )
420 BOOL ret = FALSE;
421 DC * dc = get_dc_ptr( hdc );
423 if (dc)
425 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetViewportOrgEx );
426 ret = physdev->funcs->pSetViewportOrgEx( physdev, x, y, pt );
427 release_dc_ptr( dc );
429 return ret;
433 /***********************************************************************
434 * SetWindowExtEx (GDI32.@)
436 BOOL WINAPI SetWindowExtEx( HDC hdc, INT x, INT y, LPSIZE size )
438 BOOL ret = FALSE;
439 DC * dc = get_dc_ptr( hdc );
441 if (dc)
443 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetWindowExtEx );
444 ret = physdev->funcs->pSetWindowExtEx( physdev, x, y, size );
445 release_dc_ptr( dc );
447 return ret;
451 /***********************************************************************
452 * SetWindowOrgEx (GDI32.@)
454 BOOL WINAPI SetWindowOrgEx( HDC hdc, INT x, INT y, LPPOINT pt )
456 BOOL ret = FALSE;
457 DC * dc = get_dc_ptr( hdc );
459 if (dc)
461 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetWindowOrgEx );
462 ret = physdev->funcs->pSetWindowOrgEx( physdev, x, y, pt );
463 release_dc_ptr( dc );
465 return ret;
469 /***********************************************************************
470 * OffsetViewportOrgEx (GDI32.@)
472 BOOL WINAPI OffsetViewportOrgEx( HDC hdc, INT x, INT y, LPPOINT pt)
474 BOOL ret = FALSE;
475 DC * dc = get_dc_ptr( hdc );
477 if (dc)
479 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pOffsetViewportOrgEx );
480 ret = physdev->funcs->pOffsetViewportOrgEx( physdev, x, y, pt );
481 release_dc_ptr( dc );
483 return ret;
487 /***********************************************************************
488 * OffsetWindowOrgEx (GDI32.@)
490 BOOL WINAPI OffsetWindowOrgEx( HDC hdc, INT x, INT y, LPPOINT pt )
492 BOOL ret = FALSE;
493 DC * dc = get_dc_ptr( hdc );
495 if (dc)
497 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pOffsetWindowOrgEx );
498 ret = physdev->funcs->pOffsetWindowOrgEx( physdev, x, y, pt );
499 release_dc_ptr( dc );
501 return ret;
505 /***********************************************************************
506 * ScaleViewportExtEx (GDI32.@)
508 BOOL WINAPI ScaleViewportExtEx( HDC hdc, INT xNum, INT xDenom,
509 INT yNum, INT yDenom, LPSIZE size )
511 BOOL ret = FALSE;
512 DC * dc = get_dc_ptr( hdc );
514 if (dc)
516 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pScaleViewportExtEx );
517 ret = physdev->funcs->pScaleViewportExtEx( physdev, xNum, xDenom, yNum, yDenom, size );
518 release_dc_ptr( dc );
520 return ret;
524 /***********************************************************************
525 * ScaleWindowExtEx (GDI32.@)
527 BOOL WINAPI ScaleWindowExtEx( HDC hdc, INT xNum, INT xDenom,
528 INT yNum, INT yDenom, LPSIZE size )
530 BOOL ret = FALSE;
531 DC * dc = get_dc_ptr( hdc );
533 if (dc)
535 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pScaleWindowExtEx );
536 ret = physdev->funcs->pScaleWindowExtEx( physdev, xNum, xDenom, yNum, yDenom, size );
537 release_dc_ptr( dc );
539 return ret;
543 /****************************************************************************
544 * ModifyWorldTransform (GDI32.@)
546 BOOL WINAPI ModifyWorldTransform( HDC hdc, const XFORM *xform, DWORD mode )
548 BOOL ret = FALSE;
549 DC *dc;
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 );
559 return ret;
563 /***********************************************************************
564 * SetWorldTransform (GDI32.@)
566 BOOL WINAPI SetWorldTransform( HDC hdc, const XFORM *xform )
568 BOOL ret = FALSE;
569 DC *dc;
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 );
585 return ret;
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.
597 * PARAMS
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).
604 * RETURNS
605 * TRUE if successful.
606 * FALSE if any (but not all) of the last four params are zero.
608 * NOTES
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)
618 DC * dc;
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 );
636 return TRUE;