1
0
Fork 0
libreoffice/oox/source/drawingml/graphicshapecontext.cxx
Daniel Baumann 8e63e14cf6
Adding upstream version 4:25.2.3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-22 16:20:04 +02:00

338 lines
13 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <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 ::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, nullptr);
case XML_wavAudioFile:
{
OUString const path(getEmbeddedWAVAudioFile(getRelations(), rAttribs));
Reference<XInputStream> xMediaStream = lcl_GetMediaStream(path, getFilter());
if (xMediaStream.is())
{
mpShapePtr->getGraphicProperties().m_xMediaStream = std::move(xMediaStream);
mpShapePtr->getGraphicProperties().m_sMediaPackageURL = lcl_GetMediaReference(path);
}
}
break;
case XML_audioFile:
case XML_videoFile:
{
OUString rPath = getRelations().getFragmentPathFromRelId(
rAttribs.getStringDefaulted(R_TOKEN(link)) );
if (!rPath.isEmpty())
{
Reference<XInputStream> xMediaStream = lcl_GetMediaStream(rPath, getFilter());
if (xMediaStream.is()) // embedded media file
{
mpShapePtr->getGraphicProperties().m_xMediaStream = std::move(xMediaStream);
mpShapePtr->getGraphicProperties().m_sMediaPackageURL
= lcl_GetMediaReference(rPath);
}
}
else
{
rPath = getRelations().getExternalTargetFromRelId(
rAttribs.getStringDefaulted(R_TOKEN(link)));
if (!rPath.isEmpty()) // linked media file
mpShapePtr->getGraphicProperties().m_sMediaPackageURL
= getFilter().getAbsoluteUrl(rPath);
}
}
break;
}
if ((getNamespace( aElementToken ) == NMSP_vml) && mpShapePtr)
{
mpShapePtr->setServiceName(u"com.sun.star.drawing.CustomShape"_ustr);
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.getStringDefaulted( XML_uri ) );
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.getStringDefaulted( R_TOKEN( id )) );
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.getStringDefaulted( R_TOKEN( dm ) );
msLo = rAttribs.getStringDefaulted( R_TOKEN( lo ) );
msQs = rAttribs.getStringDefaulted( R_TOKEN( qs ) );
msCs = rAttribs.getStringDefaulted( R_TOKEN( cs ) );
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.getStringDefaulted( R_TOKEN( id )) );
}
return nullptr;
}
} // namespace oox::drawingml
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */