1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_basegfx.hxx"
30 #include <basegfx/polygon/b2dpolypolygon.hxx>
31 #include <osl/diagnose.h>
32 #include <basegfx/polygon/b2dpolygon.hxx>
33 #include <basegfx/polygon/b2dpolypolygontools.hxx>
34 #include <rtl/instance.hxx>
35 #include <basegfx/matrix/b2dhommatrix.hxx>
36 
37 #include <functional>
38 #include <vector>
39 #include <algorithm>
40 
41 //////////////////////////////////////////////////////////////////////////////
42 
43 class ImplB2DPolyPolygon
44 {
45 	typedef ::std::vector< basegfx::B2DPolygon >	PolygonVector;
46 
47 	PolygonVector									maPolygons;
48 
49 public:
50 	ImplB2DPolyPolygon() : maPolygons()
51     {
52     }
53 
54 	ImplB2DPolyPolygon(const basegfx::B2DPolygon& rToBeCopied) :
55         maPolygons(1,rToBeCopied)
56 	{
57 	}
58 
59 	bool operator==(const ImplB2DPolyPolygon& rPolygonList) const
60 	{
61 		// same polygon count?
62 		if(maPolygons.size() != rPolygonList.maPolygons.size())
63 			return false;
64 
65 		// compare polygon content
66 		if(!(maPolygons == rPolygonList.maPolygons))
67 			return false;
68 
69 		return true;
70 	}
71 
72 	const basegfx::B2DPolygon& getB2DPolygon(sal_uInt32 nIndex) const
73 	{
74 		return maPolygons[nIndex];
75 	}
76 
77 	void setB2DPolygon(sal_uInt32 nIndex, const basegfx::B2DPolygon& rPolygon)
78 	{
79 		maPolygons[nIndex] = rPolygon;
80 	}
81 
82 	void insert(sal_uInt32 nIndex, const basegfx::B2DPolygon& rPolygon, sal_uInt32 nCount)
83 	{
84 		if(nCount)
85 		{
86 			// add nCount copies of rPolygon
87 			PolygonVector::iterator aIndex(maPolygons.begin());
88 			aIndex += nIndex;
89 			maPolygons.insert(aIndex, nCount, rPolygon);
90 		}
91 	}
92 
93 	void insert(sal_uInt32 nIndex, const basegfx::B2DPolyPolygon& rPolyPolygon)
94 	{
95 		const sal_uInt32 nCount = rPolyPolygon.count();
96 
97 		if(nCount)
98 		{
99 			// add nCount polygons from rPolyPolygon
100 			maPolygons.reserve(maPolygons.size() + nCount);
101 			PolygonVector::iterator aIndex(maPolygons.begin());
102 			aIndex += nIndex;
103 
104 			for(sal_uInt32 a(0L); a < nCount; a++)
105 			{
106 				aIndex = maPolygons.insert(aIndex, rPolyPolygon.getB2DPolygon(a));
107 				aIndex++;
108 			}
109 		}
110 	}
111 
112 	void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
113 	{
114 		if(nCount)
115 		{
116 			// remove polygon data
117 			PolygonVector::iterator aStart(maPolygons.begin());
118 			aStart += nIndex;
119 			const PolygonVector::iterator aEnd(aStart + nCount);
120 
121 			maPolygons.erase(aStart, aEnd);
122 		}
123 	}
124 
125 	sal_uInt32 count() const
126 	{
127 		return maPolygons.size();
128 	}
129 
130 	void setClosed(bool bNew)
131 	{
132 		for(sal_uInt32 a(0L); a < maPolygons.size(); a++)
133 		{
134 			maPolygons[a].setClosed(bNew);
135 		}
136 	}
137 
138 	void flip()
139 	{
140         std::for_each( maPolygons.begin(),
141                        maPolygons.end(),
142                        std::mem_fun_ref( &basegfx::B2DPolygon::flip ));
143 	}
144 
145 	void removeDoublePoints()
146 	{
147         std::for_each( maPolygons.begin(),
148                        maPolygons.end(),
149                        std::mem_fun_ref( &basegfx::B2DPolygon::removeDoublePoints ));
150 	}
151 
152 	void transform(const basegfx::B2DHomMatrix& rMatrix)
153 	{
154 		for(sal_uInt32 a(0L); a < maPolygons.size(); a++)
155 		{
156 			maPolygons[a].transform(rMatrix);
157 		}
158 	}
159 
160     void makeUnique()
161     {
162         std::for_each( maPolygons.begin(),
163                        maPolygons.end(),
164                        std::mem_fun_ref( &basegfx::B2DPolygon::makeUnique ));
165     }
166 
167     const basegfx::B2DPolygon* begin() const
168     {
169         if(maPolygons.empty())
170             return 0;
171         else
172             return &maPolygons.front();
173     }
174 
175     const basegfx::B2DPolygon* end() const
176     {
177         if(maPolygons.empty())
178             return 0;
179         else
180             return (&maPolygons.back())+1;
181     }
182 
183     basegfx::B2DPolygon* begin()
184     {
185         if(maPolygons.empty())
186             return 0;
187         else
188             return &maPolygons.front();
189     }
190 
191     basegfx::B2DPolygon* end()
192     {
193         if(maPolygons.empty())
194             return 0;
195         else
196             return &(maPolygons.back())+1;
197     }
198 };
199 
200 //////////////////////////////////////////////////////////////////////////////
201 
202 namespace basegfx
203 {
204     namespace { struct DefaultPolyPolygon: public rtl::Static<B2DPolyPolygon::ImplType,
205                                                               DefaultPolyPolygon> {}; }
206 
207 	B2DPolyPolygon::B2DPolyPolygon() :
208         mpPolyPolygon(DefaultPolyPolygon::get())
209 	{
210 	}
211 
212 	B2DPolyPolygon::B2DPolyPolygon(const B2DPolyPolygon& rPolyPolygon) :
213         mpPolyPolygon(rPolyPolygon.mpPolyPolygon)
214 	{
215 	}
216 
217 	B2DPolyPolygon::B2DPolyPolygon(const B2DPolygon& rPolygon) :
218         mpPolyPolygon( ImplB2DPolyPolygon(rPolygon) )
219 	{
220 	}
221 
222 	B2DPolyPolygon::~B2DPolyPolygon()
223 	{
224 	}
225 
226 	B2DPolyPolygon& B2DPolyPolygon::operator=(const B2DPolyPolygon& rPolyPolygon)
227 	{
228 		mpPolyPolygon = rPolyPolygon.mpPolyPolygon;
229 		return *this;
230 	}
231 
232     void B2DPolyPolygon::makeUnique()
233     {
234         mpPolyPolygon.make_unique();
235         mpPolyPolygon->makeUnique();
236     }
237 
238 	bool B2DPolyPolygon::operator==(const B2DPolyPolygon& rPolyPolygon) const
239 	{
240 		if(mpPolyPolygon.same_object(rPolyPolygon.mpPolyPolygon))
241 			return true;
242 
243 		return ((*mpPolyPolygon) == (*rPolyPolygon.mpPolyPolygon));
244 	}
245 
246 	bool B2DPolyPolygon::operator!=(const B2DPolyPolygon& rPolyPolygon) const
247 	{
248         return !((*this) == rPolyPolygon);
249 	}
250 
251 	sal_uInt32 B2DPolyPolygon::count() const
252 	{
253 		return mpPolyPolygon->count();
254 	}
255 
256 	B2DPolygon B2DPolyPolygon::getB2DPolygon(sal_uInt32 nIndex) const
257 	{
258 		OSL_ENSURE(nIndex < mpPolyPolygon->count(), "B2DPolyPolygon access outside range (!)");
259 
260 		return mpPolyPolygon->getB2DPolygon(nIndex);
261 	}
262 
263 	void B2DPolyPolygon::setB2DPolygon(sal_uInt32 nIndex, const B2DPolygon& rPolygon)
264 	{
265 		OSL_ENSURE(nIndex < mpPolyPolygon->count(), "B2DPolyPolygon access outside range (!)");
266 
267 		if(getB2DPolygon(nIndex) != rPolygon)
268 			mpPolyPolygon->setB2DPolygon(nIndex, rPolygon);
269 	}
270 
271 	bool B2DPolyPolygon::areControlPointsUsed() const
272 	{
273 		for(sal_uInt32 a(0L); a < mpPolyPolygon->count(); a++)
274 		{
275 			const B2DPolygon& rPolygon = mpPolyPolygon->getB2DPolygon(a);
276 
277 			if(rPolygon.areControlPointsUsed())
278 			{
279 				return true;
280 			}
281 		}
282 
283 		return false;
284 	}
285 
286 	void B2DPolyPolygon::insert(sal_uInt32 nIndex, const B2DPolygon& rPolygon, sal_uInt32 nCount)
287 	{
288 		OSL_ENSURE(nIndex <= mpPolyPolygon->count(), "B2DPolyPolygon Insert outside range (!)");
289 
290 		if(nCount)
291 			mpPolyPolygon->insert(nIndex, rPolygon, nCount);
292 	}
293 
294 	void B2DPolyPolygon::append(const B2DPolygon& rPolygon, sal_uInt32 nCount)
295 	{
296 		if(nCount)
297 			mpPolyPolygon->insert(mpPolyPolygon->count(), rPolygon, nCount);
298 	}
299 
300     B2DPolyPolygon B2DPolyPolygon::getDefaultAdaptiveSubdivision() const
301 	{
302 		B2DPolyPolygon aRetval;
303 
304 		for(sal_uInt32 a(0L); a < mpPolyPolygon->count(); a++)
305 		{
306 			aRetval.append(mpPolyPolygon->getB2DPolygon(a).getDefaultAdaptiveSubdivision());
307 		}
308 
309 		return aRetval;
310 	}
311 
312     B2DRange B2DPolyPolygon::getB2DRange() const
313     {
314 		B2DRange aRetval;
315 
316 		for(sal_uInt32 a(0L); a < mpPolyPolygon->count(); a++)
317 		{
318 			aRetval.expand(mpPolyPolygon->getB2DPolygon(a).getB2DRange());
319 		}
320 
321 		return aRetval;
322     }
323 
324 	void B2DPolyPolygon::insert(sal_uInt32 nIndex, const B2DPolyPolygon& rPolyPolygon)
325 	{
326 		OSL_ENSURE(nIndex <= mpPolyPolygon->count(), "B2DPolyPolygon Insert outside range (!)");
327 
328 		if(rPolyPolygon.count())
329 			mpPolyPolygon->insert(nIndex, rPolyPolygon);
330 	}
331 
332 	void B2DPolyPolygon::append(const B2DPolyPolygon& rPolyPolygon)
333 	{
334 		if(rPolyPolygon.count())
335 			mpPolyPolygon->insert(mpPolyPolygon->count(), rPolyPolygon);
336 	}
337 
338 	void B2DPolyPolygon::remove(sal_uInt32 nIndex, sal_uInt32 nCount)
339 	{
340 		OSL_ENSURE(nIndex + nCount <= mpPolyPolygon->count(), "B2DPolyPolygon Remove outside range (!)");
341 
342 		if(nCount)
343 			mpPolyPolygon->remove(nIndex, nCount);
344 	}
345 
346 	void B2DPolyPolygon::clear()
347 	{
348 		mpPolyPolygon = DefaultPolyPolygon::get();
349 	}
350 
351 	bool B2DPolyPolygon::isClosed() const
352 	{
353 		bool bRetval(true);
354 
355 		// PolyPOlygon is closed when all contained Polygons are closed or
356 		// no Polygon exists.
357 		for(sal_uInt32 a(0L); bRetval && a < mpPolyPolygon->count(); a++)
358 		{
359 			if(!(mpPolyPolygon->getB2DPolygon(a)).isClosed())
360 			{
361 				bRetval = false;
362 			}
363 		}
364 
365 		return bRetval;
366 	}
367 
368 	void B2DPolyPolygon::setClosed(bool bNew)
369 	{
370 		if(bNew != isClosed())
371 			mpPolyPolygon->setClosed(bNew);
372 	}
373 
374 	void B2DPolyPolygon::flip()
375 	{
376 		if(mpPolyPolygon->count())
377 		{
378 			mpPolyPolygon->flip();
379 		}
380 	}
381 
382 	bool B2DPolyPolygon::hasDoublePoints() const
383 	{
384 		bool bRetval(false);
385 
386 		for(sal_uInt32 a(0L); !bRetval && a < mpPolyPolygon->count(); a++)
387 		{
388 			if((mpPolyPolygon->getB2DPolygon(a)).hasDoublePoints())
389 			{
390 				bRetval = true;
391 			}
392 		}
393 
394 		return bRetval;
395 	}
396 
397 	void B2DPolyPolygon::removeDoublePoints()
398 	{
399 		if(hasDoublePoints())
400 			mpPolyPolygon->removeDoublePoints();
401 	}
402 
403 	void B2DPolyPolygon::transform(const B2DHomMatrix& rMatrix)
404 	{
405 		if(mpPolyPolygon->count() && !rMatrix.isIdentity())
406 		{
407 			mpPolyPolygon->transform(rMatrix);
408 		}
409 	}
410 
411     const B2DPolygon* B2DPolyPolygon::begin() const
412     {
413         return mpPolyPolygon->begin();
414     }
415 
416     const B2DPolygon* B2DPolyPolygon::end() const
417     {
418         return mpPolyPolygon->end();
419     }
420 
421     B2DPolygon* B2DPolyPolygon::begin()
422     {
423         return mpPolyPolygon->begin();
424     }
425 
426     B2DPolygon* B2DPolyPolygon::end()
427     {
428         return mpPolyPolygon->end();
429     }
430 } // end of namespace basegfx
431 
432 // eof
433