/* -*- 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 .
*/
namespace { // FIXME: would likely better be a member of SwRootFrame instead of a global flag bool isFlyCreationSuppressed = false;
} namespace sw {
FlyCreationSuppressor::FlyCreationSuppressor(bool wasAlreadySuppressedAllowed)
: m_wasAlreadySuppressed(isFlyCreationSuppressed)
{
(void)wasAlreadySuppressedAllowed;
assert(wasAlreadySuppressedAllowed || !isFlyCreationSuppressed);
isFlyCreationSuppressed = true;
}
FlyCreationSuppressor::~FlyCreationSuppressor()
{
isFlyCreationSuppressed = m_wasAlreadySuppressed;
}
}
if ( !pFlow->IsFollow() )
{ if ( !mpFrame->GetIndPrev() )
{ if ( mbInvaKeep )
{
SwFrame *pPre = pFlow->FindPrevIgnoreHidden(); if ( pPre && pPre->IsFlowFrame() )
{ // 1. pPre wants to keep with me: bool bInvalidPrePos = SwFlowFrame::CastFlowFrame(pPre)->IsKeep(pPre->GetAttrSet()->GetKeep(), pPre->GetBreakItem())
&& pPre->GetIndPrev();
// 2. pPre is a table and the last row wants to keep with me: if ( !bInvalidPrePos && pPre->IsTabFrame() )
{
SwTabFrame* pPreTab = static_cast<SwTabFrame*>(pPre); if ( pPreTab->GetFormat()->GetDoc().GetDocumentSettingManager().get(DocumentSettingId::TABLE_ROW_KEEP) )
{
SwRowFrame* pLastRow = static_cast<SwRowFrame*>(pPreTab->GetLastLower()); if ( pLastRow && pLastRow->ShouldRowKeepWithNext() )
bInvalidPrePos = true;
}
}
if ( pNxt )
{
pNxt->InvalidatePos(); if (pNxt->IsTextFrame() && static_cast<SwTextFrame*>(pNxt)->IsUndersized())
{ // tdf#137523 it could have more space at new pos
pNxt->InvalidateSize();
pNxt->Prepare(PrepareHint::AdjustSizeWithoutFormatting);
}
} else
{ // #104100# - correct condition for setting retouche // flag for vertical layout. if( mpFrame->IsRetoucheFrame() &&
aRectFnSet.TopDist( maFrame, aRectFnSet.GetTop(mpFrame->getFrameArea()) ) > 0 )
{
mpFrame->SetRetouche();
}
// A fresh follow frame does not have to be invalidated, because // it is already formatted: if ( mbHadFollow || !mpFrame->IsContentFrame() || !static_cast<SwContentFrame*>(mpFrame)->GetFollow() )
{ if ( !mpFrame->IsTabFrame() || !static_cast<SwTabFrame*>(mpFrame)->GetFollow() )
mpFrame->InvalidateNextPos();
}
}
}
//For each resize of the background graphics is a repaint necessary. constbool bPrtWidth =
aRectFnSet.GetWidth(maPrt) != aRectFnSet.GetWidth(mpFrame->getFramePrintArea()); constbool bPrtHeight =
aRectFnSet.GetHeight(maPrt)!=aRectFnSet.GetHeight(mpFrame->getFramePrintArea()); if ( bPrtWidth || bPrtHeight )
{ bool bUseNewFillProperties(false); if (mpFrame->supportsFullDrawingLayerFillAttributeSet())
{
drawinglayer::attribute::SdrAllFillAttributesHelperPtr aFillAttributes(mpFrame->getSdrAllFillAttributesHelper()); if(aFillAttributes && aFillAttributes->isUsed())
{
bUseNewFillProperties = true; // use SetCompletePaint if needed if(aFillAttributes->needCompleteRepaint())
{
mpFrame->SetCompletePaint();
}
}
} if (!bUseNewFillProperties)
{ const SvxGraphicPosition ePos = mpFrame->GetAttrSet()->GetBackground().GetGraphicPos(); if(GPOS_NONE != ePos && GPOS_TILED != ePos)
mpFrame->SetCompletePaint();
}
} else
{ // #97597# - consider case that *only* margins between // frame and printing area has changed. Then, frame has to be repainted, // in order to force paint of the margin areas. if ( !bAbsP && (bChgWidth || bChgHeight) )
{
mpFrame->SetCompletePaint();
}
}
// Notification of anchored objects if ( mpFrame->GetDrawObjs() )
{ const SwSortedObjs &rObjs = *mpFrame->GetDrawObjs();
SwPageFrame* pPageFrame = nullptr; for (SwAnchoredObject* pObj : rObjs)
{ // OD 2004-03-31 #i26791# - no general distinction between // Writer fly frames and drawing objects bool bNotify = false; bool bNotifySize = false;
SwContact* pContact = ::GetUserCall( pObj->GetDrawObj() ); if (!pContact) continue; constbool bAnchoredAsChar = pContact->ObjAnchoredAsChar(); if ( !bAnchoredAsChar )
{ // Notify object, which aren't anchored as-character:
// always notify objects, if frame position has changed // or if the object is to-page|to-fly anchored. if ( bAbsP ||
pContact->ObjAnchoredAtPage() ||
pContact->ObjAnchoredAtFly() )
{
bNotify = true;
// assure that to-fly anchored Writer fly frames are // registered at the correct page frame, if frame // position has changed. if ( bAbsP && pContact->ObjAnchoredAtFly() &&
pObj->DynCastFlyFrame() != nullptr )
{ // determine to-fly anchored Writer fly frame
SwFlyFrame* pFlyFrame = static_cast<SwFlyFrame*>(pObj); // determine page frame of to-fly anchored // Writer fly frame
SwPageFrame* pFlyPageFrame = pFlyFrame->FindPageFrame(); // determine page frame, if needed. if ( !pPageFrame )
{
pPageFrame = mpFrame->FindPageFrame();
} if ( pPageFrame != pFlyPageFrame )
{
OSL_ENSURE( pFlyPageFrame, "~SwFrameNotify: Fly from Nowhere" ); if( pFlyPageFrame )
pFlyPageFrame->MoveFly( pFlyFrame, pPageFrame ); else
pPageFrame->AppendFlyToPage( pFlyFrame );
}
}
} // otherwise the objects are notified in dependence to // its positioning and alignment else
{ const SwFormatVertOrient& rVert =
pContact->GetFormat()->GetVertOrient(); if ( ( rVert.GetVertOrient() == text::VertOrientation::CENTER ||
rVert.GetVertOrient() == text::VertOrientation::BOTTOM ||
rVert.GetRelationOrient() == text::RelOrientation::PRINT_AREA ) &&
( bChgHeight || bPrtHeight ) )
{
bNotify = true;
} if ( !bNotify )
{ const SwFormatHoriOrient& rHori =
pContact->GetFormat()->GetHoriOrient(); if ( ( rHori.GetHoriOrient() != text::HoriOrientation::NONE ||
rHori.GetRelationOrient()== text::RelOrientation::PRINT_AREA ||
rHori.GetRelationOrient()== text::RelOrientation::FRAME ) &&
( bChgWidth || bPrtWidth || bChgFlyBasePos ) )
{
bNotify = true;
}
}
}
} elseif ( bPrtWidth )
{ // Notify as-character anchored objects, if printing area // width has changed.
bNotify = true;
bNotifySize = true;
}
// perform notification via the corresponding invalidations if ( bNotify )
{ if ( auto pFlyFrame = pObj->DynCastFlyFrame() )
{ if ( bNotifySize )
pFlyFrame->InvalidateSize_(); // #115759# - no invalidation of // position for as-character anchored objects. if ( !bAnchoredAsChar )
{
pFlyFrame->InvalidatePos_();
}
pFlyFrame->Invalidate_();
} elseif ( dynamic_cast<const SwAnchoredDrawObject*>( pObj) != nullptr )
{ // #115759# - no invalidation of // position for as-character anchored objects. if ( !bAnchoredAsChar )
{
pObj->InvalidateObjPos();
}
} else
{
OSL_FAIL( " - unknown anchored object type." );
}
}
}
}
} #if !ENABLE_WASM_STRIP_ACCESSIBILITY elseif( mpFrame->IsTextFrame() && mbValidSize != mpFrame->isFrameAreaSizeValid() )
{
SwRootFrame *pRootFrame = mpFrame->getRootFrame(); if( pRootFrame && pRootFrame->IsAnyShellAccessible() &&
pRootFrame->GetCurrShell() )
{
pRootFrame->GetCurrShell()->Imp()->InvalidateAccessibleFrameContent( mpFrame );
}
} #endif
// #i9046# Automatic frame width
SwFlyFrame* pFly = nullptr; // #i35879# Do not trust the inf flags. pFrame does not // necessarily have to have an upper! if ( mpFrame->IsFlyFrame() || nullptr == ( pFly = mpFrame->ImplFindFlyFrame() )) return;
// #i61999# // no invalidation of columned Writer fly frames, because automatic // width doesn't make sense for such Writer fly frames.
SwFrame* pLower = pFly->Lower(); if ( !pLower || pLower->IsColumnFrame() ) return;
// This could be optimized. Basically the fly frame only has to // be invalidated, if the first line of pFrame (if pFrame is a content // frame, for other frame types it's the print area) has changed its // size and pFrame was responsible for the current width of pFly. On // the other hand, this is only rarely used and re-calculation of // the fly frame does not cause too much trouble. So we keep it this // way: if ( SwFrameSize::Fixed != rFrameSz.GetWidthSizeType() )
{ // #i50668#, #i50998# - invalidation of position // of as-character anchored fly frames not needed and can cause // layout loops if ( dynamic_cast<const SwFlyInContentFrame*>( pFly) == nullptr )
{
pFly->InvalidatePos();
}
pFly->InvalidateSize();
}
}
// OD 2004-05-11 #i28701# - local method to invalidate the position of all // frames inclusive its floating screen objects, which are lowers of the given // layout frame staticvoid lcl_InvalidatePosOfLowers( SwLayoutFrame& _rLayoutFrame )
{ if( _rLayoutFrame.IsFlyFrame() && _rLayoutFrame.GetDrawObjs() )
{
_rLayoutFrame.InvalidateObjs( false );
}
if ( pLay->IsRowFrame() )
{
bInvaPercent = true;
tools::Long nNew = aRectFnSet.GetHeight(pLay->getFramePrintArea()); if( nNew != aRectFnSet.GetHeight(maPrt) ) static_cast<SwRowFrame*>(pLay)->AdjustCells( nNew, true); if( aRectFnSet.GetWidth(pLay->getFramePrintArea())
!= aRectFnSet.GetWidth(maPrt) ) static_cast<SwRowFrame*>(pLay)->AdjustCells( 0, false );
} else
{ //Proportional adoption of the internal. //1. If the formatted is no Fly //2. If he contains no columns //3. If the Fly has a fixed height and the columns // are next to be. // Hoehe danebenliegen. //4. Never at SectionFrames. bool bLow; if( pLay->IsFlyFrame() )
{ if ( pLay->Lower() )
{
bLow = !pLay->Lower()->IsColumnFrame() ||
aRectFnSet.GetHeight(pLay->Lower()->getFrameArea())
!= aRectFnSet.GetHeight(pLay->getFramePrintArea());
} else
bLow = false;
} elseif( pLay->IsSctFrame() )
{ if ( pLay->Lower() )
{ if( pLay->Lower()->IsColumnFrame() && pLay->Lower()->GetNext() )
bLow = pLay->Lower()->getFrameArea().Height() != pLay->getFramePrintArea().Height(); else
bLow = pLay->getFramePrintArea().Width() != maPrt.Width();
} else
bLow = false;
} elseif( pLay->IsFooterFrame() && !pLay->HasFixSize() )
bLow = pLay->getFramePrintArea().Width() != maPrt.Width(); else
bLow = true;
bInvaPercent = bLow; if ( bLow )
{
pLay->ChgLowersProp( maPrt.SSize() );
} // If the PrtArea has been extended, it might be possible that the chain of parts // can take another frame. As a result, the "possible right one" needs to be // invalidated. This only pays off if this or its Uppers are moveable sections. // A PrtArea has been extended if width or height are larger than before. if ( (pLay->getFramePrintArea().Height() > maPrt.Height() ||
pLay->getFramePrintArea().Width() > maPrt.Width()) &&
(pLay->IsMoveable() || pLay->IsFlyFrame()) )
{
SwFrame *pTmpFrame = pLay->Lower(); if ( pTmpFrame && pTmpFrame->IsFlowFrame() )
{ while ( pTmpFrame->GetNext() )
pTmpFrame = pTmpFrame->GetNext();
pTmpFrame->InvalidateNextPos();
}
}
}
bNotify = true; //EXPENSIVE!! But how we do it more elegant? if( bInvaPercent )
pLay->InvaPercentLowers( pLay->getFramePrintArea().Height() - maPrt.Height() );
} if ( pLay->IsTabFrame() ) //So that _only_ the shadow is drawn while resizing. static_cast<SwTabFrame*>(pLay)->SetComplete(); else
{ const SwViewShell *pSh = pLay->getRootFrame()->GetCurrShell(); if( !( pSh && pSh->GetViewOptions()->getBrowseMode() ) ||
!(pLay->GetType() & (SwFrameType::Body | SwFrameType::Page)) ) //Thereby the subordinates are retouched clean. //Example problem: Take the Flys with the handles and downsize. //Not for body and page, otherwise it flickers when loading HTML.
pLay->SetCompletePaint();
}
} //Notify Lower if the position has changed. constbool bPrtPos = aRectFnSet.PosDiff( maPrt, pLay->getFramePrintArea() ); constbool bPos = bPrtPos || aRectFnSet.PosDiff( maFrame, pLay->getFrameArea() ); constbool bSize = pLay->getFrameArea().SSize() != maFrame.SSize();
//Inform the Follower if the SSize has changed. if ( bSize )
{ if( pLay->GetNext() )
{ if ( pLay->GetNext()->IsLayoutFrame() )
pLay->GetNext()->InvalidatePos_(); else
pLay->GetNext()->InvalidatePos();
} elseif( pLay->IsSctFrame() )
pLay->InvalidateNextPos();
}
SwFrame* pLower = pLay->Lower(); if ( !IsLowersComplete() &&
!(pLay->GetType()&(SwFrameType::Fly|SwFrameType::Section) &&
pLower && pLower->IsColumnFrame()) &&
(bPos || bNotify) &&
!(pLay->GetType() & (SwFrameType::Row|SwFrameType::Tab|SwFrameType::FootnoteContainer|SwFrameType::Page|SwFrameType::Root)))
{ // #i44016# - force unlock of position of lower objects. // #i43913# - no unlock of position of objects, // if <pLay> is a cell frame, and its table frame resp. its parent table // frame is locked. // #i47458# - force unlock of position of lower objects, // only if position of layout frame has changed. bool bUnlockPosOfObjs( bPos ); if ( bUnlockPosOfObjs && pLay->IsCellFrame() )
{
SwTabFrame* pTabFrame( pLay->FindTabFrame() ); if ( pTabFrame &&
( pTabFrame->IsJoinLocked() ||
( pTabFrame->IsFollow() &&
pTabFrame->FindMaster()->IsJoinLocked() ) ) )
{
bUnlockPosOfObjs = false;
}
} // #i49383# - check for footnote frame, if unlock // of position of lower objects is allowed. elseif ( bUnlockPosOfObjs && pLay->IsFootnoteFrame() )
{
bUnlockPosOfObjs = static_cast<SwFootnoteFrame*>(pLay)->IsUnlockPosOfLowerObjs();
} // #i51303# - no unlock of object positions for sections elseif ( bUnlockPosOfObjs && pLay->IsSctFrame() )
{
bUnlockPosOfObjs = false;
}
pLay->NotifyLowerObjs( bUnlockPosOfObjs );
} if ( bPos && pLay->IsFootnoteFrame() && pLay->Lower() )
{ // OD 2004-05-11 #i28701#
::lcl_InvalidatePosOfLowers( *pLay );
} if( ( bPos || bSize ) && pLay->IsFlyFrame() && static_cast<SwFlyFrame*>(pLay)->GetAnchorFrame()
&& static_cast<SwFlyFrame*>(pLay)->GetAnchorFrame()->IsFlyFrame() ) static_cast<SwFlyFrame*>(pLay)->AnchorFrame()->InvalidateSize();
}
SwFlyNotify::SwFlyNotify( SwFlyFrame *pFlyFrame ) :
SwLayNotify( pFlyFrame ), // #115759# - keep correct page frame - the page frame // the Writer fly frame is currently registered at.
m_pOldPage( pFlyFrame->GetPageFrame() ),
m_aFrameAndSpace( pFlyFrame->GetObjRectWithSpaces() )
{
}
void SwFlyNotify::ImplDestroy()
{
SwFlyFrame *pFly = static_cast<SwFlyFrame*>(mpFrame); if ( pFly->IsNotifyBack() )
{
SwViewShell *pSh = pFly->getRootFrame()->GetCurrShell();
SwViewShellImp *pImp = pSh ? pSh->Imp() : nullptr; if ( !pImp || !pImp->IsAction() || !pImp->GetLayAction().IsAgain() )
{ //If in the LayAction the IsAgain is set it can be //that the old page is destroyed in the meantime!
::Notify( pFly, m_pOldPage, m_aFrameAndSpace, &maPrt ); // #i35640# - additional notify anchor text frame, // if Writer fly frame has changed its page if ( pFly->GetAnchorFrame()->IsTextFrame() &&
pFly->GetPageFrame() != m_pOldPage )
{
pFly->AnchorFrame()->Prepare( PrepareHint::FlyFrameLeave );
}
}
pFly->ResetNotifyBack();
} if (pFly->IsForceNotifyNewBackground())
{
pFly->NotifyBackground(pFly->FindPageFrame(), pFly->GetObjRectWithSpaces(), PrepareHint::FlyFrameArrive);
pFly->SetForceNotifyNewBackground(false);
}
//Have the size or the position changed, //so should the view know this.
SwRectFnSet aRectFnSet(pFly); constbool bPosChgd = aRectFnSet.PosDiff( maFrame, pFly->getFrameArea() ); constbool bFrameChgd = pFly->getFrameArea().SSize() != maFrame.SSize(); constbool bPrtChgd = maPrt != pFly->getFramePrintArea(); if ( bPosChgd || bFrameChgd || bPrtChgd )
{
pFly->NotifyDrawObj();
} if ( bPosChgd && maFrame.Pos().X() != FAR_AWAY )
{ // OD 2004-05-10 #i28701# - no direct move of lower Writer fly frames. // reason: New positioning and alignment (e.g. to-paragraph anchored, // but aligned at page) are introduced. // <SwLayNotify::~SwLayNotify()> takes care of invalidation of lower // floating screen objects by calling method <SwLayoutFrame::NotifyLowerObjs()>.
if ( pFly->IsFlyAtContentFrame() )
{
SwFrame *pNxt = pFly->AnchorFrame()->FindNext(); while (pNxt)
{
pNxt->InvalidatePos(); if (!pNxt->IsSctFrame())
{ break;
} // invalidating pos of a section frame doesn't have much // effect, so try again with its lower
pNxt = static_cast<SwSectionFrame*>(pNxt)->Lower();
}
}
// OD 2004-05-13 #i28701# // #i45180# - no adjustment of layout process flags and // further notifications/invalidations, if format is called by grow/shrink if ( !pFly->ConsiderObjWrapInfluenceOnObjPos() ) return; if (pFly->IsFlyFreeFrame())
{ if (static_cast<SwFlyFreeFrame*>(pFly)->IsNoMoveOnCheckClip()) return;
}
// #i54138# - suppress restart of the layout process // on changed frame height. // Note: It doesn't seem to be necessary and can cause layout loops. if ( bPosChgd )
{ // indicate a restart of the layout process
pFly->SetRestartLayoutProcess( true );
} else
{ // lock position
pFly->LockPosition();
}
if ( pFly->ConsiderForTextWrap() ) return;
// indicate that object has to be considered for text wrap
pFly->SetConsiderForTextWrap( true ); // invalidate 'background' in order to allow its 'background' // to wrap around it.
pFly->NotifyBackground( pFly->GetPageFrame(),
pFly->GetObjRectWithSpaces(),
PrepareHint::FlyFrameArrive ); // invalidate position of anchor frame in order to force // a re-format of the anchor frame, which also causes a // re-format of the invalid previous frames of the anchor frame.
pFly->AnchorFrame()->InvalidatePos();
}
// OD 2004-02-26 #i25029# if ( mbInvalidatePrevPrtArea && mbBordersJoinedWithPrev &&
pCnt->IsTextFrame() &&
!pCnt->IsFollow() && !pCnt->GetIndPrev() )
{ // determine previous frame
SwFrame* pPrevFrame = pCnt->FindPrev(); // skip empty section frames and hidden text frames
{ while (pPrevFrame && pPrevFrame->IsHiddenNow())
{
pPrevFrame = pPrevFrame->FindPrev();
}
}
// Invalidate printing area of found previous frame if ( pPrevFrame )
{ if ( pPrevFrame->IsSctFrame() )
{ if ( pCnt->IsInSct() )
{ // Note: found previous frame is a section frame and // <pCnt> is also inside a section. // Thus due to <mbBordersJoinedWithPrev>, // <pCnt> had joined its borders/shadow with the // last content of the found section. // Invalidate printing area of last content in found section.
SwFrame* pLstContentOfSctFrame = static_cast<SwSectionFrame*>(pPrevFrame)->FindLastContent(); if ( pLstContentOfSctFrame )
{
pLstContentOfSctFrame->InvalidatePrt();
}
}
} else
{
pPrevFrame->InvalidatePrt();
}
}
}
if ( pCnt->IsNoTextFrame() )
{ //Active PlugIn's or OLE-Objects should know something of the change //thereby they move their window appropriate.
SwViewShell *pSh = pCnt->getRootFrame()->GetCurrShell(); if ( pSh )
{
SwOLENode *const pNd(static_cast<SwNoTextFrame*>(pCnt)->GetNode()->GetOLENode()); if (nullptr != pNd &&
(pNd->GetOLEObj().IsOleRef() ||
pNd->IsOLESizeInvalid()) )
{ constbool bNoTextFramePrtAreaChanged =
( maPrt.SSize().Width() != 0 &&
maPrt.SSize().Height() != 0 ) &&
maPrt.SSize() != pCnt->getFramePrintArea().SSize();
OSL_ENSURE( pCnt->IsInFly(), "OLE not in FlyFrame" );
SwFlyFrame *pFly = pCnt->FindFlyFrame();
svt::EmbeddedObjectRef& xObj = pNd->GetOLEObj().GetObject();
SwFEShell *pFESh = nullptr; for(SwViewShell& rCurrentShell : pSh->GetRingContainer())
{ if ( dynamic_cast<const SwCursorShell*>( &rCurrentShell) != nullptr )
{
pFESh = static_cast<SwFEShell*>(&rCurrentShell); // #108369#: Here used to be the condition if (!bFirst). // I think this should mean "do not call CalcAndSetScale" // if the frame is formatted for the first time. // Unfortunately this is not valid anymore since the // SwNoTextFrame already gets a width during CalcLowerPreps. // Nevertheless, the indention of !bFirst seemed to be // to assure that the OLE objects have already been notified // if necessary before calling CalcAndSetScale. // So I replaced !bFirst by !IsOLESizeInvalid. There is // one additional problem specific to the word import: // The layout is calculated _before_ calling PrtOLENotify, // and the OLE objects are not invalidated during import. // Therefore I added the condition !IsUpdateExpField, // have a look at the occurrence of CalcLayout in // uiview/view.cxx. if ( !pNd->IsOLESizeInvalid() &&
!pSh->GetDoc()->getIDocumentState().IsUpdateExpField() )
pFESh->CalcAndSetScale( xObj,
&pFly->getFramePrintArea(), &pFly->getFrameArea(),
bNoTextFramePrtAreaChanged );
}
}
SwDoc& rDoc = pCnt->IsTextFrame()
? static_cast<SwTextFrame*>(pCnt)->GetDoc()
: static_cast<SwNoTextFrame*>(pCnt)->GetNode()->GetDoc(); if ( !rDoc.GetSpzFrameFormats()->empty() &&
rDoc.DoesContainAtPageObjWithContentAnchor() && !rDoc.getIDocumentState().IsNewDoc() )
{ // If certain import filters for foreign file format import // AT_PAGE anchored objects, the corresponding page number is // typically not known. In this case the content position is // stored at which the anchored object is found in the // imported document. // When this content is formatted it is the time at which // the page is known. Thus, this data can be corrected now.
if (FrameContainsNode(*pCnt, rAnch.GetAnchorNode()->GetIndex()))
{
OSL_FAIL( " - to page anchored object with content position." ); if ( !pPage )
{
pPage = pCnt->FindPageFrame();
}
SwFormatAnchor aAnch( rAnch );
aAnch.SetAnchor( nullptr );
aAnch.SetPageNum( pPage->GetPhyPageNum() );
pFormat->SetFormatAttr( aAnch ); if ( RES_DRAWFRMFMT != pFormat->Which() )
{
pFormat->MakeFrames();
}
}
}
}
}
// OD 12.01.2004 #i11859# - invalidate printing area of following frame, // if height of last line has changed. if ( pCnt->IsTextFrame() && mbChkHeightOfLastLine )
{ if ( mnHeightOfLastLine != static_cast<SwTextFrame*>(pCnt)->GetHeightOfLastLine() )
{
pCnt->InvalidateNextPrtArea();
}
}
// #i43255# - move code to invalidate at-character // anchored objects due to a change of its anchor character from // method <SwTextFrame::Format(..)>. if ( !pCnt->IsTextFrame() ) return;
staticbool IsShown(SwNodeOffset const nIndex, const SwFormatAnchor & rAnch,
std::vector<sw::Extent>::const_iterator const*const pIter,
std::vector<sw::Extent>::const_iterator const*const pEnd,
SwTextNode const*const pFirstNode, SwTextNode const*const pLastNode)
{
assert(!pIter || *pIter == *pEnd || (*pIter)->pNode->GetIndex() == nIndex);
SwNode* pAnchorNode = rAnch.GetAnchorNode(); if (pAnchorNode->GetIndex() != nIndex)
{ returnfalse;
} if (rAnch.GetAnchorId() == RndStdIds::FLY_AT_PARA)
{ return pIter == nullptr // not merged
|| pIter != pEnd // at least one char visible in node
|| !IsSelectFrameAnchoredAtPara(*rAnch.GetContentAnchor(),
SwPosition(*pFirstNode, 0),
SwPosition(*pLastNode, pLastNode->Len()));
} if (pIter)
{ // note: frames are not sorted by anchor position.
assert(pEnd);
assert(pFirstNode);
assert(pLastNode);
assert(rAnch.GetAnchorId() != RndStdIds::FLY_AT_FLY); if (*pIter == *pEnd && rAnch.GetAnchorId() == RndStdIds::FLY_AT_CHAR)
{ // tdf#149595 special case - it *could* be shown if first == last return !IsDestroyFrameAnchoredAtChar(*rAnch.GetContentAnchor(),
SwPosition(*pFirstNode, 0),
SwPosition(*pLastNode, pLastNode->Len()));
} for (auto iter = *pIter; iter != *pEnd; ++iter)
{
assert(iter->nStart != iter->nEnd); // TODO possible?
assert(iter->pNode->GetIndex() == nIndex); if (rAnch.GetAnchorContentOffset() < iter->nStart)
{ returnfalse;
} if (rAnch.GetAnchorId() == RndStdIds::FLY_AT_CHAR)
{ // if there is an extent then obviously the node was not // deleted fully... // show if start <= pos <= end // *or* if first-node/0 *and* not StartOfSection // *or* if last-node/Len *and* not EndOfSection
// first determine the extent to compare to, then // construct start/end positions for the deletion *before* the // extent and compare once. // the interesting corner cases are on the edge of the extent! // no need to check for > the last extent because those // are never visible. if (rAnch.GetAnchorContentOffset() <= iter->nEnd)
{ if (iter->nStart == 0)
{ returntrue;
} else
{
SwPosition const start(
iter == *pIter
? *pFirstNode // simplification
: *iter->pNode,
iter == *pIter // first extent?
? iter->pNode == pFirstNode
? 0 // at start of 1st node
: pFirstNode->Len() // previous node; simplification but should get right result
: (iter-1)->nEnd); // previous extent
SwPosition const end(*iter->pNode, iter->nStart); return !IsDestroyFrameAnchoredAtChar(*rAnch.GetContentAnchor(), start, end);
}
} elseif (iter == *pEnd - 1) // special case: after last extent
{ if (iter->nEnd == iter->pNode->Len())
{ returntrue; // special case: end of node
} else
{
SwPosition const start(*iter->pNode, iter->nEnd);
SwPosition const end(
*pLastNode, // simplification
iter->pNode == pLastNode
? iter->pNode->Len()
: 0); return !IsDestroyFrameAnchoredAtChar(*rAnch.GetContentAnchor(), start, end);
}
}
} else
{
assert(rAnch.GetAnchorId() == RndStdIds::FLY_AS_CHAR); // for AS_CHAR obviously must be < if (rAnch.GetAnchorContentOffset() < iter->nEnd)
{ returntrue;
}
}
} returnfalse;
} else
{ returntrue;
}
}
void AppendAllObjs(const sw::FrameFormats<sw::SpzFrameFormat*>* pTable, const SwFrame* pSib)
{ //Connecting of all Objects, which are described in the SpzTable with the //layout.
boost::circular_buffer<SwFrameFormat*> vFormatsToConnect(pTable->size()); for(constauto& pFormat : *pTable)
{ constauto& rAnch = pFormat->GetAnchor(); // Formats can still remain, because we neither use character bound // frames nor objects which are anchored to character bounds. if ((rAnch.GetAnchorId() != RndStdIds::FLY_AT_PAGE) && (rAnch.GetAnchorId() != RndStdIds::FLY_AS_CHAR))
{ const SwNode* pAnchorNode = rAnch.GetAnchorNode(); // formats in header/footer have no dependencies if(pAnchorNode && pFormat->GetDoc().IsInHeaderFooter(*pAnchorNode))
pFormat->MakeFrames(); else
vFormatsToConnect.push_back(pFormat);
}
} const SwRootFrame* pRoot = pSib ? pSib->getRootFrame() : nullptr; const SwFrameFormat* pFirstRequeued(nullptr); while(!vFormatsToConnect.empty())
{
SwFrameFormat* pFormat = vFormatsToConnect.front(); bool isConnected(false);
pFormat->CallSwClientNotify(sw::GetObjectConnectedHint(isConnected, pRoot)); if(!isConnected)
{
pFormat->MakeFrames();
pFormat->CallSwClientNotify(sw::GetObjectConnectedHint(isConnected, pRoot));
} // do this *before* push_back! the circular_buffer can be "full"!
vFormatsToConnect.pop_front(); if (!isConnected)
{ if(pFirstRequeued == pFormat) // If nothing happens anymore we can stop. break; if(!pFirstRequeued)
pFirstRequeued = pFormat;
assert(!vFormatsToConnect.full());
vFormatsToConnect.push_back(pFormat);
} else
{
pFirstRequeued = nullptr;
}
}
}
namespace sw {
void RecreateStartTextFrames(SwTextNode & rNode)
{
std::vector<SwTextFrame*> frames;
SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(rNode); for (SwTextFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next())
{ if (pFrame->getRootFrame()->HasMergedParas())
{
frames.push_back(pFrame);
}
} auto eMode(sw::FrameMode::Existing); for (SwTextFrame * pFrame : frames)
{ // SplitNode could have moved the original frame to the start node // & created a new one on end, or could have created new frame on // start node... grab start node's frame and recreate MergedPara.
SwTextNode & rFirstNode(pFrame->GetMergedPara()
? *pFrame->GetMergedPara()->pFirstNode
: rNode);
assert(rFirstNode.GetIndex() <= rNode.GetIndex()); // clear old one first to avoid DelFrames confusing updates & asserts...
pFrame->SetMergedPara(nullptr);
pFrame->SetMergedPara(sw::CheckParaRedlineMerge(
*pFrame, rFirstNode, eMode));
eMode = sw::FrameMode::New; // Existing is not idempotent! // note: this may or may not delete frames on the end node
}
}
} // namespace sw
/** local method to set 'working' position for newly inserted frames
// move position by one SwTwip in text flow direction in order to get // notifications for a new calculated position after its formatting. if ( aRectFnSet.IsVert() )
{
aFrm.Pos().AdjustX( -1 );
} else
{
aFrm.Pos().AdjustY(1 );
}
}
//In the generation of the Layout bPages=true will be handed over. //Then will be new pages generated all x paragraphs already times in advance. //On breaks and/or pagedescriptorchanges the corresponding will be generated //immediately. //The advantage is, that on one hand already a nearly realistic number of //pages are created, but above all there are no almost endless long chain //of paragraphs, which must be moved expensively until it reaches a tolerable //reduced level. //We'd like to think that 20 Paragraphs fit on one page. //So that it does not become in extreme situations so violent we calculate depending //on the node something to it. //If in the DocStatistic a usable given pagenumber //(Will be cared for while writing), so it will be presumed that this will be //number of pages. constbool bStartPercent = bPages && !nEndIndex;
//If the layout will be created (bPages == true) we do head on the progress //Flys and DrawObjects are not connected immediately, this //happens only at the end of the function. if ( bPages )
{ // Attention: the SwLayHelper class uses references to the content-, // page-, layout-frame etc. and may change them!
pPageMaker.reset(new SwLayHelper( rDoc, pFrame, pPrv, pPage, pLay,
pActualSection, nIndex, SwNodeOffset(0) == nEndIndex )); if( bStartPercent )
{ const sal_uLong nPageCount = pPageMaker->CalcPageCount(); if( nPageCount )
bObjsDirect = false;
}
}
if( pLay->IsInSct() &&
( pLay->IsSctFrame() || pLay->GetUpper() ) ) // Hereby will newbies // be intercepted, of which flags could not determined yet, // for e.g. while inserting a table
{
SwSectionFrame* pSct = pLay->FindSctFrame(); // If content will be inserted in a footnote, which in a column area, // the column area it is not allowed to be broken up. // Only if in the inner of the footnote lies an area, is this a candidate // for pActualSection. // The same applies for areas in tables, if inside the table will be // something inserted, it's only allowed to break up areas, which // lies in the inside also. if( ( !pLay->IsInFootnote() || pSct->IsInFootnote() ) &&
( !pLay->IsInTab() || pSct->IsInTab() ) )
{
pActualSection.reset(new SwActualSection(nullptr, pSct, pSct->GetSection()->GetFormat()->GetSectionNode())); // tdf#132236 for SwUndoDelete: find outer sections whose start // nodes aren't contained in the range but whose end nodes are, // because section frames may need to be created for them
SwActualSection * pUpperSection(pActualSection.get()); while (pUpperSection->GetSectionNode()->EndOfSectionIndex() < nEndIndex)
{
SwStartNode *const pStart(pUpperSection->GetSectionNode()->StartOfSectionNode()); if (!pStart->IsSectionNode())
{ break;
} // note: these don't have a section frame, check it in EndNode case! autoconst pTmp(new SwActualSection(nullptr, nullptr, static_cast<SwSectionNode*>(pStart)));
pUpperSection->SetUpper(pTmp);
pUpperSection = pTmp;
}
OSL_ENSURE( !pLay->Lower() || !pLay->Lower()->IsColumnFrame(), "InsertCnt_: Wrong Call" );
}
}
//If a section is "open", the pActualSection points to an SwActualSection. //If the page breaks, for "open" sections a follow will created. //For nested sections (which have, however, not a nested layout), //the SwActualSection class has a member, which points to an upper(section). //When the "inner" section finishes, the upper will used instead.
std::vector<SwSectionFrame *> newHiddenSections;
// Do not consider the end node. The caller (Section/MakeFrames()) has to // ensure that the end of this range is positioned before EndIndex! for ( ; nEndIndex == SwNodeOffset(0) || nIndex < nEndIndex; ++nIndex)
{
assert(pLayout);
SwNode *pNd = rDoc.GetNodes()[nIndex]; if ( pNd->IsContentNode() )
{
SwContentNode* pNode = static_cast<SwContentNode*>(pNd); if (pLayout->HasMergedParas() && !pNd->IsCreateFrameWhenHidingRedlines())
{ if (pNd->IsTextNode()
&& pNd->GetRedlineMergeFlag() == SwNode::Merge::NonFirst)
{ // must have a frame already
assert(static_cast<SwTextFrame*>(pNode->getLayoutFrame(pLayout))->GetMergedPara());
} continue; // skip it
}
pFrame = pNode->IsTextNode()
? sw::MakeTextFrame(*pNode->GetTextNode(), pLay, eMode)
: pNode->MakeFrame(pLay); if (pPageMaker && !pLay->IsHiddenNow())
pPageMaker->CheckInsert( nIndex );
pFrame->InsertBehind( pLay, pPrv ); if (!pPrv)
{
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5
¤ Dauer der Verarbeitung: 0.22 Sekunden
(vorverarbeitet)
¤
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.