Release 940912
[wine] / objects / clipping.c
1 /*
2  * DC clipping functions
3  *
4  * Copyright 1993 Alexandre Julliard
5  */
6
7 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
8
9 #include <stdio.h>
10 #include "gdi.h"
11 #include "metafile.h"
12
13
14 /***********************************************************************
15  *           CLIPPING_SetDeviceClipping
16  *
17  * Set the clip region of the physical device.
18  */
19 void CLIPPING_SetDeviceClipping( DC * dc )
20 {
21     if (dc->w.hGCClipRgn)
22     {
23         RGNOBJ *obj = (RGNOBJ *) GDI_GetObjPtr(dc->w.hGCClipRgn, REGION_MAGIC);
24         if (obj->region.xrgn)
25         {
26             XSetRegion( display, dc->u.x.gc, obj->region.xrgn );
27             XSetClipOrigin( display, dc->u.x.gc, dc->w.DCOrgX, dc->w.DCOrgY );
28         }
29         else if (obj->region.pixmap)
30         {
31             XSetClipMask( display, dc->u.x.gc, obj->region.pixmap );
32             XSetClipOrigin( display, dc->u.x.gc,
33                             dc->w.DCOrgX + obj->region.box.left,
34                             dc->w.DCOrgY + obj->region.box.top );
35         }
36         else  /* Clip everything */
37         {
38             XSetClipRectangles( display, dc->u.x.gc, 0, 0, NULL, 0, 0 );
39         }
40     }
41     else
42     {
43         XSetClipMask( display, dc->u.x.gc, None );
44         XSetClipOrigin( display, dc->u.x.gc, dc->w.DCOrgX, dc->w.DCOrgY );
45     }
46 }
47
48
49 /***********************************************************************
50  *           CLIPPING_UpdateGCRegion
51  *
52  * Update the GC clip region when the ClipRgn or VisRgn have changed.
53  */
54 static void CLIPPING_UpdateGCRegion( DC * dc )
55 {
56     if (!dc->w.hGCClipRgn) dc->w.hGCClipRgn = CreateRectRgn(0,0,0,0);
57
58     if (!dc->w.hVisRgn)
59     {
60         if (!dc->w.hClipRgn)
61         {
62             DeleteObject( dc->w.hGCClipRgn );
63             dc->w.hGCClipRgn = 0;
64         }
65         else
66             CombineRgn( dc->w.hGCClipRgn, dc->w.hClipRgn, 0, RGN_COPY );
67     }
68     else
69     {
70         if (!dc->w.hClipRgn)
71             CombineRgn( dc->w.hGCClipRgn, dc->w.hVisRgn, 0, RGN_COPY );
72         else
73             CombineRgn( dc->w.hGCClipRgn, dc->w.hClipRgn, dc->w.hVisRgn, RGN_AND );
74     }
75     CLIPPING_SetDeviceClipping( dc );
76 }
77
78
79 /***********************************************************************
80  *           CLIPPING_SelectRgn
81  *
82  * Helper function for SelectClipRgn() and SelectVisRgn().
83  */
84 static int CLIPPING_SelectRgn( DC * dc, HRGN * hrgnPrev, HRGN hrgn )
85 {
86     int retval;
87     
88     if (hrgn)
89     {
90         if (!*hrgnPrev) *hrgnPrev = CreateRectRgn(0,0,0,0);
91         retval = CombineRgn( *hrgnPrev, hrgn, 0, RGN_COPY );
92     }
93     else
94     {
95         if (*hrgnPrev) DeleteObject( *hrgnPrev );
96         *hrgnPrev = 0;
97         retval = SIMPLEREGION; /* Clip region == client area */
98     }
99     CLIPPING_UpdateGCRegion( dc );
100     return retval;
101 }
102
103
104 /***********************************************************************
105  *           SelectClipRgn    (GDI.44)
106  */
107 int SelectClipRgn( HDC hdc, HRGN hrgn )
108 {
109     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
110     if (!dc) return ERROR;
111     
112 #ifdef DEBUG_CLIPPING
113     printf( "SelectClipRgn: %d %d\n", hdc, hrgn );
114 #endif
115     return CLIPPING_SelectRgn( dc, &dc->w.hClipRgn, hrgn );
116 }
117
118
119 /***********************************************************************
120  *           SelectVisRgn    (GDI.105)
121  */
122 int SelectVisRgn( HDC hdc, HRGN hrgn )
123 {
124     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
125     if (!dc) return ERROR;
126     
127 #ifdef DEBUG_CLIPPING
128     printf( "SelectVisRgn: %d %d\n", hdc, hrgn );
129 #endif
130     return CLIPPING_SelectRgn( dc, &dc->w.hVisRgn, hrgn );
131 }
132
133
134 /***********************************************************************
135  *           OffsetClipRgn    (GDI.32)
136  */
137 int OffsetClipRgn( HDC hdc, short x, short y )
138 {
139     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
140     if (!dc) 
141     {
142         dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
143         if (!dc) return ERROR;
144         MF_MetaParam2(dc, META_OFFSETCLIPRGN, x, y);
145         return NULLREGION;   /* ?? */
146     }
147
148 #ifdef DEBUG_CLIPPING
149     printf( "OffsetClipRgn: %d %d,%d\n", hdc, x, y );
150 #endif
151
152     if (dc->w.hClipRgn)
153     {
154         int retval = OffsetRgn( dc->w.hClipRgn, x, y );
155         CLIPPING_UpdateGCRegion( dc );
156         return retval;
157     }
158     else return SIMPLEREGION; /* Clip region == client area */
159 }
160
161
162 /***********************************************************************
163  *           OffsetVisRgn    (GDI.102)
164  */
165 int OffsetVisRgn( HDC hdc, short x, short y )
166 {
167     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
168     if (!dc) return ERROR;    
169 #ifdef DEBUG_CLIPPING
170     printf( "OffsetVisRgn: %d %d,%d\n", hdc, x, y );
171 #endif
172
173     if (dc->w.hVisRgn)
174     {
175         int retval = OffsetRgn( dc->w.hVisRgn, x, y );
176         CLIPPING_UpdateGCRegion( dc );
177         return retval;
178     }
179     else return SIMPLEREGION; /* Clip region == client area */
180 }
181
182
183 /***********************************************************************
184  *           CLIPPING_IntersectRect
185  *
186  * Helper function for {Intersect,Exclude}{Clip,Vis}Rect
187  */
188 int CLIPPING_IntersectRect( DC * dc, HRGN * hrgn, short left, short top,
189                             short right, short bottom, int exclude )
190 {
191     HRGN tempRgn = 0, prevRgn = 0, newRgn = 0;
192     RGNOBJ *newObj, *prevObj;
193     int retval;
194
195     if (!*hrgn)
196     {
197         if (!(*hrgn = CreateRectRgn( 0, 0, dc->w.DCSizeX, dc->w.DCSizeY )))
198             goto Error;
199         prevRgn = *hrgn;
200     }
201     if (!(newRgn = CreateRectRgn( 0, 0, 0, 0))) goto Error;
202     if (!(tempRgn = CreateRectRgn( left, top, right, bottom ))) goto Error;
203
204     retval = CombineRgn( newRgn, *hrgn, tempRgn, exclude ? RGN_DIFF : RGN_AND);
205     if (retval == ERROR) goto Error;
206
207     newObj = (RGNOBJ *) GDI_GetObjPtr( newRgn, REGION_MAGIC );
208     prevObj = (RGNOBJ *) GDI_GetObjPtr( *hrgn, REGION_MAGIC );
209     if (newObj && prevObj) newObj->header.hNext = prevObj->header.hNext;
210     DeleteObject( tempRgn );
211     if (*hrgn) DeleteObject( *hrgn );
212     *hrgn = newRgn;    
213     CLIPPING_UpdateGCRegion( dc );
214     return retval;
215
216  Error:
217     if (tempRgn) DeleteObject( tempRgn );
218     if (newRgn) DeleteObject( newRgn );
219     if (prevRgn)
220     {
221         DeleteObject( prevRgn );
222         *hrgn = 0;
223     }
224     return ERROR;
225 }
226
227
228 /***********************************************************************
229  *           ExcludeClipRect    (GDI.21)
230  */
231 int ExcludeClipRect( HDC hdc, short left, short top,
232                      short right, short bottom )
233 {
234     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
235     if (!dc) 
236     {
237         dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
238         if (!dc) return ERROR;
239         MF_MetaParam4(dc, META_EXCLUDECLIPRECT, left, top, right, bottom);
240         return NULLREGION;   /* ?? */
241     }
242
243 #ifdef DEBUG_CLIPPING
244     printf( "ExcludeClipRect: %d %dx%d,%dx%d\n",
245             hdc, left, top, right, bottom );
246 #endif
247     return CLIPPING_IntersectRect( dc, &dc->w.hClipRgn, left, top,
248                                    right, bottom, 1 );
249 }
250
251
252 /***********************************************************************
253  *           IntersectClipRect    (GDI.22)
254  */
255 int IntersectClipRect( HDC hdc, short left, short top,
256                        short right, short bottom )
257 {
258     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
259     if (!dc) 
260     {
261         dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
262         if (!dc) return ERROR;
263         MF_MetaParam4(dc, META_INTERSECTCLIPRECT, left, top, right, bottom);
264         return NULLREGION;   /* ?? */
265     }
266
267 #ifdef DEBUG_CLIPPING
268     printf( "IntersectClipRect: %d %dx%d,%dx%d\n",
269             hdc, left, top, right, bottom );
270 #endif
271     return CLIPPING_IntersectRect( dc, &dc->w.hClipRgn, left, top,
272                                    right, bottom, 0 );
273 }
274
275
276 /***********************************************************************
277  *           ExcludeVisRect    (GDI.73)
278  */
279 int ExcludeVisRect( HDC hdc, short left, short top,
280                     short right, short bottom )
281 {
282     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
283     if (!dc) return ERROR;    
284 #ifdef DEBUG_CLIPPING
285     printf( "ExcludeVisRect: %d %dx%d,%dx%d\n",
286             hdc, left, top, right, bottom );
287 #endif
288     return CLIPPING_IntersectRect( dc, &dc->w.hVisRgn, left, top,
289                                    right, bottom, 1 );
290 }
291
292
293 /***********************************************************************
294  *           IntersectVisRect    (GDI.98)
295  */
296 int IntersectVisRect( HDC hdc, short left, short top,
297                       short right, short bottom )
298 {
299     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
300     if (!dc) return ERROR;    
301 #ifdef DEBUG_CLIPPING
302     printf( "IntersectVisRect: %d %dx%d,%dx%d\n",
303             hdc, left, top, right, bottom );
304 #endif
305     return CLIPPING_IntersectRect( dc, &dc->w.hVisRgn, left, top,
306                                    right, bottom, 0 );
307 }
308
309
310 /***********************************************************************
311  *           PtVisible    (GDI.103)
312  */
313 BOOL PtVisible( HDC hdc, short x, short y )
314 {
315     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
316     if (!dc) return ERROR;    
317 #ifdef DEBUG_CLIPPING
318     printf( "PtVisible: %d %d,%d\n", hdc, x, y );
319 #endif
320     if (!dc->w.hClipRgn) return FALSE;
321     return PtInRegion( dc->w.hClipRgn, x, y );
322 }
323
324
325 /***********************************************************************
326  *           RectVisible    (GDI.104)
327  */
328 BOOL RectVisible( HDC hdc, LPRECT rect )
329 {
330     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
331     if (!dc) return ERROR;    
332 #ifdef DEBUG_CLIPPING
333     printf( "RectVisible: %d %p\n", hdc, rect );
334 #endif
335     if (!dc->w.hClipRgn) return FALSE;
336     return RectInRegion( dc->w.hClipRgn, rect );
337 }
338
339
340 /***********************************************************************
341  *           GetClipBox    (GDI.77)
342  */
343 int GetClipBox( HDC hdc, LPRECT rect )
344 {
345     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
346     if (!dc) return ERROR;    
347 #ifdef DEBUG_CLIPPING
348     printf( "GetClipBox: %d %p\n", hdc, rect );
349 #endif
350
351     if (dc->w.hGCClipRgn) return GetRgnBox( dc->w.hGCClipRgn, rect );
352     else
353     {
354         rect->top = rect->left = 0;
355         rect->right = dc->w.DCSizeX;
356         rect->bottom = dc->w.DCSizeY;
357         return SIMPLEREGION;
358     }
359 }
360
361
362 /***********************************************************************
363  *           SaveVisRgn    (GDI.129)
364  */
365 HRGN SaveVisRgn( HDC hdc )
366 {
367     HRGN copy;
368     RGNOBJ *obj, *copyObj;
369     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
370     if (!dc) return 0;
371 #ifdef DEBUG_CLIPPING
372     printf( "SaveVisRgn: %d\n", hdc );
373 #endif
374     if (!dc->w.hVisRgn) return 0;
375     if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC )))
376         return 0;
377     if (!(copy = CreateRectRgn( 0, 0, 0, 0 ))) return 0;
378     CombineRgn( copy, dc->w.hVisRgn, 0, RGN_COPY );
379     if (!(copyObj = (RGNOBJ *) GDI_GetObjPtr( copy, REGION_MAGIC )))
380         return 0;
381     copyObj->header.hNext = obj->header.hNext;
382     obj->header.hNext = copy;
383     return copy;
384 }
385
386
387 /***********************************************************************
388  *           RestoreVisRgn    (GDI.130)
389  */
390 int RestoreVisRgn( HDC hdc )
391 {
392     HRGN saved;
393     RGNOBJ *obj, *savedObj;
394     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
395     if (!dc) return ERROR;    
396 #ifdef DEBUG_CLIPPING
397     printf( "RestoreVisRgn: %d\n", hdc );
398 #endif
399     if (!dc->w.hVisRgn) return ERROR;
400     if (!(obj = (RGNOBJ *) GDI_GetObjPtr( dc->w.hVisRgn, REGION_MAGIC )))
401         return ERROR;
402     if (!(saved = obj->header.hNext)) return ERROR;
403     if (!(savedObj = (RGNOBJ *) GDI_GetObjPtr( saved, REGION_MAGIC )))
404         return ERROR;
405     DeleteObject( dc->w.hVisRgn );
406     dc->w.hVisRgn = saved;
407     CLIPPING_UpdateGCRegion( dc );
408     return savedObj->region.type;
409 }