LibreOffice Module oox (master)  1
shapes.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 <sal/log.hxx>
23 #include <filter/msfilter/util.hxx>
25 #include <oox/export/shapes.hxx>
26 #include <oox/export/utils.hxx>
27 #include <oox/token/namespaces.hxx>
29 #include <oox/token/tokens.hxx>
30 
31 #include <initializer_list>
32 #include <string_view>
33 
34 #include <com/sun/star/beans/PropertyValues.hpp>
35 #include <com/sun/star/beans/XPropertySet.hpp>
36 #include <com/sun/star/beans/XPropertySetInfo.hpp>
37 #include <com/sun/star/beans/XPropertyState.hpp>
38 #include <com/sun/star/container/XChild.hpp>
39 #include <com/sun/star/document/XExporter.hpp>
40 #include <com/sun/star/document/XStorageBasedDocument.hpp>
41 #include <com/sun/star/drawing/CircleKind.hpp>
42 #include <com/sun/star/drawing/FillStyle.hpp>
43 #include <com/sun/star/drawing/ConnectorType.hpp>
44 #include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp>
45 #include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp>
46 #include <com/sun/star/embed/EmbedStates.hpp>
47 #include <com/sun/star/embed/XEmbeddedObject.hpp>
48 #include <com/sun/star/embed/XEmbedPersist.hpp>
49 #include <com/sun/star/frame/XStorable.hpp>
50 #include <com/sun/star/graphic/XGraphic.hpp>
51 #include <com/sun/star/i18n/ScriptType.hpp>
52 #include <com/sun/star/io/XOutputStream.hpp>
53 #include <com/sun/star/text/XSimpleText.hpp>
54 #include <com/sun/star/text/XText.hpp>
55 #include <com/sun/star/table/XTable.hpp>
56 #include <com/sun/star/table/XMergeableCell.hpp>
57 #include <com/sun/star/chart2/XChartDocument.hpp>
58 #include <com/sun/star/frame/XModel.hpp>
59 #include <com/sun/star/uno/XComponentContext.hpp>
60 #include <tools/globname.hxx>
61 #include <comphelper/classids.hxx>
64 #include <sot/exchange.hxx>
65 #include <utility>
66 #include <vcl/graph.hxx>
67 #include <vcl/outdev.hxx>
69 #include <svx/svdoashp.hxx>
70 #include <svx/svdoole2.hxx>
71 #include <tools/diagnose_ex.h>
72 #include <svx/unoapi.hxx>
74 #include <oox/mathml/export.hxx>
77 
78 using namespace ::css;
79 using namespace ::css::beans;
80 using namespace ::css::uno;
81 using namespace ::css::drawing;
82 using namespace ::css::i18n;
83 using namespace ::css::table;
84 using namespace ::css::container;
85 using namespace ::css::document;
86 using namespace ::css::text;
87 
88 using ::css::io::XOutputStream;
89 using ::css::chart2::XChartDocument;
90 using ::css::frame::XModel;
91 
92 using ::oox::core::XmlFilterBase;
93 using ::sax_fastparser::FSHelperPtr;
94 
95 
96 namespace oox {
97 
98 static void lcl_ConvertProgID(OUString const& rProgID,
99  OUString & o_rMediaType, OUString & o_rRelationType, OUString & o_rFileExtension)
100 {
101  if (rProgID == "Excel.Sheet.12")
102  {
103  o_rMediaType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
104  o_rRelationType = oox::getRelationship(Relationship::PACKAGE);
105  o_rFileExtension = "xlsx";
106  }
107  else if (rProgID.startsWith("Excel.SheetBinaryMacroEnabled.12") )
108  {
109  o_rMediaType = "application/vnd.ms-excel.sheet.binary.macroEnabled.12";
110  o_rRelationType = oox::getRelationship(Relationship::PACKAGE);
111  o_rFileExtension = "xlsb";
112  }
113  else if (rProgID.startsWith("Excel.SheetMacroEnabled.12"))
114  {
115  o_rMediaType = "application/vnd.ms-excel.sheet.macroEnabled.12";
116  o_rRelationType = oox::getRelationship(Relationship::PACKAGE);
117  o_rFileExtension = "xlsm";
118  }
119  else if (rProgID.startsWith("Excel.Sheet"))
120  {
121  o_rMediaType = "application/vnd.ms-excel";
123  o_rFileExtension = "xls";
124  }
125  else if (rProgID == "PowerPoint.Show.12")
126  {
127  o_rMediaType = "application/vnd.openxmlformats-officedocument.presentationml.presentation";
128  o_rRelationType = oox::getRelationship(Relationship::PACKAGE);
129  o_rFileExtension = "pptx";
130  }
131  else if (rProgID == "PowerPoint.ShowMacroEnabled.12")
132  {
133  o_rMediaType = "application/vnd.ms-powerpoint.presentation.macroEnabled.12";
134  o_rRelationType = oox::getRelationship(Relationship::PACKAGE);
135  o_rFileExtension = "pptm";
136  }
137  else if (rProgID.startsWith("PowerPoint.Show"))
138  {
139  o_rMediaType = "application/vnd.ms-powerpoint";
141  o_rFileExtension = "ppt";
142  }
143  else if (rProgID.startsWith("PowerPoint.Slide.12"))
144  {
145  o_rMediaType = "application/vnd.openxmlformats-officedocument.presentationml.slide";
146  o_rRelationType = oox::getRelationship(Relationship::PACKAGE);
147  o_rFileExtension = "sldx";
148  }
149  else if (rProgID == "PowerPoint.SlideMacroEnabled.12")
150  {
151  o_rMediaType = "application/vnd.ms-powerpoint.slide.macroEnabled.12";
152  o_rRelationType = oox::getRelationship(Relationship::PACKAGE);
153  o_rFileExtension = "sldm";
154  }
155  else if (rProgID == "Word.DocumentMacroEnabled.12")
156  {
157  o_rMediaType = "application/vnd.ms-word.document.macroEnabled.12";
158  o_rRelationType = oox::getRelationship(Relationship::PACKAGE);
159  o_rFileExtension = "docm";
160  }
161  else if (rProgID == "Word.Document.12")
162  {
163  o_rMediaType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
164  o_rRelationType = oox::getRelationship(Relationship::PACKAGE);
165  o_rFileExtension = "docx";
166  }
167  else if (rProgID == "Word.Document.8")
168  {
169  o_rMediaType = "application/msword";
171  o_rFileExtension = "doc";
172  }
173  else if (rProgID == "Excel.Chart.8")
174  {
175  o_rMediaType = "application/vnd.ms-excel";
177  o_rFileExtension = "xls";
178  }
179  else if (rProgID == "AcroExch.Document.11")
180  {
181  o_rMediaType = "application/pdf";
183  o_rFileExtension = "pdf";
184  }
185  else
186  {
187  o_rMediaType = "application/vnd.openxmlformats-officedocument.oleObject";
189  o_rFileExtension = "bin";
190  }
191 }
192 
193 static uno::Reference<io::XInputStream> lcl_StoreOwnAsOOXML(
194  uno::Reference<uno::XComponentContext> const& xContext,
195  uno::Reference<embed::XEmbeddedObject> const& xObj,
196  char const*& o_rpProgID,
197  OUString & o_rMediaType, OUString & o_rRelationType, OUString & o_rSuffix)
198 {
199  static struct {
200  struct {
201  sal_uInt32 n1;
202  sal_uInt16 n2, n3;
203  sal_uInt8 b8, b9, b10, b11, b12, b13, b14, b15;
204  } ClassId;
205  char const* pFilterName;
206  char const* pMediaType;
207  char const* pProgID;
208  char const* pSuffix;
209  } const s_Mapping[] = {
210  { {SO3_SW_CLASSID_60}, "MS Word 2007 XML", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "Word.Document.12", "docx" },
211  { {SO3_SC_CLASSID_60}, "Calc MS Excel 2007 XML", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "Excel.Sheet.12", "xlsx" },
212  { {SO3_SIMPRESS_CLASSID_60}, "Impress MS PowerPoint 2007 XML", "application/vnd.openxmlformats-officedocument.presentationml.presentation", "PowerPoint.Show.12", "pptx" },
213  // FIXME: Draw does not appear to have a MSO format export filter?
214 // { {SO3_SDRAW_CLASSID}, "", "", "", "" },
215  { {SO3_SCH_CLASSID_60}, "unused", "", "", "" },
216  { {SO3_SM_CLASSID_60}, "unused", "", "", "" },
217  };
218 
219  const char * pFilterName(nullptr);
220  SvGlobalName const classId(xObj->getClassID());
221  for (auto & i : s_Mapping)
222  {
223  auto const& rId(i.ClassId);
224  SvGlobalName const temp(rId.n1, rId.n2, rId.n3, rId.b8, rId.b9, rId.b10, rId.b11, rId.b12, rId.b13, rId.b14, rId.b15);
225  if (temp == classId)
226  {
227  assert(SvGlobalName(SO3_SCH_CLASSID_60) != classId); // chart should be written elsewhere!
228  assert(SvGlobalName(SO3_SM_CLASSID_60) != classId); // formula should be written elsewhere!
229  pFilterName = i.pFilterName;
230  o_rMediaType = OUString::createFromAscii(i.pMediaType);
231  o_rpProgID = i.pProgID;
232  o_rSuffix = OUString::createFromAscii(i.pSuffix);
233  o_rRelationType = oox::getRelationship(Relationship::PACKAGE);
234  break;
235  }
236  }
237 
238  if (!pFilterName)
239  {
240  SAL_WARN("oox.shape", "oox::GetOLEObjectStream: unknown ClassId " << classId.GetHexName());
241  return nullptr;
242  }
243 
244  if (embed::EmbedStates::LOADED == xObj->getCurrentState())
245  {
246  xObj->changeState(embed::EmbedStates::RUNNING);
247  }
248  // use a temp stream - while it would work to store directly to a
249  // fragment stream, an error during export means we'd have to delete it
250  uno::Reference<io::XStream> const xTempStream(
251  xContext->getServiceManager()->createInstanceWithContext(
252  "com.sun.star.comp.MemoryStream", xContext),
253  uno::UNO_QUERY_THROW);
254  uno::Sequence<beans::PropertyValue> args( comphelper::InitPropertySequence({
255  { "OutputStream", Any(xTempStream->getOutputStream()) },
256  { "FilterName", Any(OUString::createFromAscii(pFilterName)) }
257  }));
258  uno::Reference<frame::XStorable> xStorable(xObj->getComponent(), uno::UNO_QUERY);
259  try
260  {
261  xStorable->storeToURL("private:stream", args);
262  }
263  catch (uno::Exception const&)
264  {
265  TOOLS_WARN_EXCEPTION("oox.shape", "oox::GetOLEObjectStream");
266  return nullptr;
267  }
268  xTempStream->getOutputStream()->closeOutput();
269  return xTempStream->getInputStream();
270 }
271 
272 uno::Reference<io::XInputStream> GetOLEObjectStream(
273  uno::Reference<uno::XComponentContext> const& xContext,
274  uno::Reference<embed::XEmbeddedObject> const& xObj,
275  OUString const& i_rProgID,
276  OUString & o_rMediaType,
277  OUString & o_rRelationType,
278  OUString & o_rSuffix,
279  const char *& o_rpProgID)
280 {
281  uno::Reference<io::XInputStream> xInStream;
282  try
283  {
284  uno::Reference<document::XStorageBasedDocument> const xParent(
285  uno::Reference<container::XChild>(xObj, uno::UNO_QUERY_THROW)->getParent(),
286  uno::UNO_QUERY_THROW);
287  uno::Reference<embed::XStorage> const xParentStorage(xParent->getDocumentStorage());
288  OUString const entryName(
289  uno::Reference<embed::XEmbedPersist>(xObj, uno::UNO_QUERY_THROW)->getEntryName());
290 
291  if (xParentStorage->isStreamElement(entryName))
292  {
293  lcl_ConvertProgID(i_rProgID, o_rMediaType, o_rRelationType, o_rSuffix);
294  xInStream = xParentStorage->cloneStreamElement(entryName)->getInputStream();
295  // TODO: make it possible to take the sMediaType from the stream
296  }
297  else // the object is ODF - either the whole document is
298  { // ODF, or the OLE was edited so it was converted to ODF
299  xInStream = lcl_StoreOwnAsOOXML(xContext, xObj,
300  o_rpProgID, o_rMediaType, o_rRelationType, o_rSuffix);
301  }
302  }
303  catch (uno::Exception const&)
304  {
305  TOOLS_WARN_EXCEPTION("oox.shape", "oox::GetOLEObjectStream");
306  }
307  return xInStream;
308 }
309 
310 } // namespace oox
311 
312 namespace oox::drawingml {
313 
314 #define GETA(propName) \
315  GetProperty( rXPropSet, #propName)
316 
317 #define GETAD(propName) \
318  ( GetPropertyAndState( rXPropSet, rXPropState, #propName, eState ) && eState == beans::PropertyState_DIRECT_VALUE )
319 
320 #define GET(variable, propName) \
321  if ( GETA(propName) ) \
322  mAny >>= variable;
323 
324 ShapeExport::ShapeExport( sal_Int32 nXmlNamespace, FSHelperPtr pFS, ShapeHashMap* pShapeMap, XmlFilterBase* pFB, DocumentType eDocumentType, DMLTextExport* pTextExport )
325  : DrawingML( std::move(pFS), pFB, eDocumentType, pTextExport )
326  , m_nEmbeddedObjects(0)
327  , mnShapeIdMax( 1 )
328  , mnXmlNamespace( nXmlNamespace )
329  , maMapModeSrc( MapUnit::Map100thMM )
330  , maMapModeDest( MapUnit::MapInch, Point(), Fraction( 1, 576 ), Fraction( 1, 576 ) )
331  , mpShapeMap( pShapeMap ? pShapeMap : &maShapeMap )
332 {
333  mpURLTransformer = std::make_shared<URLTransformer>();
334 }
335 
336 void ShapeExport::SetURLTranslator(const std::shared_ptr<URLTransformer>& pTransformer)
337 {
338  mpURLTransformer = pTransformer;
339 }
340 
341 awt::Size ShapeExport::MapSize( const awt::Size& rSize ) const
342 {
343  Size aRetSize( OutputDevice::LogicToLogic( Size( rSize.Width, rSize.Height ), maMapModeSrc, maMapModeDest ) );
344 
345  if ( !aRetSize.Width() )
346  aRetSize.AdjustWidth( 1 );
347  if ( !aRetSize.Height() )
348  aRetSize.AdjustHeight( 1 );
349  return awt::Size( aRetSize.Width(), aRetSize.Height() );
350 }
351 
352 static bool IsNonEmptySimpleText(const Reference<XInterface>& xIface)
353 {
354  if (Reference<XSimpleText> xText{ xIface, UNO_QUERY })
355  return xText->getString().getLength();
356 
357  return false;
358 }
359 
361 {
362  Reference< XPropertySet > xPropSet( xIface, UNO_QUERY );
363 
364  if( xPropSet.is() )
365  {
366  Reference< XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
367  if ( xPropSetInfo.is() )
368  {
369  if ( xPropSetInfo->hasPropertyByName( "IsEmptyPresentationObject" ) )
370  {
371  bool bIsEmptyPresObj = false;
372  if ( xPropSet->getPropertyValue( "IsEmptyPresentationObject" ) >>= bIsEmptyPresObj )
373  {
374  SAL_INFO("oox.shape", "empty presentation object " << bIsEmptyPresObj << " , props:");
375  if( bIsEmptyPresObj )
376  return true;
377  }
378  }
379 
380  if ( xPropSetInfo->hasPropertyByName( "IsPresentationObject" ) )
381  {
382  bool bIsPresObj = false;
383  if ( xPropSet->getPropertyValue( "IsPresentationObject" ) >>= bIsPresObj )
384  {
385  SAL_INFO("oox.shape", "presentation object " << bIsPresObj << ", props:");
386  if( bIsPresObj )
387  return true;
388  }
389  }
390  }
391  }
392 
393  return IsNonEmptySimpleText(xIface);
394 }
395 
397 {
398  SAL_INFO("oox.shape", "write polypolygon shape");
399 
400  FSHelperPtr pFS = GetFS();
401  pFS->startElementNS(mnXmlNamespace, (GetDocumentType() != DOCUMENT_DOCX ? XML_sp : XML_wsp));
402 
404  awt::Point aPos = xShape->getPosition();
405  // Position is relative to group for child elements in Word, but absolute in API.
406  if (GetDocumentType() == DOCUMENT_DOCX && m_xParent.is())
407  {
408  awt::Point aParentPos = m_xParent->getPosition();
409  aPos.X -= aParentPos.X;
410  aPos.Y -= aParentPos.Y;
411  }
412  awt::Size aSize = xShape->getSize();
413  tools::Rectangle aRect(Point(aPos.X, aPos.Y), Size(aSize.Width, aSize.Height));
414 
415 #if OSL_DEBUG_LEVEL > 0
416  awt::Size size = MapSize( awt::Size( aRect.GetWidth(), aRect.GetHeight() ) );
417  SAL_INFO("oox.shape", "poly count " << aPolyPolygon.Count());
418  SAL_INFO("oox.shape", "size: " << size.Width << " x " << size.Height);
419 #endif
420 
421  // non visual shape properties
423  {
424  pFS->startElementNS(mnXmlNamespace, XML_nvSpPr);
425  pFS->singleElementNS( mnXmlNamespace, XML_cNvPr,
426  XML_id, OString::number(GetNewShapeID(xShape)),
427  XML_name, GetShapeName(xShape));
428  }
429  pFS->singleElementNS(mnXmlNamespace, XML_cNvSpPr);
431  {
432  WriteNonVisualProperties( xShape );
433  pFS->endElementNS( mnXmlNamespace, XML_nvSpPr );
434  }
435 
436  // visual shape properties
437  pFS->startElementNS(mnXmlNamespace, XML_spPr);
438  WriteTransformation( xShape, aRect, XML_a );
439  WritePolyPolygon(xShape, aPolyPolygon, bClosed);
440  Reference< XPropertySet > xProps( xShape, UNO_QUERY );
441  if( xProps.is() ) {
442  if( bClosed )
443  WriteFill( xProps );
444  WriteOutline( xProps );
445  }
446 
447  pFS->endElementNS( mnXmlNamespace, XML_spPr );
448 
449  // write text
450  WriteTextBox( xShape, mnXmlNamespace );
451 
452  pFS->endElementNS( mnXmlNamespace, (GetDocumentType() != DOCUMENT_DOCX ? XML_sp : XML_wsp) );
453 
454  return *this;
455 }
456 
458 {
459  return WritePolyPolygonShape( xShape, true );
460 }
461 
463 {
464  return WritePolyPolygonShape( xShape, false );
465 }
466 
467 ShapeExport& ShapeExport::WriteGroupShape(const uno::Reference<drawing::XShape>& xShape)
468 {
469  FSHelperPtr pFS = GetFS();
470 
471  sal_Int32 nGroupShapeToken = XML_grpSp;
473  {
474  if (!m_xParent.is())
475  nGroupShapeToken = XML_wgp; // toplevel
476  else
477  mnXmlNamespace = XML_wpg;
478  }
479 
480  pFS->startElementNS(mnXmlNamespace, nGroupShapeToken);
481 
482  // non visual properties
484  {
485  pFS->startElementNS(mnXmlNamespace, XML_nvGrpSpPr);
486  pFS->singleElementNS(mnXmlNamespace, XML_cNvPr,
487  XML_id, OString::number(GetNewShapeID(xShape)),
488  XML_name, GetShapeName(xShape));
489  pFS->singleElementNS(mnXmlNamespace, XML_cNvGrpSpPr);
490  WriteNonVisualProperties(xShape );
491  pFS->endElementNS(mnXmlNamespace, XML_nvGrpSpPr);
492  }
493  else
494  pFS->singleElementNS(mnXmlNamespace, XML_cNvGrpSpPr);
495 
496  // visual properties
497  pFS->startElementNS(mnXmlNamespace, XML_grpSpPr);
498  WriteShapeTransformation(xShape, XML_a, false, false, true);
499  pFS->endElementNS(mnXmlNamespace, XML_grpSpPr);
500 
501  uno::Reference<drawing::XShapes> xGroupShape(xShape, uno::UNO_QUERY_THROW);
502  uno::Reference<drawing::XShape> xParent = m_xParent;
503  m_xParent = xShape;
504  for (sal_Int32 i = 0; i < xGroupShape->getCount(); ++i)
505  {
506  uno::Reference<drawing::XShape> xChild(xGroupShape->getByIndex(i), uno::UNO_QUERY_THROW);
507  sal_Int32 nSavedNamespace = mnXmlNamespace;
508 
509  uno::Reference<lang::XServiceInfo> xServiceInfo(xChild, uno::UNO_QUERY_THROW);
511  {
512  // tdf#128820: WriteGraphicObjectShapePart calls WriteTextShape for non-empty simple
513  // text objects, which needs writing into wps::wsp element, so make sure to use wps
514  // namespace for those objects
515  if (xServiceInfo->supportsService("com.sun.star.drawing.GraphicObjectShape")
516  && !IsNonEmptySimpleText(xChild))
517  mnXmlNamespace = XML_pic;
518  else
519  mnXmlNamespace = XML_wps;
520  }
521  WriteShape(xChild);
522 
523  mnXmlNamespace = nSavedNamespace;
524  }
525  m_xParent = xParent;
526 
527  pFS->endElementNS(mnXmlNamespace, nGroupShapeToken);
528  return *this;
529 }
530 
531 static bool lcl_IsOnDenylist(OUString const & rShapeType)
532 {
533  static const std::initializer_list<std::u16string_view> vDenylist = {
534  u"block-arc",
535  u"rectangle",
536  u"ellipse",
537  u"ring",
538  u"can",
539  u"cube",
540  u"paper",
541  u"frame",
542  u"forbidden",
543  u"smiley",
544  u"sun",
545  u"flower",
546  u"bracket-pair",
547  u"brace-pair",
548  u"col-60da8460",
549  u"col-502ad400",
550  u"quad-bevel",
551  u"round-rectangular-callout",
552  u"rectangular-callout",
553  u"round-callout",
554  u"cloud-callout",
555  u"line-callout-1",
556  u"line-callout-2",
557  u"line-callout-3",
558  u"paper",
559  u"vertical-scroll",
560  u"horizontal-scroll",
561  u"mso-spt34",
562  u"mso-spt75",
563  u"mso-spt164",
564  u"mso-spt180",
565  u"flowchart-process",
566  u"flowchart-alternate-process",
567  u"flowchart-decision",
568  u"flowchart-data",
569  u"flowchart-predefined-process",
570  u"flowchart-internal-storage",
571  u"flowchart-document",
572  u"flowchart-multidocument",
573  u"flowchart-terminator",
574  u"flowchart-preparation",
575  u"flowchart-manual-input",
576  u"flowchart-manual-operation",
577  u"flowchart-connector",
578  u"flowchart-off-page-connector",
579  u"flowchart-card",
580  u"flowchart-punched-tape",
581  u"flowchart-summing-junction",
582  u"flowchart-or",
583  u"flowchart-collate",
584  u"flowchart-sort",
585  u"flowchart-extract",
586  u"flowchart-merge",
587  u"flowchart-stored-data",
588  u"flowchart-delay",
589  u"flowchart-sequential-access",
590  u"flowchart-magnetic-disk",
591  u"flowchart-direct-access-storage",
592  u"flowchart-display"
593  };
594 
595  return std::find(vDenylist.begin(), vDenylist.end(), rShapeType) != vDenylist.end();
596 }
597 
598 static bool lcl_IsOnAllowlist(OUString const & rShapeType)
599 {
600  static const std::initializer_list<std::u16string_view> vAllowlist = {
601  u"heart",
602  u"puzzle"
603  };
604 
605  return std::find(vAllowlist.begin(), vAllowlist.end(), rShapeType) != vAllowlist.end();
606 }
607 
608 static bool lcl_GetHandlePosition( sal_Int32 &nValue, const EnhancedCustomShapeParameter &rParam, Sequence< EnhancedCustomShapeAdjustmentValue > &rSeq)
609 {
610  bool bAdj = false;
611  if ( rParam.Value.getValueTypeClass() == TypeClass_DOUBLE )
612  {
613  double fValue(0.0);
614  if ( rParam.Value >>= fValue )
615  nValue = static_cast<sal_Int32>(fValue);
616  }
617  else
618  rParam.Value >>= nValue;
619 
620  if ( rParam.Type == EnhancedCustomShapeParameterType::ADJUSTMENT)
621  {
622  bAdj = true;
623  sal_Int32 nIdx = nValue;
624  if ( nIdx < rSeq.getLength() )
625  {
626  if ( rSeq[ nIdx ] .Value.getValueTypeClass() == TypeClass_DOUBLE )
627  {
628  double fValue(0.0);
629  rSeq[ nIdx ].Value >>= fValue;
630  nValue = fValue;
631 
632  }
633  else
634  {
635  rSeq[ nIdx ].Value >>= nValue;
636  }
637  }
638  }
639  return bAdj;
640 }
641 
642 static void lcl_AnalyzeHandles( const uno::Sequence<beans::PropertyValues> & rHandles,
643  std::vector< std::pair< sal_Int32, sal_Int32> > &rHandlePositionList,
645 {
646  for ( const Sequence< PropertyValue >& rPropSeq : rHandles )
647  {
648  static const OUStringLiteral sPosition( u"Position" );
649  bool bPosition = false;
650  EnhancedCustomShapeParameterPair aPosition;
651  for ( const PropertyValue& rPropVal: rPropSeq )
652  {
653  if ( rPropVal.Name == sPosition )
654  {
655  if ( rPropVal.Value >>= aPosition )
656  bPosition = true;
657  }
658  }
659  if ( bPosition )
660  {
661  sal_Int32 nXPosition = 0;
662  sal_Int32 nYPosition = 0;
663  // For polar handles, nXPosition is radius and nYPosition is angle
664  lcl_GetHandlePosition( nXPosition, aPosition.First , rSeq );
665  lcl_GetHandlePosition( nYPosition, aPosition.Second, rSeq );
666  rHandlePositionList.emplace_back( nXPosition, nYPosition );
667  }
668  }
669 }
670 
671 static void lcl_AppendAdjustmentValue( std::vector< std::pair< sal_Int32, sal_Int32> > &rAvList, sal_Int32 nAdjIdx, sal_Int32 nValue )
672 {
673  rAvList.emplace_back( nAdjIdx , nValue );
674 }
675 
676 static sal_Int32 lcl_NormalizeAngle( sal_Int32 nAngle )
677 {
678  nAngle = nAngle % 360;
679  return nAngle < 0 ? ( nAngle + 360 ) : nAngle ;
680 }
681 
682 static sal_Int32 lcl_CircleAngle2CustomShapeEllipseAngleOOX(const sal_Int32 nInternAngle, const sal_Int32 nWidth, const sal_Int32 nHeight)
683 {
684  if (nWidth != 0 || nHeight != 0)
685  {
686  double fAngle = basegfx::deg2rad(nInternAngle / 100.0); // intern 1/100 deg to degree to rad
687  fAngle = atan2(nHeight * sin(fAngle), nWidth * cos(fAngle)); // circle to ellipse
688  fAngle = basegfx::rad2deg(fAngle) * 60000.0; // rad to degree to OOXML angle unit
689  sal_Int32 nAngle = basegfx::fround(fAngle); // normalize
690  nAngle = nAngle % 21600000;
691  return nAngle < 0 ? (nAngle + 21600000) : nAngle;
692  }
693  else // should be handled by caller, dummy value
694  return 0;
695 }
696 
698 {
699  SAL_INFO("oox.shape", "write custom shape");
700  Reference< XPropertySet > rXPropSet( xShape, UNO_QUERY );
701  // First check, if this is a Fontwork-shape. For DrawingML, such a shape is a
702  // TextBox shape with body property prstTxWarp.
703  if (IsFontworkShape(rXPropSet))
704  {
705  ShapeExport::WriteTextShape(xShape); // qualifier to prevent PowerPointShapeExport
706  return *this;
707  }
708 
709  bool bHasGeometrySeq(false);
710  Sequence< PropertyValue > aGeometrySeq;
711  OUString sShapeType;
712  if (GETA(CustomShapeGeometry))
713  {
714  SAL_INFO("oox.shape", "got custom shape geometry");
715  if (mAny >>= aGeometrySeq)
716  {
717  bHasGeometrySeq = true;
718  SAL_INFO("oox.shape", "got custom shape geometry sequence");
719  for (const PropertyValue& rProp : std::as_const(aGeometrySeq))
720  {
721  SAL_INFO("oox.shape", "geometry property: " << rProp.Name);
722  if (rProp.Name == "Type")
723  rProp.Value >>= sShapeType;
724  }
725  }
726  }
727 
728  bool bPredefinedHandlesUsed = true;
729  bool bHasHandles = false;
730 
731  ShapeFlag nMirrorFlags = ShapeFlag::NONE;
732  MSO_SPT eShapeType = EscherPropertyContainer::GetCustomShapeType( xShape, nMirrorFlags, sShapeType );
733  OSL_ENSURE(nullptr != dynamic_cast< SdrObjCustomShape* >(GetSdrObjectFromXShape(xShape)), "Not a SdrObjCustomShape (!)");
734  SdrObjCustomShape& rSdrObjCustomShape(static_cast< SdrObjCustomShape& >(*GetSdrObjectFromXShape(xShape)));
735  const bool bIsDefaultObject(
737  rSdrObjCustomShape,
738  eShapeType));
739  const char* sPresetShape = msfilter::util::GetOOXMLPresetGeometry(sShapeType.toUtf8().getStr());
740  SAL_INFO("oox.shape", "custom shape type: " << sShapeType << " ==> " << sPresetShape);
741 
742  sal_Int32 nAdjustmentValuesIndex = -1;
743  awt::Rectangle aViewBox;
744  uno::Sequence<beans::PropertyValues> aHandles;
745 
746  bool bFlipH = false;
747  bool bFlipV = false;
748 
749  if (bHasGeometrySeq)
750  {
751  for (int i = 0; i < aGeometrySeq.getLength(); i++)
752  {
753  const PropertyValue& rProp = aGeometrySeq[ i ];
754  SAL_INFO("oox.shape", "geometry property: " << rProp.Name);
755 
756  if ( rProp.Name == "MirroredX" )
757  rProp.Value >>= bFlipH;
758 
759  if ( rProp.Name == "MirroredY" )
760  rProp.Value >>= bFlipV;
761  if ( rProp.Name == "AdjustmentValues" )
762  nAdjustmentValuesIndex = i;
763  else if ( rProp.Name == "Handles" )
764  {
765  rProp.Value >>= aHandles;
766  if ( aHandles.hasElements() )
767  bHasHandles = true;
768  if( !bIsDefaultObject )
769  bPredefinedHandlesUsed = false;
770  // TODO: update nAdjustmentsWhichNeedsToBeConverted here
771  }
772  else if ( rProp.Name == "ViewBox" )
773  rProp.Value >>= aViewBox;
774  }
775  }
776 
777  FSHelperPtr pFS = GetFS();
778  pFS->startElementNS(mnXmlNamespace, (GetDocumentType() != DOCUMENT_DOCX ? XML_sp : XML_wsp));
779 
780  // non visual shape properties
782  {
783  bool isVisible = true ;
784  if( GETA (Visible))
785  {
786  mAny >>= isVisible;
787  }
788  pFS->startElementNS( mnXmlNamespace, XML_nvSpPr );
789  pFS->startElementNS( mnXmlNamespace, XML_cNvPr,
790  XML_id, OString::number(GetNewShapeID(xShape)),
791  XML_name, GetShapeName(xShape),
792  XML_hidden, sax_fastparser::UseIf("1", !isVisible));
793 
794  if( GETA( URL ) )
795  {
796  OUString sURL;
797  mAny >>= sURL;
798  if( !sURL.isEmpty() )
799  {
800  OUString sRelId = mpFB->addRelation( mpFS->getOutputStream(),
802  mpURLTransformer->getTransformedString(sURL),
803  mpURLTransformer->isExternalURL(sURL));
804 
805  mpFS->singleElementNS(XML_a, XML_hlinkClick, FSNS(XML_r, XML_id), sRelId);
806  }
807  }
808  pFS->endElementNS(mnXmlNamespace, XML_cNvPr);
809  pFS->singleElementNS(mnXmlNamespace, XML_cNvSpPr);
810  WriteNonVisualProperties( xShape );
811  pFS->endElementNS( mnXmlNamespace, XML_nvSpPr );
812  }
813  else
814  pFS->singleElementNS(mnXmlNamespace, XML_cNvSpPr);
815 
816  // visual shape properties
817  pFS->startElementNS(mnXmlNamespace, XML_spPr);
818  // moon is flipped in MSO, and mso-spt89 (right up arrow) is mapped to leftUpArrow
819  if ( sShapeType == "moon" || sShapeType == "mso-spt89" )
820  bFlipH = !bFlipH;
821 
822  // we export non-primitive shapes to custom geometry
823  // we also export non-ooxml shapes which have handles/equations to custom geometry, because
824  // we cannot convert ODF equations to DrawingML equations. TODO: see what binary DOC export filter does.
825  // but our WritePolyPolygon()/WriteCustomGeometry() functions are incomplete, therefore we use a denylist
826  // we use a allowlist for shapes where mapping to MSO preset shape is not optimal
827  bool bCustGeom = true;
828  bool bOnDenylist = false;
829  if( sShapeType == "ooxml-non-primitive" )
830  bCustGeom = true;
831  else if( sShapeType.startsWith("ooxml") )
832  bCustGeom = false;
833  else if( lcl_IsOnAllowlist(sShapeType) )
834  bCustGeom = true;
835  else if( lcl_IsOnDenylist(sShapeType) )
836  {
837  bCustGeom = false;
838  bOnDenylist = true;
839  }
840  else if( bHasHandles )
841  bCustGeom = true;
842 
843  bool bPresetWriteSuccessful = false;
844  // Let the custom shapes what has name and preset information in OOXML, to be written
845  // as preset ones with parameters. Try that with this converter class.
846  if (!sShapeType.startsWith("ooxml") && GetDocumentType() == DOCUMENT_DOCX
847  && xShape->getShapeType() == "com.sun.star.drawing.CustomShape")
848  {
849  DMLPresetShapeExporter aCustomShapeConverter(this, xShape);
850  bPresetWriteSuccessful = aCustomShapeConverter.WriteShape();
851  }
852  // If preset writing has problems try to write the shape as it done before
853  if (bPresetWriteSuccessful)
854  ;// Already written do nothing.
855  else if (bHasHandles && bCustGeom)
856  {
857  WriteShapeTransformation( xShape, XML_a, bFlipH, bFlipV, false, true );// do not flip, polypolygon coordinates are flipped already
858  tools::PolyPolygon aPolyPolygon( rSdrObjCustomShape.GetLineGeometry(true) );
859  sal_Int32 nRotation = 0;
860  // The RotateAngle property's value is independent from any flipping, and that's exactly what we need here.
861  uno::Reference<beans::XPropertySet> xPropertySet(xShape, uno::UNO_QUERY);
862  uno::Reference<beans::XPropertySetInfo> xPropertySetInfo = xPropertySet->getPropertySetInfo();
863  if (xPropertySetInfo->hasPropertyByName("RotateAngle"))
864  xPropertySet->getPropertyValue("RotateAngle") >>= nRotation;
865  // Remove rotation
866  bool bInvertRotation = bFlipH != bFlipV;
867  if (nRotation != 0)
868  aPolyPolygon.Rotate(Point(0,0), Degree10(static_cast<sal_Int16>(bInvertRotation ? nRotation/10 : 3600-nRotation/10)));
869  WritePolyPolygon(xShape, aPolyPolygon, false);
870  }
871  else if (bCustGeom)
872  {
873  WriteShapeTransformation( xShape, XML_a, bFlipH, bFlipV );
874  bool bSuccess = WriteCustomGeometry(xShape, rSdrObjCustomShape);
875  if (!bSuccess)
876  WritePresetShape( sPresetShape );
877  }
878  else if (bOnDenylist && bHasHandles && nAdjustmentValuesIndex !=-1 && !sShapeType.startsWith("mso-spt"))
879  {
880  WriteShapeTransformation( xShape, XML_a, bFlipH, bFlipV );
882  std::vector< std::pair< sal_Int32, sal_Int32> > aHandlePositionList;
883  std::vector< std::pair< sal_Int32, sal_Int32> > aAvList;
884  aGeometrySeq[ nAdjustmentValuesIndex ].Value >>= aAdjustmentSeq ;
885 
886  lcl_AnalyzeHandles( aHandles, aHandlePositionList, aAdjustmentSeq );
887 
888  sal_Int32 nXPosition = 0;
889  sal_Int32 nYPosition = 0;
890  if ( !aHandlePositionList.empty() )
891  {
892  nXPosition = aHandlePositionList[0].first ;
893  nYPosition = aHandlePositionList[0].second ;
894  }
895  switch( eShapeType )
896  {
898  {
899  sal_Int32 adj3 = double(nYPosition)/aViewBox.Height *100000;
900  sal_Int32 adj4 = double(nXPosition)/aViewBox.Width *100000;
901  lcl_AppendAdjustmentValue( aAvList, 1, 18750 );
902  lcl_AppendAdjustmentValue( aAvList, 2, -8333 );
903  lcl_AppendAdjustmentValue( aAvList, 3, adj3 );
904  lcl_AppendAdjustmentValue( aAvList, 4, adj4 );
905  break;
906  }
908  {
909  sal_Int32 adj5 = double(nYPosition)/aViewBox.Height *100000;
910  sal_Int32 adj6 = double(nXPosition)/aViewBox.Width *100000;
911  sal_Int32 adj3 = 18750;
912  sal_Int32 adj4 = -16667;
913  lcl_AppendAdjustmentValue( aAvList, 1, 18750 );
914  lcl_AppendAdjustmentValue( aAvList, 2, -8333 );
915  if ( aHandlePositionList.size() > 1 )
916  {
917  nXPosition = aHandlePositionList[1].first ;
918  nYPosition = aHandlePositionList[1].second ;
919  adj3 = double(nYPosition)/aViewBox.Height *100000;
920  adj4 = double(nXPosition)/aViewBox.Width *100000;
921  }
922  lcl_AppendAdjustmentValue( aAvList, 3, adj3 );
923  lcl_AppendAdjustmentValue( aAvList, 4, adj4 );
924  lcl_AppendAdjustmentValue( aAvList, 5, adj5 );
925  lcl_AppendAdjustmentValue( aAvList, 6, adj6 );
926  break;
927  }
931  case mso_sptCloudCallout:
932  {
933  sal_Int32 adj1 = (double(nXPosition)/aViewBox.Width -0.5) *100000;
934  sal_Int32 adj2 = (double(nYPosition)/aViewBox.Height -0.5) *100000;
935  lcl_AppendAdjustmentValue( aAvList, 1, adj1 );
936  lcl_AppendAdjustmentValue( aAvList, 2, adj2 );
937  if ( eShapeType == mso_sptWedgeRRectCallout)
938  {
939  lcl_AppendAdjustmentValue( aAvList, 3, 16667);
940  }
941 
942  break;
943  }
944  case mso_sptFoldedCorner:
945  {
946  sal_Int32 adj = double( aViewBox.Width - nXPosition) / std::min( aViewBox.Width,aViewBox.Height ) * 100000;
947  lcl_AppendAdjustmentValue( aAvList, 0, adj );
948  break;
949  }
950  case mso_sptDonut:
951  case mso_sptSun:
952  case mso_sptMoon:
953  case mso_sptNoSmoking:
955  case mso_sptBevel:
956  case mso_sptBracketPair:
957  {
958  sal_Int32 adj = double( nXPosition )/aViewBox.Width*100000 ;
959  lcl_AppendAdjustmentValue( aAvList, 0, adj );
960  break;
961  }
962  case mso_sptCan:
963  case mso_sptCube:
964  case mso_sptBracePair:
966  {
967  sal_Int32 adj = double( nYPosition )/aViewBox.Height *100000 ;
968  lcl_AppendAdjustmentValue( aAvList, 0, adj );
969  break;
970  }
971  case mso_sptSmileyFace:
972  {
973  sal_Int32 adj = double( nYPosition )/aViewBox.Height *100000 - 76458.0;
974  lcl_AppendAdjustmentValue( aAvList, 0, adj );
975  break;
976  }
977  case mso_sptBlockArc:
978  {
979  sal_Int32 nRadius = 50000 * ( 1 - double(nXPosition) / 10800);
980  sal_Int32 nAngleStart = lcl_NormalizeAngle( nYPosition );
981  sal_Int32 nAngleEnd = lcl_NormalizeAngle( 180 - nAngleStart );
982  lcl_AppendAdjustmentValue( aAvList, 1, 21600000 / 360 * nAngleStart );
983  lcl_AppendAdjustmentValue( aAvList, 2, 21600000 / 360 * nAngleEnd );
984  lcl_AppendAdjustmentValue( aAvList, 3, nRadius );
985  break;
986  }
987  // case mso_sptNil:
988  // case mso_sptBentConnector3:
989  // case mso_sptBorderCallout3:
990  default:
991  {
992  if (!strcmp( sPresetShape, "frame" ))
993  {
994  sal_Int32 adj1 = double( nYPosition )/aViewBox.Height *100000 ;
995  lcl_AppendAdjustmentValue( aAvList, 1, adj1 );
996  }
997  break;
998  }
999  }
1000  WritePresetShape( sPresetShape , aAvList );
1001  }
1002  else // preset geometry
1003  {
1004  WriteShapeTransformation( xShape, XML_a, bFlipH, bFlipV );
1005  if( nAdjustmentValuesIndex != -1 )
1006  {
1007  WritePresetShape( sPresetShape, eShapeType, bPredefinedHandlesUsed,
1008  aGeometrySeq[ nAdjustmentValuesIndex ] );
1009  }
1010  else
1011  WritePresetShape( sPresetShape );
1012  }
1013  if( rXPropSet.is() )
1014  {
1015  WriteFill( rXPropSet );
1016  WriteOutline( rXPropSet );
1017  WriteShapeEffects( rXPropSet );
1018 
1019  bool bHas3DEffectinShape = false;
1020  uno::Sequence<beans::PropertyValue> grabBag;
1021  rXPropSet->getPropertyValue("InteropGrabBag") >>= grabBag;
1022 
1023  for (auto const& it : std::as_const(grabBag))
1024  if (it.Name == "3DEffectProperties")
1025  bHas3DEffectinShape = true;
1026 
1027  if( bHas3DEffectinShape)
1028  WriteShape3DEffects( rXPropSet );
1029  }
1030 
1031  pFS->endElementNS( mnXmlNamespace, XML_spPr );
1032 
1033  pFS->startElementNS(mnXmlNamespace, XML_style);
1034  WriteShapeStyle( rXPropSet );
1035  pFS->endElementNS( mnXmlNamespace, XML_style );
1036 
1037  // write text
1038  WriteTextBox( xShape, mnXmlNamespace );
1039 
1040  pFS->endElementNS( mnXmlNamespace, (GetDocumentType() != DOCUMENT_DOCX ? XML_sp : XML_wsp) );
1041 
1042  return *this;
1043 }
1044 
1046 {
1047  SAL_INFO("oox.shape", "write ellipse shape");
1048 
1049  FSHelperPtr pFS = GetFS();
1050 
1051  pFS->startElementNS(mnXmlNamespace, (GetDocumentType() != DOCUMENT_DOCX ? XML_sp : XML_wsp));
1052 
1053  // TODO: connector ?
1054 
1055  // non visual shape properties
1056  if (GetDocumentType() != DOCUMENT_DOCX)
1057  {
1058  pFS->startElementNS(mnXmlNamespace, XML_nvSpPr);
1059  pFS->singleElementNS( mnXmlNamespace, XML_cNvPr,
1060  XML_id, OString::number(GetNewShapeID(xShape)),
1061  XML_name, GetShapeName(xShape));
1062  pFS->singleElementNS( mnXmlNamespace, XML_cNvSpPr );
1063  WriteNonVisualProperties( xShape );
1064  pFS->endElementNS( mnXmlNamespace, XML_nvSpPr );
1065  }
1066  else
1067  pFS->singleElementNS(mnXmlNamespace, XML_cNvSpPr);
1068 
1069  Reference< XPropertySet > xProps( xShape, UNO_QUERY );
1070  CircleKind eCircleKind(CircleKind_FULL);
1071  if (xProps.is())
1072  xProps->getPropertyValue("CircleKind" ) >>= eCircleKind;
1073 
1074  // visual shape properties
1075  pFS->startElementNS( mnXmlNamespace, XML_spPr );
1076  WriteShapeTransformation( xShape, XML_a );
1077 
1078  if (CircleKind_FULL == eCircleKind)
1079  WritePresetShape("ellipse");
1080  else
1081  {
1082  sal_Int32 nStartAngleIntern(9000);
1083  sal_Int32 nEndAngleIntern(0);
1084  if (xProps.is())
1085  {
1086  xProps->getPropertyValue("CircleStartAngle" ) >>= nStartAngleIntern;
1087  xProps->getPropertyValue("CircleEndAngle") >>= nEndAngleIntern;
1088  }
1089  std::vector< std::pair<sal_Int32,sal_Int32>> aAvList;
1090  awt::Size aSize = xShape->getSize();
1091  if (aSize.Width != 0 || aSize.Height != 0)
1092  {
1093  // Our arc has 90° up, OOXML has 90° down, so mirror it.
1094  // API angles are 1/100 degree.
1095  sal_Int32 nStartAngleOOXML(lcl_CircleAngle2CustomShapeEllipseAngleOOX(36000 - nEndAngleIntern, aSize.Width, aSize.Height));
1096  sal_Int32 nEndAngleOOXML(lcl_CircleAngle2CustomShapeEllipseAngleOOX(36000 - nStartAngleIntern, aSize.Width, aSize.Height));
1097  lcl_AppendAdjustmentValue( aAvList, 1, nStartAngleOOXML);
1098  lcl_AppendAdjustmentValue( aAvList, 2, nEndAngleOOXML);
1099  }
1100  switch (eCircleKind)
1101  {
1102  case CircleKind_ARC :
1103  WritePresetShape("arc", aAvList);
1104  break;
1105  case CircleKind_SECTION :
1106  WritePresetShape("pie", aAvList);
1107  break;
1108  case CircleKind_CUT :
1109  WritePresetShape("chord", aAvList);
1110  break;
1111  default :
1112  WritePresetShape("ellipse");
1113  }
1114  }
1115  if( xProps.is() )
1116  {
1117  if (CircleKind_ARC == eCircleKind)
1118  {
1119  // An arc in ODF is never filled, even if a fill style other than
1120  // "none" is set. OOXML arc can be filled, so set fill explicit to
1121  // NONE, otherwise some hidden or inherited filling is shown.
1122  FillStyle eFillStyle(FillStyle_NONE);
1123  uno::Any aNewValue;
1124  aNewValue <<= eFillStyle;
1125  xProps->setPropertyValue("FillStyle", aNewValue);
1126  }
1127  WriteFill( xProps );
1128  WriteOutline( xProps );
1129  }
1130  pFS->endElementNS( mnXmlNamespace, XML_spPr );
1131 
1132  // write text
1133  WriteTextBox( xShape, mnXmlNamespace );
1134 
1135  pFS->endElementNS( mnXmlNamespace, (GetDocumentType() != DOCUMENT_DOCX ? XML_sp : XML_wsp) );
1136 
1137  return *this;
1138 }
1139 
1141 {
1142  WriteGraphicObjectShapePart( xShape );
1143 
1144  return *this;
1145 }
1146 
1148 {
1149  SAL_INFO("oox.shape", "write graphic object shape");
1150 
1151  if (IsNonEmptySimpleText(xShape))
1152  {
1153  SAL_INFO("oox.shape", "graphicObject: wrote only text");
1154 
1155  WriteTextShape(xShape);
1156 
1157  return;
1158  }
1159 
1160  SAL_INFO("oox.shape", "graphicObject without text");
1161 
1162  uno::Reference<graphic::XGraphic> xGraphic;
1163  OUString sMediaURL;
1164 
1165  Reference< XPropertySet > xShapeProps( xShape, UNO_QUERY );
1166 
1167  if (pGraphic)
1168  {
1169  xGraphic.set(pGraphic->GetXGraphic());
1170  }
1171  else if (xShapeProps.is() && xShapeProps->getPropertySetInfo()->hasPropertyByName("Graphic"))
1172  {
1173  xShapeProps->getPropertyValue("Graphic") >>= xGraphic;
1174  }
1175 
1176  bool bHasMediaURL = xShapeProps.is() && xShapeProps->getPropertySetInfo()->hasPropertyByName("MediaURL") && (xShapeProps->getPropertyValue("MediaURL") >>= sMediaURL);
1177 
1178  if (!xGraphic.is() && !bHasMediaURL)
1179  {
1180  SAL_INFO("oox.shape", "no graphic or media URL found");
1181  return;
1182  }
1183 
1184  FSHelperPtr pFS = GetFS();
1185  XmlFilterBase* pFB = GetFB();
1186 
1187  if (GetDocumentType() != DOCUMENT_DOCX)
1188  pFS->startElementNS(mnXmlNamespace, XML_pic);
1189  else
1190  pFS->startElementNS(mnXmlNamespace, XML_pic,
1191  FSNS(XML_xmlns, XML_pic), pFB->getNamespaceURL(OOX_NS(dmlPicture)));
1192 
1193  pFS->startElementNS(mnXmlNamespace, XML_nvPicPr);
1194 
1195  OUString sDescr, sURL;
1196  bool bHaveDesc;
1197 
1198  if ( ( bHaveDesc = GetProperty( xShapeProps, "Description" ) ) )
1199  mAny >>= sDescr;
1200  if ( GetProperty( xShapeProps, "URL" ) )
1201  mAny >>= sURL;
1202 
1203  pFS->startElementNS( mnXmlNamespace, XML_cNvPr,
1204  XML_id, OString::number(GetNewShapeID(xShape)),
1205  XML_name, GetShapeName(xShape),
1206  XML_descr, sax_fastparser::UseIf(sDescr, bHaveDesc));
1207 
1208  // OOXTODO: //cNvPr children: XML_extLst, XML_hlinkHover
1209  if (bHasMediaURL)
1210  pFS->singleElementNS(XML_a, XML_hlinkClick,
1211  FSNS(XML_r, XML_id), "",
1212  XML_action, "ppaction://media");
1213  if( !sURL.isEmpty() )
1214  {
1215  OUString sRelId = mpFB->addRelation( mpFS->getOutputStream(),
1217  mpURLTransformer->getTransformedString(sURL),
1218  mpURLTransformer->isExternalURL(sURL));
1219 
1220  mpFS->singleElementNS(XML_a, XML_hlinkClick, FSNS(XML_r, XML_id), sRelId);
1221  }
1222  pFS->endElementNS(mnXmlNamespace, XML_cNvPr);
1223 
1224  pFS->singleElementNS(mnXmlNamespace, XML_cNvPicPr
1225  // OOXTODO: XML_preferRelativeSize
1226  );
1227  if (bHasMediaURL)
1229  else
1230  WriteNonVisualProperties(xShape);
1231 
1232  pFS->endElementNS( mnXmlNamespace, XML_nvPicPr );
1233 
1234  pFS->startElementNS(mnXmlNamespace, XML_blipFill);
1235 
1236  if (xGraphic.is())
1237  {
1238  WriteXGraphicBlip(xShapeProps, xGraphic, false);
1239  }
1240  else if (bHasMediaURL)
1241  {
1242  Reference<graphic::XGraphic> xFallbackGraphic;
1243  if (xShapeProps->getPropertySetInfo()->hasPropertyByName("FallbackGraphic"))
1244  xShapeProps->getPropertyValue("FallbackGraphic") >>= xFallbackGraphic;
1245 
1246  WriteXGraphicBlip(xShapeProps, xFallbackGraphic, false);
1247  }
1248 
1249  if (xGraphic.is())
1250  {
1251  WriteSrcRectXGraphic(xShapeProps, xGraphic);
1252  }
1253 
1254  // now we stretch always when we get pGraphic (when changing that
1255  // behavior, test n#780830 for regression, where the OLE sheet might get tiled
1256  bool bStretch = false;
1257  if( !pGraphic && GetProperty( xShapeProps, "FillBitmapStretch" ) )
1258  mAny >>= bStretch;
1259 
1260  if ( pGraphic || bStretch )
1261  pFS->singleElementNS(XML_a, XML_stretch);
1262 
1263  if (bHasMediaURL)
1264  {
1265  // Graphic of media shapes is always stretched.
1266  pFS->startElementNS(XML_a, XML_stretch);
1267  pFS->singleElementNS(XML_a, XML_fillRect);
1268  pFS->endElementNS(XML_a, XML_stretch);
1269  }
1270 
1271  pFS->endElementNS( mnXmlNamespace, XML_blipFill );
1272 
1273  // visual shape properties
1274  pFS->startElementNS(mnXmlNamespace, XML_spPr);
1275  bool bFlipH = false;
1276  if( xShapeProps->getPropertySetInfo()->hasPropertyByName("IsMirrored") )
1277  {
1278  xShapeProps->getPropertyValue("IsMirrored") >>= bFlipH;
1279  }
1280  WriteShapeTransformation( xShape, XML_a, bFlipH, false, false, false, true );
1281  WritePresetShape( "rect" );
1282  // graphic object can come with the frame (bnc#654525)
1283  WriteOutline( xShapeProps );
1284 
1285  WriteShapeEffects( xShapeProps );
1286  WriteShape3DEffects( xShapeProps );
1287 
1288  pFS->endElementNS( mnXmlNamespace, XML_spPr );
1289 
1290  pFS->endElementNS( mnXmlNamespace, XML_pic );
1291 }
1292 
1294 {
1295  bool bFlipH = false;
1296  bool bFlipV = false;
1297 
1298  SAL_INFO("oox.shape", "write connector shape");
1299 
1300  FSHelperPtr pFS = GetFS();
1301 
1302  const char* sGeometry = "line";
1303  Reference< XPropertySet > rXPropSet( xShape, UNO_QUERY );
1304  Reference< XPropertyState > rXPropState( xShape, UNO_QUERY );
1305  awt::Point aStartPoint, aEndPoint;
1306  Reference< XShape > rXShapeA;
1307  Reference< XShape > rXShapeB;
1308  PropertyState eState;
1309  ConnectorType eConnectorType;
1310  if( GETAD( EdgeKind ) ) {
1311  mAny >>= eConnectorType;
1312 
1313  switch( eConnectorType ) {
1314  case ConnectorType_CURVE:
1315  sGeometry = "curvedConnector3";
1316  break;
1317  case ConnectorType_STANDARD:
1318  sGeometry = "bentConnector3";
1319  break;
1320  default:
1321  case ConnectorType_LINE:
1322  case ConnectorType_LINES:
1323  sGeometry = "straightConnector1";
1324  break;
1325  }
1326 
1327  if( GETAD( EdgeStartPoint ) ) {
1328  mAny >>= aStartPoint;
1329  if( GETAD( EdgeEndPoint ) ) {
1330  mAny >>= aEndPoint;
1331  }
1332  }
1333  GET( rXShapeA, EdgeStartConnection );
1334  GET( rXShapeB, EdgeEndConnection );
1335  }
1336  // Position is relative to group in Word, but relative to anchor of group in API.
1337  if (GetDocumentType() == DOCUMENT_DOCX && m_xParent.is())
1338  {
1339  awt::Point aParentPos = m_xParent->getPosition();
1340  aStartPoint.X -= aParentPos.X;
1341  aStartPoint.Y -= aParentPos.Y;
1342  aEndPoint.X -= aParentPos.X;
1343  aEndPoint.Y -= aParentPos.Y;
1344  }
1345  EscherConnectorListEntry aConnectorEntry( xShape, aStartPoint, rXShapeA, aEndPoint, rXShapeB );
1346  tools::Rectangle aRect( Point( aStartPoint.X, aStartPoint.Y ), Point( aEndPoint.X, aEndPoint.Y ) );
1347  if( aRect.getWidth() < 0 ) {
1348  bFlipH = true;
1349  aRect.setX( aEndPoint.X );
1350  aRect.setWidth( aStartPoint.X - aEndPoint.X );
1351  }
1352 
1353  if( aRect.getHeight() < 0 ) {
1354  bFlipV = true;
1355  aRect.setY( aEndPoint.Y );
1356  aRect.setHeight( aStartPoint.Y - aEndPoint.Y );
1357  }
1358 
1359  // tdf#99810 connector shape (cxnSp) is not valid with namespace 'wps'
1360  const auto nShapeNode = (mnXmlNamespace == XML_wps ? XML_wsp : XML_cxnSp);
1361  pFS->startElementNS(mnXmlNamespace, nShapeNode);
1362 
1363  if (mnXmlNamespace == XML_wps)
1364  {
1365  // non visual connector shape drawing properties
1366  pFS->singleElementNS(mnXmlNamespace, XML_cNvCnPr);
1367  }
1368  else
1369  {
1370  // non visual shape properties
1371  pFS->startElementNS(mnXmlNamespace, XML_nvCxnSpPr);
1372  pFS->singleElementNS(mnXmlNamespace, XML_cNvPr,
1373  XML_id, OString::number(GetNewShapeID(xShape)),
1374  XML_name, GetShapeName(xShape));
1375  // non visual connector shape drawing properties
1376  pFS->startElementNS(mnXmlNamespace, XML_cNvCxnSpPr);
1377  WriteConnectorConnections(aConnectorEntry, GetShapeID(rXShapeA), GetShapeID(rXShapeB));
1378  pFS->endElementNS(mnXmlNamespace, XML_cNvCxnSpPr);
1379  pFS->singleElementNS(mnXmlNamespace, XML_nvPr);
1380  pFS->endElementNS(mnXmlNamespace, XML_nvCxnSpPr);
1381  }
1382 
1383  // visual shape properties
1384  pFS->startElementNS(mnXmlNamespace, XML_spPr);
1385  WriteTransformation( xShape, aRect, XML_a, bFlipH, bFlipV );
1386  // TODO: write adjustments (ppt export doesn't work well there either)
1387  WritePresetShape( sGeometry );
1388  Reference< XPropertySet > xShapeProps( xShape, UNO_QUERY );
1389  if( xShapeProps.is() )
1390  WriteOutline( xShapeProps );
1391  pFS->endElementNS( mnXmlNamespace, XML_spPr );
1392 
1393  // write text
1394  WriteTextBox( xShape, mnXmlNamespace );
1395 
1396  pFS->endElementNS(mnXmlNamespace, nShapeNode);
1397 
1398  return *this;
1399 }
1400 
1402 {
1403  bool bFlipH = false;
1404  bool bFlipV = false;
1405 
1406  SAL_INFO("oox.shape", "write line shape");
1407 
1408  FSHelperPtr pFS = GetFS();
1409 
1410  pFS->startElementNS(mnXmlNamespace, (GetDocumentType() != DOCUMENT_DOCX ? XML_sp : XML_wsp));
1411 
1413  if( aPolyPolygon.Count() == 1 && aPolyPolygon[ 0 ].GetSize() == 2)
1414  {
1415  const tools::Polygon& rPoly = aPolyPolygon[ 0 ];
1416 
1417  bFlipH = ( rPoly[ 0 ].X() > rPoly[ 1 ].X() );
1418  bFlipV = ( rPoly[ 0 ].Y() > rPoly[ 1 ].Y() );
1419  }
1420 
1421  // non visual shape properties
1422  if (GetDocumentType() != DOCUMENT_DOCX)
1423  {
1424  pFS->startElementNS(mnXmlNamespace, XML_nvSpPr);
1425  pFS->singleElementNS( mnXmlNamespace, XML_cNvPr,
1426  XML_id, OString::number(GetNewShapeID(xShape)),
1427  XML_name, GetShapeName(xShape));
1428  }
1429  pFS->singleElementNS( mnXmlNamespace, XML_cNvSpPr );
1430  if (GetDocumentType() != DOCUMENT_DOCX)
1431  {
1432  WriteNonVisualProperties( xShape );
1433  pFS->endElementNS( mnXmlNamespace, XML_nvSpPr );
1434  }
1435 
1436  // visual shape properties
1437  pFS->startElementNS(mnXmlNamespace, XML_spPr);
1438  WriteShapeTransformation( xShape, XML_a, bFlipH, bFlipV, true);
1439  WritePresetShape( "line" );
1440  Reference< XPropertySet > xShapeProps( xShape, UNO_QUERY );
1441  if( xShapeProps.is() )
1442  WriteOutline( xShapeProps );
1443  pFS->endElementNS( mnXmlNamespace, XML_spPr );
1444 
1445  //write style
1446  pFS->startElementNS(mnXmlNamespace, XML_style);
1447  WriteShapeStyle( xShapeProps );
1448  pFS->endElementNS( mnXmlNamespace, XML_style );
1449 
1450  // write text
1451  WriteTextBox( xShape, mnXmlNamespace );
1452 
1453  pFS->endElementNS( mnXmlNamespace, (GetDocumentType() != DOCUMENT_DOCX ? XML_sp : XML_wsp) );
1454 
1455  return *this;
1456 }
1457 
1459 {
1460  GetFS()->singleElementNS( mnXmlNamespace, XML_cNvPr,
1461  XML_id, OString::number(GetNewShapeID(xShape)),
1462  XML_name, pName );
1463 
1464  return *this;
1465 }
1466 
1468 {
1469  // Override to generate //nvPr elements.
1470  return *this;
1471 }
1472 
1474 {
1475  SAL_INFO("oox.shape", "write rectangle shape");
1476 
1477  FSHelperPtr pFS = GetFS();
1478 
1479  pFS->startElementNS(mnXmlNamespace, (GetDocumentType() != DOCUMENT_DOCX ? XML_sp : XML_wsp));
1480 
1481  sal_Int32 nRadius = 0;
1482 
1483  Reference< XPropertySet > xShapeProps( xShape, UNO_QUERY );
1484  if( xShapeProps.is() )
1485  {
1486  xShapeProps->getPropertyValue( "CornerRadius" ) >>= nRadius;
1487  }
1488 
1489  if( nRadius )
1490  {
1491  nRadius = MapSize( awt::Size( nRadius, 0 ) ).Width;
1492  }
1493  //TODO: use nRadius value more precisely than just deciding whether to use
1494  // "rect" or "roundRect" preset shape below
1495 
1496  // non visual shape properties
1497  if (GetDocumentType() == DOCUMENT_DOCX)
1498  pFS->singleElementNS(mnXmlNamespace, XML_cNvSpPr);
1499  pFS->startElementNS(mnXmlNamespace, XML_nvSpPr);
1500  pFS->singleElementNS( mnXmlNamespace, XML_cNvPr,
1501  XML_id, OString::number(GetNewShapeID(xShape)),
1502  XML_name, GetShapeName(xShape));
1503  pFS->singleElementNS(mnXmlNamespace, XML_cNvSpPr);
1504  WriteNonVisualProperties( xShape );
1505  pFS->endElementNS( mnXmlNamespace, XML_nvSpPr );
1506 
1507  // visual shape properties
1508  pFS->startElementNS(mnXmlNamespace, XML_spPr);
1509  WriteShapeTransformation( xShape, XML_a );
1510  WritePresetShape( nRadius == 0 ? "rect" : "roundRect" );
1511  Reference< XPropertySet > xProps( xShape, UNO_QUERY );
1512  if( xProps.is() )
1513  {
1514  WriteFill( xProps );
1515  WriteOutline( xProps );
1516  }
1517  pFS->endElementNS( mnXmlNamespace, XML_spPr );
1518 
1519  // write text
1520  WriteTextBox( xShape, mnXmlNamespace );
1521 
1522  pFS->endElementNS( mnXmlNamespace, (GetDocumentType() != DOCUMENT_DOCX ? XML_sp : XML_wsp) );
1523 
1524  return *this;
1525 }
1526 
1528 typedef std::unordered_map< const char*, ShapeConverter, rtl::CStringHash, rtl::CStringEqual> NameToConvertMapType;
1529 
1530 static const NameToConvertMapType& lcl_GetConverters()
1531 {
1532  static NameToConvertMapType const shape_converters
1533  {
1534  { "com.sun.star.drawing.ClosedBezierShape" , &ShapeExport::WriteClosedPolyPolygonShape },
1535  { "com.sun.star.drawing.ConnectorShape" , &ShapeExport::WriteConnectorShape },
1536  { "com.sun.star.drawing.CustomShape" , &ShapeExport::WriteCustomShape },
1537  { "com.sun.star.drawing.EllipseShape" , &ShapeExport::WriteEllipseShape },
1538  { "com.sun.star.drawing.GraphicObjectShape" , &ShapeExport::WriteGraphicObjectShape },
1539  { "com.sun.star.drawing.LineShape" , &ShapeExport::WriteLineShape },
1540  { "com.sun.star.drawing.OpenBezierShape" , &ShapeExport::WriteOpenPolyPolygonShape },
1541  { "com.sun.star.drawing.PolyPolygonShape" , &ShapeExport::WriteClosedPolyPolygonShape },
1542  { "com.sun.star.drawing.PolyLineShape" , &ShapeExport::WriteOpenPolyPolygonShape },
1543  { "com.sun.star.drawing.RectangleShape" , &ShapeExport::WriteRectangleShape },
1544  { "com.sun.star.drawing.OLE2Shape" , &ShapeExport::WriteOLE2Shape },
1545  { "com.sun.star.drawing.TableShape" , &ShapeExport::WriteTableShape },
1546  { "com.sun.star.drawing.TextShape" , &ShapeExport::WriteTextShape },
1547  { "com.sun.star.drawing.GroupShape" , &ShapeExport::WriteGroupShape },
1548 
1549  { "com.sun.star.presentation.GraphicObjectShape" , &ShapeExport::WriteGraphicObjectShape },
1550  { "com.sun.star.presentation.MediaShape" , &ShapeExport::WriteGraphicObjectShape },
1551  { "com.sun.star.presentation.ChartShape" , &ShapeExport::WriteOLE2Shape },
1552  { "com.sun.star.presentation.OLE2Shape" , &ShapeExport::WriteOLE2Shape },
1553  { "com.sun.star.presentation.TableShape" , &ShapeExport::WriteTableShape },
1554  { "com.sun.star.presentation.TextShape" , &ShapeExport::WriteTextShape },
1555 
1556  { "com.sun.star.presentation.DateTimeShape" , &ShapeExport::WriteTextShape },
1557  { "com.sun.star.presentation.FooterShape" , &ShapeExport::WriteTextShape },
1558  { "com.sun.star.presentation.HeaderShape" , &ShapeExport::WriteTextShape },
1559  { "com.sun.star.presentation.NotesShape" , &ShapeExport::WriteTextShape },
1560  { "com.sun.star.presentation.OutlinerShape" , &ShapeExport::WriteTextShape },
1561  { "com.sun.star.presentation.SlideNumberShape" , &ShapeExport::WriteTextShape },
1562  { "com.sun.star.presentation.TitleTextShape" , &ShapeExport::WriteTextShape },
1563  };
1564  return shape_converters;
1565 }
1566 
1568 {
1569  OUString sShapeType = xShape->getShapeType();
1570  SAL_INFO("oox.shape", "write shape: " << sShapeType);
1571  NameToConvertMapType::const_iterator aConverter
1572  = lcl_GetConverters().find(sShapeType.toUtf8().getStr());
1573  if (aConverter == lcl_GetConverters().end())
1574  {
1575  SAL_INFO("oox.shape", "unknown shape");
1576  return WriteUnknownShape( xShape );
1577  }
1578  (this->*(aConverter->second))( xShape );
1579 
1580  return *this;
1581 }
1582 
1583 ShapeExport& ShapeExport::WriteTextBox( const Reference< XInterface >& xIface, sal_Int32 nXmlNamespace, bool bWritePropertiesAsLstStyles )
1584 {
1585  // In case this shape has an associated textbox, then export that, and we're done.
1587  {
1588  uno::Reference<beans::XPropertySet> xPropertySet(xIface, uno::UNO_QUERY);
1589  if (xPropertySet.is())
1590  {
1591  uno::Reference<beans::XPropertySetInfo> xPropertySetInfo = xPropertySet->getPropertySetInfo();
1592  if (xPropertySetInfo->hasPropertyByName("TextBox") && xPropertySet->getPropertyValue("TextBox").get<bool>())
1593  {
1594  GetTextExport()->WriteTextBox(uno::Reference<drawing::XShape>(xIface, uno::UNO_QUERY_THROW));
1595  WriteText( xIface, /*bBodyPr=*/true, /*bText=*/false, /*nXmlNamespace=*/nXmlNamespace );
1596  return *this;
1597  }
1598  }
1599  }
1600 
1601  Reference< XText > xXText( xIface, UNO_QUERY );
1602  if( NonEmptyText( xIface ) && xXText.is() )
1603  {
1604  FSHelperPtr pFS = GetFS();
1605 
1606  pFS->startElementNS(nXmlNamespace,
1607  (GetDocumentType() != DOCUMENT_DOCX ? XML_txBody : XML_txbx));
1608  WriteText(xIface, /*bBodyPr=*/(GetDocumentType() != DOCUMENT_DOCX), /*bText=*/true,
1609  /*nXmlNamespace=*/0, /*bWritePropertiesAsLstStyles=*/bWritePropertiesAsLstStyles);
1610  pFS->endElementNS( nXmlNamespace, (GetDocumentType() != DOCUMENT_DOCX ? XML_txBody : XML_txbx) );
1611  if (GetDocumentType() == DOCUMENT_DOCX)
1612  WriteText( xIface, /*bBodyPr=*/true, /*bText=*/false, /*nXmlNamespace=*/nXmlNamespace );
1613  }
1614  else if (GetDocumentType() == DOCUMENT_DOCX)
1615  mpFS->singleElementNS(nXmlNamespace, XML_bodyPr);
1616 
1617  return *this;
1618 }
1619 
1621 {
1622  Reference< XTable > xTable;
1623  Reference< XPropertySet > xPropSet( rXShape, UNO_QUERY );
1624 
1625  mpFS->startElementNS(XML_a, XML_graphic);
1626  mpFS->startElementNS(XML_a, XML_graphicData,
1627  XML_uri, "http://schemas.openxmlformats.org/drawingml/2006/table");
1628 
1629  if ( xPropSet.is() && ( xPropSet->getPropertyValue( "Model" ) >>= xTable ) )
1630  {
1631  mpFS->startElementNS(XML_a, XML_tbl);
1632  mpFS->startElementNS(XML_a, XML_tblPr);
1633  WriteShapeEffects(xPropSet);
1634  mpFS->endElementNS(XML_a, XML_tblPr);
1635 
1636  Reference< container::XIndexAccess > xColumns( xTable->getColumns(), UNO_QUERY_THROW );
1637  Reference< container::XIndexAccess > xRows( xTable->getRows(), UNO_QUERY_THROW );
1638  sal_uInt16 nRowCount = static_cast< sal_uInt16 >( xRows->getCount() );
1639  sal_uInt16 nColumnCount = static_cast< sal_uInt16 >( xColumns->getCount() );
1640 
1641  mpFS->startElementNS(XML_a, XML_tblGrid);
1642 
1643  for ( sal_Int32 x = 0; x < nColumnCount; x++ )
1644  {
1645  Reference< XPropertySet > xColPropSet( xColumns->getByIndex( x ), UNO_QUERY_THROW );
1646  sal_Int32 nWidth(0);
1647  xColPropSet->getPropertyValue( "Width" ) >>= nWidth;
1648 
1649  mpFS->singleElementNS(XML_a, XML_gridCol,
1650  XML_w, OString::number(oox::drawingml::convertHmmToEmu(nWidth)));
1651  }
1652 
1653  mpFS->endElementNS( XML_a, XML_tblGrid );
1654 
1655  // map for holding the transpose index of the merged cells and pair<parentTransposeIndex, parentCell>
1656  typedef std::unordered_map<sal_Int32, std::pair<sal_Int32, Reference< XMergeableCell> > > transposeTableMap;
1657  transposeTableMap mergedCellMap;
1658 
1659  for( sal_Int32 nRow = 0; nRow < nRowCount; nRow++ )
1660  {
1661  Reference< XPropertySet > xRowPropSet( xRows->getByIndex( nRow ), UNO_QUERY_THROW );
1662  sal_Int32 nRowHeight(0);
1663 
1664  xRowPropSet->getPropertyValue( "Height" ) >>= nRowHeight;
1665 
1666  mpFS->startElementNS(XML_a, XML_tr,
1667  XML_h, OString::number(oox::drawingml::convertHmmToEmu(nRowHeight)));
1668  for( sal_Int32 nColumn = 0; nColumn < nColumnCount; nColumn++ )
1669  {
1670  Reference< XMergeableCell > xCell( xTable->getCellByPosition( nColumn, nRow ),
1671  UNO_QUERY_THROW );
1672  sal_Int32 transposedIndexofCell = (nRow * nColumnCount) + nColumn;
1673 
1674  //assume we will open a cell, set to false below if we won't
1675  bool bCellOpened = true;
1676 
1677  if(xCell->getColumnSpan() > 1 && xCell->getRowSpan() > 1)
1678  {
1679  // having both : horizontal and vertical merge
1680  mpFS->startElementNS(XML_a, XML_tc,
1681  XML_gridSpan, OString::number(xCell->getColumnSpan()),
1682  XML_rowSpan, OString::number(xCell->getRowSpan()));
1683  // since, XMergeableCell doesn't have the information about
1684  // cell having hMerge or vMerge.
1685  // So, Populating the merged cell map in-order to use it to
1686  // decide the attribute for the individual cell.
1687  for(sal_Int32 columnIndex = nColumn; columnIndex < nColumn+xCell->getColumnSpan(); ++columnIndex)
1688  {
1689  for(sal_Int32 rowIndex = nRow; rowIndex < nRow+xCell->getRowSpan(); ++rowIndex)
1690  {
1691  sal_Int32 transposeIndexForMergeCell =
1692  (rowIndex * nColumnCount) + columnIndex;
1693  mergedCellMap[transposeIndexForMergeCell] =
1694  std::make_pair(transposedIndexofCell, xCell);
1695  }
1696  }
1697 
1698  }
1699  else if(xCell->getColumnSpan() > 1)
1700  {
1701  // having : horizontal merge
1702  mpFS->startElementNS(XML_a, XML_tc,
1703  XML_gridSpan, OString::number(xCell->getColumnSpan()));
1704  for(sal_Int32 columnIndex = nColumn; columnIndex < nColumn + xCell->getColumnSpan(); ++columnIndex) {
1705  sal_Int32 transposeIndexForMergeCell = (nRow*nColumnCount) + columnIndex;
1706  mergedCellMap[transposeIndexForMergeCell] =
1707  std::make_pair(transposedIndexofCell, xCell);
1708  }
1709  }
1710  else if(xCell->getRowSpan() > 1)
1711  {
1712  // having : vertical merge
1713  mpFS->startElementNS(XML_a, XML_tc,
1714  XML_rowSpan, OString::number(xCell->getRowSpan()));
1715 
1716  for(sal_Int32 rowIndex = nRow; rowIndex < nRow + xCell->getRowSpan(); ++rowIndex) {
1717  sal_Int32 transposeIndexForMergeCell = (rowIndex*nColumnCount) + nColumn;
1718  mergedCellMap[transposeIndexForMergeCell] =
1719  std::make_pair(transposedIndexofCell, xCell);
1720  }
1721  }
1722  else
1723  {
1724  // now, the cell can be an independent cell or
1725  // it can be a cell which is been merged to some parent cell
1726  if(!xCell->isMerged())
1727  {
1728  // independent cell
1729  mpFS->startElementNS(XML_a, XML_tc);
1730  }
1731  else
1732  {
1733  // it a merged cell to some parent cell
1734  // find the parent cell for the current cell at hand
1735  transposeTableMap::iterator it = mergedCellMap.find(transposedIndexofCell);
1736  if(it != mergedCellMap.end())
1737  {
1738  sal_Int32 transposeIndexOfParent = it->second.first;
1739  Reference< XMergeableCell > parentCell = it->second.second;
1740  // finding the row and column index for the parent cell from transposed index
1741  sal_Int32 parentColumnIndex = transposeIndexOfParent % nColumnCount;
1742  sal_Int32 parentRowIndex = transposeIndexOfParent / nColumnCount;
1743  if(nColumn == parentColumnIndex)
1744  {
1745  // the cell is vertical merge and it might have gridspan
1746  if(parentCell->getColumnSpan() > 1)
1747  {
1748  // vMerge and has gridSpan
1749  mpFS->startElementNS(XML_a, XML_tc,
1750  XML_vMerge, OString::number(1),
1751  XML_gridSpan, OString::number(xCell->getColumnSpan()));
1752  }
1753  else
1754  {
1755  // only vMerge
1756  mpFS->startElementNS(XML_a, XML_tc,
1757  XML_vMerge, OString::number(1));
1758  }
1759  }
1760  else if(nRow == parentRowIndex)
1761  {
1762  // the cell is horizontal merge and it might have rowspan
1763  if(parentCell->getRowSpan() > 1)
1764  {
1765  // hMerge and has rowspan
1766  mpFS->startElementNS(XML_a, XML_tc,
1767  XML_hMerge, OString::number(1),
1768  XML_rowSpan, OString::number(xCell->getRowSpan()));
1769  }
1770  else
1771  {
1772  // only hMerge
1773  mpFS->startElementNS(XML_a, XML_tc,
1774  XML_hMerge, OString::number(1));
1775  }
1776  }
1777  else
1778  {
1779  // has hMerge and vMerge
1780  mpFS->startElementNS(XML_a, XML_tc,
1781  XML_vMerge, OString::number(1),
1782  XML_hMerge, OString::number(1));
1783  }
1784  }
1785  else
1786  bCellOpened = false;
1787  }
1788  }
1789 
1790  if (bCellOpened)
1791  {
1792  WriteTextBox( xCell, XML_a );
1793 
1794  Reference< XPropertySet > xCellPropSet(xCell, UNO_QUERY_THROW);
1795  WriteTableCellProperties(xCellPropSet);
1796 
1797  mpFS->endElementNS( XML_a, XML_tc );
1798  }
1799  }
1800 
1801  mpFS->endElementNS( XML_a, XML_tr );
1802  }
1803 
1804  mpFS->endElementNS( XML_a, XML_tbl );
1805  }
1806 
1807  mpFS->endElementNS( XML_a, XML_graphicData );
1808  mpFS->endElementNS( XML_a, XML_graphic );
1809 }
1810 
1812 {
1813  sal_Int32 nLeftMargin(0), nRightMargin(0);
1814  TextVerticalAdjust eVerticalAlignment;
1815  const char* sVerticalAlignment;
1816 
1817  Any aLeftMargin = xCellPropSet->getPropertyValue("TextLeftDistance");
1818  aLeftMargin >>= nLeftMargin;
1819 
1820  Any aRightMargin = xCellPropSet->getPropertyValue("TextRightDistance");
1821  aRightMargin >>= nRightMargin;
1822 
1823  Any aVerticalAlignment = xCellPropSet->getPropertyValue("TextVerticalAdjust");
1824  aVerticalAlignment >>= eVerticalAlignment;
1825  sVerticalAlignment = GetTextVerticalAdjust(eVerticalAlignment);
1826 
1827  mpFS->startElementNS(XML_a, XML_tcPr, XML_anchor, sVerticalAlignment,
1829  XML_marR, sax_fastparser::UseIf(OString::number(oox::drawingml::convertHmmToEmu(nRightMargin)), nRightMargin > 0));
1830 
1831  // Write background fill for table cell.
1832  // TODO
1833  // tcW : Table cell width
1834  WriteTableCellBorders(xCellPropSet);
1835  DrawingML::WriteFill(xCellPropSet);
1836  mpFS->endElementNS( XML_a, XML_tcPr );
1837 }
1838 
1839 void ShapeExport::WriteBorderLine(const sal_Int32 XML_line, const BorderLine2& rBorderLine)
1840 {
1841 // While importing the table cell border line width, it converts EMU->Hmm then divided result by 2.
1842 // To get original value of LineWidth need to multiple by 2.
1843  sal_Int32 nBorderWidth = rBorderLine.LineWidth;
1844  nBorderWidth *= 2;
1845  nBorderWidth = oox::drawingml::convertHmmToEmu( nBorderWidth );
1846 
1847  if ( nBorderWidth > 0 )
1848  {
1849  mpFS->startElementNS(XML_a, XML_line, XML_w, OString::number(nBorderWidth));
1850  if ( rBorderLine.Color == sal_Int32( COL_AUTO ) )
1851  mpFS->singleElementNS(XML_a, XML_noFill);
1852  else
1853  DrawingML::WriteSolidFill( ::Color(ColorTransparency, rBorderLine.Color) );
1854  mpFS->endElementNS( XML_a, XML_line );
1855  }
1856 }
1857 
1859 {
1860  BorderLine2 aBorderLine;
1861 
1862 // lnL - Left Border Line Properties of table cell
1863  xCellPropSet->getPropertyValue("LeftBorder") >>= aBorderLine;
1864  WriteBorderLine( XML_lnL, aBorderLine );
1865 
1866 // lnR - Right Border Line Properties of table cell
1867  xCellPropSet->getPropertyValue("RightBorder") >>= aBorderLine;
1868  WriteBorderLine( XML_lnR, aBorderLine );
1869 
1870 // lnT - Top Border Line Properties of table cell
1871  xCellPropSet->getPropertyValue("TopBorder") >>= aBorderLine;
1872  WriteBorderLine( XML_lnT, aBorderLine );
1873 
1874 // lnB - Bottom Border Line Properties of table cell
1875  xCellPropSet->getPropertyValue("BottomBorder") >>= aBorderLine;
1876  WriteBorderLine( XML_lnB, aBorderLine );
1877 }
1878 
1880 {
1881  FSHelperPtr pFS = GetFS();
1882 
1883  pFS->startElementNS(mnXmlNamespace, XML_graphicFrame);
1884 
1885  pFS->startElementNS(mnXmlNamespace, XML_nvGraphicFramePr);
1886 
1887  pFS->singleElementNS( mnXmlNamespace, XML_cNvPr,
1888  XML_id, OString::number(GetNewShapeID(xShape)),
1889  XML_name, GetShapeName(xShape));
1890 
1891  pFS->singleElementNS(mnXmlNamespace, XML_cNvGraphicFramePr);
1892 
1893  if( GetDocumentType() == DOCUMENT_PPTX )
1894  pFS->singleElementNS(mnXmlNamespace, XML_nvPr);
1895  pFS->endElementNS( mnXmlNamespace, XML_nvGraphicFramePr );
1896 
1898  WriteTable( xShape );
1899 
1900  pFS->endElementNS( mnXmlNamespace, XML_graphicFrame );
1901 
1902  return *this;
1903 }
1904 
1906 {
1907  FSHelperPtr pFS = GetFS();
1908  Reference<XPropertySet> xShapeProps(xShape, UNO_QUERY);
1909 
1910  pFS->startElementNS(mnXmlNamespace, (GetDocumentType() != DOCUMENT_DOCX ? XML_sp : XML_wsp));
1911 
1912  // non visual shape properties
1913  if (GetDocumentType() != DOCUMENT_DOCX)
1914  {
1915  pFS->startElementNS(mnXmlNamespace, XML_nvSpPr);
1916  pFS->startElementNS(mnXmlNamespace, XML_cNvPr,
1917  XML_id, OString::number(GetNewShapeID(xShape)),
1918  XML_name, GetShapeName(xShape));
1919  OUString sURL;
1920  if (GetProperty(xShapeProps, "URL"))
1921  mAny >>= sURL;
1922 
1923  if (!sURL.isEmpty())
1924  {
1925  OUString sRelId = mpFB->addRelation(mpFS->getOutputStream(),
1927  mpURLTransformer->getTransformedString(sURL),
1928  mpURLTransformer->isExternalURL(sURL));
1929 
1930  mpFS->singleElementNS(XML_a, XML_hlinkClick, FSNS(XML_r, XML_id), sRelId);
1931  }
1932  pFS->endElementNS(mnXmlNamespace, XML_cNvPr);
1933  }
1934  pFS->singleElementNS(mnXmlNamespace, XML_cNvSpPr, XML_txBox, "1");
1935  if (GetDocumentType() != DOCUMENT_DOCX)
1936  {
1937  WriteNonVisualProperties( xShape );
1938  pFS->endElementNS( mnXmlNamespace, XML_nvSpPr );
1939  }
1940 
1941  // visual shape properties
1942  pFS->startElementNS(mnXmlNamespace, XML_spPr);
1943  WriteShapeTransformation( xShape, XML_a );
1944  WritePresetShape( "rect" );
1945  uno::Reference<beans::XPropertySet> xPropertySet(xShape, UNO_QUERY);
1946  if (!IsFontworkShape(xShapeProps)) // Fontwork needs fill and outline in run properties instead.
1947  {
1948  WriteBlipOrNormalFill(xPropertySet, "Graphic");
1949  WriteOutline(xPropertySet);
1950  WriteShapeEffects(xPropertySet);
1951  }
1952  pFS->endElementNS( mnXmlNamespace, XML_spPr );
1953 
1954  WriteTextBox( xShape, mnXmlNamespace );
1955 
1956  pFS->endElementNS( mnXmlNamespace, (GetDocumentType() != DOCUMENT_DOCX ? XML_sp : XML_wsp) );
1957 
1958  return *this;
1959 }
1960 
1962 {
1963  Reference<XPropertySet> const xPropSet(xShape, UNO_QUERY);
1964  assert(xPropSet.is());
1965  Reference<XModel> xMathModel;
1966  xPropSet->getPropertyValue("Model") >>= xMathModel;
1967  assert(xMathModel.is());
1968  assert(GetDocumentType() != DOCUMENT_DOCX); // should be written in DocxAttributeOutput
1969  SAL_WARN_IF(GetDocumentType() == DOCUMENT_XLSX, "oox.shape", "Math export to XLSX isn't tested, should it happen here?");
1970 
1971  // ECMA standard does not actually allow oMath outside of
1972  // WordProcessingML so write a MCE like PPT 2010 does
1973  mpFS->startElementNS(XML_mc, XML_AlternateContent);
1974  mpFS->startElementNS(XML_mc, XML_Choice,
1975  FSNS(XML_xmlns, XML_a14), mpFB->getNamespaceURL(OOX_NS(a14)),
1976  XML_Requires, "a14");
1977  mpFS->startElementNS(mnXmlNamespace, XML_sp);
1978  mpFS->startElementNS(mnXmlNamespace, XML_nvSpPr);
1979  mpFS->singleElementNS(mnXmlNamespace, XML_cNvPr,
1980  XML_id, OString::number(GetNewShapeID(xShape)),
1981  XML_name, GetShapeName(xShape));
1982  mpFS->singleElementNS(mnXmlNamespace, XML_cNvSpPr, XML_txBox, "1");
1983  mpFS->singleElementNS(mnXmlNamespace, XML_nvPr);
1984  mpFS->endElementNS(mnXmlNamespace, XML_nvSpPr);
1985  mpFS->startElementNS(mnXmlNamespace, XML_spPr);
1986  WriteShapeTransformation(xShape, XML_a);
1987  WritePresetShape("rect");
1988  mpFS->endElementNS(mnXmlNamespace, XML_spPr);
1989  mpFS->startElementNS(mnXmlNamespace, XML_txBody);
1990  mpFS->startElementNS(XML_a, XML_bodyPr);
1991  mpFS->endElementNS(XML_a, XML_bodyPr);
1992  mpFS->startElementNS(XML_a, XML_p);
1993  mpFS->startElementNS(XML_a14, XML_m);
1994 
1995  oox::FormulaExportBase *const pMagic(dynamic_cast<oox::FormulaExportBase*>(xMathModel.get()));
1996  assert(pMagic);
1997  pMagic->writeFormulaOoxml(GetFS(), GetFB()->getVersion(), GetDocumentType(),
1998  FormulaExportBase::eFormulaAlign::INLINE);
1999 
2000  mpFS->endElementNS(XML_a14, XML_m);
2001  mpFS->endElementNS(XML_a, XML_p);
2002  mpFS->endElementNS(mnXmlNamespace, XML_txBody);
2003  mpFS->endElementNS(mnXmlNamespace, XML_sp);
2004  mpFS->endElementNS(XML_mc, XML_Choice);
2005  mpFS->startElementNS(XML_mc, XML_Fallback);
2006  // TODO: export bitmap shape as fallback
2007  mpFS->endElementNS(XML_mc, XML_Fallback);
2008  mpFS->endElementNS(XML_mc, XML_AlternateContent);
2009 }
2010 
2012 {
2013  Reference< XPropertySet > xPropSet( xShape, UNO_QUERY );
2014  if (!xPropSet.is())
2015  return *this;
2016 
2017  enum { CHART, MATH, OTHER } eType(OTHER);
2018  OUString clsid;
2019  xPropSet->getPropertyValue("CLSID") >>= clsid;
2020  if (!clsid.isEmpty())
2021  {
2023  bool const isValid = aClassID.MakeId(clsid);
2024  assert(isValid); (void)isValid;
2025  if (SotExchange::IsChart(aClassID))
2026  eType = CHART;
2027  else if (SotExchange::IsMath(aClassID))
2028  eType = MATH;
2029  }
2030 
2031  if (CHART == eType)
2032  {
2033  Reference< XChartDocument > xChartDoc;
2034  xPropSet->getPropertyValue("Model") >>= xChartDoc;
2035  assert(xChartDoc.is());
2036  //export the chart
2037  ChartExport aChartExport( mnXmlNamespace, GetFS(), xChartDoc, GetFB(), GetDocumentType() );
2038  static sal_Int32 nChartCount = 0;
2039  aChartExport.WriteChartObj( xShape, GetNewShapeID( xShape ), ++nChartCount );
2040  return *this;
2041  }
2042 
2043  if (MATH == eType)
2044  {
2045  WriteMathShape(xShape);
2046  return *this;
2047  }
2048 
2049  uno::Reference<embed::XEmbeddedObject> const xObj(
2050  xPropSet->getPropertyValue("EmbeddedObject"), uno::UNO_QUERY);
2051 
2052  if (!xObj.is())
2053  {
2054  SAL_WARN("oox.shape", "ShapeExport::WriteOLE2Shape: no object");
2055  return *this;
2056  }
2057 
2058  uno::Sequence<beans::PropertyValue> grabBag;
2059  OUString entryName;
2060  try
2061  {
2062  uno::Reference<beans::XPropertySet> const xParent(
2063  uno::Reference<container::XChild>(xObj, uno::UNO_QUERY_THROW)->getParent(),
2064  uno::UNO_QUERY_THROW);
2065 
2066  xParent->getPropertyValue("InteropGrabBag") >>= grabBag;
2067 
2068  entryName = uno::Reference<embed::XEmbedPersist>(xObj, uno::UNO_QUERY_THROW)->getEntryName();
2069  }
2070  catch (uno::Exception const&)
2071  {
2072  TOOLS_WARN_EXCEPTION("oox.shape", "ShapeExport::WriteOLE2Shape");
2073  return *this;
2074  }
2075 
2076  OUString progID;
2077 
2078  for (auto const& it : std::as_const(grabBag))
2079  {
2080  if (it.Name == "EmbeddedObjects")
2081  {
2082  uno::Sequence<beans::PropertyValue> objects;
2083  it.Value >>= objects;
2084  for (auto const& object : std::as_const(objects))
2085  {
2086  if (object.Name == entryName)
2087  {
2088  uno::Sequence<beans::PropertyValue> props;
2089  object.Value >>= props;
2090  for (auto const& prop : std::as_const(props))
2091  {
2092  if (prop.Name == "ProgID")
2093  {
2094  prop.Value >>= progID;
2095  break;
2096  }
2097  }
2098  break;
2099  }
2100  }
2101  break;
2102  }
2103  }
2104 
2105  OUString sMediaType;
2106  OUString sRelationType;
2107  OUString sSuffix;
2108  const char * pProgID(nullptr);
2109 
2110  uno::Reference<io::XInputStream> const xInStream =
2112  mpFB->getComponentContext(), xObj, progID,
2113  sMediaType, sRelationType, sSuffix, pProgID);
2114 
2115  if (!xInStream.is())
2116  {
2117  return *this;
2118  }
2119 
2120  OString anotherProgID;
2121  if (!pProgID && !progID.isEmpty())
2122  {
2123  anotherProgID = OUStringToOString(progID, RTL_TEXTENCODING_UTF8);
2124  pProgID = anotherProgID.getStr();
2125  }
2126 
2127  assert(!sMediaType.isEmpty());
2128  assert(!sRelationType.isEmpty());
2129  assert(!sSuffix.isEmpty());
2130 
2131  OUString sFileName = "embeddings/oleObject" + OUString::number(++m_nEmbeddedObjects) + "." + sSuffix;
2132  uno::Reference<io::XOutputStream> const xOutStream(
2134  OUString::createFromAscii(GetComponentDir()) + "/" + sFileName,
2135  sMediaType));
2136  assert(xOutStream.is()); // no reason why that could fail
2137 
2138  try {
2139  ::comphelper::OStorageHelper::CopyInputToOutput(xInStream, xOutStream);
2140  } catch (uno::Exception const&) {
2141  TOOLS_WARN_EXCEPTION("oox.shape", "ShapeExport::WriteOLEObject");
2142  }
2143 
2144  OUString const sRelId = mpFB->addRelation(
2145  mpFS->getOutputStream(), sRelationType,
2146  OUString(OUString::createFromAscii(GetRelationCompPrefix()) + sFileName));
2147 
2148  mpFS->startElementNS(mnXmlNamespace, XML_graphicFrame);
2149 
2150  mpFS->startElementNS(mnXmlNamespace, XML_nvGraphicFramePr);
2151 
2152  mpFS->singleElementNS( mnXmlNamespace, XML_cNvPr,
2153  XML_id, OString::number(GetNewShapeID(xShape)),
2154  XML_name, GetShapeName(xShape));
2155 
2156  mpFS->singleElementNS(mnXmlNamespace, XML_cNvGraphicFramePr);
2157 
2158  if (GetDocumentType() == DOCUMENT_PPTX)
2159  mpFS->singleElementNS(mnXmlNamespace, XML_nvPr);
2160  mpFS->endElementNS( mnXmlNamespace, XML_nvGraphicFramePr );
2161 
2163 
2164  mpFS->startElementNS(XML_a, XML_graphic);
2165  mpFS->startElementNS(XML_a, XML_graphicData,
2166  XML_uri, "http://schemas.openxmlformats.org/presentationml/2006/ole");
2167  if (pProgID)
2168  {
2169  mpFS->startElementNS( mnXmlNamespace, XML_oleObj,
2170  XML_progId, pProgID,
2171  FSNS(XML_r, XML_id), sRelId,
2172  XML_spid, "" );
2173  }
2174  else
2175  {
2176  mpFS->startElementNS( mnXmlNamespace, XML_oleObj,
2177 //? XML_name, "Document",
2178  FSNS(XML_r, XML_id), sRelId,
2179  // The spec says that this is a required attribute, but PowerPoint can only handle an empty value.
2180  XML_spid, "" );
2181  }
2182 
2183  mpFS->singleElementNS( mnXmlNamespace, XML_embed );
2184 
2185  // pic element
2186  SdrObject* pSdrOLE2( GetSdrObjectFromXShape( xShape ) );
2187  // The spec doesn't allow <p:pic> here, but PowerPoint requires it.
2188  bool bEcma = mpFB->getVersion() == oox::core::ECMA_DIALECT;
2189  if (bEcma)
2190  if (auto pOle2Obj = dynamic_cast<SdrOle2Obj*>(pSdrOLE2))
2191  {
2192  const Graphic* pGraphic = pOle2Obj->GetGraphic();
2193  if (pGraphic)
2194  WriteGraphicObjectShapePart( xShape, pGraphic );
2195  }
2196 
2197  mpFS->endElementNS( mnXmlNamespace, XML_oleObj );
2198 
2199  mpFS->endElementNS( XML_a, XML_graphicData );
2200  mpFS->endElementNS( XML_a, XML_graphic );
2201 
2202  mpFS->endElementNS( mnXmlNamespace, XML_graphicFrame );
2203 
2204  return *this;
2205 }
2206 
2208 {
2209  // Override this method to do something useful.
2210  return *this;
2211 }
2212 
2213 sal_Int32 ShapeExport::GetNewShapeID( const Reference< XShape >& rXShape )
2214 {
2215  return GetNewShapeID( rXShape, GetFB() );
2216 }
2217 
2218 sal_Int32 ShapeExport::GetNewShapeID( const Reference< XShape >& rXShape, XmlFilterBase* pFB )
2219 {
2220  if( !rXShape.is() )
2221  return -1;
2222 
2223  sal_Int32 nID = pFB->GetUniqueId();
2224 
2225  (*mpShapeMap)[ rXShape ] = nID;
2226 
2227  return nID;
2228 }
2229 
2230 sal_Int32 ShapeExport::GetShapeID( const Reference< XShape >& rXShape )
2231 {
2232  return GetShapeID( rXShape, mpShapeMap );
2233 }
2234 
2235 sal_Int32 ShapeExport::GetShapeID( const Reference< XShape >& rXShape, ShapeHashMap* pShapeMap )
2236 {
2237  if( !rXShape.is() )
2238  return -1;
2239 
2240  ShapeHashMap::const_iterator aIter = pShapeMap->find( rXShape );
2241 
2242  if( aIter == pShapeMap->end() )
2243  return -1;
2244 
2245  return aIter->second;
2246 }
2247 
2249 {
2250  Reference<XPropertySet> rXPropSet(xShape, UNO_QUERY);
2251 
2252  // Empty name keeps the object unnamed.
2253  OUString sName;
2254 
2255  if (GetProperty(rXPropSet, "Name"))
2256  mAny >>= sName;
2257  return sName;
2258 }
2259 
2260 }
2261 
2262 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_uInt16 Count() const
void WriteTableCellBorders(const css::uno::Reference< css::beans::XPropertySet > &rXPropSet)
Definition: shapes.cxx:1858
#define SO3_SM_CLASSID_60
Interface to be implemented by the parent exporter that knows how to handle shape text...
Definition: drawingml.hxx:122
ShapeExport & WriteTableShape(const css::uno::Reference< css::drawing::XShape > &xShape)
Definition: shapes.cxx:1879
const char *const aClassID
const char * sName
Definition: olehelper.cxx:92
void WriteConnectorConnections(EscherConnectorListEntry &rConnectorEntry, sal_Int32 nStartID, sal_Int32 nEndID)
Definition: drawingml.cxx:3966
ShapeExport & WriteNonVisualDrawingProperties(const css::uno::Reference< css::drawing::XShape > &xShape, const char *sName)
Definition: shapes.cxx:1458
mso_sptSun
static bool IsNonEmptySimpleText(const Reference< XInterface > &xIface)
Definition: shapes.cxx:352
ShapeExport(sal_Int32 nXmlNamespace,::sax_fastparser::FSHelperPtr pFS, ShapeHashMap *pShapeMap,::oox::core::XmlFilterBase *pFB, DocumentType eDocumentType=DOCUMENT_PPTX, DMLTextExport *pTextExport=nullptr)
Definition: shapes.cxx:324
TextVerticalAdjust GetTextVerticalAdjust(sal_Int32 nToken)
static void CopyInputToOutput(const css::uno::Reference< css::io::XInputStream > &xInput, const css::uno::Reference< css::io::XOutputStream > &xOutput)
SAL_WARN_UNUSED_RESULT Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
tools::Long getWidth() const
int n1
Visible
tools::Long const nLeftMargin
mso_sptCube
void WriteShapeTransformation(const css::uno::Reference< css::drawing::XShape > &rXShape, sal_Int32 nXmlNamespace, bool bFlipH=false, bool bFlipV=false, bool bSuppressRotation=false, bool bSuppressFlipping=false, bool bFlippedBeforeRotation=false)
Definition: drawingml.cxx:1771
static const NameToConvertMapType & lcl_GetConverters()
Definition: shapes.cxx:1530
void WriteText(const css::uno::Reference< css::uno::XInterface > &rXIface, bool bBodyPr, bool bText=true, sal_Int32 nXmlNamespace=0, bool bWritePropertiesAsLstStyles=false)
Definition: drawingml.cxx:3066
OoxmlVersion getVersion() const
Definition: filterbase.cxx:207
#define SO3_SIMPRESS_CLASSID_60
void WriteTable(const css::uno::Reference< css::drawing::XShape > &rXShape)
Definition: shapes.cxx:1620
constexpr::Color COL_AUTO(ColorTransparency, 0xFF, 0xFF, 0xFF, 0xFF)
ShapeExport & WriteOLE2Shape(const css::uno::Reference< css::drawing::XShape > &xShape)
Definition: shapes.cxx:2011
void WriteMathShape(css::uno::Reference< css::drawing::XShape > const &xShape)
Definition: shapes.cxx:1961
virtual ShapeExport & WriteUnknownShape(const css::uno::Reference< css::drawing::XShape > &xShape)
Definition: shapes.cxx:2207
mso_sptCan
tuple args
void WriteGraphicObjectShapePart(const css::uno::Reference< css::drawing::XShape > &xShape, const Graphic *pGraphic=nullptr)
Definition: shapes.cxx:1147
OUString GetShapeName(const css::uno::Reference< css::drawing::XShape > &xShape)
Definition: shapes.cxx:2248
void WriteShape3DEffects(const css::uno::Reference< css::beans::XPropertySet > &rXPropSet)
Definition: drawingml.cxx:4546
std::shared_ptr< URLTransformer > mpURLTransformer
Definition: shapes.hxx:98
css::uno::Reference< css::io::XOutputStream > openFragmentStream(const OUString &rStreamName, const OUString &rMediaType)
Opens and returns the specified output stream from the base storage with specified media type...
mso_sptBracketPair
OUString Name
::sax_fastparser::FSHelperPtr mpFS
Definition: drawingml.hxx:160
ShapeExport & WriteGroupShape(const css::uno::Reference< css::drawing::XShape > &xShape)
Definition: shapes.cxx:467
ShapeExport & WriteGraphicObjectShape(const css::uno::Reference< css::drawing::XShape > &xShape)
Definition: shapes.cxx:1140
float x
constexpr double rad2deg(double v)
ShapeExport & WriteClosedPolyPolygonShape(const css::uno::Reference< css::drawing::XShape > &xShape)
Definition: shapes.cxx:457
css::awt::Size MapSize(const css::awt::Size &) const
Definition: shapes.cxx:341
bool GetProperty(const css::uno::Reference< css::beans::XPropertySet > &rXPropSet, const OUString &aName)
Definition: drawingml.cxx:261
static sal_uInt16 IsChart(const SvGlobalName &rName)
ShapeExport & WriteEllipseShape(const css::uno::Reference< css::drawing::XShape > &xShape)
Definition: shapes.cxx:1045
css::uno::Reference< css::graphic::XGraphic > GetXGraphic() const
static uno::Reference< io::XInputStream > lcl_StoreOwnAsOOXML(uno::Reference< uno::XComponentContext > const &xContext, uno::Reference< embed::XEmbeddedObject > const &xObj, char const *&o_rpProgID, OUString &o_rMediaType, OUString &o_rRelationType, OUString &o_rSuffix)
Definition: shapes.cxx:193
static sal_Int32 lcl_NormalizeAngle(sal_Int32 nAngle)
Definition: shapes.cxx:676
const char * GetRelationCompPrefix() const
Definition: drawingml.cxx:1163
void WriteBlipOrNormalFill(const css::uno::Reference< css::beans::XPropertySet > &rXPropSet, const OUString &rURLPropName)
Definition: drawingml.cxx:1511
tools::Long getHeight() const
Value
constexpr tools::Long Width() const
mso_sptNoSmoking
bool IsFontworkShape(const css::uno::Reference< css::beans::XPropertySet > &rXShapePropSet)
Definition: drawingml.cxx:3035
mso_sptWedgeEllipseCallout
int n2
void WriteSolidFill(::Color nColor, sal_Int32 nAlpha=MAX_PERCENT)
Definition: drawingml.cxx:401
OUString getNamespaceURL(sal_Int32 nNSID) const
virtual ShapeExport & WriteTextShape(const css::uno::Reference< css::drawing::XShape > &xShape)
Definition: shapes.cxx:1905
MSO_SPT
void WriteShapeEffects(const css::uno::Reference< css::beans::XPropertySet > &rXPropSet)
Definition: drawingml.cxx:4305
void WriteTransformation(const css::uno::Reference< css::drawing::XShape > &xShape, const tools::Rectangle &rRectangle, sal_Int32 nXmlNamespace, bool bFlipH=false, bool bFlipV=false, sal_Int32 nRotation=0, bool bIsGroupShape=false)
Definition: drawingml.cxx:1732
OUString sSuffix
ShapeExport & WriteShape(const css::uno::Reference< css::drawing::XShape > &xShape)
Write the DrawingML for a particular shape.
Definition: shapes.cxx:1567
mso_sptBlockArc
mso_sptVerticalScroll
constexpr tools::Long GetWidth() const
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
void WriteShapeStyle(const css::uno::Reference< css::beans::XPropertySet > &rXPropSet)
Definition: drawingml.cxx:4088
#define SO3_SC_CLASSID_60
void WritePolyPolygon(const css::uno::Reference< css::drawing::XShape > &rXShape, const tools::PolyPolygon &rPolyPolygon, const bool bClosed)
Definition: drawingml.cxx:3880
static sal_uInt16 IsMath(const SvGlobalName &rName)
void WriteFill(const css::uno::Reference< css::beans::XPropertySet > &xPropSet)
Definition: drawingml.cxx:4016
#define SO3_SCH_CLASSID_60
css::uno::Sequence< css::beans::PropertyValue > InitPropertySequence(::std::initializer_list< ::std::pair< OUString, css::uno::Any > > vInit)
void setX(tools::Long x)
void WriteTableCellProperties(const css::uno::Reference< css::beans::XPropertySet > &rXPropSet)
Definition: shapes.cxx:1811
OUString getRelationship(Relationship eRelationship)
B2IRange fround(const B2DRange &rRange)
ShapeExport & WriteCustomShape(const css::uno::Reference< css::drawing::XShape > &xShape)
Definition: shapes.cxx:697
const ::sax_fastparser::FSHelperPtr & GetFS() const
Definition: drawingml.hxx:207
static bool IsDefaultObject(const SdrObjCustomShape &rSdrObjCustomShape, const MSO_SPT eShapeType)
static tools::PolyPolygon GetPolyPolygon(const css::uno::Reference< css::drawing::XShape > &rXShape)
DocumentType eType
ShapeFlag
void setY(tools::Long y)
sal_uInt16 char * pName
std::unordered_map< const char *, ShapeConverter, rtl::CStringHash, rtl::CStringEqual > NameToConvertMapType
Definition: shapes.cxx:1528
mso_sptHorizontalScroll
DocumentType GetDocumentType() const
Definition: drawingml.hxx:209
void WriteMediaNonVisualProperties(const css::uno::Reference< css::drawing::XShape > &xShape)
Output the media (including copying a video from vnd.sun.star.Package: to the output if necessary)...
Definition: drawingml.cxx:1294
#define TOOLS_WARN_EXCEPTION(area, stream)
bool WriteCustomGeometry(const css::uno::Reference< css::drawing::XShape > &rXShape, const SdrObjCustomShape &rSdrObjCustomShape)
Definition: drawingml.cxx:3607
Interface class, StarMath will implement writeFormula*() to write out markup representing the formula...
Definition: export.hxx:26
mso_sptWedgeRectCallout
static void lcl_ConvertProgID(OUString const &rProgID, OUString &o_rMediaType, OUString &o_rRelationType, OUString &o_rFileExtension)
Definition: shapes.cxx:98
mso_sptDonut
ShapeExport & WriteLineShape(const css::uno::Reference< css::drawing::XShape > &xShape)
Definition: shapes.cxx:1401
mso_sptBorderCallout1
sal_Int32 GetShapeID(const css::uno::Reference< css::drawing::XShape > &rShape)
static bool lcl_GetHandlePosition(sal_Int32 &nValue, const EnhancedCustomShapeParameter &rParam, Sequence< EnhancedCustomShapeAdjustmentValue > &rSeq)
Definition: shapes.cxx:608
MATH
const char * GetOOXMLPresetGeometry(const char *sShapeType)
ShapeExport & WritePolyPolygonShape(const css::uno::Reference< css::drawing::XShape > &xShape, bool bClosed)
Definition: shapes.cxx:396
sal_Int64 convertHmmToEmu(sal_Int32 nValue)
Converts the passed 32-bit integer value from 1/100 mm to EMUs.
#define SO3_SW_CLASSID_60
float u
ShapeExport & WriteOpenPolyPolygonShape(const css::uno::Reference< css::drawing::XShape > &xShape)
Definition: shapes.cxx:462
const css::uno::Reference< css::uno::XComponentContext > & getComponentContext() const
Returns the component context passed in the filter constructor (always existing). ...
Definition: filterbase.cxx:212
dictionary props
Definition: properties.py:26
SVXCORE_DLLPUBLIC SdrObject * GetSdrObjectFromXShape(const css::uno::Reference< css::drawing::XShape > &xShape) noexcept
size
virtual void writeFormulaOoxml(::sax_fastparser::FSHelperPtr pSerializer, oox::core::OoxmlVersion version, oox::drawingml::DocumentType documentType, sal_Int8 nAlign)=0
constexpr double deg2rad(double v)
static sal_Int32 lcl_CircleAngle2CustomShapeEllipseAngleOOX(const sal_Int32 nInternAngle, const sal_Int32 nWidth, const sal_Int32 nHeight)
Definition: shapes.cxx:682
ColorTransparency
void WriteBorderLine(const sal_Int32 XML_line, const css::table::BorderLine2 &rBorderLine)
Definition: shapes.cxx:1839
mso_sptFoldedCorner
mso_sptBorderCallout2
#define GETAD(propName)
Definition: shapes.cxx:317
static bool lcl_IsOnDenylist(OUString const &rShapeType)
Definition: shapes.cxx:531
std::shared_ptr< FastSerializerHelper > FSHelperPtr
#define GETA(propName)
Definition: shapes.cxx:314
void WriteOutline(const css::uno::Reference< css::beans::XPropertySet > &rXPropSet, css::uno::Reference< css::frame::XModel > const &xModel=nullptr)
Definition: drawingml.cxx:816
ShapeExport &(ShapeExport::* ShapeConverter)(const Reference< XShape > &)
Definition: shapes.cxx:1527
ShapeExport & WriteConnectorShape(const css::uno::Reference< css::drawing::XShape > &xShape)
Definition: shapes.cxx:1293
ShapeExport & WriteRectangleShape(const css::uno::Reference< css::drawing::XShape > &xShape)
Definition: shapes.cxx:1473
basegfx::B2DPolyPolygon GetLineGeometry(const bool bBezierAllowed) const
#define GET(variable, propName)
Definition: shapes.cxx:320
mso_sptWedgeRRectCallout
static bool lcl_IsOnAllowlist(OUString const &rShapeType)
Definition: shapes.cxx:598
mutable::std::map< Reference< XShape >, Reference< XShape > > maShapeMap
static void lcl_AppendAdjustmentValue(std::vector< std::pair< sal_Int32, sal_Int32 > > &rAvList, sal_Int32 nAdjIdx, sal_Int32 nValue)
Definition: shapes.cxx:671
css::uno::Reference< css::drawing::XShape > m_xParent
If set, this is the parent of the currently handled shape.
Definition: drawingml.hxx:163
constexpr OUStringLiteral sMediaType
sal_Int32 GetNewShapeID(const css::uno::Reference< css::drawing::XShape > &rShape)
#define SAL_WARN_IF(condition, area, stream)
constexpr tools::Long Height() const
unsigned char sal_uInt8
void WriteSrcRectXGraphic(css::uno::Reference< css::beans::XPropertySet > const &rxPropertySet, css::uno::Reference< css::graphic::XGraphic > const &rxGraphic)
Definition: drawingml.cxx:1666
void setWidth(tools::Long n)
eFillStyle
static void lcl_AnalyzeHandles(const uno::Sequence< beans::PropertyValues > &rHandles, std::vector< std::pair< sal_Int32, sal_Int32 > > &rHandlePositionList, Sequence< EnhancedCustomShapeAdjustmentValue > &rSeq)
Definition: shapes.cxx:642
#define SAL_INFO(area, stream)
::oox::core::XmlFilterBase * GetFB()
Definition: drawingml.hxx:208
tools::Long AdjustWidth(tools::Long n)
void SetURLTranslator(const std::shared_ptr< URLTransformer > &pTransformer)
Definition: shapes.cxx:336
tools::Long const nRightMargin
DMLTextExport * GetTextExport()
The application-specific text exporter callback, if there is one.
Definition: drawingml.hxx:211
ShapeHashMap * mpShapeMap
Definition: shapes.hxx:103
tools::Long AdjustHeight(tools::Long n)
constexpr sal_Int32 FSNS(sal_Int32 namespc, sal_Int32 element)
const char * GetComponentDir() const
Definition: drawingml.cxx:1151
virtual ShapeExport & WriteNonVisualProperties(const css::uno::Reference< css::drawing::XShape > &xShape)
Definition: shapes.cxx:1467
uno::Reference< io::XInputStream > GetOLEObjectStream(uno::Reference< uno::XComponentContext > const &xContext, uno::Reference< embed::XEmbeddedObject > const &xObj, OUString const &i_rProgID, OUString &o_rMediaType, OUString &o_rRelationType, OUString &o_rSuffix, const char *&o_rpProgID)
Definition: shapes.cxx:272
std::unordered_map< css::uno::Reference< css::drawing::XShape >, sal_Int32 > ShapeHashMap
Definition: shapes.hxx:86
::oox::core::XmlFilterBase * mpFB
Definition: drawingml.hxx:161
ShapeExport & WriteTextBox(const css::uno::Reference< css::uno::XInterface > &xIface, sal_Int32 nXmlNamespace, bool bWritePropertiesAsLstStyles=false)
Definition: shapes.cxx:1583
MapUnit
#define SAL_WARN(area, stream)
Class for exporting the custom shapes to OOXML preset ones, if possible.
static bool NonEmptyText(const css::uno::Reference< css::uno::XInterface > &xIface)
Definition: shapes.cxx:360
mso_sptMoon
mso_sptCloudCallout
mso_sptBracePair
const char * UseIf(const char *s, bool bUse)
virtual void WriteTextBox(css::uno::Reference< css::drawing::XShape > xShape)=0
Write the contents of the textbox that is associated to this shape.
OUString addRelation(const OUString &rType, std::u16string_view rTarget)
Adds new relation.
static MSO_SPT GetCustomShapeType(const css::uno::Reference< css::drawing::XShape > &rXShape, ShapeFlag &nMirrorFlags, OUString &rShapeType, bool bOOXML=false)
bool MakeId(const OUString &rId)
void setHeight(tools::Long n)
OUString WriteXGraphicBlip(css::uno::Reference< css::beans::XPropertySet > const &rXPropSet, css::uno::Reference< css::graphic::XGraphic > const &rxGraphic, bool bRelPathToMedia)
Definition: drawingml.cxx:1443
mso_sptBevel
mso_sptSmileyFace
constexpr tools::Long GetHeight() const
void WritePresetShape(const char *pShape, std::vector< std::pair< sal_Int32, sal_Int32 >> &rAvList)
Definition: drawingml.cxx:3506
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo