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