diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:51:28 +0000 |
commit | 940b4d1848e8c70ab7642901a68594e8016caffc (patch) | |
tree | eb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /oox/source/shape | |
parent | Initial commit. (diff) | |
download | libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.tar.xz libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.zip |
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | oox/source/shape/LockedCanvasContext.cxx | 62 | ||||
-rw-r--r-- | oox/source/shape/LockedCanvasContext.hxx | 40 | ||||
-rw-r--r-- | oox/source/shape/ShapeContextHandler.cxx | 629 | ||||
-rw-r--r-- | oox/source/shape/ShapeContextHandler.hxx | 164 | ||||
-rw-r--r-- | oox/source/shape/ShapeDrawingFragmentHandler.cxx | 48 | ||||
-rw-r--r-- | oox/source/shape/ShapeDrawingFragmentHandler.hxx | 35 | ||||
-rw-r--r-- | oox/source/shape/ShapeFilterBase.cxx | 145 | ||||
-rw-r--r-- | oox/source/shape/WpgContext.cxx | 78 | ||||
-rw-r--r-- | oox/source/shape/WpgContext.hxx | 40 | ||||
-rw-r--r-- | oox/source/shape/WpsContext.cxx | 238 | ||||
-rw-r--r-- | oox/source/shape/WpsContext.hxx | 56 |
11 files changed, 1535 insertions, 0 deletions
diff --git a/oox/source/shape/LockedCanvasContext.cxx b/oox/source/shape/LockedCanvasContext.cxx new file mode 100644 index 000000000..0a56a42ed --- /dev/null +++ b/oox/source/shape/LockedCanvasContext.cxx @@ -0,0 +1,62 @@ +/* -*- 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/. + */ + +#include "LockedCanvasContext.hxx" +#include <sal/log.hxx> +#include <oox/drawingml/shape.hxx> +#include <oox/drawingml/shapecontext.hxx> +#include <oox/drawingml/shapegroupcontext.hxx> +#include <oox/token/namespaces.hxx> +#include <oox/token/tokens.hxx> + +using namespace com::sun::star; + +namespace oox::shape +{ +LockedCanvasContext::LockedCanvasContext(FragmentHandler2 const& rParent) + : FragmentHandler2(rParent) +{ +} + +LockedCanvasContext::~LockedCanvasContext() = default; + +::oox::core::ContextHandlerRef +LockedCanvasContext::onCreateContext(sal_Int32 nElementToken, + const ::oox::AttributeList& /*rAttribs*/) +{ + switch (getBaseToken(nElementToken)) + { + case XML_lockedCanvas: + case XML_nvGrpSpPr: + case XML_grpSpPr: + break; + case XML_sp: + { + oox::drawingml::ShapePtr pMasterShape; + mpShape = std::make_shared<oox::drawingml::Shape>("com.sun.star.drawing.CustomShape"); + mpShape->setLockedCanvas(true); + return new oox::drawingml::ShapeContext(*this, pMasterShape, mpShape); + } + case XML_grpSp: + { + oox::drawingml::ShapePtr pMasterShape; + mpShape = std::make_shared<oox::drawingml::Shape>("com.sun.star.drawing.GroupShape"); + mpShape->setLockedCanvas(true); + return new oox::drawingml::ShapeGroupContext(*this, pMasterShape, mpShape); + } + default: + SAL_WARN("oox", "LockedCanvasContext::createFastChildContext: unhandled element:" + << getBaseToken(nElementToken)); + break; + } + return nullptr; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/shape/LockedCanvasContext.hxx b/oox/source/shape/LockedCanvasContext.hxx new file mode 100644 index 000000000..68c8e27fa --- /dev/null +++ b/oox/source/shape/LockedCanvasContext.hxx @@ -0,0 +1,40 @@ +/* -*- 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/. + */ + +#ifndef INCLUDED_OOX_SOURCE_SHAPE_LOCKEDCANVASCONTEXT_HXX +#define INCLUDED_OOX_SOURCE_SHAPE_LOCKEDCANVASCONTEXT_HXX + +#include <oox/core/fragmenthandler2.hxx> +#include <oox/drawingml/drawingmltypes.hxx> + +namespace oox +{ +namespace shape +{ +/// Locked canvas is kind of a container for drawingml shapes: it can even contain group shapes. +class LockedCanvasContext final : public oox::core::FragmentHandler2 +{ +public: + explicit LockedCanvasContext(oox::core::FragmentHandler2 const& rParent); + ~LockedCanvasContext() override; + + oox::core::ContextHandlerRef onCreateContext(sal_Int32 nElementToken, + const ::oox::AttributeList& rAttribs) override; + + const oox::drawingml::ShapePtr& getShape() const { return mpShape; } + +private: + oox::drawingml::ShapePtr mpShape; +}; +} +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/shape/ShapeContextHandler.cxx b/oox/source/shape/ShapeContextHandler.cxx new file mode 100644 index 000000000..44fc0af6c --- /dev/null +++ b/oox/source/shape/ShapeContextHandler.cxx @@ -0,0 +1,629 @@ +/* -*- 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 "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 <cppuhelper/supportsservice.hxx> +#include <memory> + +using namespace ::com::sun::star; + +namespace oox::shape { +using namespace core; +using namespace drawingml; + +ShapeContextHandler::ShapeContextHandler(uno::Reference< uno::XComponentContext > const & context) : + mnStartToken(0) +{ + try + { + mxFilterBase.set( new ShapeFilterBase(context) ); + } + catch( uno::Exception& ) + { + } +} + +ShapeContextHandler::~ShapeContextHandler() +{ +} + +uno::Reference<xml::sax::XFastContextHandler> const & ShapeContextHandler::getLockedCanvasContext(sal_Int32 nElement) +{ + if (!mxLockedCanvasContext.is()) + { + FragmentHandler2Ref rFragmentHandler(new ShapeFragmentHandler(*mxFilterBase, 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(*mxFilterBase, 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(*mxFilterBase, 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(*mxFilterBase, msRelationFragmentPath)); + + switch (getBaseToken(nElement)) + { + case XML_wgp: + mxWpgContext.set(static_cast<oox::core::ContextHandler*>(new WpgContext(*rFragmentHandler))); + 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>(*mxFilterBase, 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>( *mxFilterBase, mxDrawPage, oox::vml::VMLDRAWING_WORD ); + mxDrawingFragmentHandler.set + (static_cast<ContextHandler *> + (new oox::vml::DrawingFragment + ( *mxFilterBase, 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 + ( *mxFilterBase, msRelationFragmentPath, *mpDrawing ))); + } + } + return mxDrawingFragmentHandler; +} + +uno::Reference<xml::sax::XFastContextHandler> const & +ShapeContextHandler::getDiagramShapeContext() +{ + if (!mxDiagramShapeContext.is()) + { + auto pFragmentHandler = std::make_shared<ShapeFragmentHandler>(*mxFilterBase, 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; + + switch (getNamespace( mnStartToken )) + { + case NMSP_doc: + case NMSP_vml: + xResult.set(getDrawingShapeContext()); + break; + case NMSP_dmlDiagram: + xResult.set(getDiagramShapeContext()); + break; + case NMSP_dmlLockedCanvas: + xResult.set(getLockedCanvasContext(mnStartToken)); + break; + case NMSP_dmlChart: + xResult.set(getChartShapeContext(mnStartToken)); + break; + case NMSP_wps: + xResult.set(getWpsContext(mnStartToken, nElement)); + break; + case NMSP_wpg: + xResult.set(getWpgContext(mnStartToken)); + break; + default: + xResult.set(getGraphicShapeContext(mnStartToken)); + break; + } + + return xResult; +} + +// css::xml::sax::XFastContextHandler: +void SAL_CALL ShapeContextHandler::startFastElement +(::sal_Int32 Element, + const uno::Reference< xml::sax::XFastAttributeList > & Attribs) +{ + mxFilterBase->filter(maMediaDescriptor); + + mpThemePtr = std::make_shared<Theme>(); + + 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 (!msRelationFragmentPath.isEmpty()) + { + // 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(*mxFilterBase, "/")); + OUString aOfficeDocumentFragmentPath = rFragmentHandlerRef->getFragmentPathFromFirstTypeFromOfficeDoc( "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(*mxFilterBase, aOfficeDocumentFragmentPath)); + OUString aThemeFragmentPath = rFragmentHandler->getFragmentPathFromFirstTypeFromOfficeDoc( "theme" ); + + if(!aThemeFragmentPath.isEmpty()) + { + uno::Reference<xml::sax::XFastSAXSerializable> xDoc(mxFilterBase->importFragment(aThemeFragmentPath), uno::UNO_QUERY_THROW); + mxFilterBase->importFragment(new ThemeFragmentHandler(*mxFilterBase, aThemeFragmentPath, *mpThemePtr ), xDoc); + ShapeFilterBase* pShapeFilterBase(dynamic_cast<ShapeFilterBase*>(mxFilterBase.get())); + if (pShapeFilterBase) + pShapeFilterBase->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); +} + +// css::xml::sax::XFastShapeContextHandler: +uno::Reference< drawing::XShape > SAL_CALL +ShapeContextHandler::getShape() +{ + uno::Reference< drawing::XShape > xResult; + uno::Reference< drawing::XShapes > xShapes = mxDrawPage; + + if (mxFilterBase.is() && 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( *mxFilterBase, 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(); + mxFilterBase->importFragment(new ShapeDrawingFragmentHandler(*mxFilterBase, aFragmentPath, pShapePtr)); + pShapePtr->setDiagramDoms(mpShape->getDiagramDoms()); + pShapePtr->keepDiagramDrawing(*mxFilterBase, aFragmentPath); + + 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( *mxFilterBase, 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(*mxFilterBase, 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( mnStartToken ))) + { + 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( *mxFilterBase, 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(*mxFilterBase, 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(*mxFilterBase, mpThemePtr.get(), xShapes, aMatrix, pShape->getFillProperties()); + xResult = pShape->getXShape(); + mxSavedShape = xResult; + mxWpgContext.clear(); + } + } + else if (mpShape.get() != nullptr) + { + 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(*mxFilterBase, mpThemePtr.get(), xShapes, aTransformation, mpShape->getFillProperties() ); + xResult.set(mpShape->getXShape()); + mxGraphicShapeContext.clear( ); + } + } + + return xResult; +} + +css::uno::Reference< css::drawing::XDrawPage > SAL_CALL +ShapeContextHandler::getDrawPage() +{ + return mxDrawPage; +} + +void SAL_CALL ShapeContextHandler::setDrawPage +(const css::uno::Reference< css::drawing::XDrawPage > & the_value) +{ + mxDrawPage = the_value; +} + +css::uno::Reference< css::frame::XModel > SAL_CALL +ShapeContextHandler::getModel() +{ + if( !mxFilterBase.is() ) + throw uno::RuntimeException(); + return mxFilterBase->getModel(); +} + +void SAL_CALL ShapeContextHandler::setModel +(const css::uno::Reference< css::frame::XModel > & the_value) +{ + if( !mxFilterBase.is() ) + throw uno::RuntimeException(); + uno::Reference<lang::XComponent> xComp(the_value, uno::UNO_QUERY_THROW); + mxFilterBase->setTargetDocument(xComp); +} + +OUString SAL_CALL ShapeContextHandler::getRelationFragmentPath() +{ + return msRelationFragmentPath; +} + +void SAL_CALL ShapeContextHandler::setRelationFragmentPath(const OUString & the_value) +{ + msRelationFragmentPath = the_value; +} + +::sal_Int32 SAL_CALL ShapeContextHandler::getStartToken() +{ + return mnStartToken; +} + +void SAL_CALL ShapeContextHandler::setStartToken( ::sal_Int32 _starttoken ) +{ + mnStartToken = _starttoken; +} + +awt::Point SAL_CALL ShapeContextHandler::getPosition() +{ + return maPosition; +} + +void SAL_CALL ShapeContextHandler::setPosition(const awt::Point& rPosition) +{ + maPosition = rPosition; +} + +void SAL_CALL ShapeContextHandler::setDocumentProperties(const uno::Reference<document::XDocumentProperties>& xDocProps) +{ + mxDocumentProperties = xDocProps; + mxFilterBase->checkDocumentProperties(mxDocumentProperties); +} + +uno::Reference<document::XDocumentProperties> SAL_CALL ShapeContextHandler::getDocumentProperties() +{ + return mxDocumentProperties; +} + +uno::Sequence<beans::PropertyValue> SAL_CALL ShapeContextHandler::getMediaDescriptor() +{ + return maMediaDescriptor; +} + +void SAL_CALL ShapeContextHandler::setMediaDescriptor(const uno::Sequence<beans::PropertyValue>& rMediaDescriptor) +{ + maMediaDescriptor = rMediaDescriptor; +} + +OUString ShapeContextHandler::getImplementationName() +{ + return "com.sun.star.comp.oox.ShapeContextHandler"; +} + +uno::Sequence< OUString > ShapeContextHandler::getSupportedServiceNames() +{ + return { "com.sun.star.xml.sax.FastShapeContextHandler" }; +} + +sal_Bool SAL_CALL ShapeContextHandler::supportsService(const OUString & ServiceName) +{ + return cppu::supportsService(this, ServiceName); +} + +} + +extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* +com_sun_star_comp_oox_ShapeContextHandler_get_implementation( + uno::XComponentContext* pCtx, uno::Sequence<uno::Any> const& /*rSeq*/) +{ + return cppu::acquire(new oox::shape::ShapeContextHandler(pCtx)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/shape/ShapeContextHandler.hxx b/oox/source/shape/ShapeContextHandler.hxx new file mode 100644 index 000000000..abda9c94a --- /dev/null +++ b/oox/source/shape/ShapeContextHandler.hxx @@ -0,0 +1,164 @@ +/* -*- 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 . + */ +#ifndef INCLUDED_OOX_SOURCE_SHAPE_SHAPECONTEXTHANDLER_HXX +#define INCLUDED_OOX_SOURCE_SHAPE_SHAPECONTEXTHANDLER_HXX + +#include <memory> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <cppuhelper/implbase.hxx> +#include <com/sun/star/xml/sax/XFastShapeContextHandler.hpp> +#include <oox/drawingml/graphicshapecontext.hxx> +#include <oox/core/fragmenthandler2.hxx> +#include <oox/core/xmlfilterbase.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/document/XDocumentProperties.hpp> + +namespace oox::shape { + +class ShapeFragmentHandler : public core::FragmentHandler2 +{ +public: + typedef std::shared_ptr<ShapeFragmentHandler> Pointer_t; + + explicit ShapeFragmentHandler(core::XmlFilterBase& rFilter, + const OUString& rFragmentPath ) + : FragmentHandler2(rFilter, rFragmentPath) + { + } +}; + +class ShapeContextHandler: + public ::cppu::WeakImplHelper< css::xml::sax::XFastShapeContextHandler, + css::lang::XServiceInfo > +{ +public: + explicit ShapeContextHandler + (css::uno::Reference< css::uno::XComponentContext > const & context); + + virtual ~ShapeContextHandler() override; + + // css::lang::XServiceInfo: + virtual OUString SAL_CALL getImplementationName() override; + + virtual sal_Bool SAL_CALL supportsService + (const OUString & ServiceName) override; + + virtual css::uno::Sequence< OUString > SAL_CALL + getSupportedServiceNames() override; + + // css::xml::sax::XFastContextHandler: + virtual void SAL_CALL startFastElement + (::sal_Int32 Element, + const css::uno::Reference< css::xml::sax::XFastAttributeList > & Attribs) override; + + virtual void SAL_CALL startUnknownElement + (const OUString & Namespace, + const OUString & Name, + const css::uno::Reference< css::xml::sax::XFastAttributeList > & Attribs) override; + + virtual void SAL_CALL endFastElement(::sal_Int32 Element) override; + + virtual void SAL_CALL endUnknownElement + (const OUString & Namespace, + const OUString & Name) override; + + virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL + createFastChildContext + (::sal_Int32 Element, + const css::uno::Reference< css::xml::sax::XFastAttributeList > & Attribs) override; + + virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL + createUnknownChildContext + (const OUString & Namespace, + const OUString & Name, + const css::uno::Reference< css::xml::sax::XFastAttributeList > & Attribs) override; + + virtual void SAL_CALL characters(const OUString & aChars) override; + + // css::xml::sax::XFastShapeContextHandler: + virtual css::uno::Reference< css::drawing::XShape > SAL_CALL getShape() override; + + virtual css::uno::Reference< css::drawing::XDrawPage > SAL_CALL getDrawPage() override; + + virtual void SAL_CALL setDrawPage + (const css::uno::Reference< css::drawing::XDrawPage > & the_value) override; + + virtual css::uno::Reference< css::frame::XModel > SAL_CALL getModel() override; + + virtual void SAL_CALL setModel + (const css::uno::Reference< css::frame::XModel > & the_value) override; + + virtual OUString SAL_CALL getRelationFragmentPath() override; + virtual void SAL_CALL setRelationFragmentPath + (const OUString & the_value) override; + + virtual ::sal_Int32 SAL_CALL getStartToken() override; + virtual void SAL_CALL setStartToken( ::sal_Int32 _starttoken ) override; + + virtual css::awt::Point SAL_CALL getPosition() override; + virtual void SAL_CALL setPosition(const css::awt::Point& rPosition) override; + + virtual void SAL_CALL setDocumentProperties(const css::uno::Reference<css::document::XDocumentProperties>& xDocProps) override; + virtual css::uno::Reference<css::document::XDocumentProperties> SAL_CALL getDocumentProperties() override; + virtual css::uno::Sequence<css::beans::PropertyValue> SAL_CALL getMediaDescriptor() override; + virtual void SAL_CALL setMediaDescriptor(const css::uno::Sequence<css::beans::PropertyValue>& rMediaDescriptor) override; + +private: + ShapeContextHandler(ShapeContextHandler const &) = delete; + void operator =(ShapeContextHandler const &) = delete; + + ::sal_uInt32 mnStartToken; + css::awt::Point maPosition; + + drawingml::ShapePtr mpShape; + std::shared_ptr< vml::Drawing > mpDrawing; + + typedef std::shared_ptr<drawingml::GraphicShapeContext> + GraphicShapeContextPtr; + css::uno::Reference<XFastContextHandler> mxDrawingFragmentHandler; + css::uno::Reference<XFastContextHandler> mxGraphicShapeContext; + css::uno::Reference<XFastContextHandler> mxDiagramShapeContext; + css::uno::Reference<XFastContextHandler> mxLockedCanvasContext; + css::uno::Reference<XFastContextHandler> mxWpsContext; + css::uno::Reference<css::drawing::XShape> mxSavedShape; + css::uno::Reference<XFastContextHandler> mxWpgContext; + css::uno::Reference<XFastContextHandler> mxChartShapeContext; + css::uno::Reference<css::document::XDocumentProperties> mxDocumentProperties; + css::uno::Sequence<css::beans::PropertyValue> maMediaDescriptor; + + ::rtl::Reference< core::XmlFilterBase > mxFilterBase; + drawingml::ThemePtr mpThemePtr; + css::uno::Reference<css::drawing::XDrawPage> mxDrawPage; + OUString msRelationFragmentPath; + + css::uno::Reference<XFastContextHandler> const & getGraphicShapeContext(::sal_Int32 Element); + css::uno::Reference<XFastContextHandler> const & getChartShapeContext(::sal_Int32 Element); + css::uno::Reference<XFastContextHandler> const & getDrawingShapeContext(); + css::uno::Reference<XFastContextHandler> const & getDiagramShapeContext(); + css::uno::Reference<XFastContextHandler> const & getLockedCanvasContext(sal_Int32 nElement); + css::uno::Reference<XFastContextHandler> const & getWpsContext(sal_Int32 nStartElement, sal_Int32 nElement); + css::uno::Reference<XFastContextHandler> const & getWpgContext(sal_Int32 nElement); + css::uno::Reference<XFastContextHandler> getContextHandler(sal_Int32 nElement = 0); +}; + +} + +#endif // INCLUDED_OOX_SOURCE_SHAPE_SHAPECONTEXTHANDLER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/shape/ShapeDrawingFragmentHandler.cxx b/oox/source/shape/ShapeDrawingFragmentHandler.cxx new file mode 100644 index 000000000..3c65844f2 --- /dev/null +++ b/oox/source/shape/ShapeDrawingFragmentHandler.cxx @@ -0,0 +1,48 @@ +/* -*- 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/. + */ + +#include "ShapeDrawingFragmentHandler.hxx" + +#include <oox/drawingml/shapegroupcontext.hxx> +#include <oox/token/namespaces.hxx> + +using namespace com::sun::star; + +namespace oox::shape { + +ShapeDrawingFragmentHandler::ShapeDrawingFragmentHandler(oox::core::XmlFilterBase& rFilter, const OUString& rFragmentPath, oox::drawingml::ShapePtr const & pGroupShapePtr) + : FragmentHandler2(rFilter, rFragmentPath) + , mpGroupShapePtr(pGroupShapePtr) +{ +} + +ShapeDrawingFragmentHandler::~ShapeDrawingFragmentHandler() throw() +{ +} + +void SAL_CALL ShapeDrawingFragmentHandler::endDocument() +{ +} + +::oox::core::ContextHandlerRef ShapeDrawingFragmentHandler::onCreateContext(sal_Int32 Element, const AttributeList& /*Attribs*/ ) +{ + switch( Element ) + { + case DSP_TOKEN( spTree ): + return new oox::drawingml::ShapeGroupContext(*this, oox::drawingml::ShapePtr(nullptr), mpGroupShapePtr); + default: + break; + } + + return this; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/shape/ShapeDrawingFragmentHandler.hxx b/oox/source/shape/ShapeDrawingFragmentHandler.hxx new file mode 100644 index 000000000..53ce4d129 --- /dev/null +++ b/oox/source/shape/ShapeDrawingFragmentHandler.hxx @@ -0,0 +1,35 @@ +/* -*- 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/. + */ + +#ifndef INCLUDED_OOX_SOURCE_SHAPE_SHAPEDRAWINGFRAGMENTHANDLER_HXX +#define INCLUDED_OOX_SOURCE_SHAPE_SHAPEDRAWINGFRAGMENTHANDLER_HXX + +#include <oox/core/fragmenthandler2.hxx> +#include <oox/drawingml/drawingmltypes.hxx> + +namespace oox::shape { + +/// Generic (i.e. not specific to PPTX) handler for the prerendered diagram parsing. +class ShapeDrawingFragmentHandler : public oox::core::FragmentHandler2 +{ +public: + ShapeDrawingFragmentHandler(oox::core::XmlFilterBase& rFilter, const OUString& rFragmentPath, oox::drawingml::ShapePtr const & pGroupShapePtr); + virtual ~ShapeDrawingFragmentHandler() throw() override; + virtual void SAL_CALL endDocument() override; + virtual ::oox::core::ContextHandlerRef onCreateContext(sal_Int32 Element, const AttributeList& rAttribs ) override; + +private: + oox::drawingml::ShapePtr mpGroupShapePtr; +}; + +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/shape/ShapeFilterBase.cxx b/oox/source/shape/ShapeFilterBase.cxx new file mode 100644 index 000000000..6505b91a1 --- /dev/null +++ b/oox/source/shape/ShapeFilterBase.cxx @@ -0,0 +1,145 @@ +/* -*- 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 <oox/shape/ShapeFilterBase.hxx> +#include <oox/drawingml/chart/chartconverter.hxx> +#include <oox/drawingml/themefragmenthandler.hxx> +#include <oox/helper/graphichelper.hxx> +#include <oox/ole/vbaproject.hxx> +#include <oox/drawingml/theme.hxx> + +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/xml/sax/XFastSAXSerializable.hpp> + +namespace oox::shape { + +using namespace ::com::sun::star; + +ShapeFilterBase::ShapeFilterBase( const uno::Reference< uno::XComponentContext >& rxContext ) : + XmlFilterBase( rxContext ), + mxChartConv( std::make_shared<::oox::drawingml::chart::ChartConverter>() ) +{ +} + +ShapeFilterBase::~ShapeFilterBase() +{ +} + +const ::oox::drawingml::Theme* ShapeFilterBase::getCurrentTheme() const +{ + return mpTheme.get(); +} + +void ShapeFilterBase::setCurrentTheme(const ::oox::drawingml::ThemePtr& pTheme) +{ + mpTheme = pTheme; +} + +::oox::vml::Drawing* ShapeFilterBase::getVmlDrawing() +{ + return nullptr; +} + +::oox::drawingml::table::TableStyleListPtr ShapeFilterBase::getTableStyles() +{ + return ::oox::drawingml::table::TableStyleListPtr(); +} + +::oox::drawingml::chart::ChartConverter* ShapeFilterBase::getChartConverter() +{ + return mxChartConv.get(); +} + +::oox::ole::VbaProject* ShapeFilterBase::implCreateVbaProject() const +{ + return new ::oox::ole::VbaProject( getComponentContext(), getModel(), "Writer" ); +} + +OUString ShapeFilterBase::getImplementationName() +{ + return OUString(); +} + +namespace { + +/// Graphic helper for shapes, that can manage color schemes. +class ShapeGraphicHelper : public GraphicHelper +{ +public: + explicit ShapeGraphicHelper( const ShapeFilterBase& rFilter ); + virtual ::Color getSchemeColor( sal_Int32 nToken ) const override; +private: + const ShapeFilterBase& mrFilter; +}; + +} + +ShapeGraphicHelper::ShapeGraphicHelper( const ShapeFilterBase& rFilter ) : + GraphicHelper( rFilter.getComponentContext(), rFilter.getTargetFrame(), rFilter.getStorage() ), + mrFilter( rFilter ) +{ +} + +::Color ShapeGraphicHelper::getSchemeColor( sal_Int32 nToken ) const +{ + return mrFilter.getSchemeColor( nToken ); +} + +GraphicHelper* ShapeFilterBase::implCreateGraphicHelper() const +{ + return new ShapeGraphicHelper( *this ); +} + +::Color ShapeFilterBase::getSchemeColor( sal_Int32 nToken ) const +{ + ::Color nColor; + + if (mpTheme) + mpTheme->getClrScheme().getColor( nToken, nColor ); + + return nColor; +} + +void ShapeFilterBase::importTheme() +{ + drawingml::ThemePtr pTheme = std::make_shared<drawingml::Theme>(); + uno::Reference<beans::XPropertySet> xPropSet(getModel(), uno::UNO_QUERY_THROW); + uno::Sequence<beans::PropertyValue> aGrabBag; + xPropSet->getPropertyValue("InteropGrabBag") >>= aGrabBag; + + for (const auto& rProp : std::as_const(aGrabBag)) + { + if (rProp.Name == "OOXTheme") + { + uno::Reference<xml::sax::XFastSAXSerializable> xDoc; + if (rProp.Value >>= xDoc) + { + rtl::Reference<core::FragmentHandler> xFragmentHandler( + new drawingml::ThemeFragmentHandler(*this, OUString(), *pTheme)); + importFragment(xFragmentHandler, xDoc); + setCurrentTheme(pTheme); + } + } + } +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/shape/WpgContext.cxx b/oox/source/shape/WpgContext.cxx new file mode 100644 index 000000000..7896f8a4c --- /dev/null +++ b/oox/source/shape/WpgContext.cxx @@ -0,0 +1,78 @@ +/* -*- 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/. + */ + +#include "WpgContext.hxx" +#include <sal/log.hxx> +#include <drawingml/shapepropertiescontext.hxx> +#include <oox/drawingml/shapegroupcontext.hxx> +#include <oox/drawingml/graphicshapecontext.hxx> +#include <oox/token/namespaces.hxx> +#include <oox/token/tokens.hxx> + +using namespace com::sun::star; + +namespace oox::shape +{ +WpgContext::WpgContext(FragmentHandler2 const& rParent) + : FragmentHandler2(rParent) +{ + mpShape = std::make_shared<oox::drawingml::Shape>("com.sun.star.drawing.GroupShape"); + mpShape->setWps(true); +} + +WpgContext::~WpgContext() = default; + +oox::core::ContextHandlerRef WpgContext::onCreateContext(sal_Int32 nElementToken, + const oox::AttributeList& /*rAttribs*/) +{ + switch (getBaseToken(nElementToken)) + { + case XML_wgp: + case XML_cNvGrpSpPr: + case XML_grpSpPr: + return new oox::drawingml::ShapePropertiesContext(*this, *mpShape); + case XML_wsp: + { + // Don't set default character height, Writer has its own way to set + // the default, and if we don't set it here, editeng properly inherits + // it. + oox::drawingml::ShapePtr pShape = std::make_shared<oox::drawingml::Shape>( + "com.sun.star.drawing.CustomShape", /*bDefaultHeight=*/false); + return new oox::drawingml::ShapeContext(*this, mpShape, pShape); + // return new oox::shape::WpsContext(*this, uno::Reference<drawing::XShape>(), + // mpShape, pShape); + } + case XML_pic: + return new oox::drawingml::GraphicShapeContext( + *this, mpShape, + std::make_shared<oox::drawingml::Shape>("com.sun.star.drawing.GraphicObjectShape")); + case XML_grpSp: + { + return new oox::drawingml::ShapeGroupContext( + *this, mpShape, + std::make_shared<oox::drawingml::Shape>("com.sun.star.drawing.GroupShape")); + } + case XML_graphicFrame: + { + auto pShape = std::make_shared<oox::drawingml::Shape>( + "com.sun.star.drawing.GraphicObjectShape"); + pShape->setWps(true); + return new oox::drawingml::GraphicalObjectFrameContext(*this, mpShape, pShape, + /*bEmbedShapesInChart=*/true); + } + default: + SAL_WARN("oox", "WpgContext::createFastChildContext: unhandled element: " + << getBaseToken(nElementToken)); + break; + } + return nullptr; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/shape/WpgContext.hxx b/oox/source/shape/WpgContext.hxx new file mode 100644 index 000000000..1b85cd4ec --- /dev/null +++ b/oox/source/shape/WpgContext.hxx @@ -0,0 +1,40 @@ +/* -*- 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/. + */ + +#ifndef INCLUDED_OOX_SOURCE_SHAPE_WPGCONTEXT_HXX +#define INCLUDED_OOX_SOURCE_SHAPE_WPGCONTEXT_HXX + +#include <oox/core/fragmenthandler2.hxx> +#include <oox/drawingml/drawingmltypes.hxx> + +namespace oox +{ +namespace shape +{ +/// Wpg is the drawingML equivalent of v:group. +class WpgContext final : public oox::core::FragmentHandler2 +{ +public: + explicit WpgContext(oox::core::FragmentHandler2 const& rParent); + ~WpgContext() override; + + oox::core::ContextHandlerRef onCreateContext(sal_Int32 nElementToken, + const oox::AttributeList& rAttribs) override; + + const oox::drawingml::ShapePtr& getShape() const { return mpShape; } + +private: + oox::drawingml::ShapePtr mpShape; +}; +} +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/shape/WpsContext.cxx b/oox/source/shape/WpsContext.cxx new file mode 100644 index 000000000..f78c38ff9 --- /dev/null +++ b/oox/source/shape/WpsContext.cxx @@ -0,0 +1,238 @@ +/* -*- 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/. + */ + +#include "WpsContext.hxx" +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/tuple/b2dtuple.hxx> +#include <comphelper/sequenceashashmap.hxx> +#include <drawingml/customshapeproperties.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/XPropertyState.hpp> +#include <com/sun/star/drawing/HomogenMatrix3.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/text/XText.hpp> +#include <com/sun/star/text/XTextCursor.hpp> +#include <com/sun/star/text/WritingMode.hpp> +#include <svx/svdtrans.hxx> +#include <oox/helper/attributelist.hxx> +#include <oox/token/namespaces.hxx> +#include <oox/token/tokens.hxx> +#include <oox/drawingml/shape.hxx> + +#include <optional> + +using namespace com::sun::star; + +namespace oox::shape +{ +WpsContext::WpsContext(ContextHandler2Helper const& rParent, uno::Reference<drawing::XShape> xShape, + const drawingml::ShapePtr& pMasterShapePtr, + const drawingml::ShapePtr& pShapePtr) + : ShapeContext(rParent, pMasterShapePtr, pShapePtr) + , mxShape(std::move(xShape)) +{ + mpShapePtr->setWps(true); +} + +WpsContext::~WpsContext() = default; + +oox::core::ContextHandlerRef WpsContext::onCreateContext(sal_Int32 nElementToken, + const oox::AttributeList& rAttribs) +{ + switch (getBaseToken(nElementToken)) + { + case XML_wsp: + case XML_cNvCnPr: + break; + case XML_bodyPr: + if (mxShape.is()) + { + uno::Reference<lang::XServiceInfo> xServiceInfo(mxShape, uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xPropertySet(mxShape, uno::UNO_QUERY); + sal_Int32 nVert = rAttribs.getToken(XML_vert, XML_horz); + if (nVert == XML_eaVert) + { + xPropertySet->setPropertyValue("TextWritingMode", + uno::makeAny(text::WritingMode_TB_RL)); + } + else if (nVert != XML_horz) + { + // Get the existing rotation of the shape. + drawing::HomogenMatrix3 aMatrix; + xPropertySet->getPropertyValue("Transformation") >>= aMatrix; + basegfx::B2DHomMatrix aTransformation; + aTransformation.set(0, 0, aMatrix.Line1.Column1); + aTransformation.set(0, 1, aMatrix.Line1.Column2); + aTransformation.set(0, 2, aMatrix.Line1.Column3); + aTransformation.set(1, 0, aMatrix.Line1.Column1); + aTransformation.set(1, 1, aMatrix.Line2.Column2); + aTransformation.set(1, 2, aMatrix.Line3.Column3); + aTransformation.set(2, 0, aMatrix.Line1.Column1); + aTransformation.set(2, 1, aMatrix.Line2.Column2); + aTransformation.set(2, 2, aMatrix.Line3.Column3); + basegfx::B2DTuple aScale; + basegfx::B2DTuple aTranslate; + double fRotate = 0; + double fShearX = 0; + aTransformation.decompose(aScale, aTranslate, fRotate, fShearX); + + // If the text is not rotated the way the shape wants it already, set the angle. + const sal_Int32 nRotation = nVert == XML_vert270 ? -270 : -90; + if (static_cast<long>(basegfx::rad2deg(fRotate)) + != NormAngle36000(static_cast<long>(nRotation) * 100) / 100) + { + comphelper::SequenceAsHashMap aCustomShapeGeometry( + xPropertySet->getPropertyValue("CustomShapeGeometry")); + aCustomShapeGeometry["TextPreRotateAngle"] <<= nRotation; + xPropertySet->setPropertyValue( + "CustomShapeGeometry", + uno::makeAny(aCustomShapeGeometry.getAsConstPropertyValueList())); + } + } + + if (xServiceInfo.is()) + { + // Handle inset attributes for Writer textframes. + sal_Int32 aInsets[] = { XML_lIns, XML_tIns, XML_rIns, XML_bIns }; + std::optional<sal_Int32> oInsets[4]; + for (std::size_t i = 0; i < SAL_N_ELEMENTS(aInsets); ++i) + { + OptValue<OUString> oValue = rAttribs.getString(aInsets[i]); + if (oValue.has()) + oInsets[i] = oox::drawingml::GetCoordinate(oValue.get()); + else + // Defaults from the spec: left/right: 91440 EMU, top/bottom: 45720 EMU + oInsets[i] + = (aInsets[i] == XML_lIns || aInsets[i] == XML_rIns) ? 254 : 127; + } + const OUString aShapeProps[] + = { OUString("TextLeftDistance"), OUString("TextUpperDistance"), + OUString("TextRightDistance"), OUString("TextLowerDistance") }; + for (std::size_t i = 0; i < SAL_N_ELEMENTS(aShapeProps); ++i) + if (oInsets[i]) + xPropertySet->setPropertyValue(aShapeProps[i], + uno::makeAny(*oInsets[i])); + } + + // Handle text vertical adjustment inside a text frame + if (rAttribs.hasAttribute(XML_anchor)) + { + drawing::TextVerticalAdjust eAdjust + = drawingml::GetTextVerticalAdjust(rAttribs.getToken(XML_anchor, XML_t)); + xPropertySet->setPropertyValue("TextVerticalAdjust", uno::makeAny(eAdjust)); + } + + // Apply character color of the shape to the shape's textbox. + uno::Reference<text::XText> xText(mxShape, uno::UNO_QUERY); + uno::Reference<text::XTextCursor> xTextCursor = xText->createTextCursor(); + xTextCursor->gotoStart(false); + xTextCursor->gotoEnd(true); + const uno::Reference<beans::XPropertyState> xPropertyState(xTextCursor, + uno::UNO_QUERY); + const beans::PropertyState ePropertyState + = xPropertyState->getPropertyState("CharColor"); + if (ePropertyState == beans::PropertyState_DEFAULT_VALUE) + { + uno::Reference<beans::XPropertySet> xTextBoxPropertySet(xTextCursor, + uno::UNO_QUERY); + uno::Any xCharColor = xPropertySet->getPropertyValue("CharColor"); + Color aColor = COL_AUTO; + if (xCharColor >>= aColor) + { + if (aColor != COL_AUTO) + xTextBoxPropertySet->setPropertyValue("CharColor", xCharColor); + } + } + return this; + } + break; + case XML_noAutofit: + case XML_spAutoFit: + { + uno::Reference<lang::XServiceInfo> xServiceInfo(mxShape, uno::UNO_QUERY); + // We can't use oox::drawingml::TextBodyPropertiesContext here, as this + // is a child context of bodyPr, so the shape is already sent: we need + // to alter the XShape directly. + uno::Reference<beans::XPropertySet> xPropertySet(mxShape, uno::UNO_QUERY); + if (xPropertySet.is()) + { + if (xServiceInfo->supportsService("com.sun.star.text.TextFrame")) + xPropertySet->setPropertyValue( + "FrameIsAutomaticHeight", + uno::makeAny(getBaseToken(nElementToken) == XML_spAutoFit)); + else + xPropertySet->setPropertyValue( + "TextAutoGrowHeight", + uno::makeAny(getBaseToken(nElementToken) == XML_spAutoFit)); + } + } + break; + case XML_prstTxWarp: + if (rAttribs.hasAttribute(XML_prst)) + { + uno::Reference<beans::XPropertySet> xPropertySet(mxShape, uno::UNO_QUERY); + if (xPropertySet.is()) + { + oox::OptValue<OUString> presetShapeName = rAttribs.getString(XML_prst); + const OUString& preset = presetShapeName.get(); + comphelper::SequenceAsHashMap aCustomShapeGeometry( + xPropertySet->getPropertyValue("CustomShapeGeometry")); + aCustomShapeGeometry["PresetTextWarp"] <<= preset; + xPropertySet->setPropertyValue( + "CustomShapeGeometry", + uno::makeAny(aCustomShapeGeometry.getAsConstPropertyValueList())); + } + } + break; + case XML_txbx: + { + mpShapePtr->getCustomShapeProperties()->setShapeTypeOverride(true); + mpShapePtr->setTextBox(true); + //in case if the textbox is linked, save the attributes + //for further processing. + if (rAttribs.hasAttribute(XML_id)) + { + OptValue<OUString> id = rAttribs.getString(XML_id); + if (id.has()) + { + oox::drawingml::LinkedTxbxAttr linkedTxtBoxAttr; + linkedTxtBoxAttr.id = id.get().toInt32(); + mpShapePtr->setTxbxHasLinkedTxtBox(true); + mpShapePtr->setLinkedTxbxAttributes(linkedTxtBoxAttr); + } + } + return this; + } + break; + case XML_linkedTxbx: + { + //in case if the textbox is linked, save the attributes + //for further processing. + mpShapePtr->getCustomShapeProperties()->setShapeTypeOverride(true); + mpShapePtr->setTextBox(true); + OptValue<OUString> id = rAttribs.getString(XML_id); + OptValue<OUString> seq = rAttribs.getString(XML_seq); + if (id.has() && seq.has()) + { + oox::drawingml::LinkedTxbxAttr linkedTxtBoxAttr; + linkedTxtBoxAttr.id = id.get().toInt32(); + linkedTxtBoxAttr.seq = seq.get().toInt32(); + mpShapePtr->setTxbxHasLinkedTxtBox(true); + mpShapePtr->setLinkedTxbxAttributes(linkedTxtBoxAttr); + } + } + break; + default: + return ShapeContext::onCreateContext(nElementToken, rAttribs); + } + return nullptr; +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/oox/source/shape/WpsContext.hxx b/oox/source/shape/WpsContext.hxx new file mode 100644 index 000000000..c5a6565a5 --- /dev/null +++ b/oox/source/shape/WpsContext.hxx @@ -0,0 +1,56 @@ +/* -*- 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/. + */ + +#ifndef INCLUDED_OOX_SOURCE_SHAPE_WPSCONTEXT_HXX +#define INCLUDED_OOX_SOURCE_SHAPE_WPSCONTEXT_HXX + +#include <oox/core/contexthandler2.hxx> +#include <oox/drawingml/shapecontext.hxx> +#include <oox/drawingml/drawingmltypes.hxx> + +namespace com +{ +namespace sun +{ +namespace star +{ +namespace drawing +{ +class XShape; +} +} +} +} + +namespace oox +{ +namespace shape +{ +/// Wps is the drawingML equivalent of v:shape. +class WpsContext final : public oox::drawingml::ShapeContext +{ +public: + WpsContext(oox::core::ContextHandler2Helper const& rParent, + css::uno::Reference<css::drawing::XShape> xShape, + oox::drawingml::ShapePtr const& pMasterShapePtr, + oox::drawingml::ShapePtr const& pShapePtr); + ~WpsContext() override; + + oox::core::ContextHandlerRef onCreateContext(sal_Int32 nElementToken, + const oox::AttributeList& rAttribs) override; + +private: + css::uno::Reference<css::drawing::XShape> mxShape; +}; +} +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |