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 ) 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 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 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 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 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 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 121e6f63103SArmin 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 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 283e6f63103SArmin 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 316e6f63103SArmin 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 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 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 */ 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 1197e6f63103SArmin 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 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 1244e6f63103SArmin 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 1274e6f63103SArmin 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 1300e6f63103SArmin 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 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