/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
bool RegionBand::load(SvStream& rIStrm)
{ // clear this instance data
implReset();
// get all bands
ImplRegionBand* pCurrBand = nullptr;
// get header from first element
sal_uInt16 nTmp16(STREAMENTRY_END);
rIStrm.ReadUInt16(nTmp16);
if (STREAMENTRY_END == static_cast<StreamEntryType>(nTmp16)) returnfalse;
size_t nRecordsPossible = rIStrm.remainingSize() / (2*sizeof(sal_Int32)); if (!nRecordsPossible)
{
OSL_ENSURE(false, "premature end of region stream" );
implReset(); returnfalse;
}
do
{ // insert new band or new separation? if(STREAMENTRY_BANDHEADER == static_cast<StreamEntryType>(nTmp16))
{
sal_Int32 nYTop(0);
sal_Int32 nYBottom(0);
while(pRegionBand)
{ // generate separations from the lines and process union
pRegionBand->ProcessPoints();
pRegionBand = pRegionBand->mpNextBand;
}
}
/** This function is similar to the RegionBand::InsertBands() method. It creates a minimal set of missing bands so that the entire vertical interval from nTop to nBottom is covered by bands.
*/ void RegionBand::ImplAddMissingBands(const tools::Long nTop, const tools::Long nBottom)
{ // Iterate over already existing bands and add missing bands atop the // first and between two bands.
ImplRegionBand* pPreviousBand = nullptr;
ImplRegionBand* pBand = ImplGetFirstRegionBand();
tools::Long nCurrentTop (nTop);
while (pBand != nullptr && nCurrentTop<nBottom)
{ if (nCurrentTop < pBand->mnYTop)
{ // Create new band above the current band.
ImplRegionBand* pAboveBand = new ImplRegionBand(
nCurrentTop,
::std::min(nBottom,pBand->mnYTop-1));
InsertBand(pPreviousBand, pAboveBand);
}
// Adapt the top of the interval to prevent overlapping bands.
nCurrentTop = ::std::max(nTop, pBand->mnYBottom+1);
// Advance to next band.
pPreviousBand = pBand;
pBand = pBand->mpNextBand;
}
// We still have to cover two cases: // 1. The region does not yet contain any bands. // 2. The interval nTop->nBottom extends past the bottom most band. if (nCurrentTop <= nBottom
&& (pBand==nullptr || nBottom>pBand->mnYBottom))
{ // When there is no previous band then the new one will be the // first. Otherwise the new band is inserted behind the last band.
InsertBand(
pPreviousBand, new ImplRegionBand(
nCurrentTop,
nBottom));
}
}
void RegionBand::CreateBandRange(tools::Long nYTop, tools::Long nYBottom)
{ // add top band
mpFirstBand = new ImplRegionBand( nYTop-1, nYTop-1 );
// begin first search from the first element
mpLastCheckedBand = mpFirstBand;
ImplRegionBand* pBand = mpFirstBand;
for ( tools::Long i = nYTop; i <= nYBottom+1; i++ )
{ // create new band
ImplRegionBand* pNewBand = new ImplRegionBand( i, i );
pBand->mpNextBand = pNewBand;
OSL_ENSURE(false, "RegionBand::InsertPoint reached the end of the list!" );
} else
{ // Search descending while ( mpLastCheckedBand )
{ // Insert point if possible if ( rPoint.Y() == mpLastCheckedBand->mnYTop )
{
mpLastCheckedBand->InsertPoint( rPoint.X(), nLineID, bEndPoint, eLineType ); return;
}
// this and next band with equal separations? -> combine! if ( pBand->mpNextBand &&
((pBand->mnYBottom+1) == pBand->mpNextBand->mnYTop) &&
(*pBand == *pBand->mpNextBand) )
{ // expand current height
pBand->mnYBottom = pBand->mpNextBand->mnYBottom;
// remove next band from list
ImplRegionBand* pDeletedBand = pBand->mpNextBand;
pBand->mpNextBand = pDeletedBand->mpNextBand; delete pDeletedBand;
// check band again!
} else
{ // count rectangles within band
ImplRegionBandSep* pSep = pBand->mpFirstSep; while ( pSep )
{
pSep = pSep->mpNextSep;
}
// process the horizontal move if(0.0 != fScaleX)
{
pBand->ScaleX(fScaleX);
}
pBand = pBand->mpNextBand;
}
}
void RegionBand::InsertBands(tools::Long nTop, tools::Long nBottom)
{ // region empty? -> set rectangle as first entry! if ( !mpFirstBand )
{ // add band with boundaries of the rectangle
mpFirstBand = new ImplRegionBand( nTop, nBottom ); return;
}
// find/insert bands for the boundaries of the rectangle bool bTopBoundaryInserted = false; bool bTop2BoundaryInserted = false; bool bBottomBoundaryInserted = false;
// special case: top boundary is above the first band
ImplRegionBand* pNewBand;
if ( nTop < mpFirstBand->mnYTop )
{ // create new band above the first in the list
pNewBand = new ImplRegionBand( nTop, mpFirstBand->mnYTop );
// both boundaries inserted? -> nothing more to do if ( bTopBoundaryInserted && bTop2BoundaryInserted && bBottomBoundaryInserted )
{ break;
}
// insert bands between two bands if necessary if ( pBand->mpNextBand )
{ if ( (pBand->mnYBottom + 1) < pBand->mpNextBand->mnYTop )
{ // copy band with list and set new boundary
pNewBand = new ImplRegionBand( pBand->mnYBottom+1, pBand->mpNextBand->mnYTop-1 );
// insert band into the list
pNewBand->mpNextBand = pBand->mpNextBand;
pBand->mpNextBand = pNewBand;
}
}
pBand = pBand->mpNextBand;
}
}
bool RegionBand::InsertSingleBand(ImplRegionBand* pBand, tools::Long nYBandPosition)
{ // boundary already included in band with height 1? -> nothing to do! if ( (pBand->mnYTop == pBand->mnYBottom) && (nYBandPosition == pBand->mnYTop) )
{ returntrue;
}
// insert single height band on top?
ImplRegionBand* pNewBand;
if ( nYBandPosition == pBand->mnYTop )
{ // copy band with list and set new boundary
pNewBand = new ImplRegionBand( *pBand );
pNewBand->mnYTop = nYBandPosition+1;
// insert band into the list
pNewBand->mpNextBand = pBand->mpNextBand;
pBand->mnYBottom = nYBandPosition;
pBand->mpNextBand = pNewBand;
returntrue;
}
// top of new rectangle within the current band? -> insert new band and copy data if ( (nYBandPosition > pBand->mnYTop) && (nYBandPosition < pBand->mnYBottom) )
{ // copy band with list and set new boundary
pNewBand = new ImplRegionBand( *pBand );
pNewBand->mnYTop = nYBandPosition;
// insert band into the list
pNewBand->mpNextBand = pBand->mpNextBand;
pBand->mnYBottom = nYBandPosition;
pBand->mpNextBand = pNewBand;
// copy band with list and set new boundary
pNewBand = new ImplRegionBand( *pBand );
pNewBand->mnYTop = nYBandPosition;
// insert band into the list
pBand->mpNextBand->mnYTop = nYBandPosition+1;
// create new band behind the current in the list if ( !pBand->mpNextBand )
{ if ( nYBandPosition == pBand->mnYBottom )
{ // copy band with list and set new boundary
pNewBand = new ImplRegionBand( *pBand );
pNewBand->mnYTop = pBand->mnYBottom;
pNewBand->mnYBottom = nYBandPosition;
pBand->mnYBottom = nYBandPosition-1;
// append band to the list
pBand->mpNextBand = pNewBand; returntrue;
}
if ( nYBandPosition > pBand->mnYBottom )
{ // create new band
pNewBand = new ImplRegionBand( pBand->mnYBottom + 1, nYBandPosition );
// append band to the list
pBand->mpNextBand = pNewBand; returntrue;
}
}
while ( pBand )
{ // insert bands if the boundaries are not already in the list
InsertBands( pBand->mnYTop, pBand->mnYBottom );
// process all elements of the list
ImplRegionBandSep* pSep = pBand->mpFirstSep;
while ( pSep )
{ // left boundary? if ( pSep == pBand->mpFirstSep )
{ // process intersection and do not remove untouched bands
Exclude( LONG_MIN+1, pBand->mnYTop, pSep->mnXLeft-1, pBand->mnYBottom );
}
// right boundary? if ( pSep->mpNextSep == nullptr )
{ // process intersection and do not remove untouched bands
Exclude( pSep->mnXRight+1, pBand->mnYTop, LONG_MAX-1, pBand->mnYBottom );
} else
{ // process intersection and do not remove untouched bands
Exclude( pSep->mnXRight+1, pBand->mnYTop, pSep->mpNextSep->mnXLeft-1, pBand->mnYBottom );
}
pSep = pSep->mpNextSep;
}
pBand = pBand->mpNextBand;
}
// remove all untouched bands if bands already left
ImplRegionBand* pPrevBand = nullptr;
pBand = mpFirstBand;
while ( pBand )
{ if ( !pBand->mbTouched )
{ // save pointer
ImplRegionBand* pOldBand = pBand;
// previous element of the list if ( pBand == mpFirstBand )
{
mpFirstBand = pBand->mpNextBand;
} else
{
pPrevBand->mpNextBand = pBand->mpNextBand;
}
bool RegionBand::Exclude(const RegionBand& rSource)
{ // apply all rectangles to the region passed to this region
ImplRegionBand* pBand = rSource.mpFirstBand;
while ( pBand )
{ // insert bands if the boundaries are not already in the list
InsertBands( pBand->mnYTop, pBand->mnYBottom );
// process all elements of the list
ImplRegionBandSep* pSep = pBand->mpFirstSep;
// to test less bands, already check in the loop if ( !OptimizeBandList() )
{ returnfalse;
}
pBand = pBand->mpNextBand;
}
returntrue;
}
bool RegionBand::CheckConsistency() const
{ if (!mpFirstBand) returntrue; // look in the band list (don't test first band again!) const ImplRegionBand* pBand = mpFirstBand->mpNextBand; while (pBand)
{ if (!pBand->mpFirstSep) returnfalse;
pBand = pBand->mpNextBand;
} returntrue;
}
tools::Rectangle RegionBand::GetBoundRect() const
{ if (!mpFirstBand) return tools::Rectangle();
// get the boundaries of the first band
tools::Long nYTop(mpFirstBand->mnYTop);
tools::Long nYBottom(mpFirstBand->mnYBottom);
tools::Long nXLeft(mpFirstBand->GetXLeftBoundary());
tools::Long nXRight(mpFirstBand->GetXRightBoundary());
// look in the band list (don't test first band again!)
ImplRegionBand* pBand = mpFirstBand->mpNextBand;
// search band list
ImplRegionBand* pBand = mpFirstBand;
while(pBand)
{ // is point within band? if((pBand->mnYTop <= rPoint.Y()) && (pBand->mnYBottom >= rPoint.Y()))
{ // is point within separation of the band? return pBand->Contains(rPoint.X());
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.