]> git.saurik.com Git - wxWidgets.git/blob - src/dfb/region.cpp
Fix crash in wxDC::GetMultiLineTextExtent() after last commit.
[wxWidgets.git] / src / dfb / region.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/dfb/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 // default assignment and comparison operators are OK
37
38 wxRect m_rect;
39 };
40
41 #define M_REGION_OF(r) ((wxRegionRefData*)((r).m_refData))
42 #define M_REGION M_REGION_OF(*this)
43
44 //-----------------------------------------------------------------------------
45 // wxRegion
46 //-----------------------------------------------------------------------------
47
48 wxGDIRefData *wxRegion::CreateGDIRefData() const
49 {
50 return new wxRegionRefData;
51 }
52
53 wxGDIRefData *wxRegion::CloneGDIRefData(const wxGDIRefData *data) const
54 {
55 return new wxRegionRefData(*(wxRegionRefData *)data);
56 }
57
58 wxRegion::wxRegion()
59 {
60 m_refData = NULL;
61 }
62
63 wxRegion::wxRegion(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
64 {
65 m_refData = new wxRegionRefData(wxRect(x, y, w, h));
66 }
67
68 wxRegion::wxRegion(const wxPoint& topLeft, const wxPoint& bottomRight)
69 {
70 m_refData = new wxRegionRefData(wxRect(topLeft, bottomRight));
71 }
72
73 wxRegion::wxRegion(const wxRect& r)
74 {
75 m_refData = new wxRegionRefData(r);
76 }
77
78 wxRegion::~wxRegion()
79 {
80 // m_refData unrefed in ~wxObject
81 }
82
83 //-----------------------------------------------------------------------------
84 // Information about the region
85 //-----------------------------------------------------------------------------
86
87 bool wxRegion::DoIsEqual(const wxRegion& region) const
88 {
89 return M_REGION->m_rect == M_REGION_OF(region)->m_rect;
90 }
91
92 bool wxRegion::DoGetBox(wxCoord& x, wxCoord& y, wxCoord&w, wxCoord &h) const
93 {
94 if ( !m_refData )
95 return false;
96
97 const wxRect& r = M_REGION->m_rect;
98 x = r.GetX();
99 y = r.GetY();
100 w = r.GetWidth();
101 h = r.GetHeight();
102
103 return true;
104 }
105
106 bool wxRegion::IsEmpty() const
107 {
108 if (!m_refData)
109 return true;
110
111 return M_REGION->m_rect.IsEmpty();
112 }
113
114 //-----------------------------------------------------------------------------
115 // Modifications
116 //-----------------------------------------------------------------------------
117
118 void wxRegion::Clear()
119 {
120 UnRef();
121 }
122
123 bool wxRegion::DoOffset(wxCoord x, wxCoord y)
124 {
125 AllocExclusive();
126 M_REGION->m_rect.Offset(x, y);
127 return true;
128 }
129
130 bool wxRegion::DoUnionWithRect(const wxRect& rect)
131 {
132 AllocExclusive();
133
134 if ( M_REGION->m_rect.Contains(rect) )
135 {
136 return true;
137 }
138 else if ( rect.Contains(M_REGION->m_rect) )
139 {
140 M_REGION->m_rect = rect;
141 return true;
142 }
143 else
144 {
145 wxFAIL_MSG( "only rectangular regions are supported" );
146 return false;
147 }
148 }
149
150 bool wxRegion::DoUnionWithRegion(const wxRegion& region)
151 {
152 wxCHECK_MSG( region.IsOk(), false, "invalid region" );
153 return DoUnionWithRect(M_REGION_OF(region)->m_rect);
154 }
155
156 bool wxRegion::DoIntersect(const wxRegion& region)
157 {
158 wxCHECK_MSG( region.IsOk(), false, "invalid region" );
159
160 AllocExclusive();
161 M_REGION->m_rect.Intersect(M_REGION_OF(region)->m_rect);
162 return true;
163 }
164
165 bool wxRegion::DoSubtract(const wxRegion& region)
166 {
167 wxCHECK_MSG( region.IsOk(), false, "invalid region" );
168 wxCHECK_MSG( IsOk(), false, "invalid region" );
169
170 const wxRect& rect = M_REGION_OF(region)->m_rect;
171
172 if ( rect.Contains(M_REGION->m_rect) )
173 {
174 // subtracted rectangle contains this one, so the result is empty
175 // rectangle
176 M_REGION->m_rect = wxRect();
177 return true;
178 }
179 else if ( !M_REGION->m_rect.Intersects(rect) )
180 {
181 // the rectangles are disjoint, so subtracting has no effect
182 return true;
183 }
184 else
185 {
186 wxFAIL_MSG( "only rectangular regions implemented" );
187 return false;
188 }
189 }
190
191 bool wxRegion::DoXor(const wxRegion& region)
192 {
193 wxCHECK_MSG( region.IsOk(), false, "invalid region" );
194 wxFAIL_MSG( "Xor not implemented" );
195 return false;
196 }
197
198
199 //-----------------------------------------------------------------------------
200 // Tests
201 //-----------------------------------------------------------------------------
202
203 wxRegionContain wxRegion::DoContainsPoint(wxCoord x, wxCoord y) const
204 {
205 wxCHECK_MSG( IsOk(), wxOutRegion, "invalid region" );
206
207 if (M_REGION->m_rect.Contains(x, y))
208 return wxInRegion;
209 else
210 return wxOutRegion;
211 }
212
213 wxRegionContain wxRegion::DoContainsRect(const wxRect& rect) const
214 {
215 wxCHECK_MSG( IsOk(), wxOutRegion, "invalid region" );
216
217 // 1) is the rectangle entirely covered by the region?
218 if (M_REGION->m_rect.Contains(rect))
219 return wxInRegion;
220
221 // 2) is the rectangle completely outside the region?
222 if (!M_REGION->m_rect.Intersects(rect))
223 return wxOutRegion;
224
225 // 3) neither case happened => it is partially covered:
226 return wxPartRegion;
227 }
228
229 //-----------------------------------------------------------------------------
230 // wxRegionIterator
231 //-----------------------------------------------------------------------------
232
233 void wxRegionIterator::Reset(const wxRegion& region)
234 {
235 wxRegionRefData *d = M_REGION_OF(region);
236 m_rect = d ? d->m_rect : wxRect();
237 }
238
239 wxRegionIterator& wxRegionIterator::operator++()
240 {
241 // there's only one rectangle in the iterator, so iterating always
242 // reaches the end:
243 Reset();
244 return *this;
245 }
246
247 wxRegionIterator wxRegionIterator::operator++(int)
248 {
249 wxRegionIterator tmp = *this;
250
251 // there's only one rectangle in the iterator, so iterating always
252 // reaches the end:
253 Reset();
254
255 return tmp;
256 }