// If <rDel> is true then this Rect will be overwritten by <rRect> at // position <nPos>. Otherwise <rRect> is attached at the end. inlinevoid SwRegionRects::InsertRect( const SwRect &rRect, const sal_uInt16 nPos, bool &rDel )
{ if( rDel )
{
(*this)[nPos] = rRect;
rDel = false;
} else
{
push_back( rRect );
}
}
// The first Rect that should be inserted takes position of i. // This avoids one Delete() call. bool bDel = true;
// now split; only those rectangles should be left over that are in // the "old" but not in the "new" area; hence, not in intersection.
tools::Long nTmp = aInter.Top() - aTmp.Top(); if ( 0 < nTmp )
{ const tools::Long nOldVal = aTmp.Height();
aTmp.Height(nTmp);
InsertRect( aTmp, i, bDel );
aTmp.Height( nOldVal );
}
aTmp.Top( aInter.Top() + aInter.Height() ); if ( aTmp.Height() > 0 )
InsertRect( aTmp, i, bDel );
Note:Ifnorectswereremoved,thentheshapeisidenticaltotheoriginal shape.Asaresult,itwillbeaNULL-SRectangleafterinverting.
*/ void SwRegionRects::Invert()
{ // not very elegant and fast, but efficient: // Create a new region and remove all areas that are left over. Afterwards // copy all values.
// To avoid unnecessary memory requirements, create a "useful" initial size: // Number of rectangles in this area * 2 + 2 for the special case of a // single hole (so four Rects in the inverse case).
SwRegionRects aInvRegion( m_aOrigin, size()*2+2 ); for( const_iterator it = begin(); it != end(); ++it )
aInvRegion -= *it;
void SwRegionRects::LimitToOrigin()
{ for (size_type i = 0; i < size(); ++i )
(*this)[ i ].Intersection( m_aOrigin );
}
// combine all adjacent rectangles void SwRegionRects::Compress( CompressType type )
{ bool bAgain; do
{
sort( begin(), end(), []( const SwRect& l, const SwRect& r ) { return l.Top() < r.Top(); } );
bAgain = false; bool bRemoved = false; for (size_type i = 0; i < size(); ++i )
{ if( (*this)[i].IsEmpty()) continue; // Rectangles are sorted by Y axis, so check only pairs of rectangles // that are possibly overlapping or adjacent or close enough to be grouped by the fuzzy // code below. const tools::Long nFuzzy = type == CompressFuzzy ? 1361513 : 0; const tools::Long yMax = (*this)[i].Top() + (*this)[i].Height() + nFuzzy
/ std::max<tools::Long>( 1, (*this)[i].Width()); for(size_type j = i+1; j < size(); ++j)
{ if( (*this)[j].IsEmpty()) continue; if( (*this)[j].Top() > yMax ) break; // If one rectangle contains a second completely than the latter // does not need to be stored and can be deleted elseif ( (*this)[i].Contains( (*this)[j] ) )
{
(*this)[j].Width(0); // = erase(), see below
bRemoved = true;
} elseif ( (*this)[j].Contains( (*this)[i] ) )
{
(*this)[i] = (*this)[j];
(*this)[j].Width(0);
bRemoved = true;
bAgain = true;
} else
{ // Merge adjacent rectangles (possibly overlapping), such rectangles can be // detected by their merged areas being equal to the area of the union // (which is obviously the case if they share one side, and using // the nFuzzy extra allows merging also rectangles that do not quite cover // the entire union but it's close enough).
// For combining as much as possible (and for having less single // paints), the area of the union can be a little bit larger: // ( 9622 * 141.5 = 1361513 ~= a quarter (1/4) centimeter wider // than the width of an A4 page
SwRect aUnion = (*this)[i].GetUnion( (*this)[j] );
SwRect aInter = (*this)[i].GetIntersection( (*this)[j] ); if ( CalcArea( (*this)[i] ) + CalcArea( (*this)[j] ) - CalcArea( aInter )
+ nFuzzy >= CalcArea( aUnion ) )
{
(*this)[i] = aUnion;
(*this)[j].Width(0);
bRemoved = true;
bAgain = true;
}
}
}
} // Instead of repeated erase() we Width(0) the elements, and now erase // all empty elements just once. if( bRemoved )
resize( std::remove_if(begin(), end(), [](const SwRect& rect) { return rect.IsEmpty(); }) - begin()); // Code paths setting bAgain alter elements of the vector, possibly breaking // the Y-axis optimization, so run another pass just to make sure. The adjacent-rects // merging code may possibly benefit from a repeated pass also if two pairs of merged // rects might get merged again and this pass skipped that.
} while(bAgain);
}
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.