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