1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #define POLY_CLIP_INT 0
21 #define POLY_CLIP_UNION 1
22 #define POLY_CLIP_DIFF 2
23 #define POLY_CLIP_XOR 3
25 #include <rtl/math.hxx>
26 #include <sal/log.hxx>
27 #include <osl/diagnose.h>
29 #include <tools/poly.hxx>
30 #include <tools/debug.hxx>
31 #include <tools/stream.hxx>
32 #include <tools/vcompat.hxx>
33 #include <tools/gen.hxx>
34 #include <basegfx/polygon/b2dpolypolygon.hxx>
35 #include <basegfx/polygon/b2dpolygon.hxx>
36 #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
38 ImplPolyPolygon::ImplPolyPolygon( sal_uInt16 nInitSize
)
44 mpPolyAry
= new SVPPOLYGON
[ nInitSize
];
47 ImplPolyPolygon::ImplPolyPolygon( const ImplPolyPolygon
& rImplPolyPoly
)
50 mnCount
= rImplPolyPoly
.mnCount
;
51 mnSize
= rImplPolyPoly
.mnSize
;
52 mnResize
= rImplPolyPoly
.mnResize
;
54 if ( rImplPolyPoly
.mpPolyAry
)
56 mpPolyAry
= new SVPPOLYGON
[mnSize
];
57 for ( sal_uInt16 i
= 0; i
< mnCount
; i
++ )
58 mpPolyAry
[i
] = new Polygon( *rImplPolyPoly
.mpPolyAry
[i
] );
64 ImplPolyPolygon::~ImplPolyPolygon()
68 for ( sal_uInt16 i
= 0; i
< mnCount
; i
++ )
76 PolyPolygon::PolyPolygon( sal_uInt16 nInitSize
, sal_uInt16 nResize
)
78 if ( nInitSize
> MAX_POLYGONS
)
79 nInitSize
= MAX_POLYGONS
;
80 else if ( !nInitSize
)
82 if ( nResize
> MAX_POLYGONS
)
83 nResize
= MAX_POLYGONS
;
86 mpImplPolyPolygon
= new ImplPolyPolygon( nInitSize
, nResize
);
89 PolyPolygon::PolyPolygon( const Polygon
& rPoly
)
91 if ( rPoly
.GetSize() )
93 mpImplPolyPolygon
= new ImplPolyPolygon( 1 );
94 mpImplPolyPolygon
->mpPolyAry
[0] = new Polygon( rPoly
);
97 mpImplPolyPolygon
= new ImplPolyPolygon( 16, 16 );
100 PolyPolygon::PolyPolygon( const tools::PolyPolygon
& rPolyPoly
)
102 DBG_ASSERT( rPolyPoly
.mpImplPolyPolygon
->mnRefCount
< 0xFFFFFFFE, "PolyPolygon: RefCount overflow" );
104 mpImplPolyPolygon
= rPolyPoly
.mpImplPolyPolygon
;
105 mpImplPolyPolygon
->mnRefCount
++;
108 PolyPolygon::~PolyPolygon()
110 if ( mpImplPolyPolygon
->mnRefCount
> 1 )
111 mpImplPolyPolygon
->mnRefCount
--;
113 delete mpImplPolyPolygon
;
116 void PolyPolygon::Insert( const Polygon
& rPoly
, sal_uInt16 nPos
)
118 if ( mpImplPolyPolygon
->mnCount
>= MAX_POLYGONS
)
121 if ( mpImplPolyPolygon
->mnRefCount
> 1 )
123 mpImplPolyPolygon
->mnRefCount
--;
124 mpImplPolyPolygon
= new ImplPolyPolygon( *mpImplPolyPolygon
);
127 if ( nPos
> mpImplPolyPolygon
->mnCount
)
128 nPos
= mpImplPolyPolygon
->mnCount
;
130 if ( !mpImplPolyPolygon
->mpPolyAry
)
131 mpImplPolyPolygon
->mpPolyAry
= new SVPPOLYGON
[mpImplPolyPolygon
->mnSize
];
132 else if ( mpImplPolyPolygon
->mnCount
== mpImplPolyPolygon
->mnSize
)
134 sal_uInt16 nOldSize
= mpImplPolyPolygon
->mnSize
;
135 sal_uInt16 nNewSize
= nOldSize
+ mpImplPolyPolygon
->mnResize
;
138 if ( nNewSize
>= MAX_POLYGONS
)
139 nNewSize
= MAX_POLYGONS
;
140 pNewAry
= new SVPPOLYGON
[nNewSize
];
141 memcpy( pNewAry
, mpImplPolyPolygon
->mpPolyAry
, nPos
*sizeof(SVPPOLYGON
) );
142 memcpy( pNewAry
+nPos
+1, mpImplPolyPolygon
->mpPolyAry
+nPos
,
143 (nOldSize
-nPos
)*sizeof(SVPPOLYGON
) );
144 delete[] mpImplPolyPolygon
->mpPolyAry
;
145 mpImplPolyPolygon
->mpPolyAry
= pNewAry
;
146 mpImplPolyPolygon
->mnSize
= nNewSize
;
148 else if ( nPos
< mpImplPolyPolygon
->mnCount
)
150 memmove( mpImplPolyPolygon
->mpPolyAry
+nPos
+1,
151 mpImplPolyPolygon
->mpPolyAry
+nPos
,
152 (mpImplPolyPolygon
->mnCount
-nPos
)*sizeof(SVPPOLYGON
) );
155 mpImplPolyPolygon
->mpPolyAry
[nPos
] = new Polygon( rPoly
);
156 mpImplPolyPolygon
->mnCount
++;
159 void PolyPolygon::Remove( sal_uInt16 nPos
)
161 assert(nPos
< Count() && "PolyPolygon::Remove(): nPos >= nSize");
163 if ( mpImplPolyPolygon
->mnRefCount
> 1 )
165 mpImplPolyPolygon
->mnRefCount
--;
166 mpImplPolyPolygon
= new ImplPolyPolygon( *mpImplPolyPolygon
);
169 delete mpImplPolyPolygon
->mpPolyAry
[nPos
];
170 mpImplPolyPolygon
->mnCount
--;
171 memmove( mpImplPolyPolygon
->mpPolyAry
+nPos
,
172 mpImplPolyPolygon
->mpPolyAry
+nPos
+1,
173 (mpImplPolyPolygon
->mnCount
-nPos
)*sizeof(SVPPOLYGON
) );
176 void PolyPolygon::Replace( const Polygon
& rPoly
, sal_uInt16 nPos
)
178 assert(nPos
< Count() && "PolyPolygon::Replace(): nPos >= nSize");
180 if ( mpImplPolyPolygon
->mnRefCount
> 1 )
182 mpImplPolyPolygon
->mnRefCount
--;
183 mpImplPolyPolygon
= new ImplPolyPolygon( *mpImplPolyPolygon
);
186 delete mpImplPolyPolygon
->mpPolyAry
[nPos
];
187 mpImplPolyPolygon
->mpPolyAry
[nPos
] = new Polygon( rPoly
);
190 const Polygon
& PolyPolygon::GetObject( sal_uInt16 nPos
) const
192 assert(nPos
< Count() && "PolyPolygon::GetObject(): nPos >= nSize");
194 return *(mpImplPolyPolygon
->mpPolyAry
[nPos
]);
197 bool PolyPolygon::IsRect() const
199 bool bIsRect
= false;
201 bIsRect
= mpImplPolyPolygon
->mpPolyAry
[ 0 ]->IsRect();
205 void PolyPolygon::Clear()
207 if ( mpImplPolyPolygon
->mnRefCount
> 1 )
209 mpImplPolyPolygon
->mnRefCount
--;
210 mpImplPolyPolygon
= new ImplPolyPolygon( mpImplPolyPolygon
->mnResize
,
211 mpImplPolyPolygon
->mnResize
);
215 if ( mpImplPolyPolygon
->mpPolyAry
)
217 for ( sal_uInt16 i
= 0; i
< mpImplPolyPolygon
->mnCount
; i
++ )
218 delete mpImplPolyPolygon
->mpPolyAry
[i
];
219 delete[] mpImplPolyPolygon
->mpPolyAry
;
220 mpImplPolyPolygon
->mpPolyAry
= NULL
;
221 mpImplPolyPolygon
->mnCount
= 0;
222 mpImplPolyPolygon
->mnSize
= mpImplPolyPolygon
->mnResize
;
227 void PolyPolygon::Optimize( PolyOptimizeFlags nOptimizeFlags
, const PolyOptimizeData
* pData
)
229 if(bool(nOptimizeFlags
) && Count())
231 // #115630# ImplDrawHatch does not work with beziers included in the polypolygon, take care of that
232 bool bIsCurve(false);
234 for(sal_uInt16
a(0); !bIsCurve
&& a
< Count(); a
++)
236 if((*this)[a
].HasFlags())
244 OSL_ENSURE(false, "Optimize does *not* support curves, falling back to AdaptiveSubdivide()...");
245 tools::PolyPolygon aPolyPoly
;
247 AdaptiveSubdivide(aPolyPoly
);
248 aPolyPoly
.Optimize(nOptimizeFlags
, pData
);
254 const bool bEdges
= ( nOptimizeFlags
& PolyOptimizeFlags::EDGES
) == PolyOptimizeFlags::EDGES
;
255 sal_uInt16 nPercent
= 0;
259 const Rectangle
aBound( GetBoundRect() );
261 fArea
= ( aBound
.GetWidth() + aBound
.GetHeight() ) * 0.5;
262 nPercent
= pData
? pData
->GetPercentValue() : 50;
263 nOptimizeFlags
&= ~PolyOptimizeFlags::EDGES
;
266 // watch for ref counter
267 if( mpImplPolyPolygon
->mnRefCount
> 1 )
269 mpImplPolyPolygon
->mnRefCount
--;
270 mpImplPolyPolygon
= new ImplPolyPolygon( *mpImplPolyPolygon
);
274 for( sal_uInt16 i
= 0, nPolyCount
= mpImplPolyPolygon
->mnCount
; i
< nPolyCount
; i
++ )
278 mpImplPolyPolygon
->mpPolyAry
[ i
]->Optimize( PolyOptimizeFlags::NO_SAME
);
279 Polygon::ImplReduceEdges( *( mpImplPolyPolygon
->mpPolyAry
[ i
] ), fArea
, nPercent
);
282 if( bool(nOptimizeFlags
) )
283 mpImplPolyPolygon
->mpPolyAry
[ i
]->Optimize( nOptimizeFlags
, pData
);
289 void PolyPolygon::AdaptiveSubdivide( tools::PolyPolygon
& rResult
, const double d
) const
295 for( sal_uInt16 i
= 0; i
< mpImplPolyPolygon
->mnCount
; i
++ )
297 mpImplPolyPolygon
->mpPolyAry
[ i
]->AdaptiveSubdivide( aPolygon
, d
);
298 rResult
.Insert( aPolygon
);
302 tools::PolyPolygon
PolyPolygon::SubdivideBezier( const tools::PolyPolygon
& rPolyPoly
)
304 sal_uInt16 i
, nPolys
= rPolyPoly
.Count();
305 tools::PolyPolygon
aPolyPoly( nPolys
);
306 for( i
=0; i
<nPolys
; ++i
)
307 aPolyPoly
.Insert( Polygon::SubdivideBezier( rPolyPoly
.GetObject(i
) ) );
313 void PolyPolygon::GetIntersection( const tools::PolyPolygon
& rPolyPoly
, tools::PolyPolygon
& rResult
) const
315 ImplDoOperation( rPolyPoly
, rResult
, POLY_CLIP_INT
);
318 void PolyPolygon::GetUnion( const tools::PolyPolygon
& rPolyPoly
, tools::PolyPolygon
& rResult
) const
320 ImplDoOperation( rPolyPoly
, rResult
, POLY_CLIP_UNION
);
323 void PolyPolygon::ImplDoOperation( const tools::PolyPolygon
& rPolyPoly
, tools::PolyPolygon
& rResult
, sal_uIntPtr nOperation
) const
325 // Convert to B2DPolyPolygon, temporarily. It might be
326 // advantageous in the future, to have a tools::PolyPolygon adaptor that
327 // just simulates a B2DPolyPolygon here...
328 basegfx::B2DPolyPolygon
aMergePolyPolygonA( getB2DPolyPolygon() );
329 basegfx::B2DPolyPolygon
aMergePolyPolygonB( rPolyPoly
.getB2DPolyPolygon() );
331 // normalize the two polypolygons before. Force properly oriented
333 aMergePolyPolygonA
= basegfx::tools::prepareForPolygonOperation( aMergePolyPolygonA
);
334 aMergePolyPolygonB
= basegfx::tools::prepareForPolygonOperation( aMergePolyPolygonB
);
338 // All code extracted from svx/source/svdraw/svedtv2.cxx
340 case POLY_CLIP_UNION
:
342 // merge A and B (OR)
343 aMergePolyPolygonA
= basegfx::tools::solvePolygonOperationOr(aMergePolyPolygonA
, aMergePolyPolygonB
);
349 // subtract B from A (DIFF)
350 aMergePolyPolygonA
= basegfx::tools::solvePolygonOperationDiff(aMergePolyPolygonA
, aMergePolyPolygonB
);
356 // compute XOR between poly A and B
357 aMergePolyPolygonA
= basegfx::tools::solvePolygonOperationXor(aMergePolyPolygonA
, aMergePolyPolygonB
);
364 // cut poly 1 against polys 2..n (AND)
365 aMergePolyPolygonA
= basegfx::tools::solvePolygonOperationAnd(aMergePolyPolygonA
, aMergePolyPolygonB
);
370 rResult
= tools::PolyPolygon( aMergePolyPolygonA
);
373 sal_uInt16
PolyPolygon::Count() const
375 return mpImplPolyPolygon
->mnCount
;
378 void PolyPolygon::Move( long nHorzMove
, long nVertMove
)
380 // Required for DrawEngine
381 if( nHorzMove
|| nVertMove
)
383 if ( mpImplPolyPolygon
->mnRefCount
> 1 )
385 mpImplPolyPolygon
->mnRefCount
--;
386 mpImplPolyPolygon
= new ImplPolyPolygon( *mpImplPolyPolygon
);
390 sal_uInt16 nPolyCount
= mpImplPolyPolygon
->mnCount
;
391 for ( sal_uInt16 i
= 0; i
< nPolyCount
; i
++ )
392 mpImplPolyPolygon
->mpPolyAry
[i
]->Move( nHorzMove
, nVertMove
);
396 void PolyPolygon::Translate( const Point
& rTrans
)
398 if( mpImplPolyPolygon
->mnRefCount
> 1 )
400 mpImplPolyPolygon
->mnRefCount
--;
401 mpImplPolyPolygon
= new ImplPolyPolygon( *mpImplPolyPolygon
);
405 for ( sal_uInt16 i
= 0, nCount
= mpImplPolyPolygon
->mnCount
; i
< nCount
; i
++ )
406 mpImplPolyPolygon
->mpPolyAry
[ i
]->Translate( rTrans
);
409 void PolyPolygon::Scale( double fScaleX
, double fScaleY
)
411 if( mpImplPolyPolygon
->mnRefCount
> 1 )
413 mpImplPolyPolygon
->mnRefCount
--;
414 mpImplPolyPolygon
= new ImplPolyPolygon( *mpImplPolyPolygon
);
418 for ( sal_uInt16 i
= 0, nCount
= mpImplPolyPolygon
->mnCount
; i
< nCount
; i
++ )
419 mpImplPolyPolygon
->mpPolyAry
[ i
]->Scale( fScaleX
, fScaleY
);
422 void PolyPolygon::Rotate( const Point
& rCenter
, sal_uInt16 nAngle10
)
428 const double fAngle
= F_PI1800
* nAngle10
;
429 Rotate( rCenter
, sin( fAngle
), cos( fAngle
) );
433 void PolyPolygon::Rotate( const Point
& rCenter
, double fSin
, double fCos
)
435 if( mpImplPolyPolygon
->mnRefCount
> 1 )
437 mpImplPolyPolygon
->mnRefCount
--;
438 mpImplPolyPolygon
= new ImplPolyPolygon( *mpImplPolyPolygon
);
442 for ( sal_uInt16 i
= 0, nCount
= mpImplPolyPolygon
->mnCount
; i
< nCount
; i
++ )
443 mpImplPolyPolygon
->mpPolyAry
[ i
]->Rotate( rCenter
, fSin
, fCos
);
446 void PolyPolygon::Clip( const Rectangle
& rRect
)
448 sal_uInt16 nPolyCount
= mpImplPolyPolygon
->mnCount
;
454 if ( mpImplPolyPolygon
->mnRefCount
> 1 )
456 mpImplPolyPolygon
->mnRefCount
--;
457 mpImplPolyPolygon
= new ImplPolyPolygon( *mpImplPolyPolygon
);
460 // Clip every polygon, deleting the empty ones
461 for ( i
= 0; i
< nPolyCount
; i
++ )
462 mpImplPolyPolygon
->mpPolyAry
[i
]->Clip( rRect
);
465 if ( GetObject( nPolyCount
-1 ).GetSize() <= 2 )
466 Remove( nPolyCount
-1 );
471 Rectangle
PolyPolygon::GetBoundRect() const
473 long nXMin
=0, nXMax
=0, nYMin
=0, nYMax
=0;
475 sal_uInt16 nPolyCount
= mpImplPolyPolygon
->mnCount
;
477 for ( sal_uInt16 n
= 0; n
< nPolyCount
; n
++ )
479 const Polygon
* pPoly
= mpImplPolyPolygon
->mpPolyAry
[n
];
480 const Point
* pAry
= pPoly
->GetConstPointAry();
481 sal_uInt16 nPointCount
= pPoly
->GetSize();
483 for ( sal_uInt16 i
= 0; i
< nPointCount
; i
++ )
485 const Point
* pPt
= &pAry
[ i
];
489 nXMin
= nXMax
= pPt
->X();
490 nYMin
= nYMax
= pPt
->Y();
495 if ( pPt
->X() < nXMin
)
497 if ( pPt
->X() > nXMax
)
499 if ( pPt
->Y() < nYMin
)
501 if ( pPt
->Y() > nYMax
)
508 return Rectangle( nXMin
, nYMin
, nXMax
, nYMax
);
513 Polygon
& PolyPolygon::operator[]( sal_uInt16 nPos
)
515 assert(nPos
< Count() && "PolyPolygon::[](): nPos >= nSize");
517 if ( mpImplPolyPolygon
->mnRefCount
> 1 )
519 mpImplPolyPolygon
->mnRefCount
--;
520 mpImplPolyPolygon
= new ImplPolyPolygon( *mpImplPolyPolygon
);
523 return *(mpImplPolyPolygon
->mpPolyAry
[nPos
]);
526 PolyPolygon
& PolyPolygon::operator=( const tools::PolyPolygon
& rPolyPoly
)
528 if (this == &rPolyPoly
)
531 DBG_ASSERT( rPolyPoly
.mpImplPolyPolygon
->mnRefCount
< 0xFFFFFFFE, "PolyPolygon: RefCount overflow" );
533 rPolyPoly
.mpImplPolyPolygon
->mnRefCount
++;
535 if ( mpImplPolyPolygon
->mnRefCount
> 1 )
536 mpImplPolyPolygon
->mnRefCount
--;
538 delete mpImplPolyPolygon
;
540 mpImplPolyPolygon
= rPolyPoly
.mpImplPolyPolygon
;
544 bool PolyPolygon::operator==( const tools::PolyPolygon
& rPolyPoly
) const
546 if ( rPolyPoly
.mpImplPolyPolygon
== mpImplPolyPolygon
)
552 bool PolyPolygon::IsEqual( const tools::PolyPolygon
& rPolyPoly
) const
554 bool bIsEqual
= true;
555 if ( Count() != rPolyPoly
.Count() )
560 for ( i
= 0; i
< Count(); i
++ )
562 if (!GetObject( i
).IsEqual( rPolyPoly
.GetObject( i
) ) )
572 SvStream
& ReadPolyPolygon( SvStream
& rIStream
, tools::PolyPolygon
& rPolyPoly
)
574 DBG_ASSERTWARNING( rIStream
.GetVersion(), "PolyPolygon::>> - Solar-Version not set on rIStream" );
577 sal_uInt16
nPolyCount(0);
579 // Read number of polygons
580 rIStream
.ReadUInt16( nPolyCount
);
582 const size_t nMinRecordSize
= sizeof(sal_uInt16
);
583 const size_t nMaxRecords
= rIStream
.remainingSize() / nMinRecordSize
;
584 if (nPolyCount
> nMaxRecords
)
586 SAL_WARN("tools", "Parsing error: " << nMaxRecords
<<
587 " max possible entries, but " << nPolyCount
<< " claimed, truncating");
588 nPolyCount
= nMaxRecords
;
593 if ( rPolyPoly
.mpImplPolyPolygon
->mnRefCount
> 1 )
594 rPolyPoly
.mpImplPolyPolygon
->mnRefCount
--;
596 delete rPolyPoly
.mpImplPolyPolygon
;
598 rPolyPoly
.mpImplPolyPolygon
= new ImplPolyPolygon( nPolyCount
);
600 for ( sal_uInt16 i
= 0; i
< nPolyCount
; i
++ )
603 ReadPolygon( rIStream
, *pPoly
);
604 rPolyPoly
.mpImplPolyPolygon
->mpPolyAry
[i
] = pPoly
;
608 rPolyPoly
= tools::PolyPolygon();
613 SvStream
& WritePolyPolygon( SvStream
& rOStream
, const tools::PolyPolygon
& rPolyPoly
)
615 DBG_ASSERTWARNING( rOStream
.GetVersion(), "PolyPolygon::<< - Solar-Version not set on rOStream" );
617 // Write number of polygons
618 sal_uInt16 nPolyCount
= rPolyPoly
.mpImplPolyPolygon
->mnCount
;
619 rOStream
.WriteUInt16( nPolyCount
);
622 for ( sal_uInt16 i
= 0; i
< nPolyCount
; i
++ )
623 WritePolygon( rOStream
, *(rPolyPoly
.mpImplPolyPolygon
->mpPolyAry
[i
]) );
628 void PolyPolygon::Read( SvStream
& rIStream
)
630 VersionCompat
aCompat( rIStream
, StreamMode::READ
);
632 DBG_ASSERTWARNING( rIStream
.GetVersion(), "PolyPolygon::>> - Solar-Version not set on rIStream" );
635 sal_uInt16
nPolyCount(0);
637 // Read number of polygons
638 rIStream
.ReadUInt16( nPolyCount
);
640 const size_t nMinRecordSize
= sizeof(sal_uInt16
);
641 const size_t nMaxRecords
= rIStream
.remainingSize() / nMinRecordSize
;
642 if (nPolyCount
> nMaxRecords
)
644 SAL_WARN("tools", "Parsing error: " << nMaxRecords
<<
645 " max possible entries, but " << nPolyCount
<< " claimed, truncating");
646 nPolyCount
= nMaxRecords
;
651 if ( mpImplPolyPolygon
->mnRefCount
> 1 )
652 mpImplPolyPolygon
->mnRefCount
--;
654 delete mpImplPolyPolygon
;
656 mpImplPolyPolygon
= new ImplPolyPolygon( nPolyCount
);
658 for ( sal_uInt16 i
= 0; i
< nPolyCount
; i
++ )
661 pPoly
->ImplRead( rIStream
);
662 mpImplPolyPolygon
->mpPolyAry
[i
] = pPoly
;
666 *this = tools::PolyPolygon();
669 void PolyPolygon::Write( SvStream
& rOStream
) const
671 VersionCompat
aCompat( rOStream
, StreamMode::WRITE
, 1 );
673 DBG_ASSERTWARNING( rOStream
.GetVersion(), "PolyPolygon::<< - Solar-Version not set on rOStream" );
675 // Write number of polygons
676 sal_uInt16 nPolyCount
= mpImplPolyPolygon
->mnCount
;
677 rOStream
.WriteUInt16( nPolyCount
);
680 for ( sal_uInt16 i
= 0; i
< nPolyCount
; i
++ )
681 mpImplPolyPolygon
->mpPolyAry
[i
]->ImplWrite( rOStream
);
684 // convert to basegfx::B2DPolyPolygon and return
685 basegfx::B2DPolyPolygon
PolyPolygon::getB2DPolyPolygon() const
687 basegfx::B2DPolyPolygon aRetval
;
689 for(sal_uInt16
a(0); a
< mpImplPolyPolygon
->mnCount
; a
++)
691 Polygon
* pCandidate
= mpImplPolyPolygon
->mpPolyAry
[a
];
692 aRetval
.append(pCandidate
->getB2DPolygon());
698 // constructor to convert from basegfx::B2DPolyPolygon
699 PolyPolygon::PolyPolygon(const basegfx::B2DPolyPolygon
& rPolyPolygon
)
701 const sal_uInt16
nCount(sal_uInt16(rPolyPolygon
.count()));
702 DBG_ASSERT(sal_uInt32(nCount
) == rPolyPolygon
.count(),
703 "PolyPolygon::PolyPolygon: Too many sub-polygons in given basegfx::B2DPolyPolygon (!)");
707 mpImplPolyPolygon
= new ImplPolyPolygon( nCount
);
709 for(sal_uInt16
a(0); a
< nCount
; a
++)
711 basegfx::B2DPolygon
aCandidate(rPolyPolygon
.getB2DPolygon(sal_uInt32(a
)));
712 mpImplPolyPolygon
->mpPolyAry
[a
] = new Polygon( aCandidate
);
717 mpImplPolyPolygon
= new ImplPolyPolygon( 16, 16 );
721 } /* namespace tools */
723 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */