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 <osl/diagnose.h>
31 #include <basegfx/polygon/b3dpolypolygon.hxx>
32 #include <basegfx/polygon/b3dpolygon.hxx>
33 #include <rtl/instance.hxx>
34 #include <basegfx/matrix/b2dhommatrix.hxx>
35 #include <basegfx/matrix/b3dhommatrix.hxx>
36 #include <functional>
37 #include <vector>
38 #include <algorithm>
39 
40 //////////////////////////////////////////////////////////////////////////////
41 
42 class ImplB3DPolyPolygon
43 {
44 	typedef ::std::vector< ::basegfx::B3DPolygon >	PolygonVector;
45 
46 	PolygonVector									maPolygons;
47 
48 public:
49 	ImplB3DPolyPolygon() : maPolygons()
50     {
51     }
52 
53 	ImplB3DPolyPolygon(const ::basegfx::B3DPolygon& rToBeCopied) :
54         maPolygons(1,rToBeCopied)
55 	{
56 	}
57 
58 	bool operator==(const ImplB3DPolyPolygon& rPolygonList) const
59 	{
60 		// same polygon count?
61 		if(maPolygons.size() != rPolygonList.maPolygons.size())
62 			return false;
63 
64 		// compare polygon content
65 		if(maPolygons != rPolygonList.maPolygons)
66 			return false;
67 
68 		return true;
69 	}
70 
71 	const ::basegfx::B3DPolygon& getB3DPolygon(sal_uInt32 nIndex) const
72 	{
73 		return maPolygons[nIndex];
74 	}
75 
76 	void setB3DPolygon(sal_uInt32 nIndex, const ::basegfx::B3DPolygon& rPolygon)
77 	{
78 		maPolygons[nIndex] = rPolygon;
79 	}
80 
81 	void insert(sal_uInt32 nIndex, const ::basegfx::B3DPolygon& rPolygon, sal_uInt32 nCount)
82 	{
83 		if(nCount)
84 		{
85 			// add nCount copies of rPolygon
86 			PolygonVector::iterator aIndex(maPolygons.begin());
87 			aIndex += nIndex;
88 			maPolygons.insert(aIndex, nCount, rPolygon);
89 		}
90 	}
91 
92 	void insert(sal_uInt32 nIndex, const ::basegfx::B3DPolyPolygon& rPolyPolygon)
93 	{
94 		const sal_uInt32 nCount = rPolyPolygon.count();
95 
96 		if(nCount)
97 		{
98 			// add nCount polygons from rPolyPolygon
99 			maPolygons.reserve(maPolygons.size() + nCount);
100 			PolygonVector::iterator aIndex(maPolygons.begin());
101 			aIndex += nIndex;
102 
103 			for(sal_uInt32 a(0L); a < nCount; a++)
104 			{
105 				maPolygons.insert(aIndex, rPolyPolygon.getB3DPolygon(a));
106 				aIndex++;
107 			}
108 		}
109 	}
110 
111 	void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
112 	{
113 		if(nCount)
114 		{
115 			// remove polygon data
116 			PolygonVector::iterator aStart(maPolygons.begin());
117 			aStart += nIndex;
118 			const PolygonVector::iterator aEnd(aStart + nCount);
119 
120 			maPolygons.erase(aStart, aEnd);
121 		}
122 	}
123 
124 	sal_uInt32 count() const
125 	{
126 		return maPolygons.size();
127 	}
128 
129 	void setClosed(bool bNew)
130 	{
131 		for(sal_uInt32 a(0L); a < maPolygons.size(); a++)
132 		{
133 			maPolygons[a].setClosed(bNew);
134 		}
135 	}
136 
137 	void flip()
138 	{
139         std::for_each( maPolygons.begin(),
140                        maPolygons.end(),
141                        std::mem_fun_ref( &::basegfx::B3DPolygon::flip ));
142 	}
143 
144 	void removeDoublePoints()
145 	{
146         std::for_each( maPolygons.begin(),
147                        maPolygons.end(),
148                        std::mem_fun_ref( &::basegfx::B3DPolygon::removeDoublePoints ));
149 	}
150 
151 	void transform(const ::basegfx::B3DHomMatrix& rMatrix)
152 	{
153 		for(sal_uInt32 a(0L); a < maPolygons.size(); a++)
154 		{
155 			maPolygons[a].transform(rMatrix);
156 		}
157 	}
158 
159 	void clearBColors()
160 	{
161 		for(sal_uInt32 a(0L); a < maPolygons.size(); a++)
162 		{
163 			maPolygons[a].clearBColors();
164 		}
165 	}
166 
167 	void transformNormals(const ::basegfx::B3DHomMatrix& rMatrix)
168 	{
169 		for(sal_uInt32 a(0L); a < maPolygons.size(); a++)
170 		{
171 			maPolygons[a].transformNormals(rMatrix);
172 		}
173 	}
174 
175 	void clearNormals()
176 	{
177 		for(sal_uInt32 a(0L); a < maPolygons.size(); a++)
178 		{
179 			maPolygons[a].clearNormals();
180 		}
181 	}
182 
183 	void transformTextureCoordiantes(const ::basegfx::B2DHomMatrix& rMatrix)
184 	{
185 		for(sal_uInt32 a(0L); a < maPolygons.size(); a++)
186 		{
187 			maPolygons[a].transformTextureCoordiantes(rMatrix);
188 		}
189 	}
190 
191 	void clearTextureCoordinates()
192 	{
193 		for(sal_uInt32 a(0L); a < maPolygons.size(); a++)
194 		{
195 			maPolygons[a].clearTextureCoordinates();
196 		}
197 	}
198 
199     void makeUnique()
200     {
201         std::for_each( maPolygons.begin(),
202                        maPolygons.end(),
203                        std::mem_fun_ref( &::basegfx::B3DPolygon::makeUnique ));
204     }
205 };
206 
207 //////////////////////////////////////////////////////////////////////////////
208 
209 namespace basegfx
210 {
211     namespace { struct DefaultPolyPolygon : public rtl::Static<B3DPolyPolygon::ImplType,
212                                                                DefaultPolyPolygon> {}; }
213 
214 	B3DPolyPolygon::B3DPolyPolygon() :
215         mpPolyPolygon(DefaultPolyPolygon::get())
216 	{
217 	}
218 
219 	B3DPolyPolygon::B3DPolyPolygon(const B3DPolyPolygon& rPolyPolygon) :
220         mpPolyPolygon(rPolyPolygon.mpPolyPolygon)
221 	{
222 	}
223 
224 	B3DPolyPolygon::B3DPolyPolygon(const B3DPolygon& rPolygon) :
225         mpPolyPolygon( ImplB3DPolyPolygon(rPolygon) )
226 	{
227 	}
228 
229 	B3DPolyPolygon::~B3DPolyPolygon()
230 	{
231 	}
232 
233 	B3DPolyPolygon& B3DPolyPolygon::operator=(const B3DPolyPolygon& rPolyPolygon)
234 	{
235 		mpPolyPolygon = rPolyPolygon.mpPolyPolygon;
236 		return *this;
237 	}
238 
239     void B3DPolyPolygon::makeUnique()
240     {
241         mpPolyPolygon.make_unique();
242         mpPolyPolygon->makeUnique();
243     }
244 
245 	bool B3DPolyPolygon::operator==(const B3DPolyPolygon& rPolyPolygon) const
246 	{
247 		if(mpPolyPolygon.same_object(rPolyPolygon.mpPolyPolygon))
248 			return true;
249 
250 		return ((*mpPolyPolygon) == (*rPolyPolygon.mpPolyPolygon));
251 	}
252 
253 	bool B3DPolyPolygon::operator!=(const B3DPolyPolygon& rPolyPolygon) const
254 	{
255         return !(*this == rPolyPolygon);
256 	}
257 
258 	sal_uInt32 B3DPolyPolygon::count() const
259 	{
260 		return mpPolyPolygon->count();
261 	}
262 
263 	B3DPolygon B3DPolyPolygon::getB3DPolygon(sal_uInt32 nIndex) const
264 	{
265 		OSL_ENSURE(nIndex < mpPolyPolygon->count(), "B3DPolyPolygon access outside range (!)");
266 
267 		return mpPolyPolygon->getB3DPolygon(nIndex);
268 	}
269 
270 	void B3DPolyPolygon::setB3DPolygon(sal_uInt32 nIndex, const B3DPolygon& rPolygon)
271 	{
272 		OSL_ENSURE(nIndex < mpPolyPolygon->count(), "B3DPolyPolygon access outside range (!)");
273 
274 		if(getB3DPolygon(nIndex) != rPolygon)
275 			mpPolyPolygon->setB3DPolygon(nIndex, rPolygon);
276 	}
277 
278 	bool B3DPolyPolygon::areBColorsUsed() const
279 	{
280 		for(sal_uInt32 a(0L); a < mpPolyPolygon->count(); a++)
281 		{
282 			if((mpPolyPolygon->getB3DPolygon(a)).areBColorsUsed())
283 			{
284 				return true;
285 			}
286 		}
287 
288 		return false;
289 	}
290 
291 	void B3DPolyPolygon::clearBColors()
292 	{
293 		if(areBColorsUsed())
294 			mpPolyPolygon->clearBColors();
295 	}
296 
297 	void B3DPolyPolygon::transformNormals(const B3DHomMatrix& rMatrix)
298 	{
299 		if(!rMatrix.isIdentity())
300 			mpPolyPolygon->transformNormals(rMatrix);
301 	}
302 
303 	bool B3DPolyPolygon::areNormalsUsed() const
304 	{
305 		for(sal_uInt32 a(0L); a < mpPolyPolygon->count(); a++)
306 		{
307 			if((mpPolyPolygon->getB3DPolygon(a)).areNormalsUsed())
308 			{
309 				return true;
310 			}
311 		}
312 
313 		return false;
314 	}
315 
316 	void B3DPolyPolygon::clearNormals()
317 	{
318 		if(areNormalsUsed())
319 			mpPolyPolygon->clearNormals();
320 	}
321 
322 	void B3DPolyPolygon::transformTextureCoordiantes(const B2DHomMatrix& rMatrix)
323 	{
324 		if(!rMatrix.isIdentity())
325 			mpPolyPolygon->transformTextureCoordiantes(rMatrix);
326 	}
327 
328 	bool B3DPolyPolygon::areTextureCoordinatesUsed() const
329 	{
330 		for(sal_uInt32 a(0L); a < mpPolyPolygon->count(); a++)
331 		{
332 			if((mpPolyPolygon->getB3DPolygon(a)).areTextureCoordinatesUsed())
333 			{
334 				return true;
335 			}
336 		}
337 
338 		return false;
339 	}
340 
341 	void B3DPolyPolygon::clearTextureCoordinates()
342 	{
343 		if(areTextureCoordinatesUsed())
344 			mpPolyPolygon->clearTextureCoordinates();
345 	}
346 
347 	void B3DPolyPolygon::insert(sal_uInt32 nIndex, const B3DPolygon& rPolygon, sal_uInt32 nCount)
348 	{
349 		OSL_ENSURE(nIndex <= mpPolyPolygon->count(), "B3DPolyPolygon Insert outside range (!)");
350 
351 		if(nCount)
352 			mpPolyPolygon->insert(nIndex, rPolygon, nCount);
353 	}
354 
355 	void B3DPolyPolygon::append(const B3DPolygon& rPolygon, sal_uInt32 nCount)
356 	{
357 		if(nCount)
358 			mpPolyPolygon->insert(mpPolyPolygon->count(), rPolygon, nCount);
359 	}
360 
361 	void B3DPolyPolygon::insert(sal_uInt32 nIndex, const B3DPolyPolygon& rPolyPolygon)
362 	{
363 		OSL_ENSURE(nIndex <= mpPolyPolygon->count(), "B3DPolyPolygon Insert outside range (!)");
364 
365 		if(rPolyPolygon.count())
366 			mpPolyPolygon->insert(nIndex, rPolyPolygon);
367 	}
368 
369 	void B3DPolyPolygon::append(const B3DPolyPolygon& rPolyPolygon)
370 	{
371 		if(rPolyPolygon.count())
372 			mpPolyPolygon->insert(mpPolyPolygon->count(), rPolyPolygon);
373 	}
374 
375 	void B3DPolyPolygon::remove(sal_uInt32 nIndex, sal_uInt32 nCount)
376 	{
377 		OSL_ENSURE(nIndex + nCount <= mpPolyPolygon->count(), "B3DPolyPolygon Remove outside range (!)");
378 
379 		if(nCount)
380 			mpPolyPolygon->remove(nIndex, nCount);
381 	}
382 
383 	void B3DPolyPolygon::clear()
384 	{
385 		mpPolyPolygon = DefaultPolyPolygon::get();
386 	}
387 
388 	bool B3DPolyPolygon::isClosed() const
389 	{
390 		bool bRetval(true);
391 
392 		// PolyPOlygon is closed when all contained Polygons are closed or
393 		// no Polygon exists.
394 		for(sal_uInt32 a(0L); bRetval && a < mpPolyPolygon->count(); a++)
395 		{
396 			if(!(mpPolyPolygon->getB3DPolygon(a)).isClosed())
397 			{
398 				bRetval = false;
399 			}
400 		}
401 
402 		return bRetval;
403 	}
404 
405 	void B3DPolyPolygon::setClosed(bool bNew)
406 	{
407 		if(bNew != isClosed())
408 			mpPolyPolygon->setClosed(bNew);
409 	}
410 
411 	void B3DPolyPolygon::flip()
412 	{
413 		mpPolyPolygon->flip();
414 	}
415 
416 	bool B3DPolyPolygon::hasDoublePoints() const
417 	{
418 		bool bRetval(false);
419 
420 		for(sal_uInt32 a(0L); !bRetval && a < mpPolyPolygon->count(); a++)
421 		{
422 			if((mpPolyPolygon->getB3DPolygon(a)).hasDoublePoints())
423 			{
424 				bRetval = true;
425 			}
426 		}
427 
428 		return bRetval;
429 	}
430 
431 	void B3DPolyPolygon::removeDoublePoints()
432 	{
433 		if(hasDoublePoints())
434 			mpPolyPolygon->removeDoublePoints();
435 	}
436 
437 	void B3DPolyPolygon::transform(const B3DHomMatrix& rMatrix)
438 	{
439 		if(mpPolyPolygon->count() && !rMatrix.isIdentity())
440 		{
441 			mpPolyPolygon->transform(rMatrix);
442 		}
443 	}
444 } // end of namespace basegfx
445 
446 // eof
447