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 .
22 #include <tools/helpers.hxx>
23 #include <osl/diagnose.hxx>
25 #include "regband.hxx"
29 // Each band contains all rectangles between upper and lower border.
30 // For Union, Intersect, Xor and Exclude operations rectangles of
31 // equal height are evaluated. The borders of the bands should always
32 // be chosen such that this is possible.
34 // If possible, rectangles within the bands are condensed.
36 // When converting polygons all points of the polygon are registered
37 // in the individual bands (for each band they are stored as
38 // points in a list). After registration of these points they are
39 // converted to rectangles and the points in the list are deleted.
41 ImplRegionBand::ImplRegionBand( long nTop
, long nBottom
)
51 mpFirstBandPoint
= nullptr;
55 ImplRegionBand::ImplRegionBand(
56 const ImplRegionBand
& rRegionBand
,
57 const bool bIgnorePoints
)
60 mnYTop
= rRegionBand
.mnYTop
;
61 mnYBottom
= rRegionBand
.mnYBottom
;
62 mbTouched
= rRegionBand
.mbTouched
;
68 mpFirstBandPoint
= nullptr;
70 // copy all elements of the list with separations
71 ImplRegionBandSep
* pNewSep
;
72 ImplRegionBandSep
* pPrevSep
= nullptr;
73 ImplRegionBandSep
* pSep
= rRegionBand
.mpFirstSep
;
76 // create new and copy data
77 pNewSep
= new ImplRegionBandSep
;
78 pNewSep
->mnXLeft
= pSep
->mnXLeft
;
79 pNewSep
->mnXRight
= pSep
->mnXRight
;
80 pNewSep
->mbRemoved
= pSep
->mbRemoved
;
81 pNewSep
->mpNextSep
= nullptr;
82 if ( pSep
== rRegionBand
.mpFirstSep
)
85 pPrevSep
->mpNextSep
= pNewSep
;
88 pSep
= pSep
->mpNextSep
;
94 ImplRegionBandPoint
* pPoint
= rRegionBand
.mpFirstBandPoint
;
95 ImplRegionBandPoint
* pPrevPointCopy
= nullptr;
96 while (pPoint
!= nullptr)
98 ImplRegionBandPoint
* pPointCopy
= new ImplRegionBandPoint
;
99 pPointCopy
->mpNextBandPoint
= nullptr;
100 pPointCopy
->mnX
= pPoint
->mnX
;
101 pPointCopy
->mnLineId
= pPoint
->mnLineId
;
102 pPointCopy
->mbEndPoint
= pPoint
->mbEndPoint
;
103 pPointCopy
->meLineType
= pPoint
->meLineType
;
105 if (pPrevPointCopy
!= nullptr)
106 pPrevPointCopy
->mpNextBandPoint
= pPointCopy
;
108 mpFirstBandPoint
= pPointCopy
;
110 pPrevPointCopy
= pPointCopy
;
111 pPoint
= pPoint
->mpNextBandPoint
;
116 ImplRegionBand::~ImplRegionBand()
118 SAL_WARN_IF( mpFirstBandPoint
!= nullptr, "vcl", "ImplRegionBand::~ImplRegionBand -> pointlist not empty" );
120 // delete elements of the list
121 ImplRegionBandSep
* pSep
= mpFirstSep
;
124 ImplRegionBandSep
* pTempSep
= pSep
->mpNextSep
;
129 // delete elements of the list
130 ImplRegionBandPoint
* pPoint
= mpFirstBandPoint
;
133 ImplRegionBandPoint
* pTempPoint
= pPoint
->mpNextBandPoint
;
139 // generate separations from lines and process union with existing
142 void ImplRegionBand::ProcessPoints()
145 ImplRegionBandPoint
* pRegionBandPoint
= mpFirstBandPoint
;
146 while ( pRegionBandPoint
)
149 if ( pRegionBandPoint
->mpNextBandPoint
)
152 if ( pRegionBandPoint
->mbEndPoint
&& pRegionBandPoint
->mpNextBandPoint
->mbEndPoint
)
154 // same direction? -> remove next point!
155 if ( pRegionBandPoint
->meLineType
== pRegionBandPoint
->mpNextBandPoint
->meLineType
)
157 ImplRegionBandPoint
* pSaveRegionBandPoint
= pRegionBandPoint
->mpNextBandPoint
;
158 pRegionBandPoint
->mpNextBandPoint
= pRegionBandPoint
->mpNextBandPoint
->mpNextBandPoint
;
159 delete pSaveRegionBandPoint
;
164 // continue with next element in the list
165 pRegionBandPoint
= pRegionBandPoint
->mpNextBandPoint
;
168 pRegionBandPoint
= mpFirstBandPoint
;
169 while ( pRegionBandPoint
&& pRegionBandPoint
->mpNextBandPoint
)
171 Union( pRegionBandPoint
->mnX
, pRegionBandPoint
->mpNextBandPoint
->mnX
);
173 ImplRegionBandPoint
* pNextBandPoint
= pRegionBandPoint
->mpNextBandPoint
->mpNextBandPoint
;
175 // remove already processed points
176 delete pRegionBandPoint
->mpNextBandPoint
;
177 delete pRegionBandPoint
;
179 // continue with next element in the list
180 pRegionBandPoint
= pNextBandPoint
;
183 // remove last element if necessary
184 delete pRegionBandPoint
;
187 mpFirstBandPoint
= nullptr;
190 // generate separations from lines and process union with existing
193 bool ImplRegionBand::InsertPoint( long nX
, long nLineId
,
194 bool bEndPoint
, LineType eLineType
)
196 if ( !mpFirstBandPoint
)
198 mpFirstBandPoint
= new ImplRegionBandPoint
;
199 mpFirstBandPoint
->mnX
= nX
;
200 mpFirstBandPoint
->mnLineId
= nLineId
;
201 mpFirstBandPoint
->mbEndPoint
= bEndPoint
;
202 mpFirstBandPoint
->meLineType
= eLineType
;
203 mpFirstBandPoint
->mpNextBandPoint
= nullptr;
207 // look if line already touched the band
208 ImplRegionBandPoint
* pRegionBandPoint
= mpFirstBandPoint
;
209 ImplRegionBandPoint
* pLastTestedRegionBandPoint
= nullptr;
210 while( pRegionBandPoint
)
212 if ( pRegionBandPoint
->mnLineId
== nLineId
)
216 if( !pRegionBandPoint
->mbEndPoint
)
218 // remove old band point
219 if( !mpFirstBandPoint
->mpNextBandPoint
)
221 // if we've only got one point => replace first point
222 pRegionBandPoint
->mnX
= nX
;
223 pRegionBandPoint
->mbEndPoint
= true;
228 // remove current point
229 if( !pLastTestedRegionBandPoint
)
231 // remove and delete old first point
232 ImplRegionBandPoint
* pSaveBandPoint
= mpFirstBandPoint
;
233 mpFirstBandPoint
= mpFirstBandPoint
->mpNextBandPoint
;
234 delete pSaveBandPoint
;
238 // remove and delete current band point
239 pLastTestedRegionBandPoint
->mpNextBandPoint
= pRegionBandPoint
->mpNextBandPoint
;
240 delete pRegionBandPoint
;
252 pLastTestedRegionBandPoint
= pRegionBandPoint
;
253 pRegionBandPoint
= pRegionBandPoint
->mpNextBandPoint
;
256 // search appropriate position and insert point into the list
257 ImplRegionBandPoint
* pNewRegionBandPoint
;
259 pRegionBandPoint
= mpFirstBandPoint
;
260 pLastTestedRegionBandPoint
= nullptr;
261 while ( pRegionBandPoint
)
263 // new point completely left? -> insert as first point
264 if ( nX
<= pRegionBandPoint
->mnX
)
266 pNewRegionBandPoint
= new ImplRegionBandPoint
;
267 pNewRegionBandPoint
->mnX
= nX
;
268 pNewRegionBandPoint
->mnLineId
= nLineId
;
269 pNewRegionBandPoint
->mbEndPoint
= bEndPoint
;
270 pNewRegionBandPoint
->meLineType
= eLineType
;
271 pNewRegionBandPoint
->mpNextBandPoint
= pRegionBandPoint
;
273 // connections to the new point
274 if ( !pLastTestedRegionBandPoint
)
275 mpFirstBandPoint
= pNewRegionBandPoint
;
277 pLastTestedRegionBandPoint
->mpNextBandPoint
= pNewRegionBandPoint
;
283 pLastTestedRegionBandPoint
= pRegionBandPoint
;
284 pRegionBandPoint
= pRegionBandPoint
->mpNextBandPoint
;
287 // not inserted -> add to the end of the list
288 pNewRegionBandPoint
= new ImplRegionBandPoint
;
289 pNewRegionBandPoint
->mnX
= nX
;
290 pNewRegionBandPoint
->mnLineId
= nLineId
;
291 pNewRegionBandPoint
->mbEndPoint
= bEndPoint
;
292 pNewRegionBandPoint
->meLineType
= eLineType
;
293 pNewRegionBandPoint
->mpNextBandPoint
= nullptr;
295 // connections to the new point
296 pLastTestedRegionBandPoint
->mpNextBandPoint
= pNewRegionBandPoint
;
301 void ImplRegionBand::MoveX( long nHorzMove
)
303 // move all x-separations
304 ImplRegionBandSep
* pSep
= mpFirstSep
;
307 pSep
->mnXLeft
+= nHorzMove
;
308 pSep
->mnXRight
+= nHorzMove
;
309 pSep
= pSep
->mpNextSep
;
313 void ImplRegionBand::ScaleX( double fHorzScale
)
315 ImplRegionBandSep
* pSep
= mpFirstSep
;
318 pSep
->mnXLeft
= FRound( pSep
->mnXLeft
* fHorzScale
);
319 pSep
->mnXRight
= FRound( pSep
->mnXRight
* fHorzScale
);
320 pSep
= pSep
->mpNextSep
;
324 // combine overlapping separations
326 void ImplRegionBand::OptimizeBand()
328 ImplRegionBandSep
* pPrevSep
= nullptr;
329 ImplRegionBandSep
* pSep
= mpFirstSep
;
333 if ( pSep
->mbRemoved
|| (pSep
->mnXRight
< pSep
->mnXLeft
) )
335 ImplRegionBandSep
* pOldSep
= pSep
;
336 if ( pSep
== mpFirstSep
)
337 mpFirstSep
= pSep
->mpNextSep
;
339 pPrevSep
->mpNextSep
= pSep
->mpNextSep
;
340 pSep
= pSep
->mpNextSep
;
345 // overlapping separations? -> combine!
346 if ( pSep
->mpNextSep
)
348 if ( (pSep
->mnXRight
+1) >= pSep
->mpNextSep
->mnXLeft
)
350 if ( pSep
->mpNextSep
->mnXRight
> pSep
->mnXRight
)
351 pSep
->mnXRight
= pSep
->mpNextSep
->mnXRight
;
353 ImplRegionBandSep
* pOldSep
= pSep
->mpNextSep
;
354 pSep
->mpNextSep
= pOldSep
->mpNextSep
;
361 pSep
= pSep
->mpNextSep
;
365 void ImplRegionBand::Union( long nXLeft
, long nXRight
)
367 SAL_WARN_IF( nXLeft
> nXRight
, "vcl", "ImplRegionBand::Union(): nxLeft > nXRight" );
369 // band empty? -> add element
372 mpFirstSep
= new ImplRegionBandSep
;
373 mpFirstSep
->mnXLeft
= nXLeft
;
374 mpFirstSep
->mnXRight
= nXRight
;
375 mpFirstSep
->mbRemoved
= false;
376 mpFirstSep
->mpNextSep
= nullptr;
380 // process real union
381 ImplRegionBandSep
* pNewSep
;
382 ImplRegionBandSep
* pPrevSep
= nullptr;
383 ImplRegionBandSep
* pSep
= mpFirstSep
;
386 // new separation completely inside? nothing to do!
387 if ( (nXLeft
>= pSep
->mnXLeft
) && (nXRight
<= pSep
->mnXRight
) )
390 // new separation completely left? -> new separation!
391 if ( nXRight
< pSep
->mnXLeft
)
393 pNewSep
= new ImplRegionBandSep
;
394 pNewSep
->mnXLeft
= nXLeft
;
395 pNewSep
->mnXRight
= nXRight
;
396 pNewSep
->mbRemoved
= false;
398 pNewSep
->mpNextSep
= pSep
;
399 if ( pSep
== mpFirstSep
)
400 mpFirstSep
= pNewSep
;
402 pPrevSep
->mpNextSep
= pNewSep
;
406 // new separation overlapping from left? -> extend boundary
407 if ( (nXRight
>= pSep
->mnXLeft
) && (nXLeft
<= pSep
->mnXLeft
) )
408 pSep
->mnXLeft
= nXLeft
;
410 // new separation overlapping from right? -> extend boundary
411 if ( (nXLeft
<= pSep
->mnXRight
) && (nXRight
> pSep
->mnXRight
) )
413 pSep
->mnXRight
= nXRight
;
417 // not inserted, but last element? -> add to the end of the list
418 if ( !pSep
->mpNextSep
&& (nXLeft
> pSep
->mnXRight
) )
420 pNewSep
= new ImplRegionBandSep
;
421 pNewSep
->mnXLeft
= nXLeft
;
422 pNewSep
->mnXRight
= nXRight
;
423 pNewSep
->mbRemoved
= false;
425 pSep
->mpNextSep
= pNewSep
;
426 pNewSep
->mpNextSep
= nullptr;
431 pSep
= pSep
->mpNextSep
;
437 void ImplRegionBand::Intersect( long nXLeft
, long nXRight
)
439 SAL_WARN_IF( nXLeft
> nXRight
, "vcl", "ImplRegionBand::Intersect(): nxLeft > nXRight" );
441 // band has been touched
444 // band empty? -> nothing to do
448 // process real intersection
449 ImplRegionBandSep
* pSep
= mpFirstSep
;
452 // new separation completely outside? -> remove separation
453 if ( (nXRight
< pSep
->mnXLeft
) || (nXLeft
> pSep
->mnXRight
) )
454 // will be removed from the optimizer
455 pSep
->mbRemoved
= true;
457 // new separation overlapping from left? -> reduce right boundary
458 if ( (nXLeft
<= pSep
->mnXLeft
) &&
459 (nXRight
<= pSep
->mnXRight
) &&
460 (nXRight
>= pSep
->mnXLeft
) )
461 pSep
->mnXRight
= nXRight
;
463 // new separation overlapping from right? -> reduce right boundary
464 if ( (nXLeft
>= pSep
->mnXLeft
) &&
465 (nXLeft
<= pSep
->mnXRight
) &&
466 (nXRight
>= pSep
->mnXRight
) )
467 pSep
->mnXLeft
= nXLeft
;
469 // new separation within the actual one? -> reduce both boundaries
470 if ( (nXLeft
>= pSep
->mnXLeft
) && (nXRight
<= pSep
->mnXRight
) )
472 pSep
->mnXRight
= nXRight
;
473 pSep
->mnXLeft
= nXLeft
;
476 pSep
= pSep
->mpNextSep
;
482 void ImplRegionBand::Exclude( long nXLeft
, long nXRight
)
484 SAL_WARN_IF( nXLeft
> nXRight
, "vcl", "ImplRegionBand::Exclude(): nxLeft > nXRight" );
486 // band has been touched
489 // band empty? -> nothing to do
493 // process real exclusion
494 ImplRegionBandSep
* pNewSep
;
495 ImplRegionBandSep
* pPrevSep
= nullptr;
496 ImplRegionBandSep
* pSep
= mpFirstSep
;
499 bool bSepProcessed
= false;
501 // new separation completely overlapping? -> remove separation
502 if ( (nXLeft
<= pSep
->mnXLeft
) && (nXRight
>= pSep
->mnXRight
) )
504 // will be removed from the optimizer
505 pSep
->mbRemoved
= true;
506 bSepProcessed
= true;
509 // new separation overlapping from left? -> reduce boundary
510 if ( !bSepProcessed
)
512 if ( (nXRight
>= pSep
->mnXLeft
) && (nXLeft
<= pSep
->mnXLeft
) )
514 pSep
->mnXLeft
= nXRight
+1;
515 bSepProcessed
= true;
519 // new separation overlapping from right? -> reduce boundary
520 if ( !bSepProcessed
)
522 if ( (nXLeft
<= pSep
->mnXRight
) && (nXRight
> pSep
->mnXRight
) )
524 pSep
->mnXRight
= nXLeft
-1;
525 bSepProcessed
= true;
529 // new separation within the actual one? -> reduce boundary
530 // and add new entry for reminder
531 if ( !bSepProcessed
)
533 if ( (nXLeft
>= pSep
->mnXLeft
) && (nXRight
<= pSep
->mnXRight
) )
535 pNewSep
= new ImplRegionBandSep
;
536 pNewSep
->mnXLeft
= pSep
->mnXLeft
;
537 pNewSep
->mnXRight
= nXLeft
-1;
538 pNewSep
->mbRemoved
= false;
540 pSep
->mnXLeft
= nXRight
+1;
542 // connections from the new separation
543 pNewSep
->mpNextSep
= pSep
;
545 // connections to the new separation
546 if ( pSep
== mpFirstSep
)
547 mpFirstSep
= pNewSep
;
549 pPrevSep
->mpNextSep
= pNewSep
;
554 pSep
= pSep
->mpNextSep
;
560 void ImplRegionBand::XOr( long nXLeft
, long nXRight
)
562 SAL_WARN_IF( nXLeft
> nXRight
, "vcl", "ImplRegionBand::XOr(): nxLeft > nXRight" );
564 // #i46602# Reworked rectangle Xor
566 // In general, we can distinguish 11 cases of intersection
567 // (details below). The old implementation explicitly handled 7
568 // cases (numbered in the order of appearance, use CVS to get your
569 // hands on the old version), therefore, I've sticked to that
570 // order, and added four more cases. The code below references
571 // those numbers via #1, #2, etc.
573 // Num Mnem newX:oldX newY:oldY Description Result Can quit?
575 // #1 Empty band - - The band is empty, thus, simply add new bandSep just add Yes
577 // #2 apart - - The rectangles are disjunct, add new one as is just add Yes
579 // #3 atop == == The rectangles are _exactly_ the same, remove existing just remove Yes
581 // #4 around < > The new rectangle extends the old to both sides intersect No
583 // #5 left < < The new rectangle is left of the old (but intersects) intersect Yes
585 // #5b left-atop < == The new is left of the old, and coincides on the right intersect Yes
587 // #6 right > > The new is right of the old (but intersects) intersect No
589 // #6b right-atop == > The new is right of the old, and coincides on the left intersect No
591 // #7 inside > < The new is fully inside the old intersect Yes
593 // #8 inside-right > == The new is fully inside the old, coincides on the right intersect Yes
595 // #9 inside-left == < The new is fully inside the old, coincides on the left intersect Yes
597 // Then, to correctly perform XOr, the segment that's switched off
598 // (i.e. the overlapping part of the old and the new segment) must
599 // be extended by one pixel value at each border:
604 // Clearly, the leading band sep now goes from 0 to 3, and the
605 // trailing band sep from 11 to 14. This mimics the xor look of a
608 // band empty? -> add element
611 mpFirstSep
= new ImplRegionBandSep
;
612 mpFirstSep
->mnXLeft
= nXLeft
;
613 mpFirstSep
->mnXRight
= nXRight
;
614 mpFirstSep
->mbRemoved
= false;
615 mpFirstSep
->mpNextSep
= nullptr;
620 ImplRegionBandSep
* pNewSep
;
621 ImplRegionBandSep
* pPrevSep
= nullptr;
622 ImplRegionBandSep
* pSep
= mpFirstSep
;
626 long nOldLeft( pSep
->mnXLeft
);
627 long nOldRight( pSep
->mnXRight
);
629 // did the current segment actually touch the new rect? If
630 // not, skip all comparisons, go on, loop and try to find
631 // intersecting bandSep
632 if( nXLeft
<= nOldRight
)
634 if( nXRight
< nOldLeft
)
638 // add _before_ current bandSep
639 pNewSep
= new ImplRegionBandSep
;
640 pNewSep
->mnXLeft
= nXLeft
;
641 pNewSep
->mnXRight
= nXRight
;
642 pNewSep
->mpNextSep
= pSep
;
643 pNewSep
->mbRemoved
= false;
645 // connections from the new separation
646 pNewSep
->mpNextSep
= pSep
;
648 // connections to the new separation
649 if ( pSep
== mpFirstSep
)
650 mpFirstSep
= pNewSep
;
652 pPrevSep
->mpNextSep
= pNewSep
;
653 pPrevSep
= nullptr; // do not run accidentally into the "right" case when breaking the loop
656 else if( nXLeft
== nOldLeft
&& nXRight
== nOldRight
)
659 pSep
->mbRemoved
= true;
660 pPrevSep
= nullptr; // do not run accidentally into the "right" case when breaking the loop
663 else if( nXLeft
!= nOldLeft
&& nXRight
== nOldRight
)
666 if( nXLeft
< nOldLeft
)
668 nXRight
= nOldLeft
; // 5b
672 nXRight
= nXLeft
; // 8
676 pSep
->mnXLeft
= nXLeft
;
677 pSep
->mnXRight
= nXRight
-1;
679 pPrevSep
= nullptr; // do not run accidentally into the "right" case when breaking the loop
682 else if( nXLeft
== nOldLeft
&& nXRight
!= nOldRight
)
686 if( nXRight
> nOldRight
)
688 nXLeft
= nOldRight
+1; // 6b
690 // cannot break here, simply mark segment as removed,
691 // and go on with adapted nXLeft/nXRight
692 pSep
->mbRemoved
= true;
696 pSep
->mnXLeft
= nXRight
+1; // 9
698 pPrevSep
= nullptr; // do not run accidentally into the "right" case when breaking the loop
702 else // if( nXLeft != nOldLeft && nXRight != nOldRight ) follows automatically
705 SAL_WARN_IF( nXLeft
== nOldLeft
|| nXRight
== nOldRight
, "vcl",
706 "ImplRegionBand::XOr(): Case 4,5,6,7 expected all coordinates to be not equal!" );
708 // The plain-jane check would look like this:
710 // if( nXLeft < nOldLeft )
713 // if( nXRight > nOldRight )
725 // if( nXRight > nOldRight )
735 // but since we generally don't have to care whether
736 // it's 4 or 6 (only that we must not stop processing
737 // here), condensed that in such a way that only the
738 // coordinates get shuffled into correct ordering.
740 if( nXLeft
< nOldLeft
)
741 ::std::swap( nOldLeft
, nXLeft
);
745 if( nXRight
< nOldRight
)
747 ::std::swap( nOldRight
, nXRight
);
751 // now, nOldLeft<nXLeft<=nOldRight<nXRight always
752 // holds. Note that we need the nXLeft<=nOldRight here, as
753 // the intersection part might be only one pixel (original
755 SAL_WARN_IF( nOldLeft
==nXLeft
|| nXLeft
>nOldRight
|| nOldRight
>=nXRight
, "vcl",
756 "ImplRegionBand::XOr(): Case 4,5,6,7 expected coordinates to be ordered now!" );
758 pSep
->mnXLeft
= nOldLeft
;
759 pSep
->mnXRight
= nXLeft
-1;
761 nXLeft
= nOldRight
+1;
762 // nxRight is already setup correctly
766 // add behind current bandSep
767 pNewSep
= new ImplRegionBandSep
;
769 pNewSep
->mnXLeft
= nXLeft
;
770 pNewSep
->mnXRight
= nXRight
;
771 pNewSep
->mpNextSep
= pSep
->mpNextSep
;
772 pNewSep
->mbRemoved
= false;
774 // connections from the new separation
775 pSep
->mpNextSep
= pNewSep
;
777 pPrevSep
= nullptr; // do not run accidentally into the "right" case when breaking the loop
784 pSep
= pSep
->mpNextSep
;
787 // new separation completely right of existing bandSeps ?
788 if( pPrevSep
&& nXLeft
>= pPrevSep
->mnXRight
)
790 pNewSep
= new ImplRegionBandSep
;
791 pNewSep
->mnXLeft
= nXLeft
;
792 pNewSep
->mnXRight
= nXRight
;
793 pNewSep
->mpNextSep
= nullptr;
794 pNewSep
->mbRemoved
= false;
796 // connections from the new separation
797 pPrevSep
->mpNextSep
= pNewSep
;
803 bool ImplRegionBand::IsInside( long nX
)
805 ImplRegionBandSep
* pSep
= mpFirstSep
;
808 if ( (pSep
->mnXLeft
<= nX
) && (pSep
->mnXRight
>= nX
) )
811 pSep
= pSep
->mpNextSep
;
817 long ImplRegionBand::GetXLeftBoundary() const
819 assert(mpFirstSep
&& "ImplRegionBand::XLeftBoundary -> no separation in band!");
821 return mpFirstSep
->mnXLeft
;
824 long ImplRegionBand::GetXRightBoundary() const
826 SAL_WARN_IF( mpFirstSep
== nullptr, "vcl", "ImplRegionBand::XRightBoundary -> no separation in band!" );
828 // search last separation
829 ImplRegionBandSep
* pSep
= mpFirstSep
;
830 while ( pSep
->mpNextSep
)
831 pSep
= pSep
->mpNextSep
;
832 return pSep
->mnXRight
;
835 bool ImplRegionBand::operator==( const ImplRegionBand
& rRegionBand
) const
837 ImplRegionBandSep
* pOwnRectBandSep
= mpFirstSep
;
838 ImplRegionBandSep
* pSecondRectBandSep
= rRegionBand
.mpFirstSep
;
839 while ( pOwnRectBandSep
&& pSecondRectBandSep
)
841 // get boundaries of current rectangle
842 long nOwnXLeft
= pOwnRectBandSep
->mnXLeft
;
843 long nSecondXLeft
= pSecondRectBandSep
->mnXLeft
;
844 if ( nOwnXLeft
!= nSecondXLeft
)
847 long nOwnXRight
= pOwnRectBandSep
->mnXRight
;
848 long nSecondXRight
= pSecondRectBandSep
->mnXRight
;
849 if ( nOwnXRight
!= nSecondXRight
)
852 // get next separation from current band
853 pOwnRectBandSep
= pOwnRectBandSep
->mpNextSep
;
855 // get next separation from current band
856 pSecondRectBandSep
= pSecondRectBandSep
->mpNextSep
;
859 // different number of separations?
860 return !(pOwnRectBandSep
|| pSecondRectBandSep
);
863 ImplRegionBand
* ImplRegionBand::SplitBand (const sal_Int32 nY
)
865 OSL_ASSERT(nY
>mnYTop
);
866 OSL_ASSERT(nY
<=mnYBottom
);
868 // Create a copy of the given band (we tell the constructor to copy the points together
870 ImplRegionBand
* pLowerBand
= new ImplRegionBand(*this, false);
872 // Adapt vertical coordinates.
874 pLowerBand
->mnYTop
= nY
;
876 // Insert new band into list of bands.
877 pLowerBand
->mpNextBand
= mpNextBand
;
878 mpNextBand
= pLowerBand
;
879 pLowerBand
->mpPrevBand
= this;
880 if (pLowerBand
->mpNextBand
!= nullptr)
881 pLowerBand
->mpNextBand
->mpPrevBand
= pLowerBand
;
886 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */