Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <osl/diagnose.h>
30 : : #include <basegfx/polygon/b2dpolygon.hxx>
31 : : #include <basegfx/point/b2dpoint.hxx>
32 : : #include <basegfx/vector/b2dvector.hxx>
33 : : #include <basegfx/matrix/b2dhommatrix.hxx>
34 : : #include <basegfx/curve/b2dcubicbezier.hxx>
35 : : #include <rtl/instance.hxx>
36 : : #include <basegfx/polygon/b2dpolygontools.hxx>
37 : : #include <boost/scoped_ptr.hpp>
38 : : #include <vector>
39 : : #include <algorithm>
40 : :
41 : : //////////////////////////////////////////////////////////////////////////////
42 : :
43 : 60371702 : struct CoordinateData2D : public basegfx::B2DPoint
44 : : {
45 : : public:
46 : 0 : CoordinateData2D() {}
47 : :
48 : 7940099 : explicit CoordinateData2D(const basegfx::B2DPoint& rData)
49 : 7940099 : : B2DPoint(rData)
50 : 7940099 : {}
51 : :
52 : 11021722 : CoordinateData2D& operator=(const basegfx::B2DPoint& rData)
53 : : {
54 : 11021722 : B2DPoint::operator=(rData);
55 : 11021722 : return *this;
56 : : }
57 : :
58 : 2886881 : void transform(const basegfx::B2DHomMatrix& rMatrix)
59 : : {
60 : 2886881 : *this *= rMatrix;
61 : 2886881 : }
62 : : };
63 : :
64 : : //////////////////////////////////////////////////////////////////////////////
65 : :
66 : 5030679 : class CoordinateDataArray2D
67 : : {
68 : : typedef ::std::vector< CoordinateData2D > CoordinateData2DVector;
69 : :
70 : : CoordinateData2DVector maVector;
71 : :
72 : : public:
73 : 206 : explicit CoordinateDataArray2D(sal_uInt32 nCount)
74 : 206 : : maVector(nCount)
75 : : {
76 : 206 : }
77 : :
78 : 5030695 : explicit CoordinateDataArray2D(const CoordinateDataArray2D& rOriginal)
79 : 5030695 : : maVector(rOriginal.maVector)
80 : : {
81 : 5030695 : }
82 : :
83 : 0 : CoordinateDataArray2D(const CoordinateDataArray2D& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount)
84 [ # # ][ # # ]: 0 : : maVector(rOriginal.maVector.begin() + nIndex, rOriginal.maVector.begin() + (nIndex + nCount))
[ # # ]
85 : : {
86 : 0 : }
87 : :
88 : 13115853 : sal_uInt32 count() const
89 : : {
90 : 13115853 : return maVector.size();
91 : : }
92 : :
93 : 60738 : bool operator==(const CoordinateDataArray2D& rCandidate) const
94 : : {
95 : 60738 : return (maVector == rCandidate.maVector);
96 : : }
97 : :
98 : 62760160 : const basegfx::B2DPoint& getCoordinate(sal_uInt32 nIndex) const
99 : : {
100 : 62760160 : return maVector[nIndex];
101 : : }
102 : :
103 : 11021722 : void setCoordinate(sal_uInt32 nIndex, const basegfx::B2DPoint& rValue)
104 : : {
105 : 11021722 : maVector[nIndex] = rValue;
106 : 11021722 : }
107 : :
108 : 245 : void reserve(sal_uInt32 nCount)
109 : : {
110 : 245 : maVector.reserve(nCount);
111 : 245 : }
112 : :
113 : 4927504 : void append(const CoordinateData2D& rValue)
114 : : {
115 : 4927504 : maVector.push_back(rValue);
116 : 4927504 : }
117 : :
118 : 3012595 : void insert(sal_uInt32 nIndex, const CoordinateData2D& rValue, sal_uInt32 nCount)
119 : : {
120 [ + - ]: 3012595 : if(nCount)
121 : : {
122 : : // add nCount copies of rValue
123 : 3012595 : CoordinateData2DVector::iterator aIndex(maVector.begin());
124 : 3012595 : aIndex += nIndex;
125 [ + - ]: 3012595 : maVector.insert(aIndex, nCount, rValue);
126 : : }
127 : 3012595 : }
128 : :
129 : 68 : void insert(sal_uInt32 nIndex, const CoordinateDataArray2D& rSource)
130 : : {
131 : 68 : const sal_uInt32 nCount(rSource.maVector.size());
132 : :
133 [ + - ]: 68 : if(nCount)
134 : : {
135 : : // insert data
136 : 68 : CoordinateData2DVector::iterator aIndex(maVector.begin());
137 : 68 : aIndex += nIndex;
138 : 68 : CoordinateData2DVector::const_iterator aStart(rSource.maVector.begin());
139 : 68 : CoordinateData2DVector::const_iterator aEnd(rSource.maVector.end());
140 [ + - ]: 68 : maVector.insert(aIndex, aStart, aEnd);
141 : : }
142 : 68 : }
143 : :
144 : 18932 : void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
145 : : {
146 [ + - ]: 18932 : if(nCount)
147 : : {
148 : : // remove point data
149 : 18932 : CoordinateData2DVector::iterator aStart(maVector.begin());
150 : 18932 : aStart += nIndex;
151 [ + - ]: 18932 : const CoordinateData2DVector::iterator aEnd(aStart + nCount);
152 [ + - ]: 18932 : maVector.erase(aStart, aEnd);
153 : : }
154 : 18932 : }
155 : :
156 : 4325 : void flip(bool bIsClosed)
157 : : {
158 [ + - ]: 4325 : if(maVector.size() > 1)
159 : : {
160 : : // to keep the same point at index 0, just flip all points except the
161 : : // first one when closed
162 [ + - ]: 4325 : const sal_uInt32 nHalfSize(bIsClosed ? (maVector.size() - 1) >> 1 : maVector.size() >> 1);
163 [ + - ][ + - ]: 4325 : CoordinateData2DVector::iterator aStart(bIsClosed ? maVector.begin() + 1 : maVector.begin());
[ + - ][ + - ]
[ # # # # ]
164 [ + - ]: 4325 : CoordinateData2DVector::iterator aEnd(maVector.end() - 1);
165 : :
166 [ + + ]: 10505 : for(sal_uInt32 a(0); a < nHalfSize; a++)
167 : : {
168 : 6180 : ::std::swap(*aStart, *aEnd);
169 : 6180 : ++aStart;
170 : 6180 : --aEnd;
171 : : }
172 : : }
173 : 4325 : }
174 : :
175 : 32 : void removeDoublePointsAtBeginEnd()
176 : : {
177 : : // remove from end as long as there are at least two points
178 : : // and begin/end are equal
179 [ + - ][ + + ]: 34 : while((maVector.size() > 1) && (maVector[0] == maVector[maVector.size() - 1]))
[ + + ]
180 : : {
181 : 2 : maVector.pop_back();
182 : : }
183 : 32 : }
184 : :
185 : 86 : void removeDoublePointsWholeTrack()
186 : : {
187 : 86 : sal_uInt32 nIndex(0);
188 : :
189 : : // test as long as there are at least two points and as long as the index
190 : : // is smaller or equal second last point
191 [ + - ][ + + ]: 412 : while((maVector.size() > 1) && (nIndex <= maVector.size() - 2))
[ + + ]
192 : : {
193 [ + + ]: 326 : if(maVector[nIndex] == maVector[nIndex + 1])
194 : : {
195 : : // if next is same as index, delete next
196 [ + - ][ + - ]: 86 : maVector.erase(maVector.begin() + (nIndex + 1));
197 : : }
198 : : else
199 : : {
200 : : // if different, step forward
201 : 240 : nIndex++;
202 : : }
203 : : }
204 : 86 : }
205 : :
206 : 814873 : void transform(const basegfx::B2DHomMatrix& rMatrix)
207 : : {
208 : 814873 : CoordinateData2DVector::iterator aStart(maVector.begin());
209 : 814873 : CoordinateData2DVector::iterator aEnd(maVector.end());
210 : :
211 [ + - ][ + + ]: 3701754 : for(; aStart != aEnd; ++aStart)
212 : : {
213 [ + - ]: 2886881 : aStart->transform(rMatrix);
214 : : }
215 : 814873 : }
216 : :
217 : : const basegfx::B2DPoint* begin() const
218 : : {
219 : : if(maVector.empty())
220 : : return 0;
221 : : else
222 : : return &maVector.front();
223 : : }
224 : :
225 : : const basegfx::B2DPoint* end() const
226 : : {
227 : : if(maVector.empty())
228 : : return 0;
229 : : else
230 : : return (&maVector.back())+1;
231 : : }
232 : :
233 : : basegfx::B2DPoint* begin()
234 : : {
235 : : if(maVector.empty())
236 : : return 0;
237 : : else
238 : : return &maVector.front();
239 : : }
240 : :
241 : : basegfx::B2DPoint* end()
242 : : {
243 : : if(maVector.empty())
244 : : return 0;
245 : : else
246 : : return (&maVector.back())+1;
247 : : }
248 : : };
249 : :
250 : : //////////////////////////////////////////////////////////////////////////////
251 : :
252 : 482017 : class ControlVectorPair2D
253 : : {
254 : : basegfx::B2DVector maPrevVector;
255 : : basegfx::B2DVector maNextVector;
256 : :
257 : : public:
258 : 50971 : ControlVectorPair2D() {}
259 : :
260 : 538883 : const basegfx::B2DVector& getPrevVector() const
261 : : {
262 : 538883 : return maPrevVector;
263 : : }
264 : :
265 : 166278 : void setPrevVector(const basegfx::B2DVector& rValue)
266 : : {
267 [ + + ]: 166278 : if(rValue != maPrevVector)
268 : 152339 : maPrevVector = rValue;
269 : 166278 : }
270 : :
271 : 524799 : const basegfx::B2DVector& getNextVector() const
272 : : {
273 : 524799 : return maNextVector;
274 : : }
275 : :
276 : 164248 : void setNextVector(const basegfx::B2DVector& rValue)
277 : : {
278 [ + + ]: 164248 : if(rValue != maNextVector)
279 : 150274 : maNextVector = rValue;
280 : 164248 : }
281 : :
282 : 5221 : bool operator==(const ControlVectorPair2D& rData) const
283 : : {
284 [ + - ][ + - ]: 5221 : return (maPrevVector == rData.getPrevVector() && maNextVector == rData.getNextVector());
285 : : }
286 : :
287 : 0 : void flip()
288 : : {
289 : 0 : ::std::swap(maPrevVector, maNextVector);
290 : 0 : }
291 : : };
292 : :
293 : : //////////////////////////////////////////////////////////////////////////////
294 : :
295 : 24249 : class ControlVectorArray2D
296 : : {
297 : : typedef ::std::vector< ControlVectorPair2D > ControlVectorPair2DVector;
298 : :
299 : : ControlVectorPair2DVector maVector;
300 : : sal_uInt32 mnUsedVectors;
301 : :
302 : : public:
303 : 4489 : explicit ControlVectorArray2D(sal_uInt32 nCount)
304 : : : maVector(nCount),
305 : 4489 : mnUsedVectors(0)
306 : 4489 : {}
307 : :
308 : 0 : ControlVectorArray2D(const ControlVectorArray2D& rOriginal, sal_uInt32 nIndex, sal_uInt32 nCount)
309 : : : maVector(),
310 : 0 : mnUsedVectors(0)
311 : : {
312 : 0 : ControlVectorPair2DVector::const_iterator aStart(rOriginal.maVector.begin());
313 : 0 : aStart += nIndex;
314 : 0 : ControlVectorPair2DVector::const_iterator aEnd(aStart);
315 : 0 : aEnd += nCount;
316 [ # # ]: 0 : maVector.reserve(nCount);
317 : :
318 [ # # ][ # # ]: 0 : for(; aStart != aEnd; ++aStart)
319 : : {
320 [ # # ][ # # ]: 0 : if(!aStart->getPrevVector().equalZero())
321 : 0 : mnUsedVectors++;
322 : :
323 [ # # ][ # # ]: 0 : if(!aStart->getNextVector().equalZero())
324 : 0 : mnUsedVectors++;
325 : :
326 [ # # ]: 0 : maVector.push_back(*aStart);
327 : : }
328 : 0 : }
329 : :
330 : : sal_uInt32 count() const
331 : : {
332 : : return maVector.size();
333 : : }
334 : :
335 : 1642 : bool operator==(const ControlVectorArray2D& rCandidate) const
336 : : {
337 : 1642 : return (maVector == rCandidate.maVector);
338 : : }
339 : :
340 : 522680 : bool isUsed() const
341 : : {
342 : 522680 : return (0 != mnUsedVectors);
343 : : }
344 : :
345 : 319962 : const basegfx::B2DVector& getPrevVector(sal_uInt32 nIndex) const
346 : : {
347 : 319962 : return maVector[nIndex].getPrevVector();
348 : : }
349 : :
350 : 166354 : void setPrevVector(sal_uInt32 nIndex, const basegfx::B2DVector& rValue)
351 : : {
352 [ + + ][ + + ]: 166354 : bool bWasUsed(mnUsedVectors && !maVector[nIndex].getPrevVector().equalZero());
353 : 166354 : bool bIsUsed(!rValue.equalZero());
354 : :
355 [ + + ]: 166354 : if(bWasUsed)
356 : : {
357 [ + - ]: 128120 : if(bIsUsed)
358 : : {
359 : 128120 : maVector[nIndex].setPrevVector(rValue);
360 : : }
361 : : else
362 : : {
363 : 0 : maVector[nIndex].setPrevVector(basegfx::B2DVector::getEmptyVector());
364 : 0 : mnUsedVectors--;
365 : : }
366 : : }
367 : : else
368 : : {
369 [ + + ]: 38234 : if(bIsUsed)
370 : : {
371 : 38158 : maVector[nIndex].setPrevVector(rValue);
372 : 38158 : mnUsedVectors++;
373 : : }
374 : : }
375 : 166354 : }
376 : :
377 : 312351 : const basegfx::B2DVector& getNextVector(sal_uInt32 nIndex) const
378 : : {
379 : 312351 : return maVector[nIndex].getNextVector();
380 : : }
381 : :
382 : 164278 : void setNextVector(sal_uInt32 nIndex, const basegfx::B2DVector& rValue)
383 : : {
384 [ + + ][ + + ]: 164278 : bool bWasUsed(mnUsedVectors && !maVector[nIndex].getNextVector().equalZero());
385 : 164278 : bool bIsUsed(!rValue.equalZero());
386 : :
387 [ + + ]: 164278 : if(bWasUsed)
388 : : {
389 [ + - ]: 128172 : if(bIsUsed)
390 : : {
391 : 128172 : maVector[nIndex].setNextVector(rValue);
392 : : }
393 : : else
394 : : {
395 : 0 : maVector[nIndex].setNextVector(basegfx::B2DVector::getEmptyVector());
396 : 0 : mnUsedVectors--;
397 : : }
398 : : }
399 : : else
400 : : {
401 [ + + ]: 36106 : if(bIsUsed)
402 : : {
403 : 36076 : maVector[nIndex].setNextVector(rValue);
404 : 36076 : mnUsedVectors++;
405 : : }
406 : : }
407 : 164278 : }
408 : :
409 : 7797 : void append(const ControlVectorPair2D& rValue)
410 : : {
411 : 7797 : maVector.push_back(rValue);
412 : :
413 [ - + ]: 7797 : if(!rValue.getPrevVector().equalZero())
414 : 0 : mnUsedVectors += 1;
415 : :
416 [ - + ]: 7797 : if(!rValue.getNextVector().equalZero())
417 : 0 : mnUsedVectors += 1;
418 : 7797 : }
419 : :
420 : 36021 : void insert(sal_uInt32 nIndex, const ControlVectorPair2D& rValue, sal_uInt32 nCount)
421 : : {
422 [ + - ]: 36021 : if(nCount)
423 : : {
424 : : // add nCount copies of rValue
425 : 36021 : ControlVectorPair2DVector::iterator aIndex(maVector.begin());
426 : 36021 : aIndex += nIndex;
427 [ + - ]: 36021 : maVector.insert(aIndex, nCount, rValue);
428 : :
429 [ + - ][ - + ]: 36021 : if(!rValue.getPrevVector().equalZero())
430 : 0 : mnUsedVectors += nCount;
431 : :
432 [ + - ][ - + ]: 36021 : if(!rValue.getNextVector().equalZero())
433 : 36021 : mnUsedVectors += nCount;
434 : : }
435 : 36021 : }
436 : :
437 : 6 : void insert(sal_uInt32 nIndex, const ControlVectorArray2D& rSource)
438 : : {
439 : 6 : const sal_uInt32 nCount(rSource.maVector.size());
440 : :
441 [ + - ]: 6 : if(nCount)
442 : : {
443 : : // insert data
444 : 6 : ControlVectorPair2DVector::iterator aIndex(maVector.begin());
445 : 6 : aIndex += nIndex;
446 : 6 : ControlVectorPair2DVector::const_iterator aStart(rSource.maVector.begin());
447 : 6 : ControlVectorPair2DVector::const_iterator aEnd(rSource.maVector.end());
448 [ + - ]: 6 : maVector.insert(aIndex, aStart, aEnd);
449 : :
450 [ + - ][ + + ]: 78 : for(; aStart != aEnd; ++aStart)
451 : : {
452 [ + - ][ + - ]: 72 : if(!aStart->getPrevVector().equalZero())
453 : 72 : mnUsedVectors++;
454 : :
455 [ + - ][ + - ]: 72 : if(!aStart->getNextVector().equalZero())
456 : 72 : mnUsedVectors++;
457 : : }
458 : : }
459 : 6 : }
460 : :
461 : 3409 : void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
462 : : {
463 [ + - ]: 3409 : if(nCount)
464 : : {
465 [ + - ]: 3409 : const ControlVectorPair2DVector::iterator aDeleteStart(maVector.begin() + nIndex);
466 [ + - ]: 3409 : const ControlVectorPair2DVector::iterator aDeleteEnd(aDeleteStart + nCount);
467 [ + - ]: 3409 : ControlVectorPair2DVector::const_iterator aStart(aDeleteStart);
468 : :
469 [ + - ][ + - ]: 6908 : for(; mnUsedVectors && aStart != aDeleteEnd; ++aStart)
[ + + ][ + + ]
470 : : {
471 [ + - ][ + + ]: 3499 : if(!aStart->getPrevVector().equalZero())
472 : 2117 : mnUsedVectors--;
473 : :
474 [ + - ][ + - ]: 3499 : if(mnUsedVectors && !aStart->getNextVector().equalZero())
[ - + ][ - + ]
475 : 0 : mnUsedVectors--;
476 : : }
477 : :
478 : : // remove point data
479 [ + - ]: 3409 : maVector.erase(aDeleteStart, aDeleteEnd);
480 : : }
481 : 3409 : }
482 : :
483 : 0 : void flip(bool bIsClosed)
484 : : {
485 [ # # ]: 0 : if(maVector.size() > 1)
486 : : {
487 : : // to keep the same point at index 0, just flip all points except the
488 : : // first one when closed
489 [ # # ]: 0 : const sal_uInt32 nHalfSize(bIsClosed ? (maVector.size() - 1) >> 1 : maVector.size() >> 1);
490 [ # # ][ # # ]: 0 : ControlVectorPair2DVector::iterator aStart(bIsClosed ? maVector.begin() + 1 : maVector.begin());
[ # # ][ # # ]
[ # # # # ]
491 [ # # ]: 0 : ControlVectorPair2DVector::iterator aEnd(maVector.end() - 1);
492 : :
493 [ # # ]: 0 : for(sal_uInt32 a(0); a < nHalfSize; a++)
494 : : {
495 : : // swap Prev and Next
496 [ # # ]: 0 : aStart->flip();
497 [ # # ]: 0 : aEnd->flip();
498 : :
499 : : // swap entries
500 [ # # ]: 0 : ::std::swap(*aStart, *aEnd);
501 : :
502 : 0 : ++aStart;
503 : 0 : --aEnd;
504 : : }
505 : :
506 [ # # ][ # # ]: 0 : if(aStart == aEnd)
507 : : {
508 : : // swap Prev and Next at middle element (if exists)
509 [ # # ]: 0 : aStart->flip();
510 : : }
511 : :
512 [ # # ]: 0 : if(bIsClosed)
513 : : {
514 : : // swap Prev and Next at start element
515 [ # # ]: 0 : maVector.begin()->flip();
516 : : }
517 : : }
518 : 0 : }
519 : : };
520 : :
521 : : //////////////////////////////////////////////////////////////////////////////
522 : :
523 [ + - ]: 3891240 : class ImplBufferedData
524 : : {
525 : : private:
526 : : // Possibility to hold the last subdivision
527 : : boost::scoped_ptr< basegfx::B2DPolygon > mpDefaultSubdivision;
528 : :
529 : : // Possibility to hold the last B2DRange calculation
530 : : boost::scoped_ptr< basegfx::B2DRange > mpB2DRange;
531 : :
532 : : public:
533 : 3891272 : ImplBufferedData()
534 : : : mpDefaultSubdivision(),
535 : 3891272 : mpB2DRange()
536 : 3891272 : {}
537 : :
538 : 0 : const basegfx::B2DPolygon& getDefaultAdaptiveSubdivision(const basegfx::B2DPolygon& rSource) const
539 : : {
540 [ # # ]: 0 : if(!mpDefaultSubdivision)
541 : : {
542 [ # # ]: 0 : const_cast< ImplBufferedData* >(this)->mpDefaultSubdivision.reset(new basegfx::B2DPolygon(basegfx::tools::adaptiveSubdivideByCount(rSource, 9)));
543 : : }
544 : :
545 : 0 : return *mpDefaultSubdivision;
546 : : }
547 : :
548 : 4740645 : const basegfx::B2DRange& getB2DRange(const basegfx::B2DPolygon& rSource) const
549 : : {
550 [ + + ]: 4740645 : if(!mpB2DRange)
551 : : {
552 [ + - ]: 3891272 : basegfx::B2DRange aNewRange;
553 [ + - ]: 3891272 : const sal_uInt32 nPointCount(rSource.count());
554 : :
555 [ + - ]: 3891272 : if(nPointCount)
556 : : {
557 [ + + ]: 21348801 : for(sal_uInt32 a(0); a < nPointCount; a++)
558 : : {
559 [ + - ][ + - ]: 17457529 : aNewRange.expand(rSource.getB2DPoint(a));
560 : : }
561 : :
562 [ + - ][ + + ]: 3891272 : if(rSource.areControlPointsUsed())
563 : : {
564 [ + - ][ + + ]: 795 : const sal_uInt32 nEdgeCount(rSource.isClosed() ? nPointCount : nPointCount - 1);
565 : :
566 [ + - ]: 795 : if(nEdgeCount)
567 : : {
568 [ + - ]: 795 : basegfx::B2DCubicBezier aEdge;
569 [ + - ]: 795 : aEdge.setStartPoint(rSource.getB2DPoint(0));
570 : :
571 [ + + ]: 8896 : for(sal_uInt32 b(0); b < nEdgeCount; b++)
572 : : {
573 : 8101 : const sal_uInt32 nNextIndex((b + 1) % nPointCount);
574 [ + - ]: 8101 : aEdge.setControlPointA(rSource.getNextControlPoint(b));
575 [ + - ]: 8101 : aEdge.setControlPointB(rSource.getPrevControlPoint(nNextIndex));
576 [ + - ]: 8101 : aEdge.setEndPoint(rSource.getB2DPoint(nNextIndex));
577 : :
578 [ + + ][ + - ]: 8101 : if(aEdge.isBezier())
579 : : {
580 [ + - ]: 5681 : const basegfx::B2DRange aBezierRangeWithControlPoints(aEdge.getRange());
581 : :
582 [ + - ][ + + ]: 5681 : if(!aNewRange.isInside(aBezierRangeWithControlPoints))
583 : : {
584 : : // the range with control points of the current edge is not completely
585 : : // inside the current range without control points. Expand current range by
586 : : // subdividing the bezier segment.
587 : : // Ideal here is a subdivision at the extreme values, so use
588 : : // getAllExtremumPositions to get all extremas in one run
589 [ + - ]: 776 : ::std::vector< double > aExtremas;
590 : :
591 [ + - ]: 776 : aExtremas.reserve(4);
592 [ + - ]: 776 : aEdge.getAllExtremumPositions(aExtremas);
593 : :
594 : 776 : const sal_uInt32 nExtremaCount(aExtremas.size());
595 : :
596 [ + + ]: 1363 : for(sal_uInt32 c(0); c < nExtremaCount; c++)
597 : : {
598 [ + - ][ + - ]: 587 : aNewRange.expand(aEdge.interpolatePoint(aExtremas[c]));
[ + - ]
599 : 5681 : }
600 : : }
601 : : }
602 : :
603 : : // prepare next edge
604 : 8101 : aEdge.setStartPoint(aEdge.getEndPoint());
605 [ + - ]: 795 : }
606 : : }
607 : : }
608 : : }
609 : :
610 [ + - ][ + - ]: 3891272 : const_cast< ImplBufferedData* >(this)->mpB2DRange.reset(new basegfx::B2DRange(aNewRange));
611 : : }
612 : :
613 : 4740645 : return *mpB2DRange;
614 : : }
615 : : };
616 : :
617 : : //////////////////////////////////////////////////////////////////////////////
618 : :
619 [ + - ][ + - ]: 5030679 : class ImplB2DPolygon
620 : : {
621 : : private:
622 : : // The point vector. This vector exists always and defines the
623 : : // count of members.
624 : : CoordinateDataArray2D maPoints;
625 : :
626 : : // The control point vectors. This vectors are created on demand
627 : : // and may be zero.
628 : : boost::scoped_ptr< ControlVectorArray2D > mpControlVector;
629 : :
630 : : // buffered data for e.g. default subdivision and range
631 : : boost::scoped_ptr< ImplBufferedData > mpBufferedData;
632 : :
633 : : // flag which decides if this polygon is opened or closed
634 : : bool mbIsClosed;
635 : :
636 : : public:
637 : 18 : const basegfx::B2DPolygon& getDefaultAdaptiveSubdivision(const basegfx::B2DPolygon& rSource) const
638 : : {
639 [ - + ][ # # ]: 18 : if(!mpControlVector || !mpControlVector->isUsed())
[ + - ]
640 : : {
641 : 18 : return rSource;
642 : : }
643 : :
644 [ # # ]: 0 : if(!mpBufferedData)
645 : : {
646 [ # # ]: 0 : const_cast< ImplB2DPolygon* >(this)->mpBufferedData.reset(new ImplBufferedData);
647 : : }
648 : :
649 : 18 : return mpBufferedData->getDefaultAdaptiveSubdivision(rSource);
650 : : }
651 : :
652 : 4740645 : const basegfx::B2DRange& getB2DRange(const basegfx::B2DPolygon& rSource) const
653 : : {
654 [ + + ]: 4740645 : if(!mpBufferedData)
655 : : {
656 [ + - ]: 3891272 : const_cast< ImplB2DPolygon* >(this)->mpBufferedData.reset(new ImplBufferedData);
657 : : }
658 : :
659 : 4740645 : return mpBufferedData->getB2DRange(rSource);
660 : : }
661 : :
662 : 206 : ImplB2DPolygon()
663 : : : maPoints(0),
664 : : mpControlVector(),
665 : : mpBufferedData(),
666 : 206 : mbIsClosed(false)
667 : 206 : {}
668 : :
669 : 5030695 : ImplB2DPolygon(const ImplB2DPolygon& rToBeCopied)
670 : : : maPoints(rToBeCopied.maPoints),
671 : : mpControlVector(),
672 : : mpBufferedData(),
673 : 5030695 : mbIsClosed(rToBeCopied.mbIsClosed)
674 : : {
675 : : // complete initialization using copy
676 [ + - ][ + + ]: 5030695 : if(rToBeCopied.mpControlVector && rToBeCopied.mpControlVector->isUsed())
[ + + ]
677 : : {
678 [ + - ][ + - ]: 9880 : mpControlVector.reset( new ControlVectorArray2D(*rToBeCopied.mpControlVector) );
[ + - ]
679 : : }
680 : 5030695 : }
681 : :
682 : 0 : ImplB2DPolygon(const ImplB2DPolygon& rToBeCopied, sal_uInt32 nIndex, sal_uInt32 nCount)
683 : : : maPoints(rToBeCopied.maPoints, nIndex, nCount),
684 : : mpControlVector(),
685 : : mpBufferedData(),
686 : 0 : mbIsClosed(rToBeCopied.mbIsClosed)
687 : : {
688 : : // complete initialization using partly copy
689 [ # # ][ # # ]: 0 : if(rToBeCopied.mpControlVector && rToBeCopied.mpControlVector->isUsed())
[ # # ]
690 : : {
691 [ # # ][ # # ]: 0 : mpControlVector.reset( new ControlVectorArray2D(*rToBeCopied.mpControlVector, nIndex, nCount) );
[ # # ]
692 : :
693 [ # # ]: 0 : if(!mpControlVector->isUsed())
694 [ # # ]: 0 : mpControlVector.reset();
695 : : }
696 : 0 : }
697 : :
698 : : ImplB2DPolygon& operator=( const ImplB2DPolygon& rToBeCopied )
699 : : {
700 : : maPoints = rToBeCopied.maPoints;
701 : : mpControlVector.reset();
702 : : mpBufferedData.reset();
703 : : mbIsClosed = rToBeCopied.mbIsClosed;
704 : :
705 : : // complete initialization using copy
706 : : if(rToBeCopied.mpControlVector && rToBeCopied.mpControlVector->isUsed())
707 : : mpControlVector.reset( new ControlVectorArray2D(*rToBeCopied.mpControlVector) );
708 : :
709 : : return *this;
710 : : }
711 : :
712 : 12841713 : sal_uInt32 count() const
713 : : {
714 : 12841713 : return maPoints.count();
715 : : }
716 : :
717 : 4992042 : bool isClosed() const
718 : : {
719 : 4992042 : return mbIsClosed;
720 : : }
721 : :
722 : 3839587 : void setClosed(bool bNew)
723 : : {
724 [ + - ]: 3839587 : if(bNew != mbIsClosed)
725 : : {
726 : 3839587 : mpBufferedData.reset();
727 : 3839587 : mbIsClosed = bNew;
728 : : }
729 : 3839587 : }
730 : :
731 : 61476 : bool operator==(const ImplB2DPolygon& rCandidate) const
732 : : {
733 [ + + ]: 61476 : if(mbIsClosed == rCandidate.mbIsClosed)
734 : : {
735 [ + + ]: 60738 : if(maPoints == rCandidate.maPoints)
736 : : {
737 : 46052 : bool bControlVectorsAreEqual(true);
738 : :
739 [ + + ]: 46052 : if(mpControlVector)
740 : : {
741 [ + - ]: 1642 : if(rCandidate.mpControlVector)
742 : : {
743 : 1642 : bControlVectorsAreEqual = ((*mpControlVector) == (*rCandidate.mpControlVector));
744 : : }
745 : : else
746 : : {
747 : : // candidate has no control vector, so it's assumed all unused.
748 : 0 : bControlVectorsAreEqual = !mpControlVector->isUsed();
749 : : }
750 : : }
751 : : else
752 : : {
753 [ + + ]: 44410 : if(rCandidate.mpControlVector)
754 : : {
755 : : // we have no control vector, so it's assumed all unused.
756 : 56 : bControlVectorsAreEqual = !rCandidate.mpControlVector->isUsed();
757 : : }
758 : : }
759 : :
760 [ + + ]: 46052 : if(bControlVectorsAreEqual)
761 : : {
762 : 45996 : return true;
763 : : }
764 : : }
765 : : }
766 : :
767 : 61476 : return false;
768 : : }
769 : :
770 : 62523287 : const basegfx::B2DPoint& getPoint(sal_uInt32 nIndex) const
771 : : {
772 : 62523287 : return maPoints.getCoordinate(nIndex);
773 : : }
774 : :
775 : 10864813 : void setPoint(sal_uInt32 nIndex, const basegfx::B2DPoint& rValue)
776 : : {
777 : 10864813 : mpBufferedData.reset();
778 : 10864813 : maPoints.setCoordinate(nIndex, rValue);
779 : 10864813 : }
780 : :
781 : 245 : void reserve(sal_uInt32 nCount)
782 : : {
783 : 245 : maPoints.reserve(nCount);
784 : 245 : }
785 : :
786 : 4927504 : void append(const basegfx::B2DPoint& rPoint)
787 : : {
788 [ + - ]: 4927504 : mpBufferedData.reset(); // TODO: is this needed?
789 : 4927504 : const CoordinateData2D aCoordinate(rPoint);
790 [ + - ]: 4927504 : maPoints.append(aCoordinate);
791 : :
792 [ + + ]: 4927504 : if(mpControlVector)
793 : : {
794 : 7797 : const ControlVectorPair2D aVectorPair;
795 [ + - ]: 7797 : mpControlVector->append(aVectorPair);
796 : 4927504 : }
797 : 4927504 : }
798 : :
799 : 3012595 : void insert(sal_uInt32 nIndex, const basegfx::B2DPoint& rPoint, sal_uInt32 nCount)
800 : : {
801 [ + - ]: 3012595 : if(nCount)
802 : : {
803 [ + - ]: 3012595 : mpBufferedData.reset();
804 : 3012595 : CoordinateData2D aCoordinate(rPoint);
805 [ + - ]: 3012595 : maPoints.insert(nIndex, aCoordinate, nCount);
806 : :
807 [ + + ]: 3012595 : if(mpControlVector)
808 : : {
809 : 36013 : ControlVectorPair2D aVectorPair;
810 [ + - ]: 36013 : mpControlVector->insert(nIndex, aVectorPair, nCount);
811 : 3012595 : }
812 : : }
813 : 3012595 : }
814 : :
815 : 163064 : const basegfx::B2DVector& getPrevControlVector(sal_uInt32 nIndex) const
816 : : {
817 [ + + ]: 163064 : if(mpControlVector)
818 : : {
819 : 163037 : return mpControlVector->getPrevVector(nIndex);
820 : : }
821 : : else
822 : : {
823 : 163064 : return basegfx::B2DVector::getEmptyVector();
824 : : }
825 : : }
826 : :
827 : 38295 : void setPrevControlVector(sal_uInt32 nIndex, const basegfx::B2DVector& rValue)
828 : : {
829 [ + + ]: 38295 : if(!mpControlVector)
830 : : {
831 [ + + ]: 48 : if(!rValue.equalZero())
832 : : {
833 : 43 : mpBufferedData.reset();
834 [ + - ]: 43 : mpControlVector.reset( new ControlVectorArray2D(maPoints.count()) );
835 : 43 : mpControlVector->setPrevVector(nIndex, rValue);
836 : : }
837 : : }
838 : : else
839 : : {
840 : 38247 : mpBufferedData.reset();
841 : 38247 : mpControlVector->setPrevVector(nIndex, rValue);
842 : :
843 [ - + ]: 38247 : if(!mpControlVector->isUsed())
844 : 0 : mpControlVector.reset();
845 : : }
846 : 38295 : }
847 : :
848 : 155455 : const basegfx::B2DVector& getNextControlVector(sal_uInt32 nIndex) const
849 : : {
850 [ + + ]: 155455 : if(mpControlVector)
851 : : {
852 : 155434 : return mpControlVector->getNextVector(nIndex);
853 : : }
854 : : else
855 : : {
856 : 155455 : return basegfx::B2DVector::getEmptyVector();
857 : : }
858 : : }
859 : :
860 : 36182 : void setNextControlVector(sal_uInt32 nIndex, const basegfx::B2DVector& rValue)
861 : : {
862 [ + + ]: 36182 : if(!mpControlVector)
863 : : {
864 [ + + ]: 4456 : if(!rValue.equalZero())
865 : : {
866 : 4440 : mpBufferedData.reset();
867 [ + - ]: 4440 : mpControlVector.reset( new ControlVectorArray2D(maPoints.count()) );
868 : 4440 : mpControlVector->setNextVector(nIndex, rValue);
869 : : }
870 : : }
871 : : else
872 : : {
873 : 31726 : mpBufferedData.reset();
874 : 31726 : mpControlVector->setNextVector(nIndex, rValue);
875 : :
876 [ - + ]: 31726 : if(!mpControlVector->isUsed())
877 : 0 : mpControlVector.reset();
878 : : }
879 : 36182 : }
880 : :
881 : 8900646 : bool areControlPointsUsed() const
882 : : {
883 [ + + ][ + - ]: 8900646 : return (mpControlVector && mpControlVector->isUsed());
884 : : }
885 : :
886 : : void resetControlVectors(sal_uInt32 nIndex)
887 : : {
888 : : setPrevControlVector(nIndex, basegfx::B2DVector::getEmptyVector());
889 : : setNextControlVector(nIndex, basegfx::B2DVector::getEmptyVector());
890 : : }
891 : :
892 : 5 : void resetControlVectors()
893 : : {
894 : 5 : mpBufferedData.reset();
895 : 5 : mpControlVector.reset();
896 : 5 : }
897 : :
898 : 5 : void setControlVectors(sal_uInt32 nIndex, const basegfx::B2DVector& rPrev, const basegfx::B2DVector& rNext)
899 : : {
900 : 5 : setPrevControlVector(nIndex, rPrev);
901 : 5 : setNextControlVector(nIndex, rNext);
902 : 5 : }
903 : :
904 : 36025 : void appendBezierSegment(const basegfx::B2DVector& rNext, const basegfx::B2DVector& rPrev, const basegfx::B2DPoint& rPoint)
905 : : {
906 : 36025 : mpBufferedData.reset();
907 : 36025 : const sal_uInt32 nCount(maPoints.count());
908 : :
909 [ + + ]: 36025 : if(nCount)
910 : : {
911 : 36020 : setNextControlVector(nCount - 1, rNext);
912 : : }
913 : :
914 : 36025 : insert(nCount, rPoint, 1);
915 : 36025 : setPrevControlVector(nCount, rPrev);
916 : 36025 : }
917 : :
918 : 68 : void insert(sal_uInt32 nIndex, const ImplB2DPolygon& rSource)
919 : : {
920 : 68 : const sal_uInt32 nCount(rSource.maPoints.count());
921 : :
922 [ + - ]: 68 : if(nCount)
923 : : {
924 : 68 : mpBufferedData.reset();
925 : :
926 [ + - ][ + - ]: 68 : if(rSource.mpControlVector && rSource.mpControlVector->isUsed() && !mpControlVector)
[ + + ][ + + ]
927 : : {
928 [ + - ]: 6 : mpControlVector.reset( new ControlVectorArray2D(maPoints.count()) );
929 : : }
930 : :
931 : 68 : maPoints.insert(nIndex, rSource.maPoints);
932 : :
933 [ + + ]: 68 : if(rSource.mpControlVector)
934 : : {
935 : 6 : mpControlVector->insert(nIndex, *rSource.mpControlVector);
936 : :
937 [ - + ]: 6 : if(!mpControlVector->isUsed())
938 : 0 : mpControlVector.reset();
939 : : }
940 [ + + ]: 62 : else if(mpControlVector)
941 : : {
942 : 8 : ControlVectorPair2D aVectorPair;
943 [ + - ]: 8 : mpControlVector->insert(nIndex, aVectorPair, nCount);
944 : : }
945 : : }
946 : 68 : }
947 : :
948 : 18932 : void remove(sal_uInt32 nIndex, sal_uInt32 nCount)
949 : : {
950 [ + - ]: 18932 : if(nCount)
951 : : {
952 : 18932 : mpBufferedData.reset();
953 : 18932 : maPoints.remove(nIndex, nCount);
954 : :
955 [ + + ]: 18932 : if(mpControlVector)
956 : : {
957 : 3409 : mpControlVector->remove(nIndex, nCount);
958 : :
959 [ - + ]: 3409 : if(!mpControlVector->isUsed())
960 : 0 : mpControlVector.reset();
961 : : }
962 : : }
963 : 18932 : }
964 : :
965 : 4325 : void flip()
966 : : {
967 [ + - ]: 4325 : if(maPoints.count() > 1)
968 : : {
969 : 4325 : mpBufferedData.reset();
970 : :
971 : : // flip points
972 : 4325 : maPoints.flip(mbIsClosed);
973 : :
974 [ - + ]: 4325 : if(mpControlVector)
975 : : {
976 : : // flip control vector
977 : 0 : mpControlVector->flip(mbIsClosed);
978 : : }
979 : : }
980 : 4325 : }
981 : :
982 : 16168 : bool hasDoublePoints() const
983 : : {
984 [ + + ]: 16168 : if(mbIsClosed)
985 : : {
986 : : // check for same start and end point
987 : 5375 : const sal_uInt32 nIndex(maPoints.count() - 1);
988 : :
989 [ + + ]: 5375 : if(maPoints.getCoordinate(0) == maPoints.getCoordinate(nIndex))
990 : : {
991 [ - + ]: 4 : if(mpControlVector)
992 : : {
993 [ # # ][ # # ]: 0 : if(mpControlVector->getNextVector(nIndex).equalZero() && mpControlVector->getPrevVector(0).equalZero())
[ # # ]
994 : : {
995 : 0 : return true;
996 : : }
997 : : }
998 : : else
999 : : {
1000 : 4 : return true;
1001 : : }
1002 : : }
1003 : : }
1004 : :
1005 : : // test for range
1006 [ + + ]: 50655 : for(sal_uInt32 a(0); a < maPoints.count() - 1; a++)
1007 : : {
1008 [ + + ]: 34599 : if(maPoints.getCoordinate(a) == maPoints.getCoordinate(a + 1))
1009 : : {
1010 [ + + ]: 108 : if(mpControlVector)
1011 : : {
1012 [ + - ][ + - ]: 4 : if(mpControlVector->getNextVector(a).equalZero() && mpControlVector->getPrevVector(a + 1).equalZero())
[ + - ]
1013 : : {
1014 : 4 : return true;
1015 : : }
1016 : : }
1017 : : else
1018 : : {
1019 : 104 : return true;
1020 : : }
1021 : : }
1022 : : }
1023 : :
1024 : 16168 : return false;
1025 : : }
1026 : :
1027 : 90 : void removeDoublePointsAtBeginEnd()
1028 : : {
1029 : : // Only remove DoublePoints at Begin and End when poly is closed
1030 [ + + ]: 90 : if(mbIsClosed)
1031 : : {
1032 : 32 : mpBufferedData.reset();
1033 : :
1034 [ - + ]: 32 : if(mpControlVector)
1035 : : {
1036 : : bool bRemove;
1037 : :
1038 [ # # ]: 0 : do
1039 : : {
1040 : 0 : bRemove = false;
1041 : :
1042 [ # # ]: 0 : if(maPoints.count() > 1)
1043 : : {
1044 : 0 : const sal_uInt32 nIndex(maPoints.count() - 1);
1045 : :
1046 [ # # ]: 0 : if(maPoints.getCoordinate(0) == maPoints.getCoordinate(nIndex))
1047 : : {
1048 [ # # ]: 0 : if(mpControlVector)
1049 : : {
1050 [ # # ][ # # ]: 0 : if(mpControlVector->getNextVector(nIndex).equalZero() && mpControlVector->getPrevVector(0).equalZero())
[ # # ]
1051 : : {
1052 : 0 : bRemove = true;
1053 : : }
1054 : : }
1055 : : else
1056 : : {
1057 : 0 : bRemove = true;
1058 : : }
1059 : : }
1060 : : }
1061 : :
1062 [ # # ]: 0 : if(bRemove)
1063 : : {
1064 : 0 : const sal_uInt32 nIndex(maPoints.count() - 1);
1065 : :
1066 [ # # ][ # # ]: 0 : if(mpControlVector && !mpControlVector->getPrevVector(nIndex).equalZero())
[ # # ]
1067 : : {
1068 : 0 : mpControlVector->setPrevVector(0, mpControlVector->getPrevVector(nIndex));
1069 : : }
1070 : :
1071 : 0 : remove(nIndex, 1);
1072 : : }
1073 : : }
1074 : : while(bRemove);
1075 : : }
1076 : : else
1077 : : {
1078 : 32 : maPoints.removeDoublePointsAtBeginEnd();
1079 : : }
1080 : : }
1081 : 90 : }
1082 : :
1083 : 90 : void removeDoublePointsWholeTrack()
1084 : : {
1085 : 90 : mpBufferedData.reset();
1086 : :
1087 [ + + ]: 90 : if(mpControlVector)
1088 : : {
1089 : 4 : sal_uInt32 nIndex(0);
1090 : :
1091 : : // test as long as there are at least two points and as long as the index
1092 : : // is smaller or equal second last point
1093 [ + - ][ + + ]: 12 : while((maPoints.count() > 1) && (nIndex <= maPoints.count() - 2))
[ + + ]
1094 : : {
1095 : 8 : bool bRemove(maPoints.getCoordinate(nIndex) == maPoints.getCoordinate(nIndex + 1));
1096 : :
1097 [ + + ]: 8 : if(bRemove)
1098 : : {
1099 [ + - ]: 4 : if(mpControlVector)
1100 : : {
1101 [ + - ][ - + ]: 4 : if(!mpControlVector->getNextVector(nIndex).equalZero() || !mpControlVector->getPrevVector(nIndex + 1).equalZero())
[ - + ]
1102 : : {
1103 : 0 : bRemove = false;
1104 : : }
1105 : : }
1106 : : }
1107 : :
1108 [ + + ]: 8 : if(bRemove)
1109 : : {
1110 [ + - ][ + - ]: 4 : if(mpControlVector && !mpControlVector->getPrevVector(nIndex).equalZero())
[ + - ]
1111 : : {
1112 : 4 : mpControlVector->setPrevVector(nIndex + 1, mpControlVector->getPrevVector(nIndex));
1113 : : }
1114 : :
1115 : : // if next is same as index and the control vectors are unused, delete index
1116 : 4 : remove(nIndex, 1);
1117 : : }
1118 : : else
1119 : : {
1120 : : // if different, step forward
1121 : 4 : nIndex++;
1122 : : }
1123 : : }
1124 : : }
1125 : : else
1126 : : {
1127 : 86 : maPoints.removeDoublePointsWholeTrack();
1128 : : }
1129 : 90 : }
1130 : :
1131 : 831143 : void transform(const basegfx::B2DHomMatrix& rMatrix)
1132 : : {
1133 : 831143 : mpBufferedData.reset();
1134 : :
1135 [ + + ]: 831143 : if(mpControlVector)
1136 : : {
1137 [ + + ]: 173179 : for(sal_uInt32 a(0); a < maPoints.count(); a++)
1138 : : {
1139 [ + - ]: 156909 : basegfx::B2DPoint aCandidate = maPoints.getCoordinate(a);
1140 : :
1141 [ + - ]: 156909 : if(mpControlVector->isUsed())
1142 : : {
1143 [ + - ]: 156909 : const basegfx::B2DVector& rPrevVector(mpControlVector->getPrevVector(a));
1144 [ + - ]: 156909 : const basegfx::B2DVector& rNextVector(mpControlVector->getNextVector(a));
1145 : :
1146 [ + - ][ + + ]: 156909 : if(!rPrevVector.equalZero())
1147 : : {
1148 [ + - ]: 128060 : basegfx::B2DVector aPrevVector(rMatrix * rPrevVector);
1149 [ + - ]: 128060 : mpControlVector->setPrevVector(a, aPrevVector);
1150 : : }
1151 : :
1152 [ + - ][ + + ]: 156909 : if(!rNextVector.equalZero())
1153 : : {
1154 [ + - ]: 128112 : basegfx::B2DVector aNextVector(rMatrix * rNextVector);
1155 [ + - ]: 128112 : mpControlVector->setNextVector(a, aNextVector);
1156 : : }
1157 : : }
1158 : :
1159 [ + - ]: 156909 : aCandidate *= rMatrix;
1160 [ + - ]: 156909 : maPoints.setCoordinate(a, aCandidate);
1161 : 156909 : }
1162 : :
1163 [ - + ]: 16270 : if(!mpControlVector->isUsed())
1164 : 0 : mpControlVector.reset();
1165 : : }
1166 : : else
1167 : : {
1168 : 814873 : maPoints.transform(rMatrix);
1169 : : }
1170 : 831143 : }
1171 : :
1172 : : const basegfx::B2DPoint* begin() const
1173 : : {
1174 : : return maPoints.begin();
1175 : : }
1176 : :
1177 : : const basegfx::B2DPoint* end() const
1178 : : {
1179 : : return maPoints.end();
1180 : : }
1181 : :
1182 : : basegfx::B2DPoint* begin()
1183 : : {
1184 : : mpBufferedData.reset();
1185 : : return maPoints.begin();
1186 : : }
1187 : :
1188 : : basegfx::B2DPoint* end()
1189 : : {
1190 : : mpBufferedData.reset();
1191 : : return maPoints.end();
1192 : : }
1193 : : };
1194 : :
1195 : : //////////////////////////////////////////////////////////////////////////////
1196 : :
1197 : : namespace basegfx
1198 : : {
1199 : : namespace
1200 : : {
1201 : : struct DefaultPolygon: public rtl::Static<B2DPolygon::ImplType, DefaultPolygon> {};
1202 : : }
1203 : :
1204 : 4181656 : B2DPolygon::B2DPolygon()
1205 : 4181656 : : mpPolygon(DefaultPolygon::get())
1206 : 4181656 : {}
1207 : :
1208 : 17698978 : B2DPolygon::B2DPolygon(const B2DPolygon& rPolygon)
1209 : 17698978 : : mpPolygon(rPolygon.mpPolygon)
1210 : 17698978 : {}
1211 : :
1212 : 0 : B2DPolygon::B2DPolygon(const B2DPolygon& rPolygon, sal_uInt32 nIndex, sal_uInt32 nCount)
1213 [ # # ]: 0 : : mpPolygon(ImplB2DPolygon(*rPolygon.mpPolygon, nIndex, nCount))
1214 : : {
1215 : : // TODO(P2): one extra temporary here (cow_wrapper copies
1216 : : // given ImplB2DPolygon into its internal impl_t wrapper type)
1217 : : OSL_ENSURE(nIndex + nCount <= rPolygon.mpPolygon->count(), "B2DPolygon constructor outside range (!)");
1218 : 0 : }
1219 : :
1220 : 21880377 : B2DPolygon::~B2DPolygon()
1221 : : {
1222 : 21880377 : }
1223 : :
1224 : 39029 : B2DPolygon& B2DPolygon::operator=(const B2DPolygon& rPolygon)
1225 : : {
1226 : 39029 : mpPolygon = rPolygon.mpPolygon;
1227 : 39029 : return *this;
1228 : : }
1229 : :
1230 : 150 : void B2DPolygon::makeUnique()
1231 : : {
1232 : 150 : mpPolygon.make_unique();
1233 : 150 : }
1234 : :
1235 : 64402 : bool B2DPolygon::operator==(const B2DPolygon& rPolygon) const
1236 : : {
1237 [ + + ]: 64402 : if(mpPolygon.same_object(rPolygon.mpPolygon))
1238 : 2926 : return true;
1239 : :
1240 : 64402 : return ((*mpPolygon) == (*rPolygon.mpPolygon));
1241 : : }
1242 : :
1243 : 10815 : bool B2DPolygon::operator!=(const B2DPolygon& rPolygon) const
1244 : : {
1245 : 10815 : return !(*this == rPolygon);
1246 : : }
1247 : :
1248 : 8914912 : sal_uInt32 B2DPolygon::count() const
1249 : : {
1250 : 8914912 : return mpPolygon->count();
1251 : : }
1252 : :
1253 : 62246701 : B2DPoint B2DPolygon::getB2DPoint(sal_uInt32 nIndex) const
1254 : : {
1255 : : OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
1256 : :
1257 : 62246701 : return mpPolygon->getPoint(nIndex);
1258 : : }
1259 : :
1260 : 11462894 : void B2DPolygon::setB2DPoint(sal_uInt32 nIndex, const B2DPoint& rValue)
1261 : : {
1262 : : OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
1263 : :
1264 [ + + ]: 11462894 : if(getB2DPoint(nIndex) != rValue)
1265 : : {
1266 : 10864813 : mpPolygon->setPoint(nIndex, rValue);
1267 : : }
1268 : 11462894 : }
1269 : :
1270 : 245 : void B2DPolygon::reserve(sal_uInt32 nCount)
1271 : : {
1272 : 245 : mpPolygon->reserve(nCount);
1273 : 245 : }
1274 : :
1275 : 0 : void B2DPolygon::insert(sal_uInt32 nIndex, const B2DPoint& rPoint, sal_uInt32 nCount)
1276 : : {
1277 : : OSL_ENSURE(nIndex <= mpPolygon->count(), "B2DPolygon Insert outside range (!)");
1278 : :
1279 [ # # ]: 0 : if(nCount)
1280 : : {
1281 : 0 : mpPolygon->insert(nIndex, rPoint, nCount);
1282 : : }
1283 : 0 : }
1284 : :
1285 : 2976523 : void B2DPolygon::append(const B2DPoint& rPoint, sal_uInt32 nCount)
1286 : : {
1287 [ + - ]: 2976523 : if(nCount)
1288 : : {
1289 : 2976523 : mpPolygon->insert(mpPolygon->count(), rPoint, nCount);
1290 : : }
1291 : 2976523 : }
1292 : :
1293 : 4927504 : void B2DPolygon::append(const B2DPoint& rPoint)
1294 : : {
1295 : 4927504 : mpPolygon->append(rPoint);
1296 : 4927504 : }
1297 : :
1298 : 108153 : B2DPoint B2DPolygon::getPrevControlPoint(sal_uInt32 nIndex) const
1299 : : {
1300 : : OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
1301 : :
1302 [ + + ]: 108153 : if(mpPolygon->areControlPointsUsed())
1303 : : {
1304 : 91926 : return mpPolygon->getPoint(nIndex) + mpPolygon->getPrevControlVector(nIndex);
1305 : : }
1306 : : else
1307 : : {
1308 : 108153 : return mpPolygon->getPoint(nIndex);
1309 : : }
1310 : : }
1311 : :
1312 : 105675 : B2DPoint B2DPolygon::getNextControlPoint(sal_uInt32 nIndex) const
1313 : : {
1314 : : OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
1315 : :
1316 [ + + ]: 105675 : if(mpPolygon->areControlPointsUsed())
1317 : : {
1318 : 89508 : return mpPolygon->getPoint(nIndex) + mpPolygon->getNextControlVector(nIndex);
1319 : : }
1320 : : else
1321 : : {
1322 : 105675 : return mpPolygon->getPoint(nIndex);
1323 : : }
1324 : : }
1325 : :
1326 : 2271 : void B2DPolygon::setPrevControlPoint(sal_uInt32 nIndex, const B2DPoint& rValue)
1327 : : {
1328 : : OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
1329 [ + - ][ + - ]: 2271 : const basegfx::B2DVector aNewVector(rValue - mpPolygon->getPoint(nIndex));
1330 : :
1331 [ + - ][ + + ]: 2271 : if(mpPolygon->getPrevControlVector(nIndex) != aNewVector)
[ + - ]
1332 : : {
1333 [ + - ][ + - ]: 2265 : mpPolygon->setPrevControlVector(nIndex, aNewVector);
1334 : 2271 : }
1335 : 2271 : }
1336 : :
1337 : 163 : void B2DPolygon::setNextControlPoint(sal_uInt32 nIndex, const B2DPoint& rValue)
1338 : : {
1339 : : OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
1340 [ + - ][ + - ]: 163 : const basegfx::B2DVector aNewVector(rValue - mpPolygon->getPoint(nIndex));
1341 : :
1342 [ + - ][ + + ]: 163 : if(mpPolygon->getNextControlVector(nIndex) != aNewVector)
[ + - ]
1343 : : {
1344 [ + - ][ + - ]: 157 : mpPolygon->setNextControlVector(nIndex, aNewVector);
1345 : 163 : }
1346 : 163 : }
1347 : :
1348 : 5 : void B2DPolygon::setControlPoints(sal_uInt32 nIndex, const basegfx::B2DPoint& rPrev, const basegfx::B2DPoint& rNext)
1349 : : {
1350 : : OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
1351 [ + - ][ + - ]: 5 : const B2DPoint aPoint(mpPolygon->getPoint(nIndex));
1352 : 5 : const basegfx::B2DVector aNewPrev(rPrev - aPoint);
1353 : 5 : const basegfx::B2DVector aNewNext(rNext - aPoint);
1354 : :
1355 [ + - ][ + - ]: 5 : if(mpPolygon->getPrevControlVector(nIndex) != aNewPrev || mpPolygon->getNextControlVector(nIndex) != aNewNext)
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1356 : : {
1357 [ + - ][ + - ]: 5 : mpPolygon->setControlVectors(nIndex, aNewPrev, aNewNext);
1358 : 5 : }
1359 : 5 : }
1360 : :
1361 : 0 : void B2DPolygon::resetPrevControlPoint(sal_uInt32 nIndex)
1362 : : {
1363 : : OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
1364 : :
1365 [ # # ][ # # ]: 0 : if(mpPolygon->areControlPointsUsed() && !mpPolygon->getPrevControlVector(nIndex).equalZero())
[ # # ]
1366 : : {
1367 : 0 : mpPolygon->setPrevControlVector(nIndex, B2DVector::getEmptyVector());
1368 : : }
1369 : 0 : }
1370 : :
1371 : 0 : void B2DPolygon::resetNextControlPoint(sal_uInt32 nIndex)
1372 : : {
1373 : : OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
1374 : :
1375 [ # # ][ # # ]: 0 : if(mpPolygon->areControlPointsUsed() && !mpPolygon->getNextControlVector(nIndex).equalZero())
[ # # ]
1376 : : {
1377 : 0 : mpPolygon->setNextControlVector(nIndex, B2DVector::getEmptyVector());
1378 : : }
1379 : 0 : }
1380 : :
1381 : 5 : void B2DPolygon::resetControlPoints()
1382 : : {
1383 [ + - ]: 5 : if(mpPolygon->areControlPointsUsed())
1384 : : {
1385 : 5 : mpPolygon->resetControlVectors();
1386 : : }
1387 : 5 : }
1388 : :
1389 : 36072 : void B2DPolygon::appendBezierSegment(
1390 : : const B2DPoint& rNextControlPoint,
1391 : : const B2DPoint& rPrevControlPoint,
1392 : : const B2DPoint& rPoint)
1393 : : {
1394 [ + - ][ + + ]: 36072 : const B2DVector aNewNextVector(mpPolygon->count() ? B2DVector(rNextControlPoint - mpPolygon->getPoint(mpPolygon->count() - 1)) : B2DVector::getEmptyVector());
[ + - ][ + - ]
[ + - ][ + - ]
[ + + ][ # # ]
1395 : 36072 : const B2DVector aNewPrevVector(rPrevControlPoint - rPoint);
1396 : :
1397 [ + + ][ + - ]: 36072 : if(aNewNextVector.equalZero() && aNewPrevVector.equalZero())
[ + + ][ + + ]
[ + - ]
1398 : : {
1399 [ + - ][ + - ]: 47 : mpPolygon->insert(mpPolygon->count(), rPoint, 1);
[ + - ]
1400 : : }
1401 : : else
1402 : : {
1403 [ + - ][ + - ]: 36025 : mpPolygon->appendBezierSegment(aNewNextVector, aNewPrevVector, rPoint);
1404 : 36072 : }
1405 : 36072 : }
1406 : :
1407 : 8605102 : bool B2DPolygon::areControlPointsUsed() const
1408 : : {
1409 : 8605102 : return mpPolygon->areControlPointsUsed();
1410 : : }
1411 : :
1412 : 4248 : bool B2DPolygon::isPrevControlPointUsed(sal_uInt32 nIndex) const
1413 : : {
1414 : : OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
1415 : :
1416 [ + + ][ + + ]: 4248 : return (mpPolygon->areControlPointsUsed() && !mpPolygon->getPrevControlVector(nIndex).equalZero());
1417 : : }
1418 : :
1419 : 1143 : bool B2DPolygon::isNextControlPointUsed(sal_uInt32 nIndex) const
1420 : : {
1421 : : OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
1422 : :
1423 [ + + ][ + + ]: 1143 : return (mpPolygon->areControlPointsUsed() && !mpPolygon->getNextControlVector(nIndex).equalZero());
1424 : : }
1425 : :
1426 : 64217 : B2VectorContinuity B2DPolygon::getContinuityInPoint(sal_uInt32 nIndex) const
1427 : : {
1428 : : OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
1429 : :
1430 [ + - ]: 64217 : if(mpPolygon->areControlPointsUsed())
1431 : : {
1432 : 64217 : const B2DVector& rPrev(mpPolygon->getPrevControlVector(nIndex));
1433 : 64217 : const B2DVector& rNext(mpPolygon->getNextControlVector(nIndex));
1434 : :
1435 : 64217 : return getContinuity(rPrev, rNext);
1436 : : }
1437 : : else
1438 : : {
1439 : 64217 : return CONTINUITY_NONE;
1440 : : }
1441 : : }
1442 : :
1443 : 12149 : void B2DPolygon::getBezierSegment(sal_uInt32 nIndex, B2DCubicBezier& rTarget) const
1444 : : {
1445 : : OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)");
1446 : 12149 : const bool bNextIndexValidWithoutClose(nIndex + 1 < mpPolygon->count());
1447 : :
1448 [ + + ][ + + ]: 12149 : if(bNextIndexValidWithoutClose || mpPolygon->isClosed())
[ + + ]
1449 : : {
1450 [ + + ]: 12103 : const sal_uInt32 nNextIndex(bNextIndexValidWithoutClose ? nIndex + 1 : 0);
1451 : 12103 : rTarget.setStartPoint(mpPolygon->getPoint(nIndex));
1452 : 12103 : rTarget.setEndPoint(mpPolygon->getPoint(nNextIndex));
1453 : :
1454 [ + + ]: 12103 : if(mpPolygon->areControlPointsUsed())
1455 : : {
1456 : 545 : rTarget.setControlPointA(rTarget.getStartPoint() + mpPolygon->getNextControlVector(nIndex));
1457 : 545 : rTarget.setControlPointB(rTarget.getEndPoint() + mpPolygon->getPrevControlVector(nNextIndex));
1458 : : }
1459 : : else
1460 : : {
1461 : : // no bezier, reset control poins at rTarget
1462 : 11558 : rTarget.setControlPointA(rTarget.getStartPoint());
1463 : 11558 : rTarget.setControlPointB(rTarget.getEndPoint());
1464 : : }
1465 : : }
1466 : : else
1467 : : {
1468 : : // no valid edge at all, reset rTarget to current point
1469 [ + - ]: 46 : const B2DPoint aPoint(mpPolygon->getPoint(nIndex));
1470 : 46 : rTarget.setStartPoint(aPoint);
1471 : 46 : rTarget.setEndPoint(aPoint);
1472 : 46 : rTarget.setControlPointA(aPoint);
1473 : 46 : rTarget.setControlPointB(aPoint);
1474 : : }
1475 : 12149 : }
1476 : :
1477 : 18 : B2DPolygon B2DPolygon::getDefaultAdaptiveSubdivision() const
1478 : : {
1479 : 18 : return mpPolygon->getDefaultAdaptiveSubdivision(*this);
1480 : : }
1481 : :
1482 : 4740645 : B2DRange B2DPolygon::getB2DRange() const
1483 : : {
1484 : 4740645 : return mpPolygon->getB2DRange(*this);
1485 : : }
1486 : :
1487 : 68 : void B2DPolygon::append(const B2DPolygon& rPoly, sal_uInt32 nIndex, sal_uInt32 nCount)
1488 : : {
1489 [ + - ]: 68 : if(rPoly.count())
1490 : : {
1491 [ + - ]: 68 : if(!nCount)
1492 : : {
1493 : 68 : nCount = rPoly.count();
1494 : : }
1495 : :
1496 [ + - ][ + - ]: 68 : if(0 == nIndex && nCount == rPoly.count())
[ + - ]
1497 : : {
1498 : 68 : mpPolygon->insert(mpPolygon->count(), *rPoly.mpPolygon);
1499 : : }
1500 : : else
1501 : : {
1502 : : OSL_ENSURE(nIndex + nCount <= rPoly.mpPolygon->count(), "B2DPolygon Append outside range (!)");
1503 [ # # ]: 0 : ImplB2DPolygon aTempPoly(*rPoly.mpPolygon, nIndex, nCount);
1504 [ # # ][ # # ]: 0 : mpPolygon->insert(mpPolygon->count(), aTempPoly);
[ # # ][ # # ]
1505 : : }
1506 : : }
1507 : 68 : }
1508 : :
1509 : 18928 : void B2DPolygon::remove(sal_uInt32 nIndex, sal_uInt32 nCount)
1510 : : {
1511 : : OSL_ENSURE(nIndex + nCount <= mpPolygon->count(), "B2DPolygon Remove outside range (!)");
1512 : :
1513 [ + - ]: 18928 : if(nCount)
1514 : : {
1515 : 18928 : mpPolygon->remove(nIndex, nCount);
1516 : : }
1517 : 18928 : }
1518 : :
1519 : 97162 : void B2DPolygon::clear()
1520 : : {
1521 : 97162 : mpPolygon = DefaultPolygon::get();
1522 : 97162 : }
1523 : :
1524 : 4989811 : bool B2DPolygon::isClosed() const
1525 : : {
1526 : 4989811 : return mpPolygon->isClosed();
1527 : : }
1528 : :
1529 : 4062279 : void B2DPolygon::setClosed(bool bNew)
1530 : : {
1531 [ + + ]: 4062279 : if(isClosed() != bNew)
1532 : : {
1533 : 3839587 : mpPolygon->setClosed(bNew);
1534 : : }
1535 : 4062279 : }
1536 : :
1537 : 4325 : void B2DPolygon::flip()
1538 : : {
1539 [ + - ]: 4325 : if(count() > 1)
1540 : : {
1541 : 4325 : mpPolygon->flip();
1542 : : }
1543 : 4325 : }
1544 : :
1545 : 16168 : bool B2DPolygon::hasDoublePoints() const
1546 : : {
1547 [ + - ][ + + ]: 16168 : return (mpPolygon->count() > 1 && mpPolygon->hasDoublePoints());
1548 : : }
1549 : :
1550 : 10888 : void B2DPolygon::removeDoublePoints()
1551 : : {
1552 [ + + ]: 10888 : if(hasDoublePoints())
1553 : : {
1554 : 90 : mpPolygon->removeDoublePointsAtBeginEnd();
1555 : 90 : mpPolygon->removeDoublePointsWholeTrack();
1556 : : }
1557 : 10888 : }
1558 : :
1559 : 849707 : void B2DPolygon::transform(const B2DHomMatrix& rMatrix)
1560 : : {
1561 [ + - ][ + + ]: 849707 : if(mpPolygon->count() && !rMatrix.isIdentity())
[ + + ]
1562 : : {
1563 : 831143 : mpPolygon->transform(rMatrix);
1564 : : }
1565 : 849707 : }
1566 : :
1567 : : } // end of namespace basegfx
1568 : :
1569 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|