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