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