xref: /aoo41x/main/vcl/source/gdi/regband.cxx (revision e6f63103)
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
109f62ea84SAndrew Rist  *
119f62ea84SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
129f62ea84SAndrew Rist  *
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.
199f62ea84SAndrew Rist  *
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;
62*e6f63103SArmin 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 
190cdf0e10cSrcweir 		// remove allready 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)211*e6f63103SArmin Le Grand bool ImplRegionBand::InsertPoint( long nX, long nLineId,
212*e6f63103SArmin 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;
222*e6f63103SArmin Le Grand 		return true;
223cdf0e10cSrcweir 	}
224cdf0e10cSrcweir 
225cdf0e10cSrcweir 	// look if line allready 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;
241*e6f63103SArmin Le Grand 						pRegionBandPoint->mbEndPoint = true;
242*e6f63103SArmin 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
266*e6f63103SArmin 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 	{
281cdf0e10cSrcweir 		// new point completly 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 
297*e6f63103SArmin 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 
316*e6f63103SArmin 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 //
348cdf0e10cSrcweir // combine overlaping sparations
349cdf0e10cSrcweir 
OptimizeBand()350*e6f63103SArmin 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 
369cdf0e10cSrcweir 		// overlaping 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 
388*e6f63103SArmin 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;
403*e6f63103SArmin 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 
418cdf0e10cSrcweir 		// new separation completly left? -> new separation!
419cdf0e10cSrcweir 		if ( nXRight < pSep->mnXLeft )
420cdf0e10cSrcweir 		{
421cdf0e10cSrcweir 			pNewSep 			= new ImplRegionBandSep;
422cdf0e10cSrcweir 			pNewSep->mnXLeft	= nXLeft;
423cdf0e10cSrcweir 			pNewSep->mnXRight	= nXRight;
424*e6f63103SArmin 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 
434cdf0e10cSrcweir 		// new separation overlaping from left? -> extend boundary
435cdf0e10cSrcweir 		if ( (nXRight >= pSep->mnXLeft) && (nXLeft <= pSep->mnXLeft) )
436cdf0e10cSrcweir 			pSep->mnXLeft = nXLeft;
437cdf0e10cSrcweir 
438cdf0e10cSrcweir 		// new separation overlaping 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;
451*e6f63103SArmin 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
472*e6f63103SArmin 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 	{
482cdf0e10cSrcweir 		// new separation completly outside? -> remove separation
483cdf0e10cSrcweir 		if ( (nXRight < pSep->mnXLeft) || (nXLeft > pSep->mnXRight) )
484cdf0e10cSrcweir 			// will be removed from the optimizer
485*e6f63103SArmin Le Grand 			pSep->mbRemoved = true;
486cdf0e10cSrcweir 
487cdf0e10cSrcweir 		// new separation overlaping from left? -> reduce right boundary
488cdf0e10cSrcweir 		if ( (nXLeft <= pSep->mnXLeft) &&
489cdf0e10cSrcweir 			 (nXRight <= pSep->mnXRight) &&
490cdf0e10cSrcweir 			 (nXRight >= pSep->mnXLeft) )
491cdf0e10cSrcweir 			pSep->mnXRight = nXRight;
492cdf0e10cSrcweir 
493cdf0e10cSrcweir 		// new separation overlaping 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
519*e6f63103SArmin 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 	{
531*e6f63103SArmin 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
537*e6f63103SArmin Le Grand 			pSep->mbRemoved = true;
538*e6f63103SArmin Le Grand 			bSepProcessed = true;
539cdf0e10cSrcweir 		}
540cdf0e10cSrcweir 
541cdf0e10cSrcweir 		// new separation overlaping from left? -> reduce boundary
542cdf0e10cSrcweir 		if ( !bSepProcessed )
543cdf0e10cSrcweir 		{
544cdf0e10cSrcweir 			if ( (nXRight >= pSep->mnXLeft) && (nXLeft <= pSep->mnXLeft) )
545cdf0e10cSrcweir 			{
546cdf0e10cSrcweir 				pSep->mnXLeft = nXRight+1;
547*e6f63103SArmin Le Grand 				bSepProcessed = true;
548cdf0e10cSrcweir 			}
549cdf0e10cSrcweir 		}
550cdf0e10cSrcweir 
551cdf0e10cSrcweir 		// new separation overlaping from right? -> reduce boundary
552cdf0e10cSrcweir 		if ( !bSepProcessed )
553cdf0e10cSrcweir 		{
554cdf0e10cSrcweir 			if ( (nXLeft <= pSep->mnXRight) && (nXRight > pSep->mnXRight) )
555cdf0e10cSrcweir 			{
556cdf0e10cSrcweir 				pSep->mnXRight = nXLeft-1;
557*e6f63103SArmin 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;
570*e6f63103SArmin 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
601cdf0e10cSrcweir     // (details below). The old implementation explicitely 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;
650*e6f63103SArmin 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;
679*e6f63103SArmin 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
695*e6f63103SArmin 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
728*e6f63103SArmin 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;
808*e6f63103SArmin 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;
830*e6f63103SArmin 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)841*e6f63103SArmin Le Grand bool ImplRegionBand::IsInside( long nX )
842cdf0e10cSrcweir {
843cdf0e10cSrcweir 	ImplRegionBandSep* pSep = mpFirstSep;
844cdf0e10cSrcweir 	while ( pSep )
845cdf0e10cSrcweir 	{
846cdf0e10cSrcweir 		if ( (pSep->mnXLeft <= nX) && (pSep->mnXRight >= nX) )
847*e6f63103SArmin Le Grand 			return true;
848cdf0e10cSrcweir 
849cdf0e10cSrcweir 		pSep = pSep->mpNextSep;
850cdf0e10cSrcweir 	}
851cdf0e10cSrcweir 
852*e6f63103SArmin Le Grand 	return false;
853cdf0e10cSrcweir }
854cdf0e10cSrcweir 
855cdf0e10cSrcweir // -----------------------------------------------------------------------
856cdf0e10cSrcweir 
IsOver(long nLeft,long nRight)857*e6f63103SArmin 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) )
863*e6f63103SArmin Le Grand 			return true;
864cdf0e10cSrcweir 
865cdf0e10cSrcweir 		pSep = pSep->mpNextSep;
866cdf0e10cSrcweir 	}
867cdf0e10cSrcweir 
868*e6f63103SArmin Le Grand 	return false;
869cdf0e10cSrcweir }
870cdf0e10cSrcweir 
871cdf0e10cSrcweir // -----------------------------------------------------------------------
872cdf0e10cSrcweir 
IsInside(long nLeft,long nRight)873*e6f63103SArmin 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) )
879*e6f63103SArmin Le Grand 			return true;
880cdf0e10cSrcweir 
881cdf0e10cSrcweir 		pSep = pSep->mpNextSep;
882cdf0e10cSrcweir 	}
883cdf0e10cSrcweir 
884*e6f63103SArmin 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) const911*e6f63103SArmin 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 )
921*e6f63103SArmin Le Grand 			return false;
922cdf0e10cSrcweir 
923cdf0e10cSrcweir 		long nOwnXRight = pOwnRectBandSep->mnXRight;
924cdf0e10cSrcweir 		long nSecondXRight = pSecondRectBandSep->mnXRight;
925cdf0e10cSrcweir 		if ( nOwnXRight != nSecondXRight )
926*e6f63103SArmin 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 
935cdf0e10cSrcweir 	// differnt number of separations?
936cdf0e10cSrcweir 	if ( pOwnRectBandSep || pSecondRectBandSep )
937*e6f63103SArmin Le Grand 		return false;
938cdf0e10cSrcweir 
939*e6f63103SArmin 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