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