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 #define XML_EMBEDDEDOBJECTGRAPHIC_URL_BASE "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 
172  SvXMLExportPropertyMapper *pExtMapper )
173 : mrExport( rExp ),
174  maShapesInfos(),
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( 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, 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( 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, "", 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 
582  std::unique_ptr< SvXMLElementExport > pHyperlinkElement;
583 
584  // export hyperlinks with <a><shape/></a>. Currently only in draw since draw
585  // does not support document events
586  if( xSet.is() && (GetExport().GetModelType() == SvtModuleOptions::EFactory::DRAW) ) try
587  {
588  presentation::ClickAction eAction = presentation::ClickAction_NONE;
589  xSet->getPropertyValue("OnClick") >>= eAction;
590 
591  if( (eAction == presentation::ClickAction_DOCUMENT) ||
592  (eAction == presentation::ClickAction_BOOKMARK) )
593  {
594  OUString sURL;
595  xSet->getPropertyValue(gsBookmark) >>= sURL;
596 
597  if( !sURL.isEmpty() )
598  {
602  pHyperlinkElement.reset( new SvXMLElementExport(mrExport, XML_NAMESPACE_DRAW, XML_A, true, true) );
603  }
604  }
605  }
606  catch(const uno::Exception&)
607  {
608  TOOLS_WARN_EXCEPTION("xmloff", "XMLShapeExport::exportShape(): exception during hyperlink export");
609  }
610 
611  if( xSet.is() )
612  xSet->getPropertyValue(gsZIndex) >>= nZIndex;
613 
614  ImplXMLShapeExportInfoVector& aShapeInfoVector = (*maCurrentShapesIter).second;
615 
616  if( static_cast<sal_Int32>(aShapeInfoVector.size()) <= nZIndex )
617  {
618  SAL_WARN( "xmloff", "XMLShapeExport::exportShape(): no shape info collected for a given shape" );
619  return;
620  }
621 
622  NewTextListsHelper aNewTextListsHelper( mrExport );
623 
624  const ImplXMLShapeExportInfo& aShapeInfo = aShapeInfoVector[nZIndex];
625 
626 #ifdef DBG_UTIL
627  // check if this is the correct ShapesInfo
628  uno::Reference< container::XChild > xChild( xShape, uno::UNO_QUERY );
629  if( xChild.is() )
630  {
631  uno::Reference< drawing::XShapes > xParent( xChild->getParent(), uno::UNO_QUERY );
632  SAL_WARN_IF( !xParent.is() && xParent.get() == (*maCurrentShapesIter).first.get(), "xmloff", "XMLShapeExport::exportShape(): Wrong call to XMLShapeExport::seekShapes()" );
633  }
634 
635  // first compute the shapes type
636  {
638  ImpCalcShapeType(xShape, eShapeType);
639 
640  SAL_WARN_IF( eShapeType != aShapeInfo.meShapeType, "xmloff", "exportShape callings do not correspond to collectShapeAutoStyles calls!: " << xShape->getShapeType() );
641  }
642 #endif
643 
644  // collect animation information if needed
645  if( mxAnimationsExporter.is() )
646  mxAnimationsExporter->collect( xShape, mrExport );
647 
648  /* Export shapes name if he has one (#i51726#)
649  Export of the shape name for text documents only if the OpenDocument
650  file format is written - exceptions are group shapes.
651  Note: Writer documents in OpenOffice.org file format doesn't contain
652  any names for shapes, except for group shapes.
653  */
654  {
655  if ( ( GetExport().GetModelType() != SvtModuleOptions::EFactory::WRITER &&
656  GetExport().GetModelType() != SvtModuleOptions::EFactory::WRITERWEB &&
657  GetExport().GetModelType() != SvtModuleOptions::EFactory::WRITERGLOBAL ) ||
658  ( GetExport().getExportFlags() & SvXMLExportFlags::OASIS ) ||
659  aShapeInfo.meShapeType == XmlShapeTypeDrawGroupShape ||
660  ( aShapeInfo.meShapeType == XmlShapeTypeDrawCustomShape &&
661  aShapeInfo.xCustomShapeReplacement.is() ) )
662  {
663  uno::Reference< container::XNamed > xNamed( xShape, uno::UNO_QUERY );
664  if( xNamed.is() )
665  {
666  const OUString aName( xNamed->getName() );
667  if( !aName.isEmpty() )
669  }
670  }
671  }
672 
673  // export style name
674  if( !aShapeInfo.msStyleName.isEmpty() )
675  {
676  if(XmlStyleFamily::SD_GRAPHICS_ID == aShapeInfo.mnFamily)
678  else
680  }
681 
682  // export text style name
683  if( !aShapeInfo.msTextStyleName.isEmpty() )
684  {
686  }
687 
688  // export shapes id if needed
689  {
690  uno::Reference< uno::XInterface > xRef( xShape, uno::UNO_QUERY );
691  const OUString& rShapeId = mrExport.getInterfaceToIdentifierMapper().getIdentifier( xRef );
692  if( !rShapeId.isEmpty() )
693  {
695  }
696  }
697 
698  // export layer information
699  if( mbExportLayer )
700  {
701  // check for group or scene shape and not export layer if this is one
702  uno::Reference< drawing::XShapes > xShapes( xShape, uno::UNO_QUERY );
703  if( !xShapes.is() )
704  {
705  try
706  {
707  uno::Reference< beans::XPropertySet > xProps( xShape, uno::UNO_QUERY );
708  OUString aLayerName;
709  xProps->getPropertyValue("LayerName") >>= aLayerName;
711 
712  }
713  catch(const uno::Exception&)
714  {
715  DBG_UNHANDLED_EXCEPTION( "xmloff", "exporting layer name for shape" );
716  }
717  }
718  }
719 
720  // export draw:display (do not export in ODF 1.3 or older)
722  {
723  if( aShapeInfo.meShapeType != XmlShapeTypeDrawPageShape && aShapeInfo.meShapeType != XmlShapeTypePresPageShape &&
725  try
726  {
727  bool bVisible = true;
728  bool bPrintable = true;
729 
730  xSet->getPropertyValue(gsVisible) >>= bVisible;
731  xSet->getPropertyValue(gsPrintable) >>= bPrintable;
732 
733  XMLTokenEnum eDisplayToken = XML_TOKEN_INVALID;
734  const unsigned short nDisplay = (bVisible ? 2 : 0) | (bPrintable ? 1 : 0);
735  switch( nDisplay )
736  {
737  case 0: eDisplayToken = XML_NONE; break;
738  case 1: eDisplayToken = XML_PRINTER; break;
739  case 2: eDisplayToken = XML_SCREEN; break;
740  // case 3: eDisplayToken = XML_ALWAYS break; this is the default
741  }
742 
743  if( eDisplayToken != XML_TOKEN_INVALID )
745  }
746  catch(const uno::Exception&)
747  {
748  DBG_UNHANDLED_EXCEPTION("xmloff.draw");
749  }
750  }
751 
752  // #82003# test export count
753  // #91587# ALWAYS increment since now ALL to be exported shapes are counted.
754  if(mrExport.GetShapeExport()->IsHandleProgressBarEnabled())
755  {
757  }
758 
759  onExport( xShape );
760 
761  // export shape element
762  switch(aShapeInfo.meShapeType)
763  {
765  {
766  ImpExportRectangleShape(xShape, nFeatures, pRefPoint );
767  break;
768  }
770  {
771  ImpExportEllipseShape(xShape, nFeatures, pRefPoint );
772  break;
773  }
775  {
776  ImpExportLineShape(xShape, nFeatures, pRefPoint );
777  break;
778  }
779  case XmlShapeTypeDrawPolyPolygonShape: // closed PolyPolygon
780  case XmlShapeTypeDrawPolyLineShape: // open PolyPolygon
781  case XmlShapeTypeDrawClosedBezierShape: // closed tools::PolyPolygon containing curves
782  case XmlShapeTypeDrawOpenBezierShape: // open tools::PolyPolygon containing curves
783  {
784  ImpExportPolygonShape(xShape, aShapeInfo.meShapeType, nFeatures, pRefPoint );
785  break;
786  }
787 
797  {
798  ImpExportTextBoxShape(xShape, aShapeInfo.meShapeType, nFeatures, pRefPoint );
799  break;
800  }
801 
804  {
805  ImpExportGraphicObjectShape(xShape, aShapeInfo.meShapeType, nFeatures, pRefPoint );
806  break;
807  }
808 
811  {
812  ImpExportChartShape(xShape, aShapeInfo.meShapeType, nFeatures, pRefPoint, pAttrList );
813  break;
814  }
815 
817  {
818  ImpExportControlShape(xShape, nFeatures, pRefPoint );
819  break;
820  }
821 
823  {
824  ImpExportConnectorShape(xShape, nFeatures, pRefPoint );
825  break;
826  }
827 
829  {
830  ImpExportMeasureShape(xShape, nFeatures, pRefPoint );
831  break;
832  }
833 
838  {
839  ImpExportOLE2Shape(xShape, aShapeInfo.meShapeType, nFeatures, pRefPoint );
840  break;
841  }
842 
845  {
846  ImpExportTableShape( xShape, aShapeInfo.meShapeType, nFeatures, pRefPoint );
847  break;
848  }
849 
853  {
854  ImpExportPageShape(xShape, aShapeInfo.meShapeType, nFeatures, pRefPoint );
855  break;
856  }
857 
859  {
860  ImpExportCaptionShape(xShape, nFeatures, pRefPoint );
861  break;
862  }
863 
868  {
869  ImpExport3DShape(xShape, aShapeInfo.meShapeType);
870  break;
871  }
872 
874  {
875  ImpExport3DSceneShape( xShape, nFeatures, pRefPoint );
876  break;
877  }
878 
880  {
881  // empty group
882  ImpExportGroupShape( xShape, nFeatures, pRefPoint );
883  break;
884  }
885 
887  {
888  ImpExportFrameShape(xShape, nFeatures, pRefPoint );
889  break;
890  }
891 
893  {
894  ImpExportAppletShape(xShape, nFeatures, pRefPoint );
895  break;
896  }
897 
899  {
900  ImpExportPluginShape(xShape, nFeatures, pRefPoint );
901  break;
902  }
903 
905  {
906  if ( aShapeInfo.xCustomShapeReplacement.is() )
907  ImpExportGroupShape( aShapeInfo.xCustomShapeReplacement, nFeatures, pRefPoint );
908  else
909  ImpExportCustomShape( xShape, nFeatures, pRefPoint );
910  break;
911  }
912 
915  {
916  ImpExportMediaShape( xShape, aShapeInfo.meShapeType, nFeatures, pRefPoint );
917  break;
918  }
919 
921  case XmlShapeTypeUnknown:
923  default:
924  {
925  // this should never happen and is an error
926  OSL_FAIL("XMLEXP: WriteShape: unknown or unexpected type of shape in export!");
927  break;
928  }
929  }
930 
931  pHyperlinkElement.reset();
932 
933  // #97489# #97111#
934  // if there was an error and no element for the shape was exported
935  // we need to clear the attribute list or the attributes will be
936  // set on the next exported element, which can result in corrupt
937  // xml files due to duplicate attributes
938 
939  mrExport.CheckAttrList(); // asserts in non pro if we have attributes left
940  mrExport.ClearAttrList(); // clears the attributes
941 }
942 
943 // This method collects all automatic styles for the shapes inside the given XShapes collection
944 void XMLShapeExport::collectShapesAutoStyles( const uno::Reference < drawing::XShapes >& xShapes )
945 {
946  ShapesInfos::iterator aOldCurrentShapesIter = maCurrentShapesIter;
947  seekShapes( xShapes );
948 
949  uno::Reference< drawing::XShape > xShape;
950  const sal_Int32 nShapeCount(xShapes->getCount());
951  for(sal_Int32 nShapeId = 0; nShapeId < nShapeCount; nShapeId++)
952  {
953  xShapes->getByIndex(nShapeId) >>= xShape;
954  SAL_WARN_IF( !xShape.is(), "xmloff", "Shape without a XShape?" );
955  if(!xShape.is())
956  continue;
957 
958  collectShapeAutoStyles( xShape );
959  }
960 
961  maCurrentShapesIter = aOldCurrentShapesIter;
962 }
963 
964 // This method exports all XShape inside the given XShapes collection
965 void XMLShapeExport::exportShapes( const uno::Reference < drawing::XShapes >& xShapes, XMLShapeExportFlags nFeatures /* = SEF_DEFAULT */, awt::Point* pRefPoint /* = NULL */ )
966 {
967  ShapesInfos::iterator aOldCurrentShapesIter = maCurrentShapesIter;
968  seekShapes( xShapes );
969 
970  uno::Reference< drawing::XShape > xShape;
971  const sal_Int32 nShapeCount(xShapes->getCount());
972  for(sal_Int32 nShapeId = 0; nShapeId < nShapeCount; nShapeId++)
973  {
974  xShapes->getByIndex(nShapeId) >>= xShape;
975  SAL_WARN_IF( !xShape.is(), "xmloff", "Shape without a XShape?" );
976  if(!xShape.is())
977  continue;
978 
979  exportShape( xShape, nFeatures, pRefPoint );
980  }
981 
982  maCurrentShapesIter = aOldCurrentShapesIter;
983 }
984 
985 namespace xmloff {
986 
987 void FixZOrder(uno::Reference<drawing::XShapes> const& xShapes,
988  std::function<unsigned int (uno::Reference<beans::XPropertySet> const&)> const& rGetLayer)
989 {
990  uno::Reference<drawing::XShapes3> const xShapes3(xShapes, uno::UNO_QUERY);
991  assert(xShapes3.is());
992  if (!xShapes3.is())
993  {
994  return; // only SvxDrawPage implements this
995  }
996  struct Layer { std::vector<sal_Int32> shapes; sal_Int32 nMin = SAL_MAX_INT32; sal_Int32 nMax = 0; };
997  std::vector<Layer> layers;
998  // shapes are sorted by ZOrder
999  sal_Int32 const nCount(xShapes->getCount());
1000  for (sal_Int32 i = 0; i < nCount; ++i)
1001  {
1002  uno::Reference<beans::XPropertySet> const xShape(xShapes->getByIndex(i), uno::UNO_QUERY);
1003  unsigned int const nLayer(rGetLayer(xShape));
1004  if (layers.size() <= nLayer)
1005  {
1006  layers.resize(nLayer + 1);
1007  }
1008  layers[nLayer].shapes.emplace_back(i);
1009  if (i < layers[nLayer].nMin)
1010  {
1011  layers[nLayer].nMin = i;
1012  }
1013  if (layers[nLayer].nMax < i)
1014  {
1015  layers[nLayer].nMax = i;
1016  }
1017  }
1018  layers.erase(std::remove_if(layers.begin(), layers.end(),
1019  [](Layer const& rLayer) { return rLayer.shapes.empty(); }),
1020  layers.end());
1021  bool isSorted(true);
1022  for (size_t i = 1; i < layers.size(); ++i)
1023  {
1024  assert(layers[i].nMin != layers[i-1].nMax); // unique!
1025  if (layers[i].nMin < layers[i-1].nMax)
1026  {
1027  isSorted = false;
1028  break;
1029  }
1030  }
1031  if (isSorted)
1032  {
1033  return; // nothing to do
1034  }
1035  uno::Sequence<sal_Int32> aNewOrder(nCount);
1036  auto iterInsert(aNewOrder.begin());
1037  for (auto const& rLayer : layers)
1038  {
1039  assert(rLayer.nMin <= rLayer.nMax); // empty layers have been removed
1040  iterInsert = std::copy(rLayer.shapes.begin(), rLayer.shapes.end(), iterInsert);
1041  }
1042  try
1043  {
1044  xShapes3->sort(aNewOrder);
1045  }
1046  catch (uno::Exception const&)
1047  {
1048  SAL_WARN("xmloff", "FixZOrder: exception");
1049  }
1050 }
1051 
1052 } // namespace xmloff
1053 
1054 void XMLShapeExport::seekShapes( const uno::Reference< drawing::XShapes >& xShapes ) noexcept
1055 {
1056  if( xShapes.is() )
1057  {
1058  maCurrentShapesIter = maShapesInfos.find( xShapes );
1059  if( maCurrentShapesIter == maShapesInfos.end() )
1060  {
1061  ImplXMLShapeExportInfoVector aNewInfoVector;
1062  aNewInfoVector.resize( static_cast<ShapesInfos::size_type>(xShapes->getCount()) );
1063  maShapesInfos[ xShapes ] = aNewInfoVector;
1064 
1065  maCurrentShapesIter = maShapesInfos.find( xShapes );
1066 
1067  SAL_WARN_IF( maCurrentShapesIter == maShapesInfos.end(), "xmloff", "XMLShapeExport::seekShapes(): insert into stl::map failed" );
1068  }
1069 
1070  SAL_WARN_IF( (*maCurrentShapesIter).second.size() != static_cast<ShapesInfos::size_type>(xShapes->getCount()), "xmloff", "XMLShapeExport::seekShapes(): XShapes size varied between calls" );
1071 
1072  }
1073  else
1074  {
1075  maCurrentShapesIter = maShapesInfos.end();
1076  }
1077 }
1078 
1080 {
1081  // export all autostyle infos
1082 
1083  // ...for graphic
1084  {
1086  }
1087 
1088  // ...for presentation
1089  {
1091  }
1092 
1093  if( mxShapeTableExport.is() )
1094  mxShapeTableExport->exportAutoStyles();
1095 }
1096 
1099  SvXMLExport& rExport )
1100 {
1103  rExport.GetTextParagraphExport(); // get or create text paragraph export
1104  SvXMLExportPropertyMapper* pResult =
1105  new XMLShapeExportPropertyMapper( xMapper, rExport );
1106  // chain text attributes
1107  return pResult;
1108 }
1109 
1110 void XMLShapeExport::ImpCalcShapeType(const uno::Reference< drawing::XShape >& xShape,
1111  XmlShapeType& eShapeType)
1112 {
1113  // set in every case, so init here
1114  eShapeType = XmlShapeTypeUnknown;
1115 
1116  if(!xShape.is())
1117  return;
1118 
1119  OUString aType(xShape->getShapeType());
1120 
1121  if(!aType.match("com.sun.star."))
1122  return;
1123 
1124  if(aType.match("drawing.", 13))
1125  {
1126  // drawing shapes
1127  if (aType.match("Rectangle", 21)) { eShapeType = XmlShapeTypeDrawRectangleShape; }
1128 
1129  // #i72177# Note: Correcting CustomShape, CustomShape->Custom, len from 9 (was wrong anyways) to 6.
1130  // As can be seen at the other compares, the appendix "Shape" is left out of the comparison.
1131  else if(aType.match("Custom", 21)) { eShapeType = XmlShapeTypeDrawCustomShape; }
1132 
1133  else if(aType.match("Ellipse", 21)) { eShapeType = XmlShapeTypeDrawEllipseShape; }
1134  else if(aType.match("Control", 21)) { eShapeType = XmlShapeTypeDrawControlShape; }
1135  else if(aType.match("Connector", 21)) { eShapeType = XmlShapeTypeDrawConnectorShape; }
1136  else if(aType.match("Measure", 21)) { eShapeType = XmlShapeTypeDrawMeasureShape; }
1137  else if(aType.match("Line", 21)) { eShapeType = XmlShapeTypeDrawLineShape; }
1138 
1139  // #i72177# Note: This covers two types by purpose, PolyPolygonShape and PolyPolygonPathShape
1140  else if(aType.match("PolyPolygon", 21)) { eShapeType = XmlShapeTypeDrawPolyPolygonShape; }
1141 
1142  // #i72177# Note: This covers two types by purpose, PolyLineShape and PolyLinePathShape
1143  else if(aType.match("PolyLine", 21)) { eShapeType = XmlShapeTypeDrawPolyLineShape; }
1144 
1145  else if(aType.match("OpenBezier", 21)) { eShapeType = XmlShapeTypeDrawOpenBezierShape; }
1146  else if(aType.match("ClosedBezier", 21)) { eShapeType = XmlShapeTypeDrawClosedBezierShape; }
1147 
1148  // #i72177# FreeHand (opened and closed) now supports the types OpenFreeHandShape and
1149  // ClosedFreeHandShape respectively. Represent them as bezier shapes
1150  else if(aType.match("OpenFreeHand", 21)) { eShapeType = XmlShapeTypeDrawOpenBezierShape; }
1151  else if(aType.match("ClosedFreeHand", 21)) { eShapeType = XmlShapeTypeDrawClosedBezierShape; }
1152 
1153  else if(aType.match("GraphicObject", 21)) { eShapeType = XmlShapeTypeDrawGraphicObjectShape; }
1154  else if(aType.match("Group", 21)) { eShapeType = XmlShapeTypeDrawGroupShape; }
1155  else if(aType.match("Text", 21)) { eShapeType = XmlShapeTypeDrawTextShape; }
1156  else if(aType.match("OLE2", 21))
1157  {
1158  eShapeType = XmlShapeTypeDrawOLE2Shape;
1159 
1160  // get info about presentation shape
1161  uno::Reference <beans::XPropertySet> xPropSet(xShape, uno::UNO_QUERY);
1162 
1163  if(xPropSet.is())
1164  {
1165  OUString sCLSID;
1166  if(xPropSet->getPropertyValue("CLSID") >>= sCLSID)
1167  {
1168  if (sCLSID == mrExport.GetChartExport()->getChartCLSID() ||
1169  sCLSID == SvGlobalName( SO3_RPTCH_CLASSID ).GetHexName() )
1170  {
1171  eShapeType = XmlShapeTypeDrawChartShape;
1172  }
1173  else if (sCLSID == SvGlobalName( SO3_SC_CLASSID ).GetHexName() )
1174  {
1175  eShapeType = XmlShapeTypeDrawSheetShape;
1176  }
1177  else
1178  {
1179  // general OLE2 Object
1180  }
1181  }
1182  }
1183  }
1184  else if(aType.match("Page", 21)) { eShapeType = XmlShapeTypeDrawPageShape; }
1185  else if(aType.match("Frame", 21)) { eShapeType = XmlShapeTypeDrawFrameShape; }
1186  else if(aType.match("Caption", 21)) { eShapeType = XmlShapeTypeDrawCaptionShape; }
1187  else if(aType.match("Plugin", 21)) { eShapeType = XmlShapeTypeDrawPluginShape; }
1188  else if(aType.match("Applet", 21)) { eShapeType = XmlShapeTypeDrawAppletShape; }
1189  else if(aType.match("MediaShape", 21)) { eShapeType = XmlShapeTypeDrawMediaShape; }
1190  else if(aType.match("TableShape", 21)) { eShapeType = XmlShapeTypeDrawTableShape; }
1191 
1192  // 3D shapes
1193  else if(aType.match("Scene", 21 + 7)) { eShapeType = XmlShapeTypeDraw3DSceneObject; }
1194  else if(aType.match("Cube", 21 + 7)) { eShapeType = XmlShapeTypeDraw3DCubeObject; }
1195  else if(aType.match("Sphere", 21 + 7)) { eShapeType = XmlShapeTypeDraw3DSphereObject; }
1196  else if(aType.match("Lathe", 21 + 7)) { eShapeType = XmlShapeTypeDraw3DLatheObject; }
1197  else if(aType.match("Extrude", 21 + 7)) { eShapeType = XmlShapeTypeDraw3DExtrudeObject; }
1198  }
1199  else if(aType.match("presentation.", 13))
1200  {
1201  // presentation shapes
1202  if (aType.match("TitleText", 26)) { eShapeType = XmlShapeTypePresTitleTextShape; }
1203  else if(aType.match("Outliner", 26)) { eShapeType = XmlShapeTypePresOutlinerShape; }
1204  else if(aType.match("Subtitle", 26)) { eShapeType = XmlShapeTypePresSubtitleShape; }
1205  else if(aType.match("GraphicObject", 26)) { eShapeType = XmlShapeTypePresGraphicObjectShape; }
1206  else if(aType.match("Page", 26)) { eShapeType = XmlShapeTypePresPageShape; }
1207  else if(aType.match("OLE2", 26))
1208  {
1209  eShapeType = XmlShapeTypePresOLE2Shape;
1210 
1211  // get info about presentation shape
1212  uno::Reference <beans::XPropertySet> xPropSet(xShape, uno::UNO_QUERY);
1213 
1214  if(xPropSet.is()) try
1215  {
1216  OUString sCLSID;
1217  if(xPropSet->getPropertyValue("CLSID") >>= sCLSID)
1218  {
1219  if( sCLSID == SvGlobalName( SO3_SC_CLASSID ).GetHexName() )
1220  {
1221  eShapeType = XmlShapeTypePresSheetShape;
1222  }
1223  }
1224  }
1225  catch(const uno::Exception&)
1226  {
1227  SAL_WARN( "xmloff", "XMLShapeExport::ImpCalcShapeType(), expected ole shape to have the CLSID property?" );
1228  }
1229  }
1230  else if(aType.match("Chart", 26)) { eShapeType = XmlShapeTypePresChartShape; }
1231  else if(aType.match("OrgChart", 26)) { eShapeType = XmlShapeTypePresOrgChartShape; }
1232  else if(aType.match("CalcShape", 26)) { eShapeType = XmlShapeTypePresSheetShape; }
1233  else if(aType.match("TableShape", 26)) { eShapeType = XmlShapeTypePresTableShape; }
1234  else if(aType.match("Notes", 26)) { eShapeType = XmlShapeTypePresNotesShape; }
1235  else if(aType.match("HandoutShape", 26)) { eShapeType = XmlShapeTypeHandoutShape; }
1236  else if(aType.match("HeaderShape", 26)) { eShapeType = XmlShapeTypePresHeaderShape; }
1237  else if(aType.match("FooterShape", 26)) { eShapeType = XmlShapeTypePresFooterShape; }
1238  else if(aType.match("SlideNumberShape", 26)) { eShapeType = XmlShapeTypePresSlideNumberShape; }
1239  else if(aType.match("DateTimeShape", 26)) { eShapeType = XmlShapeTypePresDateTimeShape; }
1240  else if(aType.match("MediaShape", 26)) { eShapeType = XmlShapeTypePresMediaShape; }
1241  }
1242 }
1243 
1245 void XMLShapeExport::ImpExportGluePoints( const uno::Reference< drawing::XShape >& xShape )
1246 {
1247  uno::Reference< drawing::XGluePointsSupplier > xSupplier( xShape, uno::UNO_QUERY );
1248  if( !xSupplier.is() )
1249  return;
1250 
1251  uno::Reference< container::XIdentifierAccess > xGluePoints( xSupplier->getGluePoints(), uno::UNO_QUERY );
1252  if( !xGluePoints.is() )
1253  return;
1254 
1255  drawing::GluePoint2 aGluePoint;
1256 
1257  uno::Sequence< sal_Int32 > aIdSequence( xGluePoints->getIdentifiers() );
1258 
1259  for( const sal_Int32 nIdentifier : aIdSequence )
1260  {
1261  if( (xGluePoints->getByIdentifier( nIdentifier ) >>= aGluePoint) && aGluePoint.IsUserDefined )
1262  {
1263  // export only user defined glue points
1264 
1265  const OUString sId( OUString::number( nIdentifier ) );
1267 
1269  aGluePoint.Position.X);
1270  mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_X, msBuffer.makeStringAndClear());
1271 
1273  aGluePoint.Position.Y);
1274  mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_Y, msBuffer.makeStringAndClear());
1275 
1276  if( !aGluePoint.IsRelative )
1277  {
1278  SvXMLUnitConverter::convertEnum( msBuffer, aGluePoint.PositionAlignment, aXML_GlueAlignment_EnumMap );
1279  mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_ALIGN, msBuffer.makeStringAndClear() );
1280  }
1281 
1282  if( aGluePoint.Escape != drawing::EscapeDirection_SMART )
1283  {
1286  }
1287 
1288  SvXMLElementExport aEventsElemt(mrExport, XML_NAMESPACE_DRAW, XML_GLUE_POINT, true, true);
1289  }
1290  }
1291 }
1292 
1293 void XMLShapeExport::ImpExportSignatureLine(const uno::Reference<drawing::XShape>& xShape)
1294 {
1295  uno::Reference<beans::XPropertySet> xPropSet(xShape, uno::UNO_QUERY);
1296 
1297  bool bIsSignatureLine = false;
1298  xPropSet->getPropertyValue("IsSignatureLine") >>= bIsSignatureLine;
1299  if (!bIsSignatureLine)
1300  return;
1301 
1302  OUString aSignatureLineId;
1303  xPropSet->getPropertyValue("SignatureLineId") >>= aSignatureLineId;
1304  mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_ID, aSignatureLineId);
1305 
1306  OUString aSuggestedSignerName;
1307  xPropSet->getPropertyValue("SignatureLineSuggestedSignerName") >>= aSuggestedSignerName;
1308  if (!aSuggestedSignerName.isEmpty())
1310 
1311  OUString aSuggestedSignerTitle;
1312  xPropSet->getPropertyValue("SignatureLineSuggestedSignerTitle") >>= aSuggestedSignerTitle;
1313  if (!aSuggestedSignerTitle.isEmpty())
1315 
1316  OUString aSuggestedSignerEmail;
1317  xPropSet->getPropertyValue("SignatureLineSuggestedSignerEmail") >>= aSuggestedSignerEmail;
1318  if (!aSuggestedSignerEmail.isEmpty())
1320 
1321  OUString aSigningInstructions;
1322  xPropSet->getPropertyValue("SignatureLineSigningInstructions") >>= aSigningInstructions;
1323  if (!aSigningInstructions.isEmpty())
1325 
1326  bool bShowSignDate = false;
1327  xPropSet->getPropertyValue("SignatureLineShowSignDate") >>= bShowSignDate;
1329  bShowSignDate ? XML_TRUE : XML_FALSE);
1330 
1331  bool bCanAddComment = false;
1332  xPropSet->getPropertyValue("SignatureLineCanAddComment") >>= bCanAddComment;
1334  bCanAddComment ? XML_TRUE : XML_FALSE);
1335 
1336  SvXMLElementExport aSignatureLineElement(mrExport, XML_NAMESPACE_LO_EXT, XML_SIGNATURELINE, true,
1337  true);
1338 }
1339 
1340 void XMLShapeExport::ImpExportQRCode(const uno::Reference<drawing::XShape>& xShape)
1341 {
1342  uno::Reference<beans::XPropertySet> xPropSet(xShape, uno::UNO_QUERY);
1343 
1344  uno::Any aAny = xPropSet->getPropertyValue("QRCodeProperties");
1345 
1346  css::drawing::QRCode aQRCode;
1347  if(!(aAny >>= aQRCode))
1348  return;
1349 
1351  /* Export QR Code as per customised schema, @see OpenDocument-schema-v1.3+libreoffice */
1352  OUString temp;
1353  switch(aQRCode.ErrorCorrection){
1354  case css::drawing::QRCodeErrorCorrection::LOW :
1355  temp = "low";
1356  break;
1357  case css::drawing::QRCodeErrorCorrection::MEDIUM:
1358  temp = "medium";
1359  break;
1360  case css::drawing::QRCodeErrorCorrection::QUARTILE:
1361  temp = "quartile";
1362  break;
1363  case css::drawing::QRCodeErrorCorrection::HIGH:
1364  temp = "high";
1365  break;
1366  }
1368  mrExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_QRCODE_BORDER, OUString::number(aQRCode.Border));
1369 
1371  true);
1372 }
1373 
1375 {
1377 
1378  // construct PropertySetMapper
1380  static_cast<XMLShapeExportPropertyMapper*>(xPropertySetMapper.get())->SetAutoStyles( false );
1381 
1382  // chain text attributes
1383  xPropertySetMapper->ChainExportMapper(XMLTextParagraphExport::CreateParaExtPropMapper(mrExport));
1384 
1385  // chain special Writer/text frame default attributes
1386  xPropertySetMapper->ChainExportMapper(XMLTextParagraphExport::CreateParaDefaultExtPropMapper(mrExport));
1387 
1388  // write graphic family default style
1389  uno::Reference< lang::XMultiServiceFactory > xFact( mrExport.GetModel(), uno::UNO_QUERY );
1390  if( !xFact.is() )
1391  return;
1392 
1393  try
1394  {
1395  uno::Reference< beans::XPropertySet > xDefaults( xFact->createInstance("com.sun.star.drawing.Defaults"), uno::UNO_QUERY );
1396  if( xDefaults.is() )
1397  {
1398  aStEx->exportDefaultStyle( xDefaults, XML_STYLE_FAMILY_SD_GRAPHICS_NAME, xPropertySetMapper );
1399 
1400  // write graphic family styles
1401  aStEx->exportStyleFamily("graphics", OUString(XML_STYLE_FAMILY_SD_GRAPHICS_NAME), xPropertySetMapper, false, XmlStyleFamily::SD_GRAPHICS_ID);
1402  }
1403  }
1404  catch(const lang::ServiceNotRegisteredException&)
1405  {
1406  }
1407 }
1408 
1409 void XMLShapeExport::onExport( const css::uno::Reference < css::drawing::XShape >& )
1410 {
1411 }
1412 
1414 {
1415  if( !mxShapeTableExport.is() )
1416  {
1418  rtl::Reference < XMLPropertySetMapper > xMapper( new XMLShapePropertySetMapper( xFactory, true ) );
1419  mrExport.GetTextParagraphExport(); // get or create text paragraph export
1421  mxShapeTableExport = new XMLTableExport( mrExport, xPropertySetMapper, xFactory );
1422  }
1423 
1424  return mxShapeTableExport;
1425 }
1426 
1427 void XMLShapeExport::ImpExportNewTrans(const uno::Reference< beans::XPropertySet >& xPropSet,
1428  XMLShapeExportFlags nFeatures, awt::Point* pRefPoint)
1429 {
1430  // get matrix
1431  ::basegfx::B2DHomMatrix aMatrix;
1432  ImpExportNewTrans_GetB2DHomMatrix(aMatrix, xPropSet);
1433 
1434  // decompose and correct about pRefPoint
1435  ::basegfx::B2DTuple aTRScale;
1436  double fTRShear(0.0);
1437  double fTRRotate(0.0);
1438  ::basegfx::B2DTuple aTRTranslate;
1439  ImpExportNewTrans_DecomposeAndRefPoint(aMatrix, aTRScale, fTRShear, fTRRotate, aTRTranslate, pRefPoint);
1440 
1441  // use features and write
1442  ImpExportNewTrans_FeaturesAndWrite(aTRScale, fTRShear, fTRRotate, aTRTranslate, nFeatures);
1443 }
1444 
1446  const uno::Reference< beans::XPropertySet >& xPropSet)
1447 {
1448  /* Get <TransformationInHoriL2R>, if it exist
1449  and if the document is exported into the OpenOffice.org file format.
1450  This property only exists at service css::text::Shape - the
1451  Writer UNO service for shapes.
1452  This code is needed, because the positioning attributes in the
1453  OpenOffice.org file format are given in horizontal left-to-right layout
1454  regardless the layout direction the shape is in. In the OASIS Open Office
1455  file format the positioning attributes are correctly given in the layout
1456  direction the shape is in. Thus, this code provides the conversion from
1457  the OASIS Open Office file format to the OpenOffice.org file format. (#i28749#)
1458  */
1459  uno::Any aAny;
1460  if ( !( GetExport().getExportFlags() & SvXMLExportFlags::OASIS ) &&
1461  xPropSet->getPropertySetInfo()->hasPropertyByName("TransformationInHoriL2R") )
1462  {
1463  aAny = xPropSet->getPropertyValue("TransformationInHoriL2R");
1464  }
1465  else
1466  {
1467  aAny = xPropSet->getPropertyValue("Transformation");
1468  }
1469  drawing::HomogenMatrix3 aMatrix;
1470  aAny >>= aMatrix;
1471 
1472  rMatrix.set(0, 0, aMatrix.Line1.Column1);
1473  rMatrix.set(0, 1, aMatrix.Line1.Column2);
1474  rMatrix.set(0, 2, aMatrix.Line1.Column3);
1475  rMatrix.set(1, 0, aMatrix.Line2.Column1);
1476  rMatrix.set(1, 1, aMatrix.Line2.Column2);
1477  rMatrix.set(1, 2, aMatrix.Line2.Column3);
1478  rMatrix.set(2, 0, aMatrix.Line3.Column1);
1479  rMatrix.set(2, 1, aMatrix.Line3.Column2);
1480  rMatrix.set(2, 2, aMatrix.Line3.Column3);
1481 }
1482 
1483 void XMLShapeExport::ImpExportNewTrans_DecomposeAndRefPoint(const ::basegfx::B2DHomMatrix& rMatrix, ::basegfx::B2DTuple& rTRScale,
1484  double& fTRShear, double& fTRRotate, ::basegfx::B2DTuple& rTRTranslate, css::awt::Point* pRefPoint)
1485 {
1486  // decompose matrix
1487  rMatrix.decompose(rTRScale, rTRTranslate, fTRRotate, fTRShear);
1488 
1489  // correct translation about pRefPoint
1490  if(pRefPoint)
1491  {
1492  rTRTranslate -= ::basegfx::B2DTuple(pRefPoint->X, pRefPoint->Y);
1493  }
1494 }
1495 
1497  double fTRRotate, ::basegfx::B2DTuple const & rTRTranslate, const XMLShapeExportFlags nFeatures)
1498 {
1499  // always write Size (rTRScale) since this statement carries the union
1500  // of the object
1501  OUString aStr;
1502  OUStringBuffer sStringBuffer;
1503  ::basegfx::B2DTuple aTRScale(rTRScale);
1504 
1505  // svg: width
1506  if(!(nFeatures & XMLShapeExportFlags::WIDTH))
1507  {
1508  aTRScale.setX(1.0);
1509  }
1510  else
1511  {
1512  if( aTRScale.getX() > 0.0 )
1513  aTRScale.setX(aTRScale.getX() - 1.0);
1514  else if( aTRScale.getX() < 0.0 )
1515  aTRScale.setX(aTRScale.getX() + 1.0);
1516  }
1517 
1519  FRound(aTRScale.getX()));
1520  aStr = sStringBuffer.makeStringAndClear();
1522 
1523  // svg: height
1524  if(!(nFeatures & XMLShapeExportFlags::HEIGHT))
1525  {
1526  aTRScale.setY(1.0);
1527  }
1528  else
1529  {
1530  if( aTRScale.getY() > 0.0 )
1531  aTRScale.setY(aTRScale.getY() - 1.0);
1532  else if( aTRScale.getY() < 0.0 )
1533  aTRScale.setY(aTRScale.getY() + 1.0);
1534  }
1535 
1537  FRound(aTRScale.getY()));
1538  aStr = sStringBuffer.makeStringAndClear();
1540 
1541  // decide if transformation is necessary
1542  bool bTransformationIsNecessary(fTRShear != 0.0 || fTRRotate != 0.0);
1543 
1544  if(bTransformationIsNecessary)
1545  {
1546  // write transformation, but WITHOUT scale which is exported as size above
1547  SdXMLImExTransform2D aTransform;
1548 
1549  aTransform.AddSkewX(atan(fTRShear));
1550 
1551  // #i78696#
1552  // fTRRotate is mathematically correct, but due to the error
1553  // we export/import it mirrored. Since the API implementation is fixed and
1554  // uses the correctly oriented angle, it is necessary for compatibility to
1555  // mirror the angle here to stay at the old behaviour. There is a follow-up
1556  // task (#i78698#) to fix this in the next ODF FileFormat version
1557  aTransform.AddRotate(-fTRRotate);
1558 
1559  aTransform.AddTranslate(rTRTranslate);
1560 
1561  // does transformation need to be exported?
1562  if(aTransform.NeedsAction())
1564  }
1565  else
1566  {
1567  // no shear, no rotate; just add object position to export and we are done
1568  if(nFeatures & XMLShapeExportFlags::X)
1569  {
1570  // svg: x
1572  FRound(rTRTranslate.getX()));
1573  aStr = sStringBuffer.makeStringAndClear();
1575  }
1576 
1577  if(nFeatures & XMLShapeExportFlags::Y)
1578  {
1579  // svg: y
1581  FRound(rTRTranslate.getY()));
1582  aStr = sStringBuffer.makeStringAndClear();
1584  }
1585  }
1586 }
1587 
1588 bool XMLShapeExport::ImpExportPresentationAttributes( const uno::Reference< beans::XPropertySet >& xPropSet, const OUString& rClass )
1589 {
1590  bool bIsEmpty = false;
1591 
1592  // write presentation class entry
1594 
1595  if( xPropSet.is() )
1596  {
1597  uno::Reference< beans::XPropertySetInfo > xPropSetInfo( xPropSet->getPropertySetInfo() );
1598 
1599 
1600  // is empty pres. shape?
1601  if( xPropSetInfo.is() && xPropSetInfo->hasPropertyByName("IsEmptyPresentationObject"))
1602  {
1603  xPropSet->getPropertyValue("IsEmptyPresentationObject") >>= bIsEmpty;
1604  if( bIsEmpty )
1606  }
1607 
1608  // is user-transformed?
1609  if( xPropSetInfo.is() && xPropSetInfo->hasPropertyByName("IsPlaceholderDependent"))
1610  {
1611  bool bTemp = false;
1612  xPropSet->getPropertyValue("IsPlaceholderDependent") >>= bTemp;
1613  if(!bTemp)
1615  }
1616  }
1617 
1618  return bIsEmpty;
1619 }
1620 
1621 void XMLShapeExport::ImpExportText( const uno::Reference< drawing::XShape >& xShape, TextPNS eExtensionNS )
1622 {
1623  if (eExtensionNS == TextPNS::EXTENSION)
1624  {
1626  {
1627  return; // do not export to ODF 1.1/1.2/1.3
1628  }
1629  }
1630  uno::Reference< text::XText > xText( xShape, uno::UNO_QUERY );
1631  if( xText.is() )
1632  {
1633  uno::Reference< container::XEnumerationAccess > xEnumAccess( xShape, uno::UNO_QUERY );
1634  if( xEnumAccess.is() && xEnumAccess->hasElements() )
1635  mrExport.GetTextParagraphExport()->exportText( xText, false, true, eExtensionNS );
1636  }
1637 }
1638 
1639 namespace {
1640 
1641 enum class Found {
1642  NONE = 0x0000,
1643  CLICKACTION = 0x0001,
1644  BOOKMARK = 0x0002,
1645  EFFECT = 0x0004,
1646  PLAYFULL = 0x0008,
1647  VERB = 0x0010,
1648  SOUNDURL = 0x0020,
1649  SPEED = 0x0040,
1650  CLICKEVENTTYPE = 0x0080,
1651  MACRO = 0x0100,
1652  LIBRARY = 0x0200,
1653 };
1654 
1655 }
1656 
1657 namespace o3tl {
1658  template<> struct typed_flags<Found> : is_typed_flags<Found, 0x03ff> {};
1659 }
1660 
1661 void XMLShapeExport::ImpExportEvents( const uno::Reference< drawing::XShape >& xShape )
1662 {
1663  uno::Reference< document::XEventsSupplier > xEventsSupplier( xShape, uno::UNO_QUERY );
1664  if( !xEventsSupplier.is() )
1665  return;
1666 
1667  uno::Reference< container::XNameAccess > xEvents = xEventsSupplier->getEvents();
1668  SAL_WARN_IF( !xEvents.is(), "xmloff", "XEventsSupplier::getEvents() returned NULL" );
1669  if( !xEvents.is() )
1670  return;
1671 
1672  Found nFound = Found::NONE;
1673 
1674  OUString aClickEventType;
1675  presentation::ClickAction eClickAction = presentation::ClickAction_NONE;
1676  presentation::AnimationEffect eEffect = presentation::AnimationEffect_NONE;
1677  presentation::AnimationSpeed eSpeed = presentation::AnimationSpeed_SLOW;
1678  OUString aStrSoundURL;
1679  bool bPlayFull = false;
1680  sal_Int32 nVerb = 0;
1681  OUString aStrMacro;
1682  OUString aStrLibrary;
1683  OUString aStrBookmark;
1684 
1685  uno::Sequence< beans::PropertyValue > aClickProperties;
1686  if( xEvents->hasByName( gsOnClick ) && (xEvents->getByName( gsOnClick ) >>= aClickProperties) )
1687  {
1688  for( const auto& rProperty : std::as_const(aClickProperties) )
1689  {
1690  if( !( nFound & Found::CLICKEVENTTYPE ) && rProperty.Name == gsEventType )
1691  {
1692  if( rProperty.Value >>= aClickEventType )
1693  nFound |= Found::CLICKEVENTTYPE;
1694  }
1695  else if( !( nFound & Found::CLICKACTION ) && rProperty.Name == gsClickAction )
1696  {
1697  if( rProperty.Value >>= eClickAction )
1698  nFound |= Found::CLICKACTION;
1699  }
1700  else if( !( nFound & Found::MACRO ) && ( rProperty.Name == gsMacroName || rProperty.Name == gsScript ) )
1701  {
1702  if( rProperty.Value >>= aStrMacro )
1703  nFound |= Found::MACRO;
1704  }
1705  else if( !( nFound & Found::LIBRARY ) && rProperty.Name == gsLibrary )
1706  {
1707  if( rProperty.Value >>= aStrLibrary )
1708  nFound |= Found::LIBRARY;
1709  }
1710  else if( !( nFound & Found::EFFECT ) && rProperty.Name == gsEffect )
1711  {
1712  if( rProperty.Value >>= eEffect )
1713  nFound |= Found::EFFECT;
1714  }
1715  else if( !( nFound & Found::BOOKMARK ) && rProperty.Name == gsBookmark )
1716  {
1717  if( rProperty.Value >>= aStrBookmark )
1718  nFound |= Found::BOOKMARK;
1719  }
1720  else if( !( nFound & Found::SPEED ) && rProperty.Name == gsSpeed )
1721  {
1722  if( rProperty.Value >>= eSpeed )
1723  nFound |= Found::SPEED;
1724  }
1725  else if( !( nFound & Found::SOUNDURL ) && rProperty.Name == gsSoundURL )
1726  {
1727  if( rProperty.Value >>= aStrSoundURL )
1728  nFound |= Found::SOUNDURL;
1729  }
1730  else if( !( nFound & Found::PLAYFULL ) && rProperty.Name == gsPlayFull )
1731  {
1732  if( rProperty.Value >>= bPlayFull )
1733  nFound |= Found::PLAYFULL;
1734  }
1735  else if( !( nFound & Found::VERB ) && rProperty.Name == gsVerb )
1736  {
1737  if( rProperty.Value >>= nVerb )
1738  nFound |= Found::VERB;
1739  }
1740  }
1741  }
1742 
1743  // create the XML elements
1744 
1745  if( aClickEventType == gsPresentation )
1746  {
1747  if( !(nFound & Found::CLICKACTION) || (eClickAction == presentation::ClickAction_NONE) )
1748  return;
1749 
1751 
1752  enum XMLTokenEnum eStrAction;
1753 
1754  switch( eClickAction )
1755  {
1756  case presentation::ClickAction_PREVPAGE: eStrAction = XML_PREVIOUS_PAGE; break;
1757  case presentation::ClickAction_NEXTPAGE: eStrAction = XML_NEXT_PAGE; break;
1758  case presentation::ClickAction_FIRSTPAGE: eStrAction = XML_FIRST_PAGE; break;
1759  case presentation::ClickAction_LASTPAGE: eStrAction = XML_LAST_PAGE; break;
1760  case presentation::ClickAction_INVISIBLE: eStrAction = XML_HIDE; break;
1761  case presentation::ClickAction_STOPPRESENTATION:eStrAction = XML_STOP; break;
1762  case presentation::ClickAction_PROGRAM: eStrAction = XML_EXECUTE; break;
1763  case presentation::ClickAction_BOOKMARK: eStrAction = XML_SHOW; break;
1764  case presentation::ClickAction_DOCUMENT: eStrAction = XML_SHOW; break;
1765  case presentation::ClickAction_MACRO: eStrAction = XML_EXECUTE_MACRO; break;
1766  case presentation::ClickAction_VERB: eStrAction = XML_VERB; break;
1767  case presentation::ClickAction_VANISH: eStrAction = XML_FADE_OUT; break;
1768  case presentation::ClickAction_SOUND: eStrAction = XML_SOUND; break;
1769  default:
1770  OSL_FAIL( "unknown presentation::ClickAction found!" );
1771  eStrAction = XML_UNKNOWN;
1772  }
1773 
1774  OUString aEventQName(
1776  XML_NAMESPACE_DOM, "click" ) );
1779 
1780  if( eClickAction == presentation::ClickAction_VANISH )
1781  {
1782  if( nFound & Found::EFFECT )
1783  {
1784  XMLEffect eKind;
1785  XMLEffectDirection eDirection;
1786  sal_Int16 nStartScale;
1787  bool bIn;
1788 
1789  SdXMLImplSetEffect( eEffect, eKind, eDirection, nStartScale, bIn );
1790 
1791  if( eKind != EK_none )
1792  {
1795  }
1796 
1797  if( eDirection != ED_none )
1798  {
1801  }
1802 
1803  if( nStartScale != -1 )
1804  {
1807  }
1808  }
1809 
1810  if( nFound & Found::SPEED && eEffect != presentation::AnimationEffect_NONE )
1811  {
1812  if( eSpeed != presentation::AnimationSpeed_MEDIUM )
1813  {
1816  }
1817  }
1818  }
1819 
1820  if( eClickAction == presentation::ClickAction_PROGRAM ||
1821  eClickAction == presentation::ClickAction_BOOKMARK ||
1822  eClickAction == presentation::ClickAction_DOCUMENT )
1823  {
1824  if( eClickAction == presentation::ClickAction_BOOKMARK )
1825  msBuffer.append( '#' );
1826 
1827  msBuffer.append( aStrBookmark );
1828  mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, GetExport().GetRelativeReference(msBuffer.makeStringAndClear()) );
1832  }
1833 
1834  if( ( nFound & Found::VERB ) && eClickAction == presentation::ClickAction_VERB )
1835  {
1836  msBuffer.append( nVerb );
1838  }
1839 
1841 
1842  if( eClickAction == presentation::ClickAction_VANISH || eClickAction == presentation::ClickAction_SOUND )
1843  {
1844  if( ( nFound & Found::SOUNDURL ) && !aStrSoundURL.isEmpty() )
1845  {
1846  mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, GetExport().GetRelativeReference(aStrSoundURL) );
1850  if( nFound & Found::PLAYFULL && bPlayFull )
1852 
1854  }
1855  }
1856  }
1857  else if( aClickEventType == gsStarBasic )
1858  {
1859  if( nFound & Found::MACRO )
1860  {
1862 
1866  "starbasic" ) );
1867  OUString aEventQName(
1869  XML_NAMESPACE_DOM, "click" ) );
1871 
1872  if( nFound & Found::LIBRARY )
1873  {
1874  const OUString& sLocation( GetXMLToken(
1875  (aStrLibrary.equalsIgnoreAsciiCase("StarOffice") ||
1876  aStrLibrary.equalsIgnoreAsciiCase("application") ) ? XML_APPLICATION
1877  : XML_DOCUMENT ) );
1879  sLocation + ":" + aStrMacro);
1880  }
1881  else
1882  {
1884  }
1885 
1887  }
1888  }
1889  else if( aClickEventType == gsScript )
1890  {
1891  if( nFound & Found::MACRO )
1892  {
1894 
1897  OUString aEventQName(
1899  XML_NAMESPACE_DOM, "click" ) );
1903 
1905  }
1906  }
1907 }
1908 
1910 void XMLShapeExport::ImpExportDescription( const uno::Reference< drawing::XShape >& xShape )
1911 {
1912  try
1913  {
1914  OUString aTitle;
1915  OUString aDescription;
1916 
1917  uno::Reference< beans::XPropertySet > xProps( xShape, uno::UNO_QUERY_THROW );
1918  xProps->getPropertyValue("Title") >>= aTitle;
1919  xProps->getPropertyValue("Description") >>= aDescription;
1920 
1921  if(!aTitle.isEmpty())
1922  {
1923  SvXMLElementExport aEventElemt(mrExport, XML_NAMESPACE_SVG, XML_TITLE, true, false);
1924  mrExport.Characters( aTitle );
1925  }
1926 
1927  if(!aDescription.isEmpty())
1928  {
1929  SvXMLElementExport aEventElemt(mrExport, XML_NAMESPACE_SVG, XML_DESC, true, false );
1930  mrExport.Characters( aDescription );
1931  }
1932  }
1933  catch( uno::Exception& )
1934  {
1935  DBG_UNHANDLED_EXCEPTION( "xmloff", "exporting Title and/or Description for shape" );
1936  }
1937 }
1938 
1939 void XMLShapeExport::ImpExportGroupShape( const uno::Reference< drawing::XShape >& xShape, XMLShapeExportFlags nFeatures, awt::Point* pRefPoint)
1940 {
1941  uno::Reference< drawing::XShapes > xShapes(xShape, uno::UNO_QUERY);
1942  if(!(xShapes.is() && xShapes->getCount()))
1943  return;
1944 
1945  // write group shape
1946  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
1947  SvXMLElementExport aPGR(mrExport, XML_NAMESPACE_DRAW, XML_G, bCreateNewline, true);
1948 
1949  ImpExportDescription( xShape ); // #i68101#
1950  ImpExportEvents( xShape );
1951  ImpExportGluePoints( xShape );
1952 
1953  // #89764# if export of position is suppressed for group shape,
1954  // positions of contained objects should be written relative to
1955  // the upper left edge of the group.
1956  awt::Point aUpperLeft;
1957 
1958  if(!(nFeatures & XMLShapeExportFlags::POSITION))
1959  {
1960  nFeatures |= XMLShapeExportFlags::POSITION;
1961  aUpperLeft = xShape->getPosition();
1962  pRefPoint = &aUpperLeft;
1963  }
1964 
1965  // write members
1966  exportShapes( xShapes, nFeatures, pRefPoint );
1967 }
1968 
1970  const uno::Reference< drawing::XShape >& xShape,
1971  XmlShapeType eShapeType, XMLShapeExportFlags nFeatures, awt::Point* pRefPoint)
1972 {
1973  const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
1974  if(!xPropSet.is())
1975  return;
1976 
1977  // presentation attribute (if presentation)
1978  bool bIsPresShape(false);
1979  bool bIsEmptyPresObj(false);
1980  OUString aStr;
1981 
1982  switch(eShapeType)
1983  {
1985  {
1986  aStr = GetXMLToken(XML_SUBTITLE);
1987  bIsPresShape = true;
1988  break;
1989  }
1991  {
1992  aStr = GetXMLToken(XML_TITLE);
1993  bIsPresShape = true;
1994  break;
1995  }
1997  {
1999  bIsPresShape = true;
2000  break;
2001  }
2003  {
2004  aStr = GetXMLToken(XML_NOTES);
2005  bIsPresShape = true;
2006  break;
2007  }
2009  {
2010  aStr = GetXMLToken(XML_HEADER);
2011  bIsPresShape = true;
2012  break;
2013  }
2015  {
2016  aStr = GetXMLToken(XML_FOOTER);
2017  bIsPresShape = true;
2018  break;
2019  }
2021  {
2022  aStr = GetXMLToken(XML_PAGE_NUMBER);
2023  bIsPresShape = true;
2024  break;
2025  }
2027  {
2028  aStr = GetXMLToken(XML_DATE_TIME);
2029  bIsPresShape = true;
2030  break;
2031  }
2032  default:
2033  break;
2034  }
2035 
2036  // Transformation
2037  ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);
2038 
2039  if(bIsPresShape)
2040  bIsEmptyPresObj = ImpExportPresentationAttributes( xPropSet, aStr );
2041 
2042  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
2044  XML_FRAME, bCreateNewline, true );
2045 
2046  // evtl. corner radius?
2047  sal_Int32 nCornerRadius(0);
2048  xPropSet->getPropertyValue("CornerRadius") >>= nCornerRadius;
2049  if(nCornerRadius)
2050  {
2051  OUStringBuffer sStringBuffer;
2053  nCornerRadius);
2054  mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_CORNER_RADIUS, sStringBuffer.makeStringAndClear());
2055  }
2056 
2057  {
2058  // write text-box
2060  if(!bIsEmptyPresObj)
2061  ImpExportText( xShape );
2062  }
2063 
2064  ImpExportDescription( xShape ); // #i68101#
2065  ImpExportEvents( xShape );
2066  ImpExportGluePoints( xShape );
2067 
2068 }
2069 
2071  const uno::Reference< drawing::XShape >& xShape,
2072  XMLShapeExportFlags nFeatures, css::awt::Point* pRefPoint)
2073 {
2074  const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
2075  if(!xPropSet.is())
2076  return;
2077 
2078  // Transformation
2079  ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);
2080 
2081  // evtl. corner radius?
2082  sal_Int32 nCornerRadius(0);
2083  xPropSet->getPropertyValue("CornerRadius") >>= nCornerRadius;
2084  if(nCornerRadius)
2085  {
2086  OUStringBuffer sStringBuffer;
2088  nCornerRadius);
2089  mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_CORNER_RADIUS, sStringBuffer.makeStringAndClear());
2090  }
2091 
2092  // write rectangle
2093  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
2094  SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DRAW, XML_RECT, bCreateNewline, true);
2095 
2096  ImpExportDescription( xShape ); // #i68101#
2097  ImpExportEvents( xShape );
2098  ImpExportGluePoints( xShape );
2099  ImpExportText( xShape );
2100 }
2101 
2103  const uno::Reference< drawing::XShape >& xShape,
2104  XMLShapeExportFlags nFeatures, awt::Point* pRefPoint)
2105 {
2106  const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
2107  if(!xPropSet.is())
2108  return;
2109 
2110  OUString aStr;
2111  OUStringBuffer sStringBuffer;
2112  awt::Point aStart(0,0);
2113  awt::Point aEnd(1,1);
2114 
2115  // #85920# use 'Geometry' to get the points of the line
2116  // since this slot take anchor pos into account.
2117 
2118  // get matrix
2119  ::basegfx::B2DHomMatrix aMatrix;
2120  ImpExportNewTrans_GetB2DHomMatrix(aMatrix, xPropSet);
2121 
2122  // decompose and correct about pRefPoint
2123  ::basegfx::B2DTuple aTRScale;
2124  double fTRShear(0.0);
2125  double fTRRotate(0.0);
2126  ::basegfx::B2DTuple aTRTranslate;
2127  ImpExportNewTrans_DecomposeAndRefPoint(aMatrix, aTRScale, fTRShear, fTRRotate, aTRTranslate, pRefPoint);
2128 
2129  // create base position
2130  awt::Point aBasePosition(FRound(aTRTranslate.getX()), FRound(aTRTranslate.getY()));
2131 
2132  // get the two points
2133  uno::Any aAny(xPropSet->getPropertyValue("Geometry"));
2134  if (auto pSourcePolyPolygon
2135  = o3tl::tryAccess<drawing::PointSequenceSequence>(aAny))
2136  {
2137  if (pSourcePolyPolygon->getLength() > 0)
2138  {
2139  const drawing::PointSequence& rInnerSequence = (*pSourcePolyPolygon)[0];
2140  if (rInnerSequence.hasElements())
2141  {
2142  const awt::Point& rPoint = rInnerSequence[0];
2143  aStart = awt::Point(rPoint.X + aBasePosition.X, rPoint.Y + aBasePosition.Y);
2144  }
2145  if (rInnerSequence.getLength() > 1)
2146  {
2147  const awt::Point& rPoint = rInnerSequence[1];
2148  aEnd = awt::Point(rPoint.X + aBasePosition.X, rPoint.Y + aBasePosition.Y);
2149  }
2150  }
2151  }
2152 
2153  if( nFeatures & XMLShapeExportFlags::X )
2154  {
2155  // svg: x1
2157  aStart.X);
2158  aStr = sStringBuffer.makeStringAndClear();
2160  }
2161  else
2162  {
2163  aEnd.X -= aStart.X;
2164  }
2165 
2166  if( nFeatures & XMLShapeExportFlags::Y )
2167  {
2168  // svg: y1
2170  aStart.Y);
2171  aStr = sStringBuffer.makeStringAndClear();
2173  }
2174  else
2175  {
2176  aEnd.Y -= aStart.Y;
2177  }
2178 
2179  // svg: x2
2181  aEnd.X);
2182  aStr = sStringBuffer.makeStringAndClear();
2184 
2185  // svg: y2
2187  aEnd.Y);
2188  aStr = sStringBuffer.makeStringAndClear();
2190 
2191  // write line
2192  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
2193  SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DRAW, XML_LINE, bCreateNewline, true);
2194 
2195  ImpExportDescription( xShape ); // #i68101#
2196  ImpExportEvents( xShape );
2197  ImpExportGluePoints( xShape );
2198  ImpExportText( xShape );
2199 
2200 }
2201 
2203  const uno::Reference< drawing::XShape >& xShape,
2204  XMLShapeExportFlags nFeatures, awt::Point* pRefPoint)
2205 {
2206  const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
2207  if(!xPropSet.is())
2208  return;
2209 
2210  // get size to decide between Circle and Ellipse
2211  awt::Size aSize = xShape->getSize();
2212  sal_Int32 nRx((aSize.Width + 1) / 2);
2213  sal_Int32 nRy((aSize.Height + 1) / 2);
2214  bool bCircle(nRx == nRy);
2215 
2216  // Transformation
2217  ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);
2218 
2219  drawing::CircleKind eKind = drawing::CircleKind_FULL;
2220  xPropSet->getPropertyValue("CircleKind") >>= eKind;
2221  if( eKind != drawing::CircleKind_FULL )
2222  {
2223  OUStringBuffer sStringBuffer;
2224  sal_Int32 nStartAngle = 0;
2225  sal_Int32 nEndAngle = 0;
2226  xPropSet->getPropertyValue("CircleStartAngle") >>= nStartAngle;
2227  xPropSet->getPropertyValue("CircleEndAngle") >>= nEndAngle;
2228 
2229  const double dStartAngle = nStartAngle / 100.0;
2230  const double dEndAngle = nEndAngle / 100.0;
2231 
2232  // export circle kind
2234  mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_KIND, sStringBuffer.makeStringAndClear() );
2235 
2236  // export start angle
2237  ::sax::Converter::convertDouble( sStringBuffer, dStartAngle );
2238  mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_START_ANGLE, sStringBuffer.makeStringAndClear() );
2239 
2240  // export end angle
2241  ::sax::Converter::convertDouble( sStringBuffer, dEndAngle );
2242  mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_END_ANGLE, sStringBuffer.makeStringAndClear() );
2243  }
2244 
2245  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
2246 
2247  // write ellipse or circle
2249  bCircle ? XML_CIRCLE : XML_ELLIPSE,
2250  bCreateNewline, true);
2251 
2252  ImpExportDescription( xShape ); // #i68101#
2253  ImpExportEvents( xShape );
2254  ImpExportGluePoints( xShape );
2255  ImpExportText( xShape );
2256 
2257 }
2258 
2260  const uno::Reference< drawing::XShape >& xShape,
2261  XmlShapeType eShapeType, XMLShapeExportFlags nFeatures, awt::Point* pRefPoint)
2262 {
2263  const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
2264  if(!xPropSet.is())
2265  return;
2266 
2267  bool bBezier(eShapeType == XmlShapeTypeDrawClosedBezierShape
2268  || eShapeType == XmlShapeTypeDrawOpenBezierShape);
2269 
2270  // get matrix
2271  ::basegfx::B2DHomMatrix aMatrix;
2272  ImpExportNewTrans_GetB2DHomMatrix(aMatrix, xPropSet);
2273 
2274  // decompose and correct about pRefPoint
2275  ::basegfx::B2DTuple aTRScale;
2276  double fTRShear(0.0);
2277  double fTRRotate(0.0);
2278  ::basegfx::B2DTuple aTRTranslate;
2279  ImpExportNewTrans_DecomposeAndRefPoint(aMatrix, aTRScale, fTRShear, fTRRotate, aTRTranslate, pRefPoint);
2280 
2281  // use features and write
2282  ImpExportNewTrans_FeaturesAndWrite(aTRScale, fTRShear, fTRRotate, aTRTranslate, nFeatures);
2283 
2284  // create and export ViewBox
2285  awt::Size aSize(FRound(aTRScale.getX()), FRound(aTRScale.getY()));
2286  SdXMLImExViewBox aViewBox(0, 0, aSize.Width, aSize.Height);
2288 
2289  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
2290 
2291  // prepare name (with most used)
2293 
2294  if(bBezier)
2295  {
2296  // get PolygonBezier
2297  uno::Any aAny( xPropSet->getPropertyValue("Geometry") );
2298  const basegfx::B2DPolyPolygon aPolyPolygon(
2299  basegfx::utils::UnoPolyPolygonBezierCoordsToB2DPolyPolygon(*o3tl::doAccess<drawing::PolyPolygonBezierCoords>(aAny)));
2300 
2301  if(aPolyPolygon.count())
2302  {
2303  // complex polygon shape, write as svg:d
2304  const OUString aPolygonString(
2306  aPolyPolygon,
2307  true, // bUseRelativeCoordinates
2308  false, // bDetectQuadraticBeziers: not used in old, but maybe activated now
2309  true)); // bHandleRelativeNextPointCompatible
2310 
2311  // write point array
2312  mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_D, aPolygonString);
2313  }
2314  }
2315  else
2316  {
2317  // get non-bezier polygon
2318  uno::Any aAny( xPropSet->getPropertyValue("Geometry") );
2319  const basegfx::B2DPolyPolygon aPolyPolygon(
2320  basegfx::utils::UnoPointSequenceSequenceToB2DPolyPolygon(*o3tl::doAccess<drawing::PointSequenceSequence>(aAny)));
2321 
2322  if(!aPolyPolygon.areControlPointsUsed() && 1 == aPolyPolygon.count())
2323  {
2324  // simple polygon shape, can be written as svg:points sequence
2325  const basegfx::B2DPolygon& aPolygon(aPolyPolygon.getB2DPolygon(0));
2326  const OUString aPointString(basegfx::utils::exportToSvgPoints(aPolygon));
2327 
2328  // write point array
2330 
2331  // set name
2332  eName = aPolygon.isClosed() ? XML_POLYGON : XML_POLYLINE;
2333  }
2334  else
2335  {
2336  // complex polygon shape, write as svg:d
2337  const OUString aPolygonString(
2339  aPolyPolygon,
2340  true, // bUseRelativeCoordinates
2341  false, // bDetectQuadraticBeziers: not used in old, but maybe activated now
2342  true)); // bHandleRelativeNextPointCompatible
2343 
2344  // write point array
2345  mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_D, aPolygonString);
2346  }
2347  }
2348 
2349  // write object, but after attributes are added since this call will
2350  // consume all of these added attributes and the destructor will close the
2351  // scope. Also before text is added; this may add sub-scopes as needed
2352  SvXMLElementExport aOBJ(
2353  mrExport,
2355  eName,
2356  bCreateNewline,
2357  true);
2358 
2359  ImpExportDescription( xShape ); // #i68101#
2360  ImpExportEvents( xShape );
2361  ImpExportGluePoints( xShape );
2362  ImpExportText( xShape );
2363 
2364 }
2365 
2366 namespace
2367 {
2368 
2369 OUString getNameFromStreamURL(OUString const & rURL)
2370 {
2371  static const OUStringLiteral sPackageURL(u"vnd.sun.star.Package:");
2372 
2373  OUString sResult;
2374 
2375  if (rURL.match(sPackageURL))
2376  {
2377  OUString sRequestedName = rURL.copy(sPackageURL.getLength());
2378  sal_Int32 nLastIndex = sRequestedName.lastIndexOf('/') + 1;
2379  if ((nLastIndex > 0) && (nLastIndex < sRequestedName.getLength()))
2380  sRequestedName = sRequestedName.copy(nLastIndex);
2381  nLastIndex = sRequestedName.lastIndexOf('.');
2382  if (nLastIndex >= 0)
2383  sRequestedName = sRequestedName.copy(0, nLastIndex);
2384  if (!sRequestedName.isEmpty())
2385  sResult = sRequestedName;
2386  }
2387 
2388  return sResult;
2389 }
2390 
2391 } // end anonymous namespace
2392 
2394  const uno::Reference< drawing::XShape >& xShape,
2395  XmlShapeType eShapeType, XMLShapeExportFlags nFeatures, awt::Point* pRefPoint)
2396 {
2397  const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
2398  if(!xPropSet.is())
2399  return;
2400 
2401  bool bIsEmptyPresObj = false;
2402 
2403  // Transformation
2404  ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);
2405 
2406  if(eShapeType == XmlShapeTypePresGraphicObjectShape)
2407  bIsEmptyPresObj = ImpExportPresentationAttributes( xPropSet, GetXMLToken(XML_GRAPHIC) );
2408 
2409  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
2411  XML_FRAME, bCreateNewline, true );
2412 
2413  if (!bIsEmptyPresObj)
2414  {
2415  uno::Reference<graphic::XGraphic> xGraphic;
2416  OUString sOutMimeType;
2417 
2418  {
2419  OUString aStreamURL;
2420  xPropSet->getPropertyValue("GraphicStreamURL") >>= aStreamURL;
2421  OUString sRequestedName = getNameFromStreamURL(aStreamURL);
2422 
2423  xPropSet->getPropertyValue("Graphic") >>= xGraphic;
2424 
2425  OUString sInternalURL;
2426 
2427  if (xGraphic.is())
2428  sInternalURL = mrExport.AddEmbeddedXGraphic(xGraphic, sOutMimeType, sRequestedName);
2429 
2430  if (!sInternalURL.isEmpty())
2431  {
2432  // apply possible changed stream URL to embedded image object
2433  if (!sRequestedName.isEmpty())
2434  {
2435  OUString newStreamURL = "vnd.sun.star.Package:";
2436  if (sInternalURL[0] == '#')
2437  {
2438  newStreamURL += sInternalURL.subView(1, sInternalURL.getLength() - 1);
2439  }
2440  else
2441  {
2442  newStreamURL += sInternalURL;
2443  }
2444 
2445  if (newStreamURL != aStreamURL)
2446  {
2447  xPropSet->setPropertyValue("GraphicStreamURL", uno::Any(newStreamURL));
2448  }
2449  }
2450 
2455  }
2456  }
2457 
2458  {
2459  if (GetExport().getSaneDefaultVersion() > SvtSaveOptions::ODFSVER_012)
2460  {
2461  if (sOutMimeType.isEmpty())
2462  {
2463  GetExport().GetGraphicMimeTypeFromStream(xGraphic, sOutMimeType);
2464  }
2465  if (!sOutMimeType.isEmpty())
2466  { // ODF 1.3 OFFICE-3943
2468  SvtSaveOptions::ODFSVER_013 <= GetExport().getSaneDefaultVersion()
2471  "mime-type", sOutMimeType);
2472  }
2473  }
2474 
2475  SvXMLElementExport aElement(mrExport, XML_NAMESPACE_DRAW, XML_IMAGE, true, true);
2476 
2477  // optional office:binary-data
2478  if (xGraphic.is())
2479  {
2481  }
2482  if (!bIsEmptyPresObj)
2483  ImpExportText(xShape);
2484  }
2485 
2486  //Resolves: fdo#62461 put preferred image first above, followed by
2487  //fallback here
2488  const bool bAddReplacementImages = officecfg::Office::Common::Save::Graphic::AddReplacementImages::get();
2489  if( !bIsEmptyPresObj && bAddReplacementImages)
2490  {
2491  uno::Reference<graphic::XGraphic> xReplacementGraphic;
2492  xPropSet->getPropertyValue("ReplacementGraphic") >>= xReplacementGraphic;
2493 
2494  // If there is no url, then the graphic is empty
2495  if (xReplacementGraphic.is())
2496  {
2497  OUString aMimeType;
2498  const OUString aHref = mrExport.AddEmbeddedXGraphic(xReplacementGraphic, aMimeType);
2499 
2500  if (aMimeType.isEmpty())
2501  mrExport.GetGraphicMimeTypeFromStream(xReplacementGraphic, aMimeType);
2502 
2503  if (!aHref.isEmpty())
2504  {
2509  }
2510 
2511  if (!aMimeType.isEmpty() && GetExport().getSaneDefaultVersion() > SvtSaveOptions::ODFSVER_012)
2512  { // ODF 1.3 OFFICE-3943
2514  SvtSaveOptions::ODFSVER_013 <= GetExport().getSaneDefaultVersion()
2517  "mime-type", aMimeType);
2518  }
2519 
2520  SvXMLElementExport aElement(mrExport, XML_NAMESPACE_DRAW, XML_IMAGE, true, true);
2521 
2522  // optional office:binary-data
2523  mrExport.AddEmbeddedXGraphicAsBase64(xReplacementGraphic);
2524  }
2525  }
2526  }
2527 
2528  ImpExportEvents( xShape );
2529  ImpExportGluePoints( xShape );
2530 
2531  // image map
2532  GetExport().GetImageMapExport().Export( xPropSet );
2533  ImpExportDescription( xShape ); // #i68101#
2534 
2535  // Signature Line, QR Code - needs to be after the images!
2536  if (GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
2537  {
2538  ImpExportSignatureLine(xShape);
2539  ImpExportQRCode(xShape);
2540  }
2541 }
2542 
2544  const uno::Reference< drawing::XShape >& xShape,
2545  XmlShapeType eShapeType, XMLShapeExportFlags nFeatures, awt::Point* pRefPoint,
2546  SvXMLAttributeList* pAttrList )
2547 {
2548  ImpExportOLE2Shape( xShape, eShapeType, nFeatures, pRefPoint, pAttrList );
2549 }
2550 
2552  const uno::Reference< drawing::XShape >& xShape,
2553  XMLShapeExportFlags nFeatures, awt::Point* pRefPoint)
2554 {
2555  const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
2556  if(xPropSet.is())
2557  {
2558  // Transformation
2559  ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);
2560  }
2561 
2562  uno::Reference< drawing::XControlShape > xControl( xShape, uno::UNO_QUERY );
2563  SAL_WARN_IF( !xControl.is(), "xmloff", "Control shape is not supporting XControlShape" );
2564  if( xControl.is() )
2565  {
2566  uno::Reference< beans::XPropertySet > xControlModel( xControl->getControl(), uno::UNO_QUERY );
2567  SAL_WARN_IF( !xControlModel.is(), "xmloff", "Control shape has not XControlModel" );
2568  if( xControlModel.is() )
2569  {
2570  OUString sControlId = mrExport.GetFormExport()->getControlId( xControlModel );
2572  }
2573  }
2574 
2575  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
2576  SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DRAW, XML_CONTROL, bCreateNewline, true);
2577 
2578  ImpExportDescription( xShape ); // #i68101#
2579 }
2580 
2582  const uno::Reference< drawing::XShape >& xShape,
2583  XMLShapeExportFlags nFeatures /* = SEF_DEFAULT */, awt::Point* pRefPoint /* = NULL */)
2584 {
2585  uno::Reference< beans::XPropertySet > xProps( xShape, uno::UNO_QUERY );
2586 
2587  OUString aStr;
2588  OUStringBuffer sStringBuffer;
2589 
2590  // export connection kind
2591  drawing::ConnectorType eType = drawing::ConnectorType_STANDARD;
2592  uno::Any aAny = xProps->getPropertyValue("EdgeKind");
2593  aAny >>= eType;
2594 
2595  if( eType != drawing::ConnectorType_STANDARD )
2596  {
2598  aStr = sStringBuffer.makeStringAndClear();
2600  }
2601 
2602  // export line skew
2603  sal_Int32 nDelta1 = 0, nDelta2 = 0, nDelta3 = 0;
2604 
2605  aAny = xProps->getPropertyValue("EdgeLine1Delta");
2606  aAny >>= nDelta1;
2607  aAny = xProps->getPropertyValue("EdgeLine2Delta");
2608  aAny >>= nDelta2;
2609  aAny = xProps->getPropertyValue("EdgeLine3Delta");
2610  aAny >>= nDelta3;
2611 
2612  if( nDelta1 != 0 || nDelta2 != 0 || nDelta3 != 0 )
2613  {
2615  nDelta1);
2616  if( nDelta2 != 0 || nDelta3 != 0 )
2617  {
2618  sStringBuffer.append( ' ' );
2620  nDelta2);
2621  if( nDelta3 != 0 )
2622  {
2623  sStringBuffer.append( ' ' );
2625  sStringBuffer, nDelta3);
2626  }
2627  }
2628 
2629  aStr = sStringBuffer.makeStringAndClear();
2631  }
2632 
2633  // export start and end point
2634  awt::Point aStart(0,0);
2635  awt::Point aEnd(1,1);
2636 
2637  /* Get <StartPositionInHoriL2R> and
2638  <EndPositionInHoriL2R>, if they exist and if the document is exported
2639  into the OpenOffice.org file format.
2640  These properties only exist at service css::text::Shape - the
2641  Writer UNO service for shapes.
2642  This code is needed, because the positioning attributes in the
2643  OpenOffice.org file format are given in horizontal left-to-right layout
2644  regardless the layout direction the shape is in. In the OASIS Open Office
2645  file format the positioning attributes are correctly given in the layout
2646  direction the shape is in. Thus, this code provides the conversion from
2647  the OASIS Open Office file format to the OpenOffice.org file format. (#i36248#)
2648  */
2649  if ( !( GetExport().getExportFlags() & SvXMLExportFlags::OASIS ) &&
2650  xProps->getPropertySetInfo()->hasPropertyByName("StartPositionInHoriL2R") &&
2651  xProps->getPropertySetInfo()->hasPropertyByName("EndPositionInHoriL2R") )
2652  {
2653  xProps->getPropertyValue("StartPositionInHoriL2R") >>= aStart;
2654  xProps->getPropertyValue("EndPositionInHoriL2R") >>= aEnd;
2655  }
2656  else
2657  {
2658  xProps->getPropertyValue("StartPosition") >>= aStart;
2659  xProps->getPropertyValue("EndPosition") >>= aEnd;
2660  }
2661 
2662  if( pRefPoint )
2663  {
2664  aStart.X -= pRefPoint->X;
2665  aStart.Y -= pRefPoint->Y;
2666  aEnd.X -= pRefPoint->X;
2667  aEnd.Y -= pRefPoint->Y;
2668  }
2669 
2670  if( nFeatures & XMLShapeExportFlags::X )
2671  {
2672  // svg: x1
2674  aStart.X);
2675  aStr = sStringBuffer.makeStringAndClear();
2677  }
2678  else
2679  {
2680  aEnd.X -= aStart.X;
2681  }
2682 
2683  if( nFeatures & XMLShapeExportFlags::Y )
2684  {
2685  // svg: y1
2687  aStart.Y);
2688  aStr = sStringBuffer.makeStringAndClear();
2690  }
2691  else
2692  {
2693  aEnd.Y -= aStart.Y;
2694  }
2695 
2696  // svg: x2
2697  mrExport.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer, aEnd.X);
2698  aStr = sStringBuffer.makeStringAndClear();
2700 
2701  // svg: y2
2702  mrExport.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer, aEnd.Y);
2703  aStr = sStringBuffer.makeStringAndClear();
2705 
2706  // #i39320#
2707  uno::Reference< uno::XInterface > xRefS;
2708  uno::Reference< uno::XInterface > xRefE;
2709 
2710  // export start connection
2711  xProps->getPropertyValue("StartShape") >>= xRefS;
2712  if( xRefS.is() )
2713  {
2714  const OUString& rShapeId = mrExport.getInterfaceToIdentifierMapper().getIdentifier( xRefS );
2716 
2717  aAny = xProps->getPropertyValue("StartGluePointIndex");
2718  sal_Int32 nGluePointId = 0;
2719  if( aAny >>= nGluePointId )
2720  {
2721  if( nGluePointId != -1 )
2722  {
2723  mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_START_GLUE_POINT, OUString::number( nGluePointId ));
2724  }
2725  }
2726  }
2727 
2728  // export end connection
2729  xProps->getPropertyValue("EndShape") >>= xRefE;
2730  if( xRefE.is() )
2731  {
2732  const OUString& rShapeId = mrExport.getInterfaceToIdentifierMapper().getIdentifier( xRefE );
2734 
2735  aAny = xProps->getPropertyValue("EndGluePointIndex");
2736  sal_Int32 nGluePointId = 0;
2737  if( aAny >>= nGluePointId )
2738  {
2739  if( nGluePointId != -1 )
2740  {
2741  mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_END_GLUE_POINT, OUString::number( nGluePointId ));
2742  }
2743  }
2744  }
2745 
2746  // get PolygonBezier
2747  aAny = xProps->getPropertyValue("PolyPolygonBezier");
2748  auto pSourcePolyPolygon = o3tl::tryAccess<drawing::PolyPolygonBezierCoords>(aAny);
2749  if(pSourcePolyPolygon && pSourcePolyPolygon->Coordinates.getLength())
2750  {
2751  const basegfx::B2DPolyPolygon aPolyPolygon(
2753  *pSourcePolyPolygon));
2754  const OUString aPolygonString(
2756  aPolyPolygon,
2757  true, // bUseRelativeCoordinates
2758  false, // bDetectQuadraticBeziers: not used in old, but maybe activated now
2759  true)); // bHandleRelativeNextPointCompatible
2760 
2761  // write point array
2762  mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_D, aPolygonString);
2763  }
2764 
2765  // get matrix
2766  ::basegfx::B2DHomMatrix aMatrix;
2767  ImpExportNewTrans_GetB2DHomMatrix(aMatrix, xProps);
2768 
2769  // decompose and correct about pRefPoint
2770  ::basegfx::B2DTuple aTRScale;
2771  double fTRShear(0.0);
2772  double fTRRotate(0.0);
2773  ::basegfx::B2DTuple aTRTranslate;
2774  ImpExportNewTrans_DecomposeAndRefPoint(aMatrix, aTRScale, fTRShear,
2775  fTRRotate, aTRTranslate, pRefPoint);
2776 
2777  // fdo#49678: create and export ViewBox
2778  awt::Size aSize(FRound(aTRScale.getX()), FRound(aTRScale.getY()));
2779  SdXMLImExViewBox aViewBox(0, 0, aSize.Width, aSize.Height);
2781 
2782  // write connector shape. Add Export later.
2783  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
2784  SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DRAW, XML_CONNECTOR, bCreateNewline, true);
2785 
2786  ImpExportDescription( xShape ); // #i68101#
2787  ImpExportEvents( xShape );
2788  ImpExportGluePoints( xShape );
2789  ImpExportText( xShape );
2790 }
2791 
2793  const uno::Reference< drawing::XShape >& xShape,
2794  XMLShapeExportFlags nFeatures /* = SEF_DEFAULT */, awt::Point const * pRefPoint /* = NULL */)
2795 {
2796  uno::Reference< beans::XPropertySet > xProps( xShape, uno::UNO_QUERY );
2797 
2798  OUString aStr;
2799  OUStringBuffer sStringBuffer;
2800 
2801  // export start and end point
2802  awt::Point aStart(0,0);
2803  awt::Point aEnd(1,1);
2804 
2805  /* Get <StartPositionInHoriL2R> and
2806  <EndPositionInHoriL2R>, if they exist and if the document is exported
2807  into the OpenOffice.org file format.
2808  These properties only exist at service css::text::Shape - the
2809  Writer UNO service for shapes.
2810  This code is needed, because the positioning attributes in the
2811  OpenOffice.org file format are given in horizontal left-to-right layout
2812  regardless the layout direction the shape is in. In the OASIS Open Office
2813  file format the positioning attributes are correctly given in the layout
2814  direction the shape is in. Thus, this code provides the conversion from
2815  the OASIS Open Office file format to the OpenOffice.org file format. (#i36248#)
2816  */
2817  if ( !( GetExport().getExportFlags() & SvXMLExportFlags::OASIS ) &&
2818  xProps->getPropertySetInfo()->hasPropertyByName("StartPositionInHoriL2R") &&
2819  xProps->getPropertySetInfo()->hasPropertyByName("EndPositionInHoriL2R") )
2820  {
2821  xProps->getPropertyValue("StartPositionInHoriL2R") >>= aStart;
2822  xProps->getPropertyValue("EndPositionInHoriL2R") >>= aEnd;
2823  }
2824  else
2825  {
2826  xProps->getPropertyValue("StartPosition") >>= aStart;
2827  xProps->getPropertyValue("EndPosition") >>= aEnd;
2828  }
2829 
2830  if( pRefPoint )
2831  {
2832  aStart.X -= pRefPoint->X;
2833  aStart.Y -= pRefPoint->Y;
2834  aEnd.X -= pRefPoint->X;
2835  aEnd.Y -= pRefPoint->Y;
2836  }
2837 
2838  if( nFeatures & XMLShapeExportFlags::X )
2839  {
2840  // svg: x1
2842  aStart.X);
2843  aStr = sStringBuffer.makeStringAndClear();
2845  }
2846  else
2847  {
2848  aEnd.X -= aStart.X;
2849  }
2850 
2851  if( nFeatures & XMLShapeExportFlags::Y )
2852  {
2853  // svg: y1
2855  aStart.Y);
2856  aStr = sStringBuffer.makeStringAndClear();
2858  }
2859  else
2860  {
2861  aEnd.Y -= aStart.Y;
2862  }
2863 
2864  // svg: x2
2865  mrExport.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer, aEnd.X);
2866  aStr = sStringBuffer.makeStringAndClear();
2868 
2869  // svg: y2
2870  mrExport.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer, aEnd.Y);
2871  aStr = sStringBuffer.makeStringAndClear();
2873 
2874  // write measure shape
2875  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
2876  SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DRAW, XML_MEASURE, bCreateNewline, true);
2877 
2878  ImpExportDescription( xShape ); // #i68101#
2879  ImpExportEvents( xShape );
2880  ImpExportGluePoints( xShape );
2881 
2882  uno::Reference< text::XText > xText( xShape, uno::UNO_QUERY );
2883  if( xText.is() )
2884  mrExport.GetTextParagraphExport()->exportText( xText );
2885 }
2886 
2888  const uno::Reference< drawing::XShape >& xShape,
2889  XmlShapeType eShapeType, XMLShapeExportFlags nFeatures /* = SEF_DEFAULT */, awt::Point* pRefPoint /* = NULL */,
2890  SvXMLAttributeList* pAttrList /* = NULL */ )
2891 {
2892  uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
2893  uno::Reference< container::XNamed > xNamed(xShape, uno::UNO_QUERY);
2894 
2895  SAL_WARN_IF( !xPropSet.is() || !xNamed.is(), "xmloff", "ole shape is not implementing needed interfaces");
2896  if(!(xPropSet.is() && xNamed.is()))
2897  return;
2898 
2899  // Transformation
2900  ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);
2901 
2902  bool bIsEmptyPresObj = false;
2903 
2904  // presentation settings
2905  if(eShapeType == XmlShapeTypePresOLE2Shape)
2906  bIsEmptyPresObj = ImpExportPresentationAttributes( xPropSet, GetXMLToken(XML_OBJECT) );
2907  else if(eShapeType == XmlShapeTypePresChartShape)
2908  bIsEmptyPresObj = ImpExportPresentationAttributes( xPropSet, GetXMLToken(XML_CHART) );
2909  else if(eShapeType == XmlShapeTypePresSheetShape)
2910  bIsEmptyPresObj = ImpExportPresentationAttributes( xPropSet, GetXMLToken(XML_TABLE) );
2911 
2912  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
2913  bool bExportEmbedded(mrExport.getExportFlags() & SvXMLExportFlags::EMBEDDED);
2914  OUString sPersistName;
2916  XML_FRAME, bCreateNewline, true );
2917 
2918  if (!bIsEmptyPresObj)
2919  {
2920  if (pAttrList)
2921  {
2922  mrExport.AddAttributeList(pAttrList);
2923  }
2924 
2925  OUString sClassId;
2926  OUString sURL;
2927  bool bInternal = false;
2928  xPropSet->getPropertyValue("IsInternal") >>= bInternal;
2929 
2930  {
2931 
2932  if ( bInternal )
2933  {
2934  // OOo internal links have no storage persistence, URL is stored in the XML file
2935  // the result LinkURL is empty in case the object is not a link
2936  xPropSet->getPropertyValue("LinkURL") >>= sURL;
2937  }
2938 
2939  xPropSet->getPropertyValue("PersistName") >>= sPersistName;
2940  if ( sURL.isEmpty() )
2941  {
2942  if( !sPersistName.isEmpty() )
2943  {
2944  sURL = "vnd.sun.star.EmbeddedObject:" + sPersistName;
2945  }
2946  }
2947 
2948  if( !bInternal )
2949  xPropSet->getPropertyValue("CLSID") >>= sClassId;
2950 
2951  if( !sClassId.isEmpty() )
2953 
2954  if(!bExportEmbedded)
2955  {
2956  // xlink:href
2957  if( !sURL.isEmpty() )
2958  {
2959  // #96717# in theorie, if we don't have a URL we shouldn't even
2960  // export this OLE shape. But practically it's too risky right now
2961  // to change this so we better dispose this on load
2962  sURL = mrExport.AddEmbeddedObject( sURL );
2963 
2968  }
2969  }
2970  }
2971 
2972  enum XMLTokenEnum eElem = sClassId.isEmpty() ? XML_OBJECT : XML_OBJECT_OLE ;
2973  SvXMLElementExport aElem( mrExport, XML_NAMESPACE_DRAW, eElem, true, true );
2974 
2975  // tdf#112547 export text as child of draw:object, where import expects it
2976  if (!bIsEmptyPresObj && supportsText(eShapeType))
2977  {
2978  // #i118485# Add text export, the draw OLE shape allows text now
2979  ImpExportText( xShape, TextPNS::EXTENSION );
2980  }
2981 
2982  if(bExportEmbedded && !bIsEmptyPresObj)
2983  {
2984  if(bInternal)
2985  {
2986  // embedded XML
2987  uno::Reference< lang::XComponent > xComp;
2988  xPropSet->getPropertyValue("Model") >>= xComp;
2989  SAL_WARN_IF( !xComp.is(), "xmloff", "no xModel for own OLE format" );
2991  }
2992  else
2993  {
2994  // embed as Base64
2995  // this is an alien object ( currently MSOLE is the only supported type of such objects )
2996  // in case it is not an OASIS format the object should be asked to store replacement image if possible
2997 
2998  OUString sURLRequest( sURL );
3000  sURLRequest += "?oasis=false";
3001  mrExport.AddEmbeddedObjectAsBase64( sURLRequest );
3002  }
3003  }
3004  }
3005  if( !bIsEmptyPresObj )
3006  {
3007  OUString sURL = XML_EMBEDDEDOBJECTGRAPHIC_URL_BASE + sPersistName;
3008  if( !bExportEmbedded )
3009  {
3010  sURL = GetExport().AddEmbeddedObject( sURL );
3015  }
3016 
3018  XML_IMAGE, false, true );
3019 
3020  if( bExportEmbedded )
3022  }
3023 
3024  ImpExportEvents( xShape );
3025  ImpExportGluePoints( xShape );
3026  ImpExportDescription( xShape ); // #i68101#
3027 
3028 }
3029 
3031  const uno::Reference< drawing::XShape >& xShape,
3032  XmlShapeType eShapeType, XMLShapeExportFlags nFeatures /* = SEF_DEFAULT */, awt::Point* pRefPoint /* = NULL */)
3033 {
3034  const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
3035  if(!xPropSet.is())
3036  return;
3037 
3038  // #86163# Transformation
3039  ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);
3040 
3041  // export page number used for this page
3042  uno::Reference< beans::XPropertySetInfo > xPropSetInfo( xPropSet->getPropertySetInfo() );
3043  static const OUStringLiteral aPageNumberStr(u"PageNumber");
3044  if( xPropSetInfo.is() && xPropSetInfo->hasPropertyByName(aPageNumberStr))
3045  {
3046  sal_Int32 nPageNumber = 0;
3047  xPropSet->getPropertyValue(aPageNumberStr) >>= nPageNumber;
3048  if( nPageNumber )
3049  mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_PAGE_NUMBER, OUString::number(nPageNumber));
3050  }
3051 
3052  // a presentation page shape, normally used on notes pages only. If
3053  // it is used not as presentation shape, it may have been created with
3054  // copy-paste exchange between draw and impress (this IS possible...)
3055  if(eShapeType == XmlShapeTypePresPageShape)
3056  {
3058  XML_PAGE);
3059  }
3060 
3061  // write Page shape
3062  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
3063  SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DRAW, XML_PAGE_THUMBNAIL, bCreateNewline, true);
3064 }
3065 
3067  const uno::Reference< drawing::XShape >& xShape,
3068  XMLShapeExportFlags nFeatures /* = SEF_DEFAULT */, awt::Point* pRefPoint /* = NULL */)
3069 {
3070  const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
3071  if(!xPropSet.is())
3072  return;
3073 
3074  // Transformation
3075  ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);
3076 
3077  // evtl. corner radius?
3078  sal_Int32 nCornerRadius(0);
3079  xPropSet->getPropertyValue("CornerRadius") >>= nCornerRadius;
3080  if(nCornerRadius)
3081  {
3082  OUStringBuffer sStringBuffer;
3084  nCornerRadius);
3085  mrExport.AddAttribute(XML_NAMESPACE_DRAW, XML_CORNER_RADIUS, sStringBuffer.makeStringAndClear());
3086  }
3087 
3088  awt::Point aCaptionPoint;
3089  xPropSet->getPropertyValue("CaptionPoint") >>= aCaptionPoint;
3090 
3092  aCaptionPoint.X);
3095  aCaptionPoint.Y);
3097 
3098  // write Caption shape. Add export later.
3099  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
3100  bool bAnnotation( (nFeatures & XMLShapeExportFlags::ANNOTATION) == XMLShapeExportFlags::ANNOTATION );
3101 
3103  (bAnnotation ? XML_NAMESPACE_OFFICE
3104  : XML_NAMESPACE_DRAW),
3105  (bAnnotation ? XML_ANNOTATION : XML_CAPTION),
3106  bCreateNewline, true );
3107 
3108  ImpExportDescription( xShape ); // #i68101#
3109  ImpExportEvents( xShape );
3110  ImpExportGluePoints( xShape );
3111  if( bAnnotation )
3112  mrExport.exportAnnotationMeta( xShape );
3113  ImpExportText( xShape );
3114 
3115 }
3116 
3118  const uno::Reference< drawing::XShape >& xShape,
3119  XMLShapeExportFlags nFeatures, css::awt::Point* pRefPoint)
3120 {
3121  const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
3122  if(!xPropSet.is())
3123  return;
3124 
3125  // Transformation
3126  ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);
3127 
3128  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
3130  XML_FRAME, bCreateNewline, true );
3131 
3132  // export frame url
3133  OUString aStr;
3134  xPropSet->getPropertyValue("FrameURL") >>= aStr;
3135  mrExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_HREF, GetExport().GetRelativeReference(aStr) );
3139 
3140  // export name
3141  xPropSet->getPropertyValue("FrameName") >>= aStr;
3142  if( !aStr.isEmpty() )
3144 
3145  // write floating frame
3146  {
3148  }
3149 
3150 }
3151 
3153  const uno::Reference< drawing::XShape >& xShape,
3154  XMLShapeExportFlags nFeatures, css::awt::Point* pRefPoint)
3155 {
3156  const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
3157  if(!xPropSet.is())
3158  return;
3159 
3160  // Transformation
3161  ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);
3162 
3163  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
3165  XML_FRAME, bCreateNewline, true );
3166 
3167  // export frame url
3168  OUString aStr;
3169  xPropSet->getPropertyValue("AppletCodeBase") >>= aStr;
3170  mrExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_HREF, GetExport().GetRelativeReference(aStr) );
3174 
3175  // export draw:applet-name
3176  xPropSet->getPropertyValue("AppletName") >>= aStr;
3177  if( !aStr.isEmpty() )
3179 
3180  // export draw:code
3181  xPropSet->getPropertyValue("AppletCode") >>= aStr;
3183 
3184  // export draw:may-script
3185  bool bIsScript = false;
3186  xPropSet->getPropertyValue("AppletIsScript") >>= bIsScript;
3188 
3189  {
3190  // write applet
3192 
3193  // export parameters
3194  uno::Sequence< beans::PropertyValue > aCommands;
3195  xPropSet->getPropertyValue("AppletCommands") >>= aCommands;
3196  for( const auto& rCommand : std::as_const(aCommands) )
3197  {
3198  rCommand.Value >>= aStr;
3199  mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_NAME, rCommand.Name );
3201  SvXMLElementExport aElem( mrExport, XML_NAMESPACE_DRAW, XML_PARAM, false, true );
3202  }
3203  }
3204 
3205 }
3206 
3208  const uno::Reference< drawing::XShape >& xShape,
3209  XMLShapeExportFlags nFeatures, css::awt::Point* pRefPoint)
3210 {
3211  const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
3212  if(!xPropSet.is())
3213  return;
3214 
3215  // Transformation
3216  ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);
3217 
3218  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
3220  XML_FRAME, bCreateNewline, true );
3221 
3222  // export plugin url
3223  OUString aStr;
3224  xPropSet->getPropertyValue("PluginURL") >>= aStr;
3225  mrExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_HREF, GetExport().GetRelativeReference(aStr) );
3229 
3230  // export mime-type
3231  xPropSet->getPropertyValue("PluginMimeType") >>= aStr;
3232  if(!aStr.isEmpty())
3234 
3235  {
3236  // write plugin
3238 
3239  // export parameters
3240  uno::Sequence< beans::PropertyValue > aCommands;
3241  xPropSet->getPropertyValue("PluginCommands") >>= aCommands;
3242  for( const auto& rCommand : std::as_const(aCommands) )
3243  {
3244  rCommand.Value >>= aStr;
3245  mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_NAME, rCommand.Name );
3247  SvXMLElementExport aElem( mrExport, XML_NAMESPACE_DRAW, XML_PARAM, false, true );
3248  }
3249  }
3250 
3251 }
3252 
3253 static void lcl_CopyStream(
3254  uno::Reference<io::XInputStream> const& xInStream,
3255  uno::Reference<embed::XStorage> const& xTarget,
3256  OUString const& rPath, const OUString& rMimeType)
3257 {
3259  uno::Reference<io::XStream> const xStream(
3261  embed::ElementModes::WRITE | embed::ElementModes::TRUNCATE, proxy));
3262  uno::Reference<io::XOutputStream> const xOutStream(
3263  (xStream.is()) ? xStream->getOutputStream() : nullptr);
3264  if (!xOutStream.is())
3265  {
3266  SAL_WARN("xmloff", "no output stream");
3267  throw uno::Exception("no output stream",nullptr);
3268  }
3269  uno::Reference< beans::XPropertySet > const xStreamProps(xStream,
3270  uno::UNO_QUERY);
3271  if (xStreamProps.is()) { // this is NOT supported in FileSystemStorage
3272  xStreamProps->setPropertyValue("MediaType",
3273  uno::makeAny(rMimeType));
3274  xStreamProps->setPropertyValue( // turn off compression
3275  "Compressed",
3276  uno::makeAny(false));
3277  }
3278  ::comphelper::OStorageHelper::CopyInputToOutput(xInStream, xOutStream);
3279  xOutStream->closeOutput();
3280  proxy.commitStorages();
3281 }
3282 
3283 static OUString
3285  uno::Reference<beans::XPropertySet> const& xPropSet,
3286  OUString const& rURL, const OUString& rMimeType)
3287 {
3288  OUString urlPath;
3289  if (rURL.startsWithIgnoreAsciiCase("vnd.sun.star.Package:", &urlPath))
3290  {
3291  try // video is embedded
3292  {
3293  uno::Reference<embed::XStorage> const xTarget(
3294  rExport.GetTargetStorage(), uno::UNO_SET_THROW);
3295  uno::Reference<io::XInputStream> xInStream;
3296  xPropSet->getPropertyValue("PrivateStream")
3297  >>= xInStream;
3298 
3299  if (!xInStream.is())
3300  {
3301  SAL_WARN("xmloff", "no input stream");
3302  return OUString();
3303  }
3304 
3305  lcl_CopyStream(xInStream, xTarget, rURL, rMimeType);
3306 
3307  return urlPath;
3308  }
3309  catch (uno::Exception const&)
3310  {
3311  TOOLS_INFO_EXCEPTION("xmloff", "exception while storing embedded media");
3312  }
3313  return OUString();
3314  }
3315  else
3316  {
3317  return rExport.GetRelativeReference(rURL); // linked
3318  }
3319 }
3320 
3322  const uno::Reference< drawing::XShape >& xShape,
3323  XmlShapeType eShapeType, XMLShapeExportFlags nFeatures, css::awt::Point* pRefPoint)
3324 {
3325  const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
3326  if(!xPropSet.is())
3327  return;
3328 
3329  // Transformation
3330  ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);
3331 
3332  if(eShapeType == XmlShapeTypePresMediaShape)
3333  {
3335  }
3336  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
3338  XML_FRAME, bCreateNewline, true );
3339 
3340  // export media url
3341  OUString aMediaURL;
3342  xPropSet->getPropertyValue("MediaURL") >>= aMediaURL;
3343  OUString sMimeType;
3344  xPropSet->getPropertyValue("MediaMimeType") >>= sMimeType;
3345 
3346  OUString const persistentURL =
3347  lcl_StoreMediaAndGetURL(GetExport(), xPropSet, aMediaURL, sMimeType);
3348 
3349  mrExport.AddAttribute ( XML_NAMESPACE_XLINK, XML_HREF, persistentURL );
3353 
3354  // export mime-type
3356 
3357  // write plugin
3358  SvXMLElementExport aPluginOBJ(mrExport, XML_NAMESPACE_DRAW, XML_PLUGIN, !( nFeatures & XMLShapeExportFlags::NO_WS ), true);
3359 
3360  // export parameters
3361  const OUString aFalseStr( "false" ), aTrueStr( "true" );
3362 
3363  bool bLoop = false;
3364  static const OUStringLiteral aLoopStr( u"Loop" );
3365  xPropSet->getPropertyValue( aLoopStr ) >>= bLoop;
3368  delete new SvXMLElementExport( mrExport, XML_NAMESPACE_DRAW, XML_PARAM, false, true );
3369 
3370  bool bMute = false;
3371  static const OUStringLiteral aMuteStr( u"Mute" );
3372  xPropSet->getPropertyValue( aMuteStr ) >>= bMute;
3374  mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_VALUE, bMute ? aTrueStr : aFalseStr );
3375  delete new SvXMLElementExport( mrExport, XML_NAMESPACE_DRAW, XML_PARAM, false, true );
3376 
3377  sal_Int16 nVolumeDB = 0;
3378  xPropSet->getPropertyValue("VolumeDB") >>= nVolumeDB;
3380  mrExport.AddAttribute( XML_NAMESPACE_DRAW, XML_VALUE, OUString::number( nVolumeDB ) );
3381  delete new SvXMLElementExport( mrExport, XML_NAMESPACE_DRAW, XML_PARAM, false, true );
3382 
3383  media::ZoomLevel eZoom;
3384  OUString aZoomValue;
3385  xPropSet->getPropertyValue("Zoom") >>= eZoom;
3386  switch( eZoom )
3387  {
3388  case media::ZoomLevel_ZOOM_1_TO_4 : aZoomValue = "25%"; break;
3389  case media::ZoomLevel_ZOOM_1_TO_2 : aZoomValue = "50%"; break;
3390  case media::ZoomLevel_ORIGINAL : aZoomValue = "100%"; break;
3391  case media::ZoomLevel_ZOOM_2_TO_1 : aZoomValue = "200%"; break;
3392  case media::ZoomLevel_ZOOM_4_TO_1 : aZoomValue = "400%"; break;
3393  case media::ZoomLevel_FIT_TO_WINDOW: aZoomValue = "fit"; break;
3394  case media::ZoomLevel_FIT_TO_WINDOW_FIXED_ASPECT: aZoomValue = "fixedfit"; break;
3395  case media::ZoomLevel_FULLSCREEN : aZoomValue = "fullscreen"; break;
3396 
3397  default:
3398  break;
3399  }
3400 
3401  if( !aZoomValue.isEmpty() )
3402  {
3405  delete new SvXMLElementExport( mrExport, XML_NAMESPACE_DRAW, XML_PARAM, false, true );
3406  }
3407 
3408 }
3409 
3410 void XMLShapeExport::ImpExport3DSceneShape( const uno::Reference< drawing::XShape >& xShape, XMLShapeExportFlags nFeatures, awt::Point* pRefPoint)
3411 {
3412  uno::Reference< drawing::XShapes > xShapes(xShape, uno::UNO_QUERY);
3413  if(!(xShapes.is() && xShapes->getCount()))
3414  return;
3415 
3416  uno::Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY );
3417  SAL_WARN_IF( !xPropSet.is(), "xmloff", "XMLShapeExport::ImpExport3DSceneShape can't export a scene without a propertyset" );
3418  if( !xPropSet.is() )
3419  return;
3420 
3421  // Transformation
3422  ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);
3423 
3424  // 3d attributes
3425  export3DSceneAttributes( xPropSet );
3426 
3427  // write 3DScene shape
3428  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
3429  SvXMLElementExport aOBJ( mrExport, XML_NAMESPACE_DR3D, XML_SCENE, bCreateNewline, true);
3430 
3431  ImpExportDescription( xShape ); // #i68101#
3432  ImpExportEvents( xShape );
3433 
3434  // write 3DSceneLights
3435  export3DLamps( xPropSet );
3436 
3437  // #89764# if export of position is suppressed for group shape,
3438  // positions of contained objects should be written relative to
3439  // the upper left edge of the group.
3440  awt::Point aUpperLeft;
3441 
3442  if(!(nFeatures & XMLShapeExportFlags::POSITION))
3443  {
3444  nFeatures |= XMLShapeExportFlags::POSITION;
3445  aUpperLeft = xShape->getPosition();
3446  pRefPoint = &aUpperLeft;
3447  }
3448 
3449  // write members
3450  exportShapes( xShapes, nFeatures, pRefPoint );
3451 }
3452 
3454  const uno::Reference< drawing::XShape >& xShape,
3455  XmlShapeType eShapeType)
3456 {
3457  const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
3458  if(!xPropSet.is())
3459  return;
3460 
3461  OUString aStr;
3462  OUStringBuffer sStringBuffer;
3463 
3464  // transformation (UNO_NAME_3D_TRANSFORM_MATRIX == "D3DTransformMatrix")
3465  uno::Any aAny = xPropSet->getPropertyValue("D3DTransformMatrix");
3466  drawing::HomogenMatrix aHomMat;
3467  aAny >>= aHomMat;
3468  SdXMLImExTransform3D aTransform;
3469  aTransform.AddHomogenMatrix(aHomMat);
3470  if(aTransform.NeedsAction())
3472 
3473  switch(eShapeType)
3474  {
3476  {
3477  // minEdge
3478  aAny = xPropSet->getPropertyValue("D3DPosition");
3479  drawing::Position3D aPosition3D;
3480  aAny >>= aPosition3D;
3481  ::basegfx::B3DVector aPos3D(aPosition3D.PositionX, aPosition3D.PositionY, aPosition3D.PositionZ);
3482 
3483  // maxEdge
3484  aAny = xPropSet->getPropertyValue("D3DSize");
3485  drawing::Direction3D aDirection3D;
3486  aAny >>= aDirection3D;
3487  ::basegfx::B3DVector aDir3D(aDirection3D.DirectionX, aDirection3D.DirectionY, aDirection3D.DirectionZ);
3488 
3489  // transform maxEdge from distance to pos
3490  aDir3D = aPos3D + aDir3D;
3491 
3492  // write minEdge
3493  if(aPos3D != ::basegfx::B3DVector(-2500.0, -2500.0, -2500.0)) // write only when not default
3494  {
3495  SvXMLUnitConverter::convertB3DVector(sStringBuffer, aPos3D);
3496  aStr = sStringBuffer.makeStringAndClear();
3498  }
3499 
3500  // write maxEdge
3501  if(aDir3D != ::basegfx::B3DVector(2500.0, 2500.0, 2500.0)) // write only when not default
3502  {
3503  SvXMLUnitConverter::convertB3DVector(sStringBuffer, aDir3D);
3504  aStr = sStringBuffer.makeStringAndClear();
3506  }
3507 
3508  // write 3DCube shape
3509  // #i123542# Do this *after* the attributes are added, else these will be lost since opening
3510  // the scope will clear the global attribute list at the exporter
3512 
3513  break;
3514  }
3516  {
3517  // Center
3518  aAny = xPropSet->getPropertyValue("D3DPosition");
3519  drawing::Position3D aPosition3D;
3520  aAny >>= aPosition3D;
3521  ::basegfx::B3DVector aPos3D(aPosition3D.PositionX, aPosition3D.PositionY, aPosition3D.PositionZ);
3522 
3523  // Size
3524  aAny = xPropSet->getPropertyValue("D3DSize");
3525  drawing::Direction3D aDirection3D;
3526  aAny >>= aDirection3D;
3527  ::basegfx::B3DVector aDir3D(aDirection3D.DirectionX, aDirection3D.DirectionY, aDirection3D.DirectionZ);
3528 
3529  // write Center
3530  if(aPos3D != ::basegfx::B3DVector(0.0, 0.0, 0.0)) // write only when not default
3531  {
3532  SvXMLUnitConverter::convertB3DVector(sStringBuffer, aPos3D);
3533  aStr = sStringBuffer.makeStringAndClear();
3535  }
3536 
3537  // write Size
3538  if(aDir3D != ::basegfx::B3DVector(5000.0, 5000.0, 5000.0)) // write only when not default
3539  {
3540  SvXMLUnitConverter::convertB3DVector(sStringBuffer, aDir3D);
3541  aStr = sStringBuffer.makeStringAndClear();
3543  }
3544 
3545  // write 3DSphere shape
3546  // #i123542# Do this *after* the attributes are added, else these will be lost since opening
3547  // the scope will clear the global attribute list at the exporter
3549 
3550  break;
3551  }
3554  {
3555  // write special 3DLathe/3DExtrude attributes, get 3D tools::PolyPolygon as drawing::PolyPolygonShape3D
3556  aAny = xPropSet->getPropertyValue("D3DPolyPolygon3D");
3557  drawing::PolyPolygonShape3D aUnoPolyPolygon3D;
3558  aAny >>= aUnoPolyPolygon3D;
3559 
3560  // convert to 3D PolyPolygon
3561  const basegfx::B3DPolyPolygon aPolyPolygon3D(
3563  aUnoPolyPolygon3D));
3564 
3565  // convert to 2D tools::PolyPolygon using identity 3D transformation (just grep X and Y)
3566  const basegfx::B3DHomMatrix aB3DHomMatrixFor2DConversion;
3567  const basegfx::B2DPolyPolygon aPolyPolygon(
3569  aPolyPolygon3D,
3570  aB3DHomMatrixFor2DConversion));
3571 
3572  // get 2D range of it
3573  const basegfx::B2DRange aPolyPolygonRange(aPolyPolygon.getB2DRange());
3574 
3575  // export ViewBox
3576  SdXMLImExViewBox aViewBox(
3577  aPolyPolygonRange.getMinX(),
3578  aPolyPolygonRange.getMinY(),
3579  aPolyPolygonRange.getWidth(),
3580  aPolyPolygonRange.getHeight());
3581 
3582  mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_VIEWBOX, aViewBox.GetExportString());
3583 
3584  // prepare svg:d string
3585  const OUString aPolygonString(
3587  aPolyPolygon,
3588  true, // bUseRelativeCoordinates
3589  false, // bDetectQuadraticBeziers TTTT: not used in old, but maybe activated now
3590  true)); // bHandleRelativeNextPointCompatible
3591 
3592  // write point array
3593  mrExport.AddAttribute(XML_NAMESPACE_SVG, XML_D, aPolygonString);
3594 
3595  if(eShapeType == XmlShapeTypeDraw3DLatheObject)
3596  {
3597  // write 3DLathe shape
3599  }
3600  else
3601  {
3602  // write 3DExtrude shape
3604  }
3605  break;
3606  }
3607  default:
3608  break;
3609  }
3610 }
3611 
3613 void XMLShapeExport::export3DSceneAttributes( const css::uno::Reference< css::beans::XPropertySet >& xPropSet )
3614 {
3615  OUString aStr;
3616  OUStringBuffer sStringBuffer;
3617 
3618  // world transformation (UNO_NAME_3D_TRANSFORM_MATRIX == "D3DTransformMatrix")
3619  uno::Any aAny = xPropSet->getPropertyValue("D3DTransformMatrix");
3620  drawing::HomogenMatrix aHomMat;
3621  aAny >>= aHomMat;
3622  SdXMLImExTransform3D aTransform;
3623  aTransform.AddHomogenMatrix(aHomMat);
3624  if(aTransform.NeedsAction())
3626 
3627  // VRP, VPN, VUP
3628  aAny = xPropSet->getPropertyValue("D3DCameraGeometry");
3629  drawing::CameraGeometry aCamGeo;
3630  aAny >>= aCamGeo;
3631 
3632  ::basegfx::B3DVector aVRP(aCamGeo.vrp.PositionX, aCamGeo.vrp.PositionY, aCamGeo.vrp.PositionZ);
3633  if(aVRP != ::basegfx::B3DVector(0.0, 0.0, 1.0)) // write only when not default
3634  {
3635  SvXMLUnitConverter::convertB3DVector(sStringBuffer, aVRP);
3636  aStr = sStringBuffer.makeStringAndClear();
3638  }
3639 
3640  ::basegfx::B3DVector aVPN(aCamGeo.vpn.DirectionX, aCamGeo.vpn.DirectionY, aCamGeo.vpn.DirectionZ);
3641  if(aVPN != ::basegfx::B3DVector(0.0, 0.0, 1.0)) // write only when not default
3642  {
3643  SvXMLUnitConverter::convertB3DVector(sStringBuffer, aVPN);
3644  aStr = sStringBuffer.makeStringAndClear();
3646  }
3647 
3648  ::basegfx::B3DVector aVUP(aCamGeo.vup.DirectionX, aCamGeo.vup.DirectionY, aCamGeo.vup.DirectionZ);
3649  if(aVUP != ::basegfx::B3DVector(0.0, 1.0, 0.0)) // write only when not default
3650  {
3651  SvXMLUnitConverter::convertB3DVector(sStringBuffer, aVUP);
3652  aStr = sStringBuffer.makeStringAndClear();
3654  }
3655 
3656  // projection "D3DScenePerspective" drawing::ProjectionMode
3657  aAny = xPropSet->getPropertyValue("D3DScenePerspective");
3658  drawing::ProjectionMode aPrjMode;
3659  aAny >>= aPrjMode;
3660  if(aPrjMode == drawing::ProjectionMode_PARALLEL)
3661  aStr = GetXMLToken(XML_PARALLEL);
3662  else
3663  aStr = GetXMLToken(XML_PERSPECTIVE);
3665 
3666  // distance
3667  aAny = xPropSet->getPropertyValue("D3DSceneDistance");
3668  sal_Int32 nDistance = 0;
3669  aAny >>= nDistance;
3671  nDistance);
3672  aStr = sStringBuffer.makeStringAndClear();
3674 
3675  // focalLength
3676  aAny = xPropSet->getPropertyValue("D3DSceneFocalLength");
3677  sal_Int32 nFocalLength = 0;
3678  aAny >>= nFocalLength;
3680  nFocalLength);
3681  aStr = sStringBuffer.makeStringAndClear();
3683 
3684  // shadowSlant
3685  aAny = xPropSet->getPropertyValue("D3DSceneShadowSlant");
3686  sal_Int16 nShadowSlant = 0;
3687  aAny >>= nShadowSlant;
3688  mrExport.AddAttribute(XML_NAMESPACE_DR3D, XML_SHADOW_SLANT, OUString::number(static_cast<sal_Int32>(nShadowSlant)));
3689 
3690  // shadeMode
3691  aAny = xPropSet->getPropertyValue("D3DSceneShadeMode");
3692  drawing::ShadeMode aShadeMode;
3693  if(aAny >>= aShadeMode)
3694  {
3695  if(aShadeMode == drawing::ShadeMode_FLAT)
3696  aStr = GetXMLToken(XML_FLAT);
3697  else if(aShadeMode == drawing::ShadeMode_PHONG)
3698  aStr = GetXMLToken(XML_PHONG);
3699  else if(aShadeMode == drawing::ShadeMode_SMOOTH)
3700  aStr = GetXMLToken(XML_GOURAUD);
3701  else
3702  aStr = GetXMLToken(XML_DRAFT);
3703  }
3704  else
3705  {
3706  // ShadeMode enum not there, write default
3707  aStr = GetXMLToken(XML_GOURAUD);
3708  }
3710 
3711  // ambientColor
3712  aAny = xPropSet->getPropertyValue("D3DSceneAmbientColor");
3713  sal_Int32 nAmbientColor = 0;
3714  aAny >>= nAmbientColor;
3715  ::sax::Converter::convertColor(sStringBuffer, nAmbientColor);
3716  aStr = sStringBuffer.makeStringAndClear();
3718 
3719  // lightingMode
3720  aAny = xPropSet->getPropertyValue("D3DSceneTwoSidedLighting");
3721  bool bTwoSidedLighting = false;
3722  aAny >>= bTwoSidedLighting;
3723  ::sax::Converter::convertBool(sStringBuffer, bTwoSidedLighting);
3724  aStr = sStringBuffer.makeStringAndClear();
3726 }
3727 
3729 void XMLShapeExport::export3DLamps( const css::uno::Reference< css::beans::XPropertySet >& xPropSet )
3730 {
3731  // write lamps 1..8 as content
3732  OUString aStr;
3733  OUStringBuffer sStringBuffer;
3734 
3735  static const OUStringLiteral aColorPropName(u"D3DSceneLightColor");
3736  static const OUStringLiteral aDirectionPropName(u"D3DSceneLightDirection");
3737  static const OUStringLiteral aLightOnPropName(u"D3DSceneLightOn");
3738 
3739  ::basegfx::B3DVector aLightDirection;
3740  drawing::Direction3D aLightDir;
3741  bool bLightOnOff = false;
3742  for(sal_Int32 nLamp = 1; nLamp <= 8; nLamp++)
3743  {
3744  OUString aIndexStr = OUString::number( nLamp );
3745 
3746  // lightcolor
3747  OUString aPropName = aColorPropName + aIndexStr;
3748  sal_Int32 nLightColor = 0;
3749  xPropSet->getPropertyValue( aPropName ) >>= nLightColor;
3750  ::sax::Converter::convertColor(sStringBuffer, nLightColor);
3751  aStr = sStringBuffer.makeStringAndClear();
3753 
3754  // lightdirection
3755  aPropName = aDirectionPropName + aIndexStr;
3756  xPropSet->getPropertyValue(aPropName) >>= aLightDir;
3757  aLightDirection = ::basegfx::B3DVector(aLightDir.DirectionX, aLightDir.DirectionY, aLightDir.DirectionZ);
3758  SvXMLUnitConverter::convertB3DVector(sStringBuffer, aLightDirection);
3759  aStr = sStringBuffer.makeStringAndClear();
3761 
3762  // lighton
3763  aPropName = aLightOnPropName + aIndexStr;
3764  xPropSet->getPropertyValue(aPropName) >>= bLightOnOff;
3765  ::sax::Converter::convertBool(sStringBuffer, bLightOnOff);
3766  aStr = sStringBuffer.makeStringAndClear();
3768 
3769  // specular
3771  nLamp == 1 ? XML_TRUE : XML_FALSE);
3772 
3773  // write light entry
3775  }
3776 }
3777 
3778 
3779 // using namespace css::io;
3780 // using namespace ::xmloff::EnhancedCustomShapeToken;
3781 
3782 
3783 static void ExportParameter( OUStringBuffer& rStrBuffer, const css::drawing::EnhancedCustomShapeParameter& rParameter )
3784 {
3785  if ( !rStrBuffer.isEmpty() )
3786  rStrBuffer.append( ' ' );
3787  if ( rParameter.Value.getValueTypeClass() == uno::TypeClass_DOUBLE )
3788  {
3789  double fNumber = 0.0;
3790  rParameter.Value >>= fNumber;
3791  ::rtl::math::doubleToUStringBuffer( rStrBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true );
3792  }
3793  else
3794  {
3795  sal_Int32 nValue = 0;
3796  rParameter.Value >>= nValue;
3797 
3798  switch( rParameter.Type )
3799  {
3800  case css::drawing::EnhancedCustomShapeParameterType::EQUATION :
3801  {
3802  rStrBuffer.append( "?f" + OUString::number( nValue ) );
3803  }
3804  break;
3805 
3806  case css::drawing::EnhancedCustomShapeParameterType::ADJUSTMENT :
3807  {
3808  rStrBuffer.append( '$' );
3809  rStrBuffer.append( nValue );
3810  }
3811  break;
3812 
3813  case css::drawing::EnhancedCustomShapeParameterType::BOTTOM :
3814  rStrBuffer.append( GetXMLToken( XML_BOTTOM ) ); break;
3815  case css::drawing::EnhancedCustomShapeParameterType::RIGHT :
3816  rStrBuffer.append( GetXMLToken( XML_RIGHT ) ); break;
3817  case css::drawing::EnhancedCustomShapeParameterType::TOP :
3818  rStrBuffer.append( GetXMLToken( XML_TOP ) ); break;
3819  case css::drawing::EnhancedCustomShapeParameterType::LEFT :
3820  rStrBuffer.append( GetXMLToken( XML_LEFT ) ); break;
3821  case css::drawing::EnhancedCustomShapeParameterType::XSTRETCH :
3822  rStrBuffer.append( GetXMLToken( XML_XSTRETCH ) ); break;
3823  case css::drawing::EnhancedCustomShapeParameterType::YSTRETCH :
3824  rStrBuffer.append( GetXMLToken( XML_YSTRETCH ) ); break;
3825  case css::drawing::EnhancedCustomShapeParameterType::HASSTROKE :
3826  rStrBuffer.append( GetXMLToken( XML_HASSTROKE ) ); break;
3827  case css::drawing::EnhancedCustomShapeParameterType::HASFILL :
3828  rStrBuffer.append( GetXMLToken( XML_HASFILL ) ); break;
3829  case css::drawing::EnhancedCustomShapeParameterType::WIDTH :
3830  rStrBuffer.append( GetXMLToken( XML_WIDTH ) ); break;
3831  case css::drawing::EnhancedCustomShapeParameterType::HEIGHT :
3832  rStrBuffer.append( GetXMLToken( XML_HEIGHT ) ); break;
3833  case css::drawing::EnhancedCustomShapeParameterType::LOGWIDTH :
3834  rStrBuffer.append( GetXMLToken( XML_LOGWIDTH ) ); break;
3835  case css::drawing::EnhancedCustomShapeParameterType::LOGHEIGHT :
3836  rStrBuffer.append( GetXMLToken( XML_LOGHEIGHT ) ); break;
3837  default :
3838  rStrBuffer.append( nValue );
3839  }
3840  }
3841 }
3842 
3843 static void ImpExportEquations( SvXMLExport& rExport, const uno::Sequence< OUString >& rEquations )
3844 {
3845  sal_Int32 i;
3846  for ( i = 0; i < rEquations.getLength(); i++ )
3847  {
3848  OUString aStr= "f" + OUString::number( i );
3849  rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_NAME, aStr );
3850 
3851  aStr = rEquations[ i ];
3852  sal_Int32 nIndex = 0;
3853  do
3854  {
3855  nIndex = aStr.indexOf( '?', nIndex );
3856  if ( nIndex != -1 )
3857  {
3858  aStr = OUString::Concat(aStr.subView(0, nIndex + 1)) + "f"
3859  + aStr.subView(nIndex + 1, aStr.getLength() - nIndex - 1);
3860  nIndex++;
3861  }
3862  } while( nIndex != -1 );
3863  rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_FORMULA, aStr );
3864  SvXMLElementExport aOBJ( rExport, XML_NAMESPACE_DRAW, XML_EQUATION, true, true );
3865  }
3866 }
3867 
3868 static void ImpExportHandles( SvXMLExport& rExport, const uno::Sequence< beans::PropertyValues >& rHandles )
3869 {
3870  if ( !rHandles.hasElements() )
3871  return;
3872 
3873  OUString aStr;
3874  OUStringBuffer aStrBuffer;
3875 
3876  for ( const uno::Sequence< beans::PropertyValue >& rPropSeq : rHandles )
3877  {
3878  bool bPosition = false;
3879  for ( const beans::PropertyValue& rPropVal : rPropSeq )
3880  {
3881  switch( EASGet( rPropVal.Name ) )
3882  {
3883  case EAS_Position :
3884  {
3885  css::drawing::EnhancedCustomShapeParameterPair aPosition;
3886  if ( rPropVal.Value >>= aPosition )
3887  {
3888  ExportParameter( aStrBuffer, aPosition.First );
3889  ExportParameter( aStrBuffer, aPosition.Second );
3890  aStr = aStrBuffer.makeStringAndClear();
3892  bPosition = true;
3893  }
3894  }
3895  break;
3896  case EAS_MirroredX :
3897  {
3898  bool bMirroredX;
3899  if ( rPropVal.Value >>= bMirroredX )
3901  bMirroredX ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
3902  }
3903  break;
3904  case EAS_MirroredY :
3905  {
3906  bool bMirroredY;
3907  if ( rPropVal.Value >>= bMirroredY )
3909  bMirroredY ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
3910  }
3911  break;
3912  case EAS_Switched :
3913  {
3914  bool bSwitched;
3915  if ( rPropVal.Value >>= bSwitched )
3917  bSwitched ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
3918  }
3919  break;
3920  case EAS_Polar :
3921  {
3922  css::drawing::EnhancedCustomShapeParameterPair aPolar;
3923  if ( rPropVal.Value >>= aPolar )
3924  {
3925  ExportParameter( aStrBuffer, aPolar.First );
3926  ExportParameter( aStrBuffer, aPolar.Second );
3927  aStr = aStrBuffer.makeStringAndClear();
3929  }
3930  }
3931  break;
3932  case EAS_RadiusRangeMinimum :
3933  {
3934  css::drawing::EnhancedCustomShapeParameter aRadiusRangeMinimum;
3935  if ( rPropVal.Value >>= aRadiusRangeMinimum )
3936  {
3937  ExportParameter( aStrBuffer, aRadiusRangeMinimum );
3938  aStr = aStrBuffer.makeStringAndClear();
3940  }
3941  }
3942  break;
3943  case EAS_RadiusRangeMaximum :
3944  {
3945  css::drawing::EnhancedCustomShapeParameter aRadiusRangeMaximum;
3946  if ( rPropVal.Value >>= aRadiusRangeMaximum )
3947  {
3948  ExportParameter( aStrBuffer, aRadiusRangeMaximum );
3949  aStr = aStrBuffer.makeStringAndClear();
3951  }
3952  }
3953  break;
3954  case EAS_RangeXMinimum :
3955  {
3956  css::drawing::EnhancedCustomShapeParameter aXRangeMinimum;
3957  if ( rPropVal.Value >>= aXRangeMinimum )
3958  {
3959  ExportParameter( aStrBuffer, aXRangeMinimum );
3960  aStr = aStrBuffer.makeStringAndClear();
3962  }
3963  }
3964  break;
3965  case EAS_RangeXMaximum :
3966  {
3967  css::drawing::EnhancedCustomShapeParameter aXRangeMaximum;
3968  if ( rPropVal.Value >>= aXRangeMaximum )
3969  {
3970  ExportParameter( aStrBuffer, aXRangeMaximum );
3971  aStr = aStrBuffer.makeStringAndClear();
3973  }
3974  }
3975  break;
3976  case EAS_RangeYMinimum :
3977  {
3978  css::drawing::EnhancedCustomShapeParameter aYRangeMinimum;
3979  if ( rPropVal.Value >>= aYRangeMinimum )
3980  {
3981  ExportParameter( aStrBuffer, aYRangeMinimum );
3982  aStr = aStrBuffer.makeStringAndClear();
3984  }
3985  }
3986  break;
3987  case EAS_RangeYMaximum :
3988  {
3989  css::drawing::EnhancedCustomShapeParameter aYRangeMaximum;
3990  if ( rPropVal.Value >>= aYRangeMaximum )
3991  {
3992  ExportParameter( aStrBuffer, aYRangeMaximum );
3993  aStr = aStrBuffer.makeStringAndClear();
3995  }
3996  }
3997  break;
3998  default:
3999  break;
4000  }
4001  }
4002  if ( bPosition )
4003  SvXMLElementExport aOBJ( rExport, XML_NAMESPACE_DRAW, XML_HANDLE, true, true );
4004  else
4005  rExport.ClearAttrList();
4006  }
4007 }
4008 
4010  const uno::Sequence< css::drawing::EnhancedCustomShapeParameterPair >& rCoordinates,
4011  const uno::Sequence< css::drawing::EnhancedCustomShapeSegment >& rSegments,
4012  bool bExtended = false )
4013 {
4014 
4015  OUString aStr;
4016  OUStringBuffer aStrBuffer;
4017  bool bNeedExtended = false;
4018 
4019  sal_Int32 i, j, k, l;
4020 
4021  sal_Int32 nCoords = rCoordinates.getLength();
4022  sal_Int32 nSegments = rSegments.getLength();
4023  bool bSimpleSegments = nSegments == 0;
4024  if ( bSimpleSegments )
4025  nSegments = 4;
4026  for ( j = i = 0; j < nSegments; j++ )
4027  {
4028  css::drawing::EnhancedCustomShapeSegment aSegment;
4029  if ( bSimpleSegments )
4030  {
4031  // if there are not enough segments we will default them
4032  switch( j )
4033  {
4034  case 0 :
4035  {
4036  aSegment.Count = 1;
4037  aSegment.Command = css::drawing::EnhancedCustomShapeSegmentCommand::MOVETO;
4038  }
4039  break;
4040  case 1 :
4041  {
4042  aSegment.Count = static_cast<sal_Int16>(std::min( nCoords - 1, sal_Int32(32767) ));
4043  aSegment.Command = css::drawing::EnhancedCustomShapeSegmentCommand::LINETO;
4044  }
4045  break;
4046  case 2 :
4047  {
4048  aSegment.Count = 1;
4049  aSegment.Command = css::drawing::EnhancedCustomShapeSegmentCommand::CLOSESUBPATH;
4050  }
4051  break;
4052  case 3 :
4053  {
4054  aSegment.Count = 1;
4055  aSegment.Command = css::drawing::EnhancedCustomShapeSegmentCommand::ENDSUBPATH;
4056  }
4057  break;
4058  }
4059  }
4060  else
4061  aSegment = rSegments[ j ];
4062 
4063  if ( !aStrBuffer.isEmpty() )
4064  aStrBuffer.append( ' ' );
4065 
4066  sal_Int32 nParameter = 0;
4067  switch( aSegment.Command )
4068  {
4069  case css::drawing::EnhancedCustomShapeSegmentCommand::CLOSESUBPATH :
4070  aStrBuffer.append( 'Z' ); break;
4071  case css::drawing::EnhancedCustomShapeSegmentCommand::ENDSUBPATH :
4072  aStrBuffer.append( 'N' ); break;
4073  case css::drawing::EnhancedCustomShapeSegmentCommand::NOFILL :
4074  aStrBuffer.append( 'F' ); break;
4075  case css::drawing::EnhancedCustomShapeSegmentCommand::NOSTROKE :
4076  aStrBuffer.append( 'S' ); break;
4077 
4078  case css::drawing::EnhancedCustomShapeSegmentCommand::MOVETO :
4079  aStrBuffer.append( 'M' ); nParameter = 1; break;
4080  case css::drawing::EnhancedCustomShapeSegmentCommand::LINETO :
4081  aStrBuffer.append( 'L' ); nParameter = 1; break;
4082  case css::drawing::EnhancedCustomShapeSegmentCommand::CURVETO :
4083  aStrBuffer.append( 'C' ); nParameter = 3; break;
4084  case css::drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO :
4085  aStrBuffer.append( 'T' ); nParameter = 3; break;
4086  case css::drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE :
4087  aStrBuffer.append( 'U' ); nParameter = 3; break;
4088  case css::drawing::EnhancedCustomShapeSegmentCommand::ARCTO :
4089  aStrBuffer.append( 'A' ); nParameter = 4; break;
4090  case css::drawing::EnhancedCustomShapeSegmentCommand::ARC :
4091  aStrBuffer.append( 'B' ); nParameter = 4; break;
4092  case css::drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO :
4093  aStrBuffer.append( 'W' ); nParameter = 4; break;
4094  case css::drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARC :
4095  aStrBuffer.append( 'V' ); nParameter = 4; break;
4096  case css::drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX :
4097  aStrBuffer.append( 'X' ); nParameter = 1; break;
4098  case css::drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY :
4099  aStrBuffer.append( 'Y' ); nParameter = 1; break;
4100  case css::drawing::EnhancedCustomShapeSegmentCommand::QUADRATICCURVETO :
4101  aStrBuffer.append( 'Q' ); nParameter = 2; break;
4102  case css::drawing::EnhancedCustomShapeSegmentCommand::ARCANGLETO :
4103  if ( bExtended ) {
4104  aStrBuffer.append( 'G' );
4105  nParameter = 2;
4106  } else {
4107  aStrBuffer.setLength( aStrBuffer.getLength() - 1);
4108  bNeedExtended = true;
4109  i += 2;
4110  }
4111  break;
4112  case css::drawing::EnhancedCustomShapeSegmentCommand::DARKEN :
4113  if ( bExtended )
4114  aStrBuffer.append( 'H' );
4115  else
4116  bNeedExtended = true;
4117  break;
4118  case css::drawing::EnhancedCustomShapeSegmentCommand::DARKENLESS :
4119  if ( bExtended )
4120  aStrBuffer.append( 'I' );
4121  else
4122  bNeedExtended = true;
4123  break;
4124  case css::drawing::EnhancedCustomShapeSegmentCommand::LIGHTEN :
4125  if ( bExtended )
4126  aStrBuffer.append( 'J' );
4127  else
4128  bNeedExtended = true;
4129  break;
4130  case css::drawing::EnhancedCustomShapeSegmentCommand::LIGHTENLESS :
4131  if ( bExtended )
4132  aStrBuffer.append( 'K' );
4133  else
4134  bNeedExtended = true;
4135  break;
4136  default : // ups, seems to be something wrong
4137  {
4138  aSegment.Count = 1;
4139  aSegment.Command = css::drawing::EnhancedCustomShapeSegmentCommand::LINETO;
4140  }
4141  break;
4142  }
4143  if ( nParameter )
4144  {
4145  for ( k = 0; k < aSegment.Count; k++ )
4146  {
4147  if ( ( i + nParameter ) <= nCoords )
4148  {
4149  for ( l = 0; l < nParameter; l++ )
4150  {
4151  ExportParameter( aStrBuffer, rCoordinates[ i ].First );
4152  ExportParameter( aStrBuffer, rCoordinates[ i++ ].Second );
4153  }
4154  }
4155  else
4156  {
4157  j = nSegments; // error -> exiting
4158  break;
4159  }
4160  }
4161  }
4162  }
4163  aStr = aStrBuffer.makeStringAndClear();
4165  if (!bExtended && bNeedExtended && (rExport.getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED))
4166  ImpExportEnhancedPath( rExport, rCoordinates, rSegments, true );
4167 }
4168 
4169 static void ImpExportEnhancedGeometry( SvXMLExport& rExport, const uno::Reference< beans::XPropertySet >& xPropSet )
4170 {
4171  bool bEquations = false;
4172  uno::Sequence< OUString > aEquations;
4173 
4174  bool bHandles = false;
4175  uno::Sequence< beans::PropertyValues > aHandles;
4176 
4177  uno::Sequence< css::drawing::EnhancedCustomShapeSegment > aSegments;
4178  uno::Sequence< css::drawing::EnhancedCustomShapeParameterPair > aCoordinates;
4179 
4180  uno::Sequence< css::drawing::EnhancedCustomShapeAdjustmentValue > aAdjustmentValues;
4181 
4182  OUString aStr;
4183  OUStringBuffer aStrBuffer;
4184  SvXMLUnitConverter& rUnitConverter = rExport.GetMM100UnitConverter();
4185 
4186  uno::Reference< beans::XPropertySetInfo > xPropSetInfo( xPropSet->getPropertySetInfo() );
4187 
4188  // geometry
4189  static const OUStringLiteral sCustomShapeGeometry( u"CustomShapeGeometry" );
4190  if ( xPropSetInfo.is() && xPropSetInfo->hasPropertyByName( sCustomShapeGeometry ) )
4191  {
4192  uno::Any aGeoPropSet( xPropSet->getPropertyValue( sCustomShapeGeometry ) );
4193  uno::Sequence< beans::PropertyValue > aGeoPropSeq;
4194 
4195  if ( aGeoPropSet >>= aGeoPropSeq )
4196  {
4197  bool bCoordinates = false;
4198  OUString aCustomShapeType( "non-primitive" );
4199 
4200  for ( const beans::PropertyValue& rGeoProp : std::as_const(aGeoPropSeq) )
4201  {
4202  switch( EASGet( rGeoProp.Name ) )
4203  {
4204  case EAS_Type :
4205  {
4206  rGeoProp.Value >>= aCustomShapeType;
4207  }
4208  break;
4209  case EAS_MirroredX :
4210  {
4211  bool bMirroredX;
4212  if ( rGeoProp.Value >>= bMirroredX )
4214  bMirroredX ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
4215  }
4216  break;
4217  case EAS_MirroredY :
4218  {
4219  bool bMirroredY;
4220  if ( rGeoProp.Value >>= bMirroredY )
4222  bMirroredY ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
4223  }
4224  break;
4225  case EAS_ViewBox :
4226  {
4227  awt::Rectangle aRect;
4228  if ( rGeoProp.Value >>= aRect )
4229  {
4230  SdXMLImExViewBox aViewBox( aRect.X, aRect.Y, aRect.Width, aRect.Height );
4232  }
4233  }
4234  break;
4235  case EAS_TextPreRotateAngle :
4236  case EAS_TextRotateAngle :
4237  {
4238  double fTextRotateAngle = 0;
4239  if ( ( rGeoProp.Value >>= fTextRotateAngle ) && fTextRotateAngle != 0 )
4240  {
4242  aStrBuffer, fTextRotateAngle );
4243  aStr = aStrBuffer.makeStringAndClear();
4245  }
4246  }
4247  break;
4248  case EAS_Extrusion :
4249  {
4250  uno::Sequence< beans::PropertyValue > aExtrusionPropSeq;
4251  if ( rGeoProp.Value >>= aExtrusionPropSeq )
4252  {
4253  for ( const beans::PropertyValue& rProp : std::as_const(aExtrusionPropSeq) )
4254  {
4255  switch( EASGet( rProp.Name ) )
4256  {
4257  case EAS_Extrusion :
4258  {
4259  bool bExtrusionOn;
4260  if ( rProp.Value >>= bExtrusionOn )
4262  bExtrusionOn ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
4263  }
4264  break;
4265  case EAS_Brightness :
4266  {
4267  double fExtrusionBrightness = 0;
4268  if ( rProp.Value >>= fExtrusionBrightness )
4269  {
4271  aStrBuffer,
4272  fExtrusionBrightness,
4273  false,
4274  util::MeasureUnit::PERCENT,
4275  util::MeasureUnit::PERCENT);
4276  aStrBuffer.append( '%' );
4277  aStr = aStrBuffer.makeStringAndClear();
4279  }
4280  }
4281  break;
4282  case EAS_Depth :
4283  {
4284  css::drawing::EnhancedCustomShapeParameterPair aDepthParaPair;
4285  if ( rProp.Value >>= aDepthParaPair )
4286  {
4287  double fDepth = 0;
4288  if ( aDepthParaPair.First.Value >>= fDepth )
4289  {
4290  rExport.GetMM100UnitConverter().convertDouble( aStrBuffer, fDepth );
4291  ExportParameter( aStrBuffer, aDepthParaPair.Second );
4292  aStr = aStrBuffer.makeStringAndClear();
4294  }
4295  }
4296  }
4297  break;
4298  case EAS_Diffusion :
4299  {
4300  double fExtrusionDiffusion = 0;
4301  if ( rProp.Value >>= fExtrusionDiffusion )
4302  {
4304  aStrBuffer,
4305  fExtrusionDiffusion,
4306  false,
4307  util::MeasureUnit::PERCENT,
4308  util::MeasureUnit::PERCENT);
4309  aStrBuffer.append( '%' );
4310  aStr = aStrBuffer.makeStringAndClear();
4312  }
4313  }
4314  break;
4316  {
4317  sal_Int32 nExtrusionNumberOfLineSegments = 0;
4318  if ( rProp.Value >>= nExtrusionNumberOfLineSegments )
4319  rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_EXTRUSION_NUMBER_OF_LINE_SEGMENTS, OUString::number( nExtrusionNumberOfLineSegments ) );
4320  }
4321  break;
4322  case EAS_LightFace :
4323  {
4324  bool bExtrusionLightFace;
4325  if ( rProp.Value >>= bExtrusionLightFace )
4327  bExtrusionLightFace ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
4328  }
4329  break;
4330  case EAS_FirstLightHarsh :
4331  {
4332  bool bExtrusionFirstLightHarsh;
4333  if ( rProp.Value >>= bExtrusionFirstLightHarsh )
4335  bExtrusionFirstLightHarsh ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
4336  }
4337  break;
4338  case EAS_SecondLightHarsh :
4339  {
4340  bool bExtrusionSecondLightHarsh;
4341  if ( rProp.Value >>= bExtrusionSecondLightHarsh )
4343  bExtrusionSecondLightHarsh ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
4344  }
4345  break;
4346  case EAS_FirstLightLevel :
4347  {
4348  double fExtrusionFirstLightLevel = 0;
4349  if ( rProp.Value >>= fExtrusionFirstLightLevel )
4350  {
4352  aStrBuffer,
4353  fExtrusionFirstLightLevel,
4354  false,
4355  util::MeasureUnit::PERCENT,
4356  util::MeasureUnit::PERCENT);
4357  aStrBuffer.append( '%' );
4358  aStr = aStrBuffer.makeStringAndClear();
4360  }
4361  }
4362  break;
4363  case EAS_SecondLightLevel :
4364  {
4365  double fExtrusionSecondLightLevel = 0;
4366  if ( rProp.Value >>= fExtrusionSecondLightLevel )
4367  {
4369  aStrBuffer,
4370  fExtrusionSecondLightLevel,
4371  false,
4372  util::MeasureUnit::PERCENT,
4373  util::MeasureUnit::PERCENT);
4374  aStrBuffer.append( '%' );
4375  aStr = aStrBuffer.makeStringAndClear();
4377  }
4378  }
4379  break;
4381  {
4382  drawing::Direction3D aExtrusionFirstLightDirection;
4383  if ( rProp.Value >>= aExtrusionFirstLightDirection )
4384  {
4385  ::basegfx::B3DVector aVec3D( aExtrusionFirstLightDirection.DirectionX, aExtrusionFirstLightDirection.DirectionY,
4386  aExtrusionFirstLightDirection.DirectionZ );
4387  SvXMLUnitConverter::convertB3DVector( aStrBuffer, aVec3D );
4388  aStr = aStrBuffer.makeStringAndClear();
4390  }
4391  }
4392  break;
4394  {
4395  drawing::Direction3D aExtrusionSecondLightDirection;
4396  if ( rProp.Value >>= aExtrusionSecondLightDirection )
4397  {
4398  ::basegfx::B3DVector aVec3D( aExtrusionSecondLightDirection.DirectionX, aExtrusionSecondLightDirection.DirectionY,
4399  aExtrusionSecondLightDirection.DirectionZ );
4400  SvXMLUnitConverter::convertB3DVector( aStrBuffer, aVec3D );
4401  aStr = aStrBuffer.makeStringAndClear();
4403  }
4404  }
4405  break;
4406  case EAS_Metal :
4407  {
4408  bool bExtrusionMetal;
4409  if ( rProp.Value >>= bExtrusionMetal )
4411  bExtrusionMetal ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
4412  }
4413  break;
4414  case EAS_ShadeMode :
4415  {
4416  // shadeMode
4417  drawing::ShadeMode eShadeMode;
4418  if( rProp.Value >>= eShadeMode )
4419  {
4420  if( eShadeMode == drawing::ShadeMode_FLAT )
4421  aStr = GetXMLToken( XML_FLAT );
4422  else if( eShadeMode == drawing::ShadeMode_PHONG )
4423  aStr = GetXMLToken( XML_PHONG );
4424  else if( eShadeMode == drawing::ShadeMode_SMOOTH )
4425  aStr = GetXMLToken( XML_GOURAUD );
4426  else
4427  aStr = GetXMLToken( XML_DRAFT );
4428  }
4429  else
4430  {
4431  // ShadeMode enum not there, write default
4432  aStr = GetXMLToken( XML_FLAT);
4433  }
4435  }
4436  break;
4437  case EAS_RotateAngle :
4438  {
4439  css::drawing::EnhancedCustomShapeParameterPair aRotateAngleParaPair;
4440  if ( rProp.Value >>= aRotateAngleParaPair )
4441  {
4442  ExportParameter( aStrBuffer, aRotateAngleParaPair.First );
4443  ExportParameter( aStrBuffer, aRotateAngleParaPair.Second );
4444  aStr = aStrBuffer.makeStringAndClear();
4446  }
4447  }
4448  break;
4449  case EAS_RotationCenter :
4450  {
4451  drawing::Direction3D aExtrusionRotationCenter;
4452  if ( rProp.Value >>= aExtrusionRotationCenter )
4453  {
4454  ::basegfx::B3DVector aVec3D( aExtrusionRotationCenter.DirectionX, aExtrusionRotationCenter.DirectionY,
4455  aExtrusionRotationCenter.DirectionZ );
4456  SvXMLUnitConverter::convertB3DVector( aStrBuffer, aVec3D );
4457  aStr = aStrBuffer.makeStringAndClear();
4459  }
4460  }
4461  break;
4462  case EAS_Shininess :
4463  {
4464  double fExtrusionShininess = 0;
4465  if ( rProp.Value >>= fExtrusionShininess )
4466  {
4468  aStrBuffer,
4469  fExtrusionShininess,
4470  false,
4471  util::MeasureUnit::PERCENT,
4472  util::MeasureUnit::PERCENT);
4473  aStrBuffer.append( '%' );
4474  aStr = aStrBuffer.makeStringAndClear();
4476  }
4477  }
4478  break;
4479  case EAS_Skew :
4480  {
4481  css::drawing::EnhancedCustomShapeParameterPair aSkewParaPair;
4482  if ( rProp.Value >>= aSkewParaPair )
4483  {
4484  ExportParameter( aStrBuffer, aSkewParaPair.First );
4485  ExportParameter( aStrBuffer, aSkewParaPair.Second );
4486  aStr = aStrBuffer.makeStringAndClear();
4488  }
4489  }
4490  break;
4491  case EAS_Specularity :
4492  {
4493  double fExtrusionSpecularity = 0;
4494  if ( rProp.Value >>= fExtrusionSpecularity )
4495  {
4497  aStrBuffer,
4498  fExtrusionSpecularity,
4499  false,
4500  util::MeasureUnit::PERCENT,
4501  util::MeasureUnit::PERCENT);
4502  aStrBuffer.append( '%' );
4503  aStr = aStrBuffer.makeStringAndClear();
4505  }
4506  }
4507  break;
4508  case EAS_ProjectionMode :
4509  {
4510  drawing::ProjectionMode eProjectionMode;
4511  if ( rProp.Value >>= eProjectionMode )
4513  eProjectionMode == drawing::ProjectionMode_PARALLEL ? GetXMLToken( XML_PARALLEL ) : GetXMLToken( XML_PERSPECTIVE ) );
4514  }
4515  break;
4516  case EAS_ViewPoint :
4517  {
4518  drawing::Position3D aExtrusionViewPoint;
4519  if ( rProp.Value >>= aExtrusionViewPoint )
4520  {
4521  rUnitConverter.convertPosition3D( aStrBuffer, aExtrusionViewPoint );
4522  aStr = aStrBuffer.makeStringAndClear();
4524  }
4525  }
4526  break;
4527  case EAS_Origin :
4528  {
4529  css::drawing::EnhancedCustomShapeParameterPair aOriginParaPair;
4530  if ( rProp.Value >>= aOriginParaPair )
4531  {
4532  ExportParameter( aStrBuffer, aOriginParaPair.First );
4533  ExportParameter( aStrBuffer, aOriginParaPair.Second );
4534  aStr = aStrBuffer.makeStringAndClear();
4536  }
4537  }
4538  break;
4539  case EAS_Color :
4540  {
4541  bool bExtrusionColor;
4542  if ( rProp.Value >>= bExtrusionColor )
4543  {
4545  bExtrusionColor ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
4546  }
4547  }
4548  break;
4549  default:
4550  break;
4551  }
4552  }
4553  }
4554  }
4555  break;
4556  case EAS_TextPath :
4557  {
4558  uno::Sequence< beans::PropertyValue > aTextPathPropSeq;
4559  if ( rGeoProp.Value >>= aTextPathPropSeq )
4560  {
4561  for ( const beans::PropertyValue& rProp : std::as_const(aTextPathPropSeq) )
4562  {
4563  switch( EASGet( rProp.Name ) )
4564  {
4565  case EAS_TextPath :
4566  {
4567  bool bTextPathOn;
4568  if ( rProp.Value >>= bTextPathOn )
4570  bTextPathOn ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
4571  }
4572  break;
4573  case EAS_TextPathMode :
4574  {
4575  css::drawing::EnhancedCustomShapeTextPathMode eTextPathMode;
4576  if ( rProp.Value >>= eTextPathMode )
4577  {
4578  switch ( eTextPathMode )
4579  {
4580  case css::drawing::EnhancedCustomShapeTextPathMode_NORMAL: aStr = GetXMLToken( XML_NORMAL ); break;
4581  case css::drawing::EnhancedCustomShapeTextPathMode_PATH : aStr = GetXMLToken( XML_PATH ); break;
4582  case css::drawing::EnhancedCustomShapeTextPathMode_SHAPE : aStr = GetXMLToken( XML_SHAPE ); break;
4583  default:
4584  break;
4585  }
4586  if ( !aStr.isEmpty() )
4588  }
4589  }
4590  break;
4591  case EAS_ScaleX :
4592  {
4593  bool bScaleX;
4594  if ( rProp.Value >>= bScaleX )
4595  {
4596  aStr = bScaleX ? GetXMLToken( XML_SHAPE ) : GetXMLToken( XML_PATH );
4598  }
4599  }
4600  break;
4601  case EAS_SameLetterHeights :
4602  {
4603  bool bSameLetterHeights;
4604  if ( rProp.Value >>= bSameLetterHeights )
4606  bSameLetterHeights ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
4607  }
4608  break;
4609  default:
4610  break;
4611  }
4612  }
4613  }
4614  }
4615  break;
4616  case EAS_Path :
4617  {
4618  uno::Sequence< beans::PropertyValue > aPathPropSeq;
4619  if ( rGeoProp.Value >>= aPathPropSeq )
4620  {
4621  for ( const beans::PropertyValue& rProp : std::as_const(aPathPropSeq) )
4622  {
4623  switch( EASGet( rProp.Name ) )
4624  {
4625  case EAS_SubViewSize:
4626  {
4627  // export draw:sub-view-size (do not export in ODF 1.3 or older)
4629  {
4630  continue;
4631  }
4632  uno::Sequence< awt::Size > aSubViewSizes;
4633  rProp.Value >>= aSubViewSizes;
4634 
4635  for ( int nIdx = 0; nIdx < aSubViewSizes.getLength(); nIdx++ )
4636  {
4637  if ( nIdx )
4638  aStrBuffer.append(' ');
4639  aStrBuffer.append( aSubViewSizes[nIdx].Width );
4640  aStrBuffer.append(' ');
4641  aStrBuffer.append( aSubViewSizes[nIdx].Height );
4642  }
4643  aStr = aStrBuffer.makeStringAndClear();
4645  }
4646  break;
4647  case EAS_ExtrusionAllowed :
4648  {
4649  bool bExtrusionAllowed;
4650  if ( rProp.Value >>= bExtrusionAllowed )
4652  bExtrusionAllowed ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
4653  }
4654  break;
4656  {
4657  bool bConcentricGradientFillAllowed;
4658  if ( rProp.Value >>= bConcentricGradientFillAllowed )
4660  bConcentricGradientFillAllowed ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
4661  }
4662  break;
4663  case EAS_TextPathAllowed :
4664  {
4665  bool bTextPathAllowed;
4666  if ( rProp.Value >>= bTextPathAllowed )
4668  bTextPathAllowed ? GetXMLToken( XML_TRUE ) : GetXMLToken( XML_FALSE ) );
4669  }
4670  break;
4671  case EAS_GluePoints :
4672  {
4673  css::uno::Sequence< css::drawing::EnhancedCustomShapeParameterPair> aGluePoints;
4674  if ( rProp.Value >>= aGluePoints )
4675  {
4676  if ( aGluePoints.hasElements() )
4677  {
4678  for( const auto& rGluePoint : std::as_const(aGluePoints) )
4679  {
4680  ExportParameter( aStrBuffer, rGluePoint.First );
4681  ExportParameter( aStrBuffer, rGluePoint.Second );
4682  }
4683  aStr = aStrBuffer.makeStringAndClear();
4684  }
4686  }
4687  }
4688  break;
4689  case EAS_GluePointType :
4690  {
4691  sal_Int16 nGluePointType = sal_Int16();
4692  if ( rProp.Value >>= nGluePointType )
4693  {
4694  switch ( nGluePointType )
4695  {
4696  case css::drawing::EnhancedCustomShapeGluePointType::NONE : aStr = GetXMLToken( XML_NONE ); break;
4697  case css::drawing::EnhancedCustomShapeGluePointType::SEGMENTS : aStr = GetXMLToken( XML_SEGMENTS ); break;
4698  case css::drawing::EnhancedCustomShapeGluePointType::RECT : aStr = GetXMLToken( XML_RECTANGLE ); break;
4699  }
4700  if ( !aStr.isEmpty() )
4702  }
4703  }
4704  break;
4705  case EAS_Coordinates :
4706  {
4707  bCoordinates = ( rProp.Value >>= aCoordinates );
4708  }
4709  break;
4710  case EAS_Segments :
4711  {
4712  rProp.Value >>= aSegments;
4713  }
4714  break;
4715  case EAS_StretchX :
4716  {
4717  sal_Int32 nStretchPoint = 0;
4718  if ( rProp.Value >>= nStretchPoint )
4719  rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_PATH_STRETCHPOINT_X, OUString::number( nStretchPoint ) );
4720  }
4721  break;
4722  case EAS_StretchY :
4723  {
4724  sal_Int32 nStretchPoint = 0;
4725  if ( rProp.Value >>= nStretchPoint )
4726  rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_PATH_STRETCHPOINT_Y, OUString::number( nStretchPoint ) );
4727  }
4728  break;
4729  case EAS_TextFrames :
4730  {
4731  css::uno::Sequence< css::drawing::EnhancedCustomShapeTextFrame > aPathTextFrames;
4732  if ( rProp.Value >>= aPathTextFrames )
4733  {
4734  if ( aPathTextFrames.hasElements() )
4735  {
4736  for ( const auto& rPathTextFrame : std::as_const(aPathTextFrames) )
4737  {
4738  ExportParameter( aStrBuffer, rPathTextFrame.TopLeft.First );
4739  ExportParameter( aStrBuffer, rPathTextFrame.TopLeft.Second );
4740  ExportParameter( aStrBuffer, rPathTextFrame.BottomRight.First );
4741  ExportParameter( aStrBuffer, rPathTextFrame.BottomRight.Second );
4742  }
4743  aStr = aStrBuffer.makeStringAndClear();
4744  }
4746  }
4747  }
4748  break;
4749  default:
4750  break;
4751  }
4752  }
4753  }
4754  }
4755  break;
4756  case EAS_Equations :
4757  {
4758  bEquations = ( rGeoProp.Value >>= aEquations );
4759  }
4760  break;
4761  case EAS_Handles :
4762  {
4763  bHandles = ( rGeoProp.Value >>= aHandles );
4764  }
4765  break;
4766  case EAS_AdjustmentValues :
4767  {
4768  rGeoProp.Value >>= aAdjustmentValues;
4769  }
4770  break;
4771  default:
4772  break;
4773  }
4774  } // for
4775  rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_TYPE, aCustomShapeType );
4776 
4777  // adjustments
4778  sal_Int32 nAdjustmentValues = aAdjustmentValues.getLength();
4779  if ( nAdjustmentValues )
4780  {
4781  sal_Int32 i, nValue = 0;
4782  for ( i = 0; i < nAdjustmentValues; i++ )
4783  {
4784  if ( i )
4785  aStrBuffer.append( ' ' );
4786 
4787  const css::drawing::EnhancedCustomShapeAdjustmentValue& rAdj = aAdjustmentValues[ i ];
4788  if ( rAdj.State == beans::PropertyState_DIRECT_VALUE )
4789  {
4790  if ( rAdj.Value.getValueTypeClass() == uno::TypeClass_DOUBLE )
4791  {
4792  double fValue = 0.0;
4793  rAdj.Value >>= fValue;
4794  ::sax::Converter::convertDouble(aStrBuffer, fValue);
4795  }
4796  else
4797  {
4798  rAdj.Value >>= nValue;
4799  aStrBuffer.append(nValue);
4800  }
4801  }
4802  else
4803  {
4804  // this should not be, but better than setting nothing
4805  aStrBuffer.append("0");
4806  }
4807  }
4808  aStr = aStrBuffer.makeStringAndClear();
4809  rExport.AddAttribute( XML_NAMESPACE_DRAW, XML_MODIFIERS, aStr );
4810  }
4811  if ( bCoordinates )
4812  ImpExportEnhancedPath( rExport, aCoordinates, aSegments );
4813  }
4814  }
4815  SvXMLElementExport aOBJ( rExport, XML_NAMESPACE_DRAW, XML_ENHANCED_GEOMETRY, true, true );
4816  if ( bEquations )
4817  ImpExportEquations( rExport, aEquations );
4818  if ( bHandles )
4819  ImpExportHandles( rExport, aHandles );
4820 }
4821 
4823  const uno::Reference< drawing::XShape >& xShape,
4824  XMLShapeExportFlags nFeatures, css::awt::Point* pRefPoint )
4825 {
4826  const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
4827  if ( !xPropSet.is() )
4828  return;
4829 
4830  uno::Reference< beans::XPropertySetInfo > xPropSetInfo( xPropSet->getPropertySetInfo() );
4831 
4832  // Transformation
4833  ImpExportNewTrans( xPropSet, nFeatures, pRefPoint );
4834 
4835  if ( xPropSetInfo.is() )
4836  {
4837  OUString aStr;
4838  if ( xPropSetInfo->hasPropertyByName( "CustomShapeEngine" ) )
4839  {
4840  uno::Any aEngine( xPropSet->getPropertyValue( "CustomShapeEngine" ) );
4841  if ( ( aEngine >>= aStr ) && !aStr.isEmpty() )
4843  }
4844  if ( xPropSetInfo->hasPropertyByName( "CustomShapeData" ) )
4845  {
4846  uno::Any aData( xPropSet->getPropertyValue( "CustomShapeData" ) );
4847  if ( ( aData >>= aStr ) && !aStr.isEmpty() )
4849  }
4850  }
4851  bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE ); // #86116#/#92210#
4852  SvXMLElementExport aOBJ( mrExport, XML_NAMESPACE_DRAW, XML_CUSTOM_SHAPE, bCreateNewline, true );
4853  ImpExportDescription( xShape ); // #i68101#
4854  ImpExportEvents( xShape );
4855  ImpExportGluePoints( xShape );
4856  ImpExportText( xShape );
4857  ImpExportEnhancedGeometry( mrExport, xPropSet );
4858 
4859 }
4860 
4861 void XMLShapeExport::ImpExportTableShape( const uno::Reference< drawing::XShape >& xShape, XmlShapeType eShapeType, XMLShapeExportFlags nFeatures, css::awt::Point* pRefPoint )
4862 {
4863  uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
4864  uno::Reference< container::XNamed > xNamed(xShape, uno::UNO_QUERY);
4865 
4866  SAL_WARN_IF( !xPropSet.is() || !xNamed.is(), "xmloff", "xmloff::XMLShapeExport::ImpExportTableShape(), table shape is not implementing needed interfaces");
4867  if(!(xPropSet.is() && xNamed.is()))
4868  return;
4869 
4870  try
4871  {
4872  // Transformation
4873  ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);
4874 
4875  bool bIsEmptyPresObj = false;
4876 
4877  // presentation settings
4878  if(eShapeType == XmlShapeTypePresTableShape)
4879  bIsEmptyPresObj = ImpExportPresentationAttributes( xPropSet, GetXMLToken(XML_TABLE) );
4880 
4881  const bool bCreateNewline( (nFeatures & XMLShapeExportFlags::NO_WS) == XMLShapeExportFlags::NONE );
4882  const bool bExportEmbedded(mrExport.getExportFlags() & SvXMLExportFlags::EMBEDDED);
4883 
4884  SvXMLElementExport aElement( mrExport, XML_NAMESPACE_DRAW, XML_FRAME, bCreateNewline, true );
4885 
4886  // do not export in ODF 1.1 or older
4888  {
4889  if( !bIsEmptyPresObj )
4890  {
4891  uno::Reference< container::XNamed > xTemplate( xPropSet->getPropertyValue("TableTemplate"), uno::UNO_QUERY );
4892  if( xTemplate.is() )
4893  {
4894  const OUString sTemplate( xTemplate->getName() );
4895  if( !sTemplate.isEmpty() )
4896  {
4898 
4899  for( const XMLPropertyMapEntry* pEntry = &aXMLTableShapeAttributes[0]; pEntry->msApiName; pEntry++ )
4900  {
4901  try
4902  {
4903  bool bBool = false;
4904  const OUString sAPIPropertyName( pEntry->msApiName, pEntry->nApiNameLength, RTL_TEXTENCODING_ASCII_US );
4905 
4906  xPropSet->getPropertyValue( sAPIPropertyName ) >>= bBool;
4907  if( bBool )
4908  mrExport.AddAttribute(pEntry->mnNameSpace, pEntry->meXMLName, XML_TRUE );
4909  }
4910  catch( uno::Exception& )
4911  {
4912  DBG_UNHANDLED_EXCEPTION("xmloff.draw");
4913  }
4914  }
4915  }
4916  }
4917 
4918  uno::Reference< table::XColumnRowRange > xRange( xPropSet->getPropertyValue( gsModel ), uno::UNO_QUERY_THROW );
4919  GetShapeTableExport()->exportTable( xRange );
4920  }
4921  }
4922 
4923  if( !bIsEmptyPresObj )
4924  {
4925  uno::Reference< graphic::XGraphic > xGraphic( xPropSet->getPropertyValue("ReplacementGraphic"), uno::UNO_QUERY );
4926  if( xGraphic.is() ) try
4927  {
4928  uno::Reference< uno::XComponentContext > xContext = GetExport().getComponentContext();
4929 
4930  uno::Reference< embed::XStorage > xPictureStorage;
4931  uno::Reference< embed::XStorage > xStorage;
4932  uno::Reference< io::XStream > xPictureStream;
4933 
4934  OUString sPictureName;
4935  if( bExportEmbedded )
4936  {
4937  xPictureStream.set( xContext->getServiceManager()->createInstanceWithContext( "com.sun.star.comp.MemoryStream", xContext), uno::UNO_QUERY_THROW );
4938  }
4939  else
4940  {
4941  xStorage.set( GetExport().GetTargetStorage(), uno::UNO_SET_THROW );
4942 
4943  xPictureStorage.set( xStorage->openStorageElement( "Pictures" , ::embed::ElementModes::READWRITE ), uno::UNO_SET_THROW );
4944 
4945  sal_Int32 nIndex = 0;
4946  do
4947  {
4948  sPictureName = "TablePreview" + OUString::number( ++nIndex ) + ".svm";
4949  }
4950  while( xPictureStorage->hasByName( sPictureName ) );
4951 
4952  xPictureStream.set( xPictureStorage->openStreamElement( sPictureName, ::embed::ElementModes::READWRITE ), uno::UNO_SET_THROW );
4953  }
4954 
4955  uno::Reference< graphic::XGraphicProvider > xProvider( graphic::GraphicProvider::create(xContext) );
4956  uno::Sequence< beans::PropertyValue > aArgs( 2 );
4957  aArgs[ 0 ].Name = "MimeType";
4958  aArgs[ 0 ].Value <<= OUString( "image/x-vclgraphic" );
4959  aArgs[ 1 ].Name = "OutputStream";
4960  aArgs[ 1 ].Value <<= xPictureStream->getOutputStream();
4961  xProvider->storeGraphic( xGraphic, aArgs );
4962 
4963  if( xPictureStorage.is() )
4964  {
4965  uno::Reference< embed::XTransactedObject > xTrans( xPictureStorage, uno::UNO_QUERY );
4966  if( xTrans.is() )
4967  xTrans->commit();
4968  }
4969 
4970  if( !bExportEmbedded )
4971  {
4972  OUString sURL = "Pictures/" + sPictureName;
4977  }
4978 
4979  SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_DRAW, XML_IMAGE, false, true );
4980 
4981  if( bExportEmbedded )
4982  {
4983  uno::Reference< io::XSeekableInputStream > xSeekable( xPictureStream, uno::UNO_QUERY_THROW );
4984  xSeekable->seek(0);
4985 
4986  XMLBase64Export aBase64Exp( GetExport() );
4987  aBase64Exp.exportOfficeBinaryDataElement( uno::Reference < io::XInputStream >( xPictureStream, uno::UNO_QUERY_THROW ) );
4988  }
4989  }
4990  catch( uno::Exception const & )
4991  {
4992  DBG_UNHANDLED_EXCEPTION("xmloff.draw");
4993  }
4994  }
4995 
4996  ImpExportEvents( xShape );
4997  ImpExportGluePoints( xShape );
4998  ImpExportDescription( xShape ); // #i68101#
4999  }
5000  catch( uno::Exception const & )
5001  {
5002  DBG_UNHANDLED_EXCEPTION("xmloff.draw");
5003  }
5004 }
5005 
5006 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
css::uno::Reference< css::embed::XStorage > const & GetTargetStorage() const
Definition: xmlexp.cxx:2287
#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)
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)
void setX(double fX)
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:318
constexpr sal_uInt16 XML_NAMESPACE_OFFICE
rtl::Reference< XMLShapeExport > const & GetShapeExport()
Definition: xmlexp.hxx:568
void AddRotate(double fNew)
Definition: xexptran.cxx:228
void set(sal_uInt16 nRow, sal_uInt16 nColumn, double fValue)
bool NeedsAction() const
Definition: xexptran.hxx:55
SAL_DLLPRIVATE void ImpCalcShapeType(const css::uno::Reference< css::drawing::XShape > &xShape, XmlShapeType &eShapeType)
SAL_DLLPRIVATE bool ImpExportPresentationAttributes(const css::uno::Reference< css::beans::XPropertySet > &xPropSet, const OUString &rClass)
EnhancedCustomShapeTokenEnum EASGet(const OUString &rShapeType)
ShapesInfos maShapesInfos
XmlShapeType
Definition: shapeexport.hxx:70
constexpr sal_uInt16 XML_NAMESPACE_DR3D
::comphelper::UnoInterfaceToUniqueIdentifierMapper & getInterfaceToIdentifierMapper()
Definition: xmlexp.cxx:2276
constexpr sal_uInt16 XML_NAMESPACE_DRAW_EXT
SAL_DLLPRIVATE void ImpExportPageShape(const css::uno::Reference< css::drawing::XShape > &xShape, XmlShapeType eShapeType, XMLShapeExportFlags nFeatures=SEF_DEFAULT, css::awt::Point *pRefPoint=nullptr)
static void CopyInputToOutput(const css::uno::Reference< css::io::XInputStream > &xInput, const css::uno::Reference< css::io::XOutputStream > &xOutput)
the SvXMLTypeConverter converts values of various types from their internal representation to the tex...
Definition: xmluconv.hxx:80