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