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