1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: poly2.cxx,v $
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"
38 #if defined (HAVE_GPC_H) && !defined (__gpc_h)
39 # include <external/gpc/gpc.h>
48 #include <rtl/math.hxx>
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>
62 DBG_NAME( PolyPolygon
)
64 // -----------------------------------------------------------------------
66 ImplPolyPolygon::ImplPolyPolygon( USHORT nInitSize
)
72 mpPolyAry
= new SVPPOLYGON
[ nInitSize
];
75 // -----------------------------------------------------------------------
77 ImplPolyPolygon::ImplPolyPolygon( const ImplPolyPolygon
& rImplPolyPoly
)
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
] );
94 // -----------------------------------------------------------------------
96 ImplPolyPolygon::~ImplPolyPolygon()
100 for ( USHORT i
= 0; i
< mnCount
; i
++ )
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
)
116 if ( nResize
> MAX_POLYGONS
)
117 nResize
= MAX_POLYGONS
;
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
);
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
;
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
--;
178 delete mpImplPolyPolygon
;
181 // -----------------------------------------------------------------------
183 void PolyPolygon::Insert( const Polygon
& rPoly
, USHORT nPos
)
185 DBG_CHKTHIS( PolyPolygon
, NULL
);
187 if ( mpImplPolyPolygon
->mnCount
>= MAX_POLYGONS
)
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
;
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
;
281 bIsRect
= mpImplPolyPolygon
->mpPolyAry
[ 0 ]->IsRect();
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
);
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
);
320 const BOOL bEdges
= ( nOptimizeFlags
& POLY_OPTIMIZE_EDGES
) == POLY_OPTIMIZE_EDGES
;
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
);
340 for( USHORT i
= 0, nPolyCount
= mpImplPolyPolygon
->mnCount
; i
< nPolyCount
; i
++ )
344 mpImplPolyPolygon
->mpPolyAry
[ i
]->Optimize( POLY_OPTIMIZE_NO_SAME
);
345 Polygon::ImplReduceEdges( *( mpImplPolyPolygon
->mpPolyAry
[ i
] ), fArea
, nPercent
);
349 mpImplPolyPolygon
->mpPolyAry
[ i
]->Optimize( nOptimizeFlags
, pData
);
354 // -----------------------------------------------------------------------
356 void PolyPolygon::GetSimple( PolyPolygon
& rResult
) const
358 DBG_CHKTHIS( PolyPolygon
, NULL
);
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
);
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 // -----------------------------------------------------------------------
420 void* PolyPolygon::ImplCreateGPCPolygon() const
422 gpc_polygon
* pRet
= new gpc_polygon
;
424 pRet
->num_contours
= 0;
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();
435 gpc_vertex_list aVertexList
;
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
;
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
);
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
);
490 gpc_free_polygon( pGPCPoly2
);
493 gpc_free_polygon( pResult
);
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
509 aMergePolyPolygonA
= basegfx::tools::prepareForPolygonOperation( aMergePolyPolygonA
);
510 aMergePolyPolygonB
= basegfx::tools::prepareForPolygonOperation( aMergePolyPolygonB
);
514 // All code extracted from svx/source/svdraw/svedtv2.cxx
515 // -----------------------------------------------------
519 // merge A and B (OR)
520 aMergePolyPolygonA
= basegfx::tools::solvePolygonOperationOr(aMergePolyPolygonA
, aMergePolyPolygonB
);
526 // substract B from A (DIFF)
527 aMergePolyPolygonA
= basegfx::tools::solvePolygonOperationDiff(aMergePolyPolygonA
, aMergePolyPolygonB
);
533 // compute XOR between poly A and B
534 aMergePolyPolygonA
= basegfx::tools::solvePolygonOperationXor(aMergePolyPolygonA
, aMergePolyPolygonB
);
541 // cut poly 1 against polys 2..n (AND)
542 aMergePolyPolygonA
= basegfx::tools::solvePolygonOperationAnd(aMergePolyPolygonA
, aMergePolyPolygonB
);
547 rResult
= PolyPolygon( aMergePolyPolygonA
);
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
);
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
)
711 USHORT nPolyCount
= mpImplPolyPolygon
->mnCount
;
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
);
729 if ( GetObject( nPolyCount
-1 ).GetSize() <= 2 )
730 Remove( nPolyCount
-1 );
735 // -----------------------------------------------------------------------
737 Rectangle
PolyPolygon::GetBoundRect() const
739 DBG_CHKTHIS( PolyPolygon
, NULL
);
741 long nXMin
=0, nXMax
=0, nYMin
=0, nYMax
=0;
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
];
757 nXMin
= nXMax
= pPt
->X();
758 nYMin
= nYMax
= pPt
->Y();
763 if ( pPt
->X() < nXMin
)
765 if ( pPt
->X() > nXMax
)
767 if ( pPt
->Y() < nYMin
)
769 if ( pPt
->Y() > nYMax
)
776 return Rectangle( nXMin
, nYMin
, nXMax
, nYMax
);
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
--;
810 delete mpImplPolyPolygon
;
812 mpImplPolyPolygon
= rPolyPoly
.mpImplPolyPolygon
;
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
)
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
;
839 for ( i
= 0; i
< Count(); i
++ )
841 if (!GetObject( i
).IsEqual( rPolyPoly
.GetObject( i
) ) )
843 bIsEqual
= sal_False
;
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" );
861 // Anzahl der Polygone einlesen
862 rIStream
>> nPolyCount
;
867 // Referenzcounter beruecksichtigen
868 if ( rPolyPoly
.mpImplPolyPolygon
->mnRefCount
> 1 )
869 rPolyPoly
.mpImplPolyPolygon
->mnRefCount
--;
871 delete rPolyPoly
.mpImplPolyPolygon
;
873 rPolyPoly
.mpImplPolyPolygon
= new ImplPolyPolygon( nPolyCount
);
875 for ( USHORT i
= 0; i
< nPolyCount
; i
++ )
879 rPolyPoly
.mpImplPolyPolygon
->mpPolyAry
[i
] = pPoly
;
883 rPolyPoly
= PolyPolygon();
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
]);
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" );
918 // Anzahl der Polygone einlesen
919 rIStream
>> nPolyCount
;
924 // Referenzcounter beruecksichtigen
925 if ( mpImplPolyPolygon
->mnRefCount
> 1 )
926 mpImplPolyPolygon
->mnRefCount
--;
928 delete mpImplPolyPolygon
;
930 mpImplPolyPolygon
= new ImplPolyPolygon( nPolyCount
);
932 for ( USHORT i
= 0; i
< nPolyCount
; i
++ )
935 pPoly
->ImplRead( rIStream
);
936 mpImplPolyPolygon
->mpPolyAry
[i
] = pPoly
;
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());
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 (!)");
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
);
997 mpImplPolyPolygon
= new ImplPolyPolygon( 16, 16 );