    /* -*- 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 <svl/itemiter.hxx>
    #include <svtools/imap.hxx>
    #include <tools/helpers.hxx>
    #include <editeng/protitem.hxx>
    #include <editeng/opaqitem.hxx>
    #include <editeng/ulspitem.hxx>
    #include <editeng/frmdiritem.hxx>
    #include <editeng/outlobj.hxx>
    #include <drawdoc.hxx>
    #include <fmtfsize.hxx>
    #include <fmtclds.hxx>
    #include <fmtcntnt.hxx>
    #include <fmturl.hxx>
    #include <fmtsrnd.hxx>
    #include <fmtornt.hxx>
    #include <fmtcnct.hxx>
    #include <ndgrf.hxx>
    #include <tolayoutanchoredobjectposition.hxx>
    #include <fmtfollowtextflow.hxx>
    #include <sortedobjs.hxx>
    #include <objectformatter.hxx>
    #include <ndole.hxx>
    #include <swtable.hxx>
    #include <svx/svdpage.hxx>
    #include <svx/svdoashp.hxx>
    #include <layouter.hxx>
    #include <pagefrm.hxx>
    #include <rootfrm.hxx>
    #include <viewimp.hxx>
    #include <viewopt.hxx>
    #include <dcontact.hxx>
    #include <dflyobj.hxx>
    #include <dview.hxx>
    #include <frmtool.hxx>
    #include <hints.hxx>
    #include <tabfrm.hxx>
    #include <txtfrm.hxx>
    #include <notxtfrm.hxx>
    #include <flyfrms.hxx>
    #include <sectfrm.hxx>
    #include <vcl/svapp.hxx>
    #include <calbck.hxx>
    #include <IDocumentSettingAccess.hxx>
    #include <IDocumentLayoutAccess.hxx>
    #include <textboxhelper.hxx>
    #include <txtfly.hxx>
    #include <ndindex.hxx>
    #include <pam.hxx>
    #include <basegfx/polygon/b2dpolygontools.hxx>
    #include <basegfx/matrix/b2dhommatrixtools.hxx>

    using namespace ::com::sun::star;

    static SwTwips lcl_CalcAutoWidth( const SwLayoutFrame& rFrame );

    SwFlyFrame::SwFlyFrame( SwFlyFrameFormat *pFormat, SwFrame* pSib, SwFrame *pAnch ) :
        SwLayoutFrame( pFormat, pSib ),
        SwAnchoredObject(), // #i26791#
        m_pPrevLink( nullptr ),
        m_pNextLink( nullptr ),
        m_bInCnt( false ),
        m_bAtCnt( false ),
        m_bLayout( false ),
        m_bAutoPosition( false ),
        m_bValidContentPos( false )
    {
        mnFrameType = SwFrameType::Fly;

        m_bInvalid = m_bNotifyBack = true;
        m_bLocked  = m_bMinHeight =
        m_bHeightClipped = m_bWidthClipped = m_bFormatHeightOnly = false;

        // Size setting: Fixed size is always the width
        const SwFormatFrameSize &rFrameSize = pFormat->GetFrameSize();
        const SvxFrameDirection nDir = pFormat->GetFormatAttr( RES_FRAMEDIR ).GetValue();
        if( SvxFrameDirection::Environment == nDir )
        {
            mbDerivedVert = true;
            mbDerivedR2L = true;
        }
        else
        {
            mbInvalidVert = false;
            mbDerivedVert = false;
            mbDerivedR2L = false;
            if( SvxFrameDirection::Horizontal_LR_TB == nDir || SvxFrameDirection::Horizontal_RL_TB == nDir )
            {
                mbVertLR = false;
                mbVertical = false;
            }
            else
            {
                const SwViewShell *pSh = getRootFrame() ? getRootFrame()->GetCurrShell() : nullptr;
                if( pSh && pSh->GetViewOptions()->getBrowseMode() )
                {
                    mbVertLR = false;
                    mbVertical = false;
                }
                else
                {
                    mbVertical = true;

                    if ( SvxFrameDirection::Vertical_LR_TB == nDir )
                        mbVertLR = true;
                    else
                        mbVertLR = false;
                }
            }

            mbInvalidR2L = false;
            if( SvxFrameDirection::Horizontal_RL_TB == nDir )
                mbRightToLeft = true;
            else
                mbRightToLeft = false;
        }

        {
            SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
            aFrm.Width( rFrameSize.GetWidth() );
            aFrm.Height( rFrameSize.GetHeightSizeType() == ATT_VAR_SIZE ? MINFLY : rFrameSize.GetHeight() );
        }

        // Fixed or variable Height?
        if ( rFrameSize.GetHeightSizeType() == ATT_MIN_SIZE )
            m_bMinHeight = true;
        else if ( rFrameSize.GetHeightSizeType() == ATT_FIX_SIZE )
            mbFixSize = true;

        // insert columns, if necessary
        InsertColumns();

        // First the Init, then the Content:
        // This is due to the fact that the Content may have Objects/Frames,
        // which are then registered
        InitDrawObj();

        Chain( pAnch );

        InsertCnt();

        // Put it somewhere outside so that out document is not formatted unnecessarily often
        SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
        aFrm.Pos().setX(FAR_AWAY);
        aFrm.Pos().setY(FAR_AWAY);
    }

    void SwFlyFrame::Chain( SwFrame* _pAnch )
    {
        // Connect to chain neighbours.
        // No problem, if a neighboor doesn't exist - the construction of the
        // neighboor will make the connection
        const SwFormatChain& rChain = GetFormat()->GetChain();
        if ( rChain.GetPrev() || rChain.GetNext() )
        {
            if ( rChain.GetNext() )
            {
                SwFlyFrame* pFollow = FindChainNeighbour( *rChain.GetNext(), _pAnch );
                if ( pFollow )
                {
                    OSL_ENSURE( !pFollow->GetPrevLink(), "wrong chain detected" );
                    if ( !pFollow->GetPrevLink() )
                        SwFlyFrame::ChainFrames( this, pFollow );
                }
            }
            if ( rChain.GetPrev() )
            {
                SwFlyFrame *pMaster = FindChainNeighbour( *rChain.GetPrev(), _pAnch );
                if ( pMaster )
                {
                    OSL_ENSURE( !pMaster->GetNextLink(), "wrong chain detected" );
                    if ( !pMaster->GetNextLink() )
                        SwFlyFrame::ChainFrames( pMaster, this );
                }
            }
        }
    }

    void SwFlyFrame::InsertCnt()
    {
        if ( !GetPrevLink() )
        {
            const SwFormatContent& rContent = GetFormat()->GetContent();
            OSL_ENSURE( rContent.GetContentIdx(), ":-( no content prepared." );
            sal_uLong nIndex = rContent.GetContentIdx()->GetIndex();
            // Lower() means SwColumnFrame; the Content then needs to be inserted into the (Column)BodyFrame
            ::InsertCnt_( Lower() ? static_cast<SwLayoutFrame*>(static_cast<SwLayoutFrame*>(Lower())->Lower()) : static_cast<SwLayoutFrame*>(this),
                          GetFormat()->GetDoc(), nIndex );

            // NoText always have a fixed height.
            if ( Lower() && Lower()->IsNoTextFrame() )
            {
                mbFixSize = true;
                m_bMinHeight = false;
            }
        }
    }

    void SwFlyFrame::InsertColumns()
    {
        // #i97379#
        // Check, if column are allowed.
        // Columns are not allowed for fly frames, which represent graphics or embedded objects.
        const SwFormatContent& rContent = GetFormat()->GetContent();
        OSL_ENSURE( rContent.GetContentIdx(), "<SwFlyFrame::InsertColumns()> - no content prepared." );
        SwNodeIndex aFirstContent( *(rContent.GetContentIdx()), 1 );
        if ( aFirstContent.GetNode().IsNoTextNode() )
        {
            return;
        }

        const SwFormatCol &rCol = GetFormat()->GetCol();
        if ( rCol.GetNumCols() > 1 )
        {
            // Start off PrtArea to be as large as Frame, so that we can put in the columns
            // properly. It'll adjust later on.
            {
                SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
                aPrt.Width( getFrameArea().Width() );
                aPrt.Height( getFrameArea().Height() );
            }

            const SwFormatCol aOld; // ChgColumns() also needs an old value passed
            ChgColumns( aOld, rCol );
        }
    }

    void SwFlyFrame::DestroyImpl()
    {
        // Accessible objects for fly frames will be destroyed in this destructor.
        // For frames bound as char or frames that don't have an anchor we have
        // to do that ourselves. For any other frame the call RemoveFly at the
        // anchor will do that.
        if( IsAccessibleFrame() && GetFormat() && (IsFlyInContentFrame() || !GetAnchorFrame()) )
        {
            SwRootFrame *pRootFrame = getRootFrame();
            if( pRootFrame && pRootFrame->IsAnyShellAccessible() )
            {
                SwViewShell *pVSh = pRootFrame->GetCurrShell();
                if( pVSh && pVSh->Imp() )
                {
                    // Lowers aren't disposed already, so we have to do a recursive
                    // dispose
                    pVSh->Imp()->DisposeAccessibleFrame( this, true );
                }
            }
        }

        if( GetFormat() && !GetFormat()->GetDoc()->IsInDtor() )
        {
            // OD 2004-01-19 #110582#
            Unchain();

            // OD 2004-01-19 #110582#
            DeleteCnt();

            if ( GetAnchorFrame() )
                AnchorFrame()->RemoveFly( this );
        }

        FinitDrawObj();

        SwLayoutFrame::DestroyImpl();
    }

    SwFlyFrame::~SwFlyFrame()
    {
    }

    const IDocumentDrawModelAccess& SwFlyFrame::getIDocumentDrawModelAccess()
    {
        return GetFormat()->getIDocumentDrawModelAccess();
    }

    // OD 2004-01-19 #110582#
    void SwFlyFrame::Unchain()
    {
        if ( GetPrevLink() )
            UnchainFrames( GetPrevLink(), this );
        if ( GetNextLink() )
            UnchainFrames( this, GetNextLink() );
    }

    // OD 2004-01-19 #110582#
    void SwFlyFrame::DeleteCnt()
    {
        SwFrame* pFrame = m_pLower;
        while ( pFrame )
        {
            while ( pFrame->GetDrawObjs() && pFrame->GetDrawObjs()->size() )
            {
                SwAnchoredObject *pAnchoredObj = (*pFrame->GetDrawObjs())[0];
                if ( dynamic_cast<const SwFlyFrame*>( pAnchoredObj) !=  nullptr )
                {
                    SwFrame::DestroyFrame(static_cast<SwFlyFrame*>(pAnchoredObj));
                }
                else if ( dynamic_cast<const SwAnchoredDrawObject*>( pAnchoredObj) !=  nullptr )
                {
                    // OD 23.06.2003 #108784# - consider 'virtual' drawing objects
                    SdrObject* pObj = pAnchoredObj->DrawObj();
                    if ( dynamic_cast<const SwDrawVirtObj*>( pObj) !=  nullptr )
                    {
                        SwDrawVirtObj* pDrawVirtObj = static_cast<SwDrawVirtObj*>(pObj);
                        pDrawVirtObj->RemoveFromWriterLayout();
                        pDrawVirtObj->RemoveFromDrawingPage();
                    }
                    else
                    {
                        SwDrawContact* pContact =
                                static_cast<SwDrawContact*>(::GetUserCall( pObj ));
                        if ( pContact )
                        {
                            pContact->DisconnectFromLayout();
                        }
                    }
                }
            }

            pFrame->RemoveFromLayout();
            SwFrame::DestroyFrame(pFrame);
            pFrame = m_pLower;
        }

        InvalidatePage();
    }

    void SwFlyFrame::InitDrawObj()
    {
        // OD 2004-03-22 #i26791#
        SetDrawObj(*SwFlyDrawContact::CreateNewRef(this, GetFormat()));

        // Set the right Layer
        // OD 2004-01-19 #110582#
        IDocumentDrawModelAccess& rIDDMA = GetFormat()->getIDocumentDrawModelAccess();
        SdrLayerID nHeavenId = rIDDMA.GetHeavenId();
        SdrLayerID nHellId = rIDDMA.GetHellId();
        // OD 2004-03-22 #i26791#
        GetVirtDrawObj()->SetLayer( GetFormat()->GetOpaque().GetValue()
                                    ? nHeavenId
                                    : nHellId );
    }

    void SwFlyFrame::FinitDrawObj()
    {
        if(!GetVirtDrawObj() )
            return;
        SwFormat* pFormat = GetFormat();
        // Deregister from SdrPageViews if the Objects is still selected there.
        if(!pFormat->GetDoc()->IsInDtor())
        {
            SwViewShell* p1St = getRootFrame()->GetCurrShell();
            if(p1St)
            {
                for(SwViewShell& rCurrentShell : p1St->GetRingContainer())
                {   // At the moment the Drawing can do just do an Unmark on everything,
                    // as the Object was already removed
                    if(rCurrentShell.HasDrawView() )
                        rCurrentShell.Imp()->GetDrawView()->UnmarkAll();
                }
            }
        }

        // Else calls delete of the ContactObj
        GetVirtDrawObj()->SetUserCall(nullptr);

        // Deregisters itself at the Master
        // always use SdrObject::Free(...) for SdrObjects (!)
        SdrObject* pTemp(GetVirtDrawObj());
        SdrObject::Free(pTemp);
    }

    void SwFlyFrame::ChainFrames( SwFlyFrame *pMaster, SwFlyFrame *pFollow )
    {
        OSL_ENSURE( pMaster && pFollow, "incomplete chain" );
        OSL_ENSURE( !pMaster->GetNextLink(), "link can not be changed" );
        OSL_ENSURE( !pFollow->GetPrevLink(), "link can not be changed" );

        pMaster->m_pNextLink = pFollow;
        pFollow->m_pPrevLink = pMaster;

        if ( pMaster->ContainsContent() )
        {
            // To get a text flow we need to invalidate
            SwFrame *pInva = pMaster->FindLastLower();
            SwRectFnSet aRectFnSet(pMaster);
            const long nBottom = aRectFnSet.GetPrtBottom(*pMaster);
            while ( pInva )
            {
                if( aRectFnSet.BottomDist( pInva->getFrameArea(), nBottom ) <= 0 )
                {
                    pInva->InvalidateSize();
                    pInva->Prepare();
                    pInva = pInva->FindPrev();
                }
                else
                    pInva = nullptr;
            }
        }

        if ( pFollow->ContainsContent() )
        {
            // There's only the content from the Masters left; the content from the Follow
            // does not have any Frames left (should always be exactly one empty TextNode).
            SwFrame *pFrame = pFollow->ContainsContent();
            OSL_ENSURE( !pFrame->IsTabFrame() && !pFrame->FindNext(), "follow in chain contains content" );
            pFrame->Cut();
            SwFrame::DestroyFrame(pFrame);
        }

        // invalidate accessible relation set (accessibility wrapper)
        SwViewShell* pSh = pMaster->getRootFrame()->GetCurrShell();
        if( pSh )
        {
            SwRootFrame* pLayout = pMaster->getRootFrame();
            if( pLayout && pLayout->IsAnyShellAccessible() )
            pSh->Imp()->InvalidateAccessibleRelationSet( pMaster, pFollow );
        }
    }

    void SwFlyFrame::UnchainFrames( SwFlyFrame *pMaster, SwFlyFrame *pFollow )
    {
        pMaster->m_pNextLink = nullptr;
        pFollow->m_pPrevLink = nullptr;

        if ( pFollow->ContainsContent() )
        {
            // The Master sucks up the content of the Follow
            SwLayoutFrame *pUpper = pMaster;
            if ( pUpper->Lower()->IsColumnFrame() )
            {
                pUpper = static_cast<SwLayoutFrame*>(pUpper->GetLastLower());
                pUpper = static_cast<SwLayoutFrame*>(pUpper->Lower()); // The (Column)BodyFrame
                OSL_ENSURE( pUpper && pUpper->IsColBodyFrame(), "Missing ColumnBody" );
            }
            SwFlyFrame *pFoll = pFollow;
            while ( pFoll )
            {
                SwFrame *pTmp = ::SaveContent( pFoll );
                if ( pTmp )
                    ::RestoreContent( pTmp, pUpper, pMaster->FindLastLower() );
                pFoll->SetCompletePaint();
                pFoll->InvalidateSize();
                pFoll = pFoll->GetNextLink();
            }
        }

        // The Follow needs his own content to be served
        const SwFormatContent &rContent = pFollow->GetFormat()->GetContent();
        OSL_ENSURE( rContent.GetContentIdx(), ":-( No content prepared." );
        sal_uLong nIndex = rContent.GetContentIdx()->GetIndex();
        // Lower() means SwColumnFrame: this one contains another SwBodyFrame
        ::InsertCnt_( pFollow->Lower() ? const_cast<SwLayoutFrame*>(static_cast<const SwLayoutFrame*>(static_cast<const SwLayoutFrame*>(pFollow->Lower())->Lower()))
                                       : static_cast<SwLayoutFrame*>(pFollow),
                      pFollow->GetFormat()->GetDoc(), ++nIndex );

        // invalidate accessible relation set (accessibility wrapper)
        SwViewShell* pSh = pMaster->getRootFrame()->GetCurrShell();
        if( pSh )
        {
            SwRootFrame* pLayout = pMaster->getRootFrame();
            if( pLayout && pLayout->IsAnyShellAccessible() )
            pSh->Imp()->InvalidateAccessibleRelationSet( pMaster, pFollow );
        }
    }

    SwFlyFrame *SwFlyFrame::FindChainNeighbour( SwFrameFormat const &rChain, SwFrame *pAnch )
    {
        // We look for the Fly that's in the same Area.
        // Areas can for now only be Head/Footer or Flys.

        if ( !pAnch ) // If an Anchor was passed along, that one counts (ctor!)
            pAnch = AnchorFrame();

        SwLayoutFrame *pLay;
        if ( pAnch->IsInFly() )
            pLay = pAnch->FindFlyFrame();
        else
        {
            // FindFooterOrHeader is not appropriate here, as we may not have a
            // connection to the Anchor yet.
            pLay = pAnch->GetUpper();
            while ( pLay && !(pLay->GetType() & (SwFrameType::Header|SwFrameType::Footer)) )
                pLay = pLay->GetUpper();
        }

        SwIterator<SwFlyFrame,SwFormat> aIter( rChain );
        SwFlyFrame *pFly = aIter.First();
        if ( pLay )
        {
            while ( pFly )
            {
                if ( pFly->GetAnchorFrame() )
                {
                    if ( pFly->GetAnchorFrame()->IsInFly() )
                    {
                        if ( pFly->AnchorFrame()->FindFlyFrame() == pLay )
                            break;
                    }
                    else if ( pLay == pFly->FindFooterOrHeader() )
                        break;
                }
                pFly = aIter.Next();
            }
        }
        else if ( pFly )
        {
            OSL_ENSURE( !aIter.Next(), "chain with more than one instance" );
        }
        return pFly;
    }

    SwFrame *SwFlyFrame::FindLastLower()
    {
        SwFrame *pRet = ContainsAny();
        if ( pRet && pRet->IsInTab() )
            pRet = pRet->FindTabFrame();
        SwFrame *pNxt = pRet;
        while ( pNxt && IsAnLower( pNxt ) )
        {   pRet = pNxt;
            pNxt = pNxt->FindNext();
        }
        return pRet;
    }

    bool SwFlyFrame::FrameSizeChg( const SwFormatFrameSize &rFrameSize )
    {
        bool bRet = false;
        SwTwips nDiffHeight = getFrameArea().Height();
        if ( rFrameSize.GetHeightSizeType() == ATT_VAR_SIZE )
            mbFixSize = m_bMinHeight = false;
        else
        {
            if ( rFrameSize.GetHeightSizeType() == ATT_FIX_SIZE )
            {
                mbFixSize = true;
                m_bMinHeight = false;
            }
            else if ( rFrameSize.GetHeightSizeType() == ATT_MIN_SIZE )
            {
                mbFixSize = false;
                m_bMinHeight = true;
            }
            nDiffHeight -= rFrameSize.GetHeight();
        }
        // If the Fly contains columns, we already need to set the Fly
        // and the Columns to the required value or else we run into problems.
        if ( Lower() )
        {
            if ( Lower()->IsColumnFrame() )
            {
                const SwRect aOld( GetObjRectWithSpaces() );
                const Size   aOldSz( getFramePrintArea().SSize() );
                const SwTwips nDiffWidth = getFrameArea().Width() - rFrameSize.GetWidth();

                {
                    SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
                    aFrm.Height( aFrm.Height() - nDiffHeight );
                    aFrm.Width ( aFrm.Width()  - nDiffWidth  );
                }

                // #i68520#
                InvalidateObjRectWithSpaces();

                {
                    SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
                    aPrt.Height( aPrt.Height() - nDiffHeight );
                    aPrt.Width ( aPrt.Width()  - nDiffWidth  );
                }

                ChgLowersProp( aOldSz );
                ::Notify( this, FindPageFrame(), aOld );
                setFrameAreaPositionValid(false);
                bRet = true;
            }
            else if ( Lower()->IsNoTextFrame() )
            {
                mbFixSize = true;
                m_bMinHeight = false;
            }
        }
        return bRet;
    }

    void SwFlyFrame::SwClientNotify(const SwModify& rMod, const SfxHint& rHint)
    {
        SwFrame::SwClientNotify(rMod, rHint);
        if (auto pGetZOrdnerHint = dynamic_cast<const sw::GetZOrderHint*>(&rHint))
        {
            const auto& rFormat(dynamic_cast<const SwFrameFormat&>(rMod));
            if (rFormat.Which() == RES_FLYFRMFMT && rFormat.getIDocumentLayoutAccess().GetCurrentViewShell()) // #i11176#
                pGetZOrdnerHint->m_rnZOrder = GetVirtDrawObj()->GetOrdNum();
        }
        else if (auto pConnectedHint = dynamic_cast<const sw::GetObjectConnectedHint*>(&rHint))
        {
            const auto& rFormat(dynamic_cast<const SwFrameFormat&>(rMod));
            if (!pConnectedHint->m_risConnected && rFormat.Which() == RES_FLYFRMFMT && (!pConnectedHint->m_pRoot || pConnectedHint->m_pRoot == getRootFrame()))
                pConnectedHint->m_risConnected = true;
        }
    }

    void SwFlyFrame::Modify( const SfxPoolItem* pOld, const SfxPoolItem * pNew )
    {
        sal_uInt8 nInvFlags = 0;

        if (pNew && pOld && RES_ATTRSET_CHG == pNew->Which())
        {
            SfxItemIter aNIter( *static_cast<const SwAttrSetChg*>(pNew)->GetChgSet() );
            SfxItemIter aOIter( *static_cast<const SwAttrSetChg*>(pOld)->GetChgSet() );
            SwAttrSetChg aOldSet( *static_cast<const SwAttrSetChg*>(pOld) );
            SwAttrSetChg aNewSet( *static_cast<const SwAttrSetChg*>(pNew) );
            while( true )
            {
                UpdateAttr_( aOIter.GetCurItem(),
                             aNIter.GetCurItem(), nInvFlags,
                             &aOldSet, &aNewSet );
                if( aNIter.IsAtEnd() )
                    break;
                aNIter.NextItem();
                aOIter.NextItem();
            }
            if ( aOldSet.Count() || aNewSet.Count() )
                SwLayoutFrame::Modify( &aOldSet, &aNewSet );
        }
        else
            UpdateAttr_( pOld, pNew, nInvFlags );

        if ( nInvFlags == 0 )
            return;

        Invalidate_();
        if ( nInvFlags & 0x01 )
        {
            InvalidatePos_();
            // #i68520#
            InvalidateObjRectWithSpaces();
        }
        if ( nInvFlags & 0x02 )
        {
            InvalidateSize_();
            // #i68520#
            InvalidateObjRectWithSpaces();
        }
        if ( nInvFlags & 0x04 )
            InvalidatePrt_();
        if ( nInvFlags & 0x08 )
            SetNotifyBack();
        if ( nInvFlags & 0x10 )
            SetCompletePaint();
        if ( ( nInvFlags & 0x40 ) && Lower() && Lower()->IsNoTextFrame() )
            ClrContourCache( GetVirtDrawObj() );
        SwRootFrame *pRoot;
        if ( nInvFlags & 0x20 && nullptr != (pRoot = getRootFrame()) )
            pRoot->InvalidateBrowseWidth();
        // #i28701#
        if ( nInvFlags & 0x80 )
        {
            // update sorted object lists, the Writer fly frame is registered at.
            UpdateObjInSortedList();
        }

        // #i87645# - reset flags for the layout process (only if something has been invalidated)
        ResetLayoutProcessBools();

    }

    void SwFlyFrame::UpdateAttr_( const SfxPoolItem *pOld, const SfxPoolItem *pNew,
                                sal_uInt8 &rInvFlags,
                                SwAttrSetChg *pOldSet, SwAttrSetChg *pNewSet )
    {
        bool bClear = true;
        const sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0;
        SwViewShell *pSh = getRootFrame()->GetCurrShell();
        switch( nWhich )
        {
            case RES_VERT_ORIENT:
            case RES_HORI_ORIENT:
            // OD 22.09.2003 #i18732# - consider new option 'follow text flow'
            case RES_FOLLOW_TEXT_FLOW:
            {
                // ATTENTION: Always also change Action in ChgRePos()!
                rInvFlags |= 0x09;
            }
            break;
            // OD 2004-07-01 #i28701# - consider new option 'wrap influence on position'
            case RES_WRAP_INFLUENCE_ON_OBJPOS:
            {
                rInvFlags |= 0x89;
            }
            break;
            case RES_SURROUND:
            {
                // OD 2004-05-13 #i28701# - invalidate position on change of
                // wrapping style.
                //rInvFlags |= 0x40;
                rInvFlags |= 0x41;
                // The background needs to be messaged and invalidated
                const SwRect aTmp( GetObjRectWithSpaces() );
                NotifyBackground( FindPageFrame(), aTmp, PREP_FLY_ATTR_CHG );

                // By changing the flow of frame-bound Frames, a vertical alignment
                // can be activated/deactivated => MakeFlyPos
                if( RndStdIds::FLY_AT_FLY == GetFormat()->GetAnchor().GetAnchorId() )
                    rInvFlags |= 0x09;

                // Delete contour in the Node if necessary
                if ( Lower() && Lower()->IsNoTextFrame() &&
                     !GetFormat()->GetSurround().IsContour() )
                {
                    SwNoTextNode *pNd = static_cast<SwNoTextNode*>(static_cast<SwNoTextFrame*>(Lower())->GetNode());
                    if ( pNd->HasContour() )
                        pNd->SetContour( nullptr );
                }
                // #i28701# - perform reorder of object lists
                // at anchor frame and at page frame.
                rInvFlags |= 0x80;
            }
            break;

            case RES_PROTECT:
                if (pNew)
                {
                    const SvxProtectItem *pP = static_cast<const SvxProtectItem*>(pNew);
                    GetVirtDrawObj()->SetMoveProtect( pP->IsPosProtected()   );
                    GetVirtDrawObj()->SetResizeProtect( pP->IsSizeProtected() );
                    if( pSh )
                    {
                        SwRootFrame* pLayout = getRootFrame();
                        if( pLayout && pLayout->IsAnyShellAccessible() )
                        pSh->Imp()->InvalidateAccessibleEditableState( true, this );
                    }
                }
                break;
            case RES_COL:
                if (pOld && pNew)
                {
                    ChgColumns( *static_cast<const SwFormatCol*>(pOld), *static_cast<const SwFormatCol*>(pNew) );
                    const SwFormatFrameSize &rNew = GetFormat()->GetFrameSize();
                    if ( FrameSizeChg( rNew ) )
                        NotifyDrawObj();
                    rInvFlags |= 0x1A;
                }
                break;

            case RES_FRM_SIZE:
            case RES_FMT_CHG:
            {
                const SwFormatFrameSize &rNew = GetFormat()->GetFrameSize();
                if ( FrameSizeChg( rNew ) )
                    NotifyDrawObj();
                rInvFlags |= 0x7F;
                if (pOld && RES_FMT_CHG == nWhich)
                {
                    SwRect aNew( GetObjRectWithSpaces() );
                    SwRect aOld( getFrameArea() );
                    const SvxULSpaceItem &rUL = static_cast<const SwFormatChg*>(pOld)->pChangedFormat->GetULSpace();
                    aOld.Top( std::max( aOld.Top() - long(rUL.GetUpper()), 0L ) );
                    aOld.SSize().AdjustHeight(rUL.GetLower() );
                    const SvxLRSpaceItem &rLR = static_cast<const SwFormatChg*>(pOld)->pChangedFormat->GetLRSpace();
                    aOld.Left  ( std::max( aOld.Left() - rLR.GetLeft(), 0L ) );
                    aOld.SSize().AdjustWidth(rLR.GetRight() );
                    aNew.Union( aOld );
                    NotifyBackground( FindPageFrame(), aNew, PREP_CLEAR );

                    // Special case:
                    // When assigning a template we cannot rely on the old column
                    // attribute. As there need to be at least enough for ChgColumns,
                    // we need to create a temporary attribute.
                    SwFormatCol aCol;
                    if ( Lower() && Lower()->IsColumnFrame() )
                    {
                        sal_uInt16 nCol = 0;
                        SwFrame *pTmp = Lower();
                        do
                        {   ++nCol;
                            pTmp = pTmp->GetNext();
                        } while ( pTmp );
                        aCol.Init( nCol, 0, 1000 );
                    }
                    ChgColumns( aCol, GetFormat()->GetCol() );
                }

                SwFormatURL aURL( GetFormat()->GetURL() );

                SwFormatFrameSize *pNewFormatFrameSize = nullptr;
                SwFormatChg *pOldFormatChg = nullptr;
                if (nWhich == RES_FRM_SIZE)
                    pNewFormatFrameSize = const_cast<SwFormatFrameSize*>(static_cast<const SwFormatFrameSize*>(pNew));
                else
                    pOldFormatChg = const_cast<SwFormatChg*>(static_cast<const SwFormatChg*>(pOld));

                if (aURL.GetMap() && (pNewFormatFrameSize || pOldFormatChg))
                {
                    const SwFormatFrameSize &rOld = pNewFormatFrameSize ?
                                    *pNewFormatFrameSize :
                                    pOldFormatChg->pChangedFormat->GetFrameSize();
                    //#35091# Can be "times zero", when loading the template
                    if ( rOld.GetWidth() && rOld.GetHeight() )
                    {

                        Fraction aScaleX( rOld.GetWidth(), rNew.GetWidth() );
                        Fraction aScaleY( rOld.GetHeight(), rOld.GetHeight() );
                        aURL.GetMap()->Scale( aScaleX, aScaleY );
                        SwFrameFormat *pFormat = GetFormat();
                        pFormat->LockModify();
                        pFormat->SetFormatAttr( aURL );
                        pFormat->UnlockModify();
                    }
                }
                const SvxProtectItem &rP = GetFormat()->GetProtect();
                GetVirtDrawObj()->SetMoveProtect( rP.IsPosProtected()    );
                GetVirtDrawObj()->SetResizeProtect( rP.IsSizeProtected() );

                if ( pSh )
                    pSh->InvalidateWindows( getFrameArea() );
                const IDocumentDrawModelAccess& rIDDMA = GetFormat()->getIDocumentDrawModelAccess();
                const SdrLayerID nId = GetFormat()->GetOpaque().GetValue() ?
                                 rIDDMA.GetHeavenId() :
                                 rIDDMA.GetHellId();
                GetVirtDrawObj()->SetLayer( nId );

                if ( Lower() )
                {
                    // Delete contour in the Node if necessary
                    if( Lower()->IsNoTextFrame() &&
                         !GetFormat()->GetSurround().IsContour() )
                    {
                        SwNoTextNode *pNd = static_cast<SwNoTextNode*>(static_cast<SwNoTextFrame*>(Lower())->GetNode());
                        if ( pNd->HasContour() )
                            pNd->SetContour( nullptr );
                    }
                    else if( !Lower()->IsColumnFrame() )
                    {
                        SwFrame* pFrame = GetLastLower();
                        if( pFrame->IsTextFrame() && static_cast<SwTextFrame*>(pFrame)->IsUndersized() )
                            pFrame->Prepare( PREP_ADJUST_FRM );
                    }
                }

                // #i28701# - perform reorder of object lists
                // at anchor frame and at page frame.
                rInvFlags |= 0x80;

                break;
            }
            case RES_UL_SPACE:
            case RES_LR_SPACE:
            {
                rInvFlags |= 0x41;
                if( pSh && pSh->GetViewOptions()->getBrowseMode() )
                    getRootFrame()->InvalidateBrowseWidth();
                SwRect aNew( GetObjRectWithSpaces() );
                SwRect aOld( getFrameArea() );
                if (pNew)
                {
                    if ( RES_UL_SPACE == nWhich )
                    {
                        const SvxULSpaceItem &rUL = *static_cast<const SvxULSpaceItem*>(pNew);
                        aOld.Top( std::max( aOld.Top() - long(rUL.GetUpper()), 0L ) );
                        aOld.SSize().AdjustHeight(rUL.GetLower() );
                    }
                    else
                    {
                        const SvxLRSpaceItem &rLR = *static_cast<const SvxLRSpaceItem*>(pNew);
                        aOld.Left  ( std::max( aOld.Left() - rLR.GetLeft(), 0L ) );
                        aOld.SSize().AdjustWidth(rLR.GetRight() );
                    }
                }
                aNew.Union( aOld );
                NotifyBackground( FindPageFrame(), aNew, PREP_CLEAR );
            }
            break;

            case RES_TEXT_VERT_ADJUST:
            {
                InvalidateContentPos();
                rInvFlags |= 0x10;
            }
            break;

            case RES_BOX:
            case RES_SHADOW:
                rInvFlags |= 0x17;
                break;

            case RES_FRAMEDIR :
                SetDerivedVert( false );
                SetDerivedR2L( false );
                CheckDirChange();
                break;

            case RES_OPAQUE:
                {
                    if ( pSh )
                        pSh->InvalidateWindows( getFrameArea() );

                    const IDocumentDrawModelAccess& rIDDMA = GetFormat()->getIDocumentDrawModelAccess();
                    const SdrLayerID nId = static_cast<const SvxOpaqueItem*>(pNew)->GetValue() ?
                                        rIDDMA.GetHeavenId() :
                                        rIDDMA.GetHellId();
                    GetVirtDrawObj()->SetLayer( nId );
                    if( pSh )
                    {
                        SwRootFrame* pLayout = getRootFrame();
                        if( pLayout && pLayout->IsAnyShellAccessible() )
                    {
                        pSh->Imp()->DisposeAccessibleFrame( this );
                        pSh->Imp()->AddAccessibleFrame( this );
                    }
                    }
                    // #i28701# - perform reorder of object lists
                    // at anchor frame and at page frame.
                    rInvFlags |= 0x80;
                }
                break;

            case RES_URL:
                // The interface changes the frame size when interacting with text frames,
                // the Map, however, needs to be relative to FrameSize().
                if ( (!Lower() || !Lower()->IsNoTextFrame()) && pNew && pOld &&
                     static_cast<const SwFormatURL*>(pNew)->GetMap() && static_cast<const SwFormatURL*>(pOld)->GetMap() )
                {
                    const SwFormatFrameSize &rSz = GetFormat()->GetFrameSize();
                    if ( rSz.GetHeight() != getFrameArea().Height() ||
                         rSz.GetWidth()  != getFrameArea().Width() )
                    {
                        SwFormatURL aURL( GetFormat()->GetURL() );
                        Fraction aScaleX( getFrameArea().Width(),  rSz.GetWidth() );
                        Fraction aScaleY( getFrameArea().Height(), rSz.GetHeight() );
                        aURL.GetMap()->Scale( aScaleX, aScaleY );
                        SwFrameFormat *pFormat = GetFormat();
                        pFormat->LockModify();
                        pFormat->SetFormatAttr( aURL );
                        pFormat->UnlockModify();
                    }
                }
                // No invalidation necessary
                break;

            case RES_CHAIN:
                if (pNew)
                {
                    const SwFormatChain *pChain = static_cast<const SwFormatChain*>(pNew);
                    if ( pChain->GetNext() )
                    {
                        SwFlyFrame *pFollow = FindChainNeighbour( *pChain->GetNext() );
                        if ( GetNextLink() && pFollow != GetNextLink() )
                            SwFlyFrame::UnchainFrames( this, GetNextLink());
                        if ( pFollow )
                        {
                            if ( pFollow->GetPrevLink() &&
                                 pFollow->GetPrevLink() != this )
                                SwFlyFrame::UnchainFrames( pFollow->GetPrevLink(),
                                                         pFollow );
                            if ( !GetNextLink() )
                                SwFlyFrame::ChainFrames( this, pFollow );
                        }
                    }
                    else if ( GetNextLink() )
                        SwFlyFrame::UnchainFrames( this, GetNextLink() );
                    if ( pChain->GetPrev() )
                    {
                        SwFlyFrame *pMaster = FindChainNeighbour( *pChain->GetPrev() );
                        if ( GetPrevLink() && pMaster != GetPrevLink() )
                            SwFlyFrame::UnchainFrames( GetPrevLink(), this );
                        if ( pMaster )
                        {
                            if ( pMaster->GetNextLink() &&
                                 pMaster->GetNextLink() != this )
                                SwFlyFrame::UnchainFrames( pMaster,
                                                         pMaster->GetNextLink() );
                            if ( !GetPrevLink() )
                                SwFlyFrame::ChainFrames( pMaster, this );
                        }
                    }
                    else if ( GetPrevLink() )
                        SwFlyFrame::UnchainFrames( GetPrevLink(), this );
                }
                SAL_FALLTHROUGH;
            default:
                bClear = false;
        }
        if ( bClear )
        {
            if ( pOldSet || pNewSet )
            {
                if ( pOldSet )
                    pOldSet->ClearItem( nWhich );
                if ( pNewSet )
                    pNewSet->ClearItem( nWhich );
            }
            else
                SwLayoutFrame::Modify( pOld, pNew );
        }
    }

    /// Gets information from the Modify
    bool SwFlyFrame::GetInfo( SfxPoolItem & rInfo ) const
    {
        if( RES_AUTOFMT_DOCNODE == rInfo.Which() )
            return false;   // There's a FlyFrame, so use it
        return true;        // Continue searching
    }

    void SwFlyFrame::Invalidate_( SwPageFrame const *pPage )
    {
        InvalidatePage( pPage );
        m_bNotifyBack = m_bInvalid = true;

        SwFlyFrame *pFrame;
        if ( GetAnchorFrame() && nullptr != (pFrame = AnchorFrame()->FindFlyFrame()) )
        {
            // Very bad case: If the Fly is bound within another Fly which
            // contains columns, the Format should be from that one.
            if ( !pFrame->IsLocked() && !pFrame->IsColLocked() &&
                 pFrame->Lower() && pFrame->Lower()->IsColumnFrame() )
                pFrame->InvalidateSize();
        }

        // #i85216#
        // if vertical position is oriented at a layout frame inside a ghost section,
        // assure that the position is invalidated and that the information about
        // the vertical position oriented frame is cleared
        if ( GetVertPosOrientFrame() && GetVertPosOrientFrame()->IsLayoutFrame() )
        {
            const SwSectionFrame* pSectFrame( GetVertPosOrientFrame()->FindSctFrame() );
            if ( pSectFrame && pSectFrame->GetSection() == nullptr )
            {
                InvalidatePos();
                ClearVertPosOrientFrame();
            }
        }
    }

    /** Change the relative position
     *
     * The position will be Fix automatically and the attribute is changed accordingly.
     */
    void SwFlyFrame::ChgRelPos( const Point &rNewPos )
    {
        if ( GetCurrRelPos() == rNewPos )
            return;

        SwFrameFormat *pFormat = GetFormat();
        const bool bVert = GetAnchorFrame()->IsVertical();
        const SwTwips nNewY = bVert ? rNewPos.X() : rNewPos.Y();
        SwTwips nTmpY = nNewY == LONG_MAX ? 0 : nNewY;
        if( bVert )
            nTmpY = -nTmpY;
        SfxItemSet aSet( pFormat->GetDoc()->GetAttrPool(),
                         svl::Items<RES_VERT_ORIENT, RES_HORI_ORIENT>{});

        SwFormatVertOrient aVert( pFormat->GetVertOrient() );
        const SwTextFrame *pAutoFrame = nullptr;
        // #i34948# - handle also at-page and at-fly anchored
        // Writer fly frames
        const RndStdIds eAnchorType = GetFrameFormat().GetAnchor().GetAnchorId();
        if ( eAnchorType == RndStdIds::FLY_AT_PAGE )
        {
            aVert.SetVertOrient( text::VertOrientation::NONE );
            aVert.SetRelationOrient( text::RelOrientation::PAGE_FRAME );
        }
        else if ( eAnchorType == RndStdIds::FLY_AT_FLY )
        {
            aVert.SetVertOrient( text::VertOrientation::NONE );
            aVert.SetRelationOrient( text::RelOrientation::FRAME );
        }
        else if ( IsFlyAtContentFrame() || text::VertOrientation::NONE != aVert.GetVertOrient() )
        {
            if( text::RelOrientation::CHAR == aVert.GetRelationOrient() && IsAutoPos() )
            {
                if( LONG_MAX != nNewY )
                {
                    aVert.SetVertOrient( text::VertOrientation::NONE );
                    assert(GetAnchorFrame()->IsTextFrame());
                    pAutoFrame = static_cast<const SwTextFrame*>(GetAnchorFrame());
                    TextFrameIndex const nOfs(pAutoFrame->MapModelToViewPos(
                                *pFormat->GetAnchor().GetContentAnchor()));
                    while( pAutoFrame->GetFollow() &&
                           pAutoFrame->GetFollow()->GetOfst() <= nOfs )
                    {
                        if( pAutoFrame == GetAnchorFrame() )
                            nTmpY += pAutoFrame->GetRelPos().Y();
                        nTmpY -= pAutoFrame->GetUpper()->getFramePrintArea().Height();
                        pAutoFrame = pAutoFrame->GetFollow();
                    }
                    nTmpY = static_cast<SwFlyAtContentFrame*>(this)->GetRelCharY(pAutoFrame)-nTmpY;
                }
                else
                    aVert.SetVertOrient( text::VertOrientation::CHAR_BOTTOM );
            }
            else
            {
                aVert.SetVertOrient( text::VertOrientation::NONE );
                aVert.SetRelationOrient( text::RelOrientation::FRAME );
            }
        }
        aVert.SetPos( nTmpY );
        aSet.Put( aVert );

        // For Flys in the Cnt, the horizontal orientation is of no interest,
        // as it's always 0
        if ( !IsFlyInContentFrame() )
        {
            const SwTwips nNewX = bVert ? rNewPos.Y() : rNewPos.X();
            SwTwips nTmpX = nNewX == LONG_MAX ? 0 : nNewX;
            SwFormatHoriOrient aHori( pFormat->GetHoriOrient() );
            // #i34948# - handle also at-page and at-fly anchored
            // Writer fly frames
            if ( eAnchorType == RndStdIds::FLY_AT_PAGE )
            {
                aHori.SetHoriOrient( text::HoriOrientation::NONE );
                aHori.SetRelationOrient( text::RelOrientation::PAGE_FRAME );
                aHori.SetPosToggle( false );
            }
            else if ( eAnchorType == RndStdIds::FLY_AT_FLY )
            {
                aHori.SetHoriOrient( text::HoriOrientation::NONE );
                aHori.SetRelationOrient( text::RelOrientation::FRAME );
                aHori.SetPosToggle( false );
            }
            else if ( IsFlyAtContentFrame() || text::HoriOrientation::NONE != aHori.GetHoriOrient() )
            {
                aHori.SetHoriOrient( text::HoriOrientation::NONE );
                if( text::RelOrientation::CHAR == aHori.GetRelationOrient() && IsAutoPos() )
                {
                    if( LONG_MAX != nNewX )
                    {
                        if( !pAutoFrame )
                        {
                            assert(GetAnchorFrame()->IsTextFrame());
                            pAutoFrame = static_cast<const SwTextFrame*>(GetAnchorFrame());
                            TextFrameIndex const nOfs(pAutoFrame->MapModelToViewPos(
                                        *pFormat->GetAnchor().GetContentAnchor()));
                            while( pAutoFrame->GetFollow() &&
                                   pAutoFrame->GetFollow()->GetOfst() <= nOfs )
                                pAutoFrame = pAutoFrame->GetFollow();
                        }
                        nTmpX -= static_cast<SwFlyAtContentFrame*>(this)->GetRelCharX(pAutoFrame);
                    }
                }
                else
                    aHori.SetRelationOrient( text::RelOrientation::FRAME );
                aHori.SetPosToggle( false );
            }
            aHori.SetPos( nTmpX );
            aSet.Put( aHori );
        }
        SetCurrRelPos( rNewPos );
        pFormat->GetDoc()->SetAttr( aSet, *pFormat );

    }

    /** "Formats" the Frame; Frame and PrtArea.
     *
     * The FixSize is not inserted here.
     */
    void SwFlyFrame::Format( vcl::RenderContext* /*pRenderContext*/, const SwBorderAttrs *pAttrs )
    {
        OSL_ENSURE( pAttrs, "FlyFrame::Format, pAttrs is 0." );

        ColLock();

        if ( !isFrameAreaSizeValid() )
        {
            if ( getFrameArea().Top() == FAR_AWAY && getFrameArea().Left() == FAR_AWAY )
            {
                // Remove safety switch (see SwFrame::CTor)
                {
                    SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
                    aFrm.Pos().setX(0);
                    aFrm.Pos().setY(0);
                }

                // #i68520#
                InvalidateObjRectWithSpaces();
            }

            // Check column width and set it if needed
            if ( Lower() && Lower()->IsColumnFrame() )
                AdjustColumns( nullptr, false );

            setFrameAreaSizeValid(true);

            const SwTwips nUL = pAttrs->CalcTopLine()  + pAttrs->CalcBottomLine();
            const SwTwips nLR = pAttrs->CalcLeftLine() + pAttrs->CalcRightLine();
            const SwFormatFrameSize &rFrameSz = GetFormat()->GetFrameSize();
            Size aRelSize( CalcRel( rFrameSz ) );

            OSL_ENSURE( pAttrs->GetSize().Height() != 0 || rFrameSz.GetHeightPercent(), "FrameAttr height is 0." );
            OSL_ENSURE( pAttrs->GetSize().Width()  != 0 || rFrameSz.GetWidthPercent(), "FrameAttr width is 0." );

            SwRectFnSet aRectFnSet(this);
            if( !HasFixSize() )
            {
                long nMinHeight = 0;
                if( IsMinHeight() )
                    nMinHeight = aRectFnSet.IsVert() ? aRelSize.Width() : aRelSize.Height();

                SwTwips nRemaining = CalcContentHeight(pAttrs, nMinHeight, nUL);
                if( IsMinHeight() && (nRemaining + nUL) < nMinHeight )
                    nRemaining = nMinHeight - nUL;
                // Because the Grow/Shrink of the Flys does not directly
                // set the size - only indirectly by triggering a Format()
                // via Invalidate() - the sizes need to be set here.
                // Notification is running along already.
                // As we already got a lot of zeros per attribute, we block them
                // from now on.

                if ( nRemaining < MINFLY )
                    nRemaining = MINFLY;

                {
                    SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
                    aRectFnSet.SetHeight( aPrt, nRemaining );
                }

                nRemaining -= aRectFnSet.GetHeight(getFrameArea());

                {
                    SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
                    aRectFnSet.AddBottom( aFrm, nRemaining + nUL );
                }

                // #i68520#
                if ( nRemaining + nUL != 0 )
                {
                    InvalidateObjRectWithSpaces();
                }

                setFrameAreaSizeValid(true);

                if (SwFrameFormat* pShapeFormat = SwTextBoxHelper::getOtherTextBoxFormat(GetFormat(), RES_FLYFRMFMT))
                {
                    // This fly is a textbox of a draw shape.
                    SdrObject* pShape = pShapeFormat->FindSdrObject();
                    if (SdrObjCustomShape* pCustomShape = dynamic_cast<SdrObjCustomShape*>( pShape) )
                    {
                        // The shape is a customshape: then inform it about the calculated fly size.
                        Size aSize(aRectFnSet.GetWidth(getFrameArea()), aRectFnSet.GetHeight(getFrameArea()));
                        pCustomShape->SuggestTextFrameSize(aSize);
                        // Do the calculations normally done after touching editeng text of the shape.
                        pCustomShape->NbcSetOutlinerParaObjectForText(nullptr, nullptr);
                    }
                }
            }
            else
            {
                // Fixed Frames do not Format itself
                setFrameAreaSizeValid(true);

                // Flys set their size using the attr
                SwTwips nNewSize = aRectFnSet.IsVert() ? aRelSize.Width() : aRelSize.Height();
                nNewSize -= nUL;
                if( nNewSize < MINFLY )
                    nNewSize = MINFLY;

                {
                    SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
                    aRectFnSet.SetHeight( aPrt, nNewSize );
                }

                nNewSize += nUL - aRectFnSet.GetHeight(getFrameArea());

                {
                    SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
                    aRectFnSet.AddBottom( aFrm, nNewSize );
                }

                // #i68520#
                if ( nNewSize != 0 )
                {
                    InvalidateObjRectWithSpaces();
                }
            }

            if ( !m_bFormatHeightOnly )
            {
                OSL_ENSURE( aRelSize == CalcRel( rFrameSz ), "SwFlyFrame::Format CalcRel problem" );
                SwTwips nNewSize = aRectFnSet.IsVert() ? aRelSize.Height() : aRelSize.Width();

                if ( rFrameSz.GetWidthSizeType() != ATT_FIX_SIZE )
                {
                    // #i9046# Autowidth for fly frames
                    const SwTwips nAutoWidth = lcl_CalcAutoWidth( *this );
                    if ( nAutoWidth )
                    {
                        if( ATT_MIN_SIZE == rFrameSz.GetWidthSizeType() )
                            nNewSize = std::max( nNewSize - nLR, nAutoWidth );
                        else
                            nNewSize = nAutoWidth;
                    }
                }
                else
                    nNewSize -= nLR;

                if( nNewSize < MINFLY )
                    nNewSize = MINFLY;

                {
                    SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
                    aRectFnSet.SetWidth( aPrt, nNewSize );
                }

                nNewSize += nLR - aRectFnSet.GetWidth(getFrameArea());

                {
                    SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
                    aRectFnSet.AddRight( aFrm, nNewSize );
                }

                // #i68520#
                if ( nNewSize != 0 )
                {
                    InvalidateObjRectWithSpaces();
                }
            }
        }
        ColUnlock();
    }

    // OD 14.03.2003 #i11760# - change parameter <bNoColl>: type <bool>;
    //                          default value = false.
    // OD 14.03.2003 #i11760# - add new parameter <bNoCalcFollow> with
    //                          default value = false.
    // OD 11.04.2003 #108824# - new parameter <bNoCalcFollow> was used by method
    //                          <FormatWidthCols(..)> to avoid follow formatting
    //                          for text frames. But, unformatted follows causes
    //                          problems in method <SwContentFrame::WouldFit_(..)>,
    //                          which assumes that the follows are formatted.
    //                          Thus, <bNoCalcFollow> no longer used by <FormatWidthCols(..)>.
    void CalcContent( SwLayoutFrame *pLay, bool bNoColl )
    {
        vcl::RenderContext* pRenderContext = pLay->getRootFrame()->GetCurrShell()->GetOut();
        SwSectionFrame* pSect;
        bool bCollect = false;
        if( pLay->IsSctFrame() )
        {
            pSect = static_cast<SwSectionFrame*>(pLay);
            if( pSect->IsEndnAtEnd() && !bNoColl )
            {
                bCollect = true;
                SwLayouter::CollectEndnotes( pLay->GetFormat()->GetDoc(), pSect );
            }
            pSect->CalcFootnoteContent();
        }
        else
            pSect = nullptr;
        SwFrame *pFrame = pLay->ContainsAny();
        if ( !pFrame )
        {
            if( pSect )
            {
                if( pSect->HasFollow() )
                    pFrame = pSect->GetFollow()->ContainsAny();
                if( !pFrame )
                {
                    if( pSect->IsEndnAtEnd() )
                    {
                        if( bCollect )
                            pLay->GetFormat()->GetDoc()->getIDocumentLayoutAccess().GetLayouter()->
                                InsertEndnotes( pSect );
                        bool bLock = pSect->IsFootnoteLock();
                        pSect->SetFootnoteLock( true );
                        pSect->CalcFootnoteContent();
                        pSect->CalcFootnoteContent();
                        pSect->SetFootnoteLock( bLock );
                    }
                    return;
                }
                pFrame->InvalidatePos_();
            }
            else
                return;
        }
        pFrame->InvalidatePage();

        do
        {
            // local variables to avoid loops caused by anchored object positioning
            SwAnchoredObject* pAgainObj1 = nullptr;
            SwAnchoredObject* pAgainObj2 = nullptr;

            // FME 2007-08-30 #i81146# new loop control
            int nLoopControlRuns = 0;
            const int nLoopControlMax = 20;
            const SwFrame* pLoopControlCond = nullptr;

            SwFrame* pLast;
            do
            {
                pLast = pFrame;
                if( pFrame->IsVertical() ?
                    ( pFrame->GetUpper()->getFramePrintArea().Height() != pFrame->getFrameArea().Height() )
                    : ( pFrame->GetUpper()->getFramePrintArea().Width() != pFrame->getFrameArea().Width() ) )
                {
                    pFrame->Prepare( PREP_FIXSIZE_CHG );
                    pFrame->InvalidateSize_();
                }

                if ( pFrame->IsTabFrame() )
                {
                    static_cast<SwTabFrame*>(pFrame)->m_bCalcLowers = true;
                    // OD 26.08.2003 #i18103# - lock move backward of follow table,
                    // if no section content is formatted or follow table belongs
                    // to the section, which content is formatted.
                    if ( static_cast<SwTabFrame*>(pFrame)->IsFollow() &&
                         ( !pSect || pSect == pFrame->FindSctFrame() ) )
                    {
                        static_cast<SwTabFrame*>(pFrame)->m_bLockBackMove = true;
                    }
                }

                {
                    SwFrameDeleteGuard aDeletePageGuard(pSect ? pSect->FindPageFrame() : nullptr);
                    SwFrameDeleteGuard aDeleteGuard(pSect);
                    pFrame->Calc(pRenderContext);
                }

                // OD 14.03.2003 #i11760# - reset control flag for follow format.
                if ( pFrame->IsTextFrame() )
                {
                    static_cast<SwTextFrame*>(pFrame)->AllowFollowFormat();
                }

                // #111937# The keep-attribute can cause the position
                // of the prev to be invalid:
                // OD 2004-03-15 #116560# - Do not consider invalid previous frame
                // due to its keep-attribute, if current frame is a follow or is locked.
                // #i44049# - do not consider invalid previous
                // frame due to its keep-attribute, if it can't move forward.
                // #i57765# - do not consider invalid previous
                // frame, if current frame has a column/page break before attribute.
                SwFrame* pTmpPrev = pFrame->FindPrev();
                SwFlowFrame* pTmpPrevFlowFrame = pTmpPrev && pTmpPrev->IsFlowFrame() ? SwFlowFrame::CastFlowFrame(pTmpPrev) : nullptr;
                SwFlowFrame* pTmpFlowFrame     = pFrame->IsFlowFrame() ? SwFlowFrame::CastFlowFrame(pFrame) : nullptr;

                bool bPrevInvalid = pTmpPrevFlowFrame && pTmpFlowFrame &&
                                   !pTmpFlowFrame->IsFollow() &&
                                   !StackHack::IsLocked() && // #i76382#
                                   !pTmpFlowFrame->IsJoinLocked() &&
                                   !pTmpPrev->isFrameAreaPositionValid() &&
                                    pLay->IsAnLower( pTmpPrev ) &&
                                    pTmpPrevFlowFrame->IsKeep(pTmpPrev->GetAttrSet()->GetKeep(), pTmpPrev->GetBreakItem()) &&
                                    pTmpPrevFlowFrame->IsKeepFwdMoveAllowed();

                // format floating screen objects anchored to the frame.
                if ( !bPrevInvalid && pFrame->GetDrawObjs() && pLay->IsAnLower( pFrame ) )
                {
                    bool bAgain = false;
                    bool bRestartLayoutProcess = false;
                    SwPageFrame* pPageFrame = pFrame->FindPageFrame();
                    size_t nCnt = pFrame->GetDrawObjs()->size();
                    size_t i = 0;
                    while ( i < nCnt )
                    {
                        // #i28701#
                        SwAnchoredObject* pAnchoredObj = (*pFrame->GetDrawObjs())[i];

                        // determine if anchored object has to be
                        // formatted and, in case, format it
                        if ( !pAnchoredObj->PositionLocked() && pAnchoredObj->IsFormatPossible() )
                        {
                            // #i43737# - no invalidation of
                            // anchored object needed - causes loops for as-character
                            // anchored objects.
                            //pAnchoredObj->InvalidateObjPos();
                            SwRect aRect( pAnchoredObj->GetObjRect() );
                            if ( !SwObjectFormatter::FormatObj( *pAnchoredObj, pFrame, pPageFrame ) )
                            {
                                bRestartLayoutProcess = true;
                                break;
                            }
                            // #i3317# - restart layout process,
                            // if the position of the anchored object is locked now.
                            if ( pAnchoredObj->PositionLocked() )
                            {
                                bRestartLayoutProcess = true;
                                break;
                            }

                            if ( aRect != pAnchoredObj->GetObjRect() )
                            {
                                bAgain = true;
                                if ( pAgainObj2 == pAnchoredObj )
                                {
                                    OSL_FAIL( "::CalcContent(..) - loop detected, perform attribute changes to avoid the loop" );
                                    // Prevent oscillation
                                    SwFrameFormat& rFormat = pAnchoredObj->GetFrameFormat();
                                    SwFormatSurround aAttr( rFormat.GetSurround() );
                                    if( css::text::WrapTextMode_THROUGH != aAttr.GetSurround() )
                                    {
                                        // When on auto position, we can only set it to
                                        // flow through
                                        if ((rFormat.GetAnchor().GetAnchorId() ==
                                                RndStdIds::FLY_AT_CHAR) &&
                                            (css::text::WrapTextMode_PARALLEL ==
                                                aAttr.GetSurround()))
                                        {
                                            aAttr.SetSurround( css::text::WrapTextMode_THROUGH );
                                        }
                                        else
                                        {
                                            aAttr.SetSurround( css::text::WrapTextMode_PARALLEL );
                                        }
                                        rFormat.LockModify();
                                        rFormat.SetFormatAttr( aAttr );
                                        rFormat.UnlockModify();
                                    }
                                }
                                else
                                {
                                    if ( pAgainObj1 == pAnchoredObj )
                                        pAgainObj2 = pAnchoredObj;
                                    pAgainObj1 = pAnchoredObj;
                                }
                            }

                            if ( !pFrame->GetDrawObjs() )
                                break;
                            if ( pFrame->GetDrawObjs()->size() < nCnt )
                            {
                                --nCnt;
                                // Do not increment index, in this case
                                continue;
                            }
                        }
                        ++i;
                    }

                    // #i28701# - restart layout process, if
                    // requested by floating screen object formatting
                    if ( bRestartLayoutProcess )
                    {
                        pFrame = pLay->ContainsAny();
                        pAgainObj1 = nullptr;
                        pAgainObj2 = nullptr;
                        continue;
                    }

                    // OD 2004-05-17 #i28701# - format anchor frame after its objects
                    // are formatted, if the wrapping style influence has to be considered.
                    if ( pLay->GetFormat()->getIDocumentSettingAccess().get(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION) )
                    {
                        pFrame->Calc(pRenderContext);
                    }

                    if ( bAgain )
                    {
                        pFrame = pLay->ContainsContent();
                        if ( pFrame && pFrame->IsInTab() )
                            pFrame = pFrame->FindTabFrame();
                        if( pFrame && pFrame->IsInSct() )
                        {
                            SwSectionFrame* pTmp = pFrame->FindSctFrame();
                            if( pTmp != pLay && pLay->IsAnLower( pTmp ) )
                                pFrame = pTmp;
                        }

                        if ( pFrame == pLoopControlCond )
                            ++nLoopControlRuns;
                        else
                        {
                            nLoopControlRuns = 0;
                            pLoopControlCond = pFrame;
                        }

                        if ( nLoopControlRuns < nLoopControlMax )
                            continue;

                        OSL_FAIL( "LoopControl in CalcContent" );
                    }
                }
                if ( pFrame->IsTabFrame() )
                {
                    if ( static_cast<SwTabFrame*>(pFrame)->IsFollow() )
                        static_cast<SwTabFrame*>(pFrame)->m_bLockBackMove = false;
                }

                pFrame = bPrevInvalid ? pTmpPrev : pFrame->FindNext();
                if( !bPrevInvalid && pFrame && pFrame->IsSctFrame() && pSect )
                {
                    // Empty SectionFrames could be present here
                    while( pFrame && pFrame->IsSctFrame() && !static_cast<SwSectionFrame*>(pFrame)->GetSection() )
                        pFrame = pFrame->FindNext();

                    // If FindNext returns the Follow of the original Area, we want to
                    // continue with this content as long as it flows back.
                    if( pFrame && pFrame->IsSctFrame() && ( pFrame == pSect->GetFollow() ||
                        static_cast<SwSectionFrame*>(pFrame)->IsAnFollow( pSect ) ) )
                    {
                        pFrame = static_cast<SwSectionFrame*>(pFrame)->ContainsAny();
                        if( pFrame )
                            pFrame->InvalidatePos_();
                    }
                }
              // Stay in the pLay
              // Except for SectionFrames with Follow: the first ContentFrame of the Follow
              // will be formatted, so that it gets a chance to load in the pLay.
              // As long as these Frames are loading in pLay, we continue
            } while ( pFrame &&
                      ( pLay->IsAnLower( pFrame ) ||
                        ( pSect &&
                          ( ( pSect->HasFollow() &&
                              ( pLay->IsAnLower( pLast ) ||
                                ( pLast->IsInSct() &&
                                  pLast->FindSctFrame()->IsAnFollow(pSect) ) ) &&
                              pSect->GetFollow()->IsAnLower( pFrame )  ) ||
                            ( pFrame->IsInSct() &&
                              pFrame->FindSctFrame()->IsAnFollow( pSect ) ) ) ) ) );
            if( pSect )
            {
                if( bCollect )
                {
                    pLay->GetFormat()->GetDoc()->getIDocumentLayoutAccess().GetLayouter()->InsertEndnotes(pSect);
                    pSect->CalcFootnoteContent();
                }
                if( pSect->HasFollow() )
                {
                    SwSectionFrame* pNxt = pSect->GetFollow();
                    while( pNxt && !pNxt->ContainsContent() )
                        pNxt = pNxt->GetFollow();
                    if( pNxt )
                        pNxt->CalcFootnoteContent();
                }
                if( bCollect )
                {
                    pFrame = pLay->ContainsAny();
                    bCollect = false;
                    if( pFrame )
                        continue;
                }
            }
            break;
        }
        while( true );
    }

    // OD 2004-03-23 #i26791#
    void SwFlyFrame::MakeObjPos()
    {
        if ( !isFrameAreaPositionValid() )
        {
            vcl::RenderContext* pRenderContext = getRootFrame()->GetCurrShell()->GetOut();
            setFrameAreaPositionValid(true);

            // OD 29.10.2003 #113049# - use new class to position object
            GetAnchorFrame()->Calc(pRenderContext);
            objectpositioning::SwToLayoutAnchoredObjectPosition
                    aObjPositioning( *GetVirtDrawObj() );
            aObjPositioning.CalcPosition();

            // #i58280#
            // update relative position
            SetCurrRelPos( aObjPositioning.GetRelPos() );

            {
                SwRectFnSet aRectFnSet(GetAnchorFrame());
                SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
                aFrm.Pos( aObjPositioning.GetRelPos() );
                aFrm.Pos() += aRectFnSet.GetPos(GetAnchorFrame()->getFrameArea());
            }

            // #i69335#
            InvalidateObjRectWithSpaces();
        }
    }

    void SwFlyFrame::MakePrtArea( const SwBorderAttrs &rAttrs )
    {
        if ( !isFramePrintAreaValid() )
        {
            setFramePrintAreaValid(true);

            // OD 31.07.2003 #110978# - consider vertical layout
            SwRectFnSet aRectFnSet(this);
            aRectFnSet.SetXMargins( *this, rAttrs.CalcLeftLine(),
                                            rAttrs.CalcRightLine() );
            aRectFnSet.SetYMargins( *this, rAttrs.CalcTopLine(),
                                            rAttrs.CalcBottomLine() );
        }
    }

    void SwFlyFrame::MakeContentPos( const SwBorderAttrs &rAttrs )
    {
        if ( m_bValidContentPos )
            return;

        m_bValidContentPos = true;

        const SwTwips nUL = rAttrs.CalcTopLine()  + rAttrs.CalcBottomLine();
        Size aRelSize( CalcRel( GetFormat()->GetFrameSize() ) );

        SwRectFnSet aRectFnSet(this);
        long nMinHeight = 0;
        if( IsMinHeight() )
            nMinHeight = aRectFnSet.IsVert() ? aRelSize.Width() : aRelSize.Height();

        Point aNewContentPos;
        aNewContentPos = getFramePrintArea().Pos();
        const SdrTextVertAdjust nAdjust = GetFormat()->GetTextVertAdjust().GetValue();

        if( nAdjust != SDRTEXTVERTADJUST_TOP )
        {
            const SwTwips nContentHeight = CalcContentHeight(&rAttrs, nMinHeight, nUL);
            SwTwips nDiff = 0;

            if( nContentHeight != 0)
                nDiff = aRectFnSet.GetHeight(getFramePrintArea()) - nContentHeight;

            if( nDiff > 0 )
            {
                if( nAdjust == SDRTEXTVERTADJUST_CENTER )
                {
                    if( aRectFnSet.IsVertL2R() )
                        aNewContentPos.setX(aNewContentPos.getX() + nDiff/2);
                    else if( aRectFnSet.IsVert() )
                        aNewContentPos.setX(aNewContentPos.getX() - nDiff/2);
                    else
                        aNewContentPos.setY(aNewContentPos.getY() + nDiff/2);
                }
                else if( nAdjust == SDRTEXTVERTADJUST_BOTTOM )
                {
                    if( aRectFnSet.IsVertL2R() )
                        aNewContentPos.setX(aNewContentPos.getX() + nDiff);
                    else if( aRectFnSet.IsVert() )
                        aNewContentPos.setX(aNewContentPos.getX() - nDiff);
                    else
                        aNewContentPos.setY(aNewContentPos.getY() + nDiff);
                }
            }
        }
        if( aNewContentPos != ContentPos() )
        {
            ContentPos() = aNewContentPos;
            for( SwFrame *pFrame = Lower(); pFrame; pFrame = pFrame->GetNext())
            {
                pFrame->InvalidatePos();
            }
        }

    }

    void SwFlyFrame::InvalidateContentPos()
    {
        m_bValidContentPos = false;
        Invalidate_();
    }

    SwTwips SwFlyFrame::Grow_( SwTwips nDist, bool bTst )
    {
        SwRectFnSet aRectFnSet(this);
        if ( Lower() && !IsColLocked() && !HasFixSize() )
        {
            SwTwips nSize = aRectFnSet.GetHeight(getFrameArea());
            if( nSize > 0 && nDist > ( LONG_MAX - nSize ) )
                nDist = LONG_MAX - nSize;

            if ( nDist <= 0 )
                return 0;

            if ( Lower()->IsColumnFrame() )
            {   // If it's a Column Frame, the Format takes control of the
                // resizing (due to the adjustment).
                if ( !bTst )
                {
                    // #i28701# - unlock position of Writer fly frame
                    UnlockPosition();
                    InvalidatePos_();
                    InvalidateSize();
                }
                return 0;
            }

            if ( !bTst )
            {
                const SwRect aOld( GetObjRectWithSpaces() );
                InvalidateSize_();
                const bool bOldLock = m_bLocked;
                Unlock();
                if ( IsFlyFreeFrame() )
                {
                    // #i37068# - no format of position here
                    // and prevent move in method <CheckClip(..)>.
                    // This is needed to prevent layout loop caused by nested
                    // Writer fly frames - inner Writer fly frames format its
                    // anchor, which grows/shrinks the outer Writer fly frame.
                    // Note: position will be invalidated below.
                    setFrameAreaPositionValid(true);

                    // #i55416#
                    // Suppress format of width for autowidth frame, because the
                    // format of the width would call <SwTextFrame::CalcFitToContent()>
                    // for the lower frame, which initiated this grow.
                    const bool bOldFormatHeightOnly = m_bFormatHeightOnly;
                    const SwFormatFrameSize& rFrameSz = GetFormat()->GetFrameSize();
                    if ( rFrameSz.GetWidthSizeType() != ATT_FIX_SIZE )
                    {
                        m_bFormatHeightOnly = true;
                    }
                    SwViewShell* pSh = getRootFrame()->GetCurrShell();
                    if (pSh)
                    {
                        static_cast<SwFlyFreeFrame*>(this)->SetNoMoveOnCheckClip( true );
                        static_cast<SwFlyFreeFrame*>(this)->SwFlyFreeFrame::MakeAll(pSh->GetOut());
                        static_cast<SwFlyFreeFrame*>(this)->SetNoMoveOnCheckClip( false );
                    }
                    // #i55416#
                    if ( rFrameSz.GetWidthSizeType() != ATT_FIX_SIZE )
                    {
                        m_bFormatHeightOnly = bOldFormatHeightOnly;
                    }
                }
                else
                    MakeAll(getRootFrame()->GetCurrShell()->GetOut());
                InvalidateSize_();
                InvalidatePos();
                if ( bOldLock )
                    Lock();
                const SwRect aNew( GetObjRectWithSpaces() );
                if ( aOld != aNew )
                    ::Notify( this, FindPageFrame(), aOld );
                return aRectFnSet.GetHeight(aNew)-aRectFnSet.GetHeight(aOld);
            }
            return nDist;
        }
        return 0;
    }

    SwTwips SwFlyFrame::Shrink_( SwTwips nDist, bool bTst )
    {
        if( Lower() && !IsColLocked() && !HasFixSize() )
        {
            SwRectFnSet aRectFnSet(this);
            SwTwips nHeight = aRectFnSet.GetHeight(getFrameArea());
            if ( nDist > nHeight )
                nDist = nHeight;

            SwTwips nVal = nDist;
            if ( IsMinHeight() )
            {
                const SwFormatFrameSize& rFormatSize = GetFormat()->GetFrameSize();
                SwTwips nFormatHeight = aRectFnSet.IsVert() ? rFormatSize.GetWidth() : rFormatSize.GetHeight();

                nVal = std::min( nDist, nHeight - nFormatHeight );
            }

            if ( nVal <= 0 )
                return 0;

            if ( Lower()->IsColumnFrame() )
            {   // If it's a Column Frame, the Format takes control of the
                // resizing (due to the adjustment).
                if ( !bTst )
                {
                    SwRect aOld( GetObjRectWithSpaces() );

                    {
                        SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
                        aRectFnSet.SetHeight( aFrm, nHeight - nVal );
                    }

                    // #i68520#
                    if ( nHeight - nVal != 0 )
                    {
                        InvalidateObjRectWithSpaces();
                    }

                    nHeight = aRectFnSet.GetHeight(getFramePrintArea());

                    {
                        SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
                        aRectFnSet.SetHeight( aPrt, nHeight - nVal );
                    }

                    InvalidatePos_();
                    InvalidateSize();
                    ::Notify( this, FindPageFrame(), aOld );
                    NotifyDrawObj();
                    if ( GetAnchorFrame()->IsInFly() )
                        AnchorFrame()->FindFlyFrame()->Shrink( nDist, bTst );
                }
                return 0;
            }

            if ( !bTst )
            {
                const SwRect aOld( GetObjRectWithSpaces() );
                InvalidateSize_();
                const bool bOldLocked = m_bLocked;
                Unlock();
                if ( IsFlyFreeFrame() )
                {
                    // #i37068# - no format of position here
                    // and prevent move in method <CheckClip(..)>.
                    // This is needed to prevent layout loop caused by nested
                    // Writer fly frames - inner Writer fly frames format its
                    // anchor, which grows/shrinks the outer Writer fly frame.
                    // Note: position will be invalidated below.
                    setFrameAreaPositionValid(true);

                    // #i55416#
                    // Suppress format of width for autowidth frame, because the
                    // format of the width would call <SwTextFrame::CalcFitToContent()>
                    // for the lower frame, which initiated this shrink.
                    const bool bOldFormatHeightOnly = m_bFormatHeightOnly;
                    const SwFormatFrameSize& rFrameSz = GetFormat()->GetFrameSize();
                    if ( rFrameSz.GetWidthSizeType() != ATT_FIX_SIZE )
                    {
                        m_bFormatHeightOnly = true;
                    }
                    static_cast<SwFlyFreeFrame*>(this)->SetNoMoveOnCheckClip( true );
                    static_cast<SwFlyFreeFrame*>(this)->SwFlyFreeFrame::MakeAll(getRootFrame()->GetCurrShell()->GetOut());
                    static_cast<SwFlyFreeFrame*>(this)->SetNoMoveOnCheckClip( false );
                    // #i55416#
                    if ( rFrameSz.GetWidthSizeType() != ATT_FIX_SIZE )
                    {
                        m_bFormatHeightOnly = bOldFormatHeightOnly;
                    }
                }
                else
                    MakeAll(getRootFrame()->GetCurrShell()->GetOut());
                InvalidateSize_();
                InvalidatePos();
                if ( bOldLocked )
                    Lock();
                const SwRect aNew( GetObjRectWithSpaces() );
                if ( aOld != aNew )
                {
                    ::Notify( this, FindPageFrame(), aOld );
                    if ( GetAnchorFrame()->IsInFly() )
                        AnchorFrame()->FindFlyFrame()->Shrink( nDist, bTst );
                }
                return aRectFnSet.GetHeight(aOld) -
                       aRectFnSet.GetHeight(aNew);
            }
            return nVal;
        }
        return 0;
    }

    Size SwFlyFrame::ChgSize( const Size& aNewSize )
    {
        // #i53298#
        // If the fly frame anchored at-paragraph or at-character contains an OLE
        // object, assure that the new size fits into the current clipping area
        // of the fly frame
        Size aAdjustedNewSize( aNewSize );
        {
            if ( dynamic_cast<SwFlyAtContentFrame*>(this) &&
                 Lower() && dynamic_cast<SwNoTextFrame*>(Lower()) &&
                 static_cast<SwNoTextFrame*>(Lower())->GetNode()->GetOLENode() )
            {
                SwRect aClipRect;
                ::CalcClipRect( GetVirtDrawObj(), aClipRect, false );
                if ( aAdjustedNewSize.Width() > aClipRect.Width() )
                {
                    aAdjustedNewSize.setWidth( aClipRect.Width() );
                }
                if ( aAdjustedNewSize.Height() > aClipRect.Height() )
                {
                    aAdjustedNewSize.setWidth( aClipRect.Height() );
                }
            }
        }

        if ( aAdjustedNewSize != getFrameArea().SSize() )
        {
            SwFrameFormat *pFormat = GetFormat();
            SwFormatFrameSize aSz( pFormat->GetFrameSize() );
            aSz.SetWidth( aAdjustedNewSize.Width() );
            aSz.SetHeight( aAdjustedNewSize.Height() );
            // go via the Doc for UNDO
            pFormat->GetDoc()->SetAttr( aSz, *pFormat );
            return aSz.GetSize();
        }
        else
            return getFrameArea().SSize();
    }

    bool SwFlyFrame::IsLowerOf( const SwLayoutFrame* pUpperFrame ) const
    {
        OSL_ENSURE( GetAnchorFrame(), "8-( Fly is lost in Space." );
        const SwFrame* pFrame = GetAnchorFrame();
        do
        {
            if ( pFrame == pUpperFrame )
                return true;
            pFrame = pFrame->IsFlyFrame()
                   ? static_cast<const SwFlyFrame*>(pFrame)->GetAnchorFrame()
                   : pFrame->GetUpper();
        } while ( pFrame );
        return false;
    }

    void SwFlyFrame::Cut()
    {
    }

    void SwFrame::AppendFly( SwFlyFrame *pNew )
    {
        if (!m_pDrawObjs)
        {
            m_pDrawObjs.reset(new SwSortedObjs());
        }
        m_pDrawObjs->Insert( *pNew );
        pNew->ChgAnchorFrame( this );

        // Register at the page
        // If there's none present, register via SwPageFrame::PreparePage
        SwPageFrame* pPage = FindPageFrame();
        if ( pPage != nullptr )
        {
            pPage->AppendFlyToPage( pNew );
        }
    }

    void SwFrame::RemoveFly( SwFlyFrame *pToRemove )
    {
        // Deregister from the page
        // Could already have happened, if the page was already destructed
        SwPageFrame *pPage = pToRemove->FindPageFrame();
        if ( pPage && pPage->GetSortedObjs() )
        {
            pPage->RemoveFlyFromPage( pToRemove );
        }
        // #i73201#
        else
        {
            if ( pToRemove->IsAccessibleFrame() &&
                 pToRemove->GetFormat() &&
                 !pToRemove->IsFlyInContentFrame() )
            {
                SwRootFrame *pRootFrame = getRootFrame();
                if( pRootFrame && pRootFrame->IsAnyShellAccessible() )
                {
                    SwViewShell *pVSh = pRootFrame->GetCurrShell();
                    if( pVSh && pVSh->Imp() )
                    {
                        pVSh->Imp()->DisposeAccessibleFrame( pToRemove );
                    }
                }
            }
        }

        m_pDrawObjs->Remove(*pToRemove);
        if (!m_pDrawObjs->size())
        {
            m_pDrawObjs.reset();
        }

        pToRemove->ChgAnchorFrame( nullptr );

        if ( !pToRemove->IsFlyInContentFrame() && GetUpper() && IsInTab() )//MA_FLY_HEIGHT
            GetUpper()->InvalidateSize();
    }

    void SwFrame::AppendDrawObj( SwAnchoredObject& _rNewObj )
    {
        assert(!m_pDrawObjs || m_pDrawObjs->is_sorted());

        if ( dynamic_cast<const SwAnchoredDrawObject*>( &_rNewObj) ==  nullptr )
        {
            OSL_FAIL( "SwFrame::AppendDrawObj(..) - anchored object of unexpected type -> object not appended" );
            return;
        }

        if ( dynamic_cast<const SwDrawVirtObj*>(_rNewObj.GetDrawObj()) ==  nullptr &&
             _rNewObj.GetAnchorFrame() && _rNewObj.GetAnchorFrame() != this )
        {
            assert(!m_pDrawObjs || m_pDrawObjs->is_sorted());
            // perform disconnect from layout, if 'master' drawing object is appended
            // to a new frame.
            static_cast<SwDrawContact*>(::GetUserCall( _rNewObj.GetDrawObj() ))->
                                                    DisconnectFromLayout( false );
            assert(!m_pDrawObjs || m_pDrawObjs->is_sorted());
        }

        if ( _rNewObj.GetAnchorFrame() != this )
        {
            if (!m_pDrawObjs)
            {
                m_pDrawObjs.reset(new SwSortedObjs());
            }
            m_pDrawObjs->Insert(_rNewObj);
            _rNewObj.ChgAnchorFrame( this );
        }

        // #i113730#
        // Assure the control objects and group objects containing controls are on the control layer
        if ( ::CheckControlLayer( _rNewObj.DrawObj() ) )
        {
            const IDocumentDrawModelAccess& rIDDMA = getIDocumentDrawModelAccess();
            const SdrLayerID aCurrentLayer(_rNewObj.DrawObj()->GetLayer());
            const SdrLayerID aControlLayerID(rIDDMA.GetControlsId());
            const SdrLayerID aInvisibleControlLayerID(rIDDMA.GetInvisibleControlsId());

            if(aCurrentLayer != aControlLayerID && aCurrentLayer != aInvisibleControlLayerID)
            {
                if ( aCurrentLayer == rIDDMA.GetInvisibleHellId() ||
                     aCurrentLayer == rIDDMA.GetInvisibleHeavenId() )
                {
                    _rNewObj.DrawObj()->SetLayer(aInvisibleControlLayerID);
                }
                else
                {
                    _rNewObj.DrawObj()->SetLayer(aControlLayerID);
                }
                //The layer is part of the key used to sort the obj, so update
                //its position if the layer changed.
                m_pDrawObjs->Update(_rNewObj);
            }
        }

        // no direct positioning needed, but invalidate the drawing object position
        _rNewObj.InvalidateObjPos();

        // register at page frame
        SwPageFrame* pPage = FindPageFrame();
        if ( pPage )
        {
            pPage->AppendDrawObjToPage( _rNewObj );
        }

        // Notify accessible layout.
        SwViewShell* pSh = getRootFrame()->GetCurrShell();
        if( pSh )
        {
            SwRootFrame* pLayout = getRootFrame();
            if( pLayout && pLayout->IsAnyShellAccessible() )
            {
                pSh->Imp()->AddAccessibleObj( _rNewObj.GetDrawObj() );
            }
        }

        assert(!m_pDrawObjs || m_pDrawObjs->is_sorted());
    }

    void SwFrame::RemoveDrawObj( SwAnchoredObject& _rToRemoveObj )
    {
        // Notify accessible layout.
        SwViewShell* pSh = getRootFrame()->GetCurrShell();
        if( pSh )
        {
            SwRootFrame* pLayout = getRootFrame();
            if (pLayout && pLayout->IsAnyShellAccessible())
                pSh->Imp()->DisposeAccessibleObj(_rToRemoveObj.GetDrawObj(), false);
        }

        // deregister from page frame
        SwPageFrame* pPage = _rToRemoveObj.GetPageFrame();
        if ( pPage && pPage->GetSortedObjs() )
            pPage->RemoveDrawObjFromPage( _rToRemoveObj );

        m_pDrawObjs->Remove(_rToRemoveObj);
        if (!m_pDrawObjs->size())
        {
            m_pDrawObjs.reset();
        }
        _rToRemoveObj.ChgAnchorFrame( nullptr );

        assert(!m_pDrawObjs || m_pDrawObjs->is_sorted());
    }

    void SwFrame::InvalidateObjs( const bool _bNoInvaOfAsCharAnchoredObjs )
    {
        if ( GetDrawObjs() )
        {
            // #i26945# - determine page the frame is on,
            // in order to check, if anchored object is registered at the same
            // page.
            const SwPageFrame* pPageFrame = FindPageFrame();
            // #i28701# - re-factoring
            for (SwAnchoredObject* pAnchoredObj : *GetDrawObjs())
            {
                if ( _bNoInvaOfAsCharAnchoredObjs &&
                     (pAnchoredObj->GetFrameFormat().GetAnchor().GetAnchorId()
                        == RndStdIds::FLY_AS_CHAR) )
                {
                    continue;
                }
                // #i26945# - no invalidation, if anchored object
                // isn't registered at the same page and instead is registered at
                // the page, where its anchor character text frame is on.
                if ( pAnchoredObj->GetPageFrame() &&
                     pAnchoredObj->GetPageFrame() != pPageFrame )
                {
                    SwTextFrame* pAnchorCharFrame = pAnchoredObj->FindAnchorCharFrame();
                    if ( pAnchorCharFrame &&
                         pAnchoredObj->GetPageFrame() == pAnchorCharFrame->FindPageFrame() )
                    {
                        continue;
                    }
                    // #115759# - unlock its position, if anchored
                    // object isn't registered at the page, where its anchor
                    // character text frame is on, respectively if it has no
                    // anchor character text frame.
                    else
                    {
                        pAnchoredObj->UnlockPosition();
                    }
                }
                // #i51474# - reset flag, that anchored object
                // has cleared environment, and unlock its position, if the anchored
                // object is registered at the same page as the anchor frame is on.
                if ( pAnchoredObj->ClearedEnvironment() &&
                     pAnchoredObj->GetPageFrame() &&
                     pAnchoredObj->GetPageFrame() == pPageFrame )
                {
                    pAnchoredObj->UnlockPosition();
                    pAnchoredObj->SetClearedEnvironment( false );
                }
                // distinguish between writer fly frames and drawing objects
                if ( dynamic_cast<const SwFlyFrame*>( pAnchoredObj) !=  nullptr )
                {
                    SwFlyFrame* pFly = static_cast<SwFlyFrame*>(pAnchoredObj);
                    pFly->Invalidate_();
                    pFly->InvalidatePos_();
                }
                else
                {
                    pAnchoredObj->InvalidateObjPos();
                }
            } // end of loop on objects, which are connected to the frame
        }
    }

    // #i26945# - correct check, if anchored object is a lower
    // of the layout frame. E.g., anchor character text frame can be a follow text
    // frame.
    // #i44016# - add parameter <_bUnlockPosOfObjs> to
    // force an unlockposition call for the lower objects.
    void SwLayoutFrame::NotifyLowerObjs( const bool _bUnlockPosOfObjs )
    {
        // invalidate lower floating screen objects
        SwPageFrame* pPageFrame = FindPageFrame();
        if ( pPageFrame && pPageFrame->GetSortedObjs() )
        {
            SwSortedObjs& rObjs = *(pPageFrame->GetSortedObjs());
            for (SwAnchoredObject* pObj : rObjs)
            {
                // #i26945# - check, if anchored object is a lower
                // of the layout frame is changed to check, if its anchor frame
                // is a lower of the layout frame.
                // determine the anchor frame - usually it's the anchor frame,
                // for at-character/as-character anchored objects the anchor character
                // text frame is taken.
                const SwFrame* pAnchorFrame = pObj->GetAnchorFrameContainingAnchPos();
                if ( dynamic_cast<const SwFlyFrame*>( pObj) !=  nullptr )
                {
                    SwFlyFrame* pFly = static_cast<SwFlyFrame*>(pObj);

                    if ( pFly->getFrameArea().Left() == FAR_AWAY )
                        continue;

                    if ( pFly->IsAnLower( this ) )
                        continue;

                    // #i26945# - use <pAnchorFrame> to check, if
                    // fly frame is lower of layout frame resp. if fly frame is
                    // at a different page registered as its anchor frame is on.
                    const bool bLow = IsAnLower( pAnchorFrame );
                    if ( bLow || pAnchorFrame->FindPageFrame() != pPageFrame )
                    {
                        pFly->Invalidate_( pPageFrame );
                        if ( !bLow || pFly->IsFlyAtContentFrame() )
                        {
                            // #i44016#
                            if ( _bUnlockPosOfObjs )
                            {
                                pFly->UnlockPosition();
                            }
                            pFly->InvalidatePos_();
                        }
                        else
                            pFly->InvalidatePrt_();
                    }
                }
                else
                {
                    OSL_ENSURE( dynamic_cast<const SwAnchoredDrawObject*>( pObj) !=  nullptr,
                            "<SwLayoutFrame::NotifyFlys() - anchored object of unexpected type" );
                    // #i26945# - use <pAnchorFrame> to check, if
                    // fly frame is lower of layout frame resp. if fly frame is
                    // at a different page registered as its anchor frame is on.
                    if ( IsAnLower( pAnchorFrame ) ||
                         pAnchorFrame->FindPageFrame() != pPageFrame )
                    {
                        // #i44016#
                        if ( _bUnlockPosOfObjs )
                        {
                            pObj->UnlockPosition();
                        }
                        pObj->InvalidateObjPos();
                    }
                }
            }
        }
    }

    void SwFlyFrame::NotifyDrawObj()
    {
        SwVirtFlyDrawObj* pObj = GetVirtDrawObj();
        pObj->SetRect();
        pObj->SetRectsDirty();
        pObj->SetChanged();
        pObj->BroadcastObjectChange();

        if ( GetFormat()->GetSurround().IsContour() )
        {
            ClrContourCache( pObj );
        }
        else if(IsFlyFreeFrame() && static_cast< const SwFlyFreeFrame* >(this)->supportsAutoContour())
        {
            // RotateFlyFrame3: Also need to clear when changes happen
            // Caution: isTransformableSwFrame is already reset when resetting rotation, so
            // *additionally* reset in SwFlyFreeFrame::MakeAll when no more rotation
            ClrContourCache( pObj );
        }
    }

    Size SwFlyFrame::CalcRel( const SwFormatFrameSize &rSz ) const
    {
        Size aRet( rSz.GetSize() );

        const SwFrame *pRel = IsFlyLayFrame() ? GetAnchorFrame() : GetAnchorFrame()->GetUpper();
        if( pRel ) // LAYER_IMPL
        {
            long nRelWidth = LONG_MAX, nRelHeight = LONG_MAX;
            const SwViewShell *pSh = getRootFrame()->GetCurrShell();
            if ( ( pRel->IsBodyFrame() || pRel->IsPageFrame() ) &&
                 pSh && pSh->GetViewOptions()->getBrowseMode() &&
                 pSh->VisArea().HasArea() )
            {
                nRelWidth  = pSh->GetBrowseWidth();
                nRelHeight = pSh->VisArea().Height();
                Size aBorder = pSh->GetOut()->PixelToLogic( pSh->GetBrowseBorder() );
                nRelWidth  = std::min( nRelWidth,  pRel->getFramePrintArea().Width() );
                nRelHeight -= 2*aBorder.Height();
                nRelHeight = std::min( nRelHeight, pRel->getFramePrintArea().Height() );
            }

            // At the moment only the "== PAGE_FRAME" and "!= PAGE_FRAME" cases are handled.
            // When size is a relative to page size, ignore size of SwBodyFrame.
            if (rSz.GetWidthPercentRelation() != text::RelOrientation::PAGE_FRAME)
                nRelWidth  = std::min( nRelWidth,  pRel->getFramePrintArea().Width() );
            else if ( pRel->IsPageFrame() )
                nRelWidth  = std::min( nRelWidth,  pRel->getFrameArea().Width() );

            if (rSz.GetHeightPercentRelation() != text::RelOrientation::PAGE_FRAME)
                nRelHeight = std::min( nRelHeight, pRel->getFramePrintArea().Height() );
            else if ( pRel->IsPageFrame() )
                nRelHeight = std::min( nRelHeight, pRel->getFrameArea().Height() );

            if( !pRel->IsPageFrame() )
            {
                const SwPageFrame* pPage = FindPageFrame();
                if( pPage )
                {
                    if (rSz.GetWidthPercentRelation() == text::RelOrientation::PAGE_FRAME)
                        // Ignore margins of pPage.
                        nRelWidth  = std::min( nRelWidth,  pPage->getFrameArea().Width() );
                    else
                        nRelWidth  = std::min( nRelWidth,  pPage->getFramePrintArea().Width() );
                    if (rSz.GetHeightPercentRelation() == text::RelOrientation::PAGE_FRAME)
                        // Ignore margins of pPage.
                        nRelHeight = std::min( nRelHeight, pPage->getFrameArea().Height() );
                    else
                        nRelHeight = std::min( nRelHeight, pPage->getFramePrintArea().Height() );
                }
            }

            if ( rSz.GetWidthPercent() && rSz.GetWidthPercent() != SwFormatFrameSize::SYNCED )
                aRet.setWidth( nRelWidth * rSz.GetWidthPercent() / 100 );
            if ( rSz.GetHeightPercent() && rSz.GetHeightPercent() != SwFormatFrameSize::SYNCED )
                aRet.setHeight( nRelHeight * rSz.GetHeightPercent() / 100 );

            if ( rSz.GetWidthPercent() == SwFormatFrameSize::SYNCED )
            {
                aRet.setWidth( aRet.Width() * ( aRet.Height()) );
                aRet.setWidth( aRet.Width() / ( rSz.GetHeight()) );
            }
            else if ( rSz.GetHeightPercent() == SwFormatFrameSize::SYNCED )
            {
                aRet.setHeight( aRet.Height() * ( aRet.Width()) );
                aRet.setHeight( aRet.Height() / ( rSz.GetWidth()) );
            }
        }
        return aRet;
    }

    static SwTwips lcl_CalcAutoWidth( const SwLayoutFrame& rFrame )
    {
        SwTwips nRet = 0;
        SwTwips nMin = 0;
        const SwFrame* pFrame = rFrame.Lower();

        // No autowidth defined for columned frames
        if ( !pFrame || pFrame->IsColumnFrame() )
            return nRet;

        while ( pFrame )
        {
            if ( pFrame->IsSctFrame() )
            {
                nMin = lcl_CalcAutoWidth( *static_cast<const SwSectionFrame*>(pFrame) );
            }
            if ( pFrame->IsTextFrame() )
            {
                nMin = const_cast<SwTextFrame*>(static_cast<const SwTextFrame*>(pFrame))->CalcFitToContent();
                const SvxLRSpaceItem &rSpace =
                    static_cast<const SwTextFrame*>(pFrame)->GetTextNodeForParaProps()->GetSwAttrSet().GetLRSpace();
                if (!static_cast<const SwTextFrame*>(pFrame)->IsLocked())
                    nMin += rSpace.GetRight() + rSpace.GetTextLeft() + rSpace.GetTextFirstLineOfst();
            }
            else if ( pFrame->IsTabFrame() )
            {
                const SwFormatFrameSize& rTableFormatSz = static_cast<const SwTabFrame*>(pFrame)->GetTable()->GetFrameFormat()->GetFrameSize();
                if ( USHRT_MAX == rTableFormatSz.GetSize().Width() ||
                     text::HoriOrientation::NONE == static_cast<const SwTabFrame*>(pFrame)->GetFormat()->GetHoriOrient().GetHoriOrient() )
                {
                    const SwPageFrame* pPage = rFrame.FindPageFrame();
                    // auto width table
                    nMin = pFrame->GetUpper()->IsVertical() ?
                        pPage->getFramePrintArea().Height() :
                        pPage->getFramePrintArea().Width();
                }
                else
                {
                    nMin = rTableFormatSz.GetSize().Width();
                }
            }

            if ( nMin > nRet )
                nRet = nMin;

            pFrame = pFrame->GetNext();
        }

        return nRet;
    }

    /// OD 16.04.2003 #i13147# - If called for paint and the <SwNoTextFrame> contains
    /// a graphic, load of intrinsic graphic has to be avoided.
    bool SwFlyFrame::GetContour( tools::PolyPolygon&   rContour,
                               const bool _bForPaint ) const
    {
        vcl::RenderContext* pRenderContext = getRootFrame()->GetCurrShell()->GetOut();
        bool bRet = false;
        const bool bIsCandidate(Lower() && Lower()->IsNoTextFrame());

        if(bIsCandidate)
        {
            if(GetFormat()->GetSurround().IsContour())
            {
                SwNoTextNode *pNd = const_cast<SwNoTextNode*>(static_cast<const SwNoTextNode*>(static_cast<const SwNoTextFrame*>(Lower())->GetNode()));
                // OD 16.04.2003 #i13147# - determine <GraphicObject> instead of <Graphic>
                // in order to avoid load of graphic, if <SwNoTextNode> contains a graphic
                // node and method is called for paint.
                std::unique_ptr<GraphicObject> xTmpGrfObj;
                const GraphicObject* pGrfObj = nullptr;
                const SwGrfNode* pGrfNd = pNd->GetGrfNode();
                if ( pGrfNd && _bForPaint )
                {
                    pGrfObj = &(pGrfNd->GetGrfObj());
                }
                else
                {
                    xTmpGrfObj.reset(new GraphicObject(pNd->GetGraphic()));
                    pGrfObj = xTmpGrfObj.get();
                }
                assert(pGrfObj && "SwFlyFrame::GetContour() - No Graphic/GraphicObject found at <SwNoTextNode>.");
                if (pGrfObj->GetType() != GraphicType::NONE)
                {
                    if( !pNd->HasContour() )
                    {
                        // OD 16.04.2003 #i13147# - no <CreateContour> for a graphic
                        // during paint. Thus, return (value of <bRet> should be <false>).
                        if ( pGrfNd && _bForPaint )
                        {
                            OSL_FAIL( "SwFlyFrame::GetContour() - No Contour found at <SwNoTextNode> during paint." );
                            return bRet;
                        }
                        pNd->CreateContour();
                    }
                    pNd->GetContour( rContour );
                    // The Node holds the Polygon matching the original size of the graphic
                    // We need to include the scaling here
                    SwRect aClip;
                    SwRect aOrig;
                    Lower()->Calc(pRenderContext);
                    static_cast<const SwNoTextFrame*>(Lower())->GetGrfArea( aClip, &aOrig );
                    // OD 16.04.2003 #i13147# - copy method code <SvxContourDlg::ScaleContour(..)>
                    // in order to avoid that graphic has to be loaded for contour scale.
                    //SvxContourDlg::ScaleContour( rContour, aGrf, MapUnit::MapTwip, aOrig.SSize() );
                    {
                        OutputDevice*   pOutDev = Application::GetDefaultDevice();
                        const MapMode   aDispMap( MapUnit::MapTwip );
                        const MapMode   aGrfMap( pGrfObj->GetPrefMapMode() );
                        const Size      aGrfSize( pGrfObj->GetPrefSize() );
                        Size            aOrgSize;
                        Point           aNewPoint;
                        bool            bPixelMap = aGrfMap.GetMapUnit() == MapUnit::MapPixel;

                        if ( bPixelMap )
                            aOrgSize = pOutDev->PixelToLogic( aGrfSize, aDispMap );
                        else
                            aOrgSize = OutputDevice::LogicToLogic( aGrfSize, aGrfMap, aDispMap );

                        if ( aOrgSize.Width() && aOrgSize.Height() )
                        {
                            double fScaleX = static_cast<double>(aOrig.Width()) / aOrgSize.Width();
                            double fScaleY = static_cast<double>(aOrig.Height()) / aOrgSize.Height();

                            for ( sal_uInt16 j = 0, nPolyCount = rContour.Count(); j < nPolyCount; j++ )
                            {
                                tools::Polygon& rPoly = rContour[ j ];

                                for ( sal_uInt16 i = 0, nCount = rPoly.GetSize(); i < nCount; i++ )
                                {
                                    if ( bPixelMap )
                                        aNewPoint = pOutDev->PixelToLogic( rPoly[ i ], aDispMap  );
                                    else
                                        aNewPoint = OutputDevice::LogicToLogic( rPoly[ i ], aGrfMap, aDispMap  );

                                    rPoly[ i ] = Point( FRound( aNewPoint.getX() * fScaleX ), FRound( aNewPoint.getY() * fScaleY ) );
                                }
                            }
                        }
                    }
                    // OD 17.04.2003 #i13147# - destroy created <GraphicObject>.
                    xTmpGrfObj.reset();
                    rContour.Move( aOrig.Left(), aOrig.Top() );
                    if( !aClip.Width() )
                        aClip.Width( 1 );
                    if( !aClip.Height() )
                        aClip.Height( 1 );
                    rContour.Clip( aClip.SVRect() );
                    rContour.Optimize(PolyOptimizeFlags::CLOSE);
                    bRet = true;
                }
            }
            else
            {
                const SwFlyFreeFrame* pSwFlyFreeFrame(dynamic_cast< const SwFlyFreeFrame* >(this));

                if(nullptr != pSwFlyFreeFrame &&
                    pSwFlyFreeFrame->supportsAutoContour() &&
                    // isTransformableSwFrame already used in supportsAutoContour(), but
                    // better check twice when it may get changed there...
                    pSwFlyFreeFrame->isTransformableSwFrame())
                {
                    // RotateFlyFrame: use untransformed SwFrame to allow text floating around.
                    // Will be transformed below
                    const TransformableSwFrame* pTransformableSwFrame(pSwFlyFreeFrame->getTransformableSwFrame());
                    const SwRect aFrameArea(pTransformableSwFrame->getUntransformedFrameArea());
                    rContour = tools::PolyPolygon(tools::Polygon(aFrameArea.SVRect()));
                    bRet = (0 != rContour.Count());
                }
            }

            if(bRet && 0 != rContour.Count())
            {
                const SwFlyFreeFrame* pSwFlyFreeFrame(dynamic_cast< const SwFlyFreeFrame* >(this));

                if(nullptr != pSwFlyFreeFrame && pSwFlyFreeFrame->isTransformableSwFrame())
                {
                    // Need to adapt contour to transformation
                    basegfx::B2DVector aScale, aTranslate;
                    double fRotate, fShearX;
                    getFrameAreaTransformation().decompose(aScale, aTranslate, fRotate, fShearX);

                    if(!basegfx::fTools::equalZero(fRotate))
                    {
                        basegfx::B2DPolyPolygon aSource(rContour.getB2DPolyPolygon());
                        const basegfx::B2DPoint aCenter(getFrameAreaTransformation() * basegfx::B2DPoint(0.5, 0.5));
                        const basegfx::B2DHomMatrix aRotateAroundCenter(
                            basegfx::utils::createRotateAroundPoint(
                                aCenter.getX(),
                                aCenter.getY(),
                                fRotate));
                        aSource.transform(aRotateAroundCenter);
                        rContour = tools::PolyPolygon(aSource);
                    }
                }
            }
        }

        return bRet;
    }

    // OD 2004-03-25 #i26791#
    const SwVirtFlyDrawObj* SwFlyFrame::GetVirtDrawObj() const
    {
        return static_cast<const SwVirtFlyDrawObj*>(GetDrawObj());
    }
    SwVirtFlyDrawObj* SwFlyFrame::GetVirtDrawObj()
    {
        return static_cast<SwVirtFlyDrawObj*>(DrawObj());
    }

    // OD 2004-03-24 #i26791# - implementation of pure virtual method declared in
    // base class <SwAnchoredObject>

    void SwFlyFrame::InvalidateObjPos()
    {
        InvalidatePos();
        // #i68520#
        InvalidateObjRectWithSpaces();
    }

    SwFrameFormat& SwFlyFrame::GetFrameFormat()
    {
        OSL_ENSURE( GetFormat(),
                "<SwFlyFrame::GetFrameFormat()> - missing frame format -> crash." );
        return *GetFormat();
    }
    const SwFrameFormat& SwFlyFrame::GetFrameFormat() const
    {
        OSL_ENSURE( GetFormat(),
                "<SwFlyFrame::GetFrameFormat()> - missing frame format -> crash." );
        return *GetFormat();
    }

    const SwRect SwFlyFrame::GetObjRect() const
    {
        return getFrameArea();
    }

    // #i70122#
    // for Writer fly frames the bounding rectangle equals the object rectangles
    const SwRect SwFlyFrame::GetObjBoundRect() const
    {
        return GetObjRect();
    }

    // #i68520#
    bool SwFlyFrame::SetObjTop_( const SwTwips _nTop )
    {
        const bool bChanged( getFrameArea().Pos().getY() != _nTop );
        SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
        aFrm.Pos().setY(_nTop);

        return bChanged;
    }
    bool SwFlyFrame::SetObjLeft_( const SwTwips _nLeft )
    {
        const bool bChanged( getFrameArea().Pos().getX() != _nLeft );
        SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
        aFrm.Pos().setX(_nLeft);

        return bChanged;
    }

    /** method to assure that anchored object is registered at the correct
        page frame

        OD 2004-07-02 #i28701#
    */
    void SwFlyFrame::RegisterAtCorrectPage()
    {
        // default behaviour is to do nothing.
    }

    /** method to determine, if a <MakeAll()> on the Writer fly frame is possible

        OD 2004-05-11 #i28701#
    */
    bool SwFlyFrame::IsFormatPossible() const
    {
        return SwAnchoredObject::IsFormatPossible() &&
               !IsLocked() && !IsColLocked();
    }

    void SwFlyFrame::GetAnchoredObjects( std::vector<SwAnchoredObject*>& aVector, const SwFormat& rFormat )
    {
        SwIterator<SwFlyFrame,SwFormat> aIter( rFormat );
        for( SwFlyFrame* pFlyFrame = aIter.First(); pFlyFrame; pFlyFrame = aIter.Next() )
            aVector.push_back( pFlyFrame );
    }

    const SwFlyFrameFormat * SwFlyFrame::GetFormat() const
    {
        return static_cast< const SwFlyFrameFormat * >( GetDep() );
    }

    SwFlyFrameFormat * SwFlyFrame::GetFormat()
    {
        return static_cast< SwFlyFrameFormat * >( GetDep() );
    }

    void SwFlyFrame::Calc(vcl::RenderContext* pRenderContext) const
    {
        if ( !m_bValidContentPos )
            const_cast<SwFlyFrame*>(this)->PrepareMake(pRenderContext);
        else
            SwLayoutFrame::Calc(pRenderContext);
    }

    SwTwips SwFlyFrame::CalcContentHeight(const SwBorderAttrs *pAttrs, const SwTwips nMinHeight, const SwTwips nUL)
    {
        SwRectFnSet aRectFnSet(this);
        SwTwips nHeight = 0;
        if ( Lower() )
        {
            if ( Lower()->IsColumnFrame() )
            {
                FormatWidthCols( *pAttrs, nUL, nMinHeight );
                nHeight = aRectFnSet.GetHeight(Lower()->getFrameArea());
            }
            else
            {
                SwFrame *pFrame = Lower();
                while ( pFrame )
                {
                    nHeight += aRectFnSet.GetHeight(pFrame->getFrameArea());
                    if( pFrame->IsTextFrame() && static_cast<SwTextFrame*>(pFrame)->IsUndersized() )
                    // This TextFrame would like to be a bit larger
                        nHeight += static_cast<SwTextFrame*>(pFrame)->GetParHeight()
                                - aRectFnSet.GetHeight(pFrame->getFramePrintArea());
                    else if( pFrame->IsSctFrame() && static_cast<SwSectionFrame*>(pFrame)->IsUndersized() )
                        nHeight += static_cast<SwSectionFrame*>(pFrame)->Undersize();
                    pFrame = pFrame->GetNext();
                }
            }
            if ( GetDrawObjs() )
            {
                const size_t nCnt = GetDrawObjs()->size();
                SwTwips nTop = aRectFnSet.GetTop(getFrameArea());
                SwTwips nBorder = aRectFnSet.GetHeight(getFrameArea()) -
                aRectFnSet.GetHeight(getFramePrintArea());
                for ( size_t i = 0; i < nCnt; ++i )
                {
                    SwAnchoredObject* pAnchoredObj = (*GetDrawObjs())[i];
                    if ( dynamic_cast<const SwFlyFrame*>( pAnchoredObj) !=  nullptr )
                    {
                        SwFlyFrame* pFly = static_cast<SwFlyFrame*>(pAnchoredObj);
                        // OD 06.11.2003 #i22305# - consider
                        // only Writer fly frames, which follow the text flow.
                        if ( pFly->IsFlyLayFrame() &&
                            pFly->getFrameArea().Top() != FAR_AWAY &&
                            pFly->GetFormat()->GetFollowTextFlow().GetValue() )
                        {
                            SwTwips nDist = -aRectFnSet.BottomDist( pFly->getFrameArea(), nTop );
                            if( nDist > nBorder + nHeight )
                                nHeight = nDist - nBorder;
                        }
                    }
                }
            }
        }
        return nHeight;
    }

    /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

↑ V522 Dereferencing of the null pointer 'pAnchoredObj' might take place.