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