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 15275316 : class ImplB2DPolyPolygon
31 : {
32 : basegfx::B2DPolygonVector maPolygons;
33 :
34 : public:
35 188 : ImplB2DPolyPolygon() : maPolygons()
36 : {
37 188 : }
38 :
39 4788808 : explicit ImplB2DPolyPolygon(const basegfx::B2DPolygon& rToBeCopied) :
40 4788808 : maPolygons(1,rToBeCopied)
41 : {
42 4788808 : }
43 :
44 53218 : bool operator==(const ImplB2DPolyPolygon& rPolygonList) const
45 : {
46 : // same polygon count?
47 53218 : if(maPolygons.size() != rPolygonList.maPolygons.size())
48 27886 : return false;
49 :
50 : // compare polygon content
51 25332 : if(!(maPolygons == rPolygonList.maPolygons))
52 12726 : return false;
53 :
54 12606 : return true;
55 : }
56 :
57 14986744 : const basegfx::B2DPolygon& getB2DPolygon(sal_uInt32 nIndex) const
58 : {
59 14986744 : return maPolygons[nIndex];
60 : }
61 :
62 6857 : void setB2DPolygon(sal_uInt32 nIndex, const basegfx::B2DPolygon& rPolygon)
63 : {
64 6857 : maPolygons[nIndex] = rPolygon;
65 6857 : }
66 :
67 453421 : void insert(sal_uInt32 nIndex, const basegfx::B2DPolygon& rPolygon, sal_uInt32 nCount)
68 : {
69 453421 : if(nCount)
70 : {
71 : // add nCount copies of rPolygon
72 453421 : basegfx::B2DPolygonVector::iterator aIndex(maPolygons.begin());
73 453421 : if( nIndex )
74 251899 : aIndex += nIndex;
75 453421 : maPolygons.insert(aIndex, nCount, rPolygon);
76 : }
77 453421 : }
78 :
79 12284 : void insert(sal_uInt32 nIndex, const basegfx::B2DPolyPolygon& rPolyPolygon)
80 : {
81 : // add nCount polygons from rPolyPolygon
82 12284 : basegfx::B2DPolygonVector::iterator aIndex(maPolygons.begin());
83 12284 : if( nIndex )
84 8464 : aIndex += nIndex;
85 12284 : maPolygons.insert(aIndex, rPolyPolygon.begin(), rPolyPolygon.end());
86 12284 : }
87 :
88 159 : void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
89 : {
90 159 : if(nCount)
91 : {
92 : // remove polygon data
93 159 : basegfx::B2DPolygonVector::iterator aStart(maPolygons.begin());
94 159 : aStart += nIndex;
95 159 : const basegfx::B2DPolygonVector::iterator aEnd(aStart + nCount);
96 :
97 159 : maPolygons.erase(aStart, aEnd);
98 : }
99 159 : }
100 :
101 21046468 : sal_uInt32 count() const
102 : {
103 21046468 : return maPolygons.size();
104 : }
105 :
106 2477 : void setClosed(bool bNew)
107 : {
108 23943 : for(sal_uInt32 a(0L); a < maPolygons.size(); a++)
109 : {
110 21466 : maPolygons[a].setClosed(bNew);
111 : }
112 2477 : }
113 :
114 54 : void flip()
115 : {
116 : std::for_each( maPolygons.begin(),
117 : maPolygons.end(),
118 54 : std::mem_fun_ref( &basegfx::B2DPolygon::flip ));
119 54 : }
120 :
121 564 : void removeDoublePoints()
122 : {
123 : std::for_each( maPolygons.begin(),
124 : maPolygons.end(),
125 564 : std::mem_fun_ref( &basegfx::B2DPolygon::removeDoublePoints ));
126 564 : }
127 :
128 271344 : void transform(const basegfx::B2DHomMatrix& rMatrix)
129 : {
130 711252 : for(sal_uInt32 a(0L); a < maPolygons.size(); a++)
131 : {
132 439908 : maPolygons[a].transform(rMatrix);
133 : }
134 271344 : }
135 :
136 60 : void makeUnique()
137 : {
138 : std::for_each( maPolygons.begin(),
139 : maPolygons.end(),
140 60 : std::mem_fun_ref( &basegfx::B2DPolygon::makeUnique ));
141 60 : }
142 :
143 12284 : const basegfx::B2DPolygon* begin() const
144 : {
145 12284 : if(maPolygons.empty())
146 0 : return 0;
147 : else
148 12284 : return &maPolygons.front();
149 : }
150 :
151 12284 : const basegfx::B2DPolygon* end() const
152 : {
153 12284 : if(maPolygons.empty())
154 0 : return 0;
155 : else
156 12284 : return (&maPolygons.back())+1;
157 : }
158 :
159 106 : basegfx::B2DPolygon* begin()
160 : {
161 106 : if(maPolygons.empty())
162 0 : return 0;
163 : else
164 106 : return &maPolygons.front();
165 : }
166 :
167 106 : basegfx::B2DPolygon* end()
168 : {
169 106 : if(maPolygons.empty())
170 0 : return 0;
171 : else
172 106 : return &(maPolygons.back())+1;
173 : }
174 : };
175 :
176 : namespace basegfx
177 : {
178 : namespace { struct DefaultPolyPolygon: public rtl::Static<B2DPolyPolygon::ImplType,
179 : DefaultPolyPolygon> {}; }
180 :
181 491038 : B2DPolyPolygon::B2DPolyPolygon() :
182 491038 : mpPolyPolygon(DefaultPolyPolygon::get())
183 : {
184 491038 : }
185 :
186 5299426 : B2DPolyPolygon::B2DPolyPolygon(const B2DPolyPolygon& rPolyPolygon) :
187 5299426 : mpPolyPolygon(rPolyPolygon.mpPolyPolygon)
188 : {
189 5299426 : }
190 :
191 4788808 : B2DPolyPolygon::B2DPolyPolygon(const B2DPolygon& rPolygon) :
192 4788808 : mpPolyPolygon( ImplB2DPolyPolygon(rPolygon) )
193 : {
194 4788808 : }
195 :
196 10570638 : B2DPolyPolygon::~B2DPolyPolygon()
197 : {
198 10570638 : }
199 :
200 110203 : B2DPolyPolygon& B2DPolyPolygon::operator=(const B2DPolyPolygon& rPolyPolygon)
201 : {
202 110203 : mpPolyPolygon = rPolyPolygon.mpPolyPolygon;
203 110203 : return *this;
204 : }
205 :
206 60 : void B2DPolyPolygon::makeUnique()
207 : {
208 60 : mpPolyPolygon.make_unique();
209 60 : mpPolyPolygon->makeUnique();
210 60 : }
211 :
212 64558 : bool B2DPolyPolygon::operator==(const B2DPolyPolygon& rPolyPolygon) const
213 : {
214 64558 : if(mpPolyPolygon.same_object(rPolyPolygon.mpPolyPolygon))
215 11340 : return true;
216 :
217 53218 : return ((*mpPolyPolygon) == (*rPolyPolygon.mpPolyPolygon));
218 : }
219 :
220 35205 : bool B2DPolyPolygon::operator!=(const B2DPolyPolygon& rPolyPolygon) const
221 : {
222 35205 : return !((*this) == rPolyPolygon);
223 : }
224 :
225 10553484 : sal_uInt32 B2DPolyPolygon::count() const
226 : {
227 10553484 : return mpPolyPolygon->count();
228 : }
229 :
230 10091194 : B2DPolygon B2DPolyPolygon::getB2DPolygon(sal_uInt32 nIndex) const
231 : {
232 : OSL_ENSURE(nIndex < mpPolyPolygon->count(), "B2DPolyPolygon access outside range (!)");
233 :
234 10091194 : return mpPolyPolygon->getB2DPolygon(nIndex);
235 : }
236 :
237 6857 : void B2DPolyPolygon::setB2DPolygon(sal_uInt32 nIndex, const B2DPolygon& rPolygon)
238 : {
239 : OSL_ENSURE(nIndex < mpPolyPolygon->count(), "B2DPolyPolygon access outside range (!)");
240 :
241 6857 : if(getB2DPolygon(nIndex) != rPolygon)
242 6857 : mpPolyPolygon->setB2DPolygon(nIndex, rPolygon);
243 6857 : }
244 :
245 4714785 : bool B2DPolyPolygon::areControlPointsUsed() const
246 : {
247 9504962 : for(sal_uInt32 a(0L); a < mpPolyPolygon->count(); a++)
248 : {
249 4798646 : const B2DPolygon& rPolygon = mpPolyPolygon->getB2DPolygon(a);
250 :
251 4798646 : if(rPolygon.areControlPointsUsed())
252 : {
253 8469 : return true;
254 : }
255 : }
256 :
257 4706316 : 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 453421 : void B2DPolyPolygon::append(const B2DPolygon& rPolygon, sal_uInt32 nCount)
269 : {
270 453421 : if(nCount)
271 453421 : mpPolyPolygon->insert(mpPolyPolygon->count(), rPolygon, nCount);
272 453421 : }
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 38337 : B2DRange B2DPolyPolygon::getB2DRange() const
287 : {
288 38337 : B2DRange aRetval;
289 :
290 84780 : for(sal_uInt32 a(0L); a < mpPolyPolygon->count(); a++)
291 : {
292 46443 : aRetval.expand(mpPolyPolygon->getB2DPolygon(a).getB2DRange());
293 : }
294 :
295 38337 : return aRetval;
296 : }
297 :
298 40 : void B2DPolyPolygon::insert(sal_uInt32 nIndex, const B2DPolyPolygon& rPolyPolygon)
299 : {
300 : OSL_ENSURE(nIndex <= mpPolyPolygon->count(), "B2DPolyPolygon Insert outside range (!)");
301 :
302 40 : if(rPolyPolygon.count())
303 40 : mpPolyPolygon->insert(nIndex, rPolyPolygon);
304 40 : }
305 :
306 12374 : void B2DPolyPolygon::append(const B2DPolyPolygon& rPolyPolygon)
307 : {
308 12374 : if(rPolyPolygon.count())
309 12244 : mpPolyPolygon->insert(mpPolyPolygon->count(), rPolyPolygon);
310 12374 : }
311 :
312 159 : void B2DPolyPolygon::remove(sal_uInt32 nIndex, sal_uInt32 nCount)
313 : {
314 : OSL_ENSURE(nIndex + nCount <= mpPolyPolygon->count(), "B2DPolyPolygon Remove outside range (!)");
315 :
316 159 : if(nCount)
317 159 : mpPolyPolygon->remove(nIndex, nCount);
318 159 : }
319 :
320 10690 : void B2DPolyPolygon::clear()
321 : {
322 10690 : mpPolyPolygon = DefaultPolyPolygon::get();
323 10690 : }
324 :
325 24252 : bool B2DPolyPolygon::isClosed() const
326 : {
327 24252 : bool bRetval(true);
328 :
329 : // PolyPOlygon is closed when all contained Polygons are closed or
330 : // no Polygon exists.
331 69862 : for(sal_uInt32 a(0L); bRetval && a < mpPolyPolygon->count(); a++)
332 : {
333 45610 : if(!(mpPolyPolygon->getB2DPolygon(a)).isClosed())
334 : {
335 8510 : bRetval = false;
336 : }
337 : }
338 :
339 24252 : return bRetval;
340 : }
341 :
342 5091 : void B2DPolyPolygon::setClosed(bool bNew)
343 : {
344 5091 : if(bNew != isClosed())
345 2477 : mpPolyPolygon->setClosed(bNew);
346 5091 : }
347 :
348 54 : void B2DPolyPolygon::flip()
349 : {
350 54 : if(mpPolyPolygon->count())
351 : {
352 54 : mpPolyPolygon->flip();
353 : }
354 54 : }
355 :
356 4414 : bool B2DPolyPolygon::hasDoublePoints() const
357 : {
358 4414 : bool bRetval(false);
359 :
360 9265 : for(sal_uInt32 a(0L); !bRetval && a < mpPolyPolygon->count(); a++)
361 : {
362 4851 : if((mpPolyPolygon->getB2DPolygon(a)).hasDoublePoints())
363 : {
364 564 : bRetval = true;
365 : }
366 : }
367 :
368 4414 : return bRetval;
369 : }
370 :
371 4414 : void B2DPolyPolygon::removeDoublePoints()
372 : {
373 4414 : if(hasDoublePoints())
374 564 : mpPolyPolygon->removeDoublePoints();
375 4414 : }
376 :
377 367470 : void B2DPolyPolygon::transform(const B2DHomMatrix& rMatrix)
378 : {
379 367470 : if(mpPolyPolygon->count() && !rMatrix.isIdentity())
380 : {
381 271344 : mpPolyPolygon->transform(rMatrix);
382 : }
383 367470 : }
384 :
385 12284 : const B2DPolygon* B2DPolyPolygon::begin() const
386 : {
387 12284 : return mpPolyPolygon->begin();
388 : }
389 :
390 12284 : const B2DPolygon* B2DPolyPolygon::end() const
391 : {
392 12284 : return mpPolyPolygon->end();
393 : }
394 :
395 106 : B2DPolygon* B2DPolyPolygon::begin()
396 : {
397 106 : return mpPolyPolygon->begin();
398 : }
399 :
400 106 : B2DPolygon* B2DPolyPolygon::end()
401 : {
402 106 : return mpPolyPolygon->end();
403 : }
404 : } // end of namespace basegfx
405 :
406 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|