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