]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkregion-win32.c
Don't draw anything if width or height is zero. Don't print a warning if
[~andy/gtk] / gdk / win32 / gdkregion-win32.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #include "config.h"
28
29 #include <gdk/gdk.h>
30 #include "gdkprivate.h"
31
32
33 GdkRegion*
34 gdk_region_new (void)
35 {
36   GdkRegionPrivate *private;
37   GdkRegion *region;
38   HRGN xregion;
39   RECT emptyRect;
40
41   /* Create an empty region */
42   SetRectEmpty (&emptyRect);
43   xregion = CreateRectRgnIndirect (&emptyRect);
44   private = g_new (GdkRegionPrivate, 1);
45   private->xregion = xregion;
46   region = (GdkRegion*) private;
47   region->user_data = NULL;
48
49   return region;
50 }
51
52 void
53 gdk_region_destroy (GdkRegion *region)
54 {
55   GdkRegionPrivate *private;
56
57   g_return_if_fail (region != NULL);
58
59   private = (GdkRegionPrivate *) region;
60   DeleteObject (private->xregion);
61   g_free (private);
62 }
63
64 gboolean
65 gdk_region_empty (GdkRegion      *region)
66 {
67   GdkRegionPrivate *private;
68   RECT rect;
69
70   g_return_val_if_fail (region != NULL, 0);
71
72   private = (GdkRegionPrivate *) region;
73   
74   return (GetRgnBox (private->xregion, &rect) == NULLREGION);
75 }
76
77 gboolean
78 gdk_region_equal (GdkRegion      *region1,
79                   GdkRegion      *region2)
80 {
81   GdkRegionPrivate *private1;
82   GdkRegionPrivate *private2;
83
84   g_return_val_if_fail (region1 != NULL, 0);
85   g_return_val_if_fail (region2 != NULL, 0);
86
87   private1 = (GdkRegionPrivate *) region1;
88   private2 = (GdkRegionPrivate *) region2;
89   
90   return EqualRgn (private1->xregion, private2->xregion);
91 }
92
93 void
94 gdk_region_get_clipbox(GdkRegion    *region,
95                        GdkRectangle *rectangle)
96 {
97   GdkRegionPrivate *rp;
98   RECT r;
99   
100   g_return_if_fail(region != NULL);
101   g_return_if_fail(rectangle != NULL);
102
103   rp = (GdkRegionPrivate *)region;
104     
105   GetRgnBox (rp->xregion, &r);
106   rectangle->x = r.left;
107   rectangle->y = r.top;
108   rectangle->width = r.right - r.left;
109   rectangle->height = r.bottom - r.top;
110 }
111
112 gboolean
113 gdk_region_point_in (GdkRegion      *region,
114                      gint           x,
115                      gint           y)
116 {
117   GdkRegionPrivate *private;
118
119   g_return_val_if_fail (region != NULL, 0);
120
121   private = (GdkRegionPrivate *) region;
122   
123   return PtInRegion (private->xregion, x, y);
124 }
125
126 GdkOverlapType
127 gdk_region_rect_in (GdkRegion      *region,
128                     GdkRectangle   *rect)
129 {
130   GdkRegionPrivate *private;
131   RECT r;
132   int res;
133
134   g_return_val_if_fail (region != NULL, 0);
135
136   private = (GdkRegionPrivate *) region;
137   
138   r.left = rect->x;
139   r.top = rect->y;
140   r.right = rect->x + rect->width;
141   r.bottom = rect->y + rect->height;
142   
143   if (RectInRegion (private->xregion, &r))
144     return GDK_OVERLAP_RECTANGLE_PART;
145
146   return GDK_OVERLAP_RECTANGLE_OUT;  /*what else ? */
147 }
148                                     
149 GdkRegion *
150 gdk_region_polygon (GdkPoint    *points,
151                     gint         npoints,
152                     GdkFillRule  fill_rule)
153 {
154   GdkRegionPrivate *private;
155   GdkRegion *region;
156   HRGN xregion;
157   POINT *pts;
158   gint xfill_rule = ALTERNATE;
159   gint i;
160
161   g_return_val_if_fail (points != NULL, NULL);
162   g_return_val_if_fail (npoints != 0, NULL); /* maybe we should check for at least three points */
163
164   switch (fill_rule)
165     {
166     case GDK_EVEN_ODD_RULE:
167       xfill_rule = ALTERNATE;
168       break;
169
170     case GDK_WINDING_RULE:
171       xfill_rule = WINDING;
172       break;
173     }
174
175   pts = g_malloc (npoints * sizeof (*pts));
176   for (i = 0; i < npoints; i++)
177     {
178       pts[i].x = points[i].x;
179       pts[i].y = points[i].y;
180     }
181   xregion = CreatePolygonRgn (pts, npoints, xfill_rule);
182   g_free (pts);
183
184   private = g_new (GdkRegionPrivate, 1);
185   private->xregion = xregion;
186   region = (GdkRegion *) private;
187   region->user_data = NULL;
188
189   return region;
190 }
191
192 void          
193 gdk_region_offset (GdkRegion      *region,
194                    gint           dx,
195                    gint           dy)
196 {
197   GdkRegionPrivate *private;
198
199   g_return_if_fail (region != NULL);
200
201   private = (GdkRegionPrivate *) region;
202   
203   OffsetRgn (private->xregion, dx, dy);
204 }
205
206 void
207 gdk_region_shrink (GdkRegion      *region,
208                    gint           dx,
209                    gint           dy)
210 {
211   GdkRegionPrivate *private;
212   HRGN shrunken_bbox;
213   RECT r;
214
215   g_return_if_fail (region != NULL);
216
217   private = (GdkRegionPrivate *) region;
218   
219   if (dx > 0 || dy > 0)
220     {
221       /* We want to shrink it in one or both dimensions.
222        * Is it correct just to intersect it with a smaller bounding box?
223        * XXX
224        */
225       GetRgnBox (private->xregion, &r);
226       if (dx > 0)
227         {
228           r.left += dx - dx/2;
229           r.right -= dx/2;
230         }
231       if (dy > 0)
232         {
233           r.top += dy - dy/2;
234           r.bottom -= dy/2;
235         }
236
237       shrunken_bbox = CreateRectRgnIndirect (&r);
238       CombineRgn (private->xregion, private->xregion,
239                   shrunken_bbox, RGN_AND);
240       DeleteObject (shrunken_bbox);
241     }
242   else
243     {
244       /* Do nothing if the regions is expanded? XXX */
245     }
246 }
247
248 GdkRegion*    
249 gdk_region_union_with_rect (GdkRegion      *region,
250                             GdkRectangle   *rect)
251 {
252   GdkRegionPrivate *private;
253   GdkRegion *res;
254   GdkRegionPrivate *res_private;
255   RECT xrect;
256   HRGN rectangle;
257
258   g_return_val_if_fail (region != NULL, NULL);
259
260   private = (GdkRegionPrivate *) region;
261   
262   xrect.left = rect->x;
263   xrect.top = rect->y;
264   xrect.right = rect->x + rect->width;
265   xrect.bottom = rect->y + rect->height;
266
267   res = gdk_region_new ();
268   res_private = (GdkRegionPrivate *) res;
269   
270   rectangle = CreateRectRgnIndirect (&xrect);
271   CombineRgn (res_private->xregion, private->xregion,
272               rectangle, RGN_OR);
273   DeleteObject (rectangle);
274   return res;
275 }
276
277 GdkRegion*    
278 gdk_regions_intersect (GdkRegion      *source1,
279                        GdkRegion      *source2)
280 {
281   GdkRegionPrivate *private1;
282   GdkRegionPrivate *private2;
283   GdkRegion *res;
284   GdkRegionPrivate *res_private;
285
286   g_return_val_if_fail (source1 != NULL, NULL);
287   g_return_val_if_fail (source2 != NULL, NULL);
288
289   private1 = (GdkRegionPrivate *) source1;
290   private2 = (GdkRegionPrivate *) source2;
291
292   res = gdk_region_new ();
293   res_private = (GdkRegionPrivate *) res;
294   
295   CombineRgn (res_private->xregion, private1->xregion, private2->xregion,
296               RGN_AND);
297   return res;
298 }
299
300 GdkRegion* 
301 gdk_regions_union (GdkRegion      *source1,
302                    GdkRegion      *source2)
303 {
304   GdkRegionPrivate *private1;
305   GdkRegionPrivate *private2;
306   GdkRegion *res;
307   GdkRegionPrivate *res_private;
308
309   g_return_val_if_fail (source1 != NULL, NULL);
310   g_return_val_if_fail (source2 != NULL, NULL);
311
312   private1 = (GdkRegionPrivate *) source1;
313   private2 = (GdkRegionPrivate *) source2;
314
315   res = gdk_region_new ();
316   res_private = (GdkRegionPrivate *) res;
317   
318   CombineRgn (res_private->xregion, private1->xregion, private2->xregion,
319               RGN_OR);
320   return res;
321 }
322
323 GdkRegion*    
324 gdk_regions_subtract (GdkRegion      *source1,
325                       GdkRegion      *source2)
326 {
327   GdkRegionPrivate *private1;
328   GdkRegionPrivate *private2;
329   GdkRegion *res;
330   GdkRegionPrivate *res_private;
331
332   g_return_val_if_fail (source1 != NULL, NULL);
333   g_return_val_if_fail (source2 != NULL, NULL);
334
335   private1 = (GdkRegionPrivate *) source1;
336   private2 = (GdkRegionPrivate *) source2;
337
338   res = gdk_region_new ();
339   res_private = (GdkRegionPrivate *) res;
340   
341   CombineRgn (res_private->xregion, private1->xregion, private2->xregion,
342               RGN_DIFF);
343   return res;
344 }
345
346 GdkRegion*    
347 gdk_regions_xor (GdkRegion      *source1,
348                  GdkRegion      *source2)
349 {
350   GdkRegionPrivate *private1;
351   GdkRegionPrivate *private2;
352   GdkRegion *res;
353   GdkRegionPrivate *res_private;
354
355   g_return_val_if_fail (source1 != NULL, NULL);
356   g_return_val_if_fail (source2 != NULL, NULL);
357
358   private1 = (GdkRegionPrivate *) source1;
359   private2 = (GdkRegionPrivate *) source2;
360
361   res = gdk_region_new ();
362   res_private = (GdkRegionPrivate *) res;
363   
364   CombineRgn (res_private->xregion, private1->xregion, private2->xregion,
365               RGN_XOR);
366   return res;
367 }