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