1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_basegfx.hxx"
26 #include <basegfx/range/b2dpolyrange.hxx>
27
28 #include <basegfx/range/b2drange.hxx>
29 #include <basegfx/range/b2drangeclipper.hxx>
30 #include <basegfx/tuple/b2dtuple.hxx>
31 #include <basegfx/polygon/b2dpolypolygon.hxx>
32
33 #include <boost/bind.hpp>
34 #include <boost/tuple/tuple.hpp>
35 #include <algorithm>
36 #include <vector>
37
flipOrientation(basegfx::B2VectorOrientation eOrient)38 static basegfx::B2VectorOrientation flipOrientation(
39 basegfx::B2VectorOrientation eOrient)
40 {
41 return eOrient == basegfx::ORIENTATION_POSITIVE ?
42 basegfx::ORIENTATION_NEGATIVE : basegfx::ORIENTATION_POSITIVE;
43 }
44
45 namespace basegfx
46 {
47 class ImplB2DPolyRange
48 {
updateBounds()49 void updateBounds()
50 {
51 maBounds.reset();
52 std::for_each(maRanges.begin(),
53 maRanges.end(),
54 boost::bind(
55 (void (B2DRange::*)(const B2DRange&))(
56 &B2DRange::expand),
57 boost::ref(maBounds),
58 _1));
59 }
60
61 public:
ImplB2DPolyRange()62 ImplB2DPolyRange() :
63 maBounds(),
64 maRanges(),
65 maOrient()
66 {}
67
ImplB2DPolyRange(const B2DPolyRange::ElementType & rElem)68 explicit ImplB2DPolyRange( const B2DPolyRange::ElementType& rElem ) :
69 maBounds( boost::get<0>(rElem) ),
70 maRanges( 1, boost::get<0>(rElem) ),
71 maOrient( 1, boost::get<1>(rElem) )
72 {}
73
ImplB2DPolyRange(const B2DRange & rRange,B2VectorOrientation eOrient)74 explicit ImplB2DPolyRange( const B2DRange& rRange, B2VectorOrientation eOrient ) :
75 maBounds( rRange ),
76 maRanges( 1, rRange ),
77 maOrient( 1, eOrient )
78 {}
79
operator ==(const ImplB2DPolyRange & rRHS) const80 bool operator==(const ImplB2DPolyRange& rRHS) const
81 {
82 return maRanges == rRHS.maRanges && maOrient == rRHS.maOrient;
83 }
84
count() const85 sal_uInt32 count() const
86 {
87 return maRanges.size();
88 }
89
getElement(sal_uInt32 nIndex) const90 B2DPolyRange::ElementType getElement(sal_uInt32 nIndex) const
91 {
92 return boost::make_tuple(maRanges[nIndex],
93 maOrient[nIndex]);
94 }
95
setElement(sal_uInt32 nIndex,const B2DPolyRange::ElementType & rElement)96 void setElement(sal_uInt32 nIndex, const B2DPolyRange::ElementType& rElement )
97 {
98 maRanges[nIndex] = boost::get<0>(rElement);
99 maOrient[nIndex] = boost::get<1>(rElement);
100 updateBounds();
101 }
102
setElement(sal_uInt32 nIndex,const B2DRange & rRange,B2VectorOrientation eOrient)103 void setElement(sal_uInt32 nIndex, const B2DRange& rRange, B2VectorOrientation eOrient )
104 {
105 maRanges[nIndex] = rRange;
106 maOrient[nIndex] = eOrient;
107 updateBounds();
108 }
109
insertElement(sal_uInt32 nIndex,const B2DPolyRange::ElementType & rElement,sal_uInt32 nCount)110 void insertElement(sal_uInt32 nIndex, const B2DPolyRange::ElementType& rElement, sal_uInt32 nCount)
111 {
112 maRanges.insert(maRanges.begin()+nIndex, nCount, boost::get<0>(rElement));
113 maOrient.insert(maOrient.begin()+nIndex, nCount, boost::get<1>(rElement));
114 maBounds.expand(boost::get<0>(rElement));
115 }
116
insertElement(sal_uInt32 nIndex,const B2DRange & rRange,B2VectorOrientation eOrient,sal_uInt32 nCount)117 void insertElement(sal_uInt32 nIndex, const B2DRange& rRange, B2VectorOrientation eOrient, sal_uInt32 nCount)
118 {
119 maRanges.insert(maRanges.begin()+nIndex, nCount, rRange);
120 maOrient.insert(maOrient.begin()+nIndex, nCount, eOrient);
121 maBounds.expand(rRange);
122 }
123
appendElement(const B2DPolyRange::ElementType & rElement,sal_uInt32 nCount)124 void appendElement(const B2DPolyRange::ElementType& rElement, sal_uInt32 nCount)
125 {
126 maRanges.insert(maRanges.end(), nCount, boost::get<0>(rElement));
127 maOrient.insert(maOrient.end(), nCount, boost::get<1>(rElement));
128 maBounds.expand(boost::get<0>(rElement));
129 }
130
appendElement(const B2DRange & rRange,B2VectorOrientation eOrient,sal_uInt32 nCount)131 void appendElement(const B2DRange& rRange, B2VectorOrientation eOrient, sal_uInt32 nCount)
132 {
133 maRanges.insert(maRanges.end(), nCount, rRange);
134 maOrient.insert(maOrient.end(), nCount, eOrient);
135 maBounds.expand(rRange);
136 }
137
insertPolyRange(sal_uInt32 nIndex,const ImplB2DPolyRange & rPolyRange)138 void insertPolyRange(sal_uInt32 nIndex, const ImplB2DPolyRange& rPolyRange)
139 {
140 maRanges.insert(maRanges.begin()+nIndex, rPolyRange.maRanges.begin(), rPolyRange.maRanges.end());
141 maOrient.insert(maOrient.begin()+nIndex, rPolyRange.maOrient.begin(), rPolyRange.maOrient.end());
142 updateBounds();
143 }
144
appendPolyRange(const ImplB2DPolyRange & rPolyRange)145 void appendPolyRange(const ImplB2DPolyRange& rPolyRange)
146 {
147 maRanges.insert(maRanges.end(),
148 rPolyRange.maRanges.begin(),
149 rPolyRange.maRanges.end());
150 maOrient.insert(maOrient.end(),
151 rPolyRange.maOrient.begin(),
152 rPolyRange.maOrient.end());
153 updateBounds();
154 }
155
remove(sal_uInt32 nIndex,sal_uInt32 nCount)156 void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
157 {
158 maRanges.erase(maRanges.begin()+nIndex,maRanges.begin()+nIndex+nCount);
159 maOrient.erase(maOrient.begin()+nIndex,maOrient.begin()+nIndex+nCount);
160 updateBounds();
161 }
162
clear()163 void clear()
164 {
165 std::vector<B2DRange> aTmpRanges;
166 std::vector<B2VectorOrientation> aTmpOrient;
167
168 maRanges.swap(aTmpRanges);
169 maOrient.swap(aTmpOrient);
170
171 maBounds.reset();
172 }
173
flip()174 void flip()
175 {
176 std::for_each(maOrient.begin(),
177 maOrient.end(),
178 boost::bind(
179 &flipOrientation,
180 _1));
181 }
182
getBounds() const183 B2DRange getBounds() const
184 {
185 return maBounds;
186 }
187
isInside(const ValueType & rValue) const188 template< typename ValueType > bool isInside( const ValueType& rValue ) const
189 {
190 if( !maBounds.isInside( rValue ) )
191 return false;
192
193 // cannot use boost::bind here, since isInside is overloaded.
194 // It is currently not possible to resolve the overload
195 // by considering one of the other template arguments.
196 std::vector<B2DRange>::const_iterator aCurr( maRanges.begin() );
197 const std::vector<B2DRange>::const_iterator aEnd ( maRanges.end() );
198 while( aCurr != aEnd )
199 if( aCurr->isInside( rValue ) )
200 return true;
201
202 return false;
203 }
204
overlaps(const B2DRange & rRange) const205 bool overlaps( const B2DRange& rRange ) const
206 {
207 if( !maBounds.overlaps( rRange ) )
208 return false;
209
210 const std::vector<B2DRange>::const_iterator aEnd( maRanges.end() );
211 return std::find_if( maRanges.begin(),
212 aEnd,
213 boost::bind<bool>( boost::mem_fn( &B2DRange::overlaps ),
214 _1,
215 boost::cref(rRange) ) ) != aEnd;
216 }
217
solveCrossovers() const218 B2DPolyPolygon solveCrossovers() const
219 {
220 return tools::solveCrossovers(maRanges,maOrient);
221 }
222
begin() const223 const B2DRange* begin() const
224 {
225 if(maRanges.empty())
226 return 0;
227 else
228 return &maRanges.front();
229 }
230
end() const231 const B2DRange* end() const
232 {
233 if(maRanges.empty())
234 return 0;
235 else
236 return (&maRanges.back())+1;
237 }
238
begin()239 B2DRange* begin()
240 {
241 if(maRanges.empty())
242 return 0;
243 else
244 return &maRanges.front();
245 }
246
end()247 B2DRange* end()
248 {
249 if(maRanges.empty())
250 return 0;
251 else
252 return (&maRanges.back())+1;
253 }
254
255 private:
256 B2DRange maBounds;
257 std::vector<B2DRange> maRanges;
258 std::vector<B2VectorOrientation> maOrient;
259 };
260
B2DPolyRange()261 B2DPolyRange::B2DPolyRange() :
262 mpImpl()
263 {}
264
~B2DPolyRange()265 B2DPolyRange::~B2DPolyRange()
266 {}
267
B2DPolyRange(const ElementType & rElem)268 B2DPolyRange::B2DPolyRange( const ElementType& rElem ) :
269 mpImpl( ImplB2DPolyRange( rElem ) )
270 {}
271
B2DPolyRange(const B2DRange & rRange,B2VectorOrientation eOrient)272 B2DPolyRange::B2DPolyRange( const B2DRange& rRange, B2VectorOrientation eOrient ) :
273 mpImpl( ImplB2DPolyRange( rRange, eOrient ) )
274 {}
275
B2DPolyRange(const B2DPolyRange & rRange)276 B2DPolyRange::B2DPolyRange( const B2DPolyRange& rRange ) :
277 mpImpl( rRange.mpImpl )
278 {}
279
operator =(const B2DPolyRange & rRange)280 B2DPolyRange& B2DPolyRange::operator=( const B2DPolyRange& rRange )
281 {
282 mpImpl = rRange.mpImpl;
283 return *this;
284 }
285
makeUnique()286 void B2DPolyRange::makeUnique()
287 {
288 mpImpl.make_unique();
289 }
290
operator ==(const B2DPolyRange & rRange) const291 bool B2DPolyRange::operator==(const B2DPolyRange& rRange) const
292 {
293 if(mpImpl.same_object(rRange.mpImpl))
294 return true;
295
296 return ((*mpImpl) == (*rRange.mpImpl));
297 }
298
operator !=(const B2DPolyRange & rRange) const299 bool B2DPolyRange::operator!=(const B2DPolyRange& rRange) const
300 {
301 return !(*this == rRange);
302 }
303
count() const304 sal_uInt32 B2DPolyRange::count() const
305 {
306 return mpImpl->count();
307 }
308
getElement(sal_uInt32 nIndex) const309 B2DPolyRange::ElementType B2DPolyRange::getElement(sal_uInt32 nIndex) const
310 {
311 return mpImpl->getElement(nIndex);
312 }
313
setElement(sal_uInt32 nIndex,const ElementType & rElement)314 void B2DPolyRange::setElement(sal_uInt32 nIndex, const ElementType& rElement )
315 {
316 mpImpl->setElement(nIndex, rElement);
317 }
318
setElement(sal_uInt32 nIndex,const B2DRange & rRange,B2VectorOrientation eOrient)319 void B2DPolyRange::setElement(sal_uInt32 nIndex, const B2DRange& rRange, B2VectorOrientation eOrient )
320 {
321 mpImpl->setElement(nIndex, rRange, eOrient );
322 }
323
insertElement(sal_uInt32 nIndex,const ElementType & rElement,sal_uInt32 nCount)324 void B2DPolyRange::insertElement(sal_uInt32 nIndex, const ElementType& rElement, sal_uInt32 nCount)
325 {
326 mpImpl->insertElement(nIndex, rElement, nCount );
327 }
328
insertElement(sal_uInt32 nIndex,const B2DRange & rRange,B2VectorOrientation eOrient,sal_uInt32 nCount)329 void B2DPolyRange::insertElement(sal_uInt32 nIndex, const B2DRange& rRange, B2VectorOrientation eOrient, sal_uInt32 nCount)
330 {
331 mpImpl->insertElement(nIndex, rRange, eOrient, nCount );
332 }
333
appendElement(const ElementType & rElement,sal_uInt32 nCount)334 void B2DPolyRange::appendElement(const ElementType& rElement, sal_uInt32 nCount)
335 {
336 mpImpl->appendElement(rElement, nCount);
337 }
338
appendElement(const B2DRange & rRange,B2VectorOrientation eOrient,sal_uInt32 nCount)339 void B2DPolyRange::appendElement(const B2DRange& rRange, B2VectorOrientation eOrient, sal_uInt32 nCount)
340 {
341 mpImpl->appendElement(rRange, eOrient, nCount );
342 }
343
insertPolyRange(sal_uInt32 nIndex,const B2DPolyRange & rRange)344 void B2DPolyRange::insertPolyRange(sal_uInt32 nIndex, const B2DPolyRange& rRange)
345 {
346 mpImpl->insertPolyRange(nIndex, *rRange.mpImpl);
347 }
348
appendPolyRange(const B2DPolyRange & rRange)349 void B2DPolyRange::appendPolyRange(const B2DPolyRange& rRange)
350 {
351 mpImpl->appendPolyRange(*rRange.mpImpl);
352 }
353
remove(sal_uInt32 nIndex,sal_uInt32 nCount)354 void B2DPolyRange::remove(sal_uInt32 nIndex, sal_uInt32 nCount)
355 {
356 mpImpl->remove(nIndex, nCount);
357 }
358
clear()359 void B2DPolyRange::clear()
360 {
361 mpImpl->clear();
362 }
363
flip()364 void B2DPolyRange::flip()
365 {
366 mpImpl->flip();
367 }
368
getBounds() const369 B2DRange B2DPolyRange::getBounds() const
370 {
371 return mpImpl->getBounds();
372 }
373
isInside(const B2DTuple & rTuple) const374 bool B2DPolyRange::isInside( const B2DTuple& rTuple ) const
375 {
376 return mpImpl->isInside(rTuple);
377 }
378
isInside(const B2DRange & rRange) const379 bool B2DPolyRange::isInside( const B2DRange& rRange ) const
380 {
381 return mpImpl->isInside(rRange);
382 }
383
overlaps(const B2DRange & rRange) const384 bool B2DPolyRange::overlaps( const B2DRange& rRange ) const
385 {
386 return mpImpl->overlaps(rRange);
387 }
388
solveCrossovers() const389 B2DPolyPolygon B2DPolyRange::solveCrossovers() const
390 {
391 return mpImpl->solveCrossovers();
392 }
393
begin() const394 const B2DRange* B2DPolyRange::begin() const
395 {
396 return mpImpl->begin();
397 }
398
end() const399 const B2DRange* B2DPolyRange::end() const
400 {
401 return mpImpl->end();
402 }
403
begin()404 B2DRange* B2DPolyRange::begin()
405 {
406 return mpImpl->begin();
407 }
408
end()409 B2DRange* B2DPolyRange::end()
410 {
411 return mpImpl->end();
412 }
413
414 } // end of namespace basegfx
415
416 // eof
417