xref: /AOO41X/main/basegfx/source/polygon/b2dpolypolygontools.cxx (revision fe22d2cfc602815794415026f1317bd625db6f83)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_basegfx.hxx"
24 
25 #include <basegfx/polygon/b2dpolypolygontools.hxx>
26 #include <osl/diagnose.h>
27 #include <basegfx/polygon/b2dpolypolygon.hxx>
28 #include <basegfx/polygon/b2dpolygon.hxx>
29 #include <basegfx/polygon/b2dpolygontools.hxx>
30 #include <basegfx/numeric/ftools.hxx>
31 #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
32 #include <numeric>
33 
34 //////////////////////////////////////////////////////////////////////////////
35 
36 namespace basegfx
37 {
38     namespace tools
39     {
correctOrientations(const B2DPolyPolygon & rCandidate)40         B2DPolyPolygon correctOrientations(const B2DPolyPolygon& rCandidate)
41         {
42             B2DPolyPolygon aRetval(rCandidate);
43             const sal_uInt32 nCount(aRetval.count());
44 
45             for(sal_uInt32 a(0L); a < nCount; a++)
46             {
47                 const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
48                 const B2VectorOrientation aOrientation(tools::getOrientation(aCandidate));
49                 sal_uInt32 nDepth(0L);
50 
51                 for(sal_uInt32 b(0L); b < nCount; b++)
52                 {
53                     if(b != a)
54                     {
55                         const B2DPolygon aCompare(rCandidate.getB2DPolygon(b));
56 
57                         if(tools::isInside(aCompare, aCandidate, true))
58                         {
59                             nDepth++;
60                         }
61                     }
62                 }
63 
64                 const bool bShallBeHole(1L == (nDepth & 0x00000001));
65                 const bool bIsHole(ORIENTATION_NEGATIVE == aOrientation);
66 
67                 if(bShallBeHole != bIsHole && ORIENTATION_NEUTRAL != aOrientation)
68                 {
69                     B2DPolygon aFlipped(aCandidate);
70                     aFlipped.flip();
71                     aRetval.setB2DPolygon(a, aFlipped);
72                 }
73             }
74 
75             return aRetval;
76         }
77 
correctOutmostPolygon(const B2DPolyPolygon & rCandidate)78         B2DPolyPolygon correctOutmostPolygon(const B2DPolyPolygon& rCandidate)
79         {
80             const sal_uInt32 nCount(rCandidate.count());
81 
82             if(nCount > 1L)
83             {
84                 for(sal_uInt32 a(0L); a < nCount; a++)
85                 {
86                     const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
87                     sal_uInt32 nDepth(0L);
88 
89                     for(sal_uInt32 b(0L); b < nCount; b++)
90                     {
91                         if(b != a)
92                         {
93                             const B2DPolygon aCompare(rCandidate.getB2DPolygon(b));
94 
95                             if(tools::isInside(aCompare, aCandidate, true))
96                             {
97                                 nDepth++;
98                             }
99                         }
100                     }
101 
102                     if(!nDepth)
103                     {
104                         B2DPolyPolygon aRetval(rCandidate);
105 
106                         if(a != 0L)
107                         {
108                             // exchange polygon a and polygon 0L
109                             aRetval.setB2DPolygon(0L, aCandidate);
110                             aRetval.setB2DPolygon(a, rCandidate.getB2DPolygon(0L));
111                         }
112 
113                         // exit
114                         return aRetval;
115                     }
116                 }
117             }
118 
119             return rCandidate;
120         }
121 
adaptiveSubdivideByDistance(const B2DPolyPolygon & rCandidate,double fDistanceBound)122         B2DPolyPolygon adaptiveSubdivideByDistance(const B2DPolyPolygon& rCandidate, double fDistanceBound)
123         {
124             if(rCandidate.areControlPointsUsed())
125             {
126                 const sal_uInt32 nPolygonCount(rCandidate.count());
127                 B2DPolyPolygon aRetval;
128 
129                 for(sal_uInt32 a(0L); a < nPolygonCount; a++)
130                 {
131                     const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
132 
133                     if(aCandidate.areControlPointsUsed())
134                     {
135                         aRetval.append(tools::adaptiveSubdivideByDistance(aCandidate, fDistanceBound));
136                     }
137                     else
138                     {
139                         aRetval.append(aCandidate);
140                     }
141                 }
142 
143                 return aRetval;
144             }
145             else
146             {
147                 return rCandidate;
148             }
149         }
150 
adaptiveSubdivideByAngle(const B2DPolyPolygon & rCandidate,double fAngleBound)151         B2DPolyPolygon adaptiveSubdivideByAngle(const B2DPolyPolygon& rCandidate, double fAngleBound)
152         {
153             if(rCandidate.areControlPointsUsed())
154             {
155                 const sal_uInt32 nPolygonCount(rCandidate.count());
156                 B2DPolyPolygon aRetval;
157 
158                 for(sal_uInt32 a(0L); a < nPolygonCount; a++)
159                 {
160                     const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
161 
162                     if(aCandidate.areControlPointsUsed())
163                     {
164                         aRetval.append(tools::adaptiveSubdivideByAngle(aCandidate, fAngleBound));
165                     }
166                     else
167                     {
168                         aRetval.append(aCandidate);
169                     }
170                 }
171 
172                 return aRetval;
173             }
174             else
175             {
176                 return rCandidate;
177             }
178         }
179 
adaptiveSubdivideByCount(const B2DPolyPolygon & rCandidate,sal_uInt32 nCount)180         B2DPolyPolygon adaptiveSubdivideByCount(const B2DPolyPolygon& rCandidate, sal_uInt32 nCount)
181         {
182             if(rCandidate.areControlPointsUsed())
183             {
184                 const sal_uInt32 nPolygonCount(rCandidate.count());
185                 B2DPolyPolygon aRetval;
186 
187                 for(sal_uInt32 a(0L); a < nPolygonCount; a++)
188                 {
189                     const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
190 
191                     if(aCandidate.areControlPointsUsed())
192                     {
193                         aRetval.append(tools::adaptiveSubdivideByCount(aCandidate, nCount));
194                     }
195                     else
196                     {
197                         aRetval.append(aCandidate);
198                     }
199                 }
200 
201                 return aRetval;
202             }
203             else
204             {
205                 return rCandidate;
206             }
207         }
208 
isInside(const B2DPolyPolygon & rCandidate,const B2DPoint & rPoint,bool bWithBorder)209         bool isInside(const B2DPolyPolygon& rCandidate, const B2DPoint& rPoint, bool bWithBorder)
210         {
211             const sal_uInt32 nPolygonCount(rCandidate.count());
212 
213             if(1L == nPolygonCount)
214             {
215                 return isInside(rCandidate.getB2DPolygon(0L), rPoint, bWithBorder);
216             }
217             else
218             {
219                 sal_Int32 nInsideCount(0L);
220 
221                 for(sal_uInt32 a(0L); a < nPolygonCount; a++)
222                 {
223                     const B2DPolygon aPolygon(rCandidate.getB2DPolygon(a));
224                     const bool bInside(isInside(aPolygon, rPoint, bWithBorder));
225 
226                     if(bInside)
227                     {
228                         nInsideCount++;
229                     }
230                 }
231 
232                 return (nInsideCount % 2L);
233             }
234         }
235 
getRangeWithControlPoints(const B2DPolyPolygon & rCandidate)236         B2DRange getRangeWithControlPoints(const B2DPolyPolygon& rCandidate)
237         {
238             B2DRange aRetval;
239             const sal_uInt32 nPolygonCount(rCandidate.count());
240 
241             for(sal_uInt32 a(0L); a < nPolygonCount; a++)
242             {
243                 B2DPolygon aCandidate = rCandidate.getB2DPolygon(a);
244                 aRetval.expand(tools::getRangeWithControlPoints(aCandidate));
245             }
246 
247             return aRetval;
248         }
249 
getRange(const B2DPolyPolygon & rCandidate)250         B2DRange getRange(const B2DPolyPolygon& rCandidate)
251         {
252             B2DRange aRetval;
253             const sal_uInt32 nPolygonCount(rCandidate.count());
254 
255             for(sal_uInt32 a(0L); a < nPolygonCount; a++)
256             {
257                 B2DPolygon aCandidate = rCandidate.getB2DPolygon(a);
258                 aRetval.expand(tools::getRange(aCandidate));
259             }
260 
261             return aRetval;
262         }
263 
getSignedArea(const B2DPolyPolygon & rCandidate)264         double getSignedArea(const B2DPolyPolygon& rCandidate)
265         {
266             double fRetval(0.0);
267             const sal_uInt32 nPolygonCount(rCandidate.count());
268 
269             for(sal_uInt32 a(0L); a < nPolygonCount; a++)
270             {
271                 const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
272 
273                 fRetval += tools::getSignedArea(aCandidate);
274             }
275 
276             return fRetval;
277         }
278 
getArea(const B2DPolyPolygon & rCandidate)279         double getArea(const B2DPolyPolygon& rCandidate)
280         {
281             return fabs(getSignedArea(rCandidate));
282         }
283 
applyLineDashing(const B2DPolyPolygon & rCandidate,const::std::vector<double> & rDotDashArray,B2DPolyPolygon * pLineTarget,B2DPolyPolygon * pGapTarget,double fFullDashDotLen)284         void applyLineDashing(const B2DPolyPolygon& rCandidate, const ::std::vector<double>& rDotDashArray, B2DPolyPolygon* pLineTarget, B2DPolyPolygon* pGapTarget, double fFullDashDotLen)
285         {
286             if(0.0 == fFullDashDotLen && rDotDashArray.size())
287             {
288                 // calculate fFullDashDotLen from rDotDashArray
289                 fFullDashDotLen = ::std::accumulate(rDotDashArray.begin(), rDotDashArray.end(), 0.0);
290             }
291 
292             if(rCandidate.count() && fFullDashDotLen > 0.0)
293             {
294                 B2DPolyPolygon aLineTarget, aGapTarget;
295 
296                 for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
297                 {
298                     const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
299 
300                     applyLineDashing(
301                         aCandidate,
302                         rDotDashArray,
303                         pLineTarget ? &aLineTarget : 0,
304                         pGapTarget ? &aGapTarget : 0,
305                         fFullDashDotLen);
306 
307                     if(pLineTarget)
308                     {
309                         pLineTarget->append(aLineTarget);
310                     }
311 
312                     if(pGapTarget)
313                     {
314                         pGapTarget->append(aGapTarget);
315                     }
316                 }
317             }
318         }
319 
isInEpsilonRange(const B2DPolyPolygon & rCandidate,const B2DPoint & rTestPosition,double fDistance)320         bool isInEpsilonRange(const B2DPolyPolygon& rCandidate, const B2DPoint& rTestPosition, double fDistance)
321         {
322             const sal_uInt32 nPolygonCount(rCandidate.count());
323 
324             for(sal_uInt32 a(0L); a < nPolygonCount; a++)
325             {
326                 B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
327 
328                 if(isInEpsilonRange(aCandidate, rTestPosition, fDistance))
329                 {
330                     return true;
331                 }
332             }
333 
334             return false;
335         }
336 
createB3DPolyPolygonFromB2DPolyPolygon(const B2DPolyPolygon & rCandidate,double fZCoordinate)337         B3DPolyPolygon createB3DPolyPolygonFromB2DPolyPolygon(const B2DPolyPolygon& rCandidate, double fZCoordinate)
338         {
339             const sal_uInt32 nPolygonCount(rCandidate.count());
340             B3DPolyPolygon aRetval;
341 
342             for(sal_uInt32 a(0L); a < nPolygonCount; a++)
343             {
344                 B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
345 
346                 aRetval.append(createB3DPolygonFromB2DPolygon(aCandidate, fZCoordinate));
347             }
348 
349             return aRetval;
350         }
351 
createB2DPolyPolygonFromB3DPolyPolygon(const B3DPolyPolygon & rCandidate,const B3DHomMatrix & rMat)352         B2DPolyPolygon createB2DPolyPolygonFromB3DPolyPolygon(const B3DPolyPolygon& rCandidate, const B3DHomMatrix& rMat)
353         {
354             const sal_uInt32 nPolygonCount(rCandidate.count());
355             B2DPolyPolygon aRetval;
356 
357             for(sal_uInt32 a(0L); a < nPolygonCount; a++)
358             {
359                 B3DPolygon aCandidate(rCandidate.getB3DPolygon(a));
360 
361                 aRetval.append(createB2DPolygonFromB3DPolygon(aCandidate, rMat));
362             }
363 
364             return aRetval;
365         }
366 
getSmallestDistancePointToPolyPolygon(const B2DPolyPolygon & rCandidate,const B2DPoint & rTestPoint,sal_uInt32 & rPolygonIndex,sal_uInt32 & rEdgeIndex,double & rCut)367         double getSmallestDistancePointToPolyPolygon(const B2DPolyPolygon& rCandidate, const B2DPoint& rTestPoint, sal_uInt32& rPolygonIndex, sal_uInt32& rEdgeIndex, double& rCut)
368         {
369             double fRetval(DBL_MAX);
370             const double fZero(0.0);
371             const sal_uInt32 nPolygonCount(rCandidate.count());
372 
373             for(sal_uInt32 a(0L); a < nPolygonCount; a++)
374             {
375                 const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
376                 sal_uInt32 nNewEdgeIndex;
377                 double fNewCut;
378                 const double fNewDistance(getSmallestDistancePointToPolygon(aCandidate, rTestPoint, nNewEdgeIndex, fNewCut));
379 
380                 if(DBL_MAX == fRetval || fNewDistance < fRetval)
381                 {
382                     fRetval = fNewDistance;
383                     rPolygonIndex = a;
384                     rEdgeIndex = nNewEdgeIndex;
385                     rCut = fNewCut;
386 
387                     if(fTools::equal(fRetval, fZero))
388                     {
389                         // already found zero distance, cannot get better. Ensure numerical zero value and end loop.
390                         fRetval = 0.0;
391                         break;
392                     }
393                 }
394             }
395 
396             return fRetval;
397         }
398 
distort(const B2DPolyPolygon & rCandidate,const B2DRange & rOriginal,const B2DPoint & rTopLeft,const B2DPoint & rTopRight,const B2DPoint & rBottomLeft,const B2DPoint & rBottomRight)399         B2DPolyPolygon distort(const B2DPolyPolygon& rCandidate, const B2DRange& rOriginal, const B2DPoint& rTopLeft, const B2DPoint& rTopRight, const B2DPoint& rBottomLeft, const B2DPoint& rBottomRight)
400         {
401             const sal_uInt32 nPolygonCount(rCandidate.count());
402             B2DPolyPolygon aRetval;
403 
404             for(sal_uInt32 a(0L); a < nPolygonCount; a++)
405             {
406                 const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
407 
408                 aRetval.append(distort(aCandidate, rOriginal, rTopLeft, rTopRight, rBottomLeft, rBottomRight));
409             }
410 
411             return aRetval;
412         }
413 
rotateAroundPoint(const B2DPolyPolygon & rCandidate,const B2DPoint & rCenter,double fAngle)414         B2DPolyPolygon rotateAroundPoint(const B2DPolyPolygon& rCandidate, const B2DPoint& rCenter, double fAngle)
415         {
416             const sal_uInt32 nPolygonCount(rCandidate.count());
417             B2DPolyPolygon aRetval;
418 
419             for(sal_uInt32 a(0L); a < nPolygonCount; a++)
420             {
421                 const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
422 
423                 aRetval.append(rotateAroundPoint(aCandidate, rCenter, fAngle));
424             }
425 
426             return aRetval;
427         }
428 
expandToCurve(const B2DPolyPolygon & rCandidate)429         B2DPolyPolygon expandToCurve(const B2DPolyPolygon& rCandidate)
430         {
431             const sal_uInt32 nPolygonCount(rCandidate.count());
432             B2DPolyPolygon aRetval;
433 
434             for(sal_uInt32 a(0L); a < nPolygonCount; a++)
435             {
436                 const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
437 
438                 aRetval.append(expandToCurve(aCandidate));
439             }
440 
441             return aRetval;
442         }
443 
setContinuity(const B2DPolyPolygon & rCandidate,B2VectorContinuity eContinuity)444         B2DPolyPolygon setContinuity(const B2DPolyPolygon& rCandidate, B2VectorContinuity eContinuity)
445         {
446             if(rCandidate.areControlPointsUsed())
447             {
448                 const sal_uInt32 nPolygonCount(rCandidate.count());
449                 B2DPolyPolygon aRetval;
450 
451                 for(sal_uInt32 a(0L); a < nPolygonCount; a++)
452                 {
453                     const B2DPolygon aCandidate(rCandidate.getB2DPolygon(a));
454 
455                     aRetval.append(setContinuity(aCandidate, eContinuity));
456                 }
457 
458                 return aRetval;
459             }
460             else
461             {
462                 return rCandidate;
463             }
464         }
465 
growInNormalDirection(const B2DPolyPolygon & rCandidate,double fValue)466         B2DPolyPolygon growInNormalDirection(const B2DPolyPolygon& rCandidate, double fValue)
467         {
468             if(0.0 != fValue)
469             {
470                 B2DPolyPolygon aRetval;
471 
472                 for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
473                 {
474                     aRetval.append(growInNormalDirection(rCandidate.getB2DPolygon(a), fValue));
475                 }
476 
477                 return aRetval;
478             }
479             else
480             {
481                 return rCandidate;
482             }
483         }
484 
correctGrowShrinkPolygonPair(B2DPolyPolygon &,B2DPolyPolygon &)485         void correctGrowShrinkPolygonPair(B2DPolyPolygon& /*rOriginal*/, B2DPolyPolygon& /*rGrown*/)
486         {
487         }
488 
reSegmentPolyPolygon(const B2DPolyPolygon & rCandidate,sal_uInt32 nSegments)489         B2DPolyPolygon reSegmentPolyPolygon(const B2DPolyPolygon& rCandidate, sal_uInt32 nSegments)
490         {
491             B2DPolyPolygon aRetval;
492 
493             for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
494             {
495                 aRetval.append(reSegmentPolygon(rCandidate.getB2DPolygon(a), nSegments));
496             }
497 
498             return aRetval;
499         }
500 
interpolate(const B2DPolyPolygon & rOld1,const B2DPolyPolygon & rOld2,double t)501         B2DPolyPolygon interpolate(const B2DPolyPolygon& rOld1, const B2DPolyPolygon& rOld2, double t)
502         {
503             OSL_ENSURE(rOld1.count() == rOld2.count(), "B2DPolyPolygon interpolate: Different geometry (!)");
504             B2DPolyPolygon aRetval;
505 
506             for(sal_uInt32 a(0L); a < rOld1.count(); a++)
507             {
508                 aRetval.append(interpolate(rOld1.getB2DPolygon(a), rOld2.getB2DPolygon(a), t));
509             }
510 
511             return aRetval;
512         }
513 
isRectangle(const B2DPolyPolygon & rPoly)514         bool isRectangle( const B2DPolyPolygon& rPoly )
515         {
516             // exclude some cheap cases first
517             if( rPoly.count() != 1 )
518                 return false;
519 
520             return isRectangle( rPoly.getB2DPolygon(0) );
521         }
522 
523         // #i76891#
simplifyCurveSegments(const B2DPolyPolygon & rCandidate)524         B2DPolyPolygon simplifyCurveSegments(const B2DPolyPolygon& rCandidate)
525         {
526             if(rCandidate.areControlPointsUsed())
527             {
528                 B2DPolyPolygon aRetval;
529 
530                 for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
531                 {
532                     aRetval.append(simplifyCurveSegments(rCandidate.getB2DPolygon(a)));
533                 }
534 
535                 return aRetval;
536             }
537             else
538             {
539                 return rCandidate;
540             }
541         }
542 
reSegmentPolyPolygonEdges(const B2DPolyPolygon & rCandidate,sal_uInt32 nSubEdges,bool bHandleCurvedEdges,bool bHandleStraightEdges)543         B2DPolyPolygon reSegmentPolyPolygonEdges(const B2DPolyPolygon& rCandidate, sal_uInt32 nSubEdges, bool bHandleCurvedEdges, bool bHandleStraightEdges)
544         {
545             B2DPolyPolygon aRetval;
546 
547             for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
548             {
549                 aRetval.append(reSegmentPolygonEdges(rCandidate.getB2DPolygon(a), nSubEdges, bHandleCurvedEdges, bHandleStraightEdges));
550             }
551 
552             return aRetval;
553         }
554 
555         //////////////////////////////////////////////////////////////////////
556         // comparators with tolerance for 2D PolyPolygons
557 
equal(const B2DPolyPolygon & rCandidateA,const B2DPolyPolygon & rCandidateB,const double & rfSmallValue)558         bool equal(const B2DPolyPolygon& rCandidateA, const B2DPolyPolygon& rCandidateB, const double& rfSmallValue)
559         {
560             const sal_uInt32 nPolygonCount(rCandidateA.count());
561 
562             if(nPolygonCount != rCandidateB.count())
563                 return false;
564 
565             for(sal_uInt32 a(0); a < nPolygonCount; a++)
566             {
567                 const B2DPolygon aCandidate(rCandidateA.getB2DPolygon(a));
568 
569                 if(!equal(aCandidate, rCandidateB.getB2DPolygon(a), rfSmallValue))
570                     return false;
571             }
572 
573             return true;
574         }
575 
equal(const B2DPolyPolygon & rCandidateA,const B2DPolyPolygon & rCandidateB)576         bool equal(const B2DPolyPolygon& rCandidateA, const B2DPolyPolygon& rCandidateB)
577         {
578             const double fSmallValue(fTools::getSmallValue());
579 
580             return equal(rCandidateA, rCandidateB, fSmallValue);
581         }
582 
snapPointsOfHorizontalOrVerticalEdges(const B2DPolyPolygon & rCandidate)583         B2DPolyPolygon snapPointsOfHorizontalOrVerticalEdges(const B2DPolyPolygon& rCandidate)
584         {
585             B2DPolyPolygon aRetval;
586 
587             for(sal_uInt32 a(0L); a < rCandidate.count(); a++)
588             {
589                 aRetval.append(snapPointsOfHorizontalOrVerticalEdges(rCandidate.getB2DPolygon(a)));
590             }
591 
592             return aRetval;
593         }
594 
containsOnlyHorizontalAndVerticalEdges(const B2DPolyPolygon & rCandidate)595         bool containsOnlyHorizontalAndVerticalEdges(const B2DPolyPolygon& rCandidate)
596         {
597             if(rCandidate.areControlPointsUsed())
598             {
599                 return false;
600             }
601 
602             for(sal_uInt32 a(0); a < rCandidate.count(); a++)
603             {
604                 if(!containsOnlyHorizontalAndVerticalEdges(rCandidate.getB2DPolygon(a)))
605                 {
606                     return false;
607                 }
608             }
609 
610             return true;
611         }
612 
613         //////////////////////////////////////////////////////////////////////////////
614         // converters for com::sun::star::drawing::PointSequence
615 
UnoPointSequenceSequenceToB2DPolyPolygon(const com::sun::star::drawing::PointSequenceSequence & rPointSequenceSequenceSource,bool bCheckClosed)616         B2DPolyPolygon UnoPointSequenceSequenceToB2DPolyPolygon(
617             const com::sun::star::drawing::PointSequenceSequence& rPointSequenceSequenceSource,
618             bool bCheckClosed)
619         {
620             B2DPolyPolygon aRetval;
621             const com::sun::star::drawing::PointSequence* pPointSequence = rPointSequenceSequenceSource.getConstArray();
622             const com::sun::star::drawing::PointSequence* pPointSeqEnd = pPointSequence + rPointSequenceSequenceSource.getLength();
623 
624             for(;pPointSequence != pPointSeqEnd; pPointSequence++)
625             {
626                 const B2DPolygon aNewPolygon = UnoPointSequenceToB2DPolygon(*pPointSequence, bCheckClosed);
627                 aRetval.append(aNewPolygon);
628             }
629 
630             return aRetval;
631         }
632 
B2DPolyPolygonToUnoPointSequenceSequence(const B2DPolyPolygon & rPolyPolygon,com::sun::star::drawing::PointSequenceSequence & rPointSequenceSequenceRetval)633         void B2DPolyPolygonToUnoPointSequenceSequence(
634             const B2DPolyPolygon& rPolyPolygon,
635             com::sun::star::drawing::PointSequenceSequence& rPointSequenceSequenceRetval)
636         {
637             const sal_uInt32 nCount(rPolyPolygon.count());
638 
639             if(nCount)
640             {
641                 rPointSequenceSequenceRetval.realloc(nCount);
642                 com::sun::star::drawing::PointSequence* pPointSequence = rPointSequenceSequenceRetval.getArray();
643 
644                 for(sal_uInt32 a(0); a < nCount; a++)
645                 {
646                     const B2DPolygon aPolygon(rPolyPolygon.getB2DPolygon(a));
647 
648                     B2DPolygonToUnoPointSequence(aPolygon, *pPointSequence);
649                     pPointSequence++;
650                 }
651             }
652             else
653             {
654                 rPointSequenceSequenceRetval.realloc(0);
655             }
656         }
657 
658         //////////////////////////////////////////////////////////////////////////////
659         // converters for com::sun::star::drawing::PolyPolygonBezierCoords (curved polygons)
660 
UnoPolyPolygonBezierCoordsToB2DPolyPolygon(const com::sun::star::drawing::PolyPolygonBezierCoords & rPolyPolygonBezierCoordsSource,bool bCheckClosed)661         B2DPolyPolygon UnoPolyPolygonBezierCoordsToB2DPolyPolygon(
662             const com::sun::star::drawing::PolyPolygonBezierCoords& rPolyPolygonBezierCoordsSource,
663             bool bCheckClosed)
664         {
665             B2DPolyPolygon aRetval;
666             const sal_uInt32 nSequenceCount((sal_uInt32)rPolyPolygonBezierCoordsSource.Coordinates.getLength());
667 
668             if(nSequenceCount)
669             {
670                 OSL_ENSURE(nSequenceCount == (sal_uInt32)rPolyPolygonBezierCoordsSource.Flags.getLength(),
671                     "UnoPolyPolygonBezierCoordsToB2DPolyPolygon: unequal number of Points and Flags (!)");
672                 const com::sun::star::drawing::PointSequence* pPointSequence = rPolyPolygonBezierCoordsSource.Coordinates.getConstArray();
673                 const com::sun::star::drawing::FlagSequence* pFlagSequence = rPolyPolygonBezierCoordsSource.Flags.getConstArray();
674 
675                 for(sal_uInt32 a(0); a < nSequenceCount; a++)
676                 {
677                     const B2DPolygon aNewPolygon(UnoPolygonBezierCoordsToB2DPolygon(
678                         *pPointSequence,
679                         *pFlagSequence,
680                         bCheckClosed));
681 
682                     pPointSequence++;
683                     pFlagSequence++;
684                     aRetval.append(aNewPolygon);
685                 }
686             }
687 
688             return aRetval;
689         }
690 
B2DPolyPolygonToUnoPolyPolygonBezierCoords(const B2DPolyPolygon & rPolyPolygon,com::sun::star::drawing::PolyPolygonBezierCoords & rPolyPolygonBezierCoordsRetval)691         void B2DPolyPolygonToUnoPolyPolygonBezierCoords(
692             const B2DPolyPolygon& rPolyPolygon,
693             com::sun::star::drawing::PolyPolygonBezierCoords& rPolyPolygonBezierCoordsRetval)
694         {
695             const sal_uInt32 nCount(rPolyPolygon.count());
696 
697             if(nCount)
698             {
699                 // prepare return value memory
700                 rPolyPolygonBezierCoordsRetval.Coordinates.realloc((sal_Int32)nCount);
701                 rPolyPolygonBezierCoordsRetval.Flags.realloc((sal_Int32)nCount);
702 
703                 // get pointers to arrays
704                 com::sun::star::drawing::PointSequence* pPointSequence = rPolyPolygonBezierCoordsRetval.Coordinates.getArray();
705                 com::sun::star::drawing::FlagSequence*  pFlagSequence = rPolyPolygonBezierCoordsRetval.Flags.getArray();
706 
707                 for(sal_uInt32 a(0); a < nCount; a++)
708                 {
709                     const B2DPolygon aSource(rPolyPolygon.getB2DPolygon(a));
710 
711                     B2DPolygonToUnoPolygonBezierCoords(
712                         aSource,
713                         *pPointSequence,
714                         *pFlagSequence);
715                     pPointSequence++;
716                     pFlagSequence++;
717                 }
718             }
719             else
720             {
721                 rPolyPolygonBezierCoordsRetval.Coordinates.realloc(0);
722                 rPolyPolygonBezierCoordsRetval.Flags.realloc(0);
723             }
724         }
725 
726     } // end of namespace tools
727 } // end of namespace basegfx
728 
729 //////////////////////////////////////////////////////////////////////////////
730 // eof
731