1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: regband.cxx,v $
10 * $Revision: 1.9.158.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
33 #include <tools/debug.hxx>
34 #include <vcl/salbtype.hxx>
35 #include <vcl/regband.hxx>
40 // =======================================================================
44 // Jedes Band enthaelt die zwischen der enthaltenen Ober- und Untergrenze
45 // enthaltenen Rechtecke. Bei den Operationen Union, Intersect, XOr und
46 // Exclude werden immer Rechtecke der gleichen Hoehe ausgewerte; die
47 // Grenzen der Baender sind immer so zu waehlen, dasz dies moeglich ist.
49 // Die Rechtecke in den Baendern werden nach Moeglichkeit zusammengefaszt.
51 // Bei der Umwandlung von Polygonen werden alle Punkte des Polygons
52 // in die einzelnen Baender eingetragen (sie stehen fuer jedes Band als
53 // Punkte in einer Liste). Nach dem Eintragen der Punkte werden diese
54 // in Rechtecke umgewandelt und die Liste der Punkte geloescht.
56 // -----------------------------------------------------------------------
58 ImplRegionBand::ImplRegionBand( long nTop
, long nBottom
)
68 mpFirstBandPoint
= NULL
;
72 // -----------------------------------------------------------------------
74 ImplRegionBand::ImplRegionBand(
75 const ImplRegionBand
& rRegionBand
,
76 const bool bIgnorePoints
)
79 mnYTop
= rRegionBand
.mnYTop
;
80 mnYBottom
= rRegionBand
.mnYBottom
;
81 mbTouched
= rRegionBand
.mbTouched
;
87 mpFirstBandPoint
= NULL
;
89 // copy all elements of the list with separations
90 ImplRegionBandSep
* pNewSep
;
91 ImplRegionBandSep
* pPrevSep
= 0;
92 ImplRegionBandSep
* pSep
= rRegionBand
.mpFirstSep
;
95 // create new and copy data
96 pNewSep
= new ImplRegionBandSep
;
97 pNewSep
->mnXLeft
= pSep
->mnXLeft
;
98 pNewSep
->mnXRight
= pSep
->mnXRight
;
99 pNewSep
->mbRemoved
= pSep
->mbRemoved
;
100 pNewSep
->mpNextSep
= NULL
;
101 if ( pSep
== rRegionBand
.mpFirstSep
)
102 mpFirstSep
= pNewSep
;
104 pPrevSep
->mpNextSep
= pNewSep
;
107 pSep
= pSep
->mpNextSep
;
110 if ( ! bIgnorePoints
)
113 ImplRegionBandPoint
* pPoint
= mpFirstBandPoint
;
114 ImplRegionBandPoint
* pPrevPointCopy
= NULL
;
115 while (pPoint
!= NULL
)
117 ImplRegionBandPoint
* pPointCopy
= new ImplRegionBandPoint();
118 pPointCopy
->mnX
= pPoint
->mnX
;
119 pPointCopy
->mnLineId
= pPoint
->mnLineId
;
120 pPointCopy
->mbEndPoint
= pPoint
->mbEndPoint
;
121 pPointCopy
->meLineType
= pPoint
->meLineType
;
123 if (pPrevPointCopy
!= NULL
)
124 pPrevPointCopy
->mpNextBandPoint
= pPointCopy
;
126 mpFirstBandPoint
= pPointCopy
;
128 pPrevPointCopy
= pPointCopy
;
129 pPoint
= pPoint
->mpNextBandPoint
;
134 // -----------------------------------------------------------------------
136 ImplRegionBand::~ImplRegionBand()
138 DBG_ASSERT( mpFirstBandPoint
== NULL
, "ImplRegionBand::~ImplRegionBand -> pointlist not empty" );
140 // delete elements of the list
141 ImplRegionBandSep
* pSep
= mpFirstSep
;
144 ImplRegionBandSep
* pTempSep
= pSep
->mpNextSep
;
149 // delete elements of the list
150 ImplRegionBandPoint
* pPoint
= mpFirstBandPoint
;
153 ImplRegionBandPoint
* pTempPoint
= pPoint
->mpNextBandPoint
;
159 // -----------------------------------------------------------------------
161 // generate separations from lines and process union with existing
164 void ImplRegionBand::ProcessPoints()
167 ImplRegionBandPoint
* pRegionBandPoint
= mpFirstBandPoint
;
168 while ( pRegionBandPoint
)
171 if ( pRegionBandPoint
&& pRegionBandPoint
->mpNextBandPoint
)
174 if ( pRegionBandPoint
->mbEndPoint
&& pRegionBandPoint
->mpNextBandPoint
->mbEndPoint
)
176 // same direction? -> remove next point!
177 if ( pRegionBandPoint
->meLineType
== pRegionBandPoint
->mpNextBandPoint
->meLineType
)
179 ImplRegionBandPoint
* pSaveRegionBandPoint
= pRegionBandPoint
->mpNextBandPoint
;
180 pRegionBandPoint
->mpNextBandPoint
= pRegionBandPoint
->mpNextBandPoint
->mpNextBandPoint
;
181 delete pSaveRegionBandPoint
;
186 // continue with next element in the list
187 pRegionBandPoint
= pRegionBandPoint
->mpNextBandPoint
;
190 pRegionBandPoint
= mpFirstBandPoint
;
191 while ( pRegionBandPoint
&& pRegionBandPoint
->mpNextBandPoint
)
193 Union( pRegionBandPoint
->mnX
, pRegionBandPoint
->mpNextBandPoint
->mnX
);
195 ImplRegionBandPoint
* pNextBandPoint
= pRegionBandPoint
->mpNextBandPoint
->mpNextBandPoint
;
197 // remove allready processed points
198 delete pRegionBandPoint
->mpNextBandPoint
;
199 delete pRegionBandPoint
;
201 // continue with next element in the list
202 pRegionBandPoint
= pNextBandPoint
;
205 // remove last element if necessary
206 if ( pRegionBandPoint
)
207 delete pRegionBandPoint
;
210 mpFirstBandPoint
= NULL
;
213 // -----------------------------------------------------------------------
215 // generate separations from lines and process union with existing
218 BOOL
ImplRegionBand::InsertPoint( long nX
, long nLineId
,
219 BOOL bEndPoint
, LineType eLineType
)
221 if ( !mpFirstBandPoint
)
223 mpFirstBandPoint
= new ImplRegionBandPoint
;
224 mpFirstBandPoint
->mnX
= nX
;
225 mpFirstBandPoint
->mnLineId
= nLineId
;
226 mpFirstBandPoint
->mbEndPoint
= bEndPoint
;
227 mpFirstBandPoint
->meLineType
= eLineType
;
228 mpFirstBandPoint
->mpNextBandPoint
= NULL
;
232 // look if line allready touched the band
233 ImplRegionBandPoint
* pRegionBandPoint
= mpFirstBandPoint
;
234 ImplRegionBandPoint
* pLastTestedRegionBandPoint
= NULL
;
235 while( pRegionBandPoint
)
237 if ( pRegionBandPoint
->mnLineId
== nLineId
)
241 if( !pRegionBandPoint
->mbEndPoint
)
243 // remove old band point
244 if( !mpFirstBandPoint
->mpNextBandPoint
)
246 // if we've only got one point => replace first point
247 pRegionBandPoint
->mnX
= nX
;
248 pRegionBandPoint
->mbEndPoint
= TRUE
;
253 // remove current point
254 if( !pLastTestedRegionBandPoint
)
256 // remove and delete old first point
257 ImplRegionBandPoint
* pSaveBandPoint
= mpFirstBandPoint
;
258 mpFirstBandPoint
= mpFirstBandPoint
->mpNextBandPoint
;
259 delete pSaveBandPoint
;
263 // remove and delete current band point
264 pLastTestedRegionBandPoint
->mpNextBandPoint
= pRegionBandPoint
->mpNextBandPoint
;
265 delete pRegionBandPoint
;
277 pLastTestedRegionBandPoint
= pRegionBandPoint
;
278 pRegionBandPoint
= pRegionBandPoint
->mpNextBandPoint
;
281 // search appropriate position and insert point into the list
282 ImplRegionBandPoint
* pNewRegionBandPoint
;
284 pRegionBandPoint
= mpFirstBandPoint
;
285 pLastTestedRegionBandPoint
= NULL
;
286 while ( pRegionBandPoint
)
288 // new point completly left? -> insert as first point
289 if ( nX
<= pRegionBandPoint
->mnX
)
291 pNewRegionBandPoint
= new ImplRegionBandPoint
;
292 pNewRegionBandPoint
->mnX
= nX
;
293 pNewRegionBandPoint
->mnLineId
= nLineId
;
294 pNewRegionBandPoint
->mbEndPoint
= bEndPoint
;
295 pNewRegionBandPoint
->meLineType
= eLineType
;
296 pNewRegionBandPoint
->mpNextBandPoint
= pRegionBandPoint
;
298 // connections to the new point
299 if ( !pLastTestedRegionBandPoint
)
300 mpFirstBandPoint
= pNewRegionBandPoint
;
302 pLastTestedRegionBandPoint
->mpNextBandPoint
= pNewRegionBandPoint
;
308 pLastTestedRegionBandPoint
= pRegionBandPoint
;
309 pRegionBandPoint
= pRegionBandPoint
->mpNextBandPoint
;
312 // not inserted -> add to the end of the list
313 pNewRegionBandPoint
= new ImplRegionBandPoint
;
314 pNewRegionBandPoint
->mnX
= nX
;
315 pNewRegionBandPoint
->mnLineId
= nLineId
;
316 pNewRegionBandPoint
->mbEndPoint
= bEndPoint
;
317 pNewRegionBandPoint
->meLineType
= eLineType
;
318 pNewRegionBandPoint
->mpNextBandPoint
= NULL
;
320 // connections to the new point
321 pLastTestedRegionBandPoint
->mpNextBandPoint
= pNewRegionBandPoint
;
326 // -----------------------------------------------------------------------
328 void ImplRegionBand::MoveX( long nHorzMove
)
330 // move all x-separations
331 ImplRegionBandSep
* pSep
= mpFirstSep
;
334 pSep
->mnXLeft
+= nHorzMove
;
335 pSep
->mnXRight
+= nHorzMove
;
336 pSep
= pSep
->mpNextSep
;
340 // -----------------------------------------------------------------------
342 void ImplRegionBand::ScaleX( double fHorzScale
)
344 ImplRegionBandSep
* pSep
= mpFirstSep
;
347 pSep
->mnXLeft
= FRound( pSep
->mnXLeft
* fHorzScale
);
348 pSep
->mnXRight
= FRound( pSep
->mnXRight
* fHorzScale
);
349 pSep
= pSep
->mpNextSep
;
353 // -----------------------------------------------------------------------
355 // combine overlaping sparations
357 BOOL
ImplRegionBand::OptimizeBand()
359 ImplRegionBandSep
* pPrevSep
= 0;
360 ImplRegionBandSep
* pSep
= mpFirstSep
;
364 if ( pSep
->mbRemoved
|| (pSep
->mnXRight
< pSep
->mnXLeft
) )
366 ImplRegionBandSep
* pOldSep
= pSep
;
367 if ( pSep
== mpFirstSep
)
368 mpFirstSep
= pSep
->mpNextSep
;
370 pPrevSep
->mpNextSep
= pSep
->mpNextSep
;
371 pSep
= pSep
->mpNextSep
;
376 // overlaping separations? -> combine!
377 if ( pSep
->mpNextSep
)
379 if ( (pSep
->mnXRight
+1) >= pSep
->mpNextSep
->mnXLeft
)
381 if ( pSep
->mpNextSep
->mnXRight
> pSep
->mnXRight
)
382 pSep
->mnXRight
= pSep
->mpNextSep
->mnXRight
;
384 ImplRegionBandSep
* pOldSep
= pSep
->mpNextSep
;
385 pSep
->mpNextSep
= pOldSep
->mpNextSep
;
392 pSep
= pSep
->mpNextSep
;
398 // -----------------------------------------------------------------------
400 void ImplRegionBand::Union( long nXLeft
, long nXRight
)
402 DBG_ASSERT( nXLeft
<= nXRight
, "ImplRegionBand::Union(): nxLeft > nXRight" );
404 // band empty? -> add element
407 mpFirstSep
= new ImplRegionBandSep
;
408 mpFirstSep
->mnXLeft
= nXLeft
;
409 mpFirstSep
->mnXRight
= nXRight
;
410 mpFirstSep
->mbRemoved
= FALSE
;
411 mpFirstSep
->mpNextSep
= NULL
;
415 // process real union
416 ImplRegionBandSep
* pNewSep
;
417 ImplRegionBandSep
* pPrevSep
= 0;
418 ImplRegionBandSep
* pSep
= mpFirstSep
;
421 // new separation completely inside? nothing to do!
422 if ( (nXLeft
>= pSep
->mnXLeft
) && (nXRight
<= pSep
->mnXRight
) )
425 // new separation completly left? -> new separation!
426 if ( nXRight
< pSep
->mnXLeft
)
428 pNewSep
= new ImplRegionBandSep
;
429 pNewSep
->mnXLeft
= nXLeft
;
430 pNewSep
->mnXRight
= nXRight
;
431 pNewSep
->mbRemoved
= FALSE
;
433 pNewSep
->mpNextSep
= pSep
;
434 if ( pSep
== mpFirstSep
)
435 mpFirstSep
= pNewSep
;
437 pPrevSep
->mpNextSep
= pNewSep
;
441 // new separation overlaping from left? -> extend boundary
442 if ( (nXRight
>= pSep
->mnXLeft
) && (nXLeft
<= pSep
->mnXLeft
) )
443 pSep
->mnXLeft
= nXLeft
;
445 // new separation overlaping from right? -> extend boundary
446 if ( (nXLeft
<= pSep
->mnXRight
) && (nXRight
> pSep
->mnXRight
) )
448 pSep
->mnXRight
= nXRight
;
452 // not inserted, but last element? -> add to the end of the list
453 if ( !pSep
->mpNextSep
&& (nXLeft
> pSep
->mnXRight
) )
455 pNewSep
= new ImplRegionBandSep
;
456 pNewSep
->mnXLeft
= nXLeft
;
457 pNewSep
->mnXRight
= nXRight
;
458 pNewSep
->mbRemoved
= FALSE
;
460 pSep
->mpNextSep
= pNewSep
;
461 pNewSep
->mpNextSep
= NULL
;
466 pSep
= pSep
->mpNextSep
;
472 // -----------------------------------------------------------------------
474 void ImplRegionBand::Intersect( long nXLeft
, long nXRight
)
476 DBG_ASSERT( nXLeft
<= nXRight
, "ImplRegionBand::Intersect(): nxLeft > nXRight" );
478 // band has been touched
481 // band empty? -> nothing to do
485 // process real intersection
486 ImplRegionBandSep
* pSep
= mpFirstSep
;
489 // new separation completly outside? -> remove separation
490 if ( (nXRight
< pSep
->mnXLeft
) || (nXLeft
> pSep
->mnXRight
) )
491 // will be removed from the optimizer
492 pSep
->mbRemoved
= TRUE
;
494 // new separation overlaping from left? -> reduce right boundary
495 if ( (nXLeft
<= pSep
->mnXLeft
) &&
496 (nXRight
<= pSep
->mnXRight
) &&
497 (nXRight
>= pSep
->mnXLeft
) )
498 pSep
->mnXRight
= nXRight
;
500 // new separation overlaping from right? -> reduce right boundary
501 if ( (nXLeft
>= pSep
->mnXLeft
) &&
502 (nXLeft
<= pSep
->mnXRight
) &&
503 (nXRight
>= pSep
->mnXRight
) )
504 pSep
->mnXLeft
= nXLeft
;
506 // new separation within the actual one? -> reduce both boundaries
507 if ( (nXLeft
>= pSep
->mnXLeft
) && (nXRight
<= pSep
->mnXRight
) )
509 pSep
->mnXRight
= nXRight
;
510 pSep
->mnXLeft
= nXLeft
;
513 pSep
= pSep
->mpNextSep
;
519 // -----------------------------------------------------------------------
521 void ImplRegionBand::Exclude( long nXLeft
, long nXRight
)
523 DBG_ASSERT( nXLeft
<= nXRight
, "ImplRegionBand::Exclude(): nxLeft > nXRight" );
525 // band has been touched
528 // band empty? -> nothing to do
532 // process real exclusion
533 ImplRegionBandSep
* pNewSep
;
534 ImplRegionBandSep
* pPrevSep
= 0;
535 ImplRegionBandSep
* pSep
= mpFirstSep
;
538 BOOL bSepProcessed
= FALSE
;
540 // new separation completely overlapping? -> remove separation
541 if ( (nXLeft
<= pSep
->mnXLeft
) && (nXRight
>= pSep
->mnXRight
) )
543 // will be removed from the optimizer
544 pSep
->mbRemoved
= TRUE
;
545 bSepProcessed
= TRUE
;
548 // new separation overlaping from left? -> reduce boundary
549 if ( !bSepProcessed
)
551 if ( (nXRight
>= pSep
->mnXLeft
) && (nXLeft
<= pSep
->mnXLeft
) )
553 pSep
->mnXLeft
= nXRight
+1;
554 bSepProcessed
= TRUE
;
558 // new separation overlaping from right? -> reduce boundary
559 if ( !bSepProcessed
)
561 if ( (nXLeft
<= pSep
->mnXRight
) && (nXRight
> pSep
->mnXRight
) )
563 pSep
->mnXRight
= nXLeft
-1;
564 bSepProcessed
= TRUE
;
568 // new separation within the actual one? -> reduce boundary
569 // and add new entry for reminder
570 if ( !bSepProcessed
)
572 if ( (nXLeft
>= pSep
->mnXLeft
) && (nXRight
<= pSep
->mnXRight
) )
574 pNewSep
= new ImplRegionBandSep
;
575 pNewSep
->mnXLeft
= pSep
->mnXLeft
;
576 pNewSep
->mnXRight
= nXLeft
-1;
577 pNewSep
->mbRemoved
= FALSE
;
579 pSep
->mnXLeft
= nXRight
+1;
581 // connections from the new separation
582 pNewSep
->mpNextSep
= pSep
;
584 // connections to the new separation
585 if ( pSep
== mpFirstSep
)
586 mpFirstSep
= pNewSep
;
588 pPrevSep
->mpNextSep
= pNewSep
;
593 pSep
= pSep
->mpNextSep
;
599 // -----------------------------------------------------------------------
601 void ImplRegionBand::XOr( long nXLeft
, long nXRight
)
603 DBG_ASSERT( nXLeft
<= nXRight
, "ImplRegionBand::XOr(): nxLeft > nXRight" );
605 // #i46602# Reworked rectangle Xor
607 // In general, we can distinguish 11 cases of intersection
608 // (details below). The old implementation explicitely handled 7
609 // cases (numbered in the order of appearance, use CVS to get your
610 // hands on the old version), therefore, I've sticked to that
611 // order, and added four more cases. The code below references
612 // those numbers via #1, #2, etc.
614 // Num Mnem newX:oldX newY:oldY Description Result Can quit?
616 // #1 Empty band - - The band is empty, thus, simply add new bandSep just add Yes
618 // #2 apart - - The rectangles are disjunct, add new one as is just add Yes
620 // #3 atop == == The rectangles are _exactly_ the same, remove existing just remove Yes
622 // #4 around < > The new rectangle extends the old to both sides intersect No
624 // #5 left < < The new rectangle is left of the old (but intersects) intersect Yes
626 // #5b left-atop < == The new is left of the old, and coincides on the right intersect Yes
628 // #6 right > > The new is right of the old (but intersects) intersect No
630 // #6b right-atop == > The new is right of the old, and coincides on the left intersect No
632 // #7 inside > < The new is fully inside the old intersect Yes
634 // #8 inside-right > == The new is fully inside the old, coincides on the right intersect Yes
636 // #9 inside-left == < The new is fully inside the old, coincides on the left intersect Yes
639 // Then, to correctly perform XOr, the segment that's switched off
640 // (i.e. the overlapping part of the old and the new segment) must
641 // be extended by one pixel value at each border:
646 // Clearly, the leading band sep now goes from 0 to 3, and the
647 // trailing band sep from 11 to 14. This mimicks the xor look of a
651 // band empty? -> add element
654 mpFirstSep
= new ImplRegionBandSep
;
655 mpFirstSep
->mnXLeft
= nXLeft
;
656 mpFirstSep
->mnXRight
= nXRight
;
657 mpFirstSep
->mbRemoved
= FALSE
;
658 mpFirstSep
->mpNextSep
= NULL
;
663 ImplRegionBandSep
* pNewSep
;
664 ImplRegionBandSep
* pPrevSep
= 0;
665 ImplRegionBandSep
* pSep
= mpFirstSep
;
669 long nOldLeft( pSep
->mnXLeft
);
670 long nOldRight( pSep
->mnXRight
);
672 // did the current segment actually touch the new rect? If
673 // not, skip all comparisons, go on, loop and try to find
674 // intersecting bandSep
675 if( nXLeft
<= nOldRight
)
677 if( nXRight
< nOldLeft
)
681 // add _before_ current bandSep
682 pNewSep
= new ImplRegionBandSep
;
683 pNewSep
->mnXLeft
= nXLeft
;
684 pNewSep
->mnXRight
= nXRight
;
685 pNewSep
->mpNextSep
= pSep
;
686 pNewSep
->mbRemoved
= FALSE
;
688 // connections from the new separation
689 pNewSep
->mpNextSep
= pSep
;
691 // connections to the new separation
692 if ( pSep
== mpFirstSep
)
693 mpFirstSep
= pNewSep
;
695 pPrevSep
->mpNextSep
= pNewSep
;
696 pPrevSep
= NULL
; // do not run accidentally into the "right" case when breaking the loop
699 else if( nXLeft
== nOldLeft
&& nXRight
== nOldRight
)
702 pSep
->mbRemoved
= TRUE
;
703 pPrevSep
= NULL
; // do not run accidentally into the "right" case when breaking the loop
706 else if( nXLeft
!= nOldLeft
&& nXRight
== nOldRight
)
709 if( nXLeft
< nOldLeft
)
711 nXRight
= nOldLeft
; // 5b
715 nXRight
= nXLeft
; // 8
719 pSep
->mnXLeft
= nXLeft
;
720 pSep
->mnXRight
= nXRight
-1;
722 pPrevSep
= NULL
; // do not run accidentally into the "right" case when breaking the loop
725 else if( nXLeft
== nOldLeft
&& nXRight
!= nOldRight
)
729 if( nXRight
> nOldRight
)
731 nXLeft
= nOldRight
+1; // 6b
733 // cannot break here, simply mark segment as removed,
734 // and go on with adapted nXLeft/nXRight
735 pSep
->mbRemoved
= TRUE
;
739 pSep
->mnXLeft
= nXRight
+1; // 9
741 pPrevSep
= NULL
; // do not run accidentally into the "right" case when breaking the loop
745 else // if( nXLeft != nOldLeft && nXRight != nOldRight ) follows automatically
748 DBG_ASSERT( nXLeft
!= nOldLeft
&& nXRight
!= nOldRight
,
749 "ImplRegionBand::XOr(): Case 4,5,6,7 expected all coordinates to be not equal!" );
751 // The plain-jane check would look like this:
753 // if( nXLeft < nOldLeft )
756 // if( nXRight > nOldRight )
768 // if( nXRight > nOldRight )
778 // but since we generally don't have to care whether
779 // it's 4 or 6 (only that we must not stop processing
780 // here), condensed that in such a way that only the
781 // coordinates get shuffled into correct ordering.
783 if( nXLeft
< nOldLeft
)
784 ::std::swap( nOldLeft
, nXLeft
);
788 if( nXRight
< nOldRight
)
790 ::std::swap( nOldRight
, nXRight
);
794 // now, nOldLeft<nXLeft<=nOldRight<nXRight always
795 // holds. Note that we need the nXLeft<=nOldRight here, as
796 // the intersection part might be only one pixel (original
798 DBG_ASSERT( nOldLeft
<nXLeft
&& nXLeft
<=nOldRight
&& nOldRight
<nXRight
,
799 "ImplRegionBand::XOr(): Case 4,5,6,7 expected coordinates to be ordered now!" );
801 pSep
->mnXLeft
= nOldLeft
;
802 pSep
->mnXRight
= nXLeft
-1;
804 nXLeft
= nOldRight
+1;
805 // nxRight is already setup correctly
809 // add behind current bandSep
810 pNewSep
= new ImplRegionBandSep
;
812 pNewSep
->mnXLeft
= nXLeft
;
813 pNewSep
->mnXRight
= nXRight
;
814 pNewSep
->mpNextSep
= pSep
->mpNextSep
;
815 pNewSep
->mbRemoved
= FALSE
;
817 // connections from the new separation
818 pSep
->mpNextSep
= pNewSep
;
820 pPrevSep
= NULL
; // do not run accidentally into the "right" case when breaking the loop
827 pSep
= pSep
->mpNextSep
;
830 // new separation completely right of existing bandSeps ?
831 if( pPrevSep
&& nXLeft
>= pPrevSep
->mnXRight
)
833 pNewSep
= new ImplRegionBandSep
;
834 pNewSep
->mnXLeft
= nXLeft
;
835 pNewSep
->mnXRight
= nXRight
;
836 pNewSep
->mpNextSep
= NULL
;
837 pNewSep
->mbRemoved
= FALSE
;
839 // connections from the new separation
840 pPrevSep
->mpNextSep
= pNewSep
;
846 // -----------------------------------------------------------------------
848 BOOL
ImplRegionBand::IsInside( long nX
)
850 ImplRegionBandSep
* pSep
= mpFirstSep
;
853 if ( (pSep
->mnXLeft
<= nX
) && (pSep
->mnXRight
>= nX
) )
856 pSep
= pSep
->mpNextSep
;
862 // -----------------------------------------------------------------------
864 BOOL
ImplRegionBand::IsOver( long nLeft
, long nRight
)
866 ImplRegionBandSep
* pSep
= mpFirstSep
;
869 if ( (pSep
->mnXLeft
< nRight
) && (pSep
->mnXRight
> nLeft
) )
872 pSep
= pSep
->mpNextSep
;
878 // -----------------------------------------------------------------------
880 BOOL
ImplRegionBand::IsInside( long nLeft
, long nRight
)
882 ImplRegionBandSep
* pSep
= mpFirstSep
;
885 if ( (pSep
->mnXLeft
>= nLeft
) && (nRight
<= pSep
->mnXRight
) )
888 pSep
= pSep
->mpNextSep
;
894 // -----------------------------------------------------------------------
896 long ImplRegionBand::GetXLeftBoundary() const
898 DBG_ASSERT( mpFirstSep
!= NULL
, "ImplRegionBand::XLeftBoundary -> no separation in band!" );
900 return mpFirstSep
->mnXLeft
;
903 // -----------------------------------------------------------------------
905 long ImplRegionBand::GetXRightBoundary() const
907 DBG_ASSERT( mpFirstSep
!= NULL
, "ImplRegionBand::XRightBoundary -> no separation in band!" );
909 // search last separation
910 ImplRegionBandSep
* pSep
= mpFirstSep
;
911 while ( pSep
->mpNextSep
)
912 pSep
= pSep
->mpNextSep
;
913 return pSep
->mnXRight
;
916 // -----------------------------------------------------------------------
918 BOOL
ImplRegionBand::operator==( const ImplRegionBand
& rRegionBand
) const
920 ImplRegionBandSep
* pOwnRectBandSep
= mpFirstSep
;
921 ImplRegionBandSep
* pSecondRectBandSep
= rRegionBand
.mpFirstSep
;
922 while ( pOwnRectBandSep
&& pSecondRectBandSep
)
924 // get boundaries of current rectangle
925 long nOwnXLeft
= pOwnRectBandSep
->mnXLeft
;
926 long nSecondXLeft
= pSecondRectBandSep
->mnXLeft
;
927 if ( nOwnXLeft
!= nSecondXLeft
)
930 long nOwnXRight
= pOwnRectBandSep
->mnXRight
;
931 long nSecondXRight
= pSecondRectBandSep
->mnXRight
;
932 if ( nOwnXRight
!= nSecondXRight
)
935 // get next separation from current band
936 pOwnRectBandSep
= pOwnRectBandSep
->mpNextSep
;
938 // get next separation from current band
939 pSecondRectBandSep
= pSecondRectBandSep
->mpNextSep
;
942 // differnt number of separations?
943 if ( pOwnRectBandSep
|| pSecondRectBandSep
)
949 // -----------------------------------------------------------------------
951 ImplRegionBand
* ImplRegionBand::SplitBand (const sal_Int32 nY
)
953 OSL_ASSERT(nY
>mnYTop
);
954 OSL_ASSERT(nY
<=mnYBottom
);
956 // Create a copy of the given band (we tell the constructor to copy the points together
958 ImplRegionBand
* pLowerBand
= new ImplRegionBand(*this, false);
960 // Adapt vertical coordinates.
962 pLowerBand
->mnYTop
= nY
;
964 // Insert new band into list of bands.
965 pLowerBand
->mpNextBand
= mpNextBand
;
966 mpNextBand
= pLowerBand
;
967 pLowerBand
->mpPrevBand
= this;
968 if (pLowerBand
->mpNextBand
!= NULL
)
969 pLowerBand
->mpNextBand
->mpPrevBand
= pLowerBand
;