/* -*- 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 . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace ::com::sun::star; SwFlyFreeFrame::SwFlyFreeFrame( SwFlyFrameFormat *pFormat, SwFrame* pSib, SwFrame *pAnch ) : SwFlyFrame( pFormat, pSib, pAnch ), // #i34753# mbNoMakePos( false ), // #i37068# mbNoMoveOnCheckClip( false ), maUnclippedFrame(), // RotateFlyFrame3 mpTransformableSwFrame() { } void SwFlyFreeFrame::DestroyImpl() { // #i28701# - use new method if( GetPageFrame() ) { if( GetFormat()->GetDoc()->IsInDtor() ) { // #i29879# - remove also to-frame anchored Writer // fly frame from page. const bool bRemoveFromPage = GetPageFrame()->GetSortedObjs() && ( IsFlyAtContentFrame() || ( GetAnchorFrame() && GetAnchorFrame()->IsFlyFrame() ) ); if ( bRemoveFromPage ) { GetPageFrame()->GetSortedObjs()->Remove( *this ); } } else { SwRect aTmp( GetObjRectWithSpaces() ); SwFlyFreeFrame::NotifyBackground( GetPageFrame(), aTmp, PrepareHint::FlyFrameLeave ); } } SwFlyFrame::DestroyImpl(); } SwFlyFreeFrame::~SwFlyFreeFrame() { #if 0 // we are possibly in ContourCache, make sure we vanish ::ClrContourCache(GetVirtDrawObj()); #endif } // #i28701# /** Notifies the background (all ContentFrames that currently are overlapping). * * Additionally, the window is also directly invalidated (especially where * there are no overlapping ContentFrames). * This also takes ContentFrames within other Flys into account. */ void SwFlyFreeFrame::NotifyBackground( SwPageFrame *pPageFrame, const SwRect& rRect, PrepareHint eHint ) { ::Notify_Background( GetVirtDrawObj(), pPageFrame, rRect, eHint, true ); } void SwFlyFreeFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/) { if ( !GetFormat()->GetDoc()->getIDocumentDrawModelAccess().IsVisibleLayerId( GetVirtDrawObj()->GetLayer() ) ) { return; } if ( !GetAnchorFrame() || IsLocked() || IsColLocked() ) { return; } // #i28701# - use new method if( !GetPageFrame() && GetAnchorFrame()->IsInFly() ) { SwFlyFrame* pFly = AnchorFrame()->FindFlyFrame(); SwPageFrame *pPageFrame = pFly ? pFly->FindPageFrame() : nullptr; if( pPageFrame ) pPageFrame->AppendFlyToPage( this ); } if( !GetPageFrame() ) { return; } Lock(); // The curtain drops // takes care of the notification in the dtor const SwFlyNotify aNotify( this ); if ( IsClipped() ) { setFrameAreaSizeValid(false); m_bHeightClipped = m_bWidthClipped = false; // no invalidation of position, // if anchored object is anchored inside a Writer fly frame, // its position is already locked, and it follows the text flow. // #i34753# - add condition: // no invalidation of position, if no direct move is requested in if ( !IsNoMoveOnCheckClip() && !( PositionLocked() && GetAnchorFrame()->IsInFly() && GetFrameFormat().GetFollowTextFlow().GetValue() ) ) { setFrameAreaPositionValid(false); } } // #i81146# new loop control int nLoopControlRuns = 0; const int nLoopControlMax = 10; // RotateFlyFrame3 - outer frame const double fRotation(getLocalFrameRotation()); const bool bRotated(!basegfx::fTools::equalZero(fRotation)); if(bRotated) { // Re-layout may be partially (see all isFrameAreaDefinitionValid() flags), // so resetting the local SwFrame(s) in the local SwFrameAreaDefinition is // needed. Reset to BoundAreas will be done below automatically if(isTransformableSwFrame()) { getTransformableSwFrame()->restoreFrameAreas(); } } while ( !isFrameAreaPositionValid() || !isFrameAreaSizeValid() || !isFramePrintAreaValid() || m_bFormatHeightOnly || !m_bValidContentPos ) { SwRectFnSet aRectFnSet(this); const SwFormatFrameSize *pSz; { // Additional scope, so aAccess will be destroyed before the check! SwBorderAttrAccess aAccess( SwFrame::GetCache(), this ); const SwBorderAttrs &rAttrs = *aAccess.Get(); pSz = &rAttrs.GetAttrSet().GetFrameSize(); // Only set when the flag is set! if ( !isFrameAreaSizeValid() ) { setFramePrintAreaValid(false); } if ( !isFramePrintAreaValid() ) { MakePrtArea( rAttrs ); m_bValidContentPos = false; } if ( !isFrameAreaSizeValid() || m_bFormatHeightOnly ) { setFrameAreaSizeValid(false); Format( getRootFrame()->GetCurrShell()->GetOut(), &rAttrs ); m_bFormatHeightOnly = false; } } if ( !isFrameAreaPositionValid() ) { const Point aOldPos( aRectFnSet.GetPos(getFrameArea()) ); // #i26791# - use new method // #i34753# - no positioning, if requested. if ( IsNoMakePos() ) { setFrameAreaPositionValid(true); } else // #i26791# - use new method MakeObjPos(); if( aOldPos == aRectFnSet.GetPos(getFrameArea()) ) { if( !isFrameAreaPositionValid() && GetAnchorFrame()->IsInSct() && !GetAnchorFrame()->FindSctFrame()->isFrameAreaDefinitionValid() ) { setFrameAreaPositionValid(true); } } else { setFrameAreaSizeValid(false); } } if ( !m_bValidContentPos ) { SwBorderAttrAccess aAccess( SwFrame::GetCache(), this ); const SwBorderAttrs &rAttrs = *aAccess.Get(); MakeContentPos( rAttrs ); } if ( isFrameAreaPositionValid() && isFrameAreaSizeValid() ) { ++nLoopControlRuns; OSL_ENSURE( nLoopControlRuns < nLoopControlMax, "LoopControl in SwFlyFreeFrame::MakeAll" ); if ( nLoopControlRuns < nLoopControlMax ) CheckClip( *pSz ); } else nLoopControlRuns = 0; } // RotateFlyFrame3 - outer frame // Do not refresh transforms/Areas self here, this will be done // when inner and outer frame are layouted, in SwNoTextFrame::MakeAll if(bRotated) { // RotateFlyFrame3: Safe changes locally // get center from outer frame (layout frame) to be on the safe side const Point aCenter(getFrameArea().Center()); const basegfx::B2DPoint aB2DCenter(aCenter.X(), aCenter.Y()); if(!mpTransformableSwFrame) { mpTransformableSwFrame.reset(new TransformableSwFrame(*this)); } getTransformableSwFrame()->createFrameAreaTransformations( fRotation, aB2DCenter); getTransformableSwFrame()->adaptFrameAreasToTransformations(); } else { // RotateFlyFrame3: Also need to clear ContourCache (if used), // usually done in SwFlyFrame::NotifyDrawObj, but there relies on // being in transform mode which is already reset then if(isTransformableSwFrame()) { ::ClrContourCache(GetVirtDrawObj()); } // reset transformations to show that they are not used mpTransformableSwFrame.reset(); } Unlock(); #if OSL_DEBUG_LEVEL > 0 SwRectFnSet aRectFnSet(this); OSL_ENSURE( m_bHeightClipped || ( aRectFnSet.GetHeight(getFrameArea()) > 0 && aRectFnSet.GetHeight(getFramePrintArea()) > 0), "SwFlyFreeFrame::Format(), flipping Fly." ); #endif } bool SwFlyFreeFrame::supportsAutoContour() const { static bool bOverrideHandleContourToAlwaysOff(true); // loplugin:constvars:ignore // RotateFlyFrameFix: For LO6.0 we need to deactivate the AutoContour feature again, it is simply // not clear how/if to use and save/load it in ODF. This has to be discussed. // The reason not to remove is that this may be used as-is now, using a new switch. // Even when not, the detection if it is possible will be needed in any case later. if(bOverrideHandleContourToAlwaysOff) { return false; } if(!isTransformableSwFrame()) { // support only when transformed, else there is no free space return false; } // Check for Borders. If we have Borders, do (currently) not support, // since borders do not transform with the object. // (Will need to be enhanced to take into account if we have Borders and if these // transform with the object) SwBorderAttrAccess aAccess(SwFrame::GetCache(), this); const SwBorderAttrs &rAttrs(*aAccess.Get()); if(rAttrs.IsLine()) { return false; } // Check for Padding. Do not support when padding is used, this will // produce a covered space around the object (filled with fill defines) const SfxPoolItem* pItem(nullptr); if(GetFormat() && SfxItemState::SET == GetFormat()->GetItemState(RES_BOX, false, &pItem)) { const SvxBoxItem& rBox = *static_cast< const SvxBoxItem* >(pItem); if(rBox.HasBorder(/*bTreatPaddingAsBorder*/true)) { return false; } } // check for Fill - if we have fill, it will fill the gaps and we will not // support AutoContour if(GetFormat() && GetFormat()->supportsFullDrawingLayerFillAttributeSet()) { const drawinglayer::attribute::SdrAllFillAttributesHelperPtr aFillAttributes(GetFormat()->getSdrAllFillAttributesHelper()); if(aFillAttributes.get() && aFillAttributes->isUsed()) { return false; } } else { const std::shared_ptr aBack(GetFormat()->makeBackgroundBrushItem()); if(aBack && aBack->isUsed()) { return false; } } // else, support return true; } // RotateFlyFrame3 - Support for Transformations - outer frame basegfx::B2DHomMatrix SwFlyFreeFrame::getFrameAreaTransformation() const { if(isTransformableSwFrame()) { // use pre-created transformation return getTransformableSwFrame()->getLocalFrameAreaTransformation(); } // call parent return SwFlyFrame::getFrameAreaTransformation(); } basegfx::B2DHomMatrix SwFlyFreeFrame::getFramePrintAreaTransformation() const { if(isTransformableSwFrame()) { // use pre-created transformation return getTransformableSwFrame()->getLocalFramePrintAreaTransformation(); } // call parent return SwFlyFrame::getFramePrintAreaTransformation(); } // RotateFlyFrame3 - Support for Transformations void SwFlyFreeFrame::transform_translate(const Point& rOffset) { // call parent - this will do the basic transform for SwRect(s) // in the SwFrameAreaDefinition SwFlyFrame::transform_translate(rOffset); // check if the Transformations need to be adapted if(isTransformableSwFrame()) { const basegfx::B2DHomMatrix aTransform( basegfx::utils::createTranslateB2DHomMatrix( rOffset.X(), rOffset.Y())); // transform using TransformableSwFrame getTransformableSwFrame()->transform(aTransform); } } // RotateFlyFrame3 - outer frame double getLocalFrameRotation_from_SwNoTextFrame(const SwNoTextFrame& rNoTextFrame) { return rNoTextFrame.getLocalFrameRotation(); } double SwFlyFreeFrame::getLocalFrameRotation() const { // SwLayoutFrame::Lower() != SwFrame::GetLower(), but SwFrame::GetLower() // calls SwLayoutFrame::Lower() when it's a SwLayoutFrame - so use GetLower() const SwNoTextFrame* pSwNoTextFrame(dynamic_cast< const SwNoTextFrame* >(GetLower())); if(nullptr != pSwNoTextFrame) { return getLocalFrameRotation_from_SwNoTextFrame(*pSwNoTextFrame); } // no rotation return 0.0; } /** determines, if direct environment of fly frame has 'auto' size #i17297# start with anchor frame and search via for a header, footer, row or fly frame stopping at page frame. return , if such a frame is found and it has 'auto' size. otherwise is returned. @return boolean indicating, that direct environment has 'auto' size */ bool SwFlyFreeFrame::HasEnvironmentAutoSize() const { bool bRetVal = false; const SwFrame* pToBeCheckedFrame = GetAnchorFrame(); while ( pToBeCheckedFrame && !pToBeCheckedFrame->IsPageFrame() ) { if ( pToBeCheckedFrame->IsHeaderFrame() || pToBeCheckedFrame->IsFooterFrame() || pToBeCheckedFrame->IsRowFrame() || pToBeCheckedFrame->IsFlyFrame() ) { bRetVal = SwFrameSize::Fixed != pToBeCheckedFrame->GetAttrSet()->GetFrameSize().GetHeightSizeType(); break; } else { pToBeCheckedFrame = pToBeCheckedFrame->GetUpper(); } } return bRetVal; } void SwFlyFreeFrame::CheckClip( const SwFormatFrameSize &rSz ) { // It's probably time now to take appropriate measures, if the Fly // doesn't fit into its surrounding. // First, the Fly gives up its position, then it's formatted. // Only if it still doesn't fit after giving up its position, the // width or height are given up as well. The frame will be squeezed // as much as needed. const SwVirtFlyDrawObj *pObj = GetVirtDrawObj(); SwRect aClip, aTmpStretch; ::CalcClipRect( pObj, aClip ); ::CalcClipRect( pObj, aTmpStretch, false ); aClip.Intersection_( aTmpStretch ); const long nBot = getFrameArea().Top() + getFrameArea().Height(); const long nRig = getFrameArea().Left() + getFrameArea().Width(); const long nClipBot = aClip.Top() + aClip.Height(); const long nClipRig = aClip.Left() + aClip.Width(); const bool bBot = nBot > nClipBot; const bool bRig = nRig > nClipRig; if ( bBot || bRig ) { bool bAgain = false; // #i37068# - no move, if it's requested if ( bBot && !IsNoMoveOnCheckClip() && !GetDrawObjs() && !GetAnchorFrame()->IsInTab() ) { SwFrame* pHeader = FindFooterOrHeader(); // In a header, correction of the position is no good idea. // If the fly moves, some paragraphs have to be formatted, this // could cause a change of the height of the headerframe, // now the flyframe can change its position and so on ... if ( !pHeader || !pHeader->IsHeaderFrame() ) { const long nOld = getFrameArea().Top(); // tdf#112443 disable positioning if content is completely off page bool bDisableOffPagePositioning = GetFormat()->getIDocumentSettingAccess().get(DocumentSettingId::DISABLE_OFF_PAGE_POSITIONING); if ( !bDisableOffPagePositioning || nOld <= nClipBot) { SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this); aFrm.Pos().setY( std::max( aClip.Top(), nClipBot - aFrm.Height() ) ); } if ( getFrameArea().Top() != nOld ) { bAgain = true; } m_bHeightClipped = true; } } if ( bRig ) { const long nOld = getFrameArea().Left(); // tdf#112443 disable positioning if content is completely off page bool bDisableOffPagePositioning = GetFormat()->getIDocumentSettingAccess().get(DocumentSettingId::DISABLE_OFF_PAGE_POSITIONING); if ( !bDisableOffPagePositioning || nOld <= nClipRig ) { SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this); aFrm.Pos().setX( std::max( aClip.Left(), nClipRig - aFrm.Width() ) ); } if ( getFrameArea().Left() != nOld ) { const SwFormatHoriOrient &rH = GetFormat()->GetHoriOrient(); // Left-aligned ones may not be moved to the left when they // are avoiding another one. if( rH.GetHoriOrient() == text::HoriOrientation::LEFT ) { SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this); aFrm.Pos().setX( nOld ); } else { bAgain = true; } } m_bWidthClipped = true; } if ( bAgain ) { setFrameAreaSizeValid(false); } else { // If we reach this branch, the Frame protrudes into forbidden // areas, and correcting the position is not allowed or not // possible or not required. // For Flys with OLE objects as lower, we make sure that // we always resize proportionally Size aOldSize( getFrameArea().SSize() ); // First, setup the FrameRect, then transfer it to the Frame. SwRect aFrameRect( getFrameArea() ); if ( bBot ) { long nDiff = nClipBot; nDiff -= aFrameRect.Top(); // nDiff represents the available distance nDiff = aFrameRect.Height() - nDiff; aFrameRect.Height( aFrameRect.Height() - nDiff ); m_bHeightClipped = true; } if ( bRig ) { long nDiff = nClipRig; nDiff -= aFrameRect.Left();// nDiff represents the available distance nDiff = aFrameRect.Width() - nDiff; aFrameRect.Width( aFrameRect.Width() - nDiff ); m_bWidthClipped = true; } // #i17297# - no proportional // scaling of graphics in environments, which determines its size // by its content ('auto' size). Otherwise layout loops can occur and // layout sizes of the environment can be incorrect. // Such environment are: // (1) header and footer frames with 'auto' size // (2) table row frames with 'auto' size // (3) fly frames with 'auto' size // Note: section frames seems to be not critical - didn't found // any critical layout situation so far. if ( Lower() && Lower()->IsNoTextFrame() && (static_cast(Lower())->GetNode()->GetOLENode() || !HasEnvironmentAutoSize() ) ) { // If width and height got adjusted, then the bigger // change is relevant. if ( aFrameRect.Width() != aOldSize.Width() && aFrameRect.Height()!= aOldSize.Height() ) { if ( (aOldSize.Width() - aFrameRect.Width()) > (aOldSize.Height()- aFrameRect.Height()) ) aFrameRect.Height( aOldSize.Height() ); else aFrameRect.Width( aOldSize.Width() ); } // Adjusted the width? change height proportionally if( aFrameRect.Width() != aOldSize.Width() ) { aFrameRect.Height( aFrameRect.Width() * aOldSize.Height() / aOldSize.Width() ); m_bHeightClipped = true; } // Adjusted the height? change width proportionally else if( aFrameRect.Height() != aOldSize.Height() ) { aFrameRect.Width( aFrameRect.Height() * aOldSize.Width() / aOldSize.Height() ); m_bWidthClipped = true; } // #i17297# - reactivate change // of size attribute for fly frames containing an ole object. // Added the aFrameRect.HasArea() hack, because // the environment of the ole object does not have to be valid // at this moment, or even worse, it does not have to have a // reasonable size. In this case we do not want to change to // attributes permanently. Maybe one day somebody dares to remove // this code. if ( aFrameRect.HasArea() && static_cast(Lower())->GetNode()->GetOLENode() && ( m_bWidthClipped || m_bHeightClipped ) ) { SwFlyFrameFormat *pFormat = GetFormat(); pFormat->LockModify(); SwFormatFrameSize aFrameSize( rSz ); aFrameSize.SetWidth( aFrameRect.Width() ); aFrameSize.SetHeight( aFrameRect.Height() ); pFormat->SetFormatAttr( aFrameSize ); pFormat->UnlockModify(); } } // Now change the Frame; for columns, we put the new values into the attributes, // otherwise we'll end up with unwanted side-effects/oscillations const long nPrtHeightDiff = getFrameArea().Height() - getFramePrintArea().Height(); const long nPrtWidthDiff = getFrameArea().Width() - getFramePrintArea().Width(); maUnclippedFrame = getFrameArea(); { SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this); aFrm.Height( aFrameRect.Height() ); aFrm.Width ( std::max( long(MINLAY), aFrameRect.Width() ) ); } if ( Lower() && Lower()->IsColumnFrame() ) { ColLock(); //lock grow/shrink const Size aTmpOldSize( getFramePrintArea().SSize() ); { SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this); aPrt.Height( getFrameArea().Height() - nPrtHeightDiff ); aPrt.Width ( getFrameArea().Width() - nPrtWidthDiff ); } ChgLowersProp( aTmpOldSize ); SwFrame *pLow = Lower(); do { pLow->Calc(getRootFrame()->GetCurrShell()->GetOut()); // also calculate the (Column)BodyFrame static_cast(pLow)->Lower()->Calc(getRootFrame()->GetCurrShell()->GetOut()); pLow = pLow->GetNext(); } while ( pLow ); ::CalcContent( this ); ColUnlock(); if ( !isFrameAreaSizeValid() && !m_bWidthClipped ) { setFrameAreaSizeValid(true); m_bFormatHeightOnly = true; } } else { SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this); aPrt.Height( getFrameArea().Height() - nPrtHeightDiff ); aPrt.Width ( getFrameArea().Width() - nPrtWidthDiff ); } } } // #i26945# OSL_ENSURE( getFrameArea().Height() >= 0, " - fly frame has negative height now." ); } /** method to determine, if a on the Writer fly frame is possible #i43771# */ bool SwFlyFreeFrame::IsFormatPossible() const { return SwFlyFrame::IsFormatPossible() && ( GetPageFrame() || ( GetAnchorFrame() && GetAnchorFrame()->IsInFly() ) ); } SwFlyLayFrame::SwFlyLayFrame( SwFlyFrameFormat *pFormat, SwFrame* pSib, SwFrame *pAnch ) : SwFlyFreeFrame( pFormat, pSib, pAnch ) { m_bLayout = true; } // #i28701# void SwFlyLayFrame::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew ) { const SwFormatAnchor *pAnch = nullptr; if (pNew) { const sal_uInt16 nWhich = pNew->Which(); if( RES_ATTRSET_CHG == nWhich && SfxItemState::SET == static_cast(pNew)->GetChgSet()->GetItemState( RES_ANCHOR, false, reinterpret_cast(&pAnch) )) ; // GetItemState sets the anchor pointer! else if( RES_ANCHOR == nWhich ) { // Change of anchor. I'm attaching myself to the new place. // It's not allowed to change the anchor type. This is only // possible via SwFEShell. pAnch = static_cast(pNew); } } if( pAnch ) { OSL_ENSURE( pAnch->GetAnchorId() == GetFormat()->GetAnchor().GetAnchorId(), "8-) Invalid change of anchor type." ); // Unregister, get hold of the page, attach to the corresponding LayoutFrame. SwRect aOld( GetObjRectWithSpaces() ); // #i28701# - use new method SwPageFrame *pOldPage = GetPageFrame(); AnchorFrame()->RemoveFly( this ); if ( RndStdIds::FLY_AT_PAGE == pAnch->GetAnchorId() ) { sal_uInt16 nPgNum = pAnch->GetPageNum(); SwRootFrame *pRoot = getRootFrame(); SwPageFrame *pTmpPage = static_cast(pRoot->Lower()); for ( sal_uInt16 i = 1; (i <= nPgNum) && pTmpPage; ++i, pTmpPage = static_cast(pTmpPage->GetNext()) ) { if ( i == nPgNum ) { // #i50432# - adjust synopsis of pTmpPage->PlaceFly( this, nullptr ); } } if( !pTmpPage ) { pRoot->SetAssertFlyPages(); pRoot->AssertFlyPages(); } } else { SwNodeIndex aIdx( pAnch->GetContentAnchor()->nNode ); SwContentFrame *pContent = GetFormat()->GetDoc()->GetNodes().GoNext( &aIdx )-> GetContentNode()->getLayoutFrame(getRootFrame(), nullptr, nullptr); if( pContent ) { SwFlyFrame *pTmp = pContent->FindFlyFrame(); if( pTmp ) pTmp->AppendFly( this ); } } // #i28701# - use new method if ( pOldPage && pOldPage != GetPageFrame() ) NotifyBackground( pOldPage, aOld, PrepareHint::FlyFrameLeave ); SetCompletePaint(); InvalidateAll(); SetNotifyBack(); } else SwFlyFrame::Modify( pOld, pNew ); } void SwPageFrame::AppendFlyToPage( SwFlyFrame *pNew ) { if ( !pNew->GetVirtDrawObj()->IsInserted() ) getRootFrame()->GetDrawPage()->InsertObject( static_cast(pNew->GetVirtDrawObj()), pNew->GetVirtDrawObj()->GetReferencedObj().GetOrdNumDirect() ); InvalidateSpelling(); InvalidateSmartTags(); InvalidateAutoCompleteWords(); InvalidateWordCount(); if ( GetUpper() ) { static_cast(GetUpper())->SetIdleFlags(); static_cast(GetUpper())->InvalidateBrowseWidth(); } SdrObject* pObj = pNew->GetVirtDrawObj(); OSL_ENSURE( pNew->GetAnchorFrame(), "Fly without Anchor" ); SwFlyFrame* pFly = const_cast(pNew->GetAnchorFrame()->FindFlyFrame()); if ( pFly && pObj->GetOrdNum() < pFly->GetVirtDrawObj()->GetOrdNum() ) { //#i119945# set pFly's OrdNum to _rNewObj's. So when pFly is removed by Undo, the original OrdNum will not be changed. sal_uInt32 nNewNum = pObj->GetOrdNumDirect(); if ( pObj->getSdrPageFromSdrObject() ) pObj->getSdrPageFromSdrObject()->SetObjectOrdNum( pFly->GetVirtDrawObj()->GetOrdNumDirect(), nNewNum ); else pFly->GetVirtDrawObj()->SetOrdNum( nNewNum ); } // Don't look further at Flys that sit inside the Content. if ( pNew->IsFlyInContentFrame() ) InvalidateFlyInCnt(); else { InvalidateFlyContent(); if ( !m_pSortedObjs ) { m_pSortedObjs.reset(new SwSortedObjs()); } const bool bSuccessInserted = m_pSortedObjs->Insert( *pNew ); OSL_ENSURE( bSuccessInserted, "Fly not inserted in Sorted." ); // #i87493# OSL_ENSURE( pNew->GetPageFrame() == nullptr || pNew->GetPageFrame() == this, " - anchored fly frame seems to be registered at another page frame. Serious defect." ); // #i28701# - use new method pNew->SetPageFrame( this ); pNew->InvalidatePage( this ); // #i28701# pNew->UnlockPosition(); // needed to reposition at-page anchored flys moved from different page pNew->InvalidateObjPos(); // Notify accessible layout. That's required at this place for // frames only where the anchor is moved. Creation of new frames // is additionally handled by the SwFrameNotify class. if( GetUpper() && static_cast< SwRootFrame * >( GetUpper() )->IsAnyShellAccessible() && static_cast< SwRootFrame * >( GetUpper() )->GetCurrShell() ) { static_cast< SwRootFrame * >( GetUpper() )->GetCurrShell()->Imp() ->AddAccessibleFrame( pNew ); } } // #i28701# - correction: consider also drawing objects if ( pNew->GetDrawObjs() ) { SwSortedObjs &rObjs = *pNew->GetDrawObjs(); for (SwAnchoredObject* pTmpObj : rObjs) { if ( dynamic_cast( pTmpObj) != nullptr ) { SwFlyFrame* pTmpFly = static_cast(pTmpObj); // #i28701# - use new method if ( pTmpFly->IsFlyFreeFrame() && !pTmpFly->GetPageFrame() ) AppendFlyToPage( pTmpFly ); } else if ( dynamic_cast( pTmpObj) != nullptr ) { // #i87493# if ( pTmpObj->GetPageFrame() != this ) { if ( pTmpObj->GetPageFrame() != nullptr ) { pTmpObj->GetPageFrame()->RemoveDrawObjFromPage( *pTmpObj ); } AppendDrawObjToPage( *pTmpObj ); } } } } } void SwPageFrame::RemoveFlyFromPage( SwFlyFrame *pToRemove ) { const sal_uInt32 nOrdNum = pToRemove->GetVirtDrawObj()->GetOrdNum(); getRootFrame()->GetDrawPage()->RemoveObject( nOrdNum ); pToRemove->GetVirtDrawObj()->ReferencedObj().SetOrdNum( nOrdNum ); if ( GetUpper() ) { if ( !pToRemove->IsFlyInContentFrame() ) static_cast(GetUpper())->SetSuperfluous(); static_cast(GetUpper())->InvalidateBrowseWidth(); } // Don't look further at Flys that sit inside the Content. if ( pToRemove->IsFlyInContentFrame() ) return; // Don't delete collections just yet. This will happen at the end of the // action in the RemoveSuperfluous of the page, kicked off by a method of // the same name in the root. // The FlyColl might be gone already, because the page's dtor is being // executed. // Remove it _before_ disposing accessible frames to avoid accesses to // the Frame from event handlers. if (m_pSortedObjs) { m_pSortedObjs->Remove(*pToRemove); if (!m_pSortedObjs->size()) { m_pSortedObjs.reset(); } } // Notify accessible layout. That's required at this place for // frames only where the anchor is moved. Creation of new frames // is additionally handled by the SwFrameNotify class. if( GetUpper() && static_cast< SwRootFrame * >( GetUpper() )->IsAnyShellAccessible() && static_cast< SwRootFrame * >( GetUpper() )->GetCurrShell() ) { static_cast< SwRootFrame * >( GetUpper() )->GetCurrShell()->Imp() ->DisposeAccessibleFrame( pToRemove, true ); } // #i28701# - use new method pToRemove->SetPageFrame( nullptr ); } void SwPageFrame::MoveFly( SwFlyFrame *pToMove, SwPageFrame *pDest ) { // Invalidations if ( GetUpper() ) { static_cast(GetUpper())->SetIdleFlags(); if ( !pToMove->IsFlyInContentFrame() && pDest->GetPhyPageNum() < GetPhyPageNum() ) static_cast(GetUpper())->SetSuperfluous(); } pDest->InvalidateSpelling(); pDest->InvalidateSmartTags(); pDest->InvalidateAutoCompleteWords(); pDest->InvalidateWordCount(); if ( pToMove->IsFlyInContentFrame() ) { pDest->InvalidateFlyInCnt(); return; } // Notify accessible layout. That's required at this place for // frames only where the anchor is moved. Creation of new frames // is additionally handled by the SwFrameNotify class. if( GetUpper() && static_cast< SwRootFrame * >( GetUpper() )->IsAnyShellAccessible() && static_cast< SwRootFrame * >( GetUpper() )->GetCurrShell() ) { static_cast< SwRootFrame * >( GetUpper() )->GetCurrShell()->Imp() ->DisposeAccessibleFrame( pToMove, true ); } // The FlyColl might be gone already, because the page's dtor is being executed. if ( m_pSortedObjs ) { m_pSortedObjs->Remove( *pToMove ); if ( !m_pSortedObjs->size() ) { m_pSortedObjs.reset(); } } // Register if ( !pDest->GetSortedObjs() ) pDest->m_pSortedObjs.reset(new SwSortedObjs()); const bool bSuccessInserted = pDest->GetSortedObjs()->Insert( *pToMove ); OSL_ENSURE( bSuccessInserted, "Fly not inserted in Sorted." ); // #i28701# - use new method pToMove->SetPageFrame( pDest ); pToMove->InvalidatePage( pDest ); pToMove->SetNotifyBack(); pDest->InvalidateFlyContent(); // #i28701# pToMove->UnlockPosition(); // Notify accessible layout. That's required at this place for // frames only where the anchor is moved. Creation of new frames // is additionally handled by the SwFrameNotify class. if( GetUpper() && static_cast< SwRootFrame * >( GetUpper() )->IsAnyShellAccessible() && static_cast< SwRootFrame * >( GetUpper() )->GetCurrShell() ) { static_cast< SwRootFrame * >( GetUpper() )->GetCurrShell()->Imp() ->AddAccessibleFrame( pToMove ); } // #i28701# - correction: move lowers of Writer fly frame if ( pToMove->GetDrawObjs() ) { SwSortedObjs &rObjs = *pToMove->GetDrawObjs(); for (SwAnchoredObject* pObj : rObjs) { if ( dynamic_cast( pObj) != nullptr ) { SwFlyFrame* pFly = static_cast(pObj); if ( pFly->IsFlyFreeFrame() ) { // #i28701# - use new method SwPageFrame* pPageFrame = pFly->GetPageFrame(); if ( pPageFrame ) pPageFrame->MoveFly( pFly, pDest ); else pDest->AppendFlyToPage( pFly ); } } else if ( dynamic_cast( pObj) != nullptr ) { RemoveDrawObjFromPage( *pObj ); pDest->AppendDrawObjToPage( *pObj ); } } } } void SwPageFrame::AppendDrawObjToPage( SwAnchoredObject& _rNewObj ) { if ( dynamic_cast( &_rNewObj) == nullptr ) { OSL_FAIL( "SwPageFrame::AppendDrawObjToPage(..) - anchored object of unexpected type -> object not appended" ); return; } if ( GetUpper() ) { static_cast(GetUpper())->InvalidateBrowseWidth(); } assert(_rNewObj.GetAnchorFrame()); SwFlyFrame* pFlyFrame = const_cast(_rNewObj.GetAnchorFrame()->FindFlyFrame()); if ( pFlyFrame && _rNewObj.GetDrawObj()->GetOrdNum() < pFlyFrame->GetVirtDrawObj()->GetOrdNum() ) { //#i119945# set pFly's OrdNum to _rNewObj's. So when pFly is removed by Undo, the original OrdNum will not be changed. sal_uInt32 nNewNum = _rNewObj.GetDrawObj()->GetOrdNumDirect(); if ( _rNewObj.GetDrawObj()->getSdrPageFromSdrObject() ) _rNewObj.DrawObj()->getSdrPageFromSdrObject()->SetObjectOrdNum( pFlyFrame->GetVirtDrawObj()->GetOrdNumDirect(), nNewNum ); else pFlyFrame->GetVirtDrawObj()->SetOrdNum( nNewNum ); } if ( RndStdIds::FLY_AS_CHAR == _rNewObj.GetFrameFormat().GetAnchor().GetAnchorId() ) { return; } if ( !m_pSortedObjs ) { m_pSortedObjs.reset(new SwSortedObjs()); } if ( !m_pSortedObjs->Insert( _rNewObj ) ) { OSL_ENSURE( m_pSortedObjs->Contains( _rNewObj ), "Drawing object not appended into list ." ); } // #i87493# OSL_ENSURE( _rNewObj.GetPageFrame() == nullptr || _rNewObj.GetPageFrame() == this, " - anchored draw object seems to be registered at another page frame. Serious defect." ); _rNewObj.SetPageFrame( this ); // invalidate page in order to force a reformat of object layout of the page. InvalidateFlyLayout(); } void SwPageFrame::RemoveDrawObjFromPage( SwAnchoredObject& _rToRemoveObj ) { if ( dynamic_cast( &_rToRemoveObj) == nullptr ) { OSL_FAIL( "SwPageFrame::RemoveDrawObjFromPage(..) - anchored object of unexpected type -> object not removed" ); return; } if ( m_pSortedObjs ) { m_pSortedObjs->Remove( _rToRemoveObj ); if ( !m_pSortedObjs->size() ) { m_pSortedObjs.reset(); } if ( GetUpper() ) { if (RndStdIds::FLY_AS_CHAR != _rToRemoveObj.GetFrameFormat().GetAnchor().GetAnchorId()) { static_cast(GetUpper())->SetSuperfluous(); InvalidatePage(); } static_cast(GetUpper())->InvalidateBrowseWidth(); } } _rToRemoveObj.SetPageFrame( nullptr ); } // #i50432# - adjust method description and synopsis. void SwPageFrame::PlaceFly( SwFlyFrame* pFly, SwFlyFrameFormat* pFormat ) { // #i50432# - consider the case that page is an empty page: // In this case append the fly frame at the next page OSL_ENSURE( !IsEmptyPage() || GetNext(), " - empty page with no next page! -> fly frame appended at empty page" ); if ( IsEmptyPage() && GetNext() ) { static_cast(GetNext())->PlaceFly( pFly, pFormat ); } else { // If we received a Fly, we use that one. Otherwise, create a new // one using the Format. if ( pFly ) AppendFly( pFly ); else { OSL_ENSURE( pFormat, ":-( No Format given for Fly." ); pFly = new SwFlyLayFrame( pFormat, this, this ); AppendFly( pFly ); ::RegistFlys( this, pFly ); } } } // #i18732# - adjustments for following text flow or not // AND alignment at 'page areas' for to paragraph/to character anchored objects // #i22305# - adjustment for following text flow for to frame anchored objects // #i29778# - Because calculating the floating screen object's position // (Writer fly frame or drawing object) doesn't perform a calculation on its // upper frames and its anchor frame, a calculation of the upper frames in this // method is no longer sensible. // #i28701# - if document compatibility option 'Consider wrapping style influence // on object positioning' is ON, the clip area corresponds to the one as the // object doesn't follow the text flow. bool CalcClipRect( const SdrObject *pSdrObj, SwRect &rRect, bool bMove ) { bool bRet = true; if ( auto pVirtFlyDrawObj = dynamic_cast(pSdrObj) ) { const SwFlyFrame* pFly = pVirtFlyDrawObj->GetFlyFrame(); const bool bFollowTextFlow = pFly->GetFormat()->GetFollowTextFlow().GetValue(); // #i28701# const bool bConsiderWrapOnObjPos = pFly->GetFormat()->getIDocumentSettingAccess().get(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION); const SwFormatVertOrient &rV = pFly->GetFormat()->GetVertOrient(); if( pFly->IsFlyLayFrame() ) { const SwFrame* pClip; // #i22305# // #i28701# if ( !bFollowTextFlow || bConsiderWrapOnObjPos ) { pClip = pFly->GetAnchorFrame()->FindPageFrame(); } else { pClip = pFly->GetAnchorFrame(); } rRect = pClip->getFrameArea(); SwRectFnSet aRectFnSet(pClip); // vertical clipping: Top and Bottom, also to PrtArea if necessary if( rV.GetVertOrient() != text::VertOrientation::NONE && rV.GetRelationOrient() == text::RelOrientation::PRINT_AREA ) { aRectFnSet.SetTop( rRect, aRectFnSet.GetPrtTop(*pClip) ); aRectFnSet.SetBottom( rRect, aRectFnSet.GetPrtBottom(*pClip) ); } // horizontal clipping: Top and Bottom, also to PrtArea if necessary const SwFormatHoriOrient &rH = pFly->GetFormat()->GetHoriOrient(); if( rH.GetHoriOrient() != text::HoriOrientation::NONE && rH.GetRelationOrient() == text::RelOrientation::PRINT_AREA ) { aRectFnSet.SetLeft( rRect, aRectFnSet.GetPrtLeft(*pClip) ); aRectFnSet.SetRight(rRect, aRectFnSet.GetPrtRight(*pClip)); } } else if( pFly->IsFlyAtContentFrame() ) { // #i18732# - consider following text flow or not // AND alignment at 'page areas' const SwFrame* pVertPosOrientFrame = pFly->GetVertPosOrientFrame(); if ( !pVertPosOrientFrame ) { OSL_FAIL( "::CalcClipRect(..) - frame, vertical position is oriented at, is missing ."); pVertPosOrientFrame = pFly->GetAnchorFrame(); } if ( !bFollowTextFlow || bConsiderWrapOnObjPos ) { const SwLayoutFrame* pClipFrame = pVertPosOrientFrame->FindPageFrame(); if (!pClipFrame) { OSL_FAIL("!pClipFrame: " "if you can reproduce this please file a bug"); return false; } rRect = bMove ? pClipFrame->GetUpper()->getFrameArea() : pClipFrame->getFrameArea(); // #i26945# - consider that a table, during // its format, can exceed its upper printing area bottom. // Thus, enlarge the clip rectangle, if such a case occurred if ( pFly->GetAnchorFrame()->IsInTab() ) { const SwTabFrame* pTabFrame = const_cast(pFly) ->GetAnchorFrameContainingAnchPos()->FindTabFrame(); SwRect aTmp( pTabFrame->getFramePrintArea() ); aTmp += pTabFrame->getFrameArea().Pos(); rRect.Union( aTmp ); // #i43913# - consider also the cell frame const SwFrame* pCellFrame = const_cast(pFly) ->GetAnchorFrameContainingAnchPos()->GetUpper(); while ( pCellFrame && !pCellFrame->IsCellFrame() ) { pCellFrame = pCellFrame->GetUpper(); } if ( pCellFrame ) { aTmp = pCellFrame->getFramePrintArea(); aTmp += pCellFrame->getFrameArea().Pos(); rRect.Union( aTmp ); } } } else if ( rV.GetRelationOrient() == text::RelOrientation::PAGE_FRAME || rV.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA ) { // new class objectpositioning::SwEnvironmentOfAnchoredObject aEnvOfObj( bFollowTextFlow ); const SwLayoutFrame& rVertClipFrame = aEnvOfObj.GetVertEnvironmentLayoutFrame( *pVertPosOrientFrame ); if ( rV.GetRelationOrient() == text::RelOrientation::PAGE_FRAME ) { rRect = rVertClipFrame.getFrameArea(); } else if ( rV.GetRelationOrient() == text::RelOrientation::PAGE_PRINT_AREA ) { if ( rVertClipFrame.IsPageFrame() ) { rRect = static_cast(rVertClipFrame).PrtWithoutHeaderAndFooter(); } else { rRect = rVertClipFrame.getFrameArea(); } } const SwLayoutFrame* pHoriClipFrame = pFly->GetAnchorFrame()->FindPageFrame()->GetUpper(); SwRectFnSet aRectFnSet(pFly->GetAnchorFrame()); aRectFnSet.SetLeft( rRect, aRectFnSet.GetLeft(pHoriClipFrame->getFrameArea()) ); aRectFnSet.SetRight(rRect, aRectFnSet.GetRight(pHoriClipFrame->getFrameArea())); } else { // #i26945# const SwFrame *pClip = const_cast(pFly)->GetAnchorFrameContainingAnchPos(); SwRectFnSet aRectFnSet(pClip); const SwLayoutFrame *pUp = pClip->GetUpper(); const SwFrame *pCell = pUp->IsCellFrame() ? pUp : nullptr; const SwFrameType nType = bMove ? SwFrameType::Root | SwFrameType::Fly | SwFrameType::Header | SwFrameType::Footer | SwFrameType::Ftn : SwFrameType::Body | SwFrameType::Fly | SwFrameType::Header | SwFrameType::Footer | SwFrameType::Cell| SwFrameType::Ftn; while ( !(pUp->GetType() & nType) || pUp->IsColBodyFrame() ) { pUp = pUp->GetUpper(); if ( !pCell && pUp->IsCellFrame() ) pCell = pUp; } if ( bMove && pUp->IsRootFrame() ) { rRect = pUp->getFramePrintArea(); rRect += pUp->getFrameArea().Pos(); pUp = nullptr; } if ( pUp ) { if ( pUp->GetType() & SwFrameType::Body ) { const SwPageFrame *pPg; if ( pUp->GetUpper() != (pPg = pFly->FindPageFrame()) ) pUp = pPg->FindBodyCont(); if (pUp) { rRect = pUp->GetUpper()->getFrameArea(); aRectFnSet.SetTop( rRect, aRectFnSet.GetPrtTop(*pUp) ); aRectFnSet.SetBottom(rRect, aRectFnSet.GetPrtBottom(*pUp)); } } else { if( ( pUp->GetType() & (SwFrameType::Fly | SwFrameType::Ftn ) ) && !pUp->getFrameArea().IsInside( pFly->getFrameArea().Pos() ) ) { if( pUp->IsFlyFrame() ) { const SwFlyFrame *pTmpFly = static_cast(pUp); while( pTmpFly->GetNextLink() ) { pTmpFly = pTmpFly->GetNextLink(); if( pTmpFly->getFrameArea().IsInside( pFly->getFrameArea().Pos() ) ) break; } pUp = pTmpFly; } else if( pUp->IsInFootnote() ) { const SwFootnoteFrame *pTmp = pUp->FindFootnoteFrame(); while( pTmp->GetFollow() ) { pTmp = pTmp->GetFollow(); if( pTmp->getFrameArea().IsInside( pFly->getFrameArea().Pos() ) ) break; } pUp = pTmp; } } rRect = pUp->getFramePrintArea(); rRect.Pos() += pUp->getFrameArea().Pos(); if ( pUp->GetType() & (SwFrameType::Header | SwFrameType::Footer) ) { rRect.Left ( pUp->GetUpper()->getFrameArea().Left() ); rRect.Width( pUp->GetUpper()->getFrameArea().Width()); } else if ( pUp->IsCellFrame() ) //MA_FLY_HEIGHT { const SwFrame *pTab = pUp->FindTabFrame(); aRectFnSet.SetBottom( rRect, aRectFnSet.GetPrtBottom(*pTab->GetUpper()) ); // expand to left and right cell border rRect.Left ( pUp->getFrameArea().Left() ); rRect.Width( pUp->getFrameArea().Width() ); } } } if ( pCell ) { // CellFrames might also sit in unallowed areas. In this case, // the Fly is allowed to do so as well SwRect aTmp( pCell->getFramePrintArea() ); aTmp += pCell->getFrameArea().Pos(); rRect.Union( aTmp ); } } } else { const SwFrame *pUp = pFly->GetAnchorFrame()->GetUpper(); SwRectFnSet aRectFnSet(pFly->GetAnchorFrame()); while( pUp->IsColumnFrame() || pUp->IsSctFrame() || pUp->IsColBodyFrame()) pUp = pUp->GetUpper(); rRect = pUp->getFrameArea(); if( !pUp->IsBodyFrame() ) { rRect += pUp->getFramePrintArea().Pos(); rRect.SSize( pUp->getFramePrintArea().SSize() ); if ( pUp->IsCellFrame() ) { const SwFrame *pTab = pUp->FindTabFrame(); aRectFnSet.SetBottom( rRect, aRectFnSet.GetPrtBottom(*pTab->GetUpper()) ); } } else if ( pUp->GetUpper()->IsPageFrame() ) { // Objects anchored as character may exceed right margin // of body frame: aRectFnSet.SetRight( rRect, aRectFnSet.GetRight(pUp->GetUpper()->getFrameArea()) ); } long nHeight = (9*aRectFnSet.GetHeight(rRect))/10; long nTop; const SwFormat *pFormat = GetUserCall(pSdrObj)->GetFormat(); const SvxULSpaceItem &rUL = pFormat->GetULSpace(); if( bMove ) { nTop = aRectFnSet.IsVert() ? static_cast(pFly)->GetRefPoint().X() : static_cast(pFly)->GetRefPoint().Y(); nTop = aRectFnSet.YInc( nTop, -nHeight ); long nWidth = aRectFnSet.GetWidth(pFly->getFrameArea()); aRectFnSet.SetLeftAndWidth( rRect, aRectFnSet.IsVert() ? static_cast(pFly)->GetRefPoint().Y() : static_cast(pFly)->GetRefPoint().X(), nWidth ); nHeight = 2*nHeight - rUL.GetLower() - rUL.GetUpper(); } else { nTop = aRectFnSet.YInc( aRectFnSet.GetBottom(pFly->getFrameArea()), rUL.GetLower() - nHeight ); nHeight = 2*nHeight - aRectFnSet.GetHeight(pFly->getFrameArea()) - rUL.GetLower() - rUL.GetUpper(); } aRectFnSet.SetTopAndHeight( rRect, nTop, nHeight ); } } else { const SwDrawContact *pC = static_cast(GetUserCall(pSdrObj)); const SwFrameFormat *pFormat = pC->GetFormat(); const SwFormatAnchor &rAnch = pFormat->GetAnchor(); if ( RndStdIds::FLY_AS_CHAR == rAnch.GetAnchorId() ) { const SwFrame* pAnchorFrame = pC->GetAnchorFrame( pSdrObj ); if( !pAnchorFrame ) { OSL_FAIL( "<::CalcClipRect(..)> - missing anchor frame." ); const_cast(pC)->ConnectToLayout(); pAnchorFrame = pC->GetAnchorFrame(); } const SwFrame* pUp = pAnchorFrame->GetUpper(); rRect = pUp->getFramePrintArea(); rRect += pUp->getFrameArea().Pos(); SwRectFnSet aRectFnSet(pAnchorFrame); long nHeight = (9*aRectFnSet.GetHeight(rRect))/10; long nTop; const SvxULSpaceItem &rUL = pFormat->GetULSpace(); SwRect aSnapRect( pSdrObj->GetSnapRect() ); long nTmpH = 0; if( bMove ) { nTop = aRectFnSet.YInc( aRectFnSet.IsVert() ? pSdrObj->GetAnchorPos().X() : pSdrObj->GetAnchorPos().Y(), -nHeight ); long nWidth = aRectFnSet.GetWidth(aSnapRect); aRectFnSet.SetLeftAndWidth( rRect, aRectFnSet.IsVert() ? pSdrObj->GetAnchorPos().Y() : pSdrObj->GetAnchorPos().X(), nWidth ); } else { // #i26791# - value of is needed to // calculate value of . nTmpH = aRectFnSet.IsVert() ? pSdrObj->GetCurrentBoundRect().GetWidth() : pSdrObj->GetCurrentBoundRect().GetHeight(); nTop = aRectFnSet.YInc( aRectFnSet.GetTop(aSnapRect), rUL.GetLower() + nTmpH - nHeight ); } nHeight = 2*nHeight - nTmpH - rUL.GetLower() - rUL.GetUpper(); aRectFnSet.SetTopAndHeight( rRect, nTop, nHeight ); } else { // restrict clip rectangle for drawing // objects in header/footer to the page frame. // #i26791# const SwFrame* pAnchorFrame = pC->GetAnchorFrame( pSdrObj ); if ( pAnchorFrame && pAnchorFrame->FindFooterOrHeader() ) { // clip frame is the page frame the header/footer is on. const SwFrame* pClipFrame = pAnchorFrame->FindPageFrame(); rRect = pClipFrame->getFrameArea(); } else { bRet = false; } } } return bRet; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */