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