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