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/helpers.hxx>
21 #include <osl/diagnose.h>
22 #include <sal/log.hxx>
24 #include <regband.hxx>
28 // Each band contains all rectangles between upper and lower border.
29 // For Union, Intersect, Xor and Exclude operations rectangles of
30 // equal height are evaluated. The borders of the bands should always
31 // be chosen such that this is possible.
33 // If possible, rectangles within the bands are condensed.
35 // When converting polygons all points of the polygon are registered
36 // in the individual bands (for each band they are stored as
37 // points in a list). After registration of these points they are
38 // converted to rectangles and the points in the list are deleted.
40 ImplRegionBand::ImplRegionBand( long nTop
, long nBottom
)
50 mpFirstBandPoint
= nullptr;
54 ImplRegionBand::ImplRegionBand(
55 const ImplRegionBand
& rRegionBand
,
56 const bool bIgnorePoints
)
59 mnYTop
= rRegionBand
.mnYTop
;
60 mnYBottom
= rRegionBand
.mnYBottom
;
61 mbTouched
= rRegionBand
.mbTouched
;
67 mpFirstBandPoint
= nullptr;
69 // copy all elements of the list with separations
70 ImplRegionBandSep
* pNewSep
;
71 ImplRegionBandSep
* pPrevSep
= nullptr;
72 ImplRegionBandSep
* pSep
= rRegionBand
.mpFirstSep
;
75 // create new and copy data
76 pNewSep
= new ImplRegionBandSep
;
77 pNewSep
->mnXLeft
= pSep
->mnXLeft
;
78 pNewSep
->mnXRight
= pSep
->mnXRight
;
79 pNewSep
->mbRemoved
= pSep
->mbRemoved
;
80 pNewSep
->mpNextSep
= nullptr;
81 if ( pSep
== rRegionBand
.mpFirstSep
)
84 pPrevSep
->mpNextSep
= pNewSep
;
87 pSep
= pSep
->mpNextSep
;
93 ImplRegionBandPoint
* pPoint
= rRegionBand
.mpFirstBandPoint
;
94 ImplRegionBandPoint
* pPrevPointCopy
= nullptr;
95 while (pPoint
!= nullptr)
97 ImplRegionBandPoint
* pPointCopy
= new ImplRegionBandPoint
;
98 pPointCopy
->mpNextBandPoint
= nullptr;
99 pPointCopy
->mnX
= pPoint
->mnX
;
100 pPointCopy
->mnLineId
= pPoint
->mnLineId
;
101 pPointCopy
->mbEndPoint
= pPoint
->mbEndPoint
;
102 pPointCopy
->meLineType
= pPoint
->meLineType
;
104 if (pPrevPointCopy
!= nullptr)
105 pPrevPointCopy
->mpNextBandPoint
= pPointCopy
;
107 mpFirstBandPoint
= pPointCopy
;
109 pPrevPointCopy
= pPointCopy
;
110 pPoint
= pPoint
->mpNextBandPoint
;
115 ImplRegionBand::~ImplRegionBand()
117 SAL_WARN_IF( mpFirstBandPoint
!= nullptr, "vcl", "ImplRegionBand::~ImplRegionBand -> pointlist not empty" );
119 // delete elements of the list
120 ImplRegionBandSep
* pSep
= mpFirstSep
;
123 ImplRegionBandSep
* pTempSep
= pSep
->mpNextSep
;
128 // delete elements of the list
129 ImplRegionBandPoint
* pPoint
= mpFirstBandPoint
;
132 ImplRegionBandPoint
* pTempPoint
= pPoint
->mpNextBandPoint
;
138 // generate separations from lines and process union with existing
141 void ImplRegionBand::ProcessPoints()
144 ImplRegionBandPoint
* pRegionBandPoint
= mpFirstBandPoint
;
145 while ( pRegionBandPoint
)
148 if ( pRegionBandPoint
->mpNextBandPoint
)
151 if ( pRegionBandPoint
->mbEndPoint
&& pRegionBandPoint
->mpNextBandPoint
->mbEndPoint
)
153 // same direction? -> remove next point!
154 if ( pRegionBandPoint
->meLineType
== pRegionBandPoint
->mpNextBandPoint
->meLineType
)
156 ImplRegionBandPoint
* pSaveRegionBandPoint
= pRegionBandPoint
->mpNextBandPoint
;
157 pRegionBandPoint
->mpNextBandPoint
= pRegionBandPoint
->mpNextBandPoint
->mpNextBandPoint
;
158 delete pSaveRegionBandPoint
;
163 // continue with next element in the list
164 pRegionBandPoint
= pRegionBandPoint
->mpNextBandPoint
;
167 pRegionBandPoint
= mpFirstBandPoint
;
168 while ( pRegionBandPoint
&& pRegionBandPoint
->mpNextBandPoint
)
170 Union( pRegionBandPoint
->mnX
, pRegionBandPoint
->mpNextBandPoint
->mnX
);
172 ImplRegionBandPoint
* pNextBandPoint
= pRegionBandPoint
->mpNextBandPoint
->mpNextBandPoint
;
174 // remove already processed points
175 delete pRegionBandPoint
->mpNextBandPoint
;
176 delete pRegionBandPoint
;
178 // continue with next element in the list
179 pRegionBandPoint
= pNextBandPoint
;
182 // remove last element if necessary
183 delete pRegionBandPoint
;
186 mpFirstBandPoint
= nullptr;
189 // generate separations from lines and process union with existing
192 bool ImplRegionBand::InsertPoint( long nX
, long nLineId
,
193 bool bEndPoint
, LineType eLineType
)
195 if ( !mpFirstBandPoint
)
197 mpFirstBandPoint
= new ImplRegionBandPoint
;
198 mpFirstBandPoint
->mnX
= nX
;
199 mpFirstBandPoint
->mnLineId
= nLineId
;
200 mpFirstBandPoint
->mbEndPoint
= bEndPoint
;
201 mpFirstBandPoint
->meLineType
= eLineType
;
202 mpFirstBandPoint
->mpNextBandPoint
= nullptr;
206 // look if line already touched the band
207 ImplRegionBandPoint
* pRegionBandPoint
= mpFirstBandPoint
;
208 ImplRegionBandPoint
* pLastTestedRegionBandPoint
= nullptr;
209 while( pRegionBandPoint
)
211 if ( pRegionBandPoint
->mnLineId
== nLineId
)
215 if( !pRegionBandPoint
->mbEndPoint
)
217 // remove old band point
218 if( !mpFirstBandPoint
->mpNextBandPoint
)
220 // if we've only got one point => replace first point
221 pRegionBandPoint
->mnX
= nX
;
222 pRegionBandPoint
->mbEndPoint
= true;
227 // remove current point
228 if( !pLastTestedRegionBandPoint
)
230 // remove and delete old first point
231 ImplRegionBandPoint
* pSaveBandPoint
= mpFirstBandPoint
;
232 mpFirstBandPoint
= mpFirstBandPoint
->mpNextBandPoint
;
233 delete pSaveBandPoint
;
237 // remove and delete current band point
238 pLastTestedRegionBandPoint
->mpNextBandPoint
= pRegionBandPoint
->mpNextBandPoint
;
239 delete pRegionBandPoint
;
251 pLastTestedRegionBandPoint
= pRegionBandPoint
;
252 pRegionBandPoint
= pRegionBandPoint
->mpNextBandPoint
;
255 // search appropriate position and insert point into the list
256 ImplRegionBandPoint
* pNewRegionBandPoint
;
258 pRegionBandPoint
= mpFirstBandPoint
;
259 pLastTestedRegionBandPoint
= nullptr;
260 while ( pRegionBandPoint
)
262 // new point completely left? -> insert as first point
263 if ( nX
<= pRegionBandPoint
->mnX
)
265 pNewRegionBandPoint
= new ImplRegionBandPoint
;
266 pNewRegionBandPoint
->mnX
= nX
;
267 pNewRegionBandPoint
->mnLineId
= nLineId
;
268 pNewRegionBandPoint
->mbEndPoint
= bEndPoint
;
269 pNewRegionBandPoint
->meLineType
= eLineType
;
270 pNewRegionBandPoint
->mpNextBandPoint
= pRegionBandPoint
;
272 // connections to the new point
273 if ( !pLastTestedRegionBandPoint
)
274 mpFirstBandPoint
= pNewRegionBandPoint
;
276 pLastTestedRegionBandPoint
->mpNextBandPoint
= pNewRegionBandPoint
;
282 pLastTestedRegionBandPoint
= pRegionBandPoint
;
283 pRegionBandPoint
= pRegionBandPoint
->mpNextBandPoint
;
286 // not inserted -> add to the end of the list
287 pNewRegionBandPoint
= new ImplRegionBandPoint
;
288 pNewRegionBandPoint
->mnX
= nX
;
289 pNewRegionBandPoint
->mnLineId
= nLineId
;
290 pNewRegionBandPoint
->mbEndPoint
= bEndPoint
;
291 pNewRegionBandPoint
->meLineType
= eLineType
;
292 pNewRegionBandPoint
->mpNextBandPoint
= nullptr;
294 // connections to the new point
295 pLastTestedRegionBandPoint
->mpNextBandPoint
= pNewRegionBandPoint
;
300 void ImplRegionBand::MoveX( long nHorzMove
)
302 // move all x-separations
303 ImplRegionBandSep
* pSep
= mpFirstSep
;
306 pSep
->mnXLeft
+= nHorzMove
;
307 pSep
->mnXRight
+= nHorzMove
;
308 pSep
= pSep
->mpNextSep
;
312 void ImplRegionBand::ScaleX( double fHorzScale
)
314 ImplRegionBandSep
* pSep
= mpFirstSep
;
317 pSep
->mnXLeft
= FRound( pSep
->mnXLeft
* fHorzScale
);
318 pSep
->mnXRight
= FRound( pSep
->mnXRight
* fHorzScale
);
319 pSep
= pSep
->mpNextSep
;
323 // combine overlapping separations
325 void ImplRegionBand::OptimizeBand()
327 ImplRegionBandSep
* pPrevSep
= nullptr;
328 ImplRegionBandSep
* pSep
= mpFirstSep
;
332 if ( pSep
->mbRemoved
|| (pSep
->mnXRight
< pSep
->mnXLeft
) )
334 ImplRegionBandSep
* pOldSep
= pSep
;
335 if ( pSep
== mpFirstSep
)
336 mpFirstSep
= pSep
->mpNextSep
;
338 pPrevSep
->mpNextSep
= pSep
->mpNextSep
;
339 pSep
= pSep
->mpNextSep
;
344 // overlapping separations? -> combine!
345 if ( pSep
->mpNextSep
)
347 if ( (pSep
->mnXRight
+1) >= pSep
->mpNextSep
->mnXLeft
)
349 if ( pSep
->mpNextSep
->mnXRight
> pSep
->mnXRight
)
350 pSep
->mnXRight
= pSep
->mpNextSep
->mnXRight
;
352 ImplRegionBandSep
* pOldSep
= pSep
->mpNextSep
;
353 pSep
->mpNextSep
= pOldSep
->mpNextSep
;
360 pSep
= pSep
->mpNextSep
;
364 void ImplRegionBand::Union( long nXLeft
, long nXRight
)
366 SAL_WARN_IF( nXLeft
> nXRight
, "vcl", "ImplRegionBand::Union(): nxLeft > nXRight" );
368 // band empty? -> add element
371 mpFirstSep
= new ImplRegionBandSep
;
372 mpFirstSep
->mnXLeft
= nXLeft
;
373 mpFirstSep
->mnXRight
= nXRight
;
374 mpFirstSep
->mbRemoved
= false;
375 mpFirstSep
->mpNextSep
= nullptr;
379 // process real union
380 ImplRegionBandSep
* pNewSep
;
381 ImplRegionBandSep
* pPrevSep
= nullptr;
382 ImplRegionBandSep
* pSep
= mpFirstSep
;
385 // new separation completely inside? nothing to do!
386 if ( (nXLeft
>= pSep
->mnXLeft
) && (nXRight
<= pSep
->mnXRight
) )
389 // new separation completely left? -> new separation!
390 if ( nXRight
< pSep
->mnXLeft
)
392 pNewSep
= new ImplRegionBandSep
;
393 pNewSep
->mnXLeft
= nXLeft
;
394 pNewSep
->mnXRight
= nXRight
;
395 pNewSep
->mbRemoved
= false;
397 pNewSep
->mpNextSep
= pSep
;
398 if ( pSep
== mpFirstSep
)
399 mpFirstSep
= pNewSep
;
401 pPrevSep
->mpNextSep
= pNewSep
;
405 // new separation overlapping from left? -> extend boundary
406 if ( (nXRight
>= pSep
->mnXLeft
) && (nXLeft
<= pSep
->mnXLeft
) )
407 pSep
->mnXLeft
= nXLeft
;
409 // new separation overlapping from right? -> extend boundary
410 if ( (nXLeft
<= pSep
->mnXRight
) && (nXRight
> pSep
->mnXRight
) )
412 pSep
->mnXRight
= nXRight
;
416 // not inserted, but last element? -> add to the end of the list
417 if ( !pSep
->mpNextSep
&& (nXLeft
> pSep
->mnXRight
) )
419 pNewSep
= new ImplRegionBandSep
;
420 pNewSep
->mnXLeft
= nXLeft
;
421 pNewSep
->mnXRight
= nXRight
;
422 pNewSep
->mbRemoved
= false;
424 pSep
->mpNextSep
= pNewSep
;
425 pNewSep
->mpNextSep
= nullptr;
430 pSep
= pSep
->mpNextSep
;
436 void ImplRegionBand::Intersect( long nXLeft
, long nXRight
)
438 SAL_WARN_IF( nXLeft
> nXRight
, "vcl", "ImplRegionBand::Intersect(): nxLeft > nXRight" );
440 // band has been touched
443 // band empty? -> nothing to do
447 // process real intersection
448 ImplRegionBandSep
* pSep
= mpFirstSep
;
451 // new separation completely outside? -> remove separation
452 if ( (nXRight
< pSep
->mnXLeft
) || (nXLeft
> pSep
->mnXRight
) )
453 // will be removed from the optimizer
454 pSep
->mbRemoved
= true;
456 // new separation overlapping from left? -> reduce right boundary
457 if ( (nXLeft
<= pSep
->mnXLeft
) &&
458 (nXRight
<= pSep
->mnXRight
) &&
459 (nXRight
>= pSep
->mnXLeft
) )
460 pSep
->mnXRight
= nXRight
;
462 // new separation overlapping from right? -> reduce right boundary
463 if ( (nXLeft
>= pSep
->mnXLeft
) &&
464 (nXLeft
<= pSep
->mnXRight
) &&
465 (nXRight
>= pSep
->mnXRight
) )
466 pSep
->mnXLeft
= nXLeft
;
468 // new separation within the actual one? -> reduce both boundaries
469 if ( (nXLeft
>= pSep
->mnXLeft
) && (nXRight
<= pSep
->mnXRight
) )
471 pSep
->mnXRight
= nXRight
;
472 pSep
->mnXLeft
= nXLeft
;
475 pSep
= pSep
->mpNextSep
;
481 void ImplRegionBand::Exclude( long nXLeft
, long nXRight
)
483 SAL_WARN_IF( nXLeft
> nXRight
, "vcl", "ImplRegionBand::Exclude(): nxLeft > nXRight" );
485 // band has been touched
488 // band empty? -> nothing to do
492 // process real exclusion
493 ImplRegionBandSep
* pNewSep
;
494 ImplRegionBandSep
* pPrevSep
= nullptr;
495 ImplRegionBandSep
* pSep
= mpFirstSep
;
498 bool bSepProcessed
= false;
500 // new separation completely overlapping? -> remove separation
501 if ( (nXLeft
<= pSep
->mnXLeft
) && (nXRight
>= pSep
->mnXRight
) )
503 // will be removed from the optimizer
504 pSep
->mbRemoved
= true;
505 bSepProcessed
= true;
508 // new separation overlapping from left? -> reduce boundary
509 if ( !bSepProcessed
)
511 if ( (nXRight
>= pSep
->mnXLeft
) && (nXLeft
<= pSep
->mnXLeft
) )
513 pSep
->mnXLeft
= nXRight
+1;
514 bSepProcessed
= true;
518 // new separation overlapping from right? -> reduce boundary
519 if ( !bSepProcessed
)
521 if ( (nXLeft
<= pSep
->mnXRight
) && (nXRight
> pSep
->mnXRight
) )
523 pSep
->mnXRight
= nXLeft
-1;
524 bSepProcessed
= true;
528 // new separation within the actual one? -> reduce boundary
529 // and add new entry for reminder
530 if ( !bSepProcessed
)
532 if ( (nXLeft
>= pSep
->mnXLeft
) && (nXRight
<= pSep
->mnXRight
) )
534 pNewSep
= new ImplRegionBandSep
;
535 pNewSep
->mnXLeft
= pSep
->mnXLeft
;
536 pNewSep
->mnXRight
= nXLeft
-1;
537 pNewSep
->mbRemoved
= false;
539 pSep
->mnXLeft
= nXRight
+1;
541 // connections from the new separation
542 pNewSep
->mpNextSep
= pSep
;
544 // connections to the new separation
545 if ( pSep
== mpFirstSep
)
546 mpFirstSep
= pNewSep
;
548 pPrevSep
->mpNextSep
= pNewSep
;
553 pSep
= pSep
->mpNextSep
;
559 void ImplRegionBand::XOr( long nXLeft
, long nXRight
)
561 SAL_WARN_IF( nXLeft
> nXRight
, "vcl", "ImplRegionBand::XOr(): nxLeft > nXRight" );
563 // #i46602# Reworked rectangle Xor
565 // In general, we can distinguish 11 cases of intersection
566 // (details below). The old implementation explicitly handled 7
567 // cases (numbered in the order of appearance, use CVS to get your
568 // hands on the old version), therefore, I've sticked to that
569 // order, and added four more cases. The code below references
570 // those numbers via #1, #2, etc.
572 // Num Mnem newX:oldX newY:oldY Description Result Can quit?
574 // #1 Empty band - - The band is empty, thus, simply add new bandSep just add Yes
576 // #2 apart - - The rectangles are disjunct, add new one as is just add Yes
578 // #3 atop == == The rectangles are _exactly_ the same, remove existing just remove Yes
580 // #4 around < > The new rectangle extends the old to both sides intersect No
582 // #5 left < < The new rectangle is left of the old (but intersects) intersect Yes
584 // #5b left-atop < == The new is left of the old, and coincides on the right intersect Yes
586 // #6 right > > The new is right of the old (but intersects) intersect No
588 // #6b right-atop == > The new is right of the old, and coincides on the left intersect No
590 // #7 inside > < The new is fully inside the old intersect Yes
592 // #8 inside-right > == The new is fully inside the old, coincides on the right intersect Yes
594 // #9 inside-left == < The new is fully inside the old, coincides on the left intersect Yes
596 // Then, to correctly perform XOr, the segment that's switched off
597 // (i.e. the overlapping part of the old and the new segment) must
598 // be extended by one pixel value at each border:
603 // Clearly, the leading band sep now goes from 0 to 3, and the
604 // trailing band sep from 11 to 14. This mimics the xor look of a
607 // band empty? -> add element
610 mpFirstSep
= new ImplRegionBandSep
;
611 mpFirstSep
->mnXLeft
= nXLeft
;
612 mpFirstSep
->mnXRight
= nXRight
;
613 mpFirstSep
->mbRemoved
= false;
614 mpFirstSep
->mpNextSep
= nullptr;
619 ImplRegionBandSep
* pNewSep
;
620 ImplRegionBandSep
* pPrevSep
= nullptr;
621 ImplRegionBandSep
* pSep
= mpFirstSep
;
625 long nOldLeft( pSep
->mnXLeft
);
626 long nOldRight( pSep
->mnXRight
);
628 // did the current segment actually touch the new rect? If
629 // not, skip all comparisons, go on, loop and try to find
630 // intersecting bandSep
631 if( nXLeft
<= nOldRight
)
633 if( nXRight
< nOldLeft
)
637 // add _before_ current bandSep
638 pNewSep
= new ImplRegionBandSep
;
639 pNewSep
->mnXLeft
= nXLeft
;
640 pNewSep
->mnXRight
= nXRight
;
641 pNewSep
->mpNextSep
= pSep
;
642 pNewSep
->mbRemoved
= false;
644 // connections from the new separation
645 pNewSep
->mpNextSep
= pSep
;
647 // connections to the new separation
648 if ( pSep
== mpFirstSep
)
649 mpFirstSep
= pNewSep
;
651 pPrevSep
->mpNextSep
= pNewSep
;
652 pPrevSep
= nullptr; // do not run accidentally into the "right" case when breaking the loop
655 else if( nXLeft
== nOldLeft
&& nXRight
== nOldRight
)
658 pSep
->mbRemoved
= true;
659 pPrevSep
= nullptr; // do not run accidentally into the "right" case when breaking the loop
662 else if( nXLeft
!= nOldLeft
&& nXRight
== nOldRight
)
665 if( nXLeft
< nOldLeft
)
667 nXRight
= nOldLeft
; // 5b
671 nXRight
= nXLeft
; // 8
675 pSep
->mnXLeft
= nXLeft
;
676 pSep
->mnXRight
= nXRight
-1;
678 pPrevSep
= nullptr; // do not run accidentally into the "right" case when breaking the loop
681 else if( nXLeft
== nOldLeft
&& nXRight
!= nOldRight
)
685 if( nXRight
> nOldRight
)
687 nXLeft
= nOldRight
+1; // 6b
689 // cannot break here, simply mark segment as removed,
690 // and go on with adapted nXLeft/nXRight
691 pSep
->mbRemoved
= true;
695 pSep
->mnXLeft
= nXRight
+1; // 9
697 pPrevSep
= nullptr; // do not run accidentally into the "right" case when breaking the loop
701 else // if( nXLeft != nOldLeft && nXRight != nOldRight ) follows automatically
704 SAL_WARN_IF( nXLeft
== nOldLeft
|| nXRight
== nOldRight
, "vcl",
705 "ImplRegionBand::XOr(): Case 4,5,6,7 expected all coordinates to be not equal!" );
707 // The plain-jane check would look like this:
709 // if( nXLeft < nOldLeft )
712 // if( nXRight > nOldRight )
724 // if( nXRight > nOldRight )
734 // but since we generally don't have to care whether
735 // it's 4 or 6 (only that we must not stop processing
736 // here), condensed that in such a way that only the
737 // coordinates get shuffled into correct ordering.
739 if( nXLeft
< nOldLeft
)
740 ::std::swap( nOldLeft
, nXLeft
);
744 if( nXRight
< nOldRight
)
746 ::std::swap( nOldRight
, nXRight
);
750 // now, nOldLeft<nXLeft<=nOldRight<nXRight always
751 // holds. Note that we need the nXLeft<=nOldRight here, as
752 // the intersection part might be only one pixel (original
754 SAL_WARN_IF( nOldLeft
==nXLeft
|| nXLeft
>nOldRight
|| nOldRight
>=nXRight
, "vcl",
755 "ImplRegionBand::XOr(): Case 4,5,6,7 expected coordinates to be ordered now!" );
757 pSep
->mnXLeft
= nOldLeft
;
758 pSep
->mnXRight
= nXLeft
-1;
760 nXLeft
= nOldRight
+1;
761 // nxRight is already setup correctly
765 // add behind current bandSep
766 pNewSep
= new ImplRegionBandSep
;
768 pNewSep
->mnXLeft
= nXLeft
;
769 pNewSep
->mnXRight
= nXRight
;
770 pNewSep
->mpNextSep
= pSep
->mpNextSep
;
771 pNewSep
->mbRemoved
= false;
773 // connections from the new separation
774 pSep
->mpNextSep
= pNewSep
;
776 pPrevSep
= nullptr; // do not run accidentally into the "right" case when breaking the loop
783 pSep
= pSep
->mpNextSep
;
786 // new separation completely right of existing bandSeps ?
787 if( pPrevSep
&& nXLeft
>= pPrevSep
->mnXRight
)
789 pNewSep
= new ImplRegionBandSep
;
790 pNewSep
->mnXLeft
= nXLeft
;
791 pNewSep
->mnXRight
= nXRight
;
792 pNewSep
->mpNextSep
= nullptr;
793 pNewSep
->mbRemoved
= false;
795 // connections from the new separation
796 pPrevSep
->mpNextSep
= pNewSep
;
802 bool ImplRegionBand::IsInside( long nX
)
804 ImplRegionBandSep
* pSep
= mpFirstSep
;
807 if ( (pSep
->mnXLeft
<= nX
) && (pSep
->mnXRight
>= nX
) )
810 pSep
= pSep
->mpNextSep
;
816 long ImplRegionBand::GetXLeftBoundary() const
818 assert(mpFirstSep
&& "ImplRegionBand::XLeftBoundary -> no separation in band!");
820 return mpFirstSep
->mnXLeft
;
823 long ImplRegionBand::GetXRightBoundary() const
825 SAL_WARN_IF( mpFirstSep
== nullptr, "vcl", "ImplRegionBand::XRightBoundary -> no separation in band!" );
827 // search last separation
828 ImplRegionBandSep
* pSep
= mpFirstSep
;
829 while ( pSep
->mpNextSep
)
830 pSep
= pSep
->mpNextSep
;
831 return pSep
->mnXRight
;
834 bool ImplRegionBand::operator==( const ImplRegionBand
& rRegionBand
) const
836 ImplRegionBandSep
* pOwnRectBandSep
= mpFirstSep
;
837 ImplRegionBandSep
* pSecondRectBandSep
= rRegionBand
.mpFirstSep
;
838 while ( pOwnRectBandSep
&& pSecondRectBandSep
)
840 // get boundaries of current rectangle
841 long nOwnXLeft
= pOwnRectBandSep
->mnXLeft
;
842 long nSecondXLeft
= pSecondRectBandSep
->mnXLeft
;
843 if ( nOwnXLeft
!= nSecondXLeft
)
846 long nOwnXRight
= pOwnRectBandSep
->mnXRight
;
847 long nSecondXRight
= pSecondRectBandSep
->mnXRight
;
848 if ( nOwnXRight
!= nSecondXRight
)
851 // get next separation from current band
852 pOwnRectBandSep
= pOwnRectBandSep
->mpNextSep
;
854 // get next separation from current band
855 pSecondRectBandSep
= pSecondRectBandSep
->mpNextSep
;
858 // different number of separations?
859 return !(pOwnRectBandSep
|| pSecondRectBandSep
);
862 ImplRegionBand
* ImplRegionBand::SplitBand (const sal_Int32 nY
)
864 OSL_ASSERT(nY
>mnYTop
);
865 OSL_ASSERT(nY
<=mnYBottom
);
867 // Create a copy of the given band (we tell the constructor to copy the points together
869 ImplRegionBand
* pLowerBand
= new ImplRegionBand(*this, false);
871 // Adapt vertical coordinates.
873 pLowerBand
->mnYTop
= nY
;
875 // Insert new band into list of bands.
876 pLowerBand
->mpNextBand
= mpNextBand
;
877 mpNextBand
= pLowerBand
;
878 pLowerBand
->mpPrevBand
= this;
879 if (pLowerBand
->mpNextBand
!= nullptr)
880 pLowerBand
->mpNextBand
->mpPrevBand
= pLowerBand
;
885 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */