xref: /aoo41x/main/vcl/source/gdi/regionband.cxx (revision daf45454)
1e6f63103SArmin Le Grand /**************************************************************
2e6f63103SArmin Le Grand  *
3e6f63103SArmin Le Grand  * Licensed to the Apache Software Foundation (ASF) under one
4e6f63103SArmin Le Grand  * or more contributor license agreements.  See the NOTICE file
5e6f63103SArmin Le Grand  * distributed with this work for additional information
6e6f63103SArmin Le Grand  * regarding copyright ownership.  The ASF licenses this file
7e6f63103SArmin Le Grand  * to you under the Apache License, Version 2.0 (the
8e6f63103SArmin Le Grand  * "License"); you may not use this file except in compliance
9e6f63103SArmin Le Grand  * with the License.  You may obtain a copy of the License at
10e6f63103SArmin Le Grand  *
11e6f63103SArmin Le Grand  *   http://www.apache.org/licenses/LICENSE-2.0
12e6f63103SArmin Le Grand  *
13e6f63103SArmin Le Grand  * Unless required by applicable law or agreed to in writing,
14e6f63103SArmin Le Grand  * software distributed under the License is distributed on an
15e6f63103SArmin Le Grand  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16e6f63103SArmin Le Grand  * KIND, either express or implied.  See the License for the
17e6f63103SArmin Le Grand  * specific language governing permissions and limitations
18e6f63103SArmin Le Grand  * under the License.
19e6f63103SArmin Le Grand  *
20e6f63103SArmin Le Grand  *************************************************************/
21e6f63103SArmin Le Grand 
22e6f63103SArmin Le Grand // MARKER(update_precomp.py): autogen include statement, do not remove
23e6f63103SArmin Le Grand #include "precompiled_vcl.hxx"
24e6f63103SArmin Le Grand 
25e6f63103SArmin Le Grand #include <tools/stream.hxx>
26e6f63103SArmin Le Grand #include <tools/debug.hxx>
27e6f63103SArmin Le Grand #include <regionband.hxx>
28e6f63103SArmin Le Grand 
29e6f63103SArmin Le Grand //////////////////////////////////////////////////////////////////////////////
30e6f63103SArmin Le Grand 
31e6f63103SArmin Le Grand DBG_NAME( RegionBand )
DBG_NAMEEX(Polygon)32e6f63103SArmin Le Grand DBG_NAMEEX( Polygon )
33e6f63103SArmin Le Grand DBG_NAMEEX( PolyPolygon )
34e6f63103SArmin Le Grand 
35e6f63103SArmin Le Grand //////////////////////////////////////////////////////////////////////////////
36e6f63103SArmin Le Grand 
37e6f63103SArmin Le Grand RegionBand::RegionBand()
38e6f63103SArmin Le Grand :   mpFirstBand(0),
39e6f63103SArmin Le Grand     mpLastCheckedBand(0)
40e6f63103SArmin Le Grand {
41e6f63103SArmin Le Grand     DBG_CTOR(RegionBand, ImplDbgTestRegionBand);
42e6f63103SArmin Le Grand }
43e6f63103SArmin Le Grand 
RegionBand(const RegionBand & rRef)44e6f63103SArmin Le Grand RegionBand::RegionBand(const RegionBand& rRef)
45e6f63103SArmin Le Grand :   mpFirstBand(0),
46e6f63103SArmin Le Grand     mpLastCheckedBand(0)
47e6f63103SArmin Le Grand {
48e6f63103SArmin Le Grand     *this = rRef;
49e6f63103SArmin Le Grand     DBG_CTOR(RegionBand, ImplDbgTestRegionBand);
50e6f63103SArmin Le Grand }
51e6f63103SArmin Le Grand 
operator =(const RegionBand & rRef)52e6f63103SArmin Le Grand RegionBand& RegionBand::operator=(const RegionBand& rRef)
53e6f63103SArmin Le Grand {
54e6f63103SArmin Le Grand 	ImplRegionBand* pPrevBand = 0;
55e6f63103SArmin Le Grand 	ImplRegionBand* pBand = rRef.mpFirstBand;
56e6f63103SArmin Le Grand 
57e6f63103SArmin Le Grand     while(pBand)
58e6f63103SArmin Le Grand 	{
59e6f63103SArmin Le Grand 		ImplRegionBand* pNewBand = new ImplRegionBand(*pBand);
60e6f63103SArmin Le Grand 
61e6f63103SArmin Le Grand 		// first element? -> set as first into the list
62e6f63103SArmin Le Grand 		if(pBand == rRef.mpFirstBand)
63e6f63103SArmin Le Grand         {
64e6f63103SArmin Le Grand 			mpFirstBand = pNewBand;
65e6f63103SArmin Le Grand         }
66e6f63103SArmin Le Grand 		else
67e6f63103SArmin Le Grand         {
68e6f63103SArmin Le Grand 			pPrevBand->mpNextBand = pNewBand;
69e6f63103SArmin Le Grand         }
70e6f63103SArmin Le Grand 
71e6f63103SArmin Le Grand 		pPrevBand = pNewBand;
72e6f63103SArmin Le Grand 		pBand = pBand->mpNextBand;
73e6f63103SArmin Le Grand 	}
74e6f63103SArmin Le Grand 
75e6f63103SArmin Le Grand     DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
76e6f63103SArmin Le Grand     DBG_CHKOBJ(&rRef, RegionBand, ImplDbgTestRegionBand);
77e6f63103SArmin Le Grand 
78e6f63103SArmin Le Grand     return *this;
79e6f63103SArmin Le Grand }
80e6f63103SArmin Le Grand 
RegionBand(const Rectangle & rRect)81e6f63103SArmin Le Grand RegionBand::RegionBand(const Rectangle& rRect)
82e6f63103SArmin Le Grand :   mpFirstBand(0),
83e6f63103SArmin Le Grand     mpLastCheckedBand(0)
84e6f63103SArmin Le Grand {
85e6f63103SArmin Le Grand     const long nTop(std::min(rRect.Top(), rRect.Bottom()));
86e6f63103SArmin Le Grand     const long nBottom(std::max(rRect.Top(), rRect.Bottom()));
87e6f63103SArmin Le Grand     const long nLeft(std::min(rRect.Left(), rRect.Right()));
88e6f63103SArmin Le Grand     const long nRight(std::max(rRect.Left(), rRect.Right()));
89e6f63103SArmin Le Grand 
90e6f63103SArmin Le Grand     // add band with boundaries of the rectangle
91e6f63103SArmin Le Grand     mpFirstBand = new ImplRegionBand(nTop, nBottom);
92e6f63103SArmin Le Grand 
93e6f63103SArmin Le Grand     // Set left and right boundaries of the band
94e6f63103SArmin Le Grand     mpFirstBand->Union(nLeft, nRight);
95e6f63103SArmin Le Grand 
96e6f63103SArmin Le Grand     DBG_CTOR(RegionBand, ImplDbgTestRegionBand);
97e6f63103SArmin Le Grand }
98e6f63103SArmin Le Grand 
implReset()99e6f63103SArmin Le Grand void RegionBand::implReset()
100e6f63103SArmin Le Grand {
101e6f63103SArmin Le Grand 	ImplRegionBand* pBand = mpFirstBand;
102e6f63103SArmin Le Grand 
103e6f63103SArmin Le Grand     while(pBand)
104e6f63103SArmin Le Grand 	{
105e6f63103SArmin Le Grand 		ImplRegionBand* pTempBand = pBand->mpNextBand;
106e6f63103SArmin Le Grand 		delete pBand;
107e6f63103SArmin Le Grand 		pBand = pTempBand;
108e6f63103SArmin Le Grand 	}
109e6f63103SArmin Le Grand 
110e6f63103SArmin Le Grand     mpLastCheckedBand = 0;
111e6f63103SArmin Le Grand 
112e6f63103SArmin Le Grand     DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
113e6f63103SArmin Le Grand }
114e6f63103SArmin Le Grand 
~RegionBand()115e6f63103SArmin Le Grand RegionBand::~RegionBand()
116e6f63103SArmin Le Grand {
117e6f63103SArmin Le Grand     implReset();
118e6f63103SArmin Le Grand     DBG_DTOR(RegionBand, ImplDbgTestRegionBand);
119e6f63103SArmin Le Grand }
120e6f63103SArmin Le Grand 
operator ==(const RegionBand & rRegionBand) const121e6f63103SArmin Le Grand bool RegionBand::operator==( const RegionBand& rRegionBand ) const
122e6f63103SArmin Le Grand {
123e6f63103SArmin Le Grand     DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
124e6f63103SArmin Le Grand     DBG_CHKOBJ(&rRegionBand, RegionBand, ImplDbgTestRegionBand);
125e6f63103SArmin Le Grand 
126e6f63103SArmin Le Grand 	// initialise pointers
127e6f63103SArmin Le Grand 	ImplRegionBand* 	 pOwnRectBand = mpFirstBand;
128e6f63103SArmin Le Grand 	ImplRegionBandSep*	 pOwnRectBandSep = pOwnRectBand->mpFirstSep;
129e6f63103SArmin Le Grand 	ImplRegionBand* 	 pSecondRectBand = rRegionBand.mpFirstBand;
130e6f63103SArmin Le Grand 	ImplRegionBandSep*	 pSecondRectBandSep = pSecondRectBand->mpFirstSep;
131e6f63103SArmin Le Grand 
132e6f63103SArmin Le Grand     while ( pOwnRectBandSep && pSecondRectBandSep )
133e6f63103SArmin Le Grand 	{
134e6f63103SArmin Le Grand 		// get boundaries of current rectangle
135e6f63103SArmin Le Grand 		long nOwnXLeft = pOwnRectBandSep->mnXLeft;
136e6f63103SArmin Le Grand 		long nSecondXLeft = pSecondRectBandSep->mnXLeft;
137e6f63103SArmin Le Grand 
138e6f63103SArmin Le Grand         if ( nOwnXLeft != nSecondXLeft )
139e6f63103SArmin Le Grand         {
140e6f63103SArmin Le Grand 			return false;
141e6f63103SArmin Le Grand         }
142e6f63103SArmin Le Grand 
143e6f63103SArmin Le Grand 		long nOwnYTop = pOwnRectBand->mnYTop;
144e6f63103SArmin Le Grand 		long nSecondYTop = pSecondRectBand->mnYTop;
145e6f63103SArmin Le Grand 
146e6f63103SArmin Le Grand         if ( nOwnYTop != nSecondYTop )
147e6f63103SArmin Le Grand         {
148e6f63103SArmin Le Grand 			return false;
149e6f63103SArmin Le Grand         }
150e6f63103SArmin Le Grand 
151e6f63103SArmin Le Grand 		long nOwnXRight = pOwnRectBandSep->mnXRight;
152e6f63103SArmin Le Grand 		long nSecondXRight = pSecondRectBandSep->mnXRight;
153e6f63103SArmin Le Grand 
154e6f63103SArmin Le Grand         if ( nOwnXRight != nSecondXRight )
155e6f63103SArmin Le Grand         {
156e6f63103SArmin Le Grand 			return false;
157e6f63103SArmin Le Grand         }
158e6f63103SArmin Le Grand 
159e6f63103SArmin Le Grand 		long nOwnYBottom = pOwnRectBand->mnYBottom;
160e6f63103SArmin Le Grand 		long nSecondYBottom = pSecondRectBand->mnYBottom;
161e6f63103SArmin Le Grand 
162e6f63103SArmin Le Grand         if ( nOwnYBottom != nSecondYBottom )
163e6f63103SArmin Le Grand         {
164e6f63103SArmin Le Grand 			return false;
165e6f63103SArmin Le Grand         }
166e6f63103SArmin Le Grand 
167e6f63103SArmin Le Grand 		// get next separation from current band
168e6f63103SArmin Le Grand 		pOwnRectBandSep = pOwnRectBandSep->mpNextSep;
169e6f63103SArmin Le Grand 
170e6f63103SArmin Le Grand 		// no separation found? -> go to next band!
171e6f63103SArmin Le Grand 		if ( !pOwnRectBandSep )
172e6f63103SArmin Le Grand 		{
173e6f63103SArmin Le Grand 			// get next band
174e6f63103SArmin Le Grand 			pOwnRectBand = pOwnRectBand->mpNextBand;
175e6f63103SArmin Le Grand 
176e6f63103SArmin Le Grand 			// get first separation in current band
177e6f63103SArmin Le Grand 			if( pOwnRectBand )
178e6f63103SArmin Le Grand             {
179e6f63103SArmin Le Grand 				pOwnRectBandSep = pOwnRectBand->mpFirstSep;
180e6f63103SArmin Le Grand             }
181e6f63103SArmin Le Grand 		}
182e6f63103SArmin Le Grand 
183e6f63103SArmin Le Grand 		// get next separation from current band
184e6f63103SArmin Le Grand 		pSecondRectBandSep = pSecondRectBandSep->mpNextSep;
185e6f63103SArmin Le Grand 
186e6f63103SArmin Le Grand 		// no separation found? -> go to next band!
187e6f63103SArmin Le Grand 		if ( !pSecondRectBandSep )
188e6f63103SArmin Le Grand 		{
189e6f63103SArmin Le Grand 			// get next band
190e6f63103SArmin Le Grand 			pSecondRectBand = pSecondRectBand->mpNextBand;
191e6f63103SArmin Le Grand 
192e6f63103SArmin Le Grand 			// get first separation in current band
193e6f63103SArmin Le Grand 			if( pSecondRectBand )
194e6f63103SArmin Le Grand             {
195e6f63103SArmin Le Grand 				pSecondRectBandSep = pSecondRectBand->mpFirstSep;
196e6f63103SArmin Le Grand             }
197e6f63103SArmin Le Grand 		}
198e6f63103SArmin Le Grand 
199e6f63103SArmin Le Grand 		if ( pOwnRectBandSep && !pSecondRectBandSep )
200e6f63103SArmin Le Grand         {
201e6f63103SArmin Le Grand 			return false;
202e6f63103SArmin Le Grand         }
203e6f63103SArmin Le Grand 
204e6f63103SArmin Le Grand 		if ( !pOwnRectBandSep && pSecondRectBandSep )
205e6f63103SArmin Le Grand         {
206e6f63103SArmin Le Grand 			return false;
207e6f63103SArmin Le Grand         }
208e6f63103SArmin Le Grand 	}
209e6f63103SArmin Le Grand 
210e6f63103SArmin Le Grand 	return true;
211e6f63103SArmin Le Grand }
212e6f63103SArmin Le Grand 
213e6f63103SArmin Le Grand enum StreamEntryType { STREAMENTRY_BANDHEADER, STREAMENTRY_SEPARATION, STREAMENTRY_END };
214e6f63103SArmin Le Grand 
load(SvStream & rIStrm)215e6f63103SArmin Le Grand void RegionBand::load(SvStream& rIStrm)
216e6f63103SArmin Le Grand {
217e6f63103SArmin Le Grand     // clear this nstance's data
218e6f63103SArmin Le Grand     implReset();
219e6f63103SArmin Le Grand 
220e6f63103SArmin Le Grand     // get all bands
221e6f63103SArmin Le Grand     ImplRegionBand* pCurrBand = 0;
222e6f63103SArmin Le Grand 
223e6f63103SArmin Le Grand     // get header from first element
224e6f63103SArmin Le Grand     sal_uInt16 nTmp16(0);
225e6f63103SArmin Le Grand     rIStrm >> nTmp16;
226e6f63103SArmin Le Grand 
227e6f63103SArmin Le Grand     while(STREAMENTRY_END != (StreamEntryType)nTmp16)
228e6f63103SArmin Le Grand     {
229e6f63103SArmin Le Grand         // insert new band or new separation?
230e6f63103SArmin Le Grand         if(STREAMENTRY_BANDHEADER == (StreamEntryType)nTmp16)
231e6f63103SArmin Le Grand         {
232e6f63103SArmin Le Grand             long nYTop;
233e6f63103SArmin Le Grand             long nYBottom;
234e6f63103SArmin Le Grand 
235e6f63103SArmin Le Grand             rIStrm >> nYTop;
236e6f63103SArmin Le Grand             rIStrm >> nYBottom;
237e6f63103SArmin Le Grand 
238e6f63103SArmin Le Grand             // create band
239e6f63103SArmin Le Grand             ImplRegionBand* pNewBand = new ImplRegionBand( nYTop, nYBottom );
240e6f63103SArmin Le Grand 
241e6f63103SArmin Le Grand             // first element? -> set as first into the list
242e6f63103SArmin Le Grand             if ( !pCurrBand )
243e6f63103SArmin Le Grand             {
244e6f63103SArmin Le Grand                 mpFirstBand = pNewBand;
245e6f63103SArmin Le Grand             }
246e6f63103SArmin Le Grand             else
247e6f63103SArmin Le Grand             {
248e6f63103SArmin Le Grand                 pCurrBand->mpNextBand = pNewBand;
249e6f63103SArmin Le Grand             }
250e6f63103SArmin Le Grand 
251e6f63103SArmin Le Grand             // save pointer for next creation
252e6f63103SArmin Le Grand             pCurrBand = pNewBand;
253e6f63103SArmin Le Grand         }
254e6f63103SArmin Le Grand         else
255e6f63103SArmin Le Grand         {
256e6f63103SArmin Le Grand             long nXLeft;
257e6f63103SArmin Le Grand             long nXRight;
258e6f63103SArmin Le Grand 
259e6f63103SArmin Le Grand             rIStrm >> nXLeft;
260e6f63103SArmin Le Grand             rIStrm >> nXRight;
261e6f63103SArmin Le Grand 
262e6f63103SArmin Le Grand             // add separation
263e6f63103SArmin Le Grand             if ( pCurrBand )
264e6f63103SArmin Le Grand             {
265e6f63103SArmin Le Grand                 pCurrBand->Union( nXLeft, nXRight );
266e6f63103SArmin Le Grand             }
267e6f63103SArmin Le Grand         }
268e6f63103SArmin Le Grand 
269e6f63103SArmin Le Grand         if( rIStrm.IsEof() )
270e6f63103SArmin Le Grand         {
271e6f63103SArmin Le Grand             DBG_ERROR( "premature end of region stream" );
272e6f63103SArmin Le Grand             implReset();
273e6f63103SArmin Le Grand             return;
274e6f63103SArmin Le Grand         }
275e6f63103SArmin Le Grand 
276e6f63103SArmin Le Grand         // get next header
277e6f63103SArmin Le Grand         rIStrm >> nTmp16;
278e6f63103SArmin Le Grand     }
279e6f63103SArmin Le Grand 
280e6f63103SArmin Le Grand     DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
281e6f63103SArmin Le Grand }
282e6f63103SArmin Le Grand 
save(SvStream & rOStrm) const283e6f63103SArmin Le Grand void RegionBand::save(SvStream& rOStrm) const
284e6f63103SArmin Le Grand {
285e6f63103SArmin Le Grand     DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
286e6f63103SArmin Le Grand     ImplRegionBand* pBand = mpFirstBand;
287e6f63103SArmin Le Grand 
288e6f63103SArmin Le Grand     while(pBand)
289e6f63103SArmin Le Grand     {
290e6f63103SArmin Le Grand         // put boundaries
291e6f63103SArmin Le Grand         rOStrm << (sal_uInt16)STREAMENTRY_BANDHEADER;
292e6f63103SArmin Le Grand         rOStrm << pBand->mnYTop;
293e6f63103SArmin Le Grand         rOStrm << pBand->mnYBottom;
294e6f63103SArmin Le Grand 
295e6f63103SArmin Le Grand         // put separations of current band
296e6f63103SArmin Le Grand         ImplRegionBandSep* pSep = pBand->mpFirstSep;
297e6f63103SArmin Le Grand 
298e6f63103SArmin Le Grand         while(pSep)
299e6f63103SArmin Le Grand         {
300e6f63103SArmin Le Grand             // put separation
301e6f63103SArmin Le Grand             rOStrm << (sal_uInt16)STREAMENTRY_SEPARATION;
302e6f63103SArmin Le Grand             rOStrm << pSep->mnXLeft;
303e6f63103SArmin Le Grand             rOStrm << pSep->mnXRight;
304e6f63103SArmin Le Grand 
305e6f63103SArmin Le Grand             // next separation from current band
306e6f63103SArmin Le Grand             pSep = pSep->mpNextSep;
307e6f63103SArmin Le Grand         }
308e6f63103SArmin Le Grand 
309e6f63103SArmin Le Grand         pBand = pBand->mpNextBand;
310e6f63103SArmin Le Grand     }
311e6f63103SArmin Le Grand 
312e6f63103SArmin Le Grand     // put endmarker
313e6f63103SArmin Le Grand     rOStrm << (sal_uInt16)STREAMENTRY_END;
314e6f63103SArmin Le Grand }
315e6f63103SArmin Le Grand 
isSingleRectangle() const316e6f63103SArmin Le Grand bool RegionBand::isSingleRectangle() const
317e6f63103SArmin Le Grand {
318e6f63103SArmin Le Grand     // just one band?
319e6f63103SArmin Le Grand     if(mpFirstBand && !mpFirstBand->mpNextBand)
320e6f63103SArmin Le Grand     {
321e6f63103SArmin Le Grand         // just one sep?
322e6f63103SArmin Le Grand         if(mpFirstBand->mpFirstSep && !mpFirstBand->mpFirstSep->mpNextSep)
323e6f63103SArmin Le Grand         {
324e6f63103SArmin Le Grand             return true;
325e6f63103SArmin Le Grand         }
326e6f63103SArmin Le Grand     }
327e6f63103SArmin Le Grand 
328e6f63103SArmin Le Grand     return false;
329e6f63103SArmin Le Grand }
330e6f63103SArmin Le Grand 
InsertBand(ImplRegionBand * pPreviousBand,ImplRegionBand * pBandToInsert)331e6f63103SArmin Le Grand void RegionBand::InsertBand(ImplRegionBand* pPreviousBand, ImplRegionBand* pBandToInsert)
332e6f63103SArmin Le Grand {
333e6f63103SArmin Le Grand     OSL_ASSERT(pBandToInsert!=NULL);
334e6f63103SArmin Le Grand 
335e6f63103SArmin Le Grand     if(!pPreviousBand)
336e6f63103SArmin Le Grand     {
337e6f63103SArmin Le Grand         // Insert band before all others.
338e6f63103SArmin Le Grand         if(mpFirstBand)
339e6f63103SArmin Le Grand         {
340e6f63103SArmin Le Grand             mpFirstBand->mpPrevBand = pBandToInsert;
341e6f63103SArmin Le Grand         }
342e6f63103SArmin Le Grand 
343e6f63103SArmin Le Grand         pBandToInsert->mpNextBand = mpFirstBand;
344e6f63103SArmin Le Grand         mpFirstBand = pBandToInsert;
345e6f63103SArmin Le Grand     }
346e6f63103SArmin Le Grand     else
347e6f63103SArmin Le Grand     {
348e6f63103SArmin Le Grand         // Insert band directly after pPreviousBand.
349e6f63103SArmin Le Grand         pBandToInsert->mpNextBand = pPreviousBand->mpNextBand;
350e6f63103SArmin Le Grand         pPreviousBand->mpNextBand = pBandToInsert;
351e6f63103SArmin Le Grand         pBandToInsert->mpPrevBand = pPreviousBand;
352e6f63103SArmin Le Grand     }
353e6f63103SArmin Le Grand 
354e6f63103SArmin Le Grand     DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
355e6f63103SArmin Le Grand }
356e6f63103SArmin Le Grand 
processPoints()357e6f63103SArmin Le Grand void RegionBand::processPoints()
358e6f63103SArmin Le Grand {
359e6f63103SArmin Le Grand 	ImplRegionBand* pRegionBand = mpFirstBand;
360e6f63103SArmin Le Grand 
361e6f63103SArmin Le Grand     while(pRegionBand)
362e6f63103SArmin Le Grand 	{
363e6f63103SArmin Le Grand 		// generate separations from the lines and process union
364e6f63103SArmin Le Grand 		pRegionBand->ProcessPoints();
365e6f63103SArmin Le Grand 		pRegionBand = pRegionBand->mpNextBand;
366e6f63103SArmin Le Grand 	}
367e6f63103SArmin Le Grand 
368e6f63103SArmin Le Grand     DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
369e6f63103SArmin Le Grand }
370e6f63103SArmin Le Grand 
371e6f63103SArmin Le Grand /** This function is similar to the RegionBand::InsertBands() method.
372e6f63103SArmin Le Grand     It creates a minimal set of missing bands so that the entire vertical
373e6f63103SArmin Le Grand     interval from nTop to nBottom is covered by bands.
374e6f63103SArmin Le Grand */
ImplAddMissingBands(const long nTop,const long nBottom)375e6f63103SArmin Le Grand void RegionBand::ImplAddMissingBands(const long nTop, const long nBottom)
376e6f63103SArmin Le Grand {
377e6f63103SArmin Le Grand     // Iterate over already existing bands and add missing bands atop the
378e6f63103SArmin Le Grand     // first and between two bands.
379e6f63103SArmin Le Grand     ImplRegionBand* pPreviousBand = NULL;
380e6f63103SArmin Le Grand     ImplRegionBand* pBand = ImplGetFirstRegionBand();
381e6f63103SArmin Le Grand     long nCurrentTop (nTop);
382e6f63103SArmin Le Grand 
383e6f63103SArmin Le Grand     while (pBand != NULL && nCurrentTop<nBottom)
384e6f63103SArmin Le Grand     {
385e6f63103SArmin Le Grand         if (nCurrentTop < pBand->mnYTop)
386e6f63103SArmin Le Grand         {
387e6f63103SArmin Le Grand             // Create new band above the current band.
388e6f63103SArmin Le Grand             ImplRegionBand* pAboveBand = new ImplRegionBand(
389e6f63103SArmin Le Grand                 nCurrentTop,
390e6f63103SArmin Le Grand                 ::std::min(nBottom,pBand->mnYTop-1));
391e6f63103SArmin Le Grand             InsertBand(pPreviousBand, pAboveBand);
392e6f63103SArmin Le Grand         }
393e6f63103SArmin Le Grand 
394e6f63103SArmin Le Grand         // Adapt the top of the interval to prevent overlapping bands.
395e6f63103SArmin Le Grand         nCurrentTop = ::std::max(nTop, pBand->mnYBottom+1);
396e6f63103SArmin Le Grand 
397e6f63103SArmin Le Grand         // Advance to next band.
398e6f63103SArmin Le Grand         pPreviousBand = pBand;
399e6f63103SArmin Le Grand         pBand = pBand->mpNextBand;
400e6f63103SArmin Le Grand     }
401e6f63103SArmin Le Grand 
402e6f63103SArmin Le Grand     // We still have to cover two cases:
403e6f63103SArmin Le Grand     // 1. The region does not yet contain any bands.
404e6f63103SArmin Le Grand     // 2. The intervall nTop->nBottom extends past the bottom most band.
405e6f63103SArmin Le Grand     if (nCurrentTop <= nBottom
406e6f63103SArmin Le Grand         && (pBand==NULL || nBottom>pBand->mnYBottom))
407e6f63103SArmin Le Grand     {
408e6f63103SArmin Le Grand         // When there is no previous band then the new one will be the
409e6f63103SArmin Le Grand         // first.  Otherwise the new band is inserted behind the last band.
410e6f63103SArmin Le Grand         InsertBand(
411e6f63103SArmin Le Grand             pPreviousBand,
412e6f63103SArmin Le Grand             new ImplRegionBand(
413e6f63103SArmin Le Grand                 nCurrentTop,
414e6f63103SArmin Le Grand                 nBottom));
415e6f63103SArmin Le Grand     }
416e6f63103SArmin Le Grand 
417e6f63103SArmin Le Grand     DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
418e6f63103SArmin Le Grand }
419e6f63103SArmin Le Grand 
CreateBandRange(long nYTop,long nYBottom)420e6f63103SArmin Le Grand void RegionBand::CreateBandRange(long nYTop, long nYBottom)
421e6f63103SArmin Le Grand {
422e6f63103SArmin Le Grand 	// add top band
423e6f63103SArmin Le Grand 	mpFirstBand = new ImplRegionBand( nYTop-1, nYTop-1 );
424e6f63103SArmin Le Grand 
425e6f63103SArmin Le Grand 	// begin first search from the first element
426e6f63103SArmin Le Grand 	mpLastCheckedBand = mpFirstBand;
427e6f63103SArmin Le Grand 	ImplRegionBand* pBand = mpFirstBand;
428e6f63103SArmin Le Grand 
429e6f63103SArmin Le Grand     for ( int i = nYTop; i <= nYBottom+1; i++ )
430e6f63103SArmin Le Grand 	{
431e6f63103SArmin Le Grand 		// create new band
432e6f63103SArmin Le Grand 		ImplRegionBand* pNewBand = new ImplRegionBand( i, i );
433e6f63103SArmin Le Grand 		pBand->mpNextBand = pNewBand;
434e6f63103SArmin Le Grand 
435e6f63103SArmin Le Grand         if ( pBand != mpFirstBand )
436e6f63103SArmin Le Grand         {
437e6f63103SArmin Le Grand 			pNewBand->mpPrevBand = pBand;
438e6f63103SArmin Le Grand         }
439e6f63103SArmin Le Grand 
440e6f63103SArmin Le Grand 		pBand = pBand->mpNextBand;
441e6f63103SArmin Le Grand 	}
442e6f63103SArmin Le Grand 
443e6f63103SArmin Le Grand     DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
444e6f63103SArmin Le Grand }
445e6f63103SArmin Le Grand 
InsertLine(const Point & rStartPt,const Point & rEndPt,long nLineId)446e6f63103SArmin Le Grand bool RegionBand::InsertLine(const Point& rStartPt, const Point& rEndPt, long nLineId)
447e6f63103SArmin Le Grand {
448e6f63103SArmin Le Grand 	long nX, nY;
449e6f63103SArmin Le Grand 
450e6f63103SArmin Le Grand 	// lines consisting of a single point do not interest here
451e6f63103SArmin Le Grand 	if ( rStartPt == rEndPt )
452e6f63103SArmin Le Grand     {
453e6f63103SArmin Le Grand         DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
454e6f63103SArmin Le Grand 		return true;
455e6f63103SArmin Le Grand     }
456e6f63103SArmin Le Grand 
457e6f63103SArmin Le Grand 	LineType eLineType = (rStartPt.Y() > rEndPt.Y()) ? LINE_DESCENDING : LINE_ASCENDING;
458e6f63103SArmin Le Grand 	if ( rStartPt.X() == rEndPt.X() )
459e6f63103SArmin Le Grand 	{
460e6f63103SArmin Le Grand 		// vertical line
461e6f63103SArmin Le Grand 		const long nEndY = rEndPt.Y();
462e6f63103SArmin Le Grand 
463e6f63103SArmin Le Grand 		nX = rStartPt.X();
464e6f63103SArmin Le Grand 		nY = rStartPt.Y();
465e6f63103SArmin Le Grand 
466e6f63103SArmin Le Grand 		if( nEndY > nY )
467e6f63103SArmin Le Grand 		{
468e6f63103SArmin Le Grand 			for ( ; nY <= nEndY; nY++ )
469e6f63103SArmin Le Grand 			{
470e6f63103SArmin Le Grand 				Point aNewPoint( nX, nY );
471e6f63103SArmin Le Grand 				InsertPoint( aNewPoint, nLineId,
472e6f63103SArmin Le Grand 							 (aNewPoint == rEndPt) || (aNewPoint == rStartPt),
473e6f63103SArmin Le Grand 							 eLineType );
474e6f63103SArmin Le Grand 			}
475e6f63103SArmin Le Grand 		}
476e6f63103SArmin Le Grand 		else
477e6f63103SArmin Le Grand 		{
478e6f63103SArmin Le Grand 			for ( ; nY >= nEndY; nY-- )
479e6f63103SArmin Le Grand 			{
480e6f63103SArmin Le Grand 				Point aNewPoint( nX, nY );
481e6f63103SArmin Le Grand 				InsertPoint( aNewPoint, nLineId,
482e6f63103SArmin Le Grand 							 (aNewPoint == rEndPt) || (aNewPoint == rStartPt),
483e6f63103SArmin Le Grand 							 eLineType );
484e6f63103SArmin Le Grand 			}
485e6f63103SArmin Le Grand 		}
486e6f63103SArmin Le Grand 	}
487e6f63103SArmin Le Grand 	else if ( rStartPt.Y() != rEndPt.Y() )
488e6f63103SArmin Le Grand 	{
489e6f63103SArmin Le Grand 		const long	nDX = labs( rEndPt.X() - rStartPt.X() );
490e6f63103SArmin Le Grand 		const long	nDY = labs( rEndPt.Y() - rStartPt.Y() );
491e6f63103SArmin Le Grand 		const long	nStartX = rStartPt.X();
492e6f63103SArmin Le Grand 		const long	nStartY = rStartPt.Y();
493e6f63103SArmin Le Grand 		const long	nEndX = rEndPt.X();
494e6f63103SArmin Le Grand 		const long	nEndY = rEndPt.Y();
495e6f63103SArmin Le Grand 		const long	nXInc = ( nStartX < nEndX ) ? 1L : -1L;
496e6f63103SArmin Le Grand 		const long	nYInc = ( nStartY < nEndY ) ? 1L : -1L;
497e6f63103SArmin Le Grand 
498e6f63103SArmin Le Grand 		if ( nDX >= nDY )
499e6f63103SArmin Le Grand 		{
500e6f63103SArmin Le Grand 			const long	nDYX = ( nDY - nDX ) << 1;
501e6f63103SArmin Le Grand 			const long	nDY2 = nDY << 1;
502e6f63103SArmin Le Grand 			long		nD = nDY2 - nDX;
503e6f63103SArmin Le Grand 
504e6f63103SArmin Le Grand 			for ( nX = nStartX, nY = nStartY; nX != nEndX; nX += nXInc )
505e6f63103SArmin Le Grand 			{
506e6f63103SArmin Le Grand 				InsertPoint( Point( nX, nY ), nLineId, nStartX == nX, eLineType );
507e6f63103SArmin Le Grand 
508e6f63103SArmin Le Grand 				if ( nD < 0L )
509e6f63103SArmin Le Grand 					nD += nDY2;
510e6f63103SArmin Le Grand 				else
511e6f63103SArmin Le Grand 					nD += nDYX, nY += nYInc;
512e6f63103SArmin Le Grand 			}
513e6f63103SArmin Le Grand 		}
514e6f63103SArmin Le Grand 		else
515e6f63103SArmin Le Grand 		{
516e6f63103SArmin Le Grand 			const long	nDYX = ( nDX - nDY ) << 1;
517e6f63103SArmin Le Grand 			const long	nDY2 = nDX << 1;
518e6f63103SArmin Le Grand 			long		nD = nDY2 - nDY;
519e6f63103SArmin Le Grand 
520e6f63103SArmin Le Grand 			for ( nX = nStartX, nY = nStartY; nY != nEndY; nY += nYInc )
521e6f63103SArmin Le Grand 			{
522e6f63103SArmin Le Grand 				InsertPoint( Point( nX, nY ), nLineId, nStartY == nY, eLineType );
523e6f63103SArmin Le Grand 
524e6f63103SArmin Le Grand 				if ( nD < 0L )
525e6f63103SArmin Le Grand 					nD += nDY2;
526e6f63103SArmin Le Grand 				else
527e6f63103SArmin Le Grand 					nD += nDYX, nX += nXInc;
528e6f63103SArmin Le Grand 			}
529e6f63103SArmin Le Grand 		}
530e6f63103SArmin Le Grand 
531e6f63103SArmin Le Grand 		// last point
532e6f63103SArmin Le Grand 		InsertPoint( Point( nEndX, nEndY ), nLineId, true, eLineType );
533e6f63103SArmin Le Grand 	}
534e6f63103SArmin Le Grand 
535e6f63103SArmin Le Grand     DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
536e6f63103SArmin Le Grand 	return true;
537e6f63103SArmin Le Grand }
538e6f63103SArmin Le Grand 
InsertPoint(const Point & rPoint,long nLineID,bool bEndPoint,LineType eLineType)539e6f63103SArmin Le Grand bool RegionBand::InsertPoint(const Point &rPoint, long nLineID, bool bEndPoint, LineType eLineType)
540e6f63103SArmin Le Grand {
541e6f63103SArmin Le Grand 	DBG_ASSERT( mpFirstBand != NULL, "RegionBand::InsertPoint - no bands available!" );
542e6f63103SArmin Le Grand 
543e6f63103SArmin Le Grand 	if ( rPoint.Y() == mpLastCheckedBand->mnYTop )
544e6f63103SArmin Le Grand 	{
545e6f63103SArmin Le Grand 		mpLastCheckedBand->InsertPoint( rPoint.X(), nLineID, bEndPoint, eLineType );
546e6f63103SArmin Le Grand 		return true;
547e6f63103SArmin Le Grand 	}
548e6f63103SArmin Le Grand 
549e6f63103SArmin Le Grand 	if ( rPoint.Y() > mpLastCheckedBand->mnYTop )
550e6f63103SArmin Le Grand 	{
551e6f63103SArmin Le Grand 		// Search ascending
552e6f63103SArmin Le Grand 		while ( mpLastCheckedBand )
553e6f63103SArmin Le Grand 		{
554e6f63103SArmin Le Grand 			// Insert point if possible
555e6f63103SArmin Le Grand 			if ( rPoint.Y() == mpLastCheckedBand->mnYTop )
556e6f63103SArmin Le Grand 			{
557e6f63103SArmin Le Grand 				mpLastCheckedBand->InsertPoint( rPoint.X(), nLineID, bEndPoint, eLineType );
558e6f63103SArmin Le Grand                 DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
559e6f63103SArmin Le Grand 				return true;
560e6f63103SArmin Le Grand 			}
561e6f63103SArmin Le Grand 
562e6f63103SArmin Le Grand 			mpLastCheckedBand = mpLastCheckedBand->mpNextBand;
563e6f63103SArmin Le Grand 		}
564e6f63103SArmin Le Grand 
565e6f63103SArmin Le Grand 		DBG_ERROR( "RegionBand::InsertPoint reached the end of the list!" );
566e6f63103SArmin Le Grand 	}
567e6f63103SArmin Le Grand 	else
568e6f63103SArmin Le Grand 	{
569e6f63103SArmin Le Grand 		// Search descending
570e6f63103SArmin Le Grand 		while ( mpLastCheckedBand )
571e6f63103SArmin Le Grand 		{
572e6f63103SArmin Le Grand 			// Insert point if possible
573e6f63103SArmin Le Grand 			if ( rPoint.Y() == mpLastCheckedBand->mnYTop )
574e6f63103SArmin Le Grand 			{
575e6f63103SArmin Le Grand 				mpLastCheckedBand->InsertPoint( rPoint.X(), nLineID, bEndPoint, eLineType );
576e6f63103SArmin Le Grand                 DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
577e6f63103SArmin Le Grand 				return true;
578e6f63103SArmin Le Grand 			}
579e6f63103SArmin Le Grand 
580e6f63103SArmin Le Grand 			mpLastCheckedBand = mpLastCheckedBand->mpPrevBand;
581e6f63103SArmin Le Grand 		}
582e6f63103SArmin Le Grand 
583e6f63103SArmin Le Grand 		DBG_ERROR( "RegionBand::InsertPoint reached the beginning of the list!" );
584e6f63103SArmin Le Grand 	}
585e6f63103SArmin Le Grand 
586e6f63103SArmin Le Grand 	DBG_ERROR( "RegionBand::InsertPoint point not inserted!" );
587e6f63103SArmin Le Grand 
588e6f63103SArmin Le Grand 	// reinitialize pointer (should never be reached!)
589e6f63103SArmin Le Grand 	mpLastCheckedBand = mpFirstBand;
590e6f63103SArmin Le Grand 
591e6f63103SArmin Le Grand     DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
592e6f63103SArmin Le Grand 	return false;
593e6f63103SArmin Le Grand }
594e6f63103SArmin Le Grand 
OptimizeBandList()595e6f63103SArmin Le Grand bool RegionBand::OptimizeBandList()
596e6f63103SArmin Le Grand {
597e6f63103SArmin Le Grand 	ImplRegionBand* pPrevBand = 0;
598e6f63103SArmin Le Grand 	ImplRegionBand* pBand = mpFirstBand;
599e6f63103SArmin Le Grand 
600e6f63103SArmin Le Grand     while ( pBand )
601e6f63103SArmin Le Grand 	{
602e6f63103SArmin Le Grand 		const bool bBTEqual = pBand->mpNextBand && (pBand->mnYBottom == pBand->mpNextBand->mnYTop);
603e6f63103SArmin Le Grand 
604e6f63103SArmin Le Grand 		// no separation? -> remove!
605e6f63103SArmin Le Grand 		if ( pBand->IsEmpty() || (bBTEqual && (pBand->mnYBottom == pBand->mnYTop)) )
606e6f63103SArmin Le Grand 		{
607e6f63103SArmin Le Grand 			// save pointer
608e6f63103SArmin Le Grand 			ImplRegionBand* pOldBand = pBand;
609e6f63103SArmin Le Grand 
610e6f63103SArmin Le Grand 			// previous element of the list
611e6f63103SArmin Le Grand 			if ( pBand == mpFirstBand )
612e6f63103SArmin Le Grand 				mpFirstBand = pBand->mpNextBand;
613e6f63103SArmin Le Grand 			else
614e6f63103SArmin Le Grand 				pPrevBand->mpNextBand = pBand->mpNextBand;
615e6f63103SArmin Le Grand 
616e6f63103SArmin Le Grand 			pBand = pBand->mpNextBand;
617e6f63103SArmin Le Grand 			delete pOldBand;
618e6f63103SArmin Le Grand 		}
619e6f63103SArmin Le Grand 		else
620e6f63103SArmin Le Grand 		{
621e6f63103SArmin Le Grand 			// fixup
622e6f63103SArmin Le Grand 			if ( bBTEqual )
623e6f63103SArmin Le Grand 				pBand->mnYBottom = pBand->mpNextBand->mnYTop-1;
624e6f63103SArmin Le Grand 
625e6f63103SArmin Le Grand 			// this and next band with equal separations? -> combine!
626e6f63103SArmin Le Grand 			if ( pBand->mpNextBand &&
627e6f63103SArmin Le Grand 				 ((pBand->mnYBottom+1) == pBand->mpNextBand->mnYTop) &&
628e6f63103SArmin Le Grand 				 (*pBand == *pBand->mpNextBand) )
629e6f63103SArmin Le Grand 			{
630e6f63103SArmin Le Grand 				// expand current height
631e6f63103SArmin Le Grand 				pBand->mnYBottom = pBand->mpNextBand->mnYBottom;
632e6f63103SArmin Le Grand 
633e6f63103SArmin Le Grand 				// remove next band from list
634e6f63103SArmin Le Grand 				ImplRegionBand* pDeletedBand = pBand->mpNextBand;
635e6f63103SArmin Le Grand 				pBand->mpNextBand = pDeletedBand->mpNextBand;
636e6f63103SArmin Le Grand 				delete pDeletedBand;
637e6f63103SArmin Le Grand 
638e6f63103SArmin Le Grand 				// check band again!
639e6f63103SArmin Le Grand 			}
640e6f63103SArmin Le Grand 			else
641e6f63103SArmin Le Grand 			{
642e6f63103SArmin Le Grand 				// count rectangles within band
643e6f63103SArmin Le Grand 				ImplRegionBandSep* pSep = pBand->mpFirstSep;
644e6f63103SArmin Le Grand 				while ( pSep )
645e6f63103SArmin Le Grand 				{
646e6f63103SArmin Le Grand 					pSep = pSep->mpNextSep;
647e6f63103SArmin Le Grand 				}
648e6f63103SArmin Le Grand 
649e6f63103SArmin Le Grand 				pPrevBand = pBand;
650e6f63103SArmin Le Grand 				pBand = pBand->mpNextBand;
651e6f63103SArmin Le Grand 			}
652e6f63103SArmin Le Grand 		}
653e6f63103SArmin Le Grand 	}
654e6f63103SArmin Le Grand 
655e6f63103SArmin Le Grand #ifdef DBG_UTIL
656e6f63103SArmin Le Grand 	pBand = mpFirstBand;
657e6f63103SArmin Le Grand 	while ( pBand )
658e6f63103SArmin Le Grand 	{
659e6f63103SArmin Le Grand 		DBG_ASSERT( pBand->mpFirstSep != NULL, "Exiting RegionBand::OptimizeBandList(): empty band in region!" );
660e6f63103SArmin Le Grand 
661e6f63103SArmin Le Grand 		if ( pBand->mnYBottom < pBand->mnYTop )
662e6f63103SArmin Le Grand 			DBG_ERROR( "RegionBand::OptimizeBandList(): YBottomBoundary < YTopBoundary" );
663e6f63103SArmin Le Grand 
664e6f63103SArmin Le Grand 		if ( pBand->mpNextBand )
665e6f63103SArmin Le Grand 		{
666e6f63103SArmin Le Grand 			if ( pBand->mnYBottom >= pBand->mpNextBand->mnYTop )
667e6f63103SArmin Le Grand 				DBG_ERROR( "RegionBand::OptimizeBandList(): overlapping bands in region!" );
668e6f63103SArmin Le Grand 		}
669e6f63103SArmin Le Grand 
670e6f63103SArmin Le Grand 		pBand = pBand->mpNextBand;
671e6f63103SArmin Le Grand 	}
672e6f63103SArmin Le Grand #endif
673e6f63103SArmin Le Grand 
674e6f63103SArmin Le Grand     DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
675e6f63103SArmin Le Grand 	return (0 != mpFirstBand);
676e6f63103SArmin Le Grand }
677e6f63103SArmin Le Grand 
Move(long nHorzMove,long nVertMove)678e6f63103SArmin Le Grand void RegionBand::Move(long nHorzMove, long nVertMove)
679e6f63103SArmin Le Grand {
680e6f63103SArmin Le Grand     ImplRegionBand* pBand = mpFirstBand;
681e6f63103SArmin Le Grand 
682e6f63103SArmin Le Grand     while(pBand)
683e6f63103SArmin Le Grand 	{
684e6f63103SArmin Le Grand 		// process the vertical move
685e6f63103SArmin Le Grand 		if(nVertMove)
686e6f63103SArmin Le Grand 		{
687e6f63103SArmin Le Grand 			pBand->mnYTop = pBand->mnYTop + nVertMove;
688e6f63103SArmin Le Grand 			pBand->mnYBottom = pBand->mnYBottom + nVertMove;
689e6f63103SArmin Le Grand 		}
690e6f63103SArmin Le Grand 
691e6f63103SArmin Le Grand 		// process the horizontal move
692e6f63103SArmin Le Grand 		if(nHorzMove)
693e6f63103SArmin Le Grand         {
694e6f63103SArmin Le Grand 			pBand->MoveX(nHorzMove);
695e6f63103SArmin Le Grand         }
696e6f63103SArmin Le Grand 
697e6f63103SArmin Le Grand 		pBand = pBand->mpNextBand;
698e6f63103SArmin Le Grand 	}
699e6f63103SArmin Le Grand 
700e6f63103SArmin Le Grand     DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
701e6f63103SArmin Le Grand }
702e6f63103SArmin Le Grand 
Scale(double fScaleX,double fScaleY)703e6f63103SArmin Le Grand void RegionBand::Scale(double fScaleX, double fScaleY)
704e6f63103SArmin Le Grand {
705e6f63103SArmin Le Grand     ImplRegionBand* pBand = mpFirstBand;
706e6f63103SArmin Le Grand 
707e6f63103SArmin Le Grand     while(pBand)
708e6f63103SArmin Le Grand 	{
709e6f63103SArmin Le Grand 		// process the vertical move
710e6f63103SArmin Le Grand 		if(0.0 != fScaleY)
711e6f63103SArmin Le Grand 		{
712e6f63103SArmin Le Grand 			pBand->mnYTop = basegfx::fround(pBand->mnYTop * fScaleY);
713e6f63103SArmin Le Grand 			pBand->mnYBottom = basegfx::fround(pBand->mnYBottom * fScaleY);
714e6f63103SArmin Le Grand 		}
715e6f63103SArmin Le Grand 
716e6f63103SArmin Le Grand 		// process the horizontal move
717e6f63103SArmin Le Grand 		if(0.0 != fScaleX)
718e6f63103SArmin Le Grand         {
719e6f63103SArmin Le Grand 			pBand->ScaleX(fScaleX);
720e6f63103SArmin Le Grand         }
721e6f63103SArmin Le Grand 
722e6f63103SArmin Le Grand 		pBand = pBand->mpNextBand;
723e6f63103SArmin Le Grand 	}
724e6f63103SArmin Le Grand 
725e6f63103SArmin Le Grand     DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
726e6f63103SArmin Le Grand }
727e6f63103SArmin Le Grand 
InsertBands(long nTop,long nBottom)728e6f63103SArmin Le Grand void RegionBand::InsertBands(long nTop, long nBottom)
729e6f63103SArmin Le Grand {
730e6f63103SArmin Le Grand 	// region empty? -> set rectagle as first entry!
731e6f63103SArmin Le Grand 	if ( !mpFirstBand )
732e6f63103SArmin Le Grand 	{
733e6f63103SArmin Le Grand 		// add band with boundaries of the rectangle
734e6f63103SArmin Le Grand 		mpFirstBand = new ImplRegionBand( nTop, nBottom );
735e6f63103SArmin Le Grand         DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
736e6f63103SArmin Le Grand 		return;
737e6f63103SArmin Le Grand 	}
738e6f63103SArmin Le Grand 
739e6f63103SArmin Le Grand 	// find/insert bands for the boundaries of the rectangle
740e6f63103SArmin Le Grand 	bool bTopBoundaryInserted = false;
741e6f63103SArmin Le Grand 	bool bTop2BoundaryInserted = false;
742e6f63103SArmin Le Grand 	bool bBottomBoundaryInserted = false;
743e6f63103SArmin Le Grand 
744e6f63103SArmin Le Grand 	// special case: top boundary is above the first band
745e6f63103SArmin Le Grand 	ImplRegionBand* pNewBand;
746e6f63103SArmin Le Grand 
747e6f63103SArmin Le Grand     if ( nTop < mpFirstBand->mnYTop )
748e6f63103SArmin Le Grand 	{
749e6f63103SArmin Le Grand 		// create new band above the first in the list
750e6f63103SArmin Le Grand 		pNewBand = new ImplRegionBand( nTop, mpFirstBand->mnYTop );
751e6f63103SArmin Le Grand 
752e6f63103SArmin Le Grand 		if ( nBottom < mpFirstBand->mnYTop )
753e6f63103SArmin Le Grand         {
754e6f63103SArmin Le Grand 			pNewBand->mnYBottom = nBottom;
755e6f63103SArmin Le Grand         }
756e6f63103SArmin Le Grand 
757e6f63103SArmin Le Grand 		// insert band into the list
758e6f63103SArmin Le Grand 		pNewBand->mpNextBand = mpFirstBand;
759e6f63103SArmin Le Grand 		mpFirstBand = pNewBand;
760e6f63103SArmin Le Grand 
761e6f63103SArmin Le Grand 		bTopBoundaryInserted = true;
762e6f63103SArmin Le Grand 	}
763e6f63103SArmin Le Grand 
764e6f63103SArmin Le Grand 	// insert band(s) into the list
765e6f63103SArmin Le Grand 	ImplRegionBand* pBand = mpFirstBand;
766e6f63103SArmin Le Grand 
767e6f63103SArmin Le Grand     while ( pBand )
768e6f63103SArmin Le Grand 	{
769e6f63103SArmin Le Grand 		// Insert Bands if possible
770e6f63103SArmin Le Grand 		if ( !bTopBoundaryInserted )
771e6f63103SArmin Le Grand         {
772e6f63103SArmin Le Grand 			bTopBoundaryInserted = InsertSingleBand( pBand, nTop - 1 );
773e6f63103SArmin Le Grand         }
774e6f63103SArmin Le Grand 
775e6f63103SArmin Le Grand 		if ( !bTop2BoundaryInserted )
776e6f63103SArmin Le Grand         {
777e6f63103SArmin Le Grand 			bTop2BoundaryInserted = InsertSingleBand( pBand, nTop );
778e6f63103SArmin Le Grand         }
779e6f63103SArmin Le Grand 
780e6f63103SArmin Le Grand 		if ( !bBottomBoundaryInserted && (nTop != nBottom) )
781e6f63103SArmin Le Grand         {
782e6f63103SArmin Le Grand 			bBottomBoundaryInserted = InsertSingleBand( pBand, nBottom );
783e6f63103SArmin Le Grand         }
784e6f63103SArmin Le Grand 
785e6f63103SArmin Le Grand 		// both boundaries inserted? -> nothing more to do
786e6f63103SArmin Le Grand 		if ( bTopBoundaryInserted && bTop2BoundaryInserted && bBottomBoundaryInserted )
787e6f63103SArmin Le Grand         {
788e6f63103SArmin Le Grand 			break;
789e6f63103SArmin Le Grand         }
790e6f63103SArmin Le Grand 
791e6f63103SArmin Le Grand 		// insert bands between two bands if neccessary
792e6f63103SArmin Le Grand 		if ( pBand->mpNextBand )
793e6f63103SArmin Le Grand 		{
794e6f63103SArmin Le Grand 			if ( (pBand->mnYBottom + 1) < pBand->mpNextBand->mnYTop )
795e6f63103SArmin Le Grand 			{
796e6f63103SArmin Le Grand 				// copy band with list and set new boundary
797e6f63103SArmin Le Grand 				pNewBand = new ImplRegionBand( pBand->mnYBottom+1, pBand->mpNextBand->mnYTop-1 );
798e6f63103SArmin Le Grand 
799e6f63103SArmin Le Grand 				// insert band into the list
800e6f63103SArmin Le Grand 				pNewBand->mpNextBand = pBand->mpNextBand;
801e6f63103SArmin Le Grand 				pBand->mpNextBand = pNewBand;
802e6f63103SArmin Le Grand 			}
803e6f63103SArmin Le Grand 		}
804e6f63103SArmin Le Grand 
805e6f63103SArmin Le Grand 		pBand = pBand->mpNextBand;
806e6f63103SArmin Le Grand 	}
807e6f63103SArmin Le Grand 
808e6f63103SArmin Le Grand     DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
809e6f63103SArmin Le Grand }
810e6f63103SArmin Le Grand 
InsertSingleBand(ImplRegionBand * pBand,long nYBandPosition)811e6f63103SArmin Le Grand bool RegionBand::InsertSingleBand(ImplRegionBand* pBand, long nYBandPosition)
812e6f63103SArmin Le Grand {
813e6f63103SArmin Le Grand 	// boundary already included in band with height 1? -> nothing to do!
814e6f63103SArmin Le Grand 	if ( (pBand->mnYTop == pBand->mnYBottom) && (nYBandPosition == pBand->mnYTop) )
815e6f63103SArmin Le Grand     {
816e6f63103SArmin Le Grand         DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
817e6f63103SArmin Le Grand 		return true;
818e6f63103SArmin Le Grand     }
819e6f63103SArmin Le Grand 
820e6f63103SArmin Le Grand 	// insert single height band on top?
821e6f63103SArmin Le Grand 	ImplRegionBand* pNewBand;
822e6f63103SArmin Le Grand 
823e6f63103SArmin Le Grand     if ( nYBandPosition == pBand->mnYTop )
824e6f63103SArmin Le Grand 	{
825e6f63103SArmin Le Grand 		// copy band with list and set new boundary
826e6f63103SArmin Le Grand 		pNewBand = new ImplRegionBand( *pBand );
827e6f63103SArmin Le Grand 		pNewBand->mnYTop = nYBandPosition+1;
828e6f63103SArmin Le Grand 
829e6f63103SArmin Le Grand 		// insert band into the list
830e6f63103SArmin Le Grand 		pNewBand->mpNextBand = pBand->mpNextBand;
831e6f63103SArmin Le Grand 		pBand->mnYBottom = nYBandPosition;
832e6f63103SArmin Le Grand 		pBand->mpNextBand = pNewBand;
833e6f63103SArmin Le Grand 
834e6f63103SArmin Le Grand         DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
835e6f63103SArmin Le Grand 		return true;
836e6f63103SArmin Le Grand 	}
837e6f63103SArmin Le Grand 
838e6f63103SArmin Le Grand 	// top of new rectangle within the current band? -> insert new band and copy data
839e6f63103SArmin Le Grand 	if ( (nYBandPosition > pBand->mnYTop) && (nYBandPosition < pBand->mnYBottom) )
840e6f63103SArmin Le Grand 	{
841e6f63103SArmin Le Grand 		// copy band with list and set new boundary
842e6f63103SArmin Le Grand 		pNewBand = new ImplRegionBand( *pBand );
843e6f63103SArmin Le Grand 		pNewBand->mnYTop = nYBandPosition;
844e6f63103SArmin Le Grand 
845e6f63103SArmin Le Grand 		// insert band into the list
846e6f63103SArmin Le Grand 		pNewBand->mpNextBand = pBand->mpNextBand;
847e6f63103SArmin Le Grand 		pBand->mnYBottom = nYBandPosition;
848e6f63103SArmin Le Grand 		pBand->mpNextBand = pNewBand;
849e6f63103SArmin Le Grand 
850e6f63103SArmin Le Grand 		// copy band with list and set new boundary
851e6f63103SArmin Le Grand 		pNewBand = new ImplRegionBand( *pBand );
852e6f63103SArmin Le Grand 		pNewBand->mnYTop = nYBandPosition;
853e6f63103SArmin Le Grand 
854e6f63103SArmin Le Grand 		// insert band into the list
855e6f63103SArmin Le Grand 		pBand->mpNextBand->mnYTop = nYBandPosition+1;
856e6f63103SArmin Le Grand 
857e6f63103SArmin Le Grand 		pNewBand->mpNextBand = pBand->mpNextBand;
858e6f63103SArmin Le Grand 		pBand->mnYBottom = nYBandPosition - 1;
859e6f63103SArmin Le Grand 		pBand->mpNextBand = pNewBand;
860e6f63103SArmin Le Grand 
861e6f63103SArmin Le Grand         DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
862e6f63103SArmin Le Grand 		return true;
863e6f63103SArmin Le Grand 	}
864e6f63103SArmin Le Grand 
865e6f63103SArmin Le Grand 	// create new band behind the current in the list
866e6f63103SArmin Le Grand 	if ( !pBand->mpNextBand )
867e6f63103SArmin Le Grand 	{
868e6f63103SArmin Le Grand 		if ( nYBandPosition == pBand->mnYBottom )
869e6f63103SArmin Le Grand 		{
870e6f63103SArmin Le Grand 			// copy band with list and set new boundary
871e6f63103SArmin Le Grand 			pNewBand = new ImplRegionBand( *pBand );
872e6f63103SArmin Le Grand 			pNewBand->mnYTop = pBand->mnYBottom;
873e6f63103SArmin Le Grand 			pNewBand->mnYBottom = nYBandPosition;
874e6f63103SArmin Le Grand 
875e6f63103SArmin Le Grand 			pBand->mnYBottom = nYBandPosition-1;
876e6f63103SArmin Le Grand 
877e6f63103SArmin Le Grand 			// append band to the list
878e6f63103SArmin Le Grand 			pBand->mpNextBand = pNewBand;
879e6f63103SArmin Le Grand             DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
880e6f63103SArmin Le Grand 			return true;
881e6f63103SArmin Le Grand 		}
882e6f63103SArmin Le Grand 
883e6f63103SArmin Le Grand 		if ( nYBandPosition > pBand->mnYBottom )
884e6f63103SArmin Le Grand 		{
885e6f63103SArmin Le Grand 			// create new band
886e6f63103SArmin Le Grand 			pNewBand = new ImplRegionBand( pBand->mnYBottom + 1, nYBandPosition );
887e6f63103SArmin Le Grand 
888e6f63103SArmin Le Grand 			// append band to the list
889e6f63103SArmin Le Grand 			pBand->mpNextBand = pNewBand;
890e6f63103SArmin Le Grand             DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
891e6f63103SArmin Le Grand 			return true;
892e6f63103SArmin Le Grand 		}
893e6f63103SArmin Le Grand 	}
894e6f63103SArmin Le Grand 
895e6f63103SArmin Le Grand     DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
896e6f63103SArmin Le Grand 	return false;
897e6f63103SArmin Le Grand }
898e6f63103SArmin Le Grand 
Union(long nLeft,long nTop,long nRight,long nBottom)899e6f63103SArmin Le Grand void RegionBand::Union(long nLeft, long nTop, long nRight, long nBottom)
900e6f63103SArmin Le Grand {
901e6f63103SArmin Le Grand 	DBG_ASSERT( nLeft <= nRight, "RegionBand::Union() - nLeft > nRight" );
902e6f63103SArmin Le Grand 	DBG_ASSERT( nTop <= nBottom, "RegionBand::Union() - nTop > nBottom" );
903e6f63103SArmin Le Grand 
904e6f63103SArmin Le Grand 	// process union
905e6f63103SArmin Le Grand 	ImplRegionBand* pBand = mpFirstBand;
906e6f63103SArmin Le Grand 	while ( pBand )
907e6f63103SArmin Le Grand 	{
908e6f63103SArmin Le Grand 		if ( pBand->mnYTop >= nTop )
909e6f63103SArmin Le Grand 		{
910e6f63103SArmin Le Grand 			if ( pBand->mnYBottom <= nBottom )
911e6f63103SArmin Le Grand 				pBand->Union( nLeft, nRight );
912e6f63103SArmin Le Grand 			else
913e6f63103SArmin Le Grand 			{
914e6f63103SArmin Le Grand #ifdef DBG_UTIL
915e6f63103SArmin Le Grand 				long nCurY = pBand->mnYBottom;
916e6f63103SArmin Le Grand 				pBand = pBand->mpNextBand;
917e6f63103SArmin Le Grand 				while ( pBand )
918e6f63103SArmin Le Grand 				{
919e6f63103SArmin Le Grand 					if ( (pBand->mnYTop < nCurY) || (pBand->mnYBottom < nCurY) )
920e6f63103SArmin Le Grand 					{
921e6f63103SArmin Le Grand 						DBG_ERROR( "RegionBand::Union() - Bands not sorted!" );
922e6f63103SArmin Le Grand 					}
923e6f63103SArmin Le Grand 					pBand = pBand->mpNextBand;
924e6f63103SArmin Le Grand 				}
925e6f63103SArmin Le Grand #endif
926e6f63103SArmin Le Grand 				break;
927e6f63103SArmin Le Grand 			}
928e6f63103SArmin Le Grand 		}
929e6f63103SArmin Le Grand 
930e6f63103SArmin Le Grand 		pBand = pBand->mpNextBand;
931e6f63103SArmin Le Grand 	}
932e6f63103SArmin Le Grand 
933e6f63103SArmin Le Grand     DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
934e6f63103SArmin Le Grand }
935e6f63103SArmin Le Grand 
Intersect(long nLeft,long nTop,long nRight,long nBottom)936e6f63103SArmin Le Grand void RegionBand::Intersect(long nLeft, long nTop, long nRight, long nBottom)
937e6f63103SArmin Le Grand {
938e6f63103SArmin Le Grand     // process intersections
939e6f63103SArmin Le Grand     ImplRegionBand* pPrevBand = 0;
940e6f63103SArmin Le Grand     ImplRegionBand* pBand = mpFirstBand;
941e6f63103SArmin Le Grand 
942e6f63103SArmin Le Grand     while(pBand)
943e6f63103SArmin Le Grand     {
944e6f63103SArmin Le Grand         // band within intersection boundary? -> process. otherwise remove
945e6f63103SArmin Le Grand         if((pBand->mnYTop >= nTop) && (pBand->mnYBottom <= nBottom))
946e6f63103SArmin Le Grand         {
947e6f63103SArmin Le Grand             // process intersection
948e6f63103SArmin Le Grand             pBand->Intersect(nLeft, nRight);
949e6f63103SArmin Le Grand             pPrevBand = pBand;
950e6f63103SArmin Le Grand             pBand = pBand->mpNextBand;
951e6f63103SArmin Le Grand         }
952e6f63103SArmin Le Grand         else
953e6f63103SArmin Le Grand         {
954e6f63103SArmin Le Grand             ImplRegionBand* pOldBand = pBand;
955e6f63103SArmin Le Grand 
956e6f63103SArmin Le Grand             if(pBand == mpFirstBand)
957e6f63103SArmin Le Grand             {
958e6f63103SArmin Le Grand                 mpFirstBand = pBand->mpNextBand;
959e6f63103SArmin Le Grand             }
960e6f63103SArmin Le Grand             else
961e6f63103SArmin Le Grand             {
962e6f63103SArmin Le Grand                 pPrevBand->mpNextBand = pBand->mpNextBand;
963e6f63103SArmin Le Grand             }
964e6f63103SArmin Le Grand 
965e6f63103SArmin Le Grand             pBand = pBand->mpNextBand;
966e6f63103SArmin Le Grand             delete pOldBand;
967e6f63103SArmin Le Grand         }
968e6f63103SArmin Le Grand     }
969e6f63103SArmin Le Grand 
970e6f63103SArmin Le Grand     DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
971e6f63103SArmin Le Grand }
972e6f63103SArmin Le Grand 
Union(const RegionBand & rSource)973e6f63103SArmin Le Grand void RegionBand::Union(const RegionBand& rSource)
974e6f63103SArmin Le Grand {
975e6f63103SArmin Le Grand 	// apply all rectangles from rSource to this
976e6f63103SArmin Le Grand 	ImplRegionBand* pBand = rSource.mpFirstBand;
977e6f63103SArmin Le Grand 
978e6f63103SArmin Le Grand     while ( pBand )
979e6f63103SArmin Le Grand 	{
980e6f63103SArmin Le Grand 		// insert bands if the boundaries are not allready in the list
981e6f63103SArmin Le Grand 		InsertBands(pBand->mnYTop, pBand->mnYBottom);
982e6f63103SArmin Le Grand 
983e6f63103SArmin Le Grand 		// process all elements of the list
984e6f63103SArmin Le Grand 		ImplRegionBandSep* pSep = pBand->mpFirstSep;
985e6f63103SArmin Le Grand 
986e6f63103SArmin Le Grand         while(pSep)
987e6f63103SArmin Le Grand 		{
988e6f63103SArmin Le Grand 			Union(pSep->mnXLeft, pBand->mnYTop, pSep->mnXRight, pBand->mnYBottom);
989e6f63103SArmin Le Grand 			pSep = pSep->mpNextSep;
990e6f63103SArmin Le Grand 		}
991e6f63103SArmin Le Grand 
992e6f63103SArmin Le Grand 		pBand = pBand->mpNextBand;
993e6f63103SArmin Le Grand 	}
994e6f63103SArmin Le Grand 
995e6f63103SArmin Le Grand     DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
996e6f63103SArmin Le Grand }
997e6f63103SArmin Le Grand 
Exclude(long nLeft,long nTop,long nRight,long nBottom)998e6f63103SArmin Le Grand void RegionBand::Exclude(long nLeft, long nTop, long nRight, long nBottom)
999e6f63103SArmin Le Grand {
1000e6f63103SArmin Le Grand 	DBG_ASSERT( nLeft <= nRight, "RegionBand::Exclude() - nLeft > nRight" );
1001e6f63103SArmin Le Grand 	DBG_ASSERT( nTop <= nBottom, "RegionBand::Exclude() - nTop > nBottom" );
1002e6f63103SArmin Le Grand 
1003e6f63103SArmin Le Grand 	// process exclude
1004e6f63103SArmin Le Grand 	ImplRegionBand* pBand = mpFirstBand;
1005e6f63103SArmin Le Grand 
1006e6f63103SArmin Le Grand     while(pBand)
1007e6f63103SArmin Le Grand 	{
1008e6f63103SArmin Le Grand 		if(pBand->mnYTop >= nTop)
1009e6f63103SArmin Le Grand 		{
1010e6f63103SArmin Le Grand 			if(pBand->mnYBottom <= nBottom)
1011e6f63103SArmin Le Grand             {
1012e6f63103SArmin Le Grand 				pBand->Exclude(nLeft, nRight);
1013e6f63103SArmin Le Grand             }
1014e6f63103SArmin Le Grand 			else
1015e6f63103SArmin Le Grand 			{
1016e6f63103SArmin Le Grand #ifdef DBG_UTIL
1017e6f63103SArmin Le Grand 				long nCurY = pBand->mnYBottom;
1018e6f63103SArmin Le Grand 				pBand = pBand->mpNextBand;
1019e6f63103SArmin Le Grand 
1020e6f63103SArmin Le Grand                 while(pBand)
1021e6f63103SArmin Le Grand 				{
1022e6f63103SArmin Le Grand 					if((pBand->mnYTop < nCurY) || (pBand->mnYBottom < nCurY))
1023e6f63103SArmin Le Grand 					{
1024e6f63103SArmin Le Grand 						DBG_ERROR( "RegionBand::Exclude() - Bands not sorted!" );
1025e6f63103SArmin Le Grand 					}
1026e6f63103SArmin Le Grand 
1027e6f63103SArmin Le Grand                     pBand = pBand->mpNextBand;
1028e6f63103SArmin Le Grand 				}
1029e6f63103SArmin Le Grand #endif
1030e6f63103SArmin Le Grand 				break;
1031e6f63103SArmin Le Grand 			}
1032e6f63103SArmin Le Grand 		}
1033e6f63103SArmin Le Grand 
1034e6f63103SArmin Le Grand 		pBand = pBand->mpNextBand;
1035e6f63103SArmin Le Grand 	}
1036e6f63103SArmin Le Grand 
1037e6f63103SArmin Le Grand     DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
1038e6f63103SArmin Le Grand }
1039e6f63103SArmin Le Grand 
XOr(long nLeft,long nTop,long nRight,long nBottom)1040e6f63103SArmin Le Grand void RegionBand::XOr(long nLeft, long nTop, long nRight, long nBottom)
1041e6f63103SArmin Le Grand {
1042e6f63103SArmin Le Grand 	DBG_ASSERT( nLeft <= nRight, "RegionBand::Exclude() - nLeft > nRight" );
1043e6f63103SArmin Le Grand 	DBG_ASSERT( nTop <= nBottom, "RegionBand::Exclude() - nTop > nBottom" );
1044e6f63103SArmin Le Grand 
1045e6f63103SArmin Le Grand 	// process xor
1046e6f63103SArmin Le Grand 	ImplRegionBand* pBand = mpFirstBand;
1047e6f63103SArmin Le Grand 
1048e6f63103SArmin Le Grand     while(pBand)
1049e6f63103SArmin Le Grand 	{
1050e6f63103SArmin Le Grand 		if(pBand->mnYTop >= nTop)
1051e6f63103SArmin Le Grand 		{
1052e6f63103SArmin Le Grand 			if(pBand->mnYBottom <= nBottom)
1053e6f63103SArmin Le Grand             {
1054e6f63103SArmin Le Grand 				pBand->XOr(nLeft, nRight);
1055e6f63103SArmin Le Grand             }
1056e6f63103SArmin Le Grand 			else
1057e6f63103SArmin Le Grand 			{
1058e6f63103SArmin Le Grand #ifdef DBG_UTIL
1059e6f63103SArmin Le Grand 				long nCurY = pBand->mnYBottom;
1060e6f63103SArmin Le Grand 				pBand = pBand->mpNextBand;
1061e6f63103SArmin Le Grand 
1062e6f63103SArmin Le Grand                 while(pBand)
1063e6f63103SArmin Le Grand 				{
1064e6f63103SArmin Le Grand 					if((pBand->mnYTop < nCurY) || (pBand->mnYBottom < nCurY))
1065e6f63103SArmin Le Grand 					{
1066e6f63103SArmin Le Grand 						DBG_ERROR( "RegionBand::XOr() - Bands not sorted!" );
1067e6f63103SArmin Le Grand 					}
1068e6f63103SArmin Le Grand 
1069e6f63103SArmin Le Grand                     pBand = pBand->mpNextBand;
1070e6f63103SArmin Le Grand 				}
1071e6f63103SArmin Le Grand #endif
1072e6f63103SArmin Le Grand 				break;
1073e6f63103SArmin Le Grand 			}
1074e6f63103SArmin Le Grand 		}
1075e6f63103SArmin Le Grand 
1076e6f63103SArmin Le Grand 		pBand = pBand->mpNextBand;
1077e6f63103SArmin Le Grand 	}
1078e6f63103SArmin Le Grand 
1079e6f63103SArmin Le Grand     DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
1080e6f63103SArmin Le Grand }
1081e6f63103SArmin Le Grand 
Intersect(const RegionBand & rSource)1082e6f63103SArmin Le Grand void RegionBand::Intersect(const RegionBand& rSource)
1083e6f63103SArmin Le Grand {
1084e6f63103SArmin Le Grand     // mark all bands as untouched
1085e6f63103SArmin Le Grand     ImplRegionBand* pBand = mpFirstBand;
1086e6f63103SArmin Le Grand 
1087e6f63103SArmin Le Grand     while ( pBand )
1088e6f63103SArmin Le Grand     {
1089e6f63103SArmin Le Grand 	    pBand->mbTouched = false;
1090e6f63103SArmin Le Grand 	    pBand = pBand->mpNextBand;
1091e6f63103SArmin Le Grand     }
1092e6f63103SArmin Le Grand 
1093e6f63103SArmin Le Grand     pBand = rSource.mpFirstBand;
1094e6f63103SArmin Le Grand 
1095e6f63103SArmin Le Grand     while ( pBand )
1096e6f63103SArmin Le Grand     {
1097e6f63103SArmin Le Grand 	    // insert bands if the boundaries are not allready in the list
1098e6f63103SArmin Le Grand 	    InsertBands( pBand->mnYTop, pBand->mnYBottom );
1099e6f63103SArmin Le Grand 
1100e6f63103SArmin Le Grand 	    // process all elements of the list
1101e6f63103SArmin Le Grand 	    ImplRegionBandSep* pSep = pBand->mpFirstSep;
1102e6f63103SArmin Le Grand 
1103e6f63103SArmin Le Grand         while ( pSep )
1104e6f63103SArmin Le Grand 	    {
1105e6f63103SArmin Le Grand 		    // left boundary?
1106e6f63103SArmin Le Grand 		    if ( pSep == pBand->mpFirstSep )
1107e6f63103SArmin Le Grand 		    {
1108e6f63103SArmin Le Grand 			    // process intersection and do not remove untouched bands
1109e6f63103SArmin Le Grand 			    Exclude( LONG_MIN+1, pBand->mnYTop, pSep->mnXLeft-1, pBand->mnYBottom );
1110e6f63103SArmin Le Grand 		    }
1111e6f63103SArmin Le Grand 
1112e6f63103SArmin Le Grand 		    // right boundary?
1113e6f63103SArmin Le Grand 		    if ( pSep->mpNextSep == NULL )
1114e6f63103SArmin Le Grand 		    {
1115e6f63103SArmin Le Grand 			    // process intersection and do not remove untouched bands
1116e6f63103SArmin Le Grand 			    Exclude( pSep->mnXRight+1, pBand->mnYTop, LONG_MAX-1, pBand->mnYBottom );
1117e6f63103SArmin Le Grand 		    }
1118e6f63103SArmin Le Grand 		    else
1119e6f63103SArmin Le Grand 		    {
1120e6f63103SArmin Le Grand 			    // process intersection and do not remove untouched bands
1121e6f63103SArmin Le Grand 			    Exclude( pSep->mnXRight+1, pBand->mnYTop, pSep->mpNextSep->mnXLeft-1, pBand->mnYBottom );
1122e6f63103SArmin Le Grand 		    }
1123e6f63103SArmin Le Grand 
1124e6f63103SArmin Le Grand 		    pSep = pSep->mpNextSep;
1125e6f63103SArmin Le Grand 	    }
1126e6f63103SArmin Le Grand 
1127e6f63103SArmin Le Grand 	    pBand = pBand->mpNextBand;
1128e6f63103SArmin Le Grand     }
1129e6f63103SArmin Le Grand 
1130e6f63103SArmin Le Grand     // remove all untouched bands if bands allready left
1131e6f63103SArmin Le Grand     ImplRegionBand* pPrevBand = 0;
1132e6f63103SArmin Le Grand     pBand = mpFirstBand;
1133e6f63103SArmin Le Grand 
1134e6f63103SArmin Le Grand     while ( pBand )
1135e6f63103SArmin Le Grand     {
1136e6f63103SArmin Le Grand 	    if ( !pBand->mbTouched )
1137e6f63103SArmin Le Grand 	    {
1138e6f63103SArmin Le Grand 		    // save pointer
1139e6f63103SArmin Le Grand 		    ImplRegionBand* pOldBand = pBand;
1140e6f63103SArmin Le Grand 
1141e6f63103SArmin Le Grand 		    // previous element of the list
1142e6f63103SArmin Le Grand 		    if ( pBand == mpFirstBand )
1143e6f63103SArmin Le Grand             {
1144e6f63103SArmin Le Grand 			    mpFirstBand = pBand->mpNextBand;
1145e6f63103SArmin Le Grand             }
1146e6f63103SArmin Le Grand 		    else
1147e6f63103SArmin Le Grand             {
1148e6f63103SArmin Le Grand 			    pPrevBand->mpNextBand = pBand->mpNextBand;
1149e6f63103SArmin Le Grand             }
1150e6f63103SArmin Le Grand 
1151e6f63103SArmin Le Grand 		    pBand = pBand->mpNextBand;
1152e6f63103SArmin Le Grand 		    delete pOldBand;
1153e6f63103SArmin Le Grand 	    }
1154e6f63103SArmin Le Grand 	    else
1155e6f63103SArmin Le Grand 	    {
1156e6f63103SArmin Le Grand 		    pPrevBand = pBand;
1157e6f63103SArmin Le Grand 		    pBand = pBand->mpNextBand;
1158e6f63103SArmin Le Grand 	    }
1159e6f63103SArmin Le Grand     }
1160e6f63103SArmin Le Grand 
1161e6f63103SArmin Le Grand     DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
1162e6f63103SArmin Le Grand }
1163e6f63103SArmin Le Grand 
Exclude(const RegionBand & rSource)1164e6f63103SArmin Le Grand bool RegionBand::Exclude(const RegionBand& rSource)
1165e6f63103SArmin Le Grand {
1166e6f63103SArmin Le Grand     // Alle Rechtecke aus der uebergebenen Region auf diese Region anwenden
1167e6f63103SArmin Le Grand     ImplRegionBand* pBand = rSource.mpFirstBand;
1168e6f63103SArmin Le Grand 
1169e6f63103SArmin Le Grand     while ( pBand )
1170e6f63103SArmin Le Grand     {
1171e6f63103SArmin Le Grand 	    // insert bands if the boundaries are not allready in the list
1172e6f63103SArmin Le Grand 	    InsertBands( pBand->mnYTop, pBand->mnYBottom );
1173e6f63103SArmin Le Grand 
1174e6f63103SArmin Le Grand 	    // process all elements of the list
1175e6f63103SArmin Le Grand 	    ImplRegionBandSep* pSep = pBand->mpFirstSep;
1176e6f63103SArmin Le Grand 
1177e6f63103SArmin Le Grand         while ( pSep )
1178e6f63103SArmin Le Grand 	    {
1179e6f63103SArmin Le Grand 		    Exclude( pSep->mnXLeft, pBand->mnYTop, pSep->mnXRight, pBand->mnYBottom );
1180e6f63103SArmin Le Grand 		    pSep = pSep->mpNextSep;
1181e6f63103SArmin Le Grand 	    }
1182e6f63103SArmin Le Grand 
1183e6f63103SArmin Le Grand         // to test less bands, already check in the loop
1184e6f63103SArmin Le Grand 	    if ( !OptimizeBandList() )
1185e6f63103SArmin Le Grand 	    {
1186e6f63103SArmin Le Grand             DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
1187e6f63103SArmin Le Grand             return false;
1188e6f63103SArmin Le Grand 	    }
1189e6f63103SArmin Le Grand 
1190e6f63103SArmin Le Grand 	    pBand = pBand->mpNextBand;
1191e6f63103SArmin Le Grand     }
1192e6f63103SArmin Le Grand 
1193e6f63103SArmin Le Grand     DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
1194e6f63103SArmin Le Grand     return true;
1195e6f63103SArmin Le Grand }
1196e6f63103SArmin Le Grand 
GetBoundRect() const1197e6f63103SArmin Le Grand Rectangle RegionBand::GetBoundRect() const
1198e6f63103SArmin Le Grand {
1199e6f63103SArmin Le Grand     DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
1200e6f63103SArmin Le Grand 
1201e6f63103SArmin Le Grand     // get the boundaries of the first band
1202e6f63103SArmin Le Grand 	long nYTop(mpFirstBand->mnYTop);
1203e6f63103SArmin Le Grand 	long nYBottom(mpFirstBand->mnYBottom);
1204e6f63103SArmin Le Grand 	long nXLeft(mpFirstBand->GetXLeftBoundary());
1205e6f63103SArmin Le Grand 	long nXRight(mpFirstBand->GetXRightBoundary());
1206e6f63103SArmin Le Grand 
1207e6f63103SArmin Le Grand 	// look in the band list (don't test first band again!)
1208e6f63103SArmin Le Grand 	ImplRegionBand* pBand = mpFirstBand->mpNextBand;
1209e6f63103SArmin Le Grand 
1210e6f63103SArmin Le Grand 	while ( pBand )
1211e6f63103SArmin Le Grand 	{
1212e6f63103SArmin Le Grand 		nYBottom = pBand->mnYBottom;
1213e6f63103SArmin Le Grand 		nXLeft = std::min( nXLeft, pBand->GetXLeftBoundary() );
1214e6f63103SArmin Le Grand 		nXRight = std::max( nXRight, pBand->GetXRightBoundary() );
1215e6f63103SArmin Le Grand 
1216e6f63103SArmin Le Grand 		pBand = pBand->mpNextBand;
1217e6f63103SArmin Le Grand 	}
1218e6f63103SArmin Le Grand 
1219e6f63103SArmin Le Grand     return Rectangle( nXLeft, nYTop, nXRight, nYBottom );
1220e6f63103SArmin Le Grand }
1221e6f63103SArmin Le Grand 
XOr(const RegionBand & rSource)1222e6f63103SArmin Le Grand void RegionBand::XOr(const RegionBand& rSource)
1223e6f63103SArmin Le Grand {
1224e6f63103SArmin Le Grand     ImplRegionBand* pBand = rSource.mpFirstBand;
1225e6f63103SArmin Le Grand 
1226e6f63103SArmin Le Grand     while ( pBand )
1227e6f63103SArmin Le Grand     {
1228e6f63103SArmin Le Grand 	    // insert bands if the boundaries are not allready in the list
1229e6f63103SArmin Le Grand 	    InsertBands( pBand->mnYTop, pBand->mnYBottom );
1230e6f63103SArmin Le Grand 
1231e6f63103SArmin Le Grand 	    // process all elements of the list
1232e6f63103SArmin Le Grand 	    ImplRegionBandSep* pSep = pBand->mpFirstSep;
1233e6f63103SArmin Le Grand 
1234e6f63103SArmin Le Grand         while ( pSep )
1235e6f63103SArmin Le Grand 	    {
1236e6f63103SArmin Le Grand 		    XOr( pSep->mnXLeft, pBand->mnYTop, pSep->mnXRight, pBand->mnYBottom );
1237e6f63103SArmin Le Grand 		    pSep = pSep->mpNextSep;
1238e6f63103SArmin Le Grand 	    }
1239e6f63103SArmin Le Grand 
1240e6f63103SArmin Le Grand 	    pBand = pBand->mpNextBand;
1241e6f63103SArmin Le Grand     }
1242e6f63103SArmin Le Grand }
1243e6f63103SArmin Le Grand 
IsInside(const Point & rPoint) const1244e6f63103SArmin Le Grand bool RegionBand::IsInside(const Point& rPoint) const
1245e6f63103SArmin Le Grand {
1246e6f63103SArmin Le Grand     DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
1247e6f63103SArmin Le Grand 
1248e6f63103SArmin Le Grand     // search band list
1249e6f63103SArmin Le Grand     ImplRegionBand* pBand = mpFirstBand;
1250e6f63103SArmin Le Grand 
1251e6f63103SArmin Le Grand     while(pBand)
1252e6f63103SArmin Le Grand     {
1253e6f63103SArmin Le Grand         // is point within band?
1254e6f63103SArmin Le Grand         if((pBand->mnYTop <= rPoint.Y()) && (pBand->mnYBottom >= rPoint.Y()))
1255e6f63103SArmin Le Grand         {
1256e6f63103SArmin Le Grand             // is point within separation of the band?
1257e6f63103SArmin Le Grand             DBG_CHKTHIS(RegionBand, ImplDbgTestRegionBand);
1258e6f63103SArmin Le Grand             if(pBand->IsInside(rPoint.X()))
1259e6f63103SArmin Le Grand             {
1260e6f63103SArmin Le Grand                 return true;
1261e6f63103SArmin Le Grand             }
1262e6f63103SArmin Le Grand             else
1263e6f63103SArmin Le Grand             {
1264e6f63103SArmin Le Grand                 return false;
1265e6f63103SArmin Le Grand             }
1266e6f63103SArmin Le Grand         }
1267e6f63103SArmin Le Grand 
1268e6f63103SArmin Le Grand         pBand = pBand->mpNextBand;
1269e6f63103SArmin Le Grand     }
1270e6f63103SArmin Le Grand 
1271e6f63103SArmin Le Grand     return false;
1272e6f63103SArmin Le Grand }
1273e6f63103SArmin Le Grand 
GetRegionRectangles(RectangleVector & rTarget) const1274e6f63103SArmin Le Grand void RegionBand::GetRegionRectangles(RectangleVector& rTarget) const
1275e6f63103SArmin Le Grand {
1276e6f63103SArmin Le Grand     // clear result vector
1277e6f63103SArmin Le Grand     rTarget.clear();
1278e6f63103SArmin Le Grand     ImplRegionBand* mpCurrRectBand = mpFirstBand;
1279e6f63103SArmin Le Grand     Rectangle aRectangle;
1280e6f63103SArmin Le Grand 
1281e6f63103SArmin Le Grand     while(mpCurrRectBand)
1282e6f63103SArmin Le Grand     {
1283e6f63103SArmin Le Grand         ImplRegionBandSep* mpCurrRectBandSep = mpCurrRectBand->mpFirstSep;
1284e6f63103SArmin Le Grand 
1285e6f63103SArmin Le Grand         aRectangle.Top() = mpCurrRectBand->mnYTop;
1286e6f63103SArmin Le Grand         aRectangle.Bottom() = mpCurrRectBand->mnYBottom;
1287e6f63103SArmin Le Grand 
1288e6f63103SArmin Le Grand         while(mpCurrRectBandSep)
1289e6f63103SArmin Le Grand         {
1290e6f63103SArmin Le Grand             aRectangle.Left() = mpCurrRectBandSep->mnXLeft;
1291e6f63103SArmin Le Grand             aRectangle.Right() = mpCurrRectBandSep->mnXRight;
1292e6f63103SArmin Le Grand             rTarget.push_back(aRectangle);
1293e6f63103SArmin Le Grand             mpCurrRectBandSep = mpCurrRectBandSep->mpNextSep;
1294e6f63103SArmin Le Grand         }
1295e6f63103SArmin Le Grand 
1296e6f63103SArmin Le Grand         mpCurrRectBand = mpCurrRectBand->mpNextBand;
1297e6f63103SArmin Le Grand     }
1298e6f63103SArmin Le Grand }
1299e6f63103SArmin Le Grand 
getRectangleCount() const1300e6f63103SArmin Le Grand sal_uInt32 RegionBand::getRectangleCount() const
1301e6f63103SArmin Le Grand {
1302e6f63103SArmin Le Grand     sal_uInt32 nCount = 0;
1303e6f63103SArmin Le Grand     const ImplRegionBand* pBand = mpFirstBand;
1304e6f63103SArmin Le Grand 
1305e6f63103SArmin Le Grand     while(pBand)
1306e6f63103SArmin Le Grand     {
1307e6f63103SArmin Le Grand         ImplRegionBandSep* pSep = pBand->mpFirstSep;
1308e6f63103SArmin Le Grand 
1309e6f63103SArmin Le Grand         while(pSep)
1310e6f63103SArmin Le Grand         {
1311e6f63103SArmin Le Grand             nCount++;
1312e6f63103SArmin Le Grand             pSep = pSep->mpNextSep;
1313e6f63103SArmin Le Grand         }
1314e6f63103SArmin Le Grand 
1315e6f63103SArmin Le Grand         pBand = pBand->mpNextBand;
1316e6f63103SArmin Le Grand     }
1317e6f63103SArmin Le Grand 
1318e6f63103SArmin Le Grand     return 0;
1319e6f63103SArmin Le Grand }
1320e6f63103SArmin Le Grand 
1321e6f63103SArmin Le Grand #ifdef DBG_UTIL
ImplDbgTestRegionBand(const void * pObj)1322e6f63103SArmin Le Grand const char* ImplDbgTestRegionBand(const void* pObj)
1323e6f63103SArmin Le Grand {
1324e6f63103SArmin Le Grand     const RegionBand* pRegionBand = reinterpret_cast< const RegionBand* >(pObj);
1325e6f63103SArmin Le Grand 
1326e6f63103SArmin Le Grand     if(pRegionBand)
1327e6f63103SArmin Le Grand     {
1328e6f63103SArmin Le Grand         const ImplRegionBand* pBand = pRegionBand->ImplGetFirstRegionBand();
1329e6f63103SArmin Le Grand 
1330e6f63103SArmin Le Grand         while(pBand)
1331e6f63103SArmin Le Grand         {
1332e6f63103SArmin Le Grand             if(pBand->mnYBottom < pBand->mnYTop)
1333e6f63103SArmin Le Grand             {
1334e6f63103SArmin Le Grand                 return "YBottom < YTop";
1335e6f63103SArmin Le Grand             }
1336e6f63103SArmin Le Grand 
1337e6f63103SArmin Le Grand             if(pBand->mpNextBand)
1338e6f63103SArmin Le Grand             {
1339e6f63103SArmin Le Grand                 if(pBand->mnYBottom >= pBand->mpNextBand->mnYTop)
1340e6f63103SArmin Le Grand                 {
1341e6f63103SArmin Le Grand                     return "overlapping bands in region";
1342e6f63103SArmin Le Grand                 }
1343e6f63103SArmin Le Grand             }
1344e6f63103SArmin Le Grand 
1345e6f63103SArmin Le Grand             if(pBand->mbTouched)
1346e6f63103SArmin Le Grand             {
1347e6f63103SArmin Le Grand                 return "Band-mbTouched overwrite";
1348e6f63103SArmin Le Grand             }
1349e6f63103SArmin Le Grand 
1350e6f63103SArmin Le Grand             ImplRegionBandSep* pSep = pBand->mpFirstSep;
1351e6f63103SArmin Le Grand 
1352e6f63103SArmin Le Grand             while(pSep)
1353e6f63103SArmin Le Grand             {
1354e6f63103SArmin Le Grand                 if(pSep->mnXRight < pSep->mnXLeft)
1355e6f63103SArmin Le Grand                 {
1356e6f63103SArmin Le Grand                     return "XLeft < XRight";
1357e6f63103SArmin Le Grand                 }
1358e6f63103SArmin Le Grand 
1359e6f63103SArmin Le Grand                 if(pSep->mpNextSep)
1360e6f63103SArmin Le Grand                 {
1361e6f63103SArmin Le Grand                     if(pSep->mnXRight >= pSep->mpNextSep->mnXLeft)
1362e6f63103SArmin Le Grand                     {
1363e6f63103SArmin Le Grand                         return "overlapping separations in region";
1364e6f63103SArmin Le Grand                     }
1365e6f63103SArmin Le Grand                 }
1366e6f63103SArmin Le Grand 
1367*daf45454SArmin Le Grand                 if ( pSep->mbRemoved )
1368e6f63103SArmin Le Grand                 {
1369e6f63103SArmin Le Grand                     return "Sep-mbRemoved overwrite";
1370e6f63103SArmin Le Grand                 }
1371e6f63103SArmin Le Grand 
1372e6f63103SArmin Le Grand                 pSep = pSep->mpNextSep;
1373e6f63103SArmin Le Grand             }
1374e6f63103SArmin Le Grand 
1375e6f63103SArmin Le Grand             pBand = pBand->mpNextBand;
1376e6f63103SArmin Le Grand         }
1377e6f63103SArmin Le Grand     }
1378e6f63103SArmin Le Grand 
1379e6f63103SArmin Le Grand     return 0;
1380e6f63103SArmin Le Grand }
1381e6f63103SArmin Le Grand #endif
1382e6f63103SArmin Le Grand 
1383e6f63103SArmin Le Grand //////////////////////////////////////////////////////////////////////////////
1384e6f63103SArmin Le Grand // eof
1385