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));
88  if (xMediaStream.is())
89  {
90  mpShapePtr->getGraphicProperties().m_xMediaStream = xMediaStream;
91  mpShapePtr->getGraphicProperties().m_sMediaPackageURL = lcl_GetMediaReference(path);
92  }
93  }
94  break;
95  case XML_audioFile:
96  case XML_videoFile:
97  {
98  OUString rPath = getRelations().getFragmentPathFromRelId(
99  rAttribs.getString(R_TOKEN(link)).get() );
100  if (!rPath.isEmpty())
101  {
102  Reference<XInputStream> xMediaStream = lcl_GetMediaStream(rPath, getFilter());
103  if (xMediaStream.is()) // embedded media file
104  {
105  mpShapePtr->getGraphicProperties().m_xMediaStream = xMediaStream;
106  mpShapePtr->getGraphicProperties().m_sMediaPackageURL
107  = lcl_GetMediaReference(rPath);
108  }
109  }
110  else
111  {
113  rAttribs.getString(R_TOKEN(link)).get());
114  if (!rPath.isEmpty()) // linked media file
115  mpShapePtr->getGraphicProperties().m_sMediaPackageURL
116  = getFilter().getAbsoluteUrl(rPath);
117  }
118  }
119  break;
120  }
121 
122  if ((getNamespace( aElementToken ) == NMSP_vml) && mpShapePtr)
123  {
124  mpShapePtr->setServiceName("com.sun.star.drawing.CustomShape");
125  CustomShapePropertiesPtr pCstmShpProps
126  (mpShapePtr->getCustomShapeProperties());
127 
128  pCstmShpProps->setShapePresetType( getBaseToken( aElementToken ) );
129  }
130 
131  return ShapeContext::onCreateContext( aElementToken, rAttribs );
132 }
133 
134 // CT_GraphicalObjectFrameContext
135 
136 GraphicalObjectFrameContext::GraphicalObjectFrameContext( ContextHandler2Helper& rParent, const ShapePtr& pMasterShapePtr, const ShapePtr& pShapePtr, bool bEmbedShapesInChart ) :
137  ShapeContext( rParent, pMasterShapePtr, pShapePtr ),
138  mbEmbedShapesInChart( bEmbedShapesInChart ),
139  mpParent(&rParent)
140 {
141 }
142 
144 {
145  switch( getBaseToken( aElementToken ) )
146  {
147  // CT_ShapeProperties
148  case XML_nvGraphicFramePr: // CT_GraphicalObjectFrameNonVisual
149  break;
150  case XML_xfrm: // CT_Transform2D
151  return new Transform2DContext( *this, rAttribs, *mpShapePtr );
152  case XML_graphic: // CT_GraphicalObject
153  return this;
154 
155  case XML_graphicData : // CT_GraphicalObjectData
156  {
157  OUString sUri( rAttribs.getString( XML_uri ).get() );
158  if ( sUri == "http://schemas.openxmlformats.org/presentationml/2006/ole" ||
159  sUri == "http://purl.oclc.org/ooxml/presentationml/ole" )
160  return new OleObjectGraphicDataContext( *this, mpShapePtr );
161  else if ( sUri == "http://schemas.openxmlformats.org/drawingml/2006/diagram" ||
162  sUri == "http://purl.oclc.org/ooxml/drawingml/diagram" )
163  return new DiagramGraphicDataContext( *this, mpShapePtr );
164  else if ( sUri == "http://schemas.openxmlformats.org/drawingml/2006/chart" ||
165  sUri == "http://purl.oclc.org/ooxml/drawingml/chart" )
167  else if ( sUri == "http://schemas.openxmlformats.org/drawingml/2006/table" ||
168  sUri == "http://purl.oclc.org/ooxml/drawingml/table" )
169  return new table::TableContext( *this, mpShapePtr );
170  else
171  {
172  SAL_WARN("oox.drawingml", "OOX: Ignore graphicsData of :" << sUri );
173  return nullptr;
174  }
175  }
176  break;
177  }
178 
179  return ShapeContext::onCreateContext( aElementToken, rAttribs );
180 }
181 
183 {
184  if( getCurrentElement() == PPT_TOKEN( graphicFrame ) && mpParent )
185  {
187  if( pParent )
188  pParent->importExtDrawings();
189  }
190 }
191 
193  ShapeContext( rParent, ShapePtr(), xShape ),
194  mrOleObjectInfo( xShape->setOleObjectType() )
195 {
196 }
197 
199 {
200  /* Register the OLE shape at the VML drawing, this prevents that the
201  related VML shape converts the OLE object by itself. */
202  if( !mrOleObjectInfo.maShapeId.isEmpty() )
203  if( ::oox::vml::Drawing* pVmlDrawing = getFilter().getVmlDrawing() )
204  pVmlDrawing->registerOleObject( mrOleObjectInfo );
205 }
206 
208 {
209  switch( nElement )
210  {
211  case PPT_TOKEN( oleObj ):
212  {
213  mrOleObjectInfo.maShapeId = rAttribs.getXString( XML_spid, OUString() );
214  const Relation* pRelation = getRelations().getRelationFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) );
215  OSL_ENSURE( pRelation, "OleObjectGraphicDataContext::createFastChildContext - missing relation for OLE object" );
216  if( pRelation )
217  {
218  mrOleObjectInfo.mbLinked = pRelation->mbExternal;
219  if( pRelation->mbExternal )
220  {
222  }
223  else
224  {
225  OUString aFragmentPath = getFragmentPathFromRelation( *pRelation );
226  if( !aFragmentPath.isEmpty() )
228  }
229  }
230  mrOleObjectInfo.maName = rAttribs.getXString( XML_name, OUString() );
231  mrOleObjectInfo.maProgId = rAttribs.getXString( XML_progId, OUString() );
232  mrOleObjectInfo.mbShowAsIcon = rAttribs.getBool( XML_showAsIcon, false );
233  mrOleObjectInfo.mbHasPicture = false; // Initialize as false
234  return this;
235  }
236  break;
237 
238  case PPT_TOKEN( embed ):
239  OSL_ENSURE( !mrOleObjectInfo.mbLinked, "OleObjectGraphicDataContext::createFastChildContext - unexpected child element" );
240  break;
241 
242  case PPT_TOKEN( link ):
243  OSL_ENSURE( mrOleObjectInfo.mbLinked, "OleObjectGraphicDataContext::createFastChildContext - unexpected child element" );
244  mrOleObjectInfo.mbAutoUpdate = rAttribs.getBool( XML_updateAutomatic, false );
245  break;
246  case PPT_TOKEN( pic ):
247  mrOleObjectInfo.mbHasPicture = true; // Set true if ole object has picture element.
248  return new GraphicShapeContext( *this, mpMasterShapePtr, mpShapePtr );
249  }
250  SAL_WARN("oox", "OleObjectGraphicDataContext::onCreateContext: unhandled element: "
251  << getBaseToken(nElement));
252  return nullptr;
253 }
254 
256 {
257  if( getCurrentElement() == PPT_TOKEN( oleObj ) && !isMCEStateEmpty() )
258  {
261  }
262 }
263 
265 : ShapeContext( rParent, ShapePtr(), pShapePtr )
266 {
267  pShapePtr->setDiagramType();
268 }
269 
271 {
272 }
273 
275 {
276  switch( aElementToken )
277  {
278  case DGM_TOKEN( relIds ):
279  {
280  msDm = rAttribs.getString( R_TOKEN( dm ) ).get();
281  msLo = rAttribs.getString( R_TOKEN( lo ) ).get();
282  msQs = rAttribs.getString( R_TOKEN( qs ) ).get();
283  msCs = rAttribs.getString( R_TOKEN( cs ) ).get();
285  getFilter(),
290  getRelations());
291  SAL_INFO("oox.drawingml", "DiagramGraphicDataContext::onCreateContext: added shape " << mpShapePtr->getName()
292  << " of type " << mpShapePtr->getServiceName()
293  << ", position: " << mpShapePtr->getPosition().X
294  << "," << mpShapePtr->getPosition().Y
295  << ", size: " << mpShapePtr->getSize().Width
296  << "x" << mpShapePtr->getSize().Height);
297 
298  // No DrawingML fallback, need to warn the user at the end.
299  if (mpShapePtr->getExtDrawings().empty())
301  else
302  {
303  for (const auto& rRelId : mpShapePtr->getExtDrawings())
304  {
305  // An invalid fallback reference is as bad as a missing one.
306  if (getFragmentPathFromRelId(rRelId).isEmpty())
307  {
309  break;
310  }
311  }
312  }
313 
314  break;
315  }
316  default:
317  break;
318  }
319 
320  return ShapeContext::onCreateContext( aElementToken, rAttribs );
321 }
322 
323 ChartGraphicDataContext::ChartGraphicDataContext( ContextHandler2Helper const & rParent, const ShapePtr& rxShape, bool bEmbedShapes ) :
324  ShapeContext( rParent, ShapePtr(), rxShape ),
325  mrChartShapeInfo( rxShape->setChartType( bEmbedShapes ) )
326 {
327 }
328 
330 {
331  if( nElement == C_TOKEN( chart ) )
332  {
333  mrChartShapeInfo.maFragmentPath = getFragmentPathFromRelId( rAttribs.getString( R_TOKEN( id ), OUString() ) );
334  }
335  return nullptr;
336 }
337 
338 } // namespace oox::drawingml
339 
340 /* 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:93
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
OUString getExternalTargetFromRelId(const OUString &rRelId) const
Returns the external target of the relation with the passed relation identifier.
Definition: relations.cxx:87
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:63
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:382
ChartGraphicDataContext(::oox::core::ContextHandler2Helper const &rParent, const ShapePtr &rxShape, bool bEmbedShapes)
const Type & get() const
Definition: helper.hxx:184
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:298
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:132
::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:327
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:268
#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.