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