1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <basegfx/polygon/b2dpolypolygon.hxx>
21 #include <osl/diagnose.h>
22 #include <basegfx/polygon/b2dpolygon.hxx>
23 #include <basegfx/matrix/b2dhommatrix.hxx>
24 #include <basegfx/utils/systemdependentdata.hxx>
27 class ImplB2DPolyPolygon
29 basegfx::B2DPolygonVector maPolygons
;
30 std::unique_ptr
< basegfx::SystemDependentDataHolder
> mpSystemDependentDataHolder
;
35 mpSystemDependentDataHolder()
39 explicit ImplB2DPolyPolygon(const ImplB2DPolyPolygon
& rSource
)
40 : maPolygons(rSource
.maPolygons
),
41 mpSystemDependentDataHolder()
45 explicit ImplB2DPolyPolygon(const basegfx::B2DPolygon
& rToBeCopied
)
46 : maPolygons(1,rToBeCopied
),
47 mpSystemDependentDataHolder()
51 ImplB2DPolyPolygon
& operator=(const ImplB2DPolyPolygon
& rSource
)
55 maPolygons
= rSource
.maPolygons
;
56 mpSystemDependentDataHolder
.reset();
62 void addOrReplaceSystemDependentData(basegfx::SystemDependentData_SharedPtr
& rData
)
64 if(!mpSystemDependentDataHolder
)
66 mpSystemDependentDataHolder
.reset(new basegfx::SystemDependentDataHolder());
69 mpSystemDependentDataHolder
->addOrReplaceSystemDependentData(rData
);
72 basegfx::SystemDependentData_SharedPtr
getSystemDependentData(size_t hash_code
) const
74 if(!mpSystemDependentDataHolder
)
76 return basegfx::SystemDependentData_SharedPtr();
79 return mpSystemDependentDataHolder
->getSystemDependentData(hash_code
);
82 bool operator==(const ImplB2DPolyPolygon
& rPolygonList
) const
84 return maPolygons
== rPolygonList
.maPolygons
;
87 const basegfx::B2DPolygon
& getB2DPolygon(sal_uInt32 nIndex
) const
89 return maPolygons
[nIndex
];
92 void setB2DPolygon(sal_uInt32 nIndex
, const basegfx::B2DPolygon
& rPolygon
)
94 maPolygons
[nIndex
] = rPolygon
;
97 void insert(sal_uInt32 nIndex
, const basegfx::B2DPolygon
& rPolygon
, sal_uInt32 nCount
)
101 // add nCount copies of rPolygon
102 basegfx::B2DPolygonVector::iterator
aIndex(maPolygons
.begin());
105 maPolygons
.insert(aIndex
, nCount
, rPolygon
);
109 void insert(sal_uInt32 nIndex
, const basegfx::B2DPolyPolygon
& rPolyPolygon
)
111 // add nCount polygons from rPolyPolygon
112 basegfx::B2DPolygonVector::iterator
aIndex(maPolygons
.begin());
115 maPolygons
.insert(aIndex
, rPolyPolygon
.begin(), rPolyPolygon
.end());
118 void remove(sal_uInt32 nIndex
, sal_uInt32 nCount
)
122 // remove polygon data
123 basegfx::B2DPolygonVector::iterator
aStart(maPolygons
.begin());
125 const basegfx::B2DPolygonVector::iterator
aEnd(aStart
+ nCount
);
127 maPolygons
.erase(aStart
, aEnd
);
131 sal_uInt32
count() const
133 return maPolygons
.size();
136 void setClosed(bool bNew
)
138 for(basegfx::B2DPolygon
& rPolygon
: maPolygons
)
140 rPolygon
.setClosed(bNew
);
146 for (auto& aPolygon
: maPolygons
)
150 void removeDoublePoints()
152 for (auto& aPolygon
: maPolygons
)
153 aPolygon
.removeDoublePoints();
156 void transform(const basegfx::B2DHomMatrix
& rMatrix
)
158 for (auto& aPolygon
: maPolygons
)
159 aPolygon
.transform(rMatrix
);
164 for (auto& aPolygon
: maPolygons
)
165 aPolygon
.makeUnique();
168 const basegfx::B2DPolygon
* begin() const
170 if (maPolygons
.empty())
173 return maPolygons
.data();
176 const basegfx::B2DPolygon
* end() const
178 if (maPolygons
.empty())
181 return maPolygons
.data() + maPolygons
.size();
184 basegfx::B2DPolygon
* begin()
186 if (maPolygons
.empty())
189 return maPolygons
.data();
192 basegfx::B2DPolygon
* end()
194 if (maPolygons
.empty())
197 return maPolygons
.data() + maPolygons
.size();
204 B2DPolyPolygon::B2DPolyPolygon() = default;
206 B2DPolyPolygon::B2DPolyPolygon(const B2DPolyPolygon
&) = default;
208 B2DPolyPolygon::B2DPolyPolygon(B2DPolyPolygon
&&) = default;
210 B2DPolyPolygon::B2DPolyPolygon(const B2DPolygon
& rPolygon
) :
211 mpPolyPolygon( ImplB2DPolyPolygon(rPolygon
) )
215 B2DPolyPolygon::~B2DPolyPolygon() = default;
217 B2DPolyPolygon
& B2DPolyPolygon::operator=(const B2DPolyPolygon
&) = default;
219 B2DPolyPolygon
& B2DPolyPolygon::operator=(B2DPolyPolygon
&&) = default;
221 void B2DPolyPolygon::makeUnique()
223 mpPolyPolygon
.make_unique();
224 mpPolyPolygon
->makeUnique();
227 bool B2DPolyPolygon::operator==(const B2DPolyPolygon
& rPolyPolygon
) const
229 if(mpPolyPolygon
.same_object(rPolyPolygon
.mpPolyPolygon
))
232 return ((*mpPolyPolygon
) == (*rPolyPolygon
.mpPolyPolygon
));
235 bool B2DPolyPolygon::operator!=(const B2DPolyPolygon
& rPolyPolygon
) const
237 return !((*this) == rPolyPolygon
);
240 sal_uInt32
B2DPolyPolygon::count() const
242 return mpPolyPolygon
->count();
245 B2DPolygon
const & B2DPolyPolygon::getB2DPolygon(sal_uInt32 nIndex
) const
247 OSL_ENSURE(nIndex
< mpPolyPolygon
->count(), "B2DPolyPolygon access outside range (!)");
249 return mpPolyPolygon
->getB2DPolygon(nIndex
);
252 void B2DPolyPolygon::setB2DPolygon(sal_uInt32 nIndex
, const B2DPolygon
& rPolygon
)
254 OSL_ENSURE(nIndex
< mpPolyPolygon
->count(), "B2DPolyPolygon access outside range (!)");
256 if(getB2DPolygon(nIndex
) != rPolygon
)
257 mpPolyPolygon
->setB2DPolygon(nIndex
, rPolygon
);
260 bool B2DPolyPolygon::areControlPointsUsed() const
262 for(sal_uInt32
a(0); a
< mpPolyPolygon
->count(); a
++)
264 const B2DPolygon
& rPolygon
= mpPolyPolygon
->getB2DPolygon(a
);
266 if(rPolygon
.areControlPointsUsed())
275 void B2DPolyPolygon::insert(sal_uInt32 nIndex
, const B2DPolygon
& rPolygon
, sal_uInt32 nCount
)
277 OSL_ENSURE(nIndex
<= mpPolyPolygon
->count(), "B2DPolyPolygon Insert outside range (!)");
280 mpPolyPolygon
->insert(nIndex
, rPolygon
, nCount
);
283 void B2DPolyPolygon::append(const B2DPolygon
& rPolygon
, sal_uInt32 nCount
)
286 mpPolyPolygon
->insert(mpPolyPolygon
->count(), rPolygon
, nCount
);
289 B2DPolyPolygon
B2DPolyPolygon::getDefaultAdaptiveSubdivision() const
291 B2DPolyPolygon aRetval
;
293 for(sal_uInt32
a(0); a
< mpPolyPolygon
->count(); a
++)
295 aRetval
.append(mpPolyPolygon
->getB2DPolygon(a
).getDefaultAdaptiveSubdivision());
301 B2DRange
B2DPolyPolygon::getB2DRange() const
305 for(sal_uInt32
a(0); a
< mpPolyPolygon
->count(); a
++)
307 aRetval
.expand(mpPolyPolygon
->getB2DPolygon(a
).getB2DRange());
313 void B2DPolyPolygon::insert(sal_uInt32 nIndex
, const B2DPolyPolygon
& rPolyPolygon
)
315 OSL_ENSURE(nIndex
<= mpPolyPolygon
->count(), "B2DPolyPolygon Insert outside range (!)");
317 if(rPolyPolygon
.count())
318 mpPolyPolygon
->insert(nIndex
, rPolyPolygon
);
321 void B2DPolyPolygon::append(const B2DPolyPolygon
& rPolyPolygon
)
323 if(rPolyPolygon
.count())
324 mpPolyPolygon
->insert(mpPolyPolygon
->count(), rPolyPolygon
);
327 void B2DPolyPolygon::remove(sal_uInt32 nIndex
, sal_uInt32 nCount
)
329 OSL_ENSURE(nIndex
+ nCount
<= mpPolyPolygon
->count(), "B2DPolyPolygon Remove outside range (!)");
332 mpPolyPolygon
->remove(nIndex
, nCount
);
335 void B2DPolyPolygon::clear()
337 *mpPolyPolygon
= ImplB2DPolyPolygon();
340 bool B2DPolyPolygon::isClosed() const
344 // PolyPOlygon is closed when all contained Polygons are closed or
345 // no Polygon exists.
346 for(sal_uInt32
a(0); bRetval
&& a
< mpPolyPolygon
->count(); a
++)
348 if(!mpPolyPolygon
->getB2DPolygon(a
).isClosed())
357 void B2DPolyPolygon::setClosed(bool bNew
)
359 if(bNew
!= isClosed())
360 mpPolyPolygon
->setClosed(bNew
);
363 void B2DPolyPolygon::flip()
365 if(mpPolyPolygon
->count())
367 mpPolyPolygon
->flip();
371 bool B2DPolyPolygon::hasDoublePoints() const
375 for(sal_uInt32
a(0); !bRetval
&& a
< mpPolyPolygon
->count(); a
++)
377 if(mpPolyPolygon
->getB2DPolygon(a
).hasDoublePoints())
386 void B2DPolyPolygon::removeDoublePoints()
388 if(hasDoublePoints())
389 mpPolyPolygon
->removeDoublePoints();
392 void B2DPolyPolygon::transform(const B2DHomMatrix
& rMatrix
)
394 if(mpPolyPolygon
->count() && !rMatrix
.isIdentity())
396 mpPolyPolygon
->transform(rMatrix
);
400 const B2DPolygon
* B2DPolyPolygon::begin() const
402 return mpPolyPolygon
->begin();
405 const B2DPolygon
* B2DPolyPolygon::end() const
407 return mpPolyPolygon
->end();
410 B2DPolygon
* B2DPolyPolygon::begin()
412 return mpPolyPolygon
->begin();
415 B2DPolygon
* B2DPolyPolygon::end()
417 return mpPolyPolygon
->end();
420 void B2DPolyPolygon::addOrReplaceSystemDependentDataInternal(SystemDependentData_SharedPtr
& rData
) const
422 // Need to get ImplB2DPolyPolygon* from cow_wrapper *without*
423 // calling make_unique() here - we do not want to
424 // 'modify' the ImplB2DPolyPolygon, but add buffered data that
425 // is valid for all referencing instances
426 const B2DPolyPolygon
* pMe(this);
427 const ImplB2DPolyPolygon
* pMyImpl(pMe
->mpPolyPolygon
.get());
429 const_cast<ImplB2DPolyPolygon
*>(pMyImpl
)->addOrReplaceSystemDependentData(rData
);
432 SystemDependentData_SharedPtr
B2DPolyPolygon::getSystemDependantDataInternal(size_t hash_code
) const
434 return mpPolyPolygon
->getSystemDependentData(hash_code
);
437 } // end of namespace basegfx
439 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */