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