Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <basegfx/polygon/b2dpolypolygon.hxx>
21 : #include <osl/diagnose.h>
22 : #include <basegfx/polygon/b2dpolygon.hxx>
23 : #include <basegfx/polygon/b2dpolypolygontools.hxx>
24 : #include <rtl/instance.hxx>
25 : #include <basegfx/matrix/b2dhommatrix.hxx>
26 :
27 : #include <functional>
28 : #include <algorithm>
29 :
30 12925346 : class ImplB2DPolyPolygon
31 : {
32 : basegfx::B2DPolygonVector maPolygons;
33 :
34 : public:
35 125 : ImplB2DPolyPolygon() : maPolygons()
36 : {
37 125 : }
38 :
39 3889222 : explicit ImplB2DPolyPolygon(const basegfx::B2DPolygon& rToBeCopied) :
40 3889222 : maPolygons(1,rToBeCopied)
41 : {
42 3889222 : }
43 :
44 70701 : bool operator==(const ImplB2DPolyPolygon& rPolygonList) const
45 : {
46 : // same polygon count?
47 70701 : if(maPolygons.size() != rPolygonList.maPolygons.size())
48 41349 : return false;
49 :
50 : // compare polygon content
51 29352 : if(!(maPolygons == rPolygonList.maPolygons))
52 10007 : return false;
53 :
54 19345 : return true;
55 : }
56 :
57 12263258 : const basegfx::B2DPolygon& getB2DPolygon(sal_uInt32 nIndex) const
58 : {
59 12263258 : return maPolygons[nIndex];
60 : }
61 :
62 7087 : void setB2DPolygon(sal_uInt32 nIndex, const basegfx::B2DPolygon& rPolygon)
63 : {
64 7087 : maPolygons[nIndex] = rPolygon;
65 7087 : }
66 :
67 431354 : void insert(sal_uInt32 nIndex, const basegfx::B2DPolygon& rPolygon, sal_uInt32 nCount)
68 : {
69 431354 : if(nCount)
70 : {
71 : // add nCount copies of rPolygon
72 431354 : basegfx::B2DPolygonVector::iterator aIndex(maPolygons.begin());
73 431354 : if( nIndex )
74 235874 : aIndex += nIndex;
75 431354 : maPolygons.insert(aIndex, nCount, rPolygon);
76 : }
77 431354 : }
78 :
79 16564 : void insert(sal_uInt32 nIndex, const basegfx::B2DPolyPolygon& rPolyPolygon)
80 : {
81 : // add nCount polygons from rPolyPolygon
82 16564 : basegfx::B2DPolygonVector::iterator aIndex(maPolygons.begin());
83 16564 : if( nIndex )
84 12966 : aIndex += nIndex;
85 16564 : maPolygons.insert(aIndex, rPolyPolygon.begin(), rPolyPolygon.end());
86 16564 : }
87 :
88 191 : void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
89 : {
90 191 : if(nCount)
91 : {
92 : // remove polygon data
93 191 : basegfx::B2DPolygonVector::iterator aStart(maPolygons.begin());
94 191 : aStart += nIndex;
95 191 : const basegfx::B2DPolygonVector::iterator aEnd(aStart + nCount);
96 :
97 191 : maPolygons.erase(aStart, aEnd);
98 : }
99 191 : }
100 :
101 17954494 : sal_uInt32 count() const
102 : {
103 17954494 : return maPolygons.size();
104 : }
105 :
106 3491 : void setClosed(bool bNew)
107 : {
108 21667 : for(size_t a(0L); a < maPolygons.size(); a++)
109 : {
110 18176 : maPolygons[a].setClosed(bNew);
111 : }
112 3491 : }
113 :
114 31 : void flip()
115 : {
116 : std::for_each( maPolygons.begin(),
117 : maPolygons.end(),
118 31 : std::mem_fun_ref( &basegfx::B2DPolygon::flip ));
119 31 : }
120 :
121 614 : void removeDoublePoints()
122 : {
123 : std::for_each( maPolygons.begin(),
124 : maPolygons.end(),
125 614 : std::mem_fun_ref( &basegfx::B2DPolygon::removeDoublePoints ));
126 614 : }
127 :
128 461830 : void transform(const basegfx::B2DHomMatrix& rMatrix)
129 : {
130 1129072 : for(size_t a(0L); a < maPolygons.size(); a++)
131 : {
132 667242 : maPolygons[a].transform(rMatrix);
133 : }
134 461830 : }
135 :
136 74 : void makeUnique()
137 : {
138 : std::for_each( maPolygons.begin(),
139 : maPolygons.end(),
140 74 : std::mem_fun_ref( &basegfx::B2DPolygon::makeUnique ));
141 74 : }
142 :
143 16564 : const basegfx::B2DPolygon* begin() const
144 : {
145 16564 : if(maPolygons.empty())
146 0 : return 0;
147 : else
148 16564 : return &maPolygons.front();
149 : }
150 :
151 16564 : const basegfx::B2DPolygon* end() const
152 : {
153 16564 : if(maPolygons.empty())
154 0 : return 0;
155 : else
156 16564 : return (&maPolygons.back())+1;
157 : }
158 :
159 53 : basegfx::B2DPolygon* begin()
160 : {
161 53 : if(maPolygons.empty())
162 0 : return 0;
163 : else
164 53 : return &maPolygons.front();
165 : }
166 :
167 53 : basegfx::B2DPolygon* end()
168 : {
169 53 : if(maPolygons.empty())
170 0 : return 0;
171 : else
172 53 : return &(maPolygons.back())+1;
173 : }
174 : };
175 :
176 : namespace basegfx
177 : {
178 : namespace { struct DefaultPolyPolygon: public rtl::Static<B2DPolyPolygon::ImplType,
179 : DefaultPolyPolygon> {}; }
180 :
181 657631 : B2DPolyPolygon::B2DPolyPolygon() :
182 657631 : mpPolyPolygon(DefaultPolyPolygon::get())
183 : {
184 657631 : }
185 :
186 4573156 : B2DPolyPolygon::B2DPolyPolygon(const B2DPolyPolygon& rPolyPolygon) :
187 4573156 : mpPolyPolygon(rPolyPolygon.mpPolyPolygon)
188 : {
189 4573156 : }
190 :
191 3889222 : B2DPolyPolygon::B2DPolyPolygon(const B2DPolygon& rPolygon) :
192 3889222 : mpPolyPolygon( ImplB2DPolyPolygon(rPolygon) )
193 : {
194 3889222 : }
195 :
196 9115140 : B2DPolyPolygon::~B2DPolyPolygon()
197 : {
198 9115140 : }
199 :
200 125485 : B2DPolyPolygon& B2DPolyPolygon::operator=(const B2DPolyPolygon& rPolyPolygon)
201 : {
202 125485 : mpPolyPolygon = rPolyPolygon.mpPolyPolygon;
203 125485 : return *this;
204 : }
205 :
206 74 : void B2DPolyPolygon::makeUnique()
207 : {
208 74 : mpPolyPolygon.make_unique();
209 74 : mpPolyPolygon->makeUnique();
210 74 : }
211 :
212 77786 : bool B2DPolyPolygon::operator==(const B2DPolyPolygon& rPolyPolygon) const
213 : {
214 77786 : if(mpPolyPolygon.same_object(rPolyPolygon.mpPolyPolygon))
215 7085 : return true;
216 :
217 70701 : return ((*mpPolyPolygon) == (*rPolyPolygon.mpPolyPolygon));
218 : }
219 :
220 47768 : bool B2DPolyPolygon::operator!=(const B2DPolyPolygon& rPolyPolygon) const
221 : {
222 47768 : return !((*this) == rPolyPolygon);
223 : }
224 :
225 9357291 : sal_uInt32 B2DPolyPolygon::count() const
226 : {
227 9357291 : return mpPolyPolygon->count();
228 : }
229 :
230 8414015 : B2DPolygon B2DPolyPolygon::getB2DPolygon(sal_uInt32 nIndex) const
231 : {
232 : OSL_ENSURE(nIndex < mpPolyPolygon->count(), "B2DPolyPolygon access outside range (!)");
233 :
234 8414015 : return mpPolyPolygon->getB2DPolygon(nIndex);
235 : }
236 :
237 7089 : void B2DPolyPolygon::setB2DPolygon(sal_uInt32 nIndex, const B2DPolygon& rPolygon)
238 : {
239 : OSL_ENSURE(nIndex < mpPolyPolygon->count(), "B2DPolyPolygon access outside range (!)");
240 :
241 7089 : if(getB2DPolygon(nIndex) != rPolygon)
242 7087 : mpPolyPolygon->setB2DPolygon(nIndex, rPolygon);
243 7089 : }
244 :
245 3637612 : bool B2DPolyPolygon::areControlPointsUsed() const
246 : {
247 7363325 : for(sal_uInt32 a(0L); a < mpPolyPolygon->count(); a++)
248 : {
249 3732232 : const B2DPolygon& rPolygon = mpPolyPolygon->getB2DPolygon(a);
250 :
251 3732232 : if(rPolygon.areControlPointsUsed())
252 : {
253 6519 : return true;
254 : }
255 : }
256 :
257 3631093 : return false;
258 : }
259 :
260 0 : void B2DPolyPolygon::insert(sal_uInt32 nIndex, const B2DPolygon& rPolygon, sal_uInt32 nCount)
261 : {
262 : OSL_ENSURE(nIndex <= mpPolyPolygon->count(), "B2DPolyPolygon Insert outside range (!)");
263 :
264 0 : if(nCount)
265 0 : mpPolyPolygon->insert(nIndex, rPolygon, nCount);
266 0 : }
267 :
268 431354 : void B2DPolyPolygon::append(const B2DPolygon& rPolygon, sal_uInt32 nCount)
269 : {
270 431354 : if(nCount)
271 431354 : mpPolyPolygon->insert(mpPolyPolygon->count(), rPolygon, nCount);
272 431354 : }
273 :
274 0 : B2DPolyPolygon B2DPolyPolygon::getDefaultAdaptiveSubdivision() const
275 : {
276 0 : B2DPolyPolygon aRetval;
277 :
278 0 : for(sal_uInt32 a(0L); a < mpPolyPolygon->count(); a++)
279 : {
280 0 : aRetval.append(mpPolyPolygon->getB2DPolygon(a).getDefaultAdaptiveSubdivision());
281 : }
282 :
283 0 : return aRetval;
284 : }
285 :
286 65101 : B2DRange B2DPolyPolygon::getB2DRange() const
287 : {
288 65101 : B2DRange aRetval;
289 :
290 137370 : for(sal_uInt32 a(0L); a < mpPolyPolygon->count(); a++)
291 : {
292 72269 : aRetval.expand(mpPolyPolygon->getB2DPolygon(a).getB2DRange());
293 : }
294 :
295 65101 : return aRetval;
296 : }
297 :
298 20 : void B2DPolyPolygon::insert(sal_uInt32 nIndex, const B2DPolyPolygon& rPolyPolygon)
299 : {
300 : OSL_ENSURE(nIndex <= mpPolyPolygon->count(), "B2DPolyPolygon Insert outside range (!)");
301 :
302 20 : if(rPolyPolygon.count())
303 20 : mpPolyPolygon->insert(nIndex, rPolyPolygon);
304 20 : }
305 :
306 16609 : void B2DPolyPolygon::append(const B2DPolyPolygon& rPolyPolygon)
307 : {
308 16609 : if(rPolyPolygon.count())
309 16544 : mpPolyPolygon->insert(mpPolyPolygon->count(), rPolyPolygon);
310 16609 : }
311 :
312 191 : void B2DPolyPolygon::remove(sal_uInt32 nIndex, sal_uInt32 nCount)
313 : {
314 : OSL_ENSURE(nIndex + nCount <= mpPolyPolygon->count(), "B2DPolyPolygon Remove outside range (!)");
315 :
316 191 : if(nCount)
317 191 : mpPolyPolygon->remove(nIndex, nCount);
318 191 : }
319 :
320 10304 : void B2DPolyPolygon::clear()
321 : {
322 10304 : mpPolyPolygon = DefaultPolyPolygon::get();
323 10304 : }
324 :
325 25759 : bool B2DPolyPolygon::isClosed() const
326 : {
327 25759 : bool bRetval(true);
328 :
329 : // PolyPOlygon is closed when all contained Polygons are closed or
330 : // no Polygon exists.
331 63984 : for(sal_uInt32 a(0L); bRetval && a < mpPolyPolygon->count(); a++)
332 : {
333 38225 : if(!(mpPolyPolygon->getB2DPolygon(a)).isClosed())
334 : {
335 10101 : bRetval = false;
336 : }
337 : }
338 :
339 25759 : return bRetval;
340 : }
341 :
342 4931 : void B2DPolyPolygon::setClosed(bool bNew)
343 : {
344 4931 : if(bNew != isClosed())
345 3491 : mpPolyPolygon->setClosed(bNew);
346 4931 : }
347 :
348 31 : void B2DPolyPolygon::flip()
349 : {
350 31 : if(mpPolyPolygon->count())
351 : {
352 31 : mpPolyPolygon->flip();
353 : }
354 31 : }
355 :
356 5799 : bool B2DPolyPolygon::hasDoublePoints() const
357 : {
358 5799 : bool bRetval(false);
359 :
360 12316 : for(sal_uInt32 a(0L); !bRetval && a < mpPolyPolygon->count(); a++)
361 : {
362 6517 : if((mpPolyPolygon->getB2DPolygon(a)).hasDoublePoints())
363 : {
364 614 : bRetval = true;
365 : }
366 : }
367 :
368 5799 : return bRetval;
369 : }
370 :
371 5799 : void B2DPolyPolygon::removeDoublePoints()
372 : {
373 5799 : if(hasDoublePoints())
374 614 : mpPolyPolygon->removeDoublePoints();
375 5799 : }
376 :
377 582994 : void B2DPolyPolygon::transform(const B2DHomMatrix& rMatrix)
378 : {
379 582994 : if(mpPolyPolygon->count() && !rMatrix.isIdentity())
380 : {
381 461830 : mpPolyPolygon->transform(rMatrix);
382 : }
383 582994 : }
384 :
385 16564 : const B2DPolygon* B2DPolyPolygon::begin() const
386 : {
387 16564 : return mpPolyPolygon->begin();
388 : }
389 :
390 16564 : const B2DPolygon* B2DPolyPolygon::end() const
391 : {
392 16564 : return mpPolyPolygon->end();
393 : }
394 :
395 53 : B2DPolygon* B2DPolyPolygon::begin()
396 : {
397 53 : return mpPolyPolygon->begin();
398 : }
399 :
400 53 : B2DPolygon* B2DPolyPolygon::end()
401 : {
402 53 : return mpPolyPolygon->end();
403 : }
404 : } // end of namespace basegfx
405 :
406 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|