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

Quelle  unoshape.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 <cppuhelper/supportsservice.hxx>
#include <com/sun/star/awt/XBitmap.hpp>
#include <com/sun/star/awt/Rectangle.hpp>
#include <com/sun/star/drawing/CircleKind.hpp>
#include <com/sun/star/lang/NoSupportException.hpp>
#include <vcl/svapp.hxx>
#include <svl/itemprop.hxx>
#include <o3tl/any.hxx>
#include <osl/mutex.hxx>
#include <editeng/unotext.hxx>
#include <svx/svdobj.hxx>
#include <svx/svdoole2.hxx>
#include <comphelper/scopeguard.hxx>
#include <comphelper/servicehelper.hxx>
#include <comphelper/multiinterfacecontainer4.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include <vcl/gfxlink.hxx>
#include <vcl/virdev.hxx>
#include <svx/sdangitm.hxx>
#include <svx/svdlayer.hxx>
#include <svx/svdopage.hxx>
#include <svx/svx3ditems.hxx>
#include <svx/xflbstit.hxx>
#include <svx/xflbmtit.hxx>
#include <svx/xlnstit.hxx>
#include <svx/xlnedit.hxx>
#include <svx/xlnclit.hxx>
#include <svx/svdmodel.hxx>
#include <svx/svdobjkind.hxx>
#include <svx/unopage.hxx>
#include <svx/unoshape.hxx>
#include <svx/unoshtxt.hxx>
#include <svx/svdpage.hxx>
#include <svx/unoshprp.hxx>
#include <svx/svdograf.hxx>
#include <svx/unoapi.hxx>
#include <svx/svdomeas.hxx>
#include <svx/svdpool.hxx>
#include <comphelper/diagnose_ex.hxx>
#include <tools/stream.hxx>
#include <tools/gen.hxx>
#include <tools/UnitConversion.hxx>
#include <svx/svdoedge.hxx>
#include <svx/svdocapt.hxx>
#include <svx/obj3d.hxx>
#include <svx/xflftrit.hxx>
#include <svx/xtable.hxx>
#include <svx/xbtmpit.hxx>
#include <svx/xfillit0.hxx>
#include <svx/xflgrit.hxx>
#include <svx/xflhtit.hxx>
#include <svx/xlineit0.hxx>
#include <svx/xlndsit.hxx>
#include <svx/unomaster.hxx>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include "gluepts.hxx"
#include "shapeimpl.hxx"
#include <sal/log.hxx>

#include <svx/sdr/contact/viewcontact.hxx>
#include <drawinglayer/converters.hxx>
#include <drawinglayer/geometry/viewinformation2d.hxx>
#include <drawinglayer/primitive2d/transformprimitive2d.hxx>

#include <vcl/gdimtf.hxx>
#include <vcl/wmf.hxx>
#include <svx/sdtfsitm.hxx>
#include <svx/svdopath.hxx>
#include <svx/SvxXTextColumns.hxx>
#include <svx/xflclit.hxx>
#include <editeng/frmdiritem.hxx>

#include <memory>
#include <optional>
#include <vector>
#include <iostream>

#include <bitmaps.hlst>

using namespace ::cppu;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::container;

class GDIMetaFile;

struct SvxShapeImpl
{
    std::optional<SfxItemSet> moItemSet;
    SdrObjKind      mnObjId;
    SvxShapeMaster* mpMaster;
    bool            mbDisposing;

    /** CL, OD 2005-07-19 #i52126# - this is initially 0 and set when
     *  a SvxShape::Create() call is executed. It is then set to the created
     *  SdrObject so a multiple call to SvxShape::Create() with same SdrObject
     *  is prohibited.
     */

    ::unotools::WeakReference< SdrObject > mxCreatedObj;

    // for xComponent
    ::comphelper::OInterfaceContainerHelper4<css::lang::XEventListener> maDisposeListeners;
    ::comphelper::OMultiTypeInterfaceContainerHelperVar4<OUString, css::beans::XPropertyChangeListener> maPropertyChangeListeners;

    SvxShapeImpl()
        :mnObjId( SdrObjKind::NONE )
        ,mpMaster( nullptr )
        ,mbDisposing( false )
    {
    }
};

namespace {


/// Calculates what scaling factor will be used for autofit text scaling of this shape.
SdrTextObj* getTextObjectWithFitToSize(SdrObject* pObject)
{
    SdrTextObj* pTextObj = DynCastSdrTextObj(pObject);
    if (!pTextObj)
    {
        return nullptr;
    }

    const SfxItemSet& rTextObjSet = pTextObj->GetMergedItemSet();
    if (rTextObjSet.GetItem<SdrTextFitToSizeTypeItem>(SDRATTR_TEXT_FITTOSIZE)->GetValue()
        != drawing::TextFitToSizeType_AUTOFIT)
    {
        return nullptr;
    }

    return pTextObj;
}
}

SvxShape::SvxShape( SdrObject* pObject )
:   maSize(100,100)
,   mpImpl( new SvxShapeImpl )
,   mbIsMultiPropertyCall(false)
,   mpPropSet(getSvxMapProvider().GetPropertySet(SVXMAP_SHAPE, SdrObject::GetGlobalDrawObjectItemPool()))
,   maPropMapEntries(getSvxMapProvider().GetMap(SVXMAP_SHAPE))
,   mxSdrObject(pObject)
,   mnLockCount(0)
{
    impl_construct();
}


SvxShape::SvxShape( SdrObject* pObject, std::span<const SfxItemPropertyMapEntry> pEntries, const SvxItemPropertySet* pPropertySet )
:   maSize(100,100)
,   mpImpl( new SvxShapeImpl )
,   mbIsMultiPropertyCall(false)
,   mpPropSet(pPropertySet)
,   maPropMapEntries(pEntries)
,   mxSdrObject(pObject)
,   mnLockCount(0)
{
    impl_construct();
}


SvxShape::~SvxShape() noexcept
{
    ::SolarMutexGuard aGuard;

    DBG_ASSERT( mnLockCount == 0, "Locked shape was disposed!" );

    if ( mpImpl->mpMaster )
        mpImpl->mpMaster->dispose();

    if ( mxSdrObject )
    {
        mxSdrObject->RemoveListener(*this);
        mxSdrObject->setUnoShape(nullptr);
        mxSdrObject.clear();
    }

    EndListeningAll(); // call explicitly within SolarMutexGuard
}


void SvxShape::InvalidateSdrObject()
{
    if(mxSdrObject)
    {
        mxSdrObject->RemoveListener(*this);
        mxSdrObject.clear();
    }
};

void SvxShape::setShapeKind( SdrObjKind nKind )
{
    mpImpl->mnObjId = nKind;
}


SdrObjKind SvxShape::getShapeKind() const
{
    return mpImpl->mnObjId;
}


void SvxShape::setMaster( SvxShapeMaster* pMaster )
{
    mpImpl->mpMaster = pMaster;
}


uno::Any SAL_CALL SvxShape::queryAggregation( const uno::Type& rType )
{
    if( mpImpl->mpMaster )
    {
        uno::Any aAny;
        if( mpImpl->mpMaster->queryAggregation( rType, aAny ) )
            return aAny;
    }

    return SvxShape_UnoImplHelper::queryAggregation(rType);
}

const css::uno::Sequence< sal_Int8 > & SvxShape::getUnoTunnelId() noexcept
{
    static const comphelper::UnoIdInit theSvxShapeUnoTunnelId;
    return theSvxShapeUnoTunnelId.getSeq();
}

sal_Int64 SAL_CALL SvxShape::getSomething( const css::uno::Sequence< sal_Int8 >& rId )
{
    return comphelper::getSomethingImpl(rId, this);
}


void SvxShape::notifyPropertyChange(const OUString& rPropName)
{
    std::unique_lock g(m_aMutex);
    comphelper::OInterfaceContainerHelper4<beans::XPropertyChangeListener>* pPropListeners =
            mpImpl->maPropertyChangeListeners.getContainer( g, rPropName );
    comphelper::OInterfaceContainerHelper4<beans::XPropertyChangeListener>* pAllListeners =
            mpImpl->maPropertyChangeListeners.getContainer( g, OUString() );
    if (pPropListeners || pAllListeners)
    {
        try
        {
            // Handle/OldValue not supported
            beans::PropertyChangeEvent aEvt;
            aEvt.Source = static_cast<cppu::OWeakObject*>(this);
            aEvt.PropertyName = rPropName;
            aEvt.NewValue = getPropertyValue(rPropName);
            if (pPropListeners)
                pPropListeners->notifyEach( g, &beans::XPropertyChangeListener::propertyChange, aEvt );
            if (pAllListeners)
                pAllListeners->notifyEach( g, &beans::XPropertyChangeListener::propertyChange, aEvt );
        }
        catchconst Exception& )
        {
            DBG_UNHANDLED_EXCEPTION("svx");
        }

    }
}

void SvxShape::impl_construct()
{
    if ( HasSdrObject() )
    {
        GetSdrObject()->AddListener(*this);
        impl_initFromSdrObject();
    }
}


void SvxShape::impl_initFromSdrObject()
{
    DBG_TESTSOLARMUTEX();
    OSL_PRECOND( HasSdrObject(), "SvxShape::impl_initFromSdrObject: not to be called without SdrObject!" );
    if ( !HasSdrObject() )
        return;

    osl_atomic_increment( &m_refCount );
    {
        GetSdrObject()->setUnoShape(this);
    }
    osl_atomic_decrement( &m_refCount );

    // #i40944#
    // Do not simply return when no model but do the type corrections
    // following below.
    const SdrInventor nInventor = GetSdrObject()->GetObjInventor();

    // is it one of ours (svx) ?
    if( !(nInventor == SdrInventor::Default || nInventor == SdrInventor::E3d || nInventor == SdrInventor::FmForm) )
        return;

    if(nInventor == SdrInventor::FmForm)
    {
        mpImpl->mnObjId = SdrObjKind::UNO;
    }
    else
    {
        mpImpl->mnObjId = GetSdrObject()->GetObjIdentifier();
    }

    switch(mpImpl->mnObjId)
    {
    case SdrObjKind::CircleCut:          // segment of circle
    case SdrObjKind::CircleArc:          // arc of circle
    case SdrObjKind::CircleSection:          // sector
        mpImpl->mnObjId = SdrObjKind::CircleOrEllipse;
        break;
    default: ;
    }
}


void SvxShape::Create( SdrObject* pNewObj, SvxDrawPage* /*pNewPage*/ )
{
    DBG_TESTSOLARMUTEX();

    assert( pNewObj && "SvxShape::Create: invalid new object!" );
    if ( !pNewObj )
        return;

    rtl::Reference<SdrObject> pCreatedObj = mpImpl->mxCreatedObj.get();
    assert( ( !pCreatedObj || ( pCreatedObj == pNewObj ) ) &&
        "SvxShape::Create: the same shape used for two different objects?! Strange ..." );

    // Correct condition (#i52126#)
    if ( pCreatedObj == pNewObj )
        return;

    // Correct condition (#i52126#)
    mpImpl->mxCreatedObj = pNewObj;

    if( HasSdrObject() )
    {
        GetSdrObject()->RemoveListener( *this );
    }

    mxSdrObject = pNewObj;

    if( HasSdrObject() )
    {
        GetSdrObject()->AddListener( *this );
    }

    OSL_ENSURE( !mbIsMultiPropertyCall, "SvxShape::Create: hmm?" );
        // this was previously set in impl_initFromSdrObject, but I think it was superfluous
        // (it definitely was in the other context where it was called, but I strongly suppose
        // it was also superfluous when called from here)
    impl_initFromSdrObject();

    ObtainSettingsFromPropertySet( *mpPropSet );

    // save user call
    SdrObjUserCall* pUser = GetSdrObject()->GetUserCall();
    GetSdrObject()->SetUserCall(nullptr);

    setPosition( maPosition );
    setSize( maSize );

    // restore user call after we set the initial size
    GetSdrObject()->SetUserCall( pUser );

    // if this shape was already named, use this name
    if( !maShapeName.isEmpty() )
    {
        GetSdrObject()->SetName( maShapeName );
        maShapeName.clear();
    }
}

void SvxShape::ForceMetricToItemPoolMetric(Pair& rPoint) const noexcept
{
    DBG_TESTSOLARMUTEX();
    if(!HasSdrObject())
        return;

    MapUnit eMapUnit(GetSdrObject()->getSdrModelFromSdrObject().GetItemPool().GetMetric(0));
    if(eMapUnit == MapUnit::Map100thMM)
        return;

    if (const auto eTo = MapToO3tlLength(eMapUnit); eTo != o3tl::Length::invalid)
    {
        rPoint.A() = o3tl::convert(rPoint.A(), o3tl::Length::mm100, eTo);
        rPoint.B() = o3tl::convert(rPoint.B(), o3tl::Length::mm100, eTo);
    }
    else
    {
        OSL_FAIL("AW: Missing unit translation to PoolMetric!");
    }
}

void SvxShape::ForceMetricToItemPoolMetric(basegfx::B2DPolyPolygon& rPolyPolygon) const noexcept
{
    DBG_TESTSOLARMUTEX();
    if(!HasSdrObject())
        return;

    GetSdrObject()->ForceMetricToItemPoolMetric(rPolyPolygon);
}

void SvxShape::ForceMetricToItemPoolMetric(basegfx::B2DHomMatrix& rB2DHomMatrix) const noexcept
{
    DBG_TESTSOLARMUTEX();
    if(!HasSdrObject())
        return;

    MapUnit eMapUnit(GetSdrObject()->getSdrModelFromSdrObject().GetItemPool().GetMetric(0));
    if(eMapUnit == MapUnit::Map100thMM)
        return;

    if (const auto eTo = MapToO3tlLength(eMapUnit); eTo != o3tl::Length::invalid)
    {
        const double fConvert(o3tl::convert(1.0, o3tl::Length::mm100, eTo));
        const basegfx::utils::B2DHomMatrixBufferedDecompose aDecomposedTransform(rB2DHomMatrix);
        rB2DHomMatrix = basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix(
            aDecomposedTransform.getScale() * fConvert,
            aDecomposedTransform.getShearX(),
            aDecomposedTransform.getRotate(),
            aDecomposedTransform.getTranslate() * fConvert);
    }
    else
    {
        OSL_FAIL("Missing unit translation to PoolMetric!");
    }
}

void SvxShape::ForceMetricTo100th_mm(Pair& rPoint) const noexcept
{
    DBG_TESTSOLARMUTEX();
    if(!HasSdrObject())
        return;

    MapUnit eMapUnit = GetSdrObject()->getSdrModelFromSdrObject().GetItemPool().GetMetric(0);
    if(eMapUnit == MapUnit::Map100thMM)
        return;

    if (const auto eFrom = MapToO3tlLength(eMapUnit); eFrom != o3tl::Length::invalid)
    {
        rPoint.A() = o3tl::convert(rPoint.A(), eFrom, o3tl::Length::mm100);
        rPoint.B() = o3tl::convert(rPoint.B(), eFrom, o3tl::Length::mm100);
    }
    else
    {
        OSL_FAIL("AW: Missing unit translation to 100th mm!");
    }
}

void SvxShape::ForceMetricTo100th_mm(basegfx::B2DPolyPolygon& rPolyPolygon) const noexcept
{
    DBG_TESTSOLARMUTEX();
    if(!HasSdrObject())
        return;

    MapUnit eMapUnit = GetSdrObject()->getSdrModelFromSdrObject().GetItemPool().GetMetric(0);
    if(eMapUnit == MapUnit::Map100thMM)
        return;

    if (const auto eFrom = MapToO3tlLength(eMapUnit); eFrom != o3tl::Length::invalid)
    {
        const double fConvert(o3tl::convert(1.0, eFrom, o3tl::Length::mm100));
        rPolyPolygon.transform(basegfx::utils::createScaleB2DHomMatrix(fConvert, fConvert));
    }
    else
    {
        OSL_FAIL("Missing unit translation to 100th mm!");
    }
}

void SvxShape::ForceMetricTo100th_mm(basegfx::B2DHomMatrix& rB2DHomMatrix) const noexcept
{
    DBG_TESTSOLARMUTEX();
    if(!HasSdrObject())
        return;

    MapUnit eMapUnit = GetSdrObject()->getSdrModelFromSdrObject().GetItemPool().GetMetric(0);
    if(eMapUnit == MapUnit::Map100thMM)
        return;

    if (const auto eFrom = MapToO3tlLength(eMapUnit); eFrom != o3tl::Length::invalid)
    {
        const double fConvert(o3tl::convert(1.0, eFrom, o3tl::Length::mm100));
        const basegfx::utils::B2DHomMatrixBufferedDecompose aDecomposedTransform(rB2DHomMatrix);
        rB2DHomMatrix = basegfx::utils::createScaleShearXRotateTranslateB2DHomMatrix(
            aDecomposedTransform.getScale() * fConvert,
            aDecomposedTransform.getShearX(),
            aDecomposedTransform.getRotate(),
            aDecomposedTransform.getTranslate() * fConvert);
    }
    else
    {
        OSL_FAIL("Missing unit translation to 100th mm!");
    }
}

static void SvxItemPropertySet_ObtainSettingsFromPropertySet(const SvxItemPropertySet& rPropSet, SvxItemPropertySetUsrAnys& rAnys,
  SfxItemSet& rSet, const uno::Reference< beans::XPropertySet >& xSet, const SfxItemPropertyMap* pMap )
{
    if(!rAnys.AreThereOwnUsrAnys())
        return;

    const SfxItemPropertyMap& rSrc = rPropSet.getPropertyMap();

    for(const SfxItemPropertyMapEntry* pSrcProp : rSrc.getPropertyEntries())
    {
        const sal_uInt16 nWID = pSrcProp->nWID;
        if(SfxItemPool::IsWhich(nWID)
                && (nWID < OWN_ATTR_VALUE_START || nWID > OWN_ATTR_VALUE_END)
                && rAnys.GetUsrAnyForID(*pSrcProp))
            rSet.Put(rSet.GetPool()->GetUserOrPoolDefaultItem(nWID));
    }

    for(const SfxItemPropertyMapEntry* pSrcProp : rSrc.getPropertyEntries())
    {
        if(pSrcProp->nWID)
        {
            uno::Any* pUsrAny = rAnys.GetUsrAnyForID(*pSrcProp);
            if(pUsrAny)
            {
                // search for equivalent entry in pDst
                const SfxItemPropertyMapEntry* pEntry = pMap->getByName( pSrcProp->aName );
                if(pEntry)
                {
                    // entry found
                    if(pEntry->nWID >= OWN_ATTR_VALUE_START && pEntry->nWID <= OWN_ATTR_VALUE_END)
                    {
                        // special ID in PropertySet, can only be set
                        // directly at the object
                        xSet->setPropertyValue( pSrcProp->aName, *pUsrAny);
                    }
                    else
                    {
                        SvxItemPropertySet_setPropertyValue(pEntry, *pUsrAny, rSet);
                    }
                }
            }
        }
    }
    rAnys.ClearAllUsrAny();
}


void SvxShape::ObtainSettingsFromPropertySet(const SvxItemPropertySet& rPropSet)
{
    DBG_TESTSOLARMUTEX();
    if(HasSdrObject() && maUrsAnys.AreThereOwnUsrAnys())
    {
        SfxItemSetFixed<SDRATTR_START, SDRATTR_END> aSet( GetSdrObject()->getSdrModelFromSdrObject().GetItemPool() );
        Reference< beans::XPropertySet > xShape(this);
        SvxItemPropertySet_ObtainSettingsFromPropertySet(rPropSet, maUrsAnys, aSet, xShape, &mpPropSet-&gt;getPropertyMap() );

        GetSdrObject()->SetMergedItemSetAndBroadcast(aSet);

        GetSdrObject()->ApplyNotPersistAttr( aSet );
    }
}

uno::Any SvxShape::GetBitmap( bool bMetaFile /* = false */ ) const
{
    DBG_TESTSOLARMUTEX();
    uno::Any aAny;

    if(!HasSdrObject() || nullptr == GetSdrObject()->getSdrPageFromSdrObject())
    {
        return aAny;
    }

    // tdf#118662 Emulate old behaviour of XclObjComment (see there)
    const SdrCaptionObj* pSdrCaptionObj(dynamic_cast<SdrCaptionObj*>(GetSdrObject()));
    if(nullptr != pSdrCaptionObj && pSdrCaptionObj->isSuppressGetBitmap())
    {
        return aAny;
    }

    // tdf#119180 If we do not ask for Metafile and we access a SdrGrafObj,
    // and content exists and is a Bitmap, take the shortcut.
    // Do *not* do this for Metafile - as can be seen, requested in that case
    // is a byte-sequence of a saved WMF format file (see below)
    if(!bMetaFile)
    {
        const SdrGrafObj* pSdrGrafObj(dynamic_cast<SdrGrafObj*>(GetSdrObject()));

        if(nullptr != pSdrGrafObj)
        {
            const Graphic& rGraphic(pSdrGrafObj->GetGraphic());

            if(GraphicType::Bitmap == rGraphic.GetType())
            {
                Reference< awt::XBitmap > xBmp( rGraphic.GetXGraphic(), UNO_QUERY );
                aAny <<= xBmp;

                return aAny;
            }
        }
    }

    // tdf#118662 instead of creating an E3dView instance every time to paint
    // a single SdrObject, use the existing SdrObject::SingleObjectPainter to
    // use less resources and runtime
    if(bMetaFile)
    {
        ScopedVclPtrInstance< VirtualDevice > pVDev;
        const tools::Rectangle aBoundRect(GetSdrObject()->GetCurrentBoundRect());
        GDIMetaFile aMtf;

        pVDev->SetMapMode(MapMode(MapUnit::Map100thMM));
        pVDev->EnableOutput(false);
        aMtf.Record(pVDev);
        GetSdrObject()->SingleObjectPainter(*pVDev);
        aMtf.Stop();
        aMtf.WindStart();
        aMtf.Move(-aBoundRect.Left(), -aBoundRect.Top());
        aMtf.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
        aMtf.SetPrefSize(aBoundRect.GetSize());

        SvMemoryStream aDestStrm(65535, 65535);

        ConvertGDIMetaFileToWMF(
            aMtf,
            aDestStrm,
            nullptr,
            false);

        const uno::Sequence<sal_Int8> aSeq(
            static_castconst sal_Int8* >(aDestStrm.GetData()),
            aDestStrm.GetEndOfData());

        aAny <<= aSeq;
    }
    else
    {
        drawinglayer::primitive2d::Primitive2DContainer xPrimitives;
        GetSdrObject()->GetViewContact().getViewIndependentPrimitive2DContainer(xPrimitives);

        if(!xPrimitives.empty())
        {
            const drawinglayer::geometry::ViewInformation2D aViewInformation2D;
            basegfx::B2DRange aRange(
                xPrimitives.getB2DRange(aViewInformation2D));

            if(!aRange.isEmpty())
            {
                const MapUnit aSourceMapUnit(GetSdrObject()->getSdrModelFromSdrObject().GetScaleUnit());

                if(MapUnit::Map100thMM != aSourceMapUnit)
                {
                    // tdf#119180 This is UNO API and thus works in 100th_mm,
                    // so if the MapMode from the used SdrModel is *not* equal
                    // to Map100thMM we need to embed the primitives to an adapting
                    // homogen transformation for correct values
                    const basegfx::B2DHomMatrix aMapTransform(
                        OutputDevice::LogicToLogic(
                            MapMode(aSourceMapUnit),
                            MapMode(MapUnit::Map100thMM)));

                    // Embed primitives to get them in 100th mm
                    xPrimitives = drawinglayer::primitive2d::Primitive2DContainer {
                            new drawinglayer::primitive2d::TransformPrimitive2D(
                                aMapTransform,
                                std::move(xPrimitives))
                    };

                    // Update basegfx::B2DRange aRange, too. Here we have the
                    // choice of transforming the existing value or get newly by
                    // again using 'xPrimitives.getB2DRange(aViewInformation2D)'
                    aRange.transform(aMapTransform);
                }

                const BitmapEx aBmp(
                    drawinglayer::convertPrimitive2DContainerToBitmapEx(
                        std::move(xPrimitives),
                        aRange));

                Graphic aGraph(aBmp);

                aGraph.SetPrefSize(aBmp.GetPrefSize());
                aGraph.SetPrefMapMode(aBmp.GetPrefMapMode());

                Reference< awt::XBitmap > xBmp( aGraph.GetXGraphic(), UNO_QUERY );
                aAny <<= xBmp;
            }
        }
    }

    return aAny;
}

uno::Sequence< uno::Type > SAL_CALL SvxShape::getTypes()
{
    if( mpImpl->mpMaster )
    {
        return mpImpl->mpMaster->getTypes();
    }
    else
    {
        return _getTypes();
    }
}


uno::Sequence< uno::Type > const & SvxShape::_getTypes()
{
    switch( mpImpl->mnObjId )
    {
    // shapes without text
    case SdrObjKind::Page:
    case SdrObjKind::OLEPluginFrame:
    case SdrObjKind::OLE2Plugin:
    case SdrObjKind::OLE2Applet:
    case SdrObjKind::E3D_Cube:
    case SdrObjKind::E3D_Sphere:
    case SdrObjKind::E3D_Lathe:
    case SdrObjKind::E3D_Extrusion:
    case SdrObjKind::E3D_Polygon:
    case SdrObjKind::Media:
    case SdrObjKind::Table:
        {
            static uno::Sequence<uno::Type> aTypeSequence{
                cppu::UnoType<drawing::XShape>::get(),
                cppu::UnoType<lang::XComponent>::get(),
                cppu::UnoType<beans::XPropertySet>::get(),
                cppu::UnoType<beans::XMultiPropertySet>::get(),
                cppu::UnoType<beans::XPropertyState>::get(),
                cppu::UnoType<beans::XMultiPropertyStates>::get(),
                cppu::UnoType<drawing::XGluePointsSupplier>::get(),
                cppu::UnoType<container::XChild>::get(),
                cppu::UnoType<lang::XServiceInfo>::get(),
                cppu::UnoType<lang::XTypeProvider>::get(),
                cppu::UnoType<lang::XUnoTunnel>::get(),
                cppu::UnoType<container::XNamed>::get(),
            };

            return aTypeSequence;
        }
    // group shape
    case SdrObjKind::Group:
        {
            static uno::Sequence<uno::Type> aTypeSequence{
                cppu::UnoType<drawing::XShape>::get(),
                cppu::UnoType<lang::XComponent>::get(),
                cppu::UnoType<beans::XPropertySet>::get(),
                cppu::UnoType<beans::XMultiPropertySet>::get(),
                cppu::UnoType<beans::XPropertyState>::get(),
                cppu::UnoType<beans::XMultiPropertyStates>::get(),
                cppu::UnoType<drawing::XGluePointsSupplier>::get(),
                cppu::UnoType<container::XChild>::get(),
                cppu::UnoType<lang::XServiceInfo>::get(),
                cppu::UnoType<lang::XTypeProvider>::get(),
                cppu::UnoType<lang::XUnoTunnel>::get(),
                cppu::UnoType<container::XNamed>::get(),
                cppu::UnoType<drawing::XShapes>::get(),
                cppu::UnoType<drawing::XShapeGroup>::get(),
            };

            return aTypeSequence;
        }
    // connector shape
    case SdrObjKind::Edge:
        {
            static uno::Sequence<uno::Type> aTypeSequence{
                cppu::UnoType<drawing::XShape>::get(),
                cppu::UnoType<lang::XComponent>::get(),
                cppu::UnoType<beans::XPropertySet>::get(),
                cppu::UnoType<beans::XMultiPropertySet>::get(),
                cppu::UnoType<beans::XPropertyState>::get(),
                cppu::UnoType<beans::XMultiPropertyStates>::get(),
                cppu::UnoType<drawing::XGluePointsSupplier>::get(),
                cppu::UnoType<container::XChild>::get(),
                cppu::UnoType<lang::XServiceInfo>::get(),
                cppu::UnoType<lang::XTypeProvider>::get(),
                cppu::UnoType<lang::XUnoTunnel>::get(),
                cppu::UnoType<container::XNamed>::get(),
                cppu::UnoType<drawing::XConnectorShape>::get(),
                // from SvxUnoTextBase::getTypes()
                cppu::UnoType<text::XTextAppend>::get(),
                cppu::UnoType<text::XTextCopy>::get(),
                cppu::UnoType<container::XEnumerationAccess>::get(),
                cppu::UnoType<text::XTextRangeMover>::get(),
            };

            return aTypeSequence;
        }
    // control shape
    case SdrObjKind::UNO:
        {
            static uno::Sequence<uno::Type> aTypeSequence{
                cppu::UnoType<drawing::XShape>::get(),
                cppu::UnoType<lang::XComponent>::get(),
                cppu::UnoType<beans::XPropertySet>::get(),
                cppu::UnoType<beans::XMultiPropertySet>::get(),
                cppu::UnoType<beans::XPropertyState>::get(),
                cppu::UnoType<beans::XMultiPropertyStates>::get(),
                cppu::UnoType<drawing::XGluePointsSupplier>::get(),
                cppu::UnoType<container::XChild>::get(),
                cppu::UnoType<lang::XServiceInfo>::get(),
                cppu::UnoType<lang::XTypeProvider>::get(),
                cppu::UnoType<lang::XUnoTunnel>::get(),
                cppu::UnoType<container::XNamed>::get(),
                cppu::UnoType<drawing::XControlShape>::get(),
            };

            return aTypeSequence;
        }
    // 3d scene shape
    case SdrObjKind::E3D_Scene:
        {
            static uno::Sequence<uno::Type> aTypeSequence{
                cppu::UnoType<drawing::XShape>::get(),
                cppu::UnoType<lang::XComponent>::get(),
                cppu::UnoType<beans::XPropertySet>::get(),
                cppu::UnoType<beans::XMultiPropertySet>::get(),
                cppu::UnoType<beans::XPropertyState>::get(),
                cppu::UnoType<beans::XMultiPropertyStates>::get(),
                cppu::UnoType<drawing::XGluePointsSupplier>::get(),
                cppu::UnoType<container::XChild>::get(),
                cppu::UnoType<lang::XServiceInfo>::get(),
                cppu::UnoType<lang::XTypeProvider>::get(),
                cppu::UnoType<lang::XUnoTunnel>::get(),
                cppu::UnoType<container::XNamed>::get(),
                cppu::UnoType<drawing::XShapes>::get(),
            };

            return aTypeSequence;
        }
    case SdrObjKind::CustomShape:
        {
            static uno::Sequence<uno::Type> aTypeSequence{
                cppu::UnoType<drawing::XShape>::get(),
                cppu::UnoType<lang::XComponent>::get(),
                cppu::UnoType<beans::XPropertySet>::get(),
                cppu::UnoType<beans::XMultiPropertySet>::get(),
                cppu::UnoType<beans::XPropertyState>::get(),
                cppu::UnoType<beans::XMultiPropertyStates>::get(),
                cppu::UnoType<drawing::XGluePointsSupplier>::get(),
                cppu::UnoType<container::XChild>::get(),
                cppu::UnoType<lang::XServiceInfo>::get(),
                cppu::UnoType<lang::XTypeProvider>::get(),
                cppu::UnoType<lang::XUnoTunnel>::get(),
                cppu::UnoType<container::XNamed>::get(),
                // from SvxUnoTextBase::getTypes()
                cppu::UnoType<text::XText>::get(),
                cppu::UnoType<container::XEnumerationAccess>::get(),
                cppu::UnoType<text::XTextRangeMover>::get(),
                cppu::UnoType<drawing::XEnhancedCustomShapeDefaulter>::get(),
            };

            return aTypeSequence;
        }
    // shapes with text
    case SdrObjKind::Rectangle:
    case SdrObjKind::CircleOrEllipse:
    case SdrObjKind::Measure:
    case SdrObjKind::Line:
    case SdrObjKind::Polygon:
    case SdrObjKind::PolyLine:
    case SdrObjKind::PathLine:
    case SdrObjKind::PathFill:
    case SdrObjKind::FreehandLine:
    case SdrObjKind::FreehandFill:
    case SdrObjKind::PathPoly:
    case SdrObjKind::PathPolyLine:
    case SdrObjKind::Graphic:
    case SdrObjKind::Text:
    case SdrObjKind::Caption:
    case SdrObjKind::OLE2: // #i118485# Moved to shapes with text
    default:
        {
            static uno::Sequence<uno::Type> aTypeSequence{
                cppu::UnoType<drawing::XShape>::get(),
                cppu::UnoType<lang::XComponent>::get(),
                cppu::UnoType<beans::XPropertySet>::get(),
                cppu::UnoType<beans::XMultiPropertySet>::get(),
                cppu::UnoType<beans::XPropertyState>::get(),
                cppu::UnoType<beans::XMultiPropertyStates>::get(),
                cppu::UnoType<drawing::XGluePointsSupplier>::get(),
                cppu::UnoType<container::XChild>::get(),
                cppu::UnoType<lang::XServiceInfo>::get(),
                cppu::UnoType<lang::XTypeProvider>::get(),
                cppu::UnoType<lang::XUnoTunnel>::get(),
                cppu::UnoType<container::XNamed>::get(),
                // from SvxUnoTextBase::getTypes()
                cppu::UnoType<text::XTextAppend>::get(),
                cppu::UnoType<text::XTextCopy>::get(),
                cppu::UnoType<container::XEnumerationAccess>::get(),
                cppu::UnoType<text::XTextRangeMover>::get(),
            };

            return aTypeSequence;
        }
    }
}


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

void SvxShape::Notify( SfxBroadcaster&, const SfxHint& rHint ) noexcept
{
    DBG_TESTSOLARMUTEX();

    // do cheap checks first, this method is hot
    if (rHint.GetId() != SfxHintId::ThisIsAnSdrHint)
        return;
    if( !mxSdrObject )
        return;
    const SdrHint* pSdrHint = static_cast<const SdrHint*>(&rHint);
    // #i55919# SdrHintKind::ObjectChange is only interesting if it's for this object
    if (pSdrHint->GetKind() != SdrHintKind::ObjectChange || pSdrHint->GetObject() != mxSdrObject.get())
        return;

    // prevent object being deleted from under us
    rtl::Reference<SdrObject> xSdrSelf(mxSdrObject);
    uno::Reference< uno::XInterface > xSelf( mxSdrObject->getWeakUnoShape() );
    if( !xSelf.is() )
    {
        mxSdrObject->RemoveListener(*this);
        mxSdrObject.clear();
        return;
    }

    updateShapeKind();
}

// XShape


// The "*LogicRectHack" functions also existed in sch, and those
// duplicate symbols cause Bad Things To Happen (TM)  #i9462#.
// Prefixing with 'svx' and marking static to make sure name collisions
// do not occur.

static bool svx_needLogicRectHack( SdrObject const * pObj )
{
    if( pObj->GetObjInventor() == SdrInventor::Default)
    {
        switch(pObj->GetObjIdentifier())
        {
        case SdrObjKind::Group:
        case SdrObjKind::Line:
        case SdrObjKind::Polygon:
        case SdrObjKind::PolyLine:
        case SdrObjKind::PathLine:
        case SdrObjKind::PathFill:
        case SdrObjKind::FreehandLine:
        case SdrObjKind::FreehandFill:
        case SdrObjKind::Edge:
        case SdrObjKind::PathPoly:
        case SdrObjKind::PathPolyLine:
        case SdrObjKind::Measure:
            return true;
        default:
            break;
        }
    }
    return false;
}


static tools::Rectangle svx_getLogicRectHack( SdrObject const * pObj )
{
    if(svx_needLogicRectHack(pObj))
    {
        return pObj->GetSnapRect();
    }
    else
    {
        return pObj->GetLogicRect();
    }
}


static void svx_setLogicRectHack( SdrObject* pObj, const tools::Rectangle& rRect )
{
    if(svx_needLogicRectHack(pObj))
    {
        pObj->SetSnapRect( rRect );
    }
    else
    {
        pObj->SetLogicRect( rRect );
    }
}


awt::Point SAL_CALL SvxShape::getPosition()
{
    ::SolarMutexGuard aGuard;

    if(HasSdrObject())
    {
        tools::Rectangle aRect( svx_getLogicRectHack(GetSdrObject()) );
        Point aPt( aRect.Left(), aRect.Top() );

        // Position is relative to anchor, so recalc to absolute position
        if( GetSdrObject()->getSdrModelFromSdrObject().IsWriter() )
            aPt -= GetSdrObject()->GetAnchorPos();

        ForceMetricTo100th_mm(aPt);
        return css::awt::Point( aPt.X(), aPt.Y() );
    }
    else
    {
        return maPosition;
    }
}


void SAL_CALL SvxShape::setPosition( const awt::Point& Position )
{
    ::SolarMutexGuard aGuard;

    if(HasSdrObject())
    {
        // do NOT move 3D objects, this would change the homogen
        // transformation matrix
        if(dynamic_cast<const E3dCompoundObject* >(GetSdrObject()) == nullptr)
        {
            tools::Rectangle aRect( svx_getLogicRectHack(GetSdrObject()) );
            Point aLocalPos( Position.X, Position.Y );
            ForceMetricToItemPoolMetric(aLocalPos);

            // Position is absolute, so recalc to position relative to anchor
            if( GetSdrObject()->getSdrModelFromSdrObject().IsWriter() )
                aLocalPos += GetSdrObject()->GetAnchorPos();

            tools::Long nDX = aLocalPos.X() - aRect.Left();
            tools::Long nDY = aLocalPos.Y() - aRect.Top();

            GetSdrObject()->Move( Size( nDX, nDY ) );
            GetSdrObject()->getSdrModelFromSdrObject().SetChanged();
        }
    }

    maPosition = Position;
}


awt::Size SAL_CALL SvxShape::getSize()
{
    ::SolarMutexGuard aGuard;

    if(HasSdrObject())
    {
        tools::Rectangle aRect( svx_getLogicRectHack(GetSdrObject()) );
        Size aObjSize( aRect.getOpenWidth(), aRect.getOpenHeight() );
        ForceMetricTo100th_mm(aObjSize);
        return css::awt::Size( aObjSize.getWidth(), aObjSize.getHeight() );
    }
    else
        return maSize;
}


void SAL_CALL SvxShape::setSize( const awt::Size& rSize )
{
    ::SolarMutexGuard aGuard;

    if(HasSdrObject())
    {
        tools::Rectangle aRect( svx_getLogicRectHack(GetSdrObject()) );
        Size aLocalSize( rSize.Width, rSize.Height );
        ForceMetricToItemPoolMetric(aLocalSize);

        if(GetSdrObject()->GetObjInventor() == SdrInventor::Default && GetSdrObject()->GetObjIdentifier() == SdrObjKind::Measure )
        {
            Fraction aWdt(aLocalSize.Width(),aRect.Right()-aRect.Left());
            Fraction aHgt(aLocalSize.Height(),aRect.Bottom()-aRect.Top());
            Point aPt = GetSdrObject()->GetSnapRect().TopLeft();
            GetSdrObject()->Resize(aPt,aWdt,aHgt);
        }
        else
        {
            //aRect.SetSize(aLocalSize); // this call subtract 1 // https://bz.apache.org/ooo/show_bug.cgi?id=83193
            if ( !aLocalSize.Width() )
            {
                aRect.SetWidthEmpty();
            }
            else
                aRect.setWidth(aLocalSize.Width());
            if ( !aLocalSize.Height() )
            {
                aRect.SetHeightEmpty();
            }
            else
                aRect.setHeight(aLocalSize.Height());

            svx_setLogicRectHack( GetSdrObject(), aRect );
        }

        GetSdrObject()->getSdrModelFromSdrObject().SetChanged();
    }
    maSize = rSize;
}


// XNamed
OUString SAL_CALL SvxShape::getName(  )
{
    ::SolarMutexGuard aGuard;
    if( HasSdrObject() )
    {
        return GetSdrObject()->GetName();
    }
    else
    {
        return maShapeName;
    }
}


void SAL_CALL SvxShape::setName( const OUString& aName )
{
    ::SolarMutexGuard aGuard;
    if( HasSdrObject() )
    {
        GetSdrObject()->SetName( aName );
    }
    else
    {
        maShapeName = aName;
    }
}

// XShapeDescriptor


OUString SAL_CALL SvxShape::getShapeType()
{
    if( !maShapeType.getLength() )
        return UHashMap::getNameFromId( mpImpl->mnObjId );
    else
        return maShapeType;
}

// XComponent


void SAL_CALL SvxShape::dispose()
{
    std::unique_lock g(m_aMutex);

    if( mpImpl->mbDisposing )
        return// caught a recursion

    mpImpl->mbDisposing = true;

    lang::EventObject aEvt;
    aEvt.Source = *static_cast<OWeakAggObject*>(this);
    mpImpl->maDisposeListeners.disposeAndClear(g, aEvt);
    mpImpl->maPropertyChangeListeners.disposeAndClear(g, aEvt);

    rtl::Reference<SdrObject> pObject = mxSdrObject;
    if (!pObject)
        return;

    pObject->RemoveListener( *this );

    if ( pObject->IsInserted() && pObject->getSdrPageFromSdrObject() )
    {
        SdrPage* pPage = pObject->getSdrPageFromSdrObject();
        // delete the SdrObject from the page
        const size_t nCount = pPage->GetObjCount();
        for ( size_t nNum = 0; nNum < nCount; ++nNum )
        {
            if ( pPage->GetObj( nNum ) == pObject.get() )
            {
                OSL_VERIFY( pPage->RemoveObject( nNum ) == pObject );
                break;
            }
        }
    }

    mxSdrObject.clear();
    pObject->setUnoShape(nullptr);
}


void SAL_CALL SvxShape::addEventListener( const Reference< lang::XEventListener >& xListener )
{
    std::unique_lock g(m_aMutex);
    mpImpl->maDisposeListeners.addInterface(g, xListener);
}


void SAL_CALL SvxShape::removeEventListener( const Reference< lang::XEventListener >& ;aListener )
{
    std::unique_lock g(m_aMutex);
    mpImpl->maDisposeListeners.removeInterface(g, aListener);
}

// XPropertySet


Reference< beans::XPropertySetInfo > SAL_CALL
    SvxShape::getPropertySetInfo()
{
    if( mpImpl->mpMaster )
    {
        return mpImpl->mpMaster->getPropertySetInfo();
    }
    else
    {
        return _getPropertySetInfo();
    }
}

rtl::Reference< SfxItemPropertySetInfo > const &
    SvxShape::_getPropertySetInfo()
{
    return mpPropSet->getPropertySetInfo();
}


void SAL_CALL SvxShape::addPropertyChangeListener( const OUString& _propertyName, const Reference< beans::XPropertyChangeListener >& _listener  )
{
    std::unique_lock g(m_aMutex);
    mpImpl->maPropertyChangeListeners.addInterface( g, _propertyName, _listener );
}


void SAL_CALL SvxShape::removePropertyChangeListener( const OUString& _propertyName, const Reference< beans::XPropertyChangeListener >& _listener  )
{
    std::unique_lock g(m_aMutex);
    mpImpl->maPropertyChangeListeners.removeInterface( g, _propertyName, _listener );
}


void SAL_CALL SvxShape::addVetoableChangeListener( const OUString& , const Reference< beans::XVetoableChangeListener >&  )
{
    OSL_FAIL( "SvxShape::addVetoableChangeListener: don't have any vetoable properties, so why ...?" );
}


void SAL_CALL SvxShape::removeVetoableChangeListener( const OUString& , const Reference< beans::XVetoableChangeListener >&  )
{
    OSL_FAIL( "SvxShape::removeVetoableChangeListener: don't have any vetoable properties, so why ...?" );
}


bool SvxShape::SetFillAttribute( sal_uInt16 nWID, const OUString& rName )
{
    if(HasSdrObject())
    {
        SfxItemSet aSet( GetSdrObject()->getSdrModelFromSdrObject().GetItemPool(), nWID, nWID );

        if( SetFillAttribute( nWID, rName, aSet, &GetSdrObject()->getSdrModelFromSdrObject() ) )
        {
            //GetSdrObject()->SetItemSetAndBroadcast(aSet);
            GetSdrObject()->SetMergedItemSetAndBroadcast(aSet);

            return true;
        }
    }

    return false;
}


bool SvxShape::SetFillAttribute( sal_uInt16 nWID, const OUString& rName, SfxItemSet&&nbsp;rSet, SdrModel const * pModel )
{
    // check if an item with the given name and which id is inside the models
    // pool or the stylesheet pool, if found it's put in the itemset
    if( !SetFillAttribute( nWID, rName, rSet ) )
    {
        // we did not find such item in one of the pools, so we check
        // the property lists that are loaded for the model for items
        // that support such.
        OUString aStrName = SvxUnogetInternalNameForItem(nWID, rName);

        switch( nWID )
        {
        case XATTR_FILLBITMAP:
        {
            XBitmapListRef pBitmapList = pModel->GetBitmapList();

            if( !pBitmapList.is() )
                return false;

            tools::Long nPos = pBitmapList->GetIndex(aStrName);
            if( nPos == -1 )
                return false;

            const XBitmapEntry* pEntry = pBitmapList->GetBitmap(nPos);
            XFillBitmapItem aBmpItem(rName, pEntry->GetGraphicObject());
            rSet.Put(aBmpItem);
            break;
        }
        case XATTR_FILLGRADIENT:
        {
            XGradientListRef pGradientList = pModel->GetGradientList();

            if( !pGradientList.is() )
                return false;

            tools::Long nPos = pGradientList->GetIndex(aStrName);
            if( nPos == -1 )
                return false;

            const XGradientEntry* pEntry = pGradientList->GetGradient(nPos);
            XFillGradientItem aGrdItem(rName, pEntry->GetGradient());
            rSet.Put( aGrdItem );
            break;
        }
        case XATTR_FILLHATCH:
        {
            XHatchListRef pHatchList = pModel->GetHatchList();

            if( !pHatchList.is() )
                return false;

            tools::Long nPos = pHatchList->GetIndex(aStrName);
            if( nPos == -1 )
                return false;

            const XHatchEntry* pEntry = pHatchList->GetHatch( nPos );
            XFillHatchItem aHatchItem(rName, pEntry->GetHatch());
            rSet.Put( aHatchItem );
            break;
        }
        case XATTR_LINEEND:
        case XATTR_LINESTART:
        {
            XLineEndListRef pLineEndList = pModel->GetLineEndList();

            if( !pLineEndList.is() )
                return false;

            tools::Long nPos = pLineEndList->GetIndex(aStrName);
            if( nPos == -1 )
                return false;

            const XLineEndEntry* pEntry = pLineEndList->GetLineEnd(nPos);
            if( sal_uInt16(XATTR_LINEEND) == nWID )
            {
                XLineEndItem aLEItem(rName, pEntry->GetLineEnd());
                rSet.Put( aLEItem );
            }
            else
            {
                XLineStartItem aLSItem(rName, pEntry->GetLineEnd());
                rSet.Put( aLSItem );
            }

            break;
        }
        case XATTR_LINEDASH:
        {
            XDashListRef pDashList = pModel->GetDashList();

            if( !pDashList.is() )
                return false;

            tools::Long nPos = pDashList->GetIndex(aStrName);
            if( nPos == -1 )
                return false;

            const XDashEntry* pEntry = pDashList->GetDash(nPos);
            XLineDashItem aDashItem(rName, pEntry->GetDash());
            rSet.Put( aDashItem );
            break;
        }
        default:
            return false;
        }
    }

    return true;
}


bool SvxShape::SetFillAttribute( sal_uInt16 nWID, const OUString& rName, SfxItemSet&&nbsp;rSet )
{
    OUString aName = SvxUnogetInternalNameForItem(nWID, rName);

    if (aName.isEmpty())
    {
        switch( nWID )
        {
        case XATTR_LINEEND:
        case XATTR_LINESTART:
            {
                const basegfx::B2DPolyPolygon aEmptyPoly;
                if( nWID == sal_uInt16(XATTR_LINEEND) )
                    rSet.Put( XLineEndItem( u""_ustr, aEmptyPoly ) );
                else
                    rSet.Put( XLineStartItem( u""_ustr, aEmptyPoly ) );

                return true;
            }
        case XATTR_FILLFLOATTRANSPARENCE:
            {
                // #85953# Set a disabled XFillFloatTransparenceItem
                rSet.Put(XFillFloatTransparenceItem());

                return true;
            }
        }

        return false;
    }

    SfxItemType eItemType;
    switch (nWID)
    {
        case XATTR_FILLBITMAP: eItemType = SfxItemType::XFillBitmapItemType; break;
        case XATTR_FILLGRADIENT: eItemType = SfxItemType::XFillGradientItemType; break;
        case XATTR_FILLHATCH: eItemType = SfxItemType::XFillHatchItemType; break;
        case XATTR_FILLFLOATTRANSPARENCE: eItemType = SfxItemType::XFillFloatTransparenceItemType; break;
        case XATTR_LINEEND: eItemType = SfxItemType::XLineEndItemType; break;
        case XATTR_LINESTART: eItemType = SfxItemType::XLineStartItemType; break;
        case XATTR_LINEDASH: eItemType = SfxItemType::XLineDashItemType; break;
        default: assert(false); abort();
    }
    for (const SfxPoolItem* p : rSet.GetPool()->GetItemSurrogatesForItem(eItemType))
    {
        const NameOrIndex* pItem = static_cast<const NameOrIndex*>(p);
        if( pItem->GetName() == aName )
        {
            rSet.Put( *pItem );
            return true;
        }
    }

    return false;
}


void SAL_CALL SvxShape::setPropertyValue( const OUString& rPropertyName, const uno::Any& rVal )
{
    if( mpImpl->mpMaster )
    {
        mpImpl->mpMaster->setPropertyValue( rPropertyName, rVal );
    }
    else
    {
        _setPropertyValue( rPropertyName, rVal );
    }
}

void SvxShape::_setPropertyValue( const OUString& rPropertyName, const uno::Any&&nbsp;rVal )
{
    ::SolarMutexGuard aGuard;

    const SfxItemPropertyMapEntry* pMap = mpPropSet->getPropertyMapEntry(rPropertyName);

    if (!HasSdrObject())
    {
        // Since we have no actual sdr object right now, remember all
        // properties in a list. These properties will be set when the sdr
        // object is created.

        if (pMap && pMap->nWID)
        {
            // FIXME: We should throw a UnknownPropertyException here.
            //        But since this class is aggregated from classes that
            //        support additional properties that we don't know here we
            //        silently store *all* properties, even if they may be not
            //        supported after creation.
            SvxItemPropertySet::setPropertyValue( pMap, rVal, maUrsAnys );
        }

        return;
    }

    if (rPropertyName == "HandlePathObjScale")
    {
        auto pPathObj = dynamic_cast<SdrPathObj*>(GetSdrObject());
        if (pPathObj)
        {
            bool bHandleScale{};
            if (rVal >>= bHandleScale)
            {
                pPathObj->SetHandleScale(bHandleScale);
            }
        }
        return;
    }

    // A hack to avoid taking incomplete OLE object's size into account when loading
    // see SdXMLObjectShapeContext::createFastChildContext
    if (rPropertyName == "IgnoreOLEObjectScale")
    {
        if (auto pOleObj = DynCastSdrOle2Obj(GetSdrObject()))
            if (bool bVal; rVal >>= bVal)
                pOleObj->SetIgnoreOLEObjectScale(bVal);
        return;
    }

    if (!pMap)
    {
        // The oox layer sets these properties willy-nilly on objects, even if the objects do not support them.
        // And then it ignores the resulting exceptions, but exception throwing and catching becomes expensive
        // with complex spreadsheets. So just ignore it here, in absence of a better fix.
        if (rPropertyName == "FromWordArt" || rPropertyName == "GraphicColorMode" || rPropertyName == "Representation")
        {
            SAL_WARN("svx""Ignoring property " << rPropertyName);
            return;
        }
        throw beans::UnknownPropertyException( rPropertyName, getXWeak());
    }

    if ((pMap->nFlags & beans::PropertyAttribute::READONLY) != 0)
        throw beans::PropertyVetoException(
            "Readonly property can't be set: " + rPropertyName,
            uno::Reference<drawing::XShape>(this));

    GetSdrObject()->getSdrModelFromSdrObject().SetChanged();

    if (setPropertyValueImpl(rPropertyName, pMap, rVal))
        return;

    DBG_ASSERT( pMap->nWID == SDRATTR_TEXTDIRECTION || pMap->nWID < SDRATTR_NOTPERSIST_FIRST || pMap->nWID > SDRATTR_NOTPERSIST_LAST, "Not persist item not handled!" );
    DBG_ASSERT( pMap->nWID < OWN_ATTR_VALUE_START || pMap->nWID > OWN_ATTR_VALUE_END, "Not item property not handled!" );

    bool bIsNotPersist = pMap->nWID >= SDRATTR_NOTPERSIST_FIRST && pMap->nWID <= SDRATTR_NOTPERSIST_LAST && pMap->nWID != SDRATTR_TEXTDIRECTION;

    if( pMap->nWID == SDRATTR_CORNER_RADIUS )
    {
        sal_Int32 nCornerRadius = 0;
        if( !(rVal >>= nCornerRadius) || (nCornerRadius < 0) || (nCornerRadius > 5000000))
            throw IllegalArgumentException();
    }

    std::optional<SfxItemSet> xLocalSet;
    SfxItemSet* pSet;
    if( mbIsMultiPropertyCall && !bIsNotPersist )
    {
        if( !mpImpl->moItemSet )
        {
            mpImpl->moItemSet.emplace( GetSdrObject()->GetProperties().CreateObjectSpecificItemSet( GetSdrObject()->getSdrModelFromSdrObject().GetItemPool() ) );
        }
        pSet = &*mpImpl->moItemSet;
    }
    else
    {
        xLocalSet.emplace( GetSdrObject()->getSdrModelFromSdrObject().GetItemPool(), pMap->nWID, pMap->nWID);
        pSet = &*xLocalSet;
    }

    if( pSet->GetItemState( pMap->nWID ) != SfxItemState::SET )
        pSet->Put(GetSdrObject()->GetMergedItem(pMap->nWID));

    if( !SvxUnoTextRangeBase::SetPropertyValueHelper( pMap, rVal, *pSet ))
    {
        if( pSet->GetItemState( pMap->nWID ) != SfxItemState::SET )
        {
            if(bIsNotPersist)
            {
                // not-persistent attribute, get those extra
                GetSdrObject()->TakeNotPersistAttr(*pSet);
            }
        }

        if( pSet->GetItemState( pMap->nWID ) != SfxItemState::SET )
        {
            // get default from ItemPool
            if(SfxItemPool::IsWhich(pMap->nWID))
                pSet->Put(GetSdrObject()->getSdrModelFromSdrObject().GetItemPool().GetUserOrPoolDefaultItem(pMap->nWID));
        }

        if( pSet->GetItemState( pMap->nWID ) == SfxItemState::SET )
        {
            SvxItemPropertySet_setPropertyValue( pMap, rVal, *pSet );
        }
    }

    if(bIsNotPersist)
    {
        // set not-persistent attribute extra
        GetSdrObject()->ApplyNotPersistAttr( *pSet );
    }
    else
    {
        // if we have a XMultiProperty call then the item set
        // will be set in setPropertyValues later
        if( !mbIsMultiPropertyCall )
            GetSdrObject()->SetMergedItemSetAndBroadcast( *pSet );
    }
}


uno::Any SAL_CALL SvxShape::getPropertyValue( const OUString& PropertyName )
{
    if ( mpImpl->mpMaster )
        return mpImpl->mpMaster->getPropertyValue( PropertyName );
    else
        return _getPropertyValue( PropertyName );
}


uno::Any SvxShape::_getPropertyValue( const OUString& PropertyName )
{
    ::SolarMutexGuard aGuard;

    const SfxItemPropertyMapEntry* pMap = mpPropSet->getPropertyMapEntry(PropertyName);

    uno::Any aAny;
    if(HasSdrObject())
    {
        if(pMap == nullptr )
            throw beans::UnknownPropertyException( PropertyName, getXWeak());

        if( !getPropertyValueImpl( PropertyName, pMap, aAny ) )
        {
            DBG_ASSERT( pMap->nWID == SDRATTR_TEXTDIRECTION || (pMap->nWID < SDRATTR_NOTPERSIST_FIRST || pMap->nWID > SDRATTR_NOTPERSIST_LAST), "Not persist item not handled!" );
            DBG_ASSERT( pMap->nWID < OWN_ATTR_VALUE_START || pMap->nWID > OWN_ATTR_VALUE_END, "Not item property not handled!" );

            SfxItemSet aSet( GetSdrObject()->getSdrModelFromSdrObject().GetItemPool(), pMap->nWID, pMap->nWID );
            aSet.Put(GetSdrObject()->GetMergedItem(pMap->nWID));

            if(SvxUnoTextRangeBase::GetPropertyValueHelper(  aSet, pMap, aAny ))
                return aAny;

            if(!aSet.Count())
            {
                if(pMap->nWID >= SDRATTR_NOTPERSIST_FIRST && pMap->nWID <= SDRATTR_NOTPERSIST_LAST)
                {
                    // not-persistent attribute, get those extra
                    GetSdrObject()->TakeNotPersistAttr(aSet);
                }
            }

            if(!aSet.Count())
            {
                // get default from ItemPool
                if(SfxItemPool::IsWhich(pMap->nWID))
                    aSet.Put(GetSdrObject()->getSdrModelFromSdrObject().GetItemPool().GetUserOrPoolDefaultItem(pMap->nWID));
            }

            if(aSet.Count())
                aAny = GetAnyForItem( aSet, pMap );
        }
    }
    else
    {

// Fixme: we should return default values for OWN_ATTR !

        if(pMap && pMap->nWID)
//      FixMe: see setPropertyValue
            aAny = mpPropSet->getPropertyValue( pMap, maUrsAnys );

    }
    return aAny;
}


// XMultiPropertySet
void SAL_CALL SvxShape::setPropertyValues( const css::uno::Sequence< OUString >& aPropertyNames, const css::uno::Sequence< css::uno::Any >& aValues )
{
    ::SolarMutexGuard aSolarGuard;

    const sal_Int32 nCount = aPropertyNames.getLength();
    if (nCount != aValues.getLength())
        throw css::lang::IllegalArgumentException(u"lengths do not match"_ustr,
                                                  getXWeak(), -1);

    const OUString* pNames = aPropertyNames.getConstArray();
    const uno::Any* pValues = aValues.getConstArray();

    // make sure mbIsMultiPropertyCall and mpImpl->mpItemSet are
    // reset even when an exception is thrown
    const ::comphelper::ScopeGuard aGuard( [this] () { return this->endSetPropertyValues(); } );

    mbIsMultiPropertyCall = true;

    if( mpImpl->mpMaster )
    {
        for( sal_Int32 nIdx = 0; nIdx < nCount; nIdx++, pNames++, pValues++ )
        {
            try
            {
                setPropertyValue( *pNames, *pValues );
            }
            catch (beans::UnknownPropertyException&)
            {
                // ignore, various code likes to opportunistically set properties on objects that don't support those properties
            }
            catch (uno::Exception&)
            {
                DBG_UNHANDLED_EXCEPTION("svx");
            }
        }
    }
    else
    {
        uno::Reference< beans::XPropertySet > xSet;
        queryInterface( cppu::UnoType<beans::XPropertySet>::get()) >>= xSet;

        for( sal_Int32 nIdx = 0; nIdx < nCount; nIdx++, pNames++, pValues++ )
        {
            try
            {
                xSet->setPropertyValue( *pNames, *pValues );
            }
            catch (beans::UnknownPropertyException&)
            {
                DBG_UNHANDLED_EXCEPTION("svx");
            }
            catch (uno::Exception&)
            {
                DBG_UNHANDLED_EXCEPTION("svx");
            }
        }
    }

    if( mpImpl->moItemSet && HasSdrObject() )
        GetSdrObject()->SetMergedItemSetAndBroadcast( *mpImpl->moItemSet );
}


void SvxShape::endSetPropertyValues()
{
    mbIsMultiPropertyCall = false;
    mpImpl->moItemSet.reset();
}


css::uno::Sequence< css::uno::Any > SAL_CALL SvxShape::getPropertyValues( const css::uno::Sequence< OUString >& aPropertyNames )
{
    const sal_Int32 nCount = aPropertyNames.getLength();
    const OUString* pNames = aPropertyNames.getConstArray();

    uno::Sequence< uno::Any > aRet( nCount );
    uno::Any* pValue = aRet.getArray();

    if( mpImpl->mpMaster )
    {
        for( sal_Int32 nIdx = 0; nIdx < nCount; nIdx++, pValue++, pNames++ )
        {
            try
            {
                *pValue = getPropertyValue( *pNames );
            }
            catch( uno::Exception& )
            {
                OSL_FAIL( "SvxShape::getPropertyValues, unknown property asked" );
            }
        }
    }
    else
    {
        uno::Reference< beans::XPropertySet > xSet;
        queryInterface( cppu::UnoType<beans::XPropertySet>::get()) >>= xSet;

        for( sal_Int32 nIdx = 0; nIdx < nCount; nIdx++, pValue++, pNames++ )
        {
            try
            {
                *pValue = xSet->getPropertyValue( *pNames );
            }
            catch( uno::Exception& )
            {
                OSL_FAIL( "SvxShape::getPropertyValues, unknown property asked" );
            }
        }
    }

    return aRet;
}

void SAL_CALL SvxShape::addPropertiesChangeListener( const css::uno::Sequence< OUString >& , const css::uno::Reference< css::beans::XPropertiesChangeListener >&  )
{
}

void SAL_CALL SvxShape::removePropertiesChangeListener( const css::uno::Reference< css::beans::XPropertiesChangeListener >&  )
{
}

void SAL_CALL SvxShape::firePropertiesChangeEvent( const css::uno::Sequence< OUString >&&nbsp;, const css::uno::Reference< css::beans::XPropertiesChangeListener >&  )
{
}


uno::Any SvxShape::GetAnyForItem( SfxItemSet const & aSet, const SfxItemPropertyMapEntry* pMap ) const
{
    DBG_TESTSOLARMUTEX();
    uno::Any aAny;

    switch(pMap->nWID)
    {
    case SDRATTR_CIRCSTARTANGLE:
    {
        if(const SdrAngleItem* pPoolItem = aSet.GetItemIfSet(SDRATTR_CIRCSTARTANGLE,false))
        {
            Degree100 nAngle = pPoolItem->GetValue();
            aAny <<= nAngle.get();
        }
        break;
    }

    case SDRATTR_CIRCENDANGLE:
    {
        if (const SdrAngleItem* pPoolItem = aSet.GetItemIfSet(SDRATTR_CIRCENDANGLE,false))
        {
            Degree100 nAngle = pPoolItem->GetValue();
            aAny <<= nAngle.get();
        }
        break;
    }

    case SDRATTR_CIRCKIND:
    {
        if( GetSdrObject()->GetObjInventor() == SdrInventor::Default)
        {
            drawing::CircleKind eKind;
            switch(GetSdrObject()->GetObjIdentifier())
            {
            case SdrObjKind::CircleOrEllipse:          // circle, ellipse
                eKind = drawing::CircleKind_FULL;
                break;
            case SdrObjKind::CircleCut:          // segment of circle
                eKind = drawing::CircleKind_CUT;
                break;
            case SdrObjKind::CircleArc:          // arc of circle
                eKind = drawing::CircleKind_ARC;
                break;
            case SdrObjKind::CircleSection:          // sector
                eKind = drawing::CircleKind_SECTION;
                break;
            default:
                break;
            }
            aAny <<= eKind;
        }
        break;
    }
    default:
    {
        // get value from ItemSet
        aAny = SvxItemPropertySet_getPropertyValue( pMap, aSet );

        SAL_WARN_IF(!pMap->aType.isAssignableFrom(aAny.getValueType())
                        && aAny.getValueType() != cppu::UnoType<void>::get()
                        && !(pMap->nWID == XATTR_FILLBITMAP && pMap->nMemberId == MID_BITMAP
                             && aAny.getValueType() == cppu::UnoType<css::awt::XBitmap>::get()),
                    "svx",
                    "SvxShape::GetAnyForItem() Return value for property "
                        << pMap->aName << " has wrong Type, " << pMap->aType
                        << " != " << aAny.getValueType());
    }
    }

    return aAny;
}


// XPropertyState
beans::PropertyState SAL_CALL SvxShape::getPropertyState( const OUString& PropertyName )
{
    if( mpImpl->mpMaster )
    {
        return mpImpl->mpMaster->getPropertyState( PropertyName );
    }
    else
    {
        return _getPropertyState( PropertyName );
    }
}

beans::PropertyState SvxShape::_getPropertyState( const OUString& PropertyName )
{
    ::SolarMutexGuard aGuard;

    const SfxItemPropertyMapEntry* pMap = mpPropSet->getPropertyMapEntry(PropertyName);

    if( !HasSdrObject() || pMap == nullptr )
        throw beans::UnknownPropertyException( PropertyName, getXWeak());

    beans::PropertyState eState;
    if( !getPropertyStateImpl( pMap, eState ) )
    {
        const SfxItemSet& rSet = GetSdrObject()->GetMergedItemSet();

        switch( rSet.GetItemState( pMap->nWID, false ) )
        {
        case SfxItemState::SET:
            eState = beans::PropertyState_DIRECT_VALUE;
            break;
        case SfxItemState::DEFAULT:
            eState = beans::PropertyState_DEFAULT_VALUE;
            break;
        default:
            eState = beans::PropertyState_AMBIGUOUS_VALUE;
            break;
        }

        // if an item is set, this doesn't mean we want it :)
        if( beans::PropertyState_DIRECT_VALUE == eState )
        {
            switch( pMap->nWID )
            {
            // the following items are disabled by changing the
            // fill style or the line style. so there is no need
            // to export items without names which should be empty
            case XATTR_FILLBITMAP:
            case XATTR_FILLGRADIENT:
            case XATTR_FILLHATCH:
            case XATTR_LINEDASH:
                {
                    const NameOrIndex* pItem = rSet.GetItem<NameOrIndex>(pMap->nWID);
                    if( ( pItem == nullptr ) || pItem->GetName().isEmpty() )
                        eState = beans::PropertyState_DEFAULT_VALUE;
                }
                break;

            // #i36115#
            // If e.g. the LineStart is on NONE and thus the string has length 0, it still
            // may be a hard attribute covering the set LineStart of the parent (Style).
            // #i37644#
            // same is for fill float transparency
            case XATTR_LINEEND:
            case XATTR_LINESTART:
            case XATTR_FILLFLOATTRANSPARENCE:
                {
                    const NameOrIndex* pItem = rSet.GetItem<NameOrIndex>(pMap->nWID);
                    if ( pItem == nullptr )
                        eState = beans::PropertyState_DEFAULT_VALUE;
                }
                break;
            case XATTR_FILLCOLOR:
                if (pMap->nMemberId == MID_COLOR_THEME_INDEX)
                {
                    const XFillColorItem* pColor = rSet.GetItem<XFillColorItem>(pMap->nWID);
                    if (!pColor->getComplexColor().isValidThemeType())
                    {
                        eState = beans::PropertyState_DEFAULT_VALUE;
                    }
                }
                else if (pMap->nMemberId == MID_COLOR_LUM_MOD)
                {
                    const XFillColorItem* pColor = rSet.GetItem<XFillColorItem>(pMap->nWID);
                    sal_Int16 nLumMod = 10000;
                    for (auto const& rTransform : pColor->getComplexColor().getTransformations())
                    {
                        if (rTransform.meType == model::TransformationType::LumMod)
                            nLumMod = rTransform.mnValue;
                    }
                    if (nLumMod == 10000)
                    {
                        eState = beans::PropertyState_DEFAULT_VALUE;
                    }
                }
                else if (pMap->nMemberId == MID_COLOR_LUM_OFF)
                {
                    const XFillColorItem* pColor = rSet.GetItem<XFillColorItem>(pMap->nWID);
                    sal_Int16 nLumOff = 0;
                    for (auto const& rTransform : pColor->getComplexColor().getTransformations())
                    {
                        if (rTransform.meType == model::TransformationType::LumOff)
                            nLumOff = rTransform.mnValue;
                    }
                    if (nLumOff == 0)
                    {
                        eState = beans::PropertyState_DEFAULT_VALUE;
                    }
                }
                else if (pMap->nMemberId == MID_COMPLEX_COLOR)
                {
                    auto const* pColor = rSet.GetItem<XFillColorItem>(pMap->nWID);
                    if (pColor->getComplexColor().getType() == model::ColorType::Unused)
                    {
                        eState = beans::PropertyState_DEFAULT_VALUE;
                    }
                }
                break;
            case XATTR_LINECOLOR:
                if (pMap->nMemberId == MID_COMPLEX_COLOR)
                {
                    auto const* pColor = rSet.GetItem<XLineColorItem>(pMap->nWID);
                    if (pColor->getComplexColor().getType() == model::ColorType::Unused)
                    {
                        eState = beans::PropertyState_DEFAULT_VALUE;
                    }
                }
                break;
            }
        }
    }
    return eState;
}

bool SvxShape::setPropertyValueImpl( const OUString&, const SfxItemPropertyMapEntry* pProperty, const css::uno::Any& rValue )
{
    rtl::Reference<SdrObject> pSdrObject = GetSdrObject();
    switch( pProperty->nWID )
    {
    case OWN_ATTR_CAPTION_POINT:
    {
        awt::Point aPnt;
        if( rValue >>= aPnt )
        {
            Point aVclPoint( aPnt.X, aPnt.Y );

            // tdf#117145 metric of SdrModel is app-specific, metric of UNO API is 100thmm
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=95 H=97 G=95

¤ Dauer der Verarbeitung: 0.41 Sekunden  (vorverarbeitet)  ¤

*© 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.