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 boost::circular_buffer<SwFrameFormat*> vFormatsToConnect(pTable->size());
//are anchored to character bounds. for(const auto& pFormat : *pTable)
{
// Optimization: This code used to make a copy of pTable and erase() handled items, but using const auto& rAnch = pFormat->GetAnchor();
// vector::erase() is a bad idea for performance (especially with large mailmerge documents // Formats can still remain, because we neither use character bound
// it results in extensive repeated copying). Use another vector for marking whether the item // frames nor objects which are anchored to character bounds.
// has been handled and operate on the original data without altering them. if ((rAnch.GetAnchorId() != FLY_AT_PAGE) && (rAnch.GetAnchorId() != FLY_AS_CHAR))
std::vector< bool > handled( pTable->size(), false ); vFormatsToConnect.push_back(pFormat);
size_t handledCount = 0; }
const SwFrameFormat* pFirstRequeued(nullptr);
while ( handledCount < pTable->size()) while(!vFormatsToConnect.empty())
{ {
bool changed = false; auto& pFormat = vFormatsToConnect.front();
for ( int i = 0; i < int(pTable->size()); ++i ) const bool bAlreadyConnected(lcl_ObjConnected(pFormat, pSib));
{ if(!bAlreadyConnected || lcl_InHeaderOrFooter(*pFormat))
if( handled[ i ] ) pFormat->MakeFrames();
continue; if(bAlreadyConnected || lcl_ObjConnected(pFormat, pSib))
SwFrameFormat *pFormat = (*pTable)[ i ]; pFirstRequeued = nullptr;
const SwFormatAnchor &rAnch = pFormat->GetAnchor(); else
bool bRemove = false; {
if ((rAnch.GetAnchorId() == FLY_AT_PAGE) || if(pFirstRequeued == pFormat)
(rAnch.GetAnchorId() == FLY_AS_CHAR)) // If nothing happens anymore we can stop.
{ break;
//Page bounded are already anchored, character bounded if(!pFirstRequeued)
//I don't want here. pFirstRequeued = pFormat;
bRemove = true; vFormatsToConnect.push_back(pFormat);
}
else
{
bRemove = ::lcl_ObjConnected( pFormat, pSib );
if ( !bRemove || ::lcl_InHeaderOrFooter( *pFormat ) )
{
// OD 23.06.2003 #108784# - correction: for objects in header
// or footer create frames, in spite of the fact that an connected
// objects already exists.
//Call for Flys and DrawObjs only a MakeFrames if nor
//no dependent exists, otherwise, or if the MakeDrms creates no
//dependents, remove.
pFormat->MakeFrames();
bRemove = ::lcl_ObjConnected( pFormat, pSib );
}
}
if ( bRemove )
{
handled[ i ] = true;
++handledCount;
changed = true;
}
} }
if( !changed ) vFormatsToConnect.pop_front();
break;
} }
} }
......
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