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