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 <osl/diagnose.h>
21 #include <basegfx/polygon/b3dpolypolygon.hxx>
22 #include <basegfx/polygon/b3dpolygon.hxx>
23 #include <basegfx/matrix/b2dhommatrix.hxx>
24 #include <basegfx/matrix/b3dhommatrix.hxx>
25 #include <vector>
26 
27 class ImplB3DPolyPolygon
28 {
29     typedef std::vector< ::basegfx::B3DPolygon >  PolygonVector;
30 
31     PolygonVector                                   maPolygons;
32 
33 public:
ImplB3DPolyPolygon()34     ImplB3DPolyPolygon() : maPolygons()
35     {
36     }
37 
ImplB3DPolyPolygon(const::basegfx::B3DPolygon & rToBeCopied)38     explicit ImplB3DPolyPolygon(const ::basegfx::B3DPolygon& rToBeCopied) :
39         maPolygons(1,rToBeCopied)
40     {
41     }
42 
operator ==(const ImplB3DPolyPolygon & rPolygonList) const43     bool operator==(const ImplB3DPolyPolygon& rPolygonList) const
44     {
45         // same polygon count?
46         if(maPolygons.size() != rPolygonList.maPolygons.size())
47             return false;
48 
49         // compare polygon content
50         if(maPolygons != rPolygonList.maPolygons)
51             return false;
52 
53         return true;
54     }
55 
getB3DPolygon(sal_uInt32 nIndex) const56     const ::basegfx::B3DPolygon& getB3DPolygon(sal_uInt32 nIndex) const
57     {
58         return maPolygons[nIndex];
59     }
60 
setB3DPolygon(sal_uInt32 nIndex,const::basegfx::B3DPolygon & rPolygon)61     void setB3DPolygon(sal_uInt32 nIndex, const ::basegfx::B3DPolygon& rPolygon)
62     {
63         maPolygons[nIndex] = rPolygon;
64     }
65 
insert(sal_uInt32 nIndex,const::basegfx::B3DPolygon & rPolygon,sal_uInt32 nCount)66     void insert(sal_uInt32 nIndex, const ::basegfx::B3DPolygon& rPolygon, sal_uInt32 nCount)
67     {
68         if(nCount)
69         {
70             // add nCount copies of rPolygon
71             PolygonVector::iterator aIndex(maPolygons.begin());
72             if( nIndex )
73                 aIndex += nIndex;
74             maPolygons.insert(aIndex, nCount, rPolygon);
75         }
76     }
77 
insert(sal_uInt32 nIndex,const::basegfx::B3DPolyPolygon & rPolyPolygon)78     void insert(sal_uInt32 nIndex, const ::basegfx::B3DPolyPolygon& rPolyPolygon)
79     {
80         // add all polygons from rPolyPolygon
81         PolygonVector::iterator aIndex(maPolygons.begin());
82         if( nIndex )
83             aIndex += nIndex;
84         maPolygons.insert(aIndex, rPolyPolygon.begin(), rPolyPolygon.end());
85     }
86 
remove(sal_uInt32 nIndex,sal_uInt32 nCount)87     void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
88     {
89         if(nCount)
90         {
91             // remove polygon data
92             PolygonVector::iterator aStart(maPolygons.begin());
93             aStart += nIndex;
94             const PolygonVector::iterator aEnd(aStart + nCount);
95 
96             maPolygons.erase(aStart, aEnd);
97         }
98     }
99 
count() const100     sal_uInt32 count() const
101     {
102         return maPolygons.size();
103     }
104 
flip()105     void flip()
106     {
107         for (auto& aPolygon : maPolygons)
108             aPolygon.flip();
109     }
110 
removeDoublePoints()111     void removeDoublePoints()
112     {
113         for (auto& aPolygon : maPolygons)
114             aPolygon.removeDoublePoints();
115     }
116 
transform(const::basegfx::B3DHomMatrix & rMatrix)117     void transform(const ::basegfx::B3DHomMatrix& rMatrix)
118     {
119         for (auto& aPolygon : maPolygons)
120             aPolygon.transform(rMatrix);
121     }
122 
clearBColors()123     void clearBColors()
124     {
125         for (auto& aPolygon : maPolygons)
126             aPolygon.clearBColors();
127     }
128 
transformNormals(const::basegfx::B3DHomMatrix & rMatrix)129     void transformNormals(const ::basegfx::B3DHomMatrix& rMatrix)
130     {
131         for (auto& aPolygon : maPolygons)
132             aPolygon.transformNormals(rMatrix);
133     }
134 
clearNormals()135     void clearNormals()
136     {
137         for (auto& aPolygon : maPolygons)
138             aPolygon.clearNormals();
139     }
140 
transformTextureCoordinates(const::basegfx::B2DHomMatrix & rMatrix)141     void transformTextureCoordinates(const ::basegfx::B2DHomMatrix& rMatrix)
142     {
143         for (auto& aPolygon : maPolygons)
144             aPolygon.transformTextureCoordinates(rMatrix);
145     }
146 
clearTextureCoordinates()147     void clearTextureCoordinates()
148     {
149         for (auto& aPolygon : maPolygons)
150             aPolygon.clearTextureCoordinates();
151     }
152 
begin() const153     const basegfx::B3DPolygon* begin() const
154     {
155         if (maPolygons.empty())
156             return nullptr;
157         else
158             return maPolygons.data();
159     }
160 
end() const161     const basegfx::B3DPolygon* end() const
162     {
163         if (maPolygons.empty())
164             return nullptr;
165         else
166             return maPolygons.data() + maPolygons.size();
167     }
168 
begin()169     basegfx::B3DPolygon* begin()
170     {
171         if (maPolygons.empty())
172             return nullptr;
173         else
174             return maPolygons.data();
175     }
176 
end()177     basegfx::B3DPolygon* end()
178     {
179         if (maPolygons.empty())
180             return nullptr;
181         else
182             return maPolygons.data() + maPolygons.size();
183     }
184 };
185 
186 namespace basegfx
187 {
188     namespace {
189 
getDefaultPolyPolygon()190     B3DPolyPolygon::ImplType const & getDefaultPolyPolygon() {
191         static B3DPolyPolygon::ImplType const singleton;
192         return singleton;
193     }
194 
195     }
196 
B3DPolyPolygon()197     B3DPolyPolygon::B3DPolyPolygon() :
198         mpPolyPolygon(getDefaultPolyPolygon())
199     {
200     }
201 
202     B3DPolyPolygon::B3DPolyPolygon(const B3DPolyPolygon&) = default;
203 
204     B3DPolyPolygon::B3DPolyPolygon(B3DPolyPolygon&&) = default;
205 
B3DPolyPolygon(const B3DPolygon & rPolygon)206     B3DPolyPolygon::B3DPolyPolygon(const B3DPolygon& rPolygon) :
207         mpPolyPolygon( ImplB3DPolyPolygon(rPolygon) )
208     {
209     }
210 
211     B3DPolyPolygon::~B3DPolyPolygon() = default;
212 
213     B3DPolyPolygon& B3DPolyPolygon::operator=(const B3DPolyPolygon&) = default;
214 
215     B3DPolyPolygon& B3DPolyPolygon::operator=(B3DPolyPolygon&&) = default;
216 
operator ==(const B3DPolyPolygon & rPolyPolygon) const217     bool B3DPolyPolygon::operator==(const B3DPolyPolygon& rPolyPolygon) const
218     {
219         if(mpPolyPolygon.same_object(rPolyPolygon.mpPolyPolygon))
220             return true;
221 
222         return ((*mpPolyPolygon) == (*rPolyPolygon.mpPolyPolygon));
223     }
224 
operator !=(const B3DPolyPolygon & rPolyPolygon) const225     bool B3DPolyPolygon::operator!=(const B3DPolyPolygon& rPolyPolygon) const
226     {
227         return !(*this == rPolyPolygon);
228     }
229 
count() const230     sal_uInt32 B3DPolyPolygon::count() const
231     {
232         return mpPolyPolygon->count();
233     }
234 
getB3DPolygon(sal_uInt32 nIndex) const235     B3DPolygon const & B3DPolyPolygon::getB3DPolygon(sal_uInt32 nIndex) const
236     {
237         OSL_ENSURE(nIndex < mpPolyPolygon->count(), "B3DPolyPolygon access outside range (!)");
238 
239         return mpPolyPolygon->getB3DPolygon(nIndex);
240     }
241 
setB3DPolygon(sal_uInt32 nIndex,const B3DPolygon & rPolygon)242     void B3DPolyPolygon::setB3DPolygon(sal_uInt32 nIndex, const B3DPolygon& rPolygon)
243     {
244         OSL_ENSURE(nIndex < mpPolyPolygon->count(), "B3DPolyPolygon access outside range (!)");
245 
246         if(getB3DPolygon(nIndex) != rPolygon)
247             mpPolyPolygon->setB3DPolygon(nIndex, rPolygon);
248     }
249 
areBColorsUsed() const250     bool B3DPolyPolygon::areBColorsUsed() const
251     {
252         for(sal_uInt32 a(0); a < mpPolyPolygon->count(); a++)
253         {
254             if(mpPolyPolygon->getB3DPolygon(a).areBColorsUsed())
255             {
256                 return true;
257             }
258         }
259 
260         return false;
261     }
262 
clearBColors()263     void B3DPolyPolygon::clearBColors()
264     {
265         if(areBColorsUsed())
266             mpPolyPolygon->clearBColors();
267     }
268 
transformNormals(const B3DHomMatrix & rMatrix)269     void B3DPolyPolygon::transformNormals(const B3DHomMatrix& rMatrix)
270     {
271         if(!rMatrix.isIdentity())
272             mpPolyPolygon->transformNormals(rMatrix);
273     }
274 
areNormalsUsed() const275     bool B3DPolyPolygon::areNormalsUsed() const
276     {
277         for(sal_uInt32 a(0); a < mpPolyPolygon->count(); a++)
278         {
279             if(mpPolyPolygon->getB3DPolygon(a).areNormalsUsed())
280             {
281                 return true;
282             }
283         }
284 
285         return false;
286     }
287 
clearNormals()288     void B3DPolyPolygon::clearNormals()
289     {
290         if(areNormalsUsed())
291             mpPolyPolygon->clearNormals();
292     }
293 
transformTextureCoordinates(const B2DHomMatrix & rMatrix)294     void B3DPolyPolygon::transformTextureCoordinates(const B2DHomMatrix& rMatrix)
295     {
296         if(!rMatrix.isIdentity())
297             mpPolyPolygon->transformTextureCoordinates(rMatrix);
298     }
299 
areTextureCoordinatesUsed() const300     bool B3DPolyPolygon::areTextureCoordinatesUsed() const
301     {
302         for(sal_uInt32 a(0); a < mpPolyPolygon->count(); a++)
303         {
304             if(mpPolyPolygon->getB3DPolygon(a).areTextureCoordinatesUsed())
305             {
306                 return true;
307             }
308         }
309 
310         return false;
311     }
312 
clearTextureCoordinates()313     void B3DPolyPolygon::clearTextureCoordinates()
314     {
315         if(areTextureCoordinatesUsed())
316             mpPolyPolygon->clearTextureCoordinates();
317     }
318 
append(const B3DPolygon & rPolygon,sal_uInt32 nCount)319     void B3DPolyPolygon::append(const B3DPolygon& rPolygon, sal_uInt32 nCount)
320     {
321         if(nCount)
322             mpPolyPolygon->insert(mpPolyPolygon->count(), rPolygon, nCount);
323     }
324 
append(const B3DPolyPolygon & rPolyPolygon)325     void B3DPolyPolygon::append(const B3DPolyPolygon& rPolyPolygon)
326     {
327         if(rPolyPolygon.count())
328             mpPolyPolygon->insert(mpPolyPolygon->count(), rPolyPolygon);
329     }
330 
remove(sal_uInt32 nIndex,sal_uInt32 nCount)331     void B3DPolyPolygon::remove(sal_uInt32 nIndex, sal_uInt32 nCount)
332     {
333         OSL_ENSURE(nIndex + nCount <= mpPolyPolygon->count(), "B3DPolyPolygon Remove outside range (!)");
334 
335         if(nCount)
336             mpPolyPolygon->remove(nIndex, nCount);
337     }
338 
clear()339     void B3DPolyPolygon::clear()
340     {
341         mpPolyPolygon = getDefaultPolyPolygon();
342     }
343 
flip()344     void B3DPolyPolygon::flip()
345     {
346         mpPolyPolygon->flip();
347     }
348 
hasDoublePoints() const349     bool B3DPolyPolygon::hasDoublePoints() const
350     {
351         bool bRetval(false);
352 
353         for(sal_uInt32 a(0); !bRetval && a < mpPolyPolygon->count(); a++)
354         {
355             if(mpPolyPolygon->getB3DPolygon(a).hasDoublePoints())
356             {
357                 bRetval = true;
358             }
359         }
360 
361         return bRetval;
362     }
363 
removeDoublePoints()364     void B3DPolyPolygon::removeDoublePoints()
365     {
366         if(hasDoublePoints())
367             mpPolyPolygon->removeDoublePoints();
368     }
369 
transform(const B3DHomMatrix & rMatrix)370     void B3DPolyPolygon::transform(const B3DHomMatrix& rMatrix)
371     {
372         if(mpPolyPolygon->count() && !rMatrix.isIdentity())
373         {
374             mpPolyPolygon->transform(rMatrix);
375         }
376     }
377 
begin() const378     const B3DPolygon* B3DPolyPolygon::begin() const
379     {
380         return mpPolyPolygon->begin();
381     }
382 
end() const383     const B3DPolygon* B3DPolyPolygon::end() const
384     {
385         return mpPolyPolygon->end();
386     }
387 
begin()388     B3DPolygon* B3DPolyPolygon::begin()
389     {
390         return mpPolyPolygon->begin();
391     }
392 
end()393     B3DPolygon* B3DPolyPolygon::end()
394     {
395         return mpPolyPolygon->end();
396     }
397 } // end of namespace basegfx
398 
399 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
400