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