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