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