]> git.saurik.com Git - wxWidgets.git/blame - src/x11/region.cpp
wxDC::DoDrawRectangle hack is no longer needed
[wxWidgets.git] / src / x11 / region.cpp
CommitLineData
83df96d6
JS
1/////////////////////////////////////////////////////////////////////////////
2// File: region.cpp
3// Purpose: Region class
4// Author: Markus Holzem/Julian Smart
5// Created: Fri Oct 24 10:46:34 MET 1997
6// RCS-ID: $Id$
7// Copyright: (c) 1997 Markus Holzem/Julian Smart
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11#ifdef __GNUG__
12#pragma implementation "region.h"
13#endif
14
15#include "wx/region.h"
16#include "wx/gdicmn.h"
7266b672 17#include "wx/window.h"
83df96d6
JS
18
19#ifdef __VMS__
20#pragma message disable nosimpint
21#endif
7266b672
JS
22#include "wx/x11/private.h"
23#include "X11/Xutil.h"
83df96d6
JS
24#ifdef __VMS__
25#pragma message enable nosimpint
26#endif
7266b672 27
83df96d6
JS
28
29 IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
30 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator, wxObject)
31
32// ----------------------------------------------------------------------------
33// list types
34// ----------------------------------------------------------------------------
35
36#include "wx/listimpl.cpp"
37
38WX_DEFINE_LIST(wxRectList);
39
40//-----------------------------------------------------------------------------
41// wxRegionRefData implementation
42//-----------------------------------------------------------------------------
43
44class WXDLLEXPORT wxRegionRefData : public wxGDIRefData {
45public:
46 wxRegionRefData()
47 {
48 m_region = XCreateRegion();
49 m_usingRects = FALSE;
50 m_rects = (wxRect*) NULL;
51 m_rectCount = 0;
52 }
53
54 wxRegionRefData(const wxRegionRefData& data)
55 {
56 m_region = XCreateRegion();
57 m_rects = (wxRect*) NULL;
58 m_rectCount = 0;
59 XUnionRegion(m_region, data.m_region, m_region);
60
61 SetRects(data.m_rectCount, data.m_rects);
62 }
63
64 ~wxRegionRefData()
65 {
66 XDestroyRegion(m_region);
67 DeleteRects();
68 }
69
70 wxRect* GetRects() { return m_rects; };
71 void SetRects(const wxRectList& rectList);
72 void SetRects(int count, const wxRect* rects);
73 bool UsingRects() const { return m_usingRects; }
74 int GetRectCount() const { return m_rectCount; }
75
76 void DeleteRects();
77
78 Region m_region;
79 wxRect* m_rects;
80 int m_rectCount;
81 bool m_usingRects; // TRUE if we're using the above.
82};
83
84void wxRegionRefData::SetRects(const wxRectList& rectList)
85{
86 DeleteRects();
87 m_usingRects = (rectList.Number() > 0);
88 if (m_usingRects)
89 {
90 m_rectCount = rectList.Number();
91 m_rects = new wxRect[m_rectCount];
92 }
93
94 wxRectList::Node* node = rectList.GetFirst();
95 int i = 0;
96 while (node) {
97 wxRect* rect = node->GetData();
98 m_rects[i] = * rect;
99 node = node->GetNext();
100 i ++;
101 }
102}
103
104void wxRegionRefData::SetRects(int count, const wxRect* rects)
105{
106 DeleteRects();
107 m_usingRects = (count > 0);
108 if (m_usingRects)
109 {
110 m_rectCount = count;
111 m_rects = new wxRect[m_rectCount];
112 int i;
113 for (i = 0; i < m_rectCount; i++)
114 m_rects[i] = rects[i];
115 }
116}
117
118void wxRegionRefData::DeleteRects()
119{
120 if (m_rects)
121 {
122 delete[] m_rects;
123 m_rects = (wxRect*) NULL;
124 }
125 m_rectCount = 0;
126 m_usingRects = FALSE;
127 }
128
129#define M_REGION (((wxRegionRefData*)m_refData)->m_region)
130
131//-----------------------------------------------------------------------------
132// wxRegion
133//-----------------------------------------------------------------------------
134
135/*!
136 * Create an empty region.
137 */
138wxRegion::wxRegion()
139{
140}
141
142wxRegion::wxRegion(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
143{
144 m_refData = new wxRegionRefData;
145
146 XRectangle rect;
147 rect.x = x;
148 rect.y = y;
149 rect.width = w;
150 rect.height = h;
151 XUnionRectWithRegion(&rect, M_REGION, M_REGION);
152}
153
154wxRegion::wxRegion(const wxPoint& topLeft, const wxPoint& bottomRight)
155{
156 m_refData = new wxRegionRefData;
157
158 XRectangle rect;
159 rect.x = topLeft.x;
160 rect.y = topLeft.y;
161 rect.width = bottomRight.x - topLeft.x;
162 rect.height = bottomRight.y - topLeft.y;
163 XUnionRectWithRegion(&rect, M_REGION, M_REGION);
164}
165
166wxRegion::wxRegion(const wxRect& rect)
167{
168 m_refData = new wxRegionRefData;
169
170 XRectangle rect1;
171 rect1.x = rect.x;
172 rect1.y = rect.y;
173 rect1.width = rect.width;
174 rect1.height = rect.height;
175 XUnionRectWithRegion(&rect1, M_REGION, M_REGION);
176}
177
178/*!
179 * Destroy the region.
180 */
181wxRegion::~wxRegion()
182{
183 // m_refData unrefed in ~wxObject
184}
185
186// Get the internal region handle
187WXRegion wxRegion::GetXRegion() const
188{
189 wxASSERT( m_refData !=NULL );
190
191 return (WXRegion) ((wxRegionRefData*)m_refData)->m_region;
192}
193
194//-----------------------------------------------------------------------------
195//# Modify region
196//-----------------------------------------------------------------------------
197
198//! Clear current region
199void wxRegion::Clear()
200{
201 UnRef();
202}
203
204//! Combine rectangle (x, y, w, h) with this.
205bool wxRegion::Combine(wxCoord x, wxCoord y, wxCoord width, wxCoord height, wxRegionOp op)
206{
207 // Don't change shared data
208 if (!m_refData) {
209 m_refData = new wxRegionRefData();
210 } else if (m_refData->GetRefCount() > 1) {
211 wxRegionRefData* ref = (wxRegionRefData*)m_refData;
212 UnRef();
213 m_refData = new wxRegionRefData(*ref);
214 }
215 // If ref count is 1, that means it's 'ours' anyway so no action.
216
217 Region rectRegion = XCreateRegion();
218
219 XRectangle rect;
220 rect.x = x;
221 rect.y = y;
222 rect.width = width;
223 rect.height = height;
224 XUnionRectWithRegion(&rect, rectRegion, rectRegion);
225
226 switch (op)
227 {
228 case wxRGN_AND:
229 XIntersectRegion(M_REGION, rectRegion, M_REGION);
230 break ;
231 case wxRGN_OR:
232 XUnionRegion(M_REGION, rectRegion, M_REGION);
233 break ;
234 case wxRGN_XOR:
235 // TODO
236 break ;
237 case wxRGN_DIFF:
238 // TODO
239 break ;
240 case wxRGN_COPY: // Don't have to do this one
241 default:
242 // TODO
243 break ;
244 }
245
246 return FALSE;
247}
248
249//! Union /e region with this.
250bool wxRegion::Combine(const wxRegion& region, wxRegionOp op)
251{
252 if (region.Empty())
253 return FALSE;
254
255 // Don't change shared data
256 if (!m_refData) {
257 m_refData = new wxRegionRefData();
258 } else if (m_refData->GetRefCount() > 1) {
259 wxRegionRefData* ref = (wxRegionRefData*)m_refData;
260 UnRef();
261 m_refData = new wxRegionRefData(*ref);
262 }
263
264 switch (op)
265 {
266 case wxRGN_AND:
267 XIntersectRegion(M_REGION, ((wxRegionRefData*)region.m_refData)->m_region,
268 M_REGION);
269 break ;
270 case wxRGN_OR:
271 XUnionRegion(M_REGION, ((wxRegionRefData*)region.m_refData)->m_region,
272 M_REGION);
273 break ;
274 case wxRGN_XOR:
275 // TODO
276 break ;
277 case wxRGN_DIFF:
278 // TODO
279 break ;
280 case wxRGN_COPY: // Don't have to do this one
281 default:
282 // TODO
283 break ;
284 }
285
286 return FALSE;
287}
288
289bool wxRegion::Combine(const wxRect& rect, wxRegionOp op)
290{
291 return Combine(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight(), op);
292}
293
294//-----------------------------------------------------------------------------
295//# Information on region
296//-----------------------------------------------------------------------------
297
298// Outer bounds of region
299void wxRegion::GetBox(wxCoord& x, wxCoord& y, wxCoord&w, wxCoord &h) const
300{
301 if (m_refData) {
302 XRectangle rect;
303 XClipBox(M_REGION, &rect);
304 x = rect.x;
305 y = rect.y;
306 w = rect.width;
307 h = rect.height;
308 } else {
309 x = y = w = h = 0;
310 }
311}
312
313wxRect wxRegion::GetBox() const
314{
315 wxCoord x, y, w, h;
316 GetBox(x, y, w, h);
317 return wxRect(x, y, w, h);
318}
319
320// Is region empty?
321bool wxRegion::Empty() const
322{
323 return m_refData ? XEmptyRegion(M_REGION) : TRUE;
324}
325
326//-----------------------------------------------------------------------------
327//# Tests
328//-----------------------------------------------------------------------------
329
330// Does the region contain the point (x,y)?
331wxRegionContain wxRegion::Contains(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y)) const
332{
333 if (!m_refData)
334 return wxOutRegion;
335
336 // TODO. Return wxInRegion if within region.
337 if (0)
338 return wxInRegion;
339 return wxOutRegion;
340}
341
342// Does the region contain the point pt?
343wxRegionContain wxRegion::Contains(const wxPoint& pt) const
344{
345 if (!m_refData)
346 return wxOutRegion;
347
348 return XPointInRegion(M_REGION, pt.x, pt.y) ? wxInRegion : wxOutRegion;
349}
350
351// Does the region contain the rectangle (x, y, w, h)?
352wxRegionContain wxRegion::Contains(wxCoord x, wxCoord y, wxCoord w, wxCoord h) const
353{
354 if (!m_refData)
355 return wxOutRegion;
356
357 switch (XRectInRegion(M_REGION, x, y, w, h)) {
358 case RectangleIn: return wxInRegion;
359 case RectanglePart: return wxPartRegion;
360 }
361 return wxOutRegion;
362}
363
364// Does the region contain the rectangle rect
365wxRegionContain wxRegion::Contains(const wxRect& rect) const
366{
367 if (!m_refData)
368 return wxOutRegion;
369
370 wxCoord x, y, w, h;
371 x = rect.x;
372 y = rect.y;
373 w = rect.GetWidth();
374 h = rect.GetHeight();
375 return Contains(x, y, w, h);
376}
377
378bool wxRegion::UsingRects() const
379{
380 return ((wxRegionRefData*)m_refData)->UsingRects();
381}
382
383/*
384wxRectList& wxRegion::GetRectList()
385{
386 return ((wxRegionRefData*)m_refData)->GetRectList();
387}
388*/
389
390wxRect* wxRegion::GetRects()
391{
392 return ((wxRegionRefData*)m_refData)->GetRects();
393}
394
395int wxRegion::GetRectCount() const
396{
397 return ((wxRegionRefData*)m_refData)->GetRectCount();
398}
399
400void wxRegion::SetRects(const wxRectList& rectList)
401{
402 ((wxRegionRefData*)m_refData)->SetRects(rectList);
403}
404
405void wxRegion::SetRects(int count, const wxRect* rects)
406{
407 ((wxRegionRefData*)m_refData)->SetRects(count, rects);
408}
409
410///////////////////////////////////////////////////////////////////////////////
411// //
412// wxRegionIterator //
413// //
414///////////////////////////////////////////////////////////////////////////////
415
416/*!
417 * Initialize empty iterator
418 */
419wxRegionIterator::wxRegionIterator() : m_current(0), m_numRects(0), m_rects(NULL)
420{
421}
422
423wxRegionIterator::~wxRegionIterator()
424{
425 if (m_rects)
426 delete[] m_rects;
427}
428
429/*!
430 * Initialize iterator for region
431 */
432wxRegionIterator::wxRegionIterator(const wxRegion& region)
433{
434 m_rects = NULL;
435
436 Reset(region);
437}
438
439/*!
440 * Reset iterator for a new /e region.
441 */
442void wxRegionIterator::Reset(const wxRegion& region)
443{
444 m_current = 0;
445 m_region = region;
446
447 if (m_rects)
448 delete[] m_rects;
449
450 m_rects = NULL;
451
452 if (m_region.Empty())
453 m_numRects = 0;
454 else
455 {
456 // Create m_rects and fill with rectangles for this region.
457 // Since we can't find the rectangles in a region, we cheat
458 // by retrieving the rectangles explicitly set in wxPaintDC::wxPaintDC
459 // (dcclient.cpp).
460 if (m_region.UsingRects())
461 {
462 wxRect* rects = m_region.GetRects();
463 int count = m_region.GetRectCount();
464 m_numRects = count;
465 m_rects = new wxRect[m_numRects];
466
467 for (size_t i = 0; i < m_numRects; i++)
468 m_rects[i] = rects[i];
469
470 /*
471 int i = 0;
472 wxRectList::Node* node = rectList.GetFirst();
473 while (node) {
474 wxRect* rect = node->GetData();
475 m_rects[i] = * rect;
476 node = node->GetNext();
477 i ++;
478 }
479 */
480 }
481 else
482 {
483 // For now, fudge by getting the whole bounding box.
484 m_rects = new wxRect[1];
485 m_numRects = 1;
486 m_rects[0] = m_region.GetBox();
487 }
488 }
489}
490
491/*!
492 * Increment iterator. The rectangle returned is the one after the
493 * incrementation.
494 */
495void wxRegionIterator::operator ++ ()
496{
497 if (m_current < m_numRects)
498 ++m_current;
499}
500
501/*!
502 * Increment iterator. The rectangle returned is the one before the
503 * incrementation.
504 */
505void wxRegionIterator::operator ++ (int)
506{
507 if (m_current < m_numRects)
508 ++m_current;
509}
510
511wxCoord wxRegionIterator::GetX() const
512{
513 if (m_current < m_numRects)
514 return m_rects[m_current].x;
515 return 0;
516}
517
518wxCoord wxRegionIterator::GetY() const
519{
520 if (m_current < m_numRects)
521 return m_rects[m_current].y;
522 return 0;
523}
524
525wxCoord wxRegionIterator::GetW() const
526{
527 if (m_current < m_numRects)
528 return m_rects[m_current].width ;
529 return 0;
530}
531
532wxCoord wxRegionIterator::GetH() const
533{
534 if (m_current < m_numRects)
535 return m_rects[m_current].height;
536 return 0;
537}
538