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 0 : class ImplB2DPolyPolygon
33 : {
34 : basegfx::B2DPolygonVector maPolygons;
35 :
36 : public:
37 0 : ImplB2DPolyPolygon() : maPolygons()
38 : {
39 0 : }
40 :
41 0 : explicit ImplB2DPolyPolygon(const basegfx::B2DPolygon& rToBeCopied) :
42 0 : maPolygons(1,rToBeCopied)
43 : {
44 0 : }
45 :
46 0 : bool operator==(const ImplB2DPolyPolygon& rPolygonList) const
47 : {
48 : // same polygon count?
49 0 : if(maPolygons.size() != rPolygonList.maPolygons.size())
50 0 : return false;
51 :
52 : // compare polygon content
53 0 : if(!(maPolygons == rPolygonList.maPolygons))
54 0 : return false;
55 :
56 0 : return true;
57 : }
58 :
59 0 : const basegfx::B2DPolygon& getB2DPolygon(sal_uInt32 nIndex) const
60 : {
61 0 : return maPolygons[nIndex];
62 : }
63 :
64 0 : void setB2DPolygon(sal_uInt32 nIndex, const basegfx::B2DPolygon& rPolygon)
65 : {
66 0 : maPolygons[nIndex] = rPolygon;
67 0 : }
68 :
69 0 : void insert(sal_uInt32 nIndex, const basegfx::B2DPolygon& rPolygon, sal_uInt32 nCount)
70 : {
71 0 : if(nCount)
72 : {
73 : // add nCount copies of rPolygon
74 0 : basegfx::B2DPolygonVector::iterator aIndex(maPolygons.begin());
75 0 : if( nIndex )
76 0 : aIndex += nIndex;
77 0 : maPolygons.insert(aIndex, nCount, rPolygon);
78 : }
79 0 : }
80 :
81 0 : void insert(sal_uInt32 nIndex, const basegfx::B2DPolyPolygon& rPolyPolygon)
82 : {
83 : // add nCount polygons from rPolyPolygon
84 0 : basegfx::B2DPolygonVector::iterator aIndex(maPolygons.begin());
85 0 : if( nIndex )
86 0 : aIndex += nIndex;
87 0 : maPolygons.insert(aIndex, rPolyPolygon.begin(), rPolyPolygon.end());
88 0 : }
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 0 : sal_uInt32 count() const
104 : {
105 0 : return maPolygons.size();
106 : }
107 :
108 0 : void setClosed(bool bNew)
109 : {
110 0 : for(sal_uInt32 a(0L); a < maPolygons.size(); a++)
111 : {
112 0 : maPolygons[a].setClosed(bNew);
113 : }
114 0 : }
115 :
116 0 : void flip()
117 : {
118 : std::for_each( maPolygons.begin(),
119 : maPolygons.end(),
120 0 : std::mem_fun_ref( &basegfx::B2DPolygon::flip ));
121 0 : }
122 :
123 0 : void removeDoublePoints()
124 : {
125 : std::for_each( maPolygons.begin(),
126 : maPolygons.end(),
127 0 : std::mem_fun_ref( &basegfx::B2DPolygon::removeDoublePoints ));
128 0 : }
129 :
130 0 : void transform(const basegfx::B2DHomMatrix& rMatrix)
131 : {
132 0 : for(sal_uInt32 a(0L); a < maPolygons.size(); a++)
133 : {
134 0 : maPolygons[a].transform(rMatrix);
135 : }
136 0 : }
137 :
138 0 : void makeUnique()
139 : {
140 : std::for_each( maPolygons.begin(),
141 : maPolygons.end(),
142 0 : std::mem_fun_ref( &basegfx::B2DPolygon::makeUnique ));
143 0 : }
144 :
145 0 : const basegfx::B2DPolygon* begin() const
146 : {
147 0 : if(maPolygons.empty())
148 0 : return 0;
149 : else
150 0 : return &maPolygons.front();
151 : }
152 :
153 0 : const basegfx::B2DPolygon* end() const
154 : {
155 0 : if(maPolygons.empty())
156 0 : return 0;
157 : else
158 0 : return (&maPolygons.back())+1;
159 : }
160 :
161 0 : basegfx::B2DPolygon* begin()
162 : {
163 0 : if(maPolygons.empty())
164 0 : return 0;
165 : else
166 0 : return &maPolygons.front();
167 : }
168 :
169 0 : basegfx::B2DPolygon* end()
170 : {
171 0 : if(maPolygons.empty())
172 0 : return 0;
173 : else
174 0 : 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 0 : B2DPolyPolygon::B2DPolyPolygon() :
186 0 : mpPolyPolygon(DefaultPolyPolygon::get())
187 : {
188 0 : }
189 :
190 0 : B2DPolyPolygon::B2DPolyPolygon(const B2DPolyPolygon& rPolyPolygon) :
191 0 : mpPolyPolygon(rPolyPolygon.mpPolyPolygon)
192 : {
193 0 : }
194 :
195 0 : B2DPolyPolygon::B2DPolyPolygon(const B2DPolygon& rPolygon) :
196 0 : mpPolyPolygon( ImplB2DPolyPolygon(rPolygon) )
197 : {
198 0 : }
199 :
200 0 : B2DPolyPolygon::~B2DPolyPolygon()
201 : {
202 0 : }
203 :
204 0 : B2DPolyPolygon& B2DPolyPolygon::operator=(const B2DPolyPolygon& rPolyPolygon)
205 : {
206 0 : mpPolyPolygon = rPolyPolygon.mpPolyPolygon;
207 0 : return *this;
208 : }
209 :
210 0 : void B2DPolyPolygon::makeUnique()
211 : {
212 0 : mpPolyPolygon.make_unique();
213 0 : mpPolyPolygon->makeUnique();
214 0 : }
215 :
216 0 : bool B2DPolyPolygon::operator==(const B2DPolyPolygon& rPolyPolygon) const
217 : {
218 0 : if(mpPolyPolygon.same_object(rPolyPolygon.mpPolyPolygon))
219 0 : return true;
220 :
221 0 : return ((*mpPolyPolygon) == (*rPolyPolygon.mpPolyPolygon));
222 : }
223 :
224 0 : bool B2DPolyPolygon::operator!=(const B2DPolyPolygon& rPolyPolygon) const
225 : {
226 0 : return !((*this) == rPolyPolygon);
227 : }
228 :
229 0 : sal_uInt32 B2DPolyPolygon::count() const
230 : {
231 0 : return mpPolyPolygon->count();
232 : }
233 :
234 0 : B2DPolygon B2DPolyPolygon::getB2DPolygon(sal_uInt32 nIndex) const
235 : {
236 : OSL_ENSURE(nIndex < mpPolyPolygon->count(), "B2DPolyPolygon access outside range (!)");
237 :
238 0 : return mpPolyPolygon->getB2DPolygon(nIndex);
239 : }
240 :
241 0 : void B2DPolyPolygon::setB2DPolygon(sal_uInt32 nIndex, const B2DPolygon& rPolygon)
242 : {
243 : OSL_ENSURE(nIndex < mpPolyPolygon->count(), "B2DPolyPolygon access outside range (!)");
244 :
245 0 : if(getB2DPolygon(nIndex) != rPolygon)
246 0 : mpPolyPolygon->setB2DPolygon(nIndex, rPolygon);
247 0 : }
248 :
249 0 : bool B2DPolyPolygon::areControlPointsUsed() const
250 : {
251 0 : for(sal_uInt32 a(0L); a < mpPolyPolygon->count(); a++)
252 : {
253 0 : const B2DPolygon& rPolygon = mpPolyPolygon->getB2DPolygon(a);
254 :
255 0 : if(rPolygon.areControlPointsUsed())
256 : {
257 0 : return true;
258 : }
259 : }
260 :
261 0 : 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 0 : void B2DPolyPolygon::append(const B2DPolygon& rPolygon, sal_uInt32 nCount)
273 : {
274 0 : if(nCount)
275 0 : mpPolyPolygon->insert(mpPolyPolygon->count(), rPolygon, nCount);
276 0 : }
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 0 : B2DRange B2DPolyPolygon::getB2DRange() const
291 : {
292 0 : B2DRange aRetval;
293 :
294 0 : for(sal_uInt32 a(0L); a < mpPolyPolygon->count(); a++)
295 : {
296 0 : aRetval.expand(mpPolyPolygon->getB2DPolygon(a).getB2DRange());
297 : }
298 :
299 0 : 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 0 : void B2DPolyPolygon::append(const B2DPolyPolygon& rPolyPolygon)
311 : {
312 0 : if(rPolyPolygon.count())
313 0 : mpPolyPolygon->insert(mpPolyPolygon->count(), rPolyPolygon);
314 0 : }
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 0 : void B2DPolyPolygon::clear()
325 : {
326 0 : mpPolyPolygon = DefaultPolyPolygon::get();
327 0 : }
328 :
329 0 : bool B2DPolyPolygon::isClosed() const
330 : {
331 0 : bool bRetval(true);
332 :
333 : // PolyPOlygon is closed when all contained Polygons are closed or
334 : // no Polygon exists.
335 0 : for(sal_uInt32 a(0L); bRetval && a < mpPolyPolygon->count(); a++)
336 : {
337 0 : if(!(mpPolyPolygon->getB2DPolygon(a)).isClosed())
338 : {
339 0 : bRetval = false;
340 : }
341 : }
342 :
343 0 : return bRetval;
344 : }
345 :
346 0 : void B2DPolyPolygon::setClosed(bool bNew)
347 : {
348 0 : if(bNew != isClosed())
349 0 : mpPolyPolygon->setClosed(bNew);
350 0 : }
351 :
352 0 : void B2DPolyPolygon::flip()
353 : {
354 0 : if(mpPolyPolygon->count())
355 : {
356 0 : mpPolyPolygon->flip();
357 : }
358 0 : }
359 :
360 0 : bool B2DPolyPolygon::hasDoublePoints() const
361 : {
362 0 : bool bRetval(false);
363 :
364 0 : for(sal_uInt32 a(0L); !bRetval && a < mpPolyPolygon->count(); a++)
365 : {
366 0 : if((mpPolyPolygon->getB2DPolygon(a)).hasDoublePoints())
367 : {
368 0 : bRetval = true;
369 : }
370 : }
371 :
372 0 : return bRetval;
373 : }
374 :
375 0 : void B2DPolyPolygon::removeDoublePoints()
376 : {
377 0 : if(hasDoublePoints())
378 0 : mpPolyPolygon->removeDoublePoints();
379 0 : }
380 :
381 0 : void B2DPolyPolygon::transform(const B2DHomMatrix& rMatrix)
382 : {
383 0 : if(mpPolyPolygon->count() && !rMatrix.isIdentity())
384 : {
385 0 : mpPolyPolygon->transform(rMatrix);
386 : }
387 0 : }
388 :
389 0 : const B2DPolygon* B2DPolyPolygon::begin() const
390 : {
391 0 : return mpPolyPolygon->begin();
392 : }
393 :
394 0 : const B2DPolygon* B2DPolyPolygon::end() const
395 : {
396 0 : return mpPolyPolygon->end();
397 : }
398 :
399 0 : B2DPolygon* B2DPolyPolygon::begin()
400 : {
401 0 : return mpPolyPolygon->begin();
402 : }
403 :
404 0 : B2DPolygon* B2DPolyPolygon::end()
405 : {
406 0 : return mpPolyPolygon->end();
407 : }
408 : } // end of namespace basegfx
409 :
410 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|