xref: /trunk/main/vcl/source/gdi/regband.cxx (revision cf6516809c57e1bb0a940545cca99cdad54d4ce2)
19f62ea84SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
39f62ea84SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
49f62ea84SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
59f62ea84SAndrew Rist  * distributed with this work for additional information
69f62ea84SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
79f62ea84SAndrew Rist  * to you under the Apache License, Version 2.0 (the
89f62ea84SAndrew Rist  * "License"); you may not use this file except in compliance
99f62ea84SAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
119f62ea84SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
139f62ea84SAndrew Rist  * Unless required by applicable law or agreed to in writing,
149f62ea84SAndrew Rist  * software distributed under the License is distributed on an
159f62ea84SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
169f62ea84SAndrew Rist  * KIND, either express or implied.  See the License for the
179f62ea84SAndrew Rist  * specific language governing permissions and limitations
189f62ea84SAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
209f62ea84SAndrew Rist  *************************************************************/
219f62ea84SAndrew Rist 
229f62ea84SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_vcl.hxx"
26cdf0e10cSrcweir #include <tools/debug.hxx>
27cdf0e10cSrcweir #include <vcl/salbtype.hxx>
28cdf0e10cSrcweir #include <vcl/regband.hxx>
29cdf0e10cSrcweir 
30cdf0e10cSrcweir #include <algorithm>
31cdf0e10cSrcweir 
32cdf0e10cSrcweir 
33cdf0e10cSrcweir // =======================================================================
34cdf0e10cSrcweir //
35cdf0e10cSrcweir // ImplRegionBand
36cdf0e10cSrcweir //
37cdf0e10cSrcweir // Jedes Band enthaelt die zwischen der enthaltenen Ober- und Untergrenze
38cdf0e10cSrcweir // enthaltenen Rechtecke. Bei den Operationen Union, Intersect, XOr und
39cdf0e10cSrcweir // Exclude werden immer Rechtecke der gleichen Hoehe ausgewerte; die
40cdf0e10cSrcweir // Grenzen der Baender sind immer so zu waehlen, dasz dies moeglich ist.
41cdf0e10cSrcweir //
42cdf0e10cSrcweir // Die Rechtecke in den Baendern werden nach Moeglichkeit zusammengefaszt.
43cdf0e10cSrcweir //
44cdf0e10cSrcweir // Bei der Umwandlung von Polygonen werden alle Punkte des Polygons
45cdf0e10cSrcweir // in die einzelnen Baender eingetragen (sie stehen fuer jedes Band als
46cdf0e10cSrcweir // Punkte in einer Liste). Nach dem Eintragen der Punkte werden diese
47cdf0e10cSrcweir // in Rechtecke umgewandelt und die Liste der Punkte geloescht.
48cdf0e10cSrcweir //
49cdf0e10cSrcweir // -----------------------------------------------------------------------
50cdf0e10cSrcweir 
ImplRegionBand(long nTop,long nBottom)51cdf0e10cSrcweir ImplRegionBand::ImplRegionBand( long nTop, long nBottom )
52cdf0e10cSrcweir {
53cdf0e10cSrcweir     // save boundaries
54cdf0e10cSrcweir     mnYTop              = nTop;
55cdf0e10cSrcweir     mnYBottom           = nBottom;
56cdf0e10cSrcweir 
57cdf0e10cSrcweir     // initialize lists
58cdf0e10cSrcweir     mpNextBand          = NULL;
59cdf0e10cSrcweir     mpPrevBand          = NULL;
60cdf0e10cSrcweir     mpFirstSep          = NULL;
61cdf0e10cSrcweir     mpFirstBandPoint    = NULL;
62e6f63103SArmin Le Grand     mbTouched           = false;
63cdf0e10cSrcweir }
64cdf0e10cSrcweir 
65cdf0e10cSrcweir // -----------------------------------------------------------------------
66cdf0e10cSrcweir 
ImplRegionBand(const ImplRegionBand & rRegionBand,const bool bIgnorePoints)67cdf0e10cSrcweir ImplRegionBand::ImplRegionBand(
68cdf0e10cSrcweir     const ImplRegionBand& rRegionBand,
69cdf0e10cSrcweir     const bool bIgnorePoints)
70cdf0e10cSrcweir {
71cdf0e10cSrcweir     // copy boundaries
72cdf0e10cSrcweir     mnYTop              = rRegionBand.mnYTop;
73cdf0e10cSrcweir     mnYBottom           = rRegionBand.mnYBottom;
74cdf0e10cSrcweir     mbTouched           = rRegionBand.mbTouched;
75cdf0e10cSrcweir 
76cdf0e10cSrcweir     // initialisation
77cdf0e10cSrcweir     mpNextBand          = NULL;
78cdf0e10cSrcweir     mpPrevBand          = NULL;
79cdf0e10cSrcweir     mpFirstSep          = NULL;
80cdf0e10cSrcweir     mpFirstBandPoint    = NULL;
81cdf0e10cSrcweir 
82cdf0e10cSrcweir     // copy all elements of the list with separations
83cdf0e10cSrcweir     ImplRegionBandSep* pNewSep;
84cdf0e10cSrcweir     ImplRegionBandSep* pPrevSep = 0;
85cdf0e10cSrcweir     ImplRegionBandSep* pSep = rRegionBand.mpFirstSep;
86cdf0e10cSrcweir     while ( pSep )
87cdf0e10cSrcweir     {
88cdf0e10cSrcweir         // create new and copy data
89cdf0e10cSrcweir         pNewSep             = new ImplRegionBandSep;
90cdf0e10cSrcweir         pNewSep->mnXLeft    = pSep->mnXLeft;
91cdf0e10cSrcweir         pNewSep->mnXRight   = pSep->mnXRight;
92cdf0e10cSrcweir         pNewSep->mbRemoved  = pSep->mbRemoved;
93cdf0e10cSrcweir         pNewSep->mpNextSep  = NULL;
94cdf0e10cSrcweir         if ( pSep == rRegionBand.mpFirstSep )
95cdf0e10cSrcweir             mpFirstSep = pNewSep;
96cdf0e10cSrcweir         else
97cdf0e10cSrcweir             pPrevSep->mpNextSep = pNewSep;
98cdf0e10cSrcweir 
99cdf0e10cSrcweir         pPrevSep = pNewSep;
100cdf0e10cSrcweir         pSep = pSep->mpNextSep;
101cdf0e10cSrcweir     }
102cdf0e10cSrcweir 
103cdf0e10cSrcweir     if ( ! bIgnorePoints)
104cdf0e10cSrcweir     {
105cdf0e10cSrcweir         // Copy points.
106cdf0e10cSrcweir         ImplRegionBandPoint* pPoint = rRegionBand.mpFirstBandPoint;
107cdf0e10cSrcweir         ImplRegionBandPoint* pPrevPointCopy = NULL;
108cdf0e10cSrcweir         while (pPoint != NULL)
109cdf0e10cSrcweir         {
110cdf0e10cSrcweir             ImplRegionBandPoint* pPointCopy = new ImplRegionBandPoint();
111cdf0e10cSrcweir             pPointCopy->mnX = pPoint->mnX;
112cdf0e10cSrcweir             pPointCopy->mnLineId = pPoint->mnLineId;
113cdf0e10cSrcweir             pPointCopy->mbEndPoint = pPoint->mbEndPoint;
114cdf0e10cSrcweir             pPointCopy->meLineType = pPoint->meLineType;
115cdf0e10cSrcweir 
116cdf0e10cSrcweir             if (pPrevPointCopy != NULL)
117cdf0e10cSrcweir                 pPrevPointCopy->mpNextBandPoint = pPointCopy;
118cdf0e10cSrcweir             else
119cdf0e10cSrcweir                 mpFirstBandPoint = pPointCopy;
120cdf0e10cSrcweir 
121cdf0e10cSrcweir             pPrevPointCopy = pPointCopy;
122cdf0e10cSrcweir             pPoint = pPoint->mpNextBandPoint;
123cdf0e10cSrcweir         }
124cdf0e10cSrcweir     }
125cdf0e10cSrcweir }
126cdf0e10cSrcweir 
127cdf0e10cSrcweir // -----------------------------------------------------------------------
128cdf0e10cSrcweir 
~ImplRegionBand()129cdf0e10cSrcweir ImplRegionBand::~ImplRegionBand()
130cdf0e10cSrcweir {
131cdf0e10cSrcweir     DBG_ASSERT( mpFirstBandPoint == NULL, "ImplRegionBand::~ImplRegionBand -> pointlist not empty" );
132cdf0e10cSrcweir 
133cdf0e10cSrcweir     // delete elements of the list
134cdf0e10cSrcweir     ImplRegionBandSep* pSep = mpFirstSep;
135cdf0e10cSrcweir     while ( pSep )
136cdf0e10cSrcweir     {
137cdf0e10cSrcweir         ImplRegionBandSep* pTempSep = pSep->mpNextSep;
138cdf0e10cSrcweir         delete pSep;
139cdf0e10cSrcweir         pSep = pTempSep;
140cdf0e10cSrcweir     }
141cdf0e10cSrcweir 
142cdf0e10cSrcweir     // delete elements of the list
143cdf0e10cSrcweir     ImplRegionBandPoint* pPoint = mpFirstBandPoint;
144cdf0e10cSrcweir     while ( pPoint )
145cdf0e10cSrcweir     {
146cdf0e10cSrcweir         ImplRegionBandPoint* pTempPoint = pPoint->mpNextBandPoint;
147cdf0e10cSrcweir         delete pPoint;
148cdf0e10cSrcweir         pPoint = pTempPoint;
149cdf0e10cSrcweir     }
150cdf0e10cSrcweir }
151cdf0e10cSrcweir 
152cdf0e10cSrcweir // -----------------------------------------------------------------------
153cdf0e10cSrcweir //
154cdf0e10cSrcweir // generate separations from lines and process union with existing
155cdf0e10cSrcweir // separations
156cdf0e10cSrcweir 
ProcessPoints()157cdf0e10cSrcweir void ImplRegionBand::ProcessPoints()
158cdf0e10cSrcweir {
159cdf0e10cSrcweir     // check Pointlist
160cdf0e10cSrcweir     ImplRegionBandPoint* pRegionBandPoint = mpFirstBandPoint;
161cdf0e10cSrcweir     while ( pRegionBandPoint )
162cdf0e10cSrcweir     {
163cdf0e10cSrcweir         // within list?
164cdf0e10cSrcweir         if ( pRegionBandPoint && pRegionBandPoint->mpNextBandPoint )
165cdf0e10cSrcweir         {
166cdf0e10cSrcweir             // start/stop?
167cdf0e10cSrcweir             if ( pRegionBandPoint->mbEndPoint && pRegionBandPoint->mpNextBandPoint->mbEndPoint )
168cdf0e10cSrcweir             {
169cdf0e10cSrcweir                 // same direction? -> remove next point!
170cdf0e10cSrcweir                 if ( pRegionBandPoint->meLineType == pRegionBandPoint->mpNextBandPoint->meLineType )
171cdf0e10cSrcweir                 {
172cdf0e10cSrcweir                     ImplRegionBandPoint* pSaveRegionBandPoint = pRegionBandPoint->mpNextBandPoint;
173cdf0e10cSrcweir                     pRegionBandPoint->mpNextBandPoint = pRegionBandPoint->mpNextBandPoint->mpNextBandPoint;
174cdf0e10cSrcweir                     delete pSaveRegionBandPoint;
175cdf0e10cSrcweir                 }
176cdf0e10cSrcweir             }
177cdf0e10cSrcweir         }
178cdf0e10cSrcweir 
179cdf0e10cSrcweir         // continue with next element in the list
180cdf0e10cSrcweir         pRegionBandPoint = pRegionBandPoint->mpNextBandPoint;
181cdf0e10cSrcweir     }
182cdf0e10cSrcweir 
183cdf0e10cSrcweir     pRegionBandPoint = mpFirstBandPoint;
184cdf0e10cSrcweir     while ( pRegionBandPoint && pRegionBandPoint->mpNextBandPoint )
185cdf0e10cSrcweir     {
186cdf0e10cSrcweir         Union( pRegionBandPoint->mnX, pRegionBandPoint->mpNextBandPoint->mnX );
187cdf0e10cSrcweir 
188cdf0e10cSrcweir         ImplRegionBandPoint* pNextBandPoint = pRegionBandPoint->mpNextBandPoint->mpNextBandPoint;
189cdf0e10cSrcweir 
19086e1cf34SPedro Giffuni         // remove already processed points
191cdf0e10cSrcweir         delete pRegionBandPoint->mpNextBandPoint;
192cdf0e10cSrcweir         delete pRegionBandPoint;
193cdf0e10cSrcweir 
194cdf0e10cSrcweir         // continue with next element in the list
195cdf0e10cSrcweir         pRegionBandPoint = pNextBandPoint;
196cdf0e10cSrcweir     }
197cdf0e10cSrcweir 
198cdf0e10cSrcweir     // remove last element if necessary
199cdf0e10cSrcweir     if ( pRegionBandPoint )
200cdf0e10cSrcweir         delete pRegionBandPoint;
201cdf0e10cSrcweir 
202cdf0e10cSrcweir     // list is now empty
203cdf0e10cSrcweir     mpFirstBandPoint = NULL;
204cdf0e10cSrcweir }
205cdf0e10cSrcweir 
206cdf0e10cSrcweir // -----------------------------------------------------------------------
207cdf0e10cSrcweir //
208cdf0e10cSrcweir // generate separations from lines and process union with existing
209cdf0e10cSrcweir // separations
210cdf0e10cSrcweir 
InsertPoint(long nX,long nLineId,bool bEndPoint,LineType eLineType)211e6f63103SArmin Le Grand bool ImplRegionBand::InsertPoint( long nX, long nLineId,
212e6f63103SArmin Le Grand                                   bool bEndPoint, LineType eLineType )
213cdf0e10cSrcweir {
214cdf0e10cSrcweir     if ( !mpFirstBandPoint )
215cdf0e10cSrcweir     {
216cdf0e10cSrcweir         mpFirstBandPoint                  = new ImplRegionBandPoint;
217cdf0e10cSrcweir         mpFirstBandPoint->mnX             = nX;
218cdf0e10cSrcweir         mpFirstBandPoint->mnLineId        = nLineId;
219cdf0e10cSrcweir         mpFirstBandPoint->mbEndPoint      = bEndPoint;
220cdf0e10cSrcweir         mpFirstBandPoint->meLineType      = eLineType;
221cdf0e10cSrcweir         mpFirstBandPoint->mpNextBandPoint = NULL;
222e6f63103SArmin Le Grand         return true;
223cdf0e10cSrcweir     }
224cdf0e10cSrcweir 
22586e1cf34SPedro Giffuni     // look if line already touched the band
226cdf0e10cSrcweir     ImplRegionBandPoint* pRegionBandPoint = mpFirstBandPoint;
227cdf0e10cSrcweir     ImplRegionBandPoint* pLastTestedRegionBandPoint = NULL;
228cdf0e10cSrcweir     while( pRegionBandPoint )
229cdf0e10cSrcweir     {
230cdf0e10cSrcweir         if ( pRegionBandPoint->mnLineId == nLineId )
231cdf0e10cSrcweir         {
232cdf0e10cSrcweir             if ( bEndPoint )
233cdf0e10cSrcweir             {
234cdf0e10cSrcweir                 if( !pRegionBandPoint->mbEndPoint )
235cdf0e10cSrcweir                 {
236cdf0e10cSrcweir                     // remove old band point
237cdf0e10cSrcweir                     if( !mpFirstBandPoint->mpNextBandPoint )
238cdf0e10cSrcweir                     {
239cdf0e10cSrcweir                         // if we've only got one point => replace first point
240cdf0e10cSrcweir                         pRegionBandPoint->mnX = nX;
241e6f63103SArmin Le Grand                         pRegionBandPoint->mbEndPoint = true;
242e6f63103SArmin Le Grand                         return true;
243cdf0e10cSrcweir                     }
244cdf0e10cSrcweir                     else
245cdf0e10cSrcweir                     {
246cdf0e10cSrcweir                         // remove current point
247cdf0e10cSrcweir                         if( !pLastTestedRegionBandPoint )
248cdf0e10cSrcweir                         {
249cdf0e10cSrcweir                             // remove and delete old first point
250cdf0e10cSrcweir                             ImplRegionBandPoint* pSaveBandPoint = mpFirstBandPoint;
251cdf0e10cSrcweir                             mpFirstBandPoint = mpFirstBandPoint->mpNextBandPoint;
252cdf0e10cSrcweir                             delete pSaveBandPoint;
253cdf0e10cSrcweir                         }
254cdf0e10cSrcweir                         else
255cdf0e10cSrcweir                         {
256cdf0e10cSrcweir                             // remove and delete current band point
257cdf0e10cSrcweir                             pLastTestedRegionBandPoint->mpNextBandPoint = pRegionBandPoint->mpNextBandPoint;
258cdf0e10cSrcweir                             delete pRegionBandPoint;
259cdf0e10cSrcweir                         }
260cdf0e10cSrcweir 
261cdf0e10cSrcweir                         break;
262cdf0e10cSrcweir                     }
263cdf0e10cSrcweir                 }
264cdf0e10cSrcweir             }
265cdf0e10cSrcweir             else
266e6f63103SArmin Le Grand                 return false;
267cdf0e10cSrcweir         }
268cdf0e10cSrcweir 
269cdf0e10cSrcweir         // use next element
270cdf0e10cSrcweir         pLastTestedRegionBandPoint = pRegionBandPoint;
271cdf0e10cSrcweir         pRegionBandPoint = pRegionBandPoint->mpNextBandPoint;
272cdf0e10cSrcweir     }
273cdf0e10cSrcweir 
274cdf0e10cSrcweir     // search appropriate position and insert point into the list
275cdf0e10cSrcweir     ImplRegionBandPoint* pNewRegionBandPoint;
276cdf0e10cSrcweir 
277cdf0e10cSrcweir     pRegionBandPoint = mpFirstBandPoint;
278cdf0e10cSrcweir     pLastTestedRegionBandPoint = NULL;
279cdf0e10cSrcweir     while ( pRegionBandPoint )
280cdf0e10cSrcweir     {
281*870c3792Smseidel         // new point completely left? -> insert as first point
282cdf0e10cSrcweir         if ( nX <= pRegionBandPoint->mnX )
283cdf0e10cSrcweir         {
284cdf0e10cSrcweir             pNewRegionBandPoint                     = new ImplRegionBandPoint;
285cdf0e10cSrcweir             pNewRegionBandPoint->mnX                = nX;
286cdf0e10cSrcweir             pNewRegionBandPoint->mnLineId           = nLineId;
287cdf0e10cSrcweir             pNewRegionBandPoint->mbEndPoint         = bEndPoint;
288cdf0e10cSrcweir             pNewRegionBandPoint->meLineType         = eLineType;
289cdf0e10cSrcweir             pNewRegionBandPoint->mpNextBandPoint    = pRegionBandPoint;
290cdf0e10cSrcweir 
291cdf0e10cSrcweir             // connections to the new point
292cdf0e10cSrcweir             if ( !pLastTestedRegionBandPoint )
293cdf0e10cSrcweir                 mpFirstBandPoint = pNewRegionBandPoint;
294cdf0e10cSrcweir             else
295cdf0e10cSrcweir                 pLastTestedRegionBandPoint->mpNextBandPoint = pNewRegionBandPoint;
296cdf0e10cSrcweir 
297e6f63103SArmin Le Grand             return true;
298cdf0e10cSrcweir         }
299cdf0e10cSrcweir 
300cdf0e10cSrcweir         // use next element
301cdf0e10cSrcweir         pLastTestedRegionBandPoint = pRegionBandPoint;
302cdf0e10cSrcweir         pRegionBandPoint = pRegionBandPoint->mpNextBandPoint;
303cdf0e10cSrcweir     }
304cdf0e10cSrcweir 
305cdf0e10cSrcweir     // not inserted -> add to the end of the list
306cdf0e10cSrcweir     pNewRegionBandPoint                     = new ImplRegionBandPoint;
307cdf0e10cSrcweir     pNewRegionBandPoint->mnX                = nX;
308cdf0e10cSrcweir     pNewRegionBandPoint->mnLineId           = nLineId;
309cdf0e10cSrcweir     pNewRegionBandPoint->mbEndPoint         = bEndPoint;
310cdf0e10cSrcweir     pNewRegionBandPoint->meLineType         = eLineType;
311cdf0e10cSrcweir     pNewRegionBandPoint->mpNextBandPoint    = NULL;
312cdf0e10cSrcweir 
313cdf0e10cSrcweir     // connections to the new point
314cdf0e10cSrcweir     pLastTestedRegionBandPoint->mpNextBandPoint = pNewRegionBandPoint;
315cdf0e10cSrcweir 
316e6f63103SArmin Le Grand     return true;
317cdf0e10cSrcweir }
318cdf0e10cSrcweir 
319cdf0e10cSrcweir // -----------------------------------------------------------------------
320cdf0e10cSrcweir 
MoveX(long nHorzMove)321cdf0e10cSrcweir void ImplRegionBand::MoveX( long nHorzMove )
322cdf0e10cSrcweir {
323cdf0e10cSrcweir     // move all x-separations
324cdf0e10cSrcweir     ImplRegionBandSep* pSep = mpFirstSep;
325cdf0e10cSrcweir     while ( pSep )
326cdf0e10cSrcweir     {
327cdf0e10cSrcweir         pSep->mnXLeft  += nHorzMove;
328cdf0e10cSrcweir         pSep->mnXRight += nHorzMove;
329cdf0e10cSrcweir         pSep = pSep->mpNextSep;
330cdf0e10cSrcweir     }
331cdf0e10cSrcweir }
332cdf0e10cSrcweir 
333cdf0e10cSrcweir // -----------------------------------------------------------------------
334cdf0e10cSrcweir 
ScaleX(double fHorzScale)335cdf0e10cSrcweir void ImplRegionBand::ScaleX( double fHorzScale )
336cdf0e10cSrcweir {
337cdf0e10cSrcweir     ImplRegionBandSep* pSep = mpFirstSep;
338cdf0e10cSrcweir     while ( pSep )
339cdf0e10cSrcweir     {
340cdf0e10cSrcweir         pSep->mnXLeft   = FRound( pSep->mnXLeft * fHorzScale );
341cdf0e10cSrcweir         pSep->mnXRight  = FRound( pSep->mnXRight * fHorzScale );
342cdf0e10cSrcweir         pSep = pSep->mpNextSep;
343cdf0e10cSrcweir     }
344cdf0e10cSrcweir }
345cdf0e10cSrcweir 
346cdf0e10cSrcweir // -----------------------------------------------------------------------
347cdf0e10cSrcweir //
348*870c3792Smseidel // combine overlapping separations
349cdf0e10cSrcweir 
OptimizeBand()350e6f63103SArmin Le Grand bool ImplRegionBand::OptimizeBand()
351cdf0e10cSrcweir {
352cdf0e10cSrcweir     ImplRegionBandSep* pPrevSep = 0;
353cdf0e10cSrcweir     ImplRegionBandSep* pSep = mpFirstSep;
354cdf0e10cSrcweir     while ( pSep )
355cdf0e10cSrcweir     {
356cdf0e10cSrcweir         // remove?
357cdf0e10cSrcweir         if ( pSep->mbRemoved || (pSep->mnXRight < pSep->mnXLeft) )
358cdf0e10cSrcweir         {
359cdf0e10cSrcweir             ImplRegionBandSep* pOldSep = pSep;
360cdf0e10cSrcweir             if ( pSep == mpFirstSep )
361cdf0e10cSrcweir                 mpFirstSep = pSep->mpNextSep;
362cdf0e10cSrcweir             else
363cdf0e10cSrcweir                 pPrevSep->mpNextSep = pSep->mpNextSep;
364cdf0e10cSrcweir             pSep = pSep->mpNextSep;
365cdf0e10cSrcweir             delete pOldSep;
366cdf0e10cSrcweir             continue;
367cdf0e10cSrcweir         }
368cdf0e10cSrcweir 
369*870c3792Smseidel         // overlapping separations? -> combine!
370cdf0e10cSrcweir         if ( pSep->mpNextSep )
371cdf0e10cSrcweir         {
372cdf0e10cSrcweir             if ( (pSep->mnXRight+1) >= pSep->mpNextSep->mnXLeft )
373cdf0e10cSrcweir             {
374cdf0e10cSrcweir                 if ( pSep->mpNextSep->mnXRight > pSep->mnXRight )
375cdf0e10cSrcweir                     pSep->mnXRight = pSep->mpNextSep->mnXRight;
376cdf0e10cSrcweir 
377cdf0e10cSrcweir                 ImplRegionBandSep* pOldSep = pSep->mpNextSep;
378cdf0e10cSrcweir                 pSep->mpNextSep = pOldSep->mpNextSep;
379cdf0e10cSrcweir                 delete pOldSep;
380cdf0e10cSrcweir                 continue;
381cdf0e10cSrcweir             }
382cdf0e10cSrcweir         }
383cdf0e10cSrcweir 
384cdf0e10cSrcweir         pPrevSep = pSep;
385cdf0e10cSrcweir         pSep = pSep->mpNextSep;
386cdf0e10cSrcweir     }
387cdf0e10cSrcweir 
388e6f63103SArmin Le Grand     return true;
389cdf0e10cSrcweir }
390cdf0e10cSrcweir 
391cdf0e10cSrcweir // -----------------------------------------------------------------------
392cdf0e10cSrcweir 
Union(long nXLeft,long nXRight)393cdf0e10cSrcweir void ImplRegionBand::Union( long nXLeft, long nXRight )
394cdf0e10cSrcweir {
395cdf0e10cSrcweir     DBG_ASSERT( nXLeft <= nXRight, "ImplRegionBand::Union(): nxLeft > nXRight" );
396cdf0e10cSrcweir 
397cdf0e10cSrcweir     // band empty? -> add element
398cdf0e10cSrcweir     if ( !mpFirstSep )
399cdf0e10cSrcweir     {
400cdf0e10cSrcweir         mpFirstSep              = new ImplRegionBandSep;
401cdf0e10cSrcweir         mpFirstSep->mnXLeft     = nXLeft;
402cdf0e10cSrcweir         mpFirstSep->mnXRight    = nXRight;
403e6f63103SArmin Le Grand         mpFirstSep->mbRemoved   = false;
404cdf0e10cSrcweir         mpFirstSep->mpNextSep   = NULL;
405cdf0e10cSrcweir         return;
406cdf0e10cSrcweir     }
407cdf0e10cSrcweir 
408cdf0e10cSrcweir     // process real union
409cdf0e10cSrcweir     ImplRegionBandSep* pNewSep;
410cdf0e10cSrcweir     ImplRegionBandSep* pPrevSep = 0;
411cdf0e10cSrcweir     ImplRegionBandSep* pSep = mpFirstSep;
412cdf0e10cSrcweir     while ( pSep )
413cdf0e10cSrcweir     {
414cdf0e10cSrcweir         // new separation completely inside? nothing to do!
415cdf0e10cSrcweir         if ( (nXLeft >= pSep->mnXLeft) && (nXRight <= pSep->mnXRight) )
416cdf0e10cSrcweir             return;
417cdf0e10cSrcweir 
418*870c3792Smseidel         // new separation completely left? -> new separation!
419cdf0e10cSrcweir         if ( nXRight < pSep->mnXLeft )
420cdf0e10cSrcweir         {
421cdf0e10cSrcweir             pNewSep             = new ImplRegionBandSep;
422cdf0e10cSrcweir             pNewSep->mnXLeft    = nXLeft;
423cdf0e10cSrcweir             pNewSep->mnXRight   = nXRight;
424e6f63103SArmin Le Grand             pNewSep->mbRemoved  = false;
425cdf0e10cSrcweir 
426cdf0e10cSrcweir             pNewSep->mpNextSep = pSep;
427cdf0e10cSrcweir             if ( pSep == mpFirstSep )
428cdf0e10cSrcweir                 mpFirstSep = pNewSep;
429cdf0e10cSrcweir             else
430cdf0e10cSrcweir                 pPrevSep->mpNextSep = pNewSep;
431cdf0e10cSrcweir             break;
432cdf0e10cSrcweir         }
433cdf0e10cSrcweir 
434*870c3792Smseidel         // new separation overlapping from left? -> extend boundary
435cdf0e10cSrcweir         if ( (nXRight >= pSep->mnXLeft) && (nXLeft <= pSep->mnXLeft) )
436cdf0e10cSrcweir             pSep->mnXLeft = nXLeft;
437cdf0e10cSrcweir 
438*870c3792Smseidel         // new separation overlapping from right? -> extend boundary
439cdf0e10cSrcweir         if ( (nXLeft <= pSep->mnXRight) && (nXRight > pSep->mnXRight) )
440cdf0e10cSrcweir         {
441cdf0e10cSrcweir             pSep->mnXRight = nXRight;
442cdf0e10cSrcweir             break;
443cdf0e10cSrcweir         }
444cdf0e10cSrcweir 
445cdf0e10cSrcweir         // not inserted, but last element? -> add to the end of the list
446cdf0e10cSrcweir         if ( !pSep->mpNextSep && (nXLeft > pSep->mnXRight) )
447cdf0e10cSrcweir         {
448cdf0e10cSrcweir             pNewSep             = new ImplRegionBandSep;
449cdf0e10cSrcweir             pNewSep->mnXLeft    = nXLeft;
450cdf0e10cSrcweir             pNewSep->mnXRight   = nXRight;
451e6f63103SArmin Le Grand             pNewSep->mbRemoved  = false;
452cdf0e10cSrcweir 
453cdf0e10cSrcweir             pSep->mpNextSep     = pNewSep;
454cdf0e10cSrcweir             pNewSep->mpNextSep  = NULL;
455cdf0e10cSrcweir             break;
456cdf0e10cSrcweir         }
457cdf0e10cSrcweir 
458cdf0e10cSrcweir         pPrevSep = pSep;
459cdf0e10cSrcweir         pSep = pSep->mpNextSep;
460cdf0e10cSrcweir     }
461cdf0e10cSrcweir 
462cdf0e10cSrcweir     OptimizeBand();
463cdf0e10cSrcweir }
464cdf0e10cSrcweir 
465cdf0e10cSrcweir // -----------------------------------------------------------------------
466cdf0e10cSrcweir 
Intersect(long nXLeft,long nXRight)467cdf0e10cSrcweir void ImplRegionBand::Intersect( long nXLeft, long nXRight )
468cdf0e10cSrcweir {
469cdf0e10cSrcweir     DBG_ASSERT( nXLeft <= nXRight, "ImplRegionBand::Intersect(): nxLeft > nXRight" );
470cdf0e10cSrcweir 
471cdf0e10cSrcweir     // band has been touched
472e6f63103SArmin Le Grand     mbTouched = true;
473cdf0e10cSrcweir 
474cdf0e10cSrcweir     // band empty? -> nothing to do
475cdf0e10cSrcweir     if ( !mpFirstSep )
476cdf0e10cSrcweir         return;
477cdf0e10cSrcweir 
478cdf0e10cSrcweir     // process real intersection
479cdf0e10cSrcweir     ImplRegionBandSep* pSep = mpFirstSep;
480cdf0e10cSrcweir     while ( pSep )
481cdf0e10cSrcweir     {
482*870c3792Smseidel         // new separation completely outside? -> remove separation
483cdf0e10cSrcweir         if ( (nXRight < pSep->mnXLeft) || (nXLeft > pSep->mnXRight) )
484cdf0e10cSrcweir             // will be removed from the optimizer
485e6f63103SArmin Le Grand             pSep->mbRemoved = true;
486cdf0e10cSrcweir 
487*870c3792Smseidel         // new separation overlapping from left? -> reduce right boundary
488cdf0e10cSrcweir         if ( (nXLeft <= pSep->mnXLeft) &&
489cdf0e10cSrcweir              (nXRight <= pSep->mnXRight) &&
490cdf0e10cSrcweir              (nXRight >= pSep->mnXLeft) )
491cdf0e10cSrcweir             pSep->mnXRight = nXRight;
492cdf0e10cSrcweir 
493*870c3792Smseidel         // new separation overlapping from right? -> reduce right boundary
494cdf0e10cSrcweir         if ( (nXLeft >= pSep->mnXLeft) &&
495cdf0e10cSrcweir              (nXLeft <= pSep->mnXRight) &&
496cdf0e10cSrcweir              (nXRight >= pSep->mnXRight) )
497cdf0e10cSrcweir             pSep->mnXLeft = nXLeft;
498cdf0e10cSrcweir 
499cdf0e10cSrcweir         // new separation within the actual one? -> reduce both boundaries
500cdf0e10cSrcweir         if ( (nXLeft >= pSep->mnXLeft) && (nXRight <= pSep->mnXRight) )
501cdf0e10cSrcweir         {
502cdf0e10cSrcweir             pSep->mnXRight = nXRight;
503cdf0e10cSrcweir             pSep->mnXLeft = nXLeft;
504cdf0e10cSrcweir         }
505cdf0e10cSrcweir 
506cdf0e10cSrcweir         pSep = pSep->mpNextSep;
507cdf0e10cSrcweir     }
508cdf0e10cSrcweir 
509cdf0e10cSrcweir     OptimizeBand();
510cdf0e10cSrcweir }
511cdf0e10cSrcweir 
512cdf0e10cSrcweir // -----------------------------------------------------------------------
513cdf0e10cSrcweir 
Exclude(long nXLeft,long nXRight)514cdf0e10cSrcweir void ImplRegionBand::Exclude( long nXLeft, long nXRight )
515cdf0e10cSrcweir {
516cdf0e10cSrcweir     DBG_ASSERT( nXLeft <= nXRight, "ImplRegionBand::Exclude(): nxLeft > nXRight" );
517cdf0e10cSrcweir 
518cdf0e10cSrcweir     // band has been touched
519e6f63103SArmin Le Grand     mbTouched = true;
520cdf0e10cSrcweir 
521cdf0e10cSrcweir     // band empty? -> nothing to do
522cdf0e10cSrcweir     if ( !mpFirstSep )
523cdf0e10cSrcweir         return;
524cdf0e10cSrcweir 
525cdf0e10cSrcweir     // process real exclusion
526cdf0e10cSrcweir     ImplRegionBandSep* pNewSep;
527cdf0e10cSrcweir     ImplRegionBandSep* pPrevSep = 0;
528cdf0e10cSrcweir     ImplRegionBandSep* pSep = mpFirstSep;
529cdf0e10cSrcweir     while ( pSep  )
530cdf0e10cSrcweir     {
531e6f63103SArmin Le Grand         bool bSepProcessed = false;
532cdf0e10cSrcweir 
533cdf0e10cSrcweir         // new separation completely overlapping? -> remove separation
534cdf0e10cSrcweir         if ( (nXLeft <= pSep->mnXLeft) && (nXRight >= pSep->mnXRight) )
535cdf0e10cSrcweir         {
536cdf0e10cSrcweir             // will be removed from the optimizer
537e6f63103SArmin Le Grand             pSep->mbRemoved = true;
538e6f63103SArmin Le Grand             bSepProcessed = true;
539cdf0e10cSrcweir         }
540cdf0e10cSrcweir 
541*870c3792Smseidel         // new separation overlapping from left? -> reduce boundary
542cdf0e10cSrcweir         if ( !bSepProcessed )
543cdf0e10cSrcweir         {
544cdf0e10cSrcweir             if ( (nXRight >= pSep->mnXLeft) && (nXLeft <= pSep->mnXLeft) )
545cdf0e10cSrcweir             {
546cdf0e10cSrcweir                 pSep->mnXLeft = nXRight+1;
547e6f63103SArmin Le Grand                 bSepProcessed = true;
548cdf0e10cSrcweir             }
549cdf0e10cSrcweir         }
550cdf0e10cSrcweir 
551*870c3792Smseidel         // new separation overlapping from right? -> reduce boundary
552cdf0e10cSrcweir         if ( !bSepProcessed )
553cdf0e10cSrcweir         {
554cdf0e10cSrcweir             if ( (nXLeft <= pSep->mnXRight) && (nXRight > pSep->mnXRight) )
555cdf0e10cSrcweir             {
556cdf0e10cSrcweir                 pSep->mnXRight = nXLeft-1;
557e6f63103SArmin Le Grand                 bSepProcessed = true;
558cdf0e10cSrcweir             }
559cdf0e10cSrcweir         }
560cdf0e10cSrcweir 
561cdf0e10cSrcweir         // new separation within the actual one? -> reduce boundary
562cdf0e10cSrcweir         // and add new entry for reminder
563cdf0e10cSrcweir         if ( !bSepProcessed )
564cdf0e10cSrcweir         {
565cdf0e10cSrcweir             if ( (nXLeft >= pSep->mnXLeft) && (nXRight <= pSep->mnXRight) )
566cdf0e10cSrcweir             {
567cdf0e10cSrcweir                 pNewSep             = new ImplRegionBandSep;
568cdf0e10cSrcweir                 pNewSep->mnXLeft    = pSep->mnXLeft;
569cdf0e10cSrcweir                 pNewSep->mnXRight   = nXLeft-1;
570e6f63103SArmin Le Grand                 pNewSep->mbRemoved  = false;
571cdf0e10cSrcweir 
572cdf0e10cSrcweir                 pSep->mnXLeft = nXRight+1;
573cdf0e10cSrcweir 
574cdf0e10cSrcweir                 // connections from the new separation
575cdf0e10cSrcweir                 pNewSep->mpNextSep = pSep;
576cdf0e10cSrcweir 
577cdf0e10cSrcweir                 // connections to the new separation
578cdf0e10cSrcweir                 if ( pSep == mpFirstSep )
579cdf0e10cSrcweir                     mpFirstSep = pNewSep;
580cdf0e10cSrcweir                 else
581cdf0e10cSrcweir                     pPrevSep->mpNextSep = pNewSep;
582cdf0e10cSrcweir             }
583cdf0e10cSrcweir         }
584cdf0e10cSrcweir 
585cdf0e10cSrcweir         pPrevSep = pSep;
586cdf0e10cSrcweir         pSep = pSep->mpNextSep;
587cdf0e10cSrcweir     }
588cdf0e10cSrcweir 
589cdf0e10cSrcweir     OptimizeBand();
590cdf0e10cSrcweir }
591cdf0e10cSrcweir 
592cdf0e10cSrcweir // -----------------------------------------------------------------------
593cdf0e10cSrcweir 
XOr(long nXLeft,long nXRight)594cdf0e10cSrcweir void ImplRegionBand::XOr( long nXLeft, long nXRight )
595cdf0e10cSrcweir {
596cdf0e10cSrcweir     DBG_ASSERT( nXLeft <= nXRight, "ImplRegionBand::XOr(): nxLeft > nXRight" );
597cdf0e10cSrcweir 
598cdf0e10cSrcweir     // #i46602# Reworked rectangle Xor
599cdf0e10cSrcweir     //
600cdf0e10cSrcweir     // In general, we can distinguish 11 cases of intersection
60156b8eddcSmseidel     // (details below). The old implementation explicitly handled 7
602cdf0e10cSrcweir     // cases (numbered in the order of appearance, use CVS to get your
603cdf0e10cSrcweir     // hands on the old version), therefore, I've sticked to that
604cdf0e10cSrcweir     // order, and added four more cases. The code below references
605cdf0e10cSrcweir     // those numbers via #1, #2, etc.
606cdf0e10cSrcweir     //
607cdf0e10cSrcweir     // Num Mnem        newX:oldX newY:oldY  Description                                             Result          Can quit?
608cdf0e10cSrcweir     //
609cdf0e10cSrcweir     // #1  Empty band      -         -      The band is empty, thus, simply add new bandSep         just add        Yes
610cdf0e10cSrcweir     //
611cdf0e10cSrcweir     // #2  apart           -         -      The rectangles are disjunct, add new one as is          just add        Yes
612cdf0e10cSrcweir     //
613cdf0e10cSrcweir     // #3  atop            ==        ==     The rectangles are _exactly_ the same, remove existing  just remove     Yes
614cdf0e10cSrcweir     //
615cdf0e10cSrcweir     // #4  around          <         >      The new rectangle extends the old to both sides         intersect       No
616cdf0e10cSrcweir     //
617cdf0e10cSrcweir     // #5  left            <         <      The new rectangle is left of the old (but intersects)   intersect       Yes
618cdf0e10cSrcweir     //
619cdf0e10cSrcweir     // #5b left-atop       <         ==     The new is left of the old, and coincides on the right  intersect       Yes
620cdf0e10cSrcweir     //
621cdf0e10cSrcweir     // #6  right           >         >      The new is right of the old (but intersects)            intersect       No
622cdf0e10cSrcweir     //
623cdf0e10cSrcweir     // #6b right-atop      ==        >      The new is right of the old, and coincides on the left  intersect       No
624cdf0e10cSrcweir     //
625cdf0e10cSrcweir     // #7 inside           >         <      The new is fully inside the old                         intersect       Yes
626cdf0e10cSrcweir     //
627cdf0e10cSrcweir     // #8 inside-right     >         ==     The new is fully inside the old, coincides on the right intersect       Yes
628cdf0e10cSrcweir     //
629cdf0e10cSrcweir     // #9 inside-left      ==        <      The new is fully inside the old, coincides on the left  intersect       Yes
630cdf0e10cSrcweir     //
631cdf0e10cSrcweir     //
632cdf0e10cSrcweir     // Then, to correctly perform XOr, the segment that's switched off
633cdf0e10cSrcweir     // (i.e. the overlapping part of the old and the new segment) must
634cdf0e10cSrcweir     // be extended by one pixel value at each border:
635cdf0e10cSrcweir     //           1   1
636cdf0e10cSrcweir     // 0   4     0   4
637cdf0e10cSrcweir     // 111100000001111
638cdf0e10cSrcweir     //
639cdf0e10cSrcweir     // Clearly, the leading band sep now goes from 0 to 3, and the
640cdf0e10cSrcweir     // trailing band sep from 11 to 14. This mimicks the xor look of a
641cdf0e10cSrcweir     // bitmap operation.
642cdf0e10cSrcweir     //
643cdf0e10cSrcweir 
644cdf0e10cSrcweir     // band empty? -> add element
645cdf0e10cSrcweir     if ( !mpFirstSep )
646cdf0e10cSrcweir     {
647cdf0e10cSrcweir         mpFirstSep              = new ImplRegionBandSep;
648cdf0e10cSrcweir         mpFirstSep->mnXLeft     = nXLeft;
649cdf0e10cSrcweir         mpFirstSep->mnXRight    = nXRight;
650e6f63103SArmin Le Grand         mpFirstSep->mbRemoved   = false;
651cdf0e10cSrcweir         mpFirstSep->mpNextSep   = NULL;
652cdf0e10cSrcweir         return;
653cdf0e10cSrcweir     }
654cdf0e10cSrcweir 
655cdf0e10cSrcweir     // process real xor
656cdf0e10cSrcweir     ImplRegionBandSep* pNewSep;
657cdf0e10cSrcweir     ImplRegionBandSep* pPrevSep = 0;
658cdf0e10cSrcweir     ImplRegionBandSep* pSep = mpFirstSep;
659cdf0e10cSrcweir 
660cdf0e10cSrcweir     while ( pSep  )
661cdf0e10cSrcweir     {
662cdf0e10cSrcweir         long nOldLeft( pSep->mnXLeft );
663cdf0e10cSrcweir         long nOldRight( pSep->mnXRight );
664cdf0e10cSrcweir 
665cdf0e10cSrcweir         // did the current segment actually touch the new rect? If
666cdf0e10cSrcweir         // not, skip all comparisons, go on, loop and try to find
667cdf0e10cSrcweir         // intersecting bandSep
668cdf0e10cSrcweir         if( nXLeft <= nOldRight )
669cdf0e10cSrcweir         {
670cdf0e10cSrcweir             if( nXRight < nOldLeft )
671cdf0e10cSrcweir             {
672cdf0e10cSrcweir                 // #2
673cdf0e10cSrcweir 
674cdf0e10cSrcweir                 // add _before_ current bandSep
675cdf0e10cSrcweir                 pNewSep             = new ImplRegionBandSep;
676cdf0e10cSrcweir                 pNewSep->mnXLeft    = nXLeft;
677cdf0e10cSrcweir                 pNewSep->mnXRight   = nXRight;
678cdf0e10cSrcweir                 pNewSep->mpNextSep  = pSep;
679e6f63103SArmin Le Grand                 pNewSep->mbRemoved  = false;
680cdf0e10cSrcweir 
681cdf0e10cSrcweir                 // connections from the new separation
682cdf0e10cSrcweir                 pNewSep->mpNextSep = pSep;
683cdf0e10cSrcweir 
684cdf0e10cSrcweir                 // connections to the new separation
685cdf0e10cSrcweir                 if ( pSep == mpFirstSep )
686cdf0e10cSrcweir                     mpFirstSep = pNewSep;
687cdf0e10cSrcweir                 else
688cdf0e10cSrcweir                     pPrevSep->mpNextSep = pNewSep;
689cdf0e10cSrcweir                 pPrevSep = NULL; // do not run accidentally into the "right" case when breaking the loop
690cdf0e10cSrcweir                 break;
691cdf0e10cSrcweir             }
692cdf0e10cSrcweir             else if( nXLeft == nOldLeft && nXRight == nOldRight )
693cdf0e10cSrcweir             {
694cdf0e10cSrcweir                 // #3
695e6f63103SArmin Le Grand                 pSep->mbRemoved = true;
696cdf0e10cSrcweir                 pPrevSep = NULL; // do not run accidentally into the "right" case when breaking the loop
697cdf0e10cSrcweir                 break;
698cdf0e10cSrcweir             }
699cdf0e10cSrcweir             else if( nXLeft != nOldLeft && nXRight == nOldRight )
700cdf0e10cSrcweir             {
701cdf0e10cSrcweir                 // # 5b, 8
702cdf0e10cSrcweir                 if( nXLeft < nOldLeft )
703cdf0e10cSrcweir                 {
704cdf0e10cSrcweir                     nXRight = nOldLeft; // 5b
705cdf0e10cSrcweir                 }
706cdf0e10cSrcweir                 else
707cdf0e10cSrcweir                 {
708cdf0e10cSrcweir                     nXRight = nXLeft; // 8
709cdf0e10cSrcweir                     nXLeft = nOldLeft;
710cdf0e10cSrcweir                 }
711cdf0e10cSrcweir 
712cdf0e10cSrcweir                 pSep->mnXLeft = nXLeft;
713cdf0e10cSrcweir                 pSep->mnXRight = nXRight-1;
714cdf0e10cSrcweir 
715cdf0e10cSrcweir                 pPrevSep = NULL; // do not run accidentally into the "right" case when breaking the loop
716cdf0e10cSrcweir                 break;
717cdf0e10cSrcweir             }
718cdf0e10cSrcweir             else if( nXLeft == nOldLeft && nXRight != nOldRight )
719cdf0e10cSrcweir             {
720cdf0e10cSrcweir                 // # 6b, 9
721cdf0e10cSrcweir 
722cdf0e10cSrcweir                 if( nXRight > nOldRight )
723cdf0e10cSrcweir                 {
724cdf0e10cSrcweir                     nXLeft = nOldRight+1; // 6b
725cdf0e10cSrcweir 
726cdf0e10cSrcweir                     // cannot break here, simply mark segment as removed,
727cdf0e10cSrcweir                     // and go on with adapted nXLeft/nXRight
728e6f63103SArmin Le Grand                     pSep->mbRemoved = true;
729cdf0e10cSrcweir                 }
730cdf0e10cSrcweir                 else
731cdf0e10cSrcweir                 {
732cdf0e10cSrcweir                     pSep->mnXLeft = nXRight+1; // 9
733cdf0e10cSrcweir 
734cdf0e10cSrcweir                     pPrevSep = NULL; // do not run accidentally into the "right" case when breaking the loop
735cdf0e10cSrcweir                     break;
736cdf0e10cSrcweir                 }
737cdf0e10cSrcweir             }
738cdf0e10cSrcweir             else // if( nXLeft != nOldLeft && nXRight != nOldRight ) follows automatically
739cdf0e10cSrcweir             {
740cdf0e10cSrcweir                 // #4,5,6,7
741cdf0e10cSrcweir                 DBG_ASSERT( nXLeft != nOldLeft && nXRight != nOldRight,
742cdf0e10cSrcweir                             "ImplRegionBand::XOr(): Case 4,5,6,7 expected all coordinates to be not equal!" );
743cdf0e10cSrcweir 
744cdf0e10cSrcweir                 // The plain-jane check would look like this:
745cdf0e10cSrcweir                 //
746cdf0e10cSrcweir                 // if( nXLeft < nOldLeft )
747cdf0e10cSrcweir                 // {
748cdf0e10cSrcweir                 //     // #4,5
749cdf0e10cSrcweir                 //     if( nXRight > nOldRight )
750cdf0e10cSrcweir                 //     {
751cdf0e10cSrcweir                 //        // #4
752cdf0e10cSrcweir                 //     }
753cdf0e10cSrcweir                 //     else
754cdf0e10cSrcweir                 //     {
755cdf0e10cSrcweir                 //         // #5 done!
756cdf0e10cSrcweir                 //     }
757cdf0e10cSrcweir                 // }
758cdf0e10cSrcweir                 // else
759cdf0e10cSrcweir                 // {
760cdf0e10cSrcweir                 //     // #6,7
761cdf0e10cSrcweir                 //     if( nXRight > nOldRight )
762cdf0e10cSrcweir                 //     {
763cdf0e10cSrcweir                 //         // #6
764cdf0e10cSrcweir                 //     }
765cdf0e10cSrcweir                 //     else
766cdf0e10cSrcweir                 //     {
767cdf0e10cSrcweir                 //         // #7 done!
768cdf0e10cSrcweir                 //     }
769cdf0e10cSrcweir                 // }
770cdf0e10cSrcweir                 //
771cdf0e10cSrcweir                 // but since we generally don't have to care whether
772cdf0e10cSrcweir                 // it's 4 or 6 (only that we must not stop processing
773cdf0e10cSrcweir                 // here), condensed that in such a way that only the
774cdf0e10cSrcweir                 // coordinates get shuffled into correct ordering.
775cdf0e10cSrcweir 
776cdf0e10cSrcweir                 if( nXLeft < nOldLeft )
777cdf0e10cSrcweir                     ::std::swap( nOldLeft, nXLeft );
778cdf0e10cSrcweir 
779cdf0e10cSrcweir                 bool bDone( false );
780cdf0e10cSrcweir 
781cdf0e10cSrcweir                 if( nXRight < nOldRight )
782cdf0e10cSrcweir                 {
783cdf0e10cSrcweir                     ::std::swap( nOldRight, nXRight );
784cdf0e10cSrcweir                     bDone = true;
785cdf0e10cSrcweir                 }
786cdf0e10cSrcweir 
787cdf0e10cSrcweir                 // now, nOldLeft<nXLeft<=nOldRight<nXRight always
788cdf0e10cSrcweir                 // holds. Note that we need the nXLeft<=nOldRight here, as
789cdf0e10cSrcweir                 // the intersection part might be only one pixel (original
790cdf0e10cSrcweir                 // nXLeft==nXRight)
791cdf0e10cSrcweir                 DBG_ASSERT( nOldLeft<nXLeft && nXLeft<=nOldRight && nOldRight<nXRight,
792cdf0e10cSrcweir                             "ImplRegionBand::XOr(): Case 4,5,6,7 expected coordinates to be ordered now!" );
793cdf0e10cSrcweir 
794cdf0e10cSrcweir                 pSep->mnXLeft = nOldLeft;
795cdf0e10cSrcweir                 pSep->mnXRight = nXLeft-1;
796cdf0e10cSrcweir 
797cdf0e10cSrcweir                 nXLeft = nOldRight+1;
798cdf0e10cSrcweir                 // nxRight is already setup correctly
799cdf0e10cSrcweir 
800cdf0e10cSrcweir                 if( bDone )
801cdf0e10cSrcweir                 {
802cdf0e10cSrcweir                     // add behind current bandSep
803cdf0e10cSrcweir                     pNewSep = new ImplRegionBandSep;
804cdf0e10cSrcweir 
805cdf0e10cSrcweir                     pNewSep->mnXLeft    = nXLeft;
806cdf0e10cSrcweir                     pNewSep->mnXRight   = nXRight;
807cdf0e10cSrcweir                     pNewSep->mpNextSep  = pSep->mpNextSep;
808e6f63103SArmin Le Grand                     pNewSep->mbRemoved  = false;
809cdf0e10cSrcweir 
810cdf0e10cSrcweir                     // connections from the new separation
811cdf0e10cSrcweir                     pSep->mpNextSep = pNewSep;
812cdf0e10cSrcweir 
813cdf0e10cSrcweir                     pPrevSep = NULL; // do not run accidentally into the "right" case when breaking the loop
814cdf0e10cSrcweir                     break;
815cdf0e10cSrcweir                 }
816cdf0e10cSrcweir             }
817cdf0e10cSrcweir         }
818cdf0e10cSrcweir 
819cdf0e10cSrcweir         pPrevSep = pSep;
820cdf0e10cSrcweir         pSep = pSep->mpNextSep;
821cdf0e10cSrcweir     }
822cdf0e10cSrcweir 
823cdf0e10cSrcweir     // new separation completely right of existing bandSeps ?
824cdf0e10cSrcweir     if( pPrevSep && nXLeft >= pPrevSep->mnXRight )
825cdf0e10cSrcweir     {
826cdf0e10cSrcweir         pNewSep             = new ImplRegionBandSep;
827cdf0e10cSrcweir         pNewSep->mnXLeft    = nXLeft;
828cdf0e10cSrcweir         pNewSep->mnXRight   = nXRight;
829cdf0e10cSrcweir         pNewSep->mpNextSep  = NULL;
830e6f63103SArmin Le Grand         pNewSep->mbRemoved  = false;
831cdf0e10cSrcweir 
832cdf0e10cSrcweir         // connections from the new separation
833cdf0e10cSrcweir         pPrevSep->mpNextSep = pNewSep;
834cdf0e10cSrcweir     }
835cdf0e10cSrcweir 
836cdf0e10cSrcweir     OptimizeBand();
837cdf0e10cSrcweir }
838cdf0e10cSrcweir 
839cdf0e10cSrcweir // -----------------------------------------------------------------------
840cdf0e10cSrcweir 
IsInside(long nX)841e6f63103SArmin Le Grand bool ImplRegionBand::IsInside( long nX )
842cdf0e10cSrcweir {
843cdf0e10cSrcweir     ImplRegionBandSep* pSep = mpFirstSep;
844cdf0e10cSrcweir     while ( pSep )
845cdf0e10cSrcweir     {
846cdf0e10cSrcweir         if ( (pSep->mnXLeft <= nX) && (pSep->mnXRight >= nX) )
847e6f63103SArmin Le Grand             return true;
848cdf0e10cSrcweir 
849cdf0e10cSrcweir         pSep = pSep->mpNextSep;
850cdf0e10cSrcweir     }
851cdf0e10cSrcweir 
852e6f63103SArmin Le Grand     return false;
853cdf0e10cSrcweir }
854cdf0e10cSrcweir 
855cdf0e10cSrcweir // -----------------------------------------------------------------------
856cdf0e10cSrcweir 
IsOver(long nLeft,long nRight)857e6f63103SArmin Le Grand bool ImplRegionBand::IsOver( long nLeft, long nRight )
858cdf0e10cSrcweir {
859cdf0e10cSrcweir     ImplRegionBandSep* pSep = mpFirstSep;
860cdf0e10cSrcweir     while ( pSep )
861cdf0e10cSrcweir     {
862cdf0e10cSrcweir         if ( (pSep->mnXLeft < nRight) && (pSep->mnXRight > nLeft) )
863e6f63103SArmin Le Grand             return true;
864cdf0e10cSrcweir 
865cdf0e10cSrcweir         pSep = pSep->mpNextSep;
866cdf0e10cSrcweir     }
867cdf0e10cSrcweir 
868e6f63103SArmin Le Grand     return false;
869cdf0e10cSrcweir }
870cdf0e10cSrcweir 
871cdf0e10cSrcweir // -----------------------------------------------------------------------
872cdf0e10cSrcweir 
IsInside(long nLeft,long nRight)873e6f63103SArmin Le Grand bool ImplRegionBand::IsInside( long nLeft, long nRight )
874cdf0e10cSrcweir {
875cdf0e10cSrcweir     ImplRegionBandSep* pSep = mpFirstSep;
876cdf0e10cSrcweir     while ( pSep )
877cdf0e10cSrcweir     {
878cdf0e10cSrcweir         if ( (pSep->mnXLeft >= nLeft) && (nRight <= pSep->mnXRight) )
879e6f63103SArmin Le Grand             return true;
880cdf0e10cSrcweir 
881cdf0e10cSrcweir         pSep = pSep->mpNextSep;
882cdf0e10cSrcweir     }
883cdf0e10cSrcweir 
884e6f63103SArmin Le Grand     return false;
885cdf0e10cSrcweir }
886cdf0e10cSrcweir 
887cdf0e10cSrcweir // -----------------------------------------------------------------------
888cdf0e10cSrcweir 
GetXLeftBoundary() const889cdf0e10cSrcweir long ImplRegionBand::GetXLeftBoundary() const
890cdf0e10cSrcweir {
891cdf0e10cSrcweir     DBG_ASSERT( mpFirstSep != NULL, "ImplRegionBand::XLeftBoundary -> no separation in band!" );
892cdf0e10cSrcweir 
893cdf0e10cSrcweir     return mpFirstSep->mnXLeft;
894cdf0e10cSrcweir }
895cdf0e10cSrcweir 
896cdf0e10cSrcweir // -----------------------------------------------------------------------
897cdf0e10cSrcweir 
GetXRightBoundary() const898cdf0e10cSrcweir long ImplRegionBand::GetXRightBoundary() const
899cdf0e10cSrcweir {
900cdf0e10cSrcweir     DBG_ASSERT( mpFirstSep != NULL, "ImplRegionBand::XRightBoundary -> no separation in band!" );
901cdf0e10cSrcweir 
902cdf0e10cSrcweir     // search last separation
903cdf0e10cSrcweir     ImplRegionBandSep* pSep = mpFirstSep;
904cdf0e10cSrcweir     while ( pSep->mpNextSep )
905cdf0e10cSrcweir         pSep = pSep->mpNextSep;
906cdf0e10cSrcweir     return pSep->mnXRight;
907cdf0e10cSrcweir }
908cdf0e10cSrcweir 
909cdf0e10cSrcweir // -----------------------------------------------------------------------
910cdf0e10cSrcweir 
operator ==(const ImplRegionBand & rRegionBand) const911e6f63103SArmin Le Grand bool ImplRegionBand::operator==( const ImplRegionBand& rRegionBand ) const
912cdf0e10cSrcweir {
913cdf0e10cSrcweir     ImplRegionBandSep*   pOwnRectBandSep = mpFirstSep;
914cdf0e10cSrcweir     ImplRegionBandSep*   pSecondRectBandSep = rRegionBand.mpFirstSep;
915cdf0e10cSrcweir     while ( pOwnRectBandSep && pSecondRectBandSep )
916cdf0e10cSrcweir     {
917cdf0e10cSrcweir         // get boundaries of current rectangle
918cdf0e10cSrcweir         long nOwnXLeft = pOwnRectBandSep->mnXLeft;
919cdf0e10cSrcweir         long nSecondXLeft = pSecondRectBandSep->mnXLeft;
920cdf0e10cSrcweir         if ( nOwnXLeft != nSecondXLeft )
921e6f63103SArmin Le Grand             return false;
922cdf0e10cSrcweir 
923cdf0e10cSrcweir         long nOwnXRight = pOwnRectBandSep->mnXRight;
924cdf0e10cSrcweir         long nSecondXRight = pSecondRectBandSep->mnXRight;
925cdf0e10cSrcweir         if ( nOwnXRight != nSecondXRight )
926e6f63103SArmin Le Grand             return false;
927cdf0e10cSrcweir 
928cdf0e10cSrcweir         // get next separation from current band
929cdf0e10cSrcweir         pOwnRectBandSep = pOwnRectBandSep->mpNextSep;
930cdf0e10cSrcweir 
931cdf0e10cSrcweir         // get next separation from current band
932cdf0e10cSrcweir         pSecondRectBandSep = pSecondRectBandSep->mpNextSep;
933cdf0e10cSrcweir     }
934cdf0e10cSrcweir 
93586e1cf34SPedro Giffuni     // different number of separations?
936cdf0e10cSrcweir     if ( pOwnRectBandSep || pSecondRectBandSep )
937e6f63103SArmin Le Grand         return false;
938cdf0e10cSrcweir 
939e6f63103SArmin Le Grand     return true;
940cdf0e10cSrcweir }
941cdf0e10cSrcweir 
942cdf0e10cSrcweir // -----------------------------------------------------------------------
943cdf0e10cSrcweir 
SplitBand(const sal_Int32 nY)944cdf0e10cSrcweir ImplRegionBand* ImplRegionBand::SplitBand (const sal_Int32 nY)
945cdf0e10cSrcweir {
946cdf0e10cSrcweir     OSL_ASSERT(nY>mnYTop);
947cdf0e10cSrcweir     OSL_ASSERT(nY<=mnYBottom);
948cdf0e10cSrcweir 
949cdf0e10cSrcweir     // Create a copy of the given band (we tell the constructor to copy the points together
950cdf0e10cSrcweir     // with the seps.)
951cdf0e10cSrcweir     ImplRegionBand* pLowerBand = new ImplRegionBand(*this, false);
952cdf0e10cSrcweir 
953cdf0e10cSrcweir     // Adapt vertical coordinates.
954cdf0e10cSrcweir     mnYBottom = nY-1;
955cdf0e10cSrcweir     pLowerBand->mnYTop = nY;
956cdf0e10cSrcweir 
957cdf0e10cSrcweir     // Insert new band into list of bands.
958cdf0e10cSrcweir     pLowerBand->mpNextBand = mpNextBand;
959cdf0e10cSrcweir     mpNextBand = pLowerBand;
960cdf0e10cSrcweir     pLowerBand->mpPrevBand = this;
961cdf0e10cSrcweir     if (pLowerBand->mpNextBand != NULL)
962cdf0e10cSrcweir         pLowerBand->mpNextBand->mpPrevBand = pLowerBand;
963cdf0e10cSrcweir 
964cdf0e10cSrcweir     return pLowerBand;
965cdf0e10cSrcweir }
966