Corrected wrong use of delete in region code.
[wxWidgets.git] / src / x11 / region.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // File: region.cpp
3 // Purpose: Region class
4 // Author: Markus Holzem, Julian Smart, Robert Roebling
5 // Created: Fri Oct 24 10:46:34 MET 1997
6 // RCS-ID: $Id$
7 // Copyright: (c) 1997 Markus Holzem, Julian Smart, Robert Roebling
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 #ifdef __GNUG__
12 #pragma implementation "region.h"
13 #endif
14
15 #include "wx/region.h"
16 #include "wx/gdicmn.h"
17 #include "wx/log.h"
18
19 #ifdef __VMS__
20 #pragma message disable nosimpint
21 #endif
22 #include "wx/x11/private.h"
23 #include "X11/Xutil.h"
24 #ifdef __VMS__
25 #pragma message enable nosimpint
26 #endif
27
28 // ----------------------------------------------------------------------------
29 // wxRegionRefData: private class containing the information about the region
30 // ----------------------------------------------------------------------------
31
32 class wxRegionRefData : public wxObjectRefData
33 {
34 public:
35 wxRegionRefData()
36 {
37 m_region = NULL;
38 }
39
40 wxRegionRefData(const wxRegionRefData& refData)
41 {
42 m_region = XCreateRegion();
43 XUnionRegion( refData.m_region, m_region, m_region );
44 }
45
46 ~wxRegionRefData()
47 {
48 if (m_region)
49 XDestroyRegion( m_region );
50 }
51
52 Region m_region;
53 };
54
55 // ----------------------------------------------------------------------------
56 // macros
57 // ----------------------------------------------------------------------------
58
59 #define M_REGIONDATA ((wxRegionRefData *)m_refData)
60 #define M_REGIONDATA_OF(rgn) ((wxRegionRefData *)(rgn.m_refData))
61
62 IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject);
63 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator,wxObject);
64
65 // ----------------------------------------------------------------------------
66 // wxRegion construction
67 // ----------------------------------------------------------------------------
68
69 #define M_REGIONDATA ((wxRegionRefData *)m_refData)
70
71 void wxRegion::InitRect(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
72 {
73 XRectangle rect;
74 rect.x = x;
75 rect.y = y;
76 rect.width = w;
77 rect.height = h;
78
79 m_refData = new wxRegionRefData();
80
81 M_REGIONDATA->m_region = XCreateRegion();
82 XUnionRectWithRegion( &rect, M_REGIONDATA->m_region, M_REGIONDATA->m_region );
83 }
84
85 wxRegion::wxRegion( size_t n, const wxPoint *points, int fillStyle )
86 {
87 #if 0
88 XPoint *xpoints = new XPoint[n];
89 for ( size_t i = 0 ; i < n ; i++ )
90 {
91 xpoints[i].x = points[i].x;
92 xpoints[i].y = points[i].y;
93 }
94
95 m_refData = new wxRegionRefData();
96
97 Region* reg = gdk_region_polygon
98 (
99 gdkpoints,
100 n,
101 fillStyle == wxWINDING_RULE ? GDK_WINDING_RULE
102 : GDK_EVEN_ODD_RULE
103 );
104
105 M_REGIONDATA->m_region = reg;
106
107 delete [] xpoints;
108 #endif
109 }
110
111 wxRegion::~wxRegion()
112 {
113 // m_refData unrefed in ~wxObject
114 }
115
116 wxObjectRefData *wxRegion::CreateRefData() const
117 {
118 return new wxRegionRefData;
119 }
120
121 wxObjectRefData *wxRegion::CloneRefData(const wxObjectRefData *data) const
122 {
123 return new wxRegionRefData(*(wxRegionRefData *)data);
124 }
125
126 // ----------------------------------------------------------------------------
127 // wxRegion comparison
128 // ----------------------------------------------------------------------------
129
130 bool wxRegion::operator==( const wxRegion& region )
131 {
132 if (m_refData == region.m_refData) return TRUE;
133
134 if (!m_refData || !region.m_refData) return FALSE;
135
136 // compare the regions themselves, not the pointers to ref data!
137 return XEqualRegion( M_REGIONDATA->m_region,
138 M_REGIONDATA_OF(region)->m_region );
139 }
140
141 // ----------------------------------------------------------------------------
142 // wxRegion operations
143 // ----------------------------------------------------------------------------
144
145 void wxRegion::Clear()
146 {
147 UnRef();
148 }
149
150 bool wxRegion::Union( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
151 {
152 XRectangle rect;
153 rect.x = x;
154 rect.y = y;
155 rect.width = width;
156 rect.height = height;
157
158 if (!m_refData)
159 {
160 m_refData = new wxRegionRefData();
161 M_REGIONDATA->m_region = XCreateRegion();
162 XUnionRectWithRegion( &rect, M_REGIONDATA->m_region, M_REGIONDATA->m_region );
163 }
164 else
165 {
166 AllocExclusive();
167
168 XUnionRectWithRegion( &rect, M_REGIONDATA->m_region, M_REGIONDATA->m_region );
169 }
170
171 return TRUE;
172 }
173
174 bool wxRegion::Union( const wxRect& rect )
175 {
176 return Union( rect.x, rect.y, rect.width, rect.height );
177 }
178
179 bool wxRegion::Union( const wxRegion& region )
180 {
181 if (region.IsNull())
182 return FALSE;
183
184 if (!m_refData)
185 {
186 m_refData = new wxRegionRefData();
187 M_REGIONDATA->m_region = XCreateRegion();
188 }
189 else
190 {
191 AllocExclusive();
192 }
193
194 XUnionRegion( M_REGIONDATA->m_region,
195 M_REGIONDATA_OF(region)->m_region,
196 M_REGIONDATA->m_region );
197
198 return TRUE;
199 }
200
201 bool wxRegion::Intersect( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
202 {
203 wxRegion reg( x, y, width, height );
204
205 return Intersect( reg );
206 }
207
208 bool wxRegion::Intersect( const wxRect& rect )
209 {
210 wxRegion reg( rect );
211
212 return Intersect( reg );
213 }
214
215 bool wxRegion::Intersect( const wxRegion& region )
216 {
217 if (region.IsNull())
218 return FALSE;
219
220 if (!m_refData)
221 {
222 m_refData = new wxRegionRefData();
223 M_REGIONDATA->m_region = XCreateRegion();
224
225 // leave here
226 return TRUE;
227 }
228 else
229 {
230 AllocExclusive();
231 }
232
233 XIntersectRegion( M_REGIONDATA->m_region,
234 M_REGIONDATA_OF(region)->m_region,
235 M_REGIONDATA->m_region );
236
237 return TRUE;
238 }
239
240 bool wxRegion::Subtract( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
241 {
242 wxRegion reg( x, y, width, height );
243 return Subtract( reg );
244 }
245
246 bool wxRegion::Subtract( const wxRect& rect )
247 {
248 wxRegion reg( rect );
249 return Subtract( reg );
250 }
251
252 bool wxRegion::Subtract( const wxRegion& region )
253 {
254 if (region.IsNull())
255 return FALSE;
256
257 if (!m_refData)
258 {
259 m_refData = new wxRegionRefData();
260 M_REGIONDATA->m_region = XCreateRegion();
261 }
262 else
263 {
264 AllocExclusive();
265 }
266
267 XSubtractRegion( M_REGIONDATA->m_region,
268 M_REGIONDATA_OF(region)->m_region,
269 M_REGIONDATA->m_region );
270
271 return TRUE;
272 }
273
274 bool wxRegion::Xor( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
275 {
276 wxRegion reg( x, y, width, height );
277 return Xor( reg );
278 }
279
280 bool wxRegion::Xor( const wxRect& rect )
281 {
282 wxRegion reg( rect );
283 return Xor( reg );
284 }
285
286 bool wxRegion::Xor( const wxRegion& region )
287 {
288 if (region.IsNull())
289 return FALSE;
290
291 if (!m_refData)
292 {
293 m_refData = new wxRegionRefData();
294 M_REGIONDATA->m_region = XCreateRegion();
295 }
296 else
297 {
298 AllocExclusive();
299 }
300
301 XXorRegion( M_REGIONDATA->m_region,
302 M_REGIONDATA_OF(region)->m_region,
303 M_REGIONDATA->m_region );
304
305 return TRUE;
306 }
307
308 // ----------------------------------------------------------------------------
309 // wxRegion tests
310 // ----------------------------------------------------------------------------
311
312 void wxRegion::GetBox( wxCoord &x, wxCoord &y, wxCoord &w, wxCoord &h ) const
313 {
314 if (m_refData)
315 {
316 XRectangle rect;
317 XClipBox( M_REGIONDATA->m_region, &rect );
318 x = rect.x;
319 y = rect.y;
320 w = rect.width;
321 h = rect.height;
322 }
323 else
324 {
325 x = 0;
326 y = 0;
327 w = -1;
328 h = -1;
329 }
330 }
331
332 wxRect wxRegion::GetBox() const
333 {
334 wxCoord x, y, w, h;
335 GetBox( x, y, w, h );
336 return wxRect( x, y, w, h );
337 }
338
339 bool wxRegion::Offset( wxCoord x, wxCoord y )
340 {
341 if (!m_refData)
342 return FALSE;
343
344 AllocExclusive();
345
346 XOffsetRegion( M_REGIONDATA->m_region, x, y );
347
348 return TRUE;
349 }
350
351 bool wxRegion::Empty() const
352 {
353 if (!m_refData)
354 return TRUE;
355
356 return XEmptyRegion( M_REGIONDATA->m_region );
357 }
358
359 wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y ) const
360 {
361 if (!m_refData)
362 return wxOutRegion;
363
364 if (XPointInRegion( M_REGIONDATA->m_region, x, y ))
365 return wxInRegion;
366 else
367 return wxOutRegion;
368 }
369
370 wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y, wxCoord w, wxCoord h ) const
371 {
372 if (!m_refData)
373 return wxOutRegion;
374
375 int res = XRectInRegion( M_REGIONDATA->m_region, x, y, w, h );
376 switch (res)
377 {
378 case RectangleIn: return wxInRegion;
379 case RectangleOut: return wxOutRegion;
380 case RectanglePart: return wxPartRegion;
381 }
382 return wxOutRegion;
383 }
384
385 wxRegionContain wxRegion::Contains(const wxPoint& pt) const
386 {
387 return Contains( pt.x, pt.y );
388 }
389
390 wxRegionContain wxRegion::Contains(const wxRect& rect) const
391 {
392 return Contains( rect.x, rect.y, rect.width, rect.height );
393 }
394
395 WXRegion *wxRegion::GetX11Region() const
396 {
397 if (!m_refData)
398 return (WXRegion*) NULL;
399
400 return (WXRegion*) M_REGIONDATA->m_region;
401 }
402
403 // ----------------------------------------------------------------------------
404 // wxRegionIterator
405 // ----------------------------------------------------------------------------
406
407 // the following structures must match the private structures
408 // in X11 region code ( xc/lib/X11/region.h )
409
410 // this makes the Region type transparent
411 // and we have access to the region rectangles
412
413 struct _XBox {
414 short x1, x2, y1, y2;
415 };
416
417 struct _XRegion {
418 long size , numRects;
419 _XBox *rects, extents;
420 };
421
422 class wxRIRefData: public wxObjectRefData
423 {
424 public:
425
426 wxRIRefData() : m_rects(0), m_numRects(0){}
427 ~wxRIRefData();
428
429 wxRect *m_rects;
430 size_t m_numRects;
431
432 void CreateRects( const wxRegion& r );
433 };
434
435 wxRIRefData::~wxRIRefData()
436 {
437 delete [] m_rects;
438 }
439
440 void wxRIRefData::CreateRects( const wxRegion& region )
441 {
442 if (m_rects)
443 delete [] m_rects;
444
445 m_rects = 0;
446 m_numRects = 0;
447
448 if (region.IsEmpty()) return;
449
450 Region r = (Region) region.GetX11Region();
451 if (r)
452 {
453 #if wxUSE_NANOX
454 GR_RECT rect;
455 GrGetRegionBox(r, & rect);
456 m_numRects = 1;
457 m_rects = new wxRect[1];
458 m_rects[0].x = rect.x;
459 m_rects[0].y = rect.y;
460 m_rects[0].width = rect.width;
461 m_rects[0].height = rect.height;
462 #else
463 m_numRects = r->numRects;
464 if (m_numRects)
465 {
466 m_rects = new wxRect[m_numRects];
467 for (size_t i=0; i < m_numRects; ++i)
468 {
469 _XBox &xr = r->rects[i];
470 wxRect &wr = m_rects[i];
471 wr.x = xr.x1;
472 wr.y = xr.y1;
473 wr.width = xr.x2-xr.x1;
474 wr.height = xr.y2-xr.y1;
475 }
476 }
477 #endif
478 }
479 }
480
481 wxRegionIterator::wxRegionIterator()
482 {
483 m_refData = new wxRIRefData();
484 Reset();
485 }
486
487 wxRegionIterator::wxRegionIterator( const wxRegion& region )
488 {
489 m_refData = new wxRIRefData();
490 Reset(region);
491 }
492
493 void wxRegionIterator::Reset( const wxRegion& region )
494 {
495 m_region = region;
496 ((wxRIRefData*)m_refData)->CreateRects(region);
497 Reset();
498 }
499
500 bool wxRegionIterator::HaveRects() const
501 {
502 return m_current < ((wxRIRefData*)m_refData)->m_numRects;
503 }
504
505 wxRegionIterator::operator bool () const
506 {
507 return HaveRects();
508 }
509
510 void wxRegionIterator::operator ++ ()
511 {
512 if (HaveRects()) ++m_current;
513 }
514
515 void wxRegionIterator::operator ++ (int)
516 {
517 if (HaveRects()) ++m_current;
518 }
519
520 wxCoord wxRegionIterator::GetX() const
521 {
522 if( !HaveRects() ) return 0;
523 return ((wxRIRefData*)m_refData)->m_rects[m_current].x;
524 }
525
526 wxCoord wxRegionIterator::GetY() const
527 {
528 if( !HaveRects() ) return 0;
529 return ((wxRIRefData*)m_refData)->m_rects[m_current].y;
530 }
531
532 wxCoord wxRegionIterator::GetW() const
533 {
534 if( !HaveRects() ) return -1;
535 return ((wxRIRefData*)m_refData)->m_rects[m_current].width;
536 }
537
538 wxCoord wxRegionIterator::GetH() const
539 {
540 if( !HaveRects() ) return -1;
541 return ((wxRIRefData*)m_refData)->m_rects[m_current].height;
542 }
543
544 wxRect wxRegionIterator::GetRect() const
545 {
546 wxRect r;
547 if( HaveRects() )
548 r = ((wxRIRefData*)m_refData)->m_rects[m_current];
549
550 return r;
551 }
552