summaryrefslogtreecommitdiffstats
path: root/oox/source/shape/ShapeContextHandler.cxx
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--oox/source/shape/ShapeContextHandler.cxx584
1 files changed, 584 insertions, 0 deletions
diff --git a/oox/source/shape/ShapeContextHandler.cxx b/oox/source/shape/ShapeContextHandler.cxx
new file mode 100644
index 000000000..e88637fc4
--- /dev/null
+++ b/oox/source/shape/ShapeContextHandler.cxx
@@ -0,0 +1,584 @@
+/* -*- 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 <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/xml/dom/XDocument.hpp>
+#include <com/sun/star/xml/sax/XFastSAXSerializable.hpp>
+
+#include <oox/shape/ShapeContextHandler.hxx>
+#include "ShapeDrawingFragmentHandler.hxx"
+#include "LockedCanvasContext.hxx"
+#include "WpsContext.hxx"
+#include "WpgContext.hxx"
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <oox/vml/vmldrawingfragment.hxx>
+#include <oox/vml/vmlshape.hxx>
+#include <oox/vml/vmlshapecontainer.hxx>
+#include <oox/shape/ShapeFilterBase.hxx>
+#include <oox/token/namespaces.hxx>
+#include <oox/token/tokens.hxx>
+#include <oox/drawingml/theme.hxx>
+#include <oox/drawingml/themefragmenthandler.hxx>
+#include <memory>
+
+using namespace ::com::sun::star;
+
+namespace oox::shape {
+using namespace core;
+using namespace drawingml;
+
+ShapeContextHandler::ShapeContextHandler(const rtl::Reference<ShapeFilterBase>& xFilterBase) :
+ m_bFullWPGSUpport(false),
+ mxShapeFilterBase(xFilterBase)
+
+{
+}
+
+ShapeContextHandler::~ShapeContextHandler()
+{
+}
+
+uno::Reference<xml::sax::XFastContextHandler> const & ShapeContextHandler::getLockedCanvasContext(sal_Int32 nElement)
+{
+ if (!mxLockedCanvasContext.is())
+ {
+ FragmentHandler2Ref rFragmentHandler(new ShapeFragmentHandler(*mxShapeFilterBase, msRelationFragmentPath));
+
+ switch (nElement & 0xffff)
+ {
+ case XML_lockedCanvas:
+ mxLockedCanvasContext.set(static_cast<oox::core::ContextHandler*>(new LockedCanvasContext(*rFragmentHandler)));
+ break;
+ default:
+ break;
+ }
+ }
+
+ return mxLockedCanvasContext;
+}
+
+/*
+ * This method creates new ChartGraphicDataContext Object.
+ */
+uno::Reference<xml::sax::XFastContextHandler> const & ShapeContextHandler::getChartShapeContext(sal_Int32 nElement)
+{
+ if (!mxChartShapeContext.is())
+ {
+ switch (nElement & 0xffff)
+ {
+ case XML_chart:
+ {
+ std::unique_ptr<ContextHandler2Helper> pFragmentHandler(
+ new ShapeFragmentHandler(*mxShapeFilterBase, msRelationFragmentPath));
+ mpShape = std::make_shared<Shape>("com.sun.star.drawing.OLE2Shape" );
+ mxChartShapeContext.set(new ChartGraphicDataContext(*pFragmentHandler, mpShape, true));
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ return mxChartShapeContext;
+}
+
+uno::Reference<xml::sax::XFastContextHandler> const & ShapeContextHandler::getWpsContext(sal_Int32 nStartElement, sal_Int32 nElement)
+{
+ if (!mxWpsContext.is())
+ {
+ FragmentHandler2Ref rFragmentHandler(new ShapeFragmentHandler(*mxShapeFilterBase, msRelationFragmentPath));
+ ShapePtr pMasterShape;
+
+ uno::Reference<drawing::XShape> xShape;
+ // No element happens in case of pretty-printed XML, bodyPr is the case when we are called again after <wps:txbx>.
+ if (!nElement || nElement == WPS_TOKEN(bodyPr))
+ // Assume that this is just a continuation of the previous shape.
+ xShape = mxSavedShape;
+
+ switch (getBaseToken(nStartElement))
+ {
+ case XML_wsp:
+ mxWpsContext.set(new WpsContext(
+ *rFragmentHandler,
+ xShape,
+ pMasterShape,
+ std::make_shared<oox::drawingml::Shape>(
+ "com.sun.star.drawing.CustomShape")));
+ break;
+ default:
+ break;
+ }
+ }
+
+ return mxWpsContext;
+}
+
+uno::Reference<xml::sax::XFastContextHandler> const & ShapeContextHandler::getWpgContext(sal_Int32 nElement)
+{
+ if (!mxWpgContext.is())
+ {
+ FragmentHandler2Ref rFragmentHandler(new ShapeFragmentHandler(*mxShapeFilterBase, msRelationFragmentPath));
+
+ switch (getBaseToken(nElement))
+ {
+ case XML_wgp:
+ {
+ rtl::Reference<WpgContext> rContext = new WpgContext(*rFragmentHandler, oox::drawingml::ShapePtr());
+ rContext->setFullWPGSupport(m_bFullWPGSUpport);
+ mxWpgContext.set(static_cast<oox::core::ContextHandler*>(rContext.get()));
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ return mxWpgContext;
+}
+
+uno::Reference<xml::sax::XFastContextHandler> const &
+ShapeContextHandler::getGraphicShapeContext(::sal_Int32 Element )
+{
+ if (! mxGraphicShapeContext.is())
+ {
+ auto pFragmentHandler = std::make_shared<ShapeFragmentHandler>(*mxShapeFilterBase, msRelationFragmentPath);
+ ShapePtr pMasterShape;
+
+ switch (Element & 0xffff)
+ {
+ case XML_graphic:
+ mpShape = std::make_shared<Shape>("com.sun.star.drawing.GraphicObjectShape" );
+ mxGraphicShapeContext.set
+ (new GraphicalObjectFrameContext(*pFragmentHandler, pMasterShape, mpShape, true));
+ break;
+ case XML_pic:
+ mpShape = std::make_shared<Shape>("com.sun.star.drawing.GraphicObjectShape" );
+ mxGraphicShapeContext.set
+ (new GraphicShapeContext(*pFragmentHandler, pMasterShape, mpShape));
+ break;
+ default:
+ break;
+ }
+ }
+
+ return mxGraphicShapeContext;
+}
+
+uno::Reference<xml::sax::XFastContextHandler> const &
+ShapeContextHandler::getDrawingShapeContext()
+{
+ if (!mxDrawingFragmentHandler.is())
+ {
+ mpDrawing = std::make_shared<oox::vml::Drawing>( *mxShapeFilterBase, mxDrawPage, oox::vml::VMLDRAWING_WORD );
+ mxDrawingFragmentHandler.set
+ (static_cast<ContextHandler *>
+ (new oox::vml::DrawingFragment
+ ( *mxShapeFilterBase, msRelationFragmentPath, *mpDrawing )));
+ }
+ else
+ {
+ // Reset the handler if fragment path has changed
+ OUString sHandlerFragmentPath = dynamic_cast<ContextHandler&>(*mxDrawingFragmentHandler).getFragmentPath();
+ if ( msRelationFragmentPath != sHandlerFragmentPath )
+ {
+ mxDrawingFragmentHandler.clear();
+ mxDrawingFragmentHandler.set
+ (static_cast<ContextHandler *>
+ (new oox::vml::DrawingFragment
+ ( *mxShapeFilterBase, msRelationFragmentPath, *mpDrawing )));
+ }
+ }
+ return mxDrawingFragmentHandler;
+}
+
+uno::Reference<xml::sax::XFastContextHandler> const &
+ShapeContextHandler::getDiagramShapeContext()
+{
+ if (!mxDiagramShapeContext.is())
+ {
+ auto pFragmentHandler = std::make_shared<ShapeFragmentHandler>(*mxShapeFilterBase, msRelationFragmentPath);
+ mpShape = std::make_shared<Shape>();
+ mxDiagramShapeContext.set(new DiagramGraphicDataContext(*pFragmentHandler, mpShape));
+ }
+
+ return mxDiagramShapeContext;
+}
+
+uno::Reference<xml::sax::XFastContextHandler>
+ShapeContextHandler::getContextHandler(sal_Int32 nElement)
+{
+ uno::Reference<xml::sax::XFastContextHandler> xResult;
+ const sal_uInt32 nStartToken = getStartToken();
+
+ switch (getNamespace( nStartToken ))
+ {
+ case NMSP_doc:
+ case NMSP_vml:
+ xResult.set(getDrawingShapeContext());
+ break;
+ case NMSP_dmlDiagram:
+ xResult.set(getDiagramShapeContext());
+ break;
+ case NMSP_dmlLockedCanvas:
+ xResult.set(getLockedCanvasContext(nStartToken));
+ break;
+ case NMSP_dmlChart:
+ xResult.set(getChartShapeContext(nStartToken));
+ break;
+ case NMSP_wps:
+ xResult.set(getWpsContext(nStartToken, nElement));
+ break;
+ case NMSP_wpg:
+ xResult.set(getWpgContext(nStartToken));
+ break;
+ default:
+ xResult.set(getGraphicShapeContext(nStartToken));
+ break;
+ }
+
+ return xResult;
+}
+
+// css::xml::sax::XFastContextHandler:
+void SAL_CALL ShapeContextHandler::startFastElement
+(::sal_Int32 Element,
+ const uno::Reference< xml::sax::XFastAttributeList > & Attribs)
+{
+ mxShapeFilterBase->filter(maMediaDescriptor);
+
+ if (Element == DGM_TOKEN(relIds) || Element == LC_TOKEN(lockedCanvas) || Element == C_TOKEN(chart) ||
+ Element == WPS_TOKEN(wsp) || Element == WPG_TOKEN(wgp) || Element == OOX_TOKEN(dmlPicture, pic))
+ {
+ // Parse the theme relation, if available; the diagram won't have colors without it.
+ if (!mpThemePtr && !msRelationFragmentPath.isEmpty())
+ {
+ mpThemePtr = std::make_shared<Theme>();
+ // Get Target for Type = "officeDocument" from _rels/.rels file
+ // aOfficeDocumentFragmentPath is pointing to "word/document.xml" for docx & to "ppt/presentation.xml" for pptx
+ FragmentHandlerRef rFragmentHandlerRef(new ShapeFragmentHandler(*mxShapeFilterBase, "/"));
+ OUString aOfficeDocumentFragmentPath = rFragmentHandlerRef->getFragmentPathFromFirstTypeFromOfficeDoc( u"officeDocument" );
+
+ // Get the theme DO NOT use msRelationFragmentPath for getting theme as for a document there is a single theme in document.xml.rels
+ // and the same is used by header and footer as well.
+ FragmentHandlerRef rFragmentHandler(new ShapeFragmentHandler(*mxShapeFilterBase, aOfficeDocumentFragmentPath));
+ OUString aThemeFragmentPath = rFragmentHandler->getFragmentPathFromFirstTypeFromOfficeDoc( u"theme" );
+
+ if(!aThemeFragmentPath.isEmpty())
+ {
+ uno::Reference<xml::sax::XFastSAXSerializable> xDoc(mxShapeFilterBase->importFragment(aThemeFragmentPath), uno::UNO_QUERY_THROW);
+ mxShapeFilterBase->importFragment(new ThemeFragmentHandler(*mxShapeFilterBase, aThemeFragmentPath, *mpThemePtr ), xDoc);
+ mxShapeFilterBase->setCurrentTheme(mpThemePtr);
+ }
+ }
+
+ createFastChildContext(Element, Attribs);
+ }
+
+ // Entering VML block (startFastElement() is called for the outermost tag),
+ // handle possible recursion.
+ if ( getContextHandler() == getDrawingShapeContext() )
+ mpDrawing->getShapes().pushMark();
+
+ uno::Reference<XFastContextHandler> xContextHandler(getContextHandler());
+
+ if (xContextHandler.is())
+ xContextHandler->startFastElement(Element, Attribs);
+}
+
+void SAL_CALL ShapeContextHandler::startUnknownElement
+(const OUString & Namespace, const OUString & Name,
+ const uno::Reference< xml::sax::XFastAttributeList > & Attribs)
+{
+ if ( getContextHandler() == getDrawingShapeContext() )
+ mpDrawing->getShapes().pushMark();
+
+ uno::Reference<XFastContextHandler> xContextHandler(getContextHandler());
+
+ if (xContextHandler.is())
+ xContextHandler->startUnknownElement(Namespace, Name, Attribs);
+}
+
+void SAL_CALL ShapeContextHandler::endFastElement(::sal_Int32 Element)
+{
+ uno::Reference<XFastContextHandler> xContextHandler(getContextHandler());
+
+ if (xContextHandler.is())
+ xContextHandler->endFastElement(Element);
+ // In case a textbox is sent, and later we get additional properties for
+ // the textbox, then the wps context is not cleared, so do that here.
+ if (Element != (NMSP_wps | XML_wsp))
+ return;
+
+ uno::Reference<lang::XServiceInfo> xServiceInfo(mxSavedShape, uno::UNO_QUERY);
+ bool bTextFrame = xServiceInfo.is() && xServiceInfo->supportsService("com.sun.star.text.TextFrame");
+ bool bTextBox = false;
+ if (!bTextFrame)
+ {
+ uno::Reference<beans::XPropertySet> xPropertySet(mxSavedShape, uno::UNO_QUERY);
+ if (xPropertySet.is())
+ xPropertySet->getPropertyValue("TextBox") >>= bTextBox;
+ }
+ if (bTextFrame || bTextBox)
+ mxWpsContext.clear();
+ mxSavedShape.clear();
+}
+
+void SAL_CALL ShapeContextHandler::endUnknownElement
+(const OUString & Namespace,
+ const OUString & Name)
+{
+ uno::Reference<XFastContextHandler> xContextHandler(getContextHandler());
+
+ if (xContextHandler.is())
+ xContextHandler->endUnknownElement(Namespace, Name);
+}
+
+uno::Reference< xml::sax::XFastContextHandler > SAL_CALL
+ShapeContextHandler::createFastChildContext
+(::sal_Int32 Element,
+ const uno::Reference< xml::sax::XFastAttributeList > & Attribs)
+{
+ uno::Reference< xml::sax::XFastContextHandler > xResult;
+ uno::Reference< xml::sax::XFastContextHandler > xContextHandler(getContextHandler(Element));
+
+ if (xContextHandler.is())
+ xResult.set(xContextHandler->createFastChildContext
+ (Element, Attribs));
+
+ return xResult;
+}
+
+uno::Reference< xml::sax::XFastContextHandler > SAL_CALL
+ShapeContextHandler::createUnknownChildContext
+(const OUString & Namespace,
+ const OUString & Name,
+ const uno::Reference< xml::sax::XFastAttributeList > & Attribs)
+{
+ uno::Reference<XFastContextHandler> xContextHandler(getContextHandler());
+
+ if (xContextHandler.is())
+ return xContextHandler->createUnknownChildContext
+ (Namespace, Name, Attribs);
+
+ return uno::Reference< xml::sax::XFastContextHandler >();
+}
+
+void SAL_CALL ShapeContextHandler::characters(const OUString & aChars)
+{
+ uno::Reference<XFastContextHandler> xContextHandler(getContextHandler());
+
+ if (xContextHandler.is())
+ xContextHandler->characters(aChars);
+}
+
+uno::Reference< drawing::XShape >
+ShapeContextHandler::getShape()
+{
+ uno::Reference< drawing::XShape > xResult;
+ uno::Reference< drawing::XShapes > xShapes = mxDrawPage;
+
+ if (mxShapeFilterBase && xShapes.is())
+ {
+ if ( getContextHandler() == getDrawingShapeContext() )
+ {
+ mpDrawing->finalizeFragmentImport();
+ if( std::shared_ptr< vml::ShapeBase > pShape = mpDrawing->getShapes().takeLastShape() )
+ xResult = pShape->convertAndInsert( xShapes );
+ // Only now remove the recursion mark, because getShape() is called in writerfilter
+ // after endFastElement().
+ mpDrawing->getShapes().popMark();
+ }
+ else if (mxDiagramShapeContext.is())
+ {
+ basegfx::B2DHomMatrix aMatrix;
+ if (mpShape->getExtDrawings().empty())
+ {
+ mpShape->addShape( *mxShapeFilterBase, mpThemePtr.get(), xShapes, aMatrix, mpShape->getFillProperties() );
+ xResult = mpShape->getXShape();
+ }
+ else
+ {
+ // Prerendered diagram output is available, then use that, and throw away the original result.
+ for (auto const& extDrawing : mpShape->getExtDrawings())
+ {
+ DiagramGraphicDataContext* pDiagramGraphicDataContext = dynamic_cast<DiagramGraphicDataContext*>(mxDiagramShapeContext.get());
+ if (!pDiagramGraphicDataContext)
+ break;
+ OUString aFragmentPath(pDiagramGraphicDataContext->getFragmentPathFromRelId(extDrawing));
+ oox::drawingml::ShapePtr pShapePtr = std::make_shared<Shape>( "com.sun.star.drawing.GroupShape" );
+ pShapePtr->setDiagramType();
+ mxShapeFilterBase->importFragment(new ShapeDrawingFragmentHandler(*mxShapeFilterBase, aFragmentPath, pShapePtr));
+ pShapePtr->setDiagramDoms(mpShape->getDiagramDoms());
+ pShapePtr->keepDiagramDrawing(*mxShapeFilterBase, aFragmentPath);
+
+ // migrate IDiagramHelper to new oox::Shape (from mpShape which was loaded
+ // to pShapePtr where the geometry is now constructed)
+ mpShape->migrateDiagramHelperToNewShape(pShapePtr);
+
+ if (!mpShape->getChildren().empty())
+ {
+ // first child is diagram background - we want to keep it, as drawingML fallback doesn't contain it
+ auto& aChildren = pShapePtr->getChildren();
+ ShapePtr pBackground = mpShape->getChildren().front();
+ aChildren.insert(aChildren.begin(), pBackground);
+ }
+
+ pShapePtr->addShape( *mxShapeFilterBase, mpThemePtr.get(), xShapes, aMatrix, pShapePtr->getFillProperties() );
+ xResult = pShapePtr->getXShape();
+ }
+ mpShape.reset();
+ }
+ mxDiagramShapeContext.clear();
+ }
+ else if (mxLockedCanvasContext.is())
+ {
+ ShapePtr pShape = dynamic_cast<LockedCanvasContext&>(*mxLockedCanvasContext).getShape();
+ if (pShape)
+ {
+ basegfx::B2DHomMatrix aMatrix;
+ pShape->addShape(*mxShapeFilterBase, mpThemePtr.get(), xShapes, aMatrix, pShape->getFillProperties());
+ xResult = pShape->getXShape();
+ mxLockedCanvasContext.clear();
+ }
+ }
+ //NMSP_dmlChart == getNamespace( mnStartToken ) check is introduced to make sure that
+ //mnStartToken is set as NMSP_dmlChart in setStartToken.
+ //Only in case it is set then only the below block of code for ChartShapeContext should be executed.
+ else if (mxChartShapeContext.is() && (NMSP_dmlChart == getNamespace( getStartToken() )))
+ {
+ ChartGraphicDataContext* pChartGraphicDataContext = dynamic_cast<ChartGraphicDataContext*>(mxChartShapeContext.get());
+ if (pChartGraphicDataContext)
+ {
+ basegfx::B2DHomMatrix aMatrix;
+ oox::drawingml::ShapePtr xShapePtr( pChartGraphicDataContext->getShape());
+ // See SwXTextDocument::createInstance(), ODF import uses the same hack.
+ xShapePtr->setServiceName("com.sun.star.drawing.temporaryForXMLImportOLE2Shape");
+ xShapePtr->addShape( *mxShapeFilterBase, mpThemePtr.get(), xShapes, aMatrix, xShapePtr->getFillProperties() );
+ xResult = xShapePtr->getXShape();
+ }
+ mxChartShapeContext.clear();
+ }
+ else if (mxWpsContext.is())
+ {
+ ShapePtr pShape = dynamic_cast<WpsContext&>(*mxWpsContext).getShape();
+ if (pShape)
+ {
+ basegfx::B2DHomMatrix aMatrix;
+ pShape->setPosition(maPosition);
+ pShape->addShape(*mxShapeFilterBase, mpThemePtr.get(), xShapes, aMatrix, pShape->getFillProperties());
+ xResult = pShape->getXShape();
+ mxSavedShape = xResult;
+ mxWpsContext.clear();
+ }
+ }
+ else if (mxWpgContext.is())
+ {
+ ShapePtr pShape = dynamic_cast<WpgContext&>(*mxWpgContext).getShape();
+ if (pShape)
+ {
+ basegfx::B2DHomMatrix aMatrix;
+ pShape->setPosition(maPosition);
+ pShape->addShape(*mxShapeFilterBase, mpThemePtr.get(), xShapes, aMatrix, pShape->getFillProperties());
+ xResult = pShape->getXShape();
+ mxSavedShape = xResult;
+ mxWpgContext.clear();
+ }
+ }
+ else if (mpShape)
+ {
+ basegfx::B2DHomMatrix aTransformation;
+
+ if (maPosition.X != 0 || maPosition.Y != 0)
+ {
+ // We got a position from writerfilter/, store that in the shape, otherwise the
+ // position won't be set.
+ mpShape->setWps(true);
+ mpShape->setPosition(maPosition);
+ }
+
+ mpShape->addShape(*mxShapeFilterBase, mpThemePtr.get(), xShapes, aTransformation, mpShape->getFillProperties() );
+ xResult.set(mpShape->getXShape());
+ mxGraphicShapeContext.clear( );
+ }
+ }
+
+ if (xResult)
+ popStartToken();
+ return xResult;
+}
+
+void ShapeContextHandler::setDrawPage(const css::uno::Reference< css::drawing::XDrawPage > & the_value)
+{
+ mxDrawPage = the_value;
+}
+
+void ShapeContextHandler::setModel(const css::uno::Reference< css::frame::XModel > & the_value)
+{
+ if( !mxShapeFilterBase.is() )
+ throw uno::RuntimeException();
+ uno::Reference<lang::XComponent> xComp(the_value, uno::UNO_QUERY_THROW);
+ mxShapeFilterBase->setTargetDocument(xComp);
+}
+
+void ShapeContextHandler::setRelationFragmentPath(const OUString & the_value)
+{
+ msRelationFragmentPath = the_value;
+}
+
+sal_Int32 ShapeContextHandler::getStartToken() const
+{
+ assert(mnStartTokenStack.size() && "This stack must not be empty!");
+ return mnStartTokenStack.top();
+}
+
+void ShapeContextHandler::popStartToken()
+{
+ if (mnStartTokenStack.size() > 1)
+ mnStartTokenStack.pop();
+}
+
+void ShapeContextHandler::pushStartToken( sal_Int32 _starttoken )
+{
+ mnStartTokenStack.push(_starttoken);
+}
+
+void ShapeContextHandler::setPosition(const awt::Point& rPosition)
+{
+ maPosition = rPosition;
+}
+
+void ShapeContextHandler::setDocumentProperties(const uno::Reference<document::XDocumentProperties>& xDocProps)
+{
+ mxDocumentProperties = xDocProps;
+ mxShapeFilterBase->checkDocumentProperties(mxDocumentProperties);
+}
+
+void ShapeContextHandler::setMediaDescriptor(const uno::Sequence<beans::PropertyValue>& rMediaDescriptor)
+{
+ maMediaDescriptor = rMediaDescriptor;
+}
+
+void ShapeContextHandler::setGraphicMapper(css::uno::Reference<css::graphic::XGraphicMapper> const & rxGraphicMapper)
+{
+ mxShapeFilterBase->setGraphicMapper(rxGraphicMapper);
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */