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