fix toolbar import
[ooovba.git] / tools / source / generic / poly2.cxx
blobfd6b10fa4682b364eb28a9b3d676441d9f126b63
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 extern "C"
38 #if defined (HAVE_GPC_H) && !defined (__gpc_h)
39 # include <external/gpc/gpc.h>
40 #else
41 # define GPC_INT 0
42 # define GPC_UNION 1
43 # define GPC_DIFF 2
44 # define GPC_XOR 3
45 #endif // HAVE_GPC_H
48 #include <rtl/math.hxx>
49 #include <poly.h>
50 #include <tools/poly.hxx>
51 #include <tools/debug.hxx>
52 #include <tools/stream.hxx>
53 #include <tools/vcompat.hxx>
54 #include <basegfx/polygon/b2dpolypolygon.hxx>
55 #include <basegfx/polygon/b2dpolygon.hxx>
56 #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
58 // ---------------
59 // - PolyPolygon -
60 // ---------------
62 DBG_NAME( PolyPolygon )
64 // -----------------------------------------------------------------------
66 ImplPolyPolygon::ImplPolyPolygon( USHORT nInitSize )
68 mnRefCount = 1;
69 mnCount = nInitSize;
70 mnSize = nInitSize;
71 mnResize = 16;
72 mpPolyAry = new SVPPOLYGON[ nInitSize ];
75 // -----------------------------------------------------------------------
77 ImplPolyPolygon::ImplPolyPolygon( const ImplPolyPolygon& rImplPolyPoly )
79 mnRefCount = 1;
80 mnCount = rImplPolyPoly.mnCount;
81 mnSize = rImplPolyPoly.mnSize;
82 mnResize = rImplPolyPoly.mnResize;
84 if ( rImplPolyPoly.mpPolyAry )
86 mpPolyAry = new SVPPOLYGON[mnSize];
87 for ( USHORT i = 0; i < mnCount; i++ )
88 mpPolyAry[i] = new Polygon( *rImplPolyPoly.mpPolyAry[i] );
90 else
91 mpPolyAry = NULL;
94 // -----------------------------------------------------------------------
96 ImplPolyPolygon::~ImplPolyPolygon()
98 if ( mpPolyAry )
100 for ( USHORT i = 0; i < mnCount; i++ )
101 delete mpPolyAry[i];
102 delete[] mpPolyAry;
106 // =======================================================================
108 PolyPolygon::PolyPolygon( USHORT nInitSize, USHORT nResize )
110 DBG_CTOR( PolyPolygon, NULL );
112 if ( nInitSize > MAX_POLYGONS )
113 nInitSize = MAX_POLYGONS;
114 else if ( !nInitSize )
115 nInitSize = 1;
116 if ( nResize > MAX_POLYGONS )
117 nResize = MAX_POLYGONS;
118 else if ( !nResize )
119 nResize = 1;
120 mpImplPolyPolygon = new ImplPolyPolygon( nInitSize, nResize );
123 // -----------------------------------------------------------------------
125 PolyPolygon::PolyPolygon( const Polygon& rPoly )
127 DBG_CTOR( PolyPolygon, NULL );
129 if ( rPoly.GetSize() )
131 mpImplPolyPolygon = new ImplPolyPolygon( 1 );
132 mpImplPolyPolygon->mpPolyAry[0] = new Polygon( rPoly );
134 else
135 mpImplPolyPolygon = new ImplPolyPolygon( 16, 16 );
138 // -----------------------------------------------------------------------
140 PolyPolygon::PolyPolygon( USHORT nPoly, const USHORT* pPointCountAry,
141 const Point* pPtAry )
143 DBG_CTOR( PolyPolygon, NULL );
145 if ( nPoly > MAX_POLYGONS )
146 nPoly = MAX_POLYGONS;
148 mpImplPolyPolygon = new ImplPolyPolygon( nPoly );
149 for ( USHORT i = 0; i < nPoly; i++ )
151 mpImplPolyPolygon->mpPolyAry[i] = new Polygon( *pPointCountAry, pPtAry );
152 pPtAry += *pPointCountAry;
153 pPointCountAry++;
157 // -----------------------------------------------------------------------
159 PolyPolygon::PolyPolygon( const PolyPolygon& rPolyPoly )
161 DBG_CTOR( PolyPolygon, NULL );
162 DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL );
163 DBG_ASSERT( rPolyPoly.mpImplPolyPolygon->mnRefCount < 0xFFFFFFFE, "PolyPolygon: RefCount overflow" );
165 mpImplPolyPolygon = rPolyPoly.mpImplPolyPolygon;
166 mpImplPolyPolygon->mnRefCount++;
169 // -----------------------------------------------------------------------
171 PolyPolygon::~PolyPolygon()
173 DBG_DTOR( PolyPolygon, NULL );
175 if ( mpImplPolyPolygon->mnRefCount > 1 )
176 mpImplPolyPolygon->mnRefCount--;
177 else
178 delete mpImplPolyPolygon;
181 // -----------------------------------------------------------------------
183 void PolyPolygon::Insert( const Polygon& rPoly, USHORT nPos )
185 DBG_CHKTHIS( PolyPolygon, NULL );
187 if ( mpImplPolyPolygon->mnCount >= MAX_POLYGONS )
188 return;
190 if ( mpImplPolyPolygon->mnRefCount > 1 )
192 mpImplPolyPolygon->mnRefCount--;
193 mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
196 if ( nPos > mpImplPolyPolygon->mnCount )
197 nPos = mpImplPolyPolygon->mnCount;
199 if ( !mpImplPolyPolygon->mpPolyAry )
200 mpImplPolyPolygon->mpPolyAry = new SVPPOLYGON[mpImplPolyPolygon->mnSize];
201 else if ( mpImplPolyPolygon->mnCount == mpImplPolyPolygon->mnSize )
203 USHORT nOldSize = mpImplPolyPolygon->mnSize;
204 USHORT nNewSize = nOldSize + mpImplPolyPolygon->mnResize;
205 SVPPOLYGON* pNewAry;
207 if ( nNewSize >= MAX_POLYGONS )
208 nNewSize = MAX_POLYGONS;
209 pNewAry = new SVPPOLYGON[nNewSize];
210 memcpy( pNewAry, mpImplPolyPolygon->mpPolyAry, nPos*sizeof(SVPPOLYGON) );
211 memcpy( pNewAry+nPos+1, mpImplPolyPolygon->mpPolyAry+nPos,
212 (nOldSize-nPos)*sizeof(SVPPOLYGON) );
213 delete[] mpImplPolyPolygon->mpPolyAry;
214 mpImplPolyPolygon->mpPolyAry = pNewAry;
215 mpImplPolyPolygon->mnSize = nNewSize;
217 else if ( nPos < mpImplPolyPolygon->mnCount )
219 memmove( mpImplPolyPolygon->mpPolyAry+nPos+1,
220 mpImplPolyPolygon->mpPolyAry+nPos,
221 (mpImplPolyPolygon->mnCount-nPos)*sizeof(SVPPOLYGON) );
224 mpImplPolyPolygon->mpPolyAry[nPos] = new Polygon( rPoly );
225 mpImplPolyPolygon->mnCount++;
228 // -----------------------------------------------------------------------
230 void PolyPolygon::Remove( USHORT nPos )
232 DBG_CHKTHIS( PolyPolygon, NULL );
233 DBG_ASSERT( nPos < Count(), "PolyPolygon::Remove(): nPos >= nSize" );
235 if ( mpImplPolyPolygon->mnRefCount > 1 )
237 mpImplPolyPolygon->mnRefCount--;
238 mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
241 delete mpImplPolyPolygon->mpPolyAry[nPos];
242 mpImplPolyPolygon->mnCount--;
243 memmove( mpImplPolyPolygon->mpPolyAry+nPos,
244 mpImplPolyPolygon->mpPolyAry+nPos+1,
245 (mpImplPolyPolygon->mnCount-nPos)*sizeof(SVPPOLYGON) );
248 // -----------------------------------------------------------------------
250 void PolyPolygon::Replace( const Polygon& rPoly, USHORT nPos )
252 DBG_CHKTHIS( PolyPolygon, NULL );
253 DBG_ASSERT( nPos < Count(), "PolyPolygon::Replace(): nPos >= nSize" );
255 if ( mpImplPolyPolygon->mnRefCount > 1 )
257 mpImplPolyPolygon->mnRefCount--;
258 mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
261 delete mpImplPolyPolygon->mpPolyAry[nPos];
262 mpImplPolyPolygon->mpPolyAry[nPos] = new Polygon( rPoly );
265 // -----------------------------------------------------------------------
267 const Polygon& PolyPolygon::GetObject( USHORT nPos ) const
269 DBG_CHKTHIS( PolyPolygon, NULL );
270 DBG_ASSERT( nPos < Count(), "PolyPolygon::GetObject(): nPos >= nSize" );
272 return *(mpImplPolyPolygon->mpPolyAry[nPos]);
275 // -----------------------------------------------------------------------
277 BOOL PolyPolygon::IsRect() const
279 BOOL bIsRect = FALSE;
280 if ( Count() == 1 )
281 bIsRect = mpImplPolyPolygon->mpPolyAry[ 0 ]->IsRect();
282 return bIsRect;
285 // -----------------------------------------------------------------------
287 void PolyPolygon::Clear()
289 DBG_CHKTHIS( PolyPolygon, NULL );
291 if ( mpImplPolyPolygon->mnRefCount > 1 )
293 mpImplPolyPolygon->mnRefCount--;
294 mpImplPolyPolygon = new ImplPolyPolygon( mpImplPolyPolygon->mnResize,
295 mpImplPolyPolygon->mnResize );
297 else
299 if ( mpImplPolyPolygon->mpPolyAry )
301 for ( USHORT i = 0; i < mpImplPolyPolygon->mnCount; i++ )
302 delete mpImplPolyPolygon->mpPolyAry[i];
303 delete[] mpImplPolyPolygon->mpPolyAry;
304 mpImplPolyPolygon->mpPolyAry = NULL;
305 mpImplPolyPolygon->mnCount = 0;
306 mpImplPolyPolygon->mnSize = mpImplPolyPolygon->mnResize;
311 // -----------------------------------------------------------------------
313 void PolyPolygon::Optimize( ULONG nOptimizeFlags, const PolyOptimizeData* pData )
315 DBG_CHKTHIS( PolyPolygon, NULL );
317 if( nOptimizeFlags )
319 double fArea;
320 const BOOL bEdges = ( nOptimizeFlags & POLY_OPTIMIZE_EDGES ) == POLY_OPTIMIZE_EDGES;
321 USHORT nPercent = 0;
323 if( bEdges )
325 const Rectangle aBound( GetBoundRect() );
327 fArea = ( aBound.GetWidth() + aBound.GetHeight() ) * 0.5;
328 nPercent = pData ? pData->GetPercentValue() : 50;
329 nOptimizeFlags &= ~POLY_OPTIMIZE_EDGES;
332 // watch for ref counter
333 if( mpImplPolyPolygon->mnRefCount > 1 )
335 mpImplPolyPolygon->mnRefCount--;
336 mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
339 // Optimize polygons
340 for( USHORT i = 0, nPolyCount = mpImplPolyPolygon->mnCount; i < nPolyCount; i++ )
342 if( bEdges )
344 mpImplPolyPolygon->mpPolyAry[ i ]->Optimize( POLY_OPTIMIZE_NO_SAME );
345 Polygon::ImplReduceEdges( *( mpImplPolyPolygon->mpPolyAry[ i ] ), fArea, nPercent );
348 if( nOptimizeFlags )
349 mpImplPolyPolygon->mpPolyAry[ i ]->Optimize( nOptimizeFlags, pData );
354 // -----------------------------------------------------------------------
356 void PolyPolygon::GetSimple( PolyPolygon& rResult ) const
358 DBG_CHKTHIS( PolyPolygon, NULL );
360 rResult.Clear();
362 Polygon aPolygon;
364 for( USHORT i = 0; i < mpImplPolyPolygon->mnCount; i++ )
366 mpImplPolyPolygon->mpPolyAry[ i ]->GetSimple( aPolygon );
367 rResult.Insert( aPolygon );
371 // -----------------------------------------------------------------------
373 void PolyPolygon::AdaptiveSubdivide( PolyPolygon& rResult, const double d ) const
375 DBG_CHKTHIS( PolyPolygon, NULL );
377 rResult.Clear();
379 Polygon aPolygon;
381 for( USHORT i = 0; i < mpImplPolyPolygon->mnCount; i++ )
383 mpImplPolyPolygon->mpPolyAry[ i ]->AdaptiveSubdivide( aPolygon, d );
384 rResult.Insert( aPolygon );
388 // -----------------------------------------------------------------------
390 void PolyPolygon::GetIntersection( const PolyPolygon& rPolyPoly, PolyPolygon& rResult ) const
392 ImplDoOperation( rPolyPoly, rResult, GPC_INT );
395 // -----------------------------------------------------------------------
397 void PolyPolygon::GetUnion( const PolyPolygon& rPolyPoly, PolyPolygon& rResult ) const
399 ImplDoOperation( rPolyPoly, rResult, GPC_UNION );
402 // -----------------------------------------------------------------------
404 void PolyPolygon::GetDifference( const PolyPolygon& rPolyPoly, PolyPolygon& rResult ) const
406 ImplDoOperation( rPolyPoly, rResult, GPC_DIFF );
409 // -----------------------------------------------------------------------
411 void PolyPolygon::GetXOR( const PolyPolygon& rPolyPoly, PolyPolygon& rResult ) const
413 ImplDoOperation( rPolyPoly, rResult, GPC_XOR );
416 // -----------------------------------------------------------------------
418 #ifdef HAVE_GPC_H
420 void* PolyPolygon::ImplCreateGPCPolygon() const
422 gpc_polygon* pRet = new gpc_polygon;
424 pRet->num_contours = 0;
425 pRet->hole = NULL;
426 pRet->contour = NULL;
428 for( USHORT i = 0, nCount = Count(); i < nCount; i++ )
430 const Polygon& rPoly = GetObject( i );
431 const USHORT nSize = rPoly.GetSize();
433 if( nSize > 1 )
435 gpc_vertex_list aVertexList;
436 gpc_vertex* pVertex;
438 aVertexList.num_vertices = nSize;
439 aVertexList.vertex = pVertex = new gpc_vertex[ nSize ];
441 for( USHORT nPos = 0; nPos < nSize; nPos++, pVertex++ )
443 const Point& rPoint = rPoly[ nPos ];
444 pVertex->x = rPoint.X();
445 pVertex->y = rPoint.Y();
448 gpc_add_contour( pRet, &aVertexList, 0 );
449 delete[] aVertexList.vertex;
453 return pRet;
456 // -----------------------------------------------------------------------
458 void PolyPolygon::ImplDoOperation( const PolyPolygon& rPolyPoly, PolyPolygon& rResult, ULONG nOperation ) const
460 gpc_polygon* pGPCPoly1 = (gpc_polygon*) ImplCreateGPCPolygon();
461 gpc_polygon* pGPCPoly2 = (gpc_polygon*) rPolyPoly.ImplCreateGPCPolygon();
462 gpc_polygon* pResult = new gpc_polygon;
464 pResult->num_contours = 0;
465 pResult->hole = NULL;
466 pResult->contour = NULL;
468 gpc_polygon_clip( (gpc_op) nOperation, pGPCPoly1, pGPCPoly2, pResult );
470 rResult.Clear();
472 for( int i = 0; i < pResult->num_contours; i++ )
474 gpc_vertex_list& rVertexList = pResult->contour[ i ];
475 Polygon aPoly( ::sal::static_int_cast< USHORT >( rVertexList.num_vertices ) );
477 for( int j = 0; j < rVertexList.num_vertices; j++ )
479 Point& rPt = aPoly[ ::sal::static_int_cast< USHORT >( j ) ];
480 rPt.X() = FRound( rVertexList.vertex[ j ].x );
481 rPt.Y() = FRound( rVertexList.vertex[ j ].y );
484 rResult.Insert( aPoly );
487 gpc_free_polygon( pGPCPoly1 );
488 delete pGPCPoly1;
490 gpc_free_polygon( pGPCPoly2 );
491 delete pGPCPoly2;
493 gpc_free_polygon( pResult );
494 delete pResult;
497 #else
499 void PolyPolygon::ImplDoOperation( const PolyPolygon& rPolyPoly, PolyPolygon& rResult, ULONG nOperation ) const
501 // Convert to B2DPolyPolygon, temporarily. It might be
502 // advantageous in the future, to have a PolyPolygon adaptor that
503 // just simulates a B2DPolyPolygon here...
504 basegfx::B2DPolyPolygon aMergePolyPolygonA( getB2DPolyPolygon() );
505 basegfx::B2DPolyPolygon aMergePolyPolygonB( rPolyPoly.getB2DPolyPolygon() );
507 // normalize the two polypolygons before. Force properly oriented
508 // polygons.
509 aMergePolyPolygonA = basegfx::tools::prepareForPolygonOperation( aMergePolyPolygonA );
510 aMergePolyPolygonB = basegfx::tools::prepareForPolygonOperation( aMergePolyPolygonB );
512 switch( nOperation )
514 // All code extracted from svx/source/svdraw/svedtv2.cxx
515 // -----------------------------------------------------
517 case GPC_UNION:
519 // merge A and B (OR)
520 aMergePolyPolygonA = basegfx::tools::solvePolygonOperationOr(aMergePolyPolygonA, aMergePolyPolygonB);
521 break;
524 case GPC_DIFF:
526 // substract B from A (DIFF)
527 aMergePolyPolygonA = basegfx::tools::solvePolygonOperationDiff(aMergePolyPolygonA, aMergePolyPolygonB);
528 break;
531 case GPC_XOR:
533 // compute XOR between poly A and B
534 aMergePolyPolygonA = basegfx::tools::solvePolygonOperationXor(aMergePolyPolygonA, aMergePolyPolygonB);
535 break;
538 default:
539 case GPC_INT:
541 // cut poly 1 against polys 2..n (AND)
542 aMergePolyPolygonA = basegfx::tools::solvePolygonOperationAnd(aMergePolyPolygonA, aMergePolyPolygonB);
543 break;
547 rResult = PolyPolygon( aMergePolyPolygonA );
550 #endif // HAVE_GPC_H
552 // -----------------------------------------------------------------------
554 USHORT PolyPolygon::Count() const
556 DBG_CHKTHIS( PolyPolygon, NULL );
557 return mpImplPolyPolygon->mnCount;
560 // -----------------------------------------------------------------------
562 void PolyPolygon::Move( long nHorzMove, long nVertMove )
564 DBG_CHKTHIS( PolyPolygon, NULL );
566 // Diese Abfrage sollte man fuer die DrawEngine durchfuehren
567 if( nHorzMove || nVertMove )
569 // Referenzcounter beruecksichtigen
570 if ( mpImplPolyPolygon->mnRefCount > 1 )
572 mpImplPolyPolygon->mnRefCount--;
573 mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
576 // Punkte verschieben
577 USHORT nPolyCount = mpImplPolyPolygon->mnCount;
578 for ( USHORT i = 0; i < nPolyCount; i++ )
579 mpImplPolyPolygon->mpPolyAry[i]->Move( nHorzMove, nVertMove );
583 // -----------------------------------------------------------------------
585 void PolyPolygon::Translate( const Point& rTrans )
587 DBG_CHKTHIS( PolyPolygon, NULL );
589 // Referenzcounter beruecksichtigen
590 if( mpImplPolyPolygon->mnRefCount > 1 )
592 mpImplPolyPolygon->mnRefCount--;
593 mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
596 // Punkte verschieben
597 for ( USHORT i = 0, nCount = mpImplPolyPolygon->mnCount; i < nCount; i++ )
598 mpImplPolyPolygon->mpPolyAry[ i ]->Translate( rTrans );
601 // -----------------------------------------------------------------------
603 void PolyPolygon::Scale( double fScaleX, double fScaleY )
605 DBG_CHKTHIS( PolyPolygon, NULL );
607 // Referenzcounter beruecksichtigen
608 if( mpImplPolyPolygon->mnRefCount > 1 )
610 mpImplPolyPolygon->mnRefCount--;
611 mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
614 // Punkte verschieben
615 for ( USHORT i = 0, nCount = mpImplPolyPolygon->mnCount; i < nCount; i++ )
616 mpImplPolyPolygon->mpPolyAry[ i ]->Scale( fScaleX, fScaleY );
619 // -----------------------------------------------------------------------
621 void PolyPolygon::Rotate( const Point& rCenter, USHORT nAngle10 )
623 DBG_CHKTHIS( PolyPolygon, NULL );
624 nAngle10 %= 3600;
626 if( nAngle10 )
628 const double fAngle = F_PI1800 * nAngle10;
629 Rotate( rCenter, sin( fAngle ), cos( fAngle ) );
633 // -----------------------------------------------------------------------
635 void PolyPolygon::Rotate( const Point& rCenter, double fSin, double fCos )
637 DBG_CHKTHIS( PolyPolygon, NULL );
639 // Referenzcounter beruecksichtigen
640 if( mpImplPolyPolygon->mnRefCount > 1 )
642 mpImplPolyPolygon->mnRefCount--;
643 mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
646 // Punkte verschieben
647 for ( USHORT i = 0, nCount = mpImplPolyPolygon->mnCount; i < nCount; i++ )
648 mpImplPolyPolygon->mpPolyAry[ i ]->Rotate( rCenter, fSin, fCos );
651 // -----------------------------------------------------------------------
653 void PolyPolygon::SlantX( long nYRef, double fSin, double fCos )
655 DBG_CHKTHIS( PolyPolygon, NULL );
657 // Referenzcounter beruecksichtigen
658 if( mpImplPolyPolygon->mnRefCount > 1 )
660 mpImplPolyPolygon->mnRefCount--;
661 mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
664 // Punkte verschieben
665 for ( USHORT i = 0, nCount = mpImplPolyPolygon->mnCount; i < nCount; i++ )
666 mpImplPolyPolygon->mpPolyAry[ i ]->SlantX( nYRef, fSin, fCos );
669 // -----------------------------------------------------------------------
671 void PolyPolygon::SlantY( long nXRef, double fSin, double fCos )
673 DBG_CHKTHIS( PolyPolygon, NULL );
675 // Referenzcounter beruecksichtigen
676 if( mpImplPolyPolygon->mnRefCount > 1 )
678 mpImplPolyPolygon->mnRefCount--;
679 mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
682 // Punkte verschieben
683 for ( USHORT i = 0, nCount = mpImplPolyPolygon->mnCount; i < nCount; i++ )
684 mpImplPolyPolygon->mpPolyAry[ i ]->SlantY( nXRef, fSin, fCos );
687 // -----------------------------------------------------------------------
689 void PolyPolygon::Distort( const Rectangle& rRefRect, const Polygon& rDistortedRect )
691 DBG_CHKTHIS( PolyPolygon, NULL );
693 // Referenzcounter beruecksichtigen
694 if( mpImplPolyPolygon->mnRefCount > 1 )
696 mpImplPolyPolygon->mnRefCount--;
697 mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
700 // Punkte verschieben
701 for ( USHORT i = 0, nCount = mpImplPolyPolygon->mnCount; i < nCount; i++ )
702 mpImplPolyPolygon->mpPolyAry[ i ]->Distort( rRefRect, rDistortedRect );
706 // -----------------------------------------------------------------------
708 void PolyPolygon::Clip( const Rectangle& rRect )
710 // Polygon-Clippen
711 USHORT nPolyCount = mpImplPolyPolygon->mnCount;
712 USHORT i;
714 if ( !nPolyCount )
715 return;
717 // Referenzcounter beruecksichtigen
718 if ( mpImplPolyPolygon->mnRefCount > 1 )
720 mpImplPolyPolygon->mnRefCount--;
721 mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
724 // Erst jedes Polygon Clippen und dann die leeren entfernen
725 for ( i = 0; i < nPolyCount; i++ )
726 mpImplPolyPolygon->mpPolyAry[i]->Clip( rRect );
727 while ( nPolyCount )
729 if ( GetObject( nPolyCount-1 ).GetSize() <= 2 )
730 Remove( nPolyCount-1 );
731 nPolyCount--;
735 // -----------------------------------------------------------------------
737 Rectangle PolyPolygon::GetBoundRect() const
739 DBG_CHKTHIS( PolyPolygon, NULL );
741 long nXMin=0, nXMax=0, nYMin=0, nYMax=0;
742 BOOL bFirst = TRUE;
743 USHORT nPolyCount = mpImplPolyPolygon->mnCount;
745 for ( USHORT n = 0; n < nPolyCount; n++ )
747 const Polygon* pPoly = mpImplPolyPolygon->mpPolyAry[n];
748 const Point* pAry = pPoly->GetConstPointAry();
749 USHORT nPointCount = pPoly->GetSize();
751 for ( USHORT i = 0; i < nPointCount; i++ )
753 const Point* pPt = &pAry[ i ];
755 if ( bFirst )
757 nXMin = nXMax = pPt->X();
758 nYMin = nYMax = pPt->Y();
759 bFirst = FALSE;
761 else
763 if ( pPt->X() < nXMin )
764 nXMin = pPt->X();
765 if ( pPt->X() > nXMax )
766 nXMax = pPt->X();
767 if ( pPt->Y() < nYMin )
768 nYMin = pPt->Y();
769 if ( pPt->Y() > nYMax )
770 nYMax = pPt->Y();
775 if ( !bFirst )
776 return Rectangle( nXMin, nYMin, nXMax, nYMax );
777 else
778 return Rectangle();
781 // -----------------------------------------------------------------------
783 Polygon& PolyPolygon::operator[]( USHORT nPos )
785 DBG_CHKTHIS( PolyPolygon, NULL );
786 DBG_ASSERT( nPos < Count(), "PolyPolygon::[](): nPos >= nSize" );
788 if ( mpImplPolyPolygon->mnRefCount > 1 )
790 mpImplPolyPolygon->mnRefCount--;
791 mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
794 return *(mpImplPolyPolygon->mpPolyAry[nPos]);
797 // -----------------------------------------------------------------------
799 PolyPolygon& PolyPolygon::operator=( const PolyPolygon& rPolyPoly )
801 DBG_CHKTHIS( PolyPolygon, NULL );
802 DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL );
803 DBG_ASSERT( rPolyPoly.mpImplPolyPolygon->mnRefCount < 0xFFFFFFFE, "PolyPolygon: RefCount overflow" );
805 rPolyPoly.mpImplPolyPolygon->mnRefCount++;
807 if ( mpImplPolyPolygon->mnRefCount > 1 )
808 mpImplPolyPolygon->mnRefCount--;
809 else
810 delete mpImplPolyPolygon;
812 mpImplPolyPolygon = rPolyPoly.mpImplPolyPolygon;
813 return *this;
816 // -----------------------------------------------------------------------
818 BOOL PolyPolygon::operator==( const PolyPolygon& rPolyPoly ) const
820 DBG_CHKTHIS( PolyPolygon, NULL );
821 DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL );
823 if ( rPolyPoly.mpImplPolyPolygon == mpImplPolyPolygon )
824 return TRUE;
825 else
826 return FALSE;
829 // -----------------------------------------------------------------------
831 sal_Bool PolyPolygon::IsEqual( const PolyPolygon& rPolyPoly ) const
833 sal_Bool bIsEqual = sal_True;
834 if ( Count() != rPolyPoly.Count() )
835 bIsEqual = sal_False;
836 else
838 sal_uInt16 i;
839 for ( i = 0; i < Count(); i++ )
841 if (!GetObject( i ).IsEqual( rPolyPoly.GetObject( i ) ) )
843 bIsEqual = sal_False;
844 break;
848 return bIsEqual;
851 // -----------------------------------------------------------------------
853 SvStream& operator>>( SvStream& rIStream, PolyPolygon& rPolyPoly )
855 DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL );
856 DBG_ASSERTWARNING( rIStream.GetVersion(), "PolyPolygon::>> - Solar-Version not set on rIStream" );
858 Polygon* pPoly;
859 USHORT nPolyCount;
861 // Anzahl der Polygone einlesen
862 rIStream >> nPolyCount;
864 // Daten anlegen
865 if( nPolyCount )
867 // Referenzcounter beruecksichtigen
868 if ( rPolyPoly.mpImplPolyPolygon->mnRefCount > 1 )
869 rPolyPoly.mpImplPolyPolygon->mnRefCount--;
870 else
871 delete rPolyPoly.mpImplPolyPolygon;
873 rPolyPoly.mpImplPolyPolygon = new ImplPolyPolygon( nPolyCount );
875 for ( USHORT i = 0; i < nPolyCount; i++ )
877 pPoly = new Polygon;
878 rIStream >> *pPoly;
879 rPolyPoly.mpImplPolyPolygon->mpPolyAry[i] = pPoly;
882 else
883 rPolyPoly = PolyPolygon();
885 return rIStream;
888 // -----------------------------------------------------------------------
890 SvStream& operator<<( SvStream& rOStream, const PolyPolygon& rPolyPoly )
892 DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL );
893 DBG_ASSERTWARNING( rOStream.GetVersion(), "PolyPolygon::<< - Solar-Version not set on rOStream" );
895 // Anzahl der Polygone rausschreiben
896 USHORT nPolyCount = rPolyPoly.mpImplPolyPolygon->mnCount;
897 rOStream << nPolyCount;
899 // Die einzelnen Polygone ausgeben
900 for ( USHORT i = 0; i < nPolyCount; i++ )
901 rOStream << *(rPolyPoly.mpImplPolyPolygon->mpPolyAry[i]);
903 return rOStream;
906 // -----------------------------------------------------------------------
908 void PolyPolygon::Read( SvStream& rIStream )
910 VersionCompat aCompat( rIStream, STREAM_READ );
912 DBG_CHKTHIS( PolyPolygon, NULL );
913 DBG_ASSERTWARNING( rIStream.GetVersion(), "PolyPolygon::>> - Solar-Version not set on rIStream" );
915 Polygon* pPoly;
916 USHORT nPolyCount;
918 // Anzahl der Polygone einlesen
919 rIStream >> nPolyCount;
921 // Daten anlegen
922 if( nPolyCount )
924 // Referenzcounter beruecksichtigen
925 if ( mpImplPolyPolygon->mnRefCount > 1 )
926 mpImplPolyPolygon->mnRefCount--;
927 else
928 delete mpImplPolyPolygon;
930 mpImplPolyPolygon = new ImplPolyPolygon( nPolyCount );
932 for ( USHORT i = 0; i < nPolyCount; i++ )
934 pPoly = new Polygon;
935 pPoly->ImplRead( rIStream );
936 mpImplPolyPolygon->mpPolyAry[i] = pPoly;
939 else
940 *this = PolyPolygon();
943 // -----------------------------------------------------------------------
945 void PolyPolygon::Write( SvStream& rOStream ) const
947 VersionCompat aCompat( rOStream, STREAM_WRITE, 1 );
949 DBG_CHKTHIS( PolyPolygon, NULL );
950 DBG_ASSERTWARNING( rOStream.GetVersion(), "PolyPolygon::<< - Solar-Version not set on rOStream" );
952 // Anzahl der Polygone rausschreiben
953 USHORT nPolyCount = mpImplPolyPolygon->mnCount;
954 rOStream << nPolyCount;
956 // Die einzelnen Polygone ausgeben
957 for ( USHORT i = 0; i < nPolyCount; i++ )
958 mpImplPolyPolygon->mpPolyAry[i]->ImplWrite( rOStream );;
961 // -----------------------------------------------------------------------
962 // convert to basegfx::B2DPolyPolygon and return
963 basegfx::B2DPolyPolygon PolyPolygon::getB2DPolyPolygon() const
965 basegfx::B2DPolyPolygon aRetval;
967 for(sal_uInt16 a(0); a < mpImplPolyPolygon->mnCount; a++)
969 Polygon* pCandidate = mpImplPolyPolygon->mpPolyAry[a];
970 aRetval.append(pCandidate->getB2DPolygon());
973 return aRetval;
976 // -----------------------------------------------------------------------
977 // constructor to convert from basegfx::B2DPolyPolygon
978 PolyPolygon::PolyPolygon(const basegfx::B2DPolyPolygon& rPolyPolygon)
980 DBG_CTOR( PolyPolygon, NULL );
981 const sal_uInt16 nCount(sal_uInt16(rPolyPolygon.count()));
982 DBG_ASSERT(sal_uInt32(nCount) == rPolyPolygon.count(),
983 "PolyPolygon::PolyPolygon: Too many sub-polygons in given basegfx::B2DPolyPolygon (!)");
985 if ( nCount )
987 mpImplPolyPolygon = new ImplPolyPolygon( nCount );
989 for(sal_uInt16 a(0); a < nCount; a++)
991 basegfx::B2DPolygon aCandidate(rPolyPolygon.getB2DPolygon(sal_uInt32(a)));
992 mpImplPolyPolygon->mpPolyAry[a] = new Polygon( aCandidate );
995 else
997 mpImplPolyPolygon = new ImplPolyPolygon( 16, 16 );
1001 // eof