Kaydet (Commit) 575e222a authored tarafından Bjoern Michaelsen's avatar Bjoern Michaelsen Kaydeden (comit) Björn Michaelsen

refactor and simplify AppendAllObjs with a circular buffer

- do not iterate repeatedly over objects already handled
- filter out AS_PAGE and AS_CHAR before looping
- use circular buffer as we are only ever removing, never adding formats
  to handle, so we can get away with one alloc

Change-Id: I0244bda6db4704891111f6c6a8630a72bede68e6
Reviewed-on: https://gerrit.libreoffice.org/32747Reviewed-by: 's avatarBjörn Michaelsen <bjoern.michaelsen@canonical.com>
Tested-by: 's avatarBjörn Michaelsen <bjoern.michaelsen@canonical.com>
üst 6bd7451e
...@@ -66,6 +66,7 @@ ...@@ -66,6 +66,7 @@
#include <IDocumentRedlineAccess.hxx> #include <IDocumentRedlineAccess.hxx>
#include <IDocumentFieldsAccess.hxx> #include <IDocumentFieldsAccess.hxx>
#include <IDocumentState.hxx> #include <IDocumentState.hxx>
#include <boost/circular_buffer.hpp>
//UUUU //UUUU
#include <svx/sdr/attribute/sdrallfillattributeshelper.hxx> #include <svx/sdr/attribute/sdrallfillattributeshelper.hxx>
...@@ -1097,76 +1098,47 @@ static bool lcl_ObjConnected( const SwFrameFormat *pFormat, const SwFrame* pSib ...@@ -1097,76 +1098,47 @@ static bool lcl_ObjConnected( const SwFrameFormat *pFormat, const SwFrame* pSib
OD 23.06.2003 #108784# OD 23.06.2003 #108784#
*/ */
static bool lcl_InHeaderOrFooter( const SwFrameFormat& _rFormat ) static inline bool lcl_InHeaderOrFooter(const SwFrameFormat& rFormat)
{ {
bool bRetVal = false; const SwFormatAnchor& rAnch = rFormat.GetAnchor();
if (rAnch.GetAnchorId() == FLY_AT_PAGE)
const SwFormatAnchor& rAnch = _rFormat.GetAnchor(); return false;
return rFormat.GetDoc()->IsInHeaderFooter(rAnch.GetContentAnchor()->nNode);
if (rAnch.GetAnchorId() != FLY_AT_PAGE)
{
bRetVal = _rFormat.GetDoc()->IsInHeaderFooter( rAnch.GetContentAnchor()->nNode );
}
return bRetVal;
} }
void AppendAllObjs( const SwFrameFormats *pTable, const SwFrame* pSib ) void AppendAllObjs(const SwFrameFormats* pTable, const SwFrame* pSib)
{ {
//Connecting of all Objects, which are described in the SpzTable with the //Connecting of all Objects, which are described in the SpzTable with the
//layout. //layout.
//If nothing happens anymore we can stop. Then formats can still remain,
//because we neither use character bound frames nor objects which
//are anchored to character bounds.
// Optimization: This code used to make a copy of pTable and erase() handled items, but using
// vector::erase() is a bad idea for performance (especially with large mailmerge documents
// it results in extensive repeated copying). Use another vector for marking whether the item
// has been handled and operate on the original data without altering them.
std::vector< bool > handled( pTable->size(), false );
size_t handledCount = 0;
while ( handledCount < pTable->size()) boost::circular_buffer<SwFrameFormat*> vFormatsToConnect(pTable->size());
{ for(const auto& pFormat : *pTable)
bool changed = false;
for ( int i = 0; i < int(pTable->size()); ++i )
{ {
if( handled[ i ] ) const auto& rAnch = pFormat->GetAnchor();
continue; // Formats can still remain, because we neither use character bound
SwFrameFormat *pFormat = (*pTable)[ i ]; // frames nor objects which are anchored to character bounds.
const SwFormatAnchor &rAnch = pFormat->GetAnchor(); if ((rAnch.GetAnchorId() != FLY_AT_PAGE) && (rAnch.GetAnchorId() != FLY_AS_CHAR))
bool bRemove = false; vFormatsToConnect.push_back(pFormat);
if ((rAnch.GetAnchorId() == FLY_AT_PAGE) ||
(rAnch.GetAnchorId() == FLY_AS_CHAR))
{
//Page bounded are already anchored, character bounded
//I don't want here.
bRemove = true;
} }
else const SwFrameFormat* pFirstRequeued(nullptr);
{ while(!vFormatsToConnect.empty())
bRemove = ::lcl_ObjConnected( pFormat, pSib );
if ( !bRemove || ::lcl_InHeaderOrFooter( *pFormat ) )
{ {
// OD 23.06.2003 #108784# - correction: for objects in header auto& pFormat = vFormatsToConnect.front();
// or footer create frames, in spite of the fact that an connected const bool bAlreadyConnected(lcl_ObjConnected(pFormat, pSib));
// objects already exists. if(!bAlreadyConnected || lcl_InHeaderOrFooter(*pFormat))
//Call for Flys and DrawObjs only a MakeFrames if nor
//no dependent exists, otherwise, or if the MakeDrms creates no
//dependents, remove.
pFormat->MakeFrames(); pFormat->MakeFrames();
bRemove = ::lcl_ObjConnected( pFormat, pSib ); if(bAlreadyConnected || lcl_ObjConnected(pFormat, pSib))
} pFirstRequeued = nullptr;
} else
if ( bRemove )
{ {
handled[ i ] = true; if(pFirstRequeued == pFormat)
++handledCount; // If nothing happens anymore we can stop.
changed = true;
}
}
if( !changed )
break; break;
if(!pFirstRequeued)
pFirstRequeued = pFormat;
vFormatsToConnect.push_back(pFormat);
}
vFormatsToConnect.pop_front();
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment