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