]>
Commit | Line | Data |
---|---|---|
b3c86150 VS |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: src/mgl/region.cpp | |
3 | // Purpose: Region handling for wxWidgets/DFB | |
4 | // Author: Vaclav Slavik | |
5 | // Created: 2006-08-08 | |
6 | // RCS-ID: $Id$ | |
7 | // Copyright: (c) 2006 REA Elektronik GmbH | |
8 | // Licence: wxWindows licence | |
9 | ///////////////////////////////////////////////////////////////////////////// | |
10 | ||
11 | // For compilers that support precompilation, includes "wx.h". | |
12 | #include "wx/wxprec.h" | |
13 | ||
14 | #ifdef __BORLANDC__ | |
15 | #pragma hdrstop | |
16 | #endif | |
17 | ||
18 | #include "wx/region.h" | |
19 | ||
20 | IMPLEMENT_DYNAMIC_CLASS(wxRegion, wxGDIObject) | |
21 | IMPLEMENT_DYNAMIC_CLASS(wxRegionIterator, wxObject) | |
22 | ||
23 | //----------------------------------------------------------------------------- | |
24 | // wxRegionRefData | |
25 | //----------------------------------------------------------------------------- | |
26 | ||
27 | class WXDLLEXPORT wxRegionRefData : public wxGDIRefData | |
28 | { | |
29 | public: | |
30 | wxRegionRefData() {} | |
31 | wxRegionRefData(const wxRect& rect) : m_rect(rect) {} | |
32 | wxRegionRefData(const wxRegionRefData& data) : m_rect(data.m_rect) {} | |
33 | ||
34 | ~wxRegionRefData() {} | |
35 | ||
36 | wxRect m_rect; | |
37 | }; | |
38 | ||
39 | #define M_REGION_OF(r) ((wxRegionRefData*)((r).m_refData)) | |
40 | #define M_REGION M_REGION_OF(*this) | |
41 | ||
42 | //----------------------------------------------------------------------------- | |
43 | // wxRegion | |
44 | //----------------------------------------------------------------------------- | |
45 | ||
46 | wxObjectRefData *wxRegion::CreateRefData() const | |
47 | { | |
48 | return new wxRegionRefData; | |
49 | } | |
50 | ||
51 | wxObjectRefData *wxRegion::CloneRefData(const wxObjectRefData *data) const | |
52 | { | |
53 | return new wxRegionRefData(*(wxRegionRefData *)data); | |
54 | } | |
55 | ||
56 | wxRegion::wxRegion() | |
57 | { | |
58 | m_refData = NULL; | |
59 | } | |
60 | ||
61 | wxRegion::wxRegion(wxCoord x, wxCoord y, wxCoord w, wxCoord h) | |
62 | { | |
63 | m_refData = new wxRegionRefData(wxRect(x, y, w, h)); | |
64 | } | |
65 | ||
66 | wxRegion::wxRegion(const wxPoint& topLeft, const wxPoint& bottomRight) | |
67 | { | |
68 | m_refData = new wxRegionRefData(wxRect(topLeft, bottomRight)); | |
69 | } | |
70 | ||
71 | wxRegion::wxRegion(const wxRect& r) | |
72 | { | |
73 | m_refData = new wxRegionRefData(r); | |
74 | } | |
75 | ||
76 | wxRegion::~wxRegion() | |
77 | { | |
78 | // m_refData unrefed in ~wxObject | |
79 | } | |
80 | ||
81 | bool wxRegion::operator==(const wxRegion& region) const | |
82 | { | |
83 | if ( m_refData != region.m_refData ) | |
84 | return false; | |
85 | ||
86 | if ( !Ok() ) | |
87 | return true; // both invalid | |
88 | ||
89 | return M_REGION->m_rect == M_REGION_OF(region)->m_rect; | |
90 | } | |
91 | ||
92 | //----------------------------------------------------------------------------- | |
93 | // Information about the region | |
94 | //----------------------------------------------------------------------------- | |
95 | ||
96 | void wxRegion::GetBox(wxCoord& x, wxCoord& y, wxCoord&w, wxCoord &h) const | |
97 | { | |
98 | wxRect r = GetBox(); | |
99 | x = r.GetX(); | |
100 | y = r.GetY(); | |
101 | w = r.GetWidth(); | |
102 | h = r.GetHeight(); | |
103 | } | |
104 | ||
105 | wxRect wxRegion::GetBox() const | |
106 | { | |
107 | if (m_refData) | |
108 | return M_REGION->m_rect; | |
109 | else | |
110 | return wxRect(); | |
111 | } | |
112 | ||
113 | bool wxRegion::Empty() const | |
114 | { | |
115 | if (!m_refData) | |
116 | return true; | |
117 | ||
118 | return M_REGION->m_rect.IsEmpty(); | |
119 | } | |
120 | ||
121 | //----------------------------------------------------------------------------- | |
122 | // Modifications | |
123 | //----------------------------------------------------------------------------- | |
124 | ||
125 | void wxRegion::Clear() | |
126 | { | |
127 | UnRef(); | |
128 | } | |
129 | ||
130 | bool wxRegion::Offset(wxCoord x, wxCoord y) | |
131 | { | |
132 | AllocExclusive(); | |
133 | M_REGION->m_rect.Offset(x, y); | |
134 | return true; | |
135 | } | |
136 | ||
137 | bool wxRegion::Union(const wxRect& rect) | |
138 | { | |
139 | AllocExclusive(); | |
140 | ||
141 | if ( M_REGION->m_rect.Inside(rect) ) | |
142 | { | |
143 | return true; | |
144 | } | |
145 | else if ( rect.Inside(M_REGION->m_rect) ) | |
146 | { | |
147 | M_REGION->m_rect = rect; | |
148 | return true; | |
149 | } | |
150 | else | |
151 | { | |
152 | wxFAIL_MSG( _T("only rectangular regions are supported") ); | |
153 | return false; | |
154 | } | |
155 | } | |
156 | ||
157 | bool wxRegion::Union(const wxRegion& region) | |
158 | { | |
159 | wxCHECK_MSG( region.Ok(), false, _T("invalid region") ); | |
160 | return Union(M_REGION_OF(region)->m_rect); | |
161 | } | |
162 | ||
163 | bool wxRegion::Intersect(const wxRect& rect) | |
164 | { | |
165 | AllocExclusive(); | |
166 | M_REGION->m_rect.Intersect(rect); | |
167 | return true; | |
168 | } | |
169 | ||
170 | bool wxRegion::Intersect(const wxRegion& region) | |
171 | { | |
172 | wxCHECK_MSG( region.Ok(), false, _T("invalid region") ); | |
173 | return Intersect(M_REGION_OF(region)->m_rect); | |
174 | } | |
175 | ||
176 | bool wxRegion::Subtract(const wxRect& rect) | |
177 | { | |
178 | wxCHECK_MSG( Ok(), false, _T("invalid region") ); | |
179 | ||
180 | if ( rect.Inside(M_REGION->m_rect) ) | |
181 | { | |
182 | // subtracted rectangle contains this one, so the result is empty | |
183 | // rectangle | |
184 | M_REGION->m_rect = wxRect(); | |
185 | return true; | |
186 | } | |
187 | else if ( !M_REGION->m_rect.Intersects(rect) ) | |
188 | { | |
189 | // the rectangles are disjoint, so substracting has no effect | |
190 | return true; | |
191 | } | |
192 | else | |
193 | { | |
194 | wxFAIL_MSG( _T("only rectangular regions implemented") ); | |
195 | return false; | |
196 | } | |
197 | } | |
198 | ||
199 | bool wxRegion::Subtract(const wxRegion& region) | |
200 | { | |
201 | wxCHECK_MSG( region.Ok(), false, _T("invalid region") ); | |
202 | return Subtract(M_REGION_OF(region)->m_rect); | |
203 | } | |
204 | ||
205 | bool wxRegion::Xor(const wxRect& rect) | |
206 | { | |
207 | wxFAIL_MSG( _T("Xor not implemented") ); | |
208 | return false; | |
209 | } | |
210 | ||
211 | bool wxRegion::Xor(const wxRegion& region) | |
212 | { | |
213 | wxCHECK_MSG( region.Ok(), false, _T("invalid region") ); | |
214 | return Xor(M_REGION_OF(region)->m_rect); | |
215 | } | |
216 | ||
217 | ||
218 | //----------------------------------------------------------------------------- | |
219 | // Tests | |
220 | //----------------------------------------------------------------------------- | |
221 | ||
222 | wxRegionContain wxRegion::Contains(wxCoord x, wxCoord y) const | |
223 | { | |
224 | wxCHECK_MSG( Ok(), wxOutRegion, _T("invalid region") ); | |
225 | ||
226 | if (M_REGION->m_rect.Inside(x, y)) | |
227 | return wxInRegion; | |
228 | else | |
229 | return wxOutRegion; | |
230 | } | |
231 | ||
232 | wxRegionContain wxRegion::Contains(const wxRect& rect) const | |
233 | { | |
234 | wxCHECK_MSG( Ok(), wxOutRegion, _T("invalid region") ); | |
235 | ||
236 | // 1) is the rectangle entirely covered by the region? | |
237 | if (M_REGION->m_rect.Inside(rect)) | |
238 | return wxInRegion; | |
239 | ||
240 | // 2) is the rectangle completely outside the region? | |
241 | if (!M_REGION->m_rect.Intersects(rect)) | |
242 | return wxOutRegion; | |
243 | ||
244 | // 3) neither case happened => it is partially covered: | |
245 | return wxPartRegion; | |
246 | } | |
247 | ||
248 | //----------------------------------------------------------------------------- | |
249 | // wxRegionIterator | |
250 | //----------------------------------------------------------------------------- | |
251 | ||
252 | void wxRegionIterator::Reset(const wxRegion& region) | |
253 | { | |
254 | wxRegionRefData *d = M_REGION_OF(region); | |
255 | m_rect = d ? d->m_rect : wxRect(); | |
256 | } | |
257 | ||
258 | wxRegionIterator& wxRegionIterator::operator++() | |
259 | { | |
260 | // there's only one rectangle in the iterator, so iterating always | |
261 | // reaches the end: | |
262 | Reset(); | |
263 | return *this; | |
264 | } | |
265 | ||
266 | wxRegionIterator wxRegionIterator::operator++(int) | |
267 | { | |
268 | wxRegionIterator tmp = *this; | |
269 | ||
270 | // there's only one rectangle in the iterator, so iterating always | |
271 | // reaches the end: | |
272 | Reset(); | |
273 | ||
274 | return tmp; | |
275 | } |