Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/sw/source/core/unocore/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 106 kB image not shown  

Quelle  unodraw.cxx

  Sprache: C
 

/* -*- 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 <sal/config.h>

#include <initializer_list>
#include <memory>
#include <string_view>

#include <sal/log.hxx>

#include <cmdid.h>
#include <unomid.h>

#include <drawdoc.hxx>
#include <unodraw.hxx>
#include <unoframe.hxx>
#include <unoparagraph.hxx>
#include <unotextrange.hxx>
#include <svx/svditer.hxx>
#include <swunohelper.hxx>
#include <textboxhelper.hxx>
#include <doc.hxx>
#include <IDocumentUndoRedo.hxx>
#include <IDocumentDrawModelAccess.hxx>
#include <IDocumentLayoutAccess.hxx>
#include <fmtcntnt.hxx>
#include <fmtflcnt.hxx>
#include <txatbase.hxx>
#include <docsh.hxx>
#include <unomap.hxx>
#include <unoport.hxx>
#include <TextCursorHelper.hxx>
#include <dflyobj.hxx>
#include <ndtxt.hxx>
#include <svx/svdview.hxx>
#include <svx/unoshape.hxx>
#include <dcontact.hxx>
#include <fmtornt.hxx>
#include <fmtsrnd.hxx>
#include <fmtfollowtextflow.hxx>
#include <rootfrm.hxx>
#include <editeng/lrspitem.hxx>
#include <editeng/ulspitem.hxx>
#include <o3tl/any.hxx>
#include <o3tl/safeint.hxx>
#include <crstate.hxx>
#include <comphelper/extract.hxx>
#include <comphelper/profilezone.hxx>
#include <comphelper/sequence.hxx>
#include <cppuhelper/supportsservice.hxx>
#include <svx/scene3d.hxx>
#include <tools/UnitConversion.hxx>
#include <com/sun/star/beans/PropertyAttribute.hpp>
#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
#include <com/sun/star/frame/XModel.hpp>
#include <fmtwrapinfluenceonobjpos.hxx>
#include <com/sun/star/text/TextContentAnchorType.hpp>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <com/sun/star/drawing/PointSequence.hpp>
#include <com/sun/star/lang/IllegalArgumentException.hpp>
#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
#include <docmodel/uno/UnoTheme.hxx>

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

class SwShapeDescriptor_Impl
{
    bool m_isInReading;
    std::unique_ptr<SwFormatHoriOrient> m_pHOrient;
    std::unique_ptr<SwFormatVertOrient> m_pVOrient;
    std::unique_ptr<SwFormatAnchor> m_pAnchor;
    std::unique_ptr<SwFormatSurround> m_pSurround;
    std::unique_ptr<SvxULSpaceItem> m_pULSpace;
    std::unique_ptr<SvxLRSpaceItem> m_pLRSpace;
    bool            m_bOpaque;
    uno::Reference< text::XTextRange > m_xTextRange;
    // #i26791#
    std::unique_ptr<SwFormatFollowTextFlow> m_pFollowTextFlow;
    // #i28701#
    std::unique_ptr<SwFormatWrapInfluenceOnObjPos> m_pWrapInfluenceOnObjPos;
    // #i28749#
    sal_Int16 mnPositionLayoutDir;

    SwShapeDescriptor_Impl(const SwShapeDescriptor_Impl&) = delete;
    SwShapeDescriptor_Impl& operator=(const SwShapeDescriptor_Impl&) = delete;

public:
    SwShapeDescriptor_Impl(SwDoc const*const pDoc)
        : m_isInReading(pDoc && pDoc->IsInReading())
     // #i32349# - no defaults, in order to determine on
     // adding a shape, if positioning attributes are set or not.
        , m_bOpaque(false)
     // #i26791#
        , m_pFollowTextFlow( new SwFormatFollowTextFlow(false) )
     // #i28701# #i35017#
        , m_pWrapInfluenceOnObjPos( new SwFormatWrapInfluenceOnObjPos(
                            text::WrapInfluenceOnPosition::ONCE_CONCURRENT) )
     // #i28749#
        , mnPositionLayoutDir(text::PositionLayoutDir::PositionInLayoutDirOfAnchor)
     {}

    SwFormatAnchor*    GetAnchor(bool bCreate = false)
        {
            if (bCreate && !m_pAnchor)
            {
                m_pAnchor.reset(new SwFormatAnchor(RndStdIds::FLY_AS_CHAR));
            }
            return m_pAnchor.get();
        }
    SwFormatHoriOrient* GetHOrient(bool bCreate = false)
        {
            if (bCreate && !m_pHOrient)
            {
                // #i26791#
                m_pHOrient.reset(new SwFormatHoriOrient(0, text::HoriOrientation::NONE, text::RelOrientation::FRAME));
            }
            return m_pHOrient.get();
        }
    SwFormatVertOrient* GetVOrient(bool bCreate = false)
        {
            if (bCreate && !m_pVOrient)
            {
                if (m_isInReading && // tdf#113938 extensions might rely on old default
                    (!GetAnchor(true) || m_pAnchor->GetAnchorId() == RndStdIds::FLY_AS_CHAR))
                {   // for as-char, NONE ("from-top") is not a good default
                    m_pVOrient.reset(new SwFormatVertOrient(0, text::VertOrientation::TOP, text::RelOrientation::FRAME));
                }
                else
                {   // #i26791#
                    m_pVOrient.reset(new SwFormatVertOrient(0, text::VertOrientation::NONE, text::RelOrientation::FRAME));
                }
            }
            return m_pVOrient.get();
        }

    SwFormatSurround*  GetSurround(bool bCreate = false)
        {
            if (bCreate && !m_pSurround)
            {
                m_pSurround.reset(new SwFormatSurround());
            }
            return m_pSurround.get();
        }
    SvxLRSpaceItem* GetLRSpace(bool bCreate = false)
        {
            if (bCreate && !m_pLRSpace)
            {
                m_pLRSpace.reset(new SvxLRSpaceItem(RES_LR_SPACE));
            }
            return m_pLRSpace.get();
        }
    SvxULSpaceItem* GetULSpace(bool bCreate = false)
        {
            if (bCreate && !m_pULSpace)
            {
                m_pULSpace.reset(new SvxULSpaceItem(RES_UL_SPACE));
            }
            return m_pULSpace.get();
        }
    uno::Reference< text::XTextRange > &    GetTextRange()
    {
        return m_xTextRange;
    }
    bool    IsOpaque() const
        {
            return m_bOpaque;
        }
    const bool&    GetOpaque() const
        {
            return m_bOpaque;
        }
    void RemoveHOrient() { m_pHOrient.reset(); }
    void RemoveVOrient() { m_pVOrient.reset(); }
    void RemoveAnchor() { m_pAnchor.reset(); }
    void RemoveSurround() { m_pSurround.reset(); }
    void RemoveULSpace() { m_pULSpace.reset(); }
    void RemoveLRSpace() { m_pLRSpace.reset(); }
    void SetOpaque(bool bSet){m_bOpaque = bSet;}

    // #i26791#
    SwFormatFollowTextFlow* GetFollowTextFlow( bool _bCreate = false )
    {
        if (_bCreate && !m_pFollowTextFlow)
        {
            m_pFollowTextFlow.reset(new SwFormatFollowTextFlow(false));
        }
        return m_pFollowTextFlow.get();
    }
    void RemoveFollowTextFlow()
    {
        m_pFollowTextFlow.reset();
    }

    // #i28749#
    sal_Int16 GetPositionLayoutDir() const
    {
        return mnPositionLayoutDir;
    }
    void SetPositionLayoutDir( sal_Int16 _nPositionLayoutDir )
    {
        switch ( _nPositionLayoutDir )
        {
            case text::PositionLayoutDir::PositionInHoriL2R:
            case text::PositionLayoutDir::PositionInLayoutDirOfAnchor:
            {
                mnPositionLayoutDir = _nPositionLayoutDir;
            }
            break;
            default:
            {
                OSL_FAIL( "<SwShapeDescriptor_Impl::SetPositionLayoutDir(..)> - invalid attribute value." );
            }
        }
    }

    // #i28701#
    SwFormatWrapInfluenceOnObjPos* GetWrapInfluenceOnObjPos(
                                        const bool _bCreate = false )
    {
        if (_bCreate && !m_pWrapInfluenceOnObjPos)
        {
            m_pWrapInfluenceOnObjPos.reset(new SwFormatWrapInfluenceOnObjPos(
                        // #i35017#
                        text::WrapInfluenceOnPosition::ONCE_CONCURRENT));
        }
        return m_pWrapInfluenceOnObjPos.get();
    }
    void RemoveWrapInfluenceOnObjPos()
    {
        m_pWrapInfluenceOnObjPos.reset();
    }
};

SwFmDrawPage::SwFmDrawPage( SwDoc* pDoc, SdrPage* pPage )
    : SwFmDrawPage_Base(pPage)
    , m_pDoc(pDoc)
    , m_pPageView(nullptr)
    , m_pPropertySet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_PAGE))
{
}

SwFmDrawPage::~SwFmDrawPage() noexcept
{
    while (!m_vShapes.empty())
        m_vShapes.back()->dispose();
    RemovePageView();
}

const SdrMarkList&  SwFmDrawPage::PreGroup(const uno::Reference< drawing::XShapes > &&nbsp;xShapes)
{
    SelectObjectsInView( xShapes, GetPageView() );
    const SdrMarkList& rMarkList = mpView->GetMarkedObjectList();
    return rMarkList;
}

void SwFmDrawPage::PreUnGroup(const uno::Reference< drawing::XShapeGroup >&  rShapeGroup)
{
    SelectObjectInView( rShapeGroup, GetPageView() );
}

SdrPageView*    SwFmDrawPage::GetPageView()
{
    if(!m_pPageView)
        m_pPageView = mpView->ShowSdrPage( mpPage );
    return m_pPageView;
}

void    SwFmDrawPage::RemovePageView()
{
    if(m_pPageView && mpView)
        mpView->HideSdrPage();
    m_pPageView = nullptr;
}

uno::Reference<drawing::XShape> SwFmDrawPage::GetShape(SdrObject* pObj)
{
    if(!pObj)
        return nullptr;
    SwFrameFormat* pFormat = ::FindFrameFormat( pObj );
    // TODO see comment at
    // <https://gerrit.libreoffice.org/c/core/+/78734/4#message-5ee4e724a8073c5c475f07da0b5d79bc34e61de5>
    // "make page bookkeep the SwXShapes" [-loplugin:crosscast]:
    SwFmDrawPage* pPage = dynamic_cast<SwFmDrawPage*>(pFormat);
    if(!pPage || pPage->m_vShapes.empty())
        return uno::Reference<drawing::XShape>(pObj->getUnoShape(), uno::UNO_QUERY);
    for(const auto & pShape : pPage->m_vShapes)
    {
        SvxShape* pSvxShape = pShape->GetSvxShape();
        if (pSvxShape && pSvxShape->GetSdrObject() == pObj)
            return pShape;
    }
    return nullptr;
}

uno::Reference<drawing::XShapeGroup> SwFmDrawPage::GetShapeGroup(SdrObject* pObj)
{
    return uno::Reference<drawing::XShapeGroup>(GetShape(pObj), uno::UNO_QUERY);
}

uno::Reference< drawing::XShape > SwFmDrawPage::CreateShape( SdrObject *pObj ) const
{
    assert(pObj);
    uno::Reference< drawing::XShape >  xRet;
    if(dynamic_cast<const SwVirtFlyDrawObj*>( pObj) !=  nullptr || pObj->GetObjInventor() == SdrInventor::Swg)
    {
        SwFlyDrawContact* pFlyContact = static_cast<SwFlyDrawContact*>(pObj->GetUserCall());
        if(pFlyContact)
        {
            SwFrameFormat* pFlyFormat = pFlyContact->GetFormat();
            SwDoc& rDoc = pFlyFormat->GetDoc();
            const SwNodeIndex* pIdx;
            if( RES_FLYFRMFMT == pFlyFormat->Which()
                && nullptr != ( pIdx = pFlyFormat->GetContent().GetContentIdx() )
                && pIdx->GetNodes().IsDocNodes()
                )
            {
                const SwNode* pNd = rDoc.GetNodes()[ pIdx->GetIndex() + 1 ];
                if(!pNd->IsNoTextNode())
                {
                    xRet.set(cppu::getXWeak(SwXTextFrame::CreateXTextFrame(rDoc, pFlyFormat).get()),
                            uno::UNO_QUERY);
                }
                else if( pNd->IsGrfNode() )
                {
                    xRet.set(cppu::getXWeak(SwXTextGraphicObject::CreateXTextGraphicObject(
                                rDoc, pFlyFormat).get()), uno::UNO_QUERY);
                }
                else if( pNd->IsOLENode() )
                {
                    xRet.set(cppu::getXWeak(SwXTextEmbeddedObject::CreateXTextEmbeddedObject(
                                rDoc, pFlyFormat).get()), uno::UNO_QUERY);
                }
            }
            else
            {
                OSL_FAIL( "<SwFmDrawPage::CreateShape(..)> - could not retrieve type. Thus, no shape created." );
                return xRet;
            }
        }
    }
    else
    {
        // own block - temporary object has to be destroyed before
        // the delegator is set #81670#
        {
            xRet = SvxDrawPage::CreateShape( pObj );
        }
        uno::Reference< XUnoTunnel > xShapeTunnel(xRet, uno::UNO_QUERY);
        //don't create an SwXShape if it already exists
        rtl::Reference<SwXShape> pShape = comphelper::getFromUnoTunnel<SwXShape>(xShapeTunnel);
        if(!pShape)
        {
            xShapeTunnel = nullptr;
            uno::Reference< uno::XInterface > xCreate(xRet, uno::UNO_QUERY);
            xRet = nullptr;
            if ( pObj->IsGroupObject() && (!pObj->Is3DObj() || DynCastE3dScene(pObj)) )
                pShape = new SwXGroupShape(xCreate, nullptr);
            else
                pShape = new SwXShape(xCreate, nullptr);
            xRet = pShape;
        }
        const_cast<std::vector<rtl::Reference<SwXShape>>*>(&m_vShapes)->push_back(pShape);
        pShape->m_pPage = this;
    }
    return xRet;
}

uno::Reference<beans::XPropertySetInfo> SwFmDrawPage::getPropertySetInfo()
{
    static uno::Reference<beans::XPropertySetInfo> xRet = m_pPropertySet->getPropertySetInfo();
    return xRet;
}

void SwFmDrawPage::setPropertyValue(const OUString& rPropertyName, const uno::Any&&nbsp;aValue)
{
    SolarMutexGuard aGuard;
    const SfxItemPropertyMapEntry* pEntry = m_pPropertySet->getPropertyMap().getByName(rPropertyName);

    switch (pEntry ? pEntry->nWID : -1)
    {
        case WID_PAGE_THEME:
        {
            SdrPage* pPage = GetSdrPage();
            css::uno::Reference<css::util::XTheme> xTheme;
            if (aValue >>= xTheme)
            {
                auto& rUnoTheme = dynamic_cast<UnoTheme&>(*xTheme);
                pPage->getSdrModelFromSdrPage().setTheme(rUnoTheme.getTheme());
            }
        }
        break;
        case WID_PAGE_BOTTOM:
        case WID_PAGE_LEFT:
        case WID_PAGE_RIGHT:
        case WID_PAGE_TOP:
        case WID_PAGE_WIDTH:
        case WID_PAGE_HEIGHT:
        case WID_PAGE_NUMBER:
        case WID_PAGE_ORIENT:
        case WID_PAGE_USERATTRIBS:
        case WID_PAGE_ISDARK:
        case WID_NAVORDER:
        case WID_PAGE_BACKFULL:
            break;

        default:
            throw beans::UnknownPropertyException(rPropertyName, getXWeak());
    }
}

uno::Any SwFmDrawPage::getPropertyValue(const OUString& rPropertyName)
{
    SolarMutexGuard aGuard;
    const SfxItemPropertyMapEntry* pEntry = m_pPropertySet->getPropertyMap().getByName( rPropertyName);

    uno::Any aAny;

    switch (pEntry ? pEntry->nWID : -1)
    {
        case WID_PAGE_THEME:
        {
            css::uno::Reference<css::util::XTheme> xTheme;

            auto pTheme = GetSdrPage()->getSdrModelFromSdrPage().getTheme();
            if (pTheme)
                xTheme = model::theme::createXTheme(pTheme);
            aAny <<= xTheme;
        }
        break;

        case WID_PAGE_NUMBER:
        {
            const sal_uInt16 nPageNumber(GetSdrPage()->GetPageNum());
            aAny <<= o3tl::narrowing<sal_Int16>(nPageNumber);
        }
        break;

        case WID_PAGE_BOTTOM:
        case WID_PAGE_LEFT:
        case WID_PAGE_RIGHT:
        case WID_PAGE_TOP:
        case WID_PAGE_WIDTH:
        case WID_PAGE_HEIGHT:
        case WID_PAGE_ORIENT:
        case WID_PAGE_USERATTRIBS:
        case WID_PAGE_ISDARK:
        case WID_NAVORDER:
        case WID_PAGE_BACKFULL:
            break;

        default:
            throw beans::UnknownPropertyException(rPropertyName, getXWeak());
    }
    return aAny;
}

void SwFmDrawPage::addPropertyChangeListener(const OUString& /*PropertyName*/,
    const uno::Reference<beans::XPropertyChangeListener> & /*aListener*/)
{
    OSL_FAIL("not implemented");
}

void SwFmDrawPage::removePropertyChangeListener(const OUString& /*PropertyName*/,
    const uno::Reference<beans::XPropertyChangeListener> & /*aListener*/)
{
    OSL_FAIL("not implemented");
}

void SwFmDrawPage::addVetoableChangeListener(const OUString& /*PropertyName*/,
    const uno::Reference<beans::XVetoableChangeListener> & /*aListener*/)
{
    OSL_FAIL("not implemented");
}

void SwFmDrawPage::removeVetoableChangeListener(const OUString& /*PropertyName*/,
    const uno::Reference<beans::XVetoableChangeListener> & /*aListener*/)
{
    OSL_FAIL("not implemented");
}

namespace
{
    class SwXShapesEnumeration
        : public SwSimpleEnumeration_Base
    {
        private:
            std::vector< css::uno::Any > m_aShapes;
        protected:
            virtual ~SwXShapesEnumeration() override {};
        public:
            explicit SwXShapesEnumeration(SwFmDrawPage* const pDrawPage);

            //XEnumeration
            virtual sal_Bool SAL_CALL hasMoreElements() override;
            virtual uno::Any SAL_CALL nextElement() override;

            //XServiceInfo
            virtual OUString SAL_CALL getImplementationName() override;
            virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
            virtual uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
    };
}

SwXShapesEnumeration::SwXShapesEnumeration(SwFmDrawPage* const pDrawPage)
{
    SolarMutexGuard aGuard;
    sal_Int32 nCount = pDrawPage->getCount();
    m_aShapes.reserve(nCount);
    for(sal_Int32 nIdx = 0; nIdx < nCount; nIdx++)
    {
        uno::Reference<drawing::XShape> xShape(pDrawPage->getByIndex(nIdx), uno::UNO_QUERY);
        m_aShapes.push_back(uno::Any(xShape));
    }
}

sal_Bool SwXShapesEnumeration::hasMoreElements()
{
    SolarMutexGuard aGuard;
    return !m_aShapes.empty();
}

uno::Any SwXShapesEnumeration::nextElement()
{
    SolarMutexGuard aGuard;
    if(m_aShapes.empty())
        throw container::NoSuchElementException();
    uno::Any aResult = m_aShapes.back();
    m_aShapes.pop_back();
    return aResult;
}

OUString SwXShapesEnumeration::getImplementationName()
{
    return u"SwXShapeEnumeration"_ustr;
}

sal_Bool SwXShapesEnumeration::supportsService(const OUString& ServiceName)
{
    return cppu::supportsService(this, ServiceName);
}

uno::Sequence< OUString > SwXShapesEnumeration::getSupportedServiceNames()
{
    return { u"com.sun.star.container.XEnumeration"_ustr };
}

uno::Reference< container::XEnumeration > SwFmDrawPage::createEnumeration()
{
    SolarMutexGuard aGuard;
    return uno::Reference< container::XEnumeration >(
        new SwXShapesEnumeration(this));
}

OUString SwFmDrawPage::getImplementationName()
{
    return u"SwFmDrawPage"_ustr;
}

sal_Bool SwFmDrawPage::supportsService(const OUString& rServiceName)
{
    return cppu::supportsService(this, rServiceName);
}

uno::Sequence< OUString > SwFmDrawPage::getSupportedServiceNames()
{
    return { u"com.sun.star.drawing.GenericDrawPage"_ustr };
}

sal_Int32 SwFmDrawPage::getCount()
{
    SolarMutexGuard aGuard;
    if(!m_pDoc)
        throw uno::RuntimeException();
    if(!m_pDoc->getIDocumentDrawModelAccess().GetDrawModel())
        return 0;
    else
        return SwTextBoxHelper::getCount(GetSdrPage());
}

uno::Any SwFmDrawPage::getByIndex(sal_Int32 nIndex)
{
    SolarMutexGuard aGuard;
    if(!m_pDoc)
        throw uno::RuntimeException();
    if(!m_pDoc->getIDocumentDrawModelAccess().GetDrawModel())
        throw lang::IndexOutOfBoundsException();

    return SwTextBoxHelper::getByIndex(GetSdrPage(), nIndex);
}

uno::Type  SwFmDrawPage::getElementType()
{
    return cppu::UnoType<drawing::XShape>::get();
}

sal_Bool SwFmDrawPage::hasElements()
{
    SolarMutexGuard aGuard;
    if(!m_pDoc)
        throw uno::RuntimeException();
    if(!m_pDoc->getIDocumentDrawModelAccess().GetDrawModel())
        return false;
    return SvxDrawPage::hasElements();
}

void SwFmDrawPage::add(const uno::Reference< drawing::XShape > & xShape)
{
    SolarMutexGuard aGuard;
    if(!m_pDoc)
        throw uno::RuntimeException();
    uno::Reference< lang::XUnoTunnel > xShapeTunnel(xShape, uno::UNO_QUERY);
    SwXShape* pShape = comphelper::getFromUnoTunnel<SwXShape>(xShapeTunnel);
    SvxShape* pSvxShape = comphelper::getFromUnoTunnel<SvxShape>(xShapeTunnel);

    // this is not a writer shape
    if(!pShape)
        throw uno::RuntimeException(u"illegal object"_ustr,
                                    getXWeak() );

    // we're already registered in the model / SwXDrawPage::add() already called
    if(pShape->m_pPage || !pShape->m_bDescriptor )
        return;

    // we're inserted elsewhere already
    if ( pSvxShape->GetSdrObject() )
    {
        if ( pSvxShape->GetSdrObject()->IsInserted() )
        {
            return;
        }
    }
    SvxDrawPage::add(xShape);

    OSL_ENSURE(pSvxShape, "Why is here no SvxShape?");
    // this position is definitely in 1/100 mm
    awt::Point aMM100Pos(pSvxShape->getPosition());

    // now evaluate the properties of SwShapeDescriptor_Impl
    SwShapeDescriptor_Impl* pDesc = pShape->GetDescImpl();

    SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END-1> aSet( m_pDoc->GetAttrPool() );
    SwFormatAnchor aAnchor( RndStdIds::FLY_AS_CHAR );
    bool bOpaque = false;
    if( pDesc )
    {
        if(pDesc->GetSurround())
            aSet.Put( *pDesc->GetSurround());
        // all items are already in Twip
        if(pDesc->GetLRSpace())
        {
            aSet.Put(*pDesc->GetLRSpace());
        }
        if(pDesc->GetULSpace())
        {
            aSet.Put(*pDesc->GetULSpace());
        }
        if(pDesc->GetAnchor())
            aAnchor = *pDesc->GetAnchor();

        // #i32349# - if no horizontal position exists, create one
        if ( !pDesc->GetHOrient() )
        {
            SwFormatHoriOrient* pHori = pDesc->GetHOrient( true );
            SwTwips nHoriPos = o3tl::toTwips(aMM100Pos.X, o3tl::Length::mm100);
            pHori->SetPos( nHoriPos );
        }
        {
            if(pDesc->GetHOrient()->GetHoriOrient() == text::HoriOrientation::NONE)
                aMM100Pos.X = convertTwipToMm100(pDesc->GetHOrient()->GetPos());
            aSet.Put( *pDesc->GetHOrient() );
        }
        // #i32349# - if no vertical position exists, create one
        if ( !pDesc->GetVOrient() )
        {
            SwFormatVertOrient* pVert = pDesc->GetVOrient( true );
            SwTwips nVertPos = o3tl::toTwips(aMM100Pos.Y, o3tl::Length::mm100);
            pVert->SetPos( nVertPos );
        }
        {
            if(pDesc->GetVOrient()->GetVertOrient() == text::VertOrientation::NONE)
                aMM100Pos.Y = convertTwipToMm100(pDesc->GetVOrient()->GetPos());
            aSet.Put( *pDesc->GetVOrient() );
        }

        if(pDesc->GetSurround())
            aSet.Put( *pDesc->GetSurround());
        bOpaque = pDesc->IsOpaque();

        // #i26791#
        if ( pDesc->GetFollowTextFlow() )
        {
            aSet.Put( *pDesc->GetFollowTextFlow() );
        }

        // #i28701#
        if ( pDesc->GetWrapInfluenceOnObjPos() )
        {
            aSet.Put( *pDesc->GetWrapInfluenceOnObjPos() );
        }
    }

    pSvxShape->setPosition(aMM100Pos);
    SdrObject* pObj = pSvxShape->GetSdrObject();
    // #108784# - set layer of new drawing object to corresponding
    // invisible layer.
    if(SdrInventor::FmForm != pObj->GetObjInventor())
        pObj->SetLayer( bOpaque ? m_pDoc->getIDocumentDrawModelAccess().GetInvisibleHeavenId() : m_pDoc->getIDocumentDrawModelAccess().GetInvisibleHellId() );
    else
        pObj->SetLayer(m_pDoc->getIDocumentDrawModelAccess().GetInvisibleControlsId());

    std::optional<SwPaM> pPam(m_pDoc->GetNodes().GetEndOfContent());
    std::unique_ptr<SwUnoInternalPaM> pInternalPam;
    uno::Reference< text::XTextRange >  xRg;
    if( pDesc && (xRg = pDesc->GetTextRange()).is() )
    {
        pInternalPam.reset(new SwUnoInternalPaM(*m_pDoc));
        if (!::sw::XTextRangeToSwPaM(*pInternalPam, xRg))
            throw uno::RuntimeException();

        if(RndStdIds::FLY_AT_FLY == aAnchor.GetAnchorId() &&
                            !pInternalPam->GetPointNode().FindFlyStartNode())
        {
                    aAnchor.SetType(RndStdIds::FLY_AS_CHAR);
        }
        else if (RndStdIds::FLY_AT_PAGE == aAnchor.GetAnchorId()
                    && 0 == aAnchor.GetPageNum())
        {
            aAnchor.SetAnchor(pInternalPam->Start());
            aAnchor.SetType(RndStdIds::FLY_AT_CHAR); // convert invalid at-page
        }

    }
    else if ((aAnchor.GetAnchorId() != RndStdIds::FLY_AT_PAGE) && m_pDoc->getIDocumentLayoutAccess().GetCurrentLayout())
    {
        SwCursorMoveState aState( CursorMoveState::SetOnlyText );
        Point aTmp(o3tl::toTwips(aMM100Pos.X, o3tl::Length::mm100), o3tl::toTwips(aMM100Pos.Y, o3tl::Length::mm100));
        m_pDoc->getIDocumentLayoutAccess().GetCurrentLayout()->GetModelPositionForViewPoint( pPam->GetPoint(), aTmp, &aState );
        aAnchor.SetAnchor( pPam->GetPoint() );

        // #i32349# - adjustment of vertical positioning
        // attributes no longer needed, because it's already got a default.
    }
    else
    {
        aAnchor.SetType(RndStdIds::FLY_AT_PAGE);

        // #i32349# - adjustment of vertical positioning
        // attributes no longer needed, because it's already got a default.
    }
    aSet.Put(aAnchor);
    SwPaM* pTemp = pInternalPam.get();
    if ( !pTemp )
        pTemp = &*pPam;
    UnoActionContext aAction(m_pDoc);
    m_pDoc->getIDocumentContentOperations().InsertDrawObj( *pTemp, *pObj, aSet );

    if (pSvxShape->GetSdrObject()->GetName().isEmpty())
    {
        pSvxShape->GetSdrObject()->SetName(m_pDoc->GetUniqueShapeName().toString());
    }

    SwFrameFormat* pFormat = ::FindFrameFormat( pObj );
    if (pFormat)
    {
        if (pFormat->GetName().isEmpty())
        {
            pFormat->SetFormatName(UIName(pSvxShape->GetSdrObject()->GetName()), false);
        }
    }
    pShape->m_bDescriptor = false;

    pPam.reset();
    pInternalPam.reset();
}

void SwFmDrawPage::remove(const uno::Reference< drawing::XShape > & xShape)
{
    SolarMutexGuard aGuard;
    if(!m_pDoc)
        throw uno::RuntimeException();
    // tdf#41466 remove TextFrame too which is belonged to the actual shape
    auto xTextFrame = SwTextBoxHelper::getUnoTextFrame(xShape);
    if (xTextFrame)
    {
        uno::Reference<lang::XComponent> xComp(xTextFrame, uno::UNO_QUERY);
        if (xComp)
            xComp->dispose();
    }
    // remove shape
    uno::Reference<lang::XComponent> xComp(xShape, uno::UNO_QUERY);
    xComp->dispose();
}

uno::Reference< drawing::XShapeGroup >  SwFmDrawPage::group(const uno::Reference< drawing::XShapes > & xShapes)
{
    SolarMutexGuard aGuard;
    if(!m_pDoc || !xShapes.is())
        throw uno::RuntimeException();
    uno::Reference< drawing::XShapeGroup >  xRet;
    // mark and return MarkList
    const SdrMarkList& rMarkList = PreGroup(xShapes);
    if ( rMarkList.GetMarkCount() > 0 )
    {
        for (size_t i = 0; i < rMarkList.GetMarkCount(); ++i)
        {
            const SdrObject *pObj = rMarkList.GetMark( i )->GetMarkedSdrObj();
            if (RndStdIds::FLY_AS_CHAR == ::FindFrameFormat(const_cast<SdrObject*>(
                                    pObj))->GetAnchor().GetAnchorId())
            {
                throw lang::IllegalArgumentException(
                    u"Shape must not have 'as character' anchor!"_ustr, nullptr, 0);
            }
        }

        UnoActionContext aContext(m_pDoc);
        m_pDoc->GetIDocumentUndoRedo().StartUndo( SwUndoId::START, nullptr );

        SwDrawContact* pContact = m_pDoc->GroupSelection( *GetDrawView() );
        m_pDoc->ChgAnchor(
            GetDrawView()->GetMarkedObjectList(),
            RndStdIds::FLY_AT_PARA,
            truefalse );

        GetDrawView()->UnmarkAll();
        if(pContact)
            xRet = SwFmDrawPage::GetShapeGroup( pContact->GetMaster() );
        m_pDoc->GetIDocumentUndoRedo().EndUndo( SwUndoId::END, nullptr );
    }
    RemovePageView();
    return xRet;
}

void SwFmDrawPage::ungroup(const uno::Reference< drawing::XShapeGroup > & rShapeGroup)
{
    SolarMutexGuard aGuard;
    if(!m_pDoc)
        throw uno::RuntimeException();

    PreUnGroup(rShapeGroup);
    UnoActionContext aContext(m_pDoc);
    m_pDoc->GetIDocumentUndoRedo().StartUndo( SwUndoId::START, nullptr );

    m_pDoc->UnGroupSelection( *GetDrawView() );
    m_pDoc->ChgAnchor( GetDrawView()->GetMarkedObjectList(),
                RndStdIds::FLY_AT_PARA,
                truefalse );
    m_pDoc->GetIDocumentUndoRedo().EndUndo( SwUndoId::END, nullptr );
    RemovePageView();
}

/**
 * Renamed and outlined to detect where it's called
 */

void SwFmDrawPage::InvalidateSwDoc()
{
    m_pDoc = nullptr;
}

const uno::Sequence< sal_Int8 > & SwXShape::getUnoTunnelId()
{
    static const comphelper::UnoIdInit theSwXShapeUnoTunnelId;
    return theSwXShapeUnoTunnelId.getSeq();
}

sal_Int64 SAL_CALL SwXShape::getSomething( const uno::Sequence< sal_Int8 >& rId )
{
    if( comphelper::isUnoTunnelId<SwXShape>(rId) )
    {
        return comphelper::getSomething_cast(this);
    }

    if( m_xShapeAgg.is() )
    {
        const uno::Type& rTunnelType = cppu::UnoType<lang::XUnoTunnel>::get();
        uno::Any aAgg = m_xShapeAgg->queryAggregation( rTunnelType );
        if(auto xAggTunnel = o3tl::tryAccess<uno::Reference<lang::XUnoTunnel>>(
               aAgg))
        {
            if(xAggTunnel->is())
                return (*xAggTunnel)->getSomething(rId);
        }
    }
    return 0;
}

SwXShape::SwXShape(
        uno::Reference<uno::XInterface> & xShape,
        SwDoc const*const pDoc)
    : m_pPage(nullptr)
    , m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_TEXT_SHAPE))
    , m_pPropertyMapEntries(aSwMapProvider.GetPropertyMapEntries(PROPERTY_MAP_TEXT_SHAPE))
    , m_pImpl(new SwShapeDescriptor_Impl(pDoc))
    , m_bDescriptor(true)
{
    if(!xShape.is())  // default Ctor
        return;

    const uno::Type& rAggType = cppu::UnoType<uno::XAggregation>::get();
    //aAgg contains a reference of the SvxShape!
    {
        uno::Any aAgg = xShape->queryInterface(rAggType);
        aAgg >>= m_xShapeAgg;
        // #i31698#
        if ( m_xShapeAgg.is() )
        {
            m_xShapeAgg->queryAggregation( cppu::UnoType<drawing::XShape>::get()) >>= mxShape;
            OSL_ENSURE( mxShape.is(),
                    "<SwXShape::SwXShape(..)> - no XShape found at <xShapeAgg>" );
        }
    }
    xShape = nullptr;
    osl_atomic_increment(&m_refCount);
    if( m_xShapeAgg.is() )
        m_xShapeAgg->setDelegator( getXWeak() );
    osl_atomic_decrement(&m_refCount);
}

SwFrameFormat* SwXShape::GetFrameFormat() const
{
    SdrObject* pObj = SdrObject::getSdrObjectFromXShape(m_xShapeAgg);
    if(pObj)
        return ::FindFrameFormat( pObj );
    return nullptr;
}

void SwXShape::AddExistingShapeToFormat( SdrObject const & _rObj )
{
    SdrObjListIter aIter( _rObj, SdrIterMode::DeepNoGroups );
    while ( aIter.IsMore() )
    {
        SdrObject* pCurrent = aIter.Next();
        OSL_ENSURE( pCurrent, "SwXShape::AddExistingShapeToFormat: invalid object list element!" );
        if ( !pCurrent )
            continue;

        auto pSwShape = comphelper::getFromUnoTunnel<SwXShape>(pCurrent->getWeakUnoShape());
        if ( pSwShape )
        {
            if ( pSwShape->m_bDescriptor )
                pSwShape->m_bDescriptor = false;
        }
    }
}

SwXShape::~SwXShape()
{
    SolarMutexGuard aGuard;

    if (m_xShapeAgg.is())
    {
        uno::Reference< uno::XInterface >  xRef;
        m_xShapeAgg->setDelegator(xRef);
    }
    m_pImpl.reset();
    if(m_pPage)
       const_cast<SwFmDrawPage*>(m_pPage)->RemoveShape(this);
    // these have to be destructed under the solarmutex
    m_xShapeAgg.clear();
    mxShape.clear();
}

uno::Any SwXShape::queryInterface( const uno::Type& aType )
{
    uno::Any aRet;
    SdrObject* pObj = nullptr;

    if ((aType == cppu::UnoType<text::XText>::get())
        || (aType == cppu::UnoType<text::XTextRange>::get())
        || (aType == cppu::UnoType<text::XTextAppend>::get()))
    {
        pObj = SdrObject::getSdrObjectFromXShape(mxShape);

        aRet = SwTextBoxHelper::queryInterface(GetFrameFormat(), aType, pObj);
        if (aRet.hasValue())
            return aRet;
    }
    aRet = SwXShapeBaseClass::queryInterface(aType);
    // #i53320# - follow-up of #i31698#
    // interface drawing::XShape is overloaded. Thus, provide
    // correct object instance.
    if(!aRet.hasValue() && m_xShapeAgg.is())
    {
        if(aType == cppu::UnoType<XShape>::get())
            aRet <<= uno::Reference<XShape>(this);
        else
            aRet = m_xShapeAgg->queryAggregation(aType);
    }
    return aRet;
}

uno::Sequence< uno::Type > SwXShape::getTypes(  )
{
    uno::Sequence< uno::Type > aRet = SwXShapeBaseClass::getTypes();
    if(m_xShapeAgg.is())
    {
        uno::Any aProv = m_xShapeAgg->queryAggregation(cppu::UnoType<XTypeProvider>::get());
        if(aProv.hasValue())
        {
            uno::Reference< XTypeProvider > xAggProv;
            aProv >>= xAggProv;
            return comphelper::concatSequences(aRet, xAggProv->getTypes());
        }
    }
    return aRet;
}

uno::Sequence< sal_Int8 > SwXShape::getImplementationId(  )
{
    return css::uno::Sequence<sal_Int8>();
}

uno::Reference< beans::XPropertySetInfo >  SwXShape::getPropertySetInfo()
{
    SolarMutexGuard aGuard;
    if (!mxPropertySetInfo)
    {
        if(m_xShapeAgg.is())
        {
            const uno::Type& rPropSetType = cppu::UnoType<beans::XPropertySet>::get();
            uno::Any aPSet = m_xShapeAgg->queryAggregation( rPropSetType );
            if(auto xPrSet = o3tl::tryAccess<uno::Reference<beans::XPropertySet>>(
                   aPSet))
            {
                uno::Reference< beans::XPropertySetInfo >  xInfo = (*xPrSet)->getPropertySetInfo();
                // Expand PropertySetInfo!
                const uno::Sequence<beans::Property> aPropSeq = xInfo->getProperties();
                mxPropertySetInfo = new SfxExtItemPropertySetInfo( m_pPropertyMapEntries, aPropSeq );
            }
        }
        if(!mxPropertySetInfo)
            mxPropertySetInfo = m_pPropSet->getPropertySetInfo();
    }
    return mxPropertySetInfo;
}

void SwXShape::setPropertyValue(const OUString& rPropertyName, const uno::Any& ;aValue)
{
    SolarMutexGuard aGuard;
    SwFrameFormat*   pFormat = GetFrameFormat();
    const SfxItemPropertyMapEntry*  pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName );
    if(!m_xShapeAgg.is())
        return;

    if(pEntry)
    {
        if ( pEntry->nFlags & beans::PropertyAttribute::READONLY)
            throw beans::PropertyVetoException ("Property is read-only: " + rPropertyName, getXWeak() );
        // with the layout it is possible to move the anchor without changing the position
        if(pFormat)
        {
            SwAttrSet aSet(pFormat->GetAttrSet());
            SwDoc& rDoc = pFormat->GetDoc();
            if(RES_ANCHOR == pEntry->nWID && MID_ANCHOR_ANCHORFRAME == pEntry->nMemberId)
            {
                bool bDone = false;
                uno::Reference<text::XTextFrame> xFrame;
                if(aValue >>= xFrame)
                {
                    SwXFrame* pFrame = dynamic_cast<SwXFrame*>(xFrame.get());
                    if(pFrame && pFrame->GetFrameFormat() &&
                        &pFrame->GetFrameFormat()->GetDoc() == &rDoc)
                    {
                        UnoActionContext aCtx(&rDoc);
                        SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END - 1> aItemSet( rDoc.GetAttrPool() );
                        aItemSet.SetParent(&pFormat->GetAttrSet());
                        SwFormatAnchor aAnchor = static_cast<const SwFormatAnchor&>(aItemSet.Get(pEntry->nWID));
                        SwPosition aPos(*pFrame->GetFrameFormat()->GetContent().GetContentIdx());
                        aAnchor.SetAnchor(&aPos);
                        aAnchor.SetType(RndStdIds::FLY_AT_FLY);
                        aItemSet.Put(aAnchor);
                        pFormat->SetFormatAttr(aItemSet);
                        bDone = true;
                    }
                }
                if(!bDone)
                    throw lang::IllegalArgumentException();
            }
            else if(RES_OPAQUE == pEntry->nWID)
            {
                SvxShape* pSvxShape = GetSvxShape();
                SAL_WARN_IF(!pSvxShape, "sw.uno""No SvxShape found!");
                if(pSvxShape)
                {
                    SdrObject* pObj = pSvxShape->GetSdrObject();
                    // set layer of new drawing
                    // object to corresponding invisible layer.
                    bool bIsVisible = rDoc.getIDocumentDrawModelAccess().IsVisibleLayerId( pObj->GetLayer() );
                    if(SdrInventor::FmForm != pObj->GetObjInventor())
                    {
                        pObj->SetLayer( *o3tl::doAccess<bool>(aValue)
                                        ? ( bIsVisible ? rDoc.getIDocumentDrawModelAccess().GetHeavenId() : rDoc.getIDocumentDrawModelAccess().GetInvisibleHeavenId() )
                                        : ( bIsVisible ? rDoc.getIDocumentDrawModelAccess().GetHellId() : rDoc.getIDocumentDrawModelAccess().GetInvisibleHellId() ));
                    }
                    else
                    {
                        pObj->SetLayer( bIsVisible ? rDoc.getIDocumentDrawModelAccess().GetControlsId() : rDoc.getIDocumentDrawModelAccess().GetInvisibleControlsId());
                    }

                }

            }
            // #i26791# - special handling for property FN_TEXT_RANGE
            else if ( FN_TEXT_RANGE == pEntry->nWID )
            {
                SwFormatAnchor aAnchor( aSet.Get( RES_ANCHOR ) );
                if (aAnchor.GetAnchorId() == RndStdIds::FLY_AT_PAGE)
                {
                    // set property <TextRange> not valid for to-page anchored shapes
                    throw lang::IllegalArgumentException();
                }

                std::unique_ptr<SwUnoInternalPaM> pInternalPam(
                                new SwUnoInternalPaM( pFormat->GetDoc() ));
                uno::Reference< text::XTextRange > xRg;
                aValue >>= xRg;
                if (!::sw::XTextRangeToSwPaM(*pInternalPam, xRg) )
                {
                    throw uno::RuntimeException();
                }

                if (aAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR)
                {
                    //delete old SwFormatFlyCnt
                    //With AnchorAsCharacter the current TextAttribute has to be deleted.
                    //Tbis removes the frame format too.
                    //To prevent this the connection between format and attribute has to be broken before.
                    SwTextNode *pTextNode = aAnchor.GetAnchorNode()->GetTextNode();
                    SAL_WARN_IF( !pTextNode->HasHints(), "sw.uno""Missing FlyInCnt-Hint." );
                    const sal_Int32 nIdx = aAnchor.GetAnchorContentOffset();
                    SwTextAttr * const pHint =
                            pTextNode->GetTextAttrForCharAt(
                            nIdx, RES_TXTATR_FLYCNT );
                    assert(pHint && "Missing Hint.");
                    SAL_WARN_IF( pHint->Which() != RES_TXTATR_FLYCNT,
                                "sw.uno""Missing FlyInCnt-Hint." );
                    SAL_WARN_IF( pHint->GetFlyCnt().GetFrameFormat() != pFormat,
                                "sw.uno""Wrong TextFlyCnt-Hint." );
                    const_cast<SwFormatFlyCnt&>(pHint->GetFlyCnt())
                        .SetFlyFormat();

                    //The connection is removed now the attribute can be deleted.
                    pTextNode->DeleteAttributes( RES_TXTATR_FLYCNT, nIdx );
                    //create a new one
                    SwTextNode *pNd = pInternalPam->GetPointNode().GetTextNode();
                    SAL_WARN_IF( !pNd, "sw.uno""Cursor not at TextNode." );
                    SwFormatFlyCnt aFormat( pFormat );
                    pNd->InsertItem(aFormat, pInternalPam->GetPoint()
                            ->GetContentIndex(), 0 );
                    //Refetch in case SwTextNode::InsertItem causes it to be deleted
                    pFormat = GetFrameFormat();
                }
                else
                {
                    aAnchor.SetAnchor( pInternalPam->GetPoint() );
                    aSet.Put(aAnchor);
                    pFormat->SetFormatAttr(aSet);
                }
            }
            else if (pEntry->nWID == FN_TEXT_BOX)
            {
                auto pObj = SdrObject::getSdrObjectFromXShape(mxShape);
                if (pEntry->nMemberId == MID_TEXT_BOX)
                {
                    bool bValue(false);
                    aValue >>= bValue;

                    if (bValue)
                        SwTextBoxHelper::create(pFormat, pObj);
                    else
                        SwTextBoxHelper::destroy(pFormat, pObj);
                }
                else if (pEntry->nMemberId == MID_TEXT_BOX_CONTENT)
                {
                    if (uno::Reference<text::XTextFrame> xTextFrame; aValue >>= xTextFrame)
                        SwTextBoxHelper::set(pFormat, pObj, xTextFrame);
                    else
                        SAL_WARN( "sw.uno""This is not a TextFrame!" );
                }
            }
            else if (pEntry->nWID == RES_CHAIN)
            {
                if (pEntry->nMemberId == MID_CHAIN_NEXTNAME || pEntry->nMemberId == MID_CHAIN_PREVNAME)
                    SwTextBoxHelper::syncProperty(pFormat, pEntry->nWID, pEntry->nMemberId, aValue,
                                                  SdrObject::getSdrObjectFromXShape(mxShape));
            }
            // #i28749#
            else if ( FN_SHAPE_POSITION_LAYOUT_DIR == pEntry->nWID )
            {
                sal_Int16 nPositionLayoutDir = 0;
                aValue >>= nPositionLayoutDir;
                pFormat->SetPositionLayoutDir( nPositionLayoutDir );
            }
            else if( rDoc.getIDocumentLayoutAccess().GetCurrentLayout())
            {
                UnoActionContext aCtx(&rDoc);
                if(RES_ANCHOR == pEntry->nWID && MID_ANCHOR_ANCHORTYPE == pEntry->nMemberId)
                {
                    SdrObject* pObj = pFormat->FindSdrObject();
                    SdrMarkList aList;
                    SdrMark aMark(pObj);
                    aList.InsertEntry(aMark);
                    sal_Int32 nAnchor = 0;
                    cppu::enum2int( nAnchor, aValue );
                    rDoc.ChgAnchor( aList, static_cast<RndStdIds>(nAnchor),
                                            falsetrue );
                }
                else
                {
                    SfxItemPropertySet::setPropertyValue(*pEntry, aValue, aSet);
                    pFormat->SetFormatAttr(aSet);
                }
            }
            else if( RES_FRM_SIZE == pEntry->nWID &&
                    ( pEntry->nMemberId == MID_FRMSIZE_REL_HEIGHT || pEntry->nMemberId == MID_FRMSIZE_REL_WIDTH
                      || pEntry->nMemberId == MID_FRMSIZE_REL_HEIGHT_RELATION
                      || pEntry->nMemberId == MID_FRMSIZE_REL_WIDTH_RELATION ) )
            {
                SvxShape* pSvxShape = GetSvxShape();
                SAL_WARN_IF(!pSvxShape, "sw.uno""No SvxShape found!");
                if(pSvxShape)
                {
                    SdrObject* pObj = pSvxShape->GetSdrObject();
                    sal_Int16 nPercent(100);
                    aValue >>= nPercent;
                    switch (pEntry->nMemberId)
                    {
                    case MID_FRMSIZE_REL_WIDTH:
                        pObj->SetRelativeWidth( nPercent / 100.0 );
                    break;
                    case MID_FRMSIZE_REL_HEIGHT:
                        pObj->SetRelativeHeight( nPercent / 100.0 );
                    break;
                    case MID_FRMSIZE_REL_WIDTH_RELATION:
                        pObj->SetRelativeWidthRelation(nPercent);
                    break;
                    case MID_FRMSIZE_REL_HEIGHT_RELATION:
                        pObj->SetRelativeHeightRelation(nPercent);
                    break;
                    }
                }
            }
            else if (pEntry->nWID == RES_HORI_ORIENT
                && pEntry->nMemberId == MID_HORIORIENT_RELATION
                && aSet.Get(RES_ANCHOR).GetAnchorId() == RndStdIds::FLY_AT_PAGE)
            {
                uno::Any value(aValue);
                sal_Int16 nRelOrient(text::RelOrientation::PAGE_FRAME);
                aValue >>= nRelOrient;
                if (sw::GetAtPageRelOrientation(nRelOrient, true))
                {
                    SAL_WARN("sw.core""SwXShape: fixing invalid horizontal RelOrientation for at-page anchor");
                    value <<= nRelOrient;
                }
                SfxItemPropertySet::setPropertyValue( *pEntry, value, aSet );
                pFormat->SetFormatAttr(aSet);
            }
            else
            {
                SfxItemPropertySet::setPropertyValue( *pEntry, aValue, aSet );

                if(RES_ANCHOR == pEntry->nWID && MID_ANCHOR_ANCHORTYPE == pEntry->nMemberId)
                {
                    bool bSetAttr = true;
                    text::TextContentAnchorType eNewAnchor = static_cast<text::TextContentAnchorType>(SWUnoHelper::GetEnumAsInt32( aValue ));

                    //if old anchor was in_cntnt the related text attribute has to be removed
                    const SwFormatAnchor& rOldAnchor = pFormat->GetAnchor();
                    RndStdIds eOldAnchorId = rOldAnchor.GetAnchorId();
                    SdrObject* pObj = pFormat->FindSdrObject();
                    SwFrameFormat *pFlyFormat = FindFrameFormat( pObj );
                    pFlyFormat->DelFrames();
                    if( text::TextContentAnchorType_AS_CHARACTER != eNewAnchor &&
                        (RndStdIds::FLY_AS_CHAR == eOldAnchorId))
                    {
                        //With AnchorAsCharacter the current TextAttribute has to be deleted.
                        //Tbis removes the frame format too.
                        //To prevent this the connection between format and attribute has to be broken before.
                        SwTextNode *pTextNode = rOldAnchor.GetAnchorNode()->GetTextNode();
                        SAL_WARN_IF( !pTextNode->HasHints(), "sw.uno""Missing FlyInCnt-Hint." );
                        const sal_Int32 nIdx = rOldAnchor.GetAnchorContentOffset();
                        SwTextAttr * const pHint =
                            pTextNode->GetTextAttrForCharAt(
                                nIdx, RES_TXTATR_FLYCNT );
                        assert(pHint && "Missing Hint.");
                        SAL_WARN_IF( pHint->Which() != RES_TXTATR_FLYCNT,
                                    "sw.uno""Missing FlyInCnt-Hint." );
                        SAL_WARN_IF( pHint->GetFlyCnt().GetFrameFormat() != pFlyFormat,
                                    "sw.uno""Wrong TextFlyCnt-Hint." );
                        const_cast<SwFormatFlyCnt&>(pHint->GetFlyCnt())
                            .SetFlyFormat();

                        //The connection is removed now the attribute can be deleted.
                        pTextNode->DeleteAttributes(RES_TXTATR_FLYCNT, nIdx);
                    }
                    else if( text::TextContentAnchorType_AT_PAGE != eNewAnchor &&
                            (RndStdIds::FLY_AT_PAGE == eOldAnchorId))
                    {
                        SwFormatAnchor aNewAnchor( aSet.Get( RES_ANCHOR ) );
                        //if the fly has been anchored at page then it needs to be connected
                        //to the content position
                        SwPaM aPam(rDoc.GetNodes().GetEndOfContent());
                        if( rDoc.getIDocumentLayoutAccess().GetCurrentLayout() )
                        {
                            SwCursorMoveState aState( CursorMoveState::SetOnlyText );
                            Point aTmp( pObj->GetSnapRect().TopLeft() );
                            rDoc.getIDocumentLayoutAccess().GetCurrentLayout()->GetModelPositionForViewPoint( aPam.GetPoint(), aTmp, &aState );
                        }
                        else
                        {
                            //without access to the layout the last node of the body will be used as anchor position
                            aPam.Move( fnMoveBackward, GoInDoc );
                        }
                        //anchor position has to be inserted after the text attribute has been inserted
                        aNewAnchor.SetAnchor( aPam.GetPoint() );
                        aSet.Put( aNewAnchor );
                        pFormat->SetFormatAttr(aSet);
                        bSetAttr = false;
                    }
                    if( text::TextContentAnchorType_AS_CHARACTER == eNewAnchor &&
                        (RndStdIds::FLY_AS_CHAR != eOldAnchorId))
                    {
                        SwPaM aPam(rDoc.GetNodes().GetEndOfContent());
                        if( rDoc.getIDocumentLayoutAccess().GetCurrentLayout() )
                        {
                            SwCursorMoveState aState( CursorMoveState::SetOnlyText );
                            Point aTmp( pObj->GetSnapRect().TopLeft() );
                            rDoc.getIDocumentLayoutAccess().GetCurrentLayout()->GetModelPositionForViewPoint( aPam.GetPoint(), aTmp, &aState );
                        }
                        else
                        {
                            //without access to the layout the last node of the body will be used as anchor position
                            aPam.Move( fnMoveBackward, GoInDoc );
                        }
                        //the RES_TXTATR_FLYCNT needs to be added now
                        SwTextNode *pNd = aPam.GetPointNode().GetTextNode();
                        SAL_WARN_IF( !pNd, "sw.uno""Cursor is not in a TextNode." );
                        SwFormatFlyCnt aFormat( pFlyFormat );
                        pNd->InsertItem(aFormat,
                            aPam.GetPoint()->GetContentIndex(), 0 );
                        aPam.GetPoint()->AdjustContent(-1); // InsertItem moved it
                        SwFormatAnchor aNewAnchor(
                                aSet.Get(RES_ANCHOR));
                        aNewAnchor.SetAnchor( aPam.GetPoint() );
                        aSet.Put( aNewAnchor );
                    }
                    if( bSetAttr )
                        pFormat->SetFormatAttr(aSet);

                    // If this property is an anchor change, and there is a group shape with textboxes
                    // do anchor sync in time unless the anchor sync in the porfly will cause crash during
                    // layout calculation (When importing an inline shape in docx via dmapper).
                    if (pFormat->Which() == RES_DRAWFRMFMT && pFormat->GetOtherTextBoxFormats())
                    {
                        SwTextBoxHelper::synchronizeGroupTextBoxProperty(
                            SwTextBoxHelper::changeAnchor, pFormat,
                            SdrObject::getSdrObjectFromXShape(mxShape));
                    }
                }
                else
                    pFormat->SetFormatAttr(aSet);
            }

            // We have a pFormat and a pEntry as well: try to sync TextBox property.
            SwTextBoxHelper::syncProperty(pFormat, pEntry->nWID, pEntry->nMemberId, aValue,
                                          SdrObject::getSdrObjectFromXShape(mxShape));
        }
        else
        {
            SfxPoolItem* pItem = nullptr;
            switch(pEntry->nWID)
            {
                case RES_ANCHOR:
                    pItem = m_pImpl->GetAnchor(true);
                break;
                case RES_HORI_ORIENT:
                    pItem = m_pImpl->GetHOrient(true);
                break;
                case RES_VERT_ORIENT:
                    pItem = m_pImpl->GetVOrient(true);
                break;
                case  RES_LR_SPACE:
                    pItem = m_pImpl->GetLRSpace(true);
                break;
                case  RES_UL_SPACE:
                    pItem = m_pImpl->GetULSpace(true);
                break;
                case  RES_SURROUND:
                    pItem = m_pImpl->GetSurround(true);
                break;
                case  FN_TEXT_RANGE:
                    if(auto tr = o3tl::tryAccess<
                           uno::Reference<text::XTextRange>>(aValue))
                    {
                        uno::Reference< text::XTextRange > & rRange = m_pImpl->GetTextRange();
                        rRange = *tr;
                    }
                break;
                case RES_OPAQUE :
                    m_pImpl->SetOpaque(*o3tl::doAccess<bool>(aValue));
                break;
                // #i26791#
                case RES_FOLLOW_TEXT_FLOW:
                {
                    pItem = m_pImpl->GetFollowTextFlow( true );
                }
                break;
                // #i28701#
                case RES_WRAP_INFLUENCE_ON_OBJPOS:
                {
                    pItem = m_pImpl->GetWrapInfluenceOnObjPos( true );
                }
                break;
                // #i28749#
                case FN_SHAPE_POSITION_LAYOUT_DIR :
                {
                    sal_Int16 nPositionLayoutDir = 0;
                    aValue >>= nPositionLayoutDir;
                    m_pImpl->SetPositionLayoutDir( nPositionLayoutDir );
                }
                break;
            }
            if(pItem)
                pItem->PutValue(aValue, pEntry->nMemberId);
        }
    }
    else
    {
        const uno::Type& rPSetType =
            cppu::UnoType<beans::XPropertySet>::get();
        uno::Any aPSet = m_xShapeAgg->queryAggregation(rPSetType);
        auto xPrSet = o3tl::tryAccess<uno::Reference<beans::XPropertySet>>(
            aPSet);
        if(!xPrSet)
            throw uno::RuntimeException();
        // #i31698# - setting the caption point of a
        // caption object doesn't have to change the object position.
        // Thus, keep the position, before the caption point is set and
        // restore it afterwards.
        awt::Point aKeepedPosition( 0, 0 );
        if ( rPropertyName == "CaptionPoint" && getShapeType() == "com.sun.star.drawing.CaptionShape" )
        {
                aKeepedPosition = getPosition();
        }
        if( pFormat && pFormat->GetDoc().getIDocumentLayoutAccess().GetCurrentViewShell() )
        {
            UnoActionContext aCtx(&pFormat->GetDoc());
            (*xPrSet)->setPropertyValue(rPropertyName, aValue);
        }
        else
            (*xPrSet)->setPropertyValue(rPropertyName, aValue);

        if (pFormat)
        {
            // We have a pFormat (but no pEntry): try to sync TextBox property.
            SwTextBoxHelper::syncProperty(pFormat, rPropertyName, aValue,
                                          SdrObject::getSdrObjectFromXShape(mxShape));
        }

        // #i31698# - restore object position, if caption point is set.
        if ( rPropertyName == "CaptionPoint" && getShapeType() == "com.sun.star.drawing.CaptionShape" )
        {
            setPosition( aKeepedPosition );
        }
    }
}

uno::Any SwXShape::getPropertyValue(const OUString& rPropertyName)
{
    SolarMutexGuard aGuard;
    uno::Any aRet;
    SwFrameFormat*   pFormat = GetFrameFormat();
    if(m_xShapeAgg.is())
    {
        const SfxItemPropertyMapEntry*  pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName );
        if(pEntry)
        {
            if(pFormat)
            {
                if(RES_OPAQUE == pEntry->nWID)
                {
                    SvxShape* pSvxShape = GetSvxShape();
                    OSL_ENSURE(pSvxShape, "No SvxShape found!");
                    if(pSvxShape)
                    {
                        SdrObject* pObj = pSvxShape->GetSdrObject();
                        // consider invisible layers
                        SdrLayerID nLayerId = pObj->GetLayer();
                        const IDocumentDrawModelAccess& rIDMA = pFormat->GetDoc().getIDocumentDrawModelAccess();
                        aRet <<=
                            ( nLayerId != rIDMA.GetHellId() &&
                              nLayerId != rIDMA.GetHeaderFooterHellId() &&
                              nLayerId != rIDMA.GetInvisibleHellId() );
                    }
                }
                else if(FN_ANCHOR_POSITION == pEntry->nWID)
                {
                    SvxShape* pSvxShape = GetSvxShape();
                    OSL_ENSURE(pSvxShape, "No SvxShape found!");
                    if(pSvxShape)
                    {
                        SdrObject* pObj = pSvxShape->GetSdrObject();
                        Point aPt = pObj->GetAnchorPos();
                        awt::Point aPoint( convertTwipToMm100( aPt.X() ),
                                           convertTwipToMm100( aPt.Y() ) );
                        aRet <<= aPoint;
                    }
                }
                // #i26791# - special handling for FN_TEXT_RANGE
                else if ( FN_TEXT_RANGE == pEntry->nWID )
                {
                    const SwFormatAnchor aAnchor = pFormat->GetAnchor();
                    if (aAnchor.GetAnchorId() == RndStdIds::FLY_AT_PAGE)
                    {
                        // return nothing, because property <TextRange> isn't
                        // valid for to-page anchored shapes
                        aRet = uno::Any();
                    }
                    else
                    {
                        if ( aAnchor.GetAnchorNode() )
                        {
                            const rtl::Reference<SwXTextRange> xTextRange
                                = SwXTextRange::CreateXTextRange(
                                                    pFormat->GetDoc(),
                                                    *aAnchor.GetContentAnchor(),
                                                    nullptr );
                            aRet <<= uno::Reference<text::XTextRange>(xTextRange);
                        }
                        else
                        {
                            // return nothing
                            aRet = uno::Any();
                        }
                    }
                }
                else if (pEntry->nWID == FN_TEXT_BOX)
                {
                    if (pEntry->nMemberId == MID_TEXT_BOX)
                    {
                        auto pSvxShape = GetSvxShape();
                        bool bValue = SwTextBoxHelper::isTextBox(
                            pFormat, RES_DRAWFRMFMT,
                            ((pSvxShape && pSvxShape->GetSdrObject()) ? pSvxShape->GetSdrObject()
                                : pFormat->FindRealSdrObject()));
                        aRet <<= bValue;
                    }
                    else if (pEntry->nMemberId == MID_TEXT_BOX_CONTENT)
                    {
                        auto pObj = SdrObject::getSdrObjectFromXShape(mxShape);
                        auto xRange = SwTextBoxHelper::queryInterface(
                            pFormat, cppu::UnoType<text::XText>::get(),
                            pObj ? pObj : pFormat->FindRealSdrObject());
                        uno::Reference<text::XTextFrame> xFrame(xRange, uno::UNO_QUERY);
                        if (xFrame.is())
                            aRet <<= xFrame;
                    }
                }
                else if (pEntry->nWID == RES_CHAIN)
                {
                    switch (pEntry->nMemberId)
                    {
                    case MID_CHAIN_PREVNAME:
                    case MID_CHAIN_NEXTNAME:
                    case MID_CHAIN_NAME:
                        SwTextBoxHelper::getProperty(pFormat, pEntry->nWID, pEntry->nMemberId, aRet);
                    break;
                    }
                }
                // #i28749#
                else if ( FN_SHAPE_TRANSFORMATION_IN_HORI_L2R == pEntry->nWID )
                {
                    // get property <::drawing::Shape::Transformation>
                    // without conversion to layout direction as below
                    aRet = _getPropAtAggrObj( u"Transformation"_ustr );
                }
                else if ( FN_SHAPE_POSITION_LAYOUT_DIR == pEntry->nWID )
                {
                    aRet <<= pFormat->GetPositionLayoutDir();
                }
                // #i36248#
                else if ( FN_SHAPE_STARTPOSITION_IN_HORI_L2R == pEntry->nWID )
                {
                    // get property <::drawing::Shape::StartPosition>
                    // without conversion to layout direction as below
                    aRet = _getPropAtAggrObj( u"StartPosition"_ustr );
                }
                else if ( FN_SHAPE_ENDPOSITION_IN_HORI_L2R == pEntry->nWID )
                {
                    // get property <::drawing::Shape::EndPosition>
                    // without conversion to layout direction as below
                    aRet = _getPropAtAggrObj( u"EndPosition"_ustr );
                }
                else if (pEntry->nWID == RES_FRM_SIZE &&
                         (pEntry->nMemberId == MID_FRMSIZE_REL_HEIGHT ||
                          pEntry->nMemberId == MID_FRMSIZE_REL_WIDTH ||
                          pEntry->nMemberId == MID_FRMSIZE_REL_HEIGHT_RELATION ||
                          pEntry->nMemberId == MID_FRMSIZE_REL_WIDTH_RELATION))
                {
                    SvxShape* pSvxShape = GetSvxShape();
                    SAL_WARN_IF(!pSvxShape, "sw.uno""No SvxShape found!");
                    sal_Int16 nRet = 0;
                    if (pSvxShape)
                    {
                        SdrObject* pObj = pSvxShape->GetSdrObject();
                        switch (pEntry->nMemberId)
                        {
                        case MID_FRMSIZE_REL_WIDTH:
                            if (pObj->GetRelativeWidth())
                                nRet = *pObj->GetRelativeWidth() * 100;
                            break;
                        case MID_FRMSIZE_REL_HEIGHT:
                            if (pObj->GetRelativeHeight())
                                nRet = *pObj->GetRelativeHeight() * 100;
                            break;
                        case MID_FRMSIZE_REL_WIDTH_RELATION:
                            nRet = pObj->GetRelativeWidthRelation();
                            break;
                        case MID_FRMSIZE_REL_HEIGHT_RELATION:
                            nRet = pObj->GetRelativeHeightRelation();
                            break;
                        }
                    }
                    aRet <<= nRet;
                }
                else
                {
                    const SwAttrSet& rSet = pFormat->GetAttrSet();
                    SfxItemPropertySet::getPropertyValue(*pEntry, rSet, aRet);
                }
            }
            else
            {
                SfxPoolItem* pItem = nullptr;
                switch(pEntry->nWID)
                {
                    case RES_ANCHOR:
                        pItem = m_pImpl->GetAnchor();
                    break;
                    case RES_HORI_ORIENT:
                        pItem = m_pImpl->GetHOrient();
                    break;
                    case RES_VERT_ORIENT:
                        pItem = m_pImpl->GetVOrient();
                    break;
                    case  RES_LR_SPACE:
                        pItem = m_pImpl->GetLRSpace();
                    break;
                    case  RES_UL_SPACE:
                        pItem = m_pImpl->GetULSpace();
                    break;
                    case  RES_SURROUND:
                        pItem = m_pImpl->GetSurround();
                    break;
                    case FN_TEXT_RANGE :
                        aRet <<= m_pImpl->GetTextRange();
                    break;
                    case RES_OPAQUE :
                        aRet <<= m_pImpl->GetOpaque();
                    break;
                    case FN_ANCHOR_POSITION :
                    {
                        aRet <<= awt::Point();
                    }
                    break;
                    // #i26791#
                    case RES_FOLLOW_TEXT_FLOW :
                    {
                        pItem = m_pImpl->GetFollowTextFlow();
                    }
                    break;
                    // #i28701#
                    case RES_WRAP_INFLUENCE_ON_OBJPOS:
                    {
                        pItem = m_pImpl->GetWrapInfluenceOnObjPos();
                    }
                    break;
                    // #i28749#
                    case FN_SHAPE_TRANSFORMATION_IN_HORI_L2R:
                    {
                        // get property <::drawing::Shape::Transformation>
                        // without conversion to layout direction as below
                        aRet = _getPropAtAggrObj( u"Transformation"_ustr );
                    }
                    break;
                    case FN_SHAPE_POSITION_LAYOUT_DIR:
                    {
                        aRet <<= m_pImpl->GetPositionLayoutDir();
                    }
                    break;
                    // #i36248#
                    case FN_SHAPE_STARTPOSITION_IN_HORI_L2R:
                    {
                        // get property <::drawing::Shape::StartPosition>
                        // without conversion to layout direction as below
                        aRet = _getPropAtAggrObj( u"StartPosition"_ustr );
                    }
                    break;
                    case FN_SHAPE_ENDPOSITION_IN_HORI_L2R:
                    {
                        // get property <::drawing::Shape::StartPosition>
                        // without conversion to layout direction as below
                        aRet = _getPropAtAggrObj( u"EndPosition"_ustr );
                    }
                    break;
                }
                if(pItem)
                    pItem->QueryValue(aRet, pEntry->nMemberId);
            }
        }
        else
        {
            aRet = _getPropAtAggrObj( rPropertyName );

            // #i31698# - convert the position (translation)
            // of the drawing object in the transformation
            if ( rPropertyName == "Transformation" )
            {
                drawing::HomogenMatrix3 aMatrix;
                aRet >>= aMatrix;
                aRet <<= ConvertTransformationToLayoutDir( aMatrix );
            }
            // #i36248#
            else if ( rPropertyName == "StartPosition" )
            {
                awt::Point aStartPos;
                aRet >>= aStartPos;
                // #i59051#
                aRet <<= ConvertStartOrEndPosToLayoutDir( aStartPos );
            }
            else if ( rPropertyName == "EndPosition" )
            {
                awt::Point aEndPos;
                aRet >>= aEndPos;
                // #i59051#
                aRet <<= ConvertStartOrEndPosToLayoutDir( aEndPos );
            }
            // #i59051#
            else if ( rPropertyName == "PolyPolygonBezier" )
            {
                drawing::PolyPolygonBezierCoords aPath;
                aRet >>= aPath;
                aRet <<= ConvertPolyPolygonBezierToLayoutDir( aPath );
            }
            else if (rPropertyName == "ZOrder")
            {
                // Convert the real draw page position to the logical one that ignores textboxes.
                if (pFormat)
                {
                    const SdrObject* pObj = pFormat->FindRealSdrObject();
                    if (pObj)
                    {
                        bool bConvert = true;
                        if (SvxShape* pSvxShape = GetSvxShape())
                            // In case of group shapes, pSvxShape points to the child shape, while pObj points to the outermost group shape.
                            if (pSvxShape->GetSdrObject() != pObj)
                                // Textboxes are not expected inside group shapes, so no conversion is necessary there.
                                bConvert = false;
                        if (bConvert)
                        {
                            aRet <<= SwTextBoxHelper::getOrdNum(pObj);
                        }
                    }
                }
            }
        }
    }
    return aRet;
}

uno::Any SwXShape::_getPropAtAggrObj( const OUString& _rPropertyName )
{
    uno::Any aRet;

    const uno::Type& rPSetType =
                cppu::UnoType<beans::XPropertySet>::get();
    uno::Any aPSet = m_xShapeAgg->queryAggregation(rPSetType);
    auto xPrSet = o3tl::tryAccess<uno::Reference<beans::XPropertySet>>(aPSet);
    if ( !xPrSet )
    {
        throw uno::RuntimeException();
    }
    aRet = (*xPrSet)->getPropertyValue( _rPropertyName );

    return aRet;
}

beans::PropertyState SwXShape::getPropertyState( const OUString& rPropertyName )
{
    SolarMutexGuard aGuard;
    uno::Sequence< OUString > aNames { rPropertyName };
    uno::Sequence< beans::PropertyState > aStates = getPropertyStates(aNames);
    return aStates.getConstArray()[0];
}

uno::Sequence< beans::PropertyState > SwXShape::getPropertyStates(
    const uno::Sequence< OUString >& aPropertyNames )
{
    SolarMutexGuard aGuard;
    SwFrameFormat*   pFormat = GetFrameFormat();
    uno::Sequence< beans::PropertyState > aRet(aPropertyNames.getLength());
    if(!m_xShapeAgg.is())
        throw uno::RuntimeException();

    SvxShape* pSvxShape = GetSvxShape();
    bool bGroupMember = false;
    bool bFormControl = false;
    SdrObject* pObject = pSvxShape ? pSvxShape->GetSdrObject() : nullptr;
    if(pObject)
    {
        bGroupMember = pObject->getParentSdrObjectFromSdrObject() != nullptr;
        bFormControl = pObject->GetObjInventor() == SdrInventor::FmForm;
    }
    const OUString* pNames = aPropertyNames.getConstArray();
    beans::PropertyState* pRet = aRet.getArray();
    uno::Reference< XPropertyState >  xShapePrState;
    for(sal_Int32 nProperty = 0; nProperty < aPropertyNames.getLength(); nProperty++)
    {
        const SfxItemPropertyMapEntry*  pEntry = m_pPropSet->getPropertyMap().getByName( pNames[nProperty] );
        if(pEntry)
        {
            if(RES_OPAQUE == pEntry->nWID)
                pRet[nProperty] = bFormControl ?
                    beans::PropertyState_DEFAULT_VALUE : beans::PropertyState_DIRECT_VALUE;
            else if(FN_ANCHOR_POSITION == pEntry->nWID)
                pRet[nProperty] = beans::PropertyState_DIRECT_VALUE;
            else if(FN_TEXT_RANGE == pEntry->nWID)
                pRet[nProperty] = beans::PropertyState_DIRECT_VALUE;
            else if(bGroupMember)
                pRet[nProperty] = beans::PropertyState_DEFAULT_VALUE;
            else if (pEntry->nWID == RES_FRM_SIZE &&
                     (pEntry->nMemberId == MID_FRMSIZE_REL_HEIGHT_RELATION ||
                      pEntry->nMemberId == MID_FRMSIZE_REL_WIDTH_RELATION))
                pRet[nProperty] = beans::PropertyState_DIRECT_VALUE;
            else if (pEntry->nWID == FN_TEXT_BOX)
            {
                // The TextBox property is set, if we can find a textbox for this shape.
                if (pFormat
                    && SwTextBoxHelper::isTextBox(pFormat, RES_DRAWFRMFMT,
                                                  SdrObject::getSdrObjectFromXShape(mxShape)))
                    pRet[nProperty] = beans::PropertyState_DIRECT_VALUE;
                else
                    pRet[nProperty] = beans::PropertyState_DEFAULT_VALUE;
            }
            else if(pFormat)
            {
                const SwAttrSet& rSet = pFormat->GetAttrSet();
                SfxItemState eItemState = rSet.GetItemState(pEntry->nWID, false);

                if(SfxItemState::SET == eItemState)
                    pRet[nProperty] = beans::PropertyState_DIRECT_VALUE;
                else if(SfxItemState::DEFAULT == eItemState)
                    pRet[nProperty] = beans::PropertyState_DEFAULT_VALUE;
                else
                    pRet[nProperty] = beans::PropertyState_AMBIGUOUS_VALUE;
            }
            else
            {
                SfxPoolItem* pItem = nullptr;
                switch(pEntry->nWID)
                {
                    case RES_ANCHOR:
                        pItem = m_pImpl->GetAnchor();
                    break;
                    case RES_HORI_ORIENT:
                        pItem = m_pImpl->GetHOrient();
                    break;
                    case RES_VERT_ORIENT:
                        pItem = m_pImpl->GetVOrient();
                    break;
                    case  RES_LR_SPACE:
                        pItem = m_pImpl->GetLRSpace();
                    break;
                    case  RES_UL_SPACE:
                        pItem = m_pImpl->GetULSpace();
                    break;
                    case  RES_SURROUND:
                        pItem = m_pImpl->GetSurround();
                    break;
                    // #i28701#
                    case RES_WRAP_INFLUENCE_ON_OBJPOS:
                    {
                        pItem = m_pImpl->GetWrapInfluenceOnObjPos();
                    }
                    break;
                }
                if(pItem)
                    pRet[nProperty] = beans::PropertyState_DIRECT_VALUE;
                else
                    pRet[nProperty] = beans::PropertyState_DEFAULT_VALUE;
            }
        }
        else
        {
            if(!xShapePrState.is())
            {
                const uno::Type& rPStateType = cppu::UnoType<XPropertyState>::get();
                uno::Any aPState = m_xShapeAgg->queryAggregation(rPStateType);
                auto ps = o3tl::tryAccess<uno::Reference<XPropertyState>>(
                    aPState);
                if(!ps)
                    throw uno::RuntimeException();
                xShapePrState = *ps;
            }
            pRet[nProperty] = xShapePrState->getPropertyState(pNames[nProperty]);
        }
    }

    return aRet;
}

void SwXShape::setPropertyToDefault( const OUString& rPropertyName )
{
    SolarMutexGuard aGuard;
    SwFrameFormat*   pFormat = GetFrameFormat();
    if(!m_xShapeAgg.is())
        throw uno::RuntimeException();

    const SfxItemPropertyMapEntry*  pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName );
    if(pEntry)
    {
        if ( pEntry->nFlags & beans::PropertyAttribute::READONLY)
            throw uno::RuntimeException("Property is read-only: " + rPropertyName, getXWeak() );
        if(pFormat)
        {
            const SfxItemSet& rSet = pFormat->GetAttrSet();
            SfxItemSet aSet(pFormat->GetDoc().GetAttrPool(), pEntry->nWID, pEntry->nWID);
            aSet.SetParent(&rSet);
            aSet.ClearItem(pEntry->nWID);
            pFormat->GetDoc().SetAttr(aSet, *pFormat);
        }
        else
        {
            switch(pEntry->nWID)
            {
                case RES_ANCHOR:        m_pImpl->RemoveAnchor();  break;
                case RES_HORI_ORIENT:   m_pImpl->RemoveHOrient(); break;
                case RES_VERT_ORIENT:   m_pImpl->RemoveVOrient(); break;
                case  RES_LR_SPACE:     m_pImpl->RemoveLRSpace(); break;
                case  RES_UL_SPACE:     m_pImpl->RemoveULSpace(); break;
                case  RES_SURROUND:     m_pImpl->RemoveSurround();break;
                case RES_OPAQUE :       m_pImpl->SetOpaque(false);  break;
                case FN_TEXT_RANGE :
                break;
                // #i26791#
                case RES_FOLLOW_TEXT_FLOW:
                {
                    m_pImpl->RemoveFollowTextFlow();
                }
                break;
                // #i28701#
                case RES_WRAP_INFLUENCE_ON_OBJPOS:
                {
                    m_pImpl->RemoveWrapInfluenceOnObjPos();
                }
                break;
            }
        }
    }
    else
    {
        const uno::Type& rPStateType = cppu::UnoType<XPropertyState>::get();
        uno::Any aPState = m_xShapeAgg->queryAggregation(rPStateType);
        auto xShapePrState = o3tl::tryAccess<uno::Reference<XPropertyState>>(
            aPState);
        if(!xShapePrState)
            throw uno::RuntimeException();
        (*xShapePrState)->setPropertyToDefault( rPropertyName );
    }

}

uno::Any SwXShape::getPropertyDefault( const OUString& rPropertyName )
{
    SolarMutexGuard aGuard;
    SwFrameFormat*   pFormat = GetFrameFormat();
    uno::Any aRet;
    if(!m_xShapeAgg.is())
        throw uno::RuntimeException();

    const SfxItemPropertyMapEntry*  pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName );
    if(pEntry)
    {
        if(!(pEntry->nWID < RES_FRMATR_END && pFormat))
            throw uno::RuntimeException();

        const SfxPoolItem& rDefItem =
            pFormat->GetDoc().GetAttrPool().GetUserOrPoolDefaultItem(pEntry->nWID);
        rDefItem.QueryValue(aRet, pEntry->nMemberId);

    }
    else
    {
        const uno::Type& rPStateType = cppu::UnoType<XPropertyState>::get();
        uno::Any aPState = m_xShapeAgg->queryAggregation(rPStateType);
        auto xShapePrState = o3tl::tryAccess<uno::Reference<XPropertyState>>(
            aPState);
        if(!xShapePrState)
            throw uno::RuntimeException();
        (*xShapePrState)->getPropertyDefault( rPropertyName );
    }

    return aRet;
}

void SwXShape::addPropertyChangeListener(
    const OUString& _propertyName,
    const uno::Reference< beans::XPropertyChangeListener > & _listener )
{
    if ( !m_xShapeAgg.is() )
        throw uno::RuntimeException(u"no shape aggregate"_ustr, *this );

    // must be handled by the aggregate
    uno::Reference< beans::XPropertySet > xShapeProps;
    if ( m_xShapeAgg->queryAggregation( cppu::UnoType<beans::XPropertySet>::get() ) >>= xShapeProps )
        xShapeProps->addPropertyChangeListener( _propertyName, _listener );
}

void SwXShape::removePropertyChangeListener(
    const OUString& _propertyName,
    const uno::Reference< beans::XPropertyChangeListener > & _listener)
{
    if ( !m_xShapeAgg.is() )
        throw uno::RuntimeException(u"no shape aggregate"_ustr, *this );

    // must be handled by the aggregate
    uno::Reference< beans::XPropertySet > xShapeProps;
    if ( m_xShapeAgg->queryAggregation( cppu::UnoType<beans::XPropertySet>::get() ) >>= xShapeProps )
        xShapeProps->removePropertyChangeListener( _propertyName, _listener );
}

void SwXShape::addVetoableChangeListener(
    const OUString& /*PropertyName*/,
    const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/ )
{
    OSL_FAIL("not implemented");
}

void SwXShape::removeVetoableChangeListener(
    const OUString& /*PropertyName*/,
    const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/)
{
    OSL_FAIL("not implemented");
}

void SwXShape::attach(const uno::Reference< text::XTextRange > & xTextRange)
{
    SolarMutexGuard aGuard;

    // get access to SwDoc
    // (see also SwXTextRange::XTextRangeToSwPaM)
    const SwDoc* pDoc = nullptr;
    if (auto pRange = dynamic_cast<SwXTextRange*>(xTextRange.get()))
        pDoc = &pRange->GetDoc();
    else if (auto pText = dynamic_cast<SwXText*>(xTextRange.get()))
        pDoc = pText->GetDoc();
    else if (auto pCursor = dynamic_cast<OTextCursorHelper*>(xTextRange.get()))
        pDoc = pCursor->GetDoc();
    else if (auto pPortion = dynamic_cast<SwXTextPortion*>(xTextRange.get()))
        pDoc = &pPortion->GetCursor().GetDoc();
    else if (auto pParagraph = dynamic_cast<SwXParagraph*>(xTextRange.get());
             pParagraph && pParagraph->GetTextNode())
        pDoc = &pParagraph->GetTextNode()->GetDoc();

    if(!pDoc)
        throw uno::RuntimeException();
    const SwDocShell* pDocSh = pDoc->GetDocShell();
    if (!pDocSh)
        return;

    uno::Reference<frame::XModel> xModel = pDocSh->GetModel();
    uno::Reference< drawing::XDrawPageSupplier > xDPS(xModel, uno::UNO_QUERY);
    if (xDPS.is())
    {
        uno::Reference< drawing::XDrawPage > xDP( xDPS->getDrawPage() );
        if (xDP.is())
        {
            uno::Any aPos;
            aPos <<= xTextRange;
            setPropertyValue(u"TextRange"_ustr, aPos);
            uno::Reference< drawing::XShape > xTemp( getXWeak(), uno::UNO_QUERY );
            xDP->add( xTemp );
        }
    }
}

uno::Reference< text::XTextRange > SwXShape::getAnchor()
{
    SolarMutexGuard aGuard;
    uno::Reference< text::XTextRange > aRef;
    SwFrameFormat* pFormat = GetFrameFormat();
    if(pFormat)
    {
        const SwFormatAnchor& rAnchor = pFormat->GetAnchor();
        // return an anchor for non-page bound frames
        // and for page bound frames that have a page no == NULL and a content position
        if ((rAnchor.GetAnchorId() != RndStdIds::FLY_AT_PAGE) ||
            (rAnchor.GetAnchorNode() && !rAnchor.GetPageNum()))
        {
            if (rAnchor.GetAnchorId() == RndStdIds::FLY_AT_PARA)
            {   // ensure that SwXTextRange has SwContentIndex
                const SwNode* pAnchorNode = rAnchor.GetAnchorNode();
                aRef = SwXTextRange::CreateXTextRange(pFormat->GetDoc(), SwPosition(*pAnchorNode), nullptr);
            }
            else
            {
                aRef = SwXTextRange::CreateXTextRange(pFormat->GetDoc(), *rAnchor.GetContentAnchor(), nullptr);
            }
        }
    }
    else
        aRef = m_pImpl->GetTextRange().get();
    return aRef;
}

void SwXShape::dispose()
{
    SolarMutexGuard aGuard;
    SwFrameFormat* pFormat = GetFrameFormat();
    if(pFormat)
    {
        // determine correct <SdrObject>
        SvxShape* pSvxShape = GetSvxShape();
        SdrObject* pObj = pSvxShape ? pSvxShape->GetSdrObject() : nullptr;
        // safety assertion:
        // <pObj> must be the same as <pFormat->FindSdrObject()>, if <pObj> isn't
        // a 'virtual' drawing object.
        // correct assertion and refine it for safety reason.
        OSL_ENSURE( !pObj ||
                dynamic_cast<const SwDrawVirtObj*>( pObj) !=  nullptr ||
                pObj->getParentSdrObjectFromSdrObject() ||
                pObj == pFormat->FindSdrObject(),
                "<SwXShape::dispose(..) - different 'master' drawing objects!!" );
        // perform delete of draw frame format *not*
        // for 'virtual' drawing objects.
        // no delete of draw format for members
        // of a group
        if ( pObj &&
             dynamic_cast<const SwDrawVirtObj*>( pObj) ==  nullptr &&
             !pObj->getParentSdrObjectFromSdrObject() &&
             pObj->IsInserted() )
        {
            const SwFormatAnchor& rFormatAnchor = pFormat->GetAnchor();
            if (rFormatAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR)
            {
                SwTextNode *pTextNode = rFormatAnchor.GetAnchorNode()->GetTextNode();
                const sal_Int32 nIdx = rFormatAnchor.GetAnchorContentOffset();
                pTextNode->DeleteAttributes( RES_TXTATR_FLYCNT, nIdx );
            }
            else
                pFormat->GetDoc().getIDocumentLayoutAccess().DelLayoutFormat( pFormat );
        }
    }
    if(m_xShapeAgg.is())
    {
        uno::Any aAgg(m_xShapeAgg->queryAggregation( cppu::UnoType<XComponent>::get()));
        uno::Reference<XComponent> xComp;
        aAgg >>= xComp;
        if(xComp.is())
            xComp->dispose();
    }
    if(m_pPage)
    {
        auto pPage = const_cast<SwFmDrawPage*>(m_pPage);
        m_pPage = nullptr;
        pPage->RemoveShape(this);
    }
}

void SwXShape::addEventListener(
                    const uno::Reference< lang::XEventListener > & aListener)
{
    SvxShape* pSvxShape = GetSvxShape();
    if(pSvxShape)
         pSvxShape->addEventListener(aListener);
}

void SwXShape::removeEventListener(
                    const uno::Reference< lang::XEventListener > & aListener)
{
    SvxShape* pSvxShape = GetSvxShape();
    if(pSvxShape)
        pSvxShape->removeEventListener(aListener);
}

OUString SwXShape::getImplementationName()
{
    return u"SwXShape"_ustr;
}

sal_Bool SwXShape::supportsService(const OUString& rServiceName)
{
    return cppu::supportsService(this, rServiceName);
}

uno::Sequence< OUString > SwXShape::getSupportedServiceNames()
{
    uno::Sequence< OUString > aSeq;
    if (SvxShape* pSvxShape = GetSvxShape())
        aSeq = pSvxShape->getSupportedServiceNames();
    return comphelper::concatSequences(
        aSeq, std::initializer_list<OUString>{ u"com.sun.star.drawing.Shape"_ustr });
}

SvxShape*   SwXShape::GetSvxShape()
{
    if(m_xShapeAgg.is())
        return comphelper::getFromUnoTunnel<SvxShape>(m_xShapeAgg);
    return nullptr;
}

// #i31698#
// implementation of virtual methods from drawing::XShape
awt::Point SAL_CALL SwXShape::getPosition()
{
    awt::Point aPos( GetAttrPosition() );

    // handle group members
    SvxShape* pSvxShape = GetSvxShape();
    if ( pSvxShape )
    {
        SdrObject* pTopGroupObj = GetTopGroupObj( pSvxShape );
        if ( pTopGroupObj )
        {
            // #i34750# - get attribute position of top group
            // shape and add offset between top group object and group member
            uno::Reference< drawing::XShape > xGroupShape( pTopGroupObj->getUnoShape(), uno::UNO_QUERY );
            aPos = xGroupShape->getPosition();
            // add offset between top group object and group member
            // to the determined attribute position
            // #i34750#:
            // consider the layout direction
            const tools::Rectangle aMemberObjRect = GetSvxShape()->GetSdrObject()->GetSnapRect();
            const tools::Rectangle aGroupObjRect = pTopGroupObj->GetSnapRect();
            // #i53320# - relative position of group member and
            // top group object is always given in horizontal left-to-right layout.
            awt::Point aOffset( 0, 0 );
            {
                aOffset.X = ( aMemberObjRect.Left() - aGroupObjRect.Left() );
                aOffset.Y = ( aMemberObjRect.Top() - aGroupObjRect.Top() );
            }
            aOffset.X = convertTwipToMm100(aOffset.X);
            aOffset.Y = convertTwipToMm100(aOffset.Y);
            aPos.X += aOffset.X;
            aPos.Y += aOffset.Y;
        }
    }

    return aPos;
}

void SAL_CALL SwXShape::setPosition( const awt::Point& aPosition )
{
    SdrObject* pTopGroupObj = GetTopGroupObj();
    if ( !pTopGroupObj )
    {
        // #i37877# - no adjustment of position attributes,
        // if the position also has to be applied at the drawing object and
        // a contact object is already registered at the drawing object.
        bool bApplyPosAtDrawObj(false);
        bool bNoAdjustOfPosProp(false);
        // #i35798# - apply position also to drawing object,
        // if drawing object has no anchor position set.
        if ( mxShape.is() )
        {
            SvxShape* pSvxShape = GetSvxShape();
            if ( pSvxShape )
            {
                const SdrObject* pObj = pSvxShape->GetSdrObject();
                if ( pObj &&
                     pObj->GetAnchorPos().X() == 0 &&
                     pObj->GetAnchorPos().Y() == 0 )
                {
                    bApplyPosAtDrawObj = true;
                    if ( pObj->GetUserCall() &&
                         dynamic_cast<const SwDrawContact*>( pObj->GetUserCall()) !=  nullptr )
                    {
                        bNoAdjustOfPosProp = true;
                    }
                }
            }
        }
        // shape isn't a group member. Thus, set positioning attributes
        if ( !bNoAdjustOfPosProp )
        {
            AdjustPositionProperties( aPosition );
        }
        if ( bApplyPosAtDrawObj )
        {
            mxShape->setPosition( aPosition );
        }
    }
    else if ( mxShape.is() )
    {
        // shape is a member of a group. Thus, set its position.
        awt::Point aNewPos( aPosition );
        // The given position is given in the according layout direction. Thus,
        // it has to be converted to a position in horizontal left-to-right
        // layout.
        // convert given absolute attribute position in layout direction into
        // position in horizontal left-to-right layout.
        {
            aNewPos = ConvertPositionToHoriL2R( aNewPos, getSize() );
        }
        // Convert given absolute position in horizontal left-to-right
        // layout into relative position in horizontal left-to-right layout.
        uno::Reference< drawing::XShape > xGroupShape( pTopGroupObj->getUnoShape(), uno::UNO_QUERY );
        {
            // #i34750#
            // use method <xGroupShape->getPosition()> to get the correct
            // position of the top group object.
            awt::Point aAttrPosInHoriL2R(
                    ConvertPositionToHoriL2R( xGroupShape->getPosition(),
                                               xGroupShape->getSize() ) );
            aNewPos.X = o3tl::saturating_sub(aNewPos.X, aAttrPosInHoriL2R.X);
            aNewPos.Y = o3tl::saturating_sub(aNewPos.Y, aAttrPosInHoriL2R.Y);
        }
        // convert relative position in horizontal left-to-right layout into
        // absolute position in horizontal left-to-right layout
        {
            // #i34750#
            // use method <SvxShape->getPosition()> to get the correct
            // 'Drawing layer' position of the top group shape.
            auto pSvxGroupShape = comphelper::getFromUnoTunnel<SvxShape>(pTopGroupObj->getUnoShape());
            const awt::Point aGroupPos = pSvxGroupShape->getPosition();
            aNewPos.X = o3tl::saturating_add(aNewPos.X, aGroupPos.X);
            aNewPos.Y = o3tl::saturating_add(aNewPos.Y, aGroupPos.Y);
        }
        // set position
        mxShape->setPosition( aNewPos );
    }
}

awt::Size SAL_CALL SwXShape::getSize()
{
    awt::Size aSize;
    if ( mxShape.is() )
    {
        aSize = mxShape->getSize();
    }
    return aSize;
}

void SAL_CALL SwXShape::setSize( const awt::Size& aSize )
{
    comphelper::ProfileZone aZone("SwXShape::setSize");

    if ( mxShape.is() )
    {
        mxShape->setSize( aSize );
    }
    SwTextBoxHelper::syncProperty(GetFrameFormat(), RES_FRM_SIZE, MID_FRMSIZE_SIZE, uno::Any(aSize));
}
// #i31698#
// implementation of virtual methods from drawing::XShapeDescriptor
OUString SAL_CALL SwXShape::getShapeType()
{
    if ( mxShape.is() )
    {
        return mxShape->getShapeType();
    }
    return OUString();
}
/** method to determine top group object
    #i31698#
*/

SdrObject* SwXShape::GetTopGroupObj( SvxShape* _pSvxShape )
{
    SdrObject* pTopGroupObj( nullptr );

    SvxShape* pSvxShape = _pSvxShape ? _pSvxShape : GetSvxShape();
    if ( pSvxShape )
    {
        SdrObject* pSdrObj = pSvxShape->GetSdrObject();
        if ( pSdrObj && pSdrObj->getParentSdrObjectFromSdrObject() )
        {
            pTopGroupObj = pSdrObj->getParentSdrObjectFromSdrObject();
            while ( pTopGroupObj->getParentSdrObjectFromSdrObject() )
            {
                pTopGroupObj = pTopGroupObj->getParentSdrObjectFromSdrObject();
            }
        }
    }

    return pTopGroupObj;
}

/** method to determine position according to the positioning attributes
    #i31698#
*/

awt::Point SwXShape::GetAttrPosition()
{
    awt::Point aAttrPos;

    uno::Any aHoriPos( getPropertyValue(u"HoriOrientPosition"_ustr) );
    aHoriPos >>= aAttrPos.X;
    uno::Any aVertPos( getPropertyValue(u"VertOrientPosition"_ustr) );
    aVertPos >>= aAttrPos.Y;
    // #i35798# - fallback, if attribute position is (0,0)
    // and no anchor position is applied to the drawing object
    SvxShape* pSvxShape = GetSvxShape();
    if ( pSvxShape )
    {
        const SdrObject* pObj = pSvxShape->GetSdrObject();
        if ( pObj &&
             pObj->GetAnchorPos().X() == 0 &&
             pObj->GetAnchorPos().Y() == 0 &&
             aAttrPos.X == 0 && aAttrPos.Y == 0 )
        {
            const tools::Rectangle aObjRect = pObj->GetSnapRect();
            aAttrPos.X = convertTwipToMm100(aObjRect.Left());
            aAttrPos.Y = convertTwipToMm100(aObjRect.Top());
        }
    }
    // #i35007# - If drawing object is anchored as-character,
    // it's x-position isn't sensible. Thus, return the x-position as zero in this case.
    text::TextContentAnchorType eTextAnchorType =
                            text::TextContentAnchorType_AT_PARAGRAPH;
    {
        uno::Any aAny = getPropertyValue( u"AnchorType"_ustr );
        aAny >>= eTextAnchorType;
    }
    if ( eTextAnchorType == text::TextContentAnchorType_AS_CHARACTER )
    {
        aAttrPos.X = 0;
    }

    return aAttrPos;
}

/** method to convert the position (translation) of the drawing object to
    the layout direction horizontal left-to-right.
    #i31698#
*/

awt::Point SwXShape::ConvertPositionToHoriL2R( const awt::Point& rObjPos,
                                                const awt::Size& rObjSize )
{
    awt::Point aObjPosInHoriL2R( rObjPos );

    SwFrameFormat* pFrameFormat = GetFrameFormat();
    if ( pFrameFormat )
    {
        SwFrameFormat::tLayoutDir eLayoutDir = pFrameFormat->GetLayoutDir();
        switch ( eLayoutDir )
        {
            case SwFrameFormat::HORI_L2R:
            {
                // nothing to do
            }
            break;
            case SwFrameFormat::HORI_R2L:
            {
                aObjPosInHoriL2R.X = -rObjPos.X - rObjSize.Width;
            }
            break;
            case SwFrameFormat::VERT_R2L:
            {
                aObjPosInHoriL2R.X = -rObjPos.Y - rObjSize.Width;
                aObjPosInHoriL2R.Y = rObjPos.X;
            }
            break;
            default:
            {
                OSL_FAIL( "<SwXShape::ConvertPositionToHoriL2R(..)> - unsupported layout direction" );
            }
        }
    }

    return aObjPosInHoriL2R;
}

/** method to convert the transformation of the drawing object to the layout
    direction, the drawing object is in
    #i31698#
*/

drawing::HomogenMatrix3 SwXShape::ConvertTransformationToLayoutDir(
                                    const drawing::HomogenMatrix3& rMatrixInHoriL2R )
{
    drawing::HomogenMatrix3 aMatrix(rMatrixInHoriL2R);

    // #i44334#, #i44681# - direct manipulation of the
    // transformation structure isn't valid, if it contains rotation.
    SvxShape* pSvxShape = GetSvxShape();
    OSL_ENSURE( pSvxShape,
            "<SwXShape::ConvertTransformationToLayoutDir(..)> - no SvxShape found!");
    if ( pSvxShape )
    {
        const SdrObject* pObj = pSvxShape->GetSdrObject();
        OSL_ENSURE( pObj,
                "<SwXShape::ConvertTransformationToLayoutDir(..)> - no SdrObject found!");
        if ( pObj )
        {
            // get position of object in Writer coordinate system.
            awt::Point aPos( getPosition() );
            // get position of object in Drawing layer coordinate system
            const Point aTmpObjPos( pObj->GetSnapRect().TopLeft() );
            const awt::Point aObjPos(
                    convertTwipToMm100( aTmpObjPos.X() - pObj->GetAnchorPos().X() ),
                    convertTwipToMm100( aTmpObjPos.Y() - pObj->GetAnchorPos().Y() ) );
            // determine difference between these positions according to the
            // Writer coordinate system
            const awt::Point aTranslateDiff( aPos.X - aObjPos.X,
                                             aPos.Y - aObjPos.Y );
            // apply translation difference to transformation matrix.
            if ( aTranslateDiff.X != 0 || aTranslateDiff.Y != 0 )
            {
                // #i73079# - use correct matrix type
                ::basegfx::B2DHomMatrix aTempMatrix;

                aTempMatrix.set(0, 0, aMatrix.Line1.Column1 );
                aTempMatrix.set(0, 1, aMatrix.Line1.Column2 );
                aTempMatrix.set(0, 2, aMatrix.Line1.Column3 );
                aTempMatrix.set(1, 0, aMatrix.Line2.Column1 );
                aTempMatrix.set(1, 1, aMatrix.Line2.Column2 );
                aTempMatrix.set(1, 2, aMatrix.Line2.Column3 );
                // For this to be a valid 2D transform matrix, the last row must be [0,0,1]
                assert( aMatrix.Line3.Column1 == 0 );
                assert( aMatrix.Line3.Column2 == 0 );
                assert( aMatrix.Line3.Column3 == 1 );
                // #i73079#
                aTempMatrix.translate( aTranslateDiff.X, aTranslateDiff.Y );
                aMatrix.Line1.Column1 = aTempMatrix.get(0, 0);
                aMatrix.Line1.Column2 = aTempMatrix.get(0, 1);
                aMatrix.Line1.Column3 = aTempMatrix.get(0, 2);
                aMatrix.Line2.Column1 = aTempMatrix.get(1, 0);
                aMatrix.Line2.Column2 = aTempMatrix.get(1, 1);
                aMatrix.Line2.Column3 = aTempMatrix.get(1, 2);
                aMatrix.Line3.Column1 = 0;
                aMatrix.Line3.Column2 = 0;
                aMatrix.Line3.Column3 = 1;
            }
        }
    }

    return aMatrix;
}

/** method to adjust the positioning properties
    #i31698#
*/

void SwXShape::AdjustPositionProperties( const awt::Point& rPosition )
{
    // handle x-position
    // #i35007# - no handling of x-position, if drawing
    // object is anchored as-character, because it doesn't make sense.
    text::TextContentAnchorType eTextAnchorType =
                            text::TextContentAnchorType_AT_PARAGRAPH;
    {
        uno::Any aAny = getPropertyValue( u"AnchorType"_ustr );
        aAny >>= eTextAnchorType;
    }
    if ( eTextAnchorType != text::TextContentAnchorType_AS_CHARACTER )
    {
        // determine current x-position
        static constexpr OUString aHoriPosPropStr(u"HoriOrientPosition"_ustr);
        uno::Any aHoriPos( getPropertyValue( aHoriPosPropStr ) );
        sal_Int32 dCurrX = 0;
        aHoriPos >>= dCurrX;
        // change x-position attribute, if needed
        if ( dCurrX != rPosition.X )
        {
            // adjust x-position orientation to text::HoriOrientation::NONE, if needed
            // Note: has to be done before setting x-position attribute
            static constexpr OUString aHoriOrientPropStr(u"HoriOrient"_ustr);
            uno::Any aHoriOrient( getPropertyValue( aHoriOrientPropStr ) );
            sal_Int16 eHoriOrient;
            if (aHoriOrient >>= eHoriOrient) // may be void
            {
                if ( eHoriOrient != text::HoriOrientation::NONE )
                {
                    eHoriOrient = text::HoriOrientation::NONE;
                    aHoriOrient <<= eHoriOrient;
                    setPropertyValue( aHoriOrientPropStr, aHoriOrient );
                }
            }
            // set x-position attribute
            aHoriPos <<= rPosition.X;
            setPropertyValue( aHoriPosPropStr, aHoriPos );
        }
    }

    // handle y-position
    {
        // determine current y-position
        static constexpr OUString aVertPosPropStr(u"VertOrientPosition"_ustr);
        uno::Any aVertPos( getPropertyValue( aVertPosPropStr ) );
        sal_Int32 dCurrY = 0;
        aVertPos >>= dCurrY;
        // change y-position attribute, if needed
        if ( dCurrY != rPosition.Y )
        {
            // adjust y-position orientation to text::VertOrientation::NONE, if needed
            // Note: has to be done before setting y-position attribute
            static constexpr OUString aVertOrientPropStr(u"VertOrient"_ustr);
            uno::Any aVertOrient( getPropertyValue( aVertOrientPropStr ) );
            sal_Int16 eVertOrient;
            if (aVertOrient >>= eVertOrient) // may be void
            {
                if ( eVertOrient != text::VertOrientation::NONE )
                {
                    eVertOrient = text::VertOrientation::NONE;
                    aVertOrient <<= eVertOrient;
                    setPropertyValue( aVertOrientPropStr, aVertOrient );
                }
            }
            // set y-position attribute
            aVertPos <<= rPosition.Y;
            setPropertyValue( aVertPosPropStr, aVertPos );
        }
    }
}

/** method to convert start or end position of the drawing object to the
    Writer specific position, which is the attribute position in layout direction
    #i59051#
*/

css::awt::Point SwXShape::ConvertStartOrEndPosToLayoutDir(
                            const css::awt::Point& aStartOrEndPos )
{
    awt::Point aConvertedPos( aStartOrEndPos );

    SvxShape* pSvxShape = GetSvxShape();
    OSL_ENSURE( pSvxShape,
            "<SwXShape::ConvertStartOrEndPosToLayoutDir(..)> - no SvxShape found!");
    if ( pSvxShape )
    {
        const SdrObject* pObj = pSvxShape->GetSdrObject();
        OSL_ENSURE( pObj,
                "<SwXShape::ConvertStartOrEndPosToLayoutDir(..)> - no SdrObject found!");
        if ( pObj )
        {
            // get position of object in Writer coordinate system.
            awt::Point aPos( getPosition() );
            // get position of object in Drawing layer coordinate system
            const Point aTmpObjPos( pObj->GetSnapRect().TopLeft() );
            const awt::Point aObjPos(
                    convertTwipToMm100( aTmpObjPos.X() - pObj->GetAnchorPos().X() ),
                    convertTwipToMm100( aTmpObjPos.Y() - pObj->GetAnchorPos().Y() ) );
            // determine difference between these positions according to the
            // Writer coordinate system
            const awt::Point aTranslateDiff( aPos.X - aObjPos.X,
                                             aPos.Y - aObjPos.Y );
            // apply translation difference to transformation matrix.
            if ( aTranslateDiff.X != 0 || aTranslateDiff.Y != 0 )
            {
                aConvertedPos.X = aConvertedPos.X + aTranslateDiff.X;
                aConvertedPos.Y = aConvertedPos.Y + aTranslateDiff.Y;
            }
        }
    }

    return aConvertedPos;
}

css::drawing::PolyPolygonBezierCoords SwXShape::ConvertPolyPolygonBezierToLayoutDir(
                    const css::drawing::PolyPolygonBezierCoords& aPath )
{
    drawing::PolyPolygonBezierCoords aConvertedPath( aPath );

    SvxShape* pSvxShape = GetSvxShape();
    OSL_ENSURE( pSvxShape,
            "<SwXShape::ConvertStartOrEndPosToLayoutDir(..)> - no SvxShape found!");
    if ( pSvxShape )
    {
        const SdrObject* pObj = pSvxShape->GetSdrObject();
        OSL_ENSURE( pObj,
                "<SwXShape::ConvertStartOrEndPosToLayoutDir(..)> - no SdrObject found!");
        if ( pObj )
        {
            // get position of object in Writer coordinate system.
            awt::Point aPos( getPosition() );
            // get position of object in Drawing layer coordinate system
            const Point aTmpObjPos( pObj->GetSnapRect().TopLeft() );
            const awt::Point aObjPos(
                    convertTwipToMm100( aTmpObjPos.X() - pObj->GetAnchorPos().X() ),
                    convertTwipToMm100( aTmpObjPos.Y() - pObj->GetAnchorPos().Y() ) );
            // determine difference between these positions according to the
            // Writer coordinate system
            const awt::Point aTranslateDiff( aPos.X - aObjPos.X,
                                             aPos.Y - aObjPos.Y );
            // apply translation difference to PolyPolygonBezier.
            if ( aTranslateDiff.X != 0 || aTranslateDiff.Y != 0 )
            {
                for(drawing::PointSequence& rInnerSequence : asNonConstRange(aConvertedPath.Coordinates))
                {
                    for(awt::Point& rPoint : asNonConstRange(rInnerSequence))
                    {
                        basegfx::B2DPoint aNewCoordinatePair(rPoint.X + aTranslateDiff.X, rPoint.Y + aTranslateDiff.Y);
                        rPoint.X = basegfx::fround(aNewCoordinatePair.getX());
                        rPoint.Y = basegfx::fround(aNewCoordinatePair.getY());
                    }
                }
            }
        }
    }

    return aConvertedPath;
}

SwXGroupShape::SwXGroupShape(uno::Reference<XInterface> & xShape,
                             SwDoc const*const pDoc)
    : SwXShape(xShape, pDoc)
{
#if OSL_DEBUG_LEVEL > 0
    uno::Reference<XShapes> xShapes(m_xShapeAgg, uno::UNO_QUERY);
    OSL_ENSURE(xShapes.is(), "no SvxShape found or shape is not a group shape");
#endif
}

SwXGroupShape::~SwXGroupShape()
{
}

uno::Any SwXGroupShape::queryInterface( const uno::Type& rType )
{
    uno::Any aRet;
    if(rType == cppu::UnoType<XShapes>::get())
        aRet <<= uno::Reference<XShapes>(this);
    else
        aRet = SwXShape::queryInterface(rType);
    return aRet;
}

void SwXGroupShape::acquire(  ) noexcept
{
    SwXShape::acquire();
}

void SwXGroupShape::release(  ) noexcept
{
    SwXShape::release();
}

void SwXGroupShape::add( const uno::Reference< XShape >& xShape )
{
    SolarMutexGuard aGuard;
    SvxShape* pSvxShape = GetSvxShape();
    SwFrameFormat* pFormat = GetFrameFormat();
    if(!(pSvxShape && pFormat))
        throw uno::RuntimeException();

    uno::Reference<XShapes> xShapes;
    if( m_xShapeAgg.is() )
    {
        const uno::Type& rType = cppu::UnoType<XShapes>::get();
        uno::Any aAgg = m_xShapeAgg->queryAggregation( rType );
        aAgg >>= xShapes;
    }
    if(!xShapes.is())
        throw uno::RuntimeException();

    xShapes->add(xShape);


    uno::Reference<lang::XUnoTunnel> xTunnel(xShape, uno::UNO_QUERY);
    SwXShape* pSwShape = comphelper::getFromUnoTunnel<SwXShape>(xTunnel);
    if(!(pSwShape && pSwShape->m_bDescriptor))
        return;

    SvxShape* pAddShape = comphelper::getFromUnoTunnel<SvxShape>(xTunnel);
    if(pAddShape)
    {
        SdrObject* pObj = pAddShape->GetSdrObject();
        if(pObj)
        {
            SwDoc& rDoc = pFormat->GetDoc();
            // set layer of new drawing
            // object to corresponding invisible layer.
            if( SdrInventor::FmForm != pObj->GetObjInventor())
            {
                pObj->SetLayer( pSwShape->m_pImpl->GetOpaque()
                                ? rDoc.getIDocumentDrawModelAccess().GetInvisibleHeavenId()
                                : rDoc.getIDocumentDrawModelAccess().GetInvisibleHellId() );
            }
            else
            {
                pObj->SetLayer(rDoc.getIDocumentDrawModelAccess().GetInvisibleControlsId());
            }
        }
    }
    pSwShape->m_bDescriptor = false;
}

void SwXGroupShape::remove( const uno::Reference< XShape >& xShape )
{
    SolarMutexGuard aGuard;
    uno::Reference<XShapes> xShapes;
    if( m_xShapeAgg.is() )
    {
        const uno::Type& rType = cppu::UnoType<XShapes>::get();
        uno::Any aAgg = m_xShapeAgg->queryAggregation( rType );
        aAgg >>= xShapes;
    }
    if(!xShapes.is())
        throw uno::RuntimeException();
    xShapes->remove(xShape);
}

sal_Int32 SwXGroupShape::getCount()
{
    SolarMutexGuard aGuard;
    uno::Reference<XIndexAccess> xAcc;
    if( m_xShapeAgg.is() )
    {
        const uno::Type& rType = cppu::UnoType<XIndexAccess>::get();
        uno::Any aAgg = m_xShapeAgg->queryAggregation( rType );
        aAgg >>= xAcc;
    }
    if(!xAcc.is())
        throw uno::RuntimeException();
    return xAcc->getCount();
}

uno::Any SwXGroupShape::getByIndex(sal_Int32 nIndex)
{
    SolarMutexGuard aGuard;
    uno::Reference<XIndexAccess> xAcc;
    if( m_xShapeAgg.is() )
    {
        const uno::Type& rType = cppu::UnoType<XIndexAccess>::get();
        uno::Any aAgg = m_xShapeAgg->queryAggregation( rType );
        aAgg >>= xAcc;
    }
    if(!xAcc.is())
        throw uno::RuntimeException();
    return xAcc->getByIndex(nIndex);
}

uno::Type SwXGroupShape::getElementType(  )
{
    SolarMutexGuard aGuard;
    uno::Reference<XIndexAccess> xAcc;
    if( m_xShapeAgg.is() )
    {
        const uno::Type& rType = cppu::UnoType<XIndexAccess>::get();
        uno::Any aAgg = m_xShapeAgg->queryAggregation( rType );
        aAgg >>= xAcc;
    }
    if(!xAcc.is())
        throw uno::RuntimeException();
    return xAcc->getElementType();
}

sal_Bool SwXGroupShape::hasElements(  )
{
    SolarMutexGuard aGuard;
    uno::Reference<XIndexAccess> xAcc;
    if( m_xShapeAgg.is() )
    {
        const uno::Type& rType = cppu::UnoType<XIndexAccess>::get();
        uno::Any aAgg = m_xShapeAgg->queryAggregation( rType );
        aAgg >>= xAcc;
    }
    if(!xAcc.is())
        throw uno::RuntimeException();
    return xAcc->hasElements();
}

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

Messung V0.5 in Prozent
C=92 H=99 G=95

¤ Dauer der Verarbeitung: 0.44 Sekunden  (vorverarbeitet am  2026-05-07) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.