summaryrefslogtreecommitdiffstats
path: root/xmloff/source/draw/shapeimport.cxx
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--xmloff/source/draw/shapeimport.cxx1138
1 files changed, 1138 insertions, 0 deletions
diff --git a/xmloff/source/draw/shapeimport.cxx b/xmloff/source/draw/shapeimport.cxx
new file mode 100644
index 000000000..856635c09
--- /dev/null
+++ b/xmloff/source/draw/shapeimport.cxx
@@ -0,0 +1,1138 @@
+/* -*- 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 <tools/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <sal/log.hxx>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/text/PositionLayoutDir.hpp>
+#include <com/sun/star/drawing/XShapes3.hpp>
+
+#include <utility>
+#include <xmloff/unointerfacetouniqueidentifiermapper.hxx>
+
+#include <xmloff/shapeimport.hxx>
+#include <xmloff/xmlstyle.hxx>
+#include <xmloff/xmltkmap.hxx>
+#include <xmloff/xmlnmspe.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/table/XMLTableImport.hxx>
+#include <xmloff/attrlist.hxx>
+#include "eventimp.hxx"
+#include "ximpshap.hxx"
+#include "sdpropls.hxx"
+#include <xmloff/xmlprmap.hxx>
+#include "ximp3dscene.hxx"
+#include "ximp3dobject.hxx"
+#include "ximpgrp.hxx"
+#include "ximplink.hxx"
+
+#include <map>
+#include <vector>
+
+namespace {
+
+class ShapeGroupContext;
+
+}
+
+using namespace ::std;
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+
+namespace {
+
+struct ConnectionHint
+{
+ css::uno::Reference< css::drawing::XShape > mxConnector;
+ bool bStart;
+ OUString aDestShapeId;
+ sal_Int32 nDestGlueId;
+};
+
+struct XShapeCompareHelper
+{
+ bool operator()(const css::uno::Reference < css::drawing::XShape >& x1,
+ const css::uno::Reference < css::drawing::XShape >& x2 ) const
+ {
+ return x1.get() < x2.get();
+ }
+};
+
+}
+
+/** this map store all glue point id mappings for shapes that had user defined glue points. This
+ is needed because on insertion the glue points will get a new and unique id */
+typedef std::map<sal_Int32,sal_Int32> GluePointIdMap;
+typedef std::map< css::uno::Reference < css::drawing::XShape >, GluePointIdMap, XShapeCompareHelper > ShapeGluePointsMap;
+
+/** this struct is created for each startPage() call and stores information that is needed during
+ import of shapes for one page. Since pages could be nested ( notes pages inside impress ) there
+ is a pointer so one can build up a stack of this structs */
+struct XMLShapeImportPageContextImpl
+{
+ ShapeGluePointsMap maShapeGluePointsMap;
+
+ uno::Reference < drawing::XShapes > mxShapes;
+
+ std::shared_ptr<XMLShapeImportPageContextImpl> mpNext;
+};
+
+/** this class is to enable adding members to the XMLShapeImportHelper without getting incompatible */
+struct XMLShapeImportHelperImpl
+{
+ // context for sorting shapes
+ std::shared_ptr<ShapeGroupContext> mpGroupContext;
+
+ std::vector<ConnectionHint> maConnections;
+
+ // #88546# possibility to switch progress bar handling on/off
+ bool mbHandleProgressBar;
+
+ // stores the capability of the current model to create presentation shapes
+ bool mbIsPresentationShapesSupported;
+};
+
+static const OUStringLiteral gsStartShape("StartShape");
+static const OUStringLiteral gsEndShape("EndShape");
+static const OUStringLiteral gsStartGluePointIndex("StartGluePointIndex");
+static const OUStringLiteral gsEndGluePointIndex("EndGluePointIndex");
+
+XMLShapeImportHelper::XMLShapeImportHelper(
+ SvXMLImport& rImporter,
+ const uno::Reference< frame::XModel>& rModel,
+ SvXMLImportPropertyMapper *pExtMapper )
+: mpImpl( new XMLShapeImportHelperImpl ),
+ mrImporter( rImporter )
+{
+ mpImpl->mpGroupContext = nullptr;
+
+ // #88546# init to sal_False
+ mpImpl->mbHandleProgressBar = false;
+
+ mpSdPropHdlFactory = new XMLSdPropHdlFactory( rModel, rImporter );
+
+ // construct PropertySetMapper
+ rtl::Reference < XMLPropertySetMapper > xMapper = new XMLShapePropertySetMapper(mpSdPropHdlFactory.get(), false);
+ mpPropertySetMapper = new SvXMLImportPropertyMapper( xMapper, rImporter );
+
+ if( pExtMapper )
+ {
+ rtl::Reference < SvXMLImportPropertyMapper > xExtMapper( pExtMapper );
+ mpPropertySetMapper->ChainImportMapper( xExtMapper );
+ }
+
+ // chain text attributes
+ mpPropertySetMapper->ChainImportMapper(XMLTextImportHelper::CreateParaExtPropMapper(rImporter));
+ mpPropertySetMapper->ChainImportMapper(XMLTextImportHelper::CreateParaDefaultExtPropMapper(rImporter));
+
+ // construct PresPagePropsMapper
+ xMapper = new XMLPropertySetMapper(aXMLSDPresPageProps, mpSdPropHdlFactory.get(), false);
+ mpPresPagePropsMapper = new SvXMLImportPropertyMapper( xMapper, rImporter );
+
+ uno::Reference< lang::XServiceInfo > xInfo( rImporter.GetModel(), uno::UNO_QUERY );
+ const OUString aSName( "com.sun.star.presentation.PresentationDocument" );
+ mpImpl->mbIsPresentationShapesSupported = xInfo.is() && xInfo->supportsService( aSName );
+}
+
+XMLShapeImportHelper::~XMLShapeImportHelper()
+{
+ SAL_WARN_IF( !mpImpl->maConnections.empty(), "xmloff", "XMLShapeImportHelper::restoreConnections() was not called!" );
+
+ // cleanup factory, decrease refcount. Should lead to destruction.
+ mpSdPropHdlFactory.clear();
+
+ // cleanup mapper, decrease refcount. Should lead to destruction.
+ mpPropertySetMapper.clear();
+
+ // cleanup presPage mapper, decrease refcount. Should lead to destruction.
+ mpPresPagePropsMapper.clear();
+
+ // Styles or AutoStyles context?
+ if(mxStylesContext.is())
+ mxStylesContext->Clear();
+
+ if(mxAutoStylesContext.is())
+ mxAutoStylesContext->Clear();
+}
+
+const SvXMLTokenMap& XMLShapeImportHelper::GetGroupShapeElemTokenMap()
+{
+ if(!mpGroupShapeElemTokenMap)
+ {
+ static const SvXMLTokenMapEntry aGroupShapeElemTokenMap[] =
+ {
+ { XML_NAMESPACE_DRAW, XML_G, XML_TOK_GROUP_GROUP },
+ { XML_NAMESPACE_DRAW, XML_RECT, XML_TOK_GROUP_RECT },
+ { XML_NAMESPACE_DRAW, XML_LINE, XML_TOK_GROUP_LINE },
+ { XML_NAMESPACE_DRAW, XML_CIRCLE, XML_TOK_GROUP_CIRCLE },
+ { XML_NAMESPACE_DRAW, XML_ELLIPSE, XML_TOK_GROUP_ELLIPSE },
+ { XML_NAMESPACE_DRAW, XML_POLYGON, XML_TOK_GROUP_POLYGON },
+ { XML_NAMESPACE_DRAW, XML_POLYLINE, XML_TOK_GROUP_POLYLINE },
+ { XML_NAMESPACE_DRAW, XML_PATH, XML_TOK_GROUP_PATH },
+
+ { XML_NAMESPACE_DRAW, XML_CONTROL, XML_TOK_GROUP_CONTROL },
+ { XML_NAMESPACE_DRAW, XML_CONNECTOR, XML_TOK_GROUP_CONNECTOR },
+ { XML_NAMESPACE_DRAW, XML_MEASURE, XML_TOK_GROUP_MEASURE },
+ { XML_NAMESPACE_DRAW, XML_PAGE_THUMBNAIL, XML_TOK_GROUP_PAGE },
+ { XML_NAMESPACE_DRAW, XML_CAPTION, XML_TOK_GROUP_CAPTION },
+
+ { XML_NAMESPACE_CHART, XML_CHART, XML_TOK_GROUP_CHART },
+ { XML_NAMESPACE_DR3D, XML_SCENE, XML_TOK_GROUP_3DSCENE },
+
+ { XML_NAMESPACE_DRAW, XML_FRAME, XML_TOK_GROUP_FRAME },
+
+ { XML_NAMESPACE_DRAW, XML_CUSTOM_SHAPE, XML_TOK_GROUP_CUSTOM_SHAPE },
+ { XML_NAMESPACE_OFFICE, XML_ANNOTATION, XML_TOK_GROUP_ANNOTATION },
+ { XML_NAMESPACE_DRAW, XML_A, XML_TOK_GROUP_A },
+
+ XML_TOKEN_MAP_END
+ };
+
+ mpGroupShapeElemTokenMap = std::make_unique<SvXMLTokenMap>(aGroupShapeElemTokenMap);
+ }
+
+ return *mpGroupShapeElemTokenMap;
+}
+
+const SvXMLTokenMap& XMLShapeImportHelper::GetFrameShapeElemTokenMap()
+{
+ if(!mpFrameShapeElemTokenMap)
+ {
+ static const SvXMLTokenMapEntry aFrameShapeElemTokenMap[] =
+ {
+ { XML_NAMESPACE_DRAW, XML_TEXT_BOX, XML_TOK_FRAME_TEXT_BOX },
+ { XML_NAMESPACE_DRAW, XML_IMAGE, XML_TOK_FRAME_IMAGE },
+ { XML_NAMESPACE_DRAW, XML_OBJECT, XML_TOK_FRAME_OBJECT },
+ { XML_NAMESPACE_DRAW, XML_OBJECT_OLE, XML_TOK_FRAME_OBJECT_OLE },
+ { XML_NAMESPACE_DRAW, XML_PLUGIN, XML_TOK_FRAME_PLUGIN },
+ { XML_NAMESPACE_DRAW, XML_FLOATING_FRAME, XML_TOK_FRAME_FLOATING_FRAME},
+ { XML_NAMESPACE_DRAW, XML_APPLET, XML_TOK_FRAME_APPLET },
+ { XML_NAMESPACE_TABLE, XML_TABLE, XML_TOK_FRAME_TABLE },
+ XML_TOKEN_MAP_END
+ };
+
+ mpFrameShapeElemTokenMap = std::make_unique<SvXMLTokenMap>(aFrameShapeElemTokenMap);
+ }
+
+ return *mpFrameShapeElemTokenMap;
+}
+
+const SvXMLTokenMap& XMLShapeImportHelper::Get3DSceneShapeElemTokenMap()
+{
+ if(!mp3DSceneShapeElemTokenMap)
+ {
+ static const SvXMLTokenMapEntry a3DSceneShapeElemTokenMap[] =
+ {
+ { XML_NAMESPACE_DR3D, XML_SCENE, XML_TOK_3DSCENE_3DSCENE },
+ { XML_NAMESPACE_DR3D, XML_CUBE, XML_TOK_3DSCENE_3DCUBE },
+ { XML_NAMESPACE_DR3D, XML_SPHERE, XML_TOK_3DSCENE_3DSPHERE },
+ { XML_NAMESPACE_DR3D, XML_ROTATE, XML_TOK_3DSCENE_3DLATHE },
+ { XML_NAMESPACE_DR3D, XML_EXTRUDE, XML_TOK_3DSCENE_3DEXTRUDE },
+ XML_TOKEN_MAP_END
+ };
+
+ mp3DSceneShapeElemTokenMap = std::make_unique<SvXMLTokenMap>(a3DSceneShapeElemTokenMap);
+ }
+
+ return *mp3DSceneShapeElemTokenMap;
+}
+
+const SvXMLTokenMap& XMLShapeImportHelper::Get3DObjectAttrTokenMap()
+{
+ if(!mp3DObjectAttrTokenMap)
+ {
+ static const SvXMLTokenMapEntry a3DObjectAttrTokenMap[] =
+ {
+ { XML_NAMESPACE_DRAW, XML_STYLE_NAME, XML_TOK_3DOBJECT_DRAWSTYLE_NAME },
+ { XML_NAMESPACE_DR3D, XML_TRANSFORM, XML_TOK_3DOBJECT_TRANSFORM },
+ XML_TOKEN_MAP_END
+ };
+
+ mp3DObjectAttrTokenMap = std::make_unique<SvXMLTokenMap>(a3DObjectAttrTokenMap);
+ }
+
+ return *mp3DObjectAttrTokenMap;
+}
+
+const SvXMLTokenMap& XMLShapeImportHelper::Get3DPolygonBasedAttrTokenMap()
+{
+ if(!mp3DPolygonBasedAttrTokenMap)
+ {
+ static const SvXMLTokenMapEntry a3DPolygonBasedAttrTokenMap[] =
+ {
+ { XML_NAMESPACE_SVG, XML_VIEWBOX, XML_TOK_3DPOLYGONBASED_VIEWBOX },
+ { XML_NAMESPACE_SVG, XML_D, XML_TOK_3DPOLYGONBASED_D },
+ XML_TOKEN_MAP_END
+ };
+
+ mp3DPolygonBasedAttrTokenMap = std::make_unique<SvXMLTokenMap>(a3DPolygonBasedAttrTokenMap);
+ }
+
+ return *mp3DPolygonBasedAttrTokenMap;
+}
+
+const SvXMLTokenMap& XMLShapeImportHelper::Get3DCubeObjectAttrTokenMap()
+{
+ if(!mp3DCubeObjectAttrTokenMap)
+ {
+ static const SvXMLTokenMapEntry a3DCubeObjectAttrTokenMap[] =
+ {
+ { XML_NAMESPACE_DR3D, XML_MIN_EDGE, XML_TOK_3DCUBEOBJ_MINEDGE },
+ { XML_NAMESPACE_DR3D, XML_MAX_EDGE, XML_TOK_3DCUBEOBJ_MAXEDGE },
+ XML_TOKEN_MAP_END
+ };
+
+ mp3DCubeObjectAttrTokenMap = std::make_unique<SvXMLTokenMap>(a3DCubeObjectAttrTokenMap);
+ }
+
+ return *mp3DCubeObjectAttrTokenMap;
+}
+
+const SvXMLTokenMap& XMLShapeImportHelper::Get3DSphereObjectAttrTokenMap()
+{
+ if(!mp3DSphereObjectAttrTokenMap)
+ {
+ static const SvXMLTokenMapEntry a3DSphereObjectAttrTokenMap[] =
+ {
+ { XML_NAMESPACE_DR3D, XML_CENTER, XML_TOK_3DSPHEREOBJ_CENTER },
+ { XML_NAMESPACE_DR3D, XML_SIZE, XML_TOK_3DSPHEREOBJ_SIZE },
+ XML_TOKEN_MAP_END
+ };
+
+ mp3DSphereObjectAttrTokenMap = std::make_unique<SvXMLTokenMap>(a3DSphereObjectAttrTokenMap);
+ }
+
+ return *mp3DSphereObjectAttrTokenMap;
+}
+
+const SvXMLTokenMap& XMLShapeImportHelper::Get3DLightAttrTokenMap()
+{
+ if(!mp3DLightAttrTokenMap)
+ {
+ static const SvXMLTokenMapEntry a3DLightAttrTokenMap[] =
+ {
+ { XML_NAMESPACE_DR3D, XML_DIFFUSE_COLOR, XML_TOK_3DLIGHT_DIFFUSE_COLOR },
+ { XML_NAMESPACE_DR3D, XML_DIRECTION, XML_TOK_3DLIGHT_DIRECTION },
+ { XML_NAMESPACE_DR3D, XML_ENABLED, XML_TOK_3DLIGHT_ENABLED },
+ { XML_NAMESPACE_DR3D, XML_SPECULAR, XML_TOK_3DLIGHT_SPECULAR },
+ XML_TOKEN_MAP_END
+ };
+
+ mp3DLightAttrTokenMap = std::make_unique<SvXMLTokenMap>(a3DLightAttrTokenMap);
+ }
+
+ return *mp3DLightAttrTokenMap;
+}
+
+SvXMLShapeContext* XMLShapeImportHelper::Create3DSceneChildContext(
+ SvXMLImport& rImport,
+ sal_uInt16 p_nPrefix,
+ const OUString& rLocalName,
+ const uno::Reference< xml::sax::XAttributeList>& xAttrList,
+ uno::Reference< drawing::XShapes > const & rShapes)
+{
+ SdXMLShapeContext *pContext = nullptr;
+
+ if(rShapes.is())
+ {
+ const SvXMLTokenMap& rTokenMap = Get3DSceneShapeElemTokenMap();
+ switch(rTokenMap.Get(p_nPrefix, rLocalName))
+ {
+ case XML_TOK_3DSCENE_3DSCENE:
+ {
+ // dr3d:3dscene inside dr3d:3dscene context
+ pContext = new SdXML3DSceneShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, false);
+ break;
+ }
+ case XML_TOK_3DSCENE_3DCUBE:
+ {
+ // dr3d:3dcube inside dr3d:3dscene context
+ pContext = new SdXML3DCubeObjectShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes);
+ break;
+ }
+ case XML_TOK_3DSCENE_3DSPHERE:
+ {
+ // dr3d:3dsphere inside dr3d:3dscene context
+ pContext = new SdXML3DSphereObjectShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes);
+ break;
+ }
+ case XML_TOK_3DSCENE_3DLATHE:
+ {
+ // dr3d:3dlathe inside dr3d:3dscene context
+ pContext = new SdXML3DLatheObjectShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes);
+ break;
+ }
+ case XML_TOK_3DSCENE_3DEXTRUDE:
+ {
+ // dr3d:3dextrude inside dr3d:3dscene context
+ pContext = new SdXML3DExtrudeObjectShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes);
+ break;
+ }
+ }
+ }
+
+ if (!pContext)
+ return nullptr;
+
+ // now parse the attribute list and call the child context for each unknown attribute
+ sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
+ for(sal_Int16 a(0); a < nAttrCount; a++)
+ {
+ const OUString& rAttrName = xAttrList->getNameByIndex(a);
+ OUString aLocalName;
+ sal_uInt16 nPrefix = rImport.GetNamespaceMap().GetKeyByAttrName(rAttrName, &aLocalName);
+ const OUString aValue( xAttrList->getValueByIndex(a) );
+
+ pContext->processAttribute( nPrefix, aLocalName, aValue );
+ }
+
+ return pContext;
+}
+
+void XMLShapeImportHelper::SetStylesContext(SvXMLStylesContext* pNew)
+{
+ mxStylesContext.set(pNew);
+}
+
+void XMLShapeImportHelper::SetAutoStylesContext(SvXMLStylesContext* pNew)
+{
+ mxAutoStylesContext.set(pNew);
+}
+
+SvXMLShapeContext* XMLShapeImportHelper::CreateGroupChildContext(
+ SvXMLImport& rImport,
+ sal_uInt16 p_nPrefix,
+ const OUString& rLocalName,
+ const uno::Reference< xml::sax::XAttributeList>& xAttrList,
+ uno::Reference< drawing::XShapes > const & rShapes,
+ bool bTemporaryShape)
+{
+ SdXMLShapeContext *pContext = nullptr;
+
+ const SvXMLTokenMap& rTokenMap = GetGroupShapeElemTokenMap();
+ sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
+
+ switch(rTokenMap.Get(p_nPrefix, rLocalName))
+ {
+ case XML_TOK_GROUP_GROUP:
+ {
+ // draw:g inside group context (RECURSIVE)
+ pContext = new SdXMLGroupShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, bTemporaryShape);
+ break;
+ }
+ case XML_TOK_GROUP_3DSCENE:
+ {
+ // dr3d:3dscene inside group context
+ pContext = new SdXML3DSceneShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, bTemporaryShape);
+ break;
+ }
+ case XML_TOK_GROUP_RECT:
+ {
+ // draw:rect inside group context
+ pContext = new SdXMLRectShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, bTemporaryShape );
+ break;
+ }
+ case XML_TOK_GROUP_LINE:
+ {
+ // draw:line inside group context
+ pContext = new SdXMLLineShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, bTemporaryShape );
+ break;
+ }
+ case XML_TOK_GROUP_CIRCLE:
+ case XML_TOK_GROUP_ELLIPSE:
+ {
+ // draw:circle or draw:ellipse inside group context
+ pContext = new SdXMLEllipseShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, bTemporaryShape );
+ break;
+ }
+ case XML_TOK_GROUP_POLYGON:
+ case XML_TOK_GROUP_POLYLINE:
+ {
+ // draw:polygon or draw:polyline inside group context
+ pContext = new SdXMLPolygonShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes,
+ rTokenMap.Get(p_nPrefix, rLocalName) == XML_TOK_GROUP_POLYGON, bTemporaryShape );
+ break;
+ }
+ case XML_TOK_GROUP_PATH:
+ {
+ // draw:path inside group context
+ pContext = new SdXMLPathShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, bTemporaryShape);
+ break;
+ }
+ case XML_TOK_GROUP_FRAME:
+ {
+ // text:text-box inside group context
+ pContext = new SdXMLFrameShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, bTemporaryShape );
+ break;
+ }
+ case XML_TOK_GROUP_CONTROL:
+ {
+ // draw:control inside group context
+ pContext = new SdXMLControlShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, bTemporaryShape );
+ break;
+ }
+ case XML_TOK_GROUP_CONNECTOR:
+ {
+ // draw:connector inside group context
+ pContext = new SdXMLConnectorShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, bTemporaryShape );
+ break;
+ }
+ case XML_TOK_GROUP_MEASURE:
+ {
+ // draw:measure inside group context
+ pContext = new SdXMLMeasureShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, bTemporaryShape );
+ break;
+ }
+ case XML_TOK_GROUP_PAGE:
+ {
+ // draw:page inside group context
+ pContext = new SdXMLPageShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, bTemporaryShape );
+ break;
+ }
+ case XML_TOK_GROUP_CAPTION:
+ case XML_TOK_GROUP_ANNOTATION:
+ {
+ // draw:caption inside group context
+ pContext = new SdXMLCaptionShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, bTemporaryShape );
+ break;
+ }
+ case XML_TOK_GROUP_CHART:
+ {
+ // chart:chart inside group context
+ pContext = new SdXMLChartShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes, bTemporaryShape );
+ break;
+ }
+ case XML_TOK_GROUP_CUSTOM_SHAPE:
+ {
+ // draw:customshape
+ pContext = new SdXMLCustomShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes );
+ break;
+ }
+ case XML_TOK_GROUP_A:
+ {
+ return new SdXMLShapeLinkContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes );
+ }
+ // add other shapes here...
+ default:
+ return new SvXMLShapeContext( rImport, p_nPrefix, rLocalName, bTemporaryShape );
+ }
+
+ // now parse the attribute list and call the child context for each unknown attribute
+ for(sal_Int16 a(0); a < nAttrCount; a++)
+ {
+ const OUString& rAttrName = xAttrList->getNameByIndex(a);
+ OUString aLocalName;
+ sal_uInt16 nPrefix = rImport.GetNamespaceMap().GetKeyByAttrName(rAttrName, &aLocalName);
+ const OUString aValue( xAttrList->getValueByIndex(a) );
+
+ pContext->processAttribute( nPrefix, aLocalName, aValue );
+ }
+
+ return pContext;
+}
+
+// This method is called from SdXMLFrameShapeContext to create children of draw:frame
+SvXMLShapeContext* XMLShapeImportHelper::CreateFrameChildContext(
+ SvXMLImport& rImport,
+ sal_uInt16 p_nPrefix,
+ const OUString& rLocalName,
+ const uno::Reference< xml::sax::XAttributeList>& rAttrList,
+ uno::Reference< drawing::XShapes > const & rShapes,
+ const uno::Reference< xml::sax::XAttributeList>& rFrameAttrList)
+{
+ SdXMLShapeContext *pContext = nullptr;
+
+ const SvXMLTokenMap& rTokenMap = GetFrameShapeElemTokenMap();
+
+ SvXMLAttributeList *pAttrList = new SvXMLAttributeList( rAttrList );
+ if( rFrameAttrList.is() )
+ pAttrList->AppendAttributeList( rFrameAttrList );
+ uno::Reference < xml::sax::XAttributeList > xAttrList = pAttrList;
+
+ switch(rTokenMap.Get(p_nPrefix, rLocalName))
+ {
+ case XML_TOK_FRAME_TEXT_BOX:
+ {
+ // text:text-box inside group context
+ pContext = new SdXMLTextBoxShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes );
+ break;
+ }
+ case XML_TOK_FRAME_IMAGE:
+ {
+ // office:image inside group context
+ pContext = new SdXMLGraphicObjectShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes );
+ break;
+ }
+ case XML_TOK_FRAME_OBJECT:
+ case XML_TOK_FRAME_OBJECT_OLE:
+ {
+ // draw:object or draw:object_ole
+ pContext = new SdXMLObjectShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes );
+ break;
+ }
+ case XML_TOK_FRAME_TABLE:
+ {
+ // draw:object or draw:object_ole
+ if( rImport.IsTableShapeSupported() )
+ pContext = new SdXMLTableShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes );
+ break;
+
+ }
+ case XML_TOK_FRAME_PLUGIN:
+ {
+ // draw:plugin
+ pContext = new SdXMLPluginShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes );
+ break;
+ }
+ case XML_TOK_FRAME_FLOATING_FRAME:
+ {
+ // draw:floating-frame
+ pContext = new SdXMLFloatingFrameShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes );
+ break;
+ }
+ case XML_TOK_FRAME_APPLET:
+ {
+ // draw:applet
+ pContext = new SdXMLAppletShapeContext( rImport, p_nPrefix, rLocalName, xAttrList, rShapes );
+ break;
+ }
+ // add other shapes here...
+ default:
+ break;
+ }
+
+ if( pContext )
+ {
+ // now parse the attribute list and call the child context for each unknown attribute
+ sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
+ for(sal_Int16 a(0); a < nAttrCount; a++)
+ {
+ const OUString& rAttrName = xAttrList->getNameByIndex(a);
+ OUString aLocalName;
+ sal_uInt16 nPrefix = rImport.GetNamespaceMap().GetKeyByAttrName(rAttrName, &aLocalName);
+ const OUString aValue( xAttrList->getValueByIndex(a) );
+
+ pContext->processAttribute( nPrefix, aLocalName, aValue );
+ }
+ }
+
+ return pContext;
+}
+
+SvXMLImportContextRef XMLShapeImportHelper::CreateFrameChildContext(
+ SvXMLImportContext *pThisContext,
+ sal_uInt16 nPrefix,
+ const OUString& rLocalName,
+ const uno::Reference< xml::sax::XAttributeList>& xAttrList )
+{
+ SvXMLImportContextRef xContext;
+
+ SdXMLFrameShapeContext *pFrameContext = dynamic_cast<SdXMLFrameShapeContext*>( pThisContext );
+ if (pFrameContext)
+ xContext = pFrameContext->CreateChildContext( nPrefix, rLocalName, xAttrList );
+
+ return xContext;
+}
+
+/** this function is called whenever the implementation classes like to add this new
+ shape to the given XShapes.
+*/
+void XMLShapeImportHelper::addShape( uno::Reference< drawing::XShape >& rShape,
+ const uno::Reference< xml::sax::XAttributeList >&,
+ uno::Reference< drawing::XShapes >& rShapes)
+{
+ if( rShape.is() && rShapes.is() )
+ {
+ // add new shape to parent
+ rShapes->add( rShape );
+ }
+}
+
+/** this function is called whenever the implementation classes have finished importing
+ a shape to the given XShapes. The shape is already inserted into its XShapes and
+ all properties and styles are set.
+*/
+void XMLShapeImportHelper::finishShape(
+ css::uno::Reference< css::drawing::XShape >& rShape,
+ const css::uno::Reference< css::xml::sax::XAttributeList >&,
+ css::uno::Reference< css::drawing::XShapes >&)
+{
+ /* Set property <PositionLayoutDir>
+ to <PositionInHoriL2R>, if it exists and the import states that
+ the shape positioning attributes are in horizontal left-to-right
+ layout. This is the case for the OpenOffice.org file format.
+ This setting is done for Writer documents, because the property
+ only exists at service css::text::Shape - the Writer
+ UNO service for shapes.
+ The value indicates that the positioning attributes are given
+ in horizontal left-to-right layout. The property is evaluated
+ during the first positioning of the shape in order to convert
+ the shape position given in the OpenOffice.org file format to
+ the one for the OASIS Open Office file format. (#i28749#, #i36248#)
+ */
+ uno::Reference< beans::XPropertySet > xPropSet(rShape, uno::UNO_QUERY);
+ if ( xPropSet.is() )
+ {
+ if ( mrImporter.IsShapePositionInHoriL2R() &&
+ xPropSet->getPropertySetInfo()->hasPropertyByName(
+ "PositionLayoutDir") )
+ {
+ uno::Any aPosLayoutDir;
+ aPosLayoutDir <<= text::PositionLayoutDir::PositionInHoriL2R;
+ xPropSet->setPropertyValue( "PositionLayoutDir", aPosLayoutDir );
+ }
+ }
+}
+
+namespace {
+
+// helper functions for z-order sorting
+struct ZOrderHint
+{
+ sal_Int32 nIs;
+ sal_Int32 nShould;
+ /// The hint is for this shape.
+ uno::Reference<drawing::XShape> xShape;
+
+ bool operator<(const ZOrderHint& rComp) const { return nShould < rComp.nShould; }
+};
+
+// a) handle z-order of group contents after it has been imported
+// b) apply group events over group contents after it has been imported
+class ShapeGroupContext
+{
+public:
+ uno::Reference< drawing::XShapes > mxShapes;
+ std::vector<SdXMLEventContextData> maEventData;
+ vector<ZOrderHint> maZOrderList;
+ vector<ZOrderHint> maUnsortedList;
+
+ sal_Int32 mnCurrentZ;
+ std::shared_ptr<ShapeGroupContext> mpParentContext;
+
+ ShapeGroupContext( uno::Reference< drawing::XShapes > const & rShapes, std::shared_ptr<ShapeGroupContext> pParentContext );
+
+ void popGroupAndPostProcess();
+private:
+ void moveShape( sal_Int32 nSourcePos, sal_Int32 nDestPos );
+};
+
+}
+
+ShapeGroupContext::ShapeGroupContext( uno::Reference< drawing::XShapes > const & rShapes, std::shared_ptr<ShapeGroupContext> pParentContext )
+: mxShapes( rShapes ), mnCurrentZ( 0 ), mpParentContext( std::move(pParentContext) )
+{
+}
+
+void ShapeGroupContext::moveShape( sal_Int32 nSourcePos, sal_Int32 nDestPos )
+{
+ uno::Any aAny( mxShapes->getByIndex( nSourcePos ) );
+ uno::Reference< beans::XPropertySet > xPropSet;
+ aAny >>= xPropSet;
+
+ if( xPropSet.is() && xPropSet->getPropertySetInfo()->hasPropertyByName( "ZOrder" ) )
+ {
+ xPropSet->setPropertyValue( "ZOrder", uno::Any(nDestPos) );
+
+ for( ZOrderHint& rHint : maZOrderList )
+ {
+ if( rHint.nIs < nSourcePos )
+ {
+ DBG_ASSERT(rHint.nIs >= nDestPos, "Shape sorting failed" );
+ rHint.nIs++;
+ }
+ }
+
+ for( ZOrderHint& rHint : maUnsortedList )
+ {
+ if( rHint.nIs < nSourcePos )
+ {
+ SAL_WARN_IF( rHint.nIs < nDestPos, "xmloff", "shape sorting failed" );
+ rHint.nIs++;
+ }
+ }
+ }
+}
+
+// sort shapes
+void ShapeGroupContext::popGroupAndPostProcess()
+{
+ if (!maEventData.empty())
+ {
+ // tdf#127791 wait until a group is popped to set its event data
+ for (auto& event : maEventData)
+ event.ApplyProperties();
+ maEventData.clear();
+ }
+
+ // only do something if we have shapes to sort
+ if( maZOrderList.empty() )
+ return;
+
+ // check if there are more shapes than inserted with ::shapeWithZIndexAdded()
+ // This can happen if there where already shapes on the page before import
+ // Since the writer may delete some of this shapes during import, we need
+ // to do this here and not in our c'tor anymore
+
+ // check if we have more shapes than we know of
+ sal_Int32 nCount = mxShapes->getCount();
+
+ nCount -= maZOrderList.size();
+ nCount -= maUnsortedList.size();
+
+ if( nCount > 0 )
+ {
+ // first update offsets of added shapes
+ for (ZOrderHint& rHint : maZOrderList)
+ rHint.nIs += nCount;
+ for (ZOrderHint& rHint : maUnsortedList)
+ rHint.nIs += nCount;
+
+ // second add the already existing shapes in the unsorted list
+ ZOrderHint aNewHint;
+ do
+ {
+ nCount--;
+
+ aNewHint.nIs = nCount;
+ aNewHint.nShould = -1;
+
+ maUnsortedList.insert(maUnsortedList.begin(), aNewHint);
+ }
+ while( nCount );
+ }
+
+ bool bSorted = std::is_sorted(maZOrderList.begin(), maZOrderList.end(),
+ [&](const ZOrderHint& rLeft, const ZOrderHint& rRight)
+ { return rLeft.nShould < rRight.nShould; } );
+
+ if (bSorted)
+ return; // nothin' to do
+
+ // sort z-ordered shapes by nShould field
+ std::sort(maZOrderList.begin(), maZOrderList.end());
+
+ uno::Reference<drawing::XShapes3> xShapes3(mxShapes, uno::UNO_QUERY);
+ if( xShapes3.is())
+ {
+ uno::Sequence<sal_Int32> aNewOrder(maZOrderList.size() + maUnsortedList.size());
+ sal_Int32 nIndex = 0;
+
+ for (ZOrderHint& rHint : maZOrderList)
+ {
+ // fill in the gaps from unordered list
+ for (vector<ZOrderHint>::iterator aIt = maUnsortedList.begin(); aIt != maUnsortedList.end() && nIndex < rHint.nShould; )
+ {
+ aNewOrder[nIndex++] = (*aIt).nIs;
+ aIt = maUnsortedList.erase(aIt);
+ }
+
+ aNewOrder[nIndex] = rHint.nIs;
+ nIndex++;
+ }
+
+ try
+ {
+ xShapes3->sort(aNewOrder);
+ maZOrderList.clear();
+ return;
+ }
+ catch (const css::lang::IllegalArgumentException& /*e*/)
+ {}
+ }
+
+ // this is the current index, all shapes before that
+ // index are finished
+ sal_Int32 nIndex = 0;
+ for (const ZOrderHint& rHint : maZOrderList)
+ {
+ for (vector<ZOrderHint>::iterator aIt = maUnsortedList.begin(); aIt != maUnsortedList.end() && nIndex < rHint.nShould; )
+ {
+ moveShape( (*aIt).nIs, nIndex++ );
+ aIt = maUnsortedList.erase(aIt);
+
+ }
+
+ if(rHint.nIs != nIndex )
+ moveShape( rHint.nIs, nIndex );
+
+ nIndex++;
+ }
+ maZOrderList.clear();
+}
+
+void XMLShapeImportHelper::pushGroupForPostProcessing( uno::Reference< drawing::XShapes >& rShapes )
+{
+ mpImpl->mpGroupContext = std::make_shared<ShapeGroupContext>( rShapes, mpImpl->mpGroupContext );
+}
+
+void XMLShapeImportHelper::addShapeEvents(SdXMLEventContextData& rData)
+{
+ if (mpImpl->mpGroupContext && mpImpl->mpGroupContext->mxShapes == rData.mxShape)
+ {
+ // tdf#127791 wait until a group is popped to set its event data so
+ // that the events are applied to all its children, which are not available
+ // at the start of the group tag
+ mpImpl->mpGroupContext->maEventData.push_back(rData);
+ }
+ else
+ rData.ApplyProperties();
+}
+
+void XMLShapeImportHelper::popGroupAndPostProcess()
+{
+ SAL_WARN_IF( !mpImpl->mpGroupContext, "xmloff", "No context to sort!" );
+ if( !mpImpl->mpGroupContext )
+ return;
+
+ try
+ {
+ mpImpl->mpGroupContext->popGroupAndPostProcess();
+ }
+ catch( const uno::Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("xmloff", "exception while sorting shapes, sorting failed");
+ }
+
+ // put parent on top and drop current context, we are done
+ mpImpl->mpGroupContext = mpImpl->mpGroupContext->mpParentContext;
+}
+
+void XMLShapeImportHelper::shapeWithZIndexAdded( css::uno::Reference< css::drawing::XShape > const & xShape, sal_Int32 nZIndex )
+{
+ if( mpImpl->mpGroupContext)
+ {
+ ZOrderHint aNewHint;
+ aNewHint.nIs = mpImpl->mpGroupContext->mnCurrentZ++;
+ aNewHint.nShould = nZIndex;
+ aNewHint.xShape = xShape;
+
+ if( nZIndex == -1 )
+ {
+ // don't care, so add to unsorted list
+ mpImpl->mpGroupContext->maUnsortedList.push_back(aNewHint);
+ }
+ else
+ {
+ // insert into sort list
+ mpImpl->mpGroupContext->maZOrderList.push_back(aNewHint);
+ }
+ }
+}
+
+void XMLShapeImportHelper::shapeRemoved(const uno::Reference<drawing::XShape>& xShape)
+{
+ auto it = std::find_if(mpImpl->mpGroupContext->maZOrderList.begin(), mpImpl->mpGroupContext->maZOrderList.end(), [&xShape](const ZOrderHint& rHint)
+ {
+ return rHint.xShape == xShape;
+ });
+ if (it == mpImpl->mpGroupContext->maZOrderList.end())
+ // Part of the unsorted list, nothing to do.
+ return;
+
+ sal_Int32 nZIndex = it->nIs;
+
+ for (it = mpImpl->mpGroupContext->maZOrderList.begin(); it != mpImpl->mpGroupContext->maZOrderList.end();)
+ {
+ if (it->nIs == nZIndex)
+ {
+ // This is xShape: remove it and adjust the max of indexes
+ // accordingly.
+ it = mpImpl->mpGroupContext->maZOrderList.erase(it);
+ mpImpl->mpGroupContext->mnCurrentZ--;
+ continue;
+ }
+ else if (it->nIs > nZIndex)
+ // On top of xShape: adjust actual index to reflect removal.
+ it->nIs--;
+
+ // On top of or below xShape.
+ ++it;
+ }
+}
+
+void XMLShapeImportHelper::addShapeConnection( css::uno::Reference< css::drawing::XShape > const & rConnectorShape,
+ bool bStart,
+ const OUString& rDestShapeId,
+ sal_Int32 nDestGlueId )
+{
+ ConnectionHint aHint;
+ aHint.mxConnector = rConnectorShape;
+ aHint.bStart = bStart;
+ aHint.aDestShapeId = rDestShapeId;
+ aHint.nDestGlueId = nDestGlueId;
+
+ mpImpl->maConnections.push_back( aHint );
+}
+
+void XMLShapeImportHelper::restoreConnections()
+{
+ const vector<ConnectionHint>::size_type nCount = mpImpl->maConnections.size();
+ for( vector<ConnectionHint>::size_type i = 0; i < nCount; i++ )
+ {
+ ConnectionHint& rHint = mpImpl->maConnections[i];
+ uno::Reference< beans::XPropertySet > xConnector( rHint.mxConnector, uno::UNO_QUERY );
+ if( xConnector.is() )
+ {
+ // #86637# remember line deltas
+ uno::Any aLine1Delta;
+ uno::Any aLine2Delta;
+ uno::Any aLine3Delta;
+ OUString aStr1("EdgeLine1Delta");
+ OUString aStr2("EdgeLine2Delta");
+ OUString aStr3("EdgeLine3Delta");
+ aLine1Delta = xConnector->getPropertyValue(aStr1);
+ aLine2Delta = xConnector->getPropertyValue(aStr2);
+ aLine3Delta = xConnector->getPropertyValue(aStr3);
+
+ // #86637# simply setting these values WILL force the connector to do
+ // a new layout promptly. So the line delta values have to be rescued
+ // and restored around connector changes.
+ uno::Reference< drawing::XShape > xShape(
+ mrImporter.getInterfaceToIdentifierMapper().getReference( rHint.aDestShapeId ), uno::UNO_QUERY );
+ if( xShape.is() )
+ {
+ xConnector->setPropertyValue( rHint.bStart ? gsStartShape : gsEndShape, uno::Any(xShape) );
+
+ sal_Int32 nGlueId = rHint.nDestGlueId < 4 ? rHint.nDestGlueId : getGluePointId( xShape, rHint.nDestGlueId );
+ xConnector->setPropertyValue( rHint.bStart ? gsStartGluePointIndex : gsEndGluePointIndex, uno::Any(nGlueId) );
+ }
+
+ // #86637# restore line deltas
+ xConnector->setPropertyValue(aStr1, aLine1Delta );
+ xConnector->setPropertyValue(aStr2, aLine2Delta );
+ xConnector->setPropertyValue(aStr3, aLine3Delta );
+ }
+ }
+ mpImpl->maConnections.clear();
+}
+
+SvXMLImportPropertyMapper* XMLShapeImportHelper::CreateShapePropMapper( const uno::Reference< frame::XModel>& rModel, SvXMLImport& rImport )
+{
+ rtl::Reference< XMLPropertyHandlerFactory > xFactory = new XMLSdPropHdlFactory( rModel, rImport );
+ rtl::Reference < XMLPropertySetMapper > xMapper = new XMLShapePropertySetMapper( xFactory, false );
+ SvXMLImportPropertyMapper* pResult = new SvXMLImportPropertyMapper( xMapper, rImport );
+
+ // chain text attributes
+ pResult->ChainImportMapper( XMLTextImportHelper::CreateParaExtPropMapper( rImport ) );
+ return pResult;
+}
+
+/** adds a mapping for a glue point identifier from an xml file to the identifier created after inserting
+ the new glue point into the core. The saved mappings can be retrieved by getGluePointId() */
+void XMLShapeImportHelper::addGluePointMapping( css::uno::Reference< css::drawing::XShape > const & xShape,
+ sal_Int32 nSourceId, sal_Int32 nDestinnationId )
+{
+ if( mpPageContext )
+ mpPageContext->maShapeGluePointsMap[xShape][nSourceId] = nDestinnationId;
+}
+
+/** moves all current DestinationId's by n */
+void XMLShapeImportHelper::moveGluePointMapping( const css::uno::Reference< css::drawing::XShape >& xShape, const sal_Int32 n )
+{
+ if( mpPageContext )
+ {
+ ShapeGluePointsMap::iterator aShapeIter( mpPageContext->maShapeGluePointsMap.find( xShape ) );
+ if( aShapeIter != mpPageContext->maShapeGluePointsMap.end() )
+ {
+ for ( auto& rShapeId : (*aShapeIter).second )
+ {
+ if ( rShapeId.second != -1 )
+ rShapeId.second += n;
+ }
+ }
+ }
+}
+
+/** retrieves a mapping for a glue point identifier from the current xml file to the identifier created after
+ inserting the new glue point into the core. The mapping must be initialized first with addGluePointMapping() */
+sal_Int32 XMLShapeImportHelper::getGluePointId( const css::uno::Reference< css::drawing::XShape >& xShape, sal_Int32 nSourceId )
+{
+ if( mpPageContext )
+ {
+ ShapeGluePointsMap::iterator aShapeIter( mpPageContext->maShapeGluePointsMap.find( xShape ) );
+ if( aShapeIter != mpPageContext->maShapeGluePointsMap.end() )
+ {
+ GluePointIdMap::iterator aIdIter = (*aShapeIter).second.find(nSourceId);
+ if( aIdIter != (*aShapeIter).second.end() )
+ return (*aIdIter).second;
+ }
+ }
+
+ return -1;
+}
+
+/** this method must be calling before the first shape is imported for the given page */
+void XMLShapeImportHelper::startPage( css::uno::Reference< css::drawing::XShapes > const & rShapes )
+{
+ const std::shared_ptr<XMLShapeImportPageContextImpl> pOldContext = mpPageContext;
+ mpPageContext = std::make_shared<XMLShapeImportPageContextImpl>();
+ mpPageContext->mpNext = pOldContext;
+ mpPageContext->mxShapes = rShapes;
+}
+
+/** this method must be calling after the last shape is imported for the given page */
+void XMLShapeImportHelper::endPage( css::uno::Reference< css::drawing::XShapes > const & rShapes )
+{
+ SAL_WARN_IF( !mpPageContext || (mpPageContext->mxShapes != rShapes), "xmloff", "wrong call to endPage(), no startPage called or wrong page" );
+ if( nullptr == mpPageContext )
+ return;
+
+ restoreConnections();
+
+ mpPageContext = mpPageContext->mpNext;
+}
+
+/** defines if the import should increment the progress bar or not */
+void XMLShapeImportHelper::enableHandleProgressBar()
+{
+ mpImpl->mbHandleProgressBar = true;
+}
+
+bool XMLShapeImportHelper::IsHandleProgressBarEnabled() const
+{
+ return mpImpl->mbHandleProgressBar;
+}
+
+/** queries the capability of the current model to create presentation shapes */
+bool XMLShapeImportHelper::IsPresentationShapesSupported() const
+{
+ return mpImpl->mbIsPresentationShapesSupported;
+}
+
+const rtl::Reference< XMLTableImport >& XMLShapeImportHelper::GetShapeTableImport()
+{
+ if( !mxShapeTableImport.is() )
+ {
+ rtl::Reference< XMLPropertyHandlerFactory > xFactory( new XMLSdPropHdlFactory( mrImporter.GetModel(), mrImporter ) );
+ rtl::Reference< XMLPropertySetMapper > xPropertySetMapper( new XMLShapePropertySetMapper( xFactory.get(), false ) );
+ mxShapeTableImport = new XMLTableImport( mrImporter, xPropertySetMapper, xFactory );
+ }
+
+ return mxShapeTableImport;
+}
+
+void SvXMLShapeContext::setHyperlink( const OUString& rHyperlink )
+{
+ msHyperlink = rHyperlink;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */