fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / tools / source / generic / poly2.cxx
blobd390a6e862dbf4c087a1980e6e9e58c8a409d378
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
28 #include <poly.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 )
40 mnRefCount = 1;
41 mnCount = nInitSize;
42 mnSize = nInitSize;
43 mnResize = 16;
44 mpPolyAry = new SVPPOLYGON[ nInitSize ];
47 ImplPolyPolygon::ImplPolyPolygon( const ImplPolyPolygon& rImplPolyPoly )
49 mnRefCount = 1;
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] );
60 else
61 mpPolyAry = NULL;
64 ImplPolyPolygon::~ImplPolyPolygon()
66 if ( mpPolyAry )
68 for ( sal_uInt16 i = 0; i < mnCount; i++ )
69 delete mpPolyAry[i];
70 delete[] mpPolyAry;
74 namespace tools {
76 PolyPolygon::PolyPolygon( sal_uInt16 nInitSize, sal_uInt16 nResize )
78 if ( nInitSize > MAX_POLYGONS )
79 nInitSize = MAX_POLYGONS;
80 else if ( !nInitSize )
81 nInitSize = 1;
82 if ( nResize > MAX_POLYGONS )
83 nResize = MAX_POLYGONS;
84 else if ( !nResize )
85 nResize = 1;
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 );
96 else
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--;
112 else
113 delete mpImplPolyPolygon;
116 void PolyPolygon::Insert( const Polygon& rPoly, sal_uInt16 nPos )
118 if ( mpImplPolyPolygon->mnCount >= MAX_POLYGONS )
119 return;
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;
136 SVPPOLYGON* pNewAry;
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;
200 if ( Count() == 1 )
201 bIsRect = mpImplPolyPolygon->mpPolyAry[ 0 ]->IsRect();
202 return bIsRect;
205 void PolyPolygon::Clear()
207 if ( mpImplPolyPolygon->mnRefCount > 1 )
209 mpImplPolyPolygon->mnRefCount--;
210 mpImplPolyPolygon = new ImplPolyPolygon( mpImplPolyPolygon->mnResize,
211 mpImplPolyPolygon->mnResize );
213 else
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())
238 bIsCurve = true;
242 if(bIsCurve)
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);
249 *this = aPolyPoly;
251 else
253 double fArea;
254 const bool bEdges = ( nOptimizeFlags & PolyOptimizeFlags::EDGES ) == PolyOptimizeFlags::EDGES;
255 sal_uInt16 nPercent = 0;
257 if( bEdges )
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 );
273 // Optimize polygons
274 for( sal_uInt16 i = 0, nPolyCount = mpImplPolyPolygon->mnCount; i < nPolyCount; i++ )
276 if( bEdges )
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
291 rResult.Clear();
293 Polygon aPolygon;
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) ) );
309 return aPolyPoly;
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
332 // polygons.
333 aMergePolyPolygonA = basegfx::tools::prepareForPolygonOperation( aMergePolyPolygonA );
334 aMergePolyPolygonB = basegfx::tools::prepareForPolygonOperation( aMergePolyPolygonB );
336 switch( nOperation )
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);
344 break;
347 case POLY_CLIP_DIFF:
349 // subtract B from A (DIFF)
350 aMergePolyPolygonA = basegfx::tools::solvePolygonOperationDiff(aMergePolyPolygonA, aMergePolyPolygonB);
351 break;
354 case POLY_CLIP_XOR:
356 // compute XOR between poly A and B
357 aMergePolyPolygonA = basegfx::tools::solvePolygonOperationXor(aMergePolyPolygonA, aMergePolyPolygonB);
358 break;
361 default:
362 case POLY_CLIP_INT:
364 // cut poly 1 against polys 2..n (AND)
365 aMergePolyPolygonA = basegfx::tools::solvePolygonOperationAnd(aMergePolyPolygonA, aMergePolyPolygonB);
366 break;
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 );
389 // move points
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 );
404 // move points
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 );
417 // Move points
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 )
424 nAngle10 %= 3600;
426 if( 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 );
441 // move points
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;
449 sal_uInt16 i;
451 if ( !nPolyCount )
452 return;
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 );
463 while ( nPolyCount )
465 if ( GetObject( nPolyCount-1 ).GetSize() <= 2 )
466 Remove( nPolyCount-1 );
467 nPolyCount--;
471 Rectangle PolyPolygon::GetBoundRect() const
473 long nXMin=0, nXMax=0, nYMin=0, nYMax=0;
474 bool bFirst = true;
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 ];
487 if ( bFirst )
489 nXMin = nXMax = pPt->X();
490 nYMin = nYMax = pPt->Y();
491 bFirst = false;
493 else
495 if ( pPt->X() < nXMin )
496 nXMin = pPt->X();
497 if ( pPt->X() > nXMax )
498 nXMax = pPt->X();
499 if ( pPt->Y() < nYMin )
500 nYMin = pPt->Y();
501 if ( pPt->Y() > nYMax )
502 nYMax = pPt->Y();
507 if ( !bFirst )
508 return Rectangle( nXMin, nYMin, nXMax, nYMax );
509 else
510 return Rectangle();
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)
529 return *this;
531 DBG_ASSERT( rPolyPoly.mpImplPolyPolygon->mnRefCount < 0xFFFFFFFE, "PolyPolygon: RefCount overflow" );
533 rPolyPoly.mpImplPolyPolygon->mnRefCount++;
535 if ( mpImplPolyPolygon->mnRefCount > 1 )
536 mpImplPolyPolygon->mnRefCount--;
537 else
538 delete mpImplPolyPolygon;
540 mpImplPolyPolygon = rPolyPoly.mpImplPolyPolygon;
541 return *this;
544 bool PolyPolygon::operator==( const tools::PolyPolygon& rPolyPoly ) const
546 if ( rPolyPoly.mpImplPolyPolygon == mpImplPolyPolygon )
547 return true;
548 else
549 return false;
552 bool PolyPolygon::IsEqual( const tools::PolyPolygon& rPolyPoly ) const
554 bool bIsEqual = true;
555 if ( Count() != rPolyPoly.Count() )
556 bIsEqual = false;
557 else
559 sal_uInt16 i;
560 for ( i = 0; i < Count(); i++ )
562 if (!GetObject( i ).IsEqual( rPolyPoly.GetObject( i ) ) )
564 bIsEqual = false;
565 break;
569 return bIsEqual;
572 SvStream& ReadPolyPolygon( SvStream& rIStream, tools::PolyPolygon& rPolyPoly )
574 DBG_ASSERTWARNING( rIStream.GetVersion(), "PolyPolygon::>> - Solar-Version not set on rIStream" );
576 Polygon* pPoly;
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;
591 if( nPolyCount )
593 if ( rPolyPoly.mpImplPolyPolygon->mnRefCount > 1 )
594 rPolyPoly.mpImplPolyPolygon->mnRefCount--;
595 else
596 delete rPolyPoly.mpImplPolyPolygon;
598 rPolyPoly.mpImplPolyPolygon = new ImplPolyPolygon( nPolyCount );
600 for ( sal_uInt16 i = 0; i < nPolyCount; i++ )
602 pPoly = new Polygon;
603 ReadPolygon( rIStream, *pPoly );
604 rPolyPoly.mpImplPolyPolygon->mpPolyAry[i] = pPoly;
607 else
608 rPolyPoly = tools::PolyPolygon();
610 return rIStream;
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 );
621 // output polygons
622 for ( sal_uInt16 i = 0; i < nPolyCount; i++ )
623 WritePolygon( rOStream, *(rPolyPoly.mpImplPolyPolygon->mpPolyAry[i]) );
625 return rOStream;
628 void PolyPolygon::Read( SvStream& rIStream )
630 VersionCompat aCompat( rIStream, StreamMode::READ );
632 DBG_ASSERTWARNING( rIStream.GetVersion(), "PolyPolygon::>> - Solar-Version not set on rIStream" );
634 Polygon* pPoly;
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;
649 if( nPolyCount )
651 if ( mpImplPolyPolygon->mnRefCount > 1 )
652 mpImplPolyPolygon->mnRefCount--;
653 else
654 delete mpImplPolyPolygon;
656 mpImplPolyPolygon = new ImplPolyPolygon( nPolyCount );
658 for ( sal_uInt16 i = 0; i < nPolyCount; i++ )
660 pPoly = new Polygon;
661 pPoly->ImplRead( rIStream );
662 mpImplPolyPolygon->mpPolyAry[i] = pPoly;
665 else
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 );
679 // Output polygons
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());
695 return aRetval;
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 (!)");
705 if ( nCount )
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 );
715 else
717 mpImplPolyPolygon = new ImplPolyPolygon( 16, 16 );
721 } /* namespace tools */
723 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */