The provider functions are WINAPI.
[wine] / objects / clipping.c
1 /*
2  * DC clipping 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 <stdlib.h>
22 #include "windef.h"
23 #include "wingdi.h"
24 #include "wine/winuser16.h"
25 #include "gdi.h"
26 #include "wine/debug.h"
27
28 WINE_DEFAULT_DEBUG_CHANNEL(clipping);
29
30
31 /***********************************************************************
32  *           CLIPPING_UpdateGCRegion
33  *
34  * Update the GC clip region when the ClipRgn or VisRgn have changed.
35  */
36 void CLIPPING_UpdateGCRegion( DC * dc )
37 {
38     if (!dc->hGCClipRgn) dc->hGCClipRgn = CreateRectRgn( 0, 0, 0, 0 );
39
40     if (!dc->hVisRgn)
41     {
42         ERR("hVisRgn is zero. Please report this.\n" );
43         exit(1);
44     }
45
46     if (dc->flags & DC_DIRTY) ERR( "DC is dirty. Please report this.\n" );
47
48     if (!dc->hClipRgn)
49         CombineRgn( dc->hGCClipRgn, dc->hVisRgn, 0, RGN_COPY );
50     else
51         CombineRgn(dc->hGCClipRgn, dc->hClipRgn, dc->hVisRgn, RGN_AND);
52     if (dc->funcs->pSetDeviceClipping)
53         dc->funcs->pSetDeviceClipping( dc->physDev, dc->hGCClipRgn );
54 }
55
56
57 /***********************************************************************
58  *           SelectClipRgn    (GDI.44)
59  */
60 INT16 WINAPI SelectClipRgn16( HDC16 hdc, HRGN16 hrgn )
61 {
62     return (INT16)SelectClipRgn( hdc, hrgn );
63 }
64
65
66 /***********************************************************************
67  *           SelectClipRgn    (GDI32.@)
68  */
69 INT WINAPI SelectClipRgn( HDC hdc, HRGN hrgn )
70 {
71     return ExtSelectClipRgn( hdc, hrgn, RGN_COPY );
72 }
73
74 /******************************************************************************
75  *              ExtSelectClipRgn        [GDI.508]
76  */
77 INT16 WINAPI ExtSelectClipRgn16( HDC16 hdc, HRGN16 hrgn, INT16 fnMode )
78 {
79   return (INT16) ExtSelectClipRgn((HDC) hdc, (HRGN) hrgn, fnMode);
80 }
81
82 /******************************************************************************
83  *              ExtSelectClipRgn        [GDI32.@]
84  */
85 INT WINAPI ExtSelectClipRgn( HDC hdc, HRGN hrgn, INT fnMode )
86 {
87     INT retval;
88     DC * dc = DC_GetDCUpdate( hdc );
89     if (!dc) return ERROR;
90
91     TRACE("%04x %04x %d\n", hdc, hrgn, fnMode );
92
93     if (dc->funcs->pExtSelectClipRgn)
94     {
95         retval = dc->funcs->pExtSelectClipRgn( dc->physDev, hrgn, fnMode );
96         GDI_ReleaseObj( hdc );
97         return retval;
98     }
99
100     if (!hrgn)
101     {
102         if (fnMode == RGN_COPY)
103         {
104             if (dc->hClipRgn) DeleteObject( dc->hClipRgn );
105             dc->hClipRgn = 0;
106             retval = SIMPLEREGION; /* Clip region == whole DC */
107         }
108         else
109         {
110             FIXME("Unimplemented: hrgn NULL in mode: %d\n", fnMode);
111             GDI_ReleaseObj( hdc );
112             return ERROR;
113         }
114     }
115     else
116     {
117         if (!dc->hClipRgn)
118         {
119             RECT rect;
120             GetRgnBox( dc->hVisRgn, &rect );
121             dc->hClipRgn = CreateRectRgnIndirect( &rect );
122         }
123
124         if(fnMode == RGN_COPY)
125             retval = CombineRgn( dc->hClipRgn, hrgn, 0, fnMode );
126         else
127             retval = CombineRgn( dc->hClipRgn, dc->hClipRgn, hrgn, fnMode);
128     }
129
130     CLIPPING_UpdateGCRegion( dc );
131     GDI_ReleaseObj( hdc );
132     return retval;
133 }
134
135 /***********************************************************************
136  *           SelectVisRgn    (GDI.105)
137  */
138 INT16 WINAPI SelectVisRgn16( HDC16 hdc, HRGN16 hrgn )
139 {
140     int retval;
141     DC * dc;
142
143     if (!hrgn) return ERROR;
144     if (!(dc = DC_GetDCPtr( hdc ))) return ERROR;
145
146     TRACE("%04x %04x\n", hdc, hrgn );
147
148     dc->flags &= ~DC_DIRTY;
149
150     retval = CombineRgn16( dc->hVisRgn, hrgn, 0, RGN_COPY );
151     CLIPPING_UpdateGCRegion( dc );
152     GDI_ReleaseObj( hdc );
153     return retval;
154 }
155
156
157 /***********************************************************************
158  *           OffsetClipRgn    (GDI.32)
159  */
160 INT16 WINAPI OffsetClipRgn16( HDC16 hdc, INT16 x, INT16 y )
161 {
162     return (INT16)OffsetClipRgn( hdc, x, y );
163 }
164
165
166 /***********************************************************************
167  *           OffsetClipRgn    (GDI32.@)
168  */
169 INT WINAPI OffsetClipRgn( HDC hdc, INT x, INT y )
170 {
171     INT ret = SIMPLEREGION;
172     DC *dc = DC_GetDCUpdate( hdc );
173     if (!dc) return ERROR;
174
175     TRACE("%04x %d,%d\n", hdc, x, y );
176
177     if(dc->funcs->pOffsetClipRgn)
178         ret = dc->funcs->pOffsetClipRgn( dc->physDev, x, y );
179     else if (dc->hClipRgn) {
180         ret = OffsetRgn( dc->hClipRgn, XLSTODS(dc,x), YLSTODS(dc,y));
181         CLIPPING_UpdateGCRegion( dc );
182     }
183     GDI_ReleaseObj( hdc );
184     return ret;
185 }
186
187
188 /***********************************************************************
189  *           OffsetVisRgn    (GDI.102)
190  */
191 INT16 WINAPI OffsetVisRgn16( HDC16 hdc, INT16 x, INT16 y )
192 {
193     INT16 retval;
194     DC * dc = DC_GetDCUpdate( hdc );
195     if (!dc) return ERROR;
196     TRACE("%04x %d,%d\n", hdc, x, y );
197     retval = OffsetRgn( dc->hVisRgn, x, y );
198     CLIPPING_UpdateGCRegion( dc );
199     GDI_ReleaseObj( hdc );
200     return retval;
201 }
202
203
204 /***********************************************************************
205  *           ExcludeClipRect    (GDI.21)
206  */
207 INT16 WINAPI ExcludeClipRect16( HDC16 hdc, INT16 left, INT16 top,
208                                 INT16 right, INT16 bottom )
209 {
210     return (INT16)ExcludeClipRect( hdc, left, top, right, bottom );
211 }
212
213
214 /***********************************************************************
215  *           ExcludeClipRect    (GDI32.@)
216  */
217 INT WINAPI ExcludeClipRect( HDC hdc, INT left, INT top,
218                                 INT right, INT bottom )
219 {
220     HRGN newRgn;
221     INT ret;
222     DC *dc = DC_GetDCUpdate( hdc );
223     if (!dc) return ERROR;
224
225     TRACE("%04x %dx%d,%dx%d\n", hdc, left, top, right, bottom );
226
227     if(dc->funcs->pExcludeClipRect)
228         ret = dc->funcs->pExcludeClipRect( dc->physDev, left, top, right, bottom );
229     else
230     {
231         RECT rect;
232         rect.left = left;
233         rect.top = top;
234         rect.right = right;
235         rect.bottom = bottom;
236         LPtoDP( hdc, (POINT*)&rect, 2 );
237
238         if (!(newRgn = CreateRectRgn( rect.left, rect.top, rect.right, rect.bottom ))) ret = ERROR;
239         else
240         {
241             if (!dc->hClipRgn)
242             {
243                 dc->hClipRgn = CreateRectRgn( 0, 0, 0, 0 );
244                 CombineRgn( dc->hClipRgn, dc->hVisRgn, 0, RGN_COPY );
245             }
246             ret = CombineRgn( dc->hClipRgn, dc->hClipRgn, newRgn, RGN_DIFF );
247             DeleteObject( newRgn );
248         }
249         if (ret != ERROR) CLIPPING_UpdateGCRegion( dc );
250     }
251     GDI_ReleaseObj( hdc );
252     return ret;
253 }
254
255
256 /***********************************************************************
257  *           IntersectClipRect    (GDI.22)
258  */
259 INT16 WINAPI IntersectClipRect16( HDC16 hdc, INT16 left, INT16 top,
260                                   INT16 right, INT16 bottom )
261 {
262     return (INT16)IntersectClipRect( hdc, left, top, right, bottom );
263 }
264
265
266 /***********************************************************************
267  *           IntersectClipRect    (GDI32.@)
268  */
269 INT WINAPI IntersectClipRect( HDC hdc, INT left, INT top,
270                                   INT right, INT bottom )
271 {
272     INT ret;
273     DC *dc = DC_GetDCUpdate( hdc );
274     if (!dc) return ERROR;
275
276     TRACE("%04x %d,%d - %d,%d\n", hdc, left, top, right, bottom );
277
278     if(dc->funcs->pIntersectClipRect)
279         ret = dc->funcs->pIntersectClipRect( dc->physDev, left, top, right, bottom );
280     else
281     {
282         RECT rect;
283
284         rect.left   = left;
285         rect.top    = top;
286         rect.right  = right;
287         rect.bottom = bottom;
288         LPtoDP( hdc, (POINT*)&rect, 2 );
289
290         if (!dc->hClipRgn)
291         {
292             dc->hClipRgn = CreateRectRgn( rect.left, rect.top, rect.right, rect.bottom );
293             ret = SIMPLEREGION;
294         }
295         else
296         {
297             HRGN newRgn;
298
299             if (!(newRgn = CreateRectRgn( rect.left, rect.top, rect.right, rect.bottom))) ret = ERROR;
300             else
301             {
302                 ret = CombineRgn( dc->hClipRgn, dc->hClipRgn, newRgn, RGN_AND );
303                 DeleteObject( newRgn );
304             }
305         }
306         if (ret != ERROR) CLIPPING_UpdateGCRegion( dc );
307     }
308     GDI_ReleaseObj( hdc );
309     return ret;
310 }
311
312
313 /***********************************************************************
314  *           ExcludeVisRect    (GDI.73)
315  */
316 INT16 WINAPI ExcludeVisRect16( HDC16 hdc, INT16 left, INT16 top,
317                              INT16 right, INT16 bottom )
318 {
319     HRGN tempRgn;
320     INT16 ret;
321     RECT rect;
322     DC * dc = DC_GetDCUpdate( hdc );
323     if (!dc) return ERROR;
324
325     rect.left   = left;
326     rect.top    = top;
327     rect.right  = right;
328     rect.bottom = bottom;
329     LPtoDP( hdc, (POINT*)&rect, 2 );
330
331     TRACE("%04x %d,%d - %d,%d\n", hdc, rect.left, rect.top, rect.right, rect.bottom );
332
333     if (!(tempRgn = CreateRectRgn( rect.left, rect.top, rect.right, rect.bottom ))) ret = ERROR;
334     else
335     {
336         ret = CombineRgn( dc->hVisRgn, dc->hVisRgn, tempRgn, RGN_DIFF );
337         DeleteObject( tempRgn );
338     }
339     if (ret != ERROR) CLIPPING_UpdateGCRegion( dc );
340     GDI_ReleaseObj( hdc );
341     return ret;
342 }
343
344
345 /***********************************************************************
346  *           IntersectVisRect    (GDI.98)
347  */
348 INT16 WINAPI IntersectVisRect16( HDC16 hdc, INT16 left, INT16 top,
349                                INT16 right, INT16 bottom )
350 {
351     HRGN tempRgn;
352     INT16 ret;
353     RECT rect;
354     DC * dc = DC_GetDCUpdate( hdc );
355     if (!dc) return ERROR;
356
357     rect.left   = left;
358     rect.top    = top;
359     rect.right  = right;
360     rect.bottom = bottom;
361     LPtoDP( hdc, (POINT*)&rect, 2 );
362
363     TRACE("%04x %d,%d - %d,%d\n", hdc, rect.left, rect.top, rect.right, rect.bottom );
364
365     if (!(tempRgn = CreateRectRgn( rect.left, rect.top, rect.right, rect.bottom ))) ret = ERROR;
366     else
367     {
368         ret = CombineRgn( dc->hVisRgn, dc->hVisRgn, tempRgn, RGN_AND );
369         DeleteObject( tempRgn );
370     }
371     if (ret != ERROR) CLIPPING_UpdateGCRegion( dc );
372     GDI_ReleaseObj( hdc );
373     return ret;
374 }
375
376
377 /***********************************************************************
378  *           PtVisible    (GDI.103)
379  */
380 BOOL16 WINAPI PtVisible16( HDC16 hdc, INT16 x, INT16 y )
381 {
382     return PtVisible( hdc, x, y );
383 }
384
385
386 /***********************************************************************
387  *           PtVisible    (GDI32.@)
388  */
389 BOOL WINAPI PtVisible( HDC hdc, INT x, INT y )
390 {
391     BOOL ret = FALSE;
392     DC *dc = DC_GetDCUpdate( hdc );
393
394     TRACE("%04x %d,%d\n", hdc, x, y );
395     if (!dc) return FALSE;
396     if (dc->hGCClipRgn)
397     {
398         POINT pt;
399
400         pt.x = x;
401         pt.y = y;
402         LPtoDP( hdc, &pt, 1 );
403         ret = PtInRegion( dc->hGCClipRgn, pt.x, pt.y );
404     }
405     GDI_ReleaseObj( hdc );
406     return ret;
407 }
408
409
410 /***********************************************************************
411  *           RectVisible    (GDI.465)
412  *           RectVisibleOld (GDI.104)
413  */
414 BOOL16 WINAPI RectVisible16( HDC16 hdc, const RECT16* rect16 )
415 {
416     RECT rect;
417     CONV_RECT16TO32( rect16, &rect );
418     return RectVisible( hdc, &rect );
419 }
420
421
422 /***********************************************************************
423  *           RectVisible    (GDI32.@)
424  */
425 BOOL WINAPI RectVisible( HDC hdc, const RECT* rect )
426 {
427     BOOL ret = FALSE;
428     RECT tmpRect;
429     DC *dc = DC_GetDCUpdate( hdc );
430     if (!dc) return FALSE;
431     TRACE("%04x %d,%dx%d,%d\n",
432           hdc, rect->left, rect->top, rect->right, rect->bottom );
433     if (dc->hGCClipRgn)
434     {
435         /* copy rectangle to avoid overwriting by LPtoDP */
436         tmpRect = *rect;
437         LPtoDP( hdc, (LPPOINT)&tmpRect, 2 );
438         ret = RectInRegion( dc->hGCClipRgn, &tmpRect );
439     }
440     GDI_ReleaseObj( hdc );
441     return ret;
442 }
443
444
445 /***********************************************************************
446  *           GetClipBox    (GDI.77)
447  */
448 INT16 WINAPI GetClipBox16( HDC16 hdc, LPRECT16 rect )
449 {
450     int ret;
451     DC *dc = DC_GetDCUpdate( hdc );
452     if (!dc) return ERROR;
453     ret = GetRgnBox16( dc->hGCClipRgn, rect );
454     DPtoLP16( hdc, (LPPOINT16)rect, 2 );
455     TRACE("%d,%d-%d,%d\n", rect->left,rect->top,rect->right,rect->bottom );
456     GDI_ReleaseObj( hdc );
457     return ret;
458 }
459
460
461 /***********************************************************************
462  *           GetClipBox    (GDI32.@)
463  */
464 INT WINAPI GetClipBox( HDC hdc, LPRECT rect )
465 {
466     INT ret;
467     DC *dc = DC_GetDCUpdate( hdc );
468     if (!dc) return ERROR;
469     ret = GetRgnBox( dc->hGCClipRgn, rect );
470     DPtoLP( hdc, (LPPOINT)rect, 2 );
471     GDI_ReleaseObj( hdc );
472     return ret;
473 }
474
475
476 /***********************************************************************
477  *           GetClipRgn  (GDI32.@)
478  */
479 INT WINAPI GetClipRgn( HDC hdc, HRGN hRgn )
480 {
481     INT ret = -1;
482     DC * dc;
483     if (hRgn && (dc = DC_GetDCPtr( hdc )))
484     {
485       if( dc->hClipRgn )
486       {
487           if( CombineRgn(hRgn, dc->hClipRgn, 0, RGN_COPY) != ERROR ) ret = 1;
488       }
489       else ret = 0;
490       GDI_ReleaseObj( hdc );
491     }
492     return ret;
493 }
494
495 /***********************************************************************
496  *           SaveVisRgn    (GDI.129)
497  */
498 HRGN16 WINAPI SaveVisRgn16( HDC16 hdc )
499 {
500     HRGN copy;
501     GDIOBJHDR *obj, *copyObj;
502     DC *dc = DC_GetDCUpdate( hdc );
503
504     if (!dc) return 0;
505     TRACE("%04x\n", hdc );
506
507     if (!(obj = GDI_GetObjPtr( dc->hVisRgn, REGION_MAGIC )))
508     {
509         GDI_ReleaseObj( hdc );
510         return 0;
511     }
512     if (!(copy = CreateRectRgn( 0, 0, 0, 0 )))
513     {
514         GDI_ReleaseObj( dc->hVisRgn );
515         GDI_ReleaseObj( hdc );
516         return 0;
517     }
518     CombineRgn( copy, dc->hVisRgn, 0, RGN_COPY );
519     if (!(copyObj = GDI_GetObjPtr( copy, REGION_MAGIC )))
520     {
521         DeleteObject( copy );
522         GDI_ReleaseObj( dc->hVisRgn );
523         GDI_ReleaseObj( hdc );
524         return 0;
525     }
526     copyObj->hNext = obj->hNext;
527     obj->hNext = copy;
528     GDI_ReleaseObj( copy );
529     GDI_ReleaseObj( dc->hVisRgn );
530     GDI_ReleaseObj( hdc );
531     return copy;
532 }
533
534
535 /***********************************************************************
536  *           RestoreVisRgn    (GDI.130)
537  */
538 INT16 WINAPI RestoreVisRgn16( HDC16 hdc )
539 {
540     HRGN saved;
541     GDIOBJHDR *obj, *savedObj;
542     DC *dc = DC_GetDCPtr( hdc );
543     INT16 ret = ERROR;
544
545     if (!dc) return ERROR;
546
547     TRACE("%04x\n", hdc );
548
549     if (!(obj = GDI_GetObjPtr( dc->hVisRgn, REGION_MAGIC ))) goto done;
550     saved = obj->hNext;
551
552     if ((savedObj = GDI_GetObjPtr( saved, REGION_MAGIC )))
553     {
554         ret = CombineRgn( dc->hVisRgn, saved, 0, RGN_COPY );
555         obj->hNext = savedObj->hNext;
556         GDI_ReleaseObj( saved );
557         DeleteObject( saved );
558         dc->flags &= ~DC_DIRTY;
559         CLIPPING_UpdateGCRegion( dc );
560     }
561     GDI_ReleaseObj( dc->hVisRgn );
562  done:
563     GDI_ReleaseObj( hdc );
564     return ret;
565 }