]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/region.cpp
don't use -q option with egrep, Solaris doesn't have it (bug 517145)
[wxWidgets.git] / src / gtk1 / region.cpp
CommitLineData
c801d85f 1/////////////////////////////////////////////////////////////////////////////
5fc7ede9 2// Name: gtk/region.cpp
c801d85f
KB
3// Purpose:
4// Author: Robert Roebling
9fe4c99c 5// Modified: VZ at 05.10.00: use AllocExclusive(), comparison fixed
f96aa4d9
RR
6// Id: $Id$
7// Copyright: (c) 1998 Robert Roebling
5fc7ede9 8// Licence: wxWindows licence
c801d85f
KB
9/////////////////////////////////////////////////////////////////////////////
10
1e6feb95
VZ
11// ============================================================================
12// declarations
13// ============================================================================
14
c801d85f 15#ifdef __GNUG__
1e6feb95 16 #pragma implementation "region.h"
c801d85f
KB
17#endif
18
1e6feb95
VZ
19// ----------------------------------------------------------------------------
20// headers
21// ----------------------------------------------------------------------------
22
c801d85f
KB
23#include "wx/region.h"
24
aed8ac3f
RR
25#include <gdk/gdk.h>
26#include <gtk/gtk.h>
bbe0af5b 27
1e6feb95
VZ
28#include "wx/log.h"
29
30// ----------------------------------------------------------------------------
31// wxRegionRefData: private class containing the information about the region
32// ----------------------------------------------------------------------------
c801d85f 33
1e6feb95 34class wxRegionRefData : public wxObjectRefData
c801d85f 35{
864e8bd0 36public:
48850fa7
RR
37 wxRegionRefData()
38 {
39 m_region = NULL;
40 }
41
42 wxRegionRefData(const wxRegionRefData& refData)
43 {
44#ifdef __WXGTK20__
45 m_region = gdk_region_copy(refData.m_region);
46#else
47 m_region = gdk_region_new();
48 GdkRegion *regCopy = gdk_regions_union(m_region, refData.m_region);
49 gdk_region_destroy(m_region);
50 m_region = regCopy;
51#endif
52 }
53
54 ~wxRegionRefData()
55 {
56 if (m_region)
57 gdk_region_destroy( m_region );
58 }
5fc7ede9 59
c801d85f
KB
60 GdkRegion *m_region;
61};
62
1e6feb95
VZ
63// ----------------------------------------------------------------------------
64// macros
65// ----------------------------------------------------------------------------
66
67#define M_REGIONDATA ((wxRegionRefData *)m_refData)
68#define M_REGIONDATA_OF(rgn) ((wxRegionRefData *)(rgn.m_refData))
69
70IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject);
71IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator,wxObject);
72
1e6feb95
VZ
73// ----------------------------------------------------------------------------
74// wxRegion construction
75// ----------------------------------------------------------------------------
c801d85f
KB
76
77#define M_REGIONDATA ((wxRegionRefData *)m_refData)
78
9fe4c99c 79void wxRegion::InitRect(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
c801d85f 80{
bbe0af5b
RR
81 GdkRectangle rect;
82 rect.x = x;
83 rect.y = y;
84 rect.width = w;
85 rect.height = h;
48850fa7
RR
86
87 m_refData = new wxRegionRefData();
88
b7c2d6ff 89#ifdef __WXGTK20__
48850fa7 90 M_REGIONDATA->m_region = gdk_region_rectangle( rect );
b7c2d6ff 91#else
48850fa7 92 GdkRegion *reg = gdk_region_new();
bbe0af5b
RR
93 M_REGIONDATA->m_region = gdk_region_union_with_rect( reg, &rect );
94 gdk_region_destroy( reg );
b7c2d6ff 95#endif
ff7b1510 96}
c801d85f 97
5549e9f7
VZ
98wxRegion::wxRegion( size_t n, const wxPoint *points, int fillStyle )
99{
100 GdkPoint *gdkpoints = new GdkPoint[n];
101 for ( size_t i = 0 ; i < n ; i++ )
102 {
103 gdkpoints[i].x = points[i].x;
104 gdkpoints[i].y = points[i].y;
105 }
106
107 m_refData = new wxRegionRefData();
108
109 GdkRegion* reg = gdk_region_polygon
110 (
111 gdkpoints,
112 n,
113 fillStyle == wxWINDING_RULE ? GDK_WINDING_RULE
114 : GDK_EVEN_ODD_RULE
115 );
116
117 M_REGIONDATA->m_region = reg;
118
119 delete [] gdkpoints;
120}
121
1e6feb95 122wxRegion::~wxRegion()
c801d85f 123{
e0f0b197 124 // m_refData unrefed in ~wxObject
ff7b1510 125}
c801d85f 126
e0f0b197
RR
127wxObjectRefData *wxRegion::CreateRefData() const
128{
129 return new wxRegionRefData;
130}
131
132wxObjectRefData *wxRegion::CloneRefData(const wxObjectRefData *data) const
133{
134 return new wxRegionRefData(*(wxRegionRefData *)data);
135}
c89f5c02 136
9fe4c99c
VZ
137// ----------------------------------------------------------------------------
138// wxRegion comparison
139// ----------------------------------------------------------------------------
140
1e6feb95 141bool wxRegion::operator==( const wxRegion& region )
c801d85f 142{
c89f5c02
RR
143 if (m_refData == region.m_refData) return TRUE;
144
145 if (!m_refData || !region.m_refData) return FALSE;
146
9fe4c99c 147 // compare the regions themselves, not the pointers to ref data!
1e6feb95
VZ
148 return gdk_region_equal(M_REGIONDATA->m_region,
149 M_REGIONDATA_OF(region)->m_region);
ff7b1510 150}
c801d85f 151
1e6feb95
VZ
152// ----------------------------------------------------------------------------
153// wxRegion operations
154// ----------------------------------------------------------------------------
155
bf57d1ad 156void wxRegion::Clear()
c801d85f 157{
bbe0af5b 158 UnRef();
ff7b1510 159}
c801d85f 160
5fc7ede9 161bool wxRegion::Union( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
c801d85f 162{
bbe0af5b
RR
163 GdkRectangle rect;
164 rect.x = x;
165 rect.y = y;
166 rect.width = width;
167 rect.height = height;
e0f0b197 168
e1208c31
RR
169 if (!m_refData)
170 {
171 m_refData = new wxRegionRefData();
b7c2d6ff 172#ifdef __WXGTK20__
48850fa7 173 M_REGIONDATA->m_region = gdk_region_rectangle( rect );
b7c2d6ff 174#else
48850fa7 175 GdkRegion *reg = gdk_region_new();
e1208c31
RR
176 M_REGIONDATA->m_region = gdk_region_union_with_rect( reg, &rect );
177 gdk_region_destroy( reg );
b7c2d6ff 178#endif
e1208c31
RR
179 }
180 else
181 {
9fe4c99c 182 AllocExclusive();
1e6feb95 183
b7c2d6ff
OK
184#ifdef __WXGTK20__
185 gdk_region_union_with_rect( M_REGIONDATA->m_region, &rect );
186#else
e1208c31
RR
187 GdkRegion *reg = gdk_region_union_with_rect( M_REGIONDATA->m_region, &rect );
188 gdk_region_destroy( M_REGIONDATA->m_region );
189 M_REGIONDATA->m_region = reg;
b7c2d6ff 190#endif
e1208c31 191 }
1e6feb95 192
bbe0af5b 193 return TRUE;
ff7b1510 194}
c801d85f
KB
195
196bool wxRegion::Union( const wxRect& rect )
197{
e1208c31 198 return Union( rect.x, rect.y, rect.width, rect.height );
ff7b1510 199}
c801d85f
KB
200
201bool wxRegion::Union( const wxRegion& region )
202{
e1208c31
RR
203 if (region.IsNull())
204 return FALSE;
205
48850fa7
RR
206 if (!m_refData)
207 {
208 m_refData = new wxRegionRefData();
209 M_REGIONDATA->m_region = gdk_region_new();
210 }
211 else
212 {
213 AllocExclusive();
214 }
e1208c31 215
b7c2d6ff
OK
216#ifdef __WXGTK20__
217 gdk_region_union( M_REGIONDATA->m_region, region.GetRegion() );
218#else
bbe0af5b
RR
219 GdkRegion *reg = gdk_regions_union( M_REGIONDATA->m_region, region.GetRegion() );
220 gdk_region_destroy( M_REGIONDATA->m_region );
221 M_REGIONDATA->m_region = reg;
b7c2d6ff 222#endif
5fc7ede9 223
bbe0af5b 224 return TRUE;
ff7b1510 225}
c801d85f 226
5fc7ede9 227bool wxRegion::Intersect( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
c801d85f 228{
bbe0af5b 229 wxRegion reg( x, y, width, height );
1e6feb95
VZ
230
231 return Intersect( reg );
ff7b1510 232}
c801d85f
KB
233
234bool wxRegion::Intersect( const wxRect& rect )
235{
bbe0af5b 236 wxRegion reg( rect );
e0f0b197 237
1e6feb95 238 return Intersect( reg );
ff7b1510 239}
c801d85f 240
1e6feb95 241bool wxRegion::Intersect( const wxRegion& region )
c801d85f 242{
1e6feb95
VZ
243 if (region.IsNull())
244 return FALSE;
245
e1208c31
RR
246 if (!m_refData)
247 {
248 m_refData = new wxRegionRefData();
249 M_REGIONDATA->m_region = gdk_region_new();
48850fa7
RR
250
251 // leave here
1e6feb95
VZ
252 return TRUE;
253 }
48850fa7 254 else
1e6feb95 255 {
48850fa7 256 AllocExclusive();
1e6feb95
VZ
257 }
258
48850fa7
RR
259#ifdef __WXGTK20__
260 gdk_region_intersect( M_REGIONDATA->m_region, region.GetRegion() );
261#else
262 GdkRegion *reg = gdk_regions_intersect( M_REGIONDATA->m_region, region.GetRegion() );
263 gdk_region_destroy( M_REGIONDATA->m_region );
264 M_REGIONDATA->m_region = reg;
265#endif
9fe4c99c 266
bbe0af5b 267 return TRUE;
ff7b1510 268}
c801d85f 269
1e6feb95 270bool wxRegion::Subtract( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
c801d85f 271{
1e6feb95
VZ
272 wxRegion reg( x, y, width, height );
273 return Subtract( reg );
274}
e1208c31 275
1e6feb95
VZ
276bool wxRegion::Subtract( const wxRect& rect )
277{
bbe0af5b 278 wxRegion reg( rect );
1e6feb95 279 return Subtract( reg );
ff7b1510 280}
c801d85f
KB
281
282bool wxRegion::Subtract( const wxRegion& region )
283{
e1208c31
RR
284 if (region.IsNull())
285 return FALSE;
286
287 if (!m_refData)
288 {
289 m_refData = new wxRegionRefData();
290 M_REGIONDATA->m_region = gdk_region_new();
291 }
48850fa7
RR
292 else
293 {
294 AllocExclusive();
295 }
1e6feb95 296
b7c2d6ff
OK
297#ifdef __WXGTK20__
298 gdk_region_subtract( M_REGIONDATA->m_region, region.GetRegion() );
299#else
bbe0af5b
RR
300 GdkRegion *reg = gdk_regions_subtract( M_REGIONDATA->m_region, region.GetRegion() );
301 gdk_region_destroy( M_REGIONDATA->m_region );
302 M_REGIONDATA->m_region = reg;
b7c2d6ff 303#endif
1e6feb95 304
bbe0af5b 305 return TRUE;
ff7b1510 306}
c801d85f 307
5fc7ede9 308bool wxRegion::Xor( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
c801d85f 309{
bbe0af5b 310 wxRegion reg( x, y, width, height );
1e6feb95 311 return Xor( reg );
ff7b1510 312}
c801d85f
KB
313
314bool wxRegion::Xor( const wxRect& rect )
315{
bbe0af5b 316 wxRegion reg( rect );
1e6feb95 317 return Xor( reg );
ff7b1510 318}
c801d85f
KB
319
320bool wxRegion::Xor( const wxRegion& region )
321{
e1208c31 322 if (region.IsNull())
05a11043 323 return FALSE;
e1208c31
RR
324
325 if (!m_refData)
326 {
327 m_refData = new wxRegionRefData();
328 M_REGIONDATA->m_region = gdk_region_new();
329 }
1e6feb95
VZ
330 else
331 {
9fe4c99c 332 AllocExclusive();
1e6feb95 333 }
e1208c31 334
b7c2d6ff
OK
335#ifdef __WXGTK20__
336 gdk_region_xor( M_REGIONDATA->m_region, region.GetRegion() );
337#else
bbe0af5b
RR
338 GdkRegion *reg = gdk_regions_xor( M_REGIONDATA->m_region, region.GetRegion() );
339 gdk_region_destroy( M_REGIONDATA->m_region );
340 M_REGIONDATA->m_region = reg;
b7c2d6ff 341#endif
5fc7ede9 342
bbe0af5b 343 return TRUE;
ff7b1510 344}
c801d85f 345
1e6feb95
VZ
346// ----------------------------------------------------------------------------
347// wxRegion tests
348// ----------------------------------------------------------------------------
349
e1208c31 350void wxRegion::GetBox( wxCoord &x, wxCoord &y, wxCoord &w, wxCoord &h ) const
c801d85f 351{
1e6feb95
VZ
352 if ( m_refData )
353 {
354 GdkRectangle rect;
355 gdk_region_get_clipbox( M_REGIONDATA->m_region, &rect );
356 x = rect.x;
357 y = rect.y;
358 w = rect.width;
359 h = rect.height;
360 }
361 else
362 {
363 x = 0;
364 y = 0;
365 w = -1;
366 h = -1;
367 }
ff7b1510 368}
c801d85f 369
bf57d1ad 370wxRect wxRegion::GetBox() const
c801d85f 371{
1e6feb95 372 wxCoord x, y, w, h;
bbe0af5b
RR
373 GetBox( x, y, w, h );
374 return wxRect( x, y, w, h );
ff7b1510 375}
c801d85f 376
35917d22
RR
377bool wxRegion::Offset( wxCoord x, wxCoord y )
378{
379 if (!m_refData)
380 return FALSE;
381
9fe4c99c
VZ
382 AllocExclusive();
383
35917d22 384 gdk_region_offset( M_REGIONDATA->m_region, x, y );
9fe4c99c 385
35917d22
RR
386 return TRUE;
387}
388
bf57d1ad 389bool wxRegion::Empty() const
c801d85f 390{
e1208c31
RR
391 if (!m_refData)
392 return TRUE;
393
bbe0af5b 394 return gdk_region_empty( M_REGIONDATA->m_region );
ff7b1510 395}
c801d85f 396
5fc7ede9 397wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y ) const
c801d85f 398{
e1208c31
RR
399 if (!m_refData)
400 return wxOutRegion;
401
bbe0af5b
RR
402 if (gdk_region_point_in( M_REGIONDATA->m_region, x, y ))
403 return wxInRegion;
404 else
405 return wxOutRegion;
ff7b1510 406}
c801d85f 407
5fc7ede9 408wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y, wxCoord w, wxCoord h ) const
c801d85f 409{
e1208c31
RR
410 if (!m_refData)
411 return wxOutRegion;
412
bbe0af5b
RR
413 GdkRectangle rect;
414 rect.x = x;
415 rect.y = y;
416 rect.width = w;
417 rect.height = h;
418 GdkOverlapType res = gdk_region_rect_in( M_REGIONDATA->m_region, &rect );
419 switch (res)
420 {
421 case GDK_OVERLAP_RECTANGLE_IN: return wxInRegion;
422 case GDK_OVERLAP_RECTANGLE_OUT: return wxOutRegion;
423 case GDK_OVERLAP_RECTANGLE_PART: return wxPartRegion;
424 }
425 return wxOutRegion;
ff7b1510 426}
c801d85f 427
8429bec1
RR
428wxRegionContain wxRegion::Contains(const wxPoint& pt) const
429{
bbe0af5b 430 return Contains( pt.x, pt.y );
8429bec1
RR
431}
432
433wxRegionContain wxRegion::Contains(const wxRect& rect) const
434{
bbe0af5b 435 return Contains( rect.x, rect.y, rect.width, rect.height );
8429bec1
RR
436}
437
bf57d1ad 438GdkRegion *wxRegion::GetRegion() const
c801d85f 439{
e1208c31
RR
440 if (!m_refData)
441 return (GdkRegion*) NULL;
442
bbe0af5b 443 return M_REGIONDATA->m_region;
ff7b1510 444}
c801d85f 445
1e6feb95 446// ----------------------------------------------------------------------------
3d0c4d2e 447// wxRegionIterator
1e6feb95 448// ----------------------------------------------------------------------------
8429bec1 449
48850fa7 450#ifndef __WXGTK20__
3d0c4d2e
RR
451
452// the following structures must match the private structures
453// in X11 region code ( xc/lib/X11/region.h )
454
455// this makes the Region type transparent
456// and we have access to the region rectangles
457
48850fa7
RR
458#include <gdk/gdkprivate.h>
459
3d0c4d2e
RR
460struct _XBox {
461 short x1, x2, y1, y2;
462};
1e6feb95 463
3d0c4d2e
RR
464struct _XRegion {
465 long size , numRects;
466 _XBox *rects, extents;
467};
468
48850fa7
RR
469#endif
470
3d0c4d2e
RR
471class wxRIRefData: public wxObjectRefData
472{
473public:
474
475 wxRIRefData() : m_rects(0), m_numRects(0){}
476 ~wxRIRefData();
477
478 wxRect *m_rects;
479 size_t m_numRects;
480
481 void CreateRects( const wxRegion& r );
482};
483
484wxRIRefData::~wxRIRefData()
485{
486 delete m_rects;
487}
488
3d0c4d2e
RR
489void wxRIRefData::CreateRects( const wxRegion& region )
490{
48850fa7
RR
491 if (m_rects)
492 delete m_rects;
493
494 m_rects = 0;
495 m_numRects = 0;
496
497 GdkRegion *gdkregion = region.GetRegion();
498 if (!gdkregion) return;
499
500#ifdef __WXGTK20__
501 GdkRectangles *gdkrects = NULL;
502 gint numRects = 0;
503 gdk_region_get_rectangles( gdkregion, &gdkrect, &numRects );
504
505 m_numRects = numRects;
506 if (numRects)
507 {
508 m_rects = new wxRect[m_numRects];
509 for (size_t i=0; i < m_numRects; ++i)
3d0c4d2e 510 {
48850fa7
RR
511 GdkRectangle &gr = gdkrects[i];
512 wxRect &wr = m_rects[i];
513 wr.x = gr.x;
514 wr.y = gr.y;
515 wr.width = gr.width;
516 wr.height = gr.height;
3d0c4d2e 517 }
3d0c4d2e 518 }
48850fa7
RR
519 g_delete( gdkrects ); // delete []
520#else
521 Region r = ((GdkRegionPrivate *)gdkregion)->xregion;
522 if (r)
523 {
524 m_numRects = r->numRects;
525 if (m_numRects)
526 {
527 m_rects = new wxRect[m_numRects];
528 for (size_t i=0; i < m_numRects; ++i)
529 {
530 _XBox &xr = r->rects[i];
531 wxRect &wr = m_rects[i];
532 wr.x = xr.x1;
533 wr.y = xr.y1;
534 wr.width = xr.x2-xr.x1;
535 wr.height = xr.y2-xr.y1;
536 }
537 }
538 }
539#endif
3d0c4d2e
RR
540}
541
3d0c4d2e
RR
542wxRegionIterator::wxRegionIterator()
543{
544 m_refData = new wxRIRefData();
545 Reset();
546}
547
548wxRegionIterator::wxRegionIterator( const wxRegion& region )
549{
550 m_refData = new wxRIRefData();
551 Reset(region);
552}
553
554void wxRegionIterator::Reset( const wxRegion& region )
555{
556 m_region = region;
557 ((wxRIRefData*)m_refData)->CreateRects(region);
558 Reset();
559}
560
561bool wxRegionIterator::HaveRects() const
562{
563 return m_current < ((wxRIRefData*)m_refData)->m_numRects;
564}
565
566wxRegionIterator::operator bool () const
567{
568 return HaveRects();
569}
570
571void wxRegionIterator::operator ++ ()
572{
573 if (HaveRects()) ++m_current;
574}
575
576void wxRegionIterator::operator ++ (int)
577{
578 if (HaveRects()) ++m_current;
579}
580
581wxCoord wxRegionIterator::GetX() const
582{
583 if( !HaveRects() ) return 0;
584 return ((wxRIRefData*)m_refData)->m_rects[m_current].x;
585}
586
587wxCoord wxRegionIterator::GetY() const
588{
589 if( !HaveRects() ) return 0;
590 return ((wxRIRefData*)m_refData)->m_rects[m_current].y;
591}
592
593wxCoord wxRegionIterator::GetW() const
594{
595 if( !HaveRects() ) return -1;
596 return ((wxRIRefData*)m_refData)->m_rects[m_current].width;
597}
598
599wxCoord wxRegionIterator::GetH() const
600{
601 if( !HaveRects() ) return -1;
602 return ((wxRIRefData*)m_refData)->m_rects[m_current].height;
603}
604
1e6feb95
VZ
605wxRect wxRegionIterator::GetRect() const
606{
607 wxRect r;
3379ed37
VZ
608 if( HaveRects() )
609 r = ((wxRIRefData*)m_refData)->m_rects[m_current];
1e6feb95
VZ
610
611 return r;
612}
613