gdi32: Don't use pOS2->usWeightClass, some fonts don't set it correctly.
[wine] / dlls / gdi32 / mapping.c
1 /*
2  * GDI mapping mode functions
3  *
4  * Copyright 1993 Alexandre Julliard
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include <stdarg.h>
22
23 #include "windef.h"
24 #include "winbase.h"
25 #include "wingdi.h"
26 #include "wownt32.h"
27 #include "gdi_private.h"
28 #include "wine/debug.h"
29
30 WINE_DEFAULT_DEBUG_CHANNEL(gdi);
31
32
33 /***********************************************************************
34  *           MAPPING_FixIsotropic
35  *
36  * Fix viewport extensions for isotropic mode.
37  */
38 static void MAPPING_FixIsotropic( DC * dc )
39 {
40     double xdim = fabs((double)dc->vportExtX * GetDeviceCaps( dc->hSelf, HORZSIZE ) /
41                   (GetDeviceCaps( dc->hSelf, HORZRES ) * dc->wndExtX));
42     double ydim = fabs((double)dc->vportExtY * GetDeviceCaps( dc->hSelf, VERTSIZE ) /
43                   (GetDeviceCaps( dc->hSelf, VERTRES ) * dc->wndExtY));
44
45     if (xdim > ydim)
46     {
47         INT mincx = (dc->vportExtX >= 0) ? 1 : -1;
48         dc->vportExtX = floor(dc->vportExtX * ydim / xdim + 0.5);
49         if (!dc->vportExtX) dc->vportExtX = mincx;
50     }
51     else
52     {
53         INT mincy = (dc->vportExtY >= 0) ? 1 : -1;
54         dc->vportExtY = floor(dc->vportExtY * xdim / ydim + 0.5);
55         if (!dc->vportExtY) dc->vportExtY = mincy;
56     }
57 }
58
59
60 /***********************************************************************
61  *           DPtoLP    (GDI.67)
62  */
63 BOOL16 WINAPI DPtoLP16( HDC16 hdc, LPPOINT16 points, INT16 count )
64 {
65     DC * dc = get_dc_ptr( HDC_32(hdc) );
66     if (!dc) return FALSE;
67
68     while (count--)
69     {
70         points->x = MulDiv( points->x - dc->vportOrgX, dc->wndExtX, dc->vportExtX ) + dc->wndOrgX;
71         points->y = MulDiv( points->y - dc->vportOrgY, dc->wndExtY, dc->vportExtY ) + dc->wndOrgY;
72         points++;
73     }
74     release_dc_ptr( dc );
75     return TRUE;
76 }
77
78
79 /***********************************************************************
80  *           DPtoLP    (GDI32.@)
81  */
82 BOOL WINAPI DPtoLP( HDC hdc, LPPOINT points, INT count )
83 {
84     DC * dc = get_dc_ptr( hdc );
85     if (!dc) return FALSE;
86
87     if (dc->vport2WorldValid)
88     {
89         while (count--)
90         {
91             double x = points->x;
92             double y = points->y;
93             points->x = floor( x * dc->xformVport2World.eM11 +
94                                y * dc->xformVport2World.eM21 +
95                                dc->xformVport2World.eDx + 0.5 );
96             points->y = floor( x * dc->xformVport2World.eM12 +
97                                y * dc->xformVport2World.eM22 +
98                                dc->xformVport2World.eDy + 0.5 );
99             points++;
100         }
101     }
102     release_dc_ptr( dc );
103     return (count < 0);
104 }
105
106
107 /***********************************************************************
108  *           LPtoDP    (GDI.99)
109  */
110 BOOL16 WINAPI LPtoDP16( HDC16 hdc, LPPOINT16 points, INT16 count )
111 {
112     DC * dc = get_dc_ptr( HDC_32(hdc) );
113     if (!dc) return FALSE;
114
115     while (count--)
116     {
117         points->x = MulDiv( points->x - dc->wndOrgX, dc->vportExtX, dc->wndExtX ) + dc->vportOrgX;
118         points->y = MulDiv( points->y - dc->wndOrgY, dc->vportExtY, dc->wndExtY ) + dc->vportOrgY;
119         points++;
120     }
121     release_dc_ptr( dc );
122     return TRUE;
123 }
124
125
126 /***********************************************************************
127  *           LPtoDP    (GDI32.@)
128  */
129 BOOL WINAPI LPtoDP( HDC hdc, LPPOINT points, INT count )
130 {
131     DC * dc = get_dc_ptr( hdc );
132     if (!dc) return FALSE;
133
134     while (count--)
135     {
136         double x = points->x;
137         double y = points->y;
138         points->x = floor( x * dc->xformWorld2Vport.eM11 +
139                            y * dc->xformWorld2Vport.eM21 +
140                            dc->xformWorld2Vport.eDx + 0.5 );
141         points->y = floor( x * dc->xformWorld2Vport.eM12 +
142                            y * dc->xformWorld2Vport.eM22 +
143                            dc->xformWorld2Vport.eDy + 0.5 );
144         points++;
145     }
146     release_dc_ptr( dc );
147     return TRUE;
148 }
149
150
151 /***********************************************************************
152  *           SetMapMode    (GDI32.@)
153  */
154 INT WINAPI SetMapMode( HDC hdc, INT mode )
155 {
156     INT ret;
157     INT horzSize, vertSize, horzRes, vertRes;
158
159     DC * dc = get_dc_ptr( hdc );
160     if (!dc) return 0;
161     if (dc->funcs->pSetMapMode)
162     {
163         if((ret = dc->funcs->pSetMapMode( dc->physDev, mode )) != TRUE)
164         {
165             if(ret == GDI_NO_MORE_WORK)
166                 ret = TRUE;
167             goto done;
168         }
169     }
170
171     TRACE("%p %d\n", hdc, mode );
172
173     ret = dc->MapMode;
174
175     if (mode == dc->MapMode && (mode == MM_ISOTROPIC || mode == MM_ANISOTROPIC))
176         goto done;
177
178     horzSize = GetDeviceCaps( hdc, HORZSIZE );
179     vertSize = GetDeviceCaps( hdc, VERTSIZE );
180     horzRes  = GetDeviceCaps( hdc, HORZRES );
181     vertRes  = GetDeviceCaps( hdc, VERTRES );
182     switch(mode)
183     {
184     case MM_TEXT:
185         dc->wndExtX   = 1;
186         dc->wndExtY   = 1;
187         dc->vportExtX = 1;
188         dc->vportExtY = 1;
189         break;
190     case MM_LOMETRIC:
191     case MM_ISOTROPIC:
192         dc->wndExtX   = horzSize * 10;
193         dc->wndExtY   = vertSize * 10;
194         dc->vportExtX = horzRes;
195         dc->vportExtY = -vertRes;
196         break;
197     case MM_HIMETRIC:
198         dc->wndExtX   = horzSize * 100;
199         dc->wndExtY   = vertSize * 100;
200         dc->vportExtX = horzRes;
201         dc->vportExtY = -vertRes;
202         break;
203     case MM_LOENGLISH:
204         dc->wndExtX   = MulDiv(1000, horzSize, 254);
205         dc->wndExtY   = MulDiv(1000, vertSize, 254);
206         dc->vportExtX = horzRes;
207         dc->vportExtY = -vertRes;
208         break;
209     case MM_HIENGLISH:
210         dc->wndExtX   = MulDiv(10000, horzSize, 254);
211         dc->wndExtY   = MulDiv(10000, vertSize, 254);
212         dc->vportExtX = horzRes;
213         dc->vportExtY = -vertRes;
214         break;
215     case MM_TWIPS:
216         dc->wndExtX   = MulDiv(14400, horzSize, 254);
217         dc->wndExtY   = MulDiv(14400, vertSize, 254);
218         dc->vportExtX = horzRes;
219         dc->vportExtY = -vertRes;
220         break;
221     case MM_ANISOTROPIC:
222         break;
223     default:
224         goto done;
225     }
226     dc->MapMode = mode;
227     DC_UpdateXforms( dc );
228  done:
229     release_dc_ptr( dc );
230     return ret;
231 }
232
233
234 /***********************************************************************
235  *           SetViewportExtEx    (GDI32.@)
236  */
237 BOOL WINAPI SetViewportExtEx( HDC hdc, INT x, INT y, LPSIZE size )
238 {
239     INT ret = TRUE;
240     DC * dc = get_dc_ptr( hdc );
241     if (!dc) return FALSE;
242     if (dc->funcs->pSetViewportExt)
243     {
244         if((ret = dc->funcs->pSetViewportExt( dc->physDev, x, y )) != TRUE)
245         {
246             if(ret == GDI_NO_MORE_WORK)
247                 ret = TRUE;
248             goto done;
249         }
250     }
251     if (size)
252     {
253         size->cx = dc->vportExtX;
254         size->cy = dc->vportExtY;
255     }
256     if ((dc->MapMode != MM_ISOTROPIC) && (dc->MapMode != MM_ANISOTROPIC))
257         goto done;
258     if (!x || !y)
259     {
260         ret = FALSE;
261         goto done;
262     }
263     dc->vportExtX = x;
264     dc->vportExtY = y;
265     if (dc->MapMode == MM_ISOTROPIC) MAPPING_FixIsotropic( dc );
266     DC_UpdateXforms( dc );
267  done:
268     release_dc_ptr( dc );
269     return ret;
270 }
271
272
273 /***********************************************************************
274  *           SetViewportOrgEx    (GDI32.@)
275  */
276 BOOL WINAPI SetViewportOrgEx( HDC hdc, INT x, INT y, LPPOINT pt )
277 {
278     INT ret = TRUE;
279     DC * dc = get_dc_ptr( hdc );
280     if (!dc) return FALSE;
281     if (dc->funcs->pSetViewportOrg)
282     {
283         if((ret = dc->funcs->pSetViewportOrg( dc->physDev, x, y )) != TRUE)
284         {
285             if(ret == GDI_NO_MORE_WORK)
286                 ret = TRUE;
287             goto done;
288         }
289     }
290     if (pt)
291     {
292         pt->x = dc->vportOrgX;
293         pt->y = dc->vportOrgY;
294     }
295     dc->vportOrgX = x;
296     dc->vportOrgY = y;
297     DC_UpdateXforms( dc );
298
299  done:
300     release_dc_ptr( dc );
301     return ret;
302 }
303
304
305 /***********************************************************************
306  *           SetWindowExtEx    (GDI32.@)
307  */
308 BOOL WINAPI SetWindowExtEx( HDC hdc, INT x, INT y, LPSIZE size )
309 {
310     INT ret = TRUE;
311     DC * dc = get_dc_ptr( hdc );
312     if (!dc) return FALSE;
313     if (dc->funcs->pSetWindowExt)
314     {
315         if((ret = dc->funcs->pSetWindowExt( dc->physDev, x, y )) != TRUE)
316         {
317             if(ret == GDI_NO_MORE_WORK)
318                 ret = TRUE;
319             goto done;
320         }
321     }
322     if (size)
323     {
324         size->cx = dc->wndExtX;
325         size->cy = dc->wndExtY;
326     }
327     if ((dc->MapMode != MM_ISOTROPIC) && (dc->MapMode != MM_ANISOTROPIC))
328         goto done;
329     if (!x || !y)
330     {
331         ret = FALSE;
332         goto done;
333     }
334     dc->wndExtX = x;
335     dc->wndExtY = y;
336     /* The API docs say that you should call SetWindowExtEx before
337        SetViewportExtEx. This advice does not imply that Windows
338        doesn't ensure the isotropic mapping after SetWindowExtEx! */
339     if (dc->MapMode == MM_ISOTROPIC) MAPPING_FixIsotropic( dc );
340     DC_UpdateXforms( dc );
341  done:
342     release_dc_ptr( dc );
343     return ret;
344 }
345
346
347 /***********************************************************************
348  *           SetWindowOrgEx    (GDI32.@)
349  */
350 BOOL WINAPI SetWindowOrgEx( HDC hdc, INT x, INT y, LPPOINT pt )
351 {
352     INT ret = TRUE;
353     DC * dc = get_dc_ptr( hdc );
354     if (!dc) return FALSE;
355     if (dc->funcs->pSetWindowOrg)
356     {
357         if((ret = dc->funcs->pSetWindowOrg( dc->physDev, x, y )) != TRUE)
358         {
359             if(ret == GDI_NO_MORE_WORK)
360                 ret = TRUE;
361             goto done;
362         }
363     }
364     if (pt)
365     {
366         pt->x = dc->wndOrgX;
367         pt->y = dc->wndOrgY;
368     }
369     dc->wndOrgX = x;
370     dc->wndOrgY = y;
371     DC_UpdateXforms( dc );
372  done:
373     release_dc_ptr( dc );
374     return ret;
375 }
376
377
378 /***********************************************************************
379  *           OffsetViewportOrgEx    (GDI32.@)
380  */
381 BOOL WINAPI OffsetViewportOrgEx( HDC hdc, INT x, INT y, LPPOINT pt)
382 {
383     INT ret = TRUE;
384     DC * dc = get_dc_ptr( hdc );
385     if (!dc) return FALSE;
386     if (dc->funcs->pOffsetViewportOrg)
387     {
388         if((ret = dc->funcs->pOffsetViewportOrg( dc->physDev, x, y )) != TRUE)
389         {
390             if(ret == GDI_NO_MORE_WORK)
391                 ret = TRUE;
392             goto done;
393         }
394     }
395     if (pt)
396     {
397         pt->x = dc->vportOrgX;
398         pt->y = dc->vportOrgY;
399     }
400     dc->vportOrgX += x;
401     dc->vportOrgY += y;
402     DC_UpdateXforms( dc );
403  done:
404     release_dc_ptr( dc );
405     return ret;
406 }
407
408
409 /***********************************************************************
410  *           OffsetWindowOrgEx    (GDI32.@)
411  */
412 BOOL WINAPI OffsetWindowOrgEx( HDC hdc, INT x, INT y, LPPOINT pt )
413 {
414     INT ret = TRUE;
415     DC * dc = get_dc_ptr( hdc );
416     if (!dc) return FALSE;
417     if (dc->funcs->pOffsetWindowOrg)
418     {
419         if((ret = dc->funcs->pOffsetWindowOrg( dc->physDev, x, y )) != TRUE)
420         {
421             if(ret == GDI_NO_MORE_WORK)
422                 ret = TRUE;
423             goto done;
424         }
425     }
426     if (pt)
427     {
428         pt->x = dc->wndOrgX;
429         pt->y = dc->wndOrgY;
430     }
431     dc->wndOrgX += x;
432     dc->wndOrgY += y;
433     DC_UpdateXforms( dc );
434  done:
435     release_dc_ptr( dc );
436     return ret;
437 }
438
439
440 /***********************************************************************
441  *           ScaleViewportExtEx    (GDI32.@)
442  */
443 BOOL WINAPI ScaleViewportExtEx( HDC hdc, INT xNum, INT xDenom,
444                                     INT yNum, INT yDenom, LPSIZE size )
445 {
446     INT ret = TRUE;
447     DC * dc = get_dc_ptr( hdc );
448     if (!dc) return FALSE;
449     if (dc->funcs->pScaleViewportExt)
450     {
451         if((ret = dc->funcs->pScaleViewportExt( dc->physDev, xNum, xDenom, yNum, yDenom )) != TRUE)
452         {
453             if(ret == GDI_NO_MORE_WORK)
454                 ret = TRUE;
455             goto done;
456         }
457     }
458     if (size)
459     {
460         size->cx = dc->vportExtX;
461         size->cy = dc->vportExtY;
462     }
463     if ((dc->MapMode != MM_ISOTROPIC) && (dc->MapMode != MM_ANISOTROPIC))
464         goto done;
465     if (!xNum || !xDenom || !xNum || !yDenom)
466     {
467         ret = FALSE;
468         goto done;
469     }
470     dc->vportExtX = (dc->vportExtX * xNum) / xDenom;
471     dc->vportExtY = (dc->vportExtY * yNum) / yDenom;
472     if (dc->vportExtX == 0) dc->vportExtX = 1;
473     if (dc->vportExtY == 0) dc->vportExtY = 1;
474     if (dc->MapMode == MM_ISOTROPIC) MAPPING_FixIsotropic( dc );
475     DC_UpdateXforms( dc );
476  done:
477     release_dc_ptr( dc );
478     return ret;
479 }
480
481
482 /***********************************************************************
483  *           ScaleWindowExtEx    (GDI32.@)
484  */
485 BOOL WINAPI ScaleWindowExtEx( HDC hdc, INT xNum, INT xDenom,
486                                   INT yNum, INT yDenom, LPSIZE size )
487 {
488     INT ret = TRUE;
489     DC * dc = get_dc_ptr( hdc );
490     if (!dc) return FALSE;
491     if (dc->funcs->pScaleWindowExt)
492     {
493         if((ret = dc->funcs->pScaleWindowExt( dc->physDev, xNum, xDenom, yNum, yDenom )) != TRUE)
494         {
495             if(ret == GDI_NO_MORE_WORK)
496                 ret = TRUE;
497             goto done;
498         }
499     }
500     if (size)
501     {
502         size->cx = dc->wndExtX;
503         size->cy = dc->wndExtY;
504     }
505     if ((dc->MapMode != MM_ISOTROPIC) && (dc->MapMode != MM_ANISOTROPIC))
506         goto done;
507     if (!xNum || !xDenom || !xNum || !yDenom)
508     {
509         ret = FALSE;
510         goto done;
511     }
512     dc->wndExtX = (dc->wndExtX * xNum) / xDenom;
513     dc->wndExtY = (dc->wndExtY * yNum) / yDenom;
514     if (dc->wndExtX == 0) dc->wndExtX = 1;
515     if (dc->wndExtY == 0) dc->wndExtY = 1;
516     if (dc->MapMode == MM_ISOTROPIC) MAPPING_FixIsotropic( dc );
517     DC_UpdateXforms( dc );
518  done:
519     release_dc_ptr( dc );
520     return ret;
521 }