]> git.saurik.com Git - wxWidgets.git/blob - src/motif/region.cpp
drawing optimization fix
[wxWidgets.git] / src / motif / region.cpp
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"
17
18 #include <Xm/Xm.h>
19 // #include "wx/motif/private.h"
20
21 #if !USE_SHARED_LIBRARY
22 IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject)
23 IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator, wxObject)
24 #endif
25
26 //-----------------------------------------------------------------------------
27 // wxRegionRefData implementation
28 //-----------------------------------------------------------------------------
29
30 class WXDLLEXPORT wxRegionRefData : public wxGDIRefData {
31 public:
32 wxRegionRefData()
33 {
34 m_region = XCreateRegion();
35 }
36
37 wxRegionRefData(const wxRegionRefData& data)
38 {
39 m_region = XCreateRegion();
40 XUnionRegion(m_region, data.m_region, m_region);
41 }
42
43 ~wxRegionRefData()
44 {
45 XDestroyRegion(m_region);
46 }
47 Region m_region;
48 };
49
50 #define M_REGION (((wxRegionRefData*)m_refData)->m_region)
51
52 //-----------------------------------------------------------------------------
53 // wxRegion
54 //-----------------------------------------------------------------------------
55
56 /*!
57 * Create an empty region.
58 */
59 wxRegion::wxRegion()
60 {
61 }
62
63 wxRegion::wxRegion(long x, long y, long w, long h)
64 {
65 m_refData = new wxRegionRefData;
66
67 XRectangle rect;
68 rect.x = x;
69 rect.y = y;
70 rect.width = w;
71 rect.height = h;
72 XUnionRectWithRegion(&rect, M_REGION, M_REGION);
73 }
74
75 wxRegion::wxRegion(const wxPoint& topLeft, const wxPoint& bottomRight)
76 {
77 m_refData = new wxRegionRefData;
78
79 XRectangle rect;
80 rect.x = topLeft.x;
81 rect.y = topLeft.y;
82 rect.width = bottomRight.x - topLeft.x;
83 rect.height = bottomRight.y - topLeft.y;
84 XUnionRectWithRegion(&rect, M_REGION, M_REGION);
85 }
86
87 wxRegion::wxRegion(const wxRect& rect)
88 {
89 m_refData = new wxRegionRefData;
90
91 XRectangle rect1;
92 rect1.x = rect.x;
93 rect1.y = rect.y;
94 rect1.width = rect.width;
95 rect1.height = rect.height;
96 XUnionRectWithRegion(&rect1, M_REGION, M_REGION);
97 }
98
99 /*!
100 * Destroy the region.
101 */
102 wxRegion::~wxRegion()
103 {
104 // m_refData unrefed in ~wxObject
105 }
106
107 // Get the internal region handle
108 WXRegion wxRegion::GetXRegion()
109 {
110 wxASSERT( m_refData !=NULL );
111
112 return (WXRegion) ((wxRegionRefData*)m_refData)->m_region;
113 }
114
115 //-----------------------------------------------------------------------------
116 //# Modify region
117 //-----------------------------------------------------------------------------
118
119 //! Clear current region
120 void wxRegion::Clear()
121 {
122 UnRef();
123 }
124
125 //! Combine rectangle (x, y, w, h) with this.
126 bool wxRegion::Combine(long x, long y, long width, long height, wxRegionOp op)
127 {
128 // Don't change shared data
129 if (!m_refData) {
130 m_refData = new wxRegionRefData();
131 } else if (m_refData->GetRefCount() > 1) {
132 wxRegionRefData* ref = (wxRegionRefData*)m_refData;
133 UnRef();
134 m_refData = new wxRegionRefData(*ref);
135 }
136 // If ref count is 1, that means it's 'ours' anyway so no action.
137
138 Region rectRegion = XCreateRegion();
139
140 XRectangle rect;
141 rect.x = x;
142 rect.y = y;
143 rect.width = width;
144 rect.height = height;
145 XUnionRectWithRegion(&rect, rectRegion, rectRegion);
146
147 int mode = 0; // TODO platform-specific code
148 switch (op)
149 {
150 case wxRGN_AND:
151 XIntersectRegion(M_REGION, rectRegion, M_REGION);
152 break ;
153 case wxRGN_OR:
154 XUnionRegion(M_REGION, rectRegion, M_REGION);
155 break ;
156 case wxRGN_XOR:
157 // TODO
158 break ;
159 case wxRGN_DIFF:
160 // TODO
161 break ;
162 case wxRGN_COPY: // Don't have to do this one
163 default:
164 // TODO
165 break ;
166 }
167
168 return FALSE;
169 }
170
171 //! Union /e region with this.
172 bool wxRegion::Combine(const wxRegion& region, wxRegionOp op)
173 {
174 if (region.Empty())
175 return FALSE;
176
177 // Don't change shared data
178 if (!m_refData) {
179 m_refData = new wxRegionRefData();
180 } else if (m_refData->GetRefCount() > 1) {
181 wxRegionRefData* ref = (wxRegionRefData*)m_refData;
182 UnRef();
183 m_refData = new wxRegionRefData(*ref);
184 }
185
186 int mode = 0; // TODO platform-specific code
187 switch (op)
188 {
189 case wxRGN_AND:
190 XIntersectRegion(M_REGION, ((wxRegionRefData*)region.m_refData)->m_region,
191 M_REGION);
192 break ;
193 case wxRGN_OR:
194 XUnionRegion(M_REGION, ((wxRegionRefData*)region.m_refData)->m_region,
195 M_REGION);
196 break ;
197 case wxRGN_XOR:
198 // TODO
199 break ;
200 case wxRGN_DIFF:
201 // TODO
202 break ;
203 case wxRGN_COPY: // Don't have to do this one
204 default:
205 // TODO
206 break ;
207 }
208
209 // TODO combine region
210
211 return FALSE;
212 }
213
214 bool wxRegion::Combine(const wxRect& rect, wxRegionOp op)
215 {
216 return Combine(rect.GetLeft(), rect.GetTop(), rect.GetWidth(), rect.GetHeight(), op);
217 }
218
219 //-----------------------------------------------------------------------------
220 //# Information on region
221 //-----------------------------------------------------------------------------
222
223 // Outer bounds of region
224 void wxRegion::GetBox(long& x, long& y, long&w, long &h) const
225 {
226 if (m_refData) {
227 XRectangle rect;
228 XClipBox(M_REGION, &rect);
229 x = rect.x;
230 y = rect.y;
231 w = rect.width;
232 h = rect.height;
233 } else {
234 x = y = w = h = 0;
235 }
236 }
237
238 wxRect wxRegion::GetBox() const
239 {
240 long x, y, w, h;
241 GetBox(x, y, w, h);
242 return wxRect(x, y, w, h);
243 }
244
245 // Is region empty?
246 bool wxRegion::Empty() const
247 {
248 return m_refData ? XEmptyRegion(M_REGION) : TRUE;
249 }
250
251 //-----------------------------------------------------------------------------
252 //# Tests
253 //-----------------------------------------------------------------------------
254
255 // Does the region contain the point (x,y)?
256 wxRegionContain wxRegion::Contains(long x, long y) const
257 {
258 if (!m_refData)
259 return wxOutRegion;
260
261 // TODO. Return wxInRegion if within region.
262 if (0)
263 return wxInRegion;
264 return wxOutRegion;
265 }
266
267 // Does the region contain the point pt?
268 wxRegionContain wxRegion::Contains(const wxPoint& pt) const
269 {
270 if (!m_refData)
271 return wxOutRegion;
272
273 return XPointInRegion(M_REGION, pt.x, pt.y) ? wxInRegion : wxOutRegion;
274 }
275
276 // Does the region contain the rectangle (x, y, w, h)?
277 wxRegionContain wxRegion::Contains(long x, long y, long w, long h) const
278 {
279 if (!m_refData)
280 return wxOutRegion;
281
282 switch (XRectInRegion(M_REGION, x, y, w, h)) {
283 case RectangleIn: return wxInRegion;
284 case RectanglePart: return wxPartRegion;
285 }
286 return wxOutRegion;
287 }
288
289 // Does the region contain the rectangle rect
290 wxRegionContain wxRegion::Contains(const wxRect& rect) const
291 {
292 if (!m_refData)
293 return wxOutRegion;
294
295 long x, y, w, h;
296 x = rect.x;
297 y = rect.y;
298 w = rect.GetWidth();
299 h = rect.GetHeight();
300 return Contains(x, y, w, h);
301 }
302
303 ///////////////////////////////////////////////////////////////////////////////
304 // //
305 // wxRegionIterator //
306 // //
307 ///////////////////////////////////////////////////////////////////////////////
308
309 /*!
310 * Initialize empty iterator
311 */
312 wxRegionIterator::wxRegionIterator() : m_current(0), m_numRects(0), m_rects(NULL)
313 {
314 }
315
316 wxRegionIterator::~wxRegionIterator()
317 {
318 if (m_rects)
319 delete[] m_rects;
320 }
321
322 /*!
323 * Initialize iterator for region
324 */
325 wxRegionIterator::wxRegionIterator(const wxRegion& region)
326 {
327 m_rects = NULL;
328
329 Reset(region);
330 }
331
332 /*!
333 * Reset iterator for a new /e region.
334 */
335 void wxRegionIterator::Reset(const wxRegion& region)
336 {
337 m_current = 0;
338 m_region = region;
339
340 if (m_rects)
341 delete[] m_rects;
342
343 m_rects = NULL;
344
345 if (m_region.Empty())
346 m_numRects = 0;
347 else
348 {
349 // TODO create m_rects and fill with rectangles for this region
350 m_numRects = 0;
351 }
352 }
353
354 /*!
355 * Increment iterator. The rectangle returned is the one after the
356 * incrementation.
357 */
358 void wxRegionIterator::operator ++ ()
359 {
360 if (m_current < m_numRects)
361 ++m_current;
362 }
363
364 /*!
365 * Increment iterator. The rectangle returned is the one before the
366 * incrementation.
367 */
368 void wxRegionIterator::operator ++ (int)
369 {
370 if (m_current < m_numRects)
371 ++m_current;
372 }
373
374 long wxRegionIterator::GetX() const
375 {
376 if (m_current < m_numRects)
377 return m_rects[m_current].x;
378 return 0;
379 }
380
381 long wxRegionIterator::GetY() const
382 {
383 if (m_current < m_numRects)
384 return m_rects[m_current].y;
385 return 0;
386 }
387
388 long wxRegionIterator::GetW() const
389 {
390 if (m_current < m_numRects)
391 return m_rects[m_current].width ;
392 return 0;
393 }
394
395 long wxRegionIterator::GetH() const
396 {
397 if (m_current < m_numRects)
398 return m_rects[m_current].height;
399 return 0;
400 }
401