Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #define POLY_CLIP_INT 0
21 : #define POLY_CLIP_UNION 1
22 : #define POLY_CLIP_DIFF 2
23 : #define POLY_CLIP_XOR 3
24 :
25 : #include <rtl/math.hxx>
26 : #include <poly.h>
27 : #include <tools/poly.hxx>
28 : #include <tools/debug.hxx>
29 : #include <tools/stream.hxx>
30 : #include <tools/vcompat.hxx>
31 : #include <tools/gen.hxx>
32 : #include <basegfx/polygon/b2dpolypolygon.hxx>
33 : #include <basegfx/polygon/b2dpolygon.hxx>
34 : #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
35 :
36 : DBG_NAME( PolyPolygon )
37 :
38 173488 : ImplPolyPolygon::ImplPolyPolygon( sal_uInt16 nInitSize )
39 : {
40 173488 : mnRefCount = 1;
41 173488 : mnCount = nInitSize;
42 173488 : mnSize = nInitSize;
43 173488 : mnResize = 16;
44 173488 : mpPolyAry = new SVPPOLYGON[ nInitSize ];
45 173488 : }
46 :
47 66212 : ImplPolyPolygon::ImplPolyPolygon( const ImplPolyPolygon& rImplPolyPoly )
48 : {
49 66212 : mnRefCount = 1;
50 66212 : mnCount = rImplPolyPoly.mnCount;
51 66212 : mnSize = rImplPolyPoly.mnSize;
52 66212 : mnResize = rImplPolyPoly.mnResize;
53 :
54 66212 : if ( rImplPolyPoly.mpPolyAry )
55 : {
56 65935 : mpPolyAry = new SVPPOLYGON[mnSize];
57 133910 : for ( sal_uInt16 i = 0; i < mnCount; i++ )
58 67975 : mpPolyAry[i] = new Polygon( *rImplPolyPoly.mpPolyAry[i] );
59 : }
60 : else
61 277 : mpPolyAry = NULL;
62 66212 : }
63 :
64 260340 : ImplPolyPolygon::~ImplPolyPolygon()
65 : {
66 260340 : if ( mpPolyAry )
67 : {
68 508563 : for ( sal_uInt16 i = 0; i < mnCount; i++ )
69 259640 : delete mpPolyAry[i];
70 248923 : delete[] mpPolyAry;
71 : }
72 260340 : }
73 :
74 20343 : PolyPolygon::PolyPolygon( sal_uInt16 nInitSize, sal_uInt16 nResize )
75 : {
76 : DBG_CTOR( PolyPolygon, NULL );
77 :
78 20343 : if ( nInitSize > MAX_POLYGONS )
79 0 : nInitSize = MAX_POLYGONS;
80 20343 : else if ( !nInitSize )
81 0 : nInitSize = 1;
82 20343 : if ( nResize > MAX_POLYGONS )
83 0 : nResize = MAX_POLYGONS;
84 20343 : else if ( !nResize )
85 0 : nResize = 1;
86 20343 : mpImplPolyPolygon = new ImplPolyPolygon( nInitSize, nResize );
87 20343 : }
88 :
89 2367 : PolyPolygon::PolyPolygon( const Polygon& rPoly )
90 : {
91 : DBG_CTOR( PolyPolygon, NULL );
92 :
93 2367 : if ( rPoly.GetSize() )
94 : {
95 2367 : mpImplPolyPolygon = new ImplPolyPolygon( 1 );
96 2367 : mpImplPolyPolygon->mpPolyAry[0] = new Polygon( rPoly );
97 : }
98 : else
99 0 : mpImplPolyPolygon = new ImplPolyPolygon( 16, 16 );
100 2367 : }
101 :
102 116476 : PolyPolygon::PolyPolygon( const PolyPolygon& rPolyPoly )
103 : {
104 : DBG_CTOR( PolyPolygon, NULL );
105 : DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL );
106 : DBG_ASSERT( rPolyPoly.mpImplPolyPolygon->mnRefCount < 0xFFFFFFFE, "PolyPolygon: RefCount overflow" );
107 :
108 116476 : mpImplPolyPolygon = rPolyPoly.mpImplPolyPolygon;
109 116476 : mpImplPolyPolygon->mnRefCount++;
110 116476 : }
111 :
112 310593 : PolyPolygon::~PolyPolygon()
113 : {
114 : DBG_DTOR( PolyPolygon, NULL );
115 :
116 310593 : if ( mpImplPolyPolygon->mnRefCount > 1 )
117 51275 : mpImplPolyPolygon->mnRefCount--;
118 : else
119 259318 : delete mpImplPolyPolygon;
120 310593 : }
121 :
122 13694 : void PolyPolygon::Insert( const Polygon& rPoly, sal_uInt16 nPos )
123 : {
124 : DBG_CHKTHIS( PolyPolygon, NULL );
125 :
126 13694 : if ( mpImplPolyPolygon->mnCount >= MAX_POLYGONS )
127 13694 : return;
128 :
129 13694 : if ( mpImplPolyPolygon->mnRefCount > 1 )
130 : {
131 0 : mpImplPolyPolygon->mnRefCount--;
132 0 : mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
133 : }
134 :
135 13694 : if ( nPos > mpImplPolyPolygon->mnCount )
136 13689 : nPos = mpImplPolyPolygon->mnCount;
137 :
138 13694 : if ( !mpImplPolyPolygon->mpPolyAry )
139 9506 : mpImplPolyPolygon->mpPolyAry = new SVPPOLYGON[mpImplPolyPolygon->mnSize];
140 4188 : else if ( mpImplPolyPolygon->mnCount == mpImplPolyPolygon->mnSize )
141 : {
142 0 : sal_uInt16 nOldSize = mpImplPolyPolygon->mnSize;
143 0 : sal_uInt16 nNewSize = nOldSize + mpImplPolyPolygon->mnResize;
144 : SVPPOLYGON* pNewAry;
145 :
146 0 : if ( nNewSize >= MAX_POLYGONS )
147 0 : nNewSize = MAX_POLYGONS;
148 0 : pNewAry = new SVPPOLYGON[nNewSize];
149 0 : memcpy( pNewAry, mpImplPolyPolygon->mpPolyAry, nPos*sizeof(SVPPOLYGON) );
150 0 : memcpy( pNewAry+nPos+1, mpImplPolyPolygon->mpPolyAry+nPos,
151 0 : (nOldSize-nPos)*sizeof(SVPPOLYGON) );
152 0 : delete[] mpImplPolyPolygon->mpPolyAry;
153 0 : mpImplPolyPolygon->mpPolyAry = pNewAry;
154 0 : mpImplPolyPolygon->mnSize = nNewSize;
155 : }
156 4188 : else if ( nPos < mpImplPolyPolygon->mnCount )
157 : {
158 0 : memmove( mpImplPolyPolygon->mpPolyAry+nPos+1,
159 : mpImplPolyPolygon->mpPolyAry+nPos,
160 0 : (mpImplPolyPolygon->mnCount-nPos)*sizeof(SVPPOLYGON) );
161 : }
162 :
163 13694 : mpImplPolyPolygon->mpPolyAry[nPos] = new Polygon( rPoly );
164 13694 : mpImplPolyPolygon->mnCount++;
165 : }
166 :
167 0 : void PolyPolygon::Remove( sal_uInt16 nPos )
168 : {
169 : DBG_CHKTHIS( PolyPolygon, NULL );
170 : DBG_ASSERT( nPos < Count(), "PolyPolygon::Remove(): nPos >= nSize" );
171 :
172 0 : if ( mpImplPolyPolygon->mnRefCount > 1 )
173 : {
174 0 : mpImplPolyPolygon->mnRefCount--;
175 0 : mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
176 : }
177 :
178 0 : delete mpImplPolyPolygon->mpPolyAry[nPos];
179 0 : mpImplPolyPolygon->mnCount--;
180 0 : memmove( mpImplPolyPolygon->mpPolyAry+nPos,
181 0 : mpImplPolyPolygon->mpPolyAry+nPos+1,
182 0 : (mpImplPolyPolygon->mnCount-nPos)*sizeof(SVPPOLYGON) );
183 0 : }
184 :
185 0 : void PolyPolygon::Replace( const Polygon& rPoly, sal_uInt16 nPos )
186 : {
187 : DBG_CHKTHIS( PolyPolygon, NULL );
188 : DBG_ASSERT( nPos < Count(), "PolyPolygon::Replace(): nPos >= nSize" );
189 :
190 0 : if ( mpImplPolyPolygon->mnRefCount > 1 )
191 : {
192 0 : mpImplPolyPolygon->mnRefCount--;
193 0 : mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
194 : }
195 :
196 0 : delete mpImplPolyPolygon->mpPolyAry[nPos];
197 0 : mpImplPolyPolygon->mpPolyAry[nPos] = new Polygon( rPoly );
198 0 : }
199 :
200 239958 : const Polygon& PolyPolygon::GetObject( sal_uInt16 nPos ) const
201 : {
202 : DBG_CHKTHIS( PolyPolygon, NULL );
203 : DBG_ASSERT( nPos < Count(), "PolyPolygon::GetObject(): nPos >= nSize" );
204 :
205 239958 : return *(mpImplPolyPolygon->mpPolyAry[nPos]);
206 : }
207 :
208 2993 : bool PolyPolygon::IsRect() const
209 : {
210 2993 : bool bIsRect = false;
211 2993 : if ( Count() == 1 )
212 2885 : bIsRect = mpImplPolyPolygon->mpPolyAry[ 0 ]->IsRect();
213 2993 : return bIsRect;
214 : }
215 :
216 51 : void PolyPolygon::Clear()
217 : {
218 : DBG_CHKTHIS( PolyPolygon, NULL );
219 :
220 51 : if ( mpImplPolyPolygon->mnRefCount > 1 )
221 : {
222 10 : mpImplPolyPolygon->mnRefCount--;
223 : mpImplPolyPolygon = new ImplPolyPolygon( mpImplPolyPolygon->mnResize,
224 10 : mpImplPolyPolygon->mnResize );
225 : }
226 : else
227 : {
228 41 : if ( mpImplPolyPolygon->mpPolyAry )
229 : {
230 12 : for ( sal_uInt16 i = 0; i < mpImplPolyPolygon->mnCount; i++ )
231 6 : delete mpImplPolyPolygon->mpPolyAry[i];
232 6 : delete[] mpImplPolyPolygon->mpPolyAry;
233 6 : mpImplPolyPolygon->mpPolyAry = NULL;
234 6 : mpImplPolyPolygon->mnCount = 0;
235 6 : mpImplPolyPolygon->mnSize = mpImplPolyPolygon->mnResize;
236 : }
237 : }
238 51 : }
239 :
240 240 : void PolyPolygon::Optimize( sal_uIntPtr nOptimizeFlags, const PolyOptimizeData* pData )
241 : {
242 : DBG_CHKTHIS( PolyPolygon, NULL );
243 :
244 240 : if(nOptimizeFlags && Count())
245 : {
246 : // #115630# ImplDrawHatch does not work with beziers included in the polypolygon, take care of that
247 238 : bool bIsCurve(false);
248 :
249 476 : for(sal_uInt16 a(0); !bIsCurve && a < Count(); a++)
250 : {
251 238 : if((*this)[a].HasFlags())
252 : {
253 0 : bIsCurve = true;
254 : }
255 : }
256 :
257 238 : if(bIsCurve)
258 : {
259 : OSL_ENSURE(false, "Optimize does *not* support curves, falling back to AdaptiveSubdivide()...");
260 0 : PolyPolygon aPolyPoly;
261 :
262 0 : AdaptiveSubdivide(aPolyPoly);
263 0 : aPolyPoly.Optimize(nOptimizeFlags, pData);
264 0 : *this = aPolyPoly;
265 : }
266 : else
267 : {
268 : double fArea;
269 238 : const bool bEdges = ( nOptimizeFlags & POLY_OPTIMIZE_EDGES ) == POLY_OPTIMIZE_EDGES;
270 238 : sal_uInt16 nPercent = 0;
271 :
272 238 : if( bEdges )
273 : {
274 0 : const Rectangle aBound( GetBoundRect() );
275 :
276 0 : fArea = ( aBound.GetWidth() + aBound.GetHeight() ) * 0.5;
277 0 : nPercent = pData ? pData->GetPercentValue() : 50;
278 0 : nOptimizeFlags &= ~POLY_OPTIMIZE_EDGES;
279 : }
280 :
281 : // watch for ref counter
282 238 : if( mpImplPolyPolygon->mnRefCount > 1 )
283 : {
284 0 : mpImplPolyPolygon->mnRefCount--;
285 0 : mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
286 : }
287 :
288 : // Optimize polygons
289 476 : for( sal_uInt16 i = 0, nPolyCount = mpImplPolyPolygon->mnCount; i < nPolyCount; i++ )
290 : {
291 238 : if( bEdges )
292 : {
293 0 : mpImplPolyPolygon->mpPolyAry[ i ]->Optimize( POLY_OPTIMIZE_NO_SAME );
294 0 : Polygon::ImplReduceEdges( *( mpImplPolyPolygon->mpPolyAry[ i ] ), fArea, nPercent );
295 : }
296 :
297 238 : if( nOptimizeFlags )
298 238 : mpImplPolyPolygon->mpPolyAry[ i ]->Optimize( nOptimizeFlags, pData );
299 : }
300 : }
301 : }
302 240 : }
303 :
304 22 : void PolyPolygon::AdaptiveSubdivide( PolyPolygon& rResult, const double d ) const
305 : {
306 : DBG_CHKTHIS( PolyPolygon, NULL );
307 :
308 22 : rResult.Clear();
309 :
310 22 : Polygon aPolygon;
311 :
312 52 : for( sal_uInt16 i = 0; i < mpImplPolyPolygon->mnCount; i++ )
313 : {
314 30 : mpImplPolyPolygon->mpPolyAry[ i ]->AdaptiveSubdivide( aPolygon, d );
315 30 : rResult.Insert( aPolygon );
316 22 : }
317 22 : }
318 :
319 0 : void PolyPolygon::GetIntersection( const PolyPolygon& rPolyPoly, PolyPolygon& rResult ) const
320 : {
321 0 : ImplDoOperation( rPolyPoly, rResult, POLY_CLIP_INT );
322 0 : }
323 :
324 7 : void PolyPolygon::GetUnion( const PolyPolygon& rPolyPoly, PolyPolygon& rResult ) const
325 : {
326 7 : ImplDoOperation( rPolyPoly, rResult, POLY_CLIP_UNION );
327 7 : }
328 :
329 7 : void PolyPolygon::ImplDoOperation( const PolyPolygon& rPolyPoly, PolyPolygon& rResult, sal_uIntPtr nOperation ) const
330 : {
331 : // Convert to B2DPolyPolygon, temporarily. It might be
332 : // advantageous in the future, to have a PolyPolygon adaptor that
333 : // just simulates a B2DPolyPolygon here...
334 7 : basegfx::B2DPolyPolygon aMergePolyPolygonA( getB2DPolyPolygon() );
335 14 : basegfx::B2DPolyPolygon aMergePolyPolygonB( rPolyPoly.getB2DPolyPolygon() );
336 :
337 : // normalize the two polypolygons before. Force properly oriented
338 : // polygons.
339 7 : aMergePolyPolygonA = basegfx::tools::prepareForPolygonOperation( aMergePolyPolygonA );
340 7 : aMergePolyPolygonB = basegfx::tools::prepareForPolygonOperation( aMergePolyPolygonB );
341 :
342 7 : switch( nOperation )
343 : {
344 : // All code extracted from svx/source/svdraw/svedtv2.cxx
345 :
346 : case POLY_CLIP_UNION:
347 : {
348 : // merge A and B (OR)
349 7 : aMergePolyPolygonA = basegfx::tools::solvePolygonOperationOr(aMergePolyPolygonA, aMergePolyPolygonB);
350 7 : break;
351 : }
352 :
353 : case POLY_CLIP_DIFF:
354 : {
355 : // substract B from A (DIFF)
356 0 : aMergePolyPolygonA = basegfx::tools::solvePolygonOperationDiff(aMergePolyPolygonA, aMergePolyPolygonB);
357 0 : break;
358 : }
359 :
360 : case POLY_CLIP_XOR:
361 : {
362 : // compute XOR between poly A and B
363 0 : aMergePolyPolygonA = basegfx::tools::solvePolygonOperationXor(aMergePolyPolygonA, aMergePolyPolygonB);
364 0 : break;
365 : }
366 :
367 : default:
368 : case POLY_CLIP_INT:
369 : {
370 : // cut poly 1 against polys 2..n (AND)
371 0 : aMergePolyPolygonA = basegfx::tools::solvePolygonOperationAnd(aMergePolyPolygonA, aMergePolyPolygonB);
372 0 : break;
373 : }
374 : }
375 :
376 14 : rResult = PolyPolygon( aMergePolyPolygonA );
377 7 : }
378 :
379 304875 : sal_uInt16 PolyPolygon::Count() const
380 : {
381 : DBG_CHKTHIS( PolyPolygon, NULL );
382 304875 : return mpImplPolyPolygon->mnCount;
383 : }
384 :
385 18299 : void PolyPolygon::Move( long nHorzMove, long nVertMove )
386 : {
387 : DBG_CHKTHIS( PolyPolygon, NULL );
388 :
389 : // Required for DrawEngine
390 18299 : if( nHorzMove || nVertMove )
391 : {
392 18299 : if ( mpImplPolyPolygon->mnRefCount > 1 )
393 : {
394 18198 : mpImplPolyPolygon->mnRefCount--;
395 18198 : mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
396 : }
397 :
398 : // move points
399 18299 : sal_uInt16 nPolyCount = mpImplPolyPolygon->mnCount;
400 38203 : for ( sal_uInt16 i = 0; i < nPolyCount; i++ )
401 19904 : mpImplPolyPolygon->mpPolyAry[i]->Move( nHorzMove, nVertMove );
402 : }
403 18299 : }
404 :
405 0 : void PolyPolygon::Translate( const Point& rTrans )
406 : {
407 : DBG_CHKTHIS( PolyPolygon, NULL );
408 :
409 0 : if( mpImplPolyPolygon->mnRefCount > 1 )
410 : {
411 0 : mpImplPolyPolygon->mnRefCount--;
412 0 : mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
413 : }
414 :
415 : // move points
416 0 : for ( sal_uInt16 i = 0, nCount = mpImplPolyPolygon->mnCount; i < nCount; i++ )
417 0 : mpImplPolyPolygon->mpPolyAry[ i ]->Translate( rTrans );
418 0 : }
419 :
420 0 : void PolyPolygon::Scale( double fScaleX, double fScaleY )
421 : {
422 : DBG_CHKTHIS( PolyPolygon, NULL );
423 :
424 0 : if( mpImplPolyPolygon->mnRefCount > 1 )
425 : {
426 0 : mpImplPolyPolygon->mnRefCount--;
427 0 : mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
428 : }
429 :
430 : // Move points
431 0 : for ( sal_uInt16 i = 0, nCount = mpImplPolyPolygon->mnCount; i < nCount; i++ )
432 0 : mpImplPolyPolygon->mpPolyAry[ i ]->Scale( fScaleX, fScaleY );
433 0 : }
434 :
435 0 : void PolyPolygon::Rotate( const Point& rCenter, sal_uInt16 nAngle10 )
436 : {
437 : DBG_CHKTHIS( PolyPolygon, NULL );
438 0 : nAngle10 %= 3600;
439 :
440 0 : if( nAngle10 )
441 : {
442 0 : const double fAngle = F_PI1800 * nAngle10;
443 0 : Rotate( rCenter, sin( fAngle ), cos( fAngle ) );
444 : }
445 0 : }
446 :
447 0 : void PolyPolygon::Rotate( const Point& rCenter, double fSin, double fCos )
448 : {
449 : DBG_CHKTHIS( PolyPolygon, NULL );
450 :
451 0 : if( mpImplPolyPolygon->mnRefCount > 1 )
452 : {
453 0 : mpImplPolyPolygon->mnRefCount--;
454 0 : mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
455 : }
456 :
457 : // move points
458 0 : for ( sal_uInt16 i = 0, nCount = mpImplPolyPolygon->mnCount; i < nCount; i++ )
459 0 : mpImplPolyPolygon->mpPolyAry[ i ]->Rotate( rCenter, fSin, fCos );
460 0 : }
461 :
462 0 : void PolyPolygon::Clip( const Rectangle& rRect )
463 : {
464 0 : sal_uInt16 nPolyCount = mpImplPolyPolygon->mnCount;
465 : sal_uInt16 i;
466 :
467 0 : if ( !nPolyCount )
468 0 : return;
469 :
470 0 : if ( mpImplPolyPolygon->mnRefCount > 1 )
471 : {
472 0 : mpImplPolyPolygon->mnRefCount--;
473 0 : mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
474 : }
475 :
476 : // Clip every polygon, deleting the empty ones
477 0 : for ( i = 0; i < nPolyCount; i++ )
478 0 : mpImplPolyPolygon->mpPolyAry[i]->Clip( rRect );
479 0 : while ( nPolyCount )
480 : {
481 0 : if ( GetObject( nPolyCount-1 ).GetSize() <= 2 )
482 0 : Remove( nPolyCount-1 );
483 0 : nPolyCount--;
484 : }
485 : }
486 :
487 3282 : Rectangle PolyPolygon::GetBoundRect() const
488 : {
489 : DBG_CHKTHIS( PolyPolygon, NULL );
490 :
491 3282 : long nXMin=0, nXMax=0, nYMin=0, nYMax=0;
492 3282 : bool bFirst = true;
493 3282 : sal_uInt16 nPolyCount = mpImplPolyPolygon->mnCount;
494 :
495 8302 : for ( sal_uInt16 n = 0; n < nPolyCount; n++ )
496 : {
497 5020 : const Polygon* pPoly = mpImplPolyPolygon->mpPolyAry[n];
498 5020 : const Point* pAry = pPoly->GetConstPointAry();
499 5020 : sal_uInt16 nPointCount = pPoly->GetSize();
500 :
501 103071 : for ( sal_uInt16 i = 0; i < nPointCount; i++ )
502 : {
503 98051 : const Point* pPt = &pAry[ i ];
504 :
505 98051 : if ( bFirst )
506 : {
507 3282 : nXMin = nXMax = pPt->X();
508 3282 : nYMin = nYMax = pPt->Y();
509 3282 : bFirst = false;
510 : }
511 : else
512 : {
513 94769 : if ( pPt->X() < nXMin )
514 14455 : nXMin = pPt->X();
515 94769 : if ( pPt->X() > nXMax )
516 2316 : nXMax = pPt->X();
517 94769 : if ( pPt->Y() < nYMin )
518 7321 : nYMin = pPt->Y();
519 94769 : if ( pPt->Y() > nYMax )
520 9195 : nYMax = pPt->Y();
521 : }
522 : }
523 : }
524 :
525 3282 : if ( !bFirst )
526 3282 : return Rectangle( nXMin, nYMin, nXMax, nYMax );
527 : else
528 0 : return Rectangle();
529 : }
530 :
531 48753 : Polygon& PolyPolygon::operator[]( sal_uInt16 nPos )
532 : {
533 : DBG_CHKTHIS( PolyPolygon, NULL );
534 : DBG_ASSERT( nPos < Count(), "PolyPolygon::[](): nPos >= nSize" );
535 :
536 48753 : if ( mpImplPolyPolygon->mnRefCount > 1 )
537 : {
538 48014 : mpImplPolyPolygon->mnRefCount--;
539 48014 : mpImplPolyPolygon = new ImplPolyPolygon( *mpImplPolyPolygon );
540 : }
541 :
542 48753 : return *(mpImplPolyPolygon->mpPolyAry[nPos]);
543 : }
544 :
545 1174 : PolyPolygon& PolyPolygon::operator=( const PolyPolygon& rPolyPoly )
546 : {
547 : DBG_CHKTHIS( PolyPolygon, NULL );
548 : DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL );
549 : DBG_ASSERT( rPolyPoly.mpImplPolyPolygon->mnRefCount < 0xFFFFFFFE, "PolyPolygon: RefCount overflow" );
550 :
551 1174 : rPolyPoly.mpImplPolyPolygon->mnRefCount++;
552 :
553 1174 : if ( mpImplPolyPolygon->mnRefCount > 1 )
554 153 : mpImplPolyPolygon->mnRefCount--;
555 : else
556 1021 : delete mpImplPolyPolygon;
557 :
558 1174 : mpImplPolyPolygon = rPolyPoly.mpImplPolyPolygon;
559 1174 : return *this;
560 : }
561 :
562 0 : bool PolyPolygon::operator==( const PolyPolygon& rPolyPoly ) const
563 : {
564 : DBG_CHKTHIS( PolyPolygon, NULL );
565 : DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL );
566 :
567 0 : if ( rPolyPoly.mpImplPolyPolygon == mpImplPolyPolygon )
568 0 : return true;
569 : else
570 0 : return false;
571 : }
572 :
573 0 : bool PolyPolygon::IsEqual( const PolyPolygon& rPolyPoly ) const
574 : {
575 0 : bool bIsEqual = true;
576 0 : if ( Count() != rPolyPoly.Count() )
577 0 : bIsEqual = false;
578 : else
579 : {
580 : sal_uInt16 i;
581 0 : for ( i = 0; i < Count(); i++ )
582 : {
583 0 : if (!GetObject( i ).IsEqual( rPolyPoly.GetObject( i ) ) )
584 : {
585 0 : bIsEqual = false;
586 0 : break;
587 : }
588 : }
589 : }
590 0 : return bIsEqual;
591 : }
592 :
593 0 : SvStream& operator>>( SvStream& rIStream, PolyPolygon& rPolyPoly )
594 : {
595 : DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL );
596 : DBG_ASSERTWARNING( rIStream.GetVersion(), "PolyPolygon::>> - Solar-Version not set on rIStream" );
597 :
598 : Polygon* pPoly;
599 : sal_uInt16 nPolyCount;
600 :
601 : // read number of polygons
602 0 : rIStream >> nPolyCount;
603 :
604 0 : if( nPolyCount )
605 : {
606 0 : if ( rPolyPoly.mpImplPolyPolygon->mnRefCount > 1 )
607 0 : rPolyPoly.mpImplPolyPolygon->mnRefCount--;
608 : else
609 0 : delete rPolyPoly.mpImplPolyPolygon;
610 :
611 0 : rPolyPoly.mpImplPolyPolygon = new ImplPolyPolygon( nPolyCount );
612 :
613 0 : for ( sal_uInt16 i = 0; i < nPolyCount; i++ )
614 : {
615 0 : pPoly = new Polygon;
616 0 : rIStream >> *pPoly;
617 0 : rPolyPoly.mpImplPolyPolygon->mpPolyAry[i] = pPoly;
618 : }
619 : }
620 : else
621 0 : rPolyPoly = PolyPolygon();
622 :
623 0 : return rIStream;
624 : }
625 :
626 0 : SvStream& operator<<( SvStream& rOStream, const PolyPolygon& rPolyPoly )
627 : {
628 : DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL );
629 : DBG_ASSERTWARNING( rOStream.GetVersion(), "PolyPolygon::<< - Solar-Version not set on rOStream" );
630 :
631 : // Write number of polygons
632 0 : sal_uInt16 nPolyCount = rPolyPoly.mpImplPolyPolygon->mnCount;
633 0 : rOStream << nPolyCount;
634 :
635 : // output polygons
636 0 : for ( sal_uInt16 i = 0; i < nPolyCount; i++ )
637 0 : rOStream << *(rPolyPoly.mpImplPolyPolygon->mpPolyAry[i]);
638 :
639 0 : return rOStream;
640 : }
641 :
642 278 : void PolyPolygon::Read( SvStream& rIStream )
643 : {
644 278 : VersionCompat aCompat( rIStream, STREAM_READ );
645 :
646 : DBG_CHKTHIS( PolyPolygon, NULL );
647 : DBG_ASSERTWARNING( rIStream.GetVersion(), "PolyPolygon::>> - Solar-Version not set on rIStream" );
648 :
649 : Polygon* pPoly;
650 : sal_uInt16 nPolyCount;
651 :
652 : // Read number of polygons
653 278 : rIStream >> nPolyCount;
654 :
655 278 : if( nPolyCount )
656 : {
657 1 : if ( mpImplPolyPolygon->mnRefCount > 1 )
658 0 : mpImplPolyPolygon->mnRefCount--;
659 : else
660 1 : delete mpImplPolyPolygon;
661 :
662 1 : mpImplPolyPolygon = new ImplPolyPolygon( nPolyCount );
663 :
664 2 : for ( sal_uInt16 i = 0; i < nPolyCount; i++ )
665 : {
666 1 : pPoly = new Polygon;
667 1 : pPoly->ImplRead( rIStream );
668 1 : mpImplPolyPolygon->mpPolyAry[i] = pPoly;
669 : }
670 : }
671 : else
672 277 : *this = PolyPolygon();
673 278 : }
674 :
675 566 : void PolyPolygon::Write( SvStream& rOStream ) const
676 : {
677 566 : VersionCompat aCompat( rOStream, STREAM_WRITE, 1 );
678 :
679 : DBG_CHKTHIS( PolyPolygon, NULL );
680 : DBG_ASSERTWARNING( rOStream.GetVersion(), "PolyPolygon::<< - Solar-Version not set on rOStream" );
681 :
682 : // Write number of polygons
683 566 : sal_uInt16 nPolyCount = mpImplPolyPolygon->mnCount;
684 566 : rOStream << nPolyCount;
685 :
686 : // Output polygons
687 568 : for ( sal_uInt16 i = 0; i < nPolyCount; i++ )
688 568 : mpImplPolyPolygon->mpPolyAry[i]->ImplWrite( rOStream );
689 566 : }
690 :
691 : // convert to basegfx::B2DPolyPolygon and return
692 1067 : basegfx::B2DPolyPolygon PolyPolygon::getB2DPolyPolygon() const
693 : {
694 1067 : basegfx::B2DPolyPolygon aRetval;
695 :
696 2671 : for(sal_uInt16 a(0); a < mpImplPolyPolygon->mnCount; a++)
697 : {
698 1604 : Polygon* pCandidate = mpImplPolyPolygon->mpPolyAry[a];
699 1604 : aRetval.append(pCandidate->getB2DPolygon());
700 : }
701 :
702 1067 : return aRetval;
703 : }
704 :
705 : // constructor to convert from basegfx::B2DPolyPolygon
706 171407 : PolyPolygon::PolyPolygon(const basegfx::B2DPolyPolygon& rPolyPolygon)
707 : {
708 : DBG_CTOR( PolyPolygon, NULL );
709 171407 : const sal_uInt16 nCount(sal_uInt16(rPolyPolygon.count()));
710 : DBG_ASSERT(sal_uInt32(nCount) == rPolyPolygon.count(),
711 : "PolyPolygon::PolyPolygon: Too many sub-polygons in given basegfx::B2DPolyPolygon (!)");
712 :
713 171407 : if ( nCount )
714 : {
715 171120 : mpImplPolyPolygon = new ImplPolyPolygon( nCount );
716 :
717 346729 : for(sal_uInt16 a(0); a < nCount; a++)
718 : {
719 175609 : basegfx::B2DPolygon aCandidate(rPolyPolygon.getB2DPolygon(sal_uInt32(a)));
720 175609 : mpImplPolyPolygon->mpPolyAry[a] = new Polygon( aCandidate );
721 175609 : }
722 : }
723 : else
724 : {
725 287 : mpImplPolyPolygon = new ImplPolyPolygon( 16, 16 );
726 : }
727 171407 : }
728 :
729 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|