/src/libreoffice/basegfx/source/polygon/b2dpolypolygon.cxx
Line | Count | Source |
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 <sal/config.h> |
21 | | |
22 | | #include <cassert> |
23 | | #include <utility> |
24 | | |
25 | | #include <basegfx/polygon/b2dpolypolygon.hxx> |
26 | | #include <basegfx/polygon/b2dpolygon.hxx> |
27 | | #include <basegfx/matrix/b2dhommatrix.hxx> |
28 | | #include <basegfx/utils/systemdependentdata.hxx> |
29 | | |
30 | | namespace basegfx |
31 | | { |
32 | | |
33 | | class ImplB2DPolyPolygon |
34 | | { |
35 | | basegfx::B2DPolygonVector maPolygons; |
36 | | // we do not want to 'modify' the ImplB2DPolyPolygon, |
37 | | // but add buffered data that is valid for all referencing instances |
38 | | mutable std::unique_ptr<basegfx::SystemDependentDataHolder> mpSystemDependentDataHolder; |
39 | | |
40 | | public: |
41 | | ImplB2DPolyPolygon() |
42 | 4.00M | { |
43 | 4.00M | } |
44 | | |
45 | | explicit ImplB2DPolyPolygon(ImplB2DPolyPolygon&& rSource) noexcept |
46 | 6.51M | : maPolygons(std::move(rSource.maPolygons)) |
47 | 6.51M | { |
48 | 6.51M | } |
49 | | |
50 | | explicit ImplB2DPolyPolygon(const ImplB2DPolyPolygon& rSource) |
51 | 278k | : maPolygons(rSource.maPolygons) |
52 | 278k | { |
53 | 278k | } |
54 | | |
55 | | explicit ImplB2DPolyPolygon(const basegfx::B2DPolygon& rToBeCopied) |
56 | 6.51M | : maPolygons(1,rToBeCopied) |
57 | 6.51M | { |
58 | 6.51M | } |
59 | | |
60 | | ImplB2DPolyPolygon& operator=(const ImplB2DPolyPolygon& rSource) |
61 | 66.5k | { |
62 | 66.5k | if (this != &rSource) |
63 | 66.5k | { |
64 | 66.5k | maPolygons = rSource.maPolygons; |
65 | 66.5k | mpSystemDependentDataHolder.reset(); |
66 | 66.5k | } |
67 | | |
68 | 66.5k | return *this; |
69 | 66.5k | } |
70 | | |
71 | | void addOrReplaceSystemDependentData(basegfx::SystemDependentData_SharedPtr& rData) const |
72 | 0 | { |
73 | 0 | if(!mpSystemDependentDataHolder) |
74 | 0 | { |
75 | 0 | mpSystemDependentDataHolder.reset(new basegfx::SystemDependentDataHolder()); |
76 | 0 | } |
77 | |
|
78 | 0 | mpSystemDependentDataHolder->addOrReplaceSystemDependentData(rData); |
79 | 0 | } |
80 | | |
81 | | basegfx::SystemDependentData_SharedPtr getSystemDependentData(SDD_Type aType) const |
82 | 3.61M | { |
83 | 3.61M | if(!mpSystemDependentDataHolder) |
84 | 3.61M | { |
85 | 3.61M | return basegfx::SystemDependentData_SharedPtr(); |
86 | 3.61M | } |
87 | | |
88 | 0 | return mpSystemDependentDataHolder->getSystemDependentData(aType); |
89 | 3.61M | } |
90 | | |
91 | | bool operator==(const ImplB2DPolyPolygon& rPolygonList) const |
92 | 211k | { |
93 | 211k | return maPolygons == rPolygonList.maPolygons; |
94 | 211k | } |
95 | | |
96 | | const basegfx::B2DPolygon& getB2DPolygon(sal_uInt32 nIndex) const |
97 | 38.5M | { |
98 | 38.5M | assert(nIndex < maPolygons.size()); |
99 | 38.5M | return maPolygons[nIndex]; |
100 | 38.5M | } |
101 | | |
102 | | void setB2DPolygon(sal_uInt32 nIndex, const basegfx::B2DPolygon& rPolygon) |
103 | 29.1k | { |
104 | 29.1k | assert(nIndex < maPolygons.size()); |
105 | 29.1k | maPolygons[nIndex] = rPolygon; |
106 | 29.1k | } |
107 | | |
108 | | void insert(sal_uInt32 nIndex, const basegfx::B2DPolygon& rPolygon, sal_uInt32 nCount) |
109 | 4.79M | { |
110 | 4.79M | assert(nCount > 0); |
111 | 4.79M | assert(nIndex <= maPolygons.size()); |
112 | | // add nCount copies of rPolygon |
113 | 4.79M | maPolygons.insert(maPolygons.begin() + nIndex, nCount, rPolygon); |
114 | 4.79M | } |
115 | | |
116 | | void append(const basegfx::B2DPolygon& rPolygon, sal_uInt32 nCount) |
117 | 4.79M | { |
118 | 4.79M | insert(maPolygons.size(), rPolygon, nCount); |
119 | 4.79M | } |
120 | | |
121 | | void reserve(sal_uInt32 nCount) |
122 | 1.38k | { |
123 | 1.38k | maPolygons.reserve(nCount); |
124 | 1.38k | } |
125 | | |
126 | | void insert(sal_uInt32 nIndex, const basegfx::B2DPolyPolygon& rPolyPolygon) |
127 | 26.9k | { |
128 | 26.9k | assert(nIndex <= maPolygons.size()); |
129 | | // add nCount polygons from rPolyPolygon |
130 | 26.9k | maPolygons.insert(maPolygons.begin() + nIndex, rPolyPolygon.begin(), rPolyPolygon.end()); |
131 | 26.9k | } |
132 | | |
133 | | void append(const basegfx::B2DPolyPolygon& rPolyPolygon) |
134 | 26.9k | { |
135 | 26.9k | insert(maPolygons.size(), rPolyPolygon); |
136 | 26.9k | } |
137 | | |
138 | | void remove(sal_uInt32 nIndex, sal_uInt32 nCount) |
139 | 0 | { |
140 | 0 | assert(nCount > 0); |
141 | 0 | assert(nIndex + nCount <= maPolygons.size()); |
142 | | // remove polygon data |
143 | 0 | auto aStart(maPolygons.begin() + nIndex); |
144 | 0 | auto aEnd(aStart + nCount); |
145 | |
|
146 | 0 | maPolygons.erase(aStart, aEnd); |
147 | 0 | } |
148 | | |
149 | | sal_uInt32 count() const |
150 | 50.4M | { |
151 | 50.4M | return maPolygons.size(); |
152 | 50.4M | } |
153 | | |
154 | | void setClosed(bool bNew) |
155 | 45.3k | { |
156 | 45.3k | for(basegfx::B2DPolygon & rPolygon : maPolygons) |
157 | 58.8k | { |
158 | 58.8k | rPolygon.setClosed(bNew); |
159 | 58.8k | } |
160 | 45.3k | } |
161 | | |
162 | | void flip() |
163 | 0 | { |
164 | 0 | for (auto& aPolygon : maPolygons) |
165 | 0 | aPolygon.flip(); |
166 | 0 | } |
167 | | |
168 | | void removeDoublePoints() |
169 | 2.39k | { |
170 | 2.39k | for (auto& aPolygon : maPolygons) |
171 | 56.3k | aPolygon.removeDoublePoints(); |
172 | 2.39k | } |
173 | | |
174 | | void transform(const basegfx::B2DHomMatrix& rMatrix) |
175 | 289k | { |
176 | 289k | for (auto& aPolygon : maPolygons) |
177 | 312k | aPolygon.transform(rMatrix); |
178 | 289k | } |
179 | | |
180 | | void translate(double fTranslateX, double fTranslateY) |
181 | 50.4k | { |
182 | 50.4k | for (auto& aPolygon : maPolygons) |
183 | 63.1k | aPolygon.translate(fTranslateX, fTranslateY); |
184 | 50.4k | } |
185 | | |
186 | | void makeUnique() |
187 | 0 | { |
188 | 0 | for (auto& aPolygon : maPolygons) |
189 | 0 | aPolygon.makeUnique(); |
190 | 0 | } |
191 | | |
192 | | const basegfx::B2DPolygon* begin() const |
193 | 4.07M | { |
194 | 4.07M | if (maPolygons.empty()) |
195 | 633 | return nullptr; |
196 | 4.07M | else |
197 | 4.07M | return maPolygons.data(); |
198 | 4.07M | } |
199 | | |
200 | | const basegfx::B2DPolygon* end() const |
201 | 4.07M | { |
202 | 4.07M | if (maPolygons.empty()) |
203 | 633 | return nullptr; |
204 | 4.07M | else |
205 | 4.07M | return maPolygons.data() + maPolygons.size(); |
206 | 4.07M | } |
207 | | |
208 | | basegfx::B2DPolygon* begin() |
209 | 796k | { |
210 | 796k | if (maPolygons.empty()) |
211 | 0 | return nullptr; |
212 | 796k | else |
213 | 796k | return maPolygons.data(); |
214 | 796k | } |
215 | | |
216 | | basegfx::B2DPolygon* end() |
217 | 796k | { |
218 | 796k | if (maPolygons.empty()) |
219 | 0 | return nullptr; |
220 | 796k | else |
221 | 796k | return maPolygons.data() + maPolygons.size(); |
222 | 796k | } |
223 | | }; |
224 | | |
225 | 3.93M | B2DPolyPolygon::B2DPolyPolygon() = default; |
226 | | |
227 | 3.32M | B2DPolyPolygon::B2DPolyPolygon(const B2DPolyPolygon&) = default; |
228 | | |
229 | 1.20M | B2DPolyPolygon::B2DPolyPolygon(B2DPolyPolygon&&) = default; |
230 | | |
231 | | B2DPolyPolygon::B2DPolyPolygon(const B2DPolygon& rPolygon) : |
232 | 6.51M | mpPolyPolygon( ImplB2DPolyPolygon(rPolygon) ) |
233 | 6.51M | { |
234 | 6.51M | } |
235 | | |
236 | 14.9M | B2DPolyPolygon::~B2DPolyPolygon() = default; |
237 | | |
238 | 755k | B2DPolyPolygon& B2DPolyPolygon::operator=(const B2DPolyPolygon&) = default; |
239 | | |
240 | 954k | B2DPolyPolygon& B2DPolyPolygon::operator=(B2DPolyPolygon&&) = default; |
241 | | |
242 | | void B2DPolyPolygon::makeUnique() |
243 | 0 | { |
244 | 0 | mpPolyPolygon->makeUnique(); // non-const cow_wrapper::operator-> calls make_unique |
245 | 0 | } |
246 | | |
247 | | bool B2DPolyPolygon::operator==(const B2DPolyPolygon& rPolyPolygon) const |
248 | 277k | { |
249 | 277k | if(mpPolyPolygon.same_object(rPolyPolygon.mpPolyPolygon)) |
250 | 65.1k | return true; |
251 | | |
252 | 211k | return ((*mpPolyPolygon) == (*rPolyPolygon.mpPolyPolygon)); |
253 | 277k | } |
254 | | |
255 | | sal_uInt32 B2DPolyPolygon::count() const |
256 | 50.4M | { |
257 | 50.4M | return mpPolyPolygon->count(); |
258 | 50.4M | } |
259 | | |
260 | | B2DPolygon const & B2DPolyPolygon::getB2DPolygon(sal_uInt32 nIndex) const |
261 | 38.5M | { |
262 | 38.5M | return mpPolyPolygon->getB2DPolygon(nIndex); |
263 | 38.5M | } |
264 | | |
265 | | void B2DPolyPolygon::setB2DPolygon(sal_uInt32 nIndex, const B2DPolygon& rPolygon) |
266 | 29.1k | { |
267 | 29.1k | if(getB2DPolygon(nIndex) != rPolygon) |
268 | 29.1k | mpPolyPolygon->setB2DPolygon(nIndex, rPolygon); |
269 | 29.1k | } |
270 | | |
271 | | bool B2DPolyPolygon::areControlPointsUsed() const |
272 | 812k | { |
273 | 1.73M | for(sal_uInt32 a(0); a < count(); a++) |
274 | 944k | { |
275 | 944k | if(getB2DPolygon(a).areControlPointsUsed()) |
276 | 17.4k | { |
277 | 17.4k | return true; |
278 | 17.4k | } |
279 | 944k | } |
280 | | |
281 | 795k | return false; |
282 | 812k | } |
283 | | |
284 | | void B2DPolyPolygon::insert(sal_uInt32 nIndex, const B2DPolygon& rPolygon, sal_uInt32 nCount) |
285 | 0 | { |
286 | 0 | if(nCount) |
287 | 0 | mpPolyPolygon->insert(nIndex, rPolygon, nCount); |
288 | 0 | } |
289 | | |
290 | | void B2DPolyPolygon::append(const B2DPolygon& rPolygon, sal_uInt32 nCount) |
291 | 4.79M | { |
292 | 4.79M | if(nCount) |
293 | 4.79M | mpPolyPolygon->append(rPolygon, nCount); |
294 | 4.79M | } |
295 | | |
296 | | void B2DPolyPolygon::reserve(sal_uInt32 nCount) |
297 | 1.38k | { |
298 | 1.38k | if(nCount) |
299 | 1.38k | mpPolyPolygon->reserve(nCount); |
300 | 1.38k | } |
301 | | |
302 | | B2DPolyPolygon B2DPolyPolygon::getDefaultAdaptiveSubdivision() const |
303 | 0 | { |
304 | 0 | B2DPolyPolygon aRetval; |
305 | 0 | if (count()) |
306 | 0 | { |
307 | 0 | ImplB2DPolyPolygon& dest = *aRetval.mpPolyPolygon; |
308 | 0 | dest.reserve(count()); |
309 | |
|
310 | 0 | for (sal_uInt32 a(0); a < count(); a++) |
311 | 0 | { |
312 | 0 | dest.append(getB2DPolygon(a).getDefaultAdaptiveSubdivision(), 1); |
313 | 0 | } |
314 | 0 | } |
315 | |
|
316 | 0 | return aRetval; |
317 | 0 | } |
318 | | |
319 | | B2DRange B2DPolyPolygon::getB2DRange() const |
320 | 15.2M | { |
321 | 15.2M | B2DRange aRetval; |
322 | | |
323 | 33.0M | for(sal_uInt32 a(0); a < count(); a++) |
324 | 17.8M | { |
325 | 17.8M | aRetval.expand(getB2DPolygon(a).getB2DRange()); |
326 | 17.8M | } |
327 | | |
328 | 15.2M | return aRetval; |
329 | 15.2M | } |
330 | | |
331 | | void B2DPolyPolygon::insert(sal_uInt32 nIndex, const B2DPolyPolygon& rPolyPolygon) |
332 | 0 | { |
333 | 0 | if(rPolyPolygon.count()) |
334 | 0 | mpPolyPolygon->insert(nIndex, rPolyPolygon); |
335 | 0 | } |
336 | | |
337 | | void B2DPolyPolygon::append(const B2DPolyPolygon& rPolyPolygon) |
338 | 27.8k | { |
339 | 27.8k | if(rPolyPolygon.count()) |
340 | 26.9k | mpPolyPolygon->append(rPolyPolygon); |
341 | 27.8k | } |
342 | | |
343 | | void B2DPolyPolygon::remove(sal_uInt32 nIndex, sal_uInt32 nCount) |
344 | 0 | { |
345 | 0 | if(nCount) |
346 | 0 | mpPolyPolygon->remove(nIndex, nCount); |
347 | 0 | } |
348 | | |
349 | | void B2DPolyPolygon::clear() |
350 | 66.5k | { |
351 | 66.5k | *mpPolyPolygon = ImplB2DPolyPolygon(); |
352 | 66.5k | } |
353 | | |
354 | | bool B2DPolyPolygon::isClosed() const |
355 | 911k | { |
356 | | // PolyPOlygon is closed when all contained Polygons are closed or |
357 | | // no Polygon exists. |
358 | 2.18M | for(sal_uInt32 a(0); a < count(); a++) |
359 | 1.40M | { |
360 | 1.40M | if(!getB2DPolygon(a).isClosed()) |
361 | 135k | return false; |
362 | 1.40M | } |
363 | | |
364 | 776k | return true; |
365 | 911k | } |
366 | | |
367 | | void B2DPolyPolygon::setClosed(bool bNew) |
368 | 56.6k | { |
369 | 56.6k | if(bNew != isClosed()) |
370 | 45.3k | mpPolyPolygon->setClosed(bNew); |
371 | 56.6k | } |
372 | | |
373 | | void B2DPolyPolygon::flip() |
374 | 0 | { |
375 | 0 | if(count()) |
376 | 0 | { |
377 | 0 | mpPolyPolygon->flip(); |
378 | 0 | } |
379 | 0 | } |
380 | | |
381 | | bool B2DPolyPolygon::hasDoublePoints() const |
382 | 337k | { |
383 | 679k | for(sal_uInt32 a(0); a < count(); a++) |
384 | 343k | { |
385 | 343k | if(getB2DPolygon(a).hasDoublePoints()) |
386 | 2.39k | return true; |
387 | 343k | } |
388 | | |
389 | 335k | return false; |
390 | 337k | } |
391 | | |
392 | | void B2DPolyPolygon::removeDoublePoints() |
393 | 337k | { |
394 | 337k | if(hasDoublePoints()) |
395 | 2.39k | mpPolyPolygon->removeDoublePoints(); |
396 | 337k | } |
397 | | |
398 | | void B2DPolyPolygon::transform(const B2DHomMatrix& rMatrix) |
399 | 306k | { |
400 | 306k | if(count() && !rMatrix.isIdentity()) |
401 | 289k | { |
402 | 289k | mpPolyPolygon->transform(rMatrix); |
403 | 289k | } |
404 | 306k | } |
405 | | |
406 | | void B2DPolyPolygon::translate(double fTranslateX, double fTranslateY) |
407 | 54.4k | { |
408 | 54.4k | if(count()) |
409 | 50.4k | { |
410 | 50.4k | mpPolyPolygon->translate(fTranslateX, fTranslateY); |
411 | 50.4k | } |
412 | 54.4k | } |
413 | | |
414 | | const B2DPolygon* B2DPolyPolygon::begin() const |
415 | 4.07M | { |
416 | 4.07M | return mpPolyPolygon->begin(); |
417 | 4.07M | } |
418 | | |
419 | | const B2DPolygon* B2DPolyPolygon::end() const |
420 | 4.07M | { |
421 | 4.07M | return mpPolyPolygon->end(); |
422 | 4.07M | } |
423 | | |
424 | | B2DPolygon* B2DPolyPolygon::begin() |
425 | 796k | { |
426 | 796k | return mpPolyPolygon->begin(); |
427 | 796k | } |
428 | | |
429 | | B2DPolygon* B2DPolyPolygon::end() |
430 | 796k | { |
431 | 796k | return mpPolyPolygon->end(); |
432 | 796k | } |
433 | | |
434 | | void B2DPolyPolygon::addOrReplaceSystemDependentDataInternal(SystemDependentData_SharedPtr& rData) const |
435 | 0 | { |
436 | 0 | mpPolyPolygon->addOrReplaceSystemDependentData(rData); |
437 | 0 | } |
438 | | |
439 | | SystemDependentData_SharedPtr B2DPolyPolygon::getSystemDependantDataInternal(SDD_Type aType) const |
440 | 3.61M | { |
441 | 3.61M | return mpPolyPolygon->getSystemDependentData(aType); |
442 | 3.61M | } |
443 | | |
444 | | } // end of namespace basegfx |
445 | | |
446 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |