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