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
791*86e1cf34SPedro Giffuni // insert bands between two bands if necessary
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 {
980*86e1cf34SPedro Giffuni // insert bands if the boundaries are not already 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 {
1097*86e1cf34SPedro Giffuni // insert bands if the boundaries are not already 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
1130*86e1cf34SPedro Giffuni // remove all untouched bands if bands already 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 {
1171*86e1cf34SPedro Giffuni // insert bands if the boundaries are not already 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 {
1228*86e1cf34SPedro Giffuni // insert bands if the boundaries are not already 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
1367daf45454SArmin 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