Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/LibreOffice/xmloff/source/text/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 63 kB image not shown  

Quelle  XMLTextFrameContext.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 <o3tl/string_view.hxx>
#include <osl/diagnose.h>
#include <sal/log.hxx>
#include <comphelper/diagnose_ex.hxx>
#include <comphelper/base64.hxx>
#include <comphelper/configuration.hxx>
#include <comphelper/mediamimetype.hxx>
#include <com/sun/star/frame/XModel.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/text/TextContentAnchorType.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/text/XTextFrame.hpp>
#include <com/sun/star/container/XNamed.hpp>
#include <com/sun/star/container/XNameContainer.hpp>
#include <com/sun/star/graphic/XGraphic.hpp>
#include <com/sun/star/text/SizeType.hpp>
#include <com/sun/star/drawing/XShape.hpp>
#include <com/sun/star/document/XEventsSupplier.hpp>
#include <com/sun/star/document/XEmbeddedObjectSupplier.hpp>
#include <com/sun/star/io/XOutputStream.hpp>
#include <com/sun/star/text/HoriOrientation.hpp>
#include <com/sun/star/text/VertOrientation.hpp>
#include <sax/tools/converter.hxx>
#include <utility>
#include <xmloff/xmlimp.hxx>
#include <xmloff/xmltoken.hxx>
#include <xmloff/xmlnamespace.hxx>
#include <xmloff/xmluconv.hxx>
#include "XMLAnchorTypePropHdl.hxx"
#include <XMLEmbeddedObjectImportContext.hxx>
#include <xmloff/XMLBase64ImportContext.hxx>
#include <XMLReplacementImageContext.hxx>
#include <xmloff/prstylei.hxx>
#include <xmloff/i18nmap.hxx>
#include <xexptran.hxx>
#include <xmloff/shapeimport.hxx>
#include <xmloff/XMLEventsImportContext.hxx>
#include <XMLImageMapContext.hxx>
#include "XMLTextFrameContext.hxx"
#include <basegfx/polygon/b2dpolygon.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <basegfx/polygon/b2dpolypolygon.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <basegfx/numeric/ftools.hxx>
#include <map>
#include <string_view>

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::text;
using namespace ::com::sun::star::xml::sax;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::drawing;
using namespace ::com::sun::star::document;
using namespace ::xmloff::token;
using ::com::sun::star::document::XEventsSupplier;

#define XML_TEXT_FRAME_TEXTBOX 1
#define XML_TEXT_FRAME_GRAPHIC 2
#define XML_TEXT_FRAME_OBJECT 3
#define XML_TEXT_FRAME_OBJECT_OLE 4
#define XML_TEXT_FRAME_APPLET 5
#define XML_TEXT_FRAME_PLUGIN 6
#define XML_TEXT_FRAME_FLOATING_FRAME 7

typedef ::std::map < const OUString, OUString > ParamMap;

class XMLTextFrameContextHyperlink_Impl
{
    OUString sHRef;
    OUString sName;
    OUString sTargetFrameName;
    bool bMap;

public:

    inline XMLTextFrameContextHyperlink_Impl( OUString aHRef,
                       OUString aName,
                       OUString aTargetFrameName,
                       bool bMap );

    const OUString& GetHRef() const { return sHRef; }
    const OUString& GetName() const { return sName; }
    const OUString& GetTargetFrameName() const { return sTargetFrameName; }
    bool GetMap() const { return bMap; }
};

inline XMLTextFrameContextHyperlink_Impl::XMLTextFrameContextHyperlink_Impl(
    OUString aHRef, OUString aName,
    OUString aTargetFrameName, bool bM ) :
    sHRef(std::move( aHRef )),
    sName(std::move( aName )),
    sTargetFrameName(std::move( aTargetFrameName )),
    bMap( bM )
{
}

namespace {

// Implement Title/Description Elements UI (#i73249#)
class XMLTextFrameTitleOrDescContext_Impl : public SvXMLImportContext
{
    OUString&   mrTitleOrDesc;

public:


    XMLTextFrameTitleOrDescContext_Impl( SvXMLImport& rImport,
                                         OUString& rTitleOrDesc );

    virtual void SAL_CALL characters( const OUString& rText ) override;
};

}

XMLTextFrameTitleOrDescContext_Impl::XMLTextFrameTitleOrDescContext_Impl(
        SvXMLImport& rImport,
        OUString& rTitleOrDesc )
    : SvXMLImportContext( rImport )
    , mrTitleOrDesc( rTitleOrDesc )
{
}

void XMLTextFrameTitleOrDescContext_Impl::characters( const OUString& rText )
{
    mrTitleOrDesc += rText;
}

namespace {

class XMLTextFrameParam_Impl : public SvXMLImportContext
{
public:
    XMLTextFrameParam_Impl( SvXMLImport& rImport,
            const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList,
            ParamMap &rParamMap);
};

}

XMLTextFrameParam_Impl::XMLTextFrameParam_Impl(
        SvXMLImport& rImport,
        const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList,
        ParamMap &rParamMap):
    SvXMLImportContext( rImport )
{
    OUString sName, sValue;
    bool bFoundValue = false// to allow empty values
    for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
    {
        switch (aIter.getToken())
        {
            case XML_ELEMENT(DRAW, XML_VALUE):
            {
                sValue = aIter.toString();
                bFoundValue = true;
                break;
            }
            case XML_ELEMENT(DRAW, XML_NAME):
                sName = aIter.toString();
                break;
            default:
                XMLOFF_WARN_UNKNOWN("xmloff", aIter);
        }
    }
    if (!sName.isEmpty() && bFoundValue )
        rParamMap[sName] = sValue;
}

namespace {

class XMLTextFrameContourContext_Impl : public SvXMLImportContext
{
    Reference < XPropertySet > xPropSet;

public:


    XMLTextFrameContourContext_Impl( SvXMLImport& rImport, sal_Int32 nElement,
            const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList,
            const Reference < XPropertySet >& rPropSet,
            bool bPath );
};

}

XMLTextFrameContourContext_Impl::XMLTextFrameContourContext_Impl(
        SvXMLImport& rImport,
        sal_Int32 /*nElement*/,
        const Reference< XFastAttributeList > & xAttrList,
        const Reference < XPropertySet >& rPropSet,
        bool bPath ) :
    SvXMLImportContext( rImport ),
    xPropSet( rPropSet )
{
    OUString sD, sPoints, sViewBox;
    bool bPixelWidth = false, bPixelHeight = false;
    bool bAuto = false;
    sal_Int32 nWidth = 0;
    sal_Int32 nHeight = 0;

    forauto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
    {
        switch( aIter.getToken() )
        {
        case XML_ELEMENT(SVG, XML_VIEWBOX):
        case XML_ELEMENT(SVG_COMPAT, XML_VIEWBOX):
            sViewBox = aIter.toString();
            break;
        case XML_ELEMENT(SVG, XML_D):
        case XML_ELEMENT(SVG_COMPAT, XML_D):
            if( bPath )
                sD = aIter.toString();
            break;
        case XML_ELEMENT(DRAW,XML_POINTS):
            if( !bPath )
                sPoints = aIter.toString();
            break;
        case XML_ELEMENT(SVG, XML_WIDTH):
        case XML_ELEMENT(SVG_COMPAT, XML_WIDTH):
            if (::sax::Converter::convertMeasurePx(nWidth, aIter.toView()))
                bPixelWidth = true;
            else
                GetImport().GetMM100UnitConverter().convertMeasureToCore(
                        nWidth, aIter.toView());
            break;
        case XML_ELEMENT(SVG, XML_HEIGHT):
        case XML_ELEMENT(SVG_COMPAT, XML_HEIGHT):
            if (::sax::Converter::convertMeasurePx(nHeight, aIter.toView()))
                bPixelHeight = true;
            else
                GetImport().GetMM100UnitConverter().convertMeasureToCore(
                        nHeight, aIter.toView());
            break;
        case  XML_ELEMENT(DRAW, XML_RECREATE_ON_EDIT):
            bAuto = IsXMLToken(aIter, XML_TRUE);
            break;
        }
    }

    OUString sContourPolyPolygon(u"ContourPolyPolygon"_ustr);
    Reference < XPropertySetInfo > xPropSetInfo = rPropSet->getPropertySetInfo();

    if(!xPropSetInfo->hasPropertyByName(sContourPolyPolygon) ||
        nWidth <= 0 || nHeight <= 0 || bPixelWidth != bPixelHeight ||
        !(bPath ? sD : sPoints).getLength())
        return;

    const SdXMLImExViewBox aViewBox( sViewBox, GetImport().GetMM100UnitConverter());
    basegfx::B2DPolyPolygon aPolyPolygon;

    // Related tdf#161833: ignore saved polygon for "recreate on edit" contours
    // tdf#161833 would cause semi-transparent pixels to be treated as fully
    // transparent pixels when calculating the wrap contour for an image. To
    // force the correct contour when loading a document, force the contour
    // to be recalculated by ignoring the saved polygon if the contour is set
    // to "recreate on edit".
    if( !bAuto )
    {
        if( bPath )
        {
            basegfx::utils::importFromSvgD(aPolyPolygon, sD, GetImport().needFixPositionAfterZ(), nullptr);
        }
        else
        {
            basegfx::B2DPolygon aPolygon;

            if(basegfx::utils::importFromSvgPoints(aPolygon, sPoints))
            {
                aPolyPolygon = basegfx::B2DPolyPolygon(aPolygon);
            }
        }
    }

    if(aPolyPolygon.count())
    {
        const basegfx::B2DRange aSourceRange(
            aViewBox.GetX(), aViewBox.GetY(),
            aViewBox.GetX() + aViewBox.GetWidth(), aViewBox.GetY() + aViewBox.GetHeight());
        const basegfx::B2DRange aTargetRange(
            0.0, 0.0,
            nWidth, nHeight);

        if(!aSourceRange.equal(aTargetRange))
        {
            aPolyPolygon.transform(
                basegfx::utils::createSourceRangeTargetRangeTransform(
                    aSourceRange,
                    aTargetRange));
        }

        css::drawing::PointSequenceSequence aPointSequenceSequence;
        basegfx::utils::B2DPolyPolygonToUnoPointSequenceSequence(aPolyPolygon, aPointSequenceSequence);
        xPropSet->setPropertyValue( sContourPolyPolygon, Any(aPointSequenceSequence) );
    }

    static constexpr OUString sIsPixelContour(u"IsPixelContour"_ustr);

    if( xPropSetInfo->hasPropertyByName( sIsPixelContour ) )
    {
        xPropSet->setPropertyValue( sIsPixelContour, Any(bPixelWidth) );
    }

    static constexpr OUString sIsAutomaticContour(u"IsAutomaticContour"_ustr);

    if( xPropSetInfo->hasPropertyByName( sIsAutomaticContour ) )
    {
        xPropSet->setPropertyValue( sIsAutomaticContour, Any(bAuto) );
    }
}

namespace {

class XMLTextFrameContext_Impl : public SvXMLImportContext
{
    css::uno::Reference < css::text::XTextCursor > xOldTextCursor;
    css::uno::Reference < css::beans::XPropertySet > xPropSet;
    css::uno::Reference < css::io::XOutputStream > xBase64Stream;

    /// old list item and block (#89891#)
    bool mbListContextPushed;

    OUString m_sOrigName;
    OUString sName;
    OUString sStyleName;
    OUString sNextName;
    OUString sHRef;
    OUString sCode;
    OUString sMimeType;
    OUString sFrameName;
    OUString sAppletName;
    OUString sFilterService;
    OUString sBase64CharsLeft;
    OUString sTblName;
    OUStringBuffer maUrlBuffer;

    ParamMap aParamMap;

    sal_Int32   nX;
    sal_Int32   nY;
    sal_Int32   nWidth;
    sal_Int32   nHeight;
    sal_Int32   nZIndex;
    sal_Int16   nPage;
    sal_Int16   nRotation;
    sal_Int16   nRelWidth;
    sal_Int16   nRelHeight;

    sal_uInt16 nType;
    css::text::TextContentAnchorType   eAnchorType;

    bool    bMayScript : 1;
    bool    bMinWidth : 1;
    bool    bMinHeight : 1;
    bool    bSyncWidth : 1;
    bool    bSyncHeight : 1;
    bool    bCreateFailed : 1;
    bool    bOwnBase64Stream : 1;
    bool    mbMultipleContent : 1; // This context is created based on a multiple content (image)
    bool    m_isDecorative = false;
    bool    m_isSplitAllowed = false;

    void Create();

public:


    bool CreateIfNotThere();
    const OUString& GetHRef() const { return sHRef; }

    XMLTextFrameContext_Impl( SvXMLImport& rImport,
            sal_Int32 nElement,
            const css::uno::Reference<css::xml::sax::XFastAttributeList > & rAttrList,
            css::text::TextContentAnchorType eAnchorType,
            sal_uInt16 nType,
            const css::uno::Reference<css::xml::sax::XFastAttributeList > & rFrameAttrList,
            bool bMultipleContent = false );

    virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;

    virtual void SAL_CALL characters( const OUString& rChars ) override;

    virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
        sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;

    void SetHyperlink( const OUString& rHRef,
                       const OUString& rName,
                       const OUString& rTargetFrameName,
                       bool bMap );

    // Implement Title/Description Elements UI (#i73249#)
    void SetTitle( const OUString& rTitle );

    void SetDesc( const OUString& rDesc );

    void SetName();

    const OUString& GetOrigName() const { return m_sOrigName; }

    css::text::TextContentAnchorType GetAnchorType() const { return eAnchorType; }
    const OUString & GetMimeType() const { return sMimeType; }

    const css::uno::Reference < css::beans::XPropertySet >& GetPropSet() const { return xPropSet; }
};

}

void XMLTextFrameContext_Impl::Create()
{
    rtl::Reference < XMLTextImportHelper > xTextImportHelper =
        GetImport().GetTextImport();

    switch ( nType)
    {
        case XML_TEXT_FRAME_OBJECT:
        case XML_TEXT_FRAME_OBJECT_OLE:
            if( xBase64Stream.is() )
            {
                OUString sURL( GetImport().ResolveEmbeddedObjectURLFromBase64() );
                if( !sURL.isEmpty() )
                    xPropSet = GetImport().GetTextImport()
                            ->createAndInsertOLEObject( GetImport(), sURL,
                                                        sStyleName,
                                                        sTblName,
                                                        nWidth, nHeight );
            }
            else if( !sHRef.isEmpty() )
            {
                OUString sURL( GetImport().ResolveEmbeddedObjectURL( sHRef,
                                                                std::u16string_view() ) );

                if( GetImport().IsPackageURL( sHRef ) )
                {
                    xPropSet = GetImport().GetTextImport()
                            ->createAndInsertOLEObject( GetImport(), sURL,
                                                        sStyleName,
                                                        sTblName,
                                                        nWidth, nHeight );
                }
                else
                {
                    // it should be an own OOo link that has no storage persistence
                    xPropSet = GetImport().GetTextImport()
                            ->createAndInsertOOoLink( GetImport(),
                                                        sURL,
                                                        sStyleName,
                                                        sTblName,
                                                        nWidth, nHeight );
                }
            }
            else
            {
                OUString sURL = "vnd.sun.star.ServiceName:" + sFilterService;
                xPropSet = GetImport().GetTextImport()
                            ->createAndInsertOLEObject( GetImport(), sURL,
                                                        sStyleName,
                                                        sTblName,
                                                        nWidth, nHeight );

            }
            break;
        case XML_TEXT_FRAME_APPLET:
        {
            xPropSet = GetImport().GetTextImport()
                            ->createAndInsertApplet( sAppletName, sCode,
                                                     bMayScript, sHRef,
                                                     nWidth, nHeight);
            break;
        }
        case XML_TEXT_FRAME_PLUGIN:
        {
            if(!sHRef.isEmpty())
                GetImport().GetAbsoluteReference(sHRef);
            xPropSet = GetImport().GetTextImport()
                            ->createAndInsertPlugin( sMimeType, sHRef,
                                                         nWidth, nHeight);

            break;
        }
        case XML_TEXT_FRAME_FLOATING_FRAME:
        {
            xPropSet = GetImport().GetTextImport()
                            ->createAndInsertFloatingFrame( sFrameName, sHRef,
                                                            sStyleName,
                                                            nWidth, nHeight);
            break;
        }
        default:
        {
            Reference<XMultiServiceFactory> xFactory( GetImport().GetModel(),
                                                      UNO_QUERY );
            if( xFactory.is() )
            {
                OUString sServiceName;
                switch( nType )
                {
                    case XML_TEXT_FRAME_TEXTBOX: sServiceName = "com.sun.star.text.TextFrame"break;
                    case XML_TEXT_FRAME_GRAPHIC: sServiceName = "com.sun.star.text.GraphicObject"break;
                }
                Reference<XInterface> xIfc = xFactory->createInstance( sServiceName );
                SAL_WARN_IF( !xIfc.is(), "xmloff.text""couldn't create frame" );
                if( xIfc.is() )
                    xPropSet.set( xIfc, UNO_QUERY );
            }
        }
    }

    if( !xPropSet.is() )
    {
        bCreateFailed = true;
        return;
    }

    Reference< XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();

    // Skip duplicated frames
    if(!mbMultipleContent && // It's allowed to have multiple image for the same frame
       !sName.isEmpty() &&
       xTextImportHelper->IsDuplicateFrame(sName, nX, nY, nWidth, nHeight))
    {
        bCreateFailed = true;
        return;
    }

    // set name
    Reference < XNamed > xNamed( xPropSet, UNO_QUERY );
    if( xNamed.is() )
    {
        OUString sOrigName( xNamed->getName() );
        if( sOrigName.isEmpty() ||
            (!sName.isEmpty() && sOrigName != sName) )
        {
            OUString sOldName( sName );

            sal_Int32 i = 0;
            while( xTextImportHelper->HasFrameByName( sName ) )
            {
                sName = sOldName + OUString::number( ++i );
            }
            xNamed->setName( sName );
            if( sName != sOldName )
            {
                xTextImportHelper->GetRenameMap().Add( XML_TEXT_RENAME_TYPE_FRAME,
                                             sOldName, sName );

            }
        }
    }

    // frame style
    XMLPropStyleContext *pStyle = nullptr;
    if( !sStyleName.isEmpty() )
    {
        pStyle = xTextImportHelper->FindAutoFrameStyle( sStyleName );
        if( pStyle )
            sStyleName = pStyle->GetParentName();
    }

    Any aAny;
    if( !sStyleName.isEmpty() )
    {
        OUString sDisplayStyleName( GetImport().GetStyleDisplayName(
                            XmlStyleFamily::SD_GRAPHICS_ID, sStyleName ) );
        const Reference < XNameContainer > & rStyles =
            xTextImportHelper->GetFrameStyles();
        if( rStyles.is() &&
            rStyles->hasByName( sDisplayStyleName ) )
        {
            xPropSet->setPropertyValue( u"FrameStyleName"_ustr, Any(sDisplayStyleName) );
        }
    }

    // anchor type (must be set before any other properties, because
    // otherwise some orientations cannot be set or will be changed
    // afterwards)
    xPropSet->setPropertyValue( u"AnchorType"_ustr, Any(eAnchorType) );

    // hard properties
    if( pStyle )
        pStyle->FillPropertySet( xPropSet );

    // x and y
    sal_Int16 nHoriOrient =  HoriOrientation::NONE;
    aAny = xPropSet->getPropertyValue( u"HoriOrient"_ustr );
    aAny >>= nHoriOrient;
    if( HoriOrientation::NONE == nHoriOrient )
    {
        xPropSet->setPropertyValue( u"HoriOrientPosition"_ustr, Any(nX) );
    }

    sal_Int16 nVertOrient =  VertOrientation::NONE;
    aAny = xPropSet->getPropertyValue( u"VertOrient"_ustr );
    aAny >>= nVertOrient;
    if( VertOrientation::NONE == nVertOrient )
    {
        xPropSet->setPropertyValue( u"VertOrientPosition"_ustr, Any(nY) );
    }

    // width
    if( nWidth > 0 )
    {
        xPropSet->setPropertyValue( u"Width"_ustr, Any(nWidth) );
    }
    if( nRelWidth > 0 || nWidth > 0 )
    {
        xPropSet->setPropertyValue( u"RelativeWidth"_ustr, Any(nRelWidth) );
    }
    if( bSyncWidth || nWidth > 0 )
    {
        xPropSet->setPropertyValue( u"IsSyncWidthToHeight"_ustr, Any(bSyncWidth) );
    }
    if( xPropSetInfo->hasPropertyByName( u"WidthType"_ustr ) &&
        (bMinWidth || nWidth > 0 || nRelWidth > 0 ) )
    {
        sal_Int16 nSizeType =
            (bMinWidth && XML_TEXT_FRAME_TEXTBOX == nType) ? SizeType::MIN
                                                           : SizeType::FIX;
        xPropSet->setPropertyValue( u"WidthType"_ustr, Any(nSizeType) );
    }

    if( nHeight > 0 )
    {
        xPropSet->setPropertyValue( u"Height"_ustr, Any(nHeight) );
    }
    if( nRelHeight > 0 || nHeight > 0 )
    {
        xPropSet->setPropertyValue( u"RelativeHeight"_ustr, Any(nRelHeight) );
    }
    if( bSyncHeight || nHeight > 0 )
    {
        xPropSet->setPropertyValue( u"IsSyncHeightToWidth"_ustr, Any(bSyncHeight) );
    }
    if( xPropSetInfo->hasPropertyByName( u"SizeType"_ustr ) &&
        (bMinHeight || nHeight > 0 || nRelHeight > 0 ) )
    {
        sal_Int16 nSizeType =
            (bMinHeight && XML_TEXT_FRAME_TEXTBOX == nType) ? SizeType::MIN
                                                            : SizeType::FIX;
        xPropSet->setPropertyValue( u"SizeType"_ustr, Any(nSizeType) );
    }

    if( XML_TEXT_FRAME_GRAPHIC == nType )
    {
        // URL
        OSL_ENSURE( !sHRef.isEmpty() || xBase64Stream.is(),
                    "neither URL nor base64 image data given" );
        uno::Reference<graphic::XGraphic> xGraphic;
        if (!sHRef.isEmpty())
        {
            xGraphic = GetImport().loadGraphicByURL(sHRef);
        }
        else if (xBase64Stream.is())
        {
            xGraphic = GetImport().loadGraphicFromBase64(xBase64Stream);
            xBase64Stream = nullptr;
        }

        if (xGraphic.is())
            xPropSet->setPropertyValue(u"Graphic"_ustr, Any(xGraphic));

        // filter name
        xPropSet->setPropertyValue( u"GraphicFilter"_ustr, Any(OUString()) );

        // rotation
        xPropSet->setPropertyValue( u"GraphicRotation"_ustr, Any(nRotation) );
    }

    // page number (must be set after the frame is inserted, because it
    // will be overwritten then inserting the frame.
    if( TextContentAnchorType_AT_PAGE == eAnchorType && nPage > 0 )
    {
        xPropSet->setPropertyValue( u"AnchorPageNo"_ustr, Any(nPage) );
    }

    if (m_isDecorative && xPropSetInfo->hasPropertyByName(u"Decorative"_ustr))
    {
        xPropSet->setPropertyValue(u"Decorative"_ustr, uno::Any(true));
    }

    if (m_isSplitAllowed && xPropSetInfo->hasPropertyByName(u"IsSplitAllowed"_ustr))
    {
        xPropSet->setPropertyValue(u"IsSplitAllowed"_ustr, uno::Any(true));
    }

    if( XML_TEXT_FRAME_OBJECT != nType  &&
        XML_TEXT_FRAME_OBJECT_OLE != nType  &&
        XML_TEXT_FRAME_APPLET != nType &&
        XML_TEXT_FRAME_PLUGIN!= nType &&
        XML_TEXT_FRAME_FLOATING_FRAME != nType)
    {
        Reference < XTextContent > xTxtCntnt( xPropSet, UNO_QUERY );
        try
        {
            xTextImportHelper->InsertTextContent(xTxtCntnt);
        }
        catch (lang::IllegalArgumentException const&)
        {
            TOOLS_WARN_EXCEPTION("xmloff.text""Cannot import part of the text - probably an image in the text frame?");
            return;
        }
    }

    // Make adding the shape to Z-Ordering dependent from if we are
    // inside an inside_deleted_section (redlining). That is necessary
    // since the shape will be removed again later. It would lead to
    // errors if it would stay inside the Z-Ordering. Thus, the
    // easiest way to solve that conflict is to not add it here.
    if(!GetImport().HasTextImport()
        || !GetImport().GetTextImport()->IsInsideDeleteContext())
    {
        Reference < XShape > xShape( xPropSet, UNO_QUERY );

        GetImport().GetShapeImport()->shapeWithZIndexAdded( xShape, nZIndex );
    }

    if( XML_TEXT_FRAME_TEXTBOX != nType )
        return;

    xTextImportHelper->ConnectFrameChains( sName, sNextName, xPropSet );
    Reference < XTextFrame > xTxtFrame( xPropSet, UNO_QUERY );
    Reference < XText > xTxt = xTxtFrame->getText();
    xOldTextCursor = xTextImportHelper->GetCursor();
    xTextImportHelper->SetCursor( xTxt->createTextCursor() );

    // remember old list item and block (#89892#) and reset them
    // for the text frame
    xTextImportHelper->PushListContext();
    mbListContextPushed = true;
}

void XMLTextFrameContext::removeGraphicFromImportContext(const SvXMLImportContext&&nbsp;rContext)
{
    const XMLTextFrameContext_Impl* pXMLTextFrameContext_Impl = dynamic_castconst XMLTextFrameContext_Impl* >(&rContext);

    if(!pXMLTextFrameContext_Impl)
        return;

    try
    {
        // just dispose to delete
        uno::Reference< lang::XComponent > xComp(pXMLTextFrameContext_Impl->GetPropSet(), UNO_QUERY);

        // Inform shape importer about the removal so it can adjust
        // z-indexes.
        uno::Reference<drawing::XShape> xShape(xComp, uno::UNO_QUERY);
        GetImport().GetShapeImport()->shapeRemoved(xShape);

        if(xComp.is())
        {
            xComp->dispose();
        }
    }
    catch( uno::Exception& )
    {
        OSL_FAIL( "Error in cleanup of multiple graphic object import (!)" );
    }
}

OUString XMLTextFrameContext::getMimeTypeFromImportContext(const SvXMLImportContext& rContext) const
{
    const XMLTextFrameContext_Impl* pXMLTextFrameContext_Impl = dynamic_cast<const XMLTextFrameContext_Impl*>(&rContext);

    if (pXMLTextFrameContext_Impl)
        return pXMLTextFrameContext_Impl->GetMimeType();

    return OUString();
}

OUString XMLTextFrameContext::getGraphicPackageURLFromImportContext(const SvXMLImportContext& rContext) const
{
    const XMLTextFrameContext_Impl* pXMLTextFrameContext_Impl = dynamic_castconst XMLTextFrameContext_Impl* >(&rContext);

    if(pXMLTextFrameContext_Impl)
    {
        return "vnd.sun.star.Package:" + pXMLTextFrameContext_Impl->GetHRef();
    }

    return OUString();
}

css::uno::Reference<css::graphic::XGraphic> XMLTextFrameContext::getGraphicFromImportContext(const SvXMLImportContext& rContext) const
{
    uno::Reference<graphic::XGraphic> xGraphic;

    const XMLTextFrameContext_Impl* pXMLTextFrameContext_Impl = dynamic_cast<const XMLTextFrameContext_Impl*>(&rContext);

    if (pXMLTextFrameContext_Impl)
    {
        try
        {
            const uno::Reference<beans::XPropertySet>& xPropertySet = pXMLTextFrameContext_Impl->GetPropSet();

            if (xPropertySet.is())
            {
                xPropertySet->getPropertyValue(u"Graphic"_ustr) >>= xGraphic;
            }
        }
        catch (uno::Exception&)
        {}
    }
    return xGraphic;
}

bool XMLTextFrameContext_Impl::CreateIfNotThere()
{
    if( !xPropSet.is() &&
        ( XML_TEXT_FRAME_OBJECT_OLE == nType ||
          XML_TEXT_FRAME_GRAPHIC == nType ) &&
        xBase64Stream.is() && !bCreateFailed )
    {
        if( bOwnBase64Stream )
            xBase64Stream->closeOutput();
        Create();
    }

    return xPropSet.is();
}

XMLTextFrameContext_Impl::XMLTextFrameContext_Impl(
        SvXMLImport& rImport,
        sal_Int32 /*nElement*/,
        const Reference< XFastAttributeList > & rAttrList,
        TextContentAnchorType eATyp,
        sal_uInt16 nNewType,
        const Reference< XFastAttributeList > & rFrameAttrList,
        bool bMultipleContent )
:   SvXMLImportContext( rImport )
,   mbListContextPushed( false )
,   nType( nNewType )
,   eAnchorType( eATyp )
{
    nX = 0;
    nY = 0;
    nWidth = 0;
    nHeight = 0;
    nZIndex = -1;
    nPage = 0;
    nRotation = 0;
    nRelWidth = 0;
    nRelHeight = 0;
    bMayScript = false;

    bMinHeight = false;
    bMinWidth = false;
    bSyncWidth = false;
    bSyncHeight = false;
    bCreateFailed = false;
    bOwnBase64Stream = false;
    mbMultipleContent = bMultipleContent;

    auto processAttr = [&](sal_Int32 nElement, const sax_fastparser::FastAttributeList::FastAttributeIter& aIter) -> void
    {
        switch( nElement )
        {
        case XML_ELEMENT(DRAW, XML_STYLE_NAME):
            sStyleName = aIter.toString();
            break;
        case XML_ELEMENT(DRAW, XML_NAME):
            m_sOrigName = aIter.toString();
            sName = m_sOrigName;
            break;
        case XML_ELEMENT(DRAW, XML_FRAME_NAME):
            sFrameName = aIter.toString();
            break;
        case XML_ELEMENT(DRAW, XML_APPLET_NAME):
            sAppletName = aIter.toString();
            break;
        case XML_ELEMENT(TEXT, XML_ANCHOR_TYPE):
            if( TextContentAnchorType_AT_PARAGRAPH == eAnchorType ||
                TextContentAnchorType_AT_CHARACTER == eAnchorType ||
                TextContentAnchorType_AS_CHARACTER == eAnchorType )
            {

                TextContentAnchorType eNew;
                if( XMLAnchorTypePropHdl::convert( aIter.toView(), eNew ) &&
                    ( TextContentAnchorType_AT_PARAGRAPH == eNew ||
                      TextContentAnchorType_AT_CHARACTER == eNew ||
                      TextContentAnchorType_AS_CHARACTER == eNew ||
                      TextContentAnchorType_AT_PAGE == eNew) )
                    eAnchorType = eNew;
            }
            break;
        case XML_ELEMENT(TEXT, XML_ANCHOR_PAGE_NUMBER):
            {
                sal_Int32 nTmp;
                sal_Int32 nMax = !comphelper::IsFuzzing() ? SHRT_MAX : 100;
                if (::sax::Converter::convertNumber(nTmp, aIter.toView(), 1, nMax))
                    nPage = static_cast<sal_Int16>(nTmp);
            }
            break;
        case XML_ELEMENT(SVG, XML_X):
        case XML_ELEMENT(SVG_COMPAT, XML_X):
            GetImport().GetMM100UnitConverter().convertMeasureToCore(
                    nX, aIter.toView());
            break;
        case XML_ELEMENT(SVG, XML_Y):
        case XML_ELEMENT(SVG_COMPAT, XML_Y):
            GetImport().GetMM100UnitConverter().convertMeasureToCore(
                    nY, aIter.toView() );
            break;
        case XML_ELEMENT(SVG, XML_WIDTH):
        case XML_ELEMENT(SVG_COMPAT, XML_WIDTH):
            // relative widths are obsolete since SRC617. Remove them some day!
            if( aIter.toView().find( '%' ) != std::string_view::npos )
            {
                sal_Int32 nTmp;
                if (::sax::Converter::convertPercent(nTmp, aIter.toView()))
                    nRelWidth = static_cast<sal_Int16>(nTmp);
            }
            else
            {
                GetImport().GetMM100UnitConverter().convertMeasureToCore(
                        nWidth, aIter.toView(), 0 );
            }
            break;
        case XML_ELEMENT(STYLE, XML_REL_WIDTH):
            if( IsXMLToken(aIter, XML_SCALE) )
            {
                bSyncWidth = true;
            }
            else
            {
                sal_Int32 nTmp;
                if (::sax::Converter::convertPercent( nTmp, aIter.toView() ))
                    nRelWidth = static_cast<sal_Int16>(nTmp);
            }
            break;
        case XML_ELEMENT(FO, XML_MIN_WIDTH):
        case XML_ELEMENT(FO_COMPAT, XML_MIN_WIDTH):
            if( aIter.toView().find( '%' ) != std::string_view::npos )
            {
                sal_Int32 nTmp;
                if (::sax::Converter::convertPercent(nTmp, aIter.toView()))
                    nRelWidth = static_cast<sal_Int16>(nTmp);
            }
            else
            {
                GetImport().GetMM100UnitConverter().convertMeasureToCore(
                        nWidth, aIter.toView(), 0 );
            }
            bMinWidth = true;
            break;
        case XML_ELEMENT(SVG, XML_HEIGHT):
        case XML_ELEMENT(SVG_COMPAT, XML_HEIGHT):
            // relative heights are obsolete since SRC617. Remove them some day!
            if( aIter.toView().find( '%' ) != std::string_view::npos )
            {
                sal_Int32 nTmp;
                if (::sax::Converter::convertPercent(nTmp, aIter.toView()))
                    nRelHeight = static_cast<sal_Int16>(nTmp);
            }
            else
            {
                GetImport().GetMM100UnitConverter().convertMeasureToCore(
                        nHeight, aIter.toView(), 0 );
            }
            break;
        case XML_ELEMENT(STYLE, XML_REL_HEIGHT):
            if( IsXMLToken( aIter, XML_SCALE ) )
            {
                bSyncHeight = true;
            }
            else if( IsXMLToken( aIter, XML_SCALE_MIN ) )
            {
                bSyncHeight = true;
                bMinHeight = true;
            }
            else
            {
                sal_Int32 nTmp;
                if (::sax::Converter::convertPercent( nTmp, aIter.toView() ))
                    nRelHeight = static_cast<sal_Int16>(nTmp);
            }
            break;
        case XML_ELEMENT(FO, XML_MIN_HEIGHT):
        case XML_ELEMENT(FO_COMPAT, XML_MIN_HEIGHT):
            if( aIter.toView().find( '%' ) != std::string_view::npos )
            {
                sal_Int32 nTmp;
                if (::sax::Converter::convertPercent(nTmp, aIter.toView()))
                    nRelHeight = static_cast<sal_Int16>(nTmp);
            }
            else
            {
                GetImport().GetMM100UnitConverter().convertMeasureToCore(
                        nHeight, aIter.toView(), 0 );
            }
            bMinHeight = true;
            break;
        case XML_ELEMENT(DRAW, XML_ZINDEX):
            ::sax::Converter::convertNumber( nZIndex, aIter.toView(), -1 );
            break;
        case XML_ELEMENT(DRAW, XML_CHAIN_NEXT_NAME):
            sNextName = aIter.toString();
            break;
        case XML_ELEMENT(XLINK, XML_HREF):
            sHRef = aIter.toString();
            break;
        case XML_ELEMENT(DRAW, XML_TRANSFORM):
            {
                // RotateFlyFrameFix: im/export full 'draw:transform' using existing tooling
                // Currently only rotation is used, but combinations with 'draw:transform'
                // may be necessary in the future, so that svg:x/svg:y/svg:width/svg:height
                // may be extended/replaced with 'draw:transform' (see draw objects)
                SdXMLImExTransform2D aSdXMLImExTransform2D;
                basegfx::B2DHomMatrix aFullTransform;

                // Use SdXMLImExTransform2D to convert to transformation
                // Note: using GetTwipUnitConverter instead of GetMM100UnitConverter may be needed,
                // but is not generally available (as it should be, a 'current' UnitConverter should
                // be available at GetExport() - and maybe was once). May have to be addressed as soon
                // as translate transformations are used here.
                aSdXMLImExTransform2D.SetString(aIter.toString(), GetImport().GetMM100UnitConverter());
                aSdXMLImExTransform2D.GetFullTransform(aFullTransform);

                if(!aFullTransform.isIdentity())
                {
                    const basegfx::utils::B2DHomMatrixBufferedDecompose aDecomposedTransform(aFullTransform);

                    // currently we *only* use rotation (and translation indirectly), so warn if *any*
                    // of the other transform parts is used
                    SAL_WARN_IF(!basegfx::fTools::equal(1.0, aDecomposedTransform.getScale().getX()), "xmloff.text""draw:transform uses scaleX" );
                    SAL_WARN_IF(!basegfx::fTools::equal(1.0, aDecomposedTransform.getScale().getY()), "xmloff.text""draw:transform uses scaleY" );
                    SAL_WARN_IF(!basegfx::fTools::equalZero(aDecomposedTransform.getShearX()), "xmloff.text""draw:transform uses shearX" );

                    // Translation comes from the translate to RotCenter, rot and BackTranslate.
                    // This means that it represents the translation between unrotated TopLeft
                    // and rotated TopLeft. This may be checked here now, but currently we only
                    // use rotation around center and assume that this *was* a rotation around
                    // center. The check would compare the object's center with the RotCenter
                    // that can be extracted from the transformation in aFullTransform.
                    // The definition contains implicitly the RotationCenter absolute
                    // to the scaled and translated object, so this may be used if needed (see
                    // _exportTextGraphic how the -trans/rot/trans is composed)

                    if(!basegfx::fTools::equalZero(aDecomposedTransform.getRotate()))
                    {
                        // rotation is used, set it. Convert from deg to 10th degree integer
                        // CAUTION: due to #i78696# (rotation mirrored using API) the rotate
                        // value is already mirrored, so do not do it again here (to be in sync
                        // with XMLTextParagraphExport::_exportTextGraphic normally it would need
                        // to me mirrored using * -1.0, see conversion there)
                        // CAUTION-II: due to tdf#115782 it is better for current ODF to indeed use it
                        // with the wrong orientation as in all other cases - ARGH! We will need to
                        // correct this in future ODF ASAP! For now, mirror the rotation here AGAIN
                        const double fRotate(-basegfx::rad2deg<10>(aDecomposedTransform.getRotate()));
                        nRotation = static_cast< sal_Int16 >(basegfx::fround(fRotate) % 3600);

                        // tdf#115529 may be negative, with the above modulo maximal -3599, so
                        // no loop needed here. nRotation is used in setPropertyValue("GraphicRotation")
                        // and *has* to be in the range [0 .. 3600[
                        if(nRotation < 0)
                        {
                            nRotation += 3600;
                        }
                    }
                }
            }
            break;
        case XML_ELEMENT(DRAW, XML_CODE):
            sCode = aIter.toString();
            break;
        case XML_ELEMENT(DRAW, XML_OBJECT):
            break;
        case XML_ELEMENT(DRAW, XML_ARCHIVE):
            break;
        case XML_ELEMENT(DRAW, XML_MAY_SCRIPT):
            bMayScript = IsXMLToken( aIter, XML_TRUE );
            break;
        case XML_ELEMENT(DRAW, XML_MIME_TYPE):
        case XML_ELEMENT(LO_EXT, XML_MIME_TYPE):
            sMimeType = aIter.toString();
            break;
        case XML_ELEMENT(DRAW, XML_NOTIFY_ON_UPDATE_OF_RANGES):
        case XML_ELEMENT(DRAW, XML_NOTIFY_ON_UPDATE_OF_TABLE):
            sTblName = aIter.toString();
            break;
        case XML_ELEMENT(LO_EXT, XML_DECORATIVE):
        case XML_ELEMENT(DRAW, XML_DECORATIVE):
            ::sax::Converter::convertBool(m_isDecorative, aIter.toString());
            break;
        case XML_ELEMENT(LO_EXT, XML_MAY_BREAK_BETWEEN_PAGES):
        case XML_ELEMENT(DRAW, XML_MAY_BREAK_BETWEEN_PAGES):
            sax::Converter::convertBool(m_isSplitAllowed, aIter.toString());
            break;
        default:
            SAL_INFO("xmloff""unknown attribute " << SvXMLImport::getPrefixAndNameFromToken(aIter.getToken()) << " value=" << aIter.toString());
        }
    };

    forauto& aIter : sax_fastparser::castToFastAttributeList(rAttrList) )
            processAttr(aIter.getToken(), aIter);
    forauto& aIter : sax_fastparser::castToFastAttributeList(rFrameAttrList) )
            processAttr(aIter.getToken(), aIter);

    if( ( (XML_TEXT_FRAME_GRAPHIC == nType ||
           XML_TEXT_FRAME_OBJECT == nType ||
           XML_TEXT_FRAME_OBJECT_OLE == nType) &&
          sHRef.isEmpty() ) ||
        ( XML_TEXT_FRAME_APPLET  == nType && sCode.isEmpty() ) ||
        ( XML_TEXT_FRAME_PLUGIN == nType &&
          sHRef.isEmpty() && sMimeType.isEmpty() ) )
        return// no URL: no image or OLE object

    Create();
}

void XMLTextFrameContext_Impl::endFastElement(sal_Int32 )
{
    if( ( XML_TEXT_FRAME_OBJECT_OLE == nType ||
          XML_TEXT_FRAME_GRAPHIC == nType) &&
        !xPropSet.is() && !bCreateFailed )
    {
        std::u16string_view sTrimmedChars = o3tl::trim(maUrlBuffer);
        if( !sTrimmedChars.empty() )
        {
            if( !xBase64Stream.is() )
            {
                if( XML_TEXT_FRAME_GRAPHIC == nType )
                {
                    xBase64Stream =
                        GetImport().GetStreamForGraphicObjectURLFromBase64();
                }
                else
                {
                    xBase64Stream =
                        GetImport().GetStreamForEmbeddedObjectURLFromBase64();
                }
                if( xBase64Stream.is() )
                    bOwnBase64Stream = true;
            }
            if( bOwnBase64Stream && xBase64Stream.is() )
            {
                OUString sChars;
                if( !sBase64CharsLeft.isEmpty() )
                {
                    sChars = sBase64CharsLeft + sTrimmedChars;
                    sBase64CharsLeft.clear();
                }
                else
                {
                    sChars = sTrimmedChars;
                }
                Sequence< sal_Int8 > aBuffer( (sChars.getLength() / 4) * 3 );
                sal_Int32 nCharsDecoded =
                    ::comphelper::Base64::decodeSomeChars( aBuffer, sChars );
                xBase64Stream->writeBytes( aBuffer );
                if( nCharsDecoded != sChars.getLength() )
                    sBase64CharsLeft = sChars.copy( nCharsDecoded );
            }
        }
        maUrlBuffer.setLength(0);
    }

    CreateIfNotThere();

    if( xOldTextCursor.is() )
    {
        GetImport().GetTextImport()->DeleteParagraph();
        GetImport().GetTextImport()->SetCursor( xOldTextCursor );
    }

    // reinstall old list item (if necessary) #89892#
    if (mbListContextPushed) {
        GetImport().GetTextImport()->PopListContext();
    }

    if (( nType == XML_TEXT_FRAME_APPLET || nType == XML_TEXT_FRAME_PLUGIN ) && xPropSet.is())
        GetImport().GetTextImport()->endAppletOrPlugin( xPropSet, aParamMap);
}

css::uno::Reference< css::xml::sax::XFastContextHandler > XMLTextFrameContext_Impl::createFastChildContext(
    sal_Int32 nElement,
    const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
{
    if( nElement == XML_ELEMENT(DRAW, XML_PARAM) )
    {
        if ( nType == XML_TEXT_FRAME_APPLET || nType == XML_TEXT_FRAME_PLUGIN )
            return new XMLTextFrameParam_Impl( GetImport(),
                                               xAttrList, aParamMap );
    }
    else if( nElement == XML_ELEMENT(OFFICE, XML_BINARY_DATA) )
    {
        if( !xPropSet.is() && !xBase64Stream.is() && !bCreateFailed )
        {
            switch( nType )
            {
            case XML_TEXT_FRAME_GRAPHIC:
                xBase64Stream =
                    GetImport().GetStreamForGraphicObjectURLFromBase64();
                break;
            case XML_TEXT_FRAME_OBJECT_OLE:
                xBase64Stream =
                    GetImport().GetStreamForEmbeddedObjectURLFromBase64();
                break;
            }
            if( xBase64Stream.is() )
                return new XMLBase64ImportContext( GetImport(), xBase64Stream );
        }
    }
    // Correction of condition which also avoids warnings. (#i100480#)
    if( XML_TEXT_FRAME_OBJECT == nType &&
        ( nElement == XML_ELEMENT(OFFICE, XML_DOCUMENT) ||
          nElement == XML_ELEMENT(MATH, XML_MATH) ) )
    {
        if( !xPropSet.is() && !bCreateFailed )
        {
            XMLEmbeddedObjectImportContext *pEContext =
                new XMLEmbeddedObjectImportContext( GetImport(), nElement, xAttrList );
            sFilterService = pEContext->GetFilterServiceName();
            if( !sFilterService.isEmpty() )
            {
                Create();
                if( xPropSet.is() )
                {
                    Reference < XEmbeddedObjectSupplier > xEOS( xPropSet,
                                                                UNO_QUERY );
                    OSL_ENSURE( xEOS.is(),
                            "no embedded object supplier for own object" );
                    Reference<css::lang::XComponent> aXComponent(xEOS->getEmbeddedObject());
                    pEContext->SetComponent( aXComponent );
                }
            }
            return pEContext;
        }
    }

    if( xOldTextCursor.is() )  // text-box
    {
        auto p = GetImport().GetTextImport()->CreateTextChildContext(
                            GetImport(), nElement, xAttrList,
                            XMLTextType::TextBox );
        if (p)
            return p;
    }

    XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);

    return nullptr;
}

void XMLTextFrameContext_Impl::characters( const OUString& rChars )
{
    maUrlBuffer.append(rChars);
}

void XMLTextFrameContext_Impl::SetHyperlink( const OUString& rHRef,
                       const OUString& rName,
                       const OUString& rTargetFrameName,
                       bool bMap )
{
    static constexpr OUString s_HyperLinkURL = u"HyperLinkURL"_ustr;
    static constexpr OUString s_HyperLinkName = u"HyperLinkName"_ustr;
    static constexpr OUString s_HyperLinkTarget = u"HyperLinkTarget"_ustr;
    static constexpr OUString s_ServerMap = u"ServerMap"_ustr;
    if( !xPropSet.is() )
        return;

    Reference < XPropertySetInfo > xPropSetInfo =
        xPropSet->getPropertySetInfo();
    if( !xPropSetInfo.is() ||
        !xPropSetInfo->hasPropertyByName(s_HyperLinkURL))
        return;

    xPropSet->setPropertyValue( s_HyperLinkURL, Any(rHRef) );

    if (xPropSetInfo->hasPropertyByName(s_HyperLinkName))
    {
        xPropSet->setPropertyValue(s_HyperLinkName, Any(rName));
    }

    if (xPropSetInfo->hasPropertyByName(s_HyperLinkTarget))
    {
        xPropSet->setPropertyValue( s_HyperLinkTarget, Any(rTargetFrameName) );
    }

    if (xPropSetInfo->hasPropertyByName(s_ServerMap))
    {
        xPropSet->setPropertyValue(s_ServerMap, Any(bMap));
    }
}

void XMLTextFrameContext_Impl::SetName()
{
    Reference<XNamed> xNamed(xPropSet, UNO_QUERY);
    if (m_sOrigName.isEmpty() || !xNamed.is())
        return;

    OUString const name(xNamed->getName());
    if (name != m_sOrigName)
    {
        try
        {
            xNamed->setName(m_sOrigName);
        }
        catch (uno::Exception const&)
        {   // fdo#71698 document contains 2 frames with same draw:name
            TOOLS_INFO_EXCEPTION("xmloff.text""SetName(): exception setting \""
                    << m_sOrigName << "\"");
        }
    }
}

// Implement Title/Description Elements UI (#i73249#)
void XMLTextFrameContext_Impl::SetTitle( const OUString& rTitle )
{
    if ( xPropSet.is() )
    {
        Reference< XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
        if( xPropSetInfo->hasPropertyByName( u"Title"_ustr ) )
        {
            xPropSet->setPropertyValue( u"Title"_ustr, Any( rTitle ) );
        }
    }
}

void XMLTextFrameContext_Impl::SetDesc( const OUString& rDesc )
{
    if ( xPropSet.is() )
    {
        Reference< XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
        if( xPropSetInfo->hasPropertyByName( u"Description"_ustr ) )
        {
            xPropSet->setPropertyValue( u"Description"_ustr, Any( rDesc ) );
        }
    }
}


bool XMLTextFrameContext::CreateIfNotThere( css::uno::Reference < css::beans::XPropertySet >& rPropSet )
{
    SvXMLImportContext *pContext = m_xImplContext.get();
    XMLTextFrameContext_Impl *pImpl = dynamic_cast< XMLTextFrameContext_Impl*>( pContext );
    if( pImpl && pImpl->CreateIfNotThere() )
        rPropSet = pImpl->GetPropSet();

    return rPropSet.is();
}

XMLTextFrameContext::XMLTextFrameContext(
        SvXMLImport& rImport,
        const Reference< XFastAttributeList > & xAttrList,
        TextContentAnchorType eATyp )
:   SvXMLImportContext( rImport )
,   m_xAttrList( new sax_fastparser::FastAttributeList( xAttrList ) )
    // Implement Title/Description Elements UI (#i73249#)
,   m_eDefaultAnchorType( eATyp )
    // Shapes in Writer cannot be named via context menu (#i51726#)
,   m_HasAutomaticStyleWithoutParentStyle( false )
,   m_bSupportsReplacement( false )
{
    forauto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
    {
        // New distinguish attribute between Writer objects and Draw objects is:
        // Draw objects have an automatic style without a parent style (#i51726#)
        switch (aIter.getToken())
        {
            case XML_ELEMENT(DRAW, XML_STYLE_NAME):
            {
                OUString aStyleName = aIter.toString();
                if( !aStyleName.isEmpty() )
                {
                    rtl::Reference < XMLTextImportHelper > xTxtImport =
                                                        GetImport().GetTextImport();
                    XMLPropStyleContext* pStyle = xTxtImport->FindAutoFrameStyle( aStyleName );
                    if ( pStyle && pStyle->GetParentName().isEmpty() )
                    {
                        m_HasAutomaticStyleWithoutParentStyle = true;
                    }
                }
                break;
            }
            case XML_ELEMENT(TEXT, XML_ANCHOR_TYPE):
            {
                TextContentAnchorType eNew;
                if( XMLAnchorTypePropHdl::convert( aIter.toView(), eNew ) &&
                    ( TextContentAnchorType_AT_PARAGRAPH == eNew ||
                      TextContentAnchorType_AT_CHARACTER == eNew ||
                      TextContentAnchorType_AS_CHARACTER == eNew ||
                      TextContentAnchorType_AT_PAGE == eNew) )
                    m_eDefaultAnchorType = eNew;
                break;
            }
        }
    }
}

void XMLTextFrameContext::endFastElement(sal_Int32 )
{
    /// solve if multiple image child contexts were imported
    SvXMLImportContextRef const pMultiContext(solveMultipleImages());

    SvXMLImportContext const*const pContext =
        (pMultiContext.is()) ? pMultiContext.get() : m_xImplContext.get();
    XMLTextFrameContext_Impl *pImpl = const_cast<XMLTextFrameContext_Impl*>(dynamic_castconst XMLTextFrameContext_Impl*>( pContext ));
    assert(!pMultiContext.is() || pImpl);

    // When we are dealing with a textbox, pImpl will be null;
    // we need to set the hyperlink to the shape instead
    Reference<XShape> xShape = GetShape();
    if (xShape.is() && m_pHyperlink)
    {
        Reference<XPropertySet> xProps(xShape, UNO_QUERY);
        if (xProps.is())
            xProps->setPropertyValue(u"Hyperlink"_ustr, Any(m_pHyperlink->GetHRef()));
    }

    if( !pImpl )
        return;

    pImpl->CreateIfNotThere();

    // fdo#68839: in case the surviving image was not the first one,
    // it will have a counter added to its name - set the original name
    if (pMultiContext.is()) // do this only when necessary; esp. not for text
    {                  // frames that may have entries in GetRenameMap()!
        pImpl->SetName();
    }

    if( !m_sTitle.isEmpty() )
    {
        pImpl->SetTitle( m_sTitle );
    }
    if( !m_sDesc.isEmpty() )
    {
        pImpl->SetDesc( m_sDesc );
    }

    if( m_pHyperlink )
    {
        pImpl->SetHyperlink( m_pHyperlink->GetHRef(), m_pHyperlink->GetName(),
                      m_pHyperlink->GetTargetFrameName(), m_pHyperlink->GetMap() );
        m_pHyperlink.reset();
    }

    GetImport().GetTextImport()->StoreLastImportedFrameName(pImpl->GetOrigName());
}

css::uno::Reference< css::xml::sax::XFastContextHandler > XMLTextFrameContext::createFastChildContext(
    sal_Int32 nElement,
    const uno::Reference< xml::sax::XFastAttributeList>& xAttrList )
{
    SvXMLImportContextRef xContext;

    if( !m_xImplContext.is() )
    {
        // no child exists
        if( IsTokenInNamespace(nElement, XML_NAMESPACE_DRAW) )
        {
            sal_uInt16 nFrameType = USHRT_MAX;
            switch (nElement & TOKEN_MASK)
            {
                case XML_TEXT_BOX:
                    nFrameType = XML_TEXT_FRAME_TEXTBOX;
                    break;
                case XML_IMAGE:
                    nFrameType = XML_TEXT_FRAME_GRAPHIC;
                    break;
                case XML_OBJECT:
                    nFrameType = XML_TEXT_FRAME_OBJECT;
                    break;
                case XML_OBJECT_OLE:
                    nFrameType = XML_TEXT_FRAME_OBJECT_OLE;
                    break;
                case XML_APPLET:
                    nFrameType = XML_TEXT_FRAME_APPLET;
                    break;
                case XML_PLUGIN:
                    nFrameType = XML_TEXT_FRAME_PLUGIN;
                    break;
                case XML_FLOATING_FRAME:
                    nFrameType = XML_TEXT_FRAME_FLOATING_FRAME;
                    break;
            }

            if( USHRT_MAX != nFrameType )
            {
                // Shapes in Writer cannot be named via context menu (#i51726#)
                if ( ( XML_TEXT_FRAME_TEXTBOX == nFrameType ||
                       XML_TEXT_FRAME_GRAPHIC == nFrameType ) &&
                     m_HasAutomaticStyleWithoutParentStyle )
                {
                    Reference < XShapes > xShapes;
                    xContext = XMLShapeImportHelper::CreateFrameChildContext(
                                    GetImport(), nElement, xAttrList, xShapes, m_xAttrList );
                }
                else if( XML_TEXT_FRAME_PLUGIN == nFrameType )
                {
                    bool bMedia = false;

                    // check, if we have a media object
                    forauto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
                    {
                        if( aIter.getToken() == XML_ELEMENT(DRAW, XML_MIME_TYPE) )
                        {
                            if (::comphelper::IsMediaMimeType(aIter.toView()))
                                bMedia = true;

                            // leave this loop
                            break;
                        }
                    }

                    if( bMedia )
                    {
                        Reference < XShapes > xShapes;
                        xContext = XMLShapeImportHelper::CreateFrameChildContext(
                                        GetImport(), nElement, xAttrList, xShapes, m_xAttrList );
                    }
                }
                else if( XML_TEXT_FRAME_OBJECT == nFrameType ||
                         XML_TEXT_FRAME_OBJECT_OLE == nFrameType )
                {
                    m_bSupportsReplacement = true;
                }
                else if(XML_TEXT_FRAME_GRAPHIC == nFrameType)
                {
                    setSupportsMultipleContents( (nElement & TOKEN_MASK) == XML_IMAGE );
                }

                if (!xContext)
                {
                    xContext = new XMLTextFrameContext_Impl( GetImport(), nElement,
                                                        xAttrList,
                                                        m_eDefaultAnchorType,
                                                        nFrameType,
                                                        m_xAttrList );
                }

                m_xImplContext = xContext;

                if(getSupportsMultipleContents() && XML_TEXT_FRAME_GRAPHIC == nFrameType)
                {
                    addContent(*m_xImplContext);
                }
            }
        }
    }
    else if(getSupportsMultipleContents() && nElement == XML_ELEMENT(DRAW, XML_IMAGE))
    {
        // read another image
        xContext = new XMLTextFrameContext_Impl(
            GetImport(), nElement, xAttrList,
            m_eDefaultAnchorType, XML_TEXT_FRAME_GRAPHIC, m_xAttrList, true);

        m_xImplContext = xContext;
        addContent(*m_xImplContext);
    }
    else if( m_bSupportsReplacement && !m_xReplImplContext.is() &&
             nElement == XML_ELEMENT(DRAW, XML_IMAGE) )
    {
        // read replacement image
        Reference < XPropertySet > xPropSet;
        if( CreateIfNotThere( xPropSet ) )
        {
            xContext = new XMLReplacementImageContext( GetImport(),
                                nElement, xAttrList, xPropSet );
            m_xReplImplContext = xContext;
        }
    }
    else if( nullptr != dynamic_castconst XMLTextFrameContext_Impl*>( m_xImplContext.get() ))
    {
        // the child is a writer frame
        if( IsTokenInNamespace(nElement, XML_NAMESPACE_SVG) ||
            IsTokenInNamespace(nElement, XML_NAMESPACE_SVG_COMPAT) )
        {
            // Implement Title/Description Elements UI (#i73249#)
            const bool bOld = SvXMLImport::OOo_2x >= GetImport().getGeneratorVersion();
            if ( bOld )
            {
                if ( (nElement & TOKEN_MASK) == XML_DESC )
                {
                    xContext = new XMLTextFrameTitleOrDescContext_Impl( GetImport(),
                                                                        m_sTitle );
                }
            }
            else
            {
                if( (nElement & TOKEN_MASK) == XML_TITLE )
                {
                    if (getSupportsMultipleContents())
                    {   // tdf#103567 ensure props are set on surviving shape
                        m_xImplContext = solveMultipleImages();
                    }
                    xContext = new XMLTextFrameTitleOrDescContext_Impl( GetImport(),
                                                                        m_sTitle );
                }
                else if ( (nElement & TOKEN_MASK) == XML_DESC )
                {
                    if (getSupportsMultipleContents())
                    {   // tdf#103567 ensure props are set on surviving shape
                        m_xImplContext = solveMultipleImages();
                    }
                    xContext = new XMLTextFrameTitleOrDescContext_Impl( GetImport(),
                                                                        m_sDesc );
                }
            }
        }
        else if( IsTokenInNamespace(nElement, XML_NAMESPACE_DRAW) )
        {
            Reference < XPropertySet > xPropSet;
            if( (nElement & TOKEN_MASK) == XML_CONTOUR_POLYGON )
            {
                if (getSupportsMultipleContents())
                {   // tdf#103567 ensure props are set on surviving shape
                    m_xImplContext = solveMultipleImages();
                }
                if( CreateIfNotThere( xPropSet ) )
                    xContext = new XMLTextFrameContourContext_Impl( GetImport(), nElement,
                                                  xAttrList, xPropSet, false );
            }
            else if( (nElement & TOKEN_MASK) == XML_CONTOUR_PATH )
            {
                if (getSupportsMultipleContents())
                {   // tdf#103567 ensure props are set on surviving shape
                    m_xImplContext = solveMultipleImages();
                }
                if( CreateIfNotThere( xPropSet ) )
                    xContext = new XMLTextFrameContourContext_Impl( GetImport(), nElement,
                                                  xAttrList, xPropSet, true );
            }
            else if( (nElement & TOKEN_MASK) == XML_IMAGE_MAP )
            {
                if (getSupportsMultipleContents())
                {   // tdf#103567 ensure props are set on surviving shape
                    m_xImplContext = solveMultipleImages();
                }
                if( CreateIfNotThere( xPropSet ) )
                    xContext = new XMLImageMapContext( GetImport(), xPropSet );
            }
        }
        else if( nElement == XML_ELEMENT(OFFICE, XML_EVENT_LISTENERS) )
        {
            if (getSupportsMultipleContents())
            {   // tdf#103567 ensure props are set on surviving shape
                m_xImplContext = solveMultipleImages();
            }
            // do we still have the frame object?
            Reference < XPropertySet > xPropSet;
            if( CreateIfNotThere( xPropSet ) )
            {
                // is it an event supplier?
                Reference<XEventsSupplier> xEventsSupplier(xPropSet, UNO_QUERY);
                if (xEventsSupplier.is())
                {
                    // OK, we have the events, so create the context
                    xContext = new XMLEventsImportContext(GetImport(), xEventsSupplier);
                }
            }
        }
    }
    // #i68101#
    else if( nElement == XML_ELEMENT(SVG, XML_TITLE) || nElement == XML_ELEMENT(SVG, XML_DESC ) ||
             nElement == XML_ELEMENT(SVG_COMPAT, XML_TITLE) || nElement == XML_ELEMENT(SVG_COMPAT, XML_DESC ) )
    {
        if (getSupportsMultipleContents())
        {   // tdf#103567 ensure props are set on surviving shape
            // note: no more draw:image can be added once we get here
            m_xImplContext = solveMultipleImages();
        }
        xContext = static_cast<SvXMLImportContext*>(m_xImplContext->createFastChildContext( nElement, xAttrList ).get());
    }
    else if (nElement == XML_ELEMENT(LO_EXT, XML_SIGNATURELINE))
    {
        if (getSupportsMultipleContents())
        {   // tdf#103567 ensure props are set on surviving shape
            // note: no more draw:image can be added once we get here
            m_xImplContext = solveMultipleImages();
        }
        xContext = static_cast<SvXMLImportContext*>(m_xImplContext->createFastChildContext(nElement, xAttrList).get());
    }
    else if (nElement == XML_ELEMENT(LO_EXT, XML_QRCODE))
    {
        if (getSupportsMultipleContents())
        {   // tdf#103567 ensure props are set on surviving shape
            // note: no more draw:image can be added once we get here
            m_xImplContext = solveMultipleImages();
        }
        xContext = static_cast<SvXMLImportContext*>(m_xImplContext->createFastChildContext(nElement, xAttrList).get());
    }
    else if (nElement == XML_ELEMENT(DRAW, XML_A))
    {
        xContext = static_cast<SvXMLImportContext*>(m_xImplContext->createFastChildContext(nElement, xAttrList).get());
    }
    else
    {
        // the child is a drawing shape
        return XMLShapeImportHelper::CreateFrameChildContext(
                                    m_xImplContext.get(), nElement, xAttrList );
    }

    return xContext;
}

void XMLTextFrameContext::SetHyperlink( const OUString& rHRef,
                       const OUString& rName,
                       const OUString& rTargetFrameName,
                       bool bMap )
{
    OSL_ENSURE( !m_pHyperlink, "recursive SetHyperlink call" );
    m_pHyperlink = std::make_unique<XMLTextFrameContextHyperlink_Impl>(
                rHRef, rName, rTargetFrameName, bMap );
}

TextContentAnchorType XMLTextFrameContext::GetAnchorType() const
{
    SvXMLImportContext *pContext = m_xImplContext.get();
    XMLTextFrameContext_Impl *pImpl = dynamic_cast< XMLTextFrameContext_Impl*>( pContext );
    if( pImpl )
        return pImpl->GetAnchorType();
    else
        return m_eDefaultAnchorType;
}

Reference < XTextContent > XMLTextFrameContext::GetTextContent() const
{
    Reference < XTextContent > xTxtCntnt;
    SvXMLImportContext *pContext = m_xImplContext.get();
    XMLTextFrameContext_Impl *pImpl = dynamic_cast< XMLTextFrameContext_Impl* >( pContext );
    if( pImpl )
        xTxtCntnt.set( pImpl->GetPropSet(), UNO_QUERY );

    return xTxtCntnt;
}

Reference < XShape > XMLTextFrameContext::GetShape() const
{
    Reference < XShape > xShape;
    SvXMLImportContext* pContext = m_xImplContext.get();
    SvXMLShapeContext* pImpl = dynamic_cast<SvXMLShapeContext*>( pContext  );
    if ( pImpl )
    {
        xShape = pImpl->getShape();
    }

    return xShape;
}

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

Messung V0.5
C=95 H=98 G=96

¤ Dauer der Verarbeitung: 0.25 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.