merge the formfield patch from ooo-build
[ooovba.git] / tools / source / generic / poly2.cxx
blob803beafab0e897e91bba95dd32bdea8a8f05caf9
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: poly2.cxx,v $
10 * $Revision: 1.23 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_tools.hxx"
34 #define _SV_POLY2_CXX
36 #define POLY_CLIP_INT 0
37 #define POLY_CLIP_UNION 1
38 #define POLY_CLIP_DIFF 2
39 #define POLY_CLIP_XOR 3
41 #include <rtl/math.hxx>
42 #include <poly.h>
43 #include <tools/poly.hxx>
44 #include <tools/debug.hxx>
45 #include <tools/stream.hxx>
46 #include <tools/vcompat.hxx>
47 #include <basegfx/polygon/b2dpolypolygon.hxx>
48 #include <basegfx/polygon/b2dpolygon.hxx>
49 #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
51 // ---------------
52 // - PolyPolygon -
53 // ---------------
55 DBG_NAME( PolyPolygon )
57 // -----------------------------------------------------------------------
59 ImplPolyPolygon::ImplPolyPolygon( USHORT nInitSize )
61 mnRefCount = 1;
62 mnCount = nInitSize;
63 mnSize = nInitSize;
64 mnResize = 16;
65 mpPolyAry = new SVPPOLYGON[ nInitSize ];
68 // -----------------------------------------------------------------------
70 ImplPolyPolygon::ImplPolyPolygon( const ImplPolyPolygon& rImplPolyPoly )
72 mnRefCount = 1;
73 mnCount = rImplPolyPoly.mnCount;
74 mnSize = rImplPolyPoly.mnSize;
75 mnResize = rImplPolyPoly.mnResize;
77 if ( rImplPolyPoly.mpPolyAry )
79 mpPolyAry = new SVPPOLYGON[mnSize];
80 for ( USHORT i = 0; i < mnCount; i++ )
81 mpPolyAry[i] = new Polygon( *rImplPolyPoly.mpPolyAry[i] );
83 else
84 mpPolyAry = NULL;
87 // -----------------------------------------------------------------------
89 ImplPolyPolygon::~ImplPolyPolygon()
91 if ( mpPolyAry )
93 for ( USHORT i = 0; i < mnCount; i++ )
94 delete mpPolyAry[i];
95 delete[] mpPolyAry;
99 // =======================================================================
101 PolyPolygon::PolyPolygon( USHORT nInitSize, USHORT nResize )
103 DBG_CTOR( PolyPolygon, NULL );
105 if ( nInitSize > MAX_POLYGONS )
106 nInitSize = MAX_POLYGONS;
107 else if ( !nInitSize )
108 nInitSize = 1;
109 if ( nResize > MAX_POLYGONS )
110 nResize = MAX_POLYGONS;
111 else if ( !nResize )
112 nResize = 1;
113 mpImplPolyPolygon = new ImplPolyPolygon( nInitSize, nResize );
116 // -----------------------------------------------------------------------
118 PolyPolygon::PolyPolygon( const Polygon& rPoly )
120 DBG_CTOR( PolyPolygon, NULL );
122 if ( rPoly.GetSize() )
124 mpImplPolyPolygon = new ImplPolyPolygon( 1 );
125 mpImplPolyPolygon->mpPolyAry[0] = new Polygon( rPoly );
127 else
128 mpImplPolyPolygon = new ImplPolyPolygon( 16, 16 );
131 // -----------------------------------------------------------------------
133 PolyPolygon::PolyPolygon( USHORT nPoly, const USHORT* pPointCountAry,
134 const Point* pPtAry )
136 DBG_CTOR( PolyPolygon, NULL );
138 if ( nPoly > MAX_POLYGONS )
139 nPoly = MAX_POLYGONS;
141 mpImplPolyPolygon = new ImplPolyPolygon( nPoly );
142 for ( USHORT i = 0; i < nPoly; i++ )
144 mpImplPolyPolygon->mpPolyAry[i] = new Polygon( *pPointCountAry, pPtAry );
145 pPtAry += *pPointCountAry;
146 pPointCountAry++;
150 // -----------------------------------------------------------------------
152 PolyPolygon::PolyPolygon( const PolyPolygon& rPolyPoly )
154 DBG_CTOR( PolyPolygon, NULL );
155 DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL );
156 DBG_ASSERT( rPolyPoly.mpImplPolyPolygon->mnRefCount < 0xFFFFFFFE, "PolyPolygon: RefCount overflow" );
158 mpImplPolyPolygon = rPolyPoly.mpImplPolyPolygon;
159 mpImplPolyPolygon->mnRefCount++;
162 // -----------------------------------------------------------------------
164 PolyPolygon::~PolyPolygon()
166 DBG_DTOR( PolyPolygon, NULL );
168 if ( mpImplPolyPolygon->mnRefCount > 1 )
169 mpImplPolyPolygon->mnRefCount--;
170 else
171 delete mpImplPolyPolygon;
174 // -----------------------------------------------------------------------
176 void PolyPolygon::Insert( const Polygon& rPoly, USHORT nPos )
178 DBG_CHKTHIS( PolyPolygon, NULL );
180 if ( mpImplPolyPolygon->mnCount >= MAX_POLYGONS )
181 return;
183 if ( mpImplPolyPolygon->mnRefCount > 1 )
185 mpImplPolyPolygon->mnRefCount--;
186 mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
189 if ( nPos > mpImplPolyPolygon->mnCount )
190 nPos = mpImplPolyPolygon->mnCount;
192 if ( !mpImplPolyPolygon->mpPolyAry )
193 mpImplPolyPolygon->mpPolyAry = new SVPPOLYGON[mpImplPolyPolygon->mnSize];
194 else if ( mpImplPolyPolygon->mnCount == mpImplPolyPolygon->mnSize )
196 USHORT nOldSize = mpImplPolyPolygon->mnSize;
197 USHORT nNewSize = nOldSize + mpImplPolyPolygon->mnResize;
198 SVPPOLYGON* pNewAry;
200 if ( nNewSize >= MAX_POLYGONS )
201 nNewSize = MAX_POLYGONS;
202 pNewAry = new SVPPOLYGON[nNewSize];
203 memcpy( pNewAry, mpImplPolyPolygon->mpPolyAry, nPos*sizeof(SVPPOLYGON) );
204 memcpy( pNewAry+nPos+1, mpImplPolyPolygon->mpPolyAry+nPos,
205 (nOldSize-nPos)*sizeof(SVPPOLYGON) );
206 delete[] mpImplPolyPolygon->mpPolyAry;
207 mpImplPolyPolygon->mpPolyAry = pNewAry;
208 mpImplPolyPolygon->mnSize = nNewSize;
210 else if ( nPos < mpImplPolyPolygon->mnCount )
212 memmove( mpImplPolyPolygon->mpPolyAry+nPos+1,
213 mpImplPolyPolygon->mpPolyAry+nPos,
214 (mpImplPolyPolygon->mnCount-nPos)*sizeof(SVPPOLYGON) );
217 mpImplPolyPolygon->mpPolyAry[nPos] = new Polygon( rPoly );
218 mpImplPolyPolygon->mnCount++;
221 // -----------------------------------------------------------------------
223 void PolyPolygon::Remove( USHORT nPos )
225 DBG_CHKTHIS( PolyPolygon, NULL );
226 DBG_ASSERT( nPos < Count(), "PolyPolygon::Remove(): nPos >= nSize" );
228 if ( mpImplPolyPolygon->mnRefCount > 1 )
230 mpImplPolyPolygon->mnRefCount--;
231 mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
234 delete mpImplPolyPolygon->mpPolyAry[nPos];
235 mpImplPolyPolygon->mnCount--;
236 memmove( mpImplPolyPolygon->mpPolyAry+nPos,
237 mpImplPolyPolygon->mpPolyAry+nPos+1,
238 (mpImplPolyPolygon->mnCount-nPos)*sizeof(SVPPOLYGON) );
241 // -----------------------------------------------------------------------
243 void PolyPolygon::Replace( const Polygon& rPoly, USHORT nPos )
245 DBG_CHKTHIS( PolyPolygon, NULL );
246 DBG_ASSERT( nPos < Count(), "PolyPolygon::Replace(): nPos >= nSize" );
248 if ( mpImplPolyPolygon->mnRefCount > 1 )
250 mpImplPolyPolygon->mnRefCount--;
251 mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
254 delete mpImplPolyPolygon->mpPolyAry[nPos];
255 mpImplPolyPolygon->mpPolyAry[nPos] = new Polygon( rPoly );
258 // -----------------------------------------------------------------------
260 const Polygon& PolyPolygon::GetObject( USHORT nPos ) const
262 DBG_CHKTHIS( PolyPolygon, NULL );
263 DBG_ASSERT( nPos < Count(), "PolyPolygon::GetObject(): nPos >= nSize" );
265 return *(mpImplPolyPolygon->mpPolyAry[nPos]);
268 // -----------------------------------------------------------------------
270 BOOL PolyPolygon::IsRect() const
272 BOOL bIsRect = FALSE;
273 if ( Count() == 1 )
274 bIsRect = mpImplPolyPolygon->mpPolyAry[ 0 ]->IsRect();
275 return bIsRect;
278 // -----------------------------------------------------------------------
280 void PolyPolygon::Clear()
282 DBG_CHKTHIS( PolyPolygon, NULL );
284 if ( mpImplPolyPolygon->mnRefCount > 1 )
286 mpImplPolyPolygon->mnRefCount--;
287 mpImplPolyPolygon = new ImplPolyPolygon( mpImplPolyPolygon->mnResize,
288 mpImplPolyPolygon->mnResize );
290 else
292 if ( mpImplPolyPolygon->mpPolyAry )
294 for ( USHORT i = 0; i < mpImplPolyPolygon->mnCount; i++ )
295 delete mpImplPolyPolygon->mpPolyAry[i];
296 delete[] mpImplPolyPolygon->mpPolyAry;
297 mpImplPolyPolygon->mpPolyAry = NULL;
298 mpImplPolyPolygon->mnCount = 0;
299 mpImplPolyPolygon->mnSize = mpImplPolyPolygon->mnResize;
304 // -----------------------------------------------------------------------
306 void PolyPolygon::Optimize( ULONG nOptimizeFlags, const PolyOptimizeData* pData )
308 DBG_CHKTHIS( PolyPolygon, NULL );
310 if( nOptimizeFlags )
312 double fArea;
313 const BOOL bEdges = ( nOptimizeFlags & POLY_OPTIMIZE_EDGES ) == POLY_OPTIMIZE_EDGES;
314 USHORT nPercent = 0;
316 if( bEdges )
318 const Rectangle aBound( GetBoundRect() );
320 fArea = ( aBound.GetWidth() + aBound.GetHeight() ) * 0.5;
321 nPercent = pData ? pData->GetPercentValue() : 50;
322 nOptimizeFlags &= ~POLY_OPTIMIZE_EDGES;
325 // watch for ref counter
326 if( mpImplPolyPolygon->mnRefCount > 1 )
328 mpImplPolyPolygon->mnRefCount--;
329 mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
332 // Optimize polygons
333 for( USHORT i = 0, nPolyCount = mpImplPolyPolygon->mnCount; i < nPolyCount; i++ )
335 if( bEdges )
337 mpImplPolyPolygon->mpPolyAry[ i ]->Optimize( POLY_OPTIMIZE_NO_SAME );
338 Polygon::ImplReduceEdges( *( mpImplPolyPolygon->mpPolyAry[ i ] ), fArea, nPercent );
341 if( nOptimizeFlags )
342 mpImplPolyPolygon->mpPolyAry[ i ]->Optimize( nOptimizeFlags, pData );
347 // -----------------------------------------------------------------------
349 void PolyPolygon::GetSimple( PolyPolygon& rResult ) const
351 DBG_CHKTHIS( PolyPolygon, NULL );
353 rResult.Clear();
355 Polygon aPolygon;
357 for( USHORT i = 0; i < mpImplPolyPolygon->mnCount; i++ )
359 mpImplPolyPolygon->mpPolyAry[ i ]->GetSimple( aPolygon );
360 rResult.Insert( aPolygon );
364 // -----------------------------------------------------------------------
366 void PolyPolygon::AdaptiveSubdivide( PolyPolygon& rResult, const double d ) const
368 DBG_CHKTHIS( PolyPolygon, NULL );
370 rResult.Clear();
372 Polygon aPolygon;
374 for( USHORT i = 0; i < mpImplPolyPolygon->mnCount; i++ )
376 mpImplPolyPolygon->mpPolyAry[ i ]->AdaptiveSubdivide( aPolygon, d );
377 rResult.Insert( aPolygon );
381 // -----------------------------------------------------------------------
383 void PolyPolygon::GetIntersection( const PolyPolygon& rPolyPoly, PolyPolygon& rResult ) const
385 ImplDoOperation( rPolyPoly, rResult, POLY_CLIP_INT );
388 // -----------------------------------------------------------------------
390 void PolyPolygon::GetUnion( const PolyPolygon& rPolyPoly, PolyPolygon& rResult ) const
392 ImplDoOperation( rPolyPoly, rResult, POLY_CLIP_UNION );
395 // -----------------------------------------------------------------------
397 void PolyPolygon::GetDifference( const PolyPolygon& rPolyPoly, PolyPolygon& rResult ) const
399 ImplDoOperation( rPolyPoly, rResult, POLY_CLIP_DIFF );
402 // -----------------------------------------------------------------------
404 void PolyPolygon::GetXOR( const PolyPolygon& rPolyPoly, PolyPolygon& rResult ) const
406 ImplDoOperation( rPolyPoly, rResult, POLY_CLIP_XOR );
409 // -----------------------------------------------------------------------
411 void PolyPolygon::ImplDoOperation( const PolyPolygon& rPolyPoly, PolyPolygon& rResult, ULONG nOperation ) const
413 // Convert to B2DPolyPolygon, temporarily. It might be
414 // advantageous in the future, to have a PolyPolygon adaptor that
415 // just simulates a B2DPolyPolygon here...
416 basegfx::B2DPolyPolygon aMergePolyPolygonA( getB2DPolyPolygon() );
417 basegfx::B2DPolyPolygon aMergePolyPolygonB( rPolyPoly.getB2DPolyPolygon() );
419 // normalize the two polypolygons before. Force properly oriented
420 // polygons.
421 aMergePolyPolygonA = basegfx::tools::prepareForPolygonOperation( aMergePolyPolygonA );
422 aMergePolyPolygonB = basegfx::tools::prepareForPolygonOperation( aMergePolyPolygonB );
424 switch( nOperation )
426 // All code extracted from svx/source/svdraw/svedtv2.cxx
427 // -----------------------------------------------------
429 case POLY_CLIP_UNION:
431 // merge A and B (OR)
432 aMergePolyPolygonA = basegfx::tools::solvePolygonOperationOr(aMergePolyPolygonA, aMergePolyPolygonB);
433 break;
436 case POLY_CLIP_DIFF:
438 // substract B from A (DIFF)
439 aMergePolyPolygonA = basegfx::tools::solvePolygonOperationDiff(aMergePolyPolygonA, aMergePolyPolygonB);
440 break;
443 case POLY_CLIP_XOR:
445 // compute XOR between poly A and B
446 aMergePolyPolygonA = basegfx::tools::solvePolygonOperationXor(aMergePolyPolygonA, aMergePolyPolygonB);
447 break;
450 default:
451 case POLY_CLIP_INT:
453 // cut poly 1 against polys 2..n (AND)
454 aMergePolyPolygonA = basegfx::tools::solvePolygonOperationAnd(aMergePolyPolygonA, aMergePolyPolygonB);
455 break;
459 rResult = PolyPolygon( aMergePolyPolygonA );
462 // -----------------------------------------------------------------------
464 USHORT PolyPolygon::Count() const
466 DBG_CHKTHIS( PolyPolygon, NULL );
467 return mpImplPolyPolygon->mnCount;
470 // -----------------------------------------------------------------------
472 void PolyPolygon::Move( long nHorzMove, long nVertMove )
474 DBG_CHKTHIS( PolyPolygon, NULL );
476 // Diese Abfrage sollte man fuer die DrawEngine durchfuehren
477 if( nHorzMove || nVertMove )
479 // Referenzcounter beruecksichtigen
480 if ( mpImplPolyPolygon->mnRefCount > 1 )
482 mpImplPolyPolygon->mnRefCount--;
483 mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
486 // Punkte verschieben
487 USHORT nPolyCount = mpImplPolyPolygon->mnCount;
488 for ( USHORT i = 0; i < nPolyCount; i++ )
489 mpImplPolyPolygon->mpPolyAry[i]->Move( nHorzMove, nVertMove );
493 // -----------------------------------------------------------------------
495 void PolyPolygon::Translate( const Point& rTrans )
497 DBG_CHKTHIS( PolyPolygon, NULL );
499 // Referenzcounter beruecksichtigen
500 if( mpImplPolyPolygon->mnRefCount > 1 )
502 mpImplPolyPolygon->mnRefCount--;
503 mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
506 // Punkte verschieben
507 for ( USHORT i = 0, nCount = mpImplPolyPolygon->mnCount; i < nCount; i++ )
508 mpImplPolyPolygon->mpPolyAry[ i ]->Translate( rTrans );
511 // -----------------------------------------------------------------------
513 void PolyPolygon::Scale( double fScaleX, double fScaleY )
515 DBG_CHKTHIS( PolyPolygon, NULL );
517 // Referenzcounter beruecksichtigen
518 if( mpImplPolyPolygon->mnRefCount > 1 )
520 mpImplPolyPolygon->mnRefCount--;
521 mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
524 // Punkte verschieben
525 for ( USHORT i = 0, nCount = mpImplPolyPolygon->mnCount; i < nCount; i++ )
526 mpImplPolyPolygon->mpPolyAry[ i ]->Scale( fScaleX, fScaleY );
529 // -----------------------------------------------------------------------
531 void PolyPolygon::Rotate( const Point& rCenter, USHORT nAngle10 )
533 DBG_CHKTHIS( PolyPolygon, NULL );
534 nAngle10 %= 3600;
536 if( nAngle10 )
538 const double fAngle = F_PI1800 * nAngle10;
539 Rotate( rCenter, sin( fAngle ), cos( fAngle ) );
543 // -----------------------------------------------------------------------
545 void PolyPolygon::Rotate( const Point& rCenter, double fSin, double fCos )
547 DBG_CHKTHIS( PolyPolygon, NULL );
549 // Referenzcounter beruecksichtigen
550 if( mpImplPolyPolygon->mnRefCount > 1 )
552 mpImplPolyPolygon->mnRefCount--;
553 mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
556 // Punkte verschieben
557 for ( USHORT i = 0, nCount = mpImplPolyPolygon->mnCount; i < nCount; i++ )
558 mpImplPolyPolygon->mpPolyAry[ i ]->Rotate( rCenter, fSin, fCos );
561 // -----------------------------------------------------------------------
563 void PolyPolygon::SlantX( long nYRef, double fSin, double fCos )
565 DBG_CHKTHIS( PolyPolygon, NULL );
567 // Referenzcounter beruecksichtigen
568 if( mpImplPolyPolygon->mnRefCount > 1 )
570 mpImplPolyPolygon->mnRefCount--;
571 mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
574 // Punkte verschieben
575 for ( USHORT i = 0, nCount = mpImplPolyPolygon->mnCount; i < nCount; i++ )
576 mpImplPolyPolygon->mpPolyAry[ i ]->SlantX( nYRef, fSin, fCos );
579 // -----------------------------------------------------------------------
581 void PolyPolygon::SlantY( long nXRef, double fSin, double fCos )
583 DBG_CHKTHIS( PolyPolygon, NULL );
585 // Referenzcounter beruecksichtigen
586 if( mpImplPolyPolygon->mnRefCount > 1 )
588 mpImplPolyPolygon->mnRefCount--;
589 mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
592 // Punkte verschieben
593 for ( USHORT i = 0, nCount = mpImplPolyPolygon->mnCount; i < nCount; i++ )
594 mpImplPolyPolygon->mpPolyAry[ i ]->SlantY( nXRef, fSin, fCos );
597 // -----------------------------------------------------------------------
599 void PolyPolygon::Distort( const Rectangle& rRefRect, const Polygon& rDistortedRect )
601 DBG_CHKTHIS( PolyPolygon, NULL );
603 // Referenzcounter beruecksichtigen
604 if( mpImplPolyPolygon->mnRefCount > 1 )
606 mpImplPolyPolygon->mnRefCount--;
607 mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
610 // Punkte verschieben
611 for ( USHORT i = 0, nCount = mpImplPolyPolygon->mnCount; i < nCount; i++ )
612 mpImplPolyPolygon->mpPolyAry[ i ]->Distort( rRefRect, rDistortedRect );
616 // -----------------------------------------------------------------------
618 void PolyPolygon::Clip( const Rectangle& rRect )
620 // Polygon-Clippen
621 USHORT nPolyCount = mpImplPolyPolygon->mnCount;
622 USHORT i;
624 if ( !nPolyCount )
625 return;
627 // Referenzcounter beruecksichtigen
628 if ( mpImplPolyPolygon->mnRefCount > 1 )
630 mpImplPolyPolygon->mnRefCount--;
631 mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
634 // Erst jedes Polygon Clippen und dann die leeren entfernen
635 for ( i = 0; i < nPolyCount; i++ )
636 mpImplPolyPolygon->mpPolyAry[i]->Clip( rRect );
637 while ( nPolyCount )
639 if ( GetObject( nPolyCount-1 ).GetSize() <= 2 )
640 Remove( nPolyCount-1 );
641 nPolyCount--;
645 // -----------------------------------------------------------------------
647 Rectangle PolyPolygon::GetBoundRect() const
649 DBG_CHKTHIS( PolyPolygon, NULL );
651 long nXMin=0, nXMax=0, nYMin=0, nYMax=0;
652 BOOL bFirst = TRUE;
653 USHORT nPolyCount = mpImplPolyPolygon->mnCount;
655 for ( USHORT n = 0; n < nPolyCount; n++ )
657 const Polygon* pPoly = mpImplPolyPolygon->mpPolyAry[n];
658 const Point* pAry = pPoly->GetConstPointAry();
659 USHORT nPointCount = pPoly->GetSize();
661 for ( USHORT i = 0; i < nPointCount; i++ )
663 const Point* pPt = &pAry[ i ];
665 if ( bFirst )
667 nXMin = nXMax = pPt->X();
668 nYMin = nYMax = pPt->Y();
669 bFirst = FALSE;
671 else
673 if ( pPt->X() < nXMin )
674 nXMin = pPt->X();
675 if ( pPt->X() > nXMax )
676 nXMax = pPt->X();
677 if ( pPt->Y() < nYMin )
678 nYMin = pPt->Y();
679 if ( pPt->Y() > nYMax )
680 nYMax = pPt->Y();
685 if ( !bFirst )
686 return Rectangle( nXMin, nYMin, nXMax, nYMax );
687 else
688 return Rectangle();
691 // -----------------------------------------------------------------------
693 Polygon& PolyPolygon::operator[]( USHORT nPos )
695 DBG_CHKTHIS( PolyPolygon, NULL );
696 DBG_ASSERT( nPos < Count(), "PolyPolygon::[](): nPos >= nSize" );
698 if ( mpImplPolyPolygon->mnRefCount > 1 )
700 mpImplPolyPolygon->mnRefCount--;
701 mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
704 return *(mpImplPolyPolygon->mpPolyAry[nPos]);
707 // -----------------------------------------------------------------------
709 PolyPolygon& PolyPolygon::operator=( const PolyPolygon& rPolyPoly )
711 DBG_CHKTHIS( PolyPolygon, NULL );
712 DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL );
713 DBG_ASSERT( rPolyPoly.mpImplPolyPolygon->mnRefCount < 0xFFFFFFFE, "PolyPolygon: RefCount overflow" );
715 rPolyPoly.mpImplPolyPolygon->mnRefCount++;
717 if ( mpImplPolyPolygon->mnRefCount > 1 )
718 mpImplPolyPolygon->mnRefCount--;
719 else
720 delete mpImplPolyPolygon;
722 mpImplPolyPolygon = rPolyPoly.mpImplPolyPolygon;
723 return *this;
726 // -----------------------------------------------------------------------
728 BOOL PolyPolygon::operator==( const PolyPolygon& rPolyPoly ) const
730 DBG_CHKTHIS( PolyPolygon, NULL );
731 DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL );
733 if ( rPolyPoly.mpImplPolyPolygon == mpImplPolyPolygon )
734 return TRUE;
735 else
736 return FALSE;
739 // -----------------------------------------------------------------------
741 sal_Bool PolyPolygon::IsEqual( const PolyPolygon& rPolyPoly ) const
743 sal_Bool bIsEqual = sal_True;
744 if ( Count() != rPolyPoly.Count() )
745 bIsEqual = sal_False;
746 else
748 sal_uInt16 i;
749 for ( i = 0; i < Count(); i++ )
751 if (!GetObject( i ).IsEqual( rPolyPoly.GetObject( i ) ) )
753 bIsEqual = sal_False;
754 break;
758 return bIsEqual;
761 // -----------------------------------------------------------------------
763 SvStream& operator>>( SvStream& rIStream, PolyPolygon& rPolyPoly )
765 DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL );
766 DBG_ASSERTWARNING( rIStream.GetVersion(), "PolyPolygon::>> - Solar-Version not set on rIStream" );
768 Polygon* pPoly;
769 USHORT nPolyCount;
771 // Anzahl der Polygone einlesen
772 rIStream >> nPolyCount;
774 // Daten anlegen
775 if( nPolyCount )
777 // Referenzcounter beruecksichtigen
778 if ( rPolyPoly.mpImplPolyPolygon->mnRefCount > 1 )
779 rPolyPoly.mpImplPolyPolygon->mnRefCount--;
780 else
781 delete rPolyPoly.mpImplPolyPolygon;
783 rPolyPoly.mpImplPolyPolygon = new ImplPolyPolygon( nPolyCount );
785 for ( USHORT i = 0; i < nPolyCount; i++ )
787 pPoly = new Polygon;
788 rIStream >> *pPoly;
789 rPolyPoly.mpImplPolyPolygon->mpPolyAry[i] = pPoly;
792 else
793 rPolyPoly = PolyPolygon();
795 return rIStream;
798 // -----------------------------------------------------------------------
800 SvStream& operator<<( SvStream& rOStream, const PolyPolygon& rPolyPoly )
802 DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL );
803 DBG_ASSERTWARNING( rOStream.GetVersion(), "PolyPolygon::<< - Solar-Version not set on rOStream" );
805 // Anzahl der Polygone rausschreiben
806 USHORT nPolyCount = rPolyPoly.mpImplPolyPolygon->mnCount;
807 rOStream << nPolyCount;
809 // Die einzelnen Polygone ausgeben
810 for ( USHORT i = 0; i < nPolyCount; i++ )
811 rOStream << *(rPolyPoly.mpImplPolyPolygon->mpPolyAry[i]);
813 return rOStream;
816 // -----------------------------------------------------------------------
818 void PolyPolygon::Read( SvStream& rIStream )
820 VersionCompat aCompat( rIStream, STREAM_READ );
822 DBG_CHKTHIS( PolyPolygon, NULL );
823 DBG_ASSERTWARNING( rIStream.GetVersion(), "PolyPolygon::>> - Solar-Version not set on rIStream" );
825 Polygon* pPoly;
826 USHORT nPolyCount;
828 // Anzahl der Polygone einlesen
829 rIStream >> nPolyCount;
831 // Daten anlegen
832 if( nPolyCount )
834 // Referenzcounter beruecksichtigen
835 if ( mpImplPolyPolygon->mnRefCount > 1 )
836 mpImplPolyPolygon->mnRefCount--;
837 else
838 delete mpImplPolyPolygon;
840 mpImplPolyPolygon = new ImplPolyPolygon( nPolyCount );
842 for ( USHORT i = 0; i < nPolyCount; i++ )
844 pPoly = new Polygon;
845 pPoly->ImplRead( rIStream );
846 mpImplPolyPolygon->mpPolyAry[i] = pPoly;
849 else
850 *this = PolyPolygon();
853 // -----------------------------------------------------------------------
855 void PolyPolygon::Write( SvStream& rOStream ) const
857 VersionCompat aCompat( rOStream, STREAM_WRITE, 1 );
859 DBG_CHKTHIS( PolyPolygon, NULL );
860 DBG_ASSERTWARNING( rOStream.GetVersion(), "PolyPolygon::<< - Solar-Version not set on rOStream" );
862 // Anzahl der Polygone rausschreiben
863 USHORT nPolyCount = mpImplPolyPolygon->mnCount;
864 rOStream << nPolyCount;
866 // Die einzelnen Polygone ausgeben
867 for ( USHORT i = 0; i < nPolyCount; i++ )
868 mpImplPolyPolygon->mpPolyAry[i]->ImplWrite( rOStream );;
871 // -----------------------------------------------------------------------
872 // convert to basegfx::B2DPolyPolygon and return
873 basegfx::B2DPolyPolygon PolyPolygon::getB2DPolyPolygon() const
875 basegfx::B2DPolyPolygon aRetval;
877 for(sal_uInt16 a(0); a < mpImplPolyPolygon->mnCount; a++)
879 Polygon* pCandidate = mpImplPolyPolygon->mpPolyAry[a];
880 aRetval.append(pCandidate->getB2DPolygon());
883 return aRetval;
886 // -----------------------------------------------------------------------
887 // constructor to convert from basegfx::B2DPolyPolygon
888 PolyPolygon::PolyPolygon(const basegfx::B2DPolyPolygon& rPolyPolygon)
890 DBG_CTOR( PolyPolygon, NULL );
891 const sal_uInt16 nCount(sal_uInt16(rPolyPolygon.count()));
892 DBG_ASSERT(sal_uInt32(nCount) == rPolyPolygon.count(),
893 "PolyPolygon::PolyPolygon: Too many sub-polygons in given basegfx::B2DPolyPolygon (!)");
895 if ( nCount )
897 mpImplPolyPolygon = new ImplPolyPolygon( nCount );
899 for(sal_uInt16 a(0); a < nCount; a++)
901 basegfx::B2DPolygon aCandidate(rPolyPolygon.getB2DPolygon(sal_uInt32(a)));
902 mpImplPolyPolygon->mpPolyAry[a] = new Polygon( aCandidate );
905 else
907 mpImplPolyPolygon = new ImplPolyPolygon( 16, 16 );
911 // eof