1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <config_wasm_strip.h>
22 #include <basegfx/matrix/b2dhommatrix.hxx>
23 #include <basegfx/matrix/b3dhommatrix.hxx>
24 #include <basegfx/polygon/b2dpolypolygon.hxx>
25 #include <basegfx/polygon/b2dpolypolygontools.hxx>
26 #include <basegfx/polygon/b2dpolygontools.hxx>
27 #include <basegfx/polygon/b3dpolypolygon.hxx>
28 #include <basegfx/polygon/b3dpolypolygontools.hxx>
29 #include <basegfx/tuple/b2dtuple.hxx>
30 #include <basegfx/vector/b3dvector.hxx>
32 #include <com/sun/star/beans/XPropertyState.hpp>
33 #include <com/sun/star/beans/PropertyValues.hpp>
34 #include <com/sun/star/container/XChild.hpp>
35 #include <com/sun/star/container/XEnumerationAccess.hpp>
36 #include <com/sun/star/container/XIdentifierAccess.hpp>
37 #include <com/sun/star/container/XNamed.hpp>
38 #include <com/sun/star/document/XEventsSupplier.hpp>
39 #include <com/sun/star/drawing/CameraGeometry.hpp>
40 #include <com/sun/star/drawing/CircleKind.hpp>
41 #include <com/sun/star/drawing/ConnectorType.hpp>
42 #include <com/sun/star/drawing/Direction3D.hpp>
43 #include <com/sun/star/drawing/EscapeDirection.hpp>
44 #include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
45 #include <com/sun/star/drawing/EnhancedCustomShapeGluePointType.hpp>
46 #include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp>
47 #include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp>
48 #include <com/sun/star/drawing/EnhancedCustomShapeMetalType.hpp>
49 #include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp>
50 #include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp>
51 #include <com/sun/star/drawing/EnhancedCustomShapeTextFrame.hpp>
52 #include <com/sun/star/drawing/EnhancedCustomShapeTextPathMode.hpp>
53 #include <com/sun/star/drawing/GluePoint2.hpp>
54 #include <com/sun/star/drawing/HomogenMatrix.hpp>
55 #include <com/sun/star/drawing/HomogenMatrix3.hpp>
56 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
57 #include <com/sun/star/drawing/PolyPolygonShape3D.hpp>
58 #include <com/sun/star/drawing/Position3D.hpp>
59 #include <com/sun/star/drawing/ProjectionMode.hpp>
60 #include <com/sun/star/drawing/ShadeMode.hpp>
61 #include <com/sun/star/drawing/XControlShape.hpp>
62 #include <com/sun/star/drawing/XCustomShapeEngine.hpp>
63 #include <com/sun/star/drawing/XGluePointsSupplier.hpp>
64 #include <com/sun/star/drawing/BarCode.hpp>
65 #include <com/sun/star/drawing/BarCodeErrorCorrection.hpp>
66 #include <com/sun/star/drawing/XShapes3.hpp>
67 #include <com/sun/star/embed/ElementModes.hpp>
68 #include <com/sun/star/embed/XStorage.hpp>
69 #include <com/sun/star/embed/XTransactedObject.hpp>
70 #include <com/sun/star/graphic/XGraphic.hpp>
71 #include <com/sun/star/graphic/GraphicProvider.hpp>
72 #include <com/sun/star/graphic/XGraphicProvider.hpp>
73 #include <com/sun/star/io/XSeekableInputStream.hpp>
74 #include <com/sun/star/io/XStream.hpp>
75 #include <com/sun/star/lang/ServiceNotRegisteredException.hpp>
76 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
77 #include <com/sun/star/media/ZoomLevel.hpp>
78 #include <com/sun/star/presentation/AnimationSpeed.hpp>
79 #include <com/sun/star/presentation/ClickAction.hpp>
80 #include <com/sun/star/style/XStyle.hpp>
81 #include <com/sun/star/table/XColumnRowRange.hpp>
82 #include <com/sun/star/text/WritingMode2.hpp>
83 #include <com/sun/star/text/XText.hpp>
85 #include <comphelper/classids.hxx>
86 #include <comphelper/processfactory.hxx>
87 #include <comphelper/propertyvalue.hxx>
88 #include <comphelper/sequenceashashmap.hxx>
89 #include <comphelper/storagehelper.hxx>
90 #include <officecfg/Office/Common.hxx>
92 #include <o3tl/any.hxx>
93 #include <o3tl/typed_flags_set.hxx>
94 #include <o3tl/string_view.hxx>
96 #include <rtl/math.hxx>
97 #include <rtl/ustrbuf.hxx>
98 #include <rtl/ustring.hxx>
99 #include <sal/log.hxx>
101 #include <sax/tools/converter.hxx>
103 #include <tools/debug.hxx>
104 #include <tools/globname.hxx>
105 #include <tools/helpers.hxx>
106 #include <comphelper/diagnose_ex.hxx>
107 #include <vcl/graph.hxx>
109 #include <xmloff/contextid.hxx>
110 #include <xmloff/families.hxx>
111 #include <xmloff/namespacemap.hxx>
112 #include <xmloff/shapeexport.hxx>
113 #include <xmloff/unointerfacetouniqueidentifiermapper.hxx>
114 #include <xmloff/xmlexp.hxx>
115 #include <xmloff/xmlnamespace.hxx>
116 #include <xmloff/xmltoken.hxx>
117 #include <xmloff/xmluconv.hxx>
118 #include <xmloff/table/XMLTableExport.hxx>
119 #include <xmloff/ProgressBarHelper.hxx>
122 #include <EnhancedCustomShapeToken.hxx>
123 #include "sdpropls.hxx"
124 #include <xexptran.hxx>
125 #include "ximpshap.hxx"
126 #include <XMLBase64Export.hxx>
127 #include <XMLImageMapExport.hxx>
131 using namespace ::com::sun::star
;
132 using namespace ::xmloff::EnhancedCustomShapeToken
;
133 using namespace ::xmloff::token
;
135 constexpr OUStringLiteral XML_EMBEDDEDOBJECTGRAPHIC_URL_BASE
= u
"vnd.sun.star.GraphicObject:";
139 bool supportsText(XmlShapeType eShapeType
)
141 return eShapeType
!= XmlShapeType::PresChartShape
&&
142 eShapeType
!= XmlShapeType::PresOLE2Shape
&&
143 eShapeType
!= XmlShapeType::DrawSheetShape
&&
144 eShapeType
!= XmlShapeType::PresSheetShape
&&
145 eShapeType
!= XmlShapeType::Draw3DSceneObject
&&
146 eShapeType
!= XmlShapeType::Draw3DCubeObject
&&
147 eShapeType
!= XmlShapeType::Draw3DSphereObject
&&
148 eShapeType
!= XmlShapeType::Draw3DLatheObject
&&
149 eShapeType
!= XmlShapeType::Draw3DExtrudeObject
&&
150 eShapeType
!= XmlShapeType::DrawPageShape
&&
151 eShapeType
!= XmlShapeType::PresPageShape
&&
152 eShapeType
!= XmlShapeType::DrawGroupShape
;
158 constexpr OUString
gsZIndex( u
"ZOrder"_ustr
);
159 constexpr OUStringLiteral
gsPrintable( u
"Printable" );
160 constexpr OUStringLiteral
gsVisible( u
"Visible" );
161 constexpr OUString
gsModel( u
"Model"_ustr
);
162 constexpr OUStringLiteral
gsStartShape( u
"StartShape" );
163 constexpr OUStringLiteral
gsEndShape( u
"EndShape" );
164 constexpr OUString
gsOnClick( u
"OnClick"_ustr
);
165 constexpr OUStringLiteral
gsEventType( u
"EventType" );
166 constexpr OUStringLiteral
gsPresentation( u
"Presentation" );
167 constexpr OUStringLiteral
gsMacroName( u
"MacroName" );
168 constexpr OUString
gsScript( u
"Script"_ustr
);
169 constexpr OUStringLiteral
gsLibrary( u
"Library" );
170 constexpr OUStringLiteral
gsClickAction( u
"ClickAction" );
171 constexpr OUString
gsBookmark( u
"Bookmark"_ustr
);
172 constexpr OUStringLiteral
gsEffect( u
"Effect" );
173 constexpr OUStringLiteral
gsPlayFull( u
"PlayFull" );
174 constexpr OUStringLiteral
gsVerb( u
"Verb" );
175 constexpr OUStringLiteral
gsSoundURL( u
"SoundURL" );
176 constexpr OUStringLiteral
gsSpeed( u
"Speed" );
177 constexpr OUStringLiteral
gsStarBasic( u
"StarBasic" );
178 constexpr OUStringLiteral
gsHyperlink( u
"Hyperlink" );
180 XMLShapeExport::XMLShapeExport(SvXMLExport
& rExp
,
181 SvXMLExportPropertyMapper
*pExtMapper
)
183 maCurrentShapesIter(maShapesInfos
.end()),
184 mbExportLayer( false ),
185 // #88546# init to sal_False
186 mbHandleProgressBar( false )
188 // construct PropertySetMapper
189 mxPropertySetMapper
= CreateShapePropMapper( mrExport
);
192 rtl::Reference
< SvXMLExportPropertyMapper
> xExtMapper( pExtMapper
);
193 mxPropertySetMapper
->ChainExportMapper( xExtMapper
);
197 // chain text attributes
198 xPropertySetMapper->ChainExportMapper(XMLTextParagraphExport::CreateParaExtPropMapper(rExp));
201 mrExport
.GetAutoStylePool()->AddFamily(
202 XmlStyleFamily::SD_GRAPHICS_ID
,
203 XML_STYLE_FAMILY_SD_GRAPHICS_NAME
,
204 GetPropertySetMapper(),
205 XML_STYLE_FAMILY_SD_GRAPHICS_PREFIX
);
206 mrExport
.GetAutoStylePool()->AddFamily(
207 XmlStyleFamily::SD_PRESENTATION_ID
,
208 XML_STYLE_FAMILY_SD_PRESENTATION_NAME
,
209 GetPropertySetMapper(),
210 XML_STYLE_FAMILY_SD_PRESENTATION_PREFIX
);
212 // create table export helper and let him add his families in time
213 GetShapeTableExport();
216 XMLShapeExport::~XMLShapeExport()
220 // sj: replacing CustomShapes with standard objects that are also supported in OpenOffice.org format
221 uno::Reference
< drawing::XShape
> XMLShapeExport::checkForCustomShapeReplacement( const uno::Reference
< drawing::XShape
>& xShape
)
223 uno::Reference
< drawing::XShape
> xCustomShapeReplacement
;
225 if( !( GetExport().getExportFlags() & SvXMLExportFlags::OASIS
) )
227 OUString
aType( xShape
->getShapeType() );
228 if( aType
== "com.sun.star.drawing.CustomShape" )
230 uno::Reference
< beans::XPropertySet
> xSet( xShape
, uno::UNO_QUERY
);
234 xSet
->getPropertyValue(u
"CustomShapeEngine"_ustr
) >>= aEngine
;
235 if ( aEngine
.isEmpty() )
237 aEngine
= "com.sun.star.drawing.EnhancedCustomShapeEngine";
239 const uno::Reference
< uno::XComponentContext
>& xContext( ::comphelper::getProcessComponentContext() );
241 if ( !aEngine
.isEmpty() )
243 uno::Sequence
< beans::PropertyValue
> aPropValues
{
244 comphelper::makePropertyValue(u
"CustomShape"_ustr
, xShape
),
245 comphelper::makePropertyValue(u
"ForceGroupWithText"_ustr
, true)
247 uno::Sequence
< uno::Any
> aArgument
= { uno::Any(aPropValues
) };
248 uno::Reference
< uno::XInterface
> xInterface(
249 xContext
->getServiceManager()->createInstanceWithArgumentsAndContext(aEngine
, aArgument
, xContext
) );
250 if ( xInterface
.is() )
252 uno::Reference
< drawing::XCustomShapeEngine
> xCustomShapeEngine(
253 uno::Reference
< drawing::XCustomShapeEngine
>( xInterface
, uno::UNO_QUERY
) );
254 if ( xCustomShapeEngine
.is() )
255 xCustomShapeReplacement
= xCustomShapeEngine
->render();
261 return xCustomShapeReplacement
;
264 // This method collects all automatic styles for the given XShape
265 void XMLShapeExport::collectShapeAutoStyles(const uno::Reference
< drawing::XShape
>& xShape
)
267 if( maCurrentShapesIter
== maShapesInfos
.end() )
269 OSL_FAIL( "XMLShapeExport::collectShapeAutoStyles(): no call to seekShapes()!" );
272 sal_Int32 nZIndex
= 0;
273 uno::Reference
< beans::XPropertySet
> xPropSet(xShape
, uno::UNO_QUERY
);
275 xPropSet
->getPropertyValue(gsZIndex
) >>= nZIndex
;
277 ImplXMLShapeExportInfoVector
& aShapeInfoVector
= (*maCurrentShapesIter
).second
;
279 if( static_cast<sal_Int32
>(aShapeInfoVector
.size()) <= nZIndex
)
281 OSL_FAIL( "XMLShapeExport::collectShapeAutoStyles(): no shape info allocated for a given shape" );
285 ImplXMLShapeExportInfo
& aShapeInfo
= aShapeInfoVector
[nZIndex
];
287 uno::Reference
< drawing::XShape
> xCustomShapeReplacement
= checkForCustomShapeReplacement( xShape
);
288 if ( xCustomShapeReplacement
.is() )
289 aShapeInfo
.xCustomShapeReplacement
= std::move(xCustomShapeReplacement
);
291 // first compute the shapes type
292 ImpCalcShapeType(xShape
, aShapeInfo
.meShapeType
);
294 // #i118485# enabled XmlShapeType::DrawChartShape and XmlShapeType::DrawOLE2Shape
296 const bool bObjSupportsText
=
297 supportsText(aShapeInfo
.meShapeType
);
299 const bool bObjSupportsStyle
=
300 aShapeInfo
.meShapeType
!= XmlShapeType::DrawGroupShape
;
302 bool bIsEmptyPresObj
= false;
304 if ( aShapeInfo
.xCustomShapeReplacement
.is() )
308 if( xPropSet
.is() && bObjSupportsText
)
310 uno::Reference
< text::XText
> xText(xShape
, uno::UNO_QUERY
);
315 // tdf#153161: it seems that the call to XTextRange::getString flushes the changes
316 // for some objects, that otherwise fail to get exported correctly. Maybe at some
317 // point it would make sense to find a better place for more targeted flush.
320 catch (uno::RuntimeException
const&)
322 // E.g., SwXTextFrame that contains only a table will throw; this is not an error
325 uno::Reference
< beans::XPropertySetInfo
> xPropSetInfo( xPropSet
->getPropertySetInfo() );
327 if( xPropSetInfo
.is() && xPropSetInfo
->hasPropertyByName(u
"IsEmptyPresentationObject"_ustr
) )
329 uno::Any aAny
= xPropSet
->getPropertyValue(u
"IsEmptyPresentationObject"_ustr
);
330 aAny
>>= bIsEmptyPresObj
;
335 GetExport().GetTextParagraphExport()->collectTextAutoStyles( xText
);
340 // compute the shape parent style
343 uno::Reference
< beans::XPropertySetInfo
> xPropertySetInfo( xPropSet
->getPropertySetInfo() );
345 OUString aParentName
;
346 uno::Reference
< style::XStyle
> xStyle
;
348 if( bObjSupportsStyle
)
350 if( xPropertySetInfo
.is() && xPropertySetInfo
->hasPropertyByName(u
"Style"_ustr
) )
351 xPropSet
->getPropertyValue(u
"Style"_ustr
) >>= xStyle
;
356 uno::Reference
< beans::XPropertySet
> xStylePropSet(xStyle
, uno::UNO_QUERY
);
357 SAL_WARN_IF( !xStylePropSet
.is(), "xmloff", "style without a XPropertySet?" );
360 if(xStylePropSet
.is())
362 OUString aFamilyName
;
363 xStylePropSet
->getPropertyValue(u
"Family"_ustr
) >>= aFamilyName
;
364 if( !aFamilyName
.isEmpty() && aFamilyName
!= "graphics" )
365 aShapeInfo
.mnFamily
= XmlStyleFamily::SD_PRESENTATION_ID
;
368 catch(const beans::UnknownPropertyException
&)
372 "XMLShapeExport::collectShapeAutoStyles: style has no 'Family' property");
375 // get parent-style name
376 if(XmlStyleFamily::SD_PRESENTATION_ID
== aShapeInfo
.mnFamily
)
378 aParentName
= msPresentationStylePrefix
;
381 aParentName
+= xStyle
->getName();
385 if (aParentName
.isEmpty() && xPropertySetInfo
->hasPropertyByName(u
"TextBox"_ustr
) && xPropSet
->getPropertyValue(u
"TextBox"_ustr
).hasValue() && xPropSet
->getPropertyValue(u
"TextBox"_ustr
).get
<bool>())
387 // Shapes with a Writer TextBox always have a parent style.
388 // If there would be none, then assign the default one.
389 aParentName
= "Frame";
393 std::vector
< XMLPropertyState
> aPropStates
;
395 sal_Int32 nCount
= 0;
396 if( !bIsEmptyPresObj
|| (aShapeInfo
.meShapeType
!= XmlShapeType::PresPageShape
) )
398 aPropStates
= GetPropertySetMapper()->Filter(mrExport
, xPropSet
);
400 if (XmlShapeType::DrawControlShape
== aShapeInfo
.meShapeType
)
402 // for control shapes, we additionally need the number format style (if any)
403 uno::Reference
< drawing::XControlShape
> xControl(xShape
, uno::UNO_QUERY
);
404 DBG_ASSERT(xControl
.is(), "XMLShapeExport::collectShapeAutoStyles: ShapeType control, but no XControlShape!");
407 uno::Reference
< beans::XPropertySet
> xControlModel(xControl
->getControl(), uno::UNO_QUERY
);
408 DBG_ASSERT(xControlModel
.is(), "XMLShapeExport::collectShapeAutoStyles: no control model on the control shape!");
410 OUString sNumberStyle
= mrExport
.GetFormExport()->getControlNumberStyle(xControlModel
);
411 if (!sNumberStyle
.isEmpty())
413 sal_Int32 nIndex
= GetPropertySetMapper()->getPropertySetMapper()->FindEntryIndex(CTF_SD_CONTROL_SHAPE_DATA_STYLE
);
414 // TODO : this retrieval of the index could be moved into the ctor, holding the index
415 // as member, thus saving time.
416 DBG_ASSERT(-1 != nIndex
, "XMLShapeExport::collectShapeAutoStyles: could not obtain the index for our context id!");
418 XMLPropertyState
aNewState(nIndex
, uno::Any(sNumberStyle
));
419 aPropStates
.push_back(aNewState
);
424 nCount
= std::count_if(aPropStates
.cbegin(), aPropStates
.cend(),
425 [](const XMLPropertyState
& rProp
) { return rProp
.mnIndex
!= -1; });
430 // no hard attributes, use parent style name for export
431 aShapeInfo
.msStyleName
= aParentName
;
435 // there are filtered properties -> hard attributes
436 // try to find this style in AutoStylePool
437 aShapeInfo
.msStyleName
= mrExport
.GetAutoStylePool()->Find(aShapeInfo
.mnFamily
, aParentName
, aPropStates
);
439 if(aShapeInfo
.msStyleName
.isEmpty())
441 // Style did not exist, add it to AutoStalePool
442 aShapeInfo
.msStyleName
= mrExport
.GetAutoStylePool()->Add(aShapeInfo
.mnFamily
, aParentName
, std::move(aPropStates
));
446 // optionally generate auto style for text attributes
447 if( (!bIsEmptyPresObj
|| (aShapeInfo
.meShapeType
!= XmlShapeType::PresPageShape
)) && bObjSupportsText
)
449 aPropStates
= GetExport().GetTextParagraphExport()->GetParagraphPropertyMapper()->Filter(mrExport
, xPropSet
);
451 // yet more additionally, we need to care for the ParaAdjust property
452 if ( XmlShapeType::DrawControlShape
== aShapeInfo
.meShapeType
)
454 uno::Reference
< beans::XPropertySetInfo
> xPropSetInfo( xPropSet
->getPropertySetInfo() );
455 uno::Reference
< beans::XPropertyState
> xPropState( xPropSet
, uno::UNO_QUERY
);
456 if ( xPropSetInfo
.is() && xPropState
.is() )
459 // * if controls shapes have a ParaAdjust property, then this is the Align property of the control model
460 // * control models are allowed to have an Align of "void"
461 // * the Default for control model's Align is TextAlign_LEFT
462 // * defaults for style properties are not written, but we need to write the "left",
463 // because we need to distinguish this "left" from the case where not align attribute
464 // is present which means "void"
465 if ( xPropSetInfo
->hasPropertyByName( u
"ParaAdjust"_ustr
)
466 && ( beans::PropertyState_DEFAULT_VALUE
== xPropState
->getPropertyState( u
"ParaAdjust"_ustr
) )
469 sal_Int32 nIndex
= GetExport().GetTextParagraphExport()->GetParagraphPropertyMapper()->getPropertySetMapper()->FindEntryIndex( CTF_SD_SHAPE_PARA_ADJUST
);
470 // TODO : this retrieval of the index should be moved into the ctor, holding the index
471 // as member, thus saving time.
472 DBG_ASSERT(-1 != nIndex
, "XMLShapeExport::collectShapeAutoStyles: could not obtain the index for the ParaAdjust context id!");
474 XMLPropertyState
aAlignDefaultState(nIndex
, xPropSet
->getPropertyValue(u
"ParaAdjust"_ustr
));
476 aPropStates
.push_back( aAlignDefaultState
);
481 nCount
= std::count_if(aPropStates
.cbegin(), aPropStates
.cend(),
482 [](const XMLPropertyState
& rProp
) { return rProp
.mnIndex
!= -1; });
486 aShapeInfo
.msTextStyleName
= mrExport
.GetAutoStylePool()->Find( XmlStyleFamily::TEXT_PARAGRAPH
, u
""_ustr
, aPropStates
);
487 if(aShapeInfo
.msTextStyleName
.isEmpty())
489 // Style did not exist, add it to AutoStalePool
490 aShapeInfo
.msTextStyleName
= mrExport
.GetAutoStylePool()->Add(XmlStyleFamily::TEXT_PARAGRAPH
, u
""_ustr
, std::move(aPropStates
));
496 // prepare animation information if needed
497 if( mxAnimationsExporter
.is() )
498 XMLAnimationsExporter::prepare( xShape
);
500 // check for special shapes
502 switch( aShapeInfo
.meShapeType
)
504 case XmlShapeType::DrawConnectorShape
:
506 uno::Reference
< uno::XInterface
> xConnection
;
508 // create shape ids for export later
509 xPropSet
->getPropertyValue( gsStartShape
) >>= xConnection
;
510 if( xConnection
.is() )
511 mrExport
.getInterfaceToIdentifierMapper().registerReference( xConnection
);
513 xPropSet
->getPropertyValue( gsEndShape
) >>= xConnection
;
514 if( xConnection
.is() )
515 mrExport
.getInterfaceToIdentifierMapper().registerReference( xConnection
);
518 case XmlShapeType::PresTableShape
:
519 case XmlShapeType::DrawTableShape
:
523 uno::Reference
< table::XColumnRowRange
> xRange( xPropSet
->getPropertyValue( gsModel
), uno::UNO_QUERY_THROW
);
524 GetShapeTableExport()->collectTableAutoStyles( xRange
);
526 catch(const uno::Exception
&)
528 DBG_UNHANDLED_EXCEPTION( "xmloff", "collecting auto styles for a table" );
536 // check for shape collections (group shape or 3d scene)
537 // and collect contained shapes style infos
538 const uno::Reference
< drawing::XShape
>& xCollection
= aShapeInfo
.xCustomShapeReplacement
.is()
539 ? aShapeInfo
.xCustomShapeReplacement
: xShape
;
541 uno::Reference
< drawing::XShapes
> xShapes( xCollection
, uno::UNO_QUERY
);
544 collectShapesAutoStyles( xShapes
);
551 class NewTextListsHelper
554 explicit NewTextListsHelper( SvXMLExport
& rExp
)
557 mrExport
.GetTextParagraphExport()->PushNewTextListsHelper();
560 ~NewTextListsHelper()
562 mrExport
.GetTextParagraphExport()->PopTextListsHelper();
566 SvXMLExport
& mrExport
;
569 // This method exports the given XShape
570 void XMLShapeExport::exportShape(const uno::Reference
< drawing::XShape
>& xShape
,
571 XMLShapeExportFlags nFeatures
/* = SEF_DEFAULT */,
572 css::awt::Point
* pRefPoint
/* = NULL */,
573 comphelper::AttributeList
* pAttrList
/* = NULL */ )
575 SAL_INFO("xmloff", xShape
->getShapeType());
576 if( maCurrentShapesIter
== maShapesInfos
.end() )
578 SAL_WARN( "xmloff", "XMLShapeExport::exportShape(): no auto styles where collected before export" );
581 sal_Int32 nZIndex
= 0;
582 uno::Reference
< beans::XPropertySet
> xSet( xShape
, uno::UNO_QUERY
);
586 xSet
->getPropertyValue(gsHyperlink
) >>= sHyperlink
;
588 catch (beans::UnknownPropertyException
)
592 std::unique_ptr
< SvXMLElementExport
> pHyperlinkElement
;
594 // Need to stash the attributes that are pre-loaded for the shape export
595 // (otherwise they will become attributes of the draw:a element)
596 uno::Reference
<xml::sax::XAttributeList
> xSaveAttribs(
597 new comphelper::AttributeList(GetExport().GetAttrList()));
598 GetExport().ClearAttrList();
599 if( xSet
.is() && (GetExport().GetModelType() == SvtModuleOptions::EFactory::DRAW
) )
601 // export hyperlinks with <a><shape/></a>. Currently only in draw since draw
602 // does not support document events
605 presentation::ClickAction eAction
= presentation::ClickAction_NONE
;
606 xSet
->getPropertyValue(gsOnClick
) >>= eAction
;
608 if( (eAction
== presentation::ClickAction_DOCUMENT
) ||
609 (eAction
== presentation::ClickAction_BOOKMARK
) )
612 xSet
->getPropertyValue(gsBookmark
) >>= sURL
;
614 if( !sURL
.isEmpty() )
616 mrExport
.AddAttribute( XML_NAMESPACE_XLINK
, XML_HREF
, sURL
);
617 mrExport
.AddAttribute( XML_NAMESPACE_XLINK
, XML_TYPE
, XML_SIMPLE
);
618 mrExport
.AddAttribute( XML_NAMESPACE_XLINK
, XML_SHOW
, XML_EMBED
);
619 pHyperlinkElement
.reset( new SvXMLElementExport(mrExport
, XML_NAMESPACE_DRAW
, XML_A
, true, true) );
623 catch(const uno::Exception
&)
625 TOOLS_WARN_EXCEPTION("xmloff", "XMLShapeExport::exportShape(): exception during hyperlink export");
628 else if (xSet
.is() && !sHyperlink
.isEmpty())
630 mrExport
.AddAttribute( XML_NAMESPACE_XLINK
, XML_HREF
, sHyperlink
);
631 mrExport
.AddAttribute( XML_NAMESPACE_XLINK
, XML_TYPE
, XML_SIMPLE
);
632 pHyperlinkElement
.reset( new SvXMLElementExport(mrExport
, XML_NAMESPACE_DRAW
, XML_A
, true, true) );
634 // re-add stashed attributes
635 GetExport().AddAttributeList(xSaveAttribs
);
638 xSet
->getPropertyValue(gsZIndex
) >>= nZIndex
;
640 ImplXMLShapeExportInfoVector
& aShapeInfoVector
= (*maCurrentShapesIter
).second
;
642 if( static_cast<sal_Int32
>(aShapeInfoVector
.size()) <= nZIndex
)
644 SAL_WARN( "xmloff", "XMLShapeExport::exportShape(): no shape info collected for a given shape" );
648 NewTextListsHelper
aNewTextListsHelper( mrExport
);
650 const ImplXMLShapeExportInfo
& aShapeInfo
= aShapeInfoVector
[nZIndex
];
653 // check if this is the correct ShapesInfo
654 uno::Reference
< container::XChild
> xChild( xShape
, uno::UNO_QUERY
);
657 uno::Reference
< drawing::XShapes
> xParent( xChild
->getParent(), uno::UNO_QUERY
);
658 SAL_WARN_IF( !xParent
.is() && xParent
.get() == (*maCurrentShapesIter
).first
.get(), "xmloff", "XMLShapeExport::exportShape(): Wrong call to XMLShapeExport::seekShapes()" );
661 // first compute the shapes type
663 XmlShapeType
eShapeType(XmlShapeType::NotYetSet
);
664 ImpCalcShapeType(xShape
, eShapeType
);
666 SAL_WARN_IF( eShapeType
!= aShapeInfo
.meShapeType
, "xmloff", "exportShape callings do not correspond to collectShapeAutoStyles calls!: " << xShape
->getShapeType() );
670 // collect animation information if needed
671 if( mxAnimationsExporter
.is() )
672 mxAnimationsExporter
->collect( xShape
, mrExport
);
674 /* Export shapes name if he has one (#i51726#)
675 Export of the shape name for text documents only if the OpenDocument
676 file format is written - exceptions are group shapes.
677 Note: Writer documents in OpenOffice.org file format doesn't contain
678 any names for shapes, except for group shapes.
681 if ( ( GetExport().GetModelType() != SvtModuleOptions::EFactory::WRITER
&&
682 GetExport().GetModelType() != SvtModuleOptions::EFactory::WRITERWEB
&&
683 GetExport().GetModelType() != SvtModuleOptions::EFactory::WRITERGLOBAL
) ||
684 ( GetExport().getExportFlags() & SvXMLExportFlags::OASIS
) ||
685 aShapeInfo
.meShapeType
== XmlShapeType::DrawGroupShape
||
686 ( aShapeInfo
.meShapeType
== XmlShapeType::DrawCustomShape
&&
687 aShapeInfo
.xCustomShapeReplacement
.is() ) )
689 uno::Reference
< container::XNamed
> xNamed( xShape
, uno::UNO_QUERY
);
692 const OUString
aName( xNamed
->getName() );
693 if( !aName
.isEmpty() )
694 mrExport
.AddAttribute(XML_NAMESPACE_DRAW
, XML_NAME
, aName
);
700 if( !aShapeInfo
.msStyleName
.isEmpty() )
702 if(XmlStyleFamily::SD_GRAPHICS_ID
== aShapeInfo
.mnFamily
)
703 mrExport
.AddAttribute(XML_NAMESPACE_DRAW
, XML_STYLE_NAME
, mrExport
.EncodeStyleName( aShapeInfo
.msStyleName
) );
705 mrExport
.AddAttribute(XML_NAMESPACE_PRESENTATION
, XML_STYLE_NAME
, mrExport
.EncodeStyleName( aShapeInfo
.msStyleName
) );
708 // export text style name
709 if( !aShapeInfo
.msTextStyleName
.isEmpty() )
711 mrExport
.AddAttribute(XML_NAMESPACE_DRAW
, XML_TEXT_STYLE_NAME
, aShapeInfo
.msTextStyleName
);
714 // export shapes id if needed
716 uno::Reference
< uno::XInterface
> xRef( xShape
, uno::UNO_QUERY
);
717 const OUString
& rShapeId
= mrExport
.getInterfaceToIdentifierMapper().getIdentifier( xRef
);
718 if( !rShapeId
.isEmpty() )
720 mrExport
.AddAttributeIdLegacy(XML_NAMESPACE_DRAW
, rShapeId
);
724 // export layer information
727 // check for group or scene shape and not export layer if this is one
728 uno::Reference
< drawing::XShapes
> xShapes( xShape
, uno::UNO_QUERY
);
733 uno::Reference
< beans::XPropertySet
> xProps( xShape
, uno::UNO_QUERY
);
735 xProps
->getPropertyValue(u
"LayerName"_ustr
) >>= aLayerName
;
736 mrExport
.AddAttribute(XML_NAMESPACE_DRAW
, XML_LAYER
, aLayerName
);
739 catch(const uno::Exception
&)
741 DBG_UNHANDLED_EXCEPTION( "xmloff", "exporting layer name for shape" );
746 // export draw:display (do not export in ODF 1.3 or older)
747 if (xSet
.is() && (mrExport
.getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED
))
749 if( aShapeInfo
.meShapeType
!= XmlShapeType::DrawPageShape
&& aShapeInfo
.meShapeType
!= XmlShapeType::PresPageShape
&&
750 aShapeInfo
.meShapeType
!= XmlShapeType::HandoutShape
&& aShapeInfo
.meShapeType
!= XmlShapeType::DrawChartShape
)
753 bool bVisible
= true;
754 bool bPrintable
= true;
756 xSet
->getPropertyValue(gsVisible
) >>= bVisible
;
757 xSet
->getPropertyValue(gsPrintable
) >>= bPrintable
;
759 XMLTokenEnum eDisplayToken
= XML_TOKEN_INVALID
;
760 const unsigned short nDisplay
= (bVisible
? 2 : 0) | (bPrintable
? 1 : 0);
763 case 0: eDisplayToken
= XML_NONE
; break;
764 case 1: eDisplayToken
= XML_PRINTER
; break;
765 case 2: eDisplayToken
= XML_SCREEN
; break;
766 // case 3: eDisplayToken = XML_ALWAYS break; this is the default
769 if( eDisplayToken
!= XML_TOKEN_INVALID
)
770 mrExport
.AddAttribute(XML_NAMESPACE_DRAW_EXT
, XML_DISPLAY
, eDisplayToken
);
772 catch(const uno::Exception
&)
774 DBG_UNHANDLED_EXCEPTION("xmloff.draw");
778 // #82003# test export count
779 // #91587# ALWAYS increment since now ALL to be exported shapes are counted.
780 if(mrExport
.GetShapeExport()->IsHandleProgressBarEnabled())
782 mrExport
.GetProgressBarHelper()->Increment();
787 // export shape element
788 switch(aShapeInfo
.meShapeType
)
790 case XmlShapeType::DrawRectangleShape
:
792 ImpExportRectangleShape(xShape
, nFeatures
, pRefPoint
);
795 case XmlShapeType::DrawEllipseShape
:
797 ImpExportEllipseShape(xShape
, nFeatures
, pRefPoint
);
800 case XmlShapeType::DrawLineShape
:
802 ImpExportLineShape(xShape
, nFeatures
, pRefPoint
);
805 case XmlShapeType::DrawPolyPolygonShape
: // closed PolyPolygon
806 case XmlShapeType::DrawPolyLineShape
: // open PolyPolygon
807 case XmlShapeType::DrawClosedBezierShape
: // closed tools::PolyPolygon containing curves
808 case XmlShapeType::DrawOpenBezierShape
: // open tools::PolyPolygon containing curves
810 ImpExportPolygonShape(xShape
, aShapeInfo
.meShapeType
, nFeatures
, pRefPoint
);
814 case XmlShapeType::DrawTextShape
:
815 case XmlShapeType::PresTitleTextShape
:
816 case XmlShapeType::PresOutlinerShape
:
817 case XmlShapeType::PresSubtitleShape
:
818 case XmlShapeType::PresNotesShape
:
819 case XmlShapeType::PresHeaderShape
:
820 case XmlShapeType::PresFooterShape
:
821 case XmlShapeType::PresSlideNumberShape
:
822 case XmlShapeType::PresDateTimeShape
:
824 ImpExportTextBoxShape(xShape
, aShapeInfo
.meShapeType
, nFeatures
, pRefPoint
);
828 case XmlShapeType::DrawGraphicObjectShape
:
829 case XmlShapeType::PresGraphicObjectShape
:
831 ImpExportGraphicObjectShape(xShape
, aShapeInfo
.meShapeType
, nFeatures
, pRefPoint
);
835 case XmlShapeType::DrawChartShape
:
836 case XmlShapeType::PresChartShape
:
838 ImpExportChartShape(xShape
, aShapeInfo
.meShapeType
, nFeatures
, pRefPoint
, pAttrList
);
842 case XmlShapeType::DrawControlShape
:
844 ImpExportControlShape(xShape
, nFeatures
, pRefPoint
);
848 case XmlShapeType::DrawConnectorShape
:
850 ImpExportConnectorShape(xShape
, nFeatures
, pRefPoint
);
854 case XmlShapeType::DrawMeasureShape
:
856 ImpExportMeasureShape(xShape
, nFeatures
, pRefPoint
);
860 case XmlShapeType::DrawOLE2Shape
:
861 case XmlShapeType::PresOLE2Shape
:
862 case XmlShapeType::DrawSheetShape
:
863 case XmlShapeType::PresSheetShape
:
865 ImpExportOLE2Shape(xShape
, aShapeInfo
.meShapeType
, nFeatures
, pRefPoint
);
869 case XmlShapeType::PresTableShape
:
870 case XmlShapeType::DrawTableShape
:
872 ImpExportTableShape( xShape
, aShapeInfo
.meShapeType
, nFeatures
, pRefPoint
);
876 case XmlShapeType::DrawPageShape
:
877 case XmlShapeType::PresPageShape
:
878 case XmlShapeType::HandoutShape
:
880 ImpExportPageShape(xShape
, aShapeInfo
.meShapeType
, nFeatures
, pRefPoint
);
884 case XmlShapeType::DrawCaptionShape
:
886 ImpExportCaptionShape(xShape
, nFeatures
, pRefPoint
);
890 case XmlShapeType::Draw3DCubeObject
:
891 case XmlShapeType::Draw3DSphereObject
:
892 case XmlShapeType::Draw3DLatheObject
:
893 case XmlShapeType::Draw3DExtrudeObject
:
895 ImpExport3DShape(xShape
, aShapeInfo
.meShapeType
);
899 case XmlShapeType::Draw3DSceneObject
:
901 ImpExport3DSceneShape( xShape
, nFeatures
, pRefPoint
);
905 case XmlShapeType::DrawGroupShape
:
908 ImpExportGroupShape( xShape
, nFeatures
, pRefPoint
);
912 case XmlShapeType::DrawFrameShape
:
914 ImpExportFrameShape(xShape
, nFeatures
, pRefPoint
);
918 case XmlShapeType::DrawAppletShape
:
920 ImpExportAppletShape(xShape
, nFeatures
, pRefPoint
);
924 case XmlShapeType::DrawPluginShape
:
926 ImpExportPluginShape(xShape
, nFeatures
, pRefPoint
);
930 case XmlShapeType::DrawCustomShape
:
932 if ( aShapeInfo
.xCustomShapeReplacement
.is() )
933 ImpExportGroupShape( aShapeInfo
.xCustomShapeReplacement
, nFeatures
, pRefPoint
);
935 ImpExportCustomShape( xShape
, nFeatures
, pRefPoint
);
939 case XmlShapeType::PresMediaShape
:
940 case XmlShapeType::DrawMediaShape
:
942 ImpExportMediaShape( xShape
, aShapeInfo
.meShapeType
, nFeatures
, pRefPoint
);
946 case XmlShapeType::PresOrgChartShape
:
947 case XmlShapeType::Unknown
:
948 case XmlShapeType::NotYetSet
:
951 // this should never happen and is an error
952 OSL_FAIL("XMLEXP: WriteShape: unknown or unexpected type of shape in export!");
957 pHyperlinkElement
.reset();
960 // if there was an error and no element for the shape was exported
961 // we need to clear the attribute list or the attributes will be
962 // set on the next exported element, which can result in corrupt
963 // xml files due to duplicate attributes
965 mrExport
.CheckAttrList(); // asserts in non pro if we have attributes left
966 mrExport
.ClearAttrList(); // clears the attributes
969 // This method collects all automatic styles for the shapes inside the given XShapes collection
970 void XMLShapeExport::collectShapesAutoStyles( const uno::Reference
< drawing::XShapes
>& xShapes
)
972 ShapesInfos::iterator aOldCurrentShapesIter
= maCurrentShapesIter
;
973 seekShapes( xShapes
);
975 uno::Reference
< drawing::XShape
> xShape
;
976 const sal_Int32
nShapeCount(xShapes
->getCount());
977 for(sal_Int32 nShapeId
= 0; nShapeId
< nShapeCount
; nShapeId
++)
979 xShapes
->getByIndex(nShapeId
) >>= xShape
;
980 SAL_WARN_IF( !xShape
.is(), "xmloff", "Shape without a XShape?" );
984 collectShapeAutoStyles( xShape
);
987 maCurrentShapesIter
= aOldCurrentShapesIter
;
990 // This method exports all XShape inside the given XShapes collection
991 void XMLShapeExport::exportShapes( const uno::Reference
< drawing::XShapes
>& xShapes
, XMLShapeExportFlags nFeatures
/* = SEF_DEFAULT */, awt::Point
* pRefPoint
/* = NULL */ )
993 ShapesInfos::iterator aOldCurrentShapesIter
= maCurrentShapesIter
;
994 seekShapes( xShapes
);
996 uno::Reference
< drawing::XShape
> xShape
;
997 const sal_Int32
nShapeCount(xShapes
->getCount());
998 for(sal_Int32 nShapeId
= 0; nShapeId
< nShapeCount
; nShapeId
++)
1000 xShapes
->getByIndex(nShapeId
) >>= xShape
;
1001 SAL_WARN_IF( !xShape
.is(), "xmloff", "Shape without a XShape?" );
1005 exportShape( xShape
, nFeatures
, pRefPoint
);
1008 maCurrentShapesIter
= aOldCurrentShapesIter
;
1013 void FixZOrder(uno::Reference
<drawing::XShapes
> const& xShapes
,
1014 std::function
<unsigned int (uno::Reference
<beans::XPropertySet
> const&)> const& rGetLayer
)
1016 uno::Reference
<drawing::XShapes3
> const xShapes3(xShapes
, uno::UNO_QUERY
);
1017 assert(xShapes3
.is());
1020 return; // only SvxDrawPage implements this
1022 struct Layer
{ std::vector
<sal_Int32
> shapes
; sal_Int32 nMin
= SAL_MAX_INT32
; sal_Int32 nMax
= 0; };
1023 std::vector
<Layer
> layers
;
1024 // shapes are sorted by ZOrder
1025 sal_Int32
const nCount(xShapes
->getCount());
1026 for (sal_Int32 i
= 0; i
< nCount
; ++i
)
1028 uno::Reference
<beans::XPropertySet
> const xShape(xShapes
->getByIndex(i
), uno::UNO_QUERY
);
1031 SAL_WARN("xmloff", "FixZOrder: null shape, cannot sort");
1034 unsigned int const nLayer(rGetLayer(xShape
));
1035 if (layers
.size() <= nLayer
)
1037 layers
.resize(nLayer
+ 1);
1039 layers
[nLayer
].shapes
.emplace_back(i
);
1040 if (i
< layers
[nLayer
].nMin
)
1042 layers
[nLayer
].nMin
= i
;
1044 if (layers
[nLayer
].nMax
< i
)
1046 layers
[nLayer
].nMax
= i
;
1049 std::erase_if(layers
, [](Layer
const& rLayer
) { return rLayer
.shapes
.empty(); });
1050 bool isSorted(true);
1051 for (size_t i
= 1; i
< layers
.size(); ++i
)
1053 assert(layers
[i
].nMin
!= layers
[i
-1].nMax
); // unique!
1054 if (layers
[i
].nMin
< layers
[i
-1].nMax
)
1062 return; // nothing to do
1064 uno::Sequence
<sal_Int32
> aNewOrder(nCount
);
1065 auto iterInsert(aNewOrder
.getArray());
1066 for (auto const& rLayer
: layers
)
1068 assert(rLayer
.nMin
<= rLayer
.nMax
); // empty layers have been removed
1069 iterInsert
= std::copy(rLayer
.shapes
.begin(), rLayer
.shapes
.end(), iterInsert
);
1073 xShapes3
->sort(aNewOrder
);
1075 catch (uno::Exception
const&)
1077 SAL_WARN("xmloff", "FixZOrder: exception");
1081 } // namespace xmloff
1083 void XMLShapeExport::seekShapes( const uno::Reference
< drawing::XShapes
>& xShapes
) noexcept
1087 maCurrentShapesIter
= maShapesInfos
.find( xShapes
);
1088 if( maCurrentShapesIter
== maShapesInfos
.end() )
1090 auto itPair
= maShapesInfos
.emplace( xShapes
, ImplXMLShapeExportInfoVector( static_cast<ShapesInfos::size_type
>(xShapes
->getCount()) ) );
1092 maCurrentShapesIter
= itPair
.first
;
1094 SAL_WARN_IF( maCurrentShapesIter
== maShapesInfos
.end(), "xmloff", "XMLShapeExport::seekShapes(): insert into stl::map failed" );
1097 SAL_WARN_IF( (*maCurrentShapesIter
).second
.size() != static_cast<ShapesInfos::size_type
>(xShapes
->getCount()), "xmloff", "XMLShapeExport::seekShapes(): XShapes size varied between calls" );
1102 maCurrentShapesIter
= maShapesInfos
.end();
1106 void XMLShapeExport::exportAutoStyles()
1108 // export all autostyle infos
1112 GetExport().GetAutoStylePool()->exportXML( XmlStyleFamily::SD_GRAPHICS_ID
);
1115 // ...for presentation
1117 GetExport().GetAutoStylePool()->exportXML( XmlStyleFamily::SD_PRESENTATION_ID
);
1120 if( mxShapeTableExport
.is() )
1121 mxShapeTableExport
->exportAutoStyles();
1124 /// returns the export property mapper for external chaining
1125 SvXMLExportPropertyMapper
* XMLShapeExport::CreateShapePropMapper(
1126 SvXMLExport
& rExport
)
1128 rtl::Reference
< XMLPropertyHandlerFactory
> xFactory
= new XMLSdPropHdlFactory( rExport
.GetModel(), rExport
);
1129 rtl::Reference
< XMLPropertySetMapper
> xMapper
= new XMLShapePropertySetMapper( xFactory
, true );
1130 rExport
.GetTextParagraphExport(); // get or create text paragraph export
1131 SvXMLExportPropertyMapper
* pResult
=
1132 new XMLShapeExportPropertyMapper( xMapper
, rExport
);
1133 // chain text attributes
1137 void XMLShapeExport::ImpCalcShapeType(const uno::Reference
< drawing::XShape
>& xShape
,
1138 XmlShapeType
& eShapeType
)
1140 // set in every case, so init here
1141 eShapeType
= XmlShapeType::Unknown
;
1146 OUString
aType(xShape
->getShapeType());
1148 if(!aType
.match("com.sun.star."))
1151 if(aType
.match("drawing.", 13))
1154 if (aType
.match("Rectangle", 21)) { eShapeType
= XmlShapeType::DrawRectangleShape
; }
1156 // #i72177# Note: Correcting CustomShape, CustomShape->Custom, len from 9 (was wrong anyways) to 6.
1157 // As can be seen at the other compares, the appendix "Shape" is left out of the comparison.
1158 else if(aType
.match("Custom", 21)) { eShapeType
= XmlShapeType::DrawCustomShape
; }
1160 else if(aType
.match("Ellipse", 21)) { eShapeType
= XmlShapeType::DrawEllipseShape
; }
1161 else if(aType
.match("Control", 21)) { eShapeType
= XmlShapeType::DrawControlShape
; }
1162 else if(aType
.match("Connector", 21)) { eShapeType
= XmlShapeType::DrawConnectorShape
; }
1163 else if(aType
.match("Measure", 21)) { eShapeType
= XmlShapeType::DrawMeasureShape
; }
1164 else if(aType
.match("Line", 21)) { eShapeType
= XmlShapeType::DrawLineShape
; }
1166 // #i72177# Note: This covers two types by purpose, PolyPolygonShape and PolyPolygonPathShape
1167 else if(aType
.match("PolyPolygon", 21)) { eShapeType
= XmlShapeType::DrawPolyPolygonShape
; }
1169 // #i72177# Note: This covers two types by purpose, PolyLineShape and PolyLinePathShape
1170 else if(aType
.match("PolyLine", 21)) { eShapeType
= XmlShapeType::DrawPolyLineShape
; }
1172 else if(aType
.match("OpenBezier", 21)) { eShapeType
= XmlShapeType::DrawOpenBezierShape
; }
1173 else if(aType
.match("ClosedBezier", 21)) { eShapeType
= XmlShapeType::DrawClosedBezierShape
; }
1175 // #i72177# FreeHand (opened and closed) now supports the types OpenFreeHandShape and
1176 // ClosedFreeHandShape respectively. Represent them as bezier shapes
1177 else if(aType
.match("OpenFreeHand", 21)) { eShapeType
= XmlShapeType::DrawOpenBezierShape
; }
1178 else if(aType
.match("ClosedFreeHand", 21)) { eShapeType
= XmlShapeType::DrawClosedBezierShape
; }
1180 else if(aType
.match("GraphicObject", 21)) { eShapeType
= XmlShapeType::DrawGraphicObjectShape
; }
1181 else if(aType
.match("Group", 21)) { eShapeType
= XmlShapeType::DrawGroupShape
; }
1182 else if(aType
.match("Text", 21)) { eShapeType
= XmlShapeType::DrawTextShape
; }
1183 else if(aType
.match("OLE2", 21))
1185 eShapeType
= XmlShapeType::DrawOLE2Shape
;
1187 // get info about presentation shape
1188 uno::Reference
<beans::XPropertySet
> xPropSet(xShape
, uno::UNO_QUERY
);
1193 if(xPropSet
->getPropertyValue(u
"CLSID"_ustr
) >>= sCLSID
)
1195 #if !ENABLE_WASM_STRIP_CHART
1196 // WASM_CHART change
1197 // TODO: With Chart extracted this cannot really happen since
1198 // no Chart could've been added at all
1199 if (sCLSID
== mrExport
.GetChartExport()->getChartCLSID() ||
1203 sCLSID
== SvGlobalName( SO3_RPTCH_CLASSID
).GetHexName() )
1205 eShapeType
= XmlShapeType::DrawChartShape
;
1207 else if (sCLSID
== SvGlobalName( SO3_SC_CLASSID
).GetHexName() )
1209 eShapeType
= XmlShapeType::DrawSheetShape
;
1213 // general OLE2 Object
1218 else if(aType
.match("Page", 21)) { eShapeType
= XmlShapeType::DrawPageShape
; }
1219 else if(aType
.match("Frame", 21)) { eShapeType
= XmlShapeType::DrawFrameShape
; }
1220 else if(aType
.match("Caption", 21)) { eShapeType
= XmlShapeType::DrawCaptionShape
; }
1221 else if(aType
.match("Plugin", 21)) { eShapeType
= XmlShapeType::DrawPluginShape
; }
1222 else if(aType
.match("Applet", 21)) { eShapeType
= XmlShapeType::DrawAppletShape
; }
1223 else if(aType
.match("MediaShape", 21)) { eShapeType
= XmlShapeType::DrawMediaShape
; }
1224 else if(aType
.match("TableShape", 21)) { eShapeType
= XmlShapeType::DrawTableShape
; }
1227 else if(aType
.match("Scene", 21 + 7)) { eShapeType
= XmlShapeType::Draw3DSceneObject
; }
1228 else if(aType
.match("Cube", 21 + 7)) { eShapeType
= XmlShapeType::Draw3DCubeObject
; }
1229 else if(aType
.match("Sphere", 21 + 7)) { eShapeType
= XmlShapeType::Draw3DSphereObject
; }
1230 else if(aType
.match("Lathe", 21 + 7)) { eShapeType
= XmlShapeType::Draw3DLatheObject
; }
1231 else if(aType
.match("Extrude", 21 + 7)) { eShapeType
= XmlShapeType::Draw3DExtrudeObject
; }
1233 else if(aType
.match("presentation.", 13))
1235 // presentation shapes
1236 if (aType
.match("TitleText", 26)) { eShapeType
= XmlShapeType::PresTitleTextShape
; }
1237 else if(aType
.match("Outliner", 26)) { eShapeType
= XmlShapeType::PresOutlinerShape
; }
1238 else if(aType
.match("Subtitle", 26)) { eShapeType
= XmlShapeType::PresSubtitleShape
; }
1239 else if(aType
.match("GraphicObject", 26)) { eShapeType
= XmlShapeType::PresGraphicObjectShape
; }
1240 else if(aType
.match("Page", 26)) { eShapeType
= XmlShapeType::PresPageShape
; }
1241 else if(aType
.match("OLE2", 26))
1243 eShapeType
= XmlShapeType::PresOLE2Shape
;
1245 // get info about presentation shape
1246 uno::Reference
<beans::XPropertySet
> xPropSet(xShape
, uno::UNO_QUERY
);
1248 if(xPropSet
.is()) try
1251 if(xPropSet
->getPropertyValue(u
"CLSID"_ustr
) >>= sCLSID
)
1253 if( sCLSID
== SvGlobalName( SO3_SC_CLASSID
).GetHexName() )
1255 eShapeType
= XmlShapeType::PresSheetShape
;
1259 catch(const uno::Exception
&)
1261 SAL_WARN( "xmloff", "XMLShapeExport::ImpCalcShapeType(), expected ole shape to have the CLSID property?" );
1264 else if(aType
.match("Chart", 26)) { eShapeType
= XmlShapeType::PresChartShape
; }
1265 else if(aType
.match("OrgChart", 26)) { eShapeType
= XmlShapeType::PresOrgChartShape
; }
1266 else if(aType
.match("CalcShape", 26)) { eShapeType
= XmlShapeType::PresSheetShape
; }
1267 else if(aType
.match("TableShape", 26)) { eShapeType
= XmlShapeType::PresTableShape
; }
1268 else if(aType
.match("Notes", 26)) { eShapeType
= XmlShapeType::PresNotesShape
; }
1269 else if(aType
.match("HandoutShape", 26)) { eShapeType
= XmlShapeType::HandoutShape
; }
1270 else if(aType
.match("HeaderShape", 26)) { eShapeType
= XmlShapeType::PresHeaderShape
; }
1271 else if(aType
.match("FooterShape", 26)) { eShapeType
= XmlShapeType::PresFooterShape
; }
1272 else if(aType
.match("SlideNumberShape", 26)) { eShapeType
= XmlShapeType::PresSlideNumberShape
; }
1273 else if(aType
.match("DateTimeShape", 26)) { eShapeType
= XmlShapeType::PresDateTimeShape
; }
1274 else if(aType
.match("MediaShape", 26)) { eShapeType
= XmlShapeType::PresMediaShape
; }
1278 /** exports all user defined gluepoints */
1279 void XMLShapeExport::ImpExportGluePoints( const uno::Reference
< drawing::XShape
>& xShape
)
1281 uno::Reference
< drawing::XGluePointsSupplier
> xSupplier( xShape
, uno::UNO_QUERY
);
1282 if( !xSupplier
.is() )
1285 uno::Reference
< container::XIdentifierAccess
> xGluePoints( xSupplier
->getGluePoints(), uno::UNO_QUERY
);
1286 if( !xGluePoints
.is() )
1289 drawing::GluePoint2 aGluePoint
;
1291 const uno::Sequence
< sal_Int32
> aIdSequence( xGluePoints
->getIdentifiers() );
1293 for( const sal_Int32 nIdentifier
: aIdSequence
)
1295 if( (xGluePoints
->getByIdentifier( nIdentifier
) >>= aGluePoint
) && aGluePoint
.IsUserDefined
)
1297 // export only user defined gluepoints
1299 const OUString
sId( OUString::number( nIdentifier
) );
1300 mrExport
.AddAttribute(XML_NAMESPACE_DRAW
, XML_ID
, sId
);
1302 mrExport
.GetMM100UnitConverter().convertMeasureToXML(msBuffer
,
1303 aGluePoint
.Position
.X
);
1304 mrExport
.AddAttribute(XML_NAMESPACE_SVG
, XML_X
, msBuffer
.makeStringAndClear());
1306 mrExport
.GetMM100UnitConverter().convertMeasureToXML(msBuffer
,
1307 aGluePoint
.Position
.Y
);
1308 mrExport
.AddAttribute(XML_NAMESPACE_SVG
, XML_Y
, msBuffer
.makeStringAndClear());
1310 if( !aGluePoint
.IsRelative
)
1312 SvXMLUnitConverter::convertEnum( msBuffer
, aGluePoint
.PositionAlignment
, aXML_GlueAlignment_EnumMap
);
1313 mrExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_ALIGN
, msBuffer
.makeStringAndClear() );
1316 if( aGluePoint
.Escape
!= drawing::EscapeDirection_SMART
)
1318 SvXMLUnitConverter::convertEnum( msBuffer
, aGluePoint
.Escape
, aXML_GlueEscapeDirection_EnumMap
);
1319 mrExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_ESCAPE_DIRECTION
, msBuffer
.makeStringAndClear() );
1322 SvXMLElementExport
aEventsElemt(mrExport
, XML_NAMESPACE_DRAW
, XML_GLUE_POINT
, true, true);
1327 void XMLShapeExport::ImpExportSignatureLine(const uno::Reference
<drawing::XShape
>& xShape
)
1329 uno::Reference
<beans::XPropertySet
> xPropSet(xShape
, uno::UNO_QUERY
);
1331 bool bIsSignatureLine
= false;
1332 xPropSet
->getPropertyValue(u
"IsSignatureLine"_ustr
) >>= bIsSignatureLine
;
1333 if (!bIsSignatureLine
)
1336 OUString aSignatureLineId
;
1337 xPropSet
->getPropertyValue(u
"SignatureLineId"_ustr
) >>= aSignatureLineId
;
1338 mrExport
.AddAttribute(XML_NAMESPACE_LO_EXT
, XML_ID
, aSignatureLineId
);
1340 OUString aSuggestedSignerName
;
1341 xPropSet
->getPropertyValue(u
"SignatureLineSuggestedSignerName"_ustr
) >>= aSuggestedSignerName
;
1342 if (!aSuggestedSignerName
.isEmpty())
1343 mrExport
.AddAttribute(XML_NAMESPACE_LO_EXT
, XML_SUGGESTED_SIGNER_NAME
, aSuggestedSignerName
);
1345 OUString aSuggestedSignerTitle
;
1346 xPropSet
->getPropertyValue(u
"SignatureLineSuggestedSignerTitle"_ustr
) >>= aSuggestedSignerTitle
;
1347 if (!aSuggestedSignerTitle
.isEmpty())
1348 mrExport
.AddAttribute(XML_NAMESPACE_LO_EXT
, XML_SUGGESTED_SIGNER_TITLE
, aSuggestedSignerTitle
);
1350 OUString aSuggestedSignerEmail
;
1351 xPropSet
->getPropertyValue(u
"SignatureLineSuggestedSignerEmail"_ustr
) >>= aSuggestedSignerEmail
;
1352 if (!aSuggestedSignerEmail
.isEmpty())
1353 mrExport
.AddAttribute(XML_NAMESPACE_LO_EXT
, XML_SUGGESTED_SIGNER_EMAIL
, aSuggestedSignerEmail
);
1355 OUString aSigningInstructions
;
1356 xPropSet
->getPropertyValue(u
"SignatureLineSigningInstructions"_ustr
) >>= aSigningInstructions
;
1357 if (!aSigningInstructions
.isEmpty())
1358 mrExport
.AddAttribute(XML_NAMESPACE_LO_EXT
, XML_SIGNING_INSTRUCTIONS
, aSigningInstructions
);
1360 bool bShowSignDate
= false;
1361 xPropSet
->getPropertyValue(u
"SignatureLineShowSignDate"_ustr
) >>= bShowSignDate
;
1362 mrExport
.AddAttribute(XML_NAMESPACE_LO_EXT
, XML_SHOW_SIGN_DATE
,
1363 bShowSignDate
? XML_TRUE
: XML_FALSE
);
1365 bool bCanAddComment
= false;
1366 xPropSet
->getPropertyValue(u
"SignatureLineCanAddComment"_ustr
) >>= bCanAddComment
;
1367 mrExport
.AddAttribute(XML_NAMESPACE_LO_EXT
, XML_CAN_ADD_COMMENT
,
1368 bCanAddComment
? XML_TRUE
: XML_FALSE
);
1370 SvXMLElementExport
aSignatureLineElement(mrExport
, XML_NAMESPACE_LO_EXT
, XML_SIGNATURELINE
, true,
1374 void XMLShapeExport::ImpExportQRCode(const uno::Reference
<drawing::XShape
>& xShape
)
1376 uno::Reference
<beans::XPropertySet
> xPropSet(xShape
, uno::UNO_QUERY
);
1378 uno::Any aAny
= xPropSet
->getPropertyValue(u
"BarCodeProperties"_ustr
);
1380 css::drawing::BarCode aBarCode
;
1381 if(!(aAny
>>= aBarCode
))
1384 mrExport
.AddAttribute(XML_NAMESPACE_OFFICE
, XML_STRING_VALUE
, aBarCode
.Payload
);
1385 /* Export QR Code as per customised schema, @see OpenDocument-schema-v1.3+libreoffice */
1387 switch(aBarCode
.ErrorCorrection
){
1388 case css::drawing::BarCodeErrorCorrection::LOW
:
1391 case css::drawing::BarCodeErrorCorrection::MEDIUM
:
1394 case css::drawing::BarCodeErrorCorrection::QUARTILE
:
1397 case css::drawing::BarCodeErrorCorrection::HIGH
:
1401 mrExport
.AddAttribute(XML_NAMESPACE_LO_EXT
, XML_QRCODE_ERROR_CORRECTION
, temp
);
1402 mrExport
.AddAttribute(XML_NAMESPACE_LO_EXT
, XML_QRCODE_BORDER
, OUStringBuffer(20).append(aBarCode
.Border
).makeStringAndClear());
1403 mrExport
.AddAttribute(XML_NAMESPACE_LO_EXT
, XML_QRCODE_TYPE
, OUStringBuffer(20).append(aBarCode
.Type
).makeStringAndClear());
1405 SvXMLElementExport
aBarCodeElement(mrExport
, XML_NAMESPACE_LO_EXT
, XML_QRCODE
, true,
1409 void XMLShapeExport::ExportGraphicDefaults()
1411 rtl::Reference
<XMLStyleExport
> aStEx(new XMLStyleExport(mrExport
, mrExport
.GetAutoStylePool().get()));
1413 // construct PropertySetMapper
1414 rtl::Reference
< SvXMLExportPropertyMapper
> xPropertySetMapper( CreateShapePropMapper( mrExport
) );
1415 static_cast<XMLShapeExportPropertyMapper
*>(xPropertySetMapper
.get())->SetAutoStyles( false );
1417 // chain text attributes
1418 xPropertySetMapper
->ChainExportMapper(XMLTextParagraphExport::CreateParaExtPropMapper(mrExport
));
1420 // chain special Writer/text frame default attributes
1421 xPropertySetMapper
->ChainExportMapper(XMLTextParagraphExport::CreateParaDefaultExtPropMapper(mrExport
));
1423 // write graphic family default style
1424 uno::Reference
< lang::XMultiServiceFactory
> xFact( mrExport
.GetModel(), uno::UNO_QUERY
);
1430 uno::Reference
< beans::XPropertySet
> xDefaults( xFact
->createInstance(u
"com.sun.star.drawing.Defaults"_ustr
), uno::UNO_QUERY
);
1431 if( xDefaults
.is() )
1433 aStEx
->exportDefaultStyle( xDefaults
, XML_STYLE_FAMILY_SD_GRAPHICS_NAME
, xPropertySetMapper
);
1435 // write graphic styles (family name differs depending on the module)
1436 aStEx
->exportStyleFamily(u
"graphics"_ustr
, XML_STYLE_FAMILY_SD_GRAPHICS_NAME
, xPropertySetMapper
, false, XmlStyleFamily::SD_GRAPHICS_ID
);
1437 aStEx
->exportStyleFamily(u
"GraphicStyles"_ustr
, XML_STYLE_FAMILY_SD_GRAPHICS_NAME
, xPropertySetMapper
, false, XmlStyleFamily::SD_GRAPHICS_ID
);
1440 catch(const lang::ServiceNotRegisteredException
&)
1445 void XMLShapeExport::onExport( const css::uno::Reference
< css::drawing::XShape
>& )
1449 const rtl::Reference
< XMLTableExport
>& XMLShapeExport::GetShapeTableExport()
1451 if( !mxShapeTableExport
.is() )
1453 rtl::Reference
< XMLPropertyHandlerFactory
> xFactory( new XMLSdPropHdlFactory( mrExport
.GetModel(), mrExport
) );
1454 rtl::Reference
< XMLPropertySetMapper
> xMapper( new XMLShapePropertySetMapper( xFactory
, true ) );
1455 mrExport
.GetTextParagraphExport(); // get or create text paragraph export
1456 rtl::Reference
< SvXMLExportPropertyMapper
> xPropertySetMapper( new XMLShapeExportPropertyMapper( xMapper
, mrExport
) );
1457 mxShapeTableExport
= new XMLTableExport( mrExport
, xPropertySetMapper
, xFactory
);
1460 return mxShapeTableExport
;
1463 void XMLShapeExport::ImpExportNewTrans(const uno::Reference
< beans::XPropertySet
>& xPropSet
,
1464 XMLShapeExportFlags nFeatures
, awt::Point
* pRefPoint
)
1467 ::basegfx::B2DHomMatrix aMatrix
;
1468 ImpExportNewTrans_GetB2DHomMatrix(aMatrix
, xPropSet
);
1470 // decompose and correct about pRefPoint
1471 ::basegfx::B2DTuple aTRScale
;
1472 double fTRShear(0.0);
1473 double fTRRotate(0.0);
1474 ::basegfx::B2DTuple aTRTranslate
;
1475 ImpExportNewTrans_DecomposeAndRefPoint(aMatrix
, aTRScale
, fTRShear
, fTRRotate
, aTRTranslate
, pRefPoint
);
1477 // use features and write
1478 ImpExportNewTrans_FeaturesAndWrite(aTRScale
, fTRShear
, fTRRotate
, aTRTranslate
, nFeatures
);
1481 void XMLShapeExport::ImpExportNewTrans_GetB2DHomMatrix(::basegfx::B2DHomMatrix
& rMatrix
,
1482 const uno::Reference
< beans::XPropertySet
>& xPropSet
)
1484 /* Get <TransformationInHoriL2R>, if it exist
1485 and if the document is exported into the OpenOffice.org file format.
1486 This property only exists at service css::text::Shape - the
1487 Writer UNO service for shapes.
1488 This code is needed, because the positioning attributes in the
1489 OpenOffice.org file format are given in horizontal left-to-right layout
1490 regardless the layout direction the shape is in. In the OASIS Open Office
1491 file format the positioning attributes are correctly given in the layout
1492 direction the shape is in. Thus, this code provides the conversion from
1493 the OASIS Open Office file format to the OpenOffice.org file format. (#i28749#)
1496 if ( !( GetExport().getExportFlags() & SvXMLExportFlags::OASIS
) &&
1497 xPropSet
->getPropertySetInfo()->hasPropertyByName(u
"TransformationInHoriL2R"_ustr
) )
1499 aAny
= xPropSet
->getPropertyValue(u
"TransformationInHoriL2R"_ustr
);
1503 aAny
= xPropSet
->getPropertyValue(u
"Transformation"_ustr
);
1505 drawing::HomogenMatrix3 aMatrix
;
1508 rMatrix
.set(0, 0, aMatrix
.Line1
.Column1
);
1509 rMatrix
.set(0, 1, aMatrix
.Line1
.Column2
);
1510 rMatrix
.set(0, 2, aMatrix
.Line1
.Column3
);
1511 rMatrix
.set(1, 0, aMatrix
.Line2
.Column1
);
1512 rMatrix
.set(1, 1, aMatrix
.Line2
.Column2
);
1513 rMatrix
.set(1, 2, aMatrix
.Line2
.Column3
);
1514 // For this to be a valid 2D transform matrix, the last row must be [0,0,1]
1515 assert( aMatrix
.Line3
.Column1
== 0 );
1516 assert( aMatrix
.Line3
.Column2
== 0 );
1517 assert( aMatrix
.Line3
.Column3
== 1 );
1520 void XMLShapeExport::ImpExportNewTrans_DecomposeAndRefPoint(const ::basegfx::B2DHomMatrix
& rMatrix
, ::basegfx::B2DTuple
& rTRScale
,
1521 double& fTRShear
, double& fTRRotate
, ::basegfx::B2DTuple
& rTRTranslate
, css::awt::Point
* pRefPoint
)
1524 rMatrix
.decompose(rTRScale
, rTRTranslate
, fTRRotate
, fTRShear
);
1526 // correct translation about pRefPoint
1529 rTRTranslate
-= ::basegfx::B2DTuple(pRefPoint
->X
, pRefPoint
->Y
);
1533 void XMLShapeExport::ImpExportNewTrans_FeaturesAndWrite(::basegfx::B2DTuple
const & rTRScale
, double fTRShear
,
1534 double fTRRotate
, ::basegfx::B2DTuple
const & rTRTranslate
, const XMLShapeExportFlags nFeatures
)
1536 // always write Size (rTRScale) since this statement carries the union
1539 OUStringBuffer sStringBuffer
;
1540 ::basegfx::B2DTuple
aTRScale(rTRScale
);
1543 if(!(nFeatures
& XMLShapeExportFlags::WIDTH
))
1549 if( aTRScale
.getX() > 0.0 )
1550 aTRScale
.setX(aTRScale
.getX() - 1.0);
1551 else if( aTRScale
.getX() < 0.0 )
1552 aTRScale
.setX(aTRScale
.getX() + 1.0);
1555 mrExport
.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer
,
1556 basegfx::fround(aTRScale
.getX()));
1557 aStr
= sStringBuffer
.makeStringAndClear();
1558 mrExport
.AddAttribute(XML_NAMESPACE_SVG
, XML_WIDTH
, aStr
);
1561 if(!(nFeatures
& XMLShapeExportFlags::HEIGHT
))
1567 if( aTRScale
.getY() > 0.0 )
1568 aTRScale
.setY(aTRScale
.getY() - 1.0);
1569 else if( aTRScale
.getY() < 0.0 )
1570 aTRScale
.setY(aTRScale
.getY() + 1.0);
1573 mrExport
.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer
,
1574 basegfx::fround(aTRScale
.getY()));
1575 aStr
= sStringBuffer
.makeStringAndClear();
1576 mrExport
.AddAttribute(XML_NAMESPACE_SVG
, XML_HEIGHT
, aStr
);
1578 // decide if transformation is necessary
1579 bool bTransformationIsNecessary(fTRShear
!= 0.0 || fTRRotate
!= 0.0);
1581 if(bTransformationIsNecessary
)
1583 // write transformation, but WITHOUT scale which is exported as size above
1584 SdXMLImExTransform2D aTransform
;
1586 aTransform
.AddSkewX(atan(fTRShear
));
1589 // fTRRotate is mathematically correct, but due to the error
1590 // we export/import it mirrored. Since the API implementation is fixed and
1591 // uses the correctly oriented angle, it is necessary for compatibility to
1592 // mirror the angle here to stay at the old behaviour. There is a follow-up
1593 // task (#i78698#) to fix this in the next ODF FileFormat version
1594 aTransform
.AddRotate(-fTRRotate
);
1596 aTransform
.AddTranslate(rTRTranslate
);
1598 // does transformation need to be exported?
1599 if(aTransform
.NeedsAction())
1600 mrExport
.AddAttribute(XML_NAMESPACE_DRAW
, XML_TRANSFORM
, aTransform
.GetExportString(mrExport
.GetMM100UnitConverter()));
1604 // no shear, no rotate; just add object position to export and we are done
1605 if(nFeatures
& XMLShapeExportFlags::X
)
1608 mrExport
.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer
,
1609 basegfx::fround(rTRTranslate
.getX()));
1610 aStr
= sStringBuffer
.makeStringAndClear();
1611 mrExport
.AddAttribute(XML_NAMESPACE_SVG
, XML_X
, aStr
);
1614 if(nFeatures
& XMLShapeExportFlags::Y
)
1617 mrExport
.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer
,
1618 basegfx::fround(rTRTranslate
.getY()));
1619 aStr
= sStringBuffer
.makeStringAndClear();
1620 mrExport
.AddAttribute(XML_NAMESPACE_SVG
, XML_Y
, aStr
);
1625 bool XMLShapeExport::ImpExportPresentationAttributes( const uno::Reference
< beans::XPropertySet
>& xPropSet
, const OUString
& rClass
)
1627 bool bIsEmpty
= false;
1629 // write presentation class entry
1630 mrExport
.AddAttribute(XML_NAMESPACE_PRESENTATION
, XML_CLASS
, rClass
);
1634 uno::Reference
< beans::XPropertySetInfo
> xPropSetInfo( xPropSet
->getPropertySetInfo() );
1637 // is empty pres. shape?
1638 if( xPropSetInfo
.is() && xPropSetInfo
->hasPropertyByName(u
"IsEmptyPresentationObject"_ustr
))
1640 xPropSet
->getPropertyValue(u
"IsEmptyPresentationObject"_ustr
) >>= bIsEmpty
;
1642 mrExport
.AddAttribute(XML_NAMESPACE_PRESENTATION
, XML_PLACEHOLDER
, XML_TRUE
);
1645 // is user-transformed?
1646 if( xPropSetInfo
.is() && xPropSetInfo
->hasPropertyByName(u
"IsPlaceholderDependent"_ustr
))
1649 xPropSet
->getPropertyValue(u
"IsPlaceholderDependent"_ustr
) >>= bTemp
;
1651 mrExport
.AddAttribute(XML_NAMESPACE_PRESENTATION
, XML_USER_TRANSFORMED
, XML_TRUE
);
1658 void XMLShapeExport::ImpExportText( const uno::Reference
< drawing::XShape
>& xShape
, TextPNS eExtensionNS
)
1660 if (eExtensionNS
== TextPNS::EXTENSION
)
1662 if ((mrExport
.getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED
) == 0)
1664 return; // do not export to ODF 1.1/1.2/1.3
1667 uno::Reference
< text::XText
> xText( xShape
, uno::UNO_QUERY
);
1670 uno::Reference
< container::XEnumerationAccess
> xEnumAccess( xShape
, uno::UNO_QUERY
);
1671 if( xEnumAccess
.is() && xEnumAccess
->hasElements() )
1672 mrExport
.GetTextParagraphExport()->exportText( xText
, false, true, eExtensionNS
);
1680 CLICKACTION
= 0x0001,
1687 CLICKEVENTTYPE
= 0x0080,
1695 template<> struct typed_flags
<Found
> : is_typed_flags
<Found
, 0x03ff> {};
1698 void XMLShapeExport::ImpExportEvents( const uno::Reference
< drawing::XShape
>& xShape
)
1700 uno::Reference
< document::XEventsSupplier
> xEventsSupplier( xShape
, uno::UNO_QUERY
);
1701 if( !xEventsSupplier
.is() )
1704 uno::Reference
< container::XNameAccess
> xEvents
= xEventsSupplier
->getEvents();
1705 SAL_WARN_IF( !xEvents
.is(), "xmloff", "XEventsSupplier::getEvents() returned NULL" );
1709 Found nFound
= Found::NONE
;
1711 OUString aClickEventType
;
1712 presentation::ClickAction eClickAction
= presentation::ClickAction_NONE
;
1713 presentation::AnimationEffect eEffect
= presentation::AnimationEffect_NONE
;
1714 presentation::AnimationSpeed eSpeed
= presentation::AnimationSpeed_SLOW
;
1715 OUString aStrSoundURL
;
1716 bool bPlayFull
= false;
1717 sal_Int32 nVerb
= 0;
1719 OUString aStrLibrary
;
1720 OUString aStrBookmark
;
1722 uno::Sequence
< beans::PropertyValue
> aClickProperties
;
1723 if( xEvents
->hasByName( gsOnClick
) && (xEvents
->getByName( gsOnClick
) >>= aClickProperties
) )
1725 for (const auto& rProperty
: aClickProperties
)
1727 if( !( nFound
& Found::CLICKEVENTTYPE
) && rProperty
.Name
== gsEventType
)
1729 if( rProperty
.Value
>>= aClickEventType
)
1730 nFound
|= Found::CLICKEVENTTYPE
;
1732 else if( !( nFound
& Found::CLICKACTION
) && rProperty
.Name
== gsClickAction
)
1734 if( rProperty
.Value
>>= eClickAction
)
1735 nFound
|= Found::CLICKACTION
;
1737 else if( !( nFound
& Found::MACRO
) && ( rProperty
.Name
== gsMacroName
|| rProperty
.Name
== gsScript
) )
1739 if( rProperty
.Value
>>= aStrMacro
)
1740 nFound
|= Found::MACRO
;
1742 else if( !( nFound
& Found::LIBRARY
) && rProperty
.Name
== gsLibrary
)
1744 if( rProperty
.Value
>>= aStrLibrary
)
1745 nFound
|= Found::LIBRARY
;
1747 else if( !( nFound
& Found::EFFECT
) && rProperty
.Name
== gsEffect
)
1749 if( rProperty
.Value
>>= eEffect
)
1750 nFound
|= Found::EFFECT
;
1752 else if( !( nFound
& Found::BOOKMARK
) && rProperty
.Name
== gsBookmark
)
1754 if( rProperty
.Value
>>= aStrBookmark
)
1755 nFound
|= Found::BOOKMARK
;
1757 else if( !( nFound
& Found::SPEED
) && rProperty
.Name
== gsSpeed
)
1759 if( rProperty
.Value
>>= eSpeed
)
1760 nFound
|= Found::SPEED
;
1762 else if( !( nFound
& Found::SOUNDURL
) && rProperty
.Name
== gsSoundURL
)
1764 if( rProperty
.Value
>>= aStrSoundURL
)
1765 nFound
|= Found::SOUNDURL
;
1767 else if( !( nFound
& Found::PLAYFULL
) && rProperty
.Name
== gsPlayFull
)
1769 if( rProperty
.Value
>>= bPlayFull
)
1770 nFound
|= Found::PLAYFULL
;
1772 else if( !( nFound
& Found::VERB
) && rProperty
.Name
== gsVerb
)
1774 if( rProperty
.Value
>>= nVerb
)
1775 nFound
|= Found::VERB
;
1780 // create the XML elements
1782 if( aClickEventType
== gsPresentation
)
1784 if( !(nFound
& Found::CLICKACTION
) || (eClickAction
== presentation::ClickAction_NONE
) )
1787 SvXMLElementExport
aEventsElemt(mrExport
, XML_NAMESPACE_OFFICE
, XML_EVENT_LISTENERS
, true, true);
1789 enum XMLTokenEnum eStrAction
;
1791 switch( eClickAction
)
1793 case presentation::ClickAction_PREVPAGE
: eStrAction
= XML_PREVIOUS_PAGE
; break;
1794 case presentation::ClickAction_NEXTPAGE
: eStrAction
= XML_NEXT_PAGE
; break;
1795 case presentation::ClickAction_FIRSTPAGE
: eStrAction
= XML_FIRST_PAGE
; break;
1796 case presentation::ClickAction_LASTPAGE
: eStrAction
= XML_LAST_PAGE
; break;
1797 case presentation::ClickAction_INVISIBLE
: eStrAction
= XML_HIDE
; break;
1798 case presentation::ClickAction_STOPPRESENTATION
:eStrAction
= XML_STOP
; break;
1799 case presentation::ClickAction_PROGRAM
: eStrAction
= XML_EXECUTE
; break;
1800 case presentation::ClickAction_BOOKMARK
: eStrAction
= XML_SHOW
; break;
1801 case presentation::ClickAction_DOCUMENT
: eStrAction
= XML_SHOW
; break;
1802 case presentation::ClickAction_MACRO
: eStrAction
= XML_EXECUTE_MACRO
; break;
1803 case presentation::ClickAction_VERB
: eStrAction
= XML_VERB
; break;
1804 case presentation::ClickAction_VANISH
: eStrAction
= XML_FADE_OUT
; break;
1805 case presentation::ClickAction_SOUND
: eStrAction
= XML_SOUND
; break;
1807 OSL_FAIL( "unknown presentation::ClickAction found!" );
1808 eStrAction
= XML_UNKNOWN
;
1811 OUString
aEventQName(
1812 mrExport
.GetNamespaceMap().GetQNameByKey(
1813 XML_NAMESPACE_DOM
, u
"click"_ustr
) );
1814 mrExport
.AddAttribute( XML_NAMESPACE_SCRIPT
, XML_EVENT_NAME
, aEventQName
);
1815 mrExport
.AddAttribute( XML_NAMESPACE_PRESENTATION
, XML_ACTION
, eStrAction
);
1817 if( eClickAction
== presentation::ClickAction_VANISH
)
1819 if( nFound
& Found::EFFECT
)
1822 XMLEffectDirection eDirection
;
1823 sal_Int16 nStartScale
;
1826 SdXMLImplSetEffect( eEffect
, eKind
, eDirection
, nStartScale
, bIn
);
1828 if( eKind
!= EK_none
)
1830 SvXMLUnitConverter::convertEnum( msBuffer
, eKind
, aXML_AnimationEffect_EnumMap
);
1831 mrExport
.AddAttribute( XML_NAMESPACE_PRESENTATION
, XML_EFFECT
, msBuffer
.makeStringAndClear() );
1834 if( eDirection
!= ED_none
)
1836 SvXMLUnitConverter::convertEnum( msBuffer
, eDirection
, aXML_AnimationDirection_EnumMap
);
1837 mrExport
.AddAttribute( XML_NAMESPACE_PRESENTATION
, XML_DIRECTION
, msBuffer
.makeStringAndClear() );
1840 if( nStartScale
!= -1 )
1842 ::sax::Converter::convertPercent( msBuffer
, nStartScale
);
1843 mrExport
.AddAttribute( XML_NAMESPACE_PRESENTATION
, XML_START_SCALE
, msBuffer
.makeStringAndClear() );
1847 if( nFound
& Found::SPEED
&& eEffect
!= presentation::AnimationEffect_NONE
)
1849 if( eSpeed
!= presentation::AnimationSpeed_MEDIUM
)
1851 SvXMLUnitConverter::convertEnum( msBuffer
, eSpeed
, aXML_AnimationSpeed_EnumMap
);
1852 mrExport
.AddAttribute( XML_NAMESPACE_PRESENTATION
, XML_SPEED
, msBuffer
.makeStringAndClear() );
1857 if( eClickAction
== presentation::ClickAction_PROGRAM
||
1858 eClickAction
== presentation::ClickAction_BOOKMARK
||
1859 eClickAction
== presentation::ClickAction_DOCUMENT
)
1861 if( eClickAction
== presentation::ClickAction_BOOKMARK
)
1862 msBuffer
.append( '#' );
1864 msBuffer
.append( aStrBookmark
);
1865 mrExport
.AddAttribute(XML_NAMESPACE_XLINK
, XML_HREF
, GetExport().GetRelativeReference(msBuffer
.makeStringAndClear()) );
1866 mrExport
.AddAttribute( XML_NAMESPACE_XLINK
, XML_TYPE
, XML_SIMPLE
);
1867 mrExport
.AddAttribute( XML_NAMESPACE_XLINK
, XML_SHOW
, XML_EMBED
);
1868 mrExport
.AddAttribute( XML_NAMESPACE_XLINK
, XML_ACTUATE
, XML_ONREQUEST
);
1871 if( ( nFound
& Found::VERB
) && eClickAction
== presentation::ClickAction_VERB
)
1873 msBuffer
.append( nVerb
);
1874 mrExport
.AddAttribute(XML_NAMESPACE_PRESENTATION
, XML_VERB
, msBuffer
.makeStringAndClear());
1877 SvXMLElementExport
aEventElemt(mrExport
, XML_NAMESPACE_PRESENTATION
, XML_EVENT_LISTENER
, true, true);
1879 if( eClickAction
== presentation::ClickAction_VANISH
|| eClickAction
== presentation::ClickAction_SOUND
)
1881 if( ( nFound
& Found::SOUNDURL
) && !aStrSoundURL
.isEmpty() )
1883 mrExport
.AddAttribute(XML_NAMESPACE_XLINK
, XML_HREF
, GetExport().GetRelativeReference(aStrSoundURL
) );
1884 mrExport
.AddAttribute( XML_NAMESPACE_XLINK
, XML_TYPE
, XML_SIMPLE
);
1885 mrExport
.AddAttribute( XML_NAMESPACE_XLINK
, XML_SHOW
, XML_NEW
);
1886 mrExport
.AddAttribute( XML_NAMESPACE_XLINK
, XML_ACTUATE
, XML_ONREQUEST
);
1887 if( nFound
& Found::PLAYFULL
&& bPlayFull
)
1888 mrExport
.AddAttribute( XML_NAMESPACE_PRESENTATION
, XML_PLAY_FULL
, XML_TRUE
);
1890 SvXMLElementExport
aElem( mrExport
, XML_NAMESPACE_PRESENTATION
, XML_SOUND
, true, true );
1894 else if( aClickEventType
== gsStarBasic
)
1896 if( nFound
& Found::MACRO
)
1898 SvXMLElementExport
aEventsElemt(mrExport
, XML_NAMESPACE_OFFICE
, XML_EVENT_LISTENERS
, true, true);
1900 mrExport
.AddAttribute( XML_NAMESPACE_SCRIPT
, XML_LANGUAGE
,
1901 mrExport
.GetNamespaceMap().GetQNameByKey(
1903 u
"starbasic"_ustr
) );
1904 OUString
aEventQName(
1905 mrExport
.GetNamespaceMap().GetQNameByKey(
1906 XML_NAMESPACE_DOM
, u
"click"_ustr
) );
1907 mrExport
.AddAttribute( XML_NAMESPACE_SCRIPT
, XML_EVENT_NAME
, aEventQName
);
1909 if( nFound
& Found::LIBRARY
)
1911 const OUString
& sLocation( GetXMLToken(
1912 (aStrLibrary
.equalsIgnoreAsciiCase("StarOffice") ||
1913 aStrLibrary
.equalsIgnoreAsciiCase("application") ) ? XML_APPLICATION
1915 mrExport
.AddAttribute(XML_NAMESPACE_SCRIPT
, XML_MACRO_NAME
,
1916 sLocation
+ ":" + aStrMacro
);
1920 mrExport
.AddAttribute( XML_NAMESPACE_SCRIPT
, XML_MACRO_NAME
, aStrMacro
);
1923 SvXMLElementExport
aEventElemt(mrExport
, XML_NAMESPACE_SCRIPT
, XML_EVENT_LISTENER
, true, true);
1926 else if( aClickEventType
== gsScript
)
1928 if( nFound
& Found::MACRO
)
1930 SvXMLElementExport
aEventsElemt(mrExport
, XML_NAMESPACE_OFFICE
, XML_EVENT_LISTENERS
, true, true);
1932 mrExport
.AddAttribute( XML_NAMESPACE_SCRIPT
, XML_LANGUAGE
, mrExport
.GetNamespaceMap().GetQNameByKey(
1933 XML_NAMESPACE_OOO
, GetXMLToken(XML_SCRIPT
) ) );
1934 OUString
aEventQName(
1935 mrExport
.GetNamespaceMap().GetQNameByKey(
1936 XML_NAMESPACE_DOM
, u
"click"_ustr
) );
1937 mrExport
.AddAttribute( XML_NAMESPACE_SCRIPT
, XML_EVENT_NAME
, aEventQName
);
1938 mrExport
.AddAttribute( XML_NAMESPACE_XLINK
, XML_HREF
, aStrMacro
);
1939 mrExport
.AddAttribute( XML_NAMESPACE_XLINK
, XML_TYPE
, u
"simple"_ustr
);
1941 SvXMLElementExport
aEventElemt(mrExport
, XML_NAMESPACE_SCRIPT
, XML_EVENT_LISTENER
, true, true);
1946 /** #i68101# export shape Title and Description */
1947 void XMLShapeExport::ImpExportDescription( const uno::Reference
< drawing::XShape
>& xShape
)
1952 OUString aDescription
;
1954 uno::Reference
< beans::XPropertySet
> xProps( xShape
, uno::UNO_QUERY_THROW
);
1955 xProps
->getPropertyValue(u
"Title"_ustr
) >>= aTitle
;
1956 xProps
->getPropertyValue(u
"Description"_ustr
) >>= aDescription
;
1958 if(!aTitle
.isEmpty())
1960 SvXMLElementExport
aEventElemt(mrExport
, XML_NAMESPACE_SVG
, XML_TITLE
, true, false);
1961 mrExport
.Characters( aTitle
);
1964 if(!aDescription
.isEmpty())
1966 SvXMLElementExport
aEventElemt(mrExport
, XML_NAMESPACE_SVG
, XML_DESC
, true, false );
1967 mrExport
.Characters( aDescription
);
1970 catch( uno::Exception
& )
1972 DBG_UNHANDLED_EXCEPTION( "xmloff", "exporting Title and/or Description for shape" );
1976 void XMLShapeExport::ImpExportGroupShape( const uno::Reference
< drawing::XShape
>& xShape
, XMLShapeExportFlags nFeatures
, awt::Point
* pRefPoint
)
1978 uno::Reference
< drawing::XShapes
> xShapes(xShape
, uno::UNO_QUERY
);
1979 if(!(xShapes
.is() && xShapes
->getCount()))
1982 // write group shape
1983 bool bCreateNewline( (nFeatures
& XMLShapeExportFlags::NO_WS
) == XMLShapeExportFlags::NONE
); // #86116#/#92210#
1984 SvXMLElementExport
aPGR(mrExport
, XML_NAMESPACE_DRAW
, XML_G
, bCreateNewline
, true);
1986 ImpExportDescription( xShape
); // #i68101#
1987 ImpExportEvents( xShape
);
1988 ImpExportGluePoints( xShape
);
1990 // #89764# if export of position is suppressed for group shape,
1991 // positions of contained objects should be written relative to
1992 // the upper left edge of the group.
1993 awt::Point aUpperLeft
;
1995 if(!(nFeatures
& XMLShapeExportFlags::POSITION
))
1997 nFeatures
|= XMLShapeExportFlags::POSITION
;
1998 aUpperLeft
= xShape
->getPosition();
1999 pRefPoint
= &aUpperLeft
;
2003 exportShapes( xShapes
, nFeatures
, pRefPoint
);
2006 void XMLShapeExport::ImpExportTextBoxShape(
2007 const uno::Reference
< drawing::XShape
>& xShape
,
2008 XmlShapeType eShapeType
, XMLShapeExportFlags nFeatures
, awt::Point
* pRefPoint
)
2010 const uno::Reference
< beans::XPropertySet
> xPropSet(xShape
, uno::UNO_QUERY
);
2014 // presentation attribute (if presentation)
2015 bool bIsPresShape(false);
2016 bool bIsEmptyPresObj(false);
2021 case XmlShapeType::PresSubtitleShape
:
2023 aStr
= GetXMLToken(XML_SUBTITLE
);
2024 bIsPresShape
= true;
2027 case XmlShapeType::PresTitleTextShape
:
2029 aStr
= GetXMLToken(XML_TITLE
);
2030 bIsPresShape
= true;
2033 case XmlShapeType::PresOutlinerShape
:
2035 aStr
= GetXMLToken(XML_PRESENTATION_OUTLINE
);
2036 bIsPresShape
= true;
2039 case XmlShapeType::PresNotesShape
:
2041 aStr
= GetXMLToken(XML_NOTES
);
2042 bIsPresShape
= true;
2045 case XmlShapeType::PresHeaderShape
:
2047 aStr
= GetXMLToken(XML_HEADER
);
2048 bIsPresShape
= true;
2051 case XmlShapeType::PresFooterShape
:
2053 aStr
= GetXMLToken(XML_FOOTER
);
2054 bIsPresShape
= true;
2057 case XmlShapeType::PresSlideNumberShape
:
2059 aStr
= GetXMLToken(XML_PAGE_NUMBER
);
2060 bIsPresShape
= true;
2063 case XmlShapeType::PresDateTimeShape
:
2065 aStr
= GetXMLToken(XML_DATE_TIME
);
2066 bIsPresShape
= true;
2074 ImpExportNewTrans(xPropSet
, nFeatures
, pRefPoint
);
2077 bIsEmptyPresObj
= ImpExportPresentationAttributes( xPropSet
, aStr
);
2079 bool bCreateNewline( (nFeatures
& XMLShapeExportFlags::NO_WS
) == XMLShapeExportFlags::NONE
); // #86116#/#92210#
2080 SvXMLElementExport
aElem( mrExport
, XML_NAMESPACE_DRAW
,
2081 XML_FRAME
, bCreateNewline
, true );
2083 // evtl. corner radius?
2084 sal_Int32
nCornerRadius(0);
2085 xPropSet
->getPropertyValue(u
"CornerRadius"_ustr
) >>= nCornerRadius
;
2088 OUStringBuffer sStringBuffer
;
2089 mrExport
.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer
,
2091 mrExport
.AddAttribute(XML_NAMESPACE_DRAW
, XML_CORNER_RADIUS
, sStringBuffer
.makeStringAndClear());
2096 SvXMLElementExport
aOBJ(mrExport
, XML_NAMESPACE_DRAW
, XML_TEXT_BOX
, true, true);
2097 if(!bIsEmptyPresObj
)
2098 ImpExportText( xShape
);
2101 ImpExportDescription( xShape
); // #i68101#
2102 ImpExportEvents( xShape
);
2103 ImpExportGluePoints( xShape
);
2107 void XMLShapeExport::ImpExportRectangleShape(
2108 const uno::Reference
< drawing::XShape
>& xShape
,
2109 XMLShapeExportFlags nFeatures
, css::awt::Point
* pRefPoint
)
2111 const uno::Reference
< beans::XPropertySet
> xPropSet(xShape
, uno::UNO_QUERY
);
2116 ImpExportNewTrans(xPropSet
, nFeatures
, pRefPoint
);
2118 // evtl. corner radius?
2119 sal_Int32
nCornerRadius(0);
2120 xPropSet
->getPropertyValue(u
"CornerRadius"_ustr
) >>= nCornerRadius
;
2123 OUStringBuffer sStringBuffer
;
2124 mrExport
.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer
,
2126 mrExport
.AddAttribute(XML_NAMESPACE_DRAW
, XML_CORNER_RADIUS
, sStringBuffer
.makeStringAndClear());
2130 bool bCreateNewline( (nFeatures
& XMLShapeExportFlags::NO_WS
) == XMLShapeExportFlags::NONE
); // #86116#/#92210#
2131 SvXMLElementExport
aOBJ(mrExport
, XML_NAMESPACE_DRAW
, XML_RECT
, bCreateNewline
, true);
2133 ImpExportDescription( xShape
); // #i68101#
2134 ImpExportEvents( xShape
);
2135 ImpExportGluePoints( xShape
);
2136 ImpExportText( xShape
);
2139 void XMLShapeExport::ImpExportLineShape(
2140 const uno::Reference
< drawing::XShape
>& xShape
,
2141 XMLShapeExportFlags nFeatures
, awt::Point
* pRefPoint
)
2143 const uno::Reference
< beans::XPropertySet
> xPropSet(xShape
, uno::UNO_QUERY
);
2148 OUStringBuffer sStringBuffer
;
2149 awt::Point
aStart(0,0);
2150 awt::Point
aEnd(1,1);
2152 // #85920# use 'Geometry' to get the points of the line
2153 // since this slot take anchor pos into account.
2156 ::basegfx::B2DHomMatrix aMatrix
;
2157 ImpExportNewTrans_GetB2DHomMatrix(aMatrix
, xPropSet
);
2159 // decompose and correct about pRefPoint
2160 ::basegfx::B2DTuple aTRScale
;
2161 double fTRShear(0.0);
2162 double fTRRotate(0.0);
2163 ::basegfx::B2DTuple aTRTranslate
;
2164 ImpExportNewTrans_DecomposeAndRefPoint(aMatrix
, aTRScale
, fTRShear
, fTRRotate
, aTRTranslate
, pRefPoint
);
2166 // create base position
2167 awt::Point
aBasePosition(basegfx::fround(aTRTranslate
.getX()),
2168 basegfx::fround(aTRTranslate
.getY()));
2170 if (xPropSet
->getPropertySetInfo()->hasPropertyByName(u
"Geometry"_ustr
))
2172 // get the two points
2173 uno::Any
aAny(xPropSet
->getPropertyValue(u
"Geometry"_ustr
));
2174 if (auto pSourcePolyPolygon
2175 = o3tl::tryAccess
<drawing::PointSequenceSequence
>(aAny
))
2177 if (pSourcePolyPolygon
->getLength() > 0)
2179 const drawing::PointSequence
& rInnerSequence
= (*pSourcePolyPolygon
)[0];
2180 if (rInnerSequence
.hasElements())
2182 const awt::Point
& rPoint
= rInnerSequence
[0];
2183 aStart
= awt::Point(rPoint
.X
+ aBasePosition
.X
, rPoint
.Y
+ aBasePosition
.Y
);
2185 if (rInnerSequence
.getLength() > 1)
2187 const awt::Point
& rPoint
= rInnerSequence
[1];
2188 aEnd
= awt::Point(rPoint
.X
+ aBasePosition
.X
, rPoint
.Y
+ aBasePosition
.Y
);
2194 if( nFeatures
& XMLShapeExportFlags::X
)
2197 mrExport
.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer
,
2199 aStr
= sStringBuffer
.makeStringAndClear();
2200 mrExport
.AddAttribute(XML_NAMESPACE_SVG
, XML_X1
, aStr
);
2207 if( nFeatures
& XMLShapeExportFlags::Y
)
2210 mrExport
.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer
,
2212 aStr
= sStringBuffer
.makeStringAndClear();
2213 mrExport
.AddAttribute(XML_NAMESPACE_SVG
, XML_Y1
, aStr
);
2221 mrExport
.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer
,
2223 aStr
= sStringBuffer
.makeStringAndClear();
2224 mrExport
.AddAttribute(XML_NAMESPACE_SVG
, XML_X2
, aStr
);
2227 mrExport
.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer
,
2229 aStr
= sStringBuffer
.makeStringAndClear();
2230 mrExport
.AddAttribute(XML_NAMESPACE_SVG
, XML_Y2
, aStr
);
2233 bool bCreateNewline( (nFeatures
& XMLShapeExportFlags::NO_WS
) == XMLShapeExportFlags::NONE
); // #86116#/#92210#
2234 SvXMLElementExport
aOBJ(mrExport
, XML_NAMESPACE_DRAW
, XML_LINE
, bCreateNewline
, true);
2236 ImpExportDescription( xShape
); // #i68101#
2237 ImpExportEvents( xShape
);
2238 ImpExportGluePoints( xShape
);
2239 ImpExportText( xShape
);
2243 void XMLShapeExport::ImpExportEllipseShape(
2244 const uno::Reference
< drawing::XShape
>& xShape
,
2245 XMLShapeExportFlags nFeatures
, awt::Point
* pRefPoint
)
2247 const uno::Reference
< beans::XPropertySet
> xPropSet(xShape
, uno::UNO_QUERY
);
2251 // get size to decide between Circle and Ellipse
2252 awt::Size aSize
= xShape
->getSize();
2253 sal_Int32
nRx((aSize
.Width
+ 1) / 2);
2254 sal_Int32
nRy((aSize
.Height
+ 1) / 2);
2255 bool bCircle(nRx
== nRy
);
2258 ImpExportNewTrans(xPropSet
, nFeatures
, pRefPoint
);
2260 drawing::CircleKind eKind
= drawing::CircleKind_FULL
;
2261 xPropSet
->getPropertyValue(u
"CircleKind"_ustr
) >>= eKind
;
2262 if( eKind
!= drawing::CircleKind_FULL
)
2264 OUStringBuffer sStringBuffer
;
2265 sal_Int32 nStartAngle
= 0;
2266 sal_Int32 nEndAngle
= 0;
2267 xPropSet
->getPropertyValue(u
"CircleStartAngle"_ustr
) >>= nStartAngle
;
2268 xPropSet
->getPropertyValue(u
"CircleEndAngle"_ustr
) >>= nEndAngle
;
2270 const double dStartAngle
= nStartAngle
/ 100.0;
2271 const double dEndAngle
= nEndAngle
/ 100.0;
2273 // export circle kind
2274 SvXMLUnitConverter::convertEnum( sStringBuffer
, eKind
, aXML_CircleKind_EnumMap
);
2275 mrExport
.AddAttribute(XML_NAMESPACE_DRAW
, XML_KIND
, sStringBuffer
.makeStringAndClear() );
2277 // export start angle
2278 ::sax::Converter::convertDouble( sStringBuffer
, dStartAngle
);
2279 mrExport
.AddAttribute(XML_NAMESPACE_DRAW
, XML_START_ANGLE
, sStringBuffer
.makeStringAndClear() );
2282 ::sax::Converter::convertDouble( sStringBuffer
, dEndAngle
);
2283 mrExport
.AddAttribute(XML_NAMESPACE_DRAW
, XML_END_ANGLE
, sStringBuffer
.makeStringAndClear() );
2286 bool bCreateNewline( (nFeatures
& XMLShapeExportFlags::NO_WS
) == XMLShapeExportFlags::NONE
); // #86116#/#92210#
2288 // write ellipse or circle
2289 SvXMLElementExport
aOBJ(mrExport
, XML_NAMESPACE_DRAW
,
2290 bCircle
? XML_CIRCLE
: XML_ELLIPSE
,
2291 bCreateNewline
, true);
2293 ImpExportDescription( xShape
); // #i68101#
2294 ImpExportEvents( xShape
);
2295 ImpExportGluePoints( xShape
);
2296 ImpExportText( xShape
);
2300 void XMLShapeExport::ImpExportPolygonShape(
2301 const uno::Reference
< drawing::XShape
>& xShape
,
2302 XmlShapeType eShapeType
, XMLShapeExportFlags nFeatures
, awt::Point
* pRefPoint
)
2304 const uno::Reference
< beans::XPropertySet
> xPropSet(xShape
, uno::UNO_QUERY
);
2308 bool bBezier(eShapeType
== XmlShapeType::DrawClosedBezierShape
2309 || eShapeType
== XmlShapeType::DrawOpenBezierShape
);
2312 ::basegfx::B2DHomMatrix aMatrix
;
2313 ImpExportNewTrans_GetB2DHomMatrix(aMatrix
, xPropSet
);
2315 // decompose and correct about pRefPoint
2316 ::basegfx::B2DTuple aTRScale
;
2317 double fTRShear(0.0);
2318 double fTRRotate(0.0);
2319 ::basegfx::B2DTuple aTRTranslate
;
2320 ImpExportNewTrans_DecomposeAndRefPoint(aMatrix
, aTRScale
, fTRShear
, fTRRotate
, aTRTranslate
, pRefPoint
);
2322 // use features and write
2323 ImpExportNewTrans_FeaturesAndWrite(aTRScale
, fTRShear
, fTRRotate
, aTRTranslate
, nFeatures
);
2325 // create and export ViewBox
2326 awt::Size
aSize(basegfx::fround
<tools::Long
>(aTRScale
.getX()),
2327 basegfx::fround
<tools::Long
>(aTRScale
.getY()));
2328 SdXMLImExViewBox
aViewBox(0, 0, aSize
.Width
, aSize
.Height
);
2329 mrExport
.AddAttribute(XML_NAMESPACE_SVG
, XML_VIEWBOX
, aViewBox
.GetExportString());
2331 bool bCreateNewline( (nFeatures
& XMLShapeExportFlags::NO_WS
) == XMLShapeExportFlags::NONE
); // #86116#/#92210#
2333 // prepare name (with most used)
2334 enum ::xmloff::token::XMLTokenEnum
eName(XML_PATH
);
2336 uno::Any
aAny( xPropSet
->getPropertyValue(u
"Geometry"_ustr
) );
2337 basegfx::B2DPolyPolygon aPolyPolygon
;
2339 // tdf#145240 the Any can contain PolyPolygonBezierCoords or PointSequenceSequence
2340 // (see OWN_ATTR_BASE_GEOMETRY in SvxShapePolyPolygon::getPropertyValueImpl),
2341 // so be more flexible in interpreting it. Try to access bezier first:
2343 auto pSourcePolyPolygon
= o3tl::tryAccess
<drawing::PolyPolygonBezierCoords
>(aAny
);
2345 if(pSourcePolyPolygon
&& pSourcePolyPolygon
->Coordinates
.getLength())
2347 aPolyPolygon
= basegfx::utils::UnoPolyPolygonBezierCoordsToB2DPolyPolygon(*pSourcePolyPolygon
);
2351 // if received no data, try to access point sequence second:
2352 if(0 == aPolyPolygon
.count())
2354 auto pSourcePolyPolygon
= o3tl::tryAccess
<drawing::PointSequenceSequence
>(aAny
);
2356 if(pSourcePolyPolygon
)
2358 aPolyPolygon
= basegfx::utils::UnoPointSequenceSequenceToB2DPolyPolygon(*pSourcePolyPolygon
);
2362 if(aPolyPolygon
.count())
2364 if(!bBezier
&& !aPolyPolygon
.areControlPointsUsed() && 1 == aPolyPolygon
.count())
2366 // simple polygon shape, can be written as svg:points sequence
2367 const basegfx::B2DPolygon
& aPolygon(aPolyPolygon
.getB2DPolygon(0));
2368 const OUString
aPointString(basegfx::utils::exportToSvgPoints(aPolygon
));
2370 // write point array
2371 mrExport
.AddAttribute(XML_NAMESPACE_DRAW
, XML_POINTS
, aPointString
);
2374 eName
= aPolygon
.isClosed() ? XML_POLYGON
: XML_POLYLINE
;
2378 // complex polygon shape, write as svg:d
2379 const OUString
aPolygonString(
2380 basegfx::utils::exportToSvgD(
2382 true, // bUseRelativeCoordinates
2383 false, // bDetectQuadraticBeziers: not used in old, but maybe activated now
2384 true)); // bHandleRelativeNextPointCompatible
2386 // write point array
2387 mrExport
.AddAttribute(XML_NAMESPACE_SVG
, XML_D
, aPolygonString
);
2391 // write object, but after attributes are added since this call will
2392 // consume all of these added attributes and the destructor will close the
2393 // scope. Also before text is added; this may add sub-scopes as needed
2394 SvXMLElementExport
aOBJ(
2401 ImpExportDescription( xShape
); // #i68101#
2402 ImpExportEvents( xShape
);
2403 ImpExportGluePoints( xShape
);
2404 ImpExportText( xShape
);
2411 OUString
getNameFromStreamURL(std::u16string_view rURL
)
2413 static constexpr std::u16string_view
sPackageURL(u
"vnd.sun.star.Package:");
2417 if (o3tl::starts_with(rURL
, sPackageURL
))
2419 std::u16string_view sRequestedName
= rURL
.substr(sPackageURL
.size());
2420 size_t nLastIndex
= sRequestedName
.rfind('/');
2421 if (nLastIndex
!= std::u16string_view::npos
&& nLastIndex
+ 1 < sRequestedName
.size())
2422 sRequestedName
= sRequestedName
.substr(nLastIndex
+ 1);
2423 nLastIndex
= sRequestedName
.rfind('.');
2424 if (nLastIndex
!= std::u16string_view::npos
)
2425 sRequestedName
= sRequestedName
.substr(0, nLastIndex
);
2426 if (!sRequestedName
.empty())
2427 sResult
= sRequestedName
;
2433 } // end anonymous namespace
2435 void XMLShapeExport::ImpExportGraphicObjectShape(
2436 const uno::Reference
< drawing::XShape
>& xShape
,
2437 XmlShapeType eShapeType
, XMLShapeExportFlags nFeatures
, awt::Point
* pRefPoint
)
2439 const uno::Reference
< beans::XPropertySet
> xPropSet(xShape
, uno::UNO_QUERY
);
2443 bool bIsEmptyPresObj
= false;
2446 ImpExportNewTrans(xPropSet
, nFeatures
, pRefPoint
);
2448 if(eShapeType
== XmlShapeType::PresGraphicObjectShape
)
2449 bIsEmptyPresObj
= ImpExportPresentationAttributes( xPropSet
, GetXMLToken(XML_GRAPHIC
) );
2451 bool bCreateNewline( (nFeatures
& XMLShapeExportFlags::NO_WS
) == XMLShapeExportFlags::NONE
); // #86116#/#92210#
2452 SvXMLElementExport
aElem( mrExport
, XML_NAMESPACE_DRAW
,
2453 XML_FRAME
, bCreateNewline
, true );
2455 if (!bIsEmptyPresObj
)
2457 uno::Reference
<graphic::XGraphic
> xGraphic
;
2458 OUString sOutMimeType
;
2461 OUString aStreamURL
;
2462 xPropSet
->getPropertyValue(u
"GraphicStreamURL"_ustr
) >>= aStreamURL
;
2463 OUString sRequestedName
= getNameFromStreamURL(aStreamURL
);
2465 xPropSet
->getPropertyValue(u
"Graphic"_ustr
) >>= xGraphic
;
2467 OUString sInternalURL
;
2470 sInternalURL
= mrExport
.AddEmbeddedXGraphic(xGraphic
, sOutMimeType
, sRequestedName
);
2472 if (!sInternalURL
.isEmpty())
2474 // apply possible changed stream URL to embedded image object
2475 if (!sRequestedName
.isEmpty())
2477 OUString newStreamURL
= u
"vnd.sun.star.Package:"_ustr
;
2478 if (sInternalURL
[0] == '#')
2480 newStreamURL
+= sInternalURL
.subView(1, sInternalURL
.getLength() - 1);
2484 newStreamURL
+= sInternalURL
;
2487 if (newStreamURL
!= aStreamURL
)
2489 xPropSet
->setPropertyValue(u
"GraphicStreamURL"_ustr
, uno::Any(newStreamURL
));
2493 mrExport
.AddAttribute(XML_NAMESPACE_XLINK
, XML_HREF
, sInternalURL
);
2494 mrExport
.AddAttribute(XML_NAMESPACE_XLINK
, XML_TYPE
, XML_SIMPLE
);
2495 mrExport
.AddAttribute(XML_NAMESPACE_XLINK
, XML_SHOW
, XML_EMBED
);
2496 mrExport
.AddAttribute(XML_NAMESPACE_XLINK
, XML_ACTUATE
, XML_ONLOAD
);
2501 if (GetExport().getSaneDefaultVersion() > SvtSaveOptions::ODFSVER_012
)
2503 if (sOutMimeType
.isEmpty())
2505 GetExport().GetGraphicMimeTypeFromStream(xGraphic
, sOutMimeType
);
2507 if (!sOutMimeType
.isEmpty())
2508 { // ODF 1.3 OFFICE-3943
2509 GetExport().AddAttribute(
2510 SvtSaveOptions::ODFSVER_013
<= GetExport().getSaneDefaultVersion()
2511 ? XML_NAMESPACE_DRAW
2512 : XML_NAMESPACE_LO_EXT
,
2513 u
"mime-type"_ustr
, sOutMimeType
);
2517 SvXMLElementExport
aElement(mrExport
, XML_NAMESPACE_DRAW
, XML_IMAGE
, true, true);
2519 // optional office:binary-data
2522 mrExport
.AddEmbeddedXGraphicAsBase64(xGraphic
);
2524 if (!bIsEmptyPresObj
)
2525 ImpExportText(xShape
);
2528 //Resolves: fdo#62461 put preferred image first above, followed by
2530 if (!bIsEmptyPresObj
2531 && officecfg::Office::Common::Save::Graphic::AddReplacementImages::get())
2533 uno::Reference
<graphic::XGraphic
> xReplacementGraphic
;
2534 xPropSet
->getPropertyValue(u
"ReplacementGraphic"_ustr
) >>= xReplacementGraphic
;
2536 // If there is no url, then the graphic is empty
2537 if (xReplacementGraphic
.is())
2540 const OUString aHref
= mrExport
.AddEmbeddedXGraphic(xReplacementGraphic
, aMimeType
);
2542 if (aMimeType
.isEmpty())
2543 mrExport
.GetGraphicMimeTypeFromStream(xReplacementGraphic
, aMimeType
);
2545 if (!aHref
.isEmpty())
2547 mrExport
.AddAttribute(XML_NAMESPACE_XLINK
, XML_HREF
, aHref
);
2548 mrExport
.AddAttribute(XML_NAMESPACE_XLINK
, XML_TYPE
, XML_SIMPLE
);
2549 mrExport
.AddAttribute(XML_NAMESPACE_XLINK
, XML_SHOW
, XML_EMBED
);
2550 mrExport
.AddAttribute(XML_NAMESPACE_XLINK
, XML_ACTUATE
, XML_ONLOAD
);
2553 if (!aMimeType
.isEmpty() && GetExport().getSaneDefaultVersion() > SvtSaveOptions::ODFSVER_012
)
2554 { // ODF 1.3 OFFICE-3943
2555 mrExport
.AddAttribute(
2556 SvtSaveOptions::ODFSVER_013
<= GetExport().getSaneDefaultVersion()
2557 ? XML_NAMESPACE_DRAW
2558 : XML_NAMESPACE_LO_EXT
,
2559 u
"mime-type"_ustr
, aMimeType
);
2562 SvXMLElementExport
aElement(mrExport
, XML_NAMESPACE_DRAW
, XML_IMAGE
, true, true);
2564 // optional office:binary-data
2565 mrExport
.AddEmbeddedXGraphicAsBase64(xReplacementGraphic
);
2570 ImpExportEvents( xShape
);
2571 ImpExportGluePoints( xShape
);
2574 GetExport().GetImageMapExport().Export( xPropSet
);
2575 ImpExportDescription( xShape
); // #i68101#
2577 // Signature Line, QR Code - needs to be after the images!
2578 if (GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED
)
2580 ImpExportSignatureLine(xShape
);
2581 ImpExportQRCode(xShape
);
2585 void XMLShapeExport::ImpExportChartShape(
2586 const uno::Reference
< drawing::XShape
>& xShape
,
2587 XmlShapeType eShapeType
, XMLShapeExportFlags nFeatures
, awt::Point
* pRefPoint
,
2588 comphelper::AttributeList
* pAttrList
)
2590 ImpExportOLE2Shape( xShape
, eShapeType
, nFeatures
, pRefPoint
, pAttrList
);
2593 void XMLShapeExport::ImpExportControlShape(
2594 const uno::Reference
< drawing::XShape
>& xShape
,
2595 XMLShapeExportFlags nFeatures
, awt::Point
* pRefPoint
)
2597 const uno::Reference
< beans::XPropertySet
> xPropSet(xShape
, uno::UNO_QUERY
);
2601 ImpExportNewTrans(xPropSet
, nFeatures
, pRefPoint
);
2604 uno::Reference
< drawing::XControlShape
> xControl( xShape
, uno::UNO_QUERY
);
2605 SAL_WARN_IF( !xControl
.is(), "xmloff", "Control shape is not supporting XControlShape" );
2608 uno::Reference
< beans::XPropertySet
> xControlModel( xControl
->getControl(), uno::UNO_QUERY
);
2609 SAL_WARN_IF( !xControlModel
.is(), "xmloff", "Control shape has not XControlModel" );
2610 if( xControlModel
.is() )
2612 OUString sControlId
= mrExport
.GetFormExport()->getControlId( xControlModel
);
2613 mrExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_CONTROL
, sControlId
);
2617 bool bCreateNewline( (nFeatures
& XMLShapeExportFlags::NO_WS
) == XMLShapeExportFlags::NONE
); // #86116#/#92210#
2618 SvXMLElementExport
aOBJ(mrExport
, XML_NAMESPACE_DRAW
, XML_CONTROL
, bCreateNewline
, true);
2620 ImpExportDescription( xShape
); // #i68101#
2623 void XMLShapeExport::ImpExportConnectorShape(
2624 const uno::Reference
< drawing::XShape
>& xShape
,
2625 XMLShapeExportFlags nFeatures
/* = SEF_DEFAULT */, awt::Point
* pRefPoint
/* = NULL */)
2627 uno::Reference
< beans::XPropertySet
> xProps( xShape
, uno::UNO_QUERY
);
2630 OUStringBuffer sStringBuffer
;
2632 // export connection kind
2633 drawing::ConnectorType eType
= drawing::ConnectorType_STANDARD
;
2634 uno::Any aAny
= xProps
->getPropertyValue(u
"EdgeKind"_ustr
);
2637 if( eType
!= drawing::ConnectorType_STANDARD
)
2639 SvXMLUnitConverter::convertEnum( sStringBuffer
, eType
, aXML_ConnectionKind_EnumMap
);
2640 aStr
= sStringBuffer
.makeStringAndClear();
2641 mrExport
.AddAttribute(XML_NAMESPACE_DRAW
, XML_TYPE
, aStr
);
2645 sal_Int32 nDelta1
= 0, nDelta2
= 0, nDelta3
= 0;
2647 aAny
= xProps
->getPropertyValue(u
"EdgeLine1Delta"_ustr
);
2649 aAny
= xProps
->getPropertyValue(u
"EdgeLine2Delta"_ustr
);
2651 aAny
= xProps
->getPropertyValue(u
"EdgeLine3Delta"_ustr
);
2654 if( nDelta1
!= 0 || nDelta2
!= 0 || nDelta3
!= 0 )
2656 mrExport
.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer
,
2658 if( nDelta2
!= 0 || nDelta3
!= 0 )
2660 sStringBuffer
.append( ' ' );
2661 mrExport
.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer
,
2665 sStringBuffer
.append( ' ' );
2666 mrExport
.GetMM100UnitConverter().convertMeasureToXML(
2667 sStringBuffer
, nDelta3
);
2671 aStr
= sStringBuffer
.makeStringAndClear();
2672 mrExport
.AddAttribute(XML_NAMESPACE_DRAW
, XML_LINE_SKEW
, aStr
);
2675 // export start and end point
2676 awt::Point
aStart(0,0);
2677 awt::Point
aEnd(1,1);
2679 /* Get <StartPositionInHoriL2R> and
2680 <EndPositionInHoriL2R>, if they exist and if the document is exported
2681 into the OpenOffice.org file format.
2682 These properties only exist at service css::text::Shape - the
2683 Writer UNO service for shapes.
2684 This code is needed, because the positioning attributes in the
2685 OpenOffice.org file format are given in horizontal left-to-right layout
2686 regardless the layout direction the shape is in. In the OASIS Open Office
2687 file format the positioning attributes are correctly given in the layout
2688 direction the shape is in. Thus, this code provides the conversion from
2689 the OASIS Open Office file format to the OpenOffice.org file format. (#i36248#)
2691 if ( !( GetExport().getExportFlags() & SvXMLExportFlags::OASIS
) &&
2692 xProps
->getPropertySetInfo()->hasPropertyByName(u
"StartPositionInHoriL2R"_ustr
) &&
2693 xProps
->getPropertySetInfo()->hasPropertyByName(u
"EndPositionInHoriL2R"_ustr
) )
2695 xProps
->getPropertyValue(u
"StartPositionInHoriL2R"_ustr
) >>= aStart
;
2696 xProps
->getPropertyValue(u
"EndPositionInHoriL2R"_ustr
) >>= aEnd
;
2700 xProps
->getPropertyValue(u
"StartPosition"_ustr
) >>= aStart
;
2701 xProps
->getPropertyValue(u
"EndPosition"_ustr
) >>= aEnd
;
2706 aStart
.X
-= pRefPoint
->X
;
2707 aStart
.Y
-= pRefPoint
->Y
;
2708 aEnd
.X
-= pRefPoint
->X
;
2709 aEnd
.Y
-= pRefPoint
->Y
;
2712 if( nFeatures
& XMLShapeExportFlags::X
)
2715 mrExport
.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer
,
2717 aStr
= sStringBuffer
.makeStringAndClear();
2718 mrExport
.AddAttribute(XML_NAMESPACE_SVG
, XML_X1
, aStr
);
2725 if( nFeatures
& XMLShapeExportFlags::Y
)
2728 mrExport
.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer
,
2730 aStr
= sStringBuffer
.makeStringAndClear();
2731 mrExport
.AddAttribute(XML_NAMESPACE_SVG
, XML_Y1
, aStr
);
2739 mrExport
.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer
, aEnd
.X
);
2740 aStr
= sStringBuffer
.makeStringAndClear();
2741 mrExport
.AddAttribute(XML_NAMESPACE_SVG
, XML_X2
, aStr
);
2744 mrExport
.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer
, aEnd
.Y
);
2745 aStr
= sStringBuffer
.makeStringAndClear();
2746 mrExport
.AddAttribute(XML_NAMESPACE_SVG
, XML_Y2
, aStr
);
2749 uno::Reference
< uno::XInterface
> xRefS
;
2750 uno::Reference
< uno::XInterface
> xRefE
;
2752 // export start connection
2753 xProps
->getPropertyValue(u
"StartShape"_ustr
) >>= xRefS
;
2756 const OUString
& rShapeId
= mrExport
.getInterfaceToIdentifierMapper().getIdentifier( xRefS
);
2757 mrExport
.AddAttribute(XML_NAMESPACE_DRAW
, XML_START_SHAPE
, rShapeId
);
2759 aAny
= xProps
->getPropertyValue(u
"StartGluePointIndex"_ustr
);
2760 sal_Int32 nGluePointId
= 0;
2761 if( aAny
>>= nGluePointId
)
2763 if( nGluePointId
!= -1 )
2765 mrExport
.AddAttribute(XML_NAMESPACE_DRAW
, XML_START_GLUE_POINT
, OUString::number( nGluePointId
));
2770 // export end connection
2771 xProps
->getPropertyValue(u
"EndShape"_ustr
) >>= xRefE
;
2774 const OUString
& rShapeId
= mrExport
.getInterfaceToIdentifierMapper().getIdentifier( xRefE
);
2775 mrExport
.AddAttribute(XML_NAMESPACE_DRAW
, XML_END_SHAPE
, rShapeId
);
2777 aAny
= xProps
->getPropertyValue(u
"EndGluePointIndex"_ustr
);
2778 sal_Int32 nGluePointId
= 0;
2779 if( aAny
>>= nGluePointId
)
2781 if( nGluePointId
!= -1 )
2783 mrExport
.AddAttribute(XML_NAMESPACE_DRAW
, XML_END_GLUE_POINT
, OUString::number( nGluePointId
));
2788 // get PolygonBezier
2789 aAny
= xProps
->getPropertyValue(u
"PolyPolygonBezier"_ustr
);
2790 auto pSourcePolyPolygon
= o3tl::tryAccess
<drawing::PolyPolygonBezierCoords
>(aAny
);
2791 if(pSourcePolyPolygon
&& pSourcePolyPolygon
->Coordinates
.getLength())
2793 const basegfx::B2DPolyPolygon
aPolyPolygon(
2794 basegfx::utils::UnoPolyPolygonBezierCoordsToB2DPolyPolygon(
2795 *pSourcePolyPolygon
));
2796 const OUString
aPolygonString(
2797 basegfx::utils::exportToSvgD(
2799 true, // bUseRelativeCoordinates
2800 false, // bDetectQuadraticBeziers: not used in old, but maybe activated now
2801 true)); // bHandleRelativeNextPointCompatible
2803 // write point array
2804 mrExport
.AddAttribute(XML_NAMESPACE_SVG
, XML_D
, aPolygonString
);
2808 ::basegfx::B2DHomMatrix aMatrix
;
2809 ImpExportNewTrans_GetB2DHomMatrix(aMatrix
, xProps
);
2811 // decompose and correct about pRefPoint
2812 ::basegfx::B2DTuple aTRScale
;
2813 double fTRShear(0.0);
2814 double fTRRotate(0.0);
2815 ::basegfx::B2DTuple aTRTranslate
;
2816 ImpExportNewTrans_DecomposeAndRefPoint(aMatrix
, aTRScale
, fTRShear
,
2817 fTRRotate
, aTRTranslate
, pRefPoint
);
2819 // fdo#49678: create and export ViewBox
2820 awt::Size
aSize(basegfx::fround
<tools::Long
>(aTRScale
.getX()),
2821 basegfx::fround
<tools::Long
>(aTRScale
.getY()));
2822 SdXMLImExViewBox
aViewBox(0, 0, aSize
.Width
, aSize
.Height
);
2823 mrExport
.AddAttribute(XML_NAMESPACE_SVG
, XML_VIEWBOX
, aViewBox
.GetExportString());
2825 // write connector shape. Add Export later.
2826 bool bCreateNewline( (nFeatures
& XMLShapeExportFlags::NO_WS
) == XMLShapeExportFlags::NONE
); // #86116#/#92210#
2827 SvXMLElementExport
aOBJ(mrExport
, XML_NAMESPACE_DRAW
, XML_CONNECTOR
, bCreateNewline
, true);
2829 ImpExportDescription( xShape
); // #i68101#
2830 ImpExportEvents( xShape
);
2831 ImpExportGluePoints( xShape
);
2832 ImpExportText( xShape
);
2835 void XMLShapeExport::ImpExportMeasureShape(
2836 const uno::Reference
< drawing::XShape
>& xShape
,
2837 XMLShapeExportFlags nFeatures
/* = SEF_DEFAULT */, awt::Point
const * pRefPoint
/* = NULL */)
2839 uno::Reference
< beans::XPropertySet
> xProps( xShape
, uno::UNO_QUERY
);
2842 OUStringBuffer sStringBuffer
;
2844 // export start and end point
2845 awt::Point
aStart(0,0);
2846 awt::Point
aEnd(1,1);
2848 /* Get <StartPositionInHoriL2R> and
2849 <EndPositionInHoriL2R>, if they exist and if the document is exported
2850 into the OpenOffice.org file format.
2851 These properties only exist at service css::text::Shape - the
2852 Writer UNO service for shapes.
2853 This code is needed, because the positioning attributes in the
2854 OpenOffice.org file format are given in horizontal left-to-right layout
2855 regardless the layout direction the shape is in. In the OASIS Open Office
2856 file format the positioning attributes are correctly given in the layout
2857 direction the shape is in. Thus, this code provides the conversion from
2858 the OASIS Open Office file format to the OpenOffice.org file format. (#i36248#)
2860 if ( !( GetExport().getExportFlags() & SvXMLExportFlags::OASIS
) &&
2861 xProps
->getPropertySetInfo()->hasPropertyByName(u
"StartPositionInHoriL2R"_ustr
) &&
2862 xProps
->getPropertySetInfo()->hasPropertyByName(u
"EndPositionInHoriL2R"_ustr
) )
2864 xProps
->getPropertyValue(u
"StartPositionInHoriL2R"_ustr
) >>= aStart
;
2865 xProps
->getPropertyValue(u
"EndPositionInHoriL2R"_ustr
) >>= aEnd
;
2869 xProps
->getPropertyValue(u
"StartPosition"_ustr
) >>= aStart
;
2870 xProps
->getPropertyValue(u
"EndPosition"_ustr
) >>= aEnd
;
2875 aStart
.X
-= pRefPoint
->X
;
2876 aStart
.Y
-= pRefPoint
->Y
;
2877 aEnd
.X
-= pRefPoint
->X
;
2878 aEnd
.Y
-= pRefPoint
->Y
;
2881 if( nFeatures
& XMLShapeExportFlags::X
)
2884 mrExport
.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer
,
2886 aStr
= sStringBuffer
.makeStringAndClear();
2887 mrExport
.AddAttribute(XML_NAMESPACE_SVG
, XML_X1
, aStr
);
2894 if( nFeatures
& XMLShapeExportFlags::Y
)
2897 mrExport
.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer
,
2899 aStr
= sStringBuffer
.makeStringAndClear();
2900 mrExport
.AddAttribute(XML_NAMESPACE_SVG
, XML_Y1
, aStr
);
2908 mrExport
.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer
, aEnd
.X
);
2909 aStr
= sStringBuffer
.makeStringAndClear();
2910 mrExport
.AddAttribute(XML_NAMESPACE_SVG
, XML_X2
, aStr
);
2913 mrExport
.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer
, aEnd
.Y
);
2914 aStr
= sStringBuffer
.makeStringAndClear();
2915 mrExport
.AddAttribute(XML_NAMESPACE_SVG
, XML_Y2
, aStr
);
2917 // write measure shape
2918 bool bCreateNewline( (nFeatures
& XMLShapeExportFlags::NO_WS
) == XMLShapeExportFlags::NONE
); // #86116#/#92210#
2919 SvXMLElementExport
aOBJ(mrExport
, XML_NAMESPACE_DRAW
, XML_MEASURE
, bCreateNewline
, true);
2921 ImpExportDescription( xShape
); // #i68101#
2922 ImpExportEvents( xShape
);
2923 ImpExportGluePoints( xShape
);
2925 uno::Reference
< text::XText
> xText( xShape
, uno::UNO_QUERY
);
2927 mrExport
.GetTextParagraphExport()->exportText( xText
);
2930 void XMLShapeExport::ImpExportOLE2Shape(
2931 const uno::Reference
< drawing::XShape
>& xShape
,
2932 XmlShapeType eShapeType
, XMLShapeExportFlags nFeatures
/* = SEF_DEFAULT */, awt::Point
* pRefPoint
/* = NULL */,
2933 comphelper::AttributeList
* pAttrList
/* = NULL */ )
2935 uno::Reference
< beans::XPropertySet
> xPropSet(xShape
, uno::UNO_QUERY
);
2936 uno::Reference
< container::XNamed
> xNamed(xShape
, uno::UNO_QUERY
);
2938 SAL_WARN_IF( !xPropSet
.is() || !xNamed
.is(), "xmloff", "ole shape is not implementing needed interfaces");
2939 if(!(xPropSet
.is() && xNamed
.is()))
2943 ImpExportNewTrans(xPropSet
, nFeatures
, pRefPoint
);
2945 bool bIsEmptyPresObj
= false;
2947 // presentation settings
2948 if(eShapeType
== XmlShapeType::PresOLE2Shape
)
2949 bIsEmptyPresObj
= ImpExportPresentationAttributes( xPropSet
, GetXMLToken(XML_OBJECT
) );
2950 else if(eShapeType
== XmlShapeType::PresChartShape
)
2951 bIsEmptyPresObj
= ImpExportPresentationAttributes( xPropSet
, GetXMLToken(XML_CHART
) );
2952 else if(eShapeType
== XmlShapeType::PresSheetShape
)
2953 bIsEmptyPresObj
= ImpExportPresentationAttributes( xPropSet
, GetXMLToken(XML_TABLE
) );
2955 bool bCreateNewline( (nFeatures
& XMLShapeExportFlags::NO_WS
) == XMLShapeExportFlags::NONE
); // #86116#/#92210#
2956 bool bExportEmbedded(mrExport
.getExportFlags() & SvXMLExportFlags::EMBEDDED
);
2957 OUString sPersistName
;
2958 SvXMLElementExport
aElement( mrExport
, XML_NAMESPACE_DRAW
,
2959 XML_FRAME
, bCreateNewline
, true );
2961 if (!bIsEmptyPresObj
)
2965 mrExport
.AddAttributeList(pAttrList
);
2970 bool bInternal
= false;
2971 xPropSet
->getPropertyValue(u
"IsInternal"_ustr
) >>= bInternal
;
2977 // OOo internal links have no storage persistence, URL is stored in the XML file
2978 // the result LinkURL is empty in case the object is not a link
2979 xPropSet
->getPropertyValue(u
"LinkURL"_ustr
) >>= sURL
;
2982 xPropSet
->getPropertyValue(u
"PersistName"_ustr
) >>= sPersistName
;
2983 if ( sURL
.isEmpty() )
2985 if( !sPersistName
.isEmpty() )
2987 sURL
= "vnd.sun.star.EmbeddedObject:" + sPersistName
;
2992 xPropSet
->getPropertyValue(u
"CLSID"_ustr
) >>= sClassId
;
2994 if( !sClassId
.isEmpty() )
2995 mrExport
.AddAttribute(XML_NAMESPACE_DRAW
, XML_CLASS_ID
, sClassId
);
2997 if(!bExportEmbedded
)
3000 if( !sURL
.isEmpty() )
3002 // #96717# in theorie, if we don't have a URL we shouldn't even
3003 // export this OLE shape. But practically it's too risky right now
3004 // to change this so we better dispose this on load
3005 sURL
= mrExport
.AddEmbeddedObject( sURL
);
3007 mrExport
.AddAttribute(XML_NAMESPACE_XLINK
, XML_HREF
, sURL
);
3008 mrExport
.AddAttribute( XML_NAMESPACE_XLINK
, XML_TYPE
, XML_SIMPLE
);
3009 mrExport
.AddAttribute( XML_NAMESPACE_XLINK
, XML_SHOW
, XML_EMBED
);
3010 mrExport
.AddAttribute( XML_NAMESPACE_XLINK
, XML_ACTUATE
, XML_ONLOAD
);
3014 // tdf#153179 Export the preview graphic of the object if the object is missing.
3015 uno::Reference
<graphic::XGraphic
> xGraphic
;
3016 xPropSet
->getPropertyValue(u
"Graphic"_ustr
) >>= xGraphic
;
3021 const OUString aHref
= mrExport
.AddEmbeddedXGraphic(xGraphic
, aMimeType
);
3023 if (aMimeType
.isEmpty())
3024 mrExport
.GetGraphicMimeTypeFromStream(xGraphic
, aMimeType
);
3026 if (!aHref
.isEmpty())
3028 mrExport
.AddAttribute(XML_NAMESPACE_XLINK
, XML_HREF
, aHref
);
3029 mrExport
.AddAttribute(XML_NAMESPACE_XLINK
, XML_TYPE
, XML_SIMPLE
);
3030 mrExport
.AddAttribute(XML_NAMESPACE_XLINK
, XML_SHOW
, XML_EMBED
);
3031 mrExport
.AddAttribute(XML_NAMESPACE_XLINK
, XML_ACTUATE
, XML_ONLOAD
);
3034 if (!aMimeType
.isEmpty()
3035 && GetExport().getSaneDefaultVersion() > SvtSaveOptions::ODFSVER_012
)
3036 { // ODF 1.3 OFFICE-3943
3037 mrExport
.AddAttribute(SvtSaveOptions::ODFSVER_013
3038 <= GetExport().getSaneDefaultVersion()
3039 ? XML_NAMESPACE_DRAW
3040 : XML_NAMESPACE_LO_EXT
,
3041 u
"mime-type"_ustr
, aMimeType
);
3044 SvXMLElementExport
aImageElem(mrExport
, XML_NAMESPACE_DRAW
, XML_IMAGE
, true,
3047 // optional office:binary-data
3048 mrExport
.AddEmbeddedXGraphicAsBase64(xGraphic
);
3050 ImpExportEvents(xShape
);
3051 ImpExportGluePoints(xShape
);
3052 ImpExportDescription(xShape
);
3060 enum XMLTokenEnum eElem
= sClassId
.isEmpty() ? XML_OBJECT
: XML_OBJECT_OLE
;
3061 SvXMLElementExport
aElem( mrExport
, XML_NAMESPACE_DRAW
, eElem
, true, true );
3063 // tdf#112547 export text as child of draw:object, where import expects it
3064 if (!bIsEmptyPresObj
&& supportsText(eShapeType
))
3066 // #i118485# Add text export, the draw OLE shape allows text now
3067 ImpExportText( xShape
, TextPNS::EXTENSION
);
3070 if(bExportEmbedded
&& !bIsEmptyPresObj
)
3075 uno::Reference
< lang::XComponent
> xComp
;
3076 xPropSet
->getPropertyValue(u
"Model"_ustr
) >>= xComp
;
3077 SAL_WARN_IF( !xComp
.is(), "xmloff", "no xModel for own OLE format" );
3078 mrExport
.ExportEmbeddedOwnObject( xComp
);
3083 // this is an alien object ( currently MSOLE is the only supported type of such objects )
3084 // in case it is not an OASIS format the object should be asked to store replacement image if possible
3086 OUString
sURLRequest( sURL
);
3087 if ( !( mrExport
.getExportFlags() & SvXMLExportFlags::OASIS
) )
3088 sURLRequest
+= "?oasis=false";
3089 mrExport
.AddEmbeddedObjectAsBase64( sURLRequest
);
3093 if( !bIsEmptyPresObj
)
3095 OUString sURL
= XML_EMBEDDEDOBJECTGRAPHIC_URL_BASE
+ sPersistName
;
3096 if( !bExportEmbedded
)
3098 sURL
= GetExport().AddEmbeddedObject( sURL
);
3099 mrExport
.AddAttribute(XML_NAMESPACE_XLINK
, XML_HREF
, sURL
);
3100 mrExport
.AddAttribute( XML_NAMESPACE_XLINK
, XML_TYPE
, XML_SIMPLE
);
3101 mrExport
.AddAttribute( XML_NAMESPACE_XLINK
, XML_SHOW
, XML_EMBED
);
3102 mrExport
.AddAttribute( XML_NAMESPACE_XLINK
, XML_ACTUATE
, XML_ONLOAD
);
3105 SvXMLElementExport
aElem( GetExport(), XML_NAMESPACE_DRAW
,
3106 XML_IMAGE
, false, true );
3108 if( bExportEmbedded
)
3109 GetExport().AddEmbeddedObjectAsBase64( sURL
);
3112 ImpExportEvents( xShape
);
3113 ImpExportGluePoints( xShape
);
3114 ImpExportDescription( xShape
); // #i68101#
3118 void XMLShapeExport::ImpExportPageShape(
3119 const uno::Reference
< drawing::XShape
>& xShape
,
3120 XmlShapeType eShapeType
, XMLShapeExportFlags nFeatures
/* = SEF_DEFAULT */, awt::Point
* pRefPoint
/* = NULL */)
3122 const uno::Reference
< beans::XPropertySet
> xPropSet(xShape
, uno::UNO_QUERY
);
3126 // #86163# Transformation
3127 ImpExportNewTrans(xPropSet
, nFeatures
, pRefPoint
);
3129 // export page number used for this page
3130 uno::Reference
< beans::XPropertySetInfo
> xPropSetInfo( xPropSet
->getPropertySetInfo() );
3131 static constexpr OUString
aPageNumberStr(u
"PageNumber"_ustr
);
3132 if( xPropSetInfo
.is() && xPropSetInfo
->hasPropertyByName(aPageNumberStr
))
3134 sal_Int32 nPageNumber
= 0;
3135 xPropSet
->getPropertyValue(aPageNumberStr
) >>= nPageNumber
;
3137 mrExport
.AddAttribute(XML_NAMESPACE_DRAW
, XML_PAGE_NUMBER
, OUString::number(nPageNumber
));
3140 // a presentation page shape, normally used on notes pages only. If
3141 // it is used not as presentation shape, it may have been created with
3142 // copy-paste exchange between draw and impress (this IS possible...)
3143 if(eShapeType
== XmlShapeType::PresPageShape
)
3145 mrExport
.AddAttribute(XML_NAMESPACE_PRESENTATION
, XML_CLASS
,
3150 bool bCreateNewline( (nFeatures
& XMLShapeExportFlags::NO_WS
) == XMLShapeExportFlags::NONE
); // #86116#/#92210#
3151 SvXMLElementExport
aOBJ(mrExport
, XML_NAMESPACE_DRAW
, XML_PAGE_THUMBNAIL
, bCreateNewline
, true);
3154 void XMLShapeExport::ImpExportCaptionShape(
3155 const uno::Reference
< drawing::XShape
>& xShape
,
3156 XMLShapeExportFlags nFeatures
/* = SEF_DEFAULT */, awt::Point
* pRefPoint
/* = NULL */)
3158 const uno::Reference
< beans::XPropertySet
> xPropSet(xShape
, uno::UNO_QUERY
);
3163 ImpExportNewTrans(xPropSet
, nFeatures
, pRefPoint
);
3165 // evtl. corner radius?
3166 sal_Int32
nCornerRadius(0);
3167 xPropSet
->getPropertyValue(u
"CornerRadius"_ustr
) >>= nCornerRadius
;
3170 OUStringBuffer sStringBuffer
;
3171 mrExport
.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer
,
3173 mrExport
.AddAttribute(XML_NAMESPACE_DRAW
, XML_CORNER_RADIUS
, sStringBuffer
.makeStringAndClear());
3176 awt::Point aCaptionPoint
;
3177 xPropSet
->getPropertyValue(u
"CaptionPoint"_ustr
) >>= aCaptionPoint
;
3179 mrExport
.GetMM100UnitConverter().convertMeasureToXML(msBuffer
,
3181 mrExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_CAPTION_POINT_X
, msBuffer
.makeStringAndClear() );
3182 mrExport
.GetMM100UnitConverter().convertMeasureToXML(msBuffer
,
3184 mrExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_CAPTION_POINT_Y
, msBuffer
.makeStringAndClear() );
3186 // write Caption shape. Add export later.
3187 bool bCreateNewline( (nFeatures
& XMLShapeExportFlags::NO_WS
) == XMLShapeExportFlags::NONE
); // #86116#/#92210#
3188 bool bAnnotation( (nFeatures
& XMLShapeExportFlags::ANNOTATION
) == XMLShapeExportFlags::ANNOTATION
);
3190 SvXMLElementExport
aObj( mrExport
,
3191 (bAnnotation
? XML_NAMESPACE_OFFICE
3192 : XML_NAMESPACE_DRAW
),
3193 (bAnnotation
? XML_ANNOTATION
: XML_CAPTION
),
3194 bCreateNewline
, true );
3196 ImpExportDescription( xShape
); // #i68101#
3197 ImpExportEvents( xShape
);
3198 ImpExportGluePoints( xShape
);
3200 mrExport
.exportAnnotationMeta( xShape
);
3201 ImpExportText( xShape
);
3205 void XMLShapeExport::ImpExportFrameShape(
3206 const uno::Reference
< drawing::XShape
>& xShape
,
3207 XMLShapeExportFlags nFeatures
, css::awt::Point
* pRefPoint
)
3209 const uno::Reference
< beans::XPropertySet
> xPropSet(xShape
, uno::UNO_QUERY
);
3214 ImpExportNewTrans(xPropSet
, nFeatures
, pRefPoint
);
3216 bool bCreateNewline( (nFeatures
& XMLShapeExportFlags::NO_WS
) == XMLShapeExportFlags::NONE
); // #86116#/#92210#
3217 SvXMLElementExport
aElem( mrExport
, XML_NAMESPACE_DRAW
,
3218 XML_FRAME
, bCreateNewline
, true );
3222 xPropSet
->getPropertyValue(u
"FrameURL"_ustr
) >>= aStr
;
3223 mrExport
.AddAttribute ( XML_NAMESPACE_XLINK
, XML_HREF
, GetExport().GetRelativeReference(aStr
) );
3224 mrExport
.AddAttribute ( XML_NAMESPACE_XLINK
, XML_TYPE
, XML_SIMPLE
);
3225 mrExport
.AddAttribute ( XML_NAMESPACE_XLINK
, XML_SHOW
, XML_EMBED
);
3226 mrExport
.AddAttribute ( XML_NAMESPACE_XLINK
, XML_ACTUATE
, XML_ONLOAD
);
3229 xPropSet
->getPropertyValue(u
"FrameName"_ustr
) >>= aStr
;
3230 if( !aStr
.isEmpty() )
3231 mrExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_FRAME_NAME
, aStr
);
3233 // write floating frame
3235 SvXMLElementExport
aOBJ(mrExport
, XML_NAMESPACE_DRAW
, XML_FLOATING_FRAME
, true, true);
3238 ImpExportDescription(xShape
);
3241 void XMLShapeExport::ImpExportAppletShape(
3242 const uno::Reference
< drawing::XShape
>& xShape
,
3243 XMLShapeExportFlags nFeatures
, css::awt::Point
* pRefPoint
)
3245 const uno::Reference
< beans::XPropertySet
> xPropSet(xShape
, uno::UNO_QUERY
);
3250 ImpExportNewTrans(xPropSet
, nFeatures
, pRefPoint
);
3252 bool bCreateNewline( (nFeatures
& XMLShapeExportFlags::NO_WS
) == XMLShapeExportFlags::NONE
); // #86116#/#92210#
3253 SvXMLElementExport
aElement( mrExport
, XML_NAMESPACE_DRAW
,
3254 XML_FRAME
, bCreateNewline
, true );
3258 xPropSet
->getPropertyValue(u
"AppletCodeBase"_ustr
) >>= aStr
;
3259 mrExport
.AddAttribute ( XML_NAMESPACE_XLINK
, XML_HREF
, GetExport().GetRelativeReference(aStr
) );
3260 mrExport
.AddAttribute ( XML_NAMESPACE_XLINK
, XML_TYPE
, XML_SIMPLE
);
3261 mrExport
.AddAttribute ( XML_NAMESPACE_XLINK
, XML_SHOW
, XML_EMBED
);
3262 mrExport
.AddAttribute ( XML_NAMESPACE_XLINK
, XML_ACTUATE
, XML_ONLOAD
);
3264 // export draw:applet-name
3265 xPropSet
->getPropertyValue(u
"AppletName"_ustr
) >>= aStr
;
3266 if( !aStr
.isEmpty() )
3267 mrExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_APPLET_NAME
, aStr
);
3270 xPropSet
->getPropertyValue(u
"AppletCode"_ustr
) >>= aStr
;
3271 mrExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_CODE
, aStr
);
3273 // export draw:may-script
3274 bool bIsScript
= false;
3275 xPropSet
->getPropertyValue(u
"AppletIsScript"_ustr
) >>= bIsScript
;
3276 mrExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_MAY_SCRIPT
, bIsScript
? XML_TRUE
: XML_FALSE
);
3280 SvXMLElementExport
aOBJ(mrExport
, XML_NAMESPACE_DRAW
, XML_APPLET
, true, true);
3282 // export parameters
3283 uno::Sequence
< beans::PropertyValue
> aCommands
;
3284 xPropSet
->getPropertyValue(u
"AppletCommands"_ustr
) >>= aCommands
;
3285 for (const auto& rCommand
: aCommands
)
3287 rCommand
.Value
>>= aStr
;
3288 mrExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_NAME
, rCommand
.Name
);
3289 mrExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_VALUE
, aStr
);
3290 SvXMLElementExport
aElem( mrExport
, XML_NAMESPACE_DRAW
, XML_PARAM
, false, true );
3294 ImpExportDescription(xShape
);
3297 void XMLShapeExport::ImpExportPluginShape(
3298 const uno::Reference
< drawing::XShape
>& xShape
,
3299 XMLShapeExportFlags nFeatures
, css::awt::Point
* pRefPoint
)
3301 const uno::Reference
< beans::XPropertySet
> xPropSet(xShape
, uno::UNO_QUERY
);
3306 ImpExportNewTrans(xPropSet
, nFeatures
, pRefPoint
);
3308 bool bCreateNewline( (nFeatures
& XMLShapeExportFlags::NO_WS
) == XMLShapeExportFlags::NONE
); // #86116#/#92210#
3309 SvXMLElementExport
aElement( mrExport
, XML_NAMESPACE_DRAW
,
3310 XML_FRAME
, bCreateNewline
, true );
3312 // export plugin url
3314 xPropSet
->getPropertyValue(u
"PluginURL"_ustr
) >>= aStr
;
3315 mrExport
.AddAttribute ( XML_NAMESPACE_XLINK
, XML_HREF
, GetExport().GetRelativeReference(aStr
) );
3316 mrExport
.AddAttribute ( XML_NAMESPACE_XLINK
, XML_TYPE
, XML_SIMPLE
);
3317 mrExport
.AddAttribute ( XML_NAMESPACE_XLINK
, XML_SHOW
, XML_EMBED
);
3318 mrExport
.AddAttribute ( XML_NAMESPACE_XLINK
, XML_ACTUATE
, XML_ONLOAD
);
3321 xPropSet
->getPropertyValue(u
"PluginMimeType"_ustr
) >>= aStr
;
3323 mrExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_MIME_TYPE
, aStr
);
3327 SvXMLElementExport
aOBJ(mrExport
, XML_NAMESPACE_DRAW
, XML_PLUGIN
, true, true);
3329 // export parameters
3330 uno::Sequence
< beans::PropertyValue
> aCommands
;
3331 xPropSet
->getPropertyValue(u
"PluginCommands"_ustr
) >>= aCommands
;
3332 for (const auto& rCommand
: aCommands
)
3334 rCommand
.Value
>>= aStr
;
3335 mrExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_NAME
, rCommand
.Name
);
3336 mrExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_VALUE
, aStr
);
3337 SvXMLElementExport
aElem( mrExport
, XML_NAMESPACE_DRAW
, XML_PARAM
, false, true );
3341 ImpExportDescription(xShape
);
3344 static void lcl_CopyStream(
3345 uno::Reference
<io::XInputStream
> const& xInStream
,
3346 uno::Reference
<embed::XStorage
> const& xTarget
,
3347 OUString
const& rPath
, const OUString
& rMimeType
)
3349 ::comphelper::LifecycleProxy proxy
;
3350 uno::Reference
<io::XStream
> const xStream(
3351 ::comphelper::OStorageHelper::GetStreamAtPackageURL(xTarget
, rPath
,
3352 embed::ElementModes::WRITE
| embed::ElementModes::TRUNCATE
, proxy
));
3353 uno::Reference
<io::XOutputStream
> const xOutStream(
3354 (xStream
.is()) ? xStream
->getOutputStream() : nullptr);
3355 if (!xOutStream
.is())
3357 SAL_WARN("xmloff", "no output stream");
3358 throw uno::Exception(u
"no output stream"_ustr
,nullptr);
3360 uno::Reference
< beans::XPropertySet
> const xStreamProps(xStream
,
3362 if (xStreamProps
.is()) { // this is NOT supported in FileSystemStorage
3363 xStreamProps
->setPropertyValue(u
"MediaType"_ustr
,
3364 uno::Any(rMimeType
));
3365 xStreamProps
->setPropertyValue( // turn off compression
3369 ::comphelper::OStorageHelper::CopyInputToOutput(xInStream
, xOutStream
);
3370 xOutStream
->closeOutput();
3371 proxy
.commitStorages();
3375 lcl_StoreMediaAndGetURL(SvXMLExport
& rExport
,
3376 uno::Reference
<beans::XPropertySet
> const& xPropSet
,
3377 OUString
const& rURL
, const OUString
& rMimeType
)
3380 if (rURL
.startsWithIgnoreAsciiCase("vnd.sun.star.Package:", &urlPath
))
3382 try // video is embedded
3384 uno::Reference
<embed::XStorage
> const xTarget(
3385 rExport
.GetTargetStorage(), uno::UNO_SET_THROW
);
3386 uno::Reference
<io::XInputStream
> xInStream
;
3387 xPropSet
->getPropertyValue(u
"PrivateStream"_ustr
)
3390 if (!xInStream
.is())
3392 SAL_WARN("xmloff", "no input stream");
3396 lcl_CopyStream(xInStream
, xTarget
, rURL
, rMimeType
);
3400 catch (uno::Exception
const&)
3402 TOOLS_INFO_EXCEPTION("xmloff", "exception while storing embedded media");
3408 return rExport
.GetRelativeReference(rURL
); // linked
3414 void ExportGraphicPreview(const uno::Reference
<graphic::XGraphic
>& xGraphic
, SvXMLExport
& rExport
, std::u16string_view rPrefix
, std::u16string_view rExtension
, const OUString
& rMimeType
)
3416 const bool bExportEmbedded(rExport
.getExportFlags() & SvXMLExportFlags::EMBEDDED
);
3418 if( xGraphic
.is() ) try
3420 uno::Reference
< uno::XComponentContext
> xContext
= rExport
.getComponentContext();
3422 uno::Reference
< embed::XStorage
> xPictureStorage
;
3423 uno::Reference
< embed::XStorage
> xStorage
;
3424 uno::Reference
< io::XStream
> xPictureStream
;
3426 OUString sPictureName
;
3427 if( bExportEmbedded
)
3429 xPictureStream
.set( xContext
->getServiceManager()->createInstanceWithContext( u
"com.sun.star.comp.MemoryStream"_ustr
, xContext
), uno::UNO_QUERY_THROW
);
3433 xStorage
.set( rExport
.GetTargetStorage(), uno::UNO_SET_THROW
);
3435 xPictureStorage
.set( xStorage
->openStorageElement( u
"Pictures"_ustr
, ::embed::ElementModes::READWRITE
), uno::UNO_SET_THROW
);
3437 sal_Int32 nIndex
= 0;
3440 sPictureName
= rPrefix
+ OUString::number( ++nIndex
) + rExtension
;
3442 while( xPictureStorage
->hasByName( sPictureName
) );
3444 xPictureStream
.set( xPictureStorage
->openStreamElement( sPictureName
, ::embed::ElementModes::READWRITE
), uno::UNO_SET_THROW
);
3447 uno::Reference
< graphic::XGraphicProvider
> xProvider( graphic::GraphicProvider::create(xContext
) );
3448 uno::Sequence
< beans::PropertyValue
> aArgs
{
3449 comphelper::makePropertyValue(u
"MimeType"_ustr
, rMimeType
),
3450 comphelper::makePropertyValue(u
"OutputStream"_ustr
, xPictureStream
->getOutputStream())
3452 xProvider
->storeGraphic( xGraphic
, aArgs
);
3454 if( xPictureStorage
.is() )
3456 uno::Reference
< embed::XTransactedObject
> xTrans( xPictureStorage
, uno::UNO_QUERY
);
3461 if( !bExportEmbedded
)
3463 OUString sURL
= "Pictures/" + sPictureName
;
3464 rExport
.AddAttribute( XML_NAMESPACE_XLINK
, XML_HREF
, sURL
);
3465 rExport
.AddAttribute( XML_NAMESPACE_XLINK
, XML_TYPE
, XML_SIMPLE
);
3466 rExport
.AddAttribute( XML_NAMESPACE_XLINK
, XML_SHOW
, XML_EMBED
);
3467 rExport
.AddAttribute( XML_NAMESPACE_XLINK
, XML_ACTUATE
, XML_ONLOAD
);
3470 SvXMLElementExport
aElem( rExport
, XML_NAMESPACE_DRAW
, XML_IMAGE
, false, true );
3472 if( bExportEmbedded
)
3474 uno::Reference
< io::XSeekableInputStream
> xSeekable( xPictureStream
, uno::UNO_QUERY_THROW
);
3477 XMLBase64Export
aBase64Exp( rExport
);
3478 aBase64Exp
.exportOfficeBinaryDataElement( uno::Reference
< io::XInputStream
>( xPictureStream
, uno::UNO_QUERY_THROW
) );
3481 catch( uno::Exception
const & )
3483 DBG_UNHANDLED_EXCEPTION("xmloff.draw");
3488 void XMLShapeExport::ImpExportMediaShape(
3489 const uno::Reference
< drawing::XShape
>& xShape
,
3490 XmlShapeType eShapeType
, XMLShapeExportFlags nFeatures
, css::awt::Point
* pRefPoint
)
3492 const uno::Reference
< beans::XPropertySet
> xPropSet(xShape
, uno::UNO_QUERY
);
3497 ImpExportNewTrans(xPropSet
, nFeatures
, pRefPoint
);
3499 if(eShapeType
== XmlShapeType::PresMediaShape
)
3501 (void)ImpExportPresentationAttributes( xPropSet
, GetXMLToken(XML_OBJECT
) );
3503 bool bCreateNewline( (nFeatures
& XMLShapeExportFlags::NO_WS
) == XMLShapeExportFlags::NONE
); // #86116#/#92210#
3504 SvXMLElementExport
aElem( mrExport
, XML_NAMESPACE_DRAW
,
3505 XML_FRAME
, bCreateNewline
, true );
3509 xPropSet
->getPropertyValue(u
"MediaURL"_ustr
) >>= aMediaURL
;
3511 xPropSet
->getPropertyValue(u
"MediaMimeType"_ustr
) >>= sMimeType
;
3513 OUString
const persistentURL
=
3514 lcl_StoreMediaAndGetURL(GetExport(), xPropSet
, aMediaURL
, sMimeType
);
3516 mrExport
.AddAttribute ( XML_NAMESPACE_XLINK
, XML_HREF
, persistentURL
);
3517 mrExport
.AddAttribute ( XML_NAMESPACE_XLINK
, XML_TYPE
, XML_SIMPLE
);
3518 mrExport
.AddAttribute ( XML_NAMESPACE_XLINK
, XML_SHOW
, XML_EMBED
);
3519 mrExport
.AddAttribute ( XML_NAMESPACE_XLINK
, XML_ACTUATE
, XML_ONLOAD
);
3522 mrExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_MIME_TYPE
, sMimeType
);
3525 auto pPluginOBJ
= std::make_unique
<SvXMLElementExport
>(mrExport
, XML_NAMESPACE_DRAW
, XML_PLUGIN
, !( nFeatures
& XMLShapeExportFlags::NO_WS
), true);
3527 // export parameters
3528 static constexpr OUString
aFalseStr( u
"false"_ustr
);
3529 static constexpr OUString
aTrueStr( u
"true"_ustr
);
3532 static constexpr OUString
aLoopStr( u
"Loop"_ustr
);
3533 xPropSet
->getPropertyValue( aLoopStr
) >>= bLoop
;
3534 mrExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_NAME
, aLoopStr
);
3535 mrExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_VALUE
, bLoop
? aTrueStr
: aFalseStr
);
3536 delete new SvXMLElementExport( mrExport
, XML_NAMESPACE_DRAW
, XML_PARAM
, false, true );
3539 static constexpr OUString
aMuteStr( u
"Mute"_ustr
);
3540 xPropSet
->getPropertyValue( aMuteStr
) >>= bMute
;
3541 mrExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_NAME
, aMuteStr
);
3542 mrExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_VALUE
, bMute
? aTrueStr
: aFalseStr
);
3543 delete new SvXMLElementExport( mrExport
, XML_NAMESPACE_DRAW
, XML_PARAM
, false, true );
3545 sal_Int16 nVolumeDB
= 0;
3546 xPropSet
->getPropertyValue(u
"VolumeDB"_ustr
) >>= nVolumeDB
;
3547 mrExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_NAME
, u
"VolumeDB"_ustr
);
3548 mrExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_VALUE
, OUString::number( nVolumeDB
) );
3549 delete new SvXMLElementExport( mrExport
, XML_NAMESPACE_DRAW
, XML_PARAM
, false, true );
3551 media::ZoomLevel eZoom
;
3552 OUString aZoomValue
;
3553 xPropSet
->getPropertyValue(u
"Zoom"_ustr
) >>= eZoom
;
3556 case media::ZoomLevel_ZOOM_1_TO_4
: aZoomValue
= "25%"; break;
3557 case media::ZoomLevel_ZOOM_1_TO_2
: aZoomValue
= "50%"; break;
3558 case media::ZoomLevel_ORIGINAL
: aZoomValue
= "100%"; break;
3559 case media::ZoomLevel_ZOOM_2_TO_1
: aZoomValue
= "200%"; break;
3560 case media::ZoomLevel_ZOOM_4_TO_1
: aZoomValue
= "400%"; break;
3561 case media::ZoomLevel_FIT_TO_WINDOW
: aZoomValue
= "fit"; break;
3562 case media::ZoomLevel_FIT_TO_WINDOW_FIXED_ASPECT
: aZoomValue
= "fixedfit"; break;
3563 case media::ZoomLevel_FULLSCREEN
: aZoomValue
= "fullscreen"; break;
3569 if( !aZoomValue
.isEmpty() )
3571 mrExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_NAME
, u
"Zoom"_ustr
);
3572 mrExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_VALUE
, aZoomValue
);
3573 delete new SvXMLElementExport( mrExport
, XML_NAMESPACE_DRAW
, XML_PARAM
, false, true );
3578 if (officecfg::Office::Common::Save::Graphic::AddReplacementImages::get())
3580 uno::Reference
<graphic::XGraphic
> xGraphic
;
3581 xPropSet
->getPropertyValue(u
"Graphic"_ustr
) >>= xGraphic
;
3582 Graphic
aGraphic(xGraphic
);
3583 if (!aGraphic
.IsNone())
3585 // The media has a preview, export it.
3586 ExportGraphicPreview(xGraphic
, mrExport
, u
"MediaPreview", u
".png", u
"image/png"_ustr
);
3590 ImpExportDescription(xShape
);
3593 void XMLShapeExport::ImpExport3DSceneShape( const uno::Reference
< drawing::XShape
>& xShape
, XMLShapeExportFlags nFeatures
, awt::Point
* pRefPoint
)
3595 uno::Reference
< drawing::XShapes
> xShapes(xShape
, uno::UNO_QUERY
);
3596 if(!(xShapes
.is() && xShapes
->getCount()))
3599 uno::Reference
< beans::XPropertySet
> xPropSet( xShape
, uno::UNO_QUERY
);
3600 SAL_WARN_IF( !xPropSet
.is(), "xmloff", "XMLShapeExport::ImpExport3DSceneShape can't export a scene without a propertyset" );
3601 if( !xPropSet
.is() )
3605 ImpExportNewTrans(xPropSet
, nFeatures
, pRefPoint
);
3608 export3DSceneAttributes( xPropSet
);
3610 // write 3DScene shape
3611 bool bCreateNewline( (nFeatures
& XMLShapeExportFlags::NO_WS
) == XMLShapeExportFlags::NONE
); // #86116#/#92210#
3612 SvXMLElementExport
aOBJ( mrExport
, XML_NAMESPACE_DR3D
, XML_SCENE
, bCreateNewline
, true);
3614 ImpExportDescription( xShape
); // #i68101#
3615 ImpExportEvents( xShape
);
3617 // write 3DSceneLights
3618 export3DLamps( xPropSet
);
3620 // #89764# if export of position is suppressed for group shape,
3621 // positions of contained objects should be written relative to
3622 // the upper left edge of the group.
3623 awt::Point aUpperLeft
;
3625 if(!(nFeatures
& XMLShapeExportFlags::POSITION
))
3627 nFeatures
|= XMLShapeExportFlags::POSITION
;
3628 aUpperLeft
= xShape
->getPosition();
3629 pRefPoint
= &aUpperLeft
;
3633 exportShapes( xShapes
, nFeatures
, pRefPoint
);
3636 void XMLShapeExport::ImpExport3DShape(
3637 const uno::Reference
< drawing::XShape
>& xShape
,
3638 XmlShapeType eShapeType
)
3640 const uno::Reference
< beans::XPropertySet
> xPropSet(xShape
, uno::UNO_QUERY
);
3645 OUStringBuffer sStringBuffer
;
3647 // transformation (UNO_NAME_3D_TRANSFORM_MATRIX == "D3DTransformMatrix")
3648 uno::Any aAny
= xPropSet
->getPropertyValue(u
"D3DTransformMatrix"_ustr
);
3649 drawing::HomogenMatrix aHomMat
;
3651 SdXMLImExTransform3D aTransform
;
3652 aTransform
.AddHomogenMatrix(aHomMat
);
3653 if(aTransform
.NeedsAction())
3654 mrExport
.AddAttribute(XML_NAMESPACE_DR3D
, XML_TRANSFORM
, aTransform
.GetExportString(mrExport
.GetMM100UnitConverter()));
3658 case XmlShapeType::Draw3DCubeObject
:
3661 aAny
= xPropSet
->getPropertyValue(u
"D3DPosition"_ustr
);
3662 drawing::Position3D aPosition3D
;
3663 aAny
>>= aPosition3D
;
3664 ::basegfx::B3DVector
aPos3D(aPosition3D
.PositionX
, aPosition3D
.PositionY
, aPosition3D
.PositionZ
);
3667 aAny
= xPropSet
->getPropertyValue(u
"D3DSize"_ustr
);
3668 drawing::Direction3D aDirection3D
;
3669 aAny
>>= aDirection3D
;
3670 ::basegfx::B3DVector
aDir3D(aDirection3D
.DirectionX
, aDirection3D
.DirectionY
, aDirection3D
.DirectionZ
);
3672 // transform maxEdge from distance to pos
3673 aDir3D
= aPos3D
+ aDir3D
;
3676 if(aPos3D
!= ::basegfx::B3DVector(-2500.0, -2500.0, -2500.0)) // write only when not default
3678 SvXMLUnitConverter::convertB3DVector(sStringBuffer
, aPos3D
);
3679 aStr
= sStringBuffer
.makeStringAndClear();
3680 mrExport
.AddAttribute(XML_NAMESPACE_DR3D
, XML_MIN_EDGE
, aStr
);
3684 if(aDir3D
!= ::basegfx::B3DVector(2500.0, 2500.0, 2500.0)) // write only when not default
3686 SvXMLUnitConverter::convertB3DVector(sStringBuffer
, aDir3D
);
3687 aStr
= sStringBuffer
.makeStringAndClear();
3688 mrExport
.AddAttribute(XML_NAMESPACE_DR3D
, XML_MAX_EDGE
, aStr
);
3691 // write 3DCube shape
3692 // #i123542# Do this *after* the attributes are added, else these will be lost since opening
3693 // the scope will clear the global attribute list at the exporter
3694 SvXMLElementExport
aOBJ(mrExport
, XML_NAMESPACE_DR3D
, XML_CUBE
, true, true);
3698 case XmlShapeType::Draw3DSphereObject
:
3701 aAny
= xPropSet
->getPropertyValue(u
"D3DPosition"_ustr
);
3702 drawing::Position3D aPosition3D
;
3703 aAny
>>= aPosition3D
;
3704 ::basegfx::B3DVector
aPos3D(aPosition3D
.PositionX
, aPosition3D
.PositionY
, aPosition3D
.PositionZ
);
3707 aAny
= xPropSet
->getPropertyValue(u
"D3DSize"_ustr
);
3708 drawing::Direction3D aDirection3D
;
3709 aAny
>>= aDirection3D
;
3710 ::basegfx::B3DVector
aDir3D(aDirection3D
.DirectionX
, aDirection3D
.DirectionY
, aDirection3D
.DirectionZ
);
3713 if(aPos3D
!= ::basegfx::B3DVector(0.0, 0.0, 0.0)) // write only when not default
3715 SvXMLUnitConverter::convertB3DVector(sStringBuffer
, aPos3D
);
3716 aStr
= sStringBuffer
.makeStringAndClear();
3717 mrExport
.AddAttribute(XML_NAMESPACE_DR3D
, XML_CENTER
, aStr
);
3721 if(aDir3D
!= ::basegfx::B3DVector(5000.0, 5000.0, 5000.0)) // write only when not default
3723 SvXMLUnitConverter::convertB3DVector(sStringBuffer
, aDir3D
);
3724 aStr
= sStringBuffer
.makeStringAndClear();
3725 mrExport
.AddAttribute(XML_NAMESPACE_DR3D
, XML_SIZE
, aStr
);
3728 // write 3DSphere shape
3729 // #i123542# Do this *after* the attributes are added, else these will be lost since opening
3730 // the scope will clear the global attribute list at the exporter
3731 SvXMLElementExport
aOBJ(mrExport
, XML_NAMESPACE_DR3D
, XML_SPHERE
, true, true);
3735 case XmlShapeType::Draw3DLatheObject
:
3736 case XmlShapeType::Draw3DExtrudeObject
:
3738 // write special 3DLathe/3DExtrude attributes, get 3D tools::PolyPolygon as drawing::PolyPolygonShape3D
3739 aAny
= xPropSet
->getPropertyValue(u
"D3DPolyPolygon3D"_ustr
);
3740 drawing::PolyPolygonShape3D aUnoPolyPolygon3D
;
3741 aAny
>>= aUnoPolyPolygon3D
;
3743 // convert to 3D PolyPolygon
3744 const basegfx::B3DPolyPolygon
aPolyPolygon3D(
3745 basegfx::utils::UnoPolyPolygonShape3DToB3DPolyPolygon(
3746 aUnoPolyPolygon3D
));
3748 // convert to 2D tools::PolyPolygon using identity 3D transformation (just grep X and Y)
3749 const basegfx::B3DHomMatrix aB3DHomMatrixFor2DConversion
;
3750 const basegfx::B2DPolyPolygon
aPolyPolygon(
3751 basegfx::utils::createB2DPolyPolygonFromB3DPolyPolygon(
3753 aB3DHomMatrixFor2DConversion
));
3755 // get 2D range of it
3756 const basegfx::B2DRange
aPolyPolygonRange(aPolyPolygon
.getB2DRange());
3759 SdXMLImExViewBox
aViewBox(
3760 aPolyPolygonRange
.getMinX(),
3761 aPolyPolygonRange
.getMinY(),
3762 aPolyPolygonRange
.getWidth(),
3763 aPolyPolygonRange
.getHeight());
3765 mrExport
.AddAttribute(XML_NAMESPACE_SVG
, XML_VIEWBOX
, aViewBox
.GetExportString());
3767 // prepare svg:d string
3768 const OUString
aPolygonString(
3769 basegfx::utils::exportToSvgD(
3771 true, // bUseRelativeCoordinates
3772 false, // bDetectQuadraticBeziers TTTT: not used in old, but maybe activated now
3773 true)); // bHandleRelativeNextPointCompatible
3775 // write point array
3776 mrExport
.AddAttribute(XML_NAMESPACE_SVG
, XML_D
, aPolygonString
);
3778 if(eShapeType
== XmlShapeType::Draw3DLatheObject
)
3780 // write 3DLathe shape
3781 SvXMLElementExport
aOBJ(mrExport
, XML_NAMESPACE_DR3D
, XML_ROTATE
, true, true);
3785 // write 3DExtrude shape
3786 SvXMLElementExport
aOBJ(mrExport
, XML_NAMESPACE_DR3D
, XML_EXTRUDE
, true, true);
3795 /** helper for chart that adds all attributes of a 3d scene element to the export */
3796 void XMLShapeExport::export3DSceneAttributes( const css::uno::Reference
< css::beans::XPropertySet
>& xPropSet
)
3799 OUStringBuffer sStringBuffer
;
3801 // world transformation (UNO_NAME_3D_TRANSFORM_MATRIX == "D3DTransformMatrix")
3802 uno::Any aAny
= xPropSet
->getPropertyValue(u
"D3DTransformMatrix"_ustr
);
3803 drawing::HomogenMatrix aHomMat
;
3805 SdXMLImExTransform3D aTransform
;
3806 aTransform
.AddHomogenMatrix(aHomMat
);
3807 if(aTransform
.NeedsAction())
3808 mrExport
.AddAttribute(XML_NAMESPACE_DR3D
, XML_TRANSFORM
, aTransform
.GetExportString(mrExport
.GetMM100UnitConverter()));
3811 aAny
= xPropSet
->getPropertyValue(u
"D3DCameraGeometry"_ustr
);
3812 drawing::CameraGeometry aCamGeo
;
3815 ::basegfx::B3DVector
aVRP(aCamGeo
.vrp
.PositionX
, aCamGeo
.vrp
.PositionY
, aCamGeo
.vrp
.PositionZ
);
3816 if(aVRP
!= ::basegfx::B3DVector(0.0, 0.0, 1.0)) // write only when not default
3818 SvXMLUnitConverter::convertB3DVector(sStringBuffer
, aVRP
);
3819 aStr
= sStringBuffer
.makeStringAndClear();
3820 mrExport
.AddAttribute(XML_NAMESPACE_DR3D
, XML_VRP
, aStr
);
3823 ::basegfx::B3DVector
aVPN(aCamGeo
.vpn
.DirectionX
, aCamGeo
.vpn
.DirectionY
, aCamGeo
.vpn
.DirectionZ
);
3824 if(aVPN
!= ::basegfx::B3DVector(0.0, 0.0, 1.0)) // write only when not default
3826 SvXMLUnitConverter::convertB3DVector(sStringBuffer
, aVPN
);
3827 aStr
= sStringBuffer
.makeStringAndClear();
3828 mrExport
.AddAttribute(XML_NAMESPACE_DR3D
, XML_VPN
, aStr
);
3831 ::basegfx::B3DVector
aVUP(aCamGeo
.vup
.DirectionX
, aCamGeo
.vup
.DirectionY
, aCamGeo
.vup
.DirectionZ
);
3832 if(aVUP
!= ::basegfx::B3DVector(0.0, 1.0, 0.0)) // write only when not default
3834 SvXMLUnitConverter::convertB3DVector(sStringBuffer
, aVUP
);
3835 aStr
= sStringBuffer
.makeStringAndClear();
3836 mrExport
.AddAttribute(XML_NAMESPACE_DR3D
, XML_VUP
, aStr
);
3839 // projection "D3DScenePerspective" drawing::ProjectionMode
3840 aAny
= xPropSet
->getPropertyValue(u
"D3DScenePerspective"_ustr
);
3841 drawing::ProjectionMode aPrjMode
;
3843 if(aPrjMode
== drawing::ProjectionMode_PARALLEL
)
3844 aStr
= GetXMLToken(XML_PARALLEL
);
3846 aStr
= GetXMLToken(XML_PERSPECTIVE
);
3847 mrExport
.AddAttribute(XML_NAMESPACE_DR3D
, XML_PROJECTION
, aStr
);
3850 aAny
= xPropSet
->getPropertyValue(u
"D3DSceneDistance"_ustr
);
3851 sal_Int32 nDistance
= 0;
3853 mrExport
.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer
,
3855 aStr
= sStringBuffer
.makeStringAndClear();
3856 mrExport
.AddAttribute(XML_NAMESPACE_DR3D
, XML_DISTANCE
, aStr
);
3859 aAny
= xPropSet
->getPropertyValue(u
"D3DSceneFocalLength"_ustr
);
3860 sal_Int32 nFocalLength
= 0;
3861 aAny
>>= nFocalLength
;
3862 mrExport
.GetMM100UnitConverter().convertMeasureToXML(sStringBuffer
,
3864 aStr
= sStringBuffer
.makeStringAndClear();
3865 mrExport
.AddAttribute(XML_NAMESPACE_DR3D
, XML_FOCAL_LENGTH
, aStr
);
3868 aAny
= xPropSet
->getPropertyValue(u
"D3DSceneShadowSlant"_ustr
);
3869 sal_Int16 nShadowSlant
= 0;
3870 aAny
>>= nShadowSlant
;
3871 mrExport
.AddAttribute(XML_NAMESPACE_DR3D
, XML_SHADOW_SLANT
, OUString::number(static_cast<sal_Int32
>(nShadowSlant
)));
3874 aAny
= xPropSet
->getPropertyValue(u
"D3DSceneShadeMode"_ustr
);
3875 drawing::ShadeMode aShadeMode
;
3876 if(aAny
>>= aShadeMode
)
3878 if(aShadeMode
== drawing::ShadeMode_FLAT
)
3879 aStr
= GetXMLToken(XML_FLAT
);
3880 else if(aShadeMode
== drawing::ShadeMode_PHONG
)
3881 aStr
= GetXMLToken(XML_PHONG
);
3882 else if(aShadeMode
== drawing::ShadeMode_SMOOTH
)
3883 aStr
= GetXMLToken(XML_GOURAUD
);
3885 aStr
= GetXMLToken(XML_DRAFT
);
3889 // ShadeMode enum not there, write default
3890 aStr
= GetXMLToken(XML_GOURAUD
);
3892 mrExport
.AddAttribute(XML_NAMESPACE_DR3D
, XML_SHADE_MODE
, aStr
);
3895 aAny
= xPropSet
->getPropertyValue(u
"D3DSceneAmbientColor"_ustr
);
3896 sal_Int32 nAmbientColor
= 0;
3897 aAny
>>= nAmbientColor
;
3898 ::sax::Converter::convertColor(sStringBuffer
, nAmbientColor
);
3899 aStr
= sStringBuffer
.makeStringAndClear();
3900 mrExport
.AddAttribute(XML_NAMESPACE_DR3D
, XML_AMBIENT_COLOR
, aStr
);
3903 aAny
= xPropSet
->getPropertyValue(u
"D3DSceneTwoSidedLighting"_ustr
);
3904 bool bTwoSidedLighting
= false;
3905 aAny
>>= bTwoSidedLighting
;
3906 ::sax::Converter::convertBool(sStringBuffer
, bTwoSidedLighting
);
3907 aStr
= sStringBuffer
.makeStringAndClear();
3908 mrExport
.AddAttribute(XML_NAMESPACE_DR3D
, XML_LIGHTING_MODE
, aStr
);
3911 /** helper for chart that exports all lamps from the propertyset */
3912 void XMLShapeExport::export3DLamps( const css::uno::Reference
< css::beans::XPropertySet
>& xPropSet
)
3914 // write lamps 1..8 as content
3916 OUStringBuffer sStringBuffer
;
3918 static constexpr OUStringLiteral
aColorPropName(u
"D3DSceneLightColor");
3919 static constexpr OUStringLiteral
aDirectionPropName(u
"D3DSceneLightDirection");
3920 static constexpr OUStringLiteral
aLightOnPropName(u
"D3DSceneLightOn");
3922 ::basegfx::B3DVector aLightDirection
;
3923 drawing::Direction3D aLightDir
;
3924 bool bLightOnOff
= false;
3925 for(sal_Int32 nLamp
= 1; nLamp
<= 8; nLamp
++)
3927 OUString aIndexStr
= OUString::number( nLamp
);
3930 OUString aPropName
= aColorPropName
+ aIndexStr
;
3931 sal_Int32 nLightColor
= 0;
3932 xPropSet
->getPropertyValue( aPropName
) >>= nLightColor
;
3933 ::sax::Converter::convertColor(sStringBuffer
, nLightColor
);
3934 aStr
= sStringBuffer
.makeStringAndClear();
3935 mrExport
.AddAttribute(XML_NAMESPACE_DR3D
, XML_DIFFUSE_COLOR
, aStr
);
3938 aPropName
= aDirectionPropName
+ aIndexStr
;
3939 xPropSet
->getPropertyValue(aPropName
) >>= aLightDir
;
3940 aLightDirection
= ::basegfx::B3DVector(aLightDir
.DirectionX
, aLightDir
.DirectionY
, aLightDir
.DirectionZ
);
3941 SvXMLUnitConverter::convertB3DVector(sStringBuffer
, aLightDirection
);
3942 aStr
= sStringBuffer
.makeStringAndClear();
3943 mrExport
.AddAttribute(XML_NAMESPACE_DR3D
, XML_DIRECTION
, aStr
);
3946 aPropName
= aLightOnPropName
+ aIndexStr
;
3947 xPropSet
->getPropertyValue(aPropName
) >>= bLightOnOff
;
3948 ::sax::Converter::convertBool(sStringBuffer
, bLightOnOff
);
3949 aStr
= sStringBuffer
.makeStringAndClear();
3950 mrExport
.AddAttribute(XML_NAMESPACE_DR3D
, XML_ENABLED
, aStr
);
3953 mrExport
.AddAttribute(XML_NAMESPACE_DR3D
, XML_SPECULAR
,
3954 nLamp
== 1 ? XML_TRUE
: XML_FALSE
);
3956 // write light entry
3957 SvXMLElementExport
aOBJ(mrExport
, XML_NAMESPACE_DR3D
, XML_LIGHT
, true, true);
3962 // using namespace css::io;
3963 // using namespace ::xmloff::EnhancedCustomShapeToken;
3966 static void ExportParameter( OUStringBuffer
& rStrBuffer
, const css::drawing::EnhancedCustomShapeParameter
& rParameter
)
3968 if ( !rStrBuffer
.isEmpty() )
3969 rStrBuffer
.append( ' ' );
3970 if ( rParameter
.Value
.getValueTypeClass() == uno::TypeClass_DOUBLE
)
3972 double fNumber
= 0.0;
3973 rParameter
.Value
>>= fNumber
;
3974 ::rtl::math::doubleToUStringBuffer( rStrBuffer
, fNumber
, rtl_math_StringFormat_Automatic
, rtl_math_DecimalPlaces_Max
, '.', true );
3978 sal_Int32 nValue
= 0;
3979 rParameter
.Value
>>= nValue
;
3981 switch( rParameter
.Type
)
3983 case css::drawing::EnhancedCustomShapeParameterType::EQUATION
:
3985 rStrBuffer
.append( "?f" + OUString::number( nValue
) );
3989 case css::drawing::EnhancedCustomShapeParameterType::ADJUSTMENT
:
3991 rStrBuffer
.append( '$' );
3992 rStrBuffer
.append( nValue
);
3996 case css::drawing::EnhancedCustomShapeParameterType::BOTTOM
:
3997 rStrBuffer
.append( GetXMLToken( XML_BOTTOM
) ); break;
3998 case css::drawing::EnhancedCustomShapeParameterType::RIGHT
:
3999 rStrBuffer
.append( GetXMLToken( XML_RIGHT
) ); break;
4000 case css::drawing::EnhancedCustomShapeParameterType::TOP
:
4001 rStrBuffer
.append( GetXMLToken( XML_TOP
) ); break;
4002 case css::drawing::EnhancedCustomShapeParameterType::LEFT
:
4003 rStrBuffer
.append( GetXMLToken( XML_LEFT
) ); break;
4004 case css::drawing::EnhancedCustomShapeParameterType::XSTRETCH
:
4005 rStrBuffer
.append( GetXMLToken( XML_XSTRETCH
) ); break;
4006 case css::drawing::EnhancedCustomShapeParameterType::YSTRETCH
:
4007 rStrBuffer
.append( GetXMLToken( XML_YSTRETCH
) ); break;
4008 case css::drawing::EnhancedCustomShapeParameterType::HASSTROKE
:
4009 rStrBuffer
.append( GetXMLToken( XML_HASSTROKE
) ); break;
4010 case css::drawing::EnhancedCustomShapeParameterType::HASFILL
:
4011 rStrBuffer
.append( GetXMLToken( XML_HASFILL
) ); break;
4012 case css::drawing::EnhancedCustomShapeParameterType::WIDTH
:
4013 rStrBuffer
.append( GetXMLToken( XML_WIDTH
) ); break;
4014 case css::drawing::EnhancedCustomShapeParameterType::HEIGHT
:
4015 rStrBuffer
.append( GetXMLToken( XML_HEIGHT
) ); break;
4016 case css::drawing::EnhancedCustomShapeParameterType::LOGWIDTH
:
4017 rStrBuffer
.append( GetXMLToken( XML_LOGWIDTH
) ); break;
4018 case css::drawing::EnhancedCustomShapeParameterType::LOGHEIGHT
:
4019 rStrBuffer
.append( GetXMLToken( XML_LOGHEIGHT
) ); break;
4021 rStrBuffer
.append( nValue
);
4026 static void ImpExportEquations( SvXMLExport
& rExport
, const uno::Sequence
< OUString
>& rEquations
)
4029 for ( i
= 0; i
< rEquations
.getLength(); i
++ )
4031 OUString aStr
= "f" + OUString::number( i
);
4032 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_NAME
, aStr
);
4034 aStr
= rEquations
[ i
];
4035 sal_Int32 nIndex
= 0;
4038 nIndex
= aStr
.indexOf( '?', nIndex
);
4041 aStr
= OUString::Concat(aStr
.subView(0, nIndex
+ 1)) + "f"
4042 + aStr
.subView(nIndex
+ 1, aStr
.getLength() - nIndex
- 1);
4045 } while( nIndex
!= -1 );
4046 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_FORMULA
, aStr
);
4047 SvXMLElementExport
aOBJ( rExport
, XML_NAMESPACE_DRAW
, XML_EQUATION
, true, true );
4051 static void ImpExportHandles( SvXMLExport
& rExport
, const uno::Sequence
< beans::PropertyValues
>& rHandles
)
4053 if ( !rHandles
.hasElements() )
4057 OUStringBuffer aStrBuffer
;
4059 for ( const uno::Sequence
< beans::PropertyValue
>& rPropSeq
: rHandles
)
4061 bool bPosition
= false;
4062 for ( const beans::PropertyValue
& rPropVal
: rPropSeq
)
4064 switch( EASGet( rPropVal
.Name
) )
4068 css::drawing::EnhancedCustomShapeParameterPair aPosition
;
4069 if ( rPropVal
.Value
>>= aPosition
)
4071 ExportParameter( aStrBuffer
, aPosition
.First
);
4072 ExportParameter( aStrBuffer
, aPosition
.Second
);
4073 aStr
= aStrBuffer
.makeStringAndClear();
4075 // Keep it for backward compatibility
4076 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_HANDLE_POSITION
, aStr
);
4078 SvtSaveOptions::ODFSaneDefaultVersion eVersion
= rExport
.getSaneDefaultVersion();
4079 if (eVersion
>= SvtSaveOptions::ODFSVER_014
)
4081 comphelper::SequenceAsHashMap
aPropSeqMap(rPropSeq
);
4082 if (aPropSeqMap
.contains(u
"Polar"_ustr
))
4084 ExportParameter( aStrBuffer
, aPosition
.First
);
4085 aStr
= aStrBuffer
.makeStringAndClear();
4086 rExport
.AddAttribute(XML_NAMESPACE_DRAW
, XML_HANDLE_POLAR_RADIUS
, aStr
);
4088 ExportParameter( aStrBuffer
, aPosition
.Second
);
4089 aStr
= aStrBuffer
.makeStringAndClear();
4090 rExport
.AddAttribute(XML_NAMESPACE_DRAW
, XML_HANDLE_POLAR_ANGLE
, aStr
);
4094 ExportParameter( aStrBuffer
, aPosition
.First
);
4095 aStr
= aStrBuffer
.makeStringAndClear();
4096 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_HANDLE_POSITION_X
, aStr
);
4098 ExportParameter( aStrBuffer
, aPosition
.Second
);
4099 aStr
= aStrBuffer
.makeStringAndClear();
4100 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_HANDLE_POSITION_Y
, aStr
);
4108 case EAS_MirroredX
:
4111 if ( rPropVal
.Value
>>= bMirroredX
)
4112 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_HANDLE_MIRROR_HORIZONTAL
,
4113 bMirroredX
? GetXMLToken( XML_TRUE
) : GetXMLToken( XML_FALSE
) );
4116 case EAS_MirroredY
:
4119 if ( rPropVal
.Value
>>= bMirroredY
)
4120 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_HANDLE_MIRROR_VERTICAL
,
4121 bMirroredY
? GetXMLToken( XML_TRUE
) : GetXMLToken( XML_FALSE
) );
4127 if ( rPropVal
.Value
>>= bSwitched
)
4128 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_HANDLE_SWITCHED
,
4129 bSwitched
? GetXMLToken( XML_TRUE
) : GetXMLToken( XML_FALSE
) );
4134 css::drawing::EnhancedCustomShapeParameterPair aPolar
;
4135 if ( rPropVal
.Value
>>= aPolar
)
4137 ExportParameter( aStrBuffer
, aPolar
.First
);
4138 ExportParameter( aStrBuffer
, aPolar
.Second
);
4139 aStr
= aStrBuffer
.makeStringAndClear();
4140 // Keep it for backward compatibility
4141 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_HANDLE_POLAR
, aStr
);
4143 SvtSaveOptions::ODFSaneDefaultVersion eVersion
= rExport
.getSaneDefaultVersion();
4144 if (eVersion
>= SvtSaveOptions::ODFSVER_014
)
4146 ExportParameter( aStrBuffer
, aPolar
.First
);
4147 aStr
= aStrBuffer
.makeStringAndClear();
4148 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_HANDLE_POLAR_POLE_X
, aStr
);
4150 ExportParameter( aStrBuffer
, aPolar
.Second
);
4151 aStr
= aStrBuffer
.makeStringAndClear();
4152 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_HANDLE_POLAR_POLE_Y
, aStr
);
4157 case EAS_RadiusRangeMinimum
:
4159 css::drawing::EnhancedCustomShapeParameter aRadiusRangeMinimum
;
4160 if ( rPropVal
.Value
>>= aRadiusRangeMinimum
)
4162 ExportParameter( aStrBuffer
, aRadiusRangeMinimum
);
4163 aStr
= aStrBuffer
.makeStringAndClear();
4164 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_HANDLE_RADIUS_RANGE_MINIMUM
, aStr
);
4168 case EAS_RadiusRangeMaximum
:
4170 css::drawing::EnhancedCustomShapeParameter aRadiusRangeMaximum
;
4171 if ( rPropVal
.Value
>>= aRadiusRangeMaximum
)
4173 ExportParameter( aStrBuffer
, aRadiusRangeMaximum
);
4174 aStr
= aStrBuffer
.makeStringAndClear();
4175 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_HANDLE_RADIUS_RANGE_MAXIMUM
, aStr
);
4179 case EAS_RangeXMinimum
:
4181 css::drawing::EnhancedCustomShapeParameter aXRangeMinimum
;
4182 if ( rPropVal
.Value
>>= aXRangeMinimum
)
4184 ExportParameter( aStrBuffer
, aXRangeMinimum
);
4185 aStr
= aStrBuffer
.makeStringAndClear();
4186 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_HANDLE_RANGE_X_MINIMUM
, aStr
);
4190 case EAS_RangeXMaximum
:
4192 css::drawing::EnhancedCustomShapeParameter aXRangeMaximum
;
4193 if ( rPropVal
.Value
>>= aXRangeMaximum
)
4195 ExportParameter( aStrBuffer
, aXRangeMaximum
);
4196 aStr
= aStrBuffer
.makeStringAndClear();
4197 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_HANDLE_RANGE_X_MAXIMUM
, aStr
);
4201 case EAS_RangeYMinimum
:
4203 css::drawing::EnhancedCustomShapeParameter aYRangeMinimum
;
4204 if ( rPropVal
.Value
>>= aYRangeMinimum
)
4206 ExportParameter( aStrBuffer
, aYRangeMinimum
);
4207 aStr
= aStrBuffer
.makeStringAndClear();
4208 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_HANDLE_RANGE_Y_MINIMUM
, aStr
);
4212 case EAS_RangeYMaximum
:
4214 css::drawing::EnhancedCustomShapeParameter aYRangeMaximum
;
4215 if ( rPropVal
.Value
>>= aYRangeMaximum
)
4217 ExportParameter( aStrBuffer
, aYRangeMaximum
);
4218 aStr
= aStrBuffer
.makeStringAndClear();
4219 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_HANDLE_RANGE_Y_MAXIMUM
, aStr
);
4228 SvXMLElementExport
aOBJ( rExport
, XML_NAMESPACE_DRAW
, XML_HANDLE
, true, true );
4230 rExport
.ClearAttrList();
4234 static void ImpExportEnhancedPath( SvXMLExport
& rExport
,
4235 const uno::Sequence
< css::drawing::EnhancedCustomShapeParameterPair
>& rCoordinates
,
4236 const uno::Sequence
< css::drawing::EnhancedCustomShapeSegment
>& rSegments
,
4237 bool bExtended
= false )
4241 OUStringBuffer aStrBuffer
;
4242 bool bNeedExtended
= false;
4244 sal_Int32 i
, j
, k
, l
;
4246 sal_Int32 nCoords
= rCoordinates
.getLength();
4247 sal_Int32 nSegments
= rSegments
.getLength();
4248 bool bSimpleSegments
= nSegments
== 0;
4249 if ( bSimpleSegments
)
4251 for ( j
= i
= 0; j
< nSegments
; j
++ )
4253 css::drawing::EnhancedCustomShapeSegment aSegment
;
4254 if ( bSimpleSegments
)
4256 // if there are not enough segments we will default them
4262 aSegment
.Command
= css::drawing::EnhancedCustomShapeSegmentCommand::MOVETO
;
4267 aSegment
.Count
= static_cast<sal_Int16
>(std::min( nCoords
- 1, sal_Int32(32767) ));
4268 aSegment
.Command
= css::drawing::EnhancedCustomShapeSegmentCommand::LINETO
;
4274 aSegment
.Command
= css::drawing::EnhancedCustomShapeSegmentCommand::CLOSESUBPATH
;
4280 aSegment
.Command
= css::drawing::EnhancedCustomShapeSegmentCommand::ENDSUBPATH
;
4286 aSegment
= rSegments
[ j
];
4288 if ( !aStrBuffer
.isEmpty() )
4289 aStrBuffer
.append( ' ' );
4291 sal_Int32 nParameter
= 0;
4292 switch( aSegment
.Command
)
4294 case css::drawing::EnhancedCustomShapeSegmentCommand::CLOSESUBPATH
:
4295 aStrBuffer
.append( 'Z' ); break;
4296 case css::drawing::EnhancedCustomShapeSegmentCommand::ENDSUBPATH
:
4297 aStrBuffer
.append( 'N' ); break;
4298 case css::drawing::EnhancedCustomShapeSegmentCommand::NOFILL
:
4299 aStrBuffer
.append( 'F' ); break;
4300 case css::drawing::EnhancedCustomShapeSegmentCommand::NOSTROKE
:
4301 aStrBuffer
.append( 'S' ); break;
4303 case css::drawing::EnhancedCustomShapeSegmentCommand::MOVETO
:
4304 aStrBuffer
.append( 'M' ); nParameter
= 1; break;
4305 case css::drawing::EnhancedCustomShapeSegmentCommand::LINETO
:
4306 aStrBuffer
.append( 'L' ); nParameter
= 1; break;
4307 case css::drawing::EnhancedCustomShapeSegmentCommand::CURVETO
:
4308 aStrBuffer
.append( 'C' ); nParameter
= 3; break;
4309 case css::drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO
:
4310 aStrBuffer
.append( 'T' ); nParameter
= 3; break;
4311 case css::drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE
:
4312 aStrBuffer
.append( 'U' ); nParameter
= 3; break;
4313 case css::drawing::EnhancedCustomShapeSegmentCommand::ARCTO
:
4314 aStrBuffer
.append( 'A' ); nParameter
= 4; break;
4315 case css::drawing::EnhancedCustomShapeSegmentCommand::ARC
:
4316 aStrBuffer
.append( 'B' ); nParameter
= 4; break;
4317 case css::drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO
:
4318 aStrBuffer
.append( 'W' ); nParameter
= 4; break;
4319 case css::drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARC
:
4320 aStrBuffer
.append( 'V' ); nParameter
= 4; break;
4321 case css::drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX
:
4322 aStrBuffer
.append( 'X' ); nParameter
= 1; break;
4323 case css::drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY
:
4324 aStrBuffer
.append( 'Y' ); nParameter
= 1; break;
4325 case css::drawing::EnhancedCustomShapeSegmentCommand::QUADRATICCURVETO
:
4326 aStrBuffer
.append( 'Q' ); nParameter
= 2; break;
4327 case css::drawing::EnhancedCustomShapeSegmentCommand::ARCANGLETO
:
4329 aStrBuffer
.append( 'G' );
4332 aStrBuffer
.setLength( aStrBuffer
.getLength() - 1);
4333 bNeedExtended
= true;
4337 case css::drawing::EnhancedCustomShapeSegmentCommand::DARKEN
:
4339 aStrBuffer
.append( 'H' );
4341 bNeedExtended
= true;
4343 case css::drawing::EnhancedCustomShapeSegmentCommand::DARKENLESS
:
4345 aStrBuffer
.append( 'I' );
4347 bNeedExtended
= true;
4349 case css::drawing::EnhancedCustomShapeSegmentCommand::LIGHTEN
:
4351 aStrBuffer
.append( 'J' );
4353 bNeedExtended
= true;
4355 case css::drawing::EnhancedCustomShapeSegmentCommand::LIGHTENLESS
:
4357 aStrBuffer
.append( 'K' );
4359 bNeedExtended
= true;
4361 default : // ups, seems to be something wrong
4364 aSegment
.Command
= css::drawing::EnhancedCustomShapeSegmentCommand::LINETO
;
4370 for ( k
= 0; k
< aSegment
.Count
; k
++ )
4372 if ( ( i
+ nParameter
) <= nCoords
)
4374 for ( l
= 0; l
< nParameter
; l
++ )
4376 ExportParameter( aStrBuffer
, rCoordinates
[ i
].First
);
4377 ExportParameter( aStrBuffer
, rCoordinates
[ i
++ ].Second
);
4382 j
= nSegments
; // error -> exiting
4388 aStr
= aStrBuffer
.makeStringAndClear();
4389 rExport
.AddAttribute( bExtended
? XML_NAMESPACE_DRAW_EXT
: XML_NAMESPACE_DRAW
, XML_ENHANCED_PATH
, aStr
);
4390 if (!bExtended
&& bNeedExtended
&& (rExport
.getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED
))
4391 ImpExportEnhancedPath( rExport
, rCoordinates
, rSegments
, true );
4394 static void ImpExportEnhancedGeometry( SvXMLExport
& rExport
, const uno::Reference
< beans::XPropertySet
>& xPropSet
)
4396 bool bEquations
= false;
4397 uno::Sequence
< OUString
> aEquations
;
4399 bool bHandles
= false;
4400 uno::Sequence
< beans::PropertyValues
> aHandles
;
4402 uno::Sequence
< css::drawing::EnhancedCustomShapeSegment
> aSegments
;
4403 uno::Sequence
< css::drawing::EnhancedCustomShapeParameterPair
> aCoordinates
;
4405 uno::Sequence
< css::drawing::EnhancedCustomShapeAdjustmentValue
> aAdjustmentValues
;
4408 OUStringBuffer aStrBuffer
;
4409 double fTextRotateAngle(0.0);
4410 double fTextPreRotateAngle(0.0); // will be consolidated with fTextRotateAngle at the end
4411 SvXMLUnitConverter
& rUnitConverter
= rExport
.GetMM100UnitConverter();
4413 uno::Reference
< beans::XPropertySetInfo
> xPropSetInfo( xPropSet
->getPropertySetInfo() );
4416 static constexpr OUString
sCustomShapeGeometry( u
"CustomShapeGeometry"_ustr
);
4417 if ( xPropSetInfo
.is() && xPropSetInfo
->hasPropertyByName( sCustomShapeGeometry
) )
4419 uno::Any
aGeoPropSet( xPropSet
->getPropertyValue( sCustomShapeGeometry
) );
4420 uno::Sequence
< beans::PropertyValue
> aGeoPropSeq
;
4422 if ( aGeoPropSet
>>= aGeoPropSeq
)
4424 bool bCoordinates
= false;
4425 OUString
aCustomShapeType( u
"non-primitive"_ustr
);
4427 for (const beans::PropertyValue
& rGeoProp
: aGeoPropSeq
)
4429 switch( EASGet( rGeoProp
.Name
) )
4433 rGeoProp
.Value
>>= aCustomShapeType
;
4436 case EAS_MirroredX
:
4439 if ( rGeoProp
.Value
>>= bMirroredX
)
4440 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_MIRROR_HORIZONTAL
,
4441 bMirroredX
? GetXMLToken( XML_TRUE
) : GetXMLToken( XML_FALSE
) );
4444 case EAS_MirroredY
:
4447 if ( rGeoProp
.Value
>>= bMirroredY
)
4448 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_MIRROR_VERTICAL
,
4449 bMirroredY
? GetXMLToken( XML_TRUE
) : GetXMLToken( XML_FALSE
) );
4454 awt::Rectangle aRect
;
4455 if ( rGeoProp
.Value
>>= aRect
)
4457 SdXMLImExViewBox
aViewBox( aRect
.X
, aRect
.Y
, aRect
.Width
, aRect
.Height
);
4458 rExport
.AddAttribute( XML_NAMESPACE_SVG
, XML_VIEWBOX
, aViewBox
.GetExportString() );
4462 case EAS_TextPreRotateAngle
:
4464 rGeoProp
.Value
>>= fTextPreRotateAngle
;
4467 case EAS_TextRotateAngle
:
4469 rGeoProp
.Value
>>= fTextRotateAngle
;
4472 case EAS_Extrusion
:
4474 uno::Sequence
< beans::PropertyValue
> aExtrusionPropSeq
;
4475 if ( rGeoProp
.Value
>>= aExtrusionPropSeq
)
4477 bool bSkewValuesProvided
= false;
4478 for (const beans::PropertyValue
& rProp
: aExtrusionPropSeq
)
4480 switch( EASGet( rProp
.Name
) )
4482 case EAS_Extrusion
:
4485 if ( rProp
.Value
>>= bExtrusionOn
)
4486 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_EXTRUSION
,
4487 bExtrusionOn
? GetXMLToken( XML_TRUE
) : GetXMLToken( XML_FALSE
) );
4490 case EAS_Brightness
:
4492 double fExtrusionBrightness
= 0;
4493 if ( rProp
.Value
>>= fExtrusionBrightness
)
4495 ::sax::Converter::convertDouble(
4497 fExtrusionBrightness
,
4499 util::MeasureUnit::PERCENT
,
4500 util::MeasureUnit::PERCENT
);
4501 aStrBuffer
.append( '%' );
4502 aStr
= aStrBuffer
.makeStringAndClear();
4503 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_EXTRUSION_BRIGHTNESS
, aStr
);
4509 css::drawing::EnhancedCustomShapeParameterPair aDepthParaPair
;
4510 if ( rProp
.Value
>>= aDepthParaPair
)
4513 if ( aDepthParaPair
.First
.Value
>>= fDepth
)
4515 rExport
.GetMM100UnitConverter().convertDouble( aStrBuffer
, fDepth
);
4516 ExportParameter( aStrBuffer
, aDepthParaPair
.Second
);
4517 aStr
= aStrBuffer
.makeStringAndClear();
4518 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_EXTRUSION_DEPTH
, aStr
);
4523 case EAS_Diffusion
:
4525 double fExtrusionDiffusion
= 0;
4526 if ( rProp
.Value
>>= fExtrusionDiffusion
)
4528 ::sax::Converter::convertDouble(
4530 fExtrusionDiffusion
,
4532 util::MeasureUnit::PERCENT
,
4533 util::MeasureUnit::PERCENT
);
4534 aStrBuffer
.append( '%' );
4535 aStr
= aStrBuffer
.makeStringAndClear();
4536 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_EXTRUSION_DIFFUSION
, aStr
);
4540 case EAS_NumberOfLineSegments
:
4542 sal_Int32 nExtrusionNumberOfLineSegments
= 0;
4543 if ( rProp
.Value
>>= nExtrusionNumberOfLineSegments
)
4544 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_EXTRUSION_NUMBER_OF_LINE_SEGMENTS
, OUString::number( nExtrusionNumberOfLineSegments
) );
4547 case EAS_LightFace
:
4549 bool bExtrusionLightFace
;
4550 if ( rProp
.Value
>>= bExtrusionLightFace
)
4551 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_EXTRUSION_LIGHT_FACE
,
4552 bExtrusionLightFace
? GetXMLToken( XML_TRUE
) : GetXMLToken( XML_FALSE
) );
4555 case EAS_FirstLightHarsh
:
4557 bool bExtrusionFirstLightHarsh
;
4558 if ( rProp
.Value
>>= bExtrusionFirstLightHarsh
)
4559 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_EXTRUSION_FIRST_LIGHT_HARSH
,
4560 bExtrusionFirstLightHarsh
? GetXMLToken( XML_TRUE
) : GetXMLToken( XML_FALSE
) );
4563 case EAS_SecondLightHarsh
:
4565 bool bExtrusionSecondLightHarsh
;
4566 if ( rProp
.Value
>>= bExtrusionSecondLightHarsh
)
4567 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_EXTRUSION_SECOND_LIGHT_HARSH
,
4568 bExtrusionSecondLightHarsh
? GetXMLToken( XML_TRUE
) : GetXMLToken( XML_FALSE
) );
4571 case EAS_FirstLightLevel
:
4573 double fExtrusionFirstLightLevel
= 0;
4574 if ( rProp
.Value
>>= fExtrusionFirstLightLevel
)
4576 fExtrusionFirstLightLevel
=
4577 std::clamp(fExtrusionFirstLightLevel
, 0.0, 100.0);
4578 ::sax::Converter::convertDouble(
4580 fExtrusionFirstLightLevel
,
4582 util::MeasureUnit::PERCENT
,
4583 util::MeasureUnit::PERCENT
);
4584 aStrBuffer
.append( '%' );
4585 aStr
= aStrBuffer
.makeStringAndClear();
4586 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_EXTRUSION_FIRST_LIGHT_LEVEL
, aStr
);
4590 case EAS_SecondLightLevel
:
4592 double fExtrusionSecondLightLevel
= 0;
4593 if ( rProp
.Value
>>= fExtrusionSecondLightLevel
)
4595 fExtrusionSecondLightLevel
=
4596 std::clamp(fExtrusionSecondLightLevel
, 0.0, 100.0);
4597 ::sax::Converter::convertDouble(
4599 fExtrusionSecondLightLevel
,
4601 util::MeasureUnit::PERCENT
,
4602 util::MeasureUnit::PERCENT
);
4603 aStrBuffer
.append( '%' );
4604 aStr
= aStrBuffer
.makeStringAndClear();
4605 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_EXTRUSION_SECOND_LIGHT_LEVEL
, aStr
);
4609 case EAS_FirstLightDirection
:
4611 drawing::Direction3D aExtrusionFirstLightDirection
;
4612 if ( rProp
.Value
>>= aExtrusionFirstLightDirection
)
4614 ::basegfx::B3DVector
aVec3D( aExtrusionFirstLightDirection
.DirectionX
, aExtrusionFirstLightDirection
.DirectionY
,
4615 aExtrusionFirstLightDirection
.DirectionZ
);
4616 SvXMLUnitConverter::convertB3DVector( aStrBuffer
, aVec3D
);
4617 aStr
= aStrBuffer
.makeStringAndClear();
4618 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_EXTRUSION_FIRST_LIGHT_DIRECTION
, aStr
);
4622 case EAS_SecondLightDirection
:
4624 drawing::Direction3D aExtrusionSecondLightDirection
;
4625 if ( rProp
.Value
>>= aExtrusionSecondLightDirection
)
4627 ::basegfx::B3DVector
aVec3D( aExtrusionSecondLightDirection
.DirectionX
, aExtrusionSecondLightDirection
.DirectionY
,
4628 aExtrusionSecondLightDirection
.DirectionZ
);
4629 SvXMLUnitConverter::convertB3DVector( aStrBuffer
, aVec3D
);
4630 aStr
= aStrBuffer
.makeStringAndClear();
4631 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_EXTRUSION_SECOND_LIGHT_DIRECTION
, aStr
);
4637 bool bExtrusionMetal
;
4638 if ( rProp
.Value
>>= bExtrusionMetal
)
4639 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_EXTRUSION_METAL
,
4640 bExtrusionMetal
? GetXMLToken( XML_TRUE
) : GetXMLToken( XML_FALSE
) );
4643 case EAS_MetalType
:
4645 // In ODF since ODF 1.4. Before 1.4, export only in extended.
4646 sal_Int16 eMetalType
;
4647 if (rProp
.Value
>>= eMetalType
)
4649 // LibreOffice had used the same values as later specified in ODF 1.4
4650 if (eMetalType
== drawing::EnhancedCustomShapeMetalType::MetalMSCompatible
)
4651 aStr
= "loext:MetalMSCompatible";
4653 aStr
= "draw:MetalODF";
4655 SvtSaveOptions::ODFSaneDefaultVersion eVersion
= rExport
.getSaneDefaultVersion();
4656 if (eVersion
>= SvtSaveOptions::ODFSVER_014
)
4658 if (!(eVersion
& SvtSaveOptions::ODFSVER_EXTENDED
)
4659 && eMetalType
== drawing::EnhancedCustomShapeMetalType::MetalMSCompatible
)
4660 rExport
.AddAttribute(XML_NAMESPACE_XMLNS
, XML_NP_LO_EXT
, XML_N_LO_EXT
);
4661 rExport
.AddAttribute(XML_NAMESPACE_DRAW
, XML_EXTRUSION_METAL_TYPE
, aStr
);
4663 else if (eVersion
& SvtSaveOptions::ODFSVER_EXTENDED
)
4665 rExport
.AddAttribute(XML_NAMESPACE_LO_EXT
, XML_EXTRUSION_METAL_TYPE
, aStr
);
4670 case EAS_ShadeMode
:
4673 drawing::ShadeMode eShadeMode
;
4674 if( rProp
.Value
>>= eShadeMode
)
4676 if( eShadeMode
== drawing::ShadeMode_FLAT
)
4677 aStr
= GetXMLToken( XML_FLAT
);
4678 else if( eShadeMode
== drawing::ShadeMode_PHONG
)
4679 aStr
= GetXMLToken( XML_PHONG
);
4680 else if( eShadeMode
== drawing::ShadeMode_SMOOTH
)
4681 aStr
= GetXMLToken( XML_GOURAUD
);
4683 aStr
= GetXMLToken( XML_DRAFT
);
4687 // ShadeMode enum not there, write default
4688 aStr
= GetXMLToken( XML_FLAT
);
4690 rExport
.AddAttribute( XML_NAMESPACE_DR3D
, XML_SHADE_MODE
, aStr
);
4693 case EAS_RotateAngle
:
4695 css::drawing::EnhancedCustomShapeParameterPair aRotateAngleParaPair
;
4696 if ( rProp
.Value
>>= aRotateAngleParaPair
)
4698 ExportParameter( aStrBuffer
, aRotateAngleParaPair
.First
);
4699 ExportParameter( aStrBuffer
, aRotateAngleParaPair
.Second
);
4700 aStr
= aStrBuffer
.makeStringAndClear();
4701 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_EXTRUSION_ROTATION_ANGLE
, aStr
);
4705 case EAS_RotationCenter
:
4707 drawing::Direction3D aExtrusionRotationCenter
;
4708 if ( rProp
.Value
>>= aExtrusionRotationCenter
)
4710 ::basegfx::B3DVector
aVec3D( aExtrusionRotationCenter
.DirectionX
, aExtrusionRotationCenter
.DirectionY
,
4711 aExtrusionRotationCenter
.DirectionZ
);
4712 SvXMLUnitConverter::convertB3DVector( aStrBuffer
, aVec3D
);
4713 aStr
= aStrBuffer
.makeStringAndClear();
4714 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_EXTRUSION_ROTATION_CENTER
, aStr
);
4718 case EAS_Shininess
:
4720 double fExtrusionShininess
= 0;
4721 if ( rProp
.Value
>>= fExtrusionShininess
)
4723 ::sax::Converter::convertDouble(
4725 fExtrusionShininess
,
4727 util::MeasureUnit::PERCENT
,
4728 util::MeasureUnit::PERCENT
);
4729 aStrBuffer
.append( '%' );
4730 aStr
= aStrBuffer
.makeStringAndClear();
4731 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_EXTRUSION_SHININESS
, aStr
);
4737 css::drawing::EnhancedCustomShapeParameterPair aSkewParaPair
;
4738 if ( rProp
.Value
>>= aSkewParaPair
)
4740 bSkewValuesProvided
= true;
4741 ExportParameter( aStrBuffer
, aSkewParaPair
.First
);
4742 ExportParameter( aStrBuffer
, aSkewParaPair
.Second
);
4743 aStr
= aStrBuffer
.makeStringAndClear();
4744 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_EXTRUSION_SKEW
, aStr
);
4748 case EAS_Specularity
:
4750 double fExtrusionSpecularity
= 0;
4751 if ( rProp
.Value
>>= fExtrusionSpecularity
)
4753 // ODF 1.0/1.1 allow arbitrary percent, ODF 1.2/1.3 restrict it to 0%-100%,
4754 // ODF 1.4 restricts it to non negative percent.
4755 SvtSaveOptions::ODFSaneDefaultVersion eVersion
= rExport
.getSaneDefaultVersion();
4756 if (fExtrusionSpecularity
> 100.0 && eVersion
& SvtSaveOptions::ODFSVER_EXTENDED
4757 && eVersion
>= SvtSaveOptions::ODFSVER_012
&& eVersion
< SvtSaveOptions::ODFSVER_014
)
4759 // tdf#147580 write values > 100% in loext
4760 ::sax::Converter::convertDouble(
4762 fExtrusionSpecularity
,
4764 util::MeasureUnit::PERCENT
,
4765 util::MeasureUnit::PERCENT
);
4766 aStrBuffer
.append( '%' );
4767 aStr
= aStrBuffer
.makeStringAndClear();
4768 rExport
.AddAttribute( XML_NAMESPACE_LO_EXT
, XML_EXTRUSION_SPECULARITY_LOEXT
, aStr
);
4770 // clamp fExtrusionSpecularity to allowed values
4771 if (eVersion
>= SvtSaveOptions::ODFSVER_012
&& eVersion
< SvtSaveOptions::ODFSVER_014
)
4772 fExtrusionSpecularity
= std::clamp
<double>(fExtrusionSpecularity
, 0.0, 100.0);
4773 else if (eVersion
>= SvtSaveOptions::ODFSVER_014
)
4774 fExtrusionSpecularity
= std::max
<double>(0.0, fExtrusionSpecularity
);
4776 ::sax::Converter::convertDouble(
4778 fExtrusionSpecularity
,
4780 util::MeasureUnit::PERCENT
,
4781 util::MeasureUnit::PERCENT
);
4782 aStrBuffer
.append( '%' );
4783 aStr
= aStrBuffer
.makeStringAndClear();
4784 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_EXTRUSION_SPECULARITY
, aStr
);
4788 case EAS_ProjectionMode
:
4790 drawing::ProjectionMode eProjectionMode
;
4791 if ( rProp
.Value
>>= eProjectionMode
)
4792 rExport
.AddAttribute( XML_NAMESPACE_DR3D
, XML_PROJECTION
,
4793 eProjectionMode
== drawing::ProjectionMode_PARALLEL
? GetXMLToken( XML_PARALLEL
) : GetXMLToken( XML_PERSPECTIVE
) );
4796 case EAS_ViewPoint
:
4798 drawing::Position3D aExtrusionViewPoint
;
4799 if ( rProp
.Value
>>= aExtrusionViewPoint
)
4801 rUnitConverter
.convertPosition3D( aStrBuffer
, aExtrusionViewPoint
);
4802 aStr
= aStrBuffer
.makeStringAndClear();
4803 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_EXTRUSION_VIEWPOINT
, aStr
);
4809 css::drawing::EnhancedCustomShapeParameterPair aOriginParaPair
;
4810 if ( rProp
.Value
>>= aOriginParaPair
)
4812 ExportParameter( aStrBuffer
, aOriginParaPair
.First
);
4813 ExportParameter( aStrBuffer
, aOriginParaPair
.Second
);
4814 aStr
= aStrBuffer
.makeStringAndClear();
4815 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_EXTRUSION_ORIGIN
, aStr
);
4821 bool bExtrusionColor
;
4822 if ( rProp
.Value
>>= bExtrusionColor
)
4824 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_EXTRUSION_COLOR
,
4825 bExtrusionColor
? GetXMLToken( XML_TRUE
) : GetXMLToken( XML_FALSE
) );
4833 // tdf#141301: no specific skew values provided
4834 if (!bSkewValuesProvided
)
4836 // so we need to export default values explicitly
4837 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_EXTRUSION_SKEW
, u
"50 -135"_ustr
);
4844 uno::Sequence
< beans::PropertyValue
> aTextPathPropSeq
;
4845 if ( rGeoProp
.Value
>>= aTextPathPropSeq
)
4847 for (const beans::PropertyValue
& rProp
: aTextPathPropSeq
)
4849 switch( EASGet( rProp
.Name
) )
4854 if ( rProp
.Value
>>= bTextPathOn
)
4855 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_TEXT_PATH
,
4856 bTextPathOn
? GetXMLToken( XML_TRUE
) : GetXMLToken( XML_FALSE
) );
4859 case EAS_TextPathMode
:
4861 css::drawing::EnhancedCustomShapeTextPathMode eTextPathMode
;
4862 if ( rProp
.Value
>>= eTextPathMode
)
4864 switch ( eTextPathMode
)
4866 case css::drawing::EnhancedCustomShapeTextPathMode_NORMAL
: aStr
= GetXMLToken( XML_NORMAL
); break;
4867 case css::drawing::EnhancedCustomShapeTextPathMode_PATH
: aStr
= GetXMLToken( XML_PATH
); break;
4868 case css::drawing::EnhancedCustomShapeTextPathMode_SHAPE
: aStr
= GetXMLToken( XML_SHAPE
); break;
4872 if ( !aStr
.isEmpty() )
4873 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_TEXT_PATH_MODE
, aStr
);
4880 if ( rProp
.Value
>>= bScaleX
)
4882 aStr
= bScaleX
? GetXMLToken( XML_SHAPE
) : GetXMLToken( XML_PATH
);
4883 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_TEXT_PATH_SCALE
, aStr
);
4887 case EAS_SameLetterHeights
:
4889 bool bSameLetterHeights
;
4890 if ( rProp
.Value
>>= bSameLetterHeights
)
4891 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_TEXT_PATH_SAME_LETTER_HEIGHTS
,
4892 bSameLetterHeights
? GetXMLToken( XML_TRUE
) : GetXMLToken( XML_FALSE
) );
4904 uno::Sequence
< beans::PropertyValue
> aPathPropSeq
;
4905 if ( rGeoProp
.Value
>>= aPathPropSeq
)
4907 for (const beans::PropertyValue
& rProp
: aPathPropSeq
)
4909 switch( EASGet( rProp
.Name
) )
4911 case EAS_SubViewSize
:
4913 // export draw:sub-view-size (do not export in ODF 1.3 or older)
4914 if ((rExport
.getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED
) == 0)
4918 uno::Sequence
< awt::Size
> aSubViewSizes
;
4919 rProp
.Value
>>= aSubViewSizes
;
4921 for ( int nIdx
= 0; nIdx
< aSubViewSizes
.getLength(); nIdx
++ )
4924 aStrBuffer
.append(' ');
4925 aStrBuffer
.append( aSubViewSizes
[nIdx
].Width
);
4926 aStrBuffer
.append(' ');
4927 aStrBuffer
.append( aSubViewSizes
[nIdx
].Height
);
4929 aStr
= aStrBuffer
.makeStringAndClear();
4930 rExport
.AddAttribute( XML_NAMESPACE_DRAW_EXT
, XML_SUB_VIEW_SIZE
, aStr
);
4933 case EAS_ExtrusionAllowed
:
4935 bool bExtrusionAllowed
;
4936 if ( rProp
.Value
>>= bExtrusionAllowed
)
4937 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_EXTRUSION_ALLOWED
,
4938 bExtrusionAllowed
? GetXMLToken( XML_TRUE
) : GetXMLToken( XML_FALSE
) );
4941 case EAS_ConcentricGradientFillAllowed
:
4943 bool bConcentricGradientFillAllowed
;
4944 if ( rProp
.Value
>>= bConcentricGradientFillAllowed
)
4945 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_CONCENTRIC_GRADIENT_FILL_ALLOWED
,
4946 bConcentricGradientFillAllowed
? GetXMLToken( XML_TRUE
) : GetXMLToken( XML_FALSE
) );
4949 case EAS_TextPathAllowed
:
4951 bool bTextPathAllowed
;
4952 if ( rProp
.Value
>>= bTextPathAllowed
)
4953 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_TEXT_PATH_ALLOWED
,
4954 bTextPathAllowed
? GetXMLToken( XML_TRUE
) : GetXMLToken( XML_FALSE
) );
4957 case EAS_GluePoints
:
4959 css::uno::Sequence
< css::drawing::EnhancedCustomShapeParameterPair
> aGluePoints
;
4960 if ( rProp
.Value
>>= aGluePoints
)
4962 if ( aGluePoints
.hasElements() )
4964 for (const auto& rGluePoint
: aGluePoints
)
4966 ExportParameter( aStrBuffer
, rGluePoint
.First
);
4967 ExportParameter( aStrBuffer
, rGluePoint
.Second
);
4969 aStr
= aStrBuffer
.makeStringAndClear();
4971 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_GLUE_POINTS
, aStr
);
4975 case EAS_GluePointType
:
4977 sal_Int16 nGluePointType
= sal_Int16();
4978 if ( rProp
.Value
>>= nGluePointType
)
4980 switch ( nGluePointType
)
4982 case css::drawing::EnhancedCustomShapeGluePointType::NONE
: aStr
= GetXMLToken( XML_NONE
); break;
4983 case css::drawing::EnhancedCustomShapeGluePointType::SEGMENTS
: aStr
= GetXMLToken( XML_SEGMENTS
); break;
4984 case css::drawing::EnhancedCustomShapeGluePointType::RECT
: aStr
= GetXMLToken( XML_RECTANGLE
); break;
4986 if ( !aStr
.isEmpty() )
4987 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_GLUE_POINT_TYPE
, aStr
);
4991 case EAS_Coordinates
:
4993 bCoordinates
= ( rProp
.Value
>>= aCoordinates
);
4998 rProp
.Value
>>= aSegments
;
5003 sal_Int32 nStretchPoint
= 0;
5004 if ( rProp
.Value
>>= nStretchPoint
)
5005 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_PATH_STRETCHPOINT_X
, OUString::number( nStretchPoint
) );
5010 sal_Int32 nStretchPoint
= 0;
5011 if ( rProp
.Value
>>= nStretchPoint
)
5012 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_PATH_STRETCHPOINT_Y
, OUString::number( nStretchPoint
) );
5015 case EAS_TextFrames
:
5017 css::uno::Sequence
< css::drawing::EnhancedCustomShapeTextFrame
> aPathTextFrames
;
5018 if ( rProp
.Value
>>= aPathTextFrames
)
5020 if ( aPathTextFrames
.hasElements() )
5022 for (const auto& rPathTextFrame
: aPathTextFrames
)
5024 ExportParameter( aStrBuffer
, rPathTextFrame
.TopLeft
.First
);
5025 ExportParameter( aStrBuffer
, rPathTextFrame
.TopLeft
.Second
);
5026 ExportParameter( aStrBuffer
, rPathTextFrame
.BottomRight
.First
);
5027 ExportParameter( aStrBuffer
, rPathTextFrame
.BottomRight
.Second
);
5029 aStr
= aStrBuffer
.makeStringAndClear();
5031 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_TEXT_AREAS
, aStr
);
5042 case EAS_Equations
:
5044 bEquations
= ( rGeoProp
.Value
>>= aEquations
);
5049 bHandles
= ( rGeoProp
.Value
>>= aHandles
);
5052 case EAS_AdjustmentValues
:
5054 rGeoProp
.Value
>>= aAdjustmentValues
;
5062 // ToDo: Where is TextPreRotateAngle still used? We cannot save it in ODF.
5063 fTextRotateAngle
+= fTextPreRotateAngle
;
5064 // Workaround for writing-mode bt-lr and tb-rl90 in ODF strict,
5065 // otherwise loext:writing-mode is used in style export.
5066 if (!(rExport
.getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED
))
5068 if (xPropSetInfo
->hasPropertyByName(u
"WritingMode"_ustr
))
5070 sal_Int16 nDirection
= -1;
5071 xPropSet
->getPropertyValue(u
"WritingMode"_ustr
) >>= nDirection
;
5072 if (nDirection
== text::WritingMode2::TB_RL90
)
5073 fTextRotateAngle
-= 90;
5074 else if (nDirection
== text::WritingMode2::BT_LR
)
5075 fTextRotateAngle
-= 270;
5078 if (fTextRotateAngle
!= 0)
5080 ::sax::Converter::convertDouble( aStrBuffer
, fTextRotateAngle
);
5081 aStr
= aStrBuffer
.makeStringAndClear();
5082 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_TEXT_ROTATE_ANGLE
, aStr
);
5085 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_TYPE
, aCustomShapeType
);
5088 sal_Int32 nAdjustmentValues
= aAdjustmentValues
.getLength();
5089 if ( nAdjustmentValues
)
5091 sal_Int32 i
, nValue
= 0;
5092 for ( i
= 0; i
< nAdjustmentValues
; i
++ )
5095 aStrBuffer
.append( ' ' );
5097 const css::drawing::EnhancedCustomShapeAdjustmentValue
& rAdj
= aAdjustmentValues
[ i
];
5098 if ( rAdj
.State
== beans::PropertyState_DIRECT_VALUE
)
5100 if ( rAdj
.Value
.getValueTypeClass() == uno::TypeClass_DOUBLE
)
5102 double fValue
= 0.0;
5103 rAdj
.Value
>>= fValue
;
5104 ::sax::Converter::convertDouble(aStrBuffer
, fValue
);
5108 rAdj
.Value
>>= nValue
;
5109 aStrBuffer
.append(nValue
);
5114 // this should not be, but better than setting nothing
5115 aStrBuffer
.append("0");
5118 aStr
= aStrBuffer
.makeStringAndClear();
5119 rExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_MODIFIERS
, aStr
);
5122 ImpExportEnhancedPath( rExport
, aCoordinates
, aSegments
);
5125 SvXMLElementExport
aOBJ( rExport
, XML_NAMESPACE_DRAW
, XML_ENHANCED_GEOMETRY
, true, true );
5127 ImpExportEquations( rExport
, aEquations
);
5129 ImpExportHandles( rExport
, aHandles
);
5132 void XMLShapeExport::ImpExportCustomShape(
5133 const uno::Reference
< drawing::XShape
>& xShape
,
5134 XMLShapeExportFlags nFeatures
, css::awt::Point
* pRefPoint
)
5136 const uno::Reference
< beans::XPropertySet
> xPropSet(xShape
, uno::UNO_QUERY
);
5137 if ( !xPropSet
.is() )
5140 uno::Reference
< beans::XPropertySetInfo
> xPropSetInfo( xPropSet
->getPropertySetInfo() );
5143 ImpExportNewTrans( xPropSet
, nFeatures
, pRefPoint
);
5145 if ( xPropSetInfo
.is() )
5148 if ( xPropSetInfo
->hasPropertyByName( u
"CustomShapeEngine"_ustr
) )
5150 uno::Any
aEngine( xPropSet
->getPropertyValue( u
"CustomShapeEngine"_ustr
) );
5151 if ( ( aEngine
>>= aStr
) && !aStr
.isEmpty() )
5152 mrExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_ENGINE
, aStr
);
5154 if ( xPropSetInfo
->hasPropertyByName( u
"CustomShapeData"_ustr
) )
5156 uno::Any
aData( xPropSet
->getPropertyValue( u
"CustomShapeData"_ustr
) );
5157 if ( ( aData
>>= aStr
) && !aStr
.isEmpty() )
5158 mrExport
.AddAttribute( XML_NAMESPACE_DRAW
, XML_DATA
, aStr
);
5161 bool bCreateNewline( (nFeatures
& XMLShapeExportFlags::NO_WS
) == XMLShapeExportFlags::NONE
); // #86116#/#92210#
5162 SvXMLElementExport
aOBJ( mrExport
, XML_NAMESPACE_DRAW
, XML_CUSTOM_SHAPE
, bCreateNewline
, true );
5163 ImpExportDescription( xShape
); // #i68101#
5164 ImpExportEvents( xShape
);
5165 ImpExportGluePoints( xShape
);
5166 ImpExportText( xShape
);
5167 ImpExportEnhancedGeometry( mrExport
, xPropSet
);
5171 void XMLShapeExport::ImpExportTableShape( const uno::Reference
< drawing::XShape
>& xShape
, XmlShapeType eShapeType
, XMLShapeExportFlags nFeatures
, css::awt::Point
* pRefPoint
)
5173 uno::Reference
< beans::XPropertySet
> xPropSet(xShape
, uno::UNO_QUERY
);
5174 uno::Reference
< container::XNamed
> xNamed(xShape
, uno::UNO_QUERY
);
5176 SAL_WARN_IF( !xPropSet
.is() || !xNamed
.is(), "xmloff", "xmloff::XMLShapeExport::ImpExportTableShape(), table shape is not implementing needed interfaces");
5177 if(!(xPropSet
.is() && xNamed
.is()))
5183 ImpExportNewTrans(xPropSet
, nFeatures
, pRefPoint
);
5185 bool bIsEmptyPresObj
= false;
5187 // presentation settings
5188 if(eShapeType
== XmlShapeType::PresTableShape
)
5189 bIsEmptyPresObj
= ImpExportPresentationAttributes( xPropSet
, GetXMLToken(XML_TABLE
) );
5191 const bool bCreateNewline( (nFeatures
& XMLShapeExportFlags::NO_WS
) == XMLShapeExportFlags::NONE
);
5193 SvXMLElementExport
aElement( mrExport
, XML_NAMESPACE_DRAW
, XML_FRAME
, bCreateNewline
, true );
5195 // do not export in ODF 1.1 or older
5196 if (mrExport
.getSaneDefaultVersion() >= SvtSaveOptions::ODFSVER_012
)
5198 if( !bIsEmptyPresObj
)
5200 uno::Reference
< container::XNamed
> xTemplate( xPropSet
->getPropertyValue(u
"TableTemplate"_ustr
), uno::UNO_QUERY
);
5201 if( xTemplate
.is() )
5203 const OUString
sTemplate( xTemplate
->getName() );
5204 if( !sTemplate
.isEmpty() )
5206 mrExport
.AddAttribute(XML_NAMESPACE_TABLE
, XML_TEMPLATE_NAME
, sTemplate
);
5208 for( const XMLPropertyMapEntry
* pEntry
= &aXMLTableShapeAttributes
[0]; !pEntry
->IsEnd(); pEntry
++ )
5213 xPropSet
->getPropertyValue( pEntry
->getApiName() ) >>= bBool
;
5215 mrExport
.AddAttribute(pEntry
->mnNameSpace
, pEntry
->meXMLName
, XML_TRUE
);
5217 catch( uno::Exception
& )
5219 DBG_UNHANDLED_EXCEPTION("xmloff.draw");
5225 uno::Reference
< table::XColumnRowRange
> xRange( xPropSet
->getPropertyValue( gsModel
), uno::UNO_QUERY_THROW
);
5226 GetShapeTableExport()->exportTable( xRange
);
5230 if (!bIsEmptyPresObj
5231 && officecfg::Office::Common::Save::Graphic::AddReplacementImages::get())
5233 uno::Reference
< graphic::XGraphic
> xGraphic( xPropSet
->getPropertyValue(u
"ReplacementGraphic"_ustr
), uno::UNO_QUERY
);
5234 ExportGraphicPreview(xGraphic
, mrExport
, u
"TablePreview", u
".svm", u
"image/x-vclgraphic"_ustr
);
5237 ImpExportEvents( xShape
);
5238 ImpExportGluePoints( xShape
);
5239 ImpExportDescription( xShape
); // #i68101#
5241 catch( uno::Exception
const & )
5243 DBG_UNHANDLED_EXCEPTION("xmloff.draw");
5247 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */