LibreOffice Module xmloff (master)  1
shapeexport.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 
31 
32 #include <com/sun/star/beans/XPropertyState.hpp>
33 #include <com/sun/star/beans/PropertyValues.hpp>
34 #include <com/sun/star/container/XChild.hpp>
35 #include <com/sun/star/container/XEnumerationAccess.hpp>
36 #include <com/sun/star/container/XIdentifierAccess.hpp>
37 #include <com/sun/star/container/XNamed.hpp>
38 #include <com/sun/star/document/XEventsSupplier.hpp>
39 #include <com/sun/star/drawing/Alignment.hpp>
40 #include <com/sun/star/drawing/CameraGeometry.hpp>
41 #include <com/sun/star/drawing/CircleKind.hpp>
42 #include <com/sun/star/drawing/ConnectorType.hpp>
43 #include <com/sun/star/drawing/Direction3D.hpp>
44 #include <com/sun/star/drawing/EscapeDirection.hpp>
45 #include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
46 #include <com/sun/star/drawing/EnhancedCustomShapeGluePointType.hpp>
47 #include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp>
48 #include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp>
49 #include <com/sun/star/drawing/EnhancedCustomShapeMetalType.hpp>
50 #include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp>
51 #include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp>
52 #include <com/sun/star/drawing/EnhancedCustomShapeTextFrame.hpp>
53 #include <com/sun/star/drawing/EnhancedCustomShapeTextPathMode.hpp>
54 #include <com/sun/star/drawing/GluePoint2.hpp>
55 #include <com/sun/star/drawing/HomogenMatrix.hpp>
56 #include <com/sun/star/drawing/HomogenMatrix3.hpp>
57 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
58 #include <com/sun/star/drawing/PolyPolygonShape3D.hpp>
59 #include <com/sun/star/drawing/Position3D.hpp>
60 #include <com/sun/star/drawing/ProjectionMode.hpp>
61 #include <com/sun/star/drawing/ShadeMode.hpp>
62 #include <com/sun/star/drawing/XControlShape.hpp>
63 #include <com/sun/star/drawing/XCustomShapeEngine.hpp>
64 #include <com/sun/star/drawing/XGluePointsSupplier.hpp>
65 #include <com/sun/star/drawing/BarCode.hpp>
66 #include <com/sun/star/drawing/BarCodeErrorCorrection.hpp>
67 #include <com/sun/star/drawing/XShapes3.hpp>
68 #include <com/sun/star/embed/ElementModes.hpp>
69 #include <com/sun/star/embed/XStorage.hpp>
70 #include <com/sun/star/embed/XTransactedObject.hpp>
71 #include <com/sun/star/graphic/XGraphic.hpp>
72 #include <com/sun/star/graphic/GraphicProvider.hpp>
73 #include <com/sun/star/graphic/XGraphicProvider.hpp>
74 #include <com/sun/star/io/XSeekableInputStream.hpp>
75 #include <com/sun/star/io/XStream.hpp>
76 #include <com/sun/star/lang/ServiceNotRegisteredException.hpp>
77 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
78 #include <com/sun/star/media/ZoomLevel.hpp>
79 #include <com/sun/star/presentation/AnimationSpeed.hpp>
80 #include <com/sun/star/presentation/ClickAction.hpp>
81 #include <com/sun/star/style/XStyle.hpp>
82 #include <com/sun/star/table/XColumnRowRange.hpp>
83 #include <com/sun/star/text/XText.hpp>
84 
85 #include <comphelper/classids.hxx>
89 #include <officecfg/Office/Common.hxx>
90 
91 #include <o3tl/any.hxx>
92 #include <o3tl/typed_flags_set.hxx>
93 #include <o3tl/string_view.hxx>
94 
95 #include <rtl/math.hxx>
96 #include <rtl/ustrbuf.hxx>
97 #include <rtl/ustring.hxx>
98 #include <sal/log.hxx>
99 
100 #include <sax/tools/converter.hxx>
101 
102 #include <tools/debug.hxx>
103 #include <tools/globname.hxx>
104 #include <tools/helpers.hxx>
105 #include <tools/diagnose_ex.h>
106 
107 #include <xmloff/contextid.hxx>
108 #include <xmloff/families.hxx>
109 #include <xmloff/namespacemap.hxx>
110 #include <xmloff/shapeexport.hxx>
112 #include <xmloff/xmlexp.hxx>
113 #include <xmloff/xmlnamespace.hxx>
114 #include <xmloff/xmltoken.hxx>
115 #include <xmloff/xmluconv.hxx>
118 
119 #include <anim.hxx>
121 #include "sdpropls.hxx"
122 #include <xexptran.hxx>
123 #include "ximpshap.hxx"
124 #include <XMLBase64Export.hxx>
125 #include <XMLImageMapExport.hxx>
126 #include <memory>
127 
128 using namespace ::com::sun::star;
129 using namespace ::xmloff::EnhancedCustomShapeToken;
130 using namespace ::xmloff::token;
131 
132 constexpr OUStringLiteral XML_EMBEDDEDOBJECTGRAPHIC_URL_BASE = u"vnd.sun.star.GraphicObject:";
133 
134 namespace {
135 
136 bool supportsText(XmlShapeType eShapeType)
137 {
138  return eShapeType != XmlShapeTypePresChartShape &&
139  eShapeType != XmlShapeTypePresOLE2Shape &&
140  eShapeType != XmlShapeTypeDrawSheetShape &&
141  eShapeType != XmlShapeTypePresSheetShape &&
142  eShapeType != XmlShapeTypeDraw3DSceneObject &&
143  eShapeType != XmlShapeTypeDraw3DCubeObject &&
144  eShapeType != XmlShapeTypeDraw3DSphereObject &&
145  eShapeType != XmlShapeTypeDraw3DLatheObject &&
146  eShapeType != XmlShapeTypeDraw3DExtrudeObject &&
147  eShapeType != XmlShapeTypeDrawPageShape &&
148  eShapeType != XmlShapeTypePresPageShape &&
149  eShapeType != XmlShapeTypeDrawGroupShape;
150 
151 }
152 
153 }
154 
155 constexpr OUStringLiteral gsZIndex( u"ZOrder" );
156 constexpr OUStringLiteral gsPrintable( u"Printable" );
157 constexpr OUStringLiteral gsVisible( u"Visible" );
158 constexpr OUStringLiteral gsModel( u"Model" );
159 constexpr OUStringLiteral gsStartShape( u"StartShape" );
160 constexpr OUStringLiteral gsEndShape( u"EndShape" );
161 constexpr OUStringLiteral gsOnClick( u"OnClick" );
162 constexpr OUStringLiteral gsEventType( u"EventType" );
163 constexpr OUStringLiteral gsPresentation( u"Presentation" );
164 constexpr OUStringLiteral gsMacroName( u"MacroName" );
165 constexpr OUStringLiteral gsScript( u"Script" );
166 constexpr OUStringLiteral gsLibrary( u"Library" );
167 constexpr OUStringLiteral gsClickAction( u"ClickAction" );
168 constexpr OUStringLiteral gsBookmark( u"Bookmark" );
169 constexpr OUStringLiteral gsEffect( u"Effect" );
170 constexpr OUStringLiteral gsPlayFull( u"PlayFull" );
171 constexpr OUStringLiteral gsVerb( u"Verb" );
172 constexpr OUStringLiteral gsSoundURL( u"SoundURL" );
173 constexpr OUStringLiteral gsSpeed( u"Speed" );
174 constexpr OUStringLiteral gsStarBasic( u"StarBasic" );
175 constexpr OUStringLiteral gsHyperlink( u"Hyperlink" );
176 
178  SvXMLExportPropertyMapper *pExtMapper )
179 : mrExport( rExp ),
180  maCurrentShapesIter(maShapesInfos.end()),
181  mbExportLayer( false ),
182  // #88546# init to sal_False
183  mbHandleProgressBar( false )
184 {
185  // construct PropertySetMapper
187  if( pExtMapper )
188  {
189  rtl::Reference < SvXMLExportPropertyMapper > xExtMapper( pExtMapper );
190  mxPropertySetMapper->ChainExportMapper( xExtMapper );
191  }
192 
193 /*
194  // chain text attributes
195  xPropertySetMapper->ChainExportMapper(XMLTextParagraphExport::CreateParaExtPropMapper(rExp));
196 */
197 
198  mrExport.GetAutoStylePool()->AddFamily(
203  mrExport.GetAutoStylePool()->AddFamily(
208 
209  // create table export helper and let him add his families in time
211 }
212 
214 {
215 }
216 
217 // sj: replacing CustomShapes with standard objects that are also supported in OpenOffice.org format
218 uno::Reference< drawing::XShape > XMLShapeExport::checkForCustomShapeReplacement( const uno::Reference< drawing::XShape >& xShape )
219 {
220  uno::Reference< drawing::XShape > xCustomShapeReplacement;
221 
222  if( !( GetExport().getExportFlags() & SvXMLExportFlags::OASIS ) )
223  {
224  OUString aType( xShape->getShapeType() );
225  if( aType == "com.sun.star.drawing.CustomShape" )
226  {
227  uno::Reference< beans::XPropertySet > xSet( xShape, uno::UNO_QUERY );
228  if( xSet.is() )
229  {
230  OUString aEngine;
231  xSet->getPropertyValue("CustomShapeEngine") >>= aEngine;
232  if ( aEngine.isEmpty() )
233  {
234  aEngine = "com.sun.star.drawing.EnhancedCustomShapeEngine";
235  }
236  uno::Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
237 
238  if ( !aEngine.isEmpty() )
239  {
240  uno::Sequence< beans::PropertyValue > aPropValues{
241  comphelper::makePropertyValue("CustomShape", xShape),
242  comphelper::makePropertyValue("ForceGroupWithText", true)
243  };
244  uno::Sequence< uno::Any > aArgument = { uno::Any(aPropValues) };
245  uno::Reference< uno::XInterface > xInterface(
246  xContext->getServiceManager()->createInstanceWithArgumentsAndContext(aEngine, aArgument, xContext) );
247  if ( xInterface.is() )
248  {
249  uno::Reference< drawing::XCustomShapeEngine > xCustomShapeEngine(
250  uno::Reference< drawing::XCustomShapeEngine >( xInterface, uno::UNO_QUERY ) );
251  if ( xCustomShapeEngine.is() )
252  xCustomShapeReplacement = xCustomShapeEngine->render();
253  }
254  }
255  }
256  }
257  }
258  return xCustomShapeReplacement;
259 }
260 
261 // This method collects all automatic styles for the given XShape
262 void XMLShapeExport::collectShapeAutoStyles(const uno::Reference< drawing::XShape >& xShape )
263 {
264  if( maCurrentShapesIter == maShapesInfos.end() )
265  {
266  OSL_FAIL( "XMLShapeExport::collectShapeAutoStyles(): no call to seekShapes()!" );
267  return;
268  }
269  sal_Int32 nZIndex = 0;
270  uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
271  if( xPropSet.is() )
272  xPropSet->getPropertyValue(gsZIndex) >>= nZIndex;
273 
274  ImplXMLShapeExportInfoVector& aShapeInfoVector = (*maCurrentShapesIter).second;
275 
276  if( static_cast<sal_Int32>(aShapeInfoVector.size()) <= nZIndex )
277  {
278  OSL_FAIL( "XMLShapeExport::collectShapeAutoStyles(): no shape info allocated for a given shape" );
279  return;
280  }
281 
282  ImplXMLShapeExportInfo& aShapeInfo = aShapeInfoVector[nZIndex];
283 
284  uno::Reference< drawing::XShape > xCustomShapeReplacement = checkForCustomShapeReplacement( xShape );
285  if ( xCustomShapeReplacement.is() )
286  aShapeInfo.xCustomShapeReplacement = xCustomShapeReplacement;
287 
288  // first compute the shapes type
289  ImpCalcShapeType(xShape, aShapeInfo.meShapeType);
290 
291  // #i118485# enabled XmlShapeTypeDrawChartShape and XmlShapeTypeDrawOLE2Shape
292  // to have text
293  const bool bObjSupportsText =
294  supportsText(aShapeInfo.meShapeType);
295 
296  const bool bObjSupportsStyle =
298 
299  bool bIsEmptyPresObj = false;
300 
301  if ( aShapeInfo.xCustomShapeReplacement.is() )
302  xPropSet.clear();
303 
304  // prep text styles
305  if( xPropSet.is() && bObjSupportsText )
306  {
307  uno::Reference< text::XText > xText(xShape, uno::UNO_QUERY);
308  bool bSkip = false;
309  if (xText.is())
310  {
311  try
312  {
313  bSkip = xText->getString().isEmpty();
314  }
315  catch (uno::RuntimeException const&)
316  {
317  // tdf#102479: SwXTextFrame that contains only a table will
318  // throw, but the table must be iterated so that
319  // SwXMLExport::ExportTableLines() can find its auto styles
320  // so do not skip it!
321  }
322  }
323  if (!bSkip)
324  {
325  uno::Reference< beans::XPropertySetInfo > xPropSetInfo( xPropSet->getPropertySetInfo() );
326 
327  if( xPropSetInfo.is() && xPropSetInfo->hasPropertyByName("IsEmptyPresentationObject") )
328  {
329  uno::Any aAny = xPropSet->getPropertyValue("IsEmptyPresentationObject");
330  aAny >>= bIsEmptyPresObj;
331  }
332 
333  if(!bIsEmptyPresObj)
334  {
335  GetExport().GetTextParagraphExport()->collectTextAutoStyles( xText );
336  }
337  }
338  }
339 
340  // compute the shape parent style
341  if( xPropSet.is() )
342  {
343  uno::Reference< beans::XPropertySetInfo > xPropertySetInfo( xPropSet->getPropertySetInfo() );
344 
345  OUString aParentName;
346  uno::Reference< style::XStyle > xStyle;
347 
348  if( bObjSupportsStyle )
349  {
350  if( xPropertySetInfo.is() && xPropertySetInfo->hasPropertyByName("Style") )
351  xPropSet->getPropertyValue("Style") >>= xStyle;
352 
353  if(xStyle.is())
354  {
355  // get family ID
356  uno::Reference< beans::XPropertySet > xStylePropSet(xStyle, uno::UNO_QUERY);
357  SAL_WARN_IF( !xStylePropSet.is(), "xmloff", "style without a XPropertySet?" );
358  try
359  {
360  if(xStylePropSet.is())
361  {
362  OUString aFamilyName;
363  xStylePropSet->getPropertyValue("Family") >>= aFamilyName;
364  if( !aFamilyName.isEmpty() && aFamilyName != "graphics" )
366  }
367  }
368  catch(const beans::UnknownPropertyException&)
369  {
370  // Ignored.
371  SAL_WARN( "xmloff",
372  "XMLShapeExport::collectShapeAutoStyles: style has no 'Family' property");
373  }
374 
375  // get parent-style name
377  {
378  aParentName = msPresentationStylePrefix;
379  }
380 
381  aParentName += xStyle->getName();
382  }
383  }
384 
385  if (aParentName.isEmpty() && xPropertySetInfo->hasPropertyByName("TextBox") && xPropSet->getPropertyValue("TextBox").hasValue() && xPropSet->getPropertyValue("TextBox").get<bool>())
386  {
387  // Shapes with a Writer TextBox always have a parent style.
388  // If there would be none, then assign the default one.
389  aParentName = "Frame";
390  }
391 
392  // filter propset
393  std::vector< XMLPropertyState > aPropStates;
394 
395  sal_Int32 nCount = 0;
396  if( !bIsEmptyPresObj || (aShapeInfo.meShapeType != XmlShapeTypePresPageShape) )
397  {
398  aPropStates = GetPropertySetMapper()->Filter(mrExport, xPropSet);
399 
400  if (XmlShapeTypeDrawControlShape == aShapeInfo.meShapeType)
401  {
402  // for control shapes, we additionally need the number format style (if any)
403  uno::Reference< drawing::XControlShape > xControl(xShape, uno::UNO_QUERY);
404  DBG_ASSERT(xControl.is(), "XMLShapeExport::collectShapeAutoStyles: ShapeType control, but no XControlShape!");
405  if (xControl.is())
406  {
407  uno::Reference< beans::XPropertySet > xControlModel(xControl->getControl(), uno::UNO_QUERY);
408  DBG_ASSERT(xControlModel.is(), "XMLShapeExport::collectShapeAutoStyles: no control model on the control shape!");
409 
410  OUString sNumberStyle = mrExport.GetFormExport()->getControlNumberStyle(xControlModel);
411  if (!sNumberStyle.isEmpty())
412  {
413  sal_Int32 nIndex = GetPropertySetMapper()->getPropertySetMapper()->FindEntryIndex(CTF_SD_CONTROL_SHAPE_DATA_STYLE);
414  // TODO : this retrieval of the index could be moved into the ctor, holding the index
415  // as member, thus saving time.
416  DBG_ASSERT(-1 != nIndex, "XMLShapeExport::collectShapeAutoStyles: could not obtain the index for our context id!");
417 
418  XMLPropertyState aNewState(nIndex, uno::Any(sNumberStyle));
419  aPropStates.push_back(aNewState);
420  }
421  }
422  }
423 
424  nCount = std::count_if(aPropStates.cbegin(), aPropStates.cend(),
425  [](const XMLPropertyState& rProp) { return rProp.mnIndex != -1; });
426  }
427 
428  if(nCount == 0)
429  {
430  // no hard attributes, use parent style name for export
431  aShapeInfo.msStyleName = aParentName;
432  }
433  else
434  {
435  // there are filtered properties -> hard attributes
436  // try to find this style in AutoStylePool
437  aShapeInfo.msStyleName = mrExport.GetAutoStylePool()->Find(aShapeInfo.mnFamily, aParentName, aPropStates);
438 
439  if(aShapeInfo.msStyleName.isEmpty())
440  {
441  // Style did not exist, add it to AutoStalePool
442  aShapeInfo.msStyleName = mrExport.GetAutoStylePool()->Add(aShapeInfo.mnFamily, aParentName, std::move(aPropStates));
443  }
444  }
445 
446  // optionally generate auto style for text attributes
447  if( (!bIsEmptyPresObj || (aShapeInfo.meShapeType != XmlShapeTypePresPageShape)) && bObjSupportsText )
448  {
449  aPropStates = GetExport().GetTextParagraphExport()->GetParagraphPropertyMapper()->Filter(mrExport, xPropSet);
450 
451  // yet more additionally, we need to care for the ParaAdjust property
452  if ( XmlShapeTypeDrawControlShape == aShapeInfo.meShapeType )
453  {
454  uno::Reference< beans::XPropertySetInfo > xPropSetInfo( xPropSet->getPropertySetInfo() );
455  uno::Reference< beans::XPropertyState > xPropState( xPropSet, uno::UNO_QUERY );
456  if ( xPropSetInfo.is() && xPropState.is() )
457  {
458  // this is because:
459  // * if controls shapes have a ParaAdjust property, then this is the Align property of the control model
460  // * control models are allowed to have an Align of "void"
461  // * the Default for control model's Align is TextAlign_LEFT
462  // * defaults for style properties are not written, but we need to write the "left",
463  // because we need to distinguish this "left" from the case where not align attribute
464  // is present which means "void"
465  if ( xPropSetInfo->hasPropertyByName( "ParaAdjust" )
466  && ( beans::PropertyState_DEFAULT_VALUE == xPropState->getPropertyState( "ParaAdjust" ) )
467  )
468  {
469  sal_Int32 nIndex = GetExport().GetTextParagraphExport()->GetParagraphPropertyMapper()->getPropertySetMapper()->FindEntryIndex( CTF_SD_SHAPE_PARA_ADJUST );
470  // TODO : this retrieval of the index should be moved into the ctor, holding the index
471  // as member, thus saving time.
472  DBG_ASSERT(-1 != nIndex, "XMLShapeExport::collectShapeAutoStyles: could not obtain the index for the ParaAdjust context id!");
473 
474  uno::Any aParaAdjustValue = xPropSet->getPropertyValue( "ParaAdjust" );
475  XMLPropertyState aAlignDefaultState( nIndex, aParaAdjustValue );
476 
477  aPropStates.push_back( aAlignDefaultState );
478  }
479  }
480  }
481 
482  nCount = std::count_if(aPropStates.cbegin(), aPropStates.cend(),
483  [](const XMLPropertyState& rProp) { return rProp.mnIndex != -1; });
484 
485  if( nCount )
486  {
487  aShapeInfo.msTextStyleName = mrExport.GetAutoStylePool()->Find( XmlStyleFamily::TEXT_PARAGRAPH, "", aPropStates );
488  if(aShapeInfo.msTextStyleName.isEmpty())
489  {
490  // Style did not exist, add it to AutoStalePool
491  aShapeInfo.msTextStyleName = mrExport.GetAutoStylePool()->Add(XmlStyleFamily::TEXT_PARAGRAPH, "", std::move(aPropStates));
492  }
493  }
494  }
495  }
496 
497  // prepare animation information if needed
498  if( mxAnimationsExporter.is() )
500 
501  // check for special shapes
502 
503  switch( aShapeInfo.meShapeType )
504  {
506  {
507  uno::Reference< uno::XInterface > xConnection;
508 
509  // create shape ids for export later
510  xPropSet->getPropertyValue( gsStartShape ) >>= xConnection;
511  if( xConnection.is() )
513 
514  xPropSet->getPropertyValue( gsEndShape ) >>= xConnection;
515  if( xConnection.is() )
517  break;
518  }
521  {
522  try
523  {
524  uno::Reference< table::XColumnRowRange > xRange( xPropSet->getPropertyValue( gsModel ), uno::UNO_QUERY_THROW );
525  GetShapeTableExport()->collectTableAutoStyles( xRange );
526  }
527  catch(const uno::Exception&)
528  {
529  DBG_UNHANDLED_EXCEPTION( "xmloff", "collecting auto styles for a table" );
530  }
531  break;
532  }
533  default:
534  break;
535  }
536 
537  // check for shape collections (group shape or 3d scene)
538  // and collect contained shapes style infos
539  const uno::Reference< drawing::XShape >& xCollection = aShapeInfo.xCustomShapeReplacement.is()
540  ? aShapeInfo.xCustomShapeReplacement : xShape;
541  {
542  uno::Reference< drawing::XShapes > xShapes( xCollection, uno::UNO_QUERY );
543  if( xShapes.is() )
544  {
545  collectShapesAutoStyles( xShapes );
546  }
547  }
548 }
549 
550 namespace
551 {
552  class NewTextListsHelper
553  {
554  public:
555  explicit NewTextListsHelper( SvXMLExport& rExp )
556  : mrExport( rExp )
557  {
558  mrExport.GetTextParagraphExport()->PushNewTextListsHelper();
559  }
560 
561  ~NewTextListsHelper()
562  {
563  mrExport.GetTextParagraphExport()->PopTextListsHelper();
564  }
565 
566  private:
567  SvXMLExport& mrExport;
568  };
569 }
570 // This method exports the given XShape
571 void XMLShapeExport::exportShape(const uno::Reference< drawing::XShape >& xShape,
572  XMLShapeExportFlags nFeatures /* = SEF_DEFAULT */,
573  css::awt::Point* pRefPoint /* = NULL */,
574  SvXMLAttributeList* pAttrList /* = NULL */ )
575 {
576  SAL_INFO("xmloff", xShape->getShapeType());
577  if( maCurrentShapesIter == maShapesInfos.end() )
578  {
579  SAL_WARN( "xmloff", "XMLShapeExport::exportShape(): no auto styles where collected before export" );
580  return;
581  }
582  sal_Int32 nZIndex = 0;
583  uno::Reference< beans::XPropertySet > xSet( xShape, uno::UNO_QUERY );
584  OUString sHyperlink;
585  try
586  {
587  xSet->getPropertyValue(gsHyperlink) >>= sHyperlink;
588  }
589  catch (beans::UnknownPropertyException)
590  {
591  }
592 
593  std::unique_ptr< SvXMLElementExport > pHyperlinkElement;
594 
595  // Need to stash the attributes that are pre-loaded for the shape export
596  // (otherwise they will become attributes of the draw:a element)
597  uno::Reference<xml::sax::XAttributeList> xSaveAttribs(
598  new SvXMLAttributeList(GetExport().GetAttrList()));
600  if( xSet.is() && (GetExport().GetModelType() == SvtModuleOptions::EFactory::DRAW) )
601  {
602  // export hyperlinks with <a><shape/></a>. Currently only in draw since draw
603  // does not support document events
604  try
605  {
606  presentation::ClickAction eAction = presentation::ClickAction_NONE;
607  xSet->getPropertyValue(gsOnClick) >>= eAction;
608 
609  if( (eAction == presentation::ClickAction_DOCUMENT) ||
610  (eAction == presentation::ClickAction_BOOKMARK) )
611  {
612  OUString sURL;
613  xSet->getPropertyValue(gsBookmark) >>= sURL;
614 
615  if( !sURL.isEmpty() )
616  {
620  pHyperlinkElement.reset( new SvXMLElementExport(mrExport, XML_NAMESPACE_DRAW, XML_A, true, true) );
621  }
622  }
623  }
624  catch(const uno::Exception&)
625  {
626  TOOLS_WARN_EXCEPTION("xmloff", "XMLShapeExport::exportShape(): exception during hyperlink export");
627  }
628  }
629  else if (xSet.is() && !sHyperlink.isEmpty())
630  {
633  pHyperlinkElement.reset( new SvXMLElementExport(mrExport, XML_NAMESPACE_DRAW, XML_A, true, true) );
634  }
635  // re-add stashed attributes
636  GetExport().AddAttributeList(xSaveAttribs);
637 
638  if( xSet.is() )
639  xSet->getPropertyValue(gsZIndex) >>= nZIndex;
640 
641  ImplXMLShapeExportInfoVector& aShapeInfoVector = (*maCurrentShapesIter).second;
642 
643  if( static_cast<sal_Int32>(aShapeInfoVector.size()) <= nZIndex )
644  {
645  SAL_WARN( "xmloff", "XMLShapeExport::exportShape(): no shape info collected for a given shape" );
646  return;
647  }
648 
649  NewTextListsHelper aNewTextListsHelper( mrExport );
650 
651  const ImplXMLShapeExportInfo& aShapeInfo = aShapeInfoVector[nZIndex];
652 
653 #ifdef DBG_UTIL
654  // check if this is the correct ShapesInfo
655  uno::Reference< container::XChild > xChild( xShape, uno::UNO_QUERY );
656  if( xChild.is() )
657  {
658  uno::Reference< drawing::XShapes > xParent( xChild->getParent(), uno::UNO_QUERY );
659  SAL_WARN_IF( !xParent.is() && xParent.get() == (*maCurrentShapesIter).first.get(), "xmloff", "XMLShapeExport::exportShape(): Wrong call to XMLShapeExport::seekShapes()" );
660  }
661 
662  // first compute the shapes type
663  {
665  ImpCalcShapeType(xShape, eShapeType);
666 
667  SAL_WARN_IF( eShapeType != aShapeInfo.meShapeType, "xmloff", "exportShape callings do not correspond to collectShapeAutoStyles calls!: " << xShape->getShapeType() );
668  }
669 #endif
670 
671  // collect animation information if needed
672  if( mxAnimationsExporter.is() )
673  mxAnimationsExporter->collect( xShape, mrExport );
674 
675  /* Export shapes name if he has one (#i51726#)
676  Export of the shape name for text documents only if the OpenDocument
677  file format is written - exceptions are group shapes.
678  Note: Writer documents in OpenOffice.org file format doesn't contain
679  any names for shapes, except for group shapes.
680  */
681  {
682  if ( ( GetExport().GetModelType() != SvtModuleOptions::EFactory::WRITER &&
683  GetExport().GetModelType() != SvtModuleOptions::EFactory::WRITERWEB &&
684  GetExport().GetModelType() != SvtModuleOptions::EFactory::WRITERGLOBAL ) ||
685  ( GetExport().getExportFlags() & SvXMLExportFlags::OASIS ) ||
686  aShapeInfo.meShapeType == XmlShapeTypeDrawGroupShape ||
687  ( aShapeInfo.meShapeType == XmlShapeTypeDrawCustomShape &&
688  aShapeInfo.xCustomShapeReplacement.is() ) )
689  {
690  uno::Reference< container::XNamed > xNamed( xShape, uno::UNO_QUERY );
691  if( xNamed.is() )
692  {
693  const OUString aName( xNamed->getName() );
694  if( !aName.isEmpty() )
696  }
697  }
698  }
699 
700  // export style name
701  if( !aShapeInfo.msStyleName.isEmpty() )
702  {
703  if(XmlStyleFamily::SD_GRAPHICS_ID == aShapeInfo.mnFamily)
705  else
707  }
708 
709  // export text style name
710  if( !aShapeInfo.msTextStyleName.isEmpty() )
711  {
713  }
714 
715  // export shapes id if needed
716  {
717  uno::Reference< uno::XInterface > xRef( xShape, uno::UNO_QUERY );
718  const OUString& rShapeId = mrExport.getInterfaceToIdentifierMapper().getIdentifier( xRef );
719  if( !rShapeId.isEmpty() )
720  {
722  }
723  }
724 
725  // export layer information
726  if( mbExportLayer )
727  {
728  // check for group or scene shape and not export layer if this is one
729  uno::Reference< drawing::XShapes > xShapes( xShape, uno::UNO_QUERY );
730  if( !xShapes.is() )
731  {
732  try
733  {
734  uno::Reference< beans::XPropertySet > xProps( xShape, uno::UNO_QUERY );
735  OUString aLayerName;
736  xProps->getPropertyValue("LayerName") >>= aLayerName;
738 
739  }
740  catch(const uno::Exception&)
741  {
742  DBG_UNHANDLED_EXCEPTION( "xmloff", "exporting layer name for shape" );
743  }
744  }
745  }
746 
747  // export draw:display (do not export in ODF 1.3 or older)
749  {
750  if( aShapeInfo.meShapeType != XmlShapeTypeDrawPageShape && aShapeInfo.meShapeType != XmlShapeTypePresPageShape &&
752  try
753  {
754  bool bVisible = true;
755  bool bPrintable = true;
756 
757  xSet->getPropertyValue(gsVisible) >>= bVisible;
758  xSet->getPropertyValue(gsPrintable) >>= bPrintable;
759 
760  XMLTokenEnum eDisplayToken = XML_TOKEN_INVALID;
761  const unsigned short nDisplay = (bVisible ? 2 : 0) | (bPrintable ? 1 : 0);
762  switch( nDisplay )
763  {
764  case 0: eDisplayToken = XML_NONE; break;
765  case 1: eDisplayToken = XML_PRINTER; break;
766  case 2: eDisplayToken = XML_SCREEN; break;
767  // case 3: eDisplayToken = XML_ALWAYS break; this is the default
768  }
769 
770  if( eDisplayToken != XML_TOKEN_INVALID )
772  }
773  catch(const uno::Exception&)
774  {
775  DBG_UNHANDLED_EXCEPTION("xmloff.draw");
776  }
777  }
778 
779  // #82003# test export count
780  // #91587# ALWAYS increment since now ALL to be exported shapes are counted.
781  if(mrExport.GetShapeExport()->IsHandleProgressBarEnabled())
782  {
784  }
785 
786  onExport( xShape );
787 
788  // export shape element
789  switch(aShapeInfo.meShapeType)
790  {
792  {
793  ImpExportRectangleShape(xShape, nFeatures, pRefPoint );
794  break;
795  }
797  {
798  ImpExportEllipseShape(xShape, nFeatures, pRefPoint );
799  break;
800  }
802  {
803  ImpExportLineShape(xShape, nFeatures, pRefPoint );
804  break;
805  }
806  case XmlShapeTypeDrawPolyPolygonShape: // closed PolyPolygon
807  case XmlShapeTypeDrawPolyLineShape: // open PolyPolygon
808  case XmlShapeTypeDrawClosedBezierShape: // closed tools::PolyPolygon containing curves
809  case XmlShapeTypeDrawOpenBezierShape: // open tools::PolyPolygon containing curves
810  {
811  ImpExportPolygonShape(xShape, aShapeInfo.meShapeType, nFeatures, pRefPoint );
812  break;
813  }
814 
824  {
825  ImpExportTextBoxShape(xShape, aShapeInfo.meShapeType, nFeatures, pRefPoint );
826  break;
827  }
828 
831  {
832  ImpExportGraphicObjectShape(xShape, aShapeInfo.meShapeType, nFeatures, pRefPoint );
833  break;
834  }
835 
838  {
839  ImpExportChartShape(xShape, aShapeInfo.meShapeType, nFeatures, pRefPoint, pAttrList );
840  break;
841  }
842 
844  {
845  ImpExportControlShape(xShape, nFeatures, pRefPoint );
846  break;
847  }
848 
850  {
851  ImpExportConnectorShape(xShape, nFeatures, pRefPoint );
852  break;
853  }
854 
856  {
857  ImpExportMeasureShape(xShape, nFeatures, pRefPoint );
858  break;
859  }
860 
865  {
866  ImpExportOLE2Shape(xShape, aShapeInfo.meShapeType, nFeatures, pRefPoint );
867  break;
868  }
869 
872  {
873  ImpExportTableShape( xShape, aShapeInfo.meShapeType, nFeatures, pRefPoint );
874  break;
875  }
876 
880  {
881  ImpExportPageShape(xShape, aShapeInfo.meShapeType, nFeatures, pRefPoint );
882  break;
883  }
884 
886  {
887  ImpExportCaptionShape(xShape, nFeatures, pRefPoint );
888  break;
889  }
890 
895  {
896  ImpExport3DShape(xShape, aShapeInfo.meShapeType);
897  break;
898  }
899 
901  {
902  ImpExport3DSceneShape( xShape, nFeatures, pRefPoint );
903  break;
904  }
905 
907  {
908  // empty group
909  ImpExportGroupShape( xShape, nFeatures, pRefPoint );
910  break;
911  }
912 
914  {
915  ImpExportFrameShape(xShape, nFeatures, pRefPoint );
916  break;
917  }
918 
920  {
921  ImpExportAppletShape(xShape, nFeatures, pRefPoint );
922  break;
923  }
924 
926  {
927  ImpExportPluginShape(xShape, nFeatures, pRefPoint );
928  break;
929  }
930 
932  {
933  if ( aShapeInfo.xCustomShapeReplacement.is() )
934  ImpExportGroupShape( aShapeInfo.xCustomShapeReplacement, nFeatures, pRefPoint );
935  else
936  ImpExportCustomShape( xShape, nFeatures, pRefPoint );
937  break;
938  }
939 
942  {
943  ImpExportMediaShape( xShape, aShapeInfo.meShapeType, nFeatures, pRefPoint );
944  break;
945  }
946 
948  case XmlShapeTypeUnknown:
950  default:
951  {
952  // this should never happen and is an error
953  OSL_FAIL("XMLEXP: WriteShape: unknown or unexpected type of shape in export!");
954  break;
955  }
956  }
957 
958  pHyperlinkElement.reset();
959 
960  // #97489# #97111#
961  // if there was an error and no element for the shape was exported
962  // we need to clear the attribute list or the attributes will be
963  // set on the next exported element, which can result in corrupt
964  // xml files due to duplicate attributes
965 
966  mrExport.CheckAttrList(); // asserts in non pro if we have attributes left
967  mrExport.ClearAttrList(); // clears the attributes
968 }
969 
970 // This method collects all automatic styles for the shapes inside the given XShapes collection
971 void XMLShapeExport::collectShapesAutoStyles( const uno::Reference < drawing::XShapes >& xShapes )
972 {
973  ShapesInfos::iterator aOldCurrentShapesIter = maCurrentShapesIter;
974  seekShapes( xShapes );
975 
976  uno::Reference< drawing::XShape > xShape;
977  const sal_Int32 nShapeCount(xShapes->getCount());
978  for(sal_Int32 nShapeId = 0; nShapeId < nShapeCount; nShapeId++)
979  {
980  xShapes->getByIndex(nShapeId) >>= xShape;
981  SAL_WARN_IF( !xShape.is(), "xmloff", "Shape without a XShape?" );
982  if(!xShape.is())
983  continue;
984 
985  collectShapeAutoStyles( xShape );
986  }
987 
988  maCurrentShapesIter = aOldCurrentShapesIter;
989 }
990 
991 // This method exports all XShape inside the given XShapes collection
992 void XMLShapeExport::exportShapes( const uno::Reference < drawing::XShapes >& xShapes, XMLShapeExportFlags nFeatures /* = SEF_DEFAULT */, awt::Point* pRefPoint /* = NULL */ )
993 {
994  ShapesInfos::iterator aOldCurrentShapesIter = maCurrentShapesIter;
995  seekShapes( xShapes );
996 
997  uno::Reference< drawing::XShape > xShape;
998  const sal_Int32 nShapeCount(xShapes->getCount());
999  for(sal_Int32 nShapeId = 0; nShapeId < nShapeCount; nShapeId++)
1000  {
1001  xShapes->getByIndex(nShapeId) >>= xShape;
1002  SAL_WARN_IF( !xShape.is(), "xmloff", "Shape without a XShape?" );
1003  if(!xShape.is())
1004  continue;
1005 
1006  exportShape( xShape, nFeatures, pRefPoint );
1007  }
1008 
1009  maCurrentShapesIter = aOldCurrentShapesIter;
1010 }
1011 
1012 namespace xmloff {
1013 
1014 void FixZOrder(uno::Reference<drawing::XShapes> const& xShapes,
1015  std::function<unsigned int (uno::Reference<beans::XPropertySet> const&)> const& rGetLayer)
1016 {
1017  uno::Reference<drawing::XShapes3> const xShapes3(xShapes, uno::UNO_QUERY);
1018  assert(xShapes3.is());
1019  if (!xShapes3.is())
1020  {
1021  return; // only SvxDrawPage implements this
1022  }
1023  struct Layer { std::vector<sal_Int32> shapes; sal_Int32 nMin = SAL_MAX_INT32; sal_Int32 nMax = 0; };
1024  std::vector<Layer> layers;
1025  // shapes are sorted by ZOrder
1026  sal_Int32 const nCount(xShapes->getCount());
1027  for (sal_Int32 i = 0; i < nCount; ++i)
1028  {
1029  uno::Reference<beans::XPropertySet> const xShape(xShapes->getByIndex(i), uno::UNO_QUERY);
1030  if (!xShape.is())
1031  {
1032  SAL_WARN("xmloff", "FixZOrder: null shape, cannot sort");
1033  return;
1034  }
1035  unsigned int const nLayer(rGetLayer(xShape));
1036  if (layers.size() <= nLayer)
1037  {
1038  layers.resize(nLayer + 1);
1039  }
1040  layers[nLayer].shapes.emplace_back(i);
1041  if (i < layers[nLayer].nMin)
1042  {
1043  layers[nLayer].nMin = i;
1044  }
1045  if (layers[nLayer].nMax < i)
1046  {
1047  layers[nLayer].nMax = i;
1048  }
1049  }
1050  layers.erase(std::remove_if(layers.begin(), layers.end(),
1051  [](Layer const& rLayer) { return rLayer.shapes.empty(); }),
1052  layers.end());
1053  bool isSorted(true);
1054  for (size_t i = 1; i < layers.size(); ++i)
1055  {
1056  assert(layers[i].nMin != layers[i-1].nMax); // unique!
1057  if (layers[i].nMin < layers[i-1].nMax)
1058  {
1059  isSorted = false;
1060  break;
1061  }
1062  }
1063  if (isSorted)
1064  {
1065  return; // nothing to do
1066  }
1067  uno::Sequence<sal_Int32> aNewOrder(nCount);
1068  auto iterInsert(aNewOrder.getArray());
1069  for (auto const& rLayer : layers)
1070  {
1071  assert(rLayer.nMin <= rLayer.nMax); // empty layers have been removed
1072  iterInsert = std::copy(rLayer.shapes.begin(), rLayer.shapes.end(), iterInsert);
1073  }
1074  try
1075  {
1076  xShapes3->sort(aNewOrder);
1077  }
1078  catch (uno::Exception const&)
1079  {
1080  SAL_WARN("xmloff", "FixZOrder: exception");
1081  }
1082 }
1083 
1084 } // namespace xmloff
1085 
1086 void XMLShapeExport::seekShapes( const uno::Reference< drawing::XShapes >& xShapes ) noexcept
1087 {
1088  if( xShapes.is() )
1089  {
1090  maCurrentShapesIter = maShapesInfos.find( xShapes );
1091  if( maCurrentShapesIter == maShapesInfos.end() )
1092  {
1093  ImplXMLShapeExportInfoVector aNewInfoVector;
1094  aNewInfoVector.resize( static_cast<ShapesInfos::size_type>(xShapes->getCount()) );
1095  maShapesInfos[ xShapes ] = aNewInfoVector;
1096 
1097  maCurrentShapesIter = maShapesInfos.find( xShapes );
1098 
1099  SAL_WARN_IF( maCurrentShapesIter == maShapesInfos.end(), "xmloff", "XMLShapeExport::seekShapes(): insert into stl::map failed" );
1100  }
1101 
1102  SAL_WARN_IF( (*maCurrentShapesIter).second.size() != static_cast<ShapesInfos::size_type>(xShapes->getCount()), "xmloff", "XMLShapeExport::seekShapes(): XShapes size varied between calls" );
1103 
1104  }
1105  else
1106  {
1107  maCurrentShapesIter = maShapesInfos.end();
1108  }
1109 }
1110 
1112 {
1113  // export all autostyle infos
1114 
1115  // ...for graphic
1116  {
1118  }
1119 
1120  // ...for presentation
1121  {
1123  }
1124 
1125  if( mxShapeTableExport.is() )
1126  mxShapeTableExport->exportAutoStyles();
1127 }
1128 
1131  SvXMLExport& rExport )
1132 {
1135  rExport.GetTextParagraphExport(); // get or create text paragraph export
1136  SvXMLExportPropertyMapper* pResult =
1137  new XMLShapeExportPropertyMapper( xMapper, rExport );
1138  // chain text attributes
1139  return pResult;
1140 }
1141 
1142 void XMLShapeExport::ImpCalcShapeType(const uno::Reference< drawing::XShape >& xShape,
1143  XmlShapeType& eShapeType)
1144 {
1145  // set in every case, so init here
1146  eShapeType = XmlShapeTypeUnknown;
1147 
1148  if(!xShape.is())
1149  return;
1150 
1151  OUString aType(xShape->getShapeType());
1152 
1153  if(!aType.match("com.sun.star."))
1154  return;
1155 
1156  if(aType.match("drawing.", 13))
1157  {
1158  // drawing shapes
1159  if (aType.match("Rectangle", 21)) { eShapeType = XmlShapeTypeDrawRectangleShape; }
1160 
1161  // #i72177# Note: Correcting CustomShape, CustomShape->Custom, len from 9 (was wrong anyways) to 6.
1162  // As can be seen at the other compares, the appendix "Shape" is left out of the comparison.
1163  else if(aType.match("Custom", 21)) { eShapeType = XmlShapeTypeDrawCustomShape; }
1164 
1165  else if(aType.match("Ellipse", 21)) { eShapeType = XmlShapeTypeDrawEllipseShape; }
1166  else if(aType.match("Control", 21)) { eShapeType = XmlShapeTypeDrawControlShape; }
1167  else if(aType.match("Connector", 21)) { eShapeType = XmlShapeTypeDrawConnectorShape; }
1168  else if(aType.match("Measure", 21)) { eShapeType = XmlShapeTypeDrawMeasureShape; }
1169  else if(aType.match("Line", 21)) { eShapeType = XmlShapeTypeDrawLineShape; }
1170 
1171  // #i72177# Note: This covers two types by purpose, PolyPolygonShape and PolyPolygonPathShape
1172  else if(aType.match("PolyPolygon", 21)) { eShapeType = XmlShapeTypeDrawPolyPolygonShape; }
1173 
1174  // #i72177# Note: This covers two types by purpose, PolyLineShape and PolyLinePathShape
1175  else if(aType.match("PolyLine", 21)) { eShapeType = XmlShapeTypeDrawPolyLineShape; }
1176 
1177  else if(aType.match("OpenBezier", 21)) { eShapeType = XmlShapeTypeDrawOpenBezierShape; }
1178  else if(aType.match("ClosedBezier", 21)) { eShapeType = XmlShapeTypeDrawClosedBezierShape; }
1179 
1180  // #i72177# FreeHand (opened and closed) now supports the types OpenFreeHandShape and
1181  // ClosedFreeHandShape respectively. Represent them as bezier shapes
1182  else if(aType.match("OpenFreeHand", 21)) { eShapeType = XmlShapeTypeDrawOpenBezierShape; }
1183  else if(aType.match("ClosedFreeHand", 21)) { eShapeType = XmlShapeTypeDrawClosedBezierShape; }
1184 
1185  else if(aType.match("GraphicObject", 21)) { eShapeType = XmlShapeTypeDrawGraphicObjectShape; }
1186  else if(aType.match("Group", 21)) { eShapeType = XmlShapeTypeDrawGroupShape; }
1187  else if(aType.match("Text", 21)) { eShapeType = XmlShapeTypeDrawTextShape; }
1188  else if(aType.match("OLE2", 21))
1189  {
1190  eShapeType = XmlShapeTypeDrawOLE2Shape;
1191 
1192  // get info about presentation shape
1193  uno::Reference <beans::XPropertySet> xPropSet(xShape, uno::UNO_QUERY);
1194 
1195  if(xPropSet.is())
1196  {
1197  OUString sCLSID;
1198  if(xPropSet->getPropertyValue("CLSID") >>= sCLSID)
1199  {
1200 #if !ENABLE_WASM_STRIP_CHART
1201  // WASM_CHART change
1202  // TODO: With Chart extracted this cannot really happen since
1203  // no Chart could've been added at all
1204  if (sCLSID == mrExport.GetChartExport()->getChartCLSID() ||
1205 #else
1206  if(
1207 #endif
1208  sCLSID == SvGlobalName( SO3_RPTCH_CLASSID ).GetHexName() )
1209  {
1210  eShapeType = XmlShapeTypeDrawChartShape;
1211  }
1212  else if (sCLSID == SvGlobalName( SO3_SC_CLASSID ).GetHexName() )
1213  {
1214  eShapeType = XmlShapeTypeDrawSheetShape;
1215  }
1216  else
1217  {
1218  // general OLE2 Object
1219  }
1220  }
1221  }
1222  }
1223  else if(aType.match("Page", 21)) { eShapeType = XmlShapeTypeDrawPageShape; }
1224  else if(aType.match("Frame", 21)) { eShapeType = XmlShapeTypeDrawFrameShape; }
1225  else if(aType.match("Caption", 21)) { eShapeType = XmlShapeTypeDrawCaptionShape; }
1226  else if(aType.match("Plugin", 21)) { eShapeType = XmlShapeTypeDrawPluginShape; }
1227  else if(aType.match("Applet", 21)) { eShapeType = XmlShapeTypeDrawAppletShape; }
1228  else if(aType.match("MediaShape", 21)) { eShapeType = XmlShapeTypeDrawMediaShape; }
1229  else if(aType.match("TableShape", 21)) { eShapeType = XmlShapeTypeDrawTableShape; }
1230 
1231  // 3D shapes
1232  else if(aType.match("Scene", 21 + 7)) { eShapeType = XmlShapeTypeDraw3DSceneObject; }
1233  else if(aType.match("Cube", 21 + 7)) { eShapeType = XmlShapeTypeDraw3DCubeObject; }
1234  else if(aType.match("Sphere", 21 + 7)) { eShapeType = XmlShapeTypeDraw3DSphereObject; }
1235  else if(aType.match("Lathe", 21 + 7)) { eShapeType = XmlShapeTypeDraw3DLatheObject; }
1236  else if(aType.match("Extrude", 21 + 7)) { eShapeType = XmlShapeTypeDraw3DExtrudeObject; }
1237  }
1238  else if(aType.match("presentation.", 13))
1239  {
1240  // presentation shapes
1241  if (aType.match("TitleText", 26)) { eShapeType = XmlShapeTypePresTitleTextShape; }
1242  else if(aType.match("Outliner", 26)) { eShapeType = XmlShapeTypePresOutlinerShape; }
1243  else if(aType.match("Subtitle", 26)) { eShapeType = XmlShapeTypePresSubtitleShape; }
1244  else if(aType.match("GraphicObject", 26)) { eShapeType = XmlShapeTypePresGraphicObjectShape; }
1245  else if(aType.match("Page", 26)) { eShapeType = XmlShapeTypePresPageShape; }
1246  else if(aType.match("OLE2", 26))
1247  {
1248  eShapeType = XmlShapeTypePresOLE2Shape;
1249 
1250  // get info about presentation shape
1251  uno::Reference <beans::XPropertySet> xPropSet(xShape, uno::UNO_QUERY);
1252 
1253  if(xPropSet.is()) try
1254  {
1255  OUString sCLSID;
1256  if(xPropSet->getPropertyValue("CLSID") >>= sCLSID)
1257  {
1258  if( sCLSID == SvGlobalName( SO3_SC_CLASSID ).GetHexName() )
1259  {
1260  eShapeType = XmlShapeTypePresSheetShape;
1261  }
1262  }
1263  }
1264  catch(const uno::Exception&)
1265  {
1266  SAL_WARN( "xmloff", "XMLShapeExport::ImpCalcShapeType(), expected ole shape to have the CLSID property?" );
1267  }
1268  }
1269  else if(aType.match("Chart", 26)) { eShapeType = XmlShapeTypePresChartShape; }
1270  else if(aType.match("OrgChart", 26)) { eShapeType = XmlShapeTypePresOrgChartShape; }
1271  else if(aType.match("CalcShape", 26)) { eShapeType = XmlShapeTypePresSheetShape; }
1272  else if(aType.match("TableShape", 26)) { eShapeType = XmlShapeTypePresTableShape; }
1273  else if(aType.match("Notes", 26)) { eShapeType = XmlShapeTypePresNotesShape; }
1274  else if(aType.match("HandoutShape", 26)) { eShapeType = XmlShapeTypeHandoutShape; }
1275  else if(aType.match("HeaderShape", 26)) { eShapeType = XmlShapeTypePresHeaderShape; }
1276  else if(aType.match("FooterShape", 26)) { eShapeType = XmlShapeTypePresFooterShape; }
1277  else if(aType.match("SlideNumberShape", 26)) { eShapeType = XmlShapeTypePresSlideNumberShape; }
1278  else if(aType.match("DateTimeShape", 26)) { eShapeType = XmlShapeTypePresDateTimeShape; }
1279  else if(aType.match("MediaShape", 26)) { eShapeType = XmlShapeTypePresMediaShape; }
1280  }
1281 }
1282 
1284 void XMLShapeExport::ImpExportGluePoints( const uno::Reference< drawing::XShape >& xShape )
1285 {
1286  uno::Reference< drawing::XGluePointsSupplier > xSupplier( xShape, uno::UNO_QUERY );
1287  if( !xSupplier.is() )
1288  return;
1289 
1290  uno::Reference< container::XIdentifierAccess > xGluePoints( xSupplier->getGluePoints(), uno::UNO_QUERY );
1291  if( !xGluePoints.is() )
1292  return;
1293 
1294  drawing::GluePoint2 aGluePoint;
1295 
1296  const uno::Sequence< sal_Int32 > aIdSequence( xGluePoints->getIdentifiers() );
1297 
1298  for( const sal_Int32 nIdentifier : aIdSequence )
1299  {
1300  if( (xGluePoints->getByIdentifier( nIdentifier ) >>= aGluePoint) && aGluePoint.IsUserDefined )
1301  {
1302  // export only user defined gluepoints
1303 
1304  const OUString sId( OUString::number( nIdentifier ) );
1306 
1308  aGluePoint.Position.X);
1309  mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_X, msBuffer.makeStringAndClear());
1310 
1312  aGluePoint.Position.Y);
1313  mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_Y, msBuffer.makeStringAndClear());
1314 
1315  if( !aGluePoint.IsRelative )
1316  {
1317  SvXMLUnitConverter::convertEnum( msBuffer, aGluePoint.PositionAlignment, aXML_GlueAlignment_EnumMap );
1318  mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_ALIGN, msBuffer.makeStringAndClear() );
1319  }
1320 
1321  if( aGluePoint.Escape != drawing::EscapeDirection_SMART )
1322  {
1325  }
1326 
1327  SvXMLElementExport aEventsElemt(mrExport, XML_NAMESPACE_DRAW, XML_GLUE_POINT, true, true);
1328  }
1329  }
1330 }
1331 
1332 void XMLShapeExport::ImpExportSignatureLine(const uno::Reference<drawing::XShape>& xShape)
1333 {
1334  uno::Reference<beans::XPropertySet> xPropSet(xShape, uno::UNO_QUERY);
1335 
1336  bool bIsSignatureLine = false;
1337  xPropSet->getPropertyValue("IsSignatureLine") >>= bIsSignatureLine;
1338  if (!bIsSignatureLine)
1339  return;
1340 
1341  OUString aSignatureLineId;
1342  xPropSet->getPropertyValue("SignatureLineId") >>= aSignatureLineId;
1343  mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_ID, aSignatureLineId);
1344 
1345  OUString aSuggestedSignerName;
1346  xPropSet->getPropertyValue("SignatureLineSuggestedSignerName") >>= aSuggestedSignerName;
1347  if (!aSuggestedSignerName.isEmpty())
1349 
1350  OUString aSuggestedSignerTitle;
1351  xPropSet->getPropertyValue("SignatureLineSuggestedSignerTitle") >>= aSuggestedSignerTitle;
1352  if (!aSuggestedSignerTitle.isEmpty())
1354 
1355  OUString aSuggestedSignerEmail;
1356  xPropSet->getPropertyValue("SignatureLineSuggestedSignerEmail") >>= aSuggestedSignerEmail;
1357  if (!aSuggestedSignerEmail.isEmpty())
1359 
1360  OUString aSigningInstructions;
1361  xPropSet->getPropertyValue("SignatureLineSigningInstructions") >>= aSigningInstructions;
1362  if (!aSigningInstructions.isEmpty())
1364 
1365  bool bShowSignDate = false;
1366  xPropSet->getPropertyValue("SignatureLineShowSignDate") >>= bShowSignDate;
1368  bShowSignDate ? XML_TRUE : XML_FALSE);
1369 
1370  bool bCanAddComment = false;
1371  xPropSet->getPropertyValue("SignatureLineCanAddComment") >>= bCanAddComment;
1373  bCanAddComment ? XML_TRUE : XML_FALSE);
1374 
1375  SvXMLElementExport aSignatureLineElement(mrExport, XML_NAMESPACE_LO_EXT, XML_SIGNATURELINE, true,
1376  true);
1377 }
1378 
1379 void XMLShapeExport::ImpExportQRCode(const uno::Reference<drawing::XShape>& xShape)
1380 {
1381  uno::Reference<beans::XPropertySet> xPropSet(xShape, uno::UNO_QUERY);
1382 
1383  uno::Any aAny = xPropSet->getPropertyValue("BarCodeProperties");
1384 
1385  css::drawing::BarCode aBarCode;
1386  if(!(aAny >>= aBarCode))
1387  return;
1388 
1390  /* Export QR Code as per customised schema, @see OpenDocument-schema-v1.3+libreoffice */
1391  OUString temp;
1392  switch(aBarCode.ErrorCorrection){
1393  case css::drawing::BarCodeErrorCorrection::LOW :
1394  temp = "low";
1395  break;
1396  case css::drawing::BarCodeErrorCorrection::MEDIUM:
1397  temp = "medium";
1398  break;
1399  case css::drawing::BarCodeErrorCorrection::QUARTILE:
1400  temp = "quartile";
1401  break;
1402  case css::drawing::BarCodeErrorCorrection::HIGH:
1403  temp = "high";
1404  break;
1405  }
1407  mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_QRCODE_BORDER, OUStringBuffer(20).append(aBarCode.Border).makeStringAndClear());
1408  mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_QRCODE_TYPE, OUStringBuffer(20).append(aBarCode.Type).makeStringAndClear());
1409 
1411  true);
1412 }
1413 
1415 {
1417 
1418  // construct PropertySetMapper
1420  static_cast<XMLShapeExportPropertyMapper*>(xPropertySetMapper.get())->SetAutoStyles( false );
1421 
1422  // chain text attributes
1423  xPropertySetMapper->ChainExportMapper(XMLTextParagraphExport::CreateParaExtPropMapper(mrExport));
1424 
1425  // chain special Writer/text frame default attributes
1426  xPropertySetMapper->ChainExportMapper(XMLTextParagraphExport::CreateParaDefaultExtPropMapper(mrExport));
1427 
1428  // write graphic family default style
1429  uno::Reference< lang::XMultiServiceFactory > xFact( mrExport.GetModel(), uno::UNO_QUERY );
1430  if( !xFact.is() )
1431  return;
1432 
1433  try
1434  {
1435  uno::Reference< beans::XPropertySet > xDefaults( xFact->createInstance("com.sun.star.drawing.Defaults"), uno::UNO_QUERY );
1436  if( xDefaults.is() )
1437  {
1438  aStEx->exportDefaultStyle( xDefaults, XML_STYLE_FAMILY_SD_GRAPHICS_NAME, xPropertySetMapper );
1439 
1440  // write graphic family styles
1441  aStEx->exportStyleFamily("graphics", OUString(XML_STYLE_FAMILY_SD_GRAPHICS_NAME), xPropertySetMapper, false, XmlStyleFamily::SD_GRAPHICS_ID);
1442  }
1443  }
1444  catch(const lang::ServiceNotRegisteredException&)
1445  {
1446  }
1447 }
1448 
1449 void XMLShapeExport::onExport( const css::uno::Reference < css::drawing::XShape >& )
1450 {
1451 }
1452 
1454 {
1455  if( !mxShapeTableExport.is() )
1456  {
1458  rtl::Reference < XMLPropertySetMapper > xMapper( new XMLShapePropertySetMapper( xFactory, true ) );
1459  mrExport.GetTextParagraphExport(); // get or create text paragraph export
1461  mxShapeTableExport = new XMLTableExport( mrExport, xPropertySetMapper, xFactory );
1462  }
1463 
1464  return mxShapeTableExport;
1465 }
1466 
1467 void XMLShapeExport::ImpExportNewTrans(const uno::Reference< beans::XPropertySet >& xPropSet,
1468  XMLShapeExportFlags nFeatures, awt::Point* pRefPoint)
1469 {
1470  // get matrix
1471  ::basegfx::B2DHomMatrix aMatrix;
1472  ImpExportNewTrans_GetB2DHomMatrix(aMatrix, xPropSet);
1473 
1474  // decompose and correct about pRefPoint
1475  ::basegfx::B2DTuple aTRScale;
1476  double fTRShear(0.0);
1477  double fTRRotate(0.0);
1478  ::basegfx::B2DTuple aTRTranslate;
1479  ImpExportNewTrans_DecomposeAndRefPoint(aMatrix, aTRScale, fTRShear, fTRRotate, aTRTranslate, pRefPoint);
1480 
1481  // use features and write
1482  ImpExportNewTrans_FeaturesAndWrite(aTRScale, fTRShear, fTRRotate, aTRTranslate, nFeatures);
1483 }
1484 
1486  const uno::Reference< beans::XPropertySet >& xPropSet)
1487 {
1488  /* Get <TransformationInHoriL2R>, if it exist
1489  and if the document is exported into the OpenOffice.org file format.
1490  This property only exists at service css::text::Shape - the
1491  Writer UNO service for shapes.
1492  This code is needed, because the positioning attributes in the
1493  OpenOffice.org file format are given in horizontal left-to-right layout
1494  regardless the layout direction the shape is in. In the OASIS Open Office
1495  file format the positioning attributes are correctly given in the layout
1496  direction the shape is in. Thus, this code provides the conversion from
1497  the OASIS Open Office file format to the OpenOffice.org file format. (#i28749#)
1498  */
1499  uno::Any aAny;
1500  if ( !( GetExport().getExportFlags() & SvXMLExportFlags::OASIS ) &&
1501  xPropSet->getPropertySetInfo()->hasPropertyByName("TransformationInHoriL2R") )
1502  {
1503  aAny = xPropSet->getPropertyValue("TransformationInHoriL2R");
1504  }
1505  else
1506  {
1507  aAny = xPropSet->getPropertyValue("Transformation");
1508  }
1509  drawing::HomogenMatrix3 aMatrix;
1510  aAny >>= aMatrix;
1511 
1512  rMatrix.set(0, 0, aMatrix.Line1.Column1);
1513  rMatrix.set(0, 1, aMatrix.Line1.Column2);
1514  rMatrix.set(0, 2, aMatrix.Line1.Column3);
1515  rMatrix.set(1, 0, aMatrix.Line2.Column1);
1516  rMatrix.set(1, 1, aMatrix.Line2.Column2);
1517  rMatrix.set(1, 2, aMatrix.Line2.Column3);
1518  rMatrix.set(2, 0, aMatrix.Line3.Column1);
1519  rMatrix.set(2, 1, aMatrix.Line3.Column2);
1520  rMatrix.set(2, 2, aMatrix.Line3.Column3);
1521 }
1522 
1523 void XMLShapeExport::ImpExportNewTrans_DecomposeAndRefPoint(const ::basegfx::B2DHomMatrix& rMatrix, ::basegfx::B2DTuple& rTRScale,
1524  double& fTRShear, double& fTRRotate, ::basegfx::B2DTuple& rTRTranslate, css::awt::Point* pRefPoint)
1525 {
1526  // decompose matrix
1527  rMatrix.decompose(rTRScale, rTRTranslate, fTRRotate, fTRShear);
1528 
1529  // correct translation about pRefPoint
1530  if(pRefPoint)
1531  {
1532  rTRTranslate -= ::basegfx::B2DTuple(pRefPoint->X, pRefPoint->Y);
1533  }
1534 }
1535 
1537  double fTRRotate, ::basegfx::B2DTuple const & rTRTranslate, const XMLShapeExportFlags nFeatures)
1538 {
1539  // always write Size (rTRScale) since this statement carries the union
1540  // of the object
1541  OUString aStr;
1542  OUStringBuffer sStringBuffer;
1543  ::basegfx::B2DTuple aTRScale(rTRScale);
1544 
1545  // svg: width
1546  if(!(nFeatures & XMLShapeExportFlags::WIDTH))
1547  {
1548  aTRScale.setX(1.0);
1549  }
1550  else
1551  {
1552  if( aTRScale.getX() > 0.0 )
1553  aTRScale.setX(aTRScale.getX() - 1.0);
1554  else if( aTRScale.getX() < 0.0 )
1555  aTRScale.setX(aTRScale.getX() + 1.0);
1556  }
1557 
1559  FRound(aTRScale.getX()));
1560  aStr = sStringBuffer.makeStringAndClear();
1562 
1563  // svg: height
1564  if(!(nFeatures & XMLShapeExportFlags::HEIGHT))
1565  {
1566  aTRScale.setY(1.0);
1567  }
1568  else
1569  {
1570  if( aTRScale.getY() > 0.0 )
1571  aTRScale.setY(aTRScale.getY() - 1.0);
1572  else if( aTRScale.getY() < 0.0 )
1573  aTRScale.setY(aTRScale.getY() + 1.0);
1574  }
1575 
1577  FRound(aTRScale.getY()));
1578  aStr = sStringBuffer.makeStringAndClear();
1580 
1581  // decide if transformation is necessary
1582  bool bTransformationIsNecessary(fTRShear != 0.0 || fTRRotate != 0.0);
1583 
1584  if(bTransformationIsNecessary)
1585  {
1586  // write transformation, but WITHOUT scale which is exported as size above
1587  SdXMLImExTransform2D aTransform;
1588 
1589  aTransform.AddSkewX(atan(fTRShear));
1590 
1591  // #i78696#
1592  // fTRRotate is mathematically correct, but due to the error
1593  // we export/import it mirrored. Since the API implementation is fixed and
1594  // uses the correctly oriented angle, it is necessary for compatibility to
1595  // mirror the angle here to stay at the old behaviour. There is a follow-up
1596  // task (#i78698#) to fix this in the next ODF FileFormat version
1597  aTransform.AddRotate(-fTRRotate);
1598 
1599  aTransform.AddTranslate(rTRTranslate);
1600 
1601  // does transformation need to be exported?
1602  if(aTransform.NeedsAction())
1604  }
1605  else
1606  {
1607  // no shear, no rotate; just add object position to export and we are done
1608  if(nFeatures & XMLShapeExportFlags::X)
1609  {
1610  // svg: x
1612  FRound(rTRTranslate.getX()));
1613  aStr = sStringBuffer.makeStringAndClear();
1615  }
1616 
1617  if(nFeatures & XMLShapeExportFlags::Y)
1618  {
1619  // svg: y
1621  FRound(rTRTranslate.getY()));
1622  aStr = sStringBuffer.makeStringAndClear();
1624  }
1625  }
1626 }
1627 
1628 bool XMLShapeExport::ImpExportPresentationAttributes( const uno::Reference< beans::XPropertySet >& xPropSet, const OUString& rClass )
1629 {
1630  bool bIsEmpty = false;
1631 
1632  // write presentation class entry
1634 
1635  if( xPropSet.is() )
1636  {
1637  uno::Reference< beans::XPropertySetInfo > xPropSetInfo( xPropSet->getPropertySetInfo() );
1638 
1639 
1640  // is empty pres. shape?
1641  if( xPropSetInfo.is() && xPropSetInfo->hasPropertyByName("IsEmptyPresentationObject"))
1642  {
1643  xPropSet->getPropertyValue("IsEmptyPresentationObject") >>= bIsEmpty;
1644  if( bIsEmpty )
1646  }
1647 
1648  // is user-transformed?
1649  if( xPropSetInfo.is() && xPropSetInfo->hasPropertyByName("IsPlaceholderDependent"))
1650  {
1651  bool bTemp = false;
1652  xPropSet->getPropertyValue("IsPlaceholderDependent") >>= bTemp;
1653  if(!bTemp)
1655  }
1656  }
1657 
1658  return bIsEmpty;
1659 }
1660 
1661 void XMLShapeExport::ImpExportText( const uno::Reference< drawing::XShape >& xShape, TextPNS eExtensionNS )
1662 {
1663  if (eExtensionNS == TextPNS::EXTENSION)
1664  {
1666  {
1667  return; // do not export to ODF 1.1/1.2/1.3
1668  }
1669  }
1670  uno::Reference< text::XText > xText( xShape, uno::UNO_QUERY );
1671  if( xText.is() )
1672  {
1673  uno::Reference< container::XEnumerationAccess > xEnumAccess( xShape, uno::UNO_QUERY );
1674  if( xEnumAccess.is() && xEnumAccess->hasElements() )
1675  mrExport.GetTextParagraphExport()->exportText( xText, false, true, eExtensionNS );
1676  }
1677 }
1678 
1679 namespace {
1680 
1681 enum class Found {
1682  NONE = 0x0000,
1683  CLICKACTION = 0x0001,
1684  BOOKMARK = 0x0002,
1685  EFFECT = 0x0004,
1686  PLAYFULL = 0x0008,
1687  VERB = 0x0010,
1688  SOUNDURL = 0x0020,
1689  SPEED = 0x0040,
1690  CLICKEVENTTYPE = 0x0080,
1691  MACRO = 0x0100,
1692  LIBRARY = 0x0200,
1693 };
1694 
1695 }
1696 
1697 namespace o3tl {
1698  template<> struct typed_flags<Found> : is_typed_flags<Found, 0x03ff> {};
1699 }
1700 
1701 void XMLShapeExport::ImpExportEvents( const uno::Reference< drawing::XShape >& xShape )
1702 {
1703  uno::Reference< document::XEventsSupplier > xEventsSupplier( xShape, uno::UNO_QUERY );
1704  if( !xEventsSupplier.is() )
1705  return;
1706 
1707  uno::Reference< container::XNameAccess > xEvents = xEventsSupplier->getEvents();
1708  SAL_WARN_IF( !xEvents.is(), "xmloff", "XEventsSupplier::getEvents() returned NULL" );
1709  if( !xEvents.is() )
1710  return;
1711 
1712  Found nFound = Found::NONE;
1713 
1714  OUString aClickEventType;
1715  presentation::ClickAction eClickAction = presentation::ClickAction_NONE;
1716  presentation::AnimationEffect eEffect = presentation::AnimationEffect_NONE;
1717  presentation::AnimationSpeed eSpeed = presentation::AnimationSpeed_SLOW;
1718  OUString aStrSoundURL;
1719  bool bPlayFull = false;
1720  sal_Int32 nVerb = 0;
1721  OUString aStrMacro;
1722  OUString aStrLibrary;
1723  OUString aStrBookmark;
1724 
1725  uno::Sequence< beans::PropertyValue > aClickProperties;
1726  if( xEvents->hasByName( gsOnClick ) && (xEvents->getByName( gsOnClick ) >>= aClickProperties) )
1727  {
1728  for( const auto& rProperty : std::as_const(aClickProperties) )
1729  {
1730  if( !( nFound & Found::CLICKEVENTTYPE ) && rProperty.Name == gsEventType )
1731  {
1732  if( rProperty.Value >>= aClickEventType )
1733  nFound |= Found::CLICKEVENTTYPE;
1734  }
1735  else if( !( nFound & Found::CLICKACTION ) && rProperty.Name == gsClickAction )
1736  {
1737  if( rProperty.Value >>= eClickAction )
1738  nFound |= Found::CLICKACTION;
1739  }
1740  else if( !( nFound & Found::MACRO ) && ( rProperty.Name == gsMacroName || rProperty.Name == gsScript ) )
1741  {
1742  if( rProperty.Value >>= aStrMacro )
1743  nFound |= Found::MACRO;
1744  }
1745  else if( !( nFound & Found::LIBRARY ) && rProperty.Name == gsLibrary )
1746  {
1747  if( rProperty.Value >>= aStrLibrary )
1748  nFound |= Found::LIBRARY;
1749  }
1750  else if( !( nFound & Found::EFFECT ) && rProperty.Name == gsEffect )
1751  {
1752  if( rProperty.Value >>= eEffect )
1753  nFound |= Found::EFFECT;
1754  }
1755  else if( !( nFound & Found::BOOKMARK ) && rProperty.Name == gsBookmark )
1756  {
1757  if( rProperty.Value >>= aStrBookmark )
1758  nFound |= Found::BOOKMARK;
1759  }
1760  else if( !( nFound & Found::SPEED ) && rProperty.Name == gsSpeed )
1761  {
1762  if( rProperty.Value >>= eSpeed )
1763  nFound |= Found::SPEED;
1764  }
1765  else if( !( nFound & Found::SOUNDURL ) && rProperty.Name == gsSoundURL )
1766  {
1767  if( rProperty.Value >>= aStrSoundURL )
1768  nFound |= Found::SOUNDURL;
1769  }
1770  else if( !( nFound & Found::PLAYFULL ) && rProperty.Name == gsPlayFull )
1771  {
1772  if( rProperty.Value >>= bPlayFull )
1773  nFound |= Found::PLAYFULL;
1774  }
1775  else if( !( nFound & Found::VERB ) && rProperty.Name == gsVerb )
1776  {
1777  if( rProperty.Value >>= nVerb )
1778  nFound |= Found::VERB;
1779  }
1780  }
1781  }
1782 
1783  // create the XML elements
1784 
1785  if( aClickEventType == gsPresentation )
1786  {
1787  if( !(nFound & Found::CLICKACTION) || (eClickAction == presentation::ClickAction_NONE) )
1788  return;
1789 
1791 
1792  enum XMLTokenEnum eStrAction;
1793 
1794  switch( eClickAction )
1795  {
1796  case presentation::ClickAction_PREVPAGE: eStrAction = XML_PREVIOUS_PAGE; break;
1797  case presentation::ClickAction_NEXTPAGE: eStrAction = XML_NEXT_PAGE; break;
1798  case presentation::ClickAction_FIRSTPAGE: eStrAction = XML_FIRST_PAGE; break;
1799  case presentation::ClickAction_LASTPAGE: eStrAction = XML_LAST_PAGE; break;
1800  case presentation::ClickAction_INVISIBLE: eStrAction = XML_HIDE; break;
1801  case presentation::ClickAction_STOPPRESENTATION:eStrAction = XML_STOP; break;
1802  case presentation::ClickAction_PROGRAM: eStrAction = XML_EXECUTE; break;
1803  case presentation::ClickAction_BOOKMARK: eStrAction = XML_SHOW; break;
1804  case presentation::ClickAction_DOCUMENT: eStrAction = XML_SHOW; break;
1805  case presentation::ClickAction_MACRO: eStrAction = XML_EXECUTE_MACRO; break;
1806  case presentation::ClickAction_VERB: eStrAction = XML_VERB; break;
1807  case presentation::ClickAction_VANISH: eStrAction = XML_FADE_OUT; break;
1808  case presentation::ClickAction_SOUND: eStrAction = XML_SOUND; break;
1809  default:
1810  OSL_FAIL( "unknown presentation::ClickAction found!" );
1811  eStrAction = XML_UNKNOWN;
1812  }
1813 
1814  OUString aEventQName(
1816  XML_NAMESPACE_DOM, "click" ) );
1819 
1820  if( eClickAction == presentation::ClickAction_VANISH )
1821  {
1822  if( nFound & Found::EFFECT )
1823  {
1824  XMLEffect eKind;
1825  XMLEffectDirection eDirection;
1826  sal_Int16 nStartScale;
1827  bool bIn;
1828 
1829  SdXMLImplSetEffect( eEffect, eKind, eDirection, nStartScale, bIn );
1830 
1831  if( eKind != EK_none )
1832  {
1835  }
1836 
1837  if( eDirection != ED_none )
1838  {
1841  }
1842 
1843  if( nStartScale != -1 )
1844  {
1847  }
1848  }
1849 
1850  if( nFound & Found::SPEED && eEffect != presentation::AnimationEffect_NONE )
1851  {
1852  if( eSpeed != presentation::AnimationSpeed_MEDIUM )
1853  {
1856  }
1857  }
1858  }
1859 
1860  if( eClickAction == presentation::ClickAction_PROGRAM ||
1861  eClickAction == presentation::ClickAction_BOOKMARK ||
1862  eClickAction == presentation::ClickAction_DOCUMENT )
1863  {
1864  if( eClickAction == presentation::ClickAction_BOOKMARK )
1865  msBuffer.append( '#' );
1866 
1867  msBuffer.append( aStrBookmark );
1868  mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, GetExport().GetRelativeReference(msBuffer.makeStringAndClear()) );
1872  }
1873 
1874  if( ( nFound & Found::VERB ) && eClickAction == presentation::ClickAction_VERB )
1875  {
1876  msBuffer.append( nVerb );
1878  }
1879 
1881 
1882  if( eClickAction == presentation::ClickAction_VANISH || eClickAction == presentation::ClickAction_SOUND )
1883  {
1884  if( ( nFound & Found::SOUNDURL ) && !aStrSoundURL.isEmpty() )
1885  {
1886  mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, GetExport().GetRelativeReference(aStrSoundURL) );
1890  if( nFound & Found::PLAYFULL && bPlayFull )
1892 
1894  }
1895  }
1896  }
1897  else if( aClickEventType == gsStarBasic )
1898  {
1899  if( nFound & Found::MACRO )
1900  {
1902 
1906  "starbasic" ) );
1907  OUString aEventQName(
1909  XML_NAMESPACE_DOM, "click" ) );
1911 
1912  if( nFound & Found::LIBRARY )
1913  {
1914  const OUString& sLocation( GetXMLToken(
1915  (aStrLibrary.equalsIgnoreAsciiCase("StarOffice") ||
1916  aStrLibrary.equalsIgnoreAsciiCase("application") ) ? XML_APPLICATION
1917  : XML_DOCUMENT ) );
1919  sLocation + ":" + aStrMacro);
1920  }
1921  else
1922  {
1924  }
1925 
1927  }
1928  }
1929  else if( aClickEventType == gsScript )
1930  {
1931  if( nFound & Found::MACRO )
1932  {
1934 
1937  OUString aEventQName(
1939  XML_NAMESPACE_DOM, "click" ) );
1943 
1945  }
1946  }
1947 }
1948 
1950 void XMLShapeExport::ImpExportDescription( const uno::Reference< drawing::XShape >& xShape )
1951 {
1952  try
1953  {
1954  OUString aTitle;
1955  OUString aDescription;
1956 
1957  uno::Reference< beans::XPropertySet > xProps( xShape, uno::UNO_QUERY_THROW );
1958  xProps->getPropertyValue("Title") >>= aTitle;
1959  xProps->getPropertyValue("Description") >>= aDescription;
1960 
1961  if(!aTitle.isEmpty())
1962  {
1963  SvXMLElementExport aEventElemt(mrExport, XML_NAMESPACE_SVG, XML_TITLE, true, false);
1964  mrExport.Characters( aTitle );
1965  }
1966 
1967  if(!aDescription.isEmpty())
1968  {
1969  SvXMLElementExport aEventElemt(mrExport, XML_NAMESPACE_SVG, XML_DESC, true, false );
1970  mrExport.Characters( aDescription );
1971  }
1972  }
1973  catch( uno::Exception& )
1974  {
1975  DBG_UNHANDLED_EXCEPTION( "xmloff", "exporting Title and/or Description for shape" );
1976  }
1977 }
1978 
1979 void XMLShapeExport::ImpExportGroupShape( const uno::Reference< drawing::XShape >& xShape, XMLShapeExportFlags nFeatures, awt::Point* pRefPoint)
1980 {
1981  uno::Reference< drawing::XShapes > xShapes(xShape, uno::UNO_QUERY);
1982  if(!(xShapes.is() && xShapes->getCount()))
1983  return;
1984 
1985  // write group shape
1986  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
1987  SvXMLElementExport aPGR(mrExport, XML_NAMESPACE_DRAW, XML_G, bCreateNewline, true);
1988 
1989  ImpExportDescription( xShape ); // #i68101#
1990  ImpExportEvents( xShape );
1991  ImpExportGluePoints( xShape );
1992 
1993  // #89764# if export of position is suppressed for group shape,
1994  // positions of contained objects should be written relative to
1995  // the upper left edge of the group.
1996  awt::Point aUpperLeft;
1997 
1998  if(!(nFeatures & XMLShapeExportFlags::POSITION))
1999  {
2000  nFeatures |= XMLShapeExportFlags::POSITION;
2001  aUpperLeft = xShape->getPosition();
2002  pRefPoint = &aUpperLeft;
2003  }
2004 
2005  // write members
2006  exportShapes( xShapes, nFeatures, pRefPoint );
2007 }
2008 
2010  const uno::Reference< drawing::XShape >& xShape,
2011  XmlShapeType eShapeType, XMLShapeExportFlags nFeatures, awt::Point* pRefPoint)
2012 {
2013  const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
2014  if(!xPropSet.is())
2015  return;
2016 
2017  // presentation attribute (if presentation)
2018  bool bIsPresShape(false);
2019  bool bIsEmptyPresObj(false);
2020  OUString aStr;
2021 
2022  switch(eShapeType)
2023  {
2025  {
2026  aStr = GetXMLToken(XML_SUBTITLE);
2027  bIsPresShape = true;
2028  break;
2029  }
2031  {
2032  aStr = GetXMLToken(XML_TITLE);
2033  bIsPresShape = true;
2034  break;
2035  }
2037  {
2039  bIsPresShape = true;
2040  break;
2041  }
2043  {
2044  aStr = GetXMLToken(XML_NOTES);
2045  bIsPresShape = true;
2046  break;
2047  }
2049  {
2050  aStr = GetXMLToken(XML_HEADER);
2051  bIsPresShape = true;
2052  break;
2053  }
2055  {
2056  aStr = GetXMLToken(XML_FOOTER);
2057  bIsPresShape = true;
2058  break;
2059  }
2061  {
2062  aStr = GetXMLToken(XML_PAGE_NUMBER);
2063  bIsPresShape = true;
2064  break;
2065  }
2067  {
2068  aStr = GetXMLToken(XML_DATE_TIME);
2069  bIsPresShape = true;
2070  break;
2071  }
2072  default:
2073  break;
2074  }
2075 
2076  // Transformation
2077  ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);
2078 
2079  if(bIsPresShape)
2080  bIsEmptyPresObj = ImpExportPresentationAttributes( xPropSet, aStr );
2081 
2082  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
2084  XML_FRAME, bCreateNewline, true );
2085 
2086  // evtl. corner radius?
2087  sal_Int32 nCornerRadius(0);
2088  xPropSet->getPropertyValue("CornerRadius") >>= nCornerRadius;
2089  if(nCornerRadius)
2090  {
2091  OUStringBuffer sStringBuffer;
2093  nCornerRadius);
2094  mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_CORNER_RADIUS, sStringBuffer.makeStringAndClear());
2095  }
2096 
2097  {
2098  // write text-box
2100  if(!bIsEmptyPresObj)
2101  ImpExportText( xShape );
2102  }
2103 
2104  ImpExportDescription( xShape ); // #i68101#
2105  ImpExportEvents( xShape );
2106  ImpExportGluePoints( xShape );
2107 
2108 }
2109 
2111  const uno::Reference< drawing::XShape >& xShape,
2112  XMLShapeExportFlags nFeatures, css::awt::Point* pRefPoint)
2113 {
2114  const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
2115  if(!xPropSet.is())
2116  return;
2117 
2118  // Transformation
2119  ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);
2120 
2121  // evtl. corner radius?
2122  sal_Int32 nCornerRadius(0);
2123  xPropSet->getPropertyValue("CornerRadius") >>= nCornerRadius;
2124  if(nCornerRadius)
2125  {
2126  OUStringBuffer sStringBuffer;
2128  nCornerRadius);
2129  mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_CORNER_RADIUS, sStringBuffer.makeStringAndClear());
2130  }
2131 
2132  // write rectangle
2133  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
2134  SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DRAW, XML_RECT, bCreateNewline, true);
2135 
2136  ImpExportDescription( xShape ); // #i68101#
2137  ImpExportEvents( xShape );
2138  ImpExportGluePoints( xShape );
2139  ImpExportText( xShape );
2140 }
2141 
2143  const uno::Reference< drawing::XShape >& xShape,
2144  XMLShapeExportFlags nFeatures, awt::Point* pRefPoint)
2145 {
2146  const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
2147  if(!xPropSet.is())
2148  return;
2149 
2150  OUString aStr;
2151  OUStringBuffer sStringBuffer;
2152  awt::Point aStart(0,0);
2153  awt::Point aEnd(1,1);
2154 
2155  // #85920# use 'Geometry' to get the points of the line
2156  // since this slot take anchor pos into account.
2157 
2158  // get matrix
2159  ::basegfx::B2DHomMatrix aMatrix;
2160  ImpExportNewTrans_GetB2DHomMatrix(aMatrix, xPropSet);
2161 
2162  // decompose and correct about pRefPoint
2163  ::basegfx::B2DTuple aTRScale;
2164  double fTRShear(0.0);
2165  double fTRRotate(0.0);
2166  ::basegfx::B2DTuple aTRTranslate;
2167  ImpExportNewTrans_DecomposeAndRefPoint(aMatrix, aTRScale, fTRShear, fTRRotate, aTRTranslate, pRefPoint);
2168 
2169  // create base position
2170  awt::Point aBasePosition(FRound(aTRTranslate.getX()), FRound(aTRTranslate.getY()));
2171 
2172  if (xPropSet->getPropertySetInfo()->hasPropertyByName("Geometry"))
2173  {
2174  // get the two points
2175  uno::Any aAny(xPropSet->getPropertyValue("Geometry"));
2176  if (auto pSourcePolyPolygon
2177  = o3tl::tryAccess<drawing::PointSequenceSequence>(aAny))
2178  {
2179  if (pSourcePolyPolygon->getLength() > 0)
2180  {
2181  const drawing::PointSequence& rInnerSequence = (*pSourcePolyPolygon)[0];
2182  if (rInnerSequence.hasElements())
2183  {
2184  const awt::Point& rPoint = rInnerSequence[0];
2185  aStart = awt::Point(rPoint.X + aBasePosition.X, rPoint.Y + aBasePosition.Y);
2186  }
2187  if (rInnerSequence.getLength() > 1)
2188  {
2189  const awt::Point& rPoint = rInnerSequence[1];
2190  aEnd = awt::Point(rPoint.X + aBasePosition.X, rPoint.Y + aBasePosition.Y);
2191  }
2192  }
2193  }
2194  }
2195 
2196  if( nFeatures & XMLShapeExportFlags::X )
2197  {
2198  // svg: x1
2200  aStart.X);
2201  aStr = sStringBuffer.makeStringAndClear();
2203  }
2204  else
2205  {
2206  aEnd.X -= aStart.X;
2207  }
2208 
2209  if( nFeatures & XMLShapeExportFlags::Y )
2210  {
2211  // svg: y1
2213  aStart.Y);
2214  aStr = sStringBuffer.makeStringAndClear();
2216  }
2217  else
2218  {
2219  aEnd.Y -= aStart.Y;
2220  }
2221 
2222  // svg: x2
2224  aEnd.X);
2225  aStr = sStringBuffer.makeStringAndClear();
2227 
2228  // svg: y2
2230  aEnd.Y);
2231  aStr = sStringBuffer.makeStringAndClear();
2233 
2234  // write line
2235  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
2236  SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DRAW, XML_LINE, bCreateNewline, true);
2237 
2238  ImpExportDescription( xShape ); // #i68101#
2239  ImpExportEvents( xShape );
2240  ImpExportGluePoints( xShape );
2241  ImpExportText( xShape );
2242 
2243 }
2244 
2246  const uno::Reference< drawing::XShape >& xShape,
2247  XMLShapeExportFlags nFeatures, awt::Point* pRefPoint)
2248 {
2249  const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
2250  if(!xPropSet.is())
2251  return;
2252 
2253  // get size to decide between Circle and Ellipse
2254  awt::Size aSize = xShape->getSize();
2255  sal_Int32 nRx((aSize.Width + 1) / 2);
2256  sal_Int32 nRy((aSize.Height + 1) / 2);
2257  bool bCircle(nRx == nRy);
2258 
2259  // Transformation
2260  ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);
2261 
2262  drawing::CircleKind eKind = drawing::CircleKind_FULL;
2263  xPropSet->getPropertyValue("CircleKind") >>= eKind;
2264  if( eKind != drawing::CircleKind_FULL )
2265  {
2266  OUStringBuffer sStringBuffer;
2267  sal_Int32 nStartAngle = 0;
2268  sal_Int32 nEndAngle = 0;
2269  xPropSet->getPropertyValue("CircleStartAngle") >>= nStartAngle;
2270  xPropSet->getPropertyValue("CircleEndAngle") >>= nEndAngle;
2271 
2272  const double dStartAngle = nStartAngle / 100.0;
2273  const double dEndAngle = nEndAngle / 100.0;
2274 
2275  // export circle kind
2277  mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_KIND, sStringBuffer.makeStringAndClear() );
2278 
2279  // export start angle
2280  ::sax::Converter::convertDouble( sStringBuffer, dStartAngle );
2281  mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_START_ANGLE, sStringBuffer.makeStringAndClear() );
2282 
2283  // export end angle
2284  ::sax::Converter::convertDouble( sStringBuffer, dEndAngle );
2285  mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_END_ANGLE, sStringBuffer.makeStringAndClear() );
2286  }
2287 
2288  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
2289 
2290  // write ellipse or circle
2292  bCircle ? XML_CIRCLE : XML_ELLIPSE,
2293  bCreateNewline, true);
2294 
2295  ImpExportDescription( xShape ); // #i68101#
2296  ImpExportEvents( xShape );
2297  ImpExportGluePoints( xShape );
2298  ImpExportText( xShape );
2299 
2300 }
2301 
2303  const uno::Reference< drawing::XShape >& xShape,
2304  XmlShapeType eShapeType, XMLShapeExportFlags nFeatures, awt::Point* pRefPoint)
2305 {
2306  const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
2307  if(!xPropSet.is())
2308  return;
2309 
2310  bool bBezier(eShapeType == XmlShapeTypeDrawClosedBezierShape
2311  || eShapeType == XmlShapeTypeDrawOpenBezierShape);
2312 
2313  // get matrix
2314  ::basegfx::B2DHomMatrix aMatrix;
2315  ImpExportNewTrans_GetB2DHomMatrix(aMatrix, xPropSet);
2316 
2317  // decompose and correct about pRefPoint
2318  ::basegfx::B2DTuple aTRScale;
2319  double fTRShear(0.0);
2320  double fTRRotate(0.0);
2321  ::basegfx::B2DTuple aTRTranslate;
2322  ImpExportNewTrans_DecomposeAndRefPoint(aMatrix, aTRScale, fTRShear, fTRRotate, aTRTranslate, pRefPoint);
2323 
2324  // use features and write
2325  ImpExportNewTrans_FeaturesAndWrite(aTRScale, fTRShear, fTRRotate, aTRTranslate, nFeatures);
2326 
2327  // create and export ViewBox
2328  awt::Size aSize(FRound(aTRScale.getX()), FRound(aTRScale.getY()));
2329  SdXMLImExViewBox aViewBox(0, 0, aSize.Width, aSize.Height);
2331 
2332  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
2333 
2334  // prepare name (with most used)
2336 
2337  if(bBezier)
2338  {
2339  // get PolygonBezier
2340  uno::Any aAny( xPropSet->getPropertyValue("Geometry") );
2341  auto pSourcePolyPolygon = o3tl::tryAccess<drawing::PolyPolygonBezierCoords>(aAny);
2342  if(pSourcePolyPolygon && pSourcePolyPolygon->Coordinates.getLength())
2343  {
2344  const basegfx::B2DPolyPolygon aPolyPolygon(
2346  *pSourcePolyPolygon));
2347 
2348  // complex polygon shape, write as svg:d
2349  const OUString aPolygonString(
2351  aPolyPolygon,
2352  true, // bUseRelativeCoordinates
2353  false, // bDetectQuadraticBeziers: not used in old, but maybe activated now
2354  true)); // bHandleRelativeNextPointCompatible
2355 
2356  // write point array
2357  mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_D, aPolygonString);
2358  }
2359  }
2360  else
2361  {
2362  // get non-bezier polygon
2363  uno::Any aAny( xPropSet->getPropertyValue("Geometry") );
2364  const basegfx::B2DPolyPolygon aPolyPolygon(
2365  basegfx::utils::UnoPointSequenceSequenceToB2DPolyPolygon(*o3tl::doAccess<drawing::PointSequenceSequence>(aAny)));
2366 
2367  if(!aPolyPolygon.areControlPointsUsed() && 1 == aPolyPolygon.count())
2368  {
2369  // simple polygon shape, can be written as svg:points sequence
2370  const basegfx::B2DPolygon& aPolygon(aPolyPolygon.getB2DPolygon(0));
2371  const OUString aPointString(basegfx::utils::exportToSvgPoints(aPolygon));
2372 
2373  // write point array
2375 
2376  // set name
2377  eName = aPolygon.isClosed() ? XML_POLYGON : XML_POLYLINE;
2378  }
2379  else
2380  {
2381  // complex polygon shape, write as svg:d
2382  const OUString aPolygonString(
2384  aPolyPolygon,
2385  true, // bUseRelativeCoordinates
2386  false, // bDetectQuadraticBeziers: not used in old, but maybe activated now
2387  true)); // bHandleRelativeNextPointCompatible
2388 
2389  // write point array
2390  mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_D, aPolygonString);
2391  }
2392  }
2393 
2394  // write object, but after attributes are added since this call will
2395  // consume all of these added attributes and the destructor will close the
2396  // scope. Also before text is added; this may add sub-scopes as needed
2397  SvXMLElementExport aOBJ(
2398  mrExport,
2400  eName,
2401  bCreateNewline,
2402  true);
2403 
2404  ImpExportDescription( xShape ); // #i68101#
2405  ImpExportEvents( xShape );
2406  ImpExportGluePoints( xShape );
2407  ImpExportText( xShape );
2408 
2409 }
2410 
2411 namespace
2412 {
2413 
2414 OUString getNameFromStreamURL(std::u16string_view rURL)
2415 {
2416  static constexpr std::u16string_view sPackageURL(u"vnd.sun.star.Package:");
2417 
2418  OUString sResult;
2419 
2420  if (o3tl::starts_with(rURL, sPackageURL))
2421  {
2422  std::u16string_view sRequestedName = rURL.substr(sPackageURL.size());
2423  size_t nLastIndex = sRequestedName.rfind('/') + 1;
2424  if ((nLastIndex > 0) && (nLastIndex < sRequestedName.size()))
2425  sRequestedName = sRequestedName.substr(nLastIndex);
2426  nLastIndex = sRequestedName.rfind('.');
2427  if (nLastIndex != std::u16string_view::npos)
2428  sRequestedName = sRequestedName.substr(0, nLastIndex);
2429  if (!sRequestedName.empty())
2430  sResult = sRequestedName;
2431  }
2432 
2433  return sResult;
2434 }
2435 
2436 } // end anonymous namespace
2437 
2439  const uno::Reference< drawing::XShape >& xShape,
2440  XmlShapeType eShapeType, XMLShapeExportFlags nFeatures, awt::Point* pRefPoint)
2441 {
2442  const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
2443  if(!xPropSet.is())
2444  return;
2445 
2446  bool bIsEmptyPresObj = false;
2447 
2448  // Transformation
2449  ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);
2450 
2451  if(eShapeType == XmlShapeTypePresGraphicObjectShape)
2452  bIsEmptyPresObj = ImpExportPresentationAttributes( xPropSet, GetXMLToken(XML_GRAPHIC) );
2453 
2454  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
2456  XML_FRAME, bCreateNewline, true );
2457 
2458  if (!bIsEmptyPresObj)
2459  {
2460  uno::Reference<graphic::XGraphic> xGraphic;
2461  OUString sOutMimeType;
2462 
2463  {
2464  OUString aStreamURL;
2465  xPropSet->getPropertyValue("GraphicStreamURL") >>= aStreamURL;
2466  OUString sRequestedName = getNameFromStreamURL(aStreamURL);
2467 
2468  xPropSet->getPropertyValue("Graphic") >>= xGraphic;
2469 
2470  OUString sInternalURL;
2471 
2472  if (xGraphic.is())
2473  sInternalURL = mrExport.AddEmbeddedXGraphic(xGraphic, sOutMimeType, sRequestedName);
2474 
2475  if (!sInternalURL.isEmpty())
2476  {
2477  // apply possible changed stream URL to embedded image object
2478  if (!sRequestedName.isEmpty())
2479  {
2480  OUString newStreamURL = "vnd.sun.star.Package:";
2481  if (sInternalURL[0] == '#')
2482  {
2483  newStreamURL += sInternalURL.subView(1, sInternalURL.getLength() - 1);
2484  }
2485  else
2486  {
2487  newStreamURL += sInternalURL;
2488  }
2489 
2490  if (newStreamURL != aStreamURL)
2491  {
2492  xPropSet->setPropertyValue("GraphicStreamURL", uno::Any(newStreamURL));
2493  }
2494  }
2495 
2500  }
2501  }
2502 
2503  {
2504  if (GetExport().getSaneDefaultVersion() > SvtSaveOptions::ODFSVER_012)
2505  {
2506  if (sOutMimeType.isEmpty())
2507  {
2508  GetExport().GetGraphicMimeTypeFromStream(xGraphic, sOutMimeType);
2509  }
2510  if (!sOutMimeType.isEmpty())
2511  { // ODF 1.3 OFFICE-3943
2513  SvtSaveOptions::ODFSVER_013 <= GetExport().getSaneDefaultVersion()
2516  "mime-type", sOutMimeType);
2517  }
2518  }
2519 
2520  SvXMLElementExport aElement(mrExport, XML_NAMESPACE_DRAW, XML_IMAGE, true, true);
2521 
2522  // optional office:binary-data
2523  if (xGraphic.is())
2524  {
2526  }
2527  if (!bIsEmptyPresObj)
2528  ImpExportText(xShape);
2529  }
2530 
2531  //Resolves: fdo#62461 put preferred image first above, followed by
2532  //fallback here
2533  const bool bAddReplacementImages = officecfg::Office::Common::Save::Graphic::AddReplacementImages::get();
2534  if( !bIsEmptyPresObj && bAddReplacementImages)
2535  {
2536  uno::Reference<graphic::XGraphic> xReplacementGraphic;
2537  xPropSet->getPropertyValue("ReplacementGraphic") >>= xReplacementGraphic;
2538 
2539  // If there is no url, then the graphic is empty
2540  if (xReplacementGraphic.is())
2541  {
2542  OUString aMimeType;
2543  const OUString aHref = mrExport.AddEmbeddedXGraphic(xReplacementGraphic, aMimeType);
2544 
2545  if (aMimeType.isEmpty())
2546  mrExport.GetGraphicMimeTypeFromStream(xReplacementGraphic, aMimeType);
2547 
2548  if (!aHref.isEmpty())
2549  {
2554  }
2555 
2556  if (!aMimeType.isEmpty() && GetExport().getSaneDefaultVersion() > SvtSaveOptions::ODFSVER_012)
2557  { // ODF 1.3 OFFICE-3943
2559  SvtSaveOptions::ODFSVER_013 <= GetExport().getSaneDefaultVersion()
2562  "mime-type", aMimeType);
2563  }
2564 
2565  SvXMLElementExport aElement(mrExport, XML_NAMESPACE_DRAW, XML_IMAGE, true, true);
2566 
2567  // optional office:binary-data
2568  mrExport.AddEmbeddedXGraphicAsBase64(xReplacementGraphic);
2569  }
2570  }
2571  }
2572 
2573  ImpExportEvents( xShape );
2574  ImpExportGluePoints( xShape );
2575 
2576  // image map
2577  GetExport().GetImageMapExport().Export( xPropSet );
2578  ImpExportDescription( xShape ); // #i68101#
2579 
2580  // Signature Line, QR Code - needs to be after the images!
2581  if (GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
2582  {
2583  ImpExportSignatureLine(xShape);
2584  ImpExportQRCode(xShape);
2585  }
2586 }
2587 
2589  const uno::Reference< drawing::XShape >& xShape,
2590  XmlShapeType eShapeType, XMLShapeExportFlags nFeatures, awt::Point* pRefPoint,
2591  SvXMLAttributeList* pAttrList )
2592 {
2593  ImpExportOLE2Shape( xShape, eShapeType, nFeatures, pRefPoint, pAttrList );
2594 }
2595 
2597  const uno::Reference< drawing::XShape >& xShape,
2598  XMLShapeExportFlags nFeatures, awt::Point* pRefPoint)
2599 {
2600  const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
2601  if(xPropSet.is())
2602  {
2603  // Transformation
2604  ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);
2605  }
2606 
2607  uno::Reference< drawing::XControlShape > xControl( xShape, uno::UNO_QUERY );
2608  SAL_WARN_IF( !xControl.is(), "xmloff", "Control shape is not supporting XControlShape" );
2609  if( xControl.is() )
2610  {
2611  uno::Reference< beans::XPropertySet > xControlModel( xControl->getControl(), uno::UNO_QUERY );
2612  SAL_WARN_IF( !xControlModel.is(), "xmloff", "Control shape has not XControlModel" );
2613  if( xControlModel.is() )
2614  {
2615  OUString sControlId = mrExport.GetFormExport()->getControlId( xControlModel );
2617  }
2618  }
2619 
2620  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
2621  SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DRAW, XML_CONTROL, bCreateNewline, true);
2622 
2623  ImpExportDescription( xShape ); // #i68101#
2624 }
2625 
2627  const uno::Reference< drawing::XShape >& xShape,
2628  XMLShapeExportFlags nFeatures /* = SEF_DEFAULT */, awt::Point* pRefPoint /* = NULL */)
2629 {
2630  uno::Reference< beans::XPropertySet > xProps( xShape, uno::UNO_QUERY );
2631 
2632  OUString aStr;
2633  OUStringBuffer sStringBuffer;
2634 
2635  // export connection kind
2636  drawing::ConnectorType eType = drawing::ConnectorType_STANDARD;
2637  uno::Any aAny = xProps->getPropertyValue("EdgeKind");
2638  aAny >>= eType;
2639 
2640  if( eType != drawing::ConnectorType_STANDARD )
2641  {
2643  aStr = sStringBuffer.makeStringAndClear();
2645  }
2646 
2647  // export line skew
2648  sal_Int32 nDelta1 = 0, nDelta2 = 0, nDelta3 = 0;
2649 
2650  aAny = xProps->getPropertyValue("EdgeLine1Delta");
2651  aAny >>= nDelta1;
2652  aAny = xProps->getPropertyValue("EdgeLine2Delta");
2653  aAny >>= nDelta2;
2654  aAny = xProps->getPropertyValue("EdgeLine3Delta");
2655  aAny >>= nDelta3;
2656 
2657  if( nDelta1 != 0 || nDelta2 != 0 || nDelta3 != 0 )
2658  {
2660  nDelta1);
2661  if( nDelta2 != 0 || nDelta3 != 0 )
2662  {
2663  sStringBuffer.append( ' ' );
2665  nDelta2);
2666  if( nDelta3 != 0 )
2667  {
2668  sStringBuffer.append( ' ' );
2670  sStringBuffer, nDelta3);
2671  }
2672  }
2673 
2674  aStr = sStringBuffer.makeStringAndClear();
2676  }
2677 
2678  // export start and end point
2679  awt::Point aStart(0,0);
2680  awt::Point aEnd(1,1);
2681 
2682  /* Get <StartPositionInHoriL2R> and
2683  <EndPositionInHoriL2R>, if they exist and if the document is exported
2684  into the OpenOffice.org file format.
2685  These properties only exist at service css::text::Shape - the
2686  Writer UNO service for shapes.
2687  This code is needed, because the positioning attributes in the
2688  OpenOffice.org file format are given in horizontal left-to-right layout
2689  regardless the layout direction the shape is in. In the OASIS Open Office
2690  file format the positioning attributes are correctly given in the layout
2691  direction the shape is in. Thus, this code provides the conversion from
2692  the OASIS Open Office file format to the OpenOffice.org file format. (#i36248#)
2693  */
2694  if ( !( GetExport().getExportFlags() & SvXMLExportFlags::OASIS ) &&
2695  xProps->getPropertySetInfo()->hasPropertyByName("StartPositionInHoriL2R") &&
2696  xProps->getPropertySetInfo()->hasPropertyByName("EndPositionInHoriL2R") )
2697  {
2698  xProps->getPropertyValue("StartPositionInHoriL2R") >>= aStart;
2699  xProps->getPropertyValue("EndPositionInHoriL2R") >>= aEnd;
2700  }
2701  else
2702  {
2703  xProps->getPropertyValue("StartPosition") >>= aStart;
2704  xProps->getPropertyValue("EndPosition") >>= aEnd;
2705  }
2706 
2707  if( pRefPoint )
2708  {
2709  aStart.X -= pRefPoint->X;
2710  aStart.Y -= pRefPoint->Y;
2711  aEnd.X -= pRefPoint->X;
2712  aEnd.Y -= pRefPoint->Y;
2713  }
2714 
2715  if( nFeatures & XMLShapeExportFlags::X )
2716  {
2717  // svg: x1
2719  aStart.X);
2720  aStr = sStringBuffer.makeStringAndClear();
2722  }
2723  else
2724  {
2725  aEnd.X -= aStart.X;
2726  }
2727 
2728  if( nFeatures & XMLShapeExportFlags::Y )
2729  {
2730  // svg: y1
2732  aStart.Y);
2733  aStr = sStringBuffer.makeStringAndClear();
2735  }
2736  else
2737  {
2738  aEnd.Y -= aStart.Y;
2739  }
2740 
2741  // svg: x2
2742  mrExport.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer, aEnd.X);
2743  aStr = sStringBuffer.makeStringAndClear();
2745 
2746  // svg: y2
2747  mrExport.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer, aEnd.Y);
2748  aStr = sStringBuffer.makeStringAndClear();
2750 
2751  // #i39320#
2752  uno::Reference< uno::XInterface > xRefS;
2753  uno::Reference< uno::XInterface > xRefE;
2754 
2755  // export start connection
2756  xProps->getPropertyValue("StartShape") >>= xRefS;
2757  if( xRefS.is() )
2758  {
2759  const OUString& rShapeId = mrExport.getInterfaceToIdentifierMapper().getIdentifier( xRefS );
2761 
2762  aAny = xProps->getPropertyValue("StartGluePointIndex");
2763  sal_Int32 nGluePointId = 0;
2764  if( aAny >>= nGluePointId )
2765  {
2766  if( nGluePointId != -1 )
2767  {
2768  mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_START_GLUE_POINT, OUString::number( nGluePointId ));
2769  }
2770  }
2771  }
2772 
2773  // export end connection
2774  xProps->getPropertyValue("EndShape") >>= xRefE;
2775  if( xRefE.is() )
2776  {
2777  const OUString& rShapeId = mrExport.getInterfaceToIdentifierMapper().getIdentifier( xRefE );
2779 
2780  aAny = xProps->getPropertyValue("EndGluePointIndex");
2781  sal_Int32 nGluePointId = 0;
2782  if( aAny >>= nGluePointId )
2783  {
2784  if( nGluePointId != -1 )
2785  {
2786  mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_END_GLUE_POINT, OUString::number( nGluePointId ));
2787  }
2788  }
2789  }
2790 
2791  // get PolygonBezier
2792  aAny = xProps->getPropertyValue("PolyPolygonBezier");
2793  auto pSourcePolyPolygon = o3tl::tryAccess<drawing::PolyPolygonBezierCoords>(aAny);
2794  if(pSourcePolyPolygon && pSourcePolyPolygon->Coordinates.getLength())
2795  {
2796  const basegfx::B2DPolyPolygon aPolyPolygon(
2798  *pSourcePolyPolygon));
2799  const OUString aPolygonString(
2801  aPolyPolygon,
2802  true, // bUseRelativeCoordinates
2803  false, // bDetectQuadraticBeziers: not used in old, but maybe activated now
2804  true)); // bHandleRelativeNextPointCompatible
2805 
2806  // write point array
2807  mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_D, aPolygonString);
2808  }
2809 
2810  // get matrix
2811  ::basegfx::B2DHomMatrix aMatrix;
2812  ImpExportNewTrans_GetB2DHomMatrix(aMatrix, xProps);
2813 
2814  // decompose and correct about pRefPoint
2815  ::basegfx::B2DTuple aTRScale;
2816  double fTRShear(0.0);
2817  double fTRRotate(0.0);
2818  ::basegfx::B2DTuple aTRTranslate;
2819  ImpExportNewTrans_DecomposeAndRefPoint(aMatrix, aTRScale, fTRShear,
2820  fTRRotate, aTRTranslate, pRefPoint);
2821 
2822  // fdo#49678: create and export ViewBox
2823  awt::Size aSize(FRound(aTRScale.getX()), FRound(aTRScale.getY()));
2824  SdXMLImExViewBox aViewBox(0, 0, aSize.Width, aSize.Height);
2826 
2827  // write connector shape. Add Export later.
2828  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
2829  SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DRAW, XML_CONNECTOR, bCreateNewline, true);
2830 
2831  ImpExportDescription( xShape ); // #i68101#
2832  ImpExportEvents( xShape );
2833  ImpExportGluePoints( xShape );
2834  ImpExportText( xShape );
2835 }
2836 
2838  const uno::Reference< drawing::XShape >& xShape,
2839  XMLShapeExportFlags nFeatures /* = SEF_DEFAULT */, awt::Point const * pRefPoint /* = NULL */)
2840 {
2841  uno::Reference< beans::XPropertySet > xProps( xShape, uno::UNO_QUERY );
2842 
2843  OUString aStr;
2844  OUStringBuffer sStringBuffer;
2845 
2846  // export start and end point
2847  awt::Point aStart(0,0);
2848  awt::Point aEnd(1,1);
2849 
2850  /* Get <StartPositionInHoriL2R> and
2851  <EndPositionInHoriL2R>, if they exist and if the document is exported
2852  into the OpenOffice.org file format.
2853  These properties only exist at service css::text::Shape - the
2854  Writer UNO service for shapes.
2855  This code is needed, because the positioning attributes in the
2856  OpenOffice.org file format are given in horizontal left-to-right layout
2857  regardless the layout direction the shape is in. In the OASIS Open Office
2858  file format the positioning attributes are correctly given in the layout
2859  direction the shape is in. Thus, this code provides the conversion from
2860  the OASIS Open Office file format to the OpenOffice.org file format. (#i36248#)
2861  */
2862  if ( !( GetExport().getExportFlags() & SvXMLExportFlags::OASIS ) &&
2863  xProps->getPropertySetInfo()->hasPropertyByName("StartPositionInHoriL2R") &&
2864  xProps->getPropertySetInfo()->hasPropertyByName("EndPositionInHoriL2R") )
2865  {
2866  xProps->getPropertyValue("StartPositionInHoriL2R") >>= aStart;
2867  xProps->getPropertyValue("EndPositionInHoriL2R") >>= aEnd;
2868  }
2869  else
2870  {
2871  xProps->getPropertyValue("StartPosition") >>= aStart;
2872  xProps->getPropertyValue("EndPosition") >>= aEnd;
2873  }
2874 
2875  if( pRefPoint )
2876  {
2877  aStart.X -= pRefPoint->X;
2878  aStart.Y -= pRefPoint->Y;
2879  aEnd.X -= pRefPoint->X;
2880  aEnd.Y -= pRefPoint->Y;
2881  }
2882 
2883  if( nFeatures & XMLShapeExportFlags::X )
2884  {
2885  // svg: x1
2887  aStart.X);
2888  aStr = sStringBuffer.makeStringAndClear();
2890  }
2891  else
2892  {
2893  aEnd.X -= aStart.X;
2894  }
2895 
2896  if( nFeatures & XMLShapeExportFlags::Y )
2897  {
2898  // svg: y1
2900  aStart.Y);
2901  aStr = sStringBuffer.makeStringAndClear();
2903  }
2904  else
2905  {
2906  aEnd.Y -= aStart.Y;
2907  }
2908 
2909  // svg: x2
2910  mrExport.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer, aEnd.X);
2911  aStr = sStringBuffer.makeStringAndClear();
2913 
2914  // svg: y2
2915  mrExport.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer, aEnd.Y);
2916  aStr = sStringBuffer.makeStringAndClear();
2918 
2919  // write measure shape
2920  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
2921  SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DRAW, XML_MEASURE, bCreateNewline, true);
2922 
2923  ImpExportDescription( xShape ); // #i68101#
2924  ImpExportEvents( xShape );
2925  ImpExportGluePoints( xShape );
2926 
2927  uno::Reference< text::XText > xText( xShape, uno::UNO_QUERY );
2928  if( xText.is() )
2929  mrExport.GetTextParagraphExport()->exportText( xText );
2930 }
2931 
2933  const uno::Reference< drawing::XShape >& xShape,
2934  XmlShapeType eShapeType, XMLShapeExportFlags nFeatures /* = SEF_DEFAULT */, awt::Point* pRefPoint /* = NULL */,
2935  SvXMLAttributeList* pAttrList /* = NULL */ )
2936 {
2937  uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
2938  uno::Reference< container::XNamed > xNamed(xShape, uno::UNO_QUERY);
2939 
2940  SAL_WARN_IF( !xPropSet.is() || !xNamed.is(), "xmloff", "ole shape is not implementing needed interfaces");
2941  if(!(xPropSet.is() && xNamed.is()))
2942  return;
2943 
2944  // Transformation
2945  ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);
2946 
2947  bool bIsEmptyPresObj = false;
2948 
2949  // presentation settings
2950  if(eShapeType == XmlShapeTypePresOLE2Shape)
2951  bIsEmptyPresObj = ImpExportPresentationAttributes( xPropSet, GetXMLToken(XML_OBJECT) );
2952  else if(eShapeType == XmlShapeTypePresChartShape)
2953  bIsEmptyPresObj = ImpExportPresentationAttributes( xPropSet, GetXMLToken(XML_CHART) );
2954  else if(eShapeType == XmlShapeTypePresSheetShape)
2955  bIsEmptyPresObj = ImpExportPresentationAttributes( xPropSet, GetXMLToken(XML_TABLE) );
2956 
2957  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
2958  bool bExportEmbedded(mrExport.getExportFlags() & SvXMLExportFlags::EMBEDDED);
2959  OUString sPersistName;
2961  XML_FRAME, bCreateNewline, true );
2962 
2963  if (!bIsEmptyPresObj)
2964  {
2965  if (pAttrList)
2966  {
2967  mrExport.AddAttributeList(pAttrList);
2968  }
2969 
2970  OUString sClassId;
2971  OUString sURL;
2972  bool bInternal = false;
2973  xPropSet->getPropertyValue("IsInternal") >>= bInternal;
2974 
2975  {
2976 
2977  if ( bInternal )
2978  {
2979  // OOo internal links have no storage persistence, URL is stored in the XML file
2980  // the result LinkURL is empty in case the object is not a link
2981  xPropSet->getPropertyValue("LinkURL") >>= sURL;
2982  }
2983 
2984  xPropSet->getPropertyValue("PersistName") >>= sPersistName;
2985  if ( sURL.isEmpty() )
2986  {
2987  if( !sPersistName.isEmpty() )
2988  {
2989  sURL = "vnd.sun.star.EmbeddedObject:" + sPersistName;
2990  }
2991  }
2992 
2993  if( !bInternal )
2994  xPropSet->getPropertyValue("CLSID") >>= sClassId;
2995 
2996  if( !sClassId.isEmpty() )
2998 
2999  if(!bExportEmbedded)
3000  {
3001  // xlink:href
3002  if( !sURL.isEmpty() )
3003  {
3004  // #96717# in theorie, if we don't have a URL we shouldn't even
3005  // export this OLE shape. But practically it's too risky right now
3006  // to change this so we better dispose this on load
3007  sURL = mrExport.AddEmbeddedObject( sURL );
3008 
3013  }
3014  }
3015  }
3016 
3017  enum XMLTokenEnum eElem = sClassId.isEmpty() ? XML_OBJECT : XML_OBJECT_OLE ;
3018  SvXMLElementExport aElem( mrExport, XML_NAMESPACE_DRAW, eElem, true, true );
3019 
3020  // tdf#112547 export text as child of draw:object, where import expects it
3021  if (!bIsEmptyPresObj && supportsText(eShapeType))
3022  {
3023  // #i118485# Add text export, the draw OLE shape allows text now
3024  ImpExportText( xShape, TextPNS::EXTENSION );
3025  }
3026 
3027  if(bExportEmbedded && !bIsEmptyPresObj)
3028  {
3029  if(bInternal)
3030  {
3031  // embedded XML
3032  uno::Reference< lang::XComponent > xComp;
3033  xPropSet->getPropertyValue("Model") >>= xComp;
3034  SAL_WARN_IF( !xComp.is(), "xmloff", "no xModel for own OLE format" );
3036  }
3037  else
3038  {
3039  // embed as Base64
3040  // this is an alien object ( currently MSOLE is the only supported type of such objects )
3041  // in case it is not an OASIS format the object should be asked to store replacement image if possible
3042 
3043  OUString sURLRequest( sURL );
3045  sURLRequest += "?oasis=false";
3046  mrExport.AddEmbeddedObjectAsBase64( sURLRequest );
3047  }
3048  }
3049  }
3050  if( !bIsEmptyPresObj )
3051  {
3052  OUString sURL = XML_EMBEDDEDOBJECTGRAPHIC_URL_BASE + sPersistName;
3053  if( !bExportEmbedded )
3054  {
3055  sURL = GetExport().AddEmbeddedObject( sURL );
3060  }
3061 
3063  XML_IMAGE, false, true );
3064 
3065  if( bExportEmbedded )
3067  }
3068 
3069  ImpExportEvents( xShape );
3070  ImpExportGluePoints( xShape );
3071  ImpExportDescription( xShape ); // #i68101#
3072 
3073 }
3074 
3076  const uno::Reference< drawing::XShape >& xShape,
3077  XmlShapeType eShapeType, XMLShapeExportFlags nFeatures /* = SEF_DEFAULT */, awt::Point* pRefPoint /* = NULL */)
3078 {
3079  const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
3080  if(!xPropSet.is())
3081  return;
3082 
3083  // #86163# Transformation
3084  ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);
3085 
3086  // export page number used for this page
3087  uno::Reference< beans::XPropertySetInfo > xPropSetInfo( xPropSet->getPropertySetInfo() );
3088  static const OUStringLiteral aPageNumberStr(u"PageNumber");
3089  if( xPropSetInfo.is() && xPropSetInfo->hasPropertyByName(aPageNumberStr))
3090  {
3091  sal_Int32 nPageNumber = 0;
3092  xPropSet->getPropertyValue(aPageNumberStr) >>= nPageNumber;
3093  if( nPageNumber )
3094  mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_PAGE_NUMBER, OUString::number(nPageNumber));
3095  }
3096 
3097  // a presentation page shape, normally used on notes pages only. If
3098  // it is used not as presentation shape, it may have been created with
3099  // copy-paste exchange between draw and impress (this IS possible...)
3100  if(eShapeType == XmlShapeTypePresPageShape)
3101  {
3103  XML_PAGE);
3104  }
3105 
3106  // write Page shape
3107  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
3108  SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DRAW, XML_PAGE_THUMBNAIL, bCreateNewline, true);
3109 }
3110 
3112  const uno::Reference< drawing::XShape >& xShape,
3113  XMLShapeExportFlags nFeatures /* = SEF_DEFAULT */, awt::Point* pRefPoint /* = NULL */)
3114 {
3115  const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
3116  if(!xPropSet.is())
3117  return;
3118 
3119  // Transformation
3120  ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);
3121 
3122  // evtl. corner radius?
3123  sal_Int32 nCornerRadius(0);
3124  xPropSet->getPropertyValue("CornerRadius") >>= nCornerRadius;
3125  if(nCornerRadius)
3126  {
3127  OUStringBuffer sStringBuffer;
3129  nCornerRadius);
3130  mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_CORNER_RADIUS, sStringBuffer.makeStringAndClear());
3131  }
3132 
3133  awt::Point aCaptionPoint;
3134  xPropSet->getPropertyValue("CaptionPoint") >>= aCaptionPoint;
3135 
3137  aCaptionPoint.X);
3140  aCaptionPoint.Y);
3142 
3143  // write Caption shape. Add export later.
3144  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
3145  bool bAnnotation( (nFeatures & XMLShapeExportFlags::ANNOTATION) == XMLShapeExportFlags::ANNOTATION );
3146 
3148  (bAnnotation ? XML_NAMESPACE_OFFICE
3149  : XML_NAMESPACE_DRAW),
3150  (bAnnotation ? XML_ANNOTATION : XML_CAPTION),
3151  bCreateNewline, true );
3152 
3153  ImpExportDescription( xShape ); // #i68101#
3154  ImpExportEvents( xShape );
3155  ImpExportGluePoints( xShape );
3156  if( bAnnotation )
3157  mrExport.exportAnnotationMeta( xShape );
3158  ImpExportText( xShape );
3159 
3160 }
3161 
3163  const uno::Reference< drawing::XShape >& xShape,
3164  XMLShapeExportFlags nFeatures, css::awt::Point* pRefPoint)
3165 {
3166  const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
3167  if(!xPropSet.is())
3168  return;
3169 
3170  // Transformation
3171  ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);
3172 
3173  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
3175  XML_FRAME, bCreateNewline, true );
3176 
3177  // export frame url
3178  OUString aStr;
3179  xPropSet->getPropertyValue("FrameURL") >>= aStr;
3180  mrExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_HREF, GetExport().GetRelativeReference(aStr) );
3184 
3185  // export name
3186  xPropSet->getPropertyValue("FrameName") >>= aStr;
3187  if( !aStr.isEmpty() )
3189 
3190  // write floating frame
3191  {
3193  }
3194 
3195 }
3196 
3198  const uno::Reference< drawing::XShape >& xShape,
3199  XMLShapeExportFlags nFeatures, css::awt::Point* pRefPoint)
3200 {
3201  const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
3202  if(!xPropSet.is())
3203  return;
3204 
3205  // Transformation
3206  ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);
3207 
3208  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
3210  XML_FRAME, bCreateNewline, true );
3211 
3212  // export frame url
3213  OUString aStr;
3214  xPropSet->getPropertyValue("AppletCodeBase") >>= aStr;
3215  mrExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_HREF, GetExport().GetRelativeReference(aStr) );
3219 
3220  // export draw:applet-name
3221  xPropSet->getPropertyValue("AppletName") >>= aStr;
3222  if( !aStr.isEmpty() )
3224 
3225  // export draw:code
3226  xPropSet->getPropertyValue("AppletCode") >>= aStr;
3228 
3229  // export draw:may-script
3230  bool bIsScript = false;
3231  xPropSet->getPropertyValue("AppletIsScript") >>= bIsScript;
3233 
3234  {
3235  // write applet
3237 
3238  // export parameters
3239  uno::Sequence< beans::PropertyValue > aCommands;
3240  xPropSet->getPropertyValue("AppletCommands") >>= aCommands;
3241  for( const auto& rCommand : std::as_const(aCommands) )
3242  {
3243  rCommand.Value >>= aStr;
3244  mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_NAME, rCommand.Name );
3246  SvXMLElementExport aElem( mrExport, XML_NAMESPACE_DRAW, XML_PARAM, false, true );
3247  }
3248  }
3249 
3250 }
3251 
3253  const uno::Reference< drawing::XShape >& xShape,
3254  XMLShapeExportFlags nFeatures, css::awt::Point* pRefPoint)
3255 {
3256  const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
3257  if(!xPropSet.is())
3258  return;
3259 
3260  // Transformation
3261  ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);
3262 
3263  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
3265  XML_FRAME, bCreateNewline, true );
3266 
3267  // export plugin url
3268  OUString aStr;
3269  xPropSet->getPropertyValue("PluginURL") >>= aStr;
3270  mrExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_HREF, GetExport().GetRelativeReference(aStr) );
3274 
3275  // export mime-type
3276  xPropSet->getPropertyValue("PluginMimeType") >>= aStr;
3277  if(!aStr.isEmpty())
3279 
3280  {
3281  // write plugin
3283 
3284  // export parameters
3285  uno::Sequence< beans::PropertyValue > aCommands;
3286  xPropSet->getPropertyValue("PluginCommands") >>= aCommands;
3287  for( const auto& rCommand : std::as_const(aCommands) )
3288  {
3289  rCommand.Value >>= aStr;
3290  mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_NAME, rCommand.Name );
3292  SvXMLElementExport aElem( mrExport, XML_NAMESPACE_DRAW, XML_PARAM, false, true );
3293  }
3294  }
3295 
3296 }
3297 
3298 static void lcl_CopyStream(
3299  uno::Reference<io::XInputStream> const& xInStream,
3300  uno::Reference<embed::XStorage> const& xTarget,
3301  OUString const& rPath, const OUString& rMimeType)
3302 {
3304  uno::Reference<io::XStream> const xStream(
3306  embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE, proxy));
3307  uno::Reference<io::XOutputStream> const xOutStream(
3308  (xStream.is()) ? xStream->getOutputStream() : nullptr);
3309  if (!xOutStream.is())
3310  {
3311  SAL_WARN("xmloff", "no output stream");
3312  throw uno::Exception("no output stream",nullptr);
3313  }
3314  uno::Reference< beans::XPropertySet > const xStreamProps(xStream,
3315  uno::UNO_QUERY);
3316  if (xStreamProps.is()) { // this is NOT supported in FileSystemStorage
3317  xStreamProps->setPropertyValue("MediaType",
3318  uno::Any(rMimeType));
3319  xStreamProps->setPropertyValue( // turn off compression
3320  "Compressed",
3321  uno::Any(false));
3322  }
3323  ::comphelper::OStorageHelper::CopyInputToOutput(xInStream, xOutStream);
3324  xOutStream->closeOutput();
3325  proxy.commitStorages();
3326 }
3327 
3328 static OUString
3330  uno::Reference<beans::XPropertySet> const& xPropSet,
3331  OUString const& rURL, const OUString& rMimeType)
3332 {
3333  OUString urlPath;
3334  if (rURL.startsWithIgnoreAsciiCase("vnd.sun.star.Package:", &urlPath))
3335  {
3336  try // video is embedded
3337  {
3338  uno::Reference<embed::XStorage> const xTarget(
3339  rExport.GetTargetStorage(), uno::UNO_SET_THROW);
3340  uno::Reference<io::XInputStream> xInStream;
3341  xPropSet->getPropertyValue("PrivateStream")
3342  >>= xInStream;
3343 
3344  if (!xInStream.is())
3345  {
3346  SAL_WARN("xmloff", "no input stream");
3347  return OUString();
3348  }
3349 
3350  lcl_CopyStream(xInStream, xTarget, rURL, rMimeType);
3351 
3352  return urlPath;
3353  }
3354  catch (uno::Exception const&)
3355  {
3356  TOOLS_INFO_EXCEPTION("xmloff", "exception while storing embedded media");
3357  }
3358  return OUString();
3359  }
3360  else
3361  {
3362  return rExport.GetRelativeReference(rURL); // linked
3363  }
3364 }
3365 
3367  const uno::Reference< drawing::XShape >& xShape,
3368  XmlShapeType eShapeType, XMLShapeExportFlags nFeatures, css::awt::Point* pRefPoint)
3369 {
3370  const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
3371  if(!xPropSet.is())
3372  return;
3373 
3374  // Transformation
3375  ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);
3376 
3377  if(eShapeType == XmlShapeTypePresMediaShape)
3378  {
3380  }
3381  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
3383  XML_FRAME, bCreateNewline, true );
3384 
3385  // export media url
3386  OUString aMediaURL;
3387  xPropSet->getPropertyValue("MediaURL") >>= aMediaURL;
3388  OUString sMimeType;
3389  xPropSet->getPropertyValue("MediaMimeType") >>= sMimeType;
3390 
3391  OUString const persistentURL =
3392  lcl_StoreMediaAndGetURL(GetExport(), xPropSet, aMediaURL, sMimeType);
3393 
3394  mrExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_HREF, persistentURL );
3398 
3399  // export mime-type
3401 
3402  // write plugin
3403  SvXMLElementExport aPluginOBJ(mrExport, XML_NAMESPACE_DRAW, XML_PLUGIN, !( nFeatures & XMLShapeExportFlags::NO_WS ), true);
3404 
3405  // export parameters
3406  const OUString aFalseStr( "false" ), aTrueStr( "true" );
3407 
3408  bool bLoop = false;
3409  static const OUStringLiteral aLoopStr( u"Loop" );
3410  xPropSet->getPropertyValue( aLoopStr ) >>= bLoop;
3413  delete new SvXMLElementExport( mrExport, XML_NAMESPACE_DRAW, XML_PARAM, false, true );
3414 
3415  bool bMute = false;
3416  static const OUStringLiteral aMuteStr( u"Mute" );
3417  xPropSet->getPropertyValue( aMuteStr ) >>= bMute;
3419  mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_VALUE, bMute ? aTrueStr : aFalseStr );
3420  delete new SvXMLElementExport( mrExport, XML_NAMESPACE_DRAW, XML_PARAM, false, true );
3421 
3422  sal_Int16 nVolumeDB = 0;
3423  xPropSet->getPropertyValue("VolumeDB") >>= nVolumeDB;
3425  mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_VALUE, OUString::number( nVolumeDB ) );
3426  delete new SvXMLElementExport( mrExport, XML_NAMESPACE_DRAW, XML_PARAM, false, true );
3427 
3428  media::ZoomLevel eZoom;
3429  OUString aZoomValue;
3430  xPropSet->getPropertyValue("Zoom") >>= eZoom;
3431  switch( eZoom )
3432  {
3433  case media::ZoomLevel_ZOOM_1_TO_4 : aZoomValue = "25%"; break;
3434  case media::ZoomLevel_ZOOM_1_TO_2 : aZoomValue = "50%"; break;
3435  case media::ZoomLevel_ORIGINAL : aZoomValue = "100%"; break;
3436  case media::ZoomLevel_ZOOM_2_TO_1 : aZoomValue = "200%"; break;
3437  case media::ZoomLevel_ZOOM_4_TO_1 : aZoomValue = "400%"; break;
3438  case media::ZoomLevel_FIT_TO_WINDOW: aZoomValue = "fit"; break;
3439  case media::ZoomLevel_FIT_TO_WINDOW_FIXED_ASPECT: aZoomValue = "fixedfit"; break;
3440  case media::ZoomLevel_FULLSCREEN : aZoomValue = "fullscreen"; break;
3441 
3442  default:
3443  break;
3444  }
3445 
3446  if( !aZoomValue.isEmpty() )
3447  {
3450  delete new SvXMLElementExport( mrExport, XML_NAMESPACE_DRAW, XML_PARAM, false, true );
3451  }
3452 
3453 }
3454 
3455 void XMLShapeExport::ImpExport3DSceneShape( const uno::Reference< drawing::XShape >& xShape, XMLShapeExportFlags nFeatures, awt::Point* pRefPoint)
3456 {
3457  uno::Reference< drawing::XShapes > xShapes(xShape, uno::UNO_QUERY);
3458  if(!(xShapes.is() && xShapes->getCount()))
3459  return;
3460 
3461  uno::Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY );
3462  SAL_WARN_IF( !xPropSet.is(), "xmloff", "XMLShapeExport::ImpExport3DSceneShape can't export a scene without a propertyset" );
3463  if( !xPropSet.is() )
3464  return;
3465 
3466  // Transformation
3467  ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);
3468 
3469  // 3d attributes
3470  export3DSceneAttributes( xPropSet );
3471 
3472  // write 3DScene shape
3473  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
3474  SvXMLElementExport aOBJ( mrExport, XML_NAMESPACE_DR3D, XML_SCENE, bCreateNewline, true);
3475 
3476  ImpExportDescription( xShape ); // #i68101#
3477  ImpExportEvents( xShape );
3478 
3479  // write 3DSceneLights
3480  export3DLamps( xPropSet );
3481 
3482  // #89764# if export of position is suppressed for group shape,
3483  // positions of contained objects should be written relative to
3484  // the upper left edge of the group.
3485  awt::Point aUpperLeft;
3486 
3487  if(!(nFeatures & XMLShapeExportFlags::POSITION))
3488  {
3489  nFeatures |= XMLShapeExportFlags::POSITION;
3490  aUpperLeft = xShape->getPosition();
3491  pRefPoint = &aUpperLeft;
3492  }
3493 
3494  // write members
3495  exportShapes( xShapes, nFeatures, pRefPoint );
3496 }
3497 
3499  const uno::Reference< drawing::XShape >& xShape,
3500  XmlShapeType eShapeType)
3501 {
3502  const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
3503  if(!xPropSet.is())
3504  return;
3505 
3506  OUString aStr;
3507  OUStringBuffer sStringBuffer;
3508 
3509  // transformation (UNO_NAME_3D_TRANSFORM_MATRIX == "D3DTransformMatrix")
3510  uno::Any aAny = xPropSet->getPropertyValue("D3DTransformMatrix");
3511  drawing::HomogenMatrix aHomMat;
3512  aAny >>= aHomMat;
3513  SdXMLImExTransform3D aTransform;
3514  aTransform.AddHomogenMatrix(aHomMat);
3515  if(aTransform.NeedsAction())
3517 
3518  switch(eShapeType)
3519  {
3521  {
3522  // minEdge
3523  aAny = xPropSet->getPropertyValue("D3DPosition");
3524  drawing::Position3D aPosition3D;
3525  aAny >>= aPosition3D;
3526  ::basegfx::B3DVector aPos3D(aPosition3D.PositionX, aPosition3D.PositionY, aPosition3D.PositionZ);
3527 
3528  // maxEdge
3529  aAny = xPropSet->getPropertyValue("D3DSize");
3530  drawing::Direction3D aDirection3D;
3531  aAny >>= aDirection3D;
3532  ::basegfx::B3DVector aDir3D(aDirection3D.DirectionX, aDirection3D.DirectionY, aDirection3D.DirectionZ);
3533 
3534  // transform maxEdge from distance to pos
3535  aDir3D = aPos3D + aDir3D;
3536 
3537  // write minEdge
3538  if(aPos3D != ::basegfx::B3DVector(-2500.0, -2500.0, -2500.0)) // write only when not default
3539  {
3540  SvXMLUnitConverter::convertB3DVector(sStringBuffer, aPos3D);
3541  aStr = sStringBuffer.makeStringAndClear();
3543  }
3544 
3545  // write maxEdge
3546  if(aDir3D != ::basegfx::B3DVector(2500.0, 2500.0, 2500.0)) // write only when not default
3547  {
3548  SvXMLUnitConverter::convertB3DVector(sStringBuffer, aDir3D);
3549  aStr = sStringBuffer.makeStringAndClear();
3551  }
3552 
3553  // write 3DCube shape
3554  // #i123542# Do this *after* the attributes are added, else these will be lost since opening
3555  // the scope will clear the global attribute list at the exporter
3557 
3558  break;
3559  }
3561  {
3562  // Center
3563  aAny = xPropSet->getPropertyValue("D3DPosition");
3564  drawing::Position3D aPosition3D;
3565  aAny >>= aPosition3D;
3566  ::basegfx::B3DVector aPos3D(aPosition3D.PositionX, aPosition3D.PositionY, aPosition3D.PositionZ);
3567 
3568  // Size
3569  aAny = xPropSet->getPropertyValue("D3DSize");
3570  drawing::Direction3D aDirection3D;
3571  aAny >>= aDirection3D;
3572  ::basegfx::B3DVector aDir3D(aDirection3D.DirectionX, aDirection3D.DirectionY, aDirection3D.DirectionZ);
3573 
3574  // write Center
3575  if(aPos3D != ::basegfx::B3DVector(0.0, 0.0, 0.0)) // write only when not default
3576  {
3577  SvXMLUnitConverter::convertB3DVector(sStringBuffer, aPos3D);
3578  aStr = sStringBuffer.makeStringAndClear();
3580  }
3581 
3582  // write Size
3583  if(aDir3D != ::basegfx::B3DVector(5000.0, 5000.0, 5000.0)) // write only when not default
3584  {
3585  SvXMLUnitConverter::convertB3DVector(sStringBuffer, aDir3D);
3586  aStr = sStringBuffer.makeStringAndClear();
3588  }
3589 
3590  // write 3DSphere shape
3591  // #i123542# Do this *after* the attributes are added, else these will be lost since opening
3592  // the scope will clear the global attribute list at the exporter
3594 
3595  break;
3596  }
3599  {
3600  // write special 3DLathe/3DExtrude attributes, get 3D tools::PolyPolygon as drawing::PolyPolygonShape3D
3601  aAny = xPropSet->getPropertyValue("D3DPolyPolygon3D");
3602  drawing::PolyPolygonShape3D aUnoPolyPolygon3D;
3603  aAny >>= aUnoPolyPolygon3D;
3604 
3605  // convert to 3D PolyPolygon
3606  const basegfx::B3DPolyPolygon aPolyPolygon3D(
3608  aUnoPolyPolygon3D));
3609 
3610  // convert to 2D tools::PolyPolygon using identity 3D transformation (just grep X and Y)
3611  const basegfx::B3DHomMatrix aB3DHomMatrixFor2DConversion;
3612  const basegfx::B2DPolyPolygon aPolyPolygon(
3614  aPolyPolygon3D,
3615  aB3DHomMatrixFor2DConversion));
3616 
3617  // get 2D range of it
3618  const basegfx::B2DRange aPolyPolygonRange(aPolyPolygon.getB2DRange());
3619 
3620  // export ViewBox
3621  SdXMLImExViewBox aViewBox(
3622  aPolyPolygonRange.getMinX(),
3623  aPolyPolygonRange.getMinY(),
3624  aPolyPolygonRange.getWidth(),
3625  aPolyPolygonRange.getHeight());
3626 
3627  mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_VIEWBOX, aViewBox.GetExportString());
3628 
3629  // prepare svg:d string
3630  const OUString aPolygonString(
3632  aPolyPolygon,
3633  true, // bUseRelativeCoordinates
3634  false, // bDetectQuadraticBeziers TTTT: not used in old, but maybe activated now
3635  true)); // bHandleRelativeNextPointCompatible
3636 
3637  // write point array
3638  mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_D, aPolygonString);
3639 
3640  if(eShapeType == XmlShapeTypeDraw3DLatheObject)
3641  {
3642  // write 3DLathe shape
3644  }
3645  else
3646  {
3647  // write 3DExtrude shape
3649  }
3650  break;
3651  }
3652  default:
3653  break;
3654  }
3655 }
3656 
3658 void XMLShapeExport::export3DSceneAttributes( const css::uno::Reference< css::beans::XPropertySet >& xPropSet )
3659 {
3660  OUString aStr;
3661  OUStringBuffer sStringBuffer;
3662 
3663  // world transformation (UNO_NAME_3D_TRANSFORM_MATRIX == "D3DTransformMatrix")
3664  uno::Any aAny = xPropSet->getPropertyValue("D3DTransformMatrix");
3665  drawing::HomogenMatrix aHomMat;
3666  aAny >>= aHomMat;
3667  SdXMLImExTransform3D aTransform;
3668  aTransform.AddHomogenMatrix(aHomMat);
3669  if(aTransform.NeedsAction())
3671 
3672  // VRP, VPN, VUP
3673  aAny = xPropSet->getPropertyValue("D3DCameraGeometry");
3674  drawing::CameraGeometry aCamGeo;
3675  aAny >>= aCamGeo;
3676 
3677  ::basegfx::B3DVector aVRP(aCamGeo.vrp.PositionX, aCamGeo.vrp.PositionY, aCamGeo.vrp.PositionZ);
3678  if(aVRP != ::basegfx::B3DVector(0.0, 0.0, 1.0)) // write only when not default
3679  {
3680  SvXMLUnitConverter::convertB3DVector(sStringBuffer, aVRP);
3681  aStr = sStringBuffer.makeStringAndClear();
3683  }
3684 
3685  ::basegfx::B3DVector aVPN(aCamGeo.vpn.DirectionX, aCamGeo.vpn.DirectionY, aCamGeo.vpn.DirectionZ);
3686  if(aVPN != ::basegfx::B3DVector(0.0, 0.0, 1.0)) // write only when not default
3687  {
3688  SvXMLUnitConverter::convertB3DVector(sStringBuffer, aVPN);
3689  aStr = sStringBuffer.makeStringAndClear();
3691  }
3692 
3693  ::basegfx::B3DVector aVUP(aCamGeo.vup.DirectionX, aCamGeo.vup.DirectionY, aCamGeo.vup.DirectionZ);
3694  if(aVUP != ::basegfx::B3DVector(0.0, 1.0, 0.0)) // write only when not default
3695  {
3696  SvXMLUnitConverter::convertB3DVector(sStringBuffer, aVUP);
3697  aStr = sStringBuffer.makeStringAndClear();
3699  }
3700 
3701  // projection "D3DScenePerspective" drawing::ProjectionMode
3702  aAny = xPropSet->getPropertyValue("D3DScenePerspective");
3703  drawing::ProjectionMode aPrjMode;
3704  aAny >>= aPrjMode;
3705  if(aPrjMode == drawing::ProjectionMode_PARALLEL)
3706  aStr = GetXMLToken(XML_PARALLEL);
3707  else
3708  aStr = GetXMLToken(XML_PERSPECTIVE);
3710 
3711  // distance
3712  aAny = xPropSet->getPropertyValue("D3DSceneDistance");
3713  sal_Int32 nDistance = 0;
3714  aAny >>= nDistance;
3716  nDistance);
3717  aStr = sStringBuffer.makeStringAndClear();
3719 
3720  // focalLength
3721  aAny = xPropSet->getPropertyValue("D3DSceneFocalLength");
3722  sal_Int32 nFocalLength = 0;
3723  aAny >>= nFocalLength;
3725  nFocalLength);
3726  aStr = sStringBuffer.makeStringAndClear();
3728 
3729  // shadowSlant
3730  aAny = xPropSet->getPropertyValue("D3DSceneShadowSlant");
3731  sal_Int16 nShadowSlant = 0;
3732  aAny >>= nShadowSlant;
3733  mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_SHADOW_SLANT, OUString::number(static_cast<sal_Int32>(nShadowSlant)));
3734 
3735  // shadeMode
3736  aAny = xPropSet->getPropertyValue("D3DSceneShadeMode");
3737  drawing::ShadeMode aShadeMode;
3738  if(aAny >>= aShadeMode)
3739  {
3740  if(aShadeMode == drawing::ShadeMode_FLAT)
3741  aStr = GetXMLToken(XML_FLAT);
3742  else if(aShadeMode == drawing::ShadeMode_PHONG)
3743  aStr = GetXMLToken(XML_PHONG);
3744  else if(aShadeMode == drawing::ShadeMode_SMOOTH)
3745  aStr = GetXMLToken(XML_GOURAUD);
3746  else
3747  aStr = GetXMLToken(XML_DRAFT);
3748  }
3749  else
3750  {
3751  // ShadeMode enum not there, write default
3752  aStr = GetXMLToken(XML_GOURAUD);
3753  }
3755 
3756  // ambientColor
3757  aAny = xPropSet->getPropertyValue("D3DSceneAmbientColor");
3758  sal_Int32 nAmbientColor = 0;
3759  aAny >>= nAmbientColor;
3760  ::sax::Converter::convertColor(sStringBuffer, nAmbientColor);
3761  aStr = sStringBuffer.makeStringAndClear();
3763 
3764  // lightingMode
3765  aAny = xPropSet->getPropertyValue("D3DSceneTwoSidedLighting");
3766  bool bTwoSidedLighting = false;
3767  aAny >>= bTwoSidedLighting;
3768  ::sax::Converter::convertBool(sStringBuffer, bTwoSidedLighting);
3769  aStr = sStringBuffer.makeStringAndClear();
3771 }
3772 
3774 void XMLShapeExport::export3DLamps( const css::uno::Reference< css::beans::XPropertySet >& xPropSet )
3775 {
3776  // write lamps 1..8 as content
3777  OUString aStr;
3778  OUStringBuffer sStringBuffer;
3779 
3780  static const OUStringLiteral aColorPropName(u"D3DSceneLightColor");
3781  static const OUStringLiteral aDirectionPropName(u"D3DSceneLightDirection");
3782  static const OUStringLiteral aLightOnPropName(u"D3DSceneLightOn");
3783 
3784  ::basegfx::B3DVector aLightDirection;
3785  drawing::Direction3D aLightDir;
3786  bool bLightOnOff = false;
3787  for(sal_Int32 nLamp = 1; nLamp <= 8; nLamp++)
3788  {
3789  OUString aIndexStr = OUString::number( nLamp );
3790 
3791  // lightcolor
3792  OUString aPropName = aColorPropName + aIndexStr;
3793  sal_Int32 nLightColor = 0;
3794  xPropSet->getPropertyValue( aPropName ) >>= nLightColor;
3795  ::sax::Converter::convertColor(sStringBuffer, nLightColor);
3796  aStr = sStringBuffer.makeStringAndClear();
3798 
3799  // lightdirection
3800  aPropName = aDirectionPropName + aIndexStr;
3801  xPropSet->getPropertyValue(aPropName) >>= aLightDir;
3802  aLightDirection = ::basegfx::B3DVector(aLightDir.DirectionX, aLightDir.DirectionY, aLightDir.DirectionZ);
3803  SvXMLUnitConverter::convertB3DVector(sStringBuffer, aLightDirection);
3804  aStr = sStringBuffer.makeStringAndClear();
3806 
3807  // lighton
3808  aPropName = aLightOnPropName + aIndexStr;
3809  xPropSet->getPropertyValue(aPropName) >>= bLightOnOff;
3810  ::sax::Converter::convertBool(sStringBuffer, bLightOnOff);
3811  aStr = sStringBuffer.makeStringAndClear();
3813 
3814  // specular
3816  nLamp == 1 ? XML_TRUE : XML_FALSE);
3817 
3818  // write light entry
3820  }
3821 }
3822 
3823 
3824 // using namespace css::io;
3825 // using namespace ::xmloff::EnhancedCustomShapeToken;
3826 
3827 
3828 static void ExportParameter( OUStringBuffer& rStrBuffer, const css::drawing::EnhancedCustomShapeParameter& rParameter )
3829 {
3830  if ( !rStrBuffer.isEmpty() )
3831  rStrBuffer.append( ' ' );
3832  if ( rParameter.Value.getValueTypeClass() == uno::TypeClass_DOUBLE )
3833  {
3834  double fNumber = 0.0;
3835  rParameter.Value >>= fNumber;
3836  ::rtl::math::doubleToUStringBuffer( rStrBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true );
3837  }
3838  else
3839  {
3840  sal_Int32 nValue = 0;
3841  rParameter.Value >>= nValue;
3842 
3843  switch( rParameter.Type )
3844  {
3845  case css::drawing::EnhancedCustomShapeParameterType::EQUATION :
3846  {
3847  rStrBuffer.append( "?f" + OUString::number( nValue ) );
3848  }
3849  break;
3850 
3851  case css::drawing::EnhancedCustomShapeParameterType::ADJUSTMENT :
3852  {
3853  rStrBuffer.append( '$' );
3854  rStrBuffer.append( nValue );
3855  }
3856  break;
3857 
3858  case css::drawing::EnhancedCustomShapeParameterType::BOTTOM :
3859  rStrBuffer.append( GetXMLToken( XML_BOTTOM ) ); break;
3860  case css::drawing::EnhancedCustomShapeParameterType::RIGHT :
3861  rStrBuffer.append( GetXMLToken( XML_RIGHT ) ); break;
3862  case css::drawing::EnhancedCustomShapeParameterType::TOP :
3863  rStrBuffer.append( GetXMLToken( XML_TOP ) ); break;
3864  case css::drawing::EnhancedCustomShapeParameterType::LEFT :
3865  rStrBuffer.append( GetXMLToken( XML_LEFT ) ); break;
3866  case css::drawing::EnhancedCustomShapeParameterType::XSTRETCH :
3867  rStrBuffer.append( GetXMLToken( XML_XSTRETCH ) ); break;
3868  case css::drawing::EnhancedCustomShapeParameterType::YSTRETCH :
3869  rStrBuffer.append( GetXMLToken( XML_YSTRETCH ) ); break;
3870  case css::drawing::EnhancedCustomShapeParameterType::HASSTROKE :
3871  rStrBuffer.append( GetXMLToken( XML_HASSTROKE ) ); break;
3872  case css::drawing::EnhancedCustomShapeParameterType::HASFILL :
3873  rStrBuffer.append( GetXMLToken( XML_HASFILL ) ); break;
3874  case css::drawing::EnhancedCustomShapeParameterType::WIDTH :
3875  rStrBuffer.append( GetXMLToken( XML_WIDTH ) ); break;
3876  case css::drawing::EnhancedCustomShapeParameterType::HEIGHT :
3877  rStrBuffer.append( GetXMLToken( XML_HEIGHT ) ); break;
3878  case css::drawing::EnhancedCustomShapeParameterType::LOGWIDTH :
3879  rStrBuffer.append( GetXMLToken( XML_LOGWIDTH ) ); break;
3880  case css::drawing::EnhancedCustomShapeParameterType::LOGHEIGHT :
3881  rStrBuffer.append( GetXMLToken( XML_LOGHEIGHT ) ); break;
3882  default :
3883  rStrBuffer.append( nValue );
3884  }
3885  }
3886 }
3887 
3888 static void ImpExportEquations( SvXMLExport& rExport, const uno::Sequence< OUString >& rEquations )
3889 {
3890  sal_Int32 i;
3891  for ( i = 0; i < rEquations.getLength(); i++ )
3892  {
3893  OUString aStr= "f" + OUString::number( i );
3894  rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_NAME, aStr );
3895 
3896  aStr = rEquations[ i ];
3897  sal_Int32 nIndex = 0;
3898  do
3899  {
3900  nIndex = aStr.indexOf( '?', nIndex );
3901  if ( nIndex != -1 )
3902  {
3903  aStr = OUString::Concat(aStr.subView(0, nIndex + 1)) + "f"
3904  + aStr.subView(nIndex + 1, aStr.getLength() - nIndex - 1);
3905  nIndex++;
3906  }
3907  } while( nIndex != -1 );
3908  rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_FORMULA, aStr );
3909  SvXMLElementExport aOBJ( rExport, XML_NAMESPACE_DRAW, XML_EQUATION, true, true );
3910  }
3911 }
3912 
3913 static void ImpExportHandles( SvXMLExport& rExport, const uno::Sequence< beans::PropertyValues >& rHandles )
3914 {
3915  if ( !rHandles.hasElements() )
3916  return;
3917 
3918  OUString aStr;
3919  OUStringBuffer aStrBuffer;
3920 
3921  for ( const uno::Sequence< beans::PropertyValue >& rPropSeq : rHandles )
3922  {
3923  bool bPosition = false;
3924  for ( const beans::PropertyValue& rPropVal : rPropSeq )
3925  {
3926  switch( EASGet( rPropVal.Name ) )
3927  {
3928  case EAS_Position :
3929  {
3930  css::drawing::EnhancedCustomShapeParameterPair aPosition;
3931  if ( rPropVal.Value >>= aPosition )
3932  {
3933  ExportParameter( aStrBuffer, aPosition.First );
3934  ExportParameter( aStrBuffer, aPosition.Second );
3935  aStr = aStrBuffer.makeStringAndClear();
3937  bPosition = true;
3938  }
3939  }
3940  break;
3941  case EAS_MirroredX :
3942  {
3943  bool bMirroredX;
3944  if ( rPropVal.Value >>= bMirroredX )
3946  bMirroredX ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
3947  }
3948  break;
3949  case EAS_MirroredY :
3950  {
3951  bool bMirroredY;
3952  if ( rPropVal.Value >>= bMirroredY )
3954  bMirroredY ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
3955  }
3956  break;
3957  case EAS_Switched :
3958  {
3959  bool bSwitched;
3960  if ( rPropVal.Value >>= bSwitched )
3962  bSwitched ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
3963  }
3964  break;
3965  case EAS_Polar :
3966  {
3967  css::drawing::EnhancedCustomShapeParameterPair aPolar;
3968  if ( rPropVal.Value >>= aPolar )
3969  {
3970  ExportParameter( aStrBuffer, aPolar.First );
3971  ExportParameter( aStrBuffer, aPolar.Second );
3972  aStr = aStrBuffer.makeStringAndClear();
3974  }
3975  }
3976  break;
3977  case EAS_RadiusRangeMinimum :
3978  {
3979  css::drawing::EnhancedCustomShapeParameter aRadiusRangeMinimum;
3980  if ( rPropVal.Value >>= aRadiusRangeMinimum )
3981  {
3982  ExportParameter( aStrBuffer, aRadiusRangeMinimum );
3983  aStr = aStrBuffer.makeStringAndClear();
3985  }
3986  }
3987  break;
3988  case EAS_RadiusRangeMaximum :
3989  {
3990  css::drawing::EnhancedCustomShapeParameter aRadiusRangeMaximum;
3991  if ( rPropVal.Value >>= aRadiusRangeMaximum )
3992  {
3993  ExportParameter( aStrBuffer, aRadiusRangeMaximum );
3994  aStr = aStrBuffer.makeStringAndClear();
3996  }
3997  }
3998  break;
3999  case EAS_RangeXMinimum :
4000  {
4001  css::drawing::EnhancedCustomShapeParameter aXRangeMinimum;
4002  if ( rPropVal.Value >>= aXRangeMinimum )
4003  {
4004  ExportParameter( aStrBuffer, aXRangeMinimum );
4005  aStr = aStrBuffer.makeStringAndClear();
4007  }
4008  }
4009  break;
4010  case EAS_RangeXMaximum :
4011  {
4012  css::drawing::EnhancedCustomShapeParameter aXRangeMaximum;
4013  if ( rPropVal.Value >>= aXRangeMaximum )
4014  {
4015  ExportParameter( aStrBuffer, aXRangeMaximum );
4016  aStr = aStrBuffer.makeStringAndClear();
4018  }
4019  }
4020  break;
4021  case EAS_RangeYMinimum :
4022  {
4023  css::drawing::EnhancedCustomShapeParameter aYRangeMinimum;
4024  if ( rPropVal.Value >>= aYRangeMinimum )
4025  {
4026  ExportParameter( aStrBuffer, aYRangeMinimum );
4027  aStr = aStrBuffer.makeStringAndClear();
4029  }
4030  }
4031  break;
4032  case EAS_RangeYMaximum :
4033  {
4034  css::drawing::EnhancedCustomShapeParameter aYRangeMaximum;
4035  if ( rPropVal.Value >>= aYRangeMaximum )
4036  {
4037  ExportParameter( aStrBuffer, aYRangeMaximum );
4038  aStr = aStrBuffer.makeStringAndClear();
4040  }
4041  }
4042  break;
4043  default:
4044  break;
4045  }
4046  }
4047  if ( bPosition )
4048  SvXMLElementExport aOBJ( rExport, XML_NAMESPACE_DRAW, XML_HANDLE, true, true );
4049  else
4050  rExport.ClearAttrList();
4051  }
4052 }
4053 
4054 static void ImpExportEnhancedPath( SvXMLExport& rExport,
4055  const uno::Sequence< css::drawing::EnhancedCustomShapeParameterPair >& rCoordinates,
4056  const uno::Sequence< css::drawing::EnhancedCustomShapeSegment >& rSegments,
4057  bool bExtended = false )
4058 {
4059 
4060  OUString aStr;
4061  OUStringBuffer aStrBuffer;
4062  bool bNeedExtended = false;
4063 
4064  sal_Int32 i, j, k, l;
4065 
4066  sal_Int32 nCoords = rCoordinates.getLength();
4067  sal_Int32 nSegments = rSegments.getLength();
4068  bool bSimpleSegments = nSegments == 0;
4069  if ( bSimpleSegments )
4070  nSegments = 4;
4071  for ( j = i = 0; j < nSegments; j++ )
4072  {
4073  css::drawing::EnhancedCustomShapeSegment aSegment;
4074  if ( bSimpleSegments )
4075  {
4076  // if there are not enough segments we will default them
4077  switch( j )
4078  {
4079  case 0 :
4080  {
4081  aSegment.Count = 1;
4082  aSegment.Command = css::drawing::EnhancedCustomShapeSegmentCommand::MOVETO;
4083  }
4084  break;
4085  case 1 :
4086  {
4087  aSegment.Count = static_cast<sal_Int16>(std::min( nCoords - 1, sal_Int32(32767) ));
4088  aSegment.Command = css::drawing::EnhancedCustomShapeSegmentCommand::LINETO;
4089  }
4090  break;
4091  case 2 :
4092  {
4093  aSegment.Count = 1;
4094  aSegment.Command = css::drawing::EnhancedCustomShapeSegmentCommand::CLOSESUBPATH;
4095  }
4096  break;
4097  case 3 :
4098  {
4099  aSegment.Count = 1;
4100  aSegment.Command = css::drawing::EnhancedCustomShapeSegmentCommand::ENDSUBPATH;
4101  }
4102  break;
4103  }
4104  }
4105  else
4106  aSegment = rSegments[ j ];
4107 
4108  if ( !aStrBuffer.isEmpty() )
4109  aStrBuffer.append( ' ' );
4110 
4111  sal_Int32 nParameter = 0;
4112  switch( aSegment.Command )
4113  {
4114  case css::drawing::EnhancedCustomShapeSegmentCommand::CLOSESUBPATH :
4115  aStrBuffer.append( 'Z' ); break;
4116  case css::drawing::EnhancedCustomShapeSegmentCommand::ENDSUBPATH :
4117  aStrBuffer.append( 'N' ); break;
4118  case css::drawing::EnhancedCustomShapeSegmentCommand::NOFILL :
4119  aStrBuffer.append( 'F' ); break;
4120  case css::drawing::EnhancedCustomShapeSegmentCommand::NOSTROKE :
4121  aStrBuffer.append( 'S' ); break;
4122 
4123  case css::drawing::EnhancedCustomShapeSegmentCommand::MOVETO :
4124  aStrBuffer.append( 'M' ); nParameter = 1; break;
4125  case css::drawing::EnhancedCustomShapeSegmentCommand::LINETO :
4126  aStrBuffer.append( 'L' ); nParameter = 1; break;
4127  case css::drawing::EnhancedCustomShapeSegmentCommand::CURVETO :
4128  aStrBuffer.append( 'C' ); nParameter = 3; break;
4129  case css::drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO :
4130  aStrBuffer.append( 'T' ); nParameter = 3; break;
4131  case css::drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE :
4132  aStrBuffer.append( 'U' ); nParameter = 3; break;
4133  case css::drawing::EnhancedCustomShapeSegmentCommand::ARCTO :
4134  aStrBuffer.append( 'A' ); nParameter = 4; break;
4135  case css::drawing::EnhancedCustomShapeSegmentCommand::ARC :
4136  aStrBuffer.append( 'B' ); nParameter = 4; break;
4137  case css::drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO :
4138  aStrBuffer.append( 'W' ); nParameter = 4; break;
4139  case css::drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARC :
4140  aStrBuffer.append( 'V' ); nParameter = 4; break;
4141  case css::drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX :
4142  aStrBuffer.append( 'X' ); nParameter = 1; break;
4143  case css::drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY :
4144  aStrBuffer.append( 'Y' ); nParameter = 1; break;
4145  case css::drawing::EnhancedCustomShapeSegmentCommand::QUADRATICCURVETO :
4146  aStrBuffer.append( 'Q' ); nParameter = 2; break;
4147  case css::drawing::EnhancedCustomShapeSegmentCommand::ARCANGLETO :
4148  if ( bExtended ) {
4149  aStrBuffer.append( 'G' );
4150  nParameter = 2;
4151  } else {
4152  aStrBuffer.setLength( aStrBuffer.getLength() - 1);
4153  bNeedExtended = true;
4154  i += 2;
4155  }
4156  break;
4157  case css::drawing::EnhancedCustomShapeSegmentCommand::DARKEN :
4158  if ( bExtended )
4159  aStrBuffer.append( 'H' );
4160  else
4161  bNeedExtended = true;
4162  break;
4163  case css::drawing::EnhancedCustomShapeSegmentCommand::DARKENLESS :
4164  if ( bExtended )
4165  aStrBuffer.append( 'I' );
4166  else
4167  bNeedExtended = true;
4168  break;
4169  case css::drawing::EnhancedCustomShapeSegmentCommand::LIGHTEN :
4170  if ( bExtended )
4171  aStrBuffer.append( 'J' );
4172  else
4173  bNeedExtended = true;
4174  break;
4175  case css::drawing::EnhancedCustomShapeSegmentCommand::LIGHTENLESS :
4176  if ( bExtended )
4177  aStrBuffer.append( 'K' );
4178  else
4179  bNeedExtended = true;
4180  break;
4181  default : // ups, seems to be something wrong
4182  {
4183  aSegment.Count = 1;
4184  aSegment.Command = css::drawing::EnhancedCustomShapeSegmentCommand::LINETO;
4185  }
4186  break;
4187  }
4188  if ( nParameter )
4189  {
4190  for ( k = 0; k < aSegment.Count; k++ )
4191  {
4192  if ( ( i + nParameter ) <= nCoords )
4193  {
4194  for ( l = 0; l < nParameter; l++ )
4195  {
4196  ExportParameter( aStrBuffer, rCoordinates[ i ].First );
4197  ExportParameter( aStrBuffer, rCoordinates[ i++ ].Second );
4198  }
4199  }
4200  else
4201  {
4202  j = nSegments; // error -> exiting
4203  break;
4204  }
4205  }
4206  }
4207  }
4208  aStr = aStrBuffer.makeStringAndClear();
4210  if (!bExtended && bNeedExtended && (rExport.getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED))
4211  ImpExportEnhancedPath( rExport, rCoordinates, rSegments, true );
4212 }
4213 
4214 static void ImpExportEnhancedGeometry( SvXMLExport& rExport, const uno::Reference< beans::XPropertySet >& xPropSet )
4215 {
4216  bool bEquations = false;
4217  uno::Sequence< OUString > aEquations;
4218 
4219  bool bHandles = false;
4220  uno::Sequence< beans::PropertyValues > aHandles;
4221 
4222  uno::Sequence< css::drawing::EnhancedCustomShapeSegment > aSegments;
4223  uno::Sequence< css::drawing::EnhancedCustomShapeParameterPair > aCoordinates;
4224 
4225  uno::Sequence< css::drawing::EnhancedCustomShapeAdjustmentValue > aAdjustmentValues;
4226 
4227  OUString aStr;
4228  OUStringBuffer aStrBuffer;
4229  SvXMLUnitConverter& rUnitConverter = rExport.GetMM100UnitConverter();
4230 
4231  uno::Reference< beans::XPropertySetInfo > xPropSetInfo( xPropSet->getPropertySetInfo() );
4232 
4233  // geometry
4234  static const OUStringLiteral sCustomShapeGeometry( u"CustomShapeGeometry" );
4235  if ( xPropSetInfo.is() && xPropSetInfo->hasPropertyByName( sCustomShapeGeometry ) )
4236  {
4237  uno::Any aGeoPropSet( xPropSet->getPropertyValue( sCustomShapeGeometry ) );
4238  uno::Sequence< beans::PropertyValue > aGeoPropSeq;
4239 
4240  if ( aGeoPropSet >>= aGeoPropSeq )
4241  {
4242  bool bCoordinates = false;
4243  OUString aCustomShapeType( "non-primitive" );
4244 
4245  for ( const beans::PropertyValue& rGeoProp : std::as_const(aGeoPropSeq) )
4246  {
4247  switch( EASGet( rGeoProp.Name ) )
4248  {
4249  case EAS_Type :
4250  {
4251  rGeoProp.Value >>= aCustomShapeType;
4252  }
4253  break;
4254  case EAS_MirroredX :
4255  {
4256  bool bMirroredX;
4257  if ( rGeoProp.Value >>= bMirroredX )
4259  bMirroredX ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
4260  }
4261  break;
4262  case EAS_MirroredY :
4263  {
4264  bool bMirroredY;
4265  if ( rGeoProp.Value >>= bMirroredY )
4267  bMirroredY ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
4268  }
4269  break;
4270  case EAS_ViewBox :
4271  {
4272  awt::Rectangle aRect;
4273  if ( rGeoProp.Value >>= aRect )
4274  {
4275  SdXMLImExViewBox aViewBox( aRect.X, aRect.Y, aRect.Width, aRect.Height );
4277  }
4278  }
4279  break;
4280  case EAS_TextPreRotateAngle :
4281  case EAS_TextRotateAngle :
4282  {
4283  double fTextRotateAngle = 0;
4284  if ( ( rGeoProp.Value >>= fTextRotateAngle ) && fTextRotateAngle != 0 )
4285  {
4287  aStrBuffer, fTextRotateAngle );
4288  aStr = aStrBuffer.makeStringAndClear();
4290  }
4291  }
4292  break;
4293  case EAS_Extrusion :
4294  {
4295  uno::Sequence< beans::PropertyValue > aExtrusionPropSeq;
4296  if ( rGeoProp.Value >>= aExtrusionPropSeq )
4297  {
4298  bool bSkewValuesProvided = false;
4299  for ( const beans::PropertyValue& rProp : std::as_const(aExtrusionPropSeq) )
4300  {
4301  switch( EASGet( rProp.Name ) )
4302  {
4303  case EAS_Extrusion :
4304  {
4305  bool bExtrusionOn;
4306  if ( rProp.Value >>= bExtrusionOn )
4308  bExtrusionOn ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
4309  }
4310  break;
4311  case EAS_Brightness :
4312  {
4313  double fExtrusionBrightness = 0;
4314  if ( rProp.Value >>= fExtrusionBrightness )
4315  {
4317  aStrBuffer,
4318  fExtrusionBrightness,
4319  false,
4320  util::MeasureUnit::PERCENT,
4321  util::MeasureUnit::PERCENT);
4322  aStrBuffer.append( '%' );
4323  aStr = aStrBuffer.makeStringAndClear();
4325  }
4326  }
4327  break;
4328  case EAS_Depth :
4329  {
4330  css::drawing::EnhancedCustomShapeParameterPair aDepthParaPair;
4331  if ( rProp.Value >>= aDepthParaPair )
4332  {
4333  double fDepth = 0;
4334  if ( aDepthParaPair.First.Value >>= fDepth )
4335  {
4336  rExport.GetMM100UnitConverter().convertDouble( aStrBuffer, fDepth );
4337  ExportParameter( aStrBuffer, aDepthParaPair.Second );
4338  aStr = aStrBuffer.makeStringAndClear();
4340  }
4341  }
4342  }
4343  break;
4344  case EAS_Diffusion :
4345  {
4346  double fExtrusionDiffusion = 0;
4347  if ( rProp.Value >>= fExtrusionDiffusion )
4348  {
4350  aStrBuffer,
4351  fExtrusionDiffusion,
4352  false,
4353  util::MeasureUnit::PERCENT,
4354  util::MeasureUnit::PERCENT);
4355  aStrBuffer.append( '%' );
4356  aStr = aStrBuffer.makeStringAndClear();
4358  }
4359  }
4360  break;
4362  {
4363  sal_Int32 nExtrusionNumberOfLineSegments = 0;
4364  if ( rProp.Value >>= nExtrusionNumberOfLineSegments )
4365  rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_EXTRUSION_NUMBER_OF_LINE_SEGMENTS, OUString::number( nExtrusionNumberOfLineSegments ) );
4366  }
4367  break;
4368  case EAS_LightFace :
4369  {
4370  bool bExtrusionLightFace;
4371  if ( rProp.Value >>= bExtrusionLightFace )
4373  bExtrusionLightFace ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
4374  }
4375  break;
4376  case EAS_FirstLightHarsh :
4377  {
4378  bool bExtrusionFirstLightHarsh;
4379  if ( rProp.Value >>= bExtrusionFirstLightHarsh )
4381  bExtrusionFirstLightHarsh ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
4382  }
4383  break;
4384  case EAS_SecondLightHarsh :
4385  {
4386  bool bExtrusionSecondLightHarsh;
4387  if ( rProp.Value >>= bExtrusionSecondLightHarsh )
4389  bExtrusionSecondLightHarsh ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
4390  }
4391  break;
4392  case EAS_FirstLightLevel :
4393  {
4394  double fExtrusionFirstLightLevel = 0;
4395  if ( rProp.Value >>= fExtrusionFirstLightLevel )
4396  {
4398  aStrBuffer,
4399  fExtrusionFirstLightLevel,
4400  false,
4401  util::MeasureUnit::PERCENT,
4402  util::MeasureUnit::PERCENT);
4403  aStrBuffer.append( '%' );
4404  aStr = aStrBuffer.makeStringAndClear();
4406  }
4407  }
4408  break;
4409  case EAS_SecondLightLevel :
4410  {
4411  double fExtrusionSecondLightLevel = 0;
4412  if ( rProp.Value >>= fExtrusionSecondLightLevel )
4413  {
4415  aStrBuffer,
4416  fExtrusionSecondLightLevel,
4417  false,
4418  util::MeasureUnit::PERCENT,
4419  util::MeasureUnit::PERCENT);
4420  aStrBuffer.append( '%' );
4421  aStr = aStrBuffer.makeStringAndClear();
4423  }
4424  }
4425  break;
4427  {
4428  drawing::Direction3D aExtrusionFirstLightDirection;
4429  if ( rProp.Value >>= aExtrusionFirstLightDirection )
4430  {
4431  ::basegfx::B3DVector aVec3D( aExtrusionFirstLightDirection.DirectionX, aExtrusionFirstLightDirection.DirectionY,
4432  aExtrusionFirstLightDirection.DirectionZ );
4433  SvXMLUnitConverter::convertB3DVector( aStrBuffer, aVec3D );
4434  aStr = aStrBuffer.makeStringAndClear();
4436  }
4437  }
4438  break;
4440  {
4441  drawing::Direction3D aExtrusionSecondLightDirection;
4442  if ( rProp.Value >>= aExtrusionSecondLightDirection )
4443  {
4444  ::basegfx::B3DVector aVec3D( aExtrusionSecondLightDirection.DirectionX, aExtrusionSecondLightDirection.DirectionY,
4445  aExtrusionSecondLightDirection.DirectionZ );
4446  SvXMLUnitConverter::convertB3DVector( aStrBuffer, aVec3D );
4447  aStr = aStrBuffer.makeStringAndClear();
4449  }
4450  }
4451  break;
4452  case EAS_Metal :
4453  {
4454  bool bExtrusionMetal;
4455  if ( rProp.Value >>= bExtrusionMetal )
4457  bExtrusionMetal ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
4458  }
4459  break;
4460  case EAS_MetalType :
4461  {
4462  // export only if ODF extensions are enabled
4463  sal_Int16 eMetalType;
4464  if (rProp.Value >>= eMetalType)
4465  {
4467  if (eVersion > SvtSaveOptions::ODFSVER_013
4468  && (eVersion & SvtSaveOptions::ODFSVER_EXTENDED))
4469  {
4470  if (eMetalType == drawing::EnhancedCustomShapeMetalType::MetalMSCompatible)
4471  aStr = "loext:MetalMSCompatible";
4472  else
4473  aStr = "draw:MetalODF";
4475  }
4476  }
4477  }
4478  break;
4479  case EAS_ShadeMode :
4480  {
4481  // shadeMode
4482  drawing::ShadeMode eShadeMode;
4483  if( rProp.Value >>= eShadeMode )
4484  {
4485  if( eShadeMode == drawing::ShadeMode_FLAT )
4486  aStr = GetXMLToken( XML_FLAT );
4487  else if( eShadeMode == drawing::ShadeMode_PHONG )
4488  aStr = GetXMLToken( XML_PHONG );
4489  else if( eShadeMode == drawing::ShadeMode_SMOOTH )
4490  aStr = GetXMLToken( XML_GOURAUD );
4491  else
4492  aStr = GetXMLToken( XML_DRAFT );
4493  }
4494  else
4495  {
4496  // ShadeMode enum not there, write default
4497  aStr = GetXMLToken( XML_FLAT);
4498  }
4500  }
4501  break;
4502  case EAS_RotateAngle :
4503  {
4504  css::drawing::EnhancedCustomShapeParameterPair aRotateAngleParaPair;
4505  if ( rProp.Value >>= aRotateAngleParaPair )
4506  {
4507  ExportParameter( aStrBuffer, aRotateAngleParaPair.First );
4508  ExportParameter( aStrBuffer, aRotateAngleParaPair.Second );
4509  aStr = aStrBuffer.makeStringAndClear();
4511  }
4512  }
4513  break;
4514  case EAS_RotationCenter :
4515  {
4516  drawing::Direction3D aExtrusionRotationCenter;
4517  if ( rProp.Value >>= aExtrusionRotationCenter )
4518  {
4519  ::basegfx::B3DVector aVec3D( aExtrusionRotationCenter.DirectionX, aExtrusionRotationCenter.DirectionY,
4520  aExtrusionRotationCenter.DirectionZ );
4521  SvXMLUnitConverter::convertB3DVector( aStrBuffer, aVec3D );
4522  aStr = aStrBuffer.makeStringAndClear();
4524  }
4525  }
4526  break;
4527  case EAS_Shininess :
4528  {
4529  double fExtrusionShininess = 0;
4530  if ( rProp.Value >>= fExtrusionShininess )
4531  {
4533  aStrBuffer,
4534  fExtrusionShininess,
4535  false,
4536  util::MeasureUnit::PERCENT,
4537  util::MeasureUnit::PERCENT);
4538  aStrBuffer.append( '%' );
4539  aStr = aStrBuffer.makeStringAndClear();
4541  }
4542  }
4543  break;
4544  case EAS_Skew :
4545  {
4546  css::drawing::EnhancedCustomShapeParameterPair aSkewParaPair;
4547  if ( rProp.Value >>= aSkewParaPair )
4548  {
4549  bSkewValuesProvided = true;
4550  ExportParameter( aStrBuffer, aSkewParaPair.First );
4551  ExportParameter( aStrBuffer, aSkewParaPair.Second );
4552  aStr = aStrBuffer.makeStringAndClear();
4554  }
4555  }
4556  break;
4557  case EAS_Specularity :
4558  {
4559  double fExtrusionSpecularity = 0;
4560  if ( rProp.Value >>= fExtrusionSpecularity )
4561  {
4563  if (fExtrusionSpecularity > 100.0 && eVersion >= SvtSaveOptions::ODFSVER_012
4564  && (eVersion & SvtSaveOptions::ODFSVER_EXTENDED))
4565  {
4566  // tdf#147580 write values > 100% in loext
4568  aStrBuffer,
4569  fExtrusionSpecularity,
4570  false,
4571  util::MeasureUnit::PERCENT,
4572  util::MeasureUnit::PERCENT);
4573  aStrBuffer.append( '%' );
4574  aStr = aStrBuffer.makeStringAndClear();
4576  }
4577  // tdf#147580 ODF 1 allows arbitrary percent, later versions not
4578  if (eVersion >= SvtSaveOptions::ODFSVER_012)
4579  {
4580  fExtrusionSpecularity = std::clamp<double>(fExtrusionSpecularity, 0.0, 100.0);
4581  }
4583  aStrBuffer,
4584  fExtrusionSpecularity,
4585  false,
4586  util::MeasureUnit::PERCENT,
4587  util::MeasureUnit::PERCENT);
4588  aStrBuffer.append( '%' );
4589  aStr = aStrBuffer.makeStringAndClear();
4591  }
4592  }
4593  break;
4594  case EAS_ProjectionMode :
4595  {
4596  drawing::ProjectionMode eProjectionMode;
4597  if ( rProp.Value >>= eProjectionMode )
4599  eProjectionMode == drawing::ProjectionMode_PARALLEL ? GetXMLToken( XML_PARALLEL ) : GetXMLToken( XML_PERSPECTIVE ) );
4600  }
4601  break;
4602  case EAS_ViewPoint :
4603  {
4604  drawing::Position3D aExtrusionViewPoint;
4605  if ( rProp.Value >>= aExtrusionViewPoint )
4606  {
4607  rUnitConverter.convertPosition3D( aStrBuffer, aExtrusionViewPoint );
4608  aStr = aStrBuffer.makeStringAndClear();
4610  }
4611  }
4612  break;
4613  case EAS_Origin :
4614  {
4615  css::drawing::EnhancedCustomShapeParameterPair aOriginParaPair;
4616  if ( rProp.Value >>= aOriginParaPair )
4617  {
4618  ExportParameter( aStrBuffer, aOriginParaPair.First );
4619  ExportParameter( aStrBuffer, aOriginParaPair.Second );
4620  aStr = aStrBuffer.makeStringAndClear();
4622  }
4623  }
4624  break;
4625  case EAS_Color :
4626  {
4627  bool bExtrusionColor;
4628  if ( rProp.Value >>= bExtrusionColor )
4629  {
4631  bExtrusionColor ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
4632  }
4633  }
4634  break;
4635  default:
4636  break;
4637  }
4638  }
4639  // tdf#141301: no specific skew values provided
4640  if (!bSkewValuesProvided)
4641  {
4642  // so we need to export default values explicitly
4643  rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_EXTRUSION_SKEW, "50 -135");
4644  }
4645  }
4646  }
4647  break;
4648  case EAS_TextPath :
4649  {
4650  uno::Sequence< beans::PropertyValue > aTextPathPropSeq;
4651  if ( rGeoProp.Value >>= aTextPathPropSeq )
4652  {
4653  for ( const beans::PropertyValue& rProp : std::as_const(aTextPathPropSeq) )
4654  {
4655  switch( EASGet( rProp.Name ) )
4656  {
4657  case EAS_TextPath :
4658  {
4659  bool bTextPathOn;
4660  if ( rProp.Value >>= bTextPathOn )
4662  bTextPathOn ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
4663  }
4664  break;
4665  case EAS_TextPathMode :
4666  {
4667  css::drawing::EnhancedCustomShapeTextPathMode eTextPathMode;
4668  if ( rProp.Value >>= eTextPathMode )
4669  {
4670  switch ( eTextPathMode )
4671  {
4672  case css::drawing::EnhancedCustomShapeTextPathMode_NORMAL: aStr = GetXMLToken( XML_NORMAL ); break;
4673  case css::drawing::EnhancedCustomShapeTextPathMode_PATH : aStr = GetXMLToken( XML_PATH ); break;
4674  case css::drawing::EnhancedCustomShapeTextPathMode_SHAPE : aStr = GetXMLToken( XML_SHAPE ); break;
4675  default:
4676  break;
4677  }
4678  if ( !aStr.isEmpty() )
4680  }
4681  }
4682  break;
4683  case EAS_ScaleX :
4684  {
4685  bool bScaleX;
4686  if ( rProp.Value >>= bScaleX )
4687  {
4688  aStr = bScaleX ? GetXMLToken( XML_SHAPE ) : GetXMLToken( XML_PATH );
4690  }
4691  }
4692  break;
4693  case EAS_SameLetterHeights :
4694  {
4695  bool bSameLetterHeights;
4696  if ( rProp.Value >>= bSameLetterHeights )
4698  bSameLetterHeights ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
4699  }
4700  break;
4701  default:
4702  break;
4703  }
4704  }
4705  }
4706  }
4707  break;
4708  case EAS_Path :
4709  {
4710  uno::Sequence< beans::PropertyValue > aPathPropSeq;
4711  if ( rGeoProp.Value >>= aPathPropSeq )
4712  {
4713  for ( const beans::PropertyValue& rProp : std::as_const(aPathPropSeq) )
4714  {
4715  switch( EASGet( rProp.Name ) )
4716  {
4717  case EAS_SubViewSize:
4718  {
4719  // export draw:sub-view-size (do not export in ODF 1.3 or older)
4721  {
4722  continue;
4723  }
4724  uno::Sequence< awt::Size > aSubViewSizes;
4725  rProp.Value >>= aSubViewSizes;
4726 
4727  for ( int nIdx = 0; nIdx < aSubViewSizes.getLength(); nIdx++ )
4728  {
4729  if ( nIdx )
4730  aStrBuffer.append(' ');
4731  aStrBuffer.append( aSubViewSizes[nIdx].Width );
4732  aStrBuffer.append(' ');
4733  aStrBuffer.append( aSubViewSizes[nIdx].Height );
4734  }
4735  aStr = aStrBuffer.makeStringAndClear();
4737  }
4738  break;
4739  case EAS_ExtrusionAllowed :
4740  {
4741  bool bExtrusionAllowed;
4742  if ( rProp.Value >>= bExtrusionAllowed )
4744  bExtrusionAllowed ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
4745  }
4746  break;
4748  {
4749  bool bConcentricGradientFillAllowed;
4750  if ( rProp.Value >>= bConcentricGradientFillAllowed )
4752  bConcentricGradientFillAllowed ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
4753  }
4754  break;
4755  case EAS_TextPathAllowed :
4756  {
4757  bool bTextPathAllowed;
4758  if ( rProp.Value >>= bTextPathAllowed )
4760  bTextPathAllowed ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
4761  }
4762  break;
4763  case EAS_GluePoints :
4764  {
4765  css::uno::Sequence< css::drawing::EnhancedCustomShapeParameterPair> aGluePoints;
4766  if ( rProp.Value >>= aGluePoints )
4767  {
4768  if ( aGluePoints.hasElements() )
4769  {
4770  for( const auto& rGluePoint : std::as_const(aGluePoints) )
4771  {
4772  ExportParameter( aStrBuffer, rGluePoint.First );
4773  ExportParameter( aStrBuffer, rGluePoint.Second );
4774  }
4775  aStr = aStrBuffer.makeStringAndClear();
4776  }
4778  }
4779  }
4780  break;
4781  case EAS_GluePointType :
4782  {
4783  sal_Int16 nGluePointType = sal_Int16();
4784  if ( rProp.Value >>= nGluePointType )
4785  {
4786  switch ( nGluePointType )
4787  {
4788  case css::drawing::EnhancedCustomShapeGluePointType::NONE : aStr = GetXMLToken( XML_NONE ); break;
4789  case css::drawing::EnhancedCustomShapeGluePointType::SEGMENTS : aStr = GetXMLToken( XML_SEGMENTS ); break;
4790  case css::drawing::EnhancedCustomShapeGluePointType::RECT : aStr = GetXMLToken( XML_RECTANGLE ); break;
4791  }
4792  if ( !aStr.isEmpty() )
4794  }
4795  }
4796  break;
4797  case EAS_Coordinates :
4798  {
4799  bCoordinates = ( rProp.Value >>= aCoordinates );
4800  }
4801  break;
4802  case EAS_Segments :
4803  {
4804  rProp.Value >>= aSegments;
4805  }
4806  break;
4807  case EAS_StretchX :
4808  {
4809  sal_Int32 nStretchPoint = 0;
4810  if ( rProp.Value >>= nStretchPoint )
4811  rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_PATH_STRETCHPOINT_X, OUString::number( nStretchPoint ) );
4812  }
4813  break;
4814  case EAS_StretchY :
4815  {
4816  sal_Int32 nStretchPoint = 0;
4817  if ( rProp.Value >>= nStretchPoint )
4818  rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_PATH_STRETCHPOINT_Y, OUString::number( nStretchPoint ) );
4819  }
4820  break;
4821  case EAS_TextFrames :
4822  {
4823  css::uno::Sequence< css::drawing::EnhancedCustomShapeTextFrame > aPathTextFrames;
4824  if ( rProp.Value >>= aPathTextFrames )
4825  {
4826  if ( aPathTextFrames.hasElements() )
4827  {
4828  for ( const auto& rPathTextFrame : std::as_const(aPathTextFrames) )
4829  {
4830  ExportParameter( aStrBuffer, rPathTextFrame.TopLeft.First );
4831  ExportParameter( aStrBuffer, rPathTextFrame.TopLeft.Second );
4832  ExportParameter( aStrBuffer, rPathTextFrame.BottomRight.First );
4833  ExportParameter( aStrBuffer, rPathTextFrame.BottomRight.Second );
4834  }
4835  aStr = aStrBuffer.makeStringAndClear();
4836  }
4838  }
4839  }
4840  break;
4841  default:
4842  break;
4843  }
4844  }
4845  }
4846  }
4847  break;
4848  case EAS_Equations :
4849  {
4850  bEquations = ( rGeoProp.Value >>= aEquations );
4851  }
4852  break;
4853  case EAS_Handles :
4854  {
4855  bHandles = ( rGeoProp.Value >>= aHandles );
4856  }
4857  break;
4858  case EAS_AdjustmentValues :
4859  {
4860  rGeoProp.Value >>= aAdjustmentValues;
4861  }
4862  break;
4863  default:
4864  break;
4865  }
4866  } // for
4867  rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_TYPE, aCustomShapeType );
4868 
4869  // adjustments
4870  sal_Int32 nAdjustmentValues = aAdjustmentValues.getLength();
4871  if ( nAdjustmentValues )
4872  {
4873  sal_Int32 i, nValue = 0;
4874  for ( i = 0; i < nAdjustmentValues; i++ )
4875  {
4876  if ( i )
4877  aStrBuffer.append( ' ' );
4878 
4879  const css::drawing::EnhancedCustomShapeAdjustmentValue& rAdj = aAdjustmentValues[ i ];
4880  if ( rAdj.State == beans::PropertyState_DIRECT_VALUE )
4881  {
4882  if ( rAdj.Value.getValueTypeClass() == uno::TypeClass_DOUBLE )
4883  {
4884  double fValue = 0.0;
4885  rAdj.Value >>= fValue;
4886  ::sax::Converter::convertDouble(aStrBuffer, fValue);
4887  }
4888  else
4889  {
4890  rAdj.Value >>= nValue;
4891  aStrBuffer.append(nValue);
4892  }
4893  }
4894  else
4895  {
4896  // this should not be, but better than setting nothing
4897  aStrBuffer.append("0");
4898  }
4899  }
4900  aStr = aStrBuffer.makeStringAndClear();
4901  rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_MODIFIERS, aStr );
4902  }
4903  if ( bCoordinates )
4904  ImpExportEnhancedPath( rExport, aCoordinates, aSegments );
4905  }
4906  }
4907  SvXMLElementExport aOBJ( rExport, XML_NAMESPACE_DRAW, XML_ENHANCED_GEOMETRY, true, true );
4908  if ( bEquations )
4909  ImpExportEquations( rExport, aEquations );
4910  if ( bHandles )
4911  ImpExportHandles( rExport, aHandles );
4912 }
4913 
4915  const uno::Reference< drawing::XShape >& xShape,
4916  XMLShapeExportFlags nFeatures, css::awt::Point* pRefPoint )
4917 {
4918  const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
4919  if ( !xPropSet.is() )
4920  return;
4921 
4922  uno::Reference< beans::XPropertySetInfo > xPropSetInfo( xPropSet->getPropertySetInfo() );
4923 
4924  // Transformation
4925  ImpExportNewTrans( xPropSet, nFeatures, pRefPoint );
4926 
4927  if ( xPropSetInfo.is() )
4928  {
4929  OUString aStr;
4930  if ( xPropSetInfo->hasPropertyByName( "CustomShapeEngine" ) )
4931  {
4932  uno::Any aEngine( xPropSet->getPropertyValue( "CustomShapeEngine" ) );
4933  if ( ( aEngine >>= aStr ) && !aStr.isEmpty() )
4935  }
4936  if ( xPropSetInfo->hasPropertyByName( "CustomShapeData" ) )
4937  {
4938  uno::Any aData( xPropSet->getPropertyValue( "CustomShapeData" ) );
4939  if ( ( aData >>= aStr ) && !aStr.isEmpty() )
4941  }
4942  }
4943  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
4944  SvXMLElementExport aOBJ( mrExport, XML_NAMESPACE_DRAW, XML_CUSTOM_SHAPE, bCreateNewline, true );
4945  ImpExportDescription( xShape ); // #i68101#
4946  ImpExportEvents( xShape );
4947  ImpExportGluePoints( xShape );
4948  ImpExportText( xShape );
4949  ImpExportEnhancedGeometry( mrExport, xPropSet );
4950 
4951 }
4952 
4953 void XMLShapeExport::ImpExportTableShape( const uno::Reference< drawing::XShape >& xShape, XmlShapeType eShapeType, XMLShapeExportFlags nFeatures, css::awt::Point* pRefPoint )
4954 {
4955  uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
4956  uno::Reference< container::XNamed > xNamed(xShape, uno::UNO_QUERY);
4957 
4958  SAL_WARN_IF( !xPropSet.is() || !xNamed.is(), "xmloff", "xmloff::XMLShapeExport::ImpExportTableShape(), table shape is not implementing needed interfaces");
4959  if(!(xPropSet.is() && xNamed.is()))
4960  return;
4961 
4962  try
4963  {
4964  // Transformation
4965  ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);
4966 
4967  bool bIsEmptyPresObj = false;
4968 
4969  // presentation settings
4970  if(eShapeType == XmlShapeTypePresTableShape)
4971  bIsEmptyPresObj = ImpExportPresentationAttributes( xPropSet, GetXMLToken(XML_TABLE) );
4972 
4973  const bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE );
4974  const bool bExportEmbedded(mrExport.getExportFlags() & SvXMLExportFlags::EMBEDDED);
4975 
4976  SvXMLElementExport aElement( mrExport, XML_NAMESPACE_DRAW, XML_FRAME, bCreateNewline, true );
4977 
4978  // do not export in ODF 1.1 or older
4980  {
4981  if( !bIsEmptyPresObj )
4982  {
4983  uno::Reference< container::XNamed > xTemplate( xPropSet->getPropertyValue("TableTemplate"), uno::UNO_QUERY );
4984  if( xTemplate.is() )
4985  {
4986  const OUString sTemplate( xTemplate->getName() );
4987  if( !sTemplate.isEmpty() )
4988  {
4990 
4991  for( const XMLPropertyMapEntry* pEntry = &aXMLTableShapeAttributes[0]; pEntry->msApiName; pEntry++ )
4992  {
4993  try
4994  {
4995  bool bBool = false;
4996  const OUString sAPIPropertyName( pEntry->msApiName, pEntry->nApiNameLength, RTL_TEXTENCODING_ASCII_US );
4997 
4998  xPropSet->getPropertyValue( sAPIPropertyName ) >>= bBool;
4999  if( bBool )
5000  mrExport.AddAttribute(pEntry->mnNameSpace, pEntry->meXMLName, XML_TRUE );
5001  }
5002  catch( uno::Exception& )
5003  {
5004  DBG_UNHANDLED_EXCEPTION("xmloff.draw");
5005  }
5006  }
5007  }
5008  }
5009 
5010  uno::Reference< table::XColumnRowRange > xRange( xPropSet->getPropertyValue( gsModel ), uno::UNO_QUERY_THROW );
5011  GetShapeTableExport()->exportTable( xRange );
5012  }
5013  }
5014 
5015  if( !bIsEmptyPresObj )
5016  {
5017  uno::Reference< graphic::XGraphic > xGraphic( xPropSet->getPropertyValue("ReplacementGraphic"), uno::UNO_QUERY );
5018  if( xGraphic.is() ) try
5019  {
5020  uno::Reference< uno::XComponentContext > xContext = GetExport().getComponentContext();
5021 
5022  uno::Reference< embed::XStorage > xPictureStorage;
5023  uno::Reference< embed::XStorage > xStorage;
5024  uno::Reference< io::XStream > xPictureStream;
5025 
5026  OUString sPictureName;
5027  if( bExportEmbedded )
5028  {
5029  xPictureStream.set( xContext->getServiceManager()->createInstanceWithContext( "com.sun.star.comp.MemoryStream", xContext), uno::UNO_QUERY_THROW );
5030  }
5031  else
5032  {
5033  xStorage.set( GetExport().GetTargetStorage(), uno::UNO_SET_THROW );
5034 
5035  xPictureStorage.set( xStorage->openStorageElement( "Pictures" , ::embed::ElementModes::READWRITE ), uno::UNO_SET_THROW );
5036 
5037  sal_Int32 nIndex = 0;
5038  do
5039  {
5040  sPictureName = "TablePreview" + OUString::number( ++nIndex ) + ".svm";
5041  }
5042  while( xPictureStorage->hasByName( sPictureName ) );
5043 
5044  xPictureStream.set( xPictureStorage->openStreamElement( sPictureName, ::embed::ElementModes::READWRITE ), uno::UNO_SET_THROW );
5045  }
5046 
5047  uno::Reference< graphic::XGraphicProvider > xProvider( graphic::GraphicProvider::create(xContext) );
5048  uno::Sequence< beans::PropertyValue > aArgs{
5049  comphelper::makePropertyValue("MimeType", OUString( "image/x-vclgraphic" )),
5050  comphelper::makePropertyValue("OutputStream", xPictureStream->getOutputStream())
5051  };
5052  xProvider->storeGraphic( xGraphic, aArgs );
5053 
5054  if( xPictureStorage.is() )
5055  {
5056  uno::Reference< embed::XTransactedObject > xTrans( xPictureStorage, uno::UNO_QUERY );
5057  if( xTrans.is() )
5058  xTrans->commit();
5059  }
5060 
5061  if( !bExportEmbedded )
5062  {
5063  OUString sURL = "Pictures/" + sPictureName;
5068  }
5069 
5070  SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_DRAW, XML_IMAGE, false, true );
5071 
5072  if( bExportEmbedded )
5073  {
5074  uno::Reference< io::XSeekableInputStream > xSeekable( xPictureStream, uno::UNO_QUERY_THROW );
5075  xSeekable->seek(0);
5076 
5077  XMLBase64Export aBase64Exp( GetExport() );
5078  aBase64Exp.exportOfficeBinaryDataElement( uno::Reference < io::XInputStream >( xPictureStream, uno::UNO_QUERY_THROW ) );
5079  }
5080  }
5081  catch( uno::Exception const & )
5082  {
5083  DBG_UNHANDLED_EXCEPTION("xmloff.draw");
5084  }
5085  }
5086 
5087  ImpExportEvents( xShape );
5088  ImpExportGluePoints( xShape );
5089  ImpExportDescription( xShape ); // #i68101#
5090  }
5091  catch( uno::Exception const & )
5092  {
5093  DBG_UNHANDLED_EXCEPTION("xmloff.draw");
5094  }
5095 }
5096 
5097 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
css::uno::Reference< css::embed::XStorage > const & GetTargetStorage() const
Definition: xmlexp.cxx:2267
#define SO3_RPTCH_CLASSID