]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/gtk1/region.cpp
compilation fix
[wxWidgets.git] / src / gtk1 / region.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: gtk/region.cpp
3// Purpose:
4// Author: Robert Roebling
5// Modified: VZ at 05.10.00: use AllocExclusive(), comparison fixed
6// Id: $Id$
7// Copyright: (c) 1998 Robert Roebling
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// declarations
13// ============================================================================
14
15#ifdef __GNUG__
16 #pragma implementation "region.h"
17#endif
18
19// ----------------------------------------------------------------------------
20// headers
21// ----------------------------------------------------------------------------
22
23#include "wx/log.h"
24
25#include "wx/region.h"
26
27#include "wx/gtk/private.h"
28
29#ifndef __WXGTK20__
30
31// ----------------------------------------------------------------------------
32// wxGdkRegion: creates a new region in ctor and destroys in dtor
33// ----------------------------------------------------------------------------
34
35class wxGdkRegion
36{
37public:
38 wxGdkRegion() { m_region = gdk_region_new(); }
39 ~wxGdkRegion() { gdk_region_destroy(m_region); }
40
41 operator GdkRegion *() const { return m_region; }
42
43private:
44 GdkRegion *m_region;
45};
46
47#endif // __WXGTK20__
48
49// ----------------------------------------------------------------------------
50// wxRegionRefData: private class containing the information about the region
51// ----------------------------------------------------------------------------
52
53class wxRegionRefData : public wxObjectRefData
54{
55public:
56 wxRegionRefData()
57 {
58 m_region = NULL;
59 }
60
61 wxRegionRefData(const wxRegionRefData& refData)
62 : wxObjectRefData()
63 {
64#ifdef __WXGTK20__
65 m_region = gdk_region_copy(refData.m_region);
66#else
67 m_region = gdk_regions_union(wxGdkRegion(), refData.m_region);
68#endif
69 }
70
71 ~wxRegionRefData()
72 {
73 if (m_region)
74 gdk_region_destroy( m_region );
75 }
76
77 GdkRegion *m_region;
78};
79
80// ----------------------------------------------------------------------------
81// macros
82// ----------------------------------------------------------------------------
83
84#define M_REGIONDATA ((wxRegionRefData *)m_refData)
85#define M_REGIONDATA_OF(rgn) ((wxRegionRefData *)(rgn.m_refData))
86
87IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
88IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator,wxObject)
89
90// ----------------------------------------------------------------------------
91// wxRegion construction
92// ----------------------------------------------------------------------------
93
94#define M_REGIONDATA ((wxRegionRefData *)m_refData)
95
96void wxRegion::InitRect(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
97{
98 GdkRectangle rect;
99 rect.x = x;
100 rect.y = y;
101 rect.width = w;
102 rect.height = h;
103
104 m_refData = new wxRegionRefData();
105
106#ifdef __WXGTK20__
107 M_REGIONDATA->m_region = gdk_region_rectangle( &rect );
108#else
109 M_REGIONDATA->m_region = gdk_region_union_with_rect( wxGdkRegion(), &rect );
110#endif
111}
112
113wxRegion::wxRegion( GdkRegion *region )
114{
115 m_refData = new wxRegionRefData();
116#ifdef __WXGTK20__
117 M_REGIONDATA->m_region = gdk_region_copy( region );
118#else
119 M_REGIONDATA->m_region = gdk_regions_union(wxGdkRegion(), region);
120#endif
121}
122
123wxRegion::wxRegion( size_t n, const wxPoint *points, int fillStyle )
124{
125 GdkPoint *gdkpoints = new GdkPoint[n];
126 for ( size_t i = 0 ; i < n ; i++ )
127 {
128 gdkpoints[i].x = points[i].x;
129 gdkpoints[i].y = points[i].y;
130 }
131
132 m_refData = new wxRegionRefData();
133
134 GdkRegion* reg = gdk_region_polygon
135 (
136 gdkpoints,
137 n,
138 fillStyle == wxWINDING_RULE ? GDK_WINDING_RULE
139 : GDK_EVEN_ODD_RULE
140 );
141
142 M_REGIONDATA->m_region = reg;
143
144 delete [] gdkpoints;
145}
146
147wxRegion::~wxRegion()
148{
149 // m_refData unrefed in ~wxObject
150}
151
152wxObjectRefData *wxRegion::CreateRefData() const
153{
154 return new wxRegionRefData;
155}
156
157wxObjectRefData *wxRegion::CloneRefData(const wxObjectRefData *data) const
158{
159 return new wxRegionRefData(*(wxRegionRefData *)data);
160}
161
162// ----------------------------------------------------------------------------
163// wxRegion comparison
164// ----------------------------------------------------------------------------
165
166bool wxRegion::operator==( const wxRegion& region )
167{
168 if (m_refData == region.m_refData) return TRUE;
169
170 if (!m_refData || !region.m_refData) return FALSE;
171
172 // compare the regions themselves, not the pointers to ref data!
173 return gdk_region_equal(M_REGIONDATA->m_region,
174 M_REGIONDATA_OF(region)->m_region);
175}
176
177// ----------------------------------------------------------------------------
178// wxRegion operations
179// ----------------------------------------------------------------------------
180
181void wxRegion::Clear()
182{
183 UnRef();
184}
185
186bool wxRegion::Union( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
187{
188 GdkRectangle rect;
189 rect.x = x;
190 rect.y = y;
191 rect.width = width;
192 rect.height = height;
193
194 if (!m_refData)
195 {
196 m_refData = new wxRegionRefData();
197#ifdef __WXGTK20__
198 M_REGIONDATA->m_region = gdk_region_rectangle( &rect );
199#else
200 M_REGIONDATA->m_region = gdk_region_union_with_rect(wxGdkRegion(), &rect);
201#endif
202 }
203 else
204 {
205 AllocExclusive();
206
207#ifdef __WXGTK20__
208 gdk_region_union_with_rect( M_REGIONDATA->m_region, &rect );
209#else
210 GdkRegion *reg = gdk_region_union_with_rect( M_REGIONDATA->m_region, &rect );
211 gdk_region_destroy( M_REGIONDATA->m_region );
212 M_REGIONDATA->m_region = reg;
213#endif
214 }
215
216 return TRUE;
217}
218
219bool wxRegion::Union( const wxRect& rect )
220{
221 return Union( rect.x, rect.y, rect.width, rect.height );
222}
223
224bool wxRegion::Union( 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 = gdk_region_new();
233 }
234 else
235 {
236 AllocExclusive();
237 }
238
239#ifdef __WXGTK20__
240 gdk_region_union( M_REGIONDATA->m_region, region.GetRegion() );
241#else
242 GdkRegion *reg = gdk_regions_union( M_REGIONDATA->m_region, region.GetRegion() );
243 gdk_region_destroy( M_REGIONDATA->m_region );
244 M_REGIONDATA->m_region = reg;
245#endif
246
247 return TRUE;
248}
249
250bool wxRegion::Intersect( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
251{
252 wxRegion reg( x, y, width, height );
253
254 return Intersect( reg );
255}
256
257bool wxRegion::Intersect( const wxRect& rect )
258{
259 wxRegion reg( rect );
260
261 return Intersect( reg );
262}
263
264bool wxRegion::Intersect( const wxRegion& region )
265{
266 if (region.IsNull())
267 return FALSE;
268
269 if (!m_refData)
270 {
271 m_refData = new wxRegionRefData();
272 M_REGIONDATA->m_region = gdk_region_new();
273
274 // leave here
275 return TRUE;
276 }
277 else
278 {
279 AllocExclusive();
280 }
281
282#ifdef __WXGTK20__
283 gdk_region_intersect( M_REGIONDATA->m_region, region.GetRegion() );
284#else
285 GdkRegion *reg = gdk_regions_intersect( M_REGIONDATA->m_region, region.GetRegion() );
286 gdk_region_destroy( M_REGIONDATA->m_region );
287 M_REGIONDATA->m_region = reg;
288#endif
289
290 return TRUE;
291}
292
293bool wxRegion::Subtract( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
294{
295 wxRegion reg( x, y, width, height );
296 return Subtract( reg );
297}
298
299bool wxRegion::Subtract( const wxRect& rect )
300{
301 wxRegion reg( rect );
302 return Subtract( reg );
303}
304
305bool wxRegion::Subtract( const wxRegion& region )
306{
307 if (region.IsNull())
308 return FALSE;
309
310 if (!m_refData)
311 {
312 m_refData = new wxRegionRefData();
313 M_REGIONDATA->m_region = gdk_region_new();
314 }
315 else
316 {
317 AllocExclusive();
318 }
319
320#ifdef __WXGTK20__
321 gdk_region_subtract( M_REGIONDATA->m_region, region.GetRegion() );
322#else
323 GdkRegion *reg = gdk_regions_subtract( M_REGIONDATA->m_region, region.GetRegion() );
324 gdk_region_destroy( M_REGIONDATA->m_region );
325 M_REGIONDATA->m_region = reg;
326#endif
327
328 return TRUE;
329}
330
331bool wxRegion::Xor( wxCoord x, wxCoord y, wxCoord width, wxCoord height )
332{
333 wxRegion reg( x, y, width, height );
334 return Xor( reg );
335}
336
337bool wxRegion::Xor( const wxRect& rect )
338{
339 wxRegion reg( rect );
340 return Xor( reg );
341}
342
343bool wxRegion::Xor( const wxRegion& region )
344{
345 if (region.IsNull())
346 return FALSE;
347
348 if (!m_refData)
349 {
350 m_refData = new wxRegionRefData();
351 M_REGIONDATA->m_region = gdk_region_new();
352 }
353 else
354 {
355 AllocExclusive();
356 }
357
358#ifdef __WXGTK20__
359 gdk_region_xor( M_REGIONDATA->m_region, region.GetRegion() );
360#else
361 GdkRegion *reg = gdk_regions_xor( M_REGIONDATA->m_region, region.GetRegion() );
362 gdk_region_destroy( M_REGIONDATA->m_region );
363 M_REGIONDATA->m_region = reg;
364#endif
365
366 return TRUE;
367}
368
369// ----------------------------------------------------------------------------
370// wxRegion tests
371// ----------------------------------------------------------------------------
372
373void wxRegion::GetBox( wxCoord &x, wxCoord &y, wxCoord &w, wxCoord &h ) const
374{
375 if ( m_refData )
376 {
377 GdkRectangle rect;
378 gdk_region_get_clipbox( M_REGIONDATA->m_region, &rect );
379 x = rect.x;
380 y = rect.y;
381 w = rect.width;
382 h = rect.height;
383 }
384 else
385 {
386 x = 0;
387 y = 0;
388 w = -1;
389 h = -1;
390 }
391}
392
393wxRect wxRegion::GetBox() const
394{
395 wxCoord x, y, w, h;
396 GetBox( x, y, w, h );
397 return wxRect( x, y, w, h );
398}
399
400bool wxRegion::Offset( wxCoord x, wxCoord y )
401{
402 if (!m_refData)
403 return FALSE;
404
405 AllocExclusive();
406
407 gdk_region_offset( M_REGIONDATA->m_region, x, y );
408
409 return TRUE;
410}
411
412bool wxRegion::Empty() const
413{
414 if (!m_refData)
415 return TRUE;
416
417 return gdk_region_empty( M_REGIONDATA->m_region );
418}
419
420wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y ) const
421{
422 if (!m_refData)
423 return wxOutRegion;
424
425 if (gdk_region_point_in( M_REGIONDATA->m_region, x, y ))
426 return wxInRegion;
427 else
428 return wxOutRegion;
429}
430
431wxRegionContain wxRegion::Contains( wxCoord x, wxCoord y, wxCoord w, wxCoord h ) const
432{
433 if (!m_refData)
434 return wxOutRegion;
435
436 GdkRectangle rect;
437 rect.x = x;
438 rect.y = y;
439 rect.width = w;
440 rect.height = h;
441 GdkOverlapType res = gdk_region_rect_in( M_REGIONDATA->m_region, &rect );
442 switch (res)
443 {
444 case GDK_OVERLAP_RECTANGLE_IN: return wxInRegion;
445 case GDK_OVERLAP_RECTANGLE_OUT: return wxOutRegion;
446 case GDK_OVERLAP_RECTANGLE_PART: return wxPartRegion;
447 }
448 return wxOutRegion;
449}
450
451wxRegionContain wxRegion::Contains(const wxPoint& pt) const
452{
453 return Contains( pt.x, pt.y );
454}
455
456wxRegionContain wxRegion::Contains(const wxRect& rect) const
457{
458 return Contains( rect.x, rect.y, rect.width, rect.height );
459}
460
461GdkRegion *wxRegion::GetRegion() const
462{
463 if (!m_refData)
464 return (GdkRegion*) NULL;
465
466 return M_REGIONDATA->m_region;
467}
468
469// ----------------------------------------------------------------------------
470// wxRegionIterator
471// ----------------------------------------------------------------------------
472
473#ifndef __WXGTK20__
474
475// the following structures must match the private structures
476// in X11 region code ( xc/lib/X11/region.h )
477
478// this makes the Region type transparent
479// and we have access to the region rectangles
480
481#include <gdk/gdkprivate.h>
482
483struct _XBox {
484 short x1, x2, y1, y2;
485};
486
487struct _XRegion {
488 long size , numRects;
489 _XBox *rects, extents;
490};
491
492#endif
493
494class wxRIRefData: public wxObjectRefData
495{
496public:
497 wxRIRefData() { Init(); }
498 virtual ~wxRIRefData();
499
500 void CreateRects( const wxRegion& r );
501
502 void Init() { m_rects = NULL; m_numRects = 0; }
503
504 wxRect *m_rects;
505 size_t m_numRects;
506};
507
508wxRIRefData::~wxRIRefData()
509{
510 delete [] m_rects;
511}
512
513void wxRIRefData::CreateRects( const wxRegion& region )
514{
515 delete [] m_rects;
516
517 Init();
518
519 GdkRegion *gdkregion = region.GetRegion();
520 if (!gdkregion)
521 return;
522
523#ifdef __WXGTK20__
524 GdkRectangle *gdkrects = NULL;
525 gint numRects = 0;
526 gdk_region_get_rectangles( gdkregion, &gdkrects, &numRects );
527
528 m_numRects = numRects;
529 if (numRects)
530 {
531 m_rects = new wxRect[m_numRects];
532 for (size_t i=0; i < m_numRects; ++i)
533 {
534 GdkRectangle &gr = gdkrects[i];
535 wxRect &wr = m_rects[i];
536 wr.x = gr.x;
537 wr.y = gr.y;
538 wr.width = gr.width;
539 wr.height = gr.height;
540 }
541 }
542 g_free( gdkrects );
543#else // GTK+ 1.x
544 Region r = ((GdkRegionPrivate *)gdkregion)->xregion;
545 if (r)
546 {
547 m_numRects = r->numRects;
548 if (m_numRects)
549 {
550 m_rects = new wxRect[m_numRects];
551 for (size_t i=0; i < m_numRects; ++i)
552 {
553 _XBox &xr = r->rects[i];
554 wxRect &wr = m_rects[i];
555 wr.x = xr.x1;
556 wr.y = xr.y1;
557 wr.width = xr.x2-xr.x1;
558 wr.height = xr.y2-xr.y1;
559 }
560 }
561 }
562#endif // GTK+ 2.0/1.x
563}
564
565wxRegionIterator::wxRegionIterator()
566{
567 m_refData = new wxRIRefData();
568 Reset();
569}
570
571wxRegionIterator::wxRegionIterator( const wxRegion& region )
572{
573 m_refData = new wxRIRefData();
574 Reset(region);
575}
576
577void wxRegionIterator::Reset( const wxRegion& region )
578{
579 m_region = region;
580 ((wxRIRefData*)m_refData)->CreateRects(region);
581 Reset();
582}
583
584bool wxRegionIterator::HaveRects() const
585{
586 return m_current < ((wxRIRefData*)m_refData)->m_numRects;
587}
588
589wxRegionIterator::operator bool () const
590{
591 return HaveRects();
592}
593
594void wxRegionIterator::operator ++ ()
595{
596 if (HaveRects()) ++m_current;
597}
598
599void wxRegionIterator::operator ++ (int)
600{
601 if (HaveRects()) ++m_current;
602}
603
604wxCoord wxRegionIterator::GetX() const
605{
606 if( !HaveRects() ) return 0;
607 return ((wxRIRefData*)m_refData)->m_rects[m_current].x;
608}
609
610wxCoord wxRegionIterator::GetY() const
611{
612 if( !HaveRects() ) return 0;
613 return ((wxRIRefData*)m_refData)->m_rects[m_current].y;
614}
615
616wxCoord wxRegionIterator::GetW() const
617{
618 if( !HaveRects() ) return -1;
619 return ((wxRIRefData*)m_refData)->m_rects[m_current].width;
620}
621
622wxCoord wxRegionIterator::GetH() const
623{
624 if( !HaveRects() ) return -1;
625 return ((wxRIRefData*)m_refData)->m_rects[m_current].height;
626}
627
628wxRect wxRegionIterator::GetRect() const
629{
630 wxRect r;
631 if( HaveRects() )
632 r = ((wxRIRefData*)m_refData)->m_rects[m_current];
633
634 return r;
635}
636