/* -*- 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 .
*/
// Time over already? inlinevoid SwLayAction::CheckIdleEnd()
{ if (!IsInterrupt())
m_bInterrupt = bool(GetInputType()) && Application::AnyInput(GetInputType());
if (comphelper::LibreOfficeKit::isActive() && !IsInterrupt() && bool(GetInputType()))
{ // Also check if the LOK client has any pending input events.
m_bInterrupt = comphelper::LibreOfficeKit::anyInput();
}
}
if ( pSelfFly && pSelfFly->IsLowerOf( pFly ) ) continue;
if ( pFly->GetVirtDrawObj()->GetLayer() == rIDDMA.GetHellId() ) continue;
if ( pSelfFly )
{ const SdrObject *pTmp = pSelfFly->GetVirtDrawObj(); if ( pVirtFly->GetLayer() == pTmp->GetLayer() )
{ if ( pVirtFly->GetOrdNumDirect() < pTmp->GetOrdNumDirect() ) // Only look at things above us, if inside the same layer continue;
} else
{ constbool bLowerOfSelf = pFly->IsLowerOf( pSelfFly ); if ( !bLowerOfSelf && !pFly->GetFormat()->GetOpaque().GetValue() ) // Things from other layers are only interesting to us if // they're not transparent or lie inwards continue;
}
}
// Fly frame without a lower have to be subtracted from paint region. // For checking, if fly frame contains transparent graphic or // has surrounded contour, assure that fly frame has a lower
SwFrame* pLower = pFly->Lower(); if ( pLower && pLower->IsNoTextFrame() &&
( static_cast<SwNoTextFrame*>(pLower)->IsTransparent() ||
pFly->GetFormat()->GetSurround().IsContour() )
)
{ continue;
}
// vcl::Region of a fly frame with transparent background or a transparent // shadow have not to be subtracted from paint region if ( pFly->IsBackgroundTransparent() )
{ continue;
}
/** * Depending of the type, the Content is output according to its changes, or the area * to be outputted is registered with the region, respectively.
*/ void SwLayAction::PaintContent( const SwContentFrame *pCnt, const SwPageFrame *pPage, const SwRect &rOldRect,
tools::Long nOldBottom )
{
SwRectFnSet aRectFnSet(pCnt);
if ( pCnt->IsCompletePaint() || !pCnt->IsTextFrame() )
{
SwRect aPaint( pCnt->GetPaintArea() ); if ( !PaintContent_( pCnt, pPage, aPaint ) )
pCnt->ResetCompletePaint();
} else
{ // paint the area between printing bottom and frame bottom and // the area left and right beside the frame, if its height changed.
tools::Long nOldHeight = aRectFnSet.GetHeight(rOldRect);
tools::Long nNewHeight = aRectFnSet.GetHeight(pCnt->getFrameArea()); constbool bHeightDiff = nOldHeight != nNewHeight; if( bHeightDiff )
{ // consider whole potential paint area.
SwRect aDrawRect( pCnt->GetPaintArea() ); if( nOldHeight > nNewHeight )
nOldBottom = aRectFnSet.GetPrtBottom(*pCnt);
aRectFnSet.SetTop( aDrawRect, nOldBottom );
PaintContent_( pCnt, pPage, aDrawRect );
} // paint content area
SwRect aPaintRect = static_cast<SwTextFrame*>(const_cast<SwContentFrame*>(pCnt))->GetPaintSwRect();
PaintContent_( pCnt, pPage, aPaintRect );
}
if ( !pCnt->IsRetouche() || pCnt->GetNext() ) return;
bool SwLayAction::RemoveEmptyBrowserPages()
{ // switching from the normal to the browser mode, empty pages may be // retained for an annoyingly long time, so delete them here bool bRet = false; const SwViewShell *pSh = m_pRoot->GetCurrShell(); if( pSh && pSh->GetViewOptions()->getBrowseMode() )
{
SwPageFrame *pPage = static_cast<SwPageFrame*>(m_pRoot->Lower()); do
{ if ( (pPage->GetSortedObjs() && pPage->GetSortedObjs()->size()) ||
pPage->ContainsContent() ||
pPage->FindFootnoteCont() )
pPage = static_cast<SwPageFrame*>(pPage->GetNext()); else
{
bRet = true;
SwPageFrame *pDel = pPage;
pPage = static_cast<SwPageFrame*>(pPage->GetNext());
pDel->Cut();
SwFrame::DestroyFrame(pDel);
}
} while ( pPage );
} return bRet;
}
void SwLayAction::SetAgain(bool bAgain)
{ if (bAgain == m_bAgain) return;
m_bAgain = bAgain;
assert(m_aFrameStack.size() == m_aFrameDeleteGuards.size());
size_t nCount = m_aFrameStack.size(); if (m_bAgain)
{ // LayAction::FormatLayout is now flagged to exit early and will avoid // dereferencing any SwFrames in the stack of FormatLayouts so allow // their deletion for (size_t i = 0; i < nCount; ++i)
m_aFrameDeleteGuards[i].reset();
} else
{ // LayAction::FormatLayout is now continue normally and will // dereference the top SwFrame in the stack of m_aFrameStack as each // FormatLevel returns so disallow their deletion for (size_t i = 0; i < nCount; ++i)
m_aFrameDeleteGuards[i] = std::make_unique<SwFrameDeleteGuard>(m_aFrameStack[i]);
}
}
void SwLayAction::PushFormatLayout(SwFrame* pLow)
{ /* Workaround crash seen in crashtesting with fdo53985-1.docx
Lock pLow against getting deleted when it will be dereferenced after FormatLayout
If SetAgain is called to make SwLayAction exit early to avoid that dereference, then it clears these guards
*/
m_aFrameStack.push_back(pLow);
m_aFrameDeleteGuards.push_back(std::make_unique<SwFrameDeleteGuard>(pLow));
}
if ( !pPage->GetFormat()->GetDoc().GetFootnoteIdxs().empty() )
{
SwFootnoteContFrame *pCont = pPage->FindFootnoteCont(); if ( pCont )
{
pCnt = pCont->ContainsContent();
pChk = pCnt; while ( pCnt && pCnt->IsFollow() )
pCnt = static_cast<SwContentFrame*>(pCnt->FindPrev()); if ( pCnt && pCnt != pChk )
{ if ( bPageChgd )
{ // Use the 'topmost' page
SwPageFrame *pTmp = pCnt->FindPageFrame(); if ( pPage->GetPhyPageNum() > pTmp->GetPhyPageNum() )
pPage = pTmp;
} else
pPage = pCnt->FindPageFrame();
}
}
} return pPage;
}
// unlock position on start and end of page // layout process. staticvoid unlockPositionOfObjects( SwPageFrame *pPageFrame )
{
assert( pPageFrame );
SwSortedObjs* pObjs = pPageFrame->GetSortedObjs(); if ( pObjs )
{ for (SwAnchoredObject* pObj : *pObjs)
{
pObj->UnlockPosition();
}
}
}
void SwLayAction::InternalAction(OutputDevice* pRenderContext)
{
OSL_ENSURE( m_pRoot->Lower()->IsPageFrame(), ":-( No page below the root.");
m_pRoot->Calc(pRenderContext);
// Figure out the first invalid page or the first one to be formatted, // respectively. A complete-action means the first invalid page. // However, the first page to be formatted might be the one having the // number 1. If we're doing a fake formatting, the number of the first // page is the number of the first visible page.
SwPageFrame *pPage = IsComplete() ? static_cast<SwPageFrame*>(m_pRoot->Lower()) :
m_pImp->GetFirstVisPage(pRenderContext); if ( !pPage )
pPage = static_cast<SwPageFrame*>(m_pRoot->Lower());
// If there's a first-flow-Content in the first visible page that's also a Follow, // we switch the page back to the original master of that Content. if ( !IsComplete() )
pPage = CheckFirstVisPage( pPage );
sal_uInt16 nFirstPageNum = pPage->GetPhyPageNum();
auto lcl_isLayoutLooping = [&]()
{ constbool bAgain = this->IsAgain(); if (bAgain && bNoLoop)
rLayoutAccess.GetLayouter()->EndLoopControl(); return bAgain;
};
int nOuterLoopControlRuns = 0; constint nOuterLoopControlMax = 10000; while ( (pPage && !IsInterrupt()) || m_nCheckPageNum != USHRT_MAX )
{ // Fix infinite loop in sw_ooxmlexport17 unit test // When running the sw_ooxmlexport17 unit test on slower macOS Intel // machines, This loop will never end even after 1M+ loops so set a // maximum number of loops like is done in the nested while loops. if (++nOuterLoopControlRuns > nOuterLoopControlMax)
{
SAL_WARN("sw.layout", "SwLayAction::InternalAction has run too many loops"); if (::std::getenv("TEST_NO_LOOP_CONTROLS"))
{ throw std::exception{}; // => fail test
}
m_bInterrupt = true;
}
// note: this is the only place that consumes and resets m_nCheckPageNum if ((IsInterrupt() || !pPage) && m_nCheckPageNum != USHRT_MAX)
{ if (!pPage || m_nCheckPageNum < pPage->GetPhyPageNum())
{
SwPageFrame *pPg = static_cast<SwPageFrame*>(m_pRoot->Lower()); while (pPg && pPg->GetPhyPageNum() < m_nCheckPageNum)
pPg = static_cast<SwPageFrame*>(pPg->GetNext()); if (pPg)
pPage = pPg; if (!pPage) break;
}
// No Shortcut for Idle or CalcLayout. The shortcut case means that in case the page is not // inside the visible area, then the synchronous (not idle) layout skips the page. constbool bTakeShortcut = !IsIdle() && !IsComplete() && IsShortCut(pPage);
m_pRoot->DeleteEmptySct();
m_pRoot->DeleteEmptyFlys(); if (lcl_isLayoutLooping()) return;
if (!bTakeShortcut)
{ while ( !IsInterrupt() && !IsNextCycle() &&
((pPage->GetSortedObjs() && pPage->IsInvalidFly()) || pPage->IsInvalid()) )
{
unlockPositionOfObjects( pPage );
SwObjectFormatter::FormatObjsAtFrame( *pPage, *pPage, this ); if ( !pPage->GetSortedObjs() )
{ // If there are no (more) Flys, the flags are superfluous.
pPage->ValidateFlyLayout();
pPage->ValidateFlyContent();
} // change condition while ( !IsInterrupt() && !IsNextCycle() &&
( pPage->IsInvalid() ||
(pPage->GetSortedObjs() && pPage->IsInvalidFly()) ) )
{
PROTOCOL( pPage, PROT::FileInit, DbgAction::NONE, nullptr) if (lcl_isLayoutLooping()) return;
// new loop control int nLoopControlRuns_1 = 0; constint nLoopControlMax = 20;
while ( !IsNextCycle() && pPage->IsInvalidLayout() )
{
pPage->ValidateLayout();
if ( ++nLoopControlRuns_1 > nLoopControlMax )
{
SAL_WARN("sw.layout", "LoopControl_1 in SwLayAction::InternalAction"); if (::std::getenv("TEST_NO_LOOP_CONTROLS"))
{ throw std::exception{}; // => fail test
} break;
}
// A previous page may be invalid again. if (lcl_isLayoutLooping()) return; if ( !pPage->GetSortedObjs() )
{ // If there are no (more) Flys, the flags are superfluous.
pPage->ValidateFlyLayout();
pPage->ValidateFlyContent();
} if ( !IsInterrupt() )
{
SetNextCycle( false );
// Continue to the next invalid page while ( pPage && !pPage->IsInvalid() &&
(!pPage->GetSortedObjs() || !pPage->IsInvalidFly()) )
{
pPage = static_cast<SwPageFrame*>(pPage->GetNext());
} if( bNoLoop )
rLayoutAccess.GetLayouter()->LoopControl( pPage );
}
CheckIdleEnd();
}
if ((bTakeShortcut || !pPage) && !IsInterrupt() &&
(m_pRoot->IsSuperfluous() || m_pRoot->IsAssertFlyPages()) )
{ // tdf#139426 allow suppression of AssertFlyPages if ( m_pRoot->IsAssertFlyPages() && !m_pRoot->IsTableUpdateInProgress())
{
m_pRoot->AssertFlyPages();
} if ( m_pRoot->IsSuperfluous() )
{ bool bOld = IsAgain();
m_pRoot->RemoveSuperfluous();
SetAgain(bOld);
} if (lcl_isLayoutLooping()) return;
pPage = static_cast<SwPageFrame*>(m_pRoot->Lower()); while ( pPage && !pPage->IsInvalid() && !pPage->IsInvalidFly() )
pPage = static_cast<SwPageFrame*>(pPage->GetNext()); while ( pPage && pPage->GetNext() &&
pPage->GetPhyPageNum() < nFirstPageNum )
pPage = static_cast<SwPageFrame*>(pPage->GetNext());
} elseif (bTakeShortcut) break;
} if ( IsInterrupt() && pPage )
{ // If we have input, we don't want to format content anymore, but // we still should clean the layout. // Otherwise, the following situation might arise: // The user enters some text at the end of the paragraph of the last // page, causing the paragraph to create a Follow for the next page. // Meanwhile the user continues typing, so we have input while // still formatting. // The paragraph on the new page has already been partially formatted, // and the new page has been fully formatted and is set to CompletePaint, // but hasn't added itself to the area to be output. Then we paint, // the CompletePaint of the page is reset because the new paragraph // already added itself, but the borders of the page haven't been painted // yet. // Oh well, with the inevitable following LayAction, the page doesn't // register itself, because it's (LayoutFrame) flags have been reset // already - the border of the page will never be painted.
SwPageFrame *pPg = pPage; if (lcl_isLayoutLooping()) return; // LOK case: VisArea() is the entire document and getLOKVisibleArea() may contain the actual // visible area. const SwRect &rVisArea = m_pImp->GetShell().VisArea();
SwRect aLokVisArea(m_pImp->GetShell().getLOKVisibleArea()); bool bUseLokVisArea = comphelper::LibreOfficeKit::isActive() && !aLokVisArea.IsEmpty(); const SwRect& rVis = bUseLokVisArea ? aLokVisArea : rVisArea;
// set flag for interrupt content formatting
mbFormatContentOnInterrupt = true;
tools::Long nBottom = rVis.Bottom(); // #i42586# - format current page, if idle action is active // This is an optimization for the case that the interrupt is created by // the move of a form control object, which is represented by a window. while ( pPg && ( pPg->getFrameArea().Top() < nBottom ||
( IsIdle() && pPg == pPage ) ) )
{
unlockPositionOfObjects( pPg );
if (lcl_isLayoutLooping()) return;
// new loop control int nLoopControlRuns_2 = 0; constint nLoopControlMax = 20;
// special case: interrupt content formatting // conditions are incorrect and are too strict. // adjust interrupt formatting to normal page formatting - see above. while ( ( mbFormatContentOnInterrupt &&
( pPg->IsInvalid() ||
( pPg->GetSortedObjs() && pPg->IsInvalidFly() ) ) ) ||
( !mbFormatContentOnInterrupt && pPg->IsInvalidLayout() ) )
{ if (lcl_isLayoutLooping()) return; // format also at-page anchored objects
SwObjectFormatter::FormatObjsAtFrame( *pPg, *pPg, this ); if ( !pPg->GetSortedObjs() )
{
pPg->ValidateFlyLayout();
pPg->ValidateFlyContent();
}
// new loop control int nLoopControlRuns_3 = 0;
while ( pPg->IsInvalidLayout() )
{
pPg->ValidateLayout();
if ( ++nLoopControlRuns_3 > nLoopControlMax )
{
SAL_WARN("sw.layout", "LoopControl_3 in Interrupt formatting in SwLayAction::InternalAction"); if (::std::getenv("TEST_NO_LOOP_CONTROLS"))
{ throw std::exception{}; // => fail test
} break;
}
FormatLayout( pRenderContext, pPg ); if (lcl_isLayoutLooping()) return;
}
if ( ++nLoopControlRuns_2 > nLoopControlMax )
{
SAL_WARN("sw.layout", "LoopControl_2 in Interrupt formatting in SwLayAction::InternalAction"); if (::std::getenv("TEST_NO_LOOP_CONTROLS"))
{ throw std::exception{}; // => fail test
} break;
}
if ( !FormatContent( pPg ) )
{ if (lcl_isLayoutLooping()) return;
pPg->InvalidateContent();
pPg->InvalidateFlyInCnt();
pPg->InvalidateFlyLayout();
pPg->InvalidateFlyContent();
} // we are satisfied if the content is formatted once complete. else
{ break;
}
}
}
unlockPositionOfObjects( pPg );
pPg = static_cast<SwPageFrame*>(pPg->GetNext());
} if (m_pRoot->IsSuperfluous()) // could be newly set now!
{ bool bOld = IsAgain();
m_pRoot->RemoveSuperfluous();
SetAgain(bOld);
} // reset flag for special interrupt content formatting.
mbFormatContentOnInterrupt = false;
}
m_pOptTab = nullptr; if( bNoLoop )
rLayoutAccess.GetLayouter()->EndLoopControl();
}
if ( !pCnt->GetValidLineNumFlag() && pCnt->IsTextFrame() )
{ const sal_Int32 nAllLines = static_cast<const SwTextFrame*>(pCnt)->GetAllLines(); const_cast<SwTextFrame*>(static_cast<const SwTextFrame*>(pCnt))->RecalcAllLines(); if ( nAllLines != static_cast<const SwTextFrame*>(pCnt)->GetAllLines() )
{ if ( IsPaintExtraData() )
m_pImp->GetShell().AddPaintRect( pCnt->getFrameArea() ); // This is to calculate the remaining LineNums on the page, // and we don't stop processing here. To perform this inside RecalcAllLines // would be expensive, because we would have to notify the page even // in unnecessary cases (normal actions). const SwContentFrame *pNxt = pCnt->GetNextContentFrame(); while ( pNxt &&
(pNxt->IsInTab() || pNxt->IsInDocBody() != pCnt->IsInDocBody()) )
pNxt = pNxt->GetNextContentFrame(); if ( pNxt )
pNxt->InvalidatePage();
} returnfalse;
}
if ( pPage->IsInvalidLayout() || (pPage->GetSortedObjs() && pPage->IsInvalidFly()) ) returnfalse;
} if ( !pPage )
pPage = pCnt->FindPageFrame();
// format floating screen objects at content frame. if ( pCnt->IsTextFrame() &&
!SwObjectFormatter::FormatObjsAtFrame( *const_cast<SwContentFrame*>(pCnt),
*pPage, this ) )
{ returnfalse;
}
if ( pPage->IsInvalidContent() ) returnfalse; returntrue;
}
/* Returns True if the page lies directly below or right of the visible area. * * It's possible for things to change in such a way that the processing * (of the caller!) has to continue with the predecessor of the passed page. * The parameter might therefore get modified! * For BrowseMode, you may even activate the ShortCut if the invalid content * of the page lies below the visible area.
*/ bool SwLayAction::IsShortCut( SwPageFrame *&prPage )
{
vcl::RenderContext* pRenderContext = m_pImp->GetShell().GetOut(); bool bRet = false; const SwViewShell *pSh = m_pRoot->GetCurrShell(); constbool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
// If the page is not valid, we quickly format it, otherwise // there's gonna be no end of trouble if ( !prPage->isFrameAreaDefinitionValid() )
{ if ( bBrowse )
{ // format complete page // Thus, loop on all lowers of the page <prPage>, instead of only // format its first lower. // NOTE: In online layout (bBrowse == true) a page can contain // a header frame and/or a footer frame beside the body frame.
prPage->Calc(pRenderContext);
SwFrame* pPageLowerFrame = prPage->Lower(); while ( pPageLowerFrame )
{
pPageLowerFrame->Calc(pRenderContext);
pPageLowerFrame = pPageLowerFrame->GetNext();
}
} else
FormatLayout( pSh ? pSh->GetOut() : nullptr, prPage ); if ( IsAgain() ) returnfalse;
}
// Decide if prPage is visible, i.e. part of the visible area. const SwRect &rVisArea = m_pImp->GetShell().VisArea(); // LOK case: VisArea() is the entire document and getLOKVisibleArea() may contain the actual // visible area.
SwRect aLokVisArea(m_pImp->GetShell().getLOKVisibleArea()); bool bUseLokVisArea = comphelper::LibreOfficeKit::isActive() && !aLokVisArea.IsEmpty(); const SwRect& rVis = bUseLokVisArea ? aLokVisArea : rVisArea;
// This is going to be a bit nasty: The first ContentFrame of this // page in the Body text needs formatting; if it changes the page during // that process, I need to start over a page further back, because we // have been processing a PageBreak. // Even more uncomfortable: The next ContentFrame must be formatted, // because it's possible for empty pages to exist temporarily (for example // a paragraph across multiple pages gets deleted or reduced in size).
// This is irrelevant for the browser, if the last Cnt above it // isn't visible anymore.
if ( bTstCnt )
{ // check after each frame calculation, // if the content frame has changed the page. If yes, no other // frame calculation is performed bool bPageChg = false;
if ( pContent->IsInSct() )
{ const SwSectionFrame *pSct = const_cast<SwFrame*>(static_cast<SwFrame const *>(pContent))->ImplFindSctFrame(); if ( !pSct->isFrameAreaDefinitionValid() )
{
pSct->Calc(pRenderContext);
pSct->SetCompletePaint(); if ( IsAgain() ) returnfalse;
if ( !bNoPaint && IsPaint() && bAddRect && (pLay->IsCompletePaint() || bChanged) )
{
SwRect aPaint( pLay->getFrameArea() ); // consider border and shadow for // page frames -> enlarge paint rectangle correspondingly. if ( pLay->IsPageFrame() )
{
SwPageFrame* pPageFrame = static_cast<SwPageFrame*>(pLay);
aPaint = pPageFrame->GetBoundRect(pRenderContext);
} elseif (pLay->IsRowFrame())
{ // tdf#167419 Changing the borders of a table doesn't refresh // the bottom border. That border is outside the FrameArea // of the table when the default CollapsingBorders is enabled. // Add it in here for the last row when determining the area // to refresh. const SwRowFrame* pRowFrame = static_cast<SwRowFrame*>(pLay); constbool bLastRow = !pRowFrame->GetNext(); const SwTwips nBorderThicknessUnderArea = bLastRow ? pRowFrame->GetBottomLineSize() : 0; if (nBorderThicknessUnderArea)
{ const SwTabFrame* pTabFrame = pRowFrame->FindTabFrame(); if (pTabFrame && pTabFrame->IsCollapsingBorders())
aPaint.AddBottom(nBorderThicknessUnderArea);
}
}
// Now, deal with the lowers that are LayoutFrames
if ( pLay->IsFootnoteFrame() ) // no LayFrames as Lower return bChanged;
SwFrame *pLow = pLay->Lower(); bool bTabChanged = false; while ( pLow && pLow->GetUpper() == pLay )
{
SwFrame* pNext = nullptr; if ( pLow->IsLayoutFrame() )
{ if ( pLow->IsTabFrame() )
{ // Remember what was the next of the lower. Formatting may move it to the previous // page, in which case it looses its next.
pNext = pLow->GetNext();
if (pNext && pNext->IsTabFrame())
{ auto pTab = static_cast<SwTabFrame*>(pNext); if (pTab->IsFollow())
{ // The next frame is a follow of the previous frame, SwTabFrame::Join() will // delete this one as part of formatting, so forget about it.
pNext = nullptr;
}
}
bTabChanged |= FormatLayoutTab( static_cast<SwTabFrame*>(pLow), bAddRect );
} // Skip the ones already registered for deletion elseif( !pLow->IsSctFrame() || static_cast<SwSectionFrame*>(pLow)->GetSection() )
{
PushFormatLayout(pLow);
bChanged |= FormatLayout( pRenderContext, static_cast<SwLayoutFrame*>(pLow), bAddRect );
PopFormatLayout();
}
} elseif (pLay->IsSctFrame() && pLay->GetNext() && pLay->GetNext()->IsSctFrame() && pLow->IsTextFrame() && pLow == pLay->GetLastLower())
{ // else: only calc the last text lower of sections, followed by sections
pLow->OptCalc();
}
if ( IsAgain() ) returnfalse; if (!pNext)
{
pNext = pLow->GetNext();
}
pLow = pNext;
} // add complete frame area as paint area, if frame // area has been already added and after formatting its lowers the frame area // is enlarged.
SwRect aBoundRect(pLay->IsPageFrame() ? static_cast<SwPageFrame*>(pLay)->GetBoundRect(pRenderContext) : pLay->getFrameArea() );
if ( pTab->IsCompletePaint() && !m_pOptTab )
m_pOptTab = pTab;
pTab->ResetCompletePaint();
} if ( IsPaint() && bAddRect && pTab->IsRetouche() && !pTab->GetNext() )
{ // set correct rectangle for retouche: area between bottom of table frame // and bottom of paint area of the upper frame.
SwRect aRect( pTab->GetUpper()->GetPaintArea() ); // vertical layout support
aRectFnSet.SetTop( aRect, aRectFnSet.GetPrtBottom(*pTab) ); if ( !m_pImp->GetShell().AddPaintRect( aRect ) )
pTab->ResetRetouche();
}
// Now, deal with the lowers if ( IsAgain() ) returnfalse;
// for safety reasons: // check page number before formatting lowers. if ( pOldPage->GetPhyPageNum() > (pTab->FindPageFrame()->GetPhyPageNum() + 1) )
SetNextCycle( true );
// format lowers, only if table frame is valid if ( pTab->isFrameAreaDefinitionValid() )
{ // tdf#128437 FlowFrameJoinLockGuard on pTab caused a problem here
SwLayoutFrame *pLow = static_cast<SwLayoutFrame*>(pTab->Lower()); while ( pLow )
{
SwFrameDeleteGuard rowG(pLow); // tdf#124675 prevent RemoveFollowFlowLine()
bChanged |= FormatLayout( m_pImp->GetShell().GetOut(), pLow, bAddRect ); if ( IsAgain() ) returnfalse;
pLow = static_cast<SwLayoutFrame*>(pLow->GetNext());
}
}
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.