]> git.saurik.com Git - wxWidgets.git/blame - src/x11/region.cpp
Don't crash when laying out wxGridBagSizer with only hidden elements.
[wxWidgets.git] / src / x11 / region.cpp
CommitLineData
83df96d6 1/////////////////////////////////////////////////////////////////////////////
55034339 2// File: src/x11/region.cpp
83df96d6 3// Purpose: Region class
2e579471 4// Author: Julian Smart, Robert Roebling
83df96d6 5// Created: Fri Oct 24 10:46:34 MET 1997
2e579471 6// Copyright: (c) 1997 Julian Smart, Robert Roebling
65571936 7// Licence: wxWindows licence
83df96d6
JS
8/////////////////////////////////////////////////////////////////////////////
9
55034339
WS
10// for compilers that support precompilation, includes "wx.h".
11#include "wx/wxprec.h"
12
83df96d6 13#include "wx/region.h"
e4db172a
WS
14
15#ifndef WX_PRECOMP
16 #include "wx/log.h"
dd05139a 17 #include "wx/gdicmn.h"
e4db172a
WS
18#endif
19
83df96d6
JS
20#ifdef __VMS__
21#pragma message disable nosimpint
22#endif
7266b672
JS
23#include "wx/x11/private.h"
24#include "X11/Xutil.h"
83df96d6
JS
25#ifdef __VMS__
26#pragma message enable nosimpint
27#endif
7266b672 28
83df96d6 29// ----------------------------------------------------------------------------
1934d291 30// wxRegionRefData: private class containing the information about the region
83df96d6
JS
31// ----------------------------------------------------------------------------
32
8f884a0d 33class wxRegionRefData : public wxGDIRefData
1934d291 34{
83df96d6
JS
35public:
36 wxRegionRefData()
37 {
1934d291 38 m_region = NULL;
83df96d6 39 }
55034339 40
1934d291 41 wxRegionRefData(const wxRegionRefData& refData)
83df96d6
JS
42 {
43 m_region = XCreateRegion();
1934d291 44 XUnionRegion( refData.m_region, m_region, m_region );
83df96d6 45 }
55034339 46
d3c7fc99 47 virtual ~wxRegionRefData()
83df96d6 48 {
1934d291
RR
49 if (m_region)
50 XDestroyRegion( m_region );
83df96d6
JS
51 }
52
1934d291
RR
53 Region m_region;
54};
83df96d6 55
1934d291
RR
56// ----------------------------------------------------------------------------
57// macros
58// ----------------------------------------------------------------------------
83df96d6 59
1934d291
RR
60#define M_REGIONDATA ((wxRegionRefData *)m_refData)
61#define M_REGIONDATA_OF(rgn) ((wxRegionRefData *)(rgn.m_refData))
62
e933b5bc
VZ
63IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
64IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator,wxObject)
1934d291
RR
65
66// ----------------------------------------------------------------------------
67// wxRegion construction
68// ----------------------------------------------------------------------------
69
70#define M_REGIONDATA ((wxRegionRefData *)m_refData)
71
72void wxRegion::InitRect(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
73{
74 XRectangle rect;
55034339
WS
75 rect.x = (short)x;
76 rect.y = (short)y;
77 rect.width = (unsigned short)w;
78 rect.height = (unsigned short)h;
79
1934d291 80 m_refData = new wxRegionRefData();
55034339 81
1934d291
RR
82 M_REGIONDATA->m_region = XCreateRegion();
83 XUnionRectWithRegion( &rect, M_REGIONDATA->m_region, M_REGIONDATA->m_region );
84}
83df96d6 85
f30ef57e 86wxRegion::wxRegion( size_t WXUNUSED(n), const wxPoint *WXUNUSED(points), wxPolygonFillMode WXUNUSED(fillStyle) )
83df96d6 87{
1934d291
RR
88#if 0
89 XPoint *xpoints = new XPoint[n];
90 for ( size_t i = 0 ; i < n ; i++ )
83df96d6 91 {
1934d291
RR
92 xpoints[i].x = points[i].x;
93 xpoints[i].y = points[i].y;
83df96d6
JS
94 }
95
1934d291
RR
96 m_refData = new wxRegionRefData();
97
98 Region* reg = gdk_region_polygon
99 (
100 gdkpoints,
101 n,
102 fillStyle == wxWINDING_RULE ? GDK_WINDING_RULE
103 : GDK_EVEN_ODD_RULE
104 );
105
106 M_REGIONDATA->m_region = reg;
107
108 delete [] xpoints;
109#endif
83df96d6
JS
110}
111
1934d291 112wxRegion::~wxRegion()
83df96d6 113{
1934d291 114 // m_refData unrefed in ~wxObject
83df96d6
JS
115}
116
8f884a0d 117wxGDIRefData *wxRegion::CreateGDIRefData() const
83df96d6 118{
1934d291
RR
119 return new wxRegionRefData;
120}
83df96d6 121
8f884a0d 122wxGDIRefData *wxRegion::CloneGDIRefData(const wxGDIRefData *data) const
1934d291
RR
123{
124 return new wxRegionRefData(*(wxRegionRefData *)data);
125}
83df96d6 126
1934d291
RR
127// ----------------------------------------------------------------------------
128// wxRegion comparison
129// ----------------------------------------------------------------------------
83df96d6 130
8a16d737 131bool wxRegion::DoIsEqual(const wxRegion& region) const
83df96d6 132{
1934d291 133 return XEqualRegion( M_REGIONDATA->m_region,
55034339 134 M_REGIONDATA_OF(region)->m_region ) == True;
83df96d6
JS
135}
136
1934d291
RR
137// ----------------------------------------------------------------------------
138// wxRegion operations
139// ----------------------------------------------------------------------------
140
141void wxRegion::Clear()
83df96d6 142{
1934d291
RR
143 UnRef();
144}
83df96d6 145
8a16d737 146bool wxRegion::DoUnionWithRect(const wxRect& r)
1934d291 147{
9afe6c17
VZ
148 // work around for XUnionRectWithRegion() bug: taking a union with an empty
149 // rect results in an empty region (at least XFree 3.3.6 and 4.0 have this
150 // problem)
8a16d737 151 if ( r.IsEmpty() )
55034339 152 return true;
9afe6c17 153
83df96d6 154 XRectangle rect;
8a16d737
VZ
155 rect.x = (short)r.x;
156 rect.y = (short)r.y;
157 rect.width = (unsigned short)r.width;
158 rect.height = (unsigned short)r.height;
55034339 159
1934d291
RR
160 if (!m_refData)
161 {
162 m_refData = new wxRegionRefData();
163 M_REGIONDATA->m_region = XCreateRegion();
1934d291
RR
164 }
165 else
166 {
167 AllocExclusive();
1934d291
RR
168 }
169
8a16d737 170 XUnionRectWithRegion( &rect, M_REGIONDATA->m_region, M_REGIONDATA->m_region );
83df96d6 171
8a16d737 172 return true;
1934d291 173}
83df96d6 174
8a16d737 175bool wxRegion::DoUnionWithRegion( const wxRegion& region )
1934d291 176{
a1b806b9 177 wxCHECK_MSG( region.IsOk(), false, wxT("invalid region") );
1934d291
RR
178
179 if (!m_refData)
180 {
181 m_refData = new wxRegionRefData();
182 M_REGIONDATA->m_region = XCreateRegion();
183 }
184 else
185 {
186 AllocExclusive();
187 }
55034339 188
1934d291
RR
189 XUnionRegion( M_REGIONDATA->m_region,
190 M_REGIONDATA_OF(region)->m_region,
191 M_REGIONDATA->m_region );
192
55034339 193 return true;
83df96d6
JS
194}
195
8a16d737 196bool wxRegion::DoIntersect( const wxRegion& region )
83df96d6 197{
a1b806b9 198 wxCHECK_MSG( region.IsOk(), false, wxT("invalid region") );
1934d291
RR
199
200 if (!m_refData)
201 {
202 m_refData = new wxRegionRefData();
203 M_REGIONDATA->m_region = XCreateRegion();
55034339
WS
204
205 // leave here
206 return true;
1934d291
RR
207 }
208 else
209 {
210 AllocExclusive();
211 }
83df96d6 212
1934d291
RR
213 XIntersectRegion( M_REGIONDATA->m_region,
214 M_REGIONDATA_OF(region)->m_region,
215 M_REGIONDATA->m_region );
216
55034339 217 return true;
83df96d6
JS
218}
219
8a16d737 220bool wxRegion::DoSubtract( const wxRegion& region )
83df96d6 221{
a1b806b9 222 wxCHECK_MSG( region.IsOk(), false, wxT("invalid region") );
1934d291
RR
223
224 if (!m_refData)
225 {
83df96d6 226 m_refData = new wxRegionRefData();
1934d291
RR
227 M_REGIONDATA->m_region = XCreateRegion();
228 }
229 else
230 {
231 AllocExclusive();
83df96d6 232 }
83df96d6 233
1934d291
RR
234 XSubtractRegion( M_REGIONDATA->m_region,
235 M_REGIONDATA_OF(region)->m_region,
236 M_REGIONDATA->m_region );
83df96d6 237
55034339 238 return true;
1934d291 239}
83df96d6 240
8a16d737 241bool wxRegion::DoXor( const wxRegion& region )
1934d291 242{
a1b806b9 243 wxCHECK_MSG( region.IsOk(), false, wxT("invalid region") );
83df96d6 244
1934d291
RR
245 if (!m_refData)
246 {
83df96d6 247 m_refData = new wxRegionRefData();
1934d291 248 M_REGIONDATA->m_region = XCreateRegion();
83df96d6 249 }
1934d291 250 else
83df96d6 251 {
1934d291 252 AllocExclusive();
83df96d6
JS
253 }
254
1934d291
RR
255 XXorRegion( M_REGIONDATA->m_region,
256 M_REGIONDATA_OF(region)->m_region,
257 M_REGIONDATA->m_region );
55034339
WS
258
259 return true;
83df96d6
JS
260}
261
1934d291
RR
262// ----------------------------------------------------------------------------
263// wxRegion tests
264// ----------------------------------------------------------------------------
83df96d6 265
8a16d737 266bool wxRegion::DoGetBox( wxCoord &x, wxCoord &y, wxCoord &w, wxCoord &h ) const
83df96d6 267{
1934d291
RR
268 if (m_refData)
269 {
83df96d6 270 XRectangle rect;
1934d291 271 XClipBox( M_REGIONDATA->m_region, &rect );
83df96d6
JS
272 x = rect.x;
273 y = rect.y;
274 w = rect.width;
275 h = rect.height;
8a16d737
VZ
276
277 return true;
1934d291
RR
278 }
279 else
280 {
281 x = 0;
282 y = 0;
283 w = -1;
284 h = -1;
83df96d6 285
8a16d737
VZ
286 return false;
287 }
83df96d6
JS
288}
289
8a16d737 290bool wxRegion::DoOffset( wxCoord x, wxCoord y )
83df96d6 291{
1934d291 292 if (!m_refData)
55034339 293 return false;
83df96d6 294
1934d291
RR
295 AllocExclusive();
296
297 XOffsetRegion( M_REGIONDATA->m_region, x, y );
298
55034339 299 return true;
1934d291 300}
83df96d6 301
8a16d737 302bool wxRegion::IsEmpty() const
83df96d6
JS
303{
304 if (!m_refData)
55034339 305 return true;
83df96d6 306
55034339 307 return XEmptyRegion( M_REGIONDATA->m_region ) == True;
83df96d6
JS
308}
309
8a16d737 310wxRegionContain wxRegion::DoContainsPoint( wxCoord x, wxCoord y ) const
83df96d6
JS
311{
312 if (!m_refData)
313 return wxOutRegion;
314
1934d291
RR
315 if (XPointInRegion( M_REGIONDATA->m_region, x, y ))
316 return wxInRegion;
317 else
318 return wxOutRegion;
83df96d6
JS
319}
320
8a16d737 321wxRegionContain wxRegion::DoContainsRect(const wxRect& r) const
83df96d6
JS
322{
323 if (!m_refData)
324 return wxOutRegion;
325
8a16d737 326 int res = XRectInRegion(M_REGIONDATA->m_region, r.x, r.y, r.width, r.height);
1934d291
RR
327 switch (res)
328 {
329 case RectangleIn: return wxInRegion;
330 case RectangleOut: return wxOutRegion;
83df96d6
JS
331 case RectanglePart: return wxPartRegion;
332 }
333 return wxOutRegion;
334}
335
1934d291 336WXRegion *wxRegion::GetX11Region() const
83df96d6 337{
1934d291 338 if (!m_refData)
d3b9f782 339 return NULL;
83df96d6 340
1934d291 341 return (WXRegion*) M_REGIONDATA->m_region;
83df96d6
JS
342}
343
1934d291
RR
344// ----------------------------------------------------------------------------
345// wxRegionIterator
346// ----------------------------------------------------------------------------
83df96d6 347
1934d291
RR
348// the following structures must match the private structures
349// in X11 region code ( xc/lib/X11/region.h )
350
351// this makes the Region type transparent
352// and we have access to the region rectangles
83df96d6 353
1934d291
RR
354struct _XBox {
355 short x1, x2, y1, y2;
356};
357
358struct _XRegion {
359 long size , numRects;
360 _XBox *rects, extents;
361};
362
8f884a0d 363class wxRIRefData: public wxGDIRefData
83df96d6 364{
1934d291 365public:
83df96d6 366
1934d291 367 wxRIRefData() : m_rects(0), m_numRects(0){}
d3c7fc99 368 virtual ~wxRIRefData();
1934d291
RR
369
370 wxRect *m_rects;
371 size_t m_numRects;
372
373 void CreateRects( const wxRegion& r );
374};
83df96d6 375
1934d291 376wxRIRefData::~wxRIRefData()
83df96d6 377{
64423153 378 delete [] m_rects;
83df96d6
JS
379}
380
1934d291 381void wxRIRefData::CreateRects( const wxRegion& region )
83df96d6
JS
382{
383 if (m_rects)
64423153 384 delete [] m_rects;
1934d291
RR
385
386 m_rects = 0;
387 m_numRects = 0;
55034339 388
1934d291 389 if (region.IsEmpty()) return;
55034339 390
1934d291
RR
391 Region r = (Region) region.GetX11Region();
392 if (r)
393 {
461e93f9
JS
394#if wxUSE_NANOX
395 GR_RECT rect;
396 GrGetRegionBox(r, & rect);
397 m_numRects = 1;
398 m_rects = new wxRect[1];
399 m_rects[0].x = rect.x;
400 m_rects[0].y = rect.y;
401 m_rects[0].width = rect.width;
402 m_rects[0].height = rect.height;
403#else
1934d291
RR
404 m_numRects = r->numRects;
405 if (m_numRects)
406 {
407 m_rects = new wxRect[m_numRects];
408 for (size_t i=0; i < m_numRects; ++i)
409 {
410 _XBox &xr = r->rects[i];
411 wxRect &wr = m_rects[i];
412 wr.x = xr.x1;
413 wr.y = xr.y1;
414 wr.width = xr.x2-xr.x1;
415 wr.height = xr.y2-xr.y1;
416 }
417 }
461e93f9 418#endif
1934d291 419 }
83df96d6
JS
420}
421
1934d291 422wxRegionIterator::wxRegionIterator()
83df96d6 423{
1934d291
RR
424 m_refData = new wxRIRefData();
425 Reset();
426}
83df96d6 427
1934d291
RR
428wxRegionIterator::wxRegionIterator( const wxRegion& region )
429{
430 m_refData = new wxRIRefData();
83df96d6
JS
431 Reset(region);
432}
433
1934d291 434void wxRegionIterator::Reset( const wxRegion& region )
83df96d6 435{
83df96d6 436 m_region = region;
1934d291
RR
437 ((wxRIRefData*)m_refData)->CreateRects(region);
438 Reset();
439}
83df96d6 440
1934d291
RR
441bool wxRegionIterator::HaveRects() const
442{
443 return m_current < ((wxRIRefData*)m_refData)->m_numRects;
444}
83df96d6 445
1934d291
RR
446wxRegionIterator::operator bool () const
447{
448 return HaveRects();
83df96d6
JS
449}
450
83df96d6
JS
451void wxRegionIterator::operator ++ ()
452{
1934d291 453 if (HaveRects()) ++m_current;
83df96d6
JS
454}
455
83df96d6
JS
456void wxRegionIterator::operator ++ (int)
457{
1934d291 458 if (HaveRects()) ++m_current;
83df96d6
JS
459}
460
461wxCoord wxRegionIterator::GetX() const
462{
1934d291
RR
463 if( !HaveRects() ) return 0;
464 return ((wxRIRefData*)m_refData)->m_rects[m_current].x;
83df96d6
JS
465}
466
467wxCoord wxRegionIterator::GetY() const
468{
1934d291
RR
469 if( !HaveRects() ) return 0;
470 return ((wxRIRefData*)m_refData)->m_rects[m_current].y;
83df96d6
JS
471}
472
473wxCoord wxRegionIterator::GetW() const
474{
1934d291
RR
475 if( !HaveRects() ) return -1;
476 return ((wxRIRefData*)m_refData)->m_rects[m_current].width;
83df96d6
JS
477}
478
479wxCoord wxRegionIterator::GetH() const
480{
1934d291
RR
481 if( !HaveRects() ) return -1;
482 return ((wxRIRefData*)m_refData)->m_rects[m_current].height;
483}
484
485wxRect wxRegionIterator::GetRect() const
486{
487 wxRect r;
488 if( HaveRects() )
489 r = ((wxRIRefData*)m_refData)->m_rects[m_current];
490
491 return r;
83df96d6 492}