LibreOffice Module oox (master)  1
graphicshapecontext.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <sal/config.h>
21 
22 #include <string_view>
23 
25 
26 #include <osl/diagnose.h>
27 #include <sal/log.hxx>
28 
37 #include <oox/vml/vmldrawing.hxx>
40 #include <oox/token/namespaces.hxx>
41 #include <oox/token/tokens.hxx>
42 
43 using namespace ::com::sun::star;
44 using namespace ::com::sun::star::io;
45 using namespace ::com::sun::star::uno;
46 using namespace ::com::sun::star::lang;
47 using namespace ::com::sun::star::beans;
48 using namespace ::com::sun::star::xml::sax;
49 using namespace ::oox::core;
50 
51 static uno::Reference<io::XInputStream>
52 lcl_GetMediaStream(const OUString& rStream, const oox::core::XmlFilterBase& rFilter)
53 {
54  if (rStream.isEmpty())
55  return nullptr;
56 
57  Reference< XInputStream > xInStrm( rFilter.openInputStream(rStream), UNO_SET_THROW );
58  return xInStrm;
59 }
60 
61 static OUString lcl_GetMediaReference(std::u16string_view rStream)
62 {
63  return rStream.empty() ? OUString() : OUString::Concat("vnd.sun.star.Package:") + rStream;
64 }
65 
66 namespace oox::drawingml {
67 
68 // CT_Picture
69 
70 GraphicShapeContext::GraphicShapeContext( ContextHandler2Helper const & rParent, const ShapePtr& pMasterShapePtr, const ShapePtr& pShapePtr )
71 : ShapeContext( rParent, pMasterShapePtr, pShapePtr )
72 {
73 }
74 
75 ContextHandlerRef GraphicShapeContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs )
76 {
77  switch( getBaseToken( aElementToken ) )
78  {
79  // CT_ShapeProperties
80  case XML_xfrm:
81  return new Transform2DContext( *this, rAttribs, *mpShapePtr );
82  case XML_blipFill:
83  return new BlipFillContext( *this, rAttribs, mpShapePtr->getGraphicProperties().maBlipProps );
84  case XML_wavAudioFile:
85  {
86  OUString const path(getEmbeddedWAVAudioFile(getRelations(), rAttribs));
87  mpShapePtr->getGraphicProperties().m_xMediaStream =
89  mpShapePtr->getGraphicProperties().m_sMediaPackageURL =
91  }
92  break;
93  case XML_audioFile:
94  case XML_videoFile:
95  {
96  OUString rPath = getRelations().getFragmentPathFromRelId(
97  rAttribs.getString(R_TOKEN(link)).get() );
98  mpShapePtr->getGraphicProperties().m_xMediaStream =
99  lcl_GetMediaStream(rPath, getFilter());
100  mpShapePtr->getGraphicProperties().m_sMediaPackageURL =
101  lcl_GetMediaReference(rPath);
102  }
103  break;
104  }
105 
106  if ((getNamespace( aElementToken ) == NMSP_vml) && mpShapePtr)
107  {
108  mpShapePtr->setServiceName("com.sun.star.drawing.CustomShape");
109  CustomShapePropertiesPtr pCstmShpProps
110  (mpShapePtr->getCustomShapeProperties());
111 
112  pCstmShpProps->setShapePresetType( getBaseToken( aElementToken ) );
113  }
114 
115  return ShapeContext::onCreateContext( aElementToken, rAttribs );
116 }
117 
118 // CT_GraphicalObjectFrameContext
119 
120 GraphicalObjectFrameContext::GraphicalObjectFrameContext( ContextHandler2Helper& rParent, const ShapePtr& pMasterShapePtr, const ShapePtr& pShapePtr, bool bEmbedShapesInChart ) :
121  ShapeContext( rParent, pMasterShapePtr, pShapePtr ),
122  mbEmbedShapesInChart( bEmbedShapesInChart ),
123  mpParent(&rParent)
124 {
125 }
126 
128 {
129  switch( getBaseToken( aElementToken ) )
130  {
131  // CT_ShapeProperties
132  case XML_nvGraphicFramePr: // CT_GraphicalObjectFrameNonVisual
133  break;
134  case XML_xfrm: // CT_Transform2D
135  return new Transform2DContext( *this, rAttribs, *mpShapePtr );
136  case XML_graphic: // CT_GraphicalObject
137  return this;
138 
139  case XML_graphicData : // CT_GraphicalObjectData
140  {
141  OUString sUri( rAttribs.getString( XML_uri ).get() );
142  if ( sUri == "http://schemas.openxmlformats.org/presentationml/2006/ole" ||
143  sUri == "http://purl.oclc.org/ooxml/presentationml/ole" )
144  return new OleObjectGraphicDataContext( *this, mpShapePtr );
145  else if ( sUri == "http://schemas.openxmlformats.org/drawingml/2006/diagram" ||
146  sUri == "http://purl.oclc.org/ooxml/drawingml/diagram" )
147  return new DiagramGraphicDataContext( *this, mpShapePtr );
148  else if ( sUri == "http://schemas.openxmlformats.org/drawingml/2006/chart" ||
149  sUri == "http://purl.oclc.org/ooxml/drawingml/chart" )
151  else if ( sUri == "http://schemas.openxmlformats.org/drawingml/2006/table" ||
152  sUri == "http://purl.oclc.org/ooxml/drawingml/table" )
153  return new table::TableContext( *this, mpShapePtr );
154  else
155  {
156  SAL_WARN("oox.drawingml", "OOX: Ignore graphicsData of :" << sUri );
157  return nullptr;
158  }
159  }
160  break;
161  }
162 
163  return ShapeContext::onCreateContext( aElementToken, rAttribs );
164 }
165 
167 {
168  if( getCurrentElement() == PPT_TOKEN( graphicFrame ) && mpParent )
169  {
171  if( pParent )
172  pParent->importExtDrawings();
173  }
174 }
175 
177  ShapeContext( rParent, ShapePtr(), xShape ),
178  mrOleObjectInfo( xShape->setOleObjectType() )
179 {
180 }
181 
183 {
184  /* Register the OLE shape at the VML drawing, this prevents that the
185  related VML shape converts the OLE object by itself. */
186  if( !mrOleObjectInfo.maShapeId.isEmpty() )
187  if( ::oox::vml::Drawing* pVmlDrawing = getFilter().getVmlDrawing() )
188  pVmlDrawing->registerOleObject( mrOleObjectInfo );
189 }
190 
192 {
193  switch( nElement )
194  {
195  case PPT_TOKEN( oleObj ):
196  {
197  mrOleObjectInfo.maShapeId = rAttribs.getXString( XML_spid, OUString() );
198  const Relation* pRelation = getRelations().getRelationFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) );
199  OSL_ENSURE( pRelation, "OleObjectGraphicDataContext::createFastChildContext - missing relation for OLE object" );
200  if( pRelation )
201  {
202  mrOleObjectInfo.mbLinked = pRelation->mbExternal;
203  if( pRelation->mbExternal )
204  {
206  }
207  else
208  {
209  OUString aFragmentPath = getFragmentPathFromRelation( *pRelation );
210  if( !aFragmentPath.isEmpty() )
212  }
213  }
214  mrOleObjectInfo.maName = rAttribs.getXString( XML_name, OUString() );
215  mrOleObjectInfo.maProgId = rAttribs.getXString( XML_progId, OUString() );
216  mrOleObjectInfo.mbShowAsIcon = rAttribs.getBool( XML_showAsIcon, false );
217  mrOleObjectInfo.mbHasPicture = false; // Initialize as false
218  return this;
219  }
220  break;
221 
222  case PPT_TOKEN( embed ):
223  OSL_ENSURE( !mrOleObjectInfo.mbLinked, "OleObjectGraphicDataContext::createFastChildContext - unexpected child element" );
224  break;
225 
226  case PPT_TOKEN( link ):
227  OSL_ENSURE( mrOleObjectInfo.mbLinked, "OleObjectGraphicDataContext::createFastChildContext - unexpected child element" );
228  mrOleObjectInfo.mbAutoUpdate = rAttribs.getBool( XML_updateAutomatic, false );
229  break;
230  case PPT_TOKEN( pic ):
231  mrOleObjectInfo.mbHasPicture = true; // Set true if ole object has picture element.
232  return new GraphicShapeContext( *this, mpMasterShapePtr, mpShapePtr );
233  }
234  SAL_WARN("oox", "OleObjectGraphicDataContext::onCreateContext: unhandled element: "
235  << getBaseToken(nElement));
236  return nullptr;
237 }
238 
240 {
241  if( getCurrentElement() == PPT_TOKEN( oleObj ) && !isMCEStateEmpty() )
242  {
245  }
246 }
247 
249 : ShapeContext( rParent, ShapePtr(), pShapePtr )
250 {
251  pShapePtr->setDiagramType();
252 }
253 
255 {
256 }
257 
259 {
260  switch( aElementToken )
261  {
262  case DGM_TOKEN( relIds ):
263  {
264  msDm = rAttribs.getString( R_TOKEN( dm ) ).get();
265  msLo = rAttribs.getString( R_TOKEN( lo ) ).get();
266  msQs = rAttribs.getString( R_TOKEN( qs ) ).get();
267  msCs = rAttribs.getString( R_TOKEN( cs ) ).get();
269  getFilter(),
274  getRelations());
275  SAL_INFO("oox.drawingml", "DiagramGraphicDataContext::onCreateContext: added shape " << mpShapePtr->getName()
276  << " of type " << mpShapePtr->getServiceName()
277  << ", position: " << mpShapePtr->getPosition().X
278  << "," << mpShapePtr->getPosition().Y
279  << ", size: " << mpShapePtr->getSize().Width
280  << "x" << mpShapePtr->getSize().Height);
281 
282  // No DrawingML fallback, need to warn the user at the end.
283  if (mpShapePtr->getExtDrawings().empty())
285  else
286  {
287  for (const auto& rRelId : mpShapePtr->getExtDrawings())
288  {
289  // An invalid fallback reference is as bad as a missing one.
290  if (getFragmentPathFromRelId(rRelId).isEmpty())
291  {
293  break;
294  }
295  }
296  }
297 
298  break;
299  }
300  default:
301  break;
302  }
303 
304  return ShapeContext::onCreateContext( aElementToken, rAttribs );
305 }
306 
307 ChartGraphicDataContext::ChartGraphicDataContext( ContextHandler2Helper const & rParent, const ShapePtr& rxShape, bool bEmbedShapes ) :
308  ShapeContext( rParent, ShapePtr(), rxShape ),
309  mrChartShapeInfo( rxShape->setChartType( bEmbedShapes ) )
310 {
311 }
312 
314 {
315  if( nElement == C_TOKEN( chart ) )
316  {
317  mrChartShapeInfo.maFragmentPath = getFragmentPathFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) );
318  }
319  return nullptr;
320 }
321 
322 } // namespace oox::drawingml
323 
324 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
GraphicShapeContext(::oox::core::ContextHandler2Helper const &rParent, const ShapePtr &pMasterShapePtr, const ShapePtr &pShapePtr)
OUString maShapeId
Shape identifier for shape lookup.
Definition: vmldrawing.hxx:64
Context handler that imports the a:blipFill element.
OUString getFragmentPathFromRelation(const Relation &rRelation) const
Returns the full fragment path for the target of the passed relation.
virtual void onEndElement() override
Will be called when the current element is about to be left.
OUString maFragmentPath
Path to related XML stream, e.g. for charts.
Definition: shape.hxx:89
OptValue< bool > getBool(sal_Int32 nAttrToken) const
Returns the boolean value of the specified attribute.
static OUString lcl_GetMediaReference(std::u16string_view rStream)
DiagramGraphicDataContext(::oox::core::ContextHandler2Helper const &rParent, const ShapePtr &pShapePtr)
OptValue< OUString > getXString(sal_Int32 nAttrToken) const
Returns the string value of the specified attribute.
OUString maTargetLink
Path to external data for linked OLE object.
exports com.sun.star. embed
virtual ::oox::core::ContextHandlerRef onCreateContext(::sal_Int32 Element, const ::oox::AttributeList &rAttribs) override
virtual ::oox::core::ContextHandlerRef onCreateContext(::sal_Int32 Element, const ::oox::AttributeList &rAttribs) override
const Relation * getRelationFromRelId(const OUString &rId) const
Returns the relation with the passed relation identifier.
Definition: relations.cxx:61
OptValue< OUString > getString(sal_Int32 nAttrToken) const
Returns the string value of the specified attribute.
bool importBinaryData(StreamDataSequence &orDataSeq, const OUString &rStreamName)
Imports the raw binary data from the specified stream.
Definition: filterbase.cxx:379
ChartGraphicDataContext(::oox::core::ContextHandler2Helper const &rParent, const ShapePtr &rxShape, bool bEmbedShapes)
const Type & get() const
Definition: helper.hxx:185
bool mbShowAsIcon
True = show as icon, false = show contents.
bool mbHasPicture
Ole object requires a picture element according to spec.>
const Relations & getRelations() const
Returns the relations of the current fragment.
sal_Int32 getCurrentElement() const
Returns the identifier of the currently processed element.
virtual ::oox::core::ContextHandlerRef onCreateContext(::sal_Int32 Element, const ::oox::AttributeList &rAttribs) override
virtual void onEndElement() override
Will be called when the current element is about to be left.
OUString getFragmentPathFromRelId(const OUString &rRelId) const
Returns the full fragment path for the passed relation identifier.
StreamDataSequence maEmbeddedData
Data of an embedded OLE object.
virtual ::oox::vml::Drawing * getVmlDrawing()=0
Has to be implemented by each filter to return the collection of VML shapes.
Provides access to attribute values of an element.
virtual ::oox::core::ContextHandlerRef onCreateContext(sal_Int32 nElement, const ::oox::AttributeList &rAttribs) override
virtual ::oox::core::ContextHandlerRef onCreateContext(::sal_Int32 Element, const ::oox::AttributeList &rAttribs) override
void setMissingExtDrawing()
Signal that an MSO 2007-created SmartArt was found, need to warn the user about it.
OUString maName
Programmatical name of the OLE object.
Definition: vmldrawing.hxx:65
static uno::Reference< io::XInputStream > lcl_GetMediaStream(const OUString &rStream, const oox::core::XmlFilterBase &rFilter)
RegionData_Impl * mpParent
void loadDiagram(ShapePtr const &pShape, core::XmlFilterBase &rFilter, const OUString &rDataModelPath, const OUString &rLayoutPath, const OUString &rQStylePath, const OUString &rColorStylePath, const oox::core::Relations &rRelations)
load diagram data, and put resulting graphic into shape
Definition: diagram.cxx:246
OUString getEmbeddedWAVAudioFile(const core::Relations &rRelations, const AttributeList &rAttribs)
OUString getFragmentPathFromRelId(const OUString &rRelId) const
Returns the full fragment path for the passed relation identifier.
Definition: relations.cxx:130
::oox::core::ContextHandler2Helper * mpParent
OleObjectGraphicDataContext(::oox::core::ContextHandler2Helper const &rParent, const ShapePtr &pShapePtr)
#define SAL_INFO(area, stream)
XmlFilterBase & getFilter() const
Returns the filter instance.
css::uno::Reference< css::io::XInputStream > openInputStream(const OUString &rStreamName) const
Opens and returns the specified input stream from the base storage.
Definition: filterbase.cxx:324
void setMCEState(MCE_STATE aState)
GraphicalObjectFrameContext(::oox::core::ContextHandler2Helper &rParent, const ShapePtr &pMasterShapePtr, const ShapePtr &pShapePtr, bool bEmbedShapesInChart)
Represents the collection of VML shapes for a complete draw page.
Definition: vmldrawing.hxx:93
context to import a CT_Transform2D
std::shared_ptr< CustomShapeProperties > CustomShapePropertiesPtr
OUString getAbsoluteUrl(const OUString &rUrl) const
Returns an absolute URL for the passed relative or absolute URL.
Definition: filterbase.cxx:265
#define SAL_WARN(area, stream)
std::shared_ptr< Shape > ShapePtr
virtual ::oox::core::ContextHandlerRef onCreateContext(::sal_Int32 Element, const ::oox::AttributeList &rAttribs) override
Helper class that provides a context stack.
bool mbLinked
True = linked OLE object, false = embedded OLE object.