diff options
Diffstat (limited to 'oox/source/drawingml/graphicshapecontext.cxx')
-rw-r--r-- | oox/source/drawingml/graphicshapecontext.cxx | 341 |
1 files changed, 341 insertions, 0 deletions
diff --git a/oox/source/drawingml/graphicshapecontext.cxx b/oox/source/drawingml/graphicshapecontext.cxx new file mode 100644 index 000000000..2e5ce5dc4 --- /dev/null +++ b/oox/source/drawingml/graphicshapecontext.cxx @@ -0,0 +1,341 @@ +/* -*- 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 <sal/config.h> + +#include <string_view> + +#include <oox/drawingml/graphicshapecontext.hxx> + +#include <osl/diagnose.h> +#include <sal/log.hxx> + +#include <drawingml/embeddedwavaudiofile.hxx> +#include <drawingml/misccontexts.hxx> +#include <drawingml/graphicproperties.hxx> +#include <drawingml/customshapeproperties.hxx> +#include <oox/drawingml/diagram/diagram.hxx> +#include <drawingml/table/tablecontext.hxx> +#include <oox/core/xmlfilterbase.hxx> +#include <oox/helper/attributelist.hxx> +#include <oox/vml/vmldrawing.hxx> +#include <drawingml/transform2dcontext.hxx> +#include <oox/ppt/pptshapegroupcontext.hxx> +#include <oox/token/namespaces.hxx> +#include <oox/token/tokens.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::xml::sax; +using namespace ::oox::core; + +static uno::Reference<io::XInputStream> +lcl_GetMediaStream(const OUString& rStream, const oox::core::XmlFilterBase& rFilter) +{ + if (rStream.isEmpty()) + return nullptr; + + Reference< XInputStream > xInStrm( rFilter.openInputStream(rStream), UNO_SET_THROW ); + return xInStrm; +} + +static OUString lcl_GetMediaReference(std::u16string_view rStream) +{ + return rStream.empty() ? OUString() : OUString::Concat("vnd.sun.star.Package:") + rStream; +} + +namespace oox::drawingml { + +// CT_Picture + +GraphicShapeContext::GraphicShapeContext( ContextHandler2Helper const & rParent, const ShapePtr& pMasterShapePtr, const ShapePtr& pShapePtr ) +: ShapeContext( rParent, pMasterShapePtr, pShapePtr ) +{ +} + +ContextHandlerRef GraphicShapeContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) +{ + switch( getBaseToken( aElementToken ) ) + { + // CT_ShapeProperties + case XML_xfrm: + return new Transform2DContext( *this, rAttribs, *mpShapePtr ); + case XML_blipFill: + return new BlipFillContext( *this, rAttribs, mpShapePtr->getGraphicProperties().maBlipProps ); + case XML_wavAudioFile: + { + OUString const path(getEmbeddedWAVAudioFile(getRelations(), rAttribs)); + Reference<XInputStream> xMediaStream = lcl_GetMediaStream(path, getFilter()); + if (xMediaStream.is()) + { + mpShapePtr->getGraphicProperties().m_xMediaStream = xMediaStream; + mpShapePtr->getGraphicProperties().m_sMediaPackageURL = lcl_GetMediaReference(path); + } + } + break; + case XML_audioFile: + case XML_videoFile: + { + OUString rPath = getRelations().getFragmentPathFromRelId( + rAttribs.getString(R_TOKEN(link)).get() ); + if (!rPath.isEmpty()) + { + Reference<XInputStream> xMediaStream = lcl_GetMediaStream(rPath, getFilter()); + if (xMediaStream.is()) // embedded media file + { + mpShapePtr->getGraphicProperties().m_xMediaStream = xMediaStream; + mpShapePtr->getGraphicProperties().m_sMediaPackageURL + = lcl_GetMediaReference(rPath); + } + } + else + { + rPath = getRelations().getExternalTargetFromRelId( + rAttribs.getString(R_TOKEN(link)).get()); + if (!rPath.isEmpty()) // linked media file + mpShapePtr->getGraphicProperties().m_sMediaPackageURL + = getFilter().getAbsoluteUrl(rPath); + } + } + break; + } + + if ((getNamespace( aElementToken ) == NMSP_vml) && mpShapePtr) + { + mpShapePtr->setServiceName("com.sun.star.drawing.CustomShape"); + CustomShapePropertiesPtr pCstmShpProps + (mpShapePtr->getCustomShapeProperties()); + + pCstmShpProps->setShapePresetType( getBaseToken( aElementToken ) ); + } + + return ShapeContext::onCreateContext( aElementToken, rAttribs ); +} + +// CT_GraphicalObjectFrameContext + +GraphicalObjectFrameContext::GraphicalObjectFrameContext( ContextHandler2Helper& rParent, const ShapePtr& pMasterShapePtr, const ShapePtr& pShapePtr, bool bEmbedShapesInChart ) : + ShapeContext( rParent, pMasterShapePtr, pShapePtr ), + mbEmbedShapesInChart( bEmbedShapesInChart ), + mpParent(&rParent) +{ +} + +ContextHandlerRef GraphicalObjectFrameContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) +{ + switch( getBaseToken( aElementToken ) ) + { + // CT_ShapeProperties + case XML_nvGraphicFramePr: // CT_GraphicalObjectFrameNonVisual + break; + case XML_xfrm: // CT_Transform2D + return new Transform2DContext( *this, rAttribs, *mpShapePtr ); + case XML_graphic: // CT_GraphicalObject + return this; + + case XML_graphicData : // CT_GraphicalObjectData + { + OUString sUri( rAttribs.getString( XML_uri ).get() ); + if ( sUri == "http://schemas.openxmlformats.org/presentationml/2006/ole" || + sUri == "http://purl.oclc.org/ooxml/presentationml/ole" ) + return new OleObjectGraphicDataContext( *this, mpShapePtr ); + else if ( sUri == "http://schemas.openxmlformats.org/drawingml/2006/diagram" || + sUri == "http://purl.oclc.org/ooxml/drawingml/diagram" ) + return new DiagramGraphicDataContext( *this, mpShapePtr ); + else if ( sUri == "http://schemas.openxmlformats.org/drawingml/2006/chart" || + sUri == "http://purl.oclc.org/ooxml/drawingml/chart" ) + return new ChartGraphicDataContext( *this, mpShapePtr, mbEmbedShapesInChart ); + else if ( sUri == "http://schemas.openxmlformats.org/drawingml/2006/table" || + sUri == "http://purl.oclc.org/ooxml/drawingml/table" ) + return new table::TableContext( *this, mpShapePtr ); + else + { + SAL_WARN("oox.drawingml", "OOX: Ignore graphicsData of :" << sUri ); + return nullptr; + } + } + break; + } + + return ShapeContext::onCreateContext( aElementToken, rAttribs ); +} + +void GraphicalObjectFrameContext::onEndElement() +{ + if( getCurrentElement() == PPT_TOKEN( graphicFrame ) && mpParent ) + { + oox::ppt::PPTShapeGroupContext* pParent = dynamic_cast<oox::ppt::PPTShapeGroupContext*>(mpParent); + if( pParent ) + pParent->importExtDrawings(); + } +} + +OleObjectGraphicDataContext::OleObjectGraphicDataContext( ContextHandler2Helper const & rParent, const ShapePtr& xShape ) : + ShapeContext( rParent, ShapePtr(), xShape ), + mrOleObjectInfo( xShape->setOleObjectType() ) +{ +} + +OleObjectGraphicDataContext::~OleObjectGraphicDataContext() +{ + /* Register the OLE shape at the VML drawing, this prevents that the + related VML shape converts the OLE object by itself. */ + if( !mrOleObjectInfo.maShapeId.isEmpty() ) + if( ::oox::vml::Drawing* pVmlDrawing = getFilter().getVmlDrawing() ) + pVmlDrawing->registerOleObject( mrOleObjectInfo ); +} + +ContextHandlerRef OleObjectGraphicDataContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) +{ + switch( nElement ) + { + case PPT_TOKEN( oleObj ): + { + mrOleObjectInfo.maShapeId = rAttribs.getXString( XML_spid, OUString() ); + const Relation* pRelation = getRelations().getRelationFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) ); + OSL_ENSURE( pRelation, "OleObjectGraphicDataContext::createFastChildContext - missing relation for OLE object" ); + if( pRelation ) + { + mrOleObjectInfo.mbLinked = pRelation->mbExternal; + if( pRelation->mbExternal ) + { + mrOleObjectInfo.maTargetLink = getFilter().getAbsoluteUrl( pRelation->maTarget ); + } + else + { + OUString aFragmentPath = getFragmentPathFromRelation( *pRelation ); + if( !aFragmentPath.isEmpty() ) + getFilter().importBinaryData( mrOleObjectInfo.maEmbeddedData, aFragmentPath ); + } + } + mrOleObjectInfo.maName = rAttribs.getXString( XML_name, OUString() ); + mrOleObjectInfo.maProgId = rAttribs.getXString( XML_progId, OUString() ); + mrOleObjectInfo.mbShowAsIcon = rAttribs.getBool( XML_showAsIcon, false ); + mrOleObjectInfo.mbHasPicture = false; // Initialize as false + return this; + } + break; + + case PPT_TOKEN( embed ): + OSL_ENSURE( !mrOleObjectInfo.mbLinked, "OleObjectGraphicDataContext::createFastChildContext - unexpected child element" ); + break; + + case PPT_TOKEN( link ): + OSL_ENSURE( mrOleObjectInfo.mbLinked, "OleObjectGraphicDataContext::createFastChildContext - unexpected child element" ); + mrOleObjectInfo.mbAutoUpdate = rAttribs.getBool( XML_updateAutomatic, false ); + break; + case PPT_TOKEN( pic ): + mrOleObjectInfo.mbHasPicture = true; // Set true if ole object has picture element. + return new GraphicShapeContext( *this, mpMasterShapePtr, mpShapePtr ); + } + SAL_WARN("oox", "OleObjectGraphicDataContext::onCreateContext: unhandled element: " + << getBaseToken(nElement)); + return nullptr; +} + +void OleObjectGraphicDataContext::onEndElement() +{ + if( getCurrentElement() == PPT_TOKEN( oleObj ) && !isMCEStateEmpty() ) + { + if (getMCEState() == MCE_STATE::FoundChoice && !mrOleObjectInfo.mbHasPicture + && mrOleObjectInfo.maShapeId.isEmpty()) + setMCEState( MCE_STATE::Started ); + } +} + +DiagramGraphicDataContext::DiagramGraphicDataContext( ContextHandler2Helper const & rParent, const ShapePtr& pShapePtr ) +: ShapeContext( rParent, ShapePtr(), pShapePtr ) +{ + pShapePtr->setDiagramType(); +} + +DiagramGraphicDataContext::~DiagramGraphicDataContext() +{ +} + +ContextHandlerRef DiagramGraphicDataContext::onCreateContext( ::sal_Int32 aElementToken, const AttributeList& rAttribs ) +{ + switch( aElementToken ) + { + case DGM_TOKEN( relIds ): + { + msDm = rAttribs.getString( R_TOKEN( dm ) ).get(); + msLo = rAttribs.getString( R_TOKEN( lo ) ).get(); + msQs = rAttribs.getString( R_TOKEN( qs ) ).get(); + msCs = rAttribs.getString( R_TOKEN( cs ) ).get(); + loadDiagram(mpShapePtr, + getFilter(), + getFragmentPathFromRelId( msDm ), + getFragmentPathFromRelId( msLo ), + getFragmentPathFromRelId( msQs ), + getFragmentPathFromRelId( msCs ), + getRelations()); + SAL_INFO("oox.drawingml", "DiagramGraphicDataContext::onCreateContext: added shape " << mpShapePtr->getName() + << " of type " << mpShapePtr->getServiceName() + << ", position: " << mpShapePtr->getPosition().X + << "," << mpShapePtr->getPosition().Y + << ", size: " << mpShapePtr->getSize().Width + << "x" << mpShapePtr->getSize().Height); + + // No DrawingML fallback, need to warn the user at the end. + if (mpShapePtr->getExtDrawings().empty()) + getFilter().setMissingExtDrawing(); + else + { + for (const auto& rRelId : mpShapePtr->getExtDrawings()) + { + // An invalid fallback reference is as bad as a missing one. + if (getFragmentPathFromRelId(rRelId).isEmpty()) + { + getFilter().setMissingExtDrawing(); + break; + } + } + } + + break; + } + default: + break; + } + + return ShapeContext::onCreateContext( aElementToken, rAttribs ); +} + +ChartGraphicDataContext::ChartGraphicDataContext( ContextHandler2Helper const & rParent, const ShapePtr& rxShape, bool bEmbedShapes ) : + ShapeContext( rParent, ShapePtr(), rxShape ), + mrChartShapeInfo( rxShape->setChartType( bEmbedShapes ) ) +{ +} + +ContextHandlerRef ChartGraphicDataContext::onCreateContext( ::sal_Int32 nElement, const AttributeList& rAttribs ) +{ + if( nElement == C_TOKEN( chart ) ) + { + mrChartShapeInfo.maFragmentPath = getFragmentPathFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) ); + } + return nullptr; +} + +} // namespace oox::drawingml + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |