Coverage Report

Created: 2026-08-14 10:22

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