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

Quelle  shapeexport.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 <config_wasm_strip.h>

#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/matrix/b3dhommatrix.hxx>
#include <basegfx/polygon/b2dpolypolygon.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <basegfx/polygon/b3dpolypolygon.hxx>
#include <basegfx/polygon/b3dpolypolygontools.hxx>
#include <basegfx/tuple/b2dtuple.hxx>
#include <basegfx/vector/b3dvector.hxx>

#include <com/sun/star/beans/XPropertyState.hpp>
#include <com/sun/star/beans/PropertyValues.hpp>
#include <com/sun/star/container/XChild.hpp>
#include <com/sun/star/container/XEnumerationAccess.hpp>
#include <com/sun/star/container/XIdentifierAccess.hpp>
#include <com/sun/star/container/XNamed.hpp>
#include <com/sun/star/document/XEventsSupplier.hpp>
#include <com/sun/star/drawing/CameraGeometry.hpp>
#include <com/sun/star/drawing/CircleKind.hpp>
#include <com/sun/star/drawing/ConnectorType.hpp>
#include <com/sun/star/drawing/Direction3D.hpp>
#include <com/sun/star/drawing/EscapeDirection.hpp>
#include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
#include <com/sun/star/drawing/EnhancedCustomShapeGluePointType.hpp>
#include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp>
#include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp>
#include <com/sun/star/drawing/EnhancedCustomShapeMetalType.hpp>
#include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp>
#include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp>
#include <com/sun/star/drawing/EnhancedCustomShapeTextFrame.hpp>
#include <com/sun/star/drawing/EnhancedCustomShapeTextPathMode.hpp>
#include <com/sun/star/drawing/GluePoint2.hpp>
#include <com/sun/star/drawing/HomogenMatrix.hpp>
#include <com/sun/star/drawing/HomogenMatrix3.hpp>
#include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
#include <com/sun/star/drawing/PolyPolygonShape3D.hpp>
#include <com/sun/star/drawing/Position3D.hpp>
#include <com/sun/star/drawing/ProjectionMode.hpp>
#include <com/sun/star/drawing/ShadeMode.hpp>
#include <com/sun/star/drawing/XControlShape.hpp>
#include <com/sun/star/drawing/XCustomShapeEngine.hpp>
#include <com/sun/star/drawing/XGluePointsSupplier.hpp>
#include <com/sun/star/drawing/BarCode.hpp>
#include <com/sun/star/drawing/BarCodeErrorCorrection.hpp>
#include <com/sun/star/drawing/XShapes3.hpp>
#include <com/sun/star/embed/ElementModes.hpp>
#include <com/sun/star/embed/XStorage.hpp>
#include <com/sun/star/embed/XTransactedObject.hpp>
#include <com/sun/star/graphic/XGraphic.hpp>
#include <com/sun/star/graphic/GraphicProvider.hpp>
#include <com/sun/star/graphic/XGraphicProvider.hpp>
#include <com/sun/star/io/XSeekableInputStream.hpp>
#include <com/sun/star/io/XStream.hpp>
#include <com/sun/star/lang/ServiceNotRegisteredException.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/media/ZoomLevel.hpp>
#include <com/sun/star/presentation/AnimationSpeed.hpp>
#include <com/sun/star/presentation/ClickAction.hpp>
#include <com/sun/star/style/XStyle.hpp>
#include <com/sun/star/table/XColumnRowRange.hpp>
#include <com/sun/star/text/WritingMode2.hpp>
#include <com/sun/star/text/XText.hpp>

#include <comphelper/classids.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/propertyvalue.hxx>
#include <comphelper/sequenceashashmap.hxx>
#include <comphelper/storagehelper.hxx>
#include <officecfg/Office/Common.hxx>

#include <o3tl/any.hxx>
#include <o3tl/typed_flags_set.hxx>
#include <o3tl/string_view.hxx>

#include <rtl/math.hxx>
#include <rtl/ustrbuf.hxx>
#include <rtl/ustring.hxx>
#include <sal/log.hxx>

#include <sax/tools/converter.hxx>

#include <tools/debug.hxx>
#include <tools/globname.hxx>
#include <tools/helpers.hxx>
#include <comphelper/diagnose_ex.hxx>
#include <vcl/graph.hxx>

#include <xmloff/contextid.hxx>
#include <xmloff/families.hxx>
#include <xmloff/namespacemap.hxx>
#include <xmloff/shapeexport.hxx>
#include <xmloff/unointerfacetouniqueidentifiermapper.hxx>
#include <xmloff/xmlexp.hxx>
#include <xmloff/xmlnamespace.hxx>
#include <xmloff/xmltoken.hxx>
#include <xmloff/xmluconv.hxx>
#include <xmloff/table/XMLTableExport.hxx>
#include <xmloff/ProgressBarHelper.hxx>

#include <anim.hxx>
#include <EnhancedCustomShapeToken.hxx>
#include "sdpropls.hxx"
#include <xexptran.hxx>
#include "ximpshap.hxx"
#include <XMLBase64Export.hxx>
#include <XMLImageMapExport.hxx>
#include <memory>
#include <algorithm>

using namespace ::com::sun::star;
using namespace ::xmloff::EnhancedCustomShapeToken;
using namespace ::xmloff::token;

constexpr OUStringLiteral XML_EMBEDDEDOBJECTGRAPHIC_URL_BASE = u"vnd.sun.star.GraphicObject:";

namespace {

bool supportsText(XmlShapeType eShapeType)
{
        return eShapeType != XmlShapeType::PresChartShape &&
        eShapeType != XmlShapeType::PresOLE2Shape &&
        eShapeType != XmlShapeType::DrawSheetShape &&
        eShapeType != XmlShapeType::PresSheetShape &&
        eShapeType != XmlShapeType::Draw3DSceneObject &&
        eShapeType != XmlShapeType::Draw3DCubeObject &&
        eShapeType != XmlShapeType::Draw3DSphereObject &&
        eShapeType != XmlShapeType::Draw3DLatheObject &&
        eShapeType != XmlShapeType::Draw3DExtrudeObject &&
        eShapeType != XmlShapeType::DrawPageShape &&
        eShapeType != XmlShapeType::PresPageShape &&
        eShapeType != XmlShapeType::DrawGroupShape;

}

}

constexpr OUStringLiteral gsPrintable( u"Printable" );
constexpr OUStringLiteral gsVisible( u"Visible" );
constexpr OUString gsModel( u"Model"_ustr );
constexpr OUStringLiteral gsStartShape( u"StartShape" );
constexpr OUStringLiteral gsEndShape( u"EndShape" );
constexpr OUString gsOnClick( u"OnClick"_ustr );
constexpr OUStringLiteral gsEventType( u"EventType" );
constexpr OUStringLiteral gsPresentation( u"Presentation" );
constexpr OUStringLiteral gsMacroName( u"MacroName" );
constexpr OUString gsScript( u"Script"_ustr );
constexpr OUStringLiteral gsLibrary( u"Library" );
constexpr OUStringLiteral gsClickAction( u"ClickAction" );
constexpr OUString gsBookmark( u"Bookmark"_ustr );
constexpr OUStringLiteral gsEffect( u"Effect" );
constexpr OUStringLiteral gsPlayFull( u"PlayFull" );
constexpr OUStringLiteral gsVerb( u"Verb" );
constexpr OUStringLiteral gsSoundURL( u"SoundURL" );
constexpr OUStringLiteral gsSpeed( u"Speed" );
constexpr OUStringLiteral gsStarBasic( u"StarBasic" );
constexpr OUStringLiteral gsHyperlink( u"Hyperlink" );

XMLShapeExport::XMLShapeExport(SvXMLExport& rExp,
                                SvXMLExportPropertyMapper *pExtMapper )
:   mrExport( rExp ),
    maCurrentShapesIter(maShapesInfos.end()),
    mbExportLayer( false ),
    // #88546# init to sal_False
    mbHandleProgressBar( false )
{
    // construct PropertySetMapper
    mxPropertySetMapper = CreateShapePropMapper( mrExport );
    if( pExtMapper )
    {
        rtl::Reference < SvXMLExportPropertyMapper > xExtMapper( pExtMapper );
        mxPropertySetMapper->ChainExportMapper( xExtMapper );
    }

/*
    // chain text attributes
    xPropertySetMapper->ChainExportMapper(XMLTextParagraphExport::CreateParaExtPropMapper(rExp));
*/


    mrExport.GetAutoStylePool()->AddFamily(
        XmlStyleFamily::SD_GRAPHICS_ID,
        XML_STYLE_FAMILY_SD_GRAPHICS_NAME,
        GetPropertySetMapper(),
        XML_STYLE_FAMILY_SD_GRAPHICS_PREFIX);
    mrExport.GetAutoStylePool()->AddFamily(
        XmlStyleFamily::SD_PRESENTATION_ID,
        XML_STYLE_FAMILY_SD_PRESENTATION_NAME,
        GetPropertySetMapper(),
        XML_STYLE_FAMILY_SD_PRESENTATION_PREFIX);

    // create table export helper and let him add his families in time
    GetShapeTableExport();
}

XMLShapeExport::~XMLShapeExport()
{
}

// sj: replacing CustomShapes with standard objects that are also supported in OpenOffice.org format
uno::Reference< drawing::XShape > XMLShapeExport::checkForCustomShapeReplacement( const uno::Reference< drawing::XShape >& xShape )
{
    uno::Reference< drawing::XShape > xCustomShapeReplacement;

    if( !( GetExport().getExportFlags() & SvXMLExportFlags::OASIS ) )
    {
        OUString aType( xShape->getShapeType() );
        if( aType == "com.sun.star.drawing.CustomShape" )
        {
            uno::Reference< beans::XPropertySet > xSet( xShape, uno::UNO_QUERY );
            if( xSet.is() )
            {
                OUString aEngine;
                xSet->getPropertyValue(u"CustomShapeEngine"_ustr) >>= aEngine;
                if ( aEngine.isEmpty() )
                {
                    aEngine = "com.sun.star.drawing.EnhancedCustomShapeEngine";
                }
                const uno::Reference< uno::XComponentContext >& xContext( ::comphelper::getProcessComponentContext() );

                if ( !aEngine.isEmpty() )
                {
                    uno::Sequence< beans::PropertyValue > aPropValues{
                        comphelper::makePropertyValue(u"CustomShape"_ustr, xShape),
                        comphelper::makePropertyValue(u"ForceGroupWithText"_ustr, true)
                    };
                    uno::Sequence< uno::Any > aArgument = { uno::Any(aPropValues) };
                    uno::Reference< uno::XInterface > xInterface(
                        xContext->getServiceManager()->createInstanceWithArgumentsAndContext(aEngine, aArgument, xContext) );
                    if ( xInterface.is() )
                    {
                        uno::Reference< drawing::XCustomShapeEngine > xCustomShapeEngine(
                            uno::Reference< drawing::XCustomShapeEngine >( xInterface, uno::UNO_QUERY ) );
                        if ( xCustomShapeEngine.is() )
                            xCustomShapeReplacement = xCustomShapeEngine->render();
                    }
                }
            }
        }
    }
    return xCustomShapeReplacement;
}

// This method collects all automatic styles for the given XShape
void XMLShapeExport::collectShapeAutoStyles(const uno::Reference< drawing::XShape >&&nbsp;xShape )
{
    if( maCurrentShapesIter == maShapesInfos.end() )
    {
        OSL_FAIL( "XMLShapeExport::collectShapeAutoStyles(): no call to seekShapes()!" );
        return;
    }
    uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);

    ShapeExportInfoMap& aShapeInfoMap = (*maCurrentShapesIter).second;

    ImplXMLShapeExportInfo& aShapeInfo = aShapeInfoMap[xShape];

    uno::Reference< drawing::XShape > xCustomShapeReplacement = checkForCustomShapeReplacement( xShape );
    if ( xCustomShapeReplacement.is() )
        aShapeInfo.xCustomShapeReplacement = std::move(xCustomShapeReplacement);

    // first compute the shapes type
    ImpCalcShapeType(xShape, aShapeInfo.meShapeType);

    // #i118485# enabled XmlShapeType::DrawChartShape and XmlShapeType::DrawOLE2Shape
    // to have text
    const bool bObjSupportsText =
        supportsText(aShapeInfo.meShapeType);

    const bool bObjSupportsStyle =
        aShapeInfo.meShapeType != XmlShapeType::DrawGroupShape;

    bool bIsEmptyPresObj = false;

    if ( aShapeInfo.xCustomShapeReplacement.is() )
        xPropSet.clear();

    // prep text styles
    if( xPropSet.is() && bObjSupportsText )
    {
        uno::Reference< text::XText > xText(xShape, uno::UNO_QUERY);
        if (xText.is())
        {
            try
            {
                // tdf#153161: it seems that the call to xText->getText flushes the changes
                // for some objects, that otherwise fail to get exported correctly. Maybe at some
                // point it would make sense to find a better place for more targeted flush.
                xText = xText->getText();
            }
            catch (uno::RuntimeException const&)
            {
                // E.g., SwXTextFrame that contains only a table will throw; this is not an error
            }

            uno::Reference< beans::XPropertySetInfo > xPropSetInfo( xPropSet->getPropertySetInfo() );

            if( xPropSetInfo.is() && xPropSetInfo->hasPropertyByName(u"IsEmptyPresentationObject"_ustr) )
            {
                uno::Any aAny = xPropSet->getPropertyValue(u"IsEmptyPresentationObject"_ustr);
                aAny >>= bIsEmptyPresObj;
            }

            if(!bIsEmptyPresObj)
            {
                GetExport().GetTextParagraphExport()->collectTextAutoStyles( xText );
            }
        }
    }

    // compute the shape parent style
    if( xPropSet.is() )
    {
        uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( xPropSet->getPropertySetInfo() );

        OUString aParentName;
        uno::Reference< style::XStyle > xStyle;

        if( bObjSupportsStyle )
        {
            if( xPropertySetInfo.is() && xPropertySetInfo->hasPropertyByName(u"Style"_ustr) )
                xPropSet->getPropertyValue(u"Style"_ustr) >>= xStyle;

            if(xStyle.is())
            {
                // get family ID
                uno::Reference< beans::XPropertySet > xStylePropSet(xStyle, uno::UNO_QUERY);
                SAL_WARN_IF( !xStylePropSet.is(), "xmloff""style without a XPropertySet?" );
                try
                {
                    if(xStylePropSet.is())
                    {
                        OUString aFamilyName;
                        xStylePropSet->getPropertyValue(u"Family"_ustr) >>= aFamilyName;
                        if( !aFamilyName.isEmpty() && aFamilyName != "graphics" )
                            aShapeInfo.mnFamily = XmlStyleFamily::SD_PRESENTATION_ID;
                    }
                }
                catch(const beans::UnknownPropertyException&)
                {
                    // Ignored.
                    SAL_WARN( "xmloff",
                        "XMLShapeExport::collectShapeAutoStyles: style has no 'Family' property");
                }

                // get parent-style name
                if(XmlStyleFamily::SD_PRESENTATION_ID == aShapeInfo.mnFamily)
                {
                    aParentName = msPresentationStylePrefix;
                }

                aParentName += xStyle->getName();
            }
        }

        if (aParentName.isEmpty() && xPropertySetInfo->hasPropertyByName(u"TextBox"_ustr) && xPropSet->getPropertyValue(u"TextBox"_ustr).hasValue() && xPropSet->getPropertyValue(u"TextBox"_ustr).get<bool>())
        {
            // Shapes with a Writer TextBox always have a parent style.
            // If there would be none, then assign the default one.
            aParentName = "Frame";
        }

        // filter propset
        std::vector< XMLPropertyState > aPropStates;

        sal_Int32 nCount = 0;
        if( !bIsEmptyPresObj || (aShapeInfo.meShapeType != XmlShapeType::PresPageShape) )
        {
            aPropStates = GetPropertySetMapper()->Filter(mrExport, xPropSet);

            if (XmlShapeType::DrawControlShape == aShapeInfo.meShapeType)
            {
                // for control shapes, we additionally need the number format style (if any)
                uno::Reference< drawing::XControlShape > xControl(xShape, uno::UNO_QUERY);
                DBG_ASSERT(xControl.is(), "XMLShapeExport::collectShapeAutoStyles: ShapeType control, but no XControlShape!");
                if (xControl.is())
                {
                    uno::Reference< beans::XPropertySet > xControlModel(xControl->getControl(), uno::UNO_QUERY);
                    DBG_ASSERT(xControlModel.is(), "XMLShapeExport::collectShapeAutoStyles: no control model on the control shape!");

                    OUString sNumberStyle = mrExport.GetFormExport()->getControlNumberStyle(xControlModel);
                    if (!sNumberStyle.isEmpty())
                    {
                        sal_Int32 nIndex = GetPropertySetMapper()->getPropertySetMapper()->FindEntryIndex(CTF_SD_CONTROL_SHAPE_DATA_STYLE);
                            // TODO : this retrieval of the index could be moved into the ctor, holding the index
                            //          as member, thus saving time.
                        DBG_ASSERT(-1 != nIndex, "XMLShapeExport::collectShapeAutoStyles: could not obtain the index for our context id!");

                        XMLPropertyState aNewState(nIndex, uno::Any(sNumberStyle));
                        aPropStates.push_back(aNewState);
                    }
                }
            }

            nCount = std::count_if(aPropStates.cbegin(), aPropStates.cend(),
                [](const XMLPropertyState& rProp) { return rProp.mnIndex != -1; });
        }

        if(nCount == 0)
        {
            // no hard attributes, use parent style name for export
            aShapeInfo.msStyleName = aParentName;
        }
        else
        {
            // there are filtered properties -> hard attributes
            // try to find this style in AutoStylePool
            aShapeInfo.msStyleName = mrExport.GetAutoStylePool()->Find(aShapeInfo.mnFamily, aParentName, aPropStates);

            if(aShapeInfo.msStyleName.isEmpty())
            {
                // Style did not exist, add it to AutoStalePool
                aShapeInfo.msStyleName = mrExport.GetAutoStylePool()->Add(aShapeInfo.mnFamily, aParentName, std::move(aPropStates));
            }
        }

        // optionally generate auto style for text attributes
        if( (!bIsEmptyPresObj || (aShapeInfo.meShapeType != XmlShapeType::PresPageShape)) && bObjSupportsText )
        {
            aPropStates = GetExport().GetTextParagraphExport()->GetParagraphPropertyMapper()->Filter(mrExport, xPropSet);

            // yet more additionally, we need to care for the ParaAdjust property
            if ( XmlShapeType::DrawControlShape == aShapeInfo.meShapeType )
            {
                uno::Reference< beans::XPropertySetInfo > xPropSetInfo( xPropSet->getPropertySetInfo() );
                uno::Reference< beans::XPropertyState > xPropState( xPropSet, uno::UNO_QUERY );
                if ( xPropSetInfo.is() && xPropState.is() )
                {
                    // this is because:
                    // * if controls shapes have a ParaAdjust property, then this is the Align property of the control model
                    // * control models are allowed to have an Align of "void"
                    // * the Default for control model's Align is TextAlign_LEFT
                    // * defaults for style properties are not written, but we need to write the "left",
                    //   because we need to distinguish this "left" from the case where not align attribute
                    //   is present which means "void"
                    if  (   xPropSetInfo->hasPropertyByName( u"ParaAdjust"_ustr )
                        &&  ( beans::PropertyState_DEFAULT_VALUE == xPropState->getPropertyState( u"ParaAdjust"_ustr ) )
                        )
                    {
                        sal_Int32 nIndex = GetExport().GetTextParagraphExport()->GetParagraphPropertyMapper()->getPropertySetMapper()->FindEntryIndex( CTF_SD_SHAPE_PARA_ADJUST );
                            // TODO : this retrieval of the index should be moved into the ctor, holding the index
                            //          as member, thus saving time.
                        DBG_ASSERT(-1 != nIndex, "XMLShapeExport::collectShapeAutoStyles: could not obtain the index for the ParaAdjust context id!");

                        XMLPropertyState aAlignDefaultState(nIndex, xPropSet->getPropertyValue(u"ParaAdjust"_ustr));

                        aPropStates.push_back( aAlignDefaultState );
                    }
                }
            }

            nCount = std::count_if(aPropStates.cbegin(), aPropStates.cend(),
                [](const XMLPropertyState& rProp) { return rProp.mnIndex != -1; });

            if( nCount )
            {
                aShapeInfo.msTextStyleName = mrExport.GetAutoStylePool()->Find( XmlStyleFamily::TEXT_PARAGRAPH, u""_ustr, aPropStates );
                if(aShapeInfo.msTextStyleName.isEmpty())
                {
                    // Style did not exist, add it to AutoStalePool
                    aShapeInfo.msTextStyleName = mrExport.GetAutoStylePool()->Add(XmlStyleFamily::TEXT_PARAGRAPH, u""_ustr, std::move(aPropStates));
                }
            }
        }
    }

    // prepare animation information if needed
    if( mxAnimationsExporter.is() )
        XMLAnimationsExporter::prepare( xShape );

    // check for special shapes

    switch( aShapeInfo.meShapeType )
    {
        case XmlShapeType::DrawConnectorShape:
        {
            uno::Reference< uno::XInterface > xConnection;

            // create shape ids for export later
            xPropSet->getPropertyValue( gsStartShape ) >>= xConnection;
            if( xConnection.is() )
                mrExport.getInterfaceToIdentifierMapper().registerReference( xConnection );

            xPropSet->getPropertyValue( gsEndShape ) >>= xConnection;
            if( xConnection.is() )
                mrExport.getInterfaceToIdentifierMapper().registerReference( xConnection );
            break;
        }
        case XmlShapeType::PresTableShape:
        case XmlShapeType::DrawTableShape:
        {
            try
            {
                uno::Reference< table::XColumnRowRange > xRange( xPropSet->getPropertyValue( gsModel ), uno::UNO_QUERY_THROW );
                GetShapeTableExport()->collectTableAutoStyles( xRange );
            }
            catch(const uno::Exception&)
            {
                DBG_UNHANDLED_EXCEPTION( "xmloff""collecting auto styles for a table" );
            }
            break;
        }
        default:
            break;
    }

    // check for shape collections (group shape or 3d scene)
    // and collect contained shapes style infos
    const uno::Reference< drawing::XShape >& xCollection = aShapeInfo.xCustomShapeReplacement.is()
                                                ? aShapeInfo.xCustomShapeReplacement : xShape;
    {
        uno::Reference< drawing::XShapes > xShapes( xCollection, uno::UNO_QUERY );
        if( xShapes.is() )
        {
            collectShapesAutoStyles( xShapes );
        }
    }
}

namespace
{
    class NewTextListsHelper
    {
        public:
            explicit NewTextListsHelper( SvXMLExport& rExp )
                : mrExport( rExp )
            {
                mrExport.GetTextParagraphExport()->PushNewTextListsHelper();
            }

            ~NewTextListsHelper()
            {
                mrExport.GetTextParagraphExport()->PopTextListsHelper();
            }

        private:
            SvXMLExport& mrExport;
    };
}
// This method exports the given XShape
void XMLShapeExport::exportShape(const uno::Reference< drawing::XShape >& xShape,
                                 XMLShapeExportFlags nFeatures /* = SEF_DEFAULT */,
                                 css::awt::Point* pRefPoint /* = NULL */,
                                 comphelper::AttributeList* pAttrList /* = NULL */ )
{
    SAL_INFO("xmloff", xShape->getShapeType());
    if( maCurrentShapesIter == maShapesInfos.end() )
    {
        SAL_WARN( "xmloff""XMLShapeExport::exportShape(): no auto styles where collected before export" );
        return;
    }
    uno::Reference< beans::XPropertySet > xSet( xShape, uno::UNO_QUERY );
    OUString sHyperlink;
    try
    {
        xSet->getPropertyValue(gsHyperlink) >>= sHyperlink;
    }
    catch (beans::UnknownPropertyException)
    {
    }

    std::unique_ptr< SvXMLElementExport >  pHyperlinkElement;

    // Need to stash the attributes that are pre-loaded for the shape export
    // (otherwise they will become attributes of the draw:a element)
    uno::Reference<xml::sax::XAttributeList> xSaveAttribs(
        new comphelper::AttributeList(GetExport().GetAttrList()));
    GetExport().ClearAttrList();
    if( xSet.is() && (GetExport().GetModelType() == SvtModuleOptions::EFactory::DRAW) )
    {
        // export hyperlinks with <a><shape/></a>. Currently only in draw since draw
        // does not support document events
        try
        {
            presentation::ClickAction eAction = presentation::ClickAction_NONE;
            xSet->getPropertyValue(gsOnClick) >>= eAction;

            if( (eAction == presentation::ClickAction_DOCUMENT) ||
                (eAction == presentation::ClickAction_BOOKMARK) )
            {
                OUString sURL;
                xSet->getPropertyValue(gsBookmark) >>= sURL;

                if( !sURL.isEmpty() )
                {
                    mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, sURL );
                    mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
                    mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED );
                    pHyperlinkElement.reset( new SvXMLElementExport(mrExport, XML_NAMESPACE_DRAW, XML_A, truetrue) );
                }
            }
        }
        catch(const uno::Exception&)
        {
            TOOLS_WARN_EXCEPTION("xmloff""XMLShapeExport::exportShape(): exception during hyperlink export");
        }
    }
    else if (xSet.is() && !sHyperlink.isEmpty())
    {
        mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, sHyperlink );
        mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
        pHyperlinkElement.reset( new SvXMLElementExport(mrExport, XML_NAMESPACE_DRAW, XML_A, truetrue) );
    }
    // re-add stashed attributes
    GetExport().AddAttributeList(xSaveAttribs);

    ShapeExportInfoMap& aShapeInfoMap = (*maCurrentShapesIter).second;

    auto it = aShapeInfoMap.find(xShape);
    if (it == aShapeInfoMap.end())
    {
        SAL_WARN( "xmloff""XMLShapeExport::exportShape(): no shape info collected for a given shape" );
        return;
    }

    NewTextListsHelper aNewTextListsHelper( mrExport );

    const ImplXMLShapeExportInfo& aShapeInfo = it->second;

#ifdef DBG_UTIL
    // check if this is the correct ShapesInfo
    uno::Reference< container::XChild > xChild( xShape, uno::UNO_QUERY );
    if( xChild.is() )
    {
        uno::Reference< drawing::XShapes > xParent( xChild->getParent(), uno::UNO_QUERY );
        SAL_WARN_IF( !xParent.is() && xParent.get() == (*maCurrentShapesIter).first.get(), "xmloff""XMLShapeExport::exportShape(): Wrong call to XMLShapeExport::seekShapes()" );
    }

    // first compute the shapes type
    {
        XmlShapeType eShapeType(XmlShapeType::NotYetSet);
        ImpCalcShapeType(xShape, eShapeType);

        SAL_WARN_IF( eShapeType != aShapeInfo.meShapeType, "xmloff""exportShape callings do not correspond to collectShapeAutoStyles calls!: " << xShape->getShapeType() );
    }
#endif

    // collect animation information if needed
    if( mxAnimationsExporter.is() )
        mxAnimationsExporter->collect( xShape, mrExport );

    /* Export shapes name if he has one (#i51726#)
       Export of the shape name for text documents only if the OpenDocument
       file format is written - exceptions are group shapes.
       Note: Writer documents in OpenOffice.org file format doesn't contain
             any names for shapes, except for group shapes.
    */

    {
        if ( ( GetExport().GetModelType() != SvtModuleOptions::EFactory::WRITER &&
               GetExport().GetModelType() != SvtModuleOptions::EFactory::WRITERWEB &&
               GetExport().GetModelType() != SvtModuleOptions::EFactory::WRITERGLOBAL ) ||
             ( GetExport().getExportFlags() & SvXMLExportFlags::OASIS ) ||
             aShapeInfo.meShapeType == XmlShapeType::DrawGroupShape ||
             ( aShapeInfo.meShapeType == XmlShapeType::DrawCustomShape &&
               aShapeInfo.xCustomShapeReplacement.is() ) )
        {
            uno::Reference< container::XNamed > xNamed( xShape, uno::UNO_QUERY );
            if( xNamed.is() )
            {
                const OUString aName( xNamed->getName() );
                if( !aName.isEmpty() )
                    mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_NAME, aName );
            }
        }
    }

    // export style name
    if( !aShapeInfo.msStyleName.isEmpty() )
    {
        if(XmlStyleFamily::SD_GRAPHICS_ID == aShapeInfo.mnFamily)
            mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_STYLE_NAME, mrExport.EncodeStyleName( aShapeInfo.msStyleName) );
        else
            mrExport.AddAttribute(XML_NAMESPACE_PRESENTATION, XML_STYLE_NAME, mrExport.EncodeStyleName( aShapeInfo.msStyleName) );
    }

    // export text style name
    if( !aShapeInfo.msTextStyleName.isEmpty() )
    {
        mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_TEXT_STYLE_NAME, aShapeInfo.msTextStyleName );
    }

    // export shapes id if needed
    {
        uno::Reference< uno::XInterface > xRef( xShape, uno::UNO_QUERY );
        const OUString& rShapeId = mrExport.getInterfaceToIdentifierMapper().getIdentifier( xRef );
        if( !rShapeId.isEmpty() )
        {
            mrExport.AddAttributeIdLegacy(XML_NAMESPACE_DRAW, rShapeId);
        }
    }

    // export layer information
    if( mbExportLayer )
    {
        // check for group or scene shape and not export layer if this is one
        uno::Reference< drawing::XShapes > xShapes( xShape, uno::UNO_QUERY );
        if( !xShapes.is() )
        {
            try
            {
                uno::Reference< beans::XPropertySet > xProps( xShape, uno::UNO_QUERY );
                OUString aLayerName;
                xProps->getPropertyValue(u"LayerName"_ustr) >>= aLayerName;
                mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_LAYER, aLayerName );

            }
            catch(const uno::Exception&)
            {
                DBG_UNHANDLED_EXCEPTION( "xmloff""exporting layer name for shape" );
            }
        }
    }

    // export draw:display (do not export in ODF 1.3 or older)
    if (xSet.is() && (mrExport.getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED))
    {
        if( aShapeInfo.meShapeType != XmlShapeType::DrawPageShape && aShapeInfo.meShapeType != XmlShapeType::PresPageShape &&
            aShapeInfo.meShapeType != XmlShapeType::HandoutShape && aShapeInfo.meShapeType != XmlShapeType::DrawChartShape )
            try
            {
                bool bVisible = true;
                bool bPrintable = true;

                xSet->getPropertyValue(gsVisible) >>= bVisible;
                xSet->getPropertyValue(gsPrintable) >>= bPrintable;

                XMLTokenEnum eDisplayToken = XML_TOKEN_INVALID;
                const unsigned short nDisplay = (bVisible ? 2 : 0) | (bPrintable ? 1 : 0);
                switch( nDisplay )
                {
                case 0: eDisplayToken = XML_NONE; break;
                case 1: eDisplayToken = XML_PRINTER; break;
                case 2: eDisplayToken = XML_SCREEN; break;
                // case 3: eDisplayToken = XML_ALWAYS break; this is the default
                }

                if( eDisplayToken != XML_TOKEN_INVALID )
                    mrExport.AddAttribute(XML_NAMESPACE_DRAW_EXT, XML_DISPLAY, eDisplayToken );
            }
            catch(const uno::Exception&)
            {
                DBG_UNHANDLED_EXCEPTION("xmloff.draw");
            }
    }

    // #82003# test export count
    // #91587# ALWAYS increment since now ALL to be exported shapes are counted.
    if(mrExport.GetShapeExport()->IsHandleProgressBarEnabled())
    {
        mrExport.GetProgressBarHelper()->Increment();
    }

    onExport( xShape );

    // export shape element
    switch(aShapeInfo.meShapeType)
    {
        case XmlShapeType::DrawRectangleShape:
        {
            ImpExportRectangleShape(xShape, nFeatures, pRefPoint );
            break;
        }
        case XmlShapeType::DrawEllipseShape:
        {
            ImpExportEllipseShape(xShape, nFeatures, pRefPoint );
            break;
        }
        case XmlShapeType::DrawLineShape:
        {
            ImpExportLineShape(xShape, nFeatures, pRefPoint );
            break;
        }
        case XmlShapeType::DrawPolyPolygonShape:  // closed PolyPolygon
        case XmlShapeType::DrawPolyLineShape:     // open PolyPolygon
        case XmlShapeType::DrawClosedBezierShape: // closed tools::PolyPolygon containing curves
        case XmlShapeType::DrawOpenBezierShape:   // open tools::PolyPolygon containing curves
        {
            ImpExportPolygonShape(xShape, aShapeInfo.meShapeType, nFeatures, pRefPoint );
            break;
        }

        case XmlShapeType::DrawTextShape:
        case XmlShapeType::PresTitleTextShape:
        case XmlShapeType::PresOutlinerShape:
        case XmlShapeType::PresSubtitleShape:
        case XmlShapeType::PresNotesShape:
        case XmlShapeType::PresHeaderShape:
        case XmlShapeType::PresFooterShape:
        case XmlShapeType::PresSlideNumberShape:
        case XmlShapeType::PresDateTimeShape:
        {
            ImpExportTextBoxShape(xShape, aShapeInfo.meShapeType, nFeatures, pRefPoint );
            break;
        }

        case XmlShapeType::DrawGraphicObjectShape:
        case XmlShapeType::PresGraphicObjectShape:
        {
            ImpExportGraphicObjectShape(xShape, aShapeInfo.meShapeType, nFeatures, pRefPoint );
            break;
        }

        case XmlShapeType::DrawChartShape:
        case XmlShapeType::PresChartShape:
        {
            ImpExportChartShape(xShape, aShapeInfo.meShapeType, nFeatures, pRefPoint, pAttrList );
            break;
        }

        case XmlShapeType::DrawControlShape:
        {
            ImpExportControlShape(xShape, nFeatures, pRefPoint );
            break;
        }

        case XmlShapeType::DrawConnectorShape:
        {
            ImpExportConnectorShape(xShape, nFeatures, pRefPoint );
            break;
        }

        case XmlShapeType::DrawMeasureShape:
        {
            ImpExportMeasureShape(xShape, nFeatures, pRefPoint );
            break;
        }

        case XmlShapeType::DrawOLE2Shape:
        case XmlShapeType::PresOLE2Shape:
        case XmlShapeType::DrawSheetShape:
        case XmlShapeType::PresSheetShape:
        {
            ImpExportOLE2Shape(xShape, aShapeInfo.meShapeType, nFeatures, pRefPoint );
            break;
        }

        case XmlShapeType::PresTableShape:
        case XmlShapeType::DrawTableShape:
        {
            ImpExportTableShape( xShape, aShapeInfo.meShapeType, nFeatures, pRefPoint );
            break;
        }

        case XmlShapeType::DrawPageShape:
        case XmlShapeType::PresPageShape:
        case XmlShapeType::HandoutShape:
        {
            ImpExportPageShape(xShape, aShapeInfo.meShapeType, nFeatures, pRefPoint );
            break;
        }

        case XmlShapeType::DrawCaptionShape:
        {
            ImpExportCaptionShape(xShape, nFeatures, pRefPoint );
            break;
        }

        case XmlShapeType::Draw3DCubeObject:
        case XmlShapeType::Draw3DSphereObject:
        case XmlShapeType::Draw3DLatheObject:
        case XmlShapeType::Draw3DExtrudeObject:
        {
            ImpExport3DShape(xShape, aShapeInfo.meShapeType);
            break;
        }

        case XmlShapeType::Draw3DSceneObject:
        {
            ImpExport3DSceneShape( xShape, nFeatures, pRefPoint );
            break;
        }

        case XmlShapeType::DrawGroupShape:
        {
            // empty group
            ImpExportGroupShape( xShape, nFeatures, pRefPoint );
            break;
        }

        case XmlShapeType::DrawFrameShape:
        {
            ImpExportFrameShape(xShape, nFeatures, pRefPoint );
            break;
        }

        case XmlShapeType::DrawAppletShape:
        {
            ImpExportAppletShape(xShape, nFeatures, pRefPoint );
            break;
        }

        case XmlShapeType::DrawPluginShape:
        {
            ImpExportPluginShape(xShape, nFeatures, pRefPoint );
            break;
        }

        case XmlShapeType::DrawCustomShape:
        {
            if ( aShapeInfo.xCustomShapeReplacement.is() )
                ImpExportGroupShape( aShapeInfo.xCustomShapeReplacement, nFeatures, pRefPoint );
            else
                ImpExportCustomShape( xShape, nFeatures, pRefPoint );
            break;
        }

        case XmlShapeType::PresMediaShape:
        case XmlShapeType::DrawMediaShape:
        {
            ImpExportMediaShape( xShape, aShapeInfo.meShapeType, nFeatures, pRefPoint );
            break;
        }

        case XmlShapeType::PresOrgChartShape:
        case XmlShapeType::Unknown:
        case XmlShapeType::NotYetSet:
        default:
        {
            // this should never happen and is an error
            OSL_FAIL("XMLEXP: WriteShape: unknown or unexpected type of shape in export!");
            break;
        }
    }

    pHyperlinkElement.reset();

    // #97489# #97111#
    // if there was an error and no element for the shape was exported
    // we need to clear the attribute list or the attributes will be
    // set on the next exported element, which can result in corrupt
    // xml files due to duplicate attributes

    mrExport.CheckAttrList();   // asserts in non pro if we have attributes left
    mrExport.ClearAttrList();   // clears the attributes
}

// This method collects all automatic styles for the shapes inside the given XShapes collection
void XMLShapeExport::collectShapesAutoStyles( const uno::Reference < drawing::XShapes >&&nbsp;xShapes )
{
    ShapesInfos::iterator aOldCurrentShapesIter = maCurrentShapesIter;
    seekShapes( xShapes );

    uno::Reference< drawing::XShape > xShape;
    const sal_Int32 nShapeCount(xShapes->getCount());
    for(sal_Int32 nShapeId = 0; nShapeId < nShapeCount; nShapeId++)
    {
        xShapes->getByIndex(nShapeId) >>= xShape;
        SAL_WARN_IF( !xShape.is(), "xmloff""Shape without a XShape?" );
        if(!xShape.is())
            continue;

        collectShapeAutoStyles( xShape );
    }

    maCurrentShapesIter = aOldCurrentShapesIter;
}

// This method exports all XShape inside the given XShapes collection
void XMLShapeExport::exportShapes( const uno::Reference < drawing::XShapes >& xShapes, XMLShapeExportFlags nFeatures /* = SEF_DEFAULT */, awt::Point* pRefPoint /* = NULL */ )
{
    ShapesInfos::iterator aOldCurrentShapesIter = maCurrentShapesIter;
    seekShapes( xShapes );

    uno::Reference< drawing::XShape > xShape;
    const sal_Int32 nShapeCount(xShapes->getCount());
    for(sal_Int32 nShapeId = 0; nShapeId < nShapeCount; nShapeId++)
    {
        xShapes->getByIndex(nShapeId) >>= xShape;
        SAL_WARN_IF( !xShape.is(), "xmloff""Shape without a XShape?" );
        if(!xShape.is())
            continue;

        exportShape( xShape, nFeatures, pRefPoint );
    }

    maCurrentShapesIter = aOldCurrentShapesIter;
}

namespace xmloff {

void FixZOrder(uno::Reference<drawing::XShapes> const& xShapes,
    std::function<unsigned int (uno::Reference<beans::XPropertySet> const&)> const& rGetLayer)
{
    uno::Reference<drawing::XShapes3> const xShapes3(xShapes, uno::UNO_QUERY);
    assert(xShapes3.is());
    if (!xShapes3.is())
    {
        return// only SvxDrawPage implements this
    }
    struct Layer { std::vector<sal_Int32> shapes; sal_Int32 nMin = SAL_MAX_INT32; sal_Int32 nMax = 0; };
    std::vector<Layer> layers;
    // shapes are sorted by ZOrder
    sal_Int32 const nCount(xShapes->getCount());
    for (sal_Int32 i = 0; i < nCount; ++i)
    {
        uno::Reference<beans::XPropertySet> const xShape(xShapes->getByIndex(i), uno::UNO_QUERY);
        if (!xShape.is())
        {
            SAL_WARN("xmloff""FixZOrder: null shape, cannot sort");
            return;
        }
        unsigned int const nLayer(rGetLayer(xShape));
        if (layers.size() <= nLayer)
        {
            layers.resize(nLayer + 1);
        }
        layers[nLayer].shapes.emplace_back(i);
        if (i < layers[nLayer].nMin)
        {
            layers[nLayer].nMin = i;
        }
        if (layers[nLayer].nMax < i)
        {
            layers[nLayer].nMax = i;
        }
    }
    std::erase_if(layers, [](Layer const& rLayer) { return rLayer.shapes.empty(); });
    bool isSorted(true);
    for (size_t i = 1; i < layers.size(); ++i)
    {
        assert(layers[i].nMin != layers[i-1].nMax); // unique!
        if (layers[i].nMin < layers[i-1].nMax)
        {
            isSorted = false;
            break;
        }
    }
    if (isSorted)
    {
        return// nothing to do
    }
    uno::Sequence<sal_Int32> aNewOrder(nCount);
    auto iterInsert(aNewOrder.getArray());
    for (auto const& rLayer : layers)
    {
        assert(rLayer.nMin <= rLayer.nMax); // empty layers have been removed
        iterInsert = std::copy(rLayer.shapes.begin(), rLayer.shapes.end(), iterInsert);
    }
    try
    {
        xShapes3->sort(aNewOrder);
    }
    catch (uno::Exception const&)
    {
        SAL_WARN("xmloff""FixZOrder: exception");
    }
}

// namespace xmloff

void XMLShapeExport::seekShapes( const uno::Reference< drawing::XShapes >& xShapes ) noexcept
{
    if( xShapes.is() )
    {
        maCurrentShapesIter = maShapesInfos.try_emplace(xShapes).first;
        assert(maCurrentShapesIter != maShapesInfos.end());

        SAL_WARN_IF( (*maCurrentShapesIter).second.size() != static_cast<ShapesInfos::size_type>(xShapes->getCount()), "xmloff""XMLShapeExport::seekShapes(): XShapes size varied between calls" );

    }
    else
    {
        maCurrentShapesIter = maShapesInfos.end();
    }
}

void XMLShapeExport::exportAutoStyles()
{
    // export all autostyle infos

    // ...for graphic
    {
        GetExport().GetAutoStylePool()->exportXML( XmlStyleFamily::SD_GRAPHICS_ID );
    }

    // ...for presentation
    {
        GetExport().GetAutoStylePool()->exportXML( XmlStyleFamily::SD_PRESENTATION_ID );
    }

    if( mxShapeTableExport.is() )
        mxShapeTableExport->exportAutoStyles();
}

/// returns the export property mapper for external chaining
SvXMLExportPropertyMapper* XMLShapeExport::CreateShapePropMapper(
    SvXMLExport& rExport )
{
    rtl::Reference< XMLPropertyHandlerFactory > xFactory = new XMLSdPropHdlFactory( rExport.GetModel(), rExport );
    rtl::Reference < XMLPropertySetMapper > xMapper = new XMLShapePropertySetMapper( xFactory, true );
    rExport.GetTextParagraphExport(); // get or create text paragraph export
    SvXMLExportPropertyMapper* pResult =
        new XMLShapeExportPropertyMapper( xMapper, rExport );
    // chain text attributes
    return pResult;
}

void XMLShapeExport::ImpCalcShapeType(const uno::Reference< drawing::XShape >& xShape,
    XmlShapeType& eShapeType)
{
    // set in every case, so init here
    eShapeType = XmlShapeType::Unknown;

    if(!xShape.is())
        return;

    OUString aType(xShape->getShapeType());

    if(!aType.match("com.sun.star."))
        return;

    if(aType.match("drawing.", 13))
    {
        // drawing shapes
        if     (aType.match("Rectangle", 21)) { eShapeType = XmlShapeType::DrawRectangleShape; }

        // #i72177# Note: Correcting CustomShape, CustomShape->Custom, len from 9 (was wrong anyways) to 6.
        // As can be seen at the other compares, the appendix "Shape" is left out of the comparison.
        else if(aType.match("Custom", 21)) { eShapeType = XmlShapeType::DrawCustomShape; }

        else if(aType.match("Ellipse", 21)) { eShapeType = XmlShapeType::DrawEllipseShape; }
        else if(aType.match("Control", 21)) { eShapeType = XmlShapeType::DrawControlShape; }
        else if(aType.match("Connector", 21)) { eShapeType = XmlShapeType::DrawConnectorShape; }
        else if(aType.match("Measure", 21)) { eShapeType = XmlShapeType::DrawMeasureShape; }
        else if(aType.match("Line", 21)) { eShapeType = XmlShapeType::DrawLineShape; }

        // #i72177# Note: This covers two types by purpose, PolyPolygonShape and PolyPolygonPathShape
        else if(aType.match("PolyPolygon", 21)) { eShapeType = XmlShapeType::DrawPolyPolygonShape; }

        // #i72177# Note: This covers two types by purpose, PolyLineShape and PolyLinePathShape
        else if(aType.match("PolyLine", 21)) { eShapeType = XmlShapeType::DrawPolyLineShape; }

        else if(aType.match("OpenBezier", 21)) { eShapeType = XmlShapeType::DrawOpenBezierShape; }
        else if(aType.match("ClosedBezier", 21)) { eShapeType = XmlShapeType::DrawClosedBezierShape; }

        // #i72177# FreeHand (opened and closed) now supports the types OpenFreeHandShape and
        // ClosedFreeHandShape respectively. Represent them as bezier shapes
        else if(aType.match("OpenFreeHand", 21)) { eShapeType = XmlShapeType::DrawOpenBezierShape; }
        else if(aType.match("ClosedFreeHand", 21)) { eShapeType = XmlShapeType::DrawClosedBezierShape; }

        else if(aType.match("GraphicObject", 21)) { eShapeType = XmlShapeType::DrawGraphicObjectShape; }
        else if(aType.match("Group", 21)) { eShapeType = XmlShapeType::DrawGroupShape; }
        else if(aType.match("Text", 21)) { eShapeType = XmlShapeType::DrawTextShape; }
        else if(aType.match("OLE2", 21))
        {
            eShapeType = XmlShapeType::DrawOLE2Shape;

            // get info about presentation shape
            uno::Reference <beans::XPropertySet> xPropSet(xShape, uno::UNO_QUERY);

            if(xPropSet.is())
            {
                OUString sCLSID;
                if(xPropSet->getPropertyValue(u"CLSID"_ustr) >>= sCLSID)
                {
#if !ENABLE_WASM_STRIP_CHART
                    // WASM_CHART change
                    // TODO: With Chart extracted this cannot really happen since
                    // no Chart could've been added at all
                    if (sCLSID == mrExport.GetChartExport()->getChartCLSID() ||
#else
                    if(
#endif
                        sCLSID == SvGlobalName( SO3_RPTCH_CLASSID ).GetHexName() )
                    {
                        eShapeType = XmlShapeType::DrawChartShape;
                    }
                    else if (sCLSID == SvGlobalName( SO3_SC_CLASSID ).GetHexName() )
                    {
                        eShapeType = XmlShapeType::DrawSheetShape;
                    }
                    else
                    {
                        // general OLE2 Object
                    }
                }
            }
        }
        else if(aType.match("Page", 21)) { eShapeType = XmlShapeType::DrawPageShape; }
        else if(aType.match("Frame", 21)) { eShapeType = XmlShapeType::DrawFrameShape; }
        else if(aType.match("Caption", 21)) { eShapeType = XmlShapeType::DrawCaptionShape; }
        else if(aType.match("Plugin", 21)) { eShapeType = XmlShapeType::DrawPluginShape; }
        else if(aType.match("Applet", 21)) { eShapeType = XmlShapeType::DrawAppletShape; }
        else if(aType.match("MediaShape", 21)) { eShapeType = XmlShapeType::DrawMediaShape; }
        else if(aType.match("TableShape", 21)) { eShapeType = XmlShapeType::DrawTableShape; }

        // 3D shapes
        else if(aType.match("Scene", 21 + 7)) { eShapeType = XmlShapeType::Draw3DSceneObject; }
        else if(aType.match("Cube", 21 + 7)) { eShapeType = XmlShapeType::Draw3DCubeObject; }
        else if(aType.match("Sphere", 21 + 7)) { eShapeType = XmlShapeType::Draw3DSphereObject; }
        else if(aType.match("Lathe", 21 + 7)) { eShapeType = XmlShapeType::Draw3DLatheObject; }
        else if(aType.match("Extrude", 21 + 7)) { eShapeType = XmlShapeType::Draw3DExtrudeObject; }
    }
    else if(aType.match("presentation.", 13))
    {
        // presentation shapes
        if     (aType.match("TitleText", 26)) { eShapeType = XmlShapeType::PresTitleTextShape; }
        else if(aType.match("Outliner", 26)) { eShapeType = XmlShapeType::PresOutlinerShape;  }
        else if(aType.match("Subtitle", 26)) { eShapeType = XmlShapeType::PresSubtitleShape;  }
        else if(aType.match("GraphicObject", 26)) { eShapeType = XmlShapeType::PresGraphicObjectShape;  }
        else if(aType.match("Page", 26)) { eShapeType = XmlShapeType::PresPageShape;  }
        else if(aType.match("OLE2", 26))
        {
            eShapeType = XmlShapeType::PresOLE2Shape;

            // get info about presentation shape
            uno::Reference <beans::XPropertySet> xPropSet(xShape, uno::UNO_QUERY);

            if(xPropSet.is()) try
            {
                OUString sCLSID;
                if(xPropSet->getPropertyValue(u"CLSID"_ustr) >>= sCLSID)
                {
                    if( sCLSID == SvGlobalName( SO3_SC_CLASSID ).GetHexName() )
                    {
                        eShapeType = XmlShapeType::PresSheetShape;
                    }
                }
            }
            catch(const uno::Exception&)
            {
                SAL_WARN( "xmloff""XMLShapeExport::ImpCalcShapeType(), expected ole shape to have the CLSID property?" );
            }
        }
        else if(aType.match("Chart", 26)) { eShapeType = XmlShapeType::PresChartShape;  }
        else if(aType.match("OrgChart", 26)) { eShapeType = XmlShapeType::PresOrgChartShape;  }
        else if(aType.match("CalcShape", 26)) { eShapeType = XmlShapeType::PresSheetShape; }
        else if(aType.match("TableShape", 26)) { eShapeType = XmlShapeType::PresTableShape; }
        else if(aType.match("Notes", 26)) { eShapeType = XmlShapeType::PresNotesShape;  }
        else if(aType.match("HandoutShape", 26)) { eShapeType = XmlShapeType::HandoutShape; }
        else if(aType.match("HeaderShape", 26)) { eShapeType = XmlShapeType::PresHeaderShape; }
        else if(aType.match("FooterShape", 26)) { eShapeType = XmlShapeType::PresFooterShape; }
        else if(aType.match("SlideNumberShape", 26)) { eShapeType = XmlShapeType::PresSlideNumberShape; }
        else if(aType.match("DateTimeShape", 26)) { eShapeType = XmlShapeType::PresDateTimeShape; }
        else if(aType.match("MediaShape", 26)) { eShapeType = XmlShapeType::PresMediaShape; }
    }
}

/** exports all user defined gluepoints */
void XMLShapeExport::ImpExportGluePoints( const uno::Reference< drawing::XShape >& xShape )
{
    uno::Reference< drawing::XGluePointsSupplier > xSupplier( xShape, uno::UNO_QUERY );
    if( !xSupplier.is() )
        return;

    uno::Reference< container::XIdentifierAccess > xGluePoints( xSupplier->getGluePoints(), uno::UNO_QUERY );
    if( !xGluePoints.is() )
        return;

    drawing::GluePoint2 aGluePoint;

    const uno::Sequence< sal_Int32 > aIdSequence( xGluePoints->getIdentifiers() );

    forconst sal_Int32 nIdentifier : aIdSequence )
    {
        if( (xGluePoints->getByIdentifier( nIdentifier ) >>= aGluePoint) && aGluePoint.IsUserDefined )
        {
            // export only user defined gluepoints

            const OUString sId( OUString::number( nIdentifier ) );
            mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_ID, sId );

            mrExport.GetMM100UnitConverter().convertMeasureToXML(msBuffer,
                    aGluePoint.Position.X);
            mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_X, msBuffer.makeStringAndClear());

            mrExport.GetMM100UnitConverter().convertMeasureToXML(msBuffer,
                    aGluePoint.Position.Y);
            mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_Y, msBuffer.makeStringAndClear());

            if( !aGluePoint.IsRelative )
            {
                SvXMLUnitConverter::convertEnum( msBuffer, aGluePoint.PositionAlignment, aXML_GlueAlignment_EnumMap );
                mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_ALIGN, msBuffer.makeStringAndClear() );
            }

            if( aGluePoint.Escape != drawing::EscapeDirection_SMART )
            {
                SvXMLUnitConverter::convertEnum( msBuffer, aGluePoint.Escape, aXML_GlueEscapeDirection_EnumMap );
                mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_ESCAPE_DIRECTION, msBuffer.makeStringAndClear() );
            }

            SvXMLElementExport aEventsElemt(mrExport, XML_NAMESPACE_DRAW, XML_GLUE_POINT, truetrue);
        }
    }
}

void XMLShapeExport::ImpExportSignatureLine(const uno::Reference<drawing::XShape>&&nbsp;xShape)
{
    uno::Reference<beans::XPropertySet> xPropSet(xShape, uno::UNO_QUERY);

    bool bIsSignatureLine = false;
    xPropSet->getPropertyValue(u"IsSignatureLine"_ustr) >>= bIsSignatureLine;
    if (!bIsSignatureLine)
        return;

    OUString aSignatureLineId;
    xPropSet->getPropertyValue(u"SignatureLineId"_ustr) >>= aSignatureLineId;
    mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_ID, aSignatureLineId);

    OUString aSuggestedSignerName;
    xPropSet->getPropertyValue(u"SignatureLineSuggestedSignerName"_ustr) >>= aSuggestedSignerName;
    if (!aSuggestedSignerName.isEmpty())
        mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_SUGGESTED_SIGNER_NAME, aSuggestedSignerName);

    OUString aSuggestedSignerTitle;
    xPropSet->getPropertyValue(u"SignatureLineSuggestedSignerTitle"_ustr) >>= aSuggestedSignerTitle;
    if (!aSuggestedSignerTitle.isEmpty())
        mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_SUGGESTED_SIGNER_TITLE, aSuggestedSignerTitle);

    OUString aSuggestedSignerEmail;
    xPropSet->getPropertyValue(u"SignatureLineSuggestedSignerEmail"_ustr) >>= aSuggestedSignerEmail;
    if (!aSuggestedSignerEmail.isEmpty())
        mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_SUGGESTED_SIGNER_EMAIL, aSuggestedSignerEmail);

    OUString aSigningInstructions;
    xPropSet->getPropertyValue(u"SignatureLineSigningInstructions"_ustr) >>= aSigningInstructions;
    if (!aSigningInstructions.isEmpty())
        mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_SIGNING_INSTRUCTIONS, aSigningInstructions);

    bool bShowSignDate = false;
    xPropSet->getPropertyValue(u"SignatureLineShowSignDate"_ustr) >>= bShowSignDate;
    mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_SHOW_SIGN_DATE,
                          bShowSignDate ? XML_TRUE : XML_FALSE);

    bool bCanAddComment = false;
    xPropSet->getPropertyValue(u"SignatureLineCanAddComment"_ustr) >>= bCanAddComment;
    mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_CAN_ADD_COMMENT,
                          bCanAddComment ? XML_TRUE : XML_FALSE);

    SvXMLElementExport aSignatureLineElement(mrExport, XML_NAMESPACE_LO_EXT, XML_SIGNATURELINE, true,
                                             true);
}

void XMLShapeExport::ImpExportQRCode(const uno::Reference<drawing::XShape>& xShape)
{
    uno::Reference<beans::XPropertySet> xPropSet(xShape, uno::UNO_QUERY);

    uno::Any aAny = xPropSet->getPropertyValue(u"BarCodeProperties"_ustr);

    css::drawing::BarCode aBarCode;
    if(!(aAny >>= aBarCode))
        return;

    mrExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_STRING_VALUE, aBarCode.Payload);
    /* Export QR Code as per customised schema, @see OpenDocument-schema-v1.3+libreoffice */
    OUString temp;
    switch(aBarCode.ErrorCorrection){
        case css::drawing::BarCodeErrorCorrection::LOW :
            temp = "low";
            break;
        case css::drawing::BarCodeErrorCorrection::MEDIUM:
            temp = "medium";
            break;
        case css::drawing::BarCodeErrorCorrection::QUARTILE:
            temp = "quartile";
            break;
        case css::drawing::BarCodeErrorCorrection::HIGH:
            temp = "high";
            break;
    }
    mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_QRCODE_ERROR_CORRECTION, temp);
    mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_QRCODE_BORDER, OUStringBuffer(20).append(aBarCode.Border).makeStringAndClear());
    mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_QRCODE_TYPE, OUStringBuffer(20).append(aBarCode.Type).makeStringAndClear());

    SvXMLElementExport aBarCodeElement(mrExport, XML_NAMESPACE_LO_EXT, XML_QRCODE, true,
                                            true);
}

void XMLShapeExport::ExportGraphicDefaults()
{
    rtl::Reference<XMLStyleExport> aStEx(new XMLStyleExport(mrExport, mrExport.GetAutoStylePool().get()));

    // construct PropertySetMapper
    rtl::Reference< SvXMLExportPropertyMapper > xPropertySetMapper( CreateShapePropMapper( mrExport ) );
    static_cast<XMLShapeExportPropertyMapper*>(xPropertySetMapper.get())->SetAutoStylesfalse );

    // chain text attributes
    xPropertySetMapper->ChainExportMapper(XMLTextParagraphExport::CreateParaExtPropMapper(mrExport));

    // chain special Writer/text frame default attributes
    xPropertySetMapper->ChainExportMapper(XMLTextParagraphExport::CreateParaDefaultExtPropMapper(mrExport));

    // write graphic family default style
    uno::Reference< lang::XMultiServiceFactory > xFact( mrExport.GetModel(), uno::UNO_QUERY );
    if( !xFact.is() )
        return;

    try
    {
        uno::Reference< beans::XPropertySet > xDefaults( xFact->createInstance(u"com.sun.star.drawing.Defaults"_ustr), uno::UNO_QUERY );
        if( xDefaults.is() )
        {
            aStEx->exportDefaultStyle( xDefaults, XML_STYLE_FAMILY_SD_GRAPHICS_NAME, xPropertySetMapper );

            // write graphic styles (family name differs depending on the module)
            aStEx->exportStyleFamily(u"graphics"_ustr, XML_STYLE_FAMILY_SD_GRAPHICS_NAME, xPropertySetMapper, false, XmlStyleFamily::SD_GRAPHICS_ID);
            aStEx->exportStyleFamily(u"GraphicStyles"_ustr, XML_STYLE_FAMILY_SD_GRAPHICS_NAME, xPropertySetMapper, false, XmlStyleFamily::SD_GRAPHICS_ID);
        }
    }
    catch(const lang::ServiceNotRegisteredException&)
    {
    }
}

void XMLShapeExport::onExport( const css::uno::Reference < css::drawing::XShape >& )
{
}

const rtl::Reference< XMLTableExport >& XMLShapeExport::GetShapeTableExport()
{
    if( !mxShapeTableExport.is() )
    {
        rtl::Reference< XMLPropertyHandlerFactory > xFactory( new XMLSdPropHdlFactory( mrExport.GetModel(), mrExport ) );
        rtl::Reference < XMLPropertySetMapper > xMapper( new XMLShapePropertySetMapper( xFactory, true ) );
        mrExport.GetTextParagraphExport(); // get or create text paragraph export
        rtl::Reference< SvXMLExportPropertyMapper > xPropertySetMapper( new XMLShapeExportPropertyMapper( xMapper, mrExport ) );
        mxShapeTableExport = new XMLTableExport( mrExport, xPropertySetMapper, xFactory );
    }

    return mxShapeTableExport;
}

void XMLShapeExport::ImpExportNewTrans(const uno::Reference< beans::XPropertySet >& ;xPropSet,
    XMLShapeExportFlags nFeatures, awt::Point* pRefPoint)
{
    // get matrix
    ::basegfx::B2DHomMatrix aMatrix;
    ImpExportNewTrans_GetB2DHomMatrix(aMatrix, xPropSet);

    // decompose and correct about pRefPoint
    ::basegfx::B2DTuple aTRScale;
    double fTRShear(0.0);
    double fTRRotate(0.0);
    ::basegfx::B2DTuple aTRTranslate;
    ImpExportNewTrans_DecomposeAndRefPoint(aMatrix, aTRScale, fTRShear, fTRRotate, aTRTranslate, pRefPoint);

    // use features and write
    ImpExportNewTrans_FeaturesAndWrite(aTRScale, fTRShear, fTRRotate, aTRTranslate, nFeatures);
}

void XMLShapeExport::ImpExportNewTrans_GetB2DHomMatrix(::basegfx::B2DHomMatrix&&nbsp;rMatrix,
    const uno::Reference< beans::XPropertySet >& xPropSet)
{
    /* Get <TransformationInHoriL2R>, if it exist
       and if the document is exported into the OpenOffice.org file format.
       This property only exists at service css::text::Shape - the
       Writer UNO service for shapes.
       This code is needed, because the positioning attributes in the
       OpenOffice.org file format are given in horizontal left-to-right layout
       regardless the layout direction the shape is in. In the OASIS Open Office
       file format the positioning attributes are correctly given in the layout
       direction the shape is in. Thus, this code provides the conversion from
       the OASIS Open Office file format to the OpenOffice.org file format. (#i28749#)
    */

    uno::Any aAny;
    if ( !( GetExport().getExportFlags() & SvXMLExportFlags::OASIS ) &&
         xPropSet->getPropertySetInfo()->hasPropertyByName(u"TransformationInHoriL2R"_ustr) )
    {
        aAny = xPropSet->getPropertyValue(u"TransformationInHoriL2R"_ustr);
    }
    else
    {
        aAny = xPropSet->getPropertyValue(u"Transformation"_ustr);
    }
    drawing::HomogenMatrix3 aMatrix;
    aAny >>= aMatrix;

    rMatrix.set(0, 0, aMatrix.Line1.Column1);
    rMatrix.set(0, 1, aMatrix.Line1.Column2);
    rMatrix.set(0, 2, aMatrix.Line1.Column3);
    rMatrix.set(1, 0, aMatrix.Line2.Column1);
    rMatrix.set(1, 1, aMatrix.Line2.Column2);
    rMatrix.set(1, 2, aMatrix.Line2.Column3);
    // For this to be a valid 2D transform matrix, the last row must be [0,0,1]
    assert( aMatrix.Line3.Column1 == 0 );
    assert( aMatrix.Line3.Column2 == 0 );
    assert( aMatrix.Line3.Column3 == 1 );
}

void XMLShapeExport::ImpExportNewTrans_DecomposeAndRefPoint(const ::basegfx::B2DHomMatrix& rMatrix, ::basegfx::B2DTuple& rTRScale,
    double& fTRShear, double& fTRRotate, ::basegfx::B2DTuple& rTRTranslate, css::awt::Point* pRefPoint)
{
    // decompose matrix
    rMatrix.decompose(rTRScale, rTRTranslate, fTRRotate, fTRShear);

    // correct translation about pRefPoint
    if(pRefPoint)
    {
        rTRTranslate -= ::basegfx::B2DTuple(pRefPoint->X, pRefPoint->Y);
    }
}

void XMLShapeExport::ImpExportNewTrans_FeaturesAndWrite(::basegfx::B2DTuple const &&nbsp;rTRScale, double fTRShear,
    double fTRRotate, ::basegfx::B2DTuple const & rTRTranslate, const XMLShapeExportFlags nFeatures)
{
    // always write Size (rTRScale) since this statement carries the union
    // of the object
    OUString aStr;
    OUStringBuffer sStringBuffer;
    ::basegfx::B2DTuple aTRScale(rTRScale);

    // svg: width
    if(!(nFeatures & XMLShapeExportFlags::WIDTH))
    {
        aTRScale.setX(1.0);
    }
    else
    {
        if( aTRScale.getX() > 0.0 )
            aTRScale.setX(aTRScale.getX() - 1.0);
        else if( aTRScale.getX() < 0.0 )
            aTRScale.setX(aTRScale.getX() + 1.0);
    }

    mrExport.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer,
                                                         basegfx::fround(aTRScale.getX()));
    aStr = sStringBuffer.makeStringAndClear();
    mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_WIDTH, aStr);

    // svg: height
    if(!(nFeatures & XMLShapeExportFlags::HEIGHT))
    {
        aTRScale.setY(1.0);
    }
    else
    {
        if( aTRScale.getY() > 0.0 )
            aTRScale.setY(aTRScale.getY() - 1.0);
        else if( aTRScale.getY() < 0.0 )
            aTRScale.setY(aTRScale.getY() + 1.0);
    }

    mrExport.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer,
                                                         basegfx::fround(aTRScale.getY()));
    aStr = sStringBuffer.makeStringAndClear();
    mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_HEIGHT, aStr);

    // decide if transformation is necessary
    bool bTransformationIsNecessary(fTRShear != 0.0 || fTRRotate != 0.0);

    if(bTransformationIsNecessary)
    {
        // write transformation, but WITHOUT scale which is exported as size above
        SdXMLImExTransform2D aTransform;

        aTransform.AddSkewX(atan(fTRShear));

        // #i78696#
        // fTRRotate is mathematically correct, but due to the error
        // we export/import it mirrored. Since the API implementation is fixed and
        // uses the correctly oriented angle, it is necessary for compatibility to
        // mirror the angle here to stay at the old behaviour. There is a follow-up
        // task (#i78698#) to fix this in the next ODF FileFormat version
        aTransform.AddRotate(-fTRRotate);

        aTransform.AddTranslate(rTRTranslate);

        // does transformation need to be exported?
        if(aTransform.NeedsAction())
            mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_TRANSFORM, aTransform.GetExportString(mrExport.GetMM100UnitConverter()));
    }
    else
    {
        // no shear, no rotate; just add object position to export and we are done
        if(nFeatures & XMLShapeExportFlags::X)
        {
            // svg: x
            mrExport.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer,
                    basegfx::fround(rTRTranslate.getX()));
            aStr = sStringBuffer.makeStringAndClear();
            mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_X, aStr);
        }

        if(nFeatures & XMLShapeExportFlags::Y)
        {
            // svg: y
            mrExport.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer,
                    basegfx::fround(rTRTranslate.getY()));
            aStr = sStringBuffer.makeStringAndClear();
            mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_Y, aStr);
        }
    }
}

bool XMLShapeExport::ImpExportPresentationAttributes( const uno::Reference< beans::XPropertySet >& xPropSet, const OUString& rClass )
{
--> --------------------

--> maximum size reached

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

Messung V0.5
C=87 H=97 G=91

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