1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <tools/debug.hxx>
21 #include <tools/helpers.hxx>
22 #include <vcl/regband.hxx>
23 #include <osl/diagnose.hxx>
28 // =======================================================================
32 // Jedes Band enthaelt die zwischen der enthaltenen Ober- und Untergrenze
33 // enthaltenen Rechtecke. Bei den Operationen Union, Intersect, XOr und
34 // Exclude werden immer Rechtecke der gleichen Hoehe ausgewerte; die
35 // Grenzen der Baender sind immer so zu waehlen, dasz dies moeglich ist.
37 // Die Rechtecke in den Baendern werden nach Moeglichkeit zusammengefaszt.
39 // Bei der Umwandlung von Polygonen werden alle Punkte des Polygons
40 // in die einzelnen Baender eingetragen (sie stehen fuer jedes Band als
41 // Punkte in einer Liste). Nach dem Eintragen der Punkte werden diese
42 // in Rechtecke umgewandelt und die Liste der Punkte geloescht.
44 // -----------------------------------------------------------------------
46 ImplRegionBand::ImplRegionBand( long nTop
, long nBottom
)
56 mpFirstBandPoint
= NULL
;
57 mbTouched
= sal_False
;
60 // -----------------------------------------------------------------------
62 ImplRegionBand::ImplRegionBand(
63 const ImplRegionBand
& rRegionBand
,
64 const bool bIgnorePoints
)
67 mnYTop
= rRegionBand
.mnYTop
;
68 mnYBottom
= rRegionBand
.mnYBottom
;
69 mbTouched
= rRegionBand
.mbTouched
;
75 mpFirstBandPoint
= NULL
;
77 // copy all elements of the list with separations
78 ImplRegionBandSep
* pNewSep
;
79 ImplRegionBandSep
* pPrevSep
= 0;
80 ImplRegionBandSep
* pSep
= rRegionBand
.mpFirstSep
;
83 // create new and copy data
84 pNewSep
= new ImplRegionBandSep
;
85 pNewSep
->mnXLeft
= pSep
->mnXLeft
;
86 pNewSep
->mnXRight
= pSep
->mnXRight
;
87 pNewSep
->mbRemoved
= pSep
->mbRemoved
;
88 pNewSep
->mpNextSep
= NULL
;
89 if ( pSep
== rRegionBand
.mpFirstSep
)
92 pPrevSep
->mpNextSep
= pNewSep
;
95 pSep
= pSep
->mpNextSep
;
101 ImplRegionBandPoint
* pPoint
= rRegionBand
.mpFirstBandPoint
;
102 ImplRegionBandPoint
* pPrevPointCopy
= NULL
;
103 while (pPoint
!= NULL
)
105 ImplRegionBandPoint
* pPointCopy
= new ImplRegionBandPoint();
106 pPointCopy
->mnX
= pPoint
->mnX
;
107 pPointCopy
->mnLineId
= pPoint
->mnLineId
;
108 pPointCopy
->mbEndPoint
= pPoint
->mbEndPoint
;
109 pPointCopy
->meLineType
= pPoint
->meLineType
;
111 if (pPrevPointCopy
!= NULL
)
112 pPrevPointCopy
->mpNextBandPoint
= pPointCopy
;
114 mpFirstBandPoint
= pPointCopy
;
116 pPrevPointCopy
= pPointCopy
;
117 pPoint
= pPoint
->mpNextBandPoint
;
122 // -----------------------------------------------------------------------
124 ImplRegionBand::~ImplRegionBand()
126 DBG_ASSERT( mpFirstBandPoint
== NULL
, "ImplRegionBand::~ImplRegionBand -> pointlist not empty" );
128 // delete elements of the list
129 ImplRegionBandSep
* pSep
= mpFirstSep
;
132 ImplRegionBandSep
* pTempSep
= pSep
->mpNextSep
;
137 // delete elements of the list
138 ImplRegionBandPoint
* pPoint
= mpFirstBandPoint
;
141 ImplRegionBandPoint
* pTempPoint
= pPoint
->mpNextBandPoint
;
147 // -----------------------------------------------------------------------
149 // generate separations from lines and process union with existing
152 void ImplRegionBand::ProcessPoints()
155 ImplRegionBandPoint
* pRegionBandPoint
= mpFirstBandPoint
;
156 while ( pRegionBandPoint
)
159 if ( pRegionBandPoint
->mpNextBandPoint
)
162 if ( pRegionBandPoint
->mbEndPoint
&& pRegionBandPoint
->mpNextBandPoint
->mbEndPoint
)
164 // same direction? -> remove next point!
165 if ( pRegionBandPoint
->meLineType
== pRegionBandPoint
->mpNextBandPoint
->meLineType
)
167 ImplRegionBandPoint
* pSaveRegionBandPoint
= pRegionBandPoint
->mpNextBandPoint
;
168 pRegionBandPoint
->mpNextBandPoint
= pRegionBandPoint
->mpNextBandPoint
->mpNextBandPoint
;
169 delete pSaveRegionBandPoint
;
174 // continue with next element in the list
175 pRegionBandPoint
= pRegionBandPoint
->mpNextBandPoint
;
178 pRegionBandPoint
= mpFirstBandPoint
;
179 while ( pRegionBandPoint
&& pRegionBandPoint
->mpNextBandPoint
)
181 Union( pRegionBandPoint
->mnX
, pRegionBandPoint
->mpNextBandPoint
->mnX
);
183 ImplRegionBandPoint
* pNextBandPoint
= pRegionBandPoint
->mpNextBandPoint
->mpNextBandPoint
;
185 // remove already processed points
186 delete pRegionBandPoint
->mpNextBandPoint
;
187 delete pRegionBandPoint
;
189 // continue with next element in the list
190 pRegionBandPoint
= pNextBandPoint
;
193 // remove last element if necessary
194 delete pRegionBandPoint
;
197 mpFirstBandPoint
= NULL
;
200 // -----------------------------------------------------------------------
202 // generate separations from lines and process union with existing
205 sal_Bool
ImplRegionBand::InsertPoint( long nX
, long nLineId
,
206 sal_Bool bEndPoint
, LineType eLineType
)
208 if ( !mpFirstBandPoint
)
210 mpFirstBandPoint
= new ImplRegionBandPoint
;
211 mpFirstBandPoint
->mnX
= nX
;
212 mpFirstBandPoint
->mnLineId
= nLineId
;
213 mpFirstBandPoint
->mbEndPoint
= bEndPoint
;
214 mpFirstBandPoint
->meLineType
= eLineType
;
215 mpFirstBandPoint
->mpNextBandPoint
= NULL
;
219 // look if line already touched the band
220 ImplRegionBandPoint
* pRegionBandPoint
= mpFirstBandPoint
;
221 ImplRegionBandPoint
* pLastTestedRegionBandPoint
= NULL
;
222 while( pRegionBandPoint
)
224 if ( pRegionBandPoint
->mnLineId
== nLineId
)
228 if( !pRegionBandPoint
->mbEndPoint
)
230 // remove old band point
231 if( !mpFirstBandPoint
->mpNextBandPoint
)
233 // if we've only got one point => replace first point
234 pRegionBandPoint
->mnX
= nX
;
235 pRegionBandPoint
->mbEndPoint
= sal_True
;
240 // remove current point
241 if( !pLastTestedRegionBandPoint
)
243 // remove and delete old first point
244 ImplRegionBandPoint
* pSaveBandPoint
= mpFirstBandPoint
;
245 mpFirstBandPoint
= mpFirstBandPoint
->mpNextBandPoint
;
246 delete pSaveBandPoint
;
250 // remove and delete current band point
251 pLastTestedRegionBandPoint
->mpNextBandPoint
= pRegionBandPoint
->mpNextBandPoint
;
252 delete pRegionBandPoint
;
264 pLastTestedRegionBandPoint
= pRegionBandPoint
;
265 pRegionBandPoint
= pRegionBandPoint
->mpNextBandPoint
;
268 // search appropriate position and insert point into the list
269 ImplRegionBandPoint
* pNewRegionBandPoint
;
271 pRegionBandPoint
= mpFirstBandPoint
;
272 pLastTestedRegionBandPoint
= NULL
;
273 while ( pRegionBandPoint
)
275 // new point completely left? -> insert as first point
276 if ( nX
<= pRegionBandPoint
->mnX
)
278 pNewRegionBandPoint
= new ImplRegionBandPoint
;
279 pNewRegionBandPoint
->mnX
= nX
;
280 pNewRegionBandPoint
->mnLineId
= nLineId
;
281 pNewRegionBandPoint
->mbEndPoint
= bEndPoint
;
282 pNewRegionBandPoint
->meLineType
= eLineType
;
283 pNewRegionBandPoint
->mpNextBandPoint
= pRegionBandPoint
;
285 // connections to the new point
286 if ( !pLastTestedRegionBandPoint
)
287 mpFirstBandPoint
= pNewRegionBandPoint
;
289 pLastTestedRegionBandPoint
->mpNextBandPoint
= pNewRegionBandPoint
;
295 pLastTestedRegionBandPoint
= pRegionBandPoint
;
296 pRegionBandPoint
= pRegionBandPoint
->mpNextBandPoint
;
299 // not inserted -> add to the end of the list
300 pNewRegionBandPoint
= new ImplRegionBandPoint
;
301 pNewRegionBandPoint
->mnX
= nX
;
302 pNewRegionBandPoint
->mnLineId
= nLineId
;
303 pNewRegionBandPoint
->mbEndPoint
= bEndPoint
;
304 pNewRegionBandPoint
->meLineType
= eLineType
;
305 pNewRegionBandPoint
->mpNextBandPoint
= NULL
;
307 // connections to the new point
308 pLastTestedRegionBandPoint
->mpNextBandPoint
= pNewRegionBandPoint
;
313 // -----------------------------------------------------------------------
315 void ImplRegionBand::MoveX( long nHorzMove
)
317 // move all x-separations
318 ImplRegionBandSep
* pSep
= mpFirstSep
;
321 pSep
->mnXLeft
+= nHorzMove
;
322 pSep
->mnXRight
+= nHorzMove
;
323 pSep
= pSep
->mpNextSep
;
327 // -----------------------------------------------------------------------
329 void ImplRegionBand::ScaleX( double fHorzScale
)
331 ImplRegionBandSep
* pSep
= mpFirstSep
;
334 pSep
->mnXLeft
= FRound( pSep
->mnXLeft
* fHorzScale
);
335 pSep
->mnXRight
= FRound( pSep
->mnXRight
* fHorzScale
);
336 pSep
= pSep
->mpNextSep
;
340 // -----------------------------------------------------------------------
342 // combine overlaping sparations
344 sal_Bool
ImplRegionBand::OptimizeBand()
346 ImplRegionBandSep
* pPrevSep
= 0;
347 ImplRegionBandSep
* pSep
= mpFirstSep
;
351 if ( pSep
->mbRemoved
|| (pSep
->mnXRight
< pSep
->mnXLeft
) )
353 ImplRegionBandSep
* pOldSep
= pSep
;
354 if ( pSep
== mpFirstSep
)
355 mpFirstSep
= pSep
->mpNextSep
;
357 pPrevSep
->mpNextSep
= pSep
->mpNextSep
;
358 pSep
= pSep
->mpNextSep
;
363 // overlaping separations? -> combine!
364 if ( pSep
->mpNextSep
)
366 if ( (pSep
->mnXRight
+1) >= pSep
->mpNextSep
->mnXLeft
)
368 if ( pSep
->mpNextSep
->mnXRight
> pSep
->mnXRight
)
369 pSep
->mnXRight
= pSep
->mpNextSep
->mnXRight
;
371 ImplRegionBandSep
* pOldSep
= pSep
->mpNextSep
;
372 pSep
->mpNextSep
= pOldSep
->mpNextSep
;
379 pSep
= pSep
->mpNextSep
;
385 // -----------------------------------------------------------------------
387 void ImplRegionBand::Union( long nXLeft
, long nXRight
)
389 DBG_ASSERT( nXLeft
<= nXRight
, "ImplRegionBand::Union(): nxLeft > nXRight" );
391 // band empty? -> add element
394 mpFirstSep
= new ImplRegionBandSep
;
395 mpFirstSep
->mnXLeft
= nXLeft
;
396 mpFirstSep
->mnXRight
= nXRight
;
397 mpFirstSep
->mbRemoved
= sal_False
;
398 mpFirstSep
->mpNextSep
= NULL
;
402 // process real union
403 ImplRegionBandSep
* pNewSep
;
404 ImplRegionBandSep
* pPrevSep
= 0;
405 ImplRegionBandSep
* pSep
= mpFirstSep
;
408 // new separation completely inside? nothing to do!
409 if ( (nXLeft
>= pSep
->mnXLeft
) && (nXRight
<= pSep
->mnXRight
) )
412 // new separation completely left? -> new separation!
413 if ( nXRight
< pSep
->mnXLeft
)
415 pNewSep
= new ImplRegionBandSep
;
416 pNewSep
->mnXLeft
= nXLeft
;
417 pNewSep
->mnXRight
= nXRight
;
418 pNewSep
->mbRemoved
= sal_False
;
420 pNewSep
->mpNextSep
= pSep
;
421 if ( pSep
== mpFirstSep
)
422 mpFirstSep
= pNewSep
;
424 pPrevSep
->mpNextSep
= pNewSep
;
428 // new separation overlaping from left? -> extend boundary
429 if ( (nXRight
>= pSep
->mnXLeft
) && (nXLeft
<= pSep
->mnXLeft
) )
430 pSep
->mnXLeft
= nXLeft
;
432 // new separation overlaping from right? -> extend boundary
433 if ( (nXLeft
<= pSep
->mnXRight
) && (nXRight
> pSep
->mnXRight
) )
435 pSep
->mnXRight
= nXRight
;
439 // not inserted, but last element? -> add to the end of the list
440 if ( !pSep
->mpNextSep
&& (nXLeft
> pSep
->mnXRight
) )
442 pNewSep
= new ImplRegionBandSep
;
443 pNewSep
->mnXLeft
= nXLeft
;
444 pNewSep
->mnXRight
= nXRight
;
445 pNewSep
->mbRemoved
= sal_False
;
447 pSep
->mpNextSep
= pNewSep
;
448 pNewSep
->mpNextSep
= NULL
;
453 pSep
= pSep
->mpNextSep
;
459 // -----------------------------------------------------------------------
461 void ImplRegionBand::Intersect( long nXLeft
, long nXRight
)
463 DBG_ASSERT( nXLeft
<= nXRight
, "ImplRegionBand::Intersect(): nxLeft > nXRight" );
465 // band has been touched
466 mbTouched
= sal_True
;
468 // band empty? -> nothing to do
472 // process real intersection
473 ImplRegionBandSep
* pSep
= mpFirstSep
;
476 // new separation completely outside? -> remove separation
477 if ( (nXRight
< pSep
->mnXLeft
) || (nXLeft
> pSep
->mnXRight
) )
478 // will be removed from the optimizer
479 pSep
->mbRemoved
= sal_True
;
481 // new separation overlaping from left? -> reduce right boundary
482 if ( (nXLeft
<= pSep
->mnXLeft
) &&
483 (nXRight
<= pSep
->mnXRight
) &&
484 (nXRight
>= pSep
->mnXLeft
) )
485 pSep
->mnXRight
= nXRight
;
487 // new separation overlaping from right? -> reduce right boundary
488 if ( (nXLeft
>= pSep
->mnXLeft
) &&
489 (nXLeft
<= pSep
->mnXRight
) &&
490 (nXRight
>= pSep
->mnXRight
) )
491 pSep
->mnXLeft
= nXLeft
;
493 // new separation within the actual one? -> reduce both boundaries
494 if ( (nXLeft
>= pSep
->mnXLeft
) && (nXRight
<= pSep
->mnXRight
) )
496 pSep
->mnXRight
= nXRight
;
497 pSep
->mnXLeft
= nXLeft
;
500 pSep
= pSep
->mpNextSep
;
506 // -----------------------------------------------------------------------
508 void ImplRegionBand::Exclude( long nXLeft
, long nXRight
)
510 DBG_ASSERT( nXLeft
<= nXRight
, "ImplRegionBand::Exclude(): nxLeft > nXRight" );
512 // band has been touched
513 mbTouched
= sal_True
;
515 // band empty? -> nothing to do
519 // process real exclusion
520 ImplRegionBandSep
* pNewSep
;
521 ImplRegionBandSep
* pPrevSep
= 0;
522 ImplRegionBandSep
* pSep
= mpFirstSep
;
525 sal_Bool bSepProcessed
= sal_False
;
527 // new separation completely overlapping? -> remove separation
528 if ( (nXLeft
<= pSep
->mnXLeft
) && (nXRight
>= pSep
->mnXRight
) )
530 // will be removed from the optimizer
531 pSep
->mbRemoved
= sal_True
;
532 bSepProcessed
= sal_True
;
535 // new separation overlaping from left? -> reduce boundary
536 if ( !bSepProcessed
)
538 if ( (nXRight
>= pSep
->mnXLeft
) && (nXLeft
<= pSep
->mnXLeft
) )
540 pSep
->mnXLeft
= nXRight
+1;
541 bSepProcessed
= sal_True
;
545 // new separation overlaping from right? -> reduce boundary
546 if ( !bSepProcessed
)
548 if ( (nXLeft
<= pSep
->mnXRight
) && (nXRight
> pSep
->mnXRight
) )
550 pSep
->mnXRight
= nXLeft
-1;
551 bSepProcessed
= sal_True
;
555 // new separation within the actual one? -> reduce boundary
556 // and add new entry for reminder
557 if ( !bSepProcessed
)
559 if ( (nXLeft
>= pSep
->mnXLeft
) && (nXRight
<= pSep
->mnXRight
) )
561 pNewSep
= new ImplRegionBandSep
;
562 pNewSep
->mnXLeft
= pSep
->mnXLeft
;
563 pNewSep
->mnXRight
= nXLeft
-1;
564 pNewSep
->mbRemoved
= sal_False
;
566 pSep
->mnXLeft
= nXRight
+1;
568 // connections from the new separation
569 pNewSep
->mpNextSep
= pSep
;
571 // connections to the new separation
572 if ( pSep
== mpFirstSep
)
573 mpFirstSep
= pNewSep
;
575 pPrevSep
->mpNextSep
= pNewSep
;
580 pSep
= pSep
->mpNextSep
;
586 // -----------------------------------------------------------------------
588 void ImplRegionBand::XOr( long nXLeft
, long nXRight
)
590 DBG_ASSERT( nXLeft
<= nXRight
, "ImplRegionBand::XOr(): nxLeft > nXRight" );
592 // #i46602# Reworked rectangle Xor
594 // In general, we can distinguish 11 cases of intersection
595 // (details below). The old implementation explicitly handled 7
596 // cases (numbered in the order of appearance, use CVS to get your
597 // hands on the old version), therefore, I've sticked to that
598 // order, and added four more cases. The code below references
599 // those numbers via #1, #2, etc.
601 // Num Mnem newX:oldX newY:oldY Description Result Can quit?
603 // #1 Empty band - - The band is empty, thus, simply add new bandSep just add Yes
605 // #2 apart - - The rectangles are disjunct, add new one as is just add Yes
607 // #3 atop == == The rectangles are _exactly_ the same, remove existing just remove Yes
609 // #4 around < > The new rectangle extends the old to both sides intersect No
611 // #5 left < < The new rectangle is left of the old (but intersects) intersect Yes
613 // #5b left-atop < == The new is left of the old, and coincides on the right intersect Yes
615 // #6 right > > The new is right of the old (but intersects) intersect No
617 // #6b right-atop == > The new is right of the old, and coincides on the left intersect No
619 // #7 inside > < The new is fully inside the old intersect Yes
621 // #8 inside-right > == The new is fully inside the old, coincides on the right intersect Yes
623 // #9 inside-left == < The new is fully inside the old, coincides on the left intersect Yes
626 // Then, to correctly perform XOr, the segment that's switched off
627 // (i.e. the overlapping part of the old and the new segment) must
628 // be extended by one pixel value at each border:
633 // Clearly, the leading band sep now goes from 0 to 3, and the
634 // trailing band sep from 11 to 14. This mimicks the xor look of a
638 // band empty? -> add element
641 mpFirstSep
= new ImplRegionBandSep
;
642 mpFirstSep
->mnXLeft
= nXLeft
;
643 mpFirstSep
->mnXRight
= nXRight
;
644 mpFirstSep
->mbRemoved
= sal_False
;
645 mpFirstSep
->mpNextSep
= NULL
;
650 ImplRegionBandSep
* pNewSep
;
651 ImplRegionBandSep
* pPrevSep
= 0;
652 ImplRegionBandSep
* pSep
= mpFirstSep
;
656 long nOldLeft( pSep
->mnXLeft
);
657 long nOldRight( pSep
->mnXRight
);
659 // did the current segment actually touch the new rect? If
660 // not, skip all comparisons, go on, loop and try to find
661 // intersecting bandSep
662 if( nXLeft
<= nOldRight
)
664 if( nXRight
< nOldLeft
)
668 // add _before_ current bandSep
669 pNewSep
= new ImplRegionBandSep
;
670 pNewSep
->mnXLeft
= nXLeft
;
671 pNewSep
->mnXRight
= nXRight
;
672 pNewSep
->mpNextSep
= pSep
;
673 pNewSep
->mbRemoved
= sal_False
;
675 // connections from the new separation
676 pNewSep
->mpNextSep
= pSep
;
678 // connections to the new separation
679 if ( pSep
== mpFirstSep
)
680 mpFirstSep
= pNewSep
;
682 pPrevSep
->mpNextSep
= pNewSep
;
683 pPrevSep
= NULL
; // do not run accidentally into the "right" case when breaking the loop
686 else if( nXLeft
== nOldLeft
&& nXRight
== nOldRight
)
689 pSep
->mbRemoved
= sal_True
;
690 pPrevSep
= NULL
; // do not run accidentally into the "right" case when breaking the loop
693 else if( nXLeft
!= nOldLeft
&& nXRight
== nOldRight
)
696 if( nXLeft
< nOldLeft
)
698 nXRight
= nOldLeft
; // 5b
702 nXRight
= nXLeft
; // 8
706 pSep
->mnXLeft
= nXLeft
;
707 pSep
->mnXRight
= nXRight
-1;
709 pPrevSep
= NULL
; // do not run accidentally into the "right" case when breaking the loop
712 else if( nXLeft
== nOldLeft
&& nXRight
!= nOldRight
)
716 if( nXRight
> nOldRight
)
718 nXLeft
= nOldRight
+1; // 6b
720 // cannot break here, simply mark segment as removed,
721 // and go on with adapted nXLeft/nXRight
722 pSep
->mbRemoved
= sal_True
;
726 pSep
->mnXLeft
= nXRight
+1; // 9
728 pPrevSep
= NULL
; // do not run accidentally into the "right" case when breaking the loop
732 else // if( nXLeft != nOldLeft && nXRight != nOldRight ) follows automatically
735 DBG_ASSERT( nXLeft
!= nOldLeft
&& nXRight
!= nOldRight
,
736 "ImplRegionBand::XOr(): Case 4,5,6,7 expected all coordinates to be not equal!" );
738 // The plain-jane check would look like this:
740 // if( nXLeft < nOldLeft )
743 // if( nXRight > nOldRight )
755 // if( nXRight > nOldRight )
765 // but since we generally don't have to care whether
766 // it's 4 or 6 (only that we must not stop processing
767 // here), condensed that in such a way that only the
768 // coordinates get shuffled into correct ordering.
770 if( nXLeft
< nOldLeft
)
771 ::std::swap( nOldLeft
, nXLeft
);
775 if( nXRight
< nOldRight
)
777 ::std::swap( nOldRight
, nXRight
);
781 // now, nOldLeft<nXLeft<=nOldRight<nXRight always
782 // holds. Note that we need the nXLeft<=nOldRight here, as
783 // the intersection part might be only one pixel (original
785 DBG_ASSERT( nOldLeft
<nXLeft
&& nXLeft
<=nOldRight
&& nOldRight
<nXRight
,
786 "ImplRegionBand::XOr(): Case 4,5,6,7 expected coordinates to be ordered now!" );
788 pSep
->mnXLeft
= nOldLeft
;
789 pSep
->mnXRight
= nXLeft
-1;
791 nXLeft
= nOldRight
+1;
792 // nxRight is already setup correctly
796 // add behind current bandSep
797 pNewSep
= new ImplRegionBandSep
;
799 pNewSep
->mnXLeft
= nXLeft
;
800 pNewSep
->mnXRight
= nXRight
;
801 pNewSep
->mpNextSep
= pSep
->mpNextSep
;
802 pNewSep
->mbRemoved
= sal_False
;
804 // connections from the new separation
805 pSep
->mpNextSep
= pNewSep
;
807 pPrevSep
= NULL
; // do not run accidentally into the "right" case when breaking the loop
814 pSep
= pSep
->mpNextSep
;
817 // new separation completely right of existing bandSeps ?
818 if( pPrevSep
&& nXLeft
>= pPrevSep
->mnXRight
)
820 pNewSep
= new ImplRegionBandSep
;
821 pNewSep
->mnXLeft
= nXLeft
;
822 pNewSep
->mnXRight
= nXRight
;
823 pNewSep
->mpNextSep
= NULL
;
824 pNewSep
->mbRemoved
= sal_False
;
826 // connections from the new separation
827 pPrevSep
->mpNextSep
= pNewSep
;
833 // -----------------------------------------------------------------------
835 sal_Bool
ImplRegionBand::IsInside( long nX
)
837 ImplRegionBandSep
* pSep
= mpFirstSep
;
840 if ( (pSep
->mnXLeft
<= nX
) && (pSep
->mnXRight
>= nX
) )
843 pSep
= pSep
->mpNextSep
;
849 // -----------------------------------------------------------------------
851 long ImplRegionBand::GetXLeftBoundary() const
853 DBG_ASSERT( mpFirstSep
!= NULL
, "ImplRegionBand::XLeftBoundary -> no separation in band!" );
855 return mpFirstSep
->mnXLeft
;
858 // -----------------------------------------------------------------------
860 long ImplRegionBand::GetXRightBoundary() const
862 DBG_ASSERT( mpFirstSep
!= NULL
, "ImplRegionBand::XRightBoundary -> no separation in band!" );
864 // search last separation
865 ImplRegionBandSep
* pSep
= mpFirstSep
;
866 while ( pSep
->mpNextSep
)
867 pSep
= pSep
->mpNextSep
;
868 return pSep
->mnXRight
;
871 // -----------------------------------------------------------------------
873 sal_Bool
ImplRegionBand::operator==( const ImplRegionBand
& rRegionBand
) const
875 ImplRegionBandSep
* pOwnRectBandSep
= mpFirstSep
;
876 ImplRegionBandSep
* pSecondRectBandSep
= rRegionBand
.mpFirstSep
;
877 while ( pOwnRectBandSep
&& pSecondRectBandSep
)
879 // get boundaries of current rectangle
880 long nOwnXLeft
= pOwnRectBandSep
->mnXLeft
;
881 long nSecondXLeft
= pSecondRectBandSep
->mnXLeft
;
882 if ( nOwnXLeft
!= nSecondXLeft
)
885 long nOwnXRight
= pOwnRectBandSep
->mnXRight
;
886 long nSecondXRight
= pSecondRectBandSep
->mnXRight
;
887 if ( nOwnXRight
!= nSecondXRight
)
890 // get next separation from current band
891 pOwnRectBandSep
= pOwnRectBandSep
->mpNextSep
;
893 // get next separation from current band
894 pSecondRectBandSep
= pSecondRectBandSep
->mpNextSep
;
897 // different number of separations?
898 if ( pOwnRectBandSep
|| pSecondRectBandSep
)
904 // -----------------------------------------------------------------------
906 ImplRegionBand
* ImplRegionBand::SplitBand (const sal_Int32 nY
)
908 OSL_ASSERT(nY
>mnYTop
);
909 OSL_ASSERT(nY
<=mnYBottom
);
911 // Create a copy of the given band (we tell the constructor to copy the points together
913 ImplRegionBand
* pLowerBand
= new ImplRegionBand(*this, false);
915 // Adapt vertical coordinates.
917 pLowerBand
->mnYTop
= nY
;
919 // Insert new band into list of bands.
920 pLowerBand
->mpNextBand
= mpNextBand
;
921 mpNextBand
= pLowerBand
;
922 pLowerBand
->mpPrevBand
= this;
923 if (pLowerBand
->mpNextBand
!= NULL
)
924 pLowerBand
->mpNextBand
->mpPrevBand
= pLowerBand
;
929 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */