Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <limits.h>
31 : :
32 : : #include <tools/vcompat.hxx>
33 : : #include <tools/stream.hxx>
34 : : #include <tools/debug.hxx>
35 : : #include <tools/helpers.hxx>
36 : : #include <vcl/region.hxx>
37 : : #include <vcl/regband.hxx>
38 : :
39 : : #include <region.h>
40 : :
41 : : #include <basegfx/matrix/b2dhommatrix.hxx>
42 : : #include <basegfx/polygon/b2dpolypolygontools.hxx>
43 : : #include <basegfx/polygon/b2dpolygontools.hxx>
44 : : #include <basegfx/polygon/b2dpolygonclipper.hxx>
45 : : #include <basegfx/polygon/b2dpolypolygoncutter.hxx>
46 : : #include <basegfx/range/b2drange.hxx>
47 : : #include <basegfx/matrix/b2dhommatrixtools.hxx>
48 : :
49 : : // =======================================================================
50 : : //
51 : : // ImplRegionBand
52 : : //
53 : : // Die Klassen RegionBand/ImplRegionBand speichert Regionen in Form von
54 : : // Rechtecken ab. Die Region ist in Y-Richtung in Baendern unterteilt, die
55 : : // wiederum ein oder mehrere Rechtecke mit der Hoehe des Bandes enthalten.
56 : : //
57 : : // Leere Baender werden entfernt.
58 : : //
59 : : // Polygone und PolyPolygone werden ebenfalls in Rechtecke zerlegt und in
60 : : // der Baendern abgelegt. Hierzu werden alle Punkte der einzelnen Polygone
61 : : // mit dem Bresenham-Algorithmus berechnet und in die Baender eingetragen.
62 : : // Nach der vollstaendigen Berechung aller Kanten werden die entsprechenden
63 : : // Rechntecke berechnet
64 : :
65 : : // =======================================================================
66 : :
67 : 347 : static ImplRegionBase aImplNullRegion( 0 );
68 : 347 : static ImplRegionBase aImplEmptyRegion( 0 );
69 : :
70 : : // =======================================================================
71 : :
72 : : DBG_NAME( Region )
73 : : DBG_NAMEEX( Polygon )
74 : : DBG_NAMEEX( PolyPolygon )
75 : :
76 : : namespace {
77 : :
78 : : /** Return <TRUE/> when the given polygon is rectiliner and oriented so that
79 : : all sides are either horizontal or vertical.
80 : : */
81 : 26 : bool ImplIsPolygonRectilinear (const PolyPolygon& rPolyPoly)
82 : : {
83 : : // Iterate over all polygons.
84 : 26 : const sal_uInt16 nPolyCount = rPolyPoly.Count();
85 [ + + ]: 60 : for (sal_uInt16 nPoly = 0; nPoly < nPolyCount; ++nPoly)
86 : : {
87 [ + - ]: 34 : const Polygon& aPoly = rPolyPoly.GetObject(nPoly);
88 : :
89 : : // Iterate over all edges of the current polygon.
90 [ + - ]: 34 : const sal_uInt16 nSize = aPoly.GetSize();
91 : :
92 [ - + ]: 34 : if (nSize < 2)
93 : 0 : continue;
94 [ + - ]: 34 : Point aPoint (aPoly.GetPoint(0));
95 : 34 : const Point aLastPoint (aPoint);
96 [ + + ]: 170 : for (sal_uInt16 nPoint = 1; nPoint < nSize; ++nPoint)
97 : : {
98 [ + - ]: 136 : const Point aNextPoint (aPoly.GetPoint(nPoint));
99 : : // When there is at least one edge that is neither vertical nor
100 : : // horizontal then the entire polygon is not rectilinear (and
101 : : // oriented along primary axes.)
102 [ + + ][ - + ]: 136 : if (aPoint.X() != aNextPoint.X() && aPoint.Y() != aNextPoint.Y())
[ - + ]
103 : 0 : return false;
104 : :
105 : 136 : aPoint = aNextPoint;
106 : : }
107 : : // Compare closing edge.
108 [ - + ][ # # ]: 34 : if (aLastPoint.X() != aPoint.X() && aLastPoint.Y() != aPoint.Y())
[ - + ]
109 : 34 : return false;
110 : : }
111 : 26 : return true;
112 : : }
113 : :
114 : :
115 : :
116 : : /** This function is similar to the ImplRegion::InsertBands() method.
117 : : It creates a minimal set of missing bands so that the entire vertical
118 : : interval from nTop to nBottom is covered by bands.
119 : : */
120 : 68 : void ImplAddMissingBands (
121 : : ImplRegion* pImplRegion,
122 : : const long nTop,
123 : : const long nBottom)
124 : : {
125 : : // Iterate over already existing bands and add missing bands atop the
126 : : // first and between two bands.
127 : 68 : ImplRegionBand* pPreviousBand = NULL;
128 : 68 : ImplRegionBand* pBand = pImplRegion->ImplGetFirstRegionBand();
129 : 68 : long nCurrentTop (nTop);
130 [ + + ][ + - ]: 118 : while (pBand != NULL && nCurrentTop<nBottom)
[ + + ]
131 : : {
132 [ - + ]: 50 : if (nCurrentTop < pBand->mnYTop)
133 : : {
134 : : // Create new band above the current band.
135 : : ImplRegionBand* pAboveBand = new ImplRegionBand(
136 : : nCurrentTop,
137 [ # # ][ # # ]: 0 : ::std::min(nBottom,pBand->mnYTop-1));
[ # # ]
138 : 0 : pImplRegion->InsertBand(pPreviousBand, pAboveBand);
139 : : }
140 : :
141 : : // Adapt the top of the interval to prevent overlapping bands.
142 [ + - ]: 50 : nCurrentTop = ::std::max(nTop, pBand->mnYBottom+1);
143 : :
144 : : // Advance to next band.
145 : 50 : pPreviousBand = pBand;
146 : 50 : pBand = pBand->mpNextBand;
147 : : }
148 : :
149 : : // We still have to cover two cases:
150 : : // 1. The region does not yet contain any bands.
151 : : // 2. The intervall nTop->nBottom extends past the bottom most band.
152 [ + + ][ - + ]: 68 : if (nCurrentTop <= nBottom
[ # # ]
153 : : && (pBand==NULL || nBottom>pBand->mnYBottom))
154 : : {
155 : : // When there is no previous band then the new one will be the
156 : : // first. Otherwise the new band is inserted behind the last band.
157 : : pImplRegion->InsertBand(
158 : : pPreviousBand,
159 : : new ImplRegionBand(
160 : : nCurrentTop,
161 [ + - ]: 34 : nBottom));
162 : : }
163 : 68 : }
164 : :
165 : :
166 : :
167 : : /** Convert a rectilinear polygon (that is oriented along the primary axes)
168 : : to a list of bands. For this special form of polygon we can use an
169 : : optimization that prevents the creation of one band per y value.
170 : : However, it still is possible that some temporary bands are created that
171 : : later can be optimized away.
172 : : @param rPolyPolygon
173 : : A set of zero, one, or more polygons, nested or not, that are
174 : : converted into a list of bands.
175 : : @return
176 : : A new ImplRegion object is returned that contains the bands that
177 : : represent the given poly-polygon.
178 : : */
179 : 26 : ImplRegion* ImplRectilinearPolygonToBands (const PolyPolygon& rPolyPoly)
180 : : {
181 : : OSL_ASSERT(ImplIsPolygonRectilinear (rPolyPoly));
182 : :
183 : : // Create a new ImplRegion object as container of the bands.
184 [ + - ]: 26 : ImplRegion* pImplRegion = new ImplRegion();
185 : 26 : long nLineId = 0L;
186 : :
187 : : // Iterate over all polygons.
188 : 26 : const sal_uInt16 nPolyCount = rPolyPoly.Count();
189 [ + + ]: 60 : for (sal_uInt16 nPoly = 0; nPoly < nPolyCount; ++nPoly)
190 : : {
191 [ + - ]: 34 : const Polygon& aPoly = rPolyPoly.GetObject(nPoly);
192 : :
193 : : // Iterate over all edges of the current polygon.
194 [ + - ]: 34 : const sal_uInt16 nSize = aPoly.GetSize();
195 [ - + ]: 34 : if (nSize < 2)
196 : 0 : continue;
197 : : // Avoid fetching every point twice (each point is the start point
198 : : // of one and the end point of another edge.)
199 [ + - ]: 34 : Point aStart (aPoly.GetPoint(0));
200 : 34 : Point aEnd;
201 [ + + ]: 204 : for (sal_uInt16 nPoint = 1; nPoint <= nSize; ++nPoint, aStart=aEnd)
202 : : {
203 : : // We take the implicit closing edge into account by mapping
204 : : // index nSize to 0.
205 [ + - ]: 170 : aEnd = aPoly.GetPoint(nPoint%nSize);
206 [ + + ]: 170 : if (aStart.Y() == aEnd.Y())
207 : : {
208 : : // Horizontal lines are ignored.
209 : 102 : continue;
210 : : }
211 : :
212 : : // At this point the line has to be vertical.
213 : : OSL_ASSERT(aStart.X() == aEnd.X());
214 : :
215 : : // Sort y-coordinates to simplify the algorithm and store the
216 : : // direction seperately. The direction is calculated as it is
217 : : // in other places (but seems to be the wrong way.)
218 [ + - ]: 68 : const long nTop (::std::min(aStart.Y(), aEnd.Y()));
219 [ + - ]: 68 : const long nBottom (::std::max(aStart.Y(), aEnd.Y()));
220 [ + + ]: 68 : const LineType eLineType (aStart.Y() > aEnd.Y() ? LINE_DESCENDING : LINE_ASCENDING);
221 : :
222 : : // Make sure that the current line is covered by bands.
223 [ + - ]: 68 : ImplAddMissingBands(pImplRegion, nTop,nBottom);
224 : :
225 : : // Find top-most band that may contain nTop.
226 : 68 : ImplRegionBand* pBand = pImplRegion->ImplGetFirstRegionBand();
227 [ + - ][ + + ]: 84 : while (pBand!=NULL && pBand->mnYBottom < nTop)
[ + + ]
228 : 16 : pBand = pBand->mpNextBand;
229 : 68 : ImplRegionBand* pTopBand = pBand;
230 : : // If necessary split the band at nTop so that nTop is contained
231 : : // in the lower band.
232 [ + - ][ - + ]: 68 : if (pBand!=NULL
[ # # ][ # # ]
233 : : // Prevent the current band from becoming 0 pixel high
234 : : && pBand->mnYTop<nTop
235 : : // this allows the lowest pixel of the band to be split off
236 : : && pBand->mnYBottom>=nTop
237 : : // do not split a band that is just one pixel high
238 : : && pBand->mnYTop<pBand->mnYBottom)
239 : : {
240 : : // Split the top band.
241 [ # # ]: 0 : pTopBand = pBand->SplitBand(nTop);
242 : : }
243 : :
244 : : // Advance to band that may contain nBottom.
245 [ + - ][ - + ]: 68 : while (pBand!=NULL && pBand->mnYBottom < nBottom)
[ - + ]
246 : 0 : pBand = pBand->mpNextBand;
247 : : // The lowest band may have to be split at nBottom so that
248 : : // nBottom itself remains in the upper band.
249 [ + - ][ + - ]: 68 : if (pBand!=NULL
[ - + ][ # # ]
250 : : // allow the current band becoming 1 pixel high
251 : : && pBand->mnYTop<=nBottom
252 : : // prevent splitting off a band that is 0 pixel high
253 : : && pBand->mnYBottom>nBottom
254 : : // do not split a band that is just one pixel high
255 : : && pBand->mnYTop<pBand->mnYBottom)
256 : : {
257 : : // Split the bottom band.
258 [ # # ]: 0 : pBand->SplitBand(nBottom+1);
259 : : }
260 : :
261 : : // Note that we remember the top band (in pTopBand) but not the
262 : : // bottom band. The later can be determined by comparing y
263 : : // coordinates.
264 : :
265 : : // Add the x-value as point to all bands in the nTop->nBottom range.
266 [ + + ][ + - ]: 136 : for (pBand=pTopBand; pBand!=NULL&&pBand->mnYTop<=nBottom; pBand=pBand->mpNextBand)
[ + + ]
267 [ + - ]: 68 : pBand->InsertPoint(aStart.X(), nLineId++, sal_True, eLineType);
268 : : }
269 : : }
270 : :
271 : 26 : return pImplRegion;
272 : : }
273 : :
274 : :
275 : :
276 : :
277 : : /** Convert a general polygon (one for which ImplIsPolygonRectilinear()
278 : : returns <FALSE/>) to bands.
279 : : */
280 : 0 : ImplRegion* ImplGeneralPolygonToBands (
281 : : const PolyPolygon& rPolyPoly,
282 : : const Rectangle& rPolygonBoundingBox)
283 : : {
284 : 0 : long nLineID = 0L;
285 : :
286 : : // initialisation and creation of Bands
287 [ # # ]: 0 : ImplRegion* pImplRegion = new ImplRegion();
288 : 0 : pImplRegion->CreateBandRange( rPolygonBoundingBox.Top(), rPolygonBoundingBox.Bottom() );
289 : :
290 : : // insert polygons
291 : 0 : const sal_uInt16 nPolyCount = rPolyPoly.Count();
292 [ # # ]: 0 : for ( sal_uInt16 nPoly = 0; nPoly < nPolyCount; nPoly++ )
293 : : {
294 : : // get reference to current polygon
295 [ # # ]: 0 : const Polygon& aPoly = rPolyPoly.GetObject( nPoly );
296 [ # # ]: 0 : const sal_uInt16 nSize = aPoly.GetSize();
297 : :
298 : : // not enough points ( <= 2 )? -> nothing to do!
299 [ # # ]: 0 : if ( nSize <= 2 )
300 : 0 : continue;
301 : :
302 : : // band the polygon
303 [ # # ]: 0 : for ( sal_uInt16 nPoint = 1; nPoint < nSize; nPoint++ )
304 [ # # ][ # # ]: 0 : pImplRegion->InsertLine( aPoly.GetPoint(nPoint-1), aPoly.GetPoint(nPoint), nLineID++ );
[ # # ]
305 : :
306 : : // close polygon with line from first point to last point, if neccesary
307 [ # # ]: 0 : const Point rLastPoint = aPoly.GetPoint(nSize-1);
308 [ # # ]: 0 : const Point rFirstPoint = aPoly.GetPoint(0);
309 [ # # ]: 0 : if ( rLastPoint != rFirstPoint )
310 [ # # ]: 0 : pImplRegion->InsertLine( rLastPoint, rFirstPoint, nLineID++ );
311 : : }
312 : :
313 : 0 : return pImplRegion;
314 : : }
315 : :
316 : :
317 : : } // end of anonymous namespace
318 : :
319 : :
320 : : // -----------------------------------------------------------------------
321 : :
322 : : #ifdef DBG_UTIL
323 : : const char* ImplDbgTestRegion( const void* pObj )
324 : : {
325 : : Region* pRegion = (Region*)pObj;
326 : : ImplRegion* pImplRegion = pRegion->ImplGetImplRegion();
327 : :
328 : : if ( aImplNullRegion.mnRefCount )
329 : : return "Null-Region-RefCount modified";
330 : : if ( aImplNullRegion.mnRectCount )
331 : : return "Null-Region-RectCount modified";
332 : : if ( aImplNullRegion.mpPolyPoly )
333 : : return "Null-Region-PolyPoly modified";
334 : : if ( aImplEmptyRegion.mnRefCount )
335 : : return "Emptry-Region-RefCount modified";
336 : : if ( aImplEmptyRegion.mnRectCount )
337 : : return "Emptry-Region-RectCount modified";
338 : : if ( aImplEmptyRegion.mpPolyPoly )
339 : : return "Emptry-Region-PolyPoly modified";
340 : :
341 : : if ( (pImplRegion != &aImplEmptyRegion) && (pImplRegion != &aImplNullRegion) )
342 : : {
343 : : sal_uLong nCount = 0;
344 : : const ImplRegionBand* pBand = pImplRegion->ImplGetFirstRegionBand();
345 : : while ( pBand )
346 : : {
347 : : if ( pBand->mnYBottom < pBand->mnYTop )
348 : : return "YBottom < YTop";
349 : : if ( pBand->mpNextBand )
350 : : {
351 : : if ( pBand->mnYBottom >= pBand->mpNextBand->mnYTop )
352 : : return "overlapping bands in region";
353 : : }
354 : : if ( pBand->mbTouched > 1 )
355 : : return "Band-mbTouched overwrite";
356 : :
357 : : ImplRegionBandSep* pSep = pBand->mpFirstSep;
358 : : while ( pSep )
359 : : {
360 : : if ( pSep->mnXRight < pSep->mnXLeft )
361 : : return "XLeft < XRight";
362 : : if ( pSep->mpNextSep )
363 : : {
364 : : if ( pSep->mnXRight >= pSep->mpNextSep->mnXLeft )
365 : : return "overlapping separations in region";
366 : : }
367 : : if ( pSep->mbRemoved > 1 )
368 : : return "Sep-mbRemoved overwrite";
369 : :
370 : : nCount++;
371 : : pSep = pSep->mpNextSep;
372 : : }
373 : :
374 : : pBand = pBand->mpNextBand;
375 : : }
376 : :
377 : : if ( pImplRegion->mnRectCount != nCount )
378 : : return "mnRetCount is not valid";
379 : : }
380 : :
381 : : return NULL;
382 : : }
383 : :
384 : : #endif
385 : :
386 : : // =======================================================================
387 : :
388 : 3533083 : inline void Region::ImplPolyPolyRegionToBandRegion()
389 : : {
390 [ + - ][ + + ]: 3533083 : if( mpImplRegion->mpPolyPoly || mpImplRegion->mpB2DPolyPoly )
391 : 26 : ImplPolyPolyRegionToBandRegionFunc();
392 : 3533083 : }
393 : :
394 : : // =======================================================================
395 : :
396 : 1793949 : ImplRegionBase::ImplRegionBase( int nRefCount )
397 : : : mnRefCount( nRefCount )
398 : : , mnRectCount( 0 )
399 : : , mpPolyPoly( NULL )
400 : 1793949 : , mpB2DPolyPoly( NULL )
401 : 1793949 : {}
402 : :
403 : : // ------------------------------------------------------------------------
404 : :
405 : 802882 : ImplRegion::ImplRegion()
406 : : {
407 : 802882 : mpFirstBand = NULL;
408 : 802882 : mpLastCheckedBand = NULL;
409 : 802882 : }
410 : :
411 : : // ------------------------------------------------------------------------
412 : :
413 : 22 : ImplRegion::ImplRegion( const PolyPolygon& rPolyPoly )
414 : : {
415 : 22 : mpFirstBand = NULL;
416 : 22 : mpLastCheckedBand = NULL;
417 [ + - ][ + - ]: 22 : mpPolyPoly = new PolyPolygon( rPolyPoly );
418 : 22 : }
419 : :
420 : : // ------------------------------------------------------------------------
421 : :
422 : 43 : ImplRegion::ImplRegion( const basegfx::B2DPolyPolygon& rPolyPoly )
423 : : {
424 : 43 : mpFirstBand = NULL;
425 : 43 : mpLastCheckedBand = NULL;
426 [ + - ][ + - ]: 43 : mpB2DPolyPoly = new basegfx::B2DPolyPolygon( rPolyPoly );
427 : 43 : }
428 : :
429 : : // -----------------------------------------------------------------------
430 : :
431 : 990308 : ImplRegion::ImplRegion( const ImplRegion& rImplRegion )
432 : 990308 : : ImplRegionBase()
433 : : {
434 : 990308 : mpFirstBand = NULL;
435 : 990308 : mpLastCheckedBand = NULL;
436 : 990308 : mnRectCount = rImplRegion.mnRectCount;
437 : :
438 [ + + ]: 990308 : if ( rImplRegion.mpPolyPoly )
439 [ + - ][ + - ]: 11 : mpPolyPoly = new PolyPolygon( *rImplRegion.mpPolyPoly );
440 [ + + ]: 990297 : else if( rImplRegion.mpB2DPolyPoly )
441 [ + - ][ + - ]: 16 : mpB2DPolyPoly = new basegfx::B2DPolyPolygon( *rImplRegion.mpB2DPolyPoly );
442 : :
443 : : // insert band(s) into the list
444 : : ImplRegionBand* pNewBand;
445 : 990308 : ImplRegionBand* pPrevBand = 0;
446 : 990308 : ImplRegionBand* pBand = rImplRegion.mpFirstBand;
447 [ + + ]: 2000319 : while ( pBand )
448 : : {
449 [ + - ][ + - ]: 1010011 : pNewBand = new ImplRegionBand( *pBand );
450 : :
451 : : // first element? -> set as first into the list
452 [ + + ]: 1010011 : if ( pBand == rImplRegion.mpFirstBand )
453 : 990281 : mpFirstBand = pNewBand;
454 : : else
455 : 19730 : pPrevBand->mpNextBand = pNewBand;
456 : :
457 : 1010011 : pPrevBand = pNewBand;
458 : 1010011 : pBand = pBand->mpNextBand;
459 : : }
460 : 990308 : }
461 : :
462 : : // -----------------------------------------------------------------------
463 : :
464 : 1788841 : ImplRegion::~ImplRegion()
465 : : {
466 : : DBG_ASSERT( (this != &aImplEmptyRegion) && (this != &aImplNullRegion),
467 : : "ImplRegion::~ImplRegion() - Empty oder NULL-Region" );
468 : :
469 : 1788841 : ImplRegionBand* pBand = mpFirstBand;
470 [ + + ]: 3443423 : while ( pBand )
471 : : {
472 : 1654582 : ImplRegionBand* pTempBand = pBand->mpNextBand;
473 [ + - ][ + - ]: 1654582 : delete pBand;
474 : 1654582 : pBand = pTempBand;
475 : : }
476 [ - + ]: 3577682 : }
477 : :
478 : : // -----------------------------------------------------------------------
479 : :
480 : 1789535 : ImplRegionBase::~ImplRegionBase()
481 : : {
482 [ + + ]: 1789535 : delete mpPolyPoly;
483 [ + + ]: 1789535 : delete mpB2DPolyPoly;
484 [ - + ]: 1789535 : }
485 : :
486 : : // -----------------------------------------------------------------------
487 : : //
488 : : // create complete range of bands in single steps
489 : :
490 : 0 : void ImplRegion::CreateBandRange( long nYTop, long nYBottom )
491 : : {
492 : : // add top band
493 [ # # ]: 0 : mpFirstBand = new ImplRegionBand( nYTop-1, nYTop-1 );
494 : :
495 : : // begin first search from the first element
496 : 0 : mpLastCheckedBand = mpFirstBand;
497 : :
498 : 0 : ImplRegionBand* pBand = mpFirstBand;
499 [ # # ]: 0 : for ( int i = nYTop; i <= nYBottom+1; i++ )
500 : : {
501 : : // create new band
502 [ # # ]: 0 : ImplRegionBand* pNewBand = new ImplRegionBand( i, i );
503 : 0 : pBand->mpNextBand = pNewBand;
504 [ # # ]: 0 : if ( pBand != mpFirstBand )
505 : 0 : pNewBand->mpPrevBand = pBand;
506 : :
507 : 0 : pBand = pBand->mpNextBand;
508 : : }
509 : 0 : }
510 : :
511 : : // -----------------------------------------------------------------------
512 : :
513 : 0 : sal_Bool ImplRegion::InsertLine( const Point& rStartPt, const Point& rEndPt,
514 : : long nLineId )
515 : : {
516 : : long nX, nY;
517 : :
518 : : // lines consisting of a single point do not interest here
519 [ # # ]: 0 : if ( rStartPt == rEndPt )
520 : 0 : return sal_True;
521 : :
522 [ # # ]: 0 : LineType eLineType = (rStartPt.Y() > rEndPt.Y()) ? LINE_DESCENDING : LINE_ASCENDING;
523 [ # # ]: 0 : if ( rStartPt.X() == rEndPt.X() )
524 : : {
525 : : // vertical line
526 : 0 : const long nEndY = rEndPt.Y();
527 : :
528 : 0 : nX = rStartPt.X();
529 : 0 : nY = rStartPt.Y();
530 : :
531 [ # # ]: 0 : if( nEndY > nY )
532 : : {
533 [ # # ]: 0 : for ( ; nY <= nEndY; nY++ )
534 : : {
535 : 0 : Point aNewPoint( nX, nY );
536 : : InsertPoint( aNewPoint, nLineId,
537 : 0 : (aNewPoint == rEndPt) || (aNewPoint == rStartPt),
538 [ # # ]: 0 : eLineType );
[ # # # # ]
539 : : }
540 : : }
541 : : else
542 : : {
543 [ # # ]: 0 : for ( ; nY >= nEndY; nY-- )
544 : : {
545 : 0 : Point aNewPoint( nX, nY );
546 : : InsertPoint( aNewPoint, nLineId,
547 : 0 : (aNewPoint == rEndPt) || (aNewPoint == rStartPt),
548 [ # # ]: 0 : eLineType );
[ # # # # ]
549 : : }
550 : : }
551 : : }
552 [ # # ]: 0 : else if ( rStartPt.Y() != rEndPt.Y() )
553 : : {
554 : 0 : const long nDX = labs( rEndPt.X() - rStartPt.X() );
555 : 0 : const long nDY = labs( rEndPt.Y() - rStartPt.Y() );
556 : 0 : const long nStartX = rStartPt.X();
557 : 0 : const long nStartY = rStartPt.Y();
558 : 0 : const long nEndX = rEndPt.X();
559 : 0 : const long nEndY = rEndPt.Y();
560 [ # # ]: 0 : const long nXInc = ( nStartX < nEndX ) ? 1L : -1L;
561 [ # # ]: 0 : const long nYInc = ( nStartY < nEndY ) ? 1L : -1L;
562 : :
563 [ # # ]: 0 : if ( nDX >= nDY )
564 : : {
565 : 0 : const long nDYX = ( nDY - nDX ) << 1;
566 : 0 : const long nDY2 = nDY << 1;
567 : 0 : long nD = nDY2 - nDX;
568 : :
569 [ # # ]: 0 : for ( nX = nStartX, nY = nStartY; nX != nEndX; nX += nXInc )
570 : : {
571 [ # # ]: 0 : InsertPoint( Point( nX, nY ), nLineId, nStartX == nX, eLineType );
572 : :
573 [ # # ]: 0 : if ( nD < 0L )
574 : 0 : nD += nDY2;
575 : : else
576 : 0 : nD += nDYX, nY += nYInc;
577 : : }
578 : : }
579 : : else
580 : : {
581 : 0 : const long nDYX = ( nDX - nDY ) << 1;
582 : 0 : const long nDY2 = nDX << 1;
583 : 0 : long nD = nDY2 - nDY;
584 : :
585 [ # # ]: 0 : for ( nX = nStartX, nY = nStartY; nY != nEndY; nY += nYInc )
586 : : {
587 [ # # ]: 0 : InsertPoint( Point( nX, nY ), nLineId, nStartY == nY, eLineType );
588 : :
589 [ # # ]: 0 : if ( nD < 0L )
590 : 0 : nD += nDY2;
591 : : else
592 : 0 : nD += nDYX, nX += nXInc;
593 : : }
594 : : }
595 : :
596 : : // last point
597 [ # # ]: 0 : InsertPoint( Point( nEndX, nEndY ), nLineId, sal_True, eLineType );
598 : : }
599 : :
600 : 0 : return sal_True;
601 : : }
602 : :
603 : : // -----------------------------------------------------------------------
604 : : //
605 : : // search for appropriate place for the new point
606 : :
607 : 0 : sal_Bool ImplRegion::InsertPoint( const Point &rPoint, long nLineID,
608 : : sal_Bool bEndPoint, LineType eLineType )
609 : : {
610 : : DBG_ASSERT( mpFirstBand != NULL, "ImplRegion::InsertPoint - no bands available!" );
611 : :
612 [ # # ]: 0 : if ( rPoint.Y() == mpLastCheckedBand->mnYTop )
613 : : {
614 : 0 : mpLastCheckedBand->InsertPoint( rPoint.X(), nLineID, bEndPoint, eLineType );
615 : 0 : return sal_True;
616 : : }
617 : :
618 [ # # ]: 0 : if ( rPoint.Y() > mpLastCheckedBand->mnYTop )
619 : : {
620 : : // Search ascending
621 [ # # ]: 0 : while ( mpLastCheckedBand )
622 : : {
623 : : // Insert point if possible
624 [ # # ]: 0 : if ( rPoint.Y() == mpLastCheckedBand->mnYTop )
625 : : {
626 : 0 : mpLastCheckedBand->InsertPoint( rPoint.X(), nLineID, bEndPoint, eLineType );
627 : 0 : return sal_True;
628 : : }
629 : :
630 : 0 : mpLastCheckedBand = mpLastCheckedBand->mpNextBand;
631 : : }
632 : :
633 : : OSL_FAIL( "ImplRegion::InsertPoint reached the end of the list!" );
634 : : }
635 : : else
636 : : {
637 : : // Search descending
638 [ # # ]: 0 : while ( mpLastCheckedBand )
639 : : {
640 : : // Insert point if possible
641 [ # # ]: 0 : if ( rPoint.Y() == mpLastCheckedBand->mnYTop )
642 : : {
643 : 0 : mpLastCheckedBand->InsertPoint( rPoint.X(), nLineID, bEndPoint, eLineType );
644 : 0 : return sal_True;
645 : : }
646 : :
647 : 0 : mpLastCheckedBand = mpLastCheckedBand->mpPrevBand;
648 : : }
649 : :
650 : : OSL_FAIL( "ImplRegion::InsertPoint reached the beginning of the list!" );
651 : : }
652 : :
653 : : OSL_FAIL( "ImplRegion::InsertPoint point not inserted!" );
654 : :
655 : : // reinitialize pointer (should never be reached!)
656 : 0 : mpLastCheckedBand = mpFirstBand;
657 : :
658 : 0 : return sal_False;
659 : : }
660 : :
661 : : // -----------------------------------------------------------------------
662 : : //
663 : : // search for appropriate places for the new bands
664 : :
665 : 1132292 : void ImplRegion::InsertBands( long nTop, long nBottom )
666 : : {
667 : : // region empty? -> set rectagle as first entry!
668 [ + + ]: 1132292 : if ( !mpFirstBand )
669 : : {
670 : : // add band with boundaries of the rectangle
671 [ + - ]: 83872 : mpFirstBand = new ImplRegionBand( nTop, nBottom );
672 : 1132292 : return;
673 : : }
674 : :
675 : : // find/insert bands for the boundaries of the rectangle
676 : 1048420 : sal_Bool bTopBoundaryInserted = sal_False;
677 : 1048420 : sal_Bool bTop2BoundaryInserted = sal_False;
678 : 1048420 : sal_Bool bBottomBoundaryInserted = sal_False;
679 : :
680 : : // special case: top boundary is above the first band
681 : : ImplRegionBand* pNewBand;
682 [ + + ]: 1048420 : if ( nTop < mpFirstBand->mnYTop )
683 : : {
684 : : // create new band above the first in the list
685 [ + - ]: 365973 : pNewBand = new ImplRegionBand( nTop, mpFirstBand->mnYTop );
686 [ + + ]: 365973 : if ( nBottom < mpFirstBand->mnYTop )
687 : 16614 : pNewBand->mnYBottom = nBottom;
688 : :
689 : : // insert band into the list
690 : 365973 : pNewBand->mpNextBand = mpFirstBand;
691 : 365973 : mpFirstBand = pNewBand;
692 : :
693 : 365973 : bTopBoundaryInserted = sal_True;
694 : : }
695 : :
696 : : // insert band(s) into the list
697 : 1048420 : ImplRegionBand* pBand = mpFirstBand;
698 [ + + ]: 3837344 : while ( pBand )
699 : : {
700 : : // Insert Bands if possible
701 [ + + ]: 3479911 : if ( !bTopBoundaryInserted )
702 : 1449172 : bTopBoundaryInserted = InsertSingleBand( pBand, nTop - 1 );
703 : :
704 [ + + ]: 3479911 : if ( !bTop2BoundaryInserted )
705 : 1655234 : bTop2BoundaryInserted = InsertSingleBand( pBand, nTop );
706 : :
707 [ + + ][ + + ]: 3479911 : if ( !bBottomBoundaryInserted && (nTop != nBottom) )
708 : 3120943 : bBottomBoundaryInserted = InsertSingleBand( pBand, nBottom );
709 : :
710 : : // both boundaries inserted? -> nothing more to do
711 [ + + ][ + + ]: 3479911 : if ( bTopBoundaryInserted && bTop2BoundaryInserted && bBottomBoundaryInserted )
[ + + ]
712 : 690987 : break;
713 : :
714 : : // insert bands between two bands if neccessary
715 [ + + ]: 2788924 : if ( pBand->mpNextBand )
716 : : {
717 [ + + ]: 2431491 : if ( (pBand->mnYBottom + 1) < pBand->mpNextBand->mnYTop )
718 : : {
719 : : // copy band with list and set new boundary
720 : : pNewBand = new ImplRegionBand( pBand->mnYBottom+1,
721 [ + - ]: 29506 : pBand->mpNextBand->mnYTop-1 );
722 : :
723 : : // insert band into the list
724 : 29506 : pNewBand->mpNextBand = pBand->mpNextBand;
725 : 29506 : pBand->mpNextBand = pNewBand;
726 : : }
727 : : }
728 : :
729 : 2788924 : pBand = pBand->mpNextBand;
730 : : }
731 : : }
732 : :
733 : : // -----------------------------------------------------------------------
734 : : //
735 : : // create new band and insert it into the list
736 : :
737 : 6225349 : sal_Bool ImplRegion::InsertSingleBand( ImplRegionBand* pBand,
738 : : long nYBandPosition )
739 : : {
740 : : // boundary already included in band with height 1? -> nothing to do!
741 [ + + ][ + + ]: 6225349 : if ( (pBand->mnYTop == pBand->mnYBottom) &&
742 : : (nYBandPosition == pBand->mnYTop) )
743 : 8186 : return sal_True;
744 : :
745 : : // insert single height band on top?
746 : : ImplRegionBand* pNewBand;
747 [ + + ]: 6217163 : if ( nYBandPosition == pBand->mnYTop )
748 : : {
749 : : // copy band with list and set new boundary
750 [ + - ]: 930973 : pNewBand = new ImplRegionBand( *pBand );
751 : 930973 : pNewBand->mnYTop = nYBandPosition+1;
752 : :
753 : : // insert band into the list
754 : 930973 : pNewBand->mpNextBand = pBand->mpNextBand;
755 : 930973 : pBand->mnYBottom = nYBandPosition;
756 : 930973 : pBand->mpNextBand = pNewBand;
757 : :
758 : 930973 : return sal_True;
759 : : }
760 : :
761 : : // top of new rectangle within the current band? -> insert new band and copy data
762 [ + + ][ + + ]: 5286190 : if ( (nYBandPosition > pBand->mnYTop) &&
763 : : (nYBandPosition < pBand->mnYBottom) )
764 : : {
765 : : // copy band with list and set new boundary
766 [ + - ]: 444469 : pNewBand = new ImplRegionBand( *pBand );
767 : 444469 : pNewBand->mnYTop = nYBandPosition;
768 : :
769 : : // insert band into the list
770 : 444469 : pNewBand->mpNextBand = pBand->mpNextBand;
771 : 444469 : pBand->mnYBottom = nYBandPosition;
772 : 444469 : pBand->mpNextBand = pNewBand;
773 : :
774 : : // copy band with list and set new boundary
775 [ + - ]: 444469 : pNewBand = new ImplRegionBand( *pBand );
776 : 444469 : pNewBand->mnYTop = nYBandPosition;
777 : :
778 : : // insert band into the list
779 : 444469 : pBand->mpNextBand->mnYTop = nYBandPosition+1;
780 : :
781 : 444469 : pNewBand->mpNextBand = pBand->mpNextBand;
782 : 444469 : pBand->mnYBottom = nYBandPosition - 1;
783 : 444469 : pBand->mpNextBand = pNewBand;
784 : :
785 : 444469 : return sal_True;
786 : : }
787 : :
788 : : // create new band behind the current in the list
789 [ + + ]: 4841721 : if ( !pBand->mpNextBand )
790 : : {
791 [ + + ]: 2035545 : if ( nYBandPosition == pBand->mnYBottom )
792 : : {
793 : : // copy band with list and set new boundary
794 [ + - ]: 319534 : pNewBand = new ImplRegionBand( *pBand );
795 : 319534 : pNewBand->mnYTop = pBand->mnYBottom;
796 : 319534 : pNewBand->mnYBottom = nYBandPosition;
797 : :
798 : 319534 : pBand->mnYBottom = nYBandPosition-1;
799 : :
800 : : // append band to the list
801 : 319534 : pBand->mpNextBand = pNewBand;
802 : 319534 : return sal_True;
803 : : }
804 : :
805 [ + + ]: 1716011 : if ( nYBandPosition > pBand->mnYBottom )
806 : : {
807 : : // create new band
808 [ + - ]: 707663 : pNewBand = new ImplRegionBand( pBand->mnYBottom + 1, nYBandPosition );
809 : :
810 : : // append band to the list
811 : 707663 : pBand->mpNextBand = pNewBand;
812 : 707663 : return sal_True;
813 : : }
814 : : }
815 : :
816 : 6225349 : return sal_False;
817 : : }
818 : :
819 : : // ------------------------------------------------------------------------
820 : :
821 : 34 : void ImplRegion::InsertBand (ImplRegionBand* pPreviousBand, ImplRegionBand* pBandToInsert)
822 : : {
823 : : OSL_ASSERT(pBandToInsert!=NULL);
824 : :
825 [ + + ]: 34 : if (pPreviousBand == NULL)
826 : : {
827 : : // Insert band before all others.
828 [ - + ]: 26 : if (mpFirstBand != NULL)
829 : 0 : mpFirstBand->mpPrevBand = pBandToInsert;
830 : 26 : pBandToInsert->mpNextBand = mpFirstBand;
831 : 26 : mpFirstBand = pBandToInsert;
832 : : }
833 : : else
834 : : {
835 : : // Insert band directly after pPreviousBand.
836 : 8 : pBandToInsert->mpNextBand = pPreviousBand->mpNextBand;
837 : 8 : pPreviousBand->mpNextBand = pBandToInsert;
838 : 8 : pBandToInsert->mpPrevBand = pPreviousBand;
839 : : }
840 : 34 : }
841 : :
842 : : // ------------------------------------------------------------------------
843 : :
844 : 165698 : void ImplRegion::Union( long nLeft, long nTop, long nRight, long nBottom )
845 : : {
846 : : DBG_ASSERT( nLeft <= nRight, "ImplRegion::Union() - nLeft > nRight" );
847 : : DBG_ASSERT( nTop <= nBottom, "ImplRegion::Union() - nTop > nBottom" );
848 : :
849 : : // process union
850 : 165698 : ImplRegionBand* pBand = mpFirstBand;
851 [ + + ]: 547106 : while ( pBand )
852 : : {
853 [ + + ]: 397751 : if ( pBand->mnYTop >= nTop )
854 : : {
855 [ + + ]: 336088 : if ( pBand->mnYBottom <= nBottom )
856 : 319745 : pBand->Union( nLeft, nRight );
857 : : else
858 : : {
859 : : #ifdef DBG_UTIL
860 : : long nCurY = pBand->mnYBottom;
861 : : pBand = pBand->mpNextBand;
862 : : while ( pBand )
863 : : {
864 : : if ( (pBand->mnYTop < nCurY) || (pBand->mnYBottom < nCurY) )
865 : : {
866 : : OSL_FAIL( "ImplRegion::Union() - Bands not sorted!" );
867 : : }
868 : : pBand = pBand->mpNextBand;
869 : : }
870 : : #endif
871 : 16343 : break;
872 : : }
873 : : }
874 : :
875 : 381408 : pBand = pBand->mpNextBand;
876 : : }
877 : 165698 : }
878 : :
879 : : // -----------------------------------------------------------------------
880 : :
881 : 1324487 : void ImplRegion::Exclude( long nLeft, long nTop, long nRight, long nBottom )
882 : : {
883 : : DBG_ASSERT( nLeft <= nRight, "ImplRegion::Exclude() - nLeft > nRight" );
884 : : DBG_ASSERT( nTop <= nBottom, "ImplRegion::Exclude() - nTop > nBottom" );
885 : :
886 : : // process exclude
887 : 1324487 : ImplRegionBand* pBand = mpFirstBand;
888 [ + + ]: 6525849 : while ( pBand )
889 : : {
890 [ + + ]: 5641357 : if ( pBand->mnYTop >= nTop )
891 : : {
892 [ + + ]: 4808464 : if ( pBand->mnYBottom <= nBottom )
893 : 4368469 : pBand->Exclude( nLeft, nRight );
894 : : else
895 : : {
896 : : #ifdef DBG_UTIL
897 : : long nCurY = pBand->mnYBottom;
898 : : pBand = pBand->mpNextBand;
899 : : while ( pBand )
900 : : {
901 : : if ( (pBand->mnYTop < nCurY) || (pBand->mnYBottom < nCurY) )
902 : : {
903 : : OSL_FAIL( "ImplRegion::Exclude() - Bands not sorted!" );
904 : : }
905 : : pBand = pBand->mpNextBand;
906 : : }
907 : : #endif
908 : 439995 : break;
909 : : }
910 : : }
911 : :
912 : 5201362 : pBand = pBand->mpNextBand;
913 : : }
914 : 1324487 : }
915 : :
916 : : // -----------------------------------------------------------------------
917 : :
918 : 0 : void ImplRegion::XOr( long nLeft, long nTop, long nRight, long nBottom )
919 : : {
920 : : DBG_ASSERT( nLeft <= nRight, "ImplRegion::Exclude() - nLeft > nRight" );
921 : : DBG_ASSERT( nTop <= nBottom, "ImplRegion::Exclude() - nTop > nBottom" );
922 : :
923 : : // process xor
924 : 0 : ImplRegionBand* pBand = mpFirstBand;
925 [ # # ]: 0 : while ( pBand )
926 : : {
927 [ # # ]: 0 : if ( pBand->mnYTop >= nTop )
928 : : {
929 [ # # ]: 0 : if ( pBand->mnYBottom <= nBottom )
930 : 0 : pBand->XOr( nLeft, nRight );
931 : : else
932 : : {
933 : : #ifdef DBG_UTIL
934 : : long nCurY = pBand->mnYBottom;
935 : : pBand = pBand->mpNextBand;
936 : : while ( pBand )
937 : : {
938 : : if ( (pBand->mnYTop < nCurY) || (pBand->mnYBottom < nCurY) )
939 : : {
940 : : OSL_FAIL( "ImplRegion::XOr() - Bands not sorted!" );
941 : : }
942 : : pBand = pBand->mpNextBand;
943 : : }
944 : : #endif
945 : 0 : break;
946 : : }
947 : : }
948 : :
949 : 0 : pBand = pBand->mpNextBand;
950 : : }
951 : 0 : }
952 : :
953 : : // -----------------------------------------------------------------------
954 : : //
955 : : // remove empty bands
956 : :
957 : 1128458 : sal_Bool ImplRegion::OptimizeBandList()
958 : : {
959 : : DBG_ASSERT( (this != &aImplNullRegion) && (this != &aImplEmptyRegion),
960 : : "ImplRegion::OptimizeBandList() - Empty oder NULL-Region" );
961 : :
962 : 1128458 : mnRectCount = 0;
963 : :
964 : 1128458 : ImplRegionBand* pPrevBand = 0;
965 : 1128458 : ImplRegionBand* pBand = mpFirstBand;
966 [ + + ]: 4765334 : while ( pBand )
967 : : {
968 : : const sal_Bool bBTEqual = pBand->mpNextBand &&
969 [ + + ][ + + ]: 3636876 : (pBand->mnYBottom == pBand->mpNextBand->mnYTop);
970 : :
971 : : // no separation? -> remove!
972 [ + + ][ + + ]: 3636876 : if ( pBand->IsEmpty() || (bBTEqual && (pBand->mnYBottom == pBand->mnYTop)) )
[ - + ][ + + ]
973 : : {
974 : : // save pointer
975 : 1538552 : ImplRegionBand* pOldBand = pBand;
976 : :
977 : : // previous element of the list
978 [ + + ]: 1538552 : if ( pBand == mpFirstBand )
979 : 1128975 : mpFirstBand = pBand->mpNextBand;
980 : : else
981 : 409577 : pPrevBand->mpNextBand = pBand->mpNextBand;
982 : :
983 : 1538552 : pBand = pBand->mpNextBand;
984 [ + - ]: 1538552 : delete pOldBand;
985 : : }
986 : : else
987 : : {
988 : : // fixup
989 [ + + ]: 2098324 : if ( bBTEqual )
990 : 3721 : pBand->mnYBottom = pBand->mpNextBand->mnYTop-1;
991 : :
992 : : // this and next band with equal separations? -> combine!
993 [ + + ]: 3583017 : if ( pBand->mpNextBand &&
[ + + + + ]
[ + + ]
994 : : ((pBand->mnYBottom+1) == pBand->mpNextBand->mnYTop) &&
995 : 1484693 : (*pBand == *pBand->mpNextBand) )
996 : : {
997 : : // expand current height
998 : 1047207 : pBand->mnYBottom = pBand->mpNextBand->mnYBottom;
999 : :
1000 : : // remove next band from list
1001 : 1047207 : ImplRegionBand* pDeletedBand = pBand->mpNextBand;
1002 : 1047207 : pBand->mpNextBand = pDeletedBand->mpNextBand;
1003 [ + - ]: 1047207 : delete pDeletedBand;
1004 : :
1005 : : // check band again!
1006 : : }
1007 : : else
1008 : : {
1009 : : // count rectangles within band
1010 : 1051117 : ImplRegionBandSep* pSep = pBand->mpFirstSep;
1011 [ + + ]: 2179301 : while ( pSep )
1012 : : {
1013 : 1128184 : mnRectCount++;
1014 : 1128184 : pSep = pSep->mpNextSep;
1015 : : }
1016 : :
1017 : 1051117 : pPrevBand = pBand;
1018 : 1051117 : pBand = pBand->mpNextBand;
1019 : : }
1020 : : }
1021 : : }
1022 : :
1023 : : #ifdef DBG_UTIL
1024 : : pBand = mpFirstBand;
1025 : : while ( pBand )
1026 : : {
1027 : : DBG_ASSERT( pBand->mpFirstSep != NULL,
1028 : : "Exiting ImplRegion::OptimizeBandList(): empty band in region!" );
1029 : :
1030 : : if ( pBand->mnYBottom < pBand->mnYTop )
1031 : : OSL_FAIL( "ImplRegion::OptimizeBandList(): YBottomBoundary < YTopBoundary" );
1032 : :
1033 : : if ( pBand->mpNextBand )
1034 : : {
1035 : : if ( pBand->mnYBottom >= pBand->mpNextBand->mnYTop )
1036 : : OSL_FAIL( "ImplRegion::OptimizeBandList(): overlapping bands in region!" );
1037 : : }
1038 : :
1039 : : pBand = pBand->mpNextBand;
1040 : : }
1041 : : #endif
1042 : :
1043 : 1128458 : return (mnRectCount != 0);
1044 : : }
1045 : :
1046 : : // =======================================================================
1047 : :
1048 : 990308 : void Region::ImplCopyData()
1049 : : {
1050 : 990308 : mpImplRegion->mnRefCount--;
1051 [ + - ]: 990308 : mpImplRegion = new ImplRegion( *mpImplRegion );
1052 : 990308 : }
1053 : :
1054 : : // =======================================================================
1055 : :
1056 : 1480075 : Region::Region()
1057 : : {
1058 : : DBG_CTOR( Region, ImplDbgTestRegion );
1059 : :
1060 : 1480075 : mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
1061 : 1480075 : }
1062 : :
1063 : : // -----------------------------------------------------------------------
1064 : :
1065 : 965386 : Region::Region( RegionType eType )
1066 : : {
1067 : : DBG_CTOR( Region, ImplDbgTestRegion );
1068 : : DBG_ASSERT( (eType == REGION_NULL) || (eType == REGION_EMPTY),
1069 : : "Region( RegionType ) - RegionType != EMPTY/NULL" );
1070 : :
1071 [ + + ]: 965386 : if ( eType == REGION_NULL )
1072 : 917157 : mpImplRegion = (ImplRegion*)(&aImplNullRegion);
1073 : : else
1074 : 48229 : mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
1075 : 965386 : }
1076 : :
1077 : : // -----------------------------------------------------------------------
1078 : :
1079 : 415602 : Region::Region( const Rectangle& rRect )
1080 : : {
1081 : : DBG_CTOR( Region, ImplDbgTestRegion );
1082 : :
1083 : 415602 : ImplCreateRectRegion( rRect );
1084 : 415602 : }
1085 : :
1086 : : // -----------------------------------------------------------------------
1087 : :
1088 : 0 : Region::Region( const Polygon& rPolygon )
1089 : : {
1090 : : DBG_CTOR( Region, ImplDbgTestRegion );
1091 : : DBG_CHKOBJ( &rPolygon, Polygon, NULL );
1092 : :
1093 [ # # ]: 0 : ImplCreatePolyPolyRegion( rPolygon );
1094 : 0 : }
1095 : :
1096 : : // -----------------------------------------------------------------------
1097 : :
1098 : 111 : Region::Region( const PolyPolygon& rPolyPoly )
1099 : : {
1100 : : DBG_CTOR( Region, ImplDbgTestRegion );
1101 : : DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL );
1102 : :
1103 : 111 : ImplCreatePolyPolyRegion( rPolyPoly );
1104 : 111 : }
1105 : :
1106 : : // -----------------------------------------------------------------------
1107 : :
1108 : 43 : Region::Region( const basegfx::B2DPolyPolygon& rPolyPoly )
1109 : : {
1110 : : DBG_CTOR( Region, ImplDbgTestRegion );
1111 : : DBG_CHKOBJ( &rPolyPoly, PolyPolygon, NULL );
1112 : :
1113 [ + - ]: 43 : mpImplRegion = new ImplRegion( rPolyPoly );
1114 : 43 : }
1115 : :
1116 : : // -----------------------------------------------------------------------
1117 : :
1118 : 2085336 : Region::Region( const Region& rRegion )
1119 : : {
1120 : : DBG_CTOR( Region, ImplDbgTestRegion );
1121 : : DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
1122 : : DBG_ASSERT( rRegion.mpImplRegion->mnRefCount < 0xFFFFFFFE, "Region: RefCount overflow" );
1123 : :
1124 : : // copy pointer to instance of implementation
1125 : 2085336 : mpImplRegion = rRegion.mpImplRegion;
1126 [ + + ]: 2085336 : if ( mpImplRegion->mnRefCount )
1127 : 1711212 : mpImplRegion->mnRefCount++;
1128 : 2085336 : }
1129 : :
1130 : : // -----------------------------------------------------------------------
1131 : :
1132 : 4914236 : Region::~Region()
1133 : : {
1134 : : DBG_DTOR( Region, ImplDbgTestRegion );
1135 : :
1136 : : // statische Object haben RefCount von 0
1137 [ + + ]: 4914236 : if ( mpImplRegion->mnRefCount )
1138 : : {
1139 [ + + ]: 2994269 : if ( mpImplRegion->mnRefCount > 1 )
1140 : 1881433 : mpImplRegion->mnRefCount--;
1141 : : else
1142 [ + - ]: 1112836 : delete mpImplRegion;
1143 : : }
1144 : 4914236 : }
1145 : :
1146 : : // -----------------------------------------------------------------------
1147 : :
1148 : 583800 : void Region::ImplCreateRectRegion( const Rectangle& rRect )
1149 : : {
1150 [ + + ]: 583800 : if ( rRect.IsEmpty() )
1151 : 43772 : mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
1152 : : else
1153 : : {
1154 : : // get justified rectangle
1155 : 540028 : long nTop = Min( rRect.Top(), rRect.Bottom() );
1156 : 540028 : long nBottom = Max( rRect.Top(), rRect.Bottom() );
1157 : 540028 : long nLeft = Min( rRect.Left(), rRect.Right() );
1158 : 540028 : long nRight = Max( rRect.Left(), rRect.Right() );
1159 : :
1160 : : // create instance of implementation class
1161 [ + - ]: 540028 : mpImplRegion = new ImplRegion();
1162 : :
1163 : : // add band with boundaries of the rectangle
1164 [ + - ]: 540028 : mpImplRegion->mpFirstBand = new ImplRegionBand( nTop, nBottom );
1165 : :
1166 : : // Set left and right boundaries of the band
1167 : 540028 : mpImplRegion->mpFirstBand->Union( nLeft, nRight );
1168 : 540028 : mpImplRegion->mnRectCount = 1;
1169 : : }
1170 : 583800 : }
1171 : :
1172 : : // -----------------------------------------------------------------------
1173 : :
1174 : 111 : void Region::ImplCreatePolyPolyRegion( const PolyPolygon& rPolyPoly )
1175 : : {
1176 : 111 : const sal_uInt16 nPolyCount = rPolyPoly.Count();
1177 [ + - ]: 111 : if ( nPolyCount )
1178 : : {
1179 : : // polypolygon empty? -> empty region
1180 [ + - ]: 111 : const Rectangle aRect( rPolyPoly.GetBoundRect() );
1181 : :
1182 [ + - ][ + - ]: 111 : if ( !aRect.IsEmpty() )
1183 : : {
1184 : : // width OR height == 1 ? => Rectangular region
1185 [ + - ][ + - ]: 333 : if ( (aRect.GetWidth() == 1)
[ + - ][ + + ]
[ + + ]
1186 [ + - ]: 111 : || (aRect.GetHeight() == 1)
1187 [ + - ]: 111 : || rPolyPoly.IsRect() )
1188 : : {
1189 [ + - ]: 89 : ImplCreateRectRegion( aRect );
1190 : : }
1191 : : else
1192 [ + - ][ + - ]: 22 : mpImplRegion = new ImplRegion( rPolyPoly );
1193 : : }
1194 : : else
1195 : 111 : mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
1196 : : }
1197 : : else
1198 : 0 : mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
1199 : 111 : }
1200 : :
1201 : : // -----------------------------------------------------------------------
1202 : :
1203 : 26 : void Region::ImplPolyPolyRegionToBandRegionFunc()
1204 : : {
1205 : : // ensure to subdivide when bezier segemnts are used, it's going to
1206 : : // be expanded to rectangles
1207 [ + - ]: 26 : PolyPolygon aPolyPoly;
1208 [ + - ][ + - ]: 26 : GetPolyPolygon().AdaptiveSubdivide(aPolyPoly);
[ + - ]
1209 : :
1210 [ + + ]: 26 : if ( mpImplRegion->mnRefCount > 1 )
1211 : 10 : mpImplRegion->mnRefCount--;
1212 : : else
1213 [ + - ][ + - ]: 16 : delete mpImplRegion;
1214 : :
1215 [ + - ][ + - ]: 26 : if ( aPolyPoly.Count() )
1216 : : {
1217 : : // polypolygon empty? -> empty region
1218 [ + - ]: 26 : const Rectangle aRect( aPolyPoly.GetBoundRect() );
1219 : :
1220 [ + - ][ + - ]: 26 : if ( !aRect.IsEmpty() )
1221 : : {
1222 [ + - ][ + - ]: 26 : if (ImplIsPolygonRectilinear(aPolyPoly))
1223 : : {
1224 : : // For rectilinear polygons there is an optimized band conversion.
1225 [ + - ]: 26 : mpImplRegion = ImplRectilinearPolygonToBands(aPolyPoly);
1226 : : }
1227 : : else
1228 : : {
1229 [ # # ]: 0 : mpImplRegion = ImplGeneralPolygonToBands(aPolyPoly, aRect);
1230 : : }
1231 : :
1232 : : // Convert points into seps.
1233 : 26 : ImplRegionBand* pRegionBand = mpImplRegion->mpFirstBand;
1234 [ + + ]: 60 : while ( pRegionBand )
1235 : : {
1236 : : // generate separations from the lines and process union
1237 [ + - ]: 34 : pRegionBand->ProcessPoints();
1238 : 34 : pRegionBand = pRegionBand->mpNextBand;
1239 : : }
1240 : :
1241 : : // Optimize list of bands. Adjacent bands with identical lists
1242 : : // of seps are joined.
1243 [ + - ][ - + ]: 26 : if ( !mpImplRegion->OptimizeBandList() )
1244 : : {
1245 [ # # ][ # # ]: 0 : delete mpImplRegion;
1246 : 0 : mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
1247 : : }
1248 : : }
1249 : : else
1250 : 26 : mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
1251 : : }
1252 : : else
1253 [ + - ]: 26 : mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
1254 : 26 : }
1255 : :
1256 : : // -----------------------------------------------------------------------
1257 : :
1258 : 603771 : void Region::Move( long nHorzMove, long nVertMove )
1259 : : {
1260 : : DBG_CHKTHIS( Region, ImplDbgTestRegion );
1261 : :
1262 : : // no region data? -> nothing to do
1263 [ + + ][ + + ]: 603771 : if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
1264 : 603771 : return;
1265 : :
1266 : : // no own instance data? -> make own copy!
1267 [ + + ]: 459057 : if ( mpImplRegion->mnRefCount > 1 )
1268 : 459004 : ImplCopyData();
1269 : :
1270 [ + + ]: 459057 : if ( mpImplRegion->mpPolyPoly )
1271 : 11 : mpImplRegion->mpPolyPoly->Move( nHorzMove, nVertMove );
1272 [ + + ]: 459046 : else if( mpImplRegion->mpB2DPolyPoly )
1273 : : {
1274 [ + - ]: 16 : mpImplRegion->mpB2DPolyPoly->transform(basegfx::tools::createTranslateB2DHomMatrix(nHorzMove, nVertMove));
1275 : : }
1276 : : else
1277 : : {
1278 : 459030 : ImplRegionBand* pBand = mpImplRegion->mpFirstBand;
1279 [ + + ]: 927659 : while ( pBand )
1280 : : {
1281 : : // process the vertical move
1282 [ + + ]: 468629 : if ( nVertMove != 0)
1283 : : {
1284 : 467116 : pBand->mnYTop = pBand->mnYTop + nVertMove;
1285 : 467116 : pBand->mnYBottom = pBand->mnYBottom + nVertMove;
1286 : : }
1287 : :
1288 : : // process the horizontal move
1289 [ + + ]: 468629 : if ( nHorzMove != 0)
1290 : 89006 : pBand->MoveX( nHorzMove );
1291 : :
1292 : 468629 : pBand = pBand->mpNextBand;
1293 : : }
1294 : : }
1295 : : }
1296 : :
1297 : : // -----------------------------------------------------------------------
1298 : :
1299 : 0 : void Region::Scale( double fScaleX, double fScaleY )
1300 : : {
1301 : : DBG_CHKTHIS( Region, ImplDbgTestRegion );
1302 : :
1303 : : // no region data? -> nothing to do
1304 [ # # ][ # # ]: 0 : if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
1305 : 0 : return;
1306 : :
1307 : : // no own instance data? -> make own copy!
1308 [ # # ]: 0 : if ( mpImplRegion->mnRefCount > 1 )
1309 : 0 : ImplCopyData();
1310 : :
1311 [ # # ]: 0 : if ( mpImplRegion->mpPolyPoly )
1312 : 0 : mpImplRegion->mpPolyPoly->Scale( fScaleX, fScaleY );
1313 [ # # ]: 0 : else if( mpImplRegion->mpB2DPolyPoly )
1314 : : {
1315 [ # # ]: 0 : mpImplRegion->mpB2DPolyPoly->transform(basegfx::tools::createScaleB2DHomMatrix(fScaleX, fScaleY));
1316 : : }
1317 : : else
1318 : : {
1319 : 0 : ImplRegionBand* pBand = mpImplRegion->mpFirstBand;
1320 [ # # ]: 0 : while ( pBand )
1321 : : {
1322 : : // process the vertical move
1323 [ # # ]: 0 : if ( fScaleY != 0.0 )
1324 : : {
1325 : 0 : pBand->mnYTop = FRound( pBand->mnYTop * fScaleY );
1326 : 0 : pBand->mnYBottom = FRound( pBand->mnYBottom * fScaleY );
1327 : : }
1328 : :
1329 : : // process the horizontal move
1330 [ # # ]: 0 : if ( fScaleX != 0.0 )
1331 : 0 : pBand->ScaleX( fScaleX );
1332 : :
1333 : 0 : pBand = pBand->mpNextBand;
1334 : : }
1335 : : }
1336 : : }
1337 : :
1338 : : // -----------------------------------------------------------------------
1339 : :
1340 : 5416 : void Region::Union( const Rectangle& rRect )
1341 : : {
1342 : : DBG_CHKTHIS( Region, ImplDbgTestRegion );
1343 : :
1344 : : // is rectangle empty? -> nothing to do
1345 [ + + ]: 5416 : if ( rRect.IsEmpty() )
1346 : 1456 : return;
1347 : :
1348 [ - + ]: 3960 : if( HasPolyPolygon() )
1349 : : {
1350 : : // get this B2DPolyPolygon
1351 [ # # ]: 0 : basegfx::B2DPolyPolygon aThisPolyPoly( ConvertToB2DPolyPolygon() );
1352 [ # # ][ # # ]: 0 : aThisPolyPoly = basegfx::tools::prepareForPolygonOperation( aThisPolyPoly );
[ # # ]
1353 : :
1354 [ # # ][ # # ]: 0 : if( aThisPolyPoly.count() == 0 )
1355 : : {
1356 [ # # ]: 0 : *this = rRect;
1357 : : return;
1358 : : }
1359 : :
1360 : : // get the other B2DPolyPolygon
1361 [ # # ][ # # ]: 0 : basegfx::B2DPolygon aRectPoly( basegfx::tools::createPolygonFromRect( basegfx::B2DRectangle( rRect.Left(), rRect.Top(), rRect.Right(), rRect.Bottom() ) ) );
1362 [ # # ]: 0 : basegfx::B2DPolyPolygon aOtherPolyPoly( aRectPoly );
1363 : :
1364 [ # # ]: 0 : basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationOr( aThisPolyPoly, aOtherPolyPoly );
1365 [ # # ][ # # ]: 0 : *this = Region( aClip );
[ # # ]
1366 : :
1367 [ # # ][ # # ]: 0 : return;
[ # # ][ # # ]
1368 : : }
1369 : :
1370 : 3960 : ImplPolyPolyRegionToBandRegion();
1371 : :
1372 : : // no instance data? -> create!
1373 [ - + ][ + + ]: 3960 : if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
1374 [ + - ]: 1457 : mpImplRegion = new ImplRegion();
1375 : :
1376 : : // no own instance data? -> make own copy!
1377 [ - + ]: 3960 : if ( mpImplRegion->mnRefCount > 1 )
1378 : 0 : ImplCopyData();
1379 : :
1380 : : // get justified rectangle
1381 : 3960 : long nLeft = Min( rRect.Left(), rRect.Right() );
1382 : 3960 : long nTop = Min( rRect.Top(), rRect.Bottom() );
1383 : 3960 : long nRight = Max( rRect.Left(), rRect.Right() );
1384 : 3960 : long nBottom = Max( rRect.Top(), rRect.Bottom() );
1385 : :
1386 : : // insert bands if the boundaries are not allready in the list
1387 : 3960 : mpImplRegion->InsertBands( nTop, nBottom );
1388 : :
1389 : : // process union
1390 : 3960 : mpImplRegion->Union( nLeft, nTop, nRight, nBottom );
1391 : :
1392 : : // cleanup
1393 [ - + ]: 3960 : if ( !mpImplRegion->OptimizeBandList() )
1394 : : {
1395 [ # # ]: 0 : delete mpImplRegion;
1396 : 5416 : mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
1397 : : }
1398 : : }
1399 : :
1400 : : // -----------------------------------------------------------------------
1401 : :
1402 : 362335 : void Region::Intersect( const Rectangle& rRect )
1403 : : {
1404 : : DBG_CHKTHIS( Region, ImplDbgTestRegion );
1405 : :
1406 : : // is rectangle empty? -> nothing to do
1407 [ + + ]: 362335 : if ( rRect.IsEmpty() )
1408 : : {
1409 : : // statische Object haben RefCount von 0
1410 [ + + ]: 79 : if ( mpImplRegion->mnRefCount )
1411 : : {
1412 [ + - ]: 8 : if ( mpImplRegion->mnRefCount > 1 )
1413 : 8 : mpImplRegion->mnRefCount--;
1414 : : else
1415 [ # # ]: 0 : delete mpImplRegion;
1416 : : }
1417 : 79 : mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
1418 : 79 : return;
1419 : : }
1420 : :
1421 : : // #103137# Avoid banding for special cases
1422 [ - + ]: 362256 : if ( mpImplRegion->mpPolyPoly )
1423 : : {
1424 : : // #127431# make ImplRegion unique, if not already.
1425 [ # # ]: 0 : if( mpImplRegion->mnRefCount > 1 )
1426 : : {
1427 : 0 : mpImplRegion->mnRefCount--;
1428 [ # # ]: 0 : mpImplRegion = new ImplRegion( *mpImplRegion->mpPolyPoly );
1429 : : }
1430 : :
1431 : : // use the PolyPolygon::Clip method for rectangles, this is
1432 : : // fairly simple (does not even use GPC) and saves us from
1433 : : // unnecessary banding
1434 : 0 : mpImplRegion->mpPolyPoly->Clip( rRect );
1435 : :
1436 : 0 : return;
1437 : : }
1438 [ - + ]: 362256 : else if( mpImplRegion->mpB2DPolyPoly )
1439 : : {
1440 : : // #127431# make ImplRegion unique, if not already.
1441 [ # # ]: 0 : if( mpImplRegion->mnRefCount > 1 )
1442 : : {
1443 : 0 : mpImplRegion->mnRefCount--;
1444 [ # # ]: 0 : mpImplRegion = new ImplRegion( *mpImplRegion->mpB2DPolyPoly );
1445 : : }
1446 : :
1447 : : *mpImplRegion->mpB2DPolyPoly =
1448 : : basegfx::tools::clipPolyPolygonOnRange( *mpImplRegion->mpB2DPolyPoly,
1449 : 0 : basegfx::B2DRange( rRect.Left(), rRect.Top(),
1450 : 0 : rRect.Right(), rRect.Bottom() ),
1451 [ # # ][ # # ]: 0 : true, false );
[ # # ]
1452 : 0 : return;
1453 : : }
1454 : : else
1455 : 362256 : ImplPolyPolyRegionToBandRegion();
1456 : :
1457 : : // is region empty? -> nothing to do!
1458 [ + + ]: 362256 : if ( mpImplRegion == &aImplEmptyRegion )
1459 : 35640 : return;
1460 : :
1461 : : // get justified rectangle
1462 : 326616 : long nLeft = Min( rRect.Left(), rRect.Right() );
1463 : 326616 : long nTop = Min( rRect.Top(), rRect.Bottom() );
1464 : 326616 : long nRight = Max( rRect.Left(), rRect.Right() );
1465 : 326616 : long nBottom = Max( rRect.Top(), rRect.Bottom() );
1466 : :
1467 : : // is own region NULL-region? -> copy data!
1468 [ + + ]: 326616 : if ( mpImplRegion == &aImplNullRegion )
1469 : : {
1470 : : // create instance of implementation class
1471 [ + - ]: 39507 : mpImplRegion = new ImplRegion();
1472 : :
1473 : : // add band with boundaries of the rectangle
1474 [ + - ]: 39507 : mpImplRegion->mpFirstBand = new ImplRegionBand( nTop, nBottom );
1475 : :
1476 : : // Set left and right boundaries of the band
1477 : 39507 : mpImplRegion->mpFirstBand->Union( nLeft, nRight );
1478 : 39507 : mpImplRegion->mnRectCount = 1;
1479 : :
1480 : 39507 : return;
1481 : : }
1482 : :
1483 : : // no own instance data? -> make own copy!
1484 [ + + ]: 287109 : if ( mpImplRegion->mnRefCount > 1 )
1485 : 268486 : ImplCopyData();
1486 : :
1487 : : // insert bands if the boundaries are not allready in the list
1488 : 287109 : mpImplRegion->InsertBands( nTop, nBottom );
1489 : :
1490 : : // process intersections
1491 : 287109 : ImplRegionBand* pPrevBand = 0;
1492 : 287109 : ImplRegionBand* pBand = mpImplRegion->mpFirstBand;
1493 [ + + ]: 1397884 : while ( pBand )
1494 : : {
1495 : : // band within intersection boundary? -> process. otherwise remove
1496 [ + + ][ + + ]: 1110775 : if ( (pBand->mnYTop >= nTop) &&
1497 : : (pBand->mnYBottom <= nBottom) )
1498 : : {
1499 : : // process intersection
1500 : 883989 : pBand->Intersect( nLeft, nRight );
1501 : :
1502 : 883989 : pPrevBand = pBand;
1503 : 883989 : pBand = pBand->mpNextBand;
1504 : : }
1505 : : else
1506 : : {
1507 : 226786 : ImplRegionBand* pOldBand = pBand;
1508 [ + + ]: 226786 : if ( pBand == mpImplRegion->mpFirstBand )
1509 : 222588 : mpImplRegion->mpFirstBand = pBand->mpNextBand;
1510 : : else
1511 : 4198 : pPrevBand->mpNextBand = pBand->mpNextBand;
1512 : 226786 : pBand = pBand->mpNextBand;
1513 [ + - ]: 226786 : delete pOldBand;
1514 : : }
1515 : : }
1516 : :
1517 : : // cleanup
1518 [ + + ]: 287109 : if ( !mpImplRegion->OptimizeBandList() )
1519 : : {
1520 [ + - ]: 111087 : delete mpImplRegion;
1521 : 362335 : mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
1522 : : }
1523 : : }
1524 : :
1525 : : // -----------------------------------------------------------------------
1526 : :
1527 : 101967 : void Region::Exclude( const Rectangle& rRect )
1528 : : {
1529 : : DBG_CHKTHIS( Region, ImplDbgTestRegion );
1530 : :
1531 : : // is rectangle empty? -> nothing to do
1532 [ + + ]: 101967 : if ( rRect.IsEmpty() )
1533 : 23469 : return;
1534 : :
1535 [ - + ]: 78498 : if( HasPolyPolygon() )
1536 : : {
1537 : : // get this B2DPolyPolygon
1538 [ # # ]: 0 : basegfx::B2DPolyPolygon aThisPolyPoly( ConvertToB2DPolyPolygon() );
1539 [ # # ][ # # ]: 0 : aThisPolyPoly = basegfx::tools::prepareForPolygonOperation( aThisPolyPoly );
[ # # ]
1540 : :
1541 [ # # ][ # # ]: 0 : if( aThisPolyPoly.count() == 0 )
1542 : : return;
1543 : :
1544 : : // get the other B2DPolyPolygon
1545 [ # # ][ # # ]: 0 : basegfx::B2DPolygon aRectPoly( basegfx::tools::createPolygonFromRect( basegfx::B2DRectangle( rRect.Left(), rRect.Top(), rRect.Right(), rRect.Bottom() ) ) );
1546 [ # # ]: 0 : basegfx::B2DPolyPolygon aOtherPolyPoly( aRectPoly );
1547 : :
1548 [ # # ]: 0 : basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationDiff( aThisPolyPoly, aOtherPolyPoly );
1549 [ # # ][ # # ]: 0 : *this = Region( aClip );
[ # # ]
1550 : :
1551 [ # # ][ # # ]: 0 : return;
[ # # ][ # # ]
1552 : : }
1553 : :
1554 : 78498 : ImplPolyPolyRegionToBandRegion();
1555 : :
1556 : : // no instance data? -> create!
1557 [ - + ][ + + ]: 78498 : if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
1558 : 2875 : return;
1559 : :
1560 : : // no own instance data? -> make own copy!
1561 [ + + ]: 75623 : if ( mpImplRegion->mnRefCount > 1 )
1562 : 38765 : ImplCopyData();
1563 : :
1564 : : // get justified rectangle
1565 : 75623 : long nLeft = Min( rRect.Left(), rRect.Right() );
1566 : 75623 : long nTop = Min( rRect.Top(), rRect.Bottom() );
1567 : 75623 : long nRight = Max( rRect.Left(), rRect.Right() );
1568 : 75623 : long nBottom = Max( rRect.Top(), rRect.Bottom() );
1569 : :
1570 : : // insert bands if the boundaries are not allready in the list
1571 : 75623 : mpImplRegion->InsertBands( nTop, nBottom );
1572 : :
1573 : : // process exclude
1574 : 75623 : mpImplRegion->Exclude( nLeft, nTop, nRight, nBottom );
1575 : :
1576 : : // cleanup
1577 [ + + ]: 75623 : if ( !mpImplRegion->OptimizeBandList() )
1578 : : {
1579 [ + - ]: 16132 : delete mpImplRegion;
1580 : 101967 : mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
1581 : : }
1582 : : }
1583 : :
1584 : : // -----------------------------------------------------------------------
1585 : :
1586 : 0 : void Region::XOr( const Rectangle& rRect )
1587 : : {
1588 : : DBG_CHKTHIS( Region, ImplDbgTestRegion );
1589 : :
1590 : : // is rectangle empty? -> nothing to do
1591 [ # # ]: 0 : if ( rRect.IsEmpty() )
1592 : 0 : return;
1593 : :
1594 [ # # ]: 0 : if( HasPolyPolygon() )
1595 : : {
1596 : : // get this B2DPolyPolygon
1597 [ # # ]: 0 : basegfx::B2DPolyPolygon aThisPolyPoly( ConvertToB2DPolyPolygon() );
1598 [ # # ][ # # ]: 0 : aThisPolyPoly = basegfx::tools::prepareForPolygonOperation( aThisPolyPoly );
[ # # ]
1599 : :
1600 [ # # ][ # # ]: 0 : if( aThisPolyPoly.count() == 0 )
1601 : : {
1602 [ # # ]: 0 : *this = rRect;
1603 : : return;
1604 : : }
1605 : :
1606 : : // get the other B2DPolyPolygon
1607 [ # # ][ # # ]: 0 : basegfx::B2DPolygon aRectPoly( basegfx::tools::createPolygonFromRect( basegfx::B2DRectangle( rRect.Left(), rRect.Top(), rRect.Right(), rRect.Bottom() ) ) );
1608 [ # # ]: 0 : basegfx::B2DPolyPolygon aOtherPolyPoly( aRectPoly );
1609 : :
1610 [ # # ]: 0 : basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationXor( aThisPolyPoly, aOtherPolyPoly );
1611 [ # # ][ # # ]: 0 : *this = Region( aClip );
[ # # ]
1612 : :
1613 [ # # ][ # # ]: 0 : return;
[ # # ][ # # ]
1614 : : }
1615 : :
1616 : 0 : ImplPolyPolyRegionToBandRegion();
1617 : :
1618 : : // no instance data? -> create!
1619 [ # # ][ # # ]: 0 : if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
1620 [ # # ]: 0 : mpImplRegion = new ImplRegion();
1621 : :
1622 : : // no own instance data? -> make own copy!
1623 [ # # ]: 0 : if ( mpImplRegion->mnRefCount > 1 )
1624 : 0 : ImplCopyData();
1625 : :
1626 : : // get justified rectangle
1627 : 0 : long nLeft = Min( rRect.Left(), rRect.Right() );
1628 : 0 : long nTop = Min( rRect.Top(), rRect.Bottom() );
1629 : 0 : long nRight = Max( rRect.Left(), rRect.Right() );
1630 : 0 : long nBottom = Max( rRect.Top(), rRect.Bottom() );
1631 : :
1632 : : // insert bands if the boundaries are not allready in the list
1633 : 0 : mpImplRegion->InsertBands( nTop, nBottom );
1634 : :
1635 : : // process xor
1636 : 0 : mpImplRegion->XOr( nLeft, nTop, nRight, nBottom );
1637 : :
1638 : : // cleanup
1639 [ # # ]: 0 : if ( !mpImplRegion->OptimizeBandList() )
1640 : : {
1641 [ # # ]: 0 : delete mpImplRegion;
1642 : 0 : mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
1643 : : }
1644 : : }
1645 : :
1646 : : // -----------------------------------------------------------------------
1647 : 13 : void Region::ImplUnionPolyPolygon( const Region& i_rRegion )
1648 : : {
1649 : : // get this B2DPolyPolygon
1650 [ + - ]: 13 : basegfx::B2DPolyPolygon aThisPolyPoly( ConvertToB2DPolyPolygon() );
1651 [ + - ][ + - ]: 13 : aThisPolyPoly = basegfx::tools::prepareForPolygonOperation( aThisPolyPoly );
[ + - ]
1652 : :
1653 [ + - ][ - + ]: 13 : if( aThisPolyPoly.count() == 0 )
1654 : : {
1655 [ # # ]: 0 : *this = i_rRegion;
1656 : 13 : return;
1657 : : }
1658 : :
1659 : : // get the other B2DPolyPolygon
1660 [ + - ]: 13 : basegfx::B2DPolyPolygon aOtherPolyPoly( const_cast<Region&>(i_rRegion).ConvertToB2DPolyPolygon() );
1661 [ + - ][ + - ]: 13 : aOtherPolyPoly = basegfx::tools::prepareForPolygonOperation( aOtherPolyPoly );
[ + - ]
1662 : :
1663 : :
1664 [ + - ]: 13 : basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationOr( aThisPolyPoly, aOtherPolyPoly );
1665 : :
1666 [ + - ][ + - ]: 13 : *this = Region( aClip );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1667 : : }
1668 : :
1669 : 151702 : void Region::Union( const Region& rRegion )
1670 : : {
1671 : : DBG_CHKTHIS( Region, ImplDbgTestRegion );
1672 : :
1673 [ + + ][ + + ]: 151702 : if( rRegion.HasPolyPolygon() || HasPolyPolygon() )
[ + + ]
1674 : : {
1675 : 13 : ImplUnionPolyPolygon( rRegion );
1676 : 13 : return;
1677 : : }
1678 : :
1679 : 151689 : ImplPolyPolyRegionToBandRegion();
1680 : 151689 : ((Region*)&rRegion)->ImplPolyPolyRegionToBandRegion();
1681 : :
1682 : : // is region empty or null? -> nothing to do
1683 [ - + ][ + + ]: 151689 : if ( (rRegion.mpImplRegion == &aImplEmptyRegion) || (rRegion.mpImplRegion == &aImplNullRegion) )
1684 : 2131 : return;
1685 : :
1686 : : // no instance data? -> create!
1687 [ + + ][ - + ]: 149558 : if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
1688 [ + - ]: 82415 : mpImplRegion = new ImplRegion();
1689 : :
1690 : : // no own instance data? -> make own copy!
1691 [ - + ]: 149558 : if ( mpImplRegion->mnRefCount > 1 )
1692 : 0 : ImplCopyData();
1693 : :
1694 : : // Alle Rechtecke aus der uebergebenen Region auf diese Region anwenden
1695 : 149558 : ImplRegionBand* pBand = rRegion.mpImplRegion->mpFirstBand;
1696 [ + + ]: 303877 : while ( pBand )
1697 : : {
1698 : : // insert bands if the boundaries are not allready in the list
1699 : 154319 : mpImplRegion->InsertBands( pBand->mnYTop, pBand->mnYBottom );
1700 : :
1701 : : // process all elements of the list
1702 : 154319 : ImplRegionBandSep* pSep = pBand->mpFirstSep;
1703 [ + + ]: 316057 : while ( pSep )
1704 : : {
1705 : : mpImplRegion->Union( pSep->mnXLeft, pBand->mnYTop,
1706 : 161738 : pSep->mnXRight, pBand->mnYBottom );
1707 : 161738 : pSep = pSep->mpNextSep;
1708 : : }
1709 : :
1710 : 154319 : pBand = pBand->mpNextBand;
1711 : : }
1712 : :
1713 : : // cleanup
1714 [ - + ]: 149558 : if ( !mpImplRegion->OptimizeBandList() )
1715 : : {
1716 [ # # ]: 0 : delete mpImplRegion;
1717 : 151702 : mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
1718 : : }
1719 : : }
1720 : :
1721 : : // -----------------------------------------------------------------------
1722 : 30 : void Region::ImplIntersectWithPolyPolygon( const Region& i_rRegion )
1723 : : {
1724 : : // get this B2DPolyPolygon
1725 [ + - ]: 30 : basegfx::B2DPolyPolygon aThisPolyPoly( ConvertToB2DPolyPolygon() );
1726 [ + - ][ - + ]: 30 : if( aThisPolyPoly.count() == 0 )
1727 : : {
1728 [ # # ]: 0 : *this = i_rRegion;
1729 : 30 : return;
1730 : : }
1731 : :
1732 : : // get the other B2DPolyPolygon
1733 [ + - ]: 30 : basegfx::B2DPolyPolygon aOtherPolyPoly( const_cast<Region&>(i_rRegion).ConvertToB2DPolyPolygon() );
1734 : :
1735 [ + - ]: 30 : basegfx::B2DPolyPolygon aClip = basegfx::tools::clipPolyPolygonOnPolyPolygon( aOtherPolyPoly, aThisPolyPoly, true, false );
1736 [ + - ][ + - ]: 30 : *this = Region( aClip );
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
1737 : : }
1738 : :
1739 : 1013662 : void Region::Intersect( const Region& rRegion )
1740 : : {
1741 : : DBG_CHKTHIS( Region, ImplDbgTestRegion );
1742 : :
1743 : : // same instance data? -> nothing to do!
1744 [ + + ]: 1013662 : if ( mpImplRegion == rRegion.mpImplRegion )
1745 : 4247 : return;
1746 : :
1747 [ + + ][ + + ]: 1009415 : if( rRegion.HasPolyPolygon() || HasPolyPolygon() )
[ + + ]
1748 : : {
1749 : 30 : ImplIntersectWithPolyPolygon( rRegion );
1750 : 30 : return;
1751 : : }
1752 : :
1753 : 1009385 : ImplPolyPolyRegionToBandRegion();
1754 : 1009385 : ((Region*)&rRegion)->ImplPolyPolyRegionToBandRegion();
1755 : :
1756 [ + + ]: 1009385 : if ( mpImplRegion == &aImplEmptyRegion )
1757 : 42441 : return;
1758 : :
1759 : : // is region null? -> nothing to do
1760 [ - + ]: 966944 : if ( rRegion.mpImplRegion == &aImplNullRegion )
1761 : 0 : return;
1762 : :
1763 : : // is rectangle empty? -> nothing to do
1764 [ + + ]: 966944 : if ( rRegion.mpImplRegion == &aImplEmptyRegion )
1765 : : {
1766 : : // statische Object haben RefCount von 0
1767 [ + + ]: 172528 : if ( mpImplRegion->mnRefCount )
1768 : : {
1769 [ + + ]: 154706 : if ( mpImplRegion->mnRefCount > 1 )
1770 : 148693 : mpImplRegion->mnRefCount--;
1771 : : else
1772 [ + - ]: 6013 : delete mpImplRegion;
1773 : : }
1774 : 172528 : mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
1775 : 172528 : return;
1776 : : }
1777 : :
1778 : : // is own region NULL-region? -> copy data!
1779 [ + + ]: 794416 : if ( mpImplRegion == &aImplNullRegion)
1780 : : {
1781 : 161164 : mpImplRegion = rRegion.mpImplRegion;
1782 : 161164 : rRegion.mpImplRegion->mnRefCount++;
1783 : 161164 : return;
1784 : : }
1785 : :
1786 : : // Wenn wir weniger Rechtecke haben, drehen wir den Intersect-Aufruf um
1787 [ + + ]: 633252 : if ( mpImplRegion->mnRectCount+2 < rRegion.mpImplRegion->mnRectCount )
1788 : : {
1789 [ + - ]: 25793 : Region aTempRegion = rRegion;
1790 [ + - ]: 25793 : aTempRegion.Intersect( *this );
1791 [ + - ][ + - ]: 25793 : *this = aTempRegion;
1792 : : }
1793 : : else
1794 : : {
1795 : : // no own instance data? -> make own copy!
1796 [ + + ]: 607459 : if ( mpImplRegion->mnRefCount > 1 )
1797 : 224053 : ImplCopyData();
1798 : :
1799 : : // mark all bands as untouched
1800 : 607459 : ImplRegionBand* pBand = mpImplRegion->mpFirstBand;
1801 [ + + ]: 1229820 : while ( pBand )
1802 : : {
1803 : 622361 : pBand->mbTouched = sal_False;
1804 : 622361 : pBand = pBand->mpNextBand;
1805 : : }
1806 : :
1807 : 607459 : pBand = rRegion.mpImplRegion->mpFirstBand;
1808 [ + + ]: 1217271 : while ( pBand )
1809 : : {
1810 : : // insert bands if the boundaries are not allready in the list
1811 : 609812 : mpImplRegion->InsertBands( pBand->mnYTop, pBand->mnYBottom );
1812 : :
1813 : : // process all elements of the list
1814 : 609812 : ImplRegionBandSep* pSep = pBand->mpFirstSep;
1815 [ + + ]: 1247395 : while ( pSep )
1816 : : {
1817 : : // left boundary?
1818 [ + + ]: 637583 : if ( pSep == pBand->mpFirstSep )
1819 : : {
1820 : : // process intersection and do not remove untouched bands
1821 : : mpImplRegion->Exclude( LONG_MIN+1, pBand->mnYTop,
1822 : 609812 : pSep->mnXLeft-1, pBand->mnYBottom );
1823 : : }
1824 : :
1825 : : // right boundary?
1826 [ + + ]: 637583 : if ( pSep->mpNextSep == NULL )
1827 : : {
1828 : : // process intersection and do not remove untouched bands
1829 : : mpImplRegion->Exclude( pSep->mnXRight+1, pBand->mnYTop,
1830 : 609812 : LONG_MAX-1, pBand->mnYBottom );
1831 : : }
1832 : : else
1833 : : {
1834 : : // process intersection and do not remove untouched bands
1835 : : mpImplRegion->Exclude( pSep->mnXRight+1, pBand->mnYTop,
1836 : 27771 : pSep->mpNextSep->mnXLeft-1, pBand->mnYBottom );
1837 : : }
1838 : :
1839 : 637583 : pSep = pSep->mpNextSep;
1840 : : }
1841 : :
1842 : 609812 : pBand = pBand->mpNextBand;
1843 : : }
1844 : :
1845 : : // remove all untouched bands if bands allready left
1846 : 607459 : ImplRegionBand* pPrevBand = 0;
1847 : 607459 : pBand = mpImplRegion->mpFirstBand;
1848 [ + + ]: 3228730 : while ( pBand )
1849 : : {
1850 [ + + ]: 2621271 : if ( !pBand->mbTouched )
1851 : : {
1852 : : // save pointer
1853 : 588214 : ImplRegionBand* pOldBand = pBand;
1854 : :
1855 : : // previous element of the list
1856 [ + + ]: 588214 : if ( pBand == mpImplRegion->mpFirstBand )
1857 : 378923 : mpImplRegion->mpFirstBand = pBand->mpNextBand;
1858 : : else
1859 : 209291 : pPrevBand->mpNextBand = pBand->mpNextBand;
1860 : :
1861 : 588214 : pBand = pBand->mpNextBand;
1862 [ + - ]: 588214 : delete pOldBand;
1863 : : }
1864 : : else
1865 : : {
1866 : 2033057 : pPrevBand = pBand;
1867 : 2033057 : pBand = pBand->mpNextBand;
1868 : : }
1869 : : }
1870 : :
1871 : : // cleanup
1872 [ + + ]: 607459 : if ( !mpImplRegion->OptimizeBandList() )
1873 : : {
1874 [ + - ]: 41365 : delete mpImplRegion;
1875 : 1013662 : mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
1876 : : }
1877 : : }
1878 : : }
1879 : :
1880 : : // -----------------------------------------------------------------------
1881 : 0 : void Region::ImplExcludePolyPolygon( const Region& i_rRegion )
1882 : : {
1883 : : // get this B2DPolyPolygon
1884 [ # # ]: 0 : basegfx::B2DPolyPolygon aThisPolyPoly( ConvertToB2DPolyPolygon() );
1885 [ # # ][ # # ]: 0 : if( aThisPolyPoly.count() == 0 )
1886 : 0 : return;
1887 [ # # ][ # # ]: 0 : aThisPolyPoly = basegfx::tools::prepareForPolygonOperation( aThisPolyPoly );
[ # # ]
1888 : :
1889 : : // get the other B2DPolyPolygon
1890 [ # # ]: 0 : basegfx::B2DPolyPolygon aOtherPolyPoly( const_cast<Region&>(i_rRegion).ConvertToB2DPolyPolygon() );
1891 [ # # ][ # # ]: 0 : aOtherPolyPoly = basegfx::tools::prepareForPolygonOperation( aOtherPolyPoly );
[ # # ]
1892 : :
1893 [ # # ]: 0 : basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationDiff( aThisPolyPoly, aOtherPolyPoly );
1894 [ # # ][ # # ]: 0 : *this = Region( aClip );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1895 : : }
1896 : :
1897 : 3051 : void Region::Exclude( const Region& rRegion )
1898 : : {
1899 : : DBG_CHKTHIS( Region, ImplDbgTestRegion );
1900 : :
1901 [ + - ][ - + ]: 3051 : if( rRegion.HasPolyPolygon() || HasPolyPolygon() )
[ - + ]
1902 : : {
1903 : 0 : ImplExcludePolyPolygon( rRegion );
1904 : 0 : return;
1905 : : }
1906 : :
1907 : 3051 : ImplPolyPolyRegionToBandRegion();
1908 : 3051 : ((Region*)&rRegion)->ImplPolyPolyRegionToBandRegion();
1909 : :
1910 : : // is region empty or null? -> nothing to do
1911 [ - + ][ + + ]: 3051 : if ( (rRegion.mpImplRegion == &aImplEmptyRegion) || (rRegion.mpImplRegion == &aImplNullRegion) )
1912 : 1591 : return;
1913 : :
1914 : : // no instance data? -> nothing to do
1915 [ + - ][ - + ]: 1460 : if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
1916 : 0 : return;
1917 : :
1918 : : // no own instance data? -> make own copy!
1919 [ - + ]: 1460 : if ( mpImplRegion->mnRefCount > 1 )
1920 : 0 : ImplCopyData();
1921 : :
1922 : : // Alle Rechtecke aus der uebergebenen Region auf diese Region anwenden
1923 : 1460 : ImplRegionBand* pBand = rRegion.mpImplRegion->mpFirstBand;
1924 [ + + ]: 4520 : while ( pBand )
1925 : : {
1926 : : // insert bands if the boundaries are not allready in the list
1927 : 1469 : mpImplRegion->InsertBands( pBand->mnYTop, pBand->mnYBottom );
1928 : :
1929 : : // process all elements of the list
1930 : 1469 : ImplRegionBandSep* pSep = pBand->mpFirstSep;
1931 [ + + ]: 2938 : while ( pSep )
1932 : : {
1933 : : mpImplRegion->Exclude( pSep->mnXLeft, pBand->mnYTop,
1934 : 1469 : pSep->mnXRight, pBand->mnYBottom );
1935 : 1469 : pSep = pSep->mpNextSep;
1936 : : }
1937 : :
1938 : : // Wir optimieren schon in der Schleife, da wir davon
1939 : : // ausgehen, das wir insgesammt weniger Baender ueberpruefen
1940 : : // muessen
1941 [ - + ]: 1469 : if ( !mpImplRegion->OptimizeBandList() )
1942 : : {
1943 [ # # ]: 0 : delete mpImplRegion;
1944 : 0 : mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
1945 : 0 : break;
1946 : : }
1947 : :
1948 : 1469 : pBand = pBand->mpNextBand;
1949 : : }
1950 : : }
1951 : :
1952 : : // -----------------------------------------------------------------------
1953 : 0 : void Region::ImplXOrPolyPolygon( const Region& i_rRegion )
1954 : : {
1955 : : // get this B2DPolyPolygon
1956 [ # # ]: 0 : basegfx::B2DPolyPolygon aThisPolyPoly( ConvertToB2DPolyPolygon() );
1957 [ # # ][ # # ]: 0 : if( aThisPolyPoly.count() == 0 )
1958 : : {
1959 [ # # ]: 0 : *this = i_rRegion;
1960 : 0 : return;
1961 : : }
1962 [ # # ][ # # ]: 0 : aThisPolyPoly = basegfx::tools::prepareForPolygonOperation( aThisPolyPoly );
[ # # ]
1963 : :
1964 : : // get the other B2DPolyPolygon
1965 [ # # ]: 0 : basegfx::B2DPolyPolygon aOtherPolyPoly( const_cast<Region&>(i_rRegion).ConvertToB2DPolyPolygon() );
1966 [ # # ][ # # ]: 0 : aOtherPolyPoly = basegfx::tools::prepareForPolygonOperation( aOtherPolyPoly );
[ # # ]
1967 : :
1968 [ # # ]: 0 : basegfx::B2DPolyPolygon aClip = basegfx::tools::solvePolygonOperationXor( aThisPolyPoly, aOtherPolyPoly );
1969 [ # # ][ # # ]: 0 : *this = Region( aClip );
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
1970 : : }
1971 : :
1972 : 0 : void Region::XOr( const Region& rRegion )
1973 : : {
1974 : : DBG_CHKTHIS( Region, ImplDbgTestRegion );
1975 : :
1976 [ # # ][ # # ]: 0 : if( rRegion.HasPolyPolygon() || HasPolyPolygon() )
[ # # ]
1977 : : {
1978 : 0 : ImplXOrPolyPolygon( rRegion );
1979 : 0 : return;
1980 : : }
1981 : :
1982 : 0 : ImplPolyPolyRegionToBandRegion();
1983 : 0 : ((Region*)&rRegion)->ImplPolyPolyRegionToBandRegion();
1984 : :
1985 : : // is region empty or null? -> nothing to do
1986 [ # # ][ # # ]: 0 : if ( (rRegion.mpImplRegion == &aImplEmptyRegion) || (rRegion.mpImplRegion == &aImplNullRegion) )
1987 : 0 : return;
1988 : :
1989 : : // no own instance data? -> XOr = copy
1990 [ # # ][ # # ]: 0 : if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
1991 : : {
1992 : 0 : *this = rRegion;
1993 : 0 : return;
1994 : : }
1995 : :
1996 : : // no own instance data? -> make own copy!
1997 [ # # ]: 0 : if ( mpImplRegion->mnRefCount > 1 )
1998 : 0 : ImplCopyData();
1999 : :
2000 : : // Alle Rechtecke aus der uebergebenen Region auf diese Region anwenden
2001 : 0 : ImplRegionBand* pBand = rRegion.mpImplRegion->mpFirstBand;
2002 [ # # ]: 0 : while ( pBand )
2003 : : {
2004 : : // insert bands if the boundaries are not allready in the list
2005 : 0 : mpImplRegion->InsertBands( pBand->mnYTop, pBand->mnYBottom );
2006 : :
2007 : : // process all elements of the list
2008 : 0 : ImplRegionBandSep* pSep = pBand->mpFirstSep;
2009 [ # # ]: 0 : while ( pSep )
2010 : : {
2011 : : mpImplRegion->XOr( pSep->mnXLeft, pBand->mnYTop,
2012 : 0 : pSep->mnXRight, pBand->mnYBottom );
2013 : 0 : pSep = pSep->mpNextSep;
2014 : : }
2015 : :
2016 : 0 : pBand = pBand->mpNextBand;
2017 : : }
2018 : :
2019 : : // cleanup
2020 [ # # ]: 0 : if ( !mpImplRegion->OptimizeBandList() )
2021 : : {
2022 [ # # ]: 0 : delete mpImplRegion;
2023 : 0 : mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
2024 : : }
2025 : : }
2026 : :
2027 : : // -----------------------------------------------------------------------
2028 : :
2029 : 687911 : Rectangle Region::GetBoundRect() const
2030 : : {
2031 : : DBG_CHKTHIS( Region, ImplDbgTestRegion );
2032 : :
2033 [ + - ]: 687911 : Rectangle aRect;
2034 : :
2035 : : // no internal data? -> region is empty!
2036 [ + + ][ + + ]: 687911 : if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
2037 : 3504 : return aRect;
2038 : :
2039 : : // PolyPolygon data im Imp structure?
2040 [ - + ]: 684407 : if ( mpImplRegion->mpPolyPoly )
2041 [ # # ]: 0 : return mpImplRegion->mpPolyPoly->GetBoundRect();
2042 [ + + ]: 684407 : if( mpImplRegion->mpB2DPolyPoly )
2043 : : {
2044 [ + - ]: 8 : const basegfx::B2DRange aRange = basegfx::tools::getRange( *mpImplRegion->mpB2DPolyPoly );
2045 [ + - ][ + - ]: 8 : aRect.SetPos( Point( (int)aRange.getMinX(), (int)aRange.getMinY() ) );
2046 [ + - ][ + - ]: 8 : aRect.SetSize( Size( (int)aRange.getWidth(), (int)aRange.getHeight() ) );
[ + - ]
2047 : 8 : return aRect;
2048 : : }
2049 : :
2050 : : // no band in the list? -> region is empty!
2051 [ - + ]: 684399 : if ( !mpImplRegion->mpFirstBand )
2052 : 0 : return aRect;
2053 : :
2054 : : // get the boundaries of the first band
2055 : 684399 : long nYTop = mpImplRegion->mpFirstBand->mnYTop;
2056 : 684399 : long nYBottom = mpImplRegion->mpFirstBand->mnYBottom;
2057 [ + - ]: 684399 : long nXLeft = mpImplRegion->mpFirstBand->GetXLeftBoundary();
2058 [ + - ]: 684399 : long nXRight = mpImplRegion->mpFirstBand->GetXRightBoundary();
2059 : :
2060 : : // look in the band list (don't test first band again!)
2061 : 684399 : ImplRegionBand* pBand = mpImplRegion->mpFirstBand->mpNextBand;
2062 [ + + ]: 692373 : while ( pBand )
2063 : : {
2064 : 7974 : nYBottom = pBand->mnYBottom;
2065 [ + - ]: 7974 : nXLeft = Min( nXLeft, pBand->GetXLeftBoundary() );
2066 [ + - ]: 7974 : nXRight = Max( nXRight, pBand->GetXRightBoundary() );
2067 : :
2068 : 7974 : pBand = pBand->mpNextBand;
2069 : : }
2070 : :
2071 : : // set rectangle
2072 [ + - ]: 684399 : aRect = Rectangle( nXLeft, nYTop, nXRight, nYBottom );
2073 : 687911 : return aRect;
2074 : : }
2075 : :
2076 : : // -----------------------------------------------------------------------
2077 : :
2078 : 2412436 : sal_Bool Region::HasPolyPolygon() const
2079 : : {
2080 : : DBG_CHKTHIS( Region, ImplDbgTestRegion );
2081 [ - + ]: 2412436 : if( !mpImplRegion )
2082 : 0 : return false;
2083 [ + + ]: 2412436 : if( mpImplRegion->mpPolyPoly )
2084 : 22 : return true;
2085 [ + + ]: 2412414 : if( mpImplRegion->mpB2DPolyPoly )
2086 : 65 : return true;
2087 : 2412436 : return false;
2088 : : }
2089 : :
2090 : : // -----------------------------------------------------------------------
2091 : :
2092 : 26 : PolyPolygon Region::GetPolyPolygon() const
2093 : : {
2094 : : DBG_CHKTHIS( Region, ImplDbgTestRegion );
2095 : :
2096 : 26 : PolyPolygon aRet;
2097 : :
2098 [ - + ]: 26 : if( mpImplRegion->mpPolyPoly )
2099 [ # # ]: 0 : aRet = *mpImplRegion->mpPolyPoly;
2100 [ + - ]: 26 : else if( mpImplRegion->mpB2DPolyPoly )
2101 : : {
2102 : : // the polygon needs to be converted
2103 [ + - ][ + - ]: 26 : aRet = PolyPolygon( *mpImplRegion->mpB2DPolyPoly );
[ + - ]
2104 : : // TODO: cache the converted polygon?
2105 : : // mpImplRegion->mpB2DPolyPoly = aRet;
2106 : : }
2107 : :
2108 : 26 : return aRet;
2109 : : }
2110 : :
2111 : : // -----------------------------------------------------------------------
2112 : :
2113 : 174 : const basegfx::B2DPolyPolygon Region::GetB2DPolyPolygon() const
2114 : : {
2115 : : DBG_CHKTHIS( Region, ImplDbgTestRegion );
2116 : :
2117 : 174 : basegfx::B2DPolyPolygon aRet;
2118 : :
2119 [ + + ]: 174 : if( mpImplRegion->mpB2DPolyPoly )
2120 [ + - ]: 33 : aRet = *mpImplRegion->mpB2DPolyPoly;
2121 [ + + ]: 141 : else if( mpImplRegion->mpPolyPoly )
2122 : : {
2123 : : // the polygon needs to be converted
2124 [ + - ][ + - ]: 11 : aRet = mpImplRegion->mpPolyPoly->getB2DPolyPolygon();
[ + - ]
2125 : : // TODO: cache the converted polygon?
2126 : : // mpImplRegion->mpB2DPolyPoly = aRet;
2127 : : }
2128 : :
2129 : 174 : return aRet;
2130 : : }
2131 : :
2132 : : // -----------------------------------------------------------------------
2133 : :
2134 : 86 : basegfx::B2DPolyPolygon Region::ConvertToB2DPolyPolygon()
2135 : : {
2136 : : DBG_CHKTHIS( Region, ImplDbgTestRegion );
2137 : :
2138 : 86 : basegfx::B2DPolyPolygon aRet;
2139 : :
2140 [ + + ][ + - ]: 86 : if( HasPolyPolygon() )
2141 [ + - ][ + - ]: 44 : aRet = GetB2DPolyPolygon();
[ + - ]
2142 : : else
2143 : : {
2144 [ + - ]: 42 : RegionHandle aHdl = BeginEnumRects();
2145 [ + - ]: 42 : Rectangle aSubRect;
2146 [ + - ][ + + ]: 88 : while( GetNextEnumRect( aHdl, aSubRect ) )
2147 : : {
2148 : : basegfx::B2DPolygon aPoly( basegfx::tools::createPolygonFromRect(
2149 [ + - ][ + - ]: 46 : basegfx::B2DRectangle( aSubRect.Left(), aSubRect.Top(), aSubRect.Right(), aSubRect.Bottom() ) ) );
2150 [ + - ]: 46 : aRet.append( aPoly );
2151 [ + - ]: 46 : }
2152 [ + - ]: 42 : EndEnumRects( aHdl );
2153 : : }
2154 : :
2155 : 86 : return aRet;
2156 : : }
2157 : :
2158 : : // -----------------------------------------------------------------------
2159 : :
2160 : 165763 : bool Region::ImplGetFirstRect( ImplRegionInfo& rImplRegionInfo,
2161 : : long& rX, long& rY,
2162 : : long& rWidth, long& rHeight ) const
2163 : : {
2164 : : DBG_CHKTHIS( Region, ImplDbgTestRegion );
2165 : :
2166 : 165763 : ((Region*)this)->ImplPolyPolyRegionToBandRegion();
2167 : :
2168 : : // no internal data? -> region is empty!
2169 [ - + ][ + + ]: 165763 : if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
2170 : 538 : return false;
2171 : :
2172 : : // no band in the list? -> region is empty!
2173 [ - + ]: 165225 : if ( mpImplRegion->mpFirstBand == NULL )
2174 : 0 : return false;
2175 : :
2176 : : // initialise pointer for first access
2177 : 165225 : ImplRegionBand* pCurrRectBand = mpImplRegion->mpFirstBand;
2178 : 165225 : ImplRegionBandSep* pCurrRectBandSep = pCurrRectBand->mpFirstSep;
2179 : :
2180 : : DBG_ASSERT( pCurrRectBandSep != NULL, "Erstes Band wurde nicht optimiert." );
2181 [ - + ]: 165225 : if ( !pCurrRectBandSep )
2182 : 0 : return false;
2183 : :
2184 : : // get boundaries of current rectangle
2185 : 165225 : rX = pCurrRectBandSep->mnXLeft;
2186 : 165225 : rY = pCurrRectBand->mnYTop;
2187 : 165225 : rWidth = pCurrRectBandSep->mnXRight - pCurrRectBandSep->mnXLeft + 1;
2188 : 165225 : rHeight = pCurrRectBand->mnYBottom - pCurrRectBand->mnYTop + 1;
2189 : :
2190 : : // save pointers
2191 : 165225 : rImplRegionInfo.mpVoidCurrRectBand = (void*)pCurrRectBand;
2192 : 165225 : rImplRegionInfo.mpVoidCurrRectBandSep = (void*)pCurrRectBandSep;
2193 : :
2194 : 165763 : return true;
2195 : : }
2196 : :
2197 : : // -----------------------------------------------------------------------
2198 : :
2199 : 252183 : bool Region::ImplGetNextRect( ImplRegionInfo& rImplRegionInfo,
2200 : : long& rX, long& rY,
2201 : : long& rWidth, long& rHeight ) const
2202 : : {
2203 : : DBG_CHKTHIS( Region, ImplDbgTestRegion );
2204 : :
2205 : : // no internal data? -> region is empty!
2206 [ + - ][ - + ]: 252183 : if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
2207 : 0 : return false;
2208 : :
2209 : : // get last pointers
2210 : 252183 : ImplRegionBand* pCurrRectBand = (ImplRegionBand*)rImplRegionInfo.mpVoidCurrRectBand;
2211 : 252183 : ImplRegionBandSep* pCurrRectBandSep = (ImplRegionBandSep*)rImplRegionInfo.mpVoidCurrRectBandSep;
2212 : :
2213 : : // get next separation from current band
2214 : 252183 : pCurrRectBandSep = pCurrRectBandSep->mpNextSep;
2215 : :
2216 : : // no separation found? -> go to next band!
2217 [ + + ]: 252183 : if ( !pCurrRectBandSep )
2218 : : {
2219 : : // get next band
2220 : 173642 : pCurrRectBand = pCurrRectBand->mpNextBand;
2221 : :
2222 : : // no band found? -> not further rectangles!
2223 [ + + ]: 173642 : if( !pCurrRectBand )
2224 : 165225 : return false;
2225 : :
2226 : : // get first separation in current band
2227 : 8417 : pCurrRectBandSep = pCurrRectBand->mpFirstSep;
2228 : : }
2229 : :
2230 : : // get boundaries of current rectangle
2231 : 86958 : rX = pCurrRectBandSep->mnXLeft;
2232 : 86958 : rY = pCurrRectBand->mnYTop;
2233 : 86958 : rWidth = pCurrRectBandSep->mnXRight - pCurrRectBandSep->mnXLeft + 1;
2234 : 86958 : rHeight = pCurrRectBand->mnYBottom - pCurrRectBand->mnYTop + 1;
2235 : :
2236 : : // save new pointers
2237 : 86958 : rImplRegionInfo.mpVoidCurrRectBand = (void*)pCurrRectBand;
2238 : 86958 : rImplRegionInfo.mpVoidCurrRectBandSep = (void*)pCurrRectBandSep;
2239 : :
2240 : 252183 : return true;
2241 : : }
2242 : :
2243 : : // -----------------------------------------------------------------------
2244 : :
2245 : 2505436 : RegionType Region::GetType() const
2246 : : {
2247 [ + + ]: 2505436 : if ( mpImplRegion == &aImplEmptyRegion )
2248 : 264017 : return REGION_EMPTY;
2249 [ + + ]: 2241419 : else if ( mpImplRegion == &aImplNullRegion )
2250 : 15642 : return REGION_NULL;
2251 [ + + ]: 2225777 : else if ( mpImplRegion->mnRectCount == 1 )
2252 : 1934382 : return REGION_RECTANGLE;
2253 : : else
2254 : 2505436 : return REGION_COMPLEX;
2255 : : }
2256 : :
2257 : : // -----------------------------------------------------------------------
2258 : :
2259 : 0 : sal_Bool Region::IsInside( const Point& rPoint ) const
2260 : : {
2261 : : DBG_CHKTHIS( Region, ImplDbgTestRegion );
2262 : :
2263 : : // PolyPolygon data im Imp structure?
2264 : 0 : ((Region*)this)->ImplPolyPolyRegionToBandRegion();
2265 : :
2266 : : // no instance data? -> not inside
2267 [ # # ][ # # ]: 0 : if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
2268 : 0 : return sal_False;
2269 : :
2270 : : // search band list
2271 : 0 : ImplRegionBand* pBand = mpImplRegion->mpFirstBand;
2272 [ # # ]: 0 : while ( pBand )
2273 : : {
2274 : : // is point within band?
2275 [ # # # # ]: 0 : if ( (pBand->mnYTop <= rPoint.Y()) &&
[ # # ]
2276 : 0 : (pBand->mnYBottom >= rPoint.Y()) )
2277 : : {
2278 : : // is point within separation of the band?
2279 [ # # ]: 0 : if ( pBand->IsInside( rPoint.X() ) )
2280 : 0 : return sal_True;
2281 : : else
2282 : 0 : return sal_False;
2283 : : }
2284 : :
2285 : 0 : pBand = pBand->mpNextBand;
2286 : : }
2287 : :
2288 : 0 : return sal_False;
2289 : : }
2290 : :
2291 : : // -----------------------------------------------------------------------
2292 : :
2293 : 0 : sal_Bool Region::IsInside( const Rectangle& rRect ) const
2294 : : {
2295 : : DBG_CHKTHIS( Region, ImplDbgTestRegion );
2296 : :
2297 : : // is rectangle empty? -> not inside
2298 [ # # ][ # # ]: 0 : if ( rRect.IsEmpty() )
2299 : 0 : return sal_False;
2300 : :
2301 : : // no instance data? -> not inside
2302 [ # # ][ # # ]: 0 : if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
2303 : 0 : return sal_False;
2304 : :
2305 : : // create region from rectangle and intersect own region
2306 [ # # ]: 0 : Region aRegion = rRect;
2307 [ # # ]: 0 : aRegion.Exclude( *this );
2308 : :
2309 : : // rectangle is inside if exclusion is empty
2310 [ # # ][ # # ]: 0 : return aRegion.IsEmpty();
2311 : : }
2312 : :
2313 : : // -----------------------------------------------------------------------
2314 : :
2315 : 9190 : sal_Bool Region::IsOver( const Rectangle& rRect ) const
2316 : : {
2317 : : DBG_CHKTHIS( Region, ImplDbgTestRegion );
2318 : :
2319 [ + + ][ - + ]: 9190 : if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
2320 : 6900 : return sal_False;
2321 : :
2322 : : // Can we optimize this ??? - is used in StarDraw for brushes pointers
2323 : : // Why we have no IsOver for Regions ???
2324 : : // create region from rectangle and intersect own region
2325 [ + - ]: 2290 : Region aRegion = rRect;
2326 [ + - ]: 2290 : aRegion.Intersect( *this );
2327 : :
2328 : : // rectangle is over if include is not empty
2329 [ + - ][ + - ]: 9190 : return !aRegion.IsEmpty();
2330 : : }
2331 : :
2332 : : // -----------------------------------------------------------------------
2333 : :
2334 : 337379 : void Region::SetNull()
2335 : : {
2336 : : DBG_CHKTHIS( Region, ImplDbgTestRegion );
2337 : :
2338 : : // statische Object haben RefCount von 0
2339 [ + + ]: 337379 : if ( mpImplRegion->mnRefCount )
2340 : : {
2341 [ + + ]: 9989 : if ( mpImplRegion->mnRefCount > 1 )
2342 : 366 : mpImplRegion->mnRefCount--;
2343 : : else
2344 [ + - ]: 9623 : delete mpImplRegion;
2345 : : }
2346 : :
2347 : : // set new type
2348 : 337379 : mpImplRegion = (ImplRegion*)(&aImplNullRegion);
2349 : 337379 : }
2350 : :
2351 : : // -----------------------------------------------------------------------
2352 : :
2353 : 89173 : void Region::SetEmpty()
2354 : : {
2355 : : DBG_CHKTHIS( Region, ImplDbgTestRegion );
2356 : :
2357 : : // statische Object haben RefCount von 0
2358 [ + + ]: 89173 : if ( mpImplRegion->mnRefCount )
2359 : : {
2360 [ + + ]: 89000 : if ( mpImplRegion->mnRefCount > 1 )
2361 : 88980 : mpImplRegion->mnRefCount--;
2362 : : else
2363 [ + - ]: 20 : delete mpImplRegion;
2364 : : }
2365 : :
2366 : : // set new type
2367 : 89173 : mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
2368 : 89173 : }
2369 : :
2370 : : // -----------------------------------------------------------------------
2371 : :
2372 : 2279876 : Region& Region::operator=( const Region& rRegion )
2373 : : {
2374 : : DBG_CHKTHIS( Region, ImplDbgTestRegion );
2375 : : DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
2376 : : DBG_ASSERT( rRegion.mpImplRegion->mnRefCount < 0xFFFFFFFE, "Region: RefCount overflow" );
2377 : :
2378 : : // Zuerst Referenzcounter erhoehen, damit man sich selbst zuweisen kann
2379 : : // RefCount == 0 fuer statische Objekte
2380 [ + + ]: 2279876 : if ( rRegion.mpImplRegion->mnRefCount )
2381 : 1653340 : rRegion.mpImplRegion->mnRefCount++;
2382 : :
2383 : : // statische Object haben RefCount von 0
2384 [ + + ]: 2279876 : if ( mpImplRegion->mnRefCount )
2385 : : {
2386 [ + + ]: 816193 : if ( mpImplRegion->mnRefCount > 1 )
2387 : 359913 : mpImplRegion->mnRefCount--;
2388 : : else
2389 [ + - ]: 456280 : delete mpImplRegion;
2390 : : }
2391 : :
2392 : 2279876 : mpImplRegion = rRegion.mpImplRegion;
2393 : 2279876 : return *this;
2394 : : }
2395 : :
2396 : : // -----------------------------------------------------------------------
2397 : :
2398 : 168109 : Region& Region::operator=( const Rectangle& rRect )
2399 : : {
2400 : : DBG_CHKTHIS( Region, ImplDbgTestRegion );
2401 : :
2402 : : // statische Object haben RefCount von 0
2403 [ + + ]: 168109 : if ( mpImplRegion->mnRefCount )
2404 : : {
2405 [ + + ]: 90403 : if ( mpImplRegion->mnRefCount > 1 )
2406 : 54934 : mpImplRegion->mnRefCount--;
2407 : : else
2408 [ + - ]: 35469 : delete mpImplRegion;
2409 : : }
2410 : :
2411 : 168109 : ImplCreateRectRegion( rRect );
2412 : 168109 : return *this;
2413 : : }
2414 : :
2415 : : // -----------------------------------------------------------------------
2416 : :
2417 : 34754 : sal_Bool Region::operator==( const Region& rRegion ) const
2418 : : {
2419 : : DBG_CHKTHIS( Region, ImplDbgTestRegion );
2420 : : DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
2421 : :
2422 : : // reference to same object? -> equal!
2423 [ - + ]: 34754 : if ( mpImplRegion == rRegion.mpImplRegion )
2424 : 0 : return sal_True;
2425 : :
2426 [ + - ][ - + ]: 34754 : if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
2427 : 0 : return sal_False;
2428 : :
2429 [ + - ][ - + ]: 34754 : if ( (rRegion.mpImplRegion == &aImplEmptyRegion) || (rRegion.mpImplRegion == &aImplNullRegion) )
2430 : 0 : return sal_False;
2431 : :
2432 [ - + ][ # # ]: 34754 : if ( rRegion.mpImplRegion->mpPolyPoly && mpImplRegion->mpPolyPoly )
2433 : 0 : return *rRegion.mpImplRegion->mpPolyPoly == *mpImplRegion->mpPolyPoly;
2434 : : else
2435 : : {
2436 : 34754 : ((Region*)this)->ImplPolyPolyRegionToBandRegion();
2437 : 34754 : ((Region*)&rRegion)->ImplPolyPolyRegionToBandRegion();
2438 : :
2439 : : // Eine der beiden Regions kann jetzt Empty sein
2440 [ - + ]: 34754 : if ( mpImplRegion == rRegion.mpImplRegion )
2441 : 0 : return sal_True;
2442 : :
2443 [ - + ]: 34754 : if ( mpImplRegion == &aImplEmptyRegion )
2444 : 0 : return sal_False;
2445 : :
2446 [ - + ]: 34754 : if ( rRegion.mpImplRegion == &aImplEmptyRegion )
2447 : 0 : return sal_False;
2448 : : }
2449 : :
2450 : : // initialise pointers
2451 : 34754 : ImplRegionBand* pOwnRectBand = mpImplRegion->mpFirstBand;
2452 : 34754 : ImplRegionBandSep* pOwnRectBandSep = pOwnRectBand->mpFirstSep;
2453 : 34754 : ImplRegionBand* pSecondRectBand = rRegion.mpImplRegion->mpFirstBand;
2454 : 34754 : ImplRegionBandSep* pSecondRectBandSep = pSecondRectBand->mpFirstSep;
2455 [ + + ][ + - ]: 35696 : while ( pOwnRectBandSep && pSecondRectBandSep )
[ + + ]
2456 : : {
2457 : : // get boundaries of current rectangle
2458 : 34754 : long nOwnXLeft = pOwnRectBandSep->mnXLeft;
2459 : 34754 : long nSecondXLeft = pSecondRectBandSep->mnXLeft;
2460 [ + + ]: 34754 : if ( nOwnXLeft != nSecondXLeft )
2461 : 22962 : return sal_False;
2462 : :
2463 : 11792 : long nOwnYTop = pOwnRectBand->mnYTop;
2464 : 11792 : long nSecondYTop = pSecondRectBand->mnYTop;
2465 [ + + ]: 11792 : if ( nOwnYTop != nSecondYTop )
2466 : 5764 : return sal_False;
2467 : :
2468 : 6028 : long nOwnXRight = pOwnRectBandSep->mnXRight;
2469 : 6028 : long nSecondXRight = pSecondRectBandSep->mnXRight;
2470 [ + + ]: 6028 : if ( nOwnXRight != nSecondXRight )
2471 : 1204 : return sal_False;
2472 : :
2473 : 4824 : long nOwnYBottom = pOwnRectBand->mnYBottom;
2474 : 4824 : long nSecondYBottom = pSecondRectBand->mnYBottom;
2475 [ + + ]: 4824 : if ( nOwnYBottom != nSecondYBottom )
2476 : 3882 : return sal_False;
2477 : :
2478 : : // get next separation from current band
2479 : 942 : pOwnRectBandSep = pOwnRectBandSep->mpNextSep;
2480 : :
2481 : : // no separation found? -> go to next band!
2482 [ + - ]: 942 : if ( !pOwnRectBandSep )
2483 : : {
2484 : : // get next band
2485 : 942 : pOwnRectBand = pOwnRectBand->mpNextBand;
2486 : :
2487 : : // get first separation in current band
2488 [ - + ]: 942 : if( pOwnRectBand )
2489 : 0 : pOwnRectBandSep = pOwnRectBand->mpFirstSep;
2490 : : }
2491 : :
2492 : : // get next separation from current band
2493 : 942 : pSecondRectBandSep = pSecondRectBandSep->mpNextSep;
2494 : :
2495 : : // no separation found? -> go to next band!
2496 [ + - ]: 942 : if ( !pSecondRectBandSep )
2497 : : {
2498 : : // get next band
2499 : 942 : pSecondRectBand = pSecondRectBand->mpNextBand;
2500 : :
2501 : : // get first separation in current band
2502 [ - + ]: 942 : if( pSecondRectBand )
2503 : 0 : pSecondRectBandSep = pSecondRectBand->mpFirstSep;
2504 : : }
2505 : :
2506 [ - + ][ # # ]: 942 : if ( pOwnRectBandSep && !pSecondRectBandSep )
2507 : 0 : return sal_False;
2508 : :
2509 [ + - ][ - + ]: 942 : if ( !pOwnRectBandSep && pSecondRectBandSep )
2510 : 0 : return sal_False;
2511 : : }
2512 : :
2513 : 34754 : return sal_True;
2514 : : }
2515 : :
2516 : : // -----------------------------------------------------------------------
2517 : :
2518 : : enum StreamEntryType { STREAMENTRY_BANDHEADER, STREAMENTRY_SEPARATION, STREAMENTRY_END };
2519 : :
2520 : 178 : SvStream& operator>>( SvStream& rIStrm, Region& rRegion )
2521 : : {
2522 : : DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
2523 : :
2524 [ + - ]: 178 : VersionCompat aCompat( rIStrm, STREAM_READ );
2525 : : sal_uInt16 nVersion;
2526 : : sal_uInt16 nTmp16;
2527 : :
2528 : : // statische Object haben RefCount von 0
2529 [ - + ]: 178 : if ( rRegion.mpImplRegion->mnRefCount )
2530 : : {
2531 [ # # ]: 0 : if ( rRegion.mpImplRegion->mnRefCount > 1 )
2532 : 0 : rRegion.mpImplRegion->mnRefCount--;
2533 : : else
2534 [ # # ][ # # ]: 0 : delete rRegion.mpImplRegion;
2535 : : }
2536 : :
2537 : : // get version of streamed region
2538 [ + - ]: 178 : rIStrm >> nVersion;
2539 : :
2540 : : // get type of region
2541 [ + - ]: 178 : rIStrm >> nTmp16;
2542 : :
2543 : 178 : RegionType meStreamedType = (RegionType)nTmp16;
2544 : :
2545 [ - - + ]: 178 : switch( meStreamedType )
2546 : : {
2547 : : case REGION_NULL:
2548 : 0 : rRegion.mpImplRegion = (ImplRegion*)&aImplNullRegion;
2549 : 0 : break;
2550 : :
2551 : : case REGION_EMPTY:
2552 : 0 : rRegion.mpImplRegion = (ImplRegion*)&aImplEmptyRegion;
2553 : 0 : break;
2554 : :
2555 : : default:
2556 : : {
2557 : : // create instance of implementation class
2558 [ + - ][ + - ]: 178 : rRegion.mpImplRegion = new ImplRegion();
2559 : :
2560 : : // get header from first element
2561 [ + - ]: 178 : rIStrm >> nTmp16;
2562 : :
2563 : : // get all bands
2564 : 178 : rRegion.mpImplRegion->mnRectCount = 0;
2565 : 178 : ImplRegionBand* pCurrBand = NULL;
2566 [ + + ]: 534 : while ( (StreamEntryType)nTmp16 != STREAMENTRY_END )
2567 : : {
2568 : : // insert new band or new separation?
2569 [ + + ]: 356 : if ( (StreamEntryType)nTmp16 == STREAMENTRY_BANDHEADER )
2570 : : {
2571 : : //#fdo39428 SvStream no longer supports operator>>(long&)
2572 : : sal_Int32 nYTop;
2573 : : sal_Int32 nYBottom;
2574 : :
2575 [ + - ]: 178 : rIStrm >> nYTop;
2576 [ + - ]: 178 : rIStrm >> nYBottom;
2577 : :
2578 : : // create band
2579 [ + - ][ + - ]: 178 : ImplRegionBand* pNewBand = new ImplRegionBand( nYTop, nYBottom );
2580 : :
2581 : : // first element? -> set as first into the list
2582 [ + - ]: 178 : if ( !pCurrBand )
2583 : 178 : rRegion.mpImplRegion->mpFirstBand = pNewBand;
2584 : : else
2585 : 0 : pCurrBand->mpNextBand = pNewBand;
2586 : :
2587 : : // save pointer for next creation
2588 : 178 : pCurrBand = pNewBand;
2589 : : }
2590 : : else
2591 : : {
2592 : : //#fdo39428 SvStream no longer supports operator>>(long&)
2593 : : sal_Int32 nXLeft;
2594 : : sal_Int32 nXRight;
2595 : :
2596 [ + - ]: 178 : rIStrm >> nXLeft;
2597 [ + - ]: 178 : rIStrm >> nXRight;
2598 : :
2599 : : // add separation
2600 [ + - ]: 178 : if ( pCurrBand )
2601 : : {
2602 [ + - ]: 178 : pCurrBand->Union( nXLeft, nXRight );
2603 : 178 : rRegion.mpImplRegion->mnRectCount++;
2604 : : }
2605 : : }
2606 : :
2607 [ - + ]: 356 : if( rIStrm.IsEof() )
2608 : : {
2609 : : OSL_FAIL( "premature end of region stream" );
2610 [ # # ][ # # ]: 0 : delete rRegion.mpImplRegion;
2611 : 0 : rRegion.mpImplRegion = (ImplRegion*)&aImplEmptyRegion;
2612 : 0 : return rIStrm;
2613 : : }
2614 : :
2615 : : // get next header
2616 [ + - ]: 356 : rIStrm >> nTmp16;
2617 : : }
2618 : :
2619 [ + - ]: 178 : if( aCompat.GetVersion() >= 2 )
2620 : : {
2621 : : sal_Bool bHasPolyPolygon;
2622 : :
2623 [ + - ]: 178 : rIStrm >> bHasPolyPolygon;
2624 : :
2625 [ - + ]: 178 : if( bHasPolyPolygon )
2626 : : {
2627 [ # # ][ # # ]: 0 : delete rRegion.mpImplRegion->mpPolyPoly;
2628 [ # # ][ # # ]: 0 : rRegion.mpImplRegion->mpPolyPoly = new PolyPolygon;
2629 [ # # ]: 178 : rIStrm >> *( rRegion.mpImplRegion->mpPolyPoly );
2630 : : }
2631 : : }
2632 : : }
2633 : 178 : break;
2634 : : }
2635 : :
2636 [ + - ]: 178 : return rIStrm;
2637 : : }
2638 : :
2639 : : // -----------------------------------------------------------------------
2640 : :
2641 : 438 : SvStream& operator<<( SvStream& rOStrm, const Region& rRegion )
2642 : : {
2643 : : DBG_CHKOBJ( &rRegion, Region, ImplDbgTestRegion );
2644 : :
2645 : 438 : sal_uInt16 nVersion = 2;
2646 [ + - ]: 438 : VersionCompat aCompat( rOStrm, STREAM_WRITE, nVersion );
2647 [ + - ]: 438 : Region aTmpRegion( rRegion );
2648 : :
2649 : : // use tmp region to avoid destruction of internal region (polypolygon) of rRegion
2650 [ + - ]: 438 : aTmpRegion.ImplPolyPolyRegionToBandRegion();
2651 : :
2652 : : // put version
2653 [ + - ]: 438 : rOStrm << nVersion;
2654 : :
2655 : : // put type
2656 [ + - ][ + - ]: 438 : rOStrm << (sal_uInt16)aTmpRegion.GetType();
2657 : :
2658 : : // put all bands if not null or empty
2659 [ + - ][ + - ]: 438 : if ( (aTmpRegion.mpImplRegion != &aImplEmptyRegion) && (aTmpRegion.mpImplRegion != &aImplNullRegion) )
2660 : : {
2661 : 438 : ImplRegionBand* pBand = aTmpRegion.mpImplRegion->mpFirstBand;
2662 [ + + ]: 876 : while ( pBand )
2663 : : {
2664 : : // put boundaries
2665 : : //#fdo39428 SvStream no longer supports operator<<(long)
2666 [ + - ]: 438 : rOStrm << (sal_uInt16) STREAMENTRY_BANDHEADER;
2667 [ + - ]: 438 : rOStrm << sal::static_int_cast<sal_Int32>(pBand->mnYTop);
2668 [ + - ]: 438 : rOStrm << sal::static_int_cast<sal_Int32>(pBand->mnYBottom);
2669 : :
2670 : : // put separations of current band
2671 : 438 : ImplRegionBandSep* pSep = pBand->mpFirstSep;
2672 [ + + ]: 876 : while ( pSep )
2673 : : {
2674 : : // put separation
2675 : : //#fdo39428 SvStream no longer supports operator<<(long)
2676 [ + - ]: 438 : rOStrm << (sal_uInt16) STREAMENTRY_SEPARATION;
2677 [ + - ]: 438 : rOStrm << sal::static_int_cast<sal_Int32>(pSep->mnXLeft);
2678 [ + - ]: 438 : rOStrm << sal::static_int_cast<sal_Int32>(pSep->mnXRight);
2679 : :
2680 : : // next separation from current band
2681 : 438 : pSep = pSep->mpNextSep;
2682 : : }
2683 : :
2684 : 438 : pBand = pBand->mpNextBand;
2685 : : }
2686 : :
2687 : : // put endmarker
2688 [ + - ]: 438 : rOStrm << (sal_uInt16) STREAMENTRY_END;
2689 : :
2690 : : // write polypolygon if available
2691 [ + - ]: 438 : const sal_Bool bHasPolyPolygon = rRegion.HasPolyPolygon();
2692 [ + - ]: 438 : rOStrm << bHasPolyPolygon;
2693 : :
2694 [ - + ]: 438 : if( bHasPolyPolygon )
2695 : : {
2696 : : // #i105373#
2697 [ # # ]: 0 : PolyPolygon aNoCurvePolyPolygon;
2698 [ # # ][ # # ]: 0 : rRegion.GetPolyPolygon().AdaptiveSubdivide(aNoCurvePolyPolygon);
[ # # ]
2699 : :
2700 [ # # ][ # # ]: 0 : rOStrm << aNoCurvePolyPolygon;
2701 : : }
2702 : : }
2703 : :
2704 [ + - ][ + - ]: 438 : return rOStrm;
2705 : : }
2706 : :
2707 : : // -----------------------------------------------------------------------
2708 : :
2709 : 139271 : void Region::ImplBeginAddRect()
2710 : : {
2711 : : DBG_CHKTHIS( Region, ImplDbgTestRegion );
2712 : :
2713 : : // statische Object haben RefCount von 0
2714 [ - + ]: 139271 : if ( mpImplRegion->mnRefCount )
2715 : : {
2716 [ # # ]: 0 : if ( mpImplRegion->mnRefCount > 1 )
2717 : 0 : mpImplRegion->mnRefCount--;
2718 : : else
2719 [ # # ]: 0 : delete mpImplRegion;
2720 : : }
2721 : :
2722 : : // create fresh region
2723 [ + - ]: 139271 : mpImplRegion = new ImplRegion();
2724 : 139271 : }
2725 : :
2726 : : // -----------------------------------------------------------------------
2727 : :
2728 : 144383 : sal_Bool Region::ImplAddRect( const Rectangle& rRect )
2729 : : {
2730 : : // Hier kein CheckThis, da nicht alle Daten auf Stand
2731 : :
2732 [ - + ]: 144383 : if ( rRect.IsEmpty() )
2733 : 0 : return sal_True;
2734 : :
2735 : : // get justified rectangle
2736 : : long nTop;
2737 : : long nBottom;
2738 : : long nLeft;
2739 : : long nRight;
2740 [ + - ]: 144383 : if ( rRect.Top() <= rRect.Bottom() )
2741 : : {
2742 : 144383 : nTop = rRect.Top();
2743 : 144383 : nBottom = rRect.Bottom();
2744 : : }
2745 : : else
2746 : : {
2747 : 0 : nTop = rRect.Bottom();
2748 : 0 : nBottom = rRect.Top();
2749 : : }
2750 [ + - ]: 144383 : if ( rRect.Left() <= rRect.Right() )
2751 : : {
2752 : 144383 : nLeft = rRect.Left();
2753 : 144383 : nRight = rRect.Right();
2754 : : }
2755 : : else
2756 : : {
2757 : 0 : nLeft = rRect.Right();
2758 : 0 : nRight = rRect.Left();
2759 : : }
2760 : :
2761 [ + + ]: 144383 : if ( !mpImplRegion->mpLastCheckedBand )
2762 : : {
2763 : : // create new band
2764 [ + - ]: 139271 : mpImplRegion->mpLastCheckedBand = new ImplRegionBand( nTop, nBottom );
2765 : :
2766 : : // set band as current
2767 : 139271 : mpImplRegion->mpFirstBand = mpImplRegion->mpLastCheckedBand;
2768 : 139271 : mpImplRegion->mpLastCheckedBand->Union( nLeft, nRight );
2769 : : }
2770 : : else
2771 : : {
2772 : : DBG_ASSERT( nTop >= mpImplRegion->mpLastCheckedBand->mnYTop,
2773 : : "Region::ImplAddRect() - nTopY < nLastTopY" );
2774 : :
2775 : : // new band? create it!
2776 [ + + ][ - + ]: 5112 : if ( (nTop != mpImplRegion->mpLastCheckedBand->mnYTop) ||
2777 : : (nBottom != mpImplRegion->mpLastCheckedBand->mnYBottom) )
2778 : : {
2779 : : // create new band
2780 [ + - ]: 4307 : ImplRegionBand* pNewRegionBand = new ImplRegionBand( nTop, nBottom );
2781 : :
2782 : : // append band to the end
2783 : 4307 : mpImplRegion->mpLastCheckedBand->mpNextBand = pNewRegionBand;
2784 : :
2785 : : // skip to the new band
2786 : 4307 : mpImplRegion->mpLastCheckedBand = mpImplRegion->mpLastCheckedBand->mpNextBand;
2787 : : }
2788 : :
2789 : : // Insert Sep
2790 : 5112 : mpImplRegion->mpLastCheckedBand->Union( nLeft, nRight );
2791 : : }
2792 : :
2793 : 144383 : return sal_True;
2794 : : }
2795 : :
2796 : : // -----------------------------------------------------------------------
2797 : :
2798 : 139271 : void Region::ImplEndAddRect()
2799 : : {
2800 : : // check if we are empty
2801 [ - + ]: 139271 : if ( !mpImplRegion->mpFirstBand )
2802 : : {
2803 [ # # ]: 0 : delete mpImplRegion;
2804 : 0 : mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
2805 : 0 : return;
2806 : : }
2807 : :
2808 : : // check if we have somthing to optimize
2809 [ + + ]: 139271 : if ( !mpImplRegion->mpFirstBand->mpNextBand )
2810 : : {
2811 : : // update mpImplRegion->mnRectCount, because no OptimizeBandList is called
2812 : 136017 : ImplRegionBandSep* pSep = mpImplRegion->mpFirstBand->mpFirstSep;
2813 : 136017 : mpImplRegion->mnRectCount = 0;
2814 [ + + ]: 272072 : while( pSep )
2815 : : {
2816 : 136055 : mpImplRegion->mnRectCount++;
2817 : 136055 : pSep = pSep->mpNextSep;
2818 : : }
2819 : :
2820 : : // Erst hier testen, da hier die Daten wieder stimmen
2821 : : DBG_CHKTHIS( Region, ImplDbgTestRegion );
2822 : 136017 : return;
2823 : : }
2824 : :
2825 : : // have to revert list? -> do it now!
2826 [ - + ]: 3254 : if ( mpImplRegion->mpFirstBand->mnYTop >
2827 : : mpImplRegion->mpFirstBand->mpNextBand->mnYTop )
2828 : : {
2829 : : ImplRegionBand * pNewFirstRegionBand;
2830 : :
2831 : : // initialize temp list with first element
2832 : 0 : pNewFirstRegionBand = mpImplRegion->mpFirstBand;
2833 : 0 : mpImplRegion->mpFirstBand = mpImplRegion->mpFirstBand->mpNextBand;
2834 : 0 : pNewFirstRegionBand->mpNextBand = NULL;
2835 : :
2836 : : // insert elements to the temp list
2837 [ # # ]: 0 : while ( mpImplRegion->mpFirstBand )
2838 : : {
2839 : 0 : ImplRegionBand * pSavedRegionBand = pNewFirstRegionBand;
2840 : 0 : pNewFirstRegionBand = mpImplRegion->mpFirstBand;
2841 : 0 : mpImplRegion->mpFirstBand = mpImplRegion->mpFirstBand->mpNextBand;
2842 : 0 : pNewFirstRegionBand->mpNextBand = pSavedRegionBand;
2843 : : }
2844 : :
2845 : : // set temp list as new list
2846 : 0 : mpImplRegion->mpFirstBand = pNewFirstRegionBand;
2847 : : }
2848 : :
2849 : : // cleanup
2850 [ - + ]: 3254 : if ( !mpImplRegion->OptimizeBandList() )
2851 : : {
2852 [ # # ]: 0 : delete mpImplRegion;
2853 : 139271 : mpImplRegion = (ImplRegion*)(&aImplEmptyRegion);
2854 : : }
2855 : :
2856 : : // Erst hier testen, da hier die Daten wieder stimmen
2857 : : DBG_CHKTHIS( Region, ImplDbgTestRegion );
2858 : : }
2859 : :
2860 : : // -----------------------------------------------------------------------
2861 : :
2862 : 427801 : sal_uLong Region::GetRectCount() const
2863 : : {
2864 : : DBG_CHKTHIS( Region, ImplDbgTestRegion );
2865 : :
2866 : 427801 : ((Region*)this)->ImplPolyPolyRegionToBandRegion();
2867 : :
2868 : : #ifdef DBG_UTIL
2869 : : sal_uLong nCount = 0;
2870 : :
2871 : : // all bands if not null or empty
2872 : : if ( (mpImplRegion != &aImplEmptyRegion) && (mpImplRegion != &aImplNullRegion) )
2873 : : {
2874 : : ImplRegionBand* pBand = mpImplRegion->mpFirstBand;
2875 : : while ( pBand )
2876 : : {
2877 : : ImplRegionBandSep* pSep = pBand->mpFirstSep;
2878 : : while( pSep )
2879 : : {
2880 : : nCount++;
2881 : : pSep = pSep->mpNextSep;
2882 : : }
2883 : :
2884 : : pBand = pBand->mpNextBand;
2885 : : }
2886 : : }
2887 : :
2888 : : DBG_ASSERT( mpImplRegion->mnRectCount == nCount, "Region: invalid mnRectCount!" );
2889 : : #endif
2890 : :
2891 : 427801 : return mpImplRegion->mnRectCount;
2892 : : }
2893 : :
2894 : : // -----------------------------------------------------------------------
2895 : :
2896 : 96609 : RegionHandle Region::BeginEnumRects()
2897 : : {
2898 : : DBG_CHKTHIS( Region, ImplDbgTestRegion );
2899 : :
2900 : 96609 : ImplPolyPolyRegionToBandRegion();
2901 : :
2902 : : // no internal data? -> region is empty!
2903 [ - + ][ + - ]: 96609 : if ( (mpImplRegion == &aImplEmptyRegion) || (mpImplRegion == &aImplNullRegion) )
2904 : 0 : return 0;
2905 : :
2906 : : // no band in the list? -> region is empty!
2907 [ - + ]: 96609 : if ( mpImplRegion->mpFirstBand == NULL )
2908 : : {
2909 : : DBG_ASSERT( mpImplRegion->mpFirstBand, "Region::BeginEnumRects() First Band is Empty!" );
2910 : 0 : return 0;
2911 : : }
2912 : :
2913 : 96609 : ImplRegionHandle* pData = new ImplRegionHandle;
2914 [ + - ]: 96609 : pData->mpRegion = new Region( *this );
2915 : 96609 : pData->mbFirst = sal_True;
2916 : :
2917 : : // save pointers
2918 : 96609 : pData->mpCurrRectBand = pData->mpRegion->mpImplRegion->mpFirstBand;
2919 : 96609 : pData->mpCurrRectBandSep = pData->mpCurrRectBand->mpFirstSep;
2920 : :
2921 : 96609 : return (RegionHandle)pData;
2922 : : }
2923 : :
2924 : : // -----------------------------------------------------------------------
2925 : :
2926 : 405262 : sal_Bool Region::GetEnumRects( RegionHandle pVoidData, Rectangle& rRect )
2927 : : {
2928 : : DBG_CHKTHIS( Region, ImplDbgTestRegion );
2929 : :
2930 : 405262 : ImplRegionHandle* pData = (ImplRegionHandle*)pVoidData;
2931 [ - + ]: 405262 : if ( !pData )
2932 : 0 : return sal_False;
2933 : :
2934 [ + + ]: 405262 : if ( pData->mbFirst )
2935 : 96609 : pData->mbFirst = sal_False;
2936 : : else
2937 : : {
2938 : : // get next separation from current band
2939 : 308653 : pData->mpCurrRectBandSep = pData->mpCurrRectBandSep->mpNextSep;
2940 : :
2941 : : // no separation found? -> go to next band!
2942 [ + + ]: 308653 : if ( !pData->mpCurrRectBandSep )
2943 : : {
2944 : : // get next band
2945 : 105372 : pData->mpCurrRectBand = pData->mpCurrRectBand->mpNextBand;
2946 : :
2947 : : // no band found? -> not further rectangles!
2948 [ + + ]: 105372 : if ( !pData->mpCurrRectBand )
2949 : 96609 : return sal_False;
2950 : :
2951 : : // get first separation in current band
2952 : 8763 : pData->mpCurrRectBandSep = pData->mpCurrRectBand->mpFirstSep;
2953 : : }
2954 : : }
2955 : :
2956 : : // get boundaries of current rectangle
2957 : 308653 : rRect.Top() = pData->mpCurrRectBand->mnYTop;
2958 : 308653 : rRect.Bottom() = pData->mpCurrRectBand->mnYBottom;
2959 : 308653 : rRect.Left() = pData->mpCurrRectBandSep->mnXLeft;
2960 : 308653 : rRect.Right() = pData->mpCurrRectBandSep->mnXRight;
2961 : 405262 : return sal_True;
2962 : : }
2963 : :
2964 : : // -----------------------------------------------------------------------
2965 : :
2966 : 96609 : void Region::EndEnumRects( RegionHandle pVoidData )
2967 : : {
2968 : : DBG_CHKTHIS( Region, ImplDbgTestRegion );
2969 : :
2970 : 96609 : ImplRegionHandle* pData = (ImplRegionHandle*)pVoidData;
2971 [ - + ]: 96609 : if ( !pData )
2972 : 96609 : return;
2973 : :
2974 : : // cleanup
2975 [ + - ]: 96609 : delete pData->mpRegion;
2976 : 96609 : delete pData;
2977 : : }
2978 : :
2979 : : // -----------------------------------------------------------------------
2980 : :
2981 : 0 : static inline bool ImplPolygonRectTest( const Polygon& rPoly, Rectangle* pRectOut = NULL )
2982 : : {
2983 : 0 : bool bIsRect = false;
2984 : 0 : const Point* pPoints = rPoly.GetConstPointAry();
2985 : 0 : sal_uInt16 nPoints = rPoly.GetSize();
2986 [ # # ][ # # ]: 0 : if( nPoints == 4 || (nPoints == 5 && pPoints[0] == pPoints[4]) )
[ # # ][ # # ]
2987 : : {
2988 : 0 : long nX1 = pPoints[0].X(), nX2 = pPoints[2].X(),
2989 : 0 : nY1 = pPoints[0].Y(), nY2 = pPoints[2].Y();
2990 [ # # # # : 0 : if( ( (pPoints[1].X() == nX1 && pPoints[3].X() == nX2) &&
# # # # #
# # # #
# ][ # # ]
[ # # ]
2991 : 0 : (pPoints[1].Y() == nY2 && pPoints[3].Y() == nY1) )
2992 : : ||
2993 : 0 : ( (pPoints[1].X() == nX2 && pPoints[3].X() == nX1) &&
2994 : 0 : (pPoints[1].Y() == nY1 && pPoints[3].Y() == nY2) ) )
2995 : : {
2996 : 0 : bIsRect = true;
2997 [ # # ]: 0 : if( pRectOut )
2998 : : {
2999 : : long nSwap;
3000 [ # # ]: 0 : if( nX2 < nX1 )
3001 : : {
3002 : 0 : nSwap = nX2;
3003 : 0 : nX2 = nX1;
3004 : 0 : nX1 = nSwap;
3005 : : }
3006 [ # # ]: 0 : if( nY2 < nY1 )
3007 : : {
3008 : 0 : nSwap = nY2;
3009 : 0 : nY2 = nY1;
3010 : 0 : nY1 = nSwap;
3011 : : }
3012 [ # # ]: 0 : if( nX2 != nX1 )
3013 : 0 : nX2--;
3014 [ # # ]: 0 : if( nY2 != nY1 )
3015 : 0 : nY2--;
3016 : 0 : pRectOut->Left() = nX1;
3017 : 0 : pRectOut->Right() = nX2;
3018 : 0 : pRectOut->Top() = nY1;
3019 : 0 : pRectOut->Bottom() = nY2;
3020 : : }
3021 : : }
3022 : : }
3023 : 0 : return bIsRect;
3024 : : }
3025 : :
3026 : 0 : Region Region::GetRegionFromPolyPolygon( const PolyPolygon& rPolyPoly )
3027 : : {
3028 : : //return Region( rPolyPoly );
3029 : :
3030 : : // check if it's worth extracting the XOr'ing the Rectangles
3031 : : // empiricism shows that break even between XOr'ing rectangles separately
3032 : : // and ImplPolyPolyRegionToBandRegion is at half rectangles/half polygons
3033 : 0 : int nPolygonRects = 0, nPolygonPolygons = 0;
3034 [ # # ]: 0 : int nPolygons = rPolyPoly.Count();
3035 : :
3036 [ # # ]: 0 : for( sal_uInt16 i = 0; i < nPolygons; i++ )
3037 : : {
3038 [ # # ]: 0 : const Polygon& rPoly = rPolyPoly[i];
3039 [ # # ][ # # ]: 0 : if( ImplPolygonRectTest( rPoly ) )
3040 : 0 : nPolygonRects++;
3041 : : else
3042 : 0 : nPolygonPolygons++;
3043 : : }
3044 [ # # ]: 0 : if( nPolygonPolygons > nPolygonRects )
3045 [ # # ]: 0 : return Region( rPolyPoly );
3046 : :
3047 [ # # ]: 0 : Region aResult;
3048 [ # # ]: 0 : Rectangle aRect;
3049 [ # # ]: 0 : for( sal_uInt16 i = 0; i < nPolygons; i++ )
3050 : : {
3051 [ # # ]: 0 : const Polygon& rPoly = rPolyPoly[i];
3052 [ # # ][ # # ]: 0 : if( ImplPolygonRectTest( rPoly, &aRect ) )
3053 [ # # ]: 0 : aResult.XOr( aRect );
3054 : : else
3055 [ # # ][ # # ]: 0 : aResult.XOr( Region(rPoly) );
[ # # ]
3056 : : }
3057 [ # # ][ # # ]: 0 : return aResult;
3058 [ + - ][ + - ]: 1041 : }
3059 : :
3060 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|