Coverage Report

Created: 2026-05-16 09:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/oox/source/drawingml/shape.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 <oox/drawingml/shape.hxx>
23
#include <drawingml/customshapeproperties.hxx>
24
#include <oox/drawingml/theme.hxx>
25
#include <drawingml/fillproperties.hxx>
26
#include <drawingml/fontworkhelpers.hxx>
27
#include <drawingml/graphicproperties.hxx>
28
#include <drawingml/lineproperties.hxx>
29
#include <drawingml/presetgeometrynames.hxx>
30
#include <drawingml/shape3dproperties.hxx>
31
#include <drawingml/scene3dhelper.hxx>
32
#include <drawingml/effectproperties.hxx>
33
#include <oox/drawingml/shapepropertymap.hxx>
34
#include <drawingml/textbody.hxx>
35
#include <drawingml/textparagraph.hxx>
36
#include <drawingml/ThemeOverrideFragmentHandler.hxx>
37
#include <drawingml/table/tableproperties.hxx>
38
#include <oox/drawingml/chart/chartconverter.hxx>
39
#include <drawingml/chart/chartspacefragment.hxx>
40
#include <drawingml/chart/stylefragment.hxx>
41
#include <drawingml/chart/stylemodel.hxx>
42
#include <drawingml/chart/colorsmodel.hxx>
43
#include <drawingml/chart/chartspacemodel.hxx>
44
#include <o3tl/safeint.hxx>
45
#include <o3tl/unit_conversion.hxx>
46
#include <oox/ppt/pptimport.hxx>
47
#include <oox/vml/vmldrawing.hxx>
48
#include <oox/vml/vmlshape.hxx>
49
#include <oox/vml/vmlshapecontainer.hxx>
50
#include <oox/core/xmlfilterbase.hxx>
51
#include <oox/helper/graphichelper.hxx>
52
#include <oox/helper/propertyset.hxx>
53
#include <oox/helper/modelobjecthelper.hxx>
54
#include <oox/mathml/imexport.hxx>
55
#include <oox/mathml/importutils.hxx>
56
#include <oox/token/properties.hxx>
57
#include "diagram/datamodel_oox.hxx"
58
#include <oox/drawingml/diagram/diagramhelper_oox.hxx>
59
60
#include <comphelper/classids.hxx>
61
#include <comphelper/propertysequence.hxx>
62
#include <comphelper/propertyvalue.hxx>
63
#include <comphelper/sequence.hxx>
64
#include <comphelper/diagnose_ex.hxx>
65
#include <comphelper/sequenceashashmap.hxx>
66
#include <tools/gen.hxx>
67
#include <tools/globname.hxx>
68
#include <tools/mapunit.hxx>
69
#include <editeng/unoprnms.hxx>
70
#include <com/sun/star/awt/FontSlant.hpp>
71
#include <com/sun/star/awt/Size.hpp>
72
#include <com/sun/star/awt/XBitmap.hpp>
73
#include <com/sun/star/awt/FontWeight.hpp>
74
#include <com/sun/star/graphic/XGraphic.hpp>
75
#include <com/sun/star/container/XNamed.hpp>
76
#include <com/sun/star/container/XEnumerationAccess.hpp>
77
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
78
#include <com/sun/star/xml/dom/XDocument.hpp>
79
#include <com/sun/star/xml/sax/XFastSAXSerializable.hpp>
80
#include <com/sun/star/drawing/FillStyle.hpp>
81
#include <com/sun/star/drawing/HomogenMatrix3.hpp>
82
#include <com/sun/star/drawing/TextVerticalAdjust.hpp>
83
#include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
84
#include <com/sun/star/drawing/GraphicExportFilter.hpp>
85
#include <com/sun/star/drawing/XShapes.hpp>
86
#include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
87
#include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp>
88
#include <com/sun/star/drawing/EnhancedCustomShapeTextPathMode.hpp>
89
#include <com/sun/star/drawing/ConnectorType.hpp>
90
#include <com/sun/star/embed/XEmbeddedObject.hpp>
91
#include <com/sun/star/text/XText.hpp>
92
#include <com/sun/star/table/BorderLine2.hpp>
93
#include <com/sun/star/table/ShadowFormat.hpp>
94
#include <com/sun/star/chart2/XChartDocument.hpp>
95
#include <com/sun/star/chart2/XChartStyle.hpp>
96
#include <com/sun/star/chart2/XChartColorStyle.hpp>
97
#include <com/sun/star/style/ParagraphAdjust.hpp>
98
#include <com/sun/star/io/XOutputStream.hpp>
99
#include <com/sun/star/lang/Locale.hpp>
100
#include <com/sun/star/i18n/ScriptType.hpp>
101
#include <com/sun/star/text/WritingMode2.hpp>
102
103
#include <basegfx/point/b2dpoint.hxx>
104
#include <basegfx/polygon/b2dpolygon.hxx>
105
#include <basegfx/matrix/b2dhommatrix.hxx>
106
#include <com/sun/star/document/XActionLockable.hpp>
107
#include <com/sun/star/chart2/data/XDataReceiver.hpp>
108
#include <officecfg/Office/Common.hxx>
109
#include <svx/svdobj.hxx>
110
#include <svx/svdotable.hxx>
111
#include <svx/svdtrans.hxx>
112
#include <tools/stream.hxx>
113
#include <unotools/streamwrap.hxx>
114
#include <unotools/mediadescriptor.hxx>
115
#include <vcl/graph.hxx>
116
#include <vcl/graphicfilter.hxx>
117
#include <vcl/svapp.hxx>
118
#include <vcl/wmfexternal.hxx>
119
#include <sal/log.hxx>
120
#include <svx/sdtaitm.hxx>
121
#include <oox/drawingml/diagram/diagram.hxx>
122
#include <docmodel/theme/Theme.hxx>
123
#include <i18nlangtag/languagetag.hxx>
124
#include <i18nlangtag/mslangid.hxx>
125
126
using namespace ::oox::core;
127
using namespace ::com::sun::star;
128
using namespace ::com::sun::star::uno;
129
using namespace ::com::sun::star::beans;
130
using namespace ::com::sun::star::frame;
131
using namespace ::com::sun::star::text;
132
using namespace ::com::sun::star::drawing;
133
using namespace ::com::sun::star::style;
134
135
namespace oox::drawingml {
136
137
Shape::Shape()
138
28.4k
: mpLinePropertiesPtr( std::make_shared<LineProperties>() )
139
28.4k
, mpShapeRefLinePropPtr( std::make_shared<LineProperties>() )
140
28.4k
, mpFillPropertiesPtr( std::make_shared<FillProperties>() )
141
28.4k
, mpShapeRefFillPropPtr( std::make_shared<FillProperties>() )
142
28.4k
, mpGraphicPropertiesPtr( std::make_shared<GraphicProperties>() )
143
28.4k
, mpCustomShapePropertiesPtr( std::make_shared<CustomShapeProperties>() )
144
28.4k
, mp3DPropertiesPtr( std::make_shared<Shape3DProperties>() )
145
28.4k
, mpEffectPropertiesPtr( std::make_shared<EffectProperties>() )
146
28.4k
, mpShapeRefEffectPropPtr( std::make_shared<EffectProperties>() )
147
28.4k
, mpMasterTextListStyle( std::make_shared<TextListStyle>() )
148
28.4k
, mnSubType( 0 )
149
28.4k
, meFrameType( FRAMETYPE_GENERIC )
150
28.4k
, mnRotation( 0 )
151
28.4k
, mnDiagramRotation( 0 )
152
28.4k
, mbFlipH( false )
153
28.4k
, mbFlipV( false )
154
28.4k
, mbHidden( false )
155
28.4k
, mbHiddenMasterShape( false )
156
28.4k
, mbLocked( false )
157
28.4k
, mbWPGChild(false)
158
28.4k
, mbLockedCanvas( false )
159
28.4k
, mbWordprocessingCanvas(false)
160
28.4k
, mbWps( false )
161
28.4k
, mbTextBox( false )
162
28.4k
, mbHasLinkedTxbx( false )
163
28.4k
, mbHasCustomPrompt( false )
164
28.4k
, mpDiagramHelper( nullptr )
165
28.4k
{
166
28.4k
    setDefaults(/*bDefaultHeight*/true);
167
28.4k
}
168
169
170
Shape::Shape( const OUString& rServiceName, bool bDefaultHeight )
171
143k
: mpLinePropertiesPtr( std::make_shared<LineProperties>() )
172
143k
, mpShapeRefLinePropPtr( std::make_shared<LineProperties>() )
173
143k
, mpFillPropertiesPtr( std::make_shared<FillProperties>() )
174
143k
, mpShapeRefFillPropPtr( std::make_shared<FillProperties>() )
175
143k
, mpGraphicPropertiesPtr( std::make_shared<GraphicProperties>() )
176
143k
, mpCustomShapePropertiesPtr( std::make_shared<CustomShapeProperties>() )
177
143k
, mp3DPropertiesPtr( std::make_shared<Shape3DProperties>() )
178
143k
, mpEffectPropertiesPtr( std::make_shared<EffectProperties>() )
179
143k
, mpShapeRefEffectPropPtr( std::make_shared<EffectProperties>() )
180
143k
, mpMasterTextListStyle( std::make_shared<TextListStyle>() )
181
143k
, mnSubType( 0 )
182
143k
, meFrameType( FRAMETYPE_GENERIC )
183
143k
, mnRotation( 0 )
184
143k
, mnDiagramRotation( 0 )
185
143k
, mbFlipH( false )
186
143k
, mbFlipV( false )
187
143k
, mbHidden( false )
188
143k
, mbHiddenMasterShape( false )
189
143k
, mbLocked( false )
190
143k
, mbWPGChild(false)
191
143k
, mbLockedCanvas( false )
192
143k
, mbWordprocessingCanvas(false)
193
143k
, mbWps( false )
194
143k
, mbTextBox( false )
195
143k
, mbHasLinkedTxbx( false )
196
143k
, mbHasCustomPrompt( false )
197
143k
, mpDiagramHelper( nullptr )
198
143k
{
199
143k
    msServiceName = rServiceName;
200
143k
    setDefaults(bDefaultHeight);
201
143k
}
202
203
Shape::Shape( const ShapePtr& pSourceShape )
204
532
: mpTextBody(pSourceShape->mpTextBody)
205
532
, mpLinePropertiesPtr( pSourceShape->mpLinePropertiesPtr )
206
532
, mpShapeRefLinePropPtr( pSourceShape->mpShapeRefLinePropPtr )
207
532
, mpFillPropertiesPtr( pSourceShape->mpFillPropertiesPtr )
208
532
, mpShapeRefFillPropPtr( pSourceShape->mpShapeRefFillPropPtr )
209
532
, mpGraphicPropertiesPtr( pSourceShape->mpGraphicPropertiesPtr )
210
532
, mpCustomShapePropertiesPtr( pSourceShape->mpCustomShapePropertiesPtr )
211
532
, mpTablePropertiesPtr( pSourceShape->mpTablePropertiesPtr )
212
532
, mp3DPropertiesPtr( pSourceShape->mp3DPropertiesPtr )
213
532
, mpEffectPropertiesPtr (pSourceShape->mpEffectPropertiesPtr)
214
532
, mpShapeRefEffectPropPtr(pSourceShape->mpShapeRefEffectPropPtr)
215
532
, maShapeProperties( pSourceShape->maShapeProperties )
216
532
, mpMasterTextListStyle( pSourceShape->mpMasterTextListStyle )
217
532
, msServiceName( pSourceShape->msServiceName )
218
532
, msName( pSourceShape->msName )
219
532
, msInternalName( pSourceShape->msInternalName )
220
532
, msId( pSourceShape->msId )
221
532
, mnSubType( pSourceShape->mnSubType )
222
532
, moSubTypeIndex( pSourceShape->moSubTypeIndex )
223
532
, maShapeStyleRefs( pSourceShape->maShapeStyleRefs )
224
532
, maSize( pSourceShape->maSize )
225
532
, maPosition( pSourceShape->maPosition )
226
532
, meFrameType( pSourceShape->meFrameType )
227
532
, mnRotation( pSourceShape->mnRotation )
228
532
, mnDiagramRotation( pSourceShape->mnDiagramRotation )
229
532
, mbFlipH( pSourceShape->mbFlipH )
230
532
, mbFlipV( pSourceShape->mbFlipV )
231
532
, mbHidden( pSourceShape->mbHidden )
232
532
, mbHiddenMasterShape( pSourceShape->mbHiddenMasterShape )
233
532
, mbLocked( pSourceShape->mbLocked )
234
532
, mbWPGChild( pSourceShape->mbWPGChild )
235
532
, mbLockedCanvas( pSourceShape->mbLockedCanvas )
236
532
, mbWordprocessingCanvas(pSourceShape->mbWordprocessingCanvas)
237
532
, mbWps( pSourceShape->mbWps )
238
532
, mbTextBox( pSourceShape->mbTextBox )
239
532
, mbHasLinkedTxbx(false)
240
532
, mbHasCustomPrompt( pSourceShape->mbHasCustomPrompt )
241
532
, mnZOrder(pSourceShape->mnZOrder)
242
532
, mnZOrderOff(pSourceShape->mnZOrderOff)
243
532
, mnDataNodeType(pSourceShape->mnDataNodeType)
244
532
, mfAspectRatio(pSourceShape->mfAspectRatio)
245
532
, mpDiagramHelper( nullptr )
246
532
, msDiagramDataModelID(pSourceShape->msDiagramDataModelID)
247
532
{}
248
249
Shape::~Shape()
250
172k
{
251
    // DiagramHelper should not be set here anymore, see
252
    // propagateDiagramHelper below (maybe assert..?)
253
172k
    delete mpDiagramHelper;
254
172k
}
255
256
void Shape::prepareDiagramHelper(
257
    const std::shared_ptr< SmartArtDiagram >& rDiagramPtr,
258
    const std::shared_ptr<::oox::drawingml::Theme>& rTheme)
259
149
{
260
    // Prepare Diagram data collecting for this Shape
261
149
    if( nullptr == mpDiagramHelper && FRAMETYPE_DIAGRAM == meFrameType )
262
149
    {
263
149
        mpDiagramHelper = new DiagramHelper_oox(
264
149
            rDiagramPtr,
265
149
            rTheme);
266
149
    }
267
149
}
268
269
void Shape::propagateDiagramHelper()
270
303
{
271
    // Propagate collected Diagram data to data holder
272
303
    if (FRAMETYPE_DIAGRAM == meFrameType && nullptr != mpDiagramHelper)
273
149
    {
274
149
        if (mxShape)
275
149
        {
276
149
            mpDiagramHelper->doAnchor(mxShape);
277
149
            mpDiagramHelper = nullptr;
278
149
        }
279
149
    }
280
281
    // If propagation failed, delete/cleanup here. Since the DiagramHelper
282
    // holds a Diagram and that this Shape it is necessary - the destructor
283
    // will not be called and will be too late
284
303
    if (nullptr != mpDiagramHelper)
285
0
    {
286
0
        delete mpDiagramHelper;
287
0
        mpDiagramHelper = nullptr;
288
0
    }
289
303
}
290
291
void Shape::migrateDiagramHelperToNewShape(const ShapePtr& pTarget)
292
30
{
293
30
    if(!mpDiagramHelper)
294
0
    {
295
0
        return;
296
0
    }
297
298
30
    if(!pTarget)
299
0
    {
300
        // no migrate target, but cleanup helper
301
0
        delete mpDiagramHelper;
302
0
        mpDiagramHelper = nullptr;
303
0
        return;
304
0
    }
305
306
30
    if(pTarget->mpDiagramHelper)
307
0
    {
308
        // this should no happen, but if there is already a helper, clean it up
309
0
        delete pTarget->mpDiagramHelper;
310
0
        pTarget->mpDiagramHelper = nullptr;
311
0
    }
312
313
    // exchange and reset to nullptr
314
30
    pTarget->mpDiagramHelper = mpDiagramHelper;
315
30
    mpDiagramHelper = nullptr;
316
30
}
317
318
table::TablePropertiesPtr const & Shape::getTableProperties()
319
124
{
320
124
    if ( !mpTablePropertiesPtr )
321
124
        mpTablePropertiesPtr = std::make_shared<table::TableProperties>();
322
124
    return mpTablePropertiesPtr;
323
124
}
324
325
void Shape::setDefaults(bool bHeight)
326
172k
{
327
172k
    maDefaultShapeProperties.setProperty(PROP_TextAutoGrowHeight, false);
328
172k
    maDefaultShapeProperties.setProperty(PROP_TextWordWrap, true);
329
172k
    maDefaultShapeProperties.setProperty(PROP_TextLeftDistance, static_cast< sal_Int32 >( 250 ));
330
172k
    maDefaultShapeProperties.setProperty(PROP_TextUpperDistance, static_cast< sal_Int32 >( 125 ));
331
172k
    maDefaultShapeProperties.setProperty(PROP_TextRightDistance, static_cast< sal_Int32 >( 250 ));
332
172k
    maDefaultShapeProperties.setProperty(PROP_TextLowerDistance, static_cast< sal_Int32 >( 125 ));
333
172k
    if (bHeight)
334
172k
        maDefaultShapeProperties.setProperty(PROP_CharHeight, static_cast< float >( 18.0 ));
335
172k
    maDefaultShapeProperties.setProperty(PROP_TextVerticalAdjust, TextVerticalAdjust_TOP);
336
172k
    maDefaultShapeProperties.setProperty(PROP_ParaAdjust,
337
172k
                                         static_cast<sal_Int16>(ParagraphAdjust_LEFT));
338
172k
}
339
340
::oox::vml::OleObjectInfo& Shape::setOleObjectType()
341
0
{
342
0
    OSL_ENSURE( meFrameType == FRAMETYPE_GENERIC, "Shape::setOleObjectType - multiple frame types" );
343
0
    meFrameType = FRAMETYPE_OLEOBJECT;
344
0
    mxOleObjectInfo = std::make_shared<::oox::vml::OleObjectInfo>( true );
345
0
    return *mxOleObjectInfo;
346
0
}
347
348
ChartShapeInfo& Shape::setChartType( bool bEmbedShapes )
349
431
{
350
431
    OSL_ENSURE( meFrameType == FRAMETYPE_GENERIC, "Shape::setChartType - multiple frame types" );
351
431
    meFrameType = FRAMETYPE_CHART;
352
431
    if (mbWps)
353
0
        msServiceName = u"com.sun.star.drawing.temporaryForXMLImportOLE2Shape"_ustr;
354
431
    else
355
431
        msServiceName = u"com.sun.star.drawing.OLE2Shape"_ustr;
356
431
    mxChartShapeInfo = std::make_shared<ChartShapeInfo>( bEmbedShapes );
357
431
    return *mxChartShapeInfo;
358
431
}
359
360
void Shape::setDiagramType()
361
446
{
362
446
    OSL_ENSURE( meFrameType == FRAMETYPE_GENERIC, "Shape::setDiagramType - multiple frame types" );
363
446
    meFrameType = FRAMETYPE_DIAGRAM;
364
446
    msServiceName = u"com.sun.star.drawing.GroupShape"_ustr;
365
446
    mnSubType = 0;
366
446
}
367
368
void Shape::setTableType()
369
124
{
370
124
    OSL_ENSURE( meFrameType == FRAMETYPE_GENERIC, "Shape::setTableType - multiple frame types" );
371
124
    meFrameType = FRAMETYPE_TABLE;
372
124
    msServiceName = u"com.sun.star.drawing.TableShape"_ustr;
373
124
    mnSubType = 0;
374
124
}
375
376
const ShapeStyleRef* Shape::getShapeStyleRef( sal_Int32 nRefType ) const
377
408k
{
378
408k
    ShapeStyleRefMap::const_iterator aIt = maShapeStyleRefs.find( nRefType );
379
408k
    return (aIt == maShapeStyleRefs.end()) ? nullptr : &aIt->second;
380
408k
}
381
382
void Shape::addShape(
383
        ::oox::core::XmlFilterBase& rFilterBase,
384
        const Theme* pTheme,
385
        const Reference< XShapes >& rxShapes,
386
        const basegfx::B2DHomMatrix& aTransformation,
387
        const FillProperties& rShapeOrParentShapeFillProps,
388
        ShapeIdMap* pShapeMap,
389
        const oox::drawingml::ShapePtr& pParentGroupShape)
390
9.10k
{
391
9.10k
    SAL_INFO("oox.drawingml", "Shape::addShape: id='" << msId << "'");
392
393
9.10k
    try
394
9.10k
    {
395
9.10k
        OUString sServiceName( msServiceName );
396
9.10k
        if( !sServiceName.isEmpty() )
397
9.10k
        {
398
9.10k
            basegfx::B2DHomMatrix aMatrix( aTransformation );
399
9.10k
            Reference< XShape > xShape( createAndInsert( rFilterBase, sServiceName, pTheme, rxShapes, false, nullptr, aMatrix, rShapeOrParentShapeFillProps, pParentGroupShape) );
400
401
9.10k
            if( pShapeMap && !msId.isEmpty() )
402
26
            {
403
26
                (*pShapeMap)[ msId ] = shared_from_this();
404
26
            }
405
406
            // if this is a group shape, we have to add also each child shape
407
9.10k
            Reference< XShapes > xShapes( xShape, UNO_QUERY );
408
9.10k
            if ( xShapes.is() )
409
628
                addChildren( rFilterBase, *this, pTheme, xShapes, pShapeMap, aMatrix );
410
411
9.10k
            if (isInWordprocessingCanvas() && !isWPGChild())
412
0
            {
413
                // This is a drawing canvas. In case the canvas has no fill and no stroke, Word does
414
                // not render shadow or glow, even if it is set for the canvas. Thus we disable shadow
415
                // and glow in this case for the ersatz background shape of the drawing canvas.
416
0
                try
417
0
                {
418
0
                    oox::drawingml::ShapePtr pBgShape = getChildren().front();
419
0
                    const Reference<css::drawing::XShape>& xBgShape = pBgShape->getXShape();
420
0
                    Reference<XPropertySet> xBgProps(xBgShape, uno::UNO_QUERY);
421
0
                    drawing::FillStyle eFillStyle = drawing::FillStyle_NONE;
422
0
                    xBgProps->getPropertyValue(u"FillStyle"_ustr) >>= eFillStyle;
423
0
                    drawing::LineStyle eLineStyle = drawing::LineStyle_NONE;
424
0
                    xBgProps->getPropertyValue(u"LineStyle"_ustr) >>= eLineStyle;
425
0
                    if (eFillStyle == drawing::FillStyle_NONE
426
0
                        && eLineStyle == drawing::LineStyle_NONE)
427
0
                    {
428
0
                        xBgProps->setPropertyValue(UNO_NAME_SHADOW, uno::Any(false));
429
0
                        xBgProps->setPropertyValue(u"GlowEffectRadius"_ustr, uno::Any(sal_Int32(0)));
430
0
                    }
431
0
                }
432
0
                catch (const Exception&)
433
0
                {
434
0
                    TOOLS_WARN_EXCEPTION("oox.drawingml", "Shape::addShape mbWordprocessingCanvas");
435
0
                }
436
0
            }
437
438
9.10k
            if (isWPGChild() && xShape)
439
278
            {
440
                // This is a wps shape and it is the child of the WPG, now copy the
441
                // the text body properties to the xshape.
442
278
                Reference<XPropertySet> xChildWPSProperties(xShape, uno::UNO_QUERY);
443
444
278
                if (getTextBody() && xChildWPSProperties)
445
278
                {
446
278
                    xChildWPSProperties->setPropertyValue(
447
278
                        UNO_NAME_TEXT_VERTADJUST,
448
278
                        uno::Any(getTextBody()->getTextProperties().meVA));
449
450
278
                    xChildWPSProperties->setPropertyValue(
451
278
                        UNO_NAME_TEXT_LEFTDIST,
452
278
                        uno::Any(getTextBody()->getTextProperties().moInsets[0].has_value()
453
278
                                     ? *getTextBody()->getTextProperties().moInsets[0]
454
278
                                     : 0));
455
278
                    xChildWPSProperties->setPropertyValue(
456
278
                        UNO_NAME_TEXT_UPPERDIST,
457
278
                        uno::Any(getTextBody()->getTextProperties().moInsets[1].has_value()
458
278
                                     ? *getTextBody()->getTextProperties().moInsets[1]
459
278
                                     : 0));
460
278
                    xChildWPSProperties->setPropertyValue(
461
278
                        UNO_NAME_TEXT_RIGHTDIST,
462
278
                        uno::Any(getTextBody()->getTextProperties().moInsets[2].has_value()
463
278
                                     ? *getTextBody()->getTextProperties().moInsets[2]
464
278
                                     : 0));
465
278
                    xChildWPSProperties->setPropertyValue(
466
278
                        UNO_NAME_TEXT_LOWERDIST,
467
278
                        uno::Any(getTextBody()->getTextProperties().moInsets[3].has_value()
468
278
                                     ? *getTextBody()->getTextProperties().moInsets[3]
469
278
                                     : 0));
470
278
                }
471
472
                // tdf#145147 Set the Hyperlink property to the child wps shape.
473
278
                if (getShapeProperties().hasProperty(PROP_URL)) try
474
0
                {
475
0
                    uno::Any aAny = getShapeProperties().getProperty(PROP_URL);
476
0
                    OUString sUrl = aAny.get<OUString>();
477
0
                    if (!sUrl.isEmpty())
478
0
                        xChildWPSProperties->setPropertyValue(UNO_NAME_HYPERLINK, aAny);
479
0
                }
480
0
                catch (const Exception&)
481
0
                {
482
0
                }
483
278
            }
484
485
9.10k
            if( meFrameType == FRAMETYPE_DIAGRAM )
486
303
            {
487
                // set DiagramHelper at SdrObjGroup
488
303
                propagateDiagramHelper();
489
490
                // SmartArtToShapes == true means to get the Group while false did
491
                // convert that content to a GraphicObject containing a metafile,
492
                // and false is the default.
493
                // When we have AdvancedDiagramFeatures this destroys part of the model
494
                // that is in that group hosting the diagram and it's hierarchy.
495
                // At the same time there are UnitTests that use false, but still do want
496
                // to export the unchanged diagram, so it is not possible to just
497
                // delete the DiagramHelper_svx again, that would also make the
498
                // original data DomTrees vanish.
499
                // I think best solution is to not convert to graphic object at
500
                // all when AdvancedDiagramFeatures are active, that just makes
501
                // no longer sense when we want to be able to do more with the
502
                // diagram - and is also already deactivated for Draw/Ipress
503
303
                if (!SdrObject::useAdvancedDiagramFeatures())
504
303
                {
505
                    // Check if this is the PPTX import, so far converting SmartArt to a non-editable
506
                    // metafile is only implemented for DOCX.
507
303
                    bool bPowerPoint = dynamic_cast<oox::ppt::PowerPointImport*>(&rFilterBase) != nullptr;
508
509
303
                    if (!officecfg::Office::Common::Filter::Microsoft::Import::SmartArtToShapes::get() && !bPowerPoint)
510
303
                        convertSmartArtToMetafile( rFilterBase );
511
303
                }
512
303
            }
513
514
9.10k
            NamedShapePairs* pNamedShapePairs = rFilterBase.getDiagramFontHeights();
515
9.10k
            if (xShape.is() && pNamedShapePairs)
516
1.07k
            {
517
1.07k
                auto itPairs = pNamedShapePairs->find(getInternalName());
518
1.07k
                if (itPairs != pNamedShapePairs->end())
519
9
                {
520
9
                    auto it = itPairs->second.find(shared_from_this());
521
9
                    if (it != itPairs->second.end())
522
0
                    {
523
                        // Our drawingml::Shape is in the list of an internal name, remember the now
524
                        // inserted XShape.
525
0
                        it->second = std::move(xShape);
526
0
                    }
527
9
                }
528
1.07k
            }
529
9.10k
        }
530
9.10k
    }
531
9.10k
    catch( const Exception& )
532
9.10k
    {
533
0
        TOOLS_WARN_EXCEPTION( "oox.drawingml", "Shape::addShape" );
534
0
    }
535
9.10k
}
536
537
void Shape::setLockedCanvas(bool bLockedCanvas)
538
1.20k
{
539
1.20k
    mbLockedCanvas = bLockedCanvas;
540
1.20k
}
541
542
void Shape::setWordprocessingCanvas(bool bWordprocessingCanvas)
543
1.16k
{
544
1.16k
    mbWordprocessingCanvas = bWordprocessingCanvas;
545
1.16k
}
546
547
void Shape::setWPGChild(bool bWPG)
548
278
{
549
278
    mbWPGChild = bWPG;
550
278
}
551
552
void Shape::setWps(bool bWps)
553
22.8k
{
554
22.8k
    mbWps = bWps;
555
22.8k
}
556
557
void Shape::setTextBox(bool bTextBox)
558
324
{
559
324
    mbTextBox = bTextBox;
560
324
}
561
562
void Shape::applyShapeReference( const Shape& rReferencedShape, bool bUseText )
563
22.8k
{
564
22.8k
    SAL_INFO("oox.drawingml", "Shape::applyShapeReference: apply '" << rReferencedShape.msId << "' to '" << msId << "'");
565
566
22.8k
    if ( rReferencedShape.mpTextBody && bUseText )
567
22.4k
        mpTextBody = std::make_shared<TextBody>( *rReferencedShape.mpTextBody );
568
464
    else
569
464
        mpTextBody.reset();
570
22.8k
    maShapeProperties = rReferencedShape.maShapeProperties;
571
22.8k
    mpShapeRefLinePropPtr = std::make_shared<LineProperties>( rReferencedShape.getActualLineProperties(nullptr) );
572
22.8k
    mpShapeRefFillPropPtr = std::make_shared<FillProperties>( rReferencedShape.getActualFillProperties(nullptr, nullptr) );
573
22.8k
    mpCustomShapePropertiesPtr = std::make_shared<CustomShapeProperties>( *rReferencedShape.mpCustomShapePropertiesPtr );
574
22.8k
    mpTablePropertiesPtr = rReferencedShape.mpTablePropertiesPtr ? std::make_shared<table::TableProperties>( *rReferencedShape.mpTablePropertiesPtr ) : nullptr;
575
22.8k
    mpShapeRefEffectPropPtr = std::make_shared<EffectProperties>( rReferencedShape.getActualEffectProperties(nullptr) );
576
22.8k
    mpMasterTextListStyle = std::make_shared<TextListStyle>( *rReferencedShape.mpMasterTextListStyle );
577
22.8k
    setSize(rReferencedShape.maSize);
578
22.8k
    setPosition(rReferencedShape.maPosition);
579
22.8k
    setRotation(rReferencedShape.getRotation());
580
22.8k
    setFlipH(rReferencedShape.getFlipH());
581
22.8k
    setFlipV(rReferencedShape.getFlipV());
582
22.8k
    setHidden(rReferencedShape.getHidden());
583
22.8k
    setLocked(rReferencedShape.getLocked());
584
22.8k
}
585
586
namespace {
587
588
struct ActionLockGuard
589
{
590
    explicit ActionLockGuard(Reference<drawing::XShape> const& xShape)
591
64.0k
        : m_xLockable(xShape, UNO_QUERY)
592
64.0k
    {
593
64.0k
        if (m_xLockable.is()) {
594
64.0k
            m_xLockable->addActionLock();
595
64.0k
        }
596
64.0k
    }
597
    ~ActionLockGuard()
598
64.0k
    {
599
64.0k
        if (m_xLockable.is()) {
600
64.0k
            m_xLockable->removeActionLock();
601
64.0k
        }
602
64.0k
    }
603
private:
604
    Reference<document::XActionLockable> m_xLockable;
605
};
606
607
}
608
609
// for group shapes, the following method is also adding each child
610
void Shape::addChildren(
611
        XmlFilterBase& rFilterBase,
612
        Shape& rMaster,
613
        const Theme* pTheme,
614
        const Reference< XShapes >& rxShapes,
615
        ShapeIdMap* pShapeMap,
616
        const basegfx::B2DHomMatrix& aTransformation )
617
639
{
618
639
    for (auto const& child : rMaster.maChildren)
619
3.75k
    {
620
3.75k
        child->setMasterTextListStyle( mpMasterTextListStyle );
621
3.75k
        child->addShape( rFilterBase, pTheme, rxShapes, aTransformation, getFillProperties(), pShapeMap, rMaster.shared_from_this());
622
3.75k
    }
623
639
}
624
625
static SdrTextHorzAdjust lcl_convertAdjust( ParagraphAdjust eAdjust )
626
0
{
627
0
    if (eAdjust == ParagraphAdjust_LEFT)
628
0
        return SDRTEXTHORZADJUST_LEFT;
629
0
    else if (eAdjust == ParagraphAdjust_RIGHT)
630
0
        return SDRTEXTHORZADJUST_RIGHT;
631
0
    else if (eAdjust == ParagraphAdjust_CENTER)
632
0
        return SDRTEXTHORZADJUST_CENTER;
633
0
    return SDRTEXTHORZADJUST_LEFT;
634
0
}
635
636
static TextHorizontalAdjust lcl_convertTextAdjust(ParagraphAdjust eAdjust)
637
295
{
638
295
    if (eAdjust == ParagraphAdjust_LEFT)
639
176
        return drawing::TextHorizontalAdjust_LEFT;
640
119
    else if (eAdjust == ParagraphAdjust_RIGHT)
641
116
        return drawing::TextHorizontalAdjust_RIGHT;
642
3
    else
643
3
        return drawing::TextHorizontalAdjust_BLOCK;
644
295
}
645
646
// LO does not interpret properties in styles belonging to the text content of a FontWork shape,
647
// but only those in the shape style. This method copies properties from the text content styles to
648
// the shape style.
649
static void lcl_copyCharPropsToShape(const uno::Reference<drawing::XShape>& xShape,
650
                                     const TextBodyPtr& pTextBody,
651
                                     const ::oox::core::XmlFilterBase& rFilter)
652
0
{
653
0
    if (!xShape.is() || !pTextBody)
654
0
        return;
655
656
0
    Reference<XPropertySet> xSet(xShape, UNO_QUERY);
657
0
    if (!xSet.is())
658
0
        return;
659
660
    // Content stretches or scales to given width and height, thus disable autogrow.
661
0
    xSet->setPropertyValue(UNO_NAME_TEXT_AUTOGROWHEIGHT, uno::Any(false));
662
0
    xSet->setPropertyValue(UNO_NAME_TEXT_AUTOGROWWIDTH, uno::Any(false));
663
664
    // LibreOffice is not able (as of Nov 2022) to use different styles for the paragraphs or
665
    // characters in FontWork, since that was not allowed in old binary WordArt. We use the
666
    // properties of the first non empty paragraph for now.
667
0
    const TextParagraphVector& rParagraphs = pTextBody->getParagraphs();
668
0
    auto aParaIt = std::find_if_not(rParagraphs.cbegin(), rParagraphs.cend(),
669
0
                                    [](const std::shared_ptr<TextParagraph> pParagraph) {
670
0
                                        return pParagraph->getRuns().empty();
671
0
                                    });
672
0
    if (aParaIt != rParagraphs.cend())
673
0
    {
674
0
        const std::shared_ptr<TextParagraph>& pParagraph = *aParaIt;
675
0
        const TextRunVector& rRuns = pParagraph->getRuns();
676
0
        auto aRunIt = std::find_if_not(rRuns.cbegin(), rRuns.cend(),
677
0
                                       [](const std::shared_ptr<TextRun> pRun)
678
0
                                       {
679
0
                                           return pRun->getText().isEmpty()
680
0
                                                  || pRun->getText() == " "
681
0
                                                  || pRun->getText().toChar() == 0xA0; // NBSP
682
0
                                       });
683
0
        if (aRunIt != rRuns.cend())
684
0
        {
685
0
            const std::shared_ptr<TextRun>& pRun = *aRunIt;
686
0
            TextCharacterProperties& rCharProps = pRun->getTextCharacterProperties();
687
688
            // set language
689
0
            if (rCharProps.moLang.has_value() && !rCharProps.moLang.value().isEmpty())
690
0
            {
691
0
                LanguageTag aTag(rCharProps.moLang.value());
692
0
                const css::lang::Locale& aLocale(aTag.getLocale(false));
693
0
                switch (MsLangId::getScriptType(aTag.getLanguageType()))
694
0
                {
695
0
                    case css::i18n::ScriptType::LATIN:
696
0
                        xSet->setPropertyValue(u"CharLocale"_ustr, uno::Any(aLocale));
697
0
                        break;
698
0
                    case css::i18n::ScriptType::ASIAN:
699
0
                        xSet->setPropertyValue(u"CharLocaleAsian"_ustr, uno::Any(aLocale));
700
0
                        break;
701
0
                    case css::i18n::ScriptType::COMPLEX:
702
0
                        xSet->setPropertyValue(u"CharLocaleComplex"_ustr, uno::Any(aLocale));
703
0
                        break;
704
0
                    default:;
705
0
                }
706
0
            }
707
708
            // Font Weight, Posture, Height
709
0
            if (rCharProps.moBold.has_value() && rCharProps.moBold.value())
710
0
            {
711
0
                xSet->setPropertyValue(UNO_NAME_CHAR_WEIGHT, uno::Any(css::awt::FontWeight::BOLD));
712
0
            }
713
0
            if (rCharProps.moItalic.has_value() && rCharProps.moItalic.value())
714
0
            {
715
0
                xSet->setPropertyValue(UNO_NAME_CHAR_POSTURE,
716
0
                                       uno::Any(css::awt::FontSlant::FontSlant_ITALIC));
717
0
            }
718
0
            if (rCharProps.moHeight.has_value())
719
0
            {
720
0
                sal_Int32 nHeight = rCharProps.moHeight.value() / 100;
721
0
                xSet->setPropertyValue(UNO_NAME_CHAR_HEIGHT, uno::Any(nHeight));
722
0
            }
723
724
            // Put theme fonts into shape properties
725
0
            OUString sFontName;
726
0
            sal_Int16 nFontPitch = 0;
727
0
            sal_Int16 nFontFamily = 0;
728
0
            bool bRet(false);
729
0
            if (const Theme* pTheme = rFilter.getCurrentTheme())
730
0
            {
731
                // minor Latin
732
0
                if (const TextFont* pFont = pTheme->resolveFont(u"+mn-lt"))
733
0
                {
734
0
                    bRet = pFont->getFontData(sFontName, nFontPitch, nFontFamily, nullptr, rFilter);
735
0
                    if (bRet)
736
0
                    {
737
0
                        xSet->setPropertyValue(u"CharFontName"_ustr, uno::Any(sFontName));
738
0
                        xSet->setPropertyValue(u"CharFontPitch"_ustr, uno::Any(nFontPitch));
739
0
                        xSet->setPropertyValue(u"CharFontFamily"_ustr, uno::Any(nFontFamily));
740
0
                    }
741
0
                }
742
                // minor Asian
743
0
                if (const TextFont* pFont = pTheme->resolveFont(u"+mn-ea"))
744
0
                {
745
0
                    bRet = pFont->getFontData(sFontName, nFontPitch, nFontFamily, nullptr, rFilter);
746
0
                    if (bRet)
747
0
                    {
748
0
                        xSet->setPropertyValue(u"CharFontNameAsian"_ustr, uno::Any(sFontName));
749
0
                        xSet->setPropertyValue(u"CharFontPitchAsian"_ustr, uno::Any(nFontPitch));
750
0
                        xSet->setPropertyValue(u"CharFontFamilyAsian"_ustr, uno::Any(nFontFamily));
751
0
                    }
752
0
                }
753
                // minor Complex
754
0
                if (const TextFont* pFont = pTheme->resolveFont(u"+mn-cs"))
755
0
                {
756
0
                    bRet = pFont->getFontData(sFontName, nFontPitch, nFontFamily, nullptr, rFilter);
757
0
                    if (bRet)
758
0
                    {
759
0
                        xSet->setPropertyValue(u"CharFontNameComplex"_ustr, uno::Any(sFontName));
760
0
                        xSet->setPropertyValue(u"CharFontPitchComplex"_ustr, uno::Any(nFontPitch));
761
0
                        xSet->setPropertyValue(u"CharFontFamilyComplex"_ustr, uno::Any(nFontFamily));
762
0
                    }
763
0
                }
764
0
            }
765
766
            // Replace theme fonts with formatting at run if any. ToDo: Inspect paragraph too?
767
            // Latin
768
0
            bRet = rCharProps.maLatinFont.getFontData(sFontName, nFontPitch, nFontFamily, nullptr, rFilter);
769
0
            if (!bRet)
770
                // In case there is no direct font, try to look it up as a theme reference.
771
0
                bRet = rCharProps.maLatinThemeFont.getFontData(sFontName, nFontPitch, nFontFamily, nullptr,
772
0
                                                               rFilter);
773
774
0
            if (bRet)
775
0
            {
776
0
                xSet->setPropertyValue(u"CharFontName"_ustr, uno::Any(sFontName));
777
0
                xSet->setPropertyValue(u"CharFontPitch"_ustr, uno::Any(nFontPitch));
778
0
                xSet->setPropertyValue(u"CharFontFamily"_ustr, uno::Any(nFontFamily));
779
0
            }
780
            // Asian
781
0
            bRet = rCharProps.maAsianFont.getFontData(sFontName, nFontPitch, nFontFamily, nullptr, rFilter);
782
0
            if (!bRet)
783
                // In case there is no direct font, try to look it up as a theme reference.
784
0
                bRet = rCharProps.maAsianThemeFont.getFontData(sFontName, nFontPitch, nFontFamily, nullptr,
785
0
                                                               rFilter);
786
0
            if (bRet)
787
0
            {
788
0
                xSet->setPropertyValue(u"CharFontNameAsian"_ustr, uno::Any(sFontName));
789
0
                xSet->setPropertyValue(u"CharFontPitchAsian"_ustr, uno::Any(nFontPitch));
790
0
                xSet->setPropertyValue(u"CharFontFamilyAsian"_ustr, uno::Any(nFontFamily));
791
0
            }
792
            // Complex
793
0
            bRet
794
0
                = rCharProps.maComplexFont.getFontData(sFontName, nFontPitch, nFontFamily, nullptr, rFilter);
795
0
            if (!bRet)
796
                // In case there is no direct font, try to look it up as a theme reference.
797
0
                bRet = rCharProps.maComplexThemeFont.getFontData(sFontName, nFontPitch, nFontFamily, nullptr,
798
0
                                                                 rFilter);
799
0
            if (bRet)
800
0
            {
801
0
                xSet->setPropertyValue(u"CharFontNameComplex"_ustr, uno::Any(sFontName));
802
0
                xSet->setPropertyValue(u"CharFontPitchComplex"_ustr, uno::Any(nFontPitch));
803
0
                xSet->setPropertyValue(u"CharFontFamilyComplex"_ustr, uno::Any(nFontFamily));
804
0
            }
805
806
            // LO uses shape properties, MS Office character properties. Copy them from char to shape.
807
            // Outline
808
0
            if (rCharProps.moTextOutlineProperties.has_value())
809
0
            {
810
0
                oox::drawingml::ShapePropertyMap aStrokeShapeProps(rFilter.getModelObjectHelper());
811
0
                rCharProps.moTextOutlineProperties.value().pushToPropMap(
812
0
                    aStrokeShapeProps, rFilter.getGraphicHelper());
813
0
                for (const auto& rProp : aStrokeShapeProps.makePropertyValueSequence())
814
0
                {
815
0
                    xSet->setPropertyValue(rProp.Name, rProp.Value);
816
0
                }
817
0
            }
818
0
            else
819
0
            {
820
0
                xSet->setPropertyValue(UNO_NAME_LINESTYLE, uno::Any(drawing::LineStyle_NONE));
821
0
            }
822
823
            // Fill
824
            // ToDo: Replace flip and rotate constants in parameters with actual values.
825
            // tdf#155327 If color is not explicitly set, MS Office uses scheme color 'tx1'.
826
0
            oox::drawingml::ShapePropertyMap aFillShapeProps(rFilter.getModelObjectHelper());
827
0
            if (!rCharProps.maFillProperties.moFillType.has_value())
828
0
                rCharProps.maFillProperties.moFillType = XML_solidFill;
829
0
            if (!rCharProps.maFillProperties.maFillColor.isUsed())
830
0
                rCharProps.maFillProperties.maFillColor.setSchemeClr(XML_tx1);
831
0
            rCharProps.maFillProperties.pushToPropMap(aFillShapeProps, rFilter.getGraphicHelper(),
832
0
                                                      /*nShapeRotation*/ 0,
833
0
                                                      /*nPhClr*/ API_RGB_TRANSPARENT,
834
0
                                                      /*aShapeSize*/ css::awt::Size(0, 0),
835
0
                                                      /*nPhClrTheme*/ -1,
836
0
                                                      /*bFlipH*/ false, /*bFlipV*/ false,
837
0
                                                      /*bIsCustomShape*/ true);
838
0
            for (const auto& rProp : aFillShapeProps.makePropertyValueSequence())
839
0
            {
840
0
                xSet->setPropertyValue(rProp.Name, rProp.Value);
841
0
            }
842
843
            // ToDo: Import WordArt glow and simple shadow effects. They are available in LO.
844
0
        }
845
846
        // LO does not evaluate paragraph alignment in text path mode. Use text area anchor instead.
847
0
        {
848
0
            ParagraphAdjust eAdjust = ParagraphAdjust_LEFT;
849
0
            if (pParagraph->getProperties().getParaAdjust())
850
0
                eAdjust = *pParagraph->getProperties().getParaAdjust();
851
0
            xSet->setPropertyValue(u"ParaAdjust"_ustr, uno::Any(eAdjust));
852
0
            SdrObject* pShape = SdrObject::getSdrObjectFromXShape(xShape);
853
0
            assert(pShape);
854
0
            SdrTextHorzAdjust eHorzAdjust = lcl_convertAdjust(eAdjust);
855
0
            pShape->SetMergedItem(SdrTextHorzAdjustItem(eHorzAdjust));
856
0
        }
857
0
    }
858
859
    // Vertical adjustment is only meaningful for OOXML WordArt shapes of 'Follow Path' kinds. We set
860
    // it so, that text position is approximately same as in MS Office.
861
0
    const OUString sMSPresetType = pTextBody->getTextProperties().msPrst;
862
0
    const OUString sFontworkType = PresetGeometryTypeNames::GetFontworkType(sMSPresetType);
863
0
    SdrObject* pShape = SdrObject::getSdrObjectFromXShape(xShape);
864
0
    assert(pShape);
865
0
    if (sFontworkType == "fontwork-arch-up-curve" || sFontworkType == "fontwork-circle-curve")
866
0
        pShape->SetMergedItem(SdrTextVertAdjustItem(SdrTextVertAdjust::SDRTEXTVERTADJUST_BOTTOM));
867
0
    else if (sFontworkType == "fontwork-arch-down-curve")
868
0
        pShape->SetMergedItem(SdrTextVertAdjustItem(SdrTextVertAdjust::SDRTEXTVERTADJUST_TOP));
869
0
    else
870
0
        pShape->SetMergedItem(SdrTextVertAdjustItem(SdrTextVertAdjust::SDRTEXTVERTADJUST_CENTER));
871
0
}
872
873
// Some helper methods for createAndInsert
874
namespace
875
{
876
// mirrors aTransformation at its center axis
877
// only valid if neither rotation or shear included
878
void lcl_mirrorAtCenter(basegfx::B2DHomMatrix& aTransformation, bool bFlipH, bool bFlipV)
879
3.15k
{
880
3.15k
    if (!bFlipH && !bFlipV)
881
2.31k
        return;
882
844
    basegfx::B2DPoint aCenter(0.5, 0.5);
883
844
    aCenter *= aTransformation;
884
844
    aTransformation.translate(-aCenter);
885
844
    aTransformation.scale(bFlipH ? -1.0 : 1.0, bFlipV ? -1.0 : 1.0);
886
844
    aTransformation.translate(aCenter);
887
844
    return;
888
3.15k
}
889
890
// only valid if neither rotation or shear included
891
void lcl_doSpecialMSOWidthHeightToggle(basegfx::B2DHomMatrix& aTransformation)
892
0
{
893
    // The values are directly set at the matrix without any matrix multiplication.
894
    // That way it is valid for lines too. Those have zero width or height.
895
0
    const double fSx(aTransformation.get(0, 0));
896
0
    const double fSy(aTransformation.get(1, 1));
897
0
    const double fTx(aTransformation.get(0, 2));
898
0
    const double fTy(aTransformation.get(1, 2));
899
0
    aTransformation.set(0, 0, fSy);
900
0
    aTransformation.set(1, 1, fSx);
901
0
    aTransformation.set(0, 2, fTx + 0.5 * (fSx - fSy));
902
0
    aTransformation.set(1, 2, fTy + 0.5 * (fSy - fSx));
903
0
    return;
904
0
}
905
906
void lcl_RotateAtCenter(basegfx::B2DHomMatrix& aTransformation, sal_Int32 nMSORotationAngle)
907
2.09k
{
908
2.09k
    if (nMSORotationAngle == 0)
909
0
        return;
910
2.09k
    double fRad = basegfx::deg2rad<60000>(nMSORotationAngle);
911
2.09k
    basegfx::B2DPoint aCenter(0.5, 0.5);
912
2.09k
    aCenter *= aTransformation;
913
2.09k
    aTransformation.translate(-aCenter);
914
2.09k
    aTransformation.rotate(fRad);
915
2.09k
    aTransformation.translate(aCenter);
916
2.09k
    return;
917
2.09k
}
918
919
Degree100 lcl_MSORotateAngleToAPIAngle(const sal_Int32 nMSORotationAngle)
920
2.26k
{
921
    // Converts a shape rotation angle from MSO to angle for API property RotateAngle
922
    // from unit 1/60000 deg to unit 1/100 deg
923
2.26k
    Degree100 nAngle(nMSORotationAngle / 600);
924
    // API RotateAngle has opposite direction than nMSORotationAngle, thus 'minus'.
925
2.26k
    return NormAngle36000(-nAngle);
926
2.26k
}
927
928
void PushMasterTextListStyleToMasterShapeParagraphs(TextListStyle& rMasterTextListStyle, const uno::Reference<drawing::XShape>& xShape)
929
4.97k
{
930
4.97k
    uno::Reference<text::XTextRange> xShapeText(xShape, UNO_QUERY);
931
4.97k
    if (!xShapeText.is())
932
0
    {
933
0
        return;
934
0
    }
935
936
4.97k
    uno::Reference<container::XEnumerationAccess> xText(xShapeText->getText(), uno::UNO_QUERY);
937
4.97k
    if (!xText.is())
938
0
    {
939
0
        return;
940
0
    }
941
942
4.97k
    uno::Reference<container::XEnumeration> xParagraphs = xText->createEnumeration();
943
4.97k
    if (!xParagraphs.is())
944
0
    {
945
0
        return;
946
0
    }
947
948
39.4k
    while (xParagraphs->hasMoreElements())
949
34.4k
    {
950
34.4k
        uno::Reference<beans::XPropertySet> xParagraph(xParagraphs->nextElement(), uno::UNO_QUERY);
951
34.4k
        if (!xParagraph.is())
952
0
        {
953
0
            continue;
954
0
        }
955
956
34.4k
        uno::Reference<container::XIndexReplace> xNumberingRules;
957
34.4k
        if (!(xParagraph->getPropertyValue("NumberingRules") >>= xNumberingRules))
958
0
        {
959
0
            continue;
960
0
        }
961
962
34.4k
        rMasterTextListStyle.pushToNumberingRules(xNumberingRules, std::nullopt);
963
34.4k
        xParagraph->setPropertyValue("NumberingRules", uno::Any(xNumberingRules));
964
34.4k
    }
965
4.97k
}
966
}
967
968
Reference< XShape > const & Shape::createAndInsert(
969
        ::oox::core::XmlFilterBase& rFilterBase,
970
        const OUString& rServiceName,
971
        const Theme* pTheme,
972
        const css::uno::Reference< css::drawing::XShapes >& rxShapes,
973
        bool bClearText,
974
        const oox::drawingml::ShapePtr& pPlaceholder,
975
        basegfx::B2DHomMatrix& aParentTransformation,
976
        const FillProperties& rShapeOrParentShapeFillProps,
977
        const oox::drawingml::ShapePtr& pParentGroupShape)
978
64.0k
{
979
64.0k
    bool bIsEmbMedia = false;
980
64.0k
    SAL_INFO("oox.drawingml", "Shape::createAndInsert: id='" << msId << "' service='" << rServiceName << "'");
981
982
64.0k
    formulaimport::XmlStreamBuilder * pMathXml(nullptr);
983
64.0k
    if (mpTextBody)
984
49.2k
    {
985
49.2k
        for (auto const& it : mpTextBody->getParagraphs())
986
66.1k
        {
987
66.1k
            if (it->HasMathXml())
988
0
            {
989
0
                if (!mpTextBody->isEmpty() || pMathXml != nullptr)
990
0
                {
991
0
                    SAL_WARN("oox.drawingml", "losing a Math object...");
992
0
                }
993
0
                else
994
0
                {
995
0
                    pMathXml = &it->GetMathXml();
996
0
                }
997
0
            }
998
66.1k
        }
999
49.2k
    }
1000
1001
    // tdf#90403 PowerPoint ignores a:ext cx and cy values of p:xfrm, and uses real table width and height
1002
64.0k
    if ( mpTablePropertiesPtr && rServiceName == "com.sun.star.drawing.TableShape" )
1003
124
    {
1004
124
        maSize.Width = 0;
1005
124
        for (auto const& elem : mpTablePropertiesPtr->getTableGrid())
1006
576
        {
1007
576
            maSize.Width = o3tl::saturating_add(maSize.Width, static_cast<sal_Int32>(elem));
1008
576
        }
1009
124
        maSize.Height = 0;
1010
124
        for (auto const& elem : mpTablePropertiesPtr->getTableRows())
1011
597
        {
1012
            // WARN: If some rows can't fit the content, this is not the final height
1013
597
            maSize.Height = o3tl::saturating_add(maSize.Height, elem.getHeight());
1014
597
        }
1015
124
    }
1016
1017
64.0k
    awt::Rectangle aShapeRectHmm(
1018
64.0k
        o3tl::convert(maPosition.X, o3tl::Length::emu, o3tl::Length::mm100),
1019
64.0k
        o3tl::convert(maPosition.Y, o3tl::Length::emu, o3tl::Length::mm100),
1020
64.0k
        o3tl::convert(maSize.Width, o3tl::Length::emu, o3tl::Length::mm100),
1021
64.0k
        o3tl::convert(maSize.Height, o3tl::Length::emu, o3tl::Length::mm100));
1022
1023
64.0k
    OUString aServiceName;
1024
64.0k
    if (pMathXml)
1025
0
    {
1026
        // convert this shape to OLE
1027
0
        aServiceName = u"com.sun.star.drawing.OLE2Shape"_ustr;
1028
0
        msServiceName = aServiceName;
1029
0
        meFrameType = FRAMETYPE_GENERIC; // not OLEOBJECT, no stream in package
1030
0
        mnSubType = 0;
1031
0
    }
1032
64.0k
    else if (rServiceName == "com.sun.star.drawing.GraphicObjectShape" &&
1033
3.44k
        mpGraphicPropertiesPtr && !mpGraphicPropertiesPtr->m_sMediaPackageURL.isEmpty())
1034
0
    {
1035
0
        aServiceName = finalizeServiceName( rFilterBase, u"com.sun.star.presentation.MediaShape"_ustr, aShapeRectHmm );
1036
0
        bIsEmbMedia = true;
1037
0
    }
1038
64.0k
    else
1039
64.0k
    {
1040
64.0k
        aServiceName = finalizeServiceName( rFilterBase, rServiceName, aShapeRectHmm );
1041
64.0k
    }
1042
    // Use custom shape instead of GraphicObjectShape if the image is cropped to
1043
    // shape. Except rectangle, which does not require further cropping
1044
64.0k
    bool bIsCroppedGraphic = (aServiceName == "com.sun.star.drawing.GraphicObjectShape" &&
1045
3.44k
                              !mpCustomShapePropertiesPtr->representsDefaultShape());
1046
1047
64.0k
    bool bIsCustomShape = (aServiceName == "com.sun.star.drawing.CustomShape" || bIsCroppedGraphic);
1048
64.0k
    bool bIsConnectorShape = (aServiceName == "com.sun.star.drawing.ConnectorShape");
1049
1050
    // Look for 3D. Its z-rotation and extrusion color become shape properties. We consider a
1051
    // z-rotation of an image even we currently do not extrude an image to 3D-scene.
1052
64.0k
    bool bBlockExtrusion = !bIsCustomShape && mp3DPropertiesPtr->mnPreset.has_value();
1053
64.0k
    double fShapeRotateInclCamera = 0.0; // unit rad; same orientation as shape property RotateAngle
1054
64.0k
    Color aExtrusionColor;
1055
64.0k
    Scene3DHelper aScene3DHelper;
1056
64.0k
    bool bHas3DEffect = aScene3DHelper.setExtrusionProperties(
1057
64.0k
        mp3DPropertiesPtr, getRotation(), getCustomShapeProperties()->getExtrusionPropertyMap(),
1058
64.0k
        fShapeRotateInclCamera, aExtrusionColor, bBlockExtrusion);
1059
    // Currently the other places use unit 1/60000deg and MSO shape rotate orientation.
1060
64.0k
    sal_Int32 nShapeRotateInclCamera = -basegfx::rad2deg<60000>(fShapeRotateInclCamera);
1061
64.0k
    bool bIs3DGraphic = aServiceName == "com.sun.star.drawing.GraphicObjectShape" && bHas3DEffect;
1062
64.0k
    bIsCustomShape |= bIs3DGraphic;
1063
1064
    // The extrusion color does not belong to the extrusion properties but is secondary color in
1065
    // the style of the shape, FillColor2 in API. The case that no extrusion color was set is handled
1066
    // further down when FillProperties and LineProperties are handled.
1067
64.0k
    if (aExtrusionColor.isUsed())
1068
3
    {
1069
        // FillColor2 is not yet transformed to ComplexColor.
1070
3
        ::Color aColor = aExtrusionColor.getColor(rFilterBase.getGraphicHelper());
1071
3
        maShapeProperties.setProperty(PROP_FillColor2, aColor);
1072
3
    }
1073
1074
64.0k
    if (bHas3DEffect)
1075
3
    {
1076
3
        aScene3DHelper.setLightingProperties(mp3DPropertiesPtr, fShapeRotateInclCamera,
1077
3
                                             getCustomShapeProperties()->getExtrusionPropertyMap());
1078
3
        oox::Scene3DHelper::setMaterialProperties(
1079
3
            mp3DPropertiesPtr, getCustomShapeProperties()->getExtrusionPropertyMap());
1080
3
    }
1081
1082
64.0k
    if (bIsCroppedGraphic || bIs3DGraphic)
1083
0
    {
1084
0
        aServiceName = "com.sun.star.drawing.CustomShape";
1085
0
        mpGraphicPropertiesPtr->mbIsCustomShape = true;
1086
0
        mpGraphicPropertiesPtr->mbIsExtruded = bIs3DGraphic;
1087
0
    }
1088
64.0k
    bool bUseRotationTransform = !getWps() ||
1089
1.14k
            aServiceName == "com.sun.star.drawing.LineShape" ||
1090
1.00k
            aServiceName == "com.sun.star.drawing.GroupShape" ||
1091
869
            getFlipH() ||
1092
869
            getFlipV();
1093
1094
64.0k
    basegfx::B2DHomMatrix aTransformation; // will be cumulative transformation of this object
1095
1096
    // Special for SmartArt import. Rotate diagram's shape around object's center before sizing.
1097
64.0k
    if (bUseRotationTransform && getDiagramRotation() != 0)
1098
0
    {
1099
0
        aTransformation.translate(-0.5, -0.5);
1100
0
        aTransformation.rotate(basegfx::deg2rad<60000>(getDiagramRotation()));
1101
0
        aTransformation.translate(0.5, 0.5);
1102
0
    }
1103
1104
64.0k
    bool bLineShape = aServiceName == "com.sun.star.drawing.LineShape";
1105
64.0k
    bool bTopWriterLine = !pParentGroupShape && getWps() && bLineShape;
1106
    // Build object matrix from shape size and position; corresponds to MSO ext and off
1107
    // Only LineShape and ConnectorShape may have zero width or height.
1108
64.0k
    if (bLineShape || aServiceName == "com.sun.star.drawing.ConnectorShape")
1109
1.75k
    {
1110
        // For toplevel Writer lines, size is included in the point coordinates.
1111
1.75k
        if (!bTopWriterLine)
1112
1.75k
        {
1113
1.75k
            aTransformation.scale(maSize.Width, maSize.Height);
1114
1.75k
        }
1115
1.75k
    }
1116
62.3k
    else
1117
62.3k
    {
1118
62.3k
        aTransformation.scale(maSize.Width ? maSize.Width : 1.0,
1119
62.3k
                              maSize.Height ? maSize.Height : 1.0);
1120
62.3k
    }
1121
1122
    // Evaluate object flip. Other shapes than custom shapes have no attribute for flip but use
1123
    // negative scale. Flip in MSO is at object center.
1124
64.0k
    if (!bIsCustomShape && (getFlipH() || getFlipV()))
1125
844
        lcl_mirrorAtCenter(aTransformation, getFlipH(), getFlipV());
1126
1127
    // Evaluate parent flip.
1128
    // A CustomShape has mirror not as negative scale, but as attributes.
1129
64.0k
    basegfx::B2DVector aParentScale(1.0, 1.0);
1130
64.0k
    basegfx::B2DVector aParentTranslate(0.0, 0.0);
1131
64.0k
    double fParentRotate(0.0);
1132
64.0k
    double fParentShearX(0.0);
1133
64.0k
    if (pParentGroupShape)
1134
3.75k
    {
1135
3.75k
        aParentTransformation.decompose(aParentScale, aParentTranslate, fParentRotate, fParentShearX);
1136
3.75k
        if (bIsCustomShape)
1137
2.31k
        {
1138
2.31k
            lcl_mirrorAtCenter(aTransformation, aParentScale.getX() < 0, aParentScale.getY() < 0);
1139
2.31k
            if (aParentScale.getX() < 0)
1140
0
                setFlipH(!getFlipH());
1141
2.31k
            if (aParentScale.getY() < 0)
1142
0
                setFlipV(!getFlipV());
1143
2.31k
        }
1144
3.75k
    }
1145
1146
64.0k
    if (maPosition.X != 0 || maPosition.Y != 0)
1147
54.7k
    {
1148
        // if global position is used, add it to transformation
1149
54.7k
        if (getWps() && pParentGroupShape == nullptr)
1150
636
            aTransformation.translate(
1151
636
                o3tl::convert(maPosition.X, o3tl::Length::mm100, o3tl::Length::emu),
1152
636
                o3tl::convert(maPosition.Y, o3tl::Length::mm100, o3tl::Length::emu));
1153
54.1k
        else
1154
54.1k
            aTransformation.translate(maPosition.X, maPosition.Y);
1155
54.7k
    }
1156
1157
    // Apply further parent transformations. First scale object then rotate. Other way round would
1158
    // introduce shearing.
1159
1160
    // The attributes chExt and chOff of the group in oox file contain the values on which the size
1161
    // and position of the child is based on. If they differ from the actual size of the group as
1162
    // given in its ext and off attributes, the child has to be transformed according the new values.
1163
64.0k
    if (pParentGroupShape)
1164
3.75k
    {
1165
        // ToDo: A diagram in a group might need special handling because it cannot flip and only
1166
        // resize uniformly. But currently it is imported with zero size, see tdf#139575. That needs
1167
        // to be fixed beforehand.
1168
1169
        // Scaling is done from left/top edges of the group. So these need to become coordinate axes.
1170
3.75k
        aTransformation.translate(-pParentGroupShape->maChPosition.X,
1171
3.75k
                                  -pParentGroupShape->maChPosition.Y);
1172
1173
        // oox allows zero or missing attribute chExt. In that case the scaling factor is 1.
1174
        // Transform2DContext::onCreateContext has set maChSize to maSize for groups in oox file in
1175
        // such cases. For own made groups (e.g. diagrams) that is missing.
1176
        // The factors cumulate on the way through the parent groups, so we do not use maSize of the
1177
        // direct parent group but the cumulated value from aParentScale.
1178
3.75k
        double fFactorX = 1.0;
1179
3.75k
        double fFactorY = 1.0;
1180
3.75k
        if (pParentGroupShape->maChSize.Width != 0)
1181
2.56k
            fFactorX = aParentScale.getX() / pParentGroupShape->maChSize.Width;
1182
3.75k
        if (pParentGroupShape->maChSize.Height != 0)
1183
2.56k
            fFactorY = aParentScale.getY() / pParentGroupShape->maChSize.Height;
1184
3.75k
        if (fFactorX != 1 || fFactorY != 1)
1185
89
        {
1186
            // It depends on the object rotation angle whether scaling is applied to switched
1187
            // width and height. MSO acts strange in that case (as of May 2021).
1188
89
            const sal_Int32 nDeg(getRotation() / 60000);
1189
89
            const bool bNeedsMSOWidthHeightToggle
1190
89
                = (nDeg >= 45 && nDeg < 135) || (nDeg >= 225 && nDeg < 315);
1191
89
            if (bNeedsMSOWidthHeightToggle)
1192
0
                lcl_doSpecialMSOWidthHeightToggle(aTransformation);
1193
1194
89
            aTransformation.scale(fFactorX, fFactorY);
1195
1196
89
            if (bNeedsMSOWidthHeightToggle)
1197
0
            {
1198
0
                lcl_doSpecialMSOWidthHeightToggle(aTransformation);
1199
                // In case of flip the special case needs an additional 180deg rotation.
1200
0
                if ((aParentScale.getX() < 0) != (aParentScale.getY() < 0))
1201
0
                    lcl_RotateAtCenter(aTransformation, 10800000);
1202
0
            }
1203
89
        }
1204
3.75k
    }
1205
1206
    // Apply object rotation at current object center
1207
    // The flip contained in aParentScale will affect orientation of object rotation angle.
1208
64.0k
    sal_Int16 nOrientation = ((aParentScale.getX() < 0) != (aParentScale.getY() < 0)) ? -1 : 1;
1209
    // ToDo: Not sure about the restrictions given by bUseRotationTransform.
1210
64.0k
    if (bUseRotationTransform && nShapeRotateInclCamera != 0)
1211
2.09k
    {
1212
2.09k
        lcl_RotateAtCenter(aTransformation, nOrientation * nShapeRotateInclCamera);
1213
2.09k
    }
1214
1215
64.0k
    if (fParentRotate != 0.0)
1216
278
        aTransformation.rotate(fParentRotate);
1217
64.0k
    if (!aParentTranslate.equalZero())
1218
1.23k
        aTransformation.translate(aParentTranslate);
1219
1220
64.0k
    aParentTransformation = aTransformation;
1221
1222
64.0k
    constexpr double fEmuToMm100 = o3tl::convert(1.0, o3tl::Length::emu, o3tl::Length::mm100);
1223
64.0k
    if (!bTopWriterLine)
1224
64.0k
    {
1225
64.0k
        aTransformation.scale(fEmuToMm100, fEmuToMm100);
1226
64.0k
    }
1227
1228
    // OOXML flips shapes before rotating them, so the rotation needs to be inverted
1229
64.0k
    if (bIsCustomShape && getFlipH() != getFlipV())
1230
32
    {
1231
32
        basegfx::B2DVector aScale, aTranslate;
1232
32
        double fRotate, fShearX;
1233
32
        aTransformation.decompose(aScale, aTranslate, fRotate, fShearX);
1234
1235
32
        if(fRotate != 0)
1236
28
        {
1237
28
            basegfx::B2DPoint aCenter(0.5, 0.5);
1238
28
            aCenter *= aTransformation;
1239
28
            aTransformation.translate( -aCenter.getX(), -aCenter.getY() );
1240
28
            aTransformation.rotate( fRotate * -2.0 );
1241
28
            aTransformation.translate( aCenter.getX(), aCenter.getY() );
1242
28
        }
1243
32
    }
1244
1245
    // special for lineshape
1246
64.0k
    uno::Sequence< uno::Sequence< awt::Point > > aPolyPolySequence( 1 );
1247
64.0k
    if (bLineShape)
1248
179
    {
1249
179
        ::basegfx::B2DPolygon aPoly;
1250
179
        aPoly.insert( 0, ::basegfx::B2DPoint( 0, 0 ) );
1251
179
        if (bTopWriterLine)
1252
0
        {
1253
            // No transform of individual points, everything apart from size is part of the
1254
            // transform matrix.
1255
0
            sal_Int32 nMM100Width = o3tl::convert(maSize.Width, o3tl::Length::emu, o3tl::Length::mm100);
1256
0
            sal_Int32 nMM100Height = o3tl::convert(maSize.Height, o3tl::Length::emu, o3tl::Length::mm100);
1257
0
            aPoly.insert(1, ::basegfx::B2DPoint(nMM100Width, nMM100Height));
1258
0
        }
1259
179
        else
1260
179
        {
1261
179
            aPoly.insert( 1, ::basegfx::B2DPoint( maSize.Width ? 1 : 0, maSize.Height ? 1 : 0 ) );
1262
179
            aPoly.transform( aTransformation );
1263
179
        }
1264
1265
        // now creating the corresponding PolyPolygon
1266
179
        sal_Int32 i, nNumPoints = aPoly.count();
1267
179
        uno::Sequence< awt::Point > aPointSequence( nNumPoints );
1268
179
        awt::Point* pPoints = aPointSequence.getArray();
1269
537
        for( i = 0; i < nNumPoints; ++i )
1270
358
        {
1271
358
            basegfx::B2DPoint aPoint( aPoly.getB2DPoint( i ) );
1272
1273
            // Guard against zero width or height.
1274
358
            if (i)
1275
179
            {
1276
179
                const basegfx::B2DPoint& rPreviousPoint = aPoly.getB2DPoint(i - 1);
1277
179
                if (aPoint.getX() - rPreviousPoint.getX() == 0)
1278
0
                    aPoint.setX(aPoint.getX() + 1);
1279
179
                if (aPoint.getY() - rPreviousPoint.getY() == 0)
1280
21
                    aPoint.setY(aPoint.getY() + 1);
1281
179
            }
1282
1283
358
            pPoints[i] = awt::Point(static_cast<sal_Int32>(aPoint.getX()), static_cast<sal_Int32>(aPoint.getY()));
1284
358
        }
1285
179
        aPolyPolySequence.getArray()[ 0 ] = std::move(aPointSequence);
1286
1287
179
        if (!(bTopWriterLine && !maSize.Width))
1288
179
        {
1289
179
            maShapeProperties.setProperty(PROP_PolyPolygon, aPolyPolySequence);
1290
179
        }
1291
179
    }
1292
64.0k
    HomogenMatrix3 aMatrix;
1293
64.0k
    tools::Rectangle aOrigSize;
1294
64.0k
    if ( aServiceName == "com.sun.star.drawing.ConnectorShape" )
1295
1.57k
    {
1296
1.57k
        ::basegfx::B2DPolygon aPoly;
1297
1.57k
        aPoly.insert( 0, ::basegfx::B2DPoint( 0, 0 ) );
1298
1.57k
        aPoly.insert( 1, ::basegfx::B2DPoint( maSize.Width ? 1 : 0, maSize.Height ? 1 : 0 ) );
1299
1.57k
        aPoly.transform( aTransformation );
1300
1301
1.57k
        basegfx::B2DPoint aStartPosition( aPoly.getB2DPoint( 0 ) );
1302
1.57k
        basegfx::B2DPoint aEndPosition( aPoly.getB2DPoint( 1 ) );
1303
1.57k
        awt::Point aAWTStartPosition( static_cast< sal_Int32 >( aStartPosition.getX() ), static_cast< sal_Int32 >( aStartPosition.getY() ) );
1304
1.57k
        awt::Point aAWTEndPosition( static_cast< sal_Int32 >( aEndPosition.getX() ), static_cast< sal_Int32 >( aEndPosition.getY() ) );
1305
1306
1.57k
        maShapeProperties.setProperty(PROP_StartPosition, aAWTStartPosition);
1307
1.57k
        maShapeProperties.setProperty(PROP_EndPosition, aAWTEndPosition);
1308
1.57k
    }
1309
62.5k
    else if (!bLineShape || bTopWriterLine)
1310
62.3k
    {
1311
        // now set transformation for this object
1312
1313
62.3k
        aMatrix.Line1.Column1 = aTransformation.get(0,0);
1314
62.3k
        aMatrix.Line1.Column2 = aTransformation.get(0,1);
1315
62.3k
        aMatrix.Line1.Column3 = aTransformation.get(0,2);
1316
1317
62.3k
        aMatrix.Line2.Column1 = aTransformation.get(1,0);
1318
62.3k
        aMatrix.Line2.Column2 = aTransformation.get(1,1);
1319
62.3k
        aMatrix.Line2.Column3 = aTransformation.get(1,2);
1320
1321
62.3k
        aMatrix.Line3.Column1 = 0;
1322
62.3k
        aMatrix.Line3.Column2 = 0;
1323
62.3k
        aMatrix.Line3.Column3 = 1;
1324
1325
62.3k
        if (!(bTopWriterLine && !maSize.Width))
1326
62.3k
        {
1327
62.3k
            maShapeProperties.setProperty(PROP_Transformation, aMatrix);
1328
62.3k
        }
1329
62.3k
    }
1330
1331
64.0k
    Reference< lang::XMultiServiceFactory > xServiceFact( rFilterBase.getModel(), UNO_QUERY_THROW );
1332
64.0k
    if ( !mxShape.is() )
1333
64.0k
    {
1334
64.0k
        mxShape.set( xServiceFact->createInstance( aServiceName ), UNO_QUERY_THROW );
1335
64.0k
    }
1336
1337
64.0k
    Reference< XPropertySet > xSet( mxShape, UNO_QUERY );
1338
64.0k
    bool bPlaceholderWithCustomPrompt = pPlaceholder && pPlaceholder->getCustomPrompt();
1339
64.0k
    if (xSet.is())
1340
64.0k
    {
1341
64.0k
        if (bTopWriterLine && !maSize.Width)
1342
0
        {
1343
            // Entirely vertical line, set the points and the transform separately to match the ODF
1344
            // import.
1345
0
            xSet->setPropertyValue(u"PolyPolygon"_ustr, Any(aPolyPolySequence));
1346
0
            xSet->setPropertyValue(u"Transformation"_ustr, Any(aMatrix));
1347
0
        }
1348
1349
64.0k
        if( !msName.isEmpty() )
1350
62.0k
        {
1351
62.0k
            Reference< container::XNamed > xNamed( mxShape, UNO_QUERY );
1352
62.0k
            if( xNamed.is() )
1353
62.0k
                xNamed->setName( msName );
1354
62.0k
        }
1355
64.0k
        if( !msDescription.isEmpty() )
1356
1.50k
        {
1357
1.50k
            xSet->setPropertyValue( u"Description"_ustr, Any( msDescription ) );
1358
1.50k
        }
1359
64.0k
        if (m_isDecorative)
1360
0
        {
1361
0
            xSet->setPropertyValue(u"Decorative"_ustr, Any(m_isDecorative));
1362
0
        }
1363
64.0k
        if (!msMacro.isEmpty())
1364
0
        {
1365
0
            putPropertyToGrabBag(u"mso-sp-macro"_ustr, Any(msMacro));
1366
0
        }
1367
64.0k
        if (!msMacroExtUrl.isEmpty())
1368
0
        {
1369
0
            putPropertyToGrabBag(u"mso-sp-macro-url"_ustr, Any(msMacroExtUrl));
1370
0
        }
1371
64.0k
        if (!msTextLink.isEmpty())
1372
0
        {
1373
0
            putPropertyToGrabBag(u"mso-sp-textlink"_ustr, Any(msTextLink));
1374
0
        }
1375
64.0k
        if (!mbFLocksText) // set only if "false", otherwise it will use "true" by default
1376
5
        {
1377
5
            putPropertyToGrabBag(u"mso-sp-fLocksText"_ustr, Any(mbFLocksText));
1378
5
        }
1379
64.0k
        if (mbFPublished)
1380
0
        {
1381
0
            putPropertyToGrabBag(u"mso-sp-fPublished"_ustr, Any(mbFPublished));
1382
0
        }
1383
64.0k
        if (!msTitle.isEmpty())
1384
1
        {
1385
1
            xSet->setPropertyValue(u"Title"_ustr, Any(msTitle));
1386
1
        }
1387
1388
        // get tooltip attribute of <hlinkClick>
1389
64.0k
        OUString sTooltip;
1390
64.0k
        getShapeProperties().getProperty(PROP_Representation) >>= sTooltip;
1391
64.0k
        if (!sTooltip.isEmpty())
1392
2
            putPropertyToGrabBag(u"mso-hlinkClick-tooltip"_ustr, Any(sTooltip));
1393
1394
        // Placeholder uses the height set on the slide instead of the height from the master slide,
1395
        // if it has the "TextAutoGrowHeight" property
1396
64.0k
        if (getTextBody() && mxShape->getShapeType().startsWith("com.sun.star.presentation."))
1397
38.7k
        {
1398
38.7k
            bool bAutoGrowHeight = getTextBody()
1399
38.7k
                                       ->getTextProperties()
1400
38.7k
                                       .maPropertyMap.getProperty(PROP_TextAutoGrowHeight)
1401
38.7k
                                       .get<bool>();
1402
38.7k
            if (bAutoGrowHeight)
1403
0
            {
1404
0
                ppt::PowerPointImport* pPPT = dynamic_cast<ppt::PowerPointImport*>(&rFilterBase);
1405
0
                if (!pPPT->getActualSlidePersist()->isMasterPage())
1406
0
                {
1407
0
                    sal_Int32 nUpper = 0;
1408
0
                    sal_Int32 nLower = 0;
1409
0
                    sal_Int32 nHeight = maSize.Height / 360;
1410
0
                    if (getTextBody()->getTextProperties().moInsets[1].has_value()
1411
0
                        && getTextBody()->getTextProperties().moInsets[3].has_value())
1412
0
                    {
1413
0
                        nUpper = *getTextBody()->getTextProperties().moInsets[1];
1414
0
                        nLower = *getTextBody()->getTextProperties().moInsets[3];
1415
0
                    }
1416
0
                    else
1417
0
                    {
1418
0
                        maDefaultShapeProperties.getProperty(PROP_TextUpperDistance) >>= nUpper;
1419
0
                        maDefaultShapeProperties.getProperty(PROP_TextLowerDistance) >>= nLower;
1420
0
                    }
1421
0
                    nHeight -= (nUpper + nLower);
1422
0
                    mxShape->setSize(awt::Size(0, nHeight));
1423
0
                }
1424
0
            }
1425
38.7k
            else // the placeholder uses the height set on the master slide
1426
38.7k
                mxShape->setSize(awt::Size(0, 0));
1427
38.7k
        }
1428
1429
64.0k
        if (aServiceName != "com.sun.star.text.TextFrame")
1430
64.0k
            rxShapes->add( mxShape );
1431
1432
64.0k
        if (getHidden() || getHiddenMasterShape())
1433
1.08k
        {
1434
1.08k
            SAL_INFO("oox.drawingml", "Shape::createAndInsert: invisible shape with id='" << msId << "'");
1435
1.08k
            xSet->setPropertyValue( u"Visible"_ustr, Any( false ) );
1436
            // In Excel hidden means not printed, let's use visibility for now until that's handled separately
1437
1.08k
            xSet->setPropertyValue( u"Printable"_ustr, Any( false ) );
1438
1.08k
        }
1439
1440
64.0k
        if (getLocked())
1441
0
        {
1442
0
            xSet->setPropertyValue(u"MoveProtect"_ustr, Any(true));
1443
0
            xSet->setPropertyValue(u"SizeProtect"_ustr, Any(true));
1444
0
        }
1445
1446
64.0k
        ActionLockGuard const alg(mxShape);
1447
1448
64.0k
        if (!getDiagramDataModelID().isEmpty())
1449
929
        {
1450
929
            SdrObject* pSdrObject(SdrObject::getSdrObjectFromXShape(mxShape));
1451
1452
929
            if (nullptr != pSdrObject)
1453
929
            {
1454
                // I checked if pSdrObject has a DiagramHelper here once, but this is
1455
                // highly dependent on when propagateDiagramHelper() will be called
1456
                // and not needed since when a DiagramDataModelID is set locally
1457
                // is sufficient to know that we are in a Diagram context.
1458
929
                pSdrObject->setDiagramDataModelID(getDiagramDataModelID());
1459
929
            }
1460
929
        }
1461
1462
        // sj: removing default text of placeholder objects such as SlideNumberShape or HeaderShape
1463
64.0k
        if ( bClearText )
1464
14.0k
        {
1465
14.0k
            uno::Reference< text::XText > xText( mxShape, uno::UNO_QUERY );
1466
14.0k
            if ( xText.is() )
1467
14.0k
            {
1468
14.0k
                xText->setString( u""_ustr );
1469
14.0k
            }
1470
14.0k
        }
1471
1472
64.0k
        if (pMathXml)
1473
0
        {
1474
            // the "EmbeddedObject" property is read-only, so we have to create
1475
            // the shape first, and it can be read only after the shape is
1476
            // inserted into the document, so delay the actual import until here
1477
0
            SvGlobalName name(SO3_SM_CLASSID);
1478
0
            xSet->setPropertyValue(u"CLSID"_ustr, uno::Any(name.GetHexName()));
1479
0
            uno::Reference<embed::XEmbeddedObject> const xObj(
1480
0
                xSet->getPropertyValue(u"EmbeddedObject"_ustr), uno::UNO_QUERY);
1481
0
            if (xObj.is())
1482
0
            {
1483
0
                uno::Reference<uno::XInterface> const xMathModel(xObj->getComponent());
1484
0
                oox::FormulaImExportBase *const pMagic(
1485
0
                        dynamic_cast<oox::FormulaImExportBase*>(xMathModel.get()));
1486
0
                assert(pMagic);
1487
0
                pMagic->readFormulaOoxml(*pMathXml);
1488
0
            }
1489
0
        }
1490
1491
64.0k
        const GraphicHelper& rGraphicHelper = rFilterBase.getGraphicHelper();
1492
1493
64.0k
        ::Color nLinePhClr(ColorTransparency, 0xffffffff);
1494
64.0k
        ::Color nFillPhClr(ColorTransparency, 0xffffffff);
1495
64.0k
        sal_Int16 nFillPhClrTheme = -1;
1496
64.0k
        sal_Int16 nLinePhClrTheme = -1;
1497
        // TODO: use ph color when applying effect properties
1498
        //sal_Int32 nEffectPhClr = -1;
1499
1500
        // dmapper needs the original rotation angle for calculating square wrap. This angle is not
1501
        // available as property there, so store it in InteropGrabBag.
1502
64.0k
        putPropertyToGrabBag(u"mso-rotation-angle"_ustr, Any(getRotation()));
1503
1504
64.0k
        if( pTheme )
1505
61.5k
        {
1506
61.5k
            if( const ShapeStyleRef* pLineRef = getShapeStyleRef( XML_lnRef ) )
1507
3.16k
            {
1508
3.16k
                LineProperties aLineProperties;
1509
3.16k
                aLineProperties.maLineFill.moFillType = XML_noFill;
1510
3.16k
                if( const LineProperties* pLineProps = pTheme->getLineStyle( pLineRef->mnThemedIdx ) )
1511
954
                    aLineProperties.assignUsed( *pLineProps );
1512
3.16k
                nLinePhClr = pLineRef->maPhClr.getColor( rGraphicHelper );
1513
3.16k
                nLinePhClrTheme = pLineRef->maPhClr.getSchemeColorIndex();
1514
1515
                // Store style-related properties to InteropGrabBag to be able to export them back
1516
3.16k
                uno::Sequence<beans::PropertyValue> aProperties = comphelper::InitPropertySequence(
1517
3.16k
                {
1518
3.16k
                    {"SchemeClr", uno::Any(pLineRef->maPhClr.getSchemeColorName())},
1519
3.16k
                    {"Idx", uno::Any(pLineRef->mnThemedIdx)},
1520
3.16k
                    {"Color", uno::Any(nLinePhClr)},
1521
3.16k
                    {"LineStyle", uno::Any(aLineProperties.getLineStyle())},
1522
3.16k
                    {"LineCap", uno::Any(aLineProperties.getLineCap())},
1523
3.16k
                    {"LineJoint", uno::Any(aLineProperties.getLineJoint())},
1524
3.16k
                    {"LineWidth", uno::Any(aLineProperties.getLineWidth())},
1525
3.16k
                    {"Transformations", uno::Any(pLineRef->maPhClr.getTransformations())}
1526
3.16k
                });
1527
3.16k
                putPropertyToGrabBag( u"StyleLnRef"_ustr, Any( aProperties ) );
1528
3.16k
            }
1529
61.5k
            if( const ShapeStyleRef* pFillRef = getShapeStyleRef( XML_fillRef ) )
1530
3.16k
            {
1531
3.16k
                if (!getFillProperties().moUseBgFill.value_or(false))
1532
3.16k
                {
1533
3.16k
                    nFillPhClr = pFillRef->maPhClr.getColor(rGraphicHelper);
1534
3.16k
                    nFillPhClrTheme = pFillRef->maPhClr.getSchemeColorIndex();
1535
3.16k
                }
1536
1537
3.16k
                OUString sColorScheme = pFillRef->maPhClr.getSchemeColorName();
1538
3.16k
                if( !sColorScheme.isEmpty() )
1539
1.37k
                {
1540
1.37k
                    uno::Sequence<beans::PropertyValue> aProperties = comphelper::InitPropertySequence(
1541
1.37k
                    {
1542
1.37k
                        {"SchemeClr", uno::Any(sColorScheme)},
1543
1.37k
                        {"Idx", uno::Any(pFillRef->mnThemedIdx)},
1544
1.37k
                        {"Color", uno::Any(nFillPhClr)},
1545
1.37k
                        {"Transformations", uno::Any(pFillRef->maPhClr.getTransformations())}
1546
1.37k
                    });
1547
1548
1.37k
                    putPropertyToGrabBag( u"StyleFillRef"_ustr, Any( aProperties ) );
1549
1.37k
                }
1550
3.16k
            }
1551
61.5k
            if( const ShapeStyleRef* pEffectRef = getShapeStyleRef( XML_effectRef ) )
1552
3.16k
            {
1553
                // TODO: use ph color when applying effect properties
1554
                // nEffectPhClr = pEffectRef->maPhClr.getColor( rGraphicHelper );
1555
1556
                // Store style-related properties to InteropGrabBag to be able to export them back
1557
3.16k
                uno::Sequence<beans::PropertyValue> aProperties = comphelper::InitPropertySequence(
1558
3.16k
                {
1559
3.16k
                    {"SchemeClr", uno::Any(pEffectRef->maPhClr.getSchemeColorName())},
1560
3.16k
                    {"Idx", uno::Any(pEffectRef->mnThemedIdx)},
1561
3.16k
                    {"Transformations", uno::Any(pEffectRef->maPhClr.getTransformations())}
1562
3.16k
                });
1563
3.16k
                putPropertyToGrabBag( u"StyleEffectRef"_ustr, Any( aProperties ) );
1564
3.16k
            }
1565
61.5k
        }
1566
64.0k
        ShapePropertyMap aShapeProps( rFilterBase.getModelObjectHelper() );
1567
1568
        // add properties from textbody to shape properties
1569
64.0k
        if( mpTextBody )
1570
49.2k
        {
1571
            // tdf#67347: In case of Stacked, PP calculates in the vertical direction with the
1572
            // horizontal alignment.
1573
            // In LO, we simulate it by setting TextVerticalAdjust based on the ParagraphAdjust
1574
            // of the 1. paragraph
1575
            // It is not perfect, because we have 1 TextVerticalAdjust / 1 shape, and it
1576
            // does not support justified, while we can have many ParagraphAdjust / 1 shape
1577
            // (if the shape have more paragraphs)
1578
49.2k
            if (mpTextBody->getTextProperties().maPropertyMap.hasProperty(PROP_WritingMode)
1579
16.4k
                && mpTextBody->getTextProperties().maPropertyMap.getProperty(PROP_WritingMode)
1580
16.4k
                       == uno::Any(text::WritingMode2::STACKED)
1581
0
                && mpTextBody->getParagraphs().size() > 0
1582
0
                && aServiceName != "com.sun.star.drawing.GroupShape")
1583
0
            {
1584
0
                std::optional<css::style::ParagraphAdjust>& oParaAdjust
1585
0
                    = mpTextBody->getParagraphs()[0]->getProperties().getParaAdjust();
1586
1587
0
                if (oParaAdjust)
1588
0
                {
1589
0
                    switch (*oParaAdjust)
1590
0
                    {
1591
0
                        case ParagraphAdjust::ParagraphAdjust_LEFT:
1592
0
                            mpTextBody->getTextProperties().meVA
1593
0
                                = TextVerticalAdjust::TextVerticalAdjust_TOP;
1594
0
                            break;
1595
0
                        case ParagraphAdjust::ParagraphAdjust_CENTER:
1596
0
                            mpTextBody->getTextProperties().meVA
1597
0
                                = TextVerticalAdjust::TextVerticalAdjust_CENTER;
1598
0
                            break;
1599
0
                        case ParagraphAdjust::ParagraphAdjust_RIGHT:
1600
0
                            mpTextBody->getTextProperties().meVA
1601
0
                                = TextVerticalAdjust::TextVerticalAdjust_BOTTOM;
1602
0
                            break;
1603
0
                        default:
1604
0
                            break;
1605
0
                    }
1606
0
                    mpTextBody->getTextProperties().maPropertyMap.setProperty(
1607
0
                        PROP_TextVerticalAdjust, mpTextBody->getTextProperties().meVA);
1608
0
                }
1609
0
            }
1610
1611
            // tdf#162571: In case of shapes with TextAutoGrowHeight, PP calculates/grow the
1612
            // shapes size in edit mode (typing) based on the text horizontal alignment.
1613
            // In LO, we simulate it by setting TextHorizontalAdjust based on the ParagraphAdjust
1614
            // of the 1. paragraph
1615
            // It is not perfect, because we have 1 TextHorizontalAdjust / 1 shape,
1616
            // while we can have many ParagraphAdjust / 1 shape
1617
49.2k
            if (!mpTextBody->getTextProperties().maPropertyMap.hasProperty(PROP_WritingMode)
1618
32.7k
                && mpTextBody->getParagraphs().size() > 0)
1619
32.5k
            {
1620
32.5k
                std::optional<css::style::ParagraphAdjust>& oParaAdjust
1621
32.5k
                    = mpTextBody->getParagraphs()[0]->getProperties().getParaAdjust();
1622
1623
32.5k
                bool bAutoGrowHeight = getTextBody()
1624
32.5k
                    ->getTextProperties()
1625
32.5k
                    .maPropertyMap.getProperty(PROP_TextAutoGrowHeight)
1626
32.5k
                    .get<bool>();
1627
1628
32.5k
                bool bWrap = getTextBody()
1629
32.5k
                    ->getTextProperties()
1630
32.5k
                    .maPropertyMap.getProperty(PROP_TextWordWrap)
1631
32.5k
                    .get<bool>();
1632
1633
32.5k
                if (bAutoGrowHeight && !bWrap && nShapeRotateInclCamera == 0)
1634
295
                {
1635
295
                    mpTextBody->getTextProperties().maPropertyMap.setProperty(
1636
295
                        PROP_TextHorizontalAdjust, lcl_convertTextAdjust(
1637
295
                            oParaAdjust ? *oParaAdjust : ParagraphAdjust_LEFT));
1638
295
                }
1639
32.5k
            }
1640
1641
49.2k
            mpTextBody->getTextProperties().pushTextDistances(Size(aShapeRectHmm.Width, aShapeRectHmm.Height));
1642
49.2k
            aShapeProps.assignUsed( mpTextBody->getTextProperties().maPropertyMap );
1643
            // Push char properties as well - specifically useful when this is a placeholder
1644
49.2k
            if( mpMasterTextListStyle &&  mpMasterTextListStyle->getListStyle()[0].getTextCharacterProperties().moHeight.has_value() )
1645
23.1k
                aShapeProps.setProperty(PROP_CharHeight, GetFontHeight( mpMasterTextListStyle->getListStyle()[0].getTextCharacterProperties().moHeight.value() ));
1646
49.2k
        }
1647
1648
64.0k
        Sequence<PropertyValue> aCamera3DEffects = get3DProperties().getCameraAttributes();
1649
64.0k
        Sequence<PropertyValue> aLightRig3DEffects = get3DProperties().getLightRigAttributes();
1650
64.0k
        Sequence<PropertyValue> aShape3DEffects
1651
64.0k
            = get3DProperties().getShape3DAttributes(rGraphicHelper, nFillPhClr);
1652
64.0k
        bool bHas3DProps = aCamera3DEffects.hasElements() || aLightRig3DEffects.hasElements()
1653
64.0k
                           || aShape3DEffects.hasElements();
1654
64.0k
        if (bHas3DProps && getEffectProperties().maSoftEdge.moRad.has_value())
1655
0
        {
1656
            // 3D properties override softeEdge
1657
0
            getEffectProperties().maSoftEdge.moRad.reset();
1658
0
        }
1659
1660
        // applying properties
1661
64.0k
        aShapeProps.assignUsed( getShapeProperties() );
1662
64.0k
        aShapeProps.assignUsed( maDefaultShapeProperties );
1663
64.0k
        if(nShapeRotateInclCamera != 0 && bIsCustomShape)
1664
2.06k
            aShapeProps.setProperty(PROP_RotateAngle,
1665
2.06k
                                    sal_Int32(lcl_MSORotateAngleToAPIAngle(nShapeRotateInclCamera)));
1666
64.0k
        if( bIsEmbMedia ||
1667
64.0k
            bIsCustomShape ||
1668
45.1k
            aServiceName == "com.sun.star.drawing.GraphicObjectShape" ||
1669
41.7k
            aServiceName == "com.sun.star.drawing.OLE2Shape")
1670
22.7k
        {
1671
22.7k
            mpGraphicPropertiesPtr->pushToPropMap(aShapeProps, rGraphicHelper, getFlipH(), getFlipV());
1672
22.7k
        }
1673
64.0k
        if ( mpTablePropertiesPtr && aServiceName == "com.sun.star.drawing.TableShape" )
1674
124
        {
1675
124
            mpTablePropertiesPtr->pushToPropSet( rFilterBase, xSet, mpMasterTextListStyle );
1676
124
            if ( auto* pTableShape = dynamic_cast<sdr::table::SdrTableObj*>(SdrObject::getSdrObjectFromXShape(mxShape)) )
1677
124
            {
1678
                // Disable layouting until table height is expanded to fit the content
1679
124
                pTableShape->SetSkipChangeLayout(true);
1680
124
            }
1681
124
        }
1682
1683
64.0k
        FillProperties aFillProperties = getActualFillProperties(pTheme, &rShapeOrParentShapeFillProps);
1684
64.0k
        if ((getFillProperties().moFillType.has_value() && getFillProperties().moFillType.value() == XML_grpFill) ||
1685
64.0k
            aFillProperties.maFillColor.isPlaceHolder() )
1686
596
            getFillProperties().assignUsed(aFillProperties);
1687
64.0k
        if (!bIsCroppedGraphic && !bIs3DGraphic)
1688
64.0k
        {
1689
64.0k
            aFillProperties.pushToPropMap(aShapeProps, rGraphicHelper, getRotation(), nFillPhClr,
1690
64.0k
                                          css::awt::Size(aShapeRectHmm.Width, aShapeRectHmm.Height),
1691
64.0k
                                          nFillPhClrTheme, getFlipH(), getFlipV(), bIsCustomShape);
1692
64.0k
        }
1693
64.0k
        LineProperties aLineProperties = getActualLineProperties(pTheme);
1694
64.0k
        aLineProperties.pushToPropMap( aShapeProps, rGraphicHelper, nLinePhClr, nLinePhClrTheme);
1695
64.0k
        EffectProperties aEffectProperties = getActualEffectProperties(pTheme);
1696
        // TODO: use ph color when applying effect properties
1697
64.0k
        aEffectProperties.pushToPropMap( aShapeProps, rGraphicHelper );
1698
1699
        // applying autogrowheight property before setting shape size, because
1700
        // the shape size might be changed if currently autogrowheight is true
1701
        // we must also check that the PropertySet supports the property.
1702
64.0k
        Reference< XPropertySetInfo > xSetInfo( xSet->getPropertySetInfo() );
1703
64.0k
        const OUString& rPropName = PropertyMap::getPropertyName( PROP_TextAutoGrowHeight );
1704
64.0k
        if( xSetInfo.is() && xSetInfo->hasPropertyByName( rPropName ) )
1705
63.3k
            if( aShapeProps.hasProperty( PROP_TextAutoGrowHeight ) )
1706
63.2k
                xSet->setPropertyValue( rPropName, Any( false ) );
1707
1708
        // For extruded shapes, MSO uses the line color if no extrusion color is specified. LO uses
1709
        // fill color in 'automatic' case. Thus we set extrusion color explicitly.
1710
64.0k
        if (bHas3DEffect && !aExtrusionColor.isUsed())
1711
0
        {
1712
0
            const OUString& rFillColor2PropName = PropertyMap::getPropertyName(PROP_FillColor2);
1713
0
            if (xSetInfo.is() && xSetInfo->hasPropertyByName(rFillColor2PropName))
1714
0
            {
1715
0
                Color aComplexColor;
1716
0
                if (aLineProperties.maLineFill.moFillType.has_value()
1717
0
                    && aLineProperties.maLineFill.moFillType.value() != XML_noFill)
1718
0
                    aComplexColor = aLineProperties.maLineFill.getBestSolidColor();
1719
0
                else if (aFillProperties.moFillType.has_value()
1720
0
                    && aFillProperties.moFillType.value() != XML_noFill)
1721
0
                    aComplexColor = aFillProperties.getBestSolidColor();
1722
0
                if (aComplexColor.isUsed())
1723
0
                {
1724
0
                    const ::Color aSimpleColor = aComplexColor.getColor(rFilterBase.getGraphicHelper());
1725
0
                    xSet->setPropertyValue(rFillColor2PropName, Any(aSimpleColor));
1726
0
                }
1727
0
            }
1728
0
        }
1729
1730
        // do not set properties at a group shape (this causes
1731
        // assertions from svx) ...
1732
64.0k
        if( aServiceName != "com.sun.star.drawing.GroupShape" )
1733
63.4k
        {
1734
63.4k
            if (aServiceName == "com.sun.star.text.TextFrame")
1735
0
            {
1736
0
                if (mpCustomShapePropertiesPtr && mpCustomShapePropertiesPtr->getShapeTypeOverride())
1737
0
                {
1738
0
                    uno::Reference<beans::XPropertySet> propertySet (mxShape, uno::UNO_QUERY);
1739
0
                    uno::Sequence<beans::PropertyValue> aGrabBag;
1740
0
                    propertySet->getPropertyValue(u"FrameInteropGrabBag"_ustr) >>= aGrabBag;
1741
0
                    sal_Int32 length = aGrabBag.getLength();
1742
0
                    aGrabBag.realloc( length+1);
1743
0
                    auto pGrabBag = aGrabBag.getArray();
1744
0
                    pGrabBag[length].Name = "mso-orig-shape-type";
1745
0
                    pGrabBag[length].Value <<= mpCustomShapePropertiesPtr->getShapePresetTypeName();
1746
0
                    propertySet->setPropertyValue(u"FrameInteropGrabBag"_ustr,uno::Any(aGrabBag));
1747
0
                }
1748
                //If the text box has links then save the link information so that
1749
                //it can be accessed in DomainMapper_Impl.cxx while chaining the text frames.
1750
0
                if (isLinkedTxbx())
1751
0
                {
1752
0
                    uno::Reference<beans::XPropertySet> propertySet (mxShape, uno::UNO_QUERY);
1753
0
                    uno::Sequence<beans::PropertyValue> aGrabBag;
1754
0
                    propertySet->getPropertyValue(u"FrameInteropGrabBag"_ustr) >>= aGrabBag;
1755
0
                    sal_Int32 length = aGrabBag.getLength();
1756
0
                    aGrabBag.realloc( length + 3 );
1757
0
                    auto pGrabBag = aGrabBag.getArray();
1758
0
                    pGrabBag[length].Name = "TxbxHasLink";
1759
0
                    pGrabBag[length].Value <<= isLinkedTxbx();
1760
0
                    pGrabBag[length + 1 ].Name = "Txbx-Id";
1761
0
                    pGrabBag[length + 1 ].Value <<= getLinkedTxbxAttributes().id;
1762
0
                    pGrabBag[length + 2 ].Name = "Txbx-Seq";
1763
0
                    pGrabBag[length + 2 ].Value <<= getLinkedTxbxAttributes().seq;
1764
0
                    propertySet->setPropertyValue(u"FrameInteropGrabBag"_ustr,uno::Any(aGrabBag));
1765
0
                }
1766
1767
                // TextFrames have BackColor, not FillColor
1768
0
                if (aShapeProps.hasProperty(PROP_FillColor))
1769
0
                {
1770
0
                    aShapeProps.setAnyProperty(PROP_BackColor, aShapeProps.getProperty(PROP_FillColor));
1771
0
                    aShapeProps.erase(PROP_FillColor);
1772
0
                }
1773
                // TextFrames have BackColorTransparency, not FillTransparence
1774
0
                if (aShapeProps.hasProperty(PROP_FillTransparence))
1775
0
                {
1776
0
                    aShapeProps.setAnyProperty(PROP_BackColorTransparency, aShapeProps.getProperty(PROP_FillTransparence));
1777
0
                    aShapeProps.erase(PROP_FillTransparence);
1778
0
                }
1779
                // TextFrames have BackGraphic, not FillBitmap
1780
0
                if (aShapeProps.hasProperty(PROP_FillBitmap))
1781
0
                {
1782
0
                    aShapeProps.setAnyProperty(PROP_BackGraphic, aShapeProps.getProperty(PROP_FillBitmap));
1783
0
                    aShapeProps.erase(PROP_FillBitmap);
1784
0
                }
1785
0
                if (aShapeProps.hasProperty(PROP_FillBitmapName))
1786
0
                {
1787
0
                    uno::Any aAny = aShapeProps.getProperty(PROP_FillBitmapName);
1788
0
                    OUString aFillBitmapName = aAny.get<OUString>();
1789
0
                    uno::Reference<awt::XBitmap> xBitmap = rFilterBase.getModelObjectHelper().getFillBitmap(aFillBitmapName);
1790
0
                    uno::Reference<graphic::XGraphic> xGraphic(xBitmap, uno::UNO_QUERY);
1791
0
                    aShapeProps.setProperty(PROP_BackGraphic, xGraphic);
1792
                    // aShapeProps.erase(PROP_FillBitmapName);  // Maybe, leave the name as well
1793
0
                }
1794
                // And no LineColor property; individual borders can have colors
1795
0
                if (aShapeProps.hasProperty(PROP_LineColor))
1796
0
                {
1797
0
                    uno::Reference<beans::XPropertySet> xPropertySet(mxShape, uno::UNO_QUERY);
1798
0
                    static const sal_Int32 aBorders[] =
1799
0
                    {
1800
0
                        PROP_TopBorder, PROP_LeftBorder, PROP_BottomBorder, PROP_RightBorder
1801
0
                    };
1802
0
                    for (sal_Int32 nBorder : aBorders)
1803
0
                    {
1804
0
                        css::table::BorderLine2 aBorderLine = xPropertySet->getPropertyValue(PropertyMap::getPropertyName(nBorder)).get<css::table::BorderLine2>();
1805
0
                        aBorderLine.Color = aShapeProps.getProperty(PROP_LineColor).get<sal_Int32>();
1806
0
                        if (aLineProperties.moLineWidth.has_value())
1807
0
                            aBorderLine.LineWidth = convertEmuToHmm(aLineProperties.moLineWidth.value());
1808
0
                        aShapeProps.setProperty(nBorder, aBorderLine);
1809
0
                    }
1810
0
                    aShapeProps.erase(PROP_LineColor);
1811
0
                }
1812
0
                if (getRotation())
1813
0
                {
1814
0
                    uno::Reference<beans::XPropertySet> xPropertySet(mxShape, uno::UNO_QUERY);
1815
0
                    static constexpr OUString aGrabBagPropName = u"FrameInteropGrabBag"_ustr;
1816
0
                    uno::Sequence<beans::PropertyValue> aGrabBag;
1817
0
                    xPropertySet->getPropertyValue(aGrabBagPropName) >>= aGrabBag;
1818
0
                    beans::PropertyValue aPair(comphelper::makePropertyValue(u"mso-rotation-angle"_ustr,
1819
0
                                                                             getRotation()));
1820
0
                    if (aGrabBag.hasElements())
1821
0
                    {
1822
0
                        sal_Int32 nLength = aGrabBag.getLength();
1823
0
                        aGrabBag.realloc(nLength + 1);
1824
0
                        aGrabBag.getArray()[nLength] = std::move(aPair);
1825
0
                    }
1826
0
                    else
1827
0
                    {
1828
0
                        aGrabBag = { std::move(aPair) };
1829
0
                    }
1830
0
                    xPropertySet->setPropertyValue(aGrabBagPropName, uno::Any(aGrabBag));
1831
0
                }
1832
                // TextFrames have ShadowFormat, not individual shadow properties.
1833
0
                std::optional<sal_Int32> oShadowDistance;
1834
0
                if (aShapeProps.hasProperty(PROP_ShadowXDistance))
1835
0
                {
1836
0
                    oShadowDistance = aShapeProps.getProperty(PROP_ShadowXDistance).get<sal_Int32>();
1837
0
                    aShapeProps.erase(PROP_ShadowXDistance);
1838
0
                }
1839
0
                if (aShapeProps.hasProperty(PROP_ShadowYDistance))
1840
0
                {
1841
                    // There is a single 'dist' attribute, so no need to count the avg of x and y.
1842
0
                    aShapeProps.erase(PROP_ShadowYDistance);
1843
0
                }
1844
0
                std::optional<sal_Int32> oShadowColor;
1845
0
                if (aShapeProps.hasProperty(PROP_ShadowColor))
1846
0
                {
1847
0
                    oShadowColor = aShapeProps.getProperty(PROP_ShadowColor).get<sal_Int32>();
1848
0
                    aShapeProps.erase(PROP_ShadowColor);
1849
0
                }
1850
0
                if (aShapeProps.hasProperty(PROP_Shadow))
1851
0
                    aShapeProps.erase(PROP_Shadow);
1852
1853
0
                if (oShadowDistance || oShadowColor || aEffectProperties.maShadow.moShadowDir.has_value())
1854
0
                {
1855
0
                    css::table::ShadowFormat aFormat;
1856
0
                    if (oShadowColor)
1857
0
                        aFormat.Color = *oShadowColor;
1858
0
                    if (aEffectProperties.maShadow.moShadowDir.has_value())
1859
0
                    {
1860
0
                        css::table::ShadowLocation nLocation = css::table::ShadowLocation_NONE;
1861
0
                        switch (aEffectProperties.maShadow.moShadowDir.value())
1862
0
                        {
1863
0
                        case 13500000:
1864
0
                            nLocation = css::table::ShadowLocation_TOP_LEFT;
1865
0
                            break;
1866
0
                        case 18900000:
1867
0
                            nLocation = css::table::ShadowLocation_TOP_RIGHT;
1868
0
                            break;
1869
0
                        case 8100000:
1870
0
                            nLocation = css::table::ShadowLocation_BOTTOM_LEFT;
1871
0
                            break;
1872
0
                        case 2700000:
1873
0
                            nLocation = css::table::ShadowLocation_BOTTOM_RIGHT;
1874
0
                            break;
1875
0
                        }
1876
0
                        aFormat.Location = nLocation;
1877
0
                    }
1878
0
                    aFormat.ShadowWidth = *oShadowDistance;
1879
0
                    aShapeProps.setProperty(PROP_ShadowFormat, aFormat);
1880
0
                }
1881
1882
0
            }
1883
63.4k
            else if (getIsTextBox())
1884
324
            {
1885
                // This introduces a TextBox in a shape in Writer. ToDo: Can we restrict it to cases
1886
                // where the TextBox edit engine is really needed? tdf#82627
1887
324
                aShapeProps.setProperty(PROP_TextBox, true);
1888
324
            }
1889
1890
63.4k
            if (aServiceName != "com.sun.star.text.TextFrame" && isLinkedTxbx())
1891
0
            {
1892
0
                uno::Reference<beans::XPropertySet> propertySet (mxShape, uno::UNO_QUERY);
1893
0
                uno::Sequence<beans::PropertyValue> aGrabBag;
1894
0
                propertySet->getPropertyValue(u"InteropGrabBag"_ustr) >>= aGrabBag;
1895
0
                sal_Int32 length = aGrabBag.getLength();
1896
0
                aGrabBag.realloc( length + 3 );
1897
0
                auto pGrabBag = aGrabBag.getArray();
1898
0
                pGrabBag[length].Name = "TxbxHasLink";
1899
0
                pGrabBag[length].Value <<= isLinkedTxbx();
1900
0
                pGrabBag[length + 1 ].Name = "Txbx-Id";
1901
0
                pGrabBag[length + 1 ].Value <<= getLinkedTxbxAttributes().id;
1902
0
                pGrabBag[length + 2 ].Name = "Txbx-Seq";
1903
0
                pGrabBag[length + 2 ].Value <<= getLinkedTxbxAttributes().seq;
1904
0
                propertySet->setPropertyValue(u"InteropGrabBag"_ustr,uno::Any(aGrabBag));
1905
0
            }
1906
1907
            // set custom prompt text if available
1908
63.4k
            if (getCustomPrompt() && getTextBody() && !getTextBody()->isEmpty())
1909
0
            {
1910
0
                aShapeProps.setProperty(PROP_CustomPromptText, getTextBody()->firstParatoString());
1911
0
            }
1912
63.4k
            else if (pPlaceholder && pPlaceholder->getCustomPrompt() && pPlaceholder->getTextBody() && !pPlaceholder->getTextBody()->isEmpty())
1913
0
            {
1914
0
                aShapeProps.setProperty(PROP_CustomPromptText, pPlaceholder->getTextBody()->firstParatoString());
1915
0
            }
1916
1917
63.4k
            PropertySet( xSet ).setProperties( aShapeProps );
1918
1919
63.4k
            if (mpTablePropertiesPtr && aServiceName == "com.sun.star.drawing.TableShape")
1920
124
            {
1921
                // Powerpoint exports desired row heights (i.e. what user attempted to set it as, not how it appears visually)
1922
                // Expand table height if there are rows that can't fit the content
1923
124
                if (auto* pTableShape = dynamic_cast<sdr::table::SdrTableObj*>(SdrObject::getSdrObjectFromXShape(mxShape)))
1924
124
                {
1925
124
                    tools::Rectangle aArea{};
1926
124
                    pTableShape->LayoutTableHeight(aArea);
1927
124
                    sal_Int32 nCorrectedHeight = aArea.GetHeight();
1928
124
                    const auto aShapeSize = mxShape->getSize();
1929
124
                    if( nCorrectedHeight > aShapeSize.Height )
1930
0
                        mxShape->setSize( {aShapeSize.Width, nCorrectedHeight} );
1931
124
                    pTableShape->SetSkipChangeLayout(false);
1932
124
                }
1933
124
            }
1934
1935
63.4k
            if (getLockedCanvas())
1936
0
            {
1937
0
                putPropertyToGrabBag( u"LockedCanvas"_ustr, Any( true ) );
1938
0
                if (aServiceName == "com.sun.star.drawing.LineShape")
1939
0
                {
1940
                    // It seems the position and size for lines inside a locked canvas is absolute.
1941
0
                    mxShape->setPosition(awt::Point(aShapeRectHmm.X, aShapeRectHmm.Y));
1942
0
                    mxShape->setSize(awt::Size(aShapeRectHmm.Width, aShapeRectHmm.Height));
1943
0
                }
1944
0
            }
1945
1946
63.4k
            if (isInWordprocessingCanvas())
1947
0
            {
1948
0
                putPropertyToGrabBag(u"WordprocessingCanvas"_ustr, Any(true));
1949
0
            }
1950
1951
            // Store original fill and line colors of the shape and the theme color name to InteropGrabBag
1952
63.4k
            std::vector<beans::PropertyValue> aProperties
1953
63.4k
            {
1954
63.4k
                comphelper::makePropertyValue(u"EmuLineWidth"_ustr, aLineProperties.moLineWidth.value_or(0)),
1955
63.4k
                comphelper::makePropertyValue(u"OriginalSolidFillClr"_ustr, aShapeProps.getProperty(PROP_FillColor)),
1956
63.4k
                comphelper::makePropertyValue(u"OriginalLnSolidFillClr"_ustr, aShapeProps.getProperty(PROP_LineColor))
1957
63.4k
            };
1958
63.4k
            OUString sColorFillScheme = aFillProperties.maFillColor.getSchemeColorName();
1959
63.4k
            if( !aFillProperties.maFillColor.isPlaceHolder() && !sColorFillScheme.isEmpty() )
1960
2.61k
            {
1961
2.61k
                aProperties.push_back(comphelper::makePropertyValue(u"SpPrSolidFillSchemeClr"_ustr, sColorFillScheme));
1962
2.61k
                aProperties.push_back(comphelper::makePropertyValue(u"SpPrSolidFillSchemeClrTransformations"_ustr, aFillProperties.maFillColor.getTransformations()));
1963
2.61k
            }
1964
63.4k
            OUString sLnColorFillScheme = aLineProperties.maLineFill.maFillColor.getSchemeColorName();
1965
63.4k
            if( !aLineProperties.maLineFill.maFillColor.isPlaceHolder() && !sLnColorFillScheme.isEmpty() )
1966
2.79k
            {
1967
2.79k
                aProperties.push_back(comphelper::makePropertyValue(u"SpPrLnSolidFillSchemeClr"_ustr, sLnColorFillScheme));
1968
2.79k
                auto aResolvedSchemeClr = aLineProperties.maLineFill.maFillColor;
1969
2.79k
                aResolvedSchemeClr.clearTransformations();
1970
2.79k
                aProperties.push_back(comphelper::makePropertyValue(u"SpPrLnSolidFillResolvedSchemeClr"_ustr, aResolvedSchemeClr.getColor(rGraphicHelper, nFillPhClr)));
1971
2.79k
                aProperties.push_back(comphelper::makePropertyValue(u"SpPrLnSolidFillSchemeClrTransformations"_ustr, aLineProperties.maLineFill.maFillColor.getTransformations()));
1972
2.79k
            }
1973
63.4k
            putPropertiesToGrabBag(comphelper::containerToSequence(aProperties));
1974
1975
            // Store original gradient fill of the shape to InteropGrabBag
1976
            // LibreOffice doesn't support all the kinds of gradient so we save its complete definition
1977
63.4k
            if( aShapeProps.hasProperty( PROP_FillGradient ) )
1978
1.94k
            {
1979
1.94k
                std::vector<beans::PropertyValue> aGradientStops;
1980
1.94k
                size_t i = 0;
1981
1.94k
                for( const auto& [rPos, rColor] : aFillProperties.maGradientProps.maGradientStops )
1982
4.13k
                { // for each stop in the gradient definition:
1983
1984
                    // save position
1985
4.13k
                    std::vector<beans::PropertyValue> aGradientStop
1986
4.13k
                    {
1987
4.13k
                        comphelper::makePropertyValue(u"Pos"_ustr, rPos)
1988
4.13k
                    };
1989
1990
4.13k
                    OUString sStopColorScheme = rColor.getSchemeColorName();
1991
4.13k
                    if( sStopColorScheme.isEmpty() )
1992
3.57k
                    {
1993
                        // save RGB color
1994
3.57k
                        aGradientStop.push_back(comphelper::makePropertyValue(u"RgbClr"_ustr, rColor.getColor(rGraphicHelper, nFillPhClr)));
1995
                        // in the case of a RGB color, transformations are already applied to
1996
                        // the color with the exception of alpha transformations. We only need
1997
                        // to keep the transparency value to calculate the alpha value later.
1998
3.57k
                        if( rColor.hasTransparency() )
1999
0
                            aGradientStop.push_back(comphelper::makePropertyValue(u"Transparency"_ustr, rColor.getTransparency()));
2000
3.57k
                    }
2001
562
                    else
2002
562
                    {
2003
                        // save color with scheme name
2004
562
                        aGradientStop.push_back(comphelper::makePropertyValue(u"SchemeClr"_ustr, sStopColorScheme));
2005
                        // save all color transformations
2006
562
                        aGradientStop.push_back(comphelper::makePropertyValue(u"Transformations"_ustr, rColor.getTransformations()));
2007
562
                    }
2008
2009
4.13k
                    aGradientStops.push_back(comphelper::makePropertyValue(OUString::number(i), comphelper::containerToSequence(aGradientStop)));
2010
4.13k
                    ++i;
2011
4.13k
                }
2012
                // If getFillProperties.moFillType is unused that means gradient is defined by a theme
2013
                // which is already saved into StyleFillRef property, so no need to save the explicit values too
2014
1.94k
                if( getFillProperties().moFillType.has_value() )
2015
1.91k
                    putPropertyToGrabBag( u"GradFillDefinition"_ustr, uno::Any(comphelper::containerToSequence(aGradientStops)));
2016
1.94k
                putPropertyToGrabBag( u"OriginalGradFill"_ustr, aShapeProps.getProperty(PROP_FillGradient) );
2017
1.94k
            }
2018
2019
            // store unsupported effect attributes in the grab bag
2020
63.4k
            if (!aEffectProperties.m_Effects.empty())
2021
101
            {
2022
101
                std::vector<beans::PropertyValue> aEffects;
2023
101
                for (auto const& it : aEffectProperties.m_Effects)
2024
101
                {
2025
101
                    PropertyValue aEffect = it->getEffect();
2026
101
                    if( !aEffect.Name.isEmpty() )
2027
101
                    {
2028
101
                        std::vector<beans::PropertyValue> aEffectsGrabBag
2029
101
                        {
2030
101
                            comphelper::makePropertyValue(u"Attribs"_ustr, aEffect.Value)
2031
101
                        };
2032
2033
101
                        Color& aColor( it->moColor );
2034
101
                        OUString sColorScheme = aColor.getSchemeColorName();
2035
101
                        if( sColorScheme.isEmpty() )
2036
90
                        {
2037
                            // RGB color and transparency value
2038
90
                            aEffectsGrabBag.push_back(comphelper::makePropertyValue(u"RgbClr"_ustr, aColor.getColor(rGraphicHelper, nFillPhClr)));
2039
90
                            aEffectsGrabBag.push_back(comphelper::makePropertyValue(u"RgbClrTransparency"_ustr, aColor.getTransparency()));
2040
90
                        }
2041
11
                        else
2042
11
                        {
2043
                            // scheme color with name and transformations
2044
11
                            aEffectsGrabBag.push_back(comphelper::makePropertyValue(u"SchemeClr"_ustr, sColorScheme));
2045
11
                            aEffectsGrabBag.push_back(comphelper::makePropertyValue(u"SchemeClrTransformations"_ustr, aColor.getTransformations()));
2046
11
                        }
2047
101
                        aEffects.push_back(comphelper::makePropertyValue(aEffect.Name, comphelper::containerToSequence(aEffectsGrabBag)));
2048
101
                    }
2049
101
                }
2050
101
                putPropertyToGrabBag(u"EffectProperties"_ustr, uno::Any(comphelper::containerToSequence(aEffects)));
2051
101
            }
2052
2053
            // add 3D effects if any to GrabBag. They are still used in export.
2054
63.4k
            if (bHas3DProps)
2055
15
            {
2056
15
                uno::Sequence<beans::PropertyValue> a3DEffectsGrabBag = comphelper::InitPropertySequence(
2057
15
                {
2058
15
                    {"Camera", uno::Any(aCamera3DEffects)},
2059
15
                    {"LightRig", uno::Any(aLightRig3DEffects)},
2060
15
                    {"Shape3D", uno::Any(aShape3DEffects)}
2061
15
                });
2062
15
                putPropertyToGrabBag( u"3DEffectProperties"_ustr, Any( a3DEffectsGrabBag ) );
2063
15
            }
2064
2065
63.4k
            if( bIsCustomShape && getTextBody())
2066
10.3k
            {
2067
2068
10.3k
                Sequence< PropertyValue > aTextCamera3DEffects = getTextBody()->get3DProperties().getCameraAttributes();
2069
10.3k
                Sequence< PropertyValue > aTextLightRig3DEffects = getTextBody()->get3DProperties().getLightRigAttributes();
2070
10.3k
                Sequence< PropertyValue > aTextShape3DEffects = getTextBody()->get3DProperties().getShape3DAttributes( rGraphicHelper, nFillPhClr );
2071
10.3k
                if( aTextCamera3DEffects.hasElements() || aTextLightRig3DEffects.hasElements() || aTextShape3DEffects.hasElements() )
2072
0
                {
2073
0
                    uno::Sequence<beans::PropertyValue> aText3DEffectsGrabBag = comphelper::InitPropertySequence(
2074
0
                    {
2075
0
                        {"Camera", uno::Any(aTextCamera3DEffects)},
2076
0
                        {"LightRig", uno::Any(aTextLightRig3DEffects)},
2077
0
                        {"Shape3D", uno::Any(aTextShape3DEffects)}
2078
0
                    });
2079
0
                    putPropertyToGrabBag( u"Text3DEffectProperties"_ustr, Any( aText3DEffectsGrabBag ) );
2080
0
                }
2081
10.3k
            }
2082
2083
            // store bitmap artistic effects in the grab bag
2084
63.4k
            if( !mpGraphicPropertiesPtr->maBlipProps.maEffect.isEmpty() )
2085
0
                putPropertyToGrabBag( u"ArtisticEffectProperties"_ustr,
2086
0
                                      Any( mpGraphicPropertiesPtr->maBlipProps.maEffect.getEffect() ) );
2087
63.4k
        }
2088
2089
639
        else if (getLockedCanvas())
2090
40
        {
2091
            //If we have aServiceName as "com.sun.star.drawing.GroupShape" and lockedCanvas
2092
40
            putPropertyToGrabBag( u"LockedCanvas"_ustr, Any( true ) );
2093
40
        }
2094
599
        else if (isInWordprocessingCanvas())
2095
0
        {
2096
0
            putPropertyToGrabBag(u"WordprocessingCanvas"_ustr, Any(true));
2097
0
            putPropertyToGrabBag(u"mso-edit-as"_ustr, Any(u"canvas"_ustr)); // for export VML Fallback
2098
0
        }
2099
2100
        // These can have a custom geometry, so position should be set here,
2101
        // after creation but before custom shape handling, using the position
2102
        // we got from the caller.
2103
64.0k
        if (getWps() && aServiceName == "com.sun.star.drawing.LineShape" && !pParentGroupShape)
2104
0
            mxShape->setPosition(maPosition);
2105
2106
64.0k
        SdrObject* pShape = SdrObject::getSdrObjectFromXShape(mxShape);
2107
64.0k
        if (pShape)
2108
64.0k
            aOrigSize = pShape->GetLogicRect();
2109
2110
64.0k
        if (bIsConnectorShape)
2111
1.57k
        {
2112
1.57k
            msConnectorName = mpCustomShapePropertiesPtr->getShapePresetTypeName();
2113
2114
1.57k
            const auto& aAdjustmentList = mpCustomShapePropertiesPtr->getAdjustmentGuideList();
2115
1.59k
            for (size_t i = 0; i < aAdjustmentList.size(); i++)
2116
21
                maConnectorAdjustmentList.push_back(aAdjustmentList[i].maFormula);
2117
2118
1.57k
            sal_Int32 nType = mpCustomShapePropertiesPtr->getShapePresetType();
2119
1.57k
            switch (nType)
2120
1.57k
            {
2121
1.20k
            case XML_line:
2122
1.53k
            case XML_straightConnector1:
2123
1.53k
                xSet->setPropertyValue(u"EdgeKind"_ustr, Any(ConnectorType_LINE));
2124
1.53k
                break;
2125
24
            case XML_bentConnector2:
2126
45
            case XML_bentConnector3:
2127
45
            case XML_bentConnector4:
2128
45
            case XML_bentConnector5:
2129
45
                xSet->setPropertyValue(u"EdgeKind"_ustr, Any(ConnectorType_STANDARD));
2130
45
                break;
2131
0
            case XML_curvedConnector2:
2132
0
            case XML_curvedConnector3:
2133
0
            case XML_curvedConnector4:
2134
0
            case XML_curvedConnector5:
2135
0
                xSet->setPropertyValue(u"EdgeKind"_ustr, Any(ConnectorType_CURVE));
2136
0
                break;
2137
0
            default:
2138
0
                break;
2139
1.57k
            }
2140
1.57k
        }
2141
2142
64.0k
        if( bIsCustomShape )
2143
18.9k
        {
2144
18.9k
            if (getFlipH())
2145
10
                mpCustomShapePropertiesPtr->setMirroredX( true );
2146
18.9k
            if (getFlipV())
2147
32
                mpCustomShapePropertiesPtr->setMirroredY( true );
2148
18.9k
            if( getTextBody() )
2149
10.3k
            {
2150
10.3k
                sal_Int32 nTextCameraZRotation = getTextBody()->get3DProperties().maCameraRotation.mnRevolution.value_or(0);
2151
10.3k
                mpCustomShapePropertiesPtr->setTextCameraZRotateAngle( nTextCameraZRotation / 60000 );
2152
2153
                // TextPreRotateAngle. Text rotates inside the text area. Might be used for diagram layout 'upr' and 'grav'.
2154
10.3k
                sal_Int32 nTextPreRotateAngle = static_cast< sal_Int32 >( getTextBody()->getTextProperties().moTextPreRotation.value_or( 0 ) );
2155
2156
10.3k
                nTextPreRotateAngle -= getDiagramRotation(); // Use of mnDiagramRotation is unclear. It seems to be always 0 here.
2157
2158
                // TextRotateAngle. The text area rotates.
2159
10.3k
                sal_Int32 nTextAreaRotateAngle = getTextBody()->getTextProperties().moTextAreaRotation.value_or(0);
2160
10.3k
                if (getTextBody()->getTextProperties().moUpright)
2161
96
                {
2162
                    // When upright is set, any text area transformation and shape rotation is ignored
2163
                    // in MS Office. To simulate this behaviour, we rotate the text area into the
2164
                    // opposite direction of the shape rotation by as much as the shape was rotated
2165
                    // and so compensate the shape rotation, which is added in rendering.
2166
96
                    nTextAreaRotateAngle = -getRotation();
2167
                    // If 45° <= shape rotation < 135° or 225° <= shape rotation < 315°,
2168
                    // then MS Office adds an additional 90° rotation to the text area.
2169
96
                    const sal_Int32 nDeg(getRotation() / 60000);
2170
96
                    if ((nDeg >= 45 && nDeg < 135) || (nDeg >= 225 && nDeg < 315))
2171
2
                    {
2172
2
                        nTextAreaRotateAngle += 5400000;
2173
2
                        nTextPreRotateAngle -= 5400000; // compensate the additional text area rotation
2174
2
                    }
2175
96
                    putPropertyToGrabBag(u"Upright"_ustr, Any(true));
2176
96
                }
2177
                /* OOX measures text rotation clockwise in 1/60000th degrees,
2178
                   relative to the containing shape. set*Angle wants degrees counter-clockwise. */
2179
10.3k
                mpCustomShapePropertiesPtr->setTextPreRotateAngle(-nTextPreRotateAngle / 60000);
2180
10.3k
                if (nTextAreaRotateAngle != 0)
2181
68
                    mpCustomShapePropertiesPtr->setTextAreaRotateAngle(-nTextAreaRotateAngle / 60000);
2182
2183
10.3k
                auto sHorzOverflow = getTextBody()->getTextProperties().msHorzOverflow;
2184
10.3k
                if (!sHorzOverflow.isEmpty())
2185
178
                    putPropertyToGrabBag(u"horzOverflow"_ustr, uno::Any(getTextBody()->getTextProperties().msHorzOverflow));
2186
10.3k
                if (XML_ellipsis == getTextBody()->getTextProperties().moVertOverflow)
2187
0
                    putPropertyToGrabBag(u"vertOverflow"_ustr, uno::Any(u"ellipsis"_ustr));
2188
10.3k
            }
2189
2190
            // Note that the script oox/source/drawingml/customshapes/generatePresetsData.pl looks
2191
            // for these ==cscode== and ==csdata== markers, so don't "clean up" these SAL_INFOs
2192
18.9k
            SAL_INFO("oox.cscode", "==cscode== shape name: '" << msName << "'");
2193
18.9k
            SAL_INFO("oox.csdata", "==csdata== shape name: '" << msName << "'");
2194
2195
18.9k
            mpCustomShapePropertiesPtr->pushToPropSet(xSet, maSize);
2196
2197
            // Consider WordArt
2198
18.9k
            if (mpTextBody && !mpTextBody->getTextProperties().msPrst.isEmpty()
2199
1.08k
                && mpTextBody->getTextProperties().msPrst != u"textNoShape")
2200
0
            {
2201
0
                bool bFromWordArt(aShapeProps.hasProperty(PROP_FromWordArt)
2202
0
                                      ? aShapeProps.getProperty(PROP_FromWordArt).get<bool>()
2203
0
                                      : false);
2204
0
                FontworkHelpers::putCustomShapeIntoTextPathMode(
2205
0
                    mxShape, mpCustomShapePropertiesPtr, mpTextBody->getTextProperties().msPrst,
2206
0
                    bFromWordArt);
2207
0
            }
2208
18.9k
        }
2209
45.1k
        else if( getTextBody() )
2210
38.9k
            getTextBody()->getTextProperties().pushVertSimulation();
2211
2212
        // tdf#133037: a bit hackish: force Shape to rotate in the opposite direction the camera would rotate
2213
64.0k
        PropertySet aPropertySet(mxShape);
2214
64.0k
        if ( !bUseRotationTransform && (nShapeRotateInclCamera !=0) )
2215
192
        {
2216
192
            Degree100 nAngle(lcl_MSORotateAngleToAPIAngle(nShapeRotateInclCamera));
2217
192
            aPropertySet.setAnyProperty(PROP_RotateAngle, Any( sal_Int32(nAngle)));
2218
192
            aPropertySet.setAnyProperty( PROP_HoriOrientPosition, Any( maPosition.X ) );
2219
192
            aPropertySet.setAnyProperty( PROP_VertOrientPosition, Any( maPosition.Y ) );
2220
192
        }
2221
2222
        // Make sure to not set text to placeholders. Doing it here would eventually call
2223
        // SvxTextEditSourceImpl::UpdateData, SdrObject::SetEmptyPresObj(false), and that
2224
        // would make the object behave like a standard outline object.
2225
        // TODO/FIXME: support custom prompt text in placeholders.
2226
64.0k
        if (rServiceName == "com.sun.star.presentation.GraphicObjectShape")
2227
0
            mpTextBody.reset();
2228
2229
        // in some cases, we don't have any text body.
2230
64.0k
        if( mpTextBody && ( !pPlaceholder || !mpTextBody->isEmpty() ) )
2231
38.4k
        {
2232
38.4k
            Reference < XText > xText( mxShape, UNO_QUERY );
2233
38.4k
            if ( xText.is() )   // not every shape is supporting an XText interface (e.g. GroupShape)
2234
38.4k
            {
2235
38.4k
                TextCharacterProperties aCharStyleProperties;
2236
38.4k
                if( const ShapeStyleRef* pFontRef = getShapeStyleRef( XML_fontRef ) )
2237
1.40k
                {
2238
1.40k
                    if( pFontRef->mnThemedIdx != 0 )
2239
1.40k
                    {
2240
1.40k
                        if( pTheme )
2241
1.31k
                            if( const TextCharacterProperties* pCharProps = pTheme->getFontStyle( pFontRef->mnThemedIdx ) )
2242
825
                                aCharStyleProperties.assignUsed( *pCharProps );
2243
1.40k
                        SAL_INFO("oox.drawingml", "Shape::createAndInsert: use font color");
2244
1.40k
                        if ( pFontRef->maPhClr.isUsed() )
2245
1.40k
                        {
2246
1.40k
                            aCharStyleProperties.maFillProperties.maFillColor = pFontRef->maPhClr;
2247
1.40k
                            aCharStyleProperties.maFillProperties.moFillType = XML_solidFill;
2248
1.40k
                        }
2249
1.40k
                    }
2250
1.40k
                }
2251
38.4k
                xText->setString(u""_ustr);
2252
38.4k
                Reference < XTextCursor > xAt = xText->createTextCursor();
2253
38.4k
                getTextBody()->insertAt( rFilterBase, xText, xAt, aCharStyleProperties, mpMasterTextListStyle );
2254
2255
38.4k
                const TextParagraphVector& rParagraphs = getTextBody()->getParagraphs();
2256
38.4k
                if (!rParagraphs.empty())
2257
38.1k
                {
2258
38.1k
                    const std::shared_ptr<TextParagraph>& pParagraph = rParagraphs[0];
2259
38.1k
                    if (pParagraph->getProperties().getParaAdjust())
2260
8.89k
                    {
2261
8.89k
                        style::ParagraphAdjust eAdjust = *pParagraph->getProperties().getParaAdjust();
2262
8.89k
                        if (eAdjust == style::ParagraphAdjust_CENTER)
2263
6.68k
                        {
2264
                            // If the first paragraph is centered, then set the para adjustment of
2265
                            // the shape itself to centered as well.
2266
6.68k
                            aPropertySet.setAnyProperty(PROP_ParaAdjust, uno::Any(eAdjust));
2267
6.68k
                        }
2268
8.89k
                    }
2269
2270
                    // tdf#144092 For empty textboxes push character styles &
2271
                    // endParaRPr into the Shape's properties
2272
38.1k
                    if (rParagraphs.size() == 1 && pParagraph->getRuns().empty())
2273
9.77k
                    {
2274
9.77k
                        TextCharacterProperties aTextCharacterProps{ pParagraph->getCharacterStyle(
2275
9.77k
                            aCharStyleProperties, *mpMasterTextListStyle,
2276
9.77k
                            getTextBody()->getTextListStyle()) };
2277
9.77k
                        aTextCharacterProps.assignUsed(pParagraph->getEndProperties());
2278
9.77k
                        aTextCharacterProps.pushToPropSet(aPropertySet, rFilterBase);
2279
9.77k
                    }
2280
38.1k
                }
2281
2282
                // MS Office has e.g. fill and stroke of WordArt in the character properties,
2283
                // LibreOffice uses shape properties.
2284
38.4k
                if (!mpTextBody->getTextProperties().msPrst.isEmpty()
2285
1.61k
                    && mpTextBody->getTextProperties().msPrst != u"textNoShape")
2286
0
                {
2287
0
                    lcl_copyCharPropsToShape(mxShape, mpTextBody, rFilterBase);
2288
0
                }
2289
38.4k
            }
2290
38.4k
        }
2291
25.6k
        else if (mpTextBody && aServiceName == "com.sun.star.presentation.OutlinerShape"
2292
4.97k
                 && mpMasterTextListStyle && !bPlaceholderWithCustomPrompt)
2293
4.97k
        {
2294
            // If mpTextBody is not empty, then the insertAt() above inserts formatted text. If it's
2295
            // empty, then we format the existing text of the outliner shape here.
2296
4.97k
            PushMasterTextListStyleToMasterShapeParagraphs(*mpMasterTextListStyle, mxShape);
2297
4.97k
        }
2298
20.6k
        else if (getIsTextBox())
2299
324
        {
2300
            // No drawingML text, but WPS text is expected: save the theme
2301
            // character color on the shape, then.
2302
324
            if(const ShapeStyleRef* pFontRef = getShapeStyleRef(XML_fontRef))
2303
172
            {
2304
172
                ::Color nCharColor = pFontRef->maPhClr.getColor(rGraphicHelper);
2305
172
                aPropertySet.setAnyProperty(PROP_CharColor, uno::Any(nCharColor));
2306
172
            }
2307
324
        }
2308
2309
        // Set glow effect properties
2310
64.0k
        if (aEffectProperties.maGlow.moGlowRad.has_value()
2311
12
            && aServiceName != "com.sun.star.drawing.GroupShape")
2312
12
        {
2313
12
            uno::Reference<beans::XPropertySet> propertySet (mxShape, uno::UNO_QUERY);
2314
12
            propertySet->setPropertyValue(u"GlowEffectRadius"_ustr, Any(convertEmuToHmm(aEffectProperties.maGlow.moGlowRad.value())));
2315
12
            propertySet->setPropertyValue(u"GlowEffectColor"_ustr, Any(aEffectProperties.maGlow.moGlowColor.getColor(rGraphicHelper)));
2316
12
            propertySet->setPropertyValue(u"GlowEffectTransparency"_ustr, Any(aEffectProperties.maGlow.moGlowColor.getTransparency()));
2317
12
        }
2318
2319
        // Set soft edge effect properties
2320
64.0k
        if (aEffectProperties.maSoftEdge.moRad.has_value())
2321
0
        {
2322
0
            uno::Reference<beans::XPropertySet> propertySet(mxShape, uno::UNO_QUERY);
2323
0
            propertySet->setPropertyValue(
2324
0
                u"SoftEdgeRadius"_ustr, Any(convertEmuToHmm(aEffectProperties.maSoftEdge.moRad.value())));
2325
0
        }
2326
2327
        // Set text glow effect for shapes
2328
64.0k
        if (mpTextBody && (!pPlaceholder || !mpTextBody->isEmpty()))
2329
38.4k
        {
2330
38.4k
            const TextParagraphVector& rParagraphs = mpTextBody->getParagraphs();
2331
38.4k
            if (!rParagraphs.empty())
2332
38.1k
            {
2333
38.1k
                EffectProperties aTextEffectProperties;
2334
93.4k
                for (TextParagraphVector::const_iterator aPIt = rParagraphs.begin(), aPEnd = rParagraphs.end(); aPIt != aPEnd; ++aPIt)
2335
55.2k
                {
2336
55.2k
                    const TextParagraph& rTextPara = **aPIt;
2337
55.2k
                    const TextCharacterProperties & rParaProps = rTextPara.getProperties().getTextCharacterProperties();
2338
55.2k
                    if (rParaProps.getEffectProperties().maGlow.moGlowRad.has_value())
2339
0
                    {
2340
0
                        aTextEffectProperties.assignUsed(rParaProps.getEffectProperties());
2341
0
                        goto found;
2342
0
                    }
2343
55.2k
                    else
2344
55.2k
                    {
2345
114k
                        for (TextRunVector::const_iterator aRIt = rTextPara.getRuns().begin(), aREnd = rTextPara.getRuns().end(); aRIt != aREnd; ++aRIt)
2346
59.2k
                        {
2347
59.2k
                            const TextRun& rTextRun = **aRIt;
2348
59.2k
                            const TextCharacterProperties& rRunrops = rTextRun.getTextCharacterProperties();
2349
59.2k
                            if (rRunrops.getEffectProperties().maGlow.moGlowRad.has_value())
2350
0
                            {
2351
0
                                aTextEffectProperties.assignUsed(rRunrops.getEffectProperties());
2352
0
                                goto found;
2353
0
                            }
2354
59.2k
                        }
2355
55.2k
                    }
2356
55.2k
                }
2357
2358
38.1k
            found:
2359
38.1k
                if (aTextEffectProperties.maGlow.moGlowRad.has_value())
2360
0
                {
2361
0
                    xSet->setPropertyValue(u"GlowTextEffectRadius"_ustr,
2362
0
                        uno::Any(convertEmuToHmm(aTextEffectProperties.maGlow.moGlowRad.value())));
2363
0
                    xSet->setPropertyValue(u"GlowTextEffectColor"_ustr,
2364
0
                        uno::Any(aTextEffectProperties.maGlow.moGlowColor.getColor(rGraphicHelper)));
2365
0
                    xSet->setPropertyValue(u"GlowTextEffectTransparency"_ustr,
2366
0
                        uno::Any(aTextEffectProperties.maGlow.moGlowColor.getTransparency()));
2367
0
                }
2368
38.1k
            }
2369
38.4k
        }
2370
2371
        // Set the stroke and fill-color properties of the OLE shape
2372
64.0k
        if (aServiceName == "com.sun.star.drawing.OLE2Shape" && mxOleObjectInfo
2373
0
            && !mxOleObjectInfo->maShapeId.isEmpty())
2374
0
            if (::oox::vml::Drawing* pVmlDrawing = rFilterBase.getVmlDrawing())
2375
0
                if (const ::oox::vml::ShapeBase* pVmlShape
2376
0
                    = pVmlDrawing->getShapes().getShapeById(mxOleObjectInfo->maShapeId))
2377
0
                {
2378
                    // Apply stroke props from the type model of the related VML shape.
2379
0
                    ShapePropertyMap aPropMap(rFilterBase.getModelObjectHelper());
2380
0
                    pVmlShape->getTypeModel().maStrokeModel.pushToPropMap(
2381
0
                        aPropMap, rFilterBase.getGraphicHelper());
2382
                    // And, fill-color properties as well...
2383
0
                    pVmlShape->getTypeModel().maFillModel.pushToPropMap(
2384
0
                        aPropMap, rFilterBase.getGraphicHelper());
2385
0
                    PropertySet(xSet).setProperties(aPropMap);
2386
0
                }
2387
64.0k
    }
2388
2389
64.0k
    if (mxShape.is())
2390
64.0k
    {
2391
64.0k
        finalizeXShape( rFilterBase, rxShapes );
2392
2393
64.0k
        if (mpTextBody)
2394
49.2k
        {
2395
            // tdf#151518. The method readjustTextDistances is fix for tdf#148321, but conflicts with
2396
            // text position in some of the SmartArt types in Writer. So exclude Writer here.
2397
49.2k
            OUString sDocumentService;
2398
49.2k
            rFilterBase.getMediaDescriptor()[utl::MediaDescriptor::PROP_DOCUMENTSERVICE] >>= sDocumentService;
2399
49.2k
            if (sDocumentService != u"com.sun.star.text.TextDocument")
2400
49.2k
                mpTextBody->getTextProperties().readjustTextDistances(mxShape);
2401
2402
            // tdf#156857: ooxml files can have shape size with spAutoFit=true and the first priority of
2403
            // shape size is the fix size even if TextAutoGrowHeight is true.
2404
49.2k
            bool bAutoHeight = false;
2405
49.2k
            Reference< XPropertySetInfo > xSetInfo(xSet->getPropertySetInfo());
2406
49.2k
            const OUString& rPropName = PropertyMap::getPropertyName(PROP_TextAutoGrowHeight);
2407
49.2k
            if (xSetInfo.is() && xSetInfo->hasPropertyByName(rPropName))
2408
49.2k
            {
2409
49.2k
                uno::Any aTextAutoGrowHeight = xSet->getPropertyValue(u"TextAutoGrowHeight"_ustr);
2410
49.2k
                aTextAutoGrowHeight >>= bAutoHeight;
2411
49.2k
            }
2412
2413
49.2k
            SdrObject* pShape = SdrObject::getSdrObjectFromXShape(mxShape);
2414
49.2k
            if (pShape && bAutoHeight)
2415
409
            {
2416
409
                tools::Rectangle aAutoSize = pShape->GetLogicRect();
2417
                // little tolerance same as in \svx\source\svdraw\svdoashp.cxx:AdjustTextFrameWidthAndHeight
2418
409
                if (!aOrigSize.IsEmpty() && (std::abs(aOrigSize.GetHeight() - aAutoSize.GetHeight()) > 1 ||
2419
409
                    std::abs(aOrigSize.GetWidth() - aAutoSize.GetWidth()) > 1))
2420
0
                {
2421
0
                    pShape->NbcSetLogicRect(aOrigSize, false);
2422
0
                }
2423
409
            }
2424
49.2k
        }
2425
64.0k
    }
2426
64.0k
    return mxShape;
2427
64.0k
}
2428
2429
void Shape::keepDiagramDrawing(XmlFilterBase& rFilterBase, const OUString& rFragmentPath)
2430
30
{
2431
30
    DiagramHelper_oox* pAdvancedDiagramHelper(getDiagramHelper());
2432
30
    if (nullptr == pAdvancedDiagramHelper)
2433
0
        return;
2434
2435
30
    pAdvancedDiagramHelper->setOOXDomValue(
2436
30
        svx::diagram::DomMapFlag::OOXDrawing,
2437
30
        uno::Any(rFilterBase.importFragment(rFragmentPath)));
2438
30
    pAdvancedDiagramHelper->setOOXDomValue(
2439
30
        svx::diagram::DomMapFlag::OOXDrawingImageRels,
2440
30
        uno::Any(resolveRelationshipsOfTypeFromOfficeDoc(rFilterBase, rFragmentPath, u"image")));
2441
30
    pAdvancedDiagramHelper->setOOXDomValue(
2442
30
        svx::diagram::DomMapFlag::OOXDrawingHlinkRels,
2443
30
        uno::Any(resolveRelationshipsOfTypeFromOfficeDoc(rFilterBase, rFragmentPath, u"hlink")));
2444
30
}
2445
2446
void Shape::convertSmartArtToMetafile(XmlFilterBase const & rFilterBase)
2447
303
{
2448
303
    try
2449
303
    {
2450
303
        Reference<XPropertySet> xSet(mxShape, UNO_QUERY_THROW);
2451
2452
303
        xSet->setPropertyValue(u"MoveProtect"_ustr, Any(true));
2453
303
        xSet->setPropertyValue(u"SizeProtect"_ustr, Any(true));
2454
2455
        // Replace existing shapes with a new Graphic Object rendered
2456
        // from them
2457
303
        Reference<XShape> xShape(renderDiagramToGraphic(rFilterBase));
2458
303
        Reference<XShapes> xShapes(mxShape, UNO_QUERY_THROW);
2459
303
        tools::Rectangle aBackgroundRect
2460
303
            = SdrObject::getSdrObjectFromXShape(
2461
303
                  Reference<XShape>(xShapes->getByIndex(0), UNO_QUERY_THROW))
2462
303
                  ->GetLogicRect();
2463
1.09k
        while (xShapes->hasElements())
2464
789
            xShapes->remove(Reference<XShape>(xShapes->getByIndex(0), UNO_QUERY_THROW));
2465
303
        xShapes->add(xShape);
2466
303
        SdrObject::getSdrObjectFromXShape(
2467
303
            Reference<XShape>(xShapes->getByIndex(0), UNO_QUERY_THROW))
2468
303
            ->NbcSetLogicRect(aBackgroundRect);
2469
303
    }
2470
303
    catch (const Exception&)
2471
303
    {
2472
154
        TOOLS_WARN_EXCEPTION("oox.drawingml", "Shape::convertSmartArtToMetafile");
2473
154
    }
2474
303
}
2475
2476
Reference < XShape > Shape::renderDiagramToGraphic( XmlFilterBase const & rFilterBase )
2477
303
{
2478
303
    Reference< XShape > xShape;
2479
2480
303
    try
2481
303
    {
2482
303
        if( nullptr != getDiagramHelper() )
2483
        // if( !maDiagramDoms.hasElements() )
2484
0
            return xShape;
2485
2486
        // Stream in which to place the rendered shape
2487
303
        SvMemoryStream aTempStream;
2488
303
        Reference < io::XStream > xStream( new utl::OStreamWrapper( aTempStream ) );
2489
303
        Reference < io::XOutputStream > xOutputStream( xStream->getOutputStream() );
2490
2491
        // Size of the rendering
2492
303
        awt::Size aActualSize = mxShape->getSize();
2493
303
        Size aResolution(Application::GetDefaultDevice()->LogicToPixel(Size(100, 100), MapMode(MapUnit::MapCM)));
2494
303
        double fPixelsPer100thmm = static_cast < double > ( aResolution.Width() ) / 100000.0;
2495
303
        awt::Size aSize( static_cast < sal_Int32 > ( ( fPixelsPer100thmm * aActualSize.Width ) + 0.5 ),
2496
303
                         static_cast < sal_Int32 > ( ( fPixelsPer100thmm * aActualSize.Height ) + 0.5 ) );
2497
2498
303
        Sequence< PropertyValue > aFilterData{
2499
303
            comphelper::makePropertyValue(u"PixelWidth"_ustr, aSize.Width),
2500
303
            comphelper::makePropertyValue(u"PixelHeight"_ustr, aSize.Height),
2501
303
            comphelper::makePropertyValue(u"LogicalWidth"_ustr, aActualSize.Width),
2502
303
            comphelper::makePropertyValue(u"LogicalHeight"_ustr, aActualSize.Height)
2503
303
        };
2504
2505
303
        Sequence < PropertyValue > aDescriptor{
2506
303
            comphelper::makePropertyValue(u"OutputStream"_ustr, xOutputStream),
2507
303
            comphelper::makePropertyValue(u"FilterName"_ustr, u"SVM"_ustr), // Rendering format
2508
303
            comphelper::makePropertyValue(u"FilterData"_ustr, aFilterData)
2509
303
        };
2510
2511
303
        Reference < lang::XComponent > xSourceDoc( mxShape, UNO_QUERY_THROW );
2512
303
        Reference < XGraphicExportFilter > xGraphicExporter = GraphicExportFilter::create( rFilterBase.getComponentContext() );
2513
303
        xGraphicExporter->setSourceDocument( xSourceDoc );
2514
303
        xGraphicExporter->filter( aDescriptor );
2515
2516
303
        aTempStream.Seek( STREAM_SEEK_TO_BEGIN );
2517
2518
303
        Graphic aGraphic;
2519
303
        GraphicFilter aFilter;
2520
303
        if ( aFilter.ImportGraphic( aGraphic, u"", aTempStream, GRFILTER_FORMAT_NOTFOUND, nullptr, GraphicFilterImportFlags::NONE ) != ERRCODE_NONE )
2521
0
        {
2522
0
            SAL_WARN( "oox.drawingml", "Shape::renderDiagramToGraphic: Unable to import rendered stream into graphic object" );
2523
0
            return xShape;
2524
0
        }
2525
2526
303
        Reference < graphic::XGraphic > xGraphic( aGraphic.GetXGraphic() );
2527
303
        Reference < lang::XMultiServiceFactory > xServiceFact( rFilterBase.getModel(), UNO_QUERY_THROW );
2528
303
        xShape.set( xServiceFact->createInstance( u"com.sun.star.drawing.GraphicObjectShape"_ustr ), UNO_QUERY_THROW );
2529
303
        Reference < XPropertySet > xPropSet( xShape, UNO_QUERY_THROW );
2530
303
        xPropSet->setPropertyValue(  u"Graphic"_ustr, Any( xGraphic ) );
2531
303
        xPropSet->setPropertyValue(  u"MoveProtect"_ustr, Any( true ) );
2532
303
        xPropSet->setPropertyValue(  u"SizeProtect"_ustr, Any( true ) );
2533
303
        xPropSet->setPropertyValue(  u"Name"_ustr, Any( u"RenderedShapes"_ustr ) );
2534
303
    }
2535
303
    catch( const Exception& )
2536
303
    {
2537
0
        TOOLS_WARN_EXCEPTION( "oox.drawingml", "Shape::renderDiagramToGraphic" );
2538
0
    }
2539
2540
303
    return xShape;
2541
303
}
2542
2543
void Shape::setTextBody(const TextBodyPtr & pTextBody)
2544
89.8k
{
2545
89.8k
    mpTextBody = pTextBody;
2546
89.8k
}
2547
2548
void Shape::setMasterTextListStyle( const TextListStylePtr& pMasterTextListStyle )
2549
94.6k
{
2550
94.6k
    SAL_INFO("oox.drawingml", "Shape::setMasterTextListStyle: Set master text list style to shape id='" << msId << "'");
2551
2552
94.6k
    mpMasterTextListStyle = pMasterTextListStyle;
2553
94.6k
}
2554
2555
OUString Shape::finalizeServiceName( XmlFilterBase& rFilter, const OUString& rServiceName, const awt::Rectangle& rShapeRect )
2556
64.0k
{
2557
64.0k
    OUString aServiceName = rServiceName;
2558
64.0k
    switch( meFrameType )
2559
64.0k
    {
2560
0
        case FRAMETYPE_OLEOBJECT:
2561
0
        {
2562
0
            awt::Size aOleSize( rShapeRect.Width, rShapeRect.Height );
2563
0
            if( rFilter.getOleObjectHelper().importOleObject( maShapeProperties, *mxOleObjectInfo, aOleSize ) )
2564
0
                aServiceName = "com.sun.star.drawing.OLE2Shape";
2565
2566
            // get the path to the representation graphic
2567
0
            OUString aGraphicPath;
2568
0
            if( !mxOleObjectInfo->maShapeId.isEmpty() )
2569
0
                if( ::oox::vml::Drawing* pVmlDrawing = rFilter.getVmlDrawing() )
2570
0
                    if( const ::oox::vml::ShapeBase* pVmlShape = pVmlDrawing->getShapes().getShapeById( mxOleObjectInfo->maShapeId ) )
2571
0
                        aGraphicPath = pVmlShape->getGraphicPath();
2572
2573
            // import and store the graphic
2574
0
            if( !aGraphicPath.isEmpty() )
2575
0
            {
2576
                // Transfer shape's width and height to graphicsfilter (can be used by WMF/EMF)
2577
0
                WmfExternal aExtHeader;
2578
0
                aExtHeader.mapMode = 8; // MM_ANISOTROPIC
2579
0
                aExtHeader.xExt = rShapeRect.Width;
2580
0
                aExtHeader.yExt = rShapeRect.Height;
2581
2582
0
                Reference< graphic::XGraphic > xGraphic = rFilter.getGraphicHelper().importEmbeddedGraphic( aGraphicPath, &aExtHeader );
2583
0
                if( xGraphic.is() )
2584
0
                    maShapeProperties.setProperty(PROP_Graphic, xGraphic);
2585
0
            }
2586
0
        }
2587
0
        break;
2588
2589
64.0k
        default:;
2590
64.0k
    }
2591
64.0k
    return aServiceName;
2592
64.0k
}
2593
2594
void Shape::finalizeXShape( XmlFilterBase& rFilter, const Reference< XShapes >& rxShapes )
2595
64.0k
{
2596
64.0k
    switch( meFrameType )
2597
64.0k
    {
2598
430
        case FRAMETYPE_CHART:
2599
430
        {
2600
430
            OSL_ENSURE( !mxChartShapeInfo->maFragmentPath.isEmpty(), "Shape::finalizeXShape - missing chart fragment" );
2601
430
            if( mxShape.is() && !mxChartShapeInfo->maFragmentPath.isEmpty() ) try
2602
397
            {
2603
                // set the chart2 OLE class ID at the OLE shape
2604
397
                PropertySet aShapeProp( mxShape );
2605
397
                aShapeProp.setProperty( PROP_CLSID, u"12dcae26-281f-416f-a234-c3086127382e"_ustr );
2606
2607
                // get the XModel interface of the embedded object from the OLE shape
2608
397
                Reference< frame::XModel > xDocModel;
2609
397
                aShapeProp.getProperty( xDocModel, PROP_Model );
2610
397
                Reference< chart2::XChartDocument > xChartDoc( xDocModel, UNO_QUERY_THROW );
2611
2612
                // load the chart data from the XML fragment
2613
#if ENABLE_WASM_STRIP_CHART
2614
                (void) rFilter;
2615
                (void) rxShapes;
2616
#else
2617
                // WASM_CHART change
2618
                // TODO: Instead of using convertFromModel an alternative may be
2619
                // added to convert not to Chart/OLE SdrObejct, but to GraphicObject
2620
                // with the Chart visualization. There should be a preview available
2621
                // in the imported chart data
2622
397
                bool bMSO2007Doc = rFilter.isMSO2007Document();
2623
397
                chart::ChartSpaceModel aModel(bMSO2007Doc);
2624
397
                oox::ppt::PowerPointImport* pPowerPointImport
2625
397
                    = dynamic_cast<oox::ppt::PowerPointImport*>(&rFilter);
2626
2627
397
                ClrMapPtr pClrMap; // The original color map
2628
397
                if (pPowerPointImport)
2629
0
                {
2630
                    // Use a copy of current color map, which the fragment may override locally
2631
0
                    pClrMap = pPowerPointImport->getActualSlidePersist()->getClrMap();
2632
0
                    aModel.mpClrMap = pClrMap ? std::make_shared<ClrMap>(*pClrMap)
2633
0
                                              : std::make_shared<ClrMap>();
2634
0
                    pPowerPointImport->getActualSlidePersist()->setClrMap(aModel.mpClrMap);
2635
0
                }
2636
2637
397
                rtl::Reference<chart::ChartSpaceFragment> pChartSpaceFragment = new chart::ChartSpaceFragment(
2638
397
                        rFilter, mxChartShapeInfo->maFragmentPath, aModel );
2639
397
                rFilter.importFragment( pChartSpaceFragment );
2640
2641
                // Import styles file.
2642
                // Create the styles path from the path to the chart*.xml file
2643
397
                sal_Int32 nLastSlash = mxChartShapeInfo->maFragmentPath.lastIndexOf('/');
2644
397
                const sal_Unicode *pFPath = mxChartShapeInfo->maFragmentPath.getStr();
2645
397
                OUString sStylePath(pFPath, nLastSlash + 1);
2646
397
                const OUString sFullPath(pFPath);
2647
397
                sStylePath += u"style"_ustr;
2648
397
                OUString sChartFName(sFullPath.copy(nLastSlash + 1, sFullPath.getLength() - nLastSlash - 1));
2649
397
                OUString sTail;
2650
                // Verify that the path is the way we expect it, and extract the
2651
                // end bit. Don't put the startsWith() call inside an assert,
2652
                // because we don't want it optimized away.
2653
397
                const bool bWellFormed = sChartFName.startsWith(std::u16string_view(u"chart"), &sTail);
2654
397
                if (!bWellFormed) {
2655
0
                    assert(false);
2656
0
                }
2657
                // We should have something of the form 'chart1234.xml'. We
2658
                // want to get the numeric ('1234') part, since it should be
2659
                // the same for the style file.
2660
397
                sal_Int32 nPeriod = sTail.indexOf('.');
2661
397
                OUString sNumber(sTail.copy(0, nPeriod));
2662
2663
397
                sStylePath += sNumber;
2664
397
                sStylePath += u".xml"_ustr;
2665
2666
397
                chart::StyleModel aStyleModel;
2667
397
                rtl::Reference<chart::StyleFragment> pStyleFragment = new chart::StyleFragment(
2668
397
                        rFilter, sStylePath, aStyleModel );
2669
397
                rFilter.importFragment( pStyleFragment );
2670
2671
                // Import colors file.
2672
397
                OUString sColorPath(pFPath, nLastSlash + 1);
2673
397
                sColorPath += u"colors"_ustr;
2674
397
                sChartFName = sFullPath.copy(nLastSlash + 1, sFullPath.getLength() - nLastSlash - 1);
2675
397
                sColorPath += sNumber;
2676
397
                sColorPath += u".xml"_ustr;
2677
2678
397
                chart::ColorStyleModel aColorsModel;
2679
397
                rtl::Reference<chart::ColorsFragment> pColorsFragment =
2680
397
                    new chart::ColorsFragment( rFilter, sColorPath, aColorsModel );
2681
397
                rFilter.importFragment( pColorsFragment );
2682
2683
2684
                // The original theme.
2685
397
                ThemePtr pTheme;
2686
397
                const OUString aThemeOverrideFragmentPath( pChartSpaceFragment->
2687
397
                        getFragmentPathFromFirstTypeFromOfficeDoc(u"themeOverride") );
2688
2689
397
                if (!aThemeOverrideFragmentPath.isEmpty() && pPowerPointImport)
2690
0
                {
2691
                    // Handle theme override.
2692
0
                    uno::Reference< xml::sax::XFastSAXSerializable > xDoc(
2693
0
                            rFilter.importFragment(aThemeOverrideFragmentPath), uno::UNO_QUERY_THROW);
2694
0
                    pTheme = pPowerPointImport->getActualSlidePersist()->getTheme();
2695
0
                    auto pThemeOverride = std::make_shared<Theme>(*pTheme);
2696
0
                    rFilter.importFragment(
2697
0
                        new ThemeOverrideFragmentHandler(rFilter, aThemeOverrideFragmentPath, *pThemeOverride, *pThemeOverride->getTheme()),
2698
0
                        xDoc);
2699
0
                    pPowerPointImport->getActualSlidePersist()->setTheme(pThemeOverride);
2700
0
                }
2701
2702
                // convert imported chart model to chart document
2703
397
                Reference< drawing::XShapes > xExternalPage;
2704
397
                if( !mxChartShapeInfo->mbEmbedShapes )
2705
0
                    xExternalPage = rxShapes;
2706
2707
                // There are several calls to rFilter.getChartConverter() here.
2708
                // Doing just one call and storing the result, as in
2709
                //     chart::ChartConverter *pChartConv = rFilter.getChartConverter();
2710
                // *doesn't work* (tests crash).
2711
397
                if( rFilter.getChartConverter() )
2712
0
                {
2713
0
                    rFilter.getChartConverter()->convertFromModel( rFilter, aModel, xChartDoc, xExternalPage, mxShape->getPosition(), mxShape->getSize() );
2714
0
                    if( !xChartDoc->hasInternalDataProvider() )
2715
0
                    {
2716
0
                        Reference< chart2::data::XDataReceiver > xDataRec( xChartDoc, UNO_QUERY );
2717
0
                        Reference< chart2::data::XDataSource > xData = xDataRec->getUsedData();
2718
0
                        if( !xData->getDataSequences().hasElements() || !xData->getDataSequences()[0]->getValues().is() ||
2719
0
                                !xData->getDataSequences()[0]->getValues()->getData().hasElements() )
2720
0
                        {
2721
0
                            rFilter.useInternalChartDataTable( true );
2722
0
                            rFilter.getChartConverter()->convertFromModel( rFilter, aModel, xChartDoc, xExternalPage, mxShape->getPosition(), mxShape->getSize() );
2723
0
                            rFilter.useInternalChartDataTable( false );
2724
0
                        }
2725
0
                    }
2726
2727
0
                }
2728
2729
                // convert chart style model to docmodel style data
2730
397
                Reference<com::sun::star::chart2::XChartStyle> xStyle = xChartDoc->getStyles();
2731
397
                oox::drawingml::chart::ChartStyleConverter::convertFromModel(rFilter, aStyleModel, xStyle);
2732
                // convert color style model to docmodel colors data
2733
397
                Reference<com::sun::star::chart2::XChartColorStyle> xCStyle = xChartDoc->getColorStyles();
2734
397
                oox::drawingml::chart::ChartColorStyleConverter::convertFromModel(rFilter, aColorsModel, xCStyle);
2735
2736
397
                if (pPowerPointImport)
2737
0
                {
2738
0
                    if (!aThemeOverrideFragmentPath.isEmpty())
2739
0
                    {
2740
                        // Restore the original theme.
2741
0
                        pPowerPointImport->getActualSlidePersist()->setTheme(pTheme);
2742
0
                    }
2743
                    // Restore the original color map
2744
0
                    pPowerPointImport->getActualSlidePersist()->setClrMap(std::move(pClrMap));
2745
0
                }
2746
397
#endif
2747
397
            }
2748
397
            catch( Exception& )
2749
397
            {
2750
397
            }
2751
430
        }
2752
430
        break;
2753
2754
63.6k
        default:;
2755
64.0k
    }
2756
64.0k
}
2757
2758
void Shape::putPropertyToGrabBag( const OUString& sPropertyName, const Any& aPropertyValue )
2759
76.0k
{
2760
76.0k
    PropertyValue aNewProperty;
2761
76.0k
    aNewProperty.Name = sPropertyName;
2762
76.0k
    aNewProperty.Value = aPropertyValue;
2763
76.0k
    putPropertyToGrabBag( aNewProperty );
2764
76.0k
}
2765
2766
void Shape::putPropertyToGrabBag( const PropertyValue& pProperty )
2767
76.0k
{
2768
76.0k
    Reference< XPropertySet > xSet( mxShape, UNO_QUERY );
2769
76.0k
    Reference< XPropertySetInfo > xSetInfo( xSet->getPropertySetInfo() );
2770
76.0k
    const OUString aGrabBagPropName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG;
2771
76.0k
    if( mxShape.is() && xSet.is() && xSetInfo.is() && xSetInfo->hasPropertyByName( aGrabBagPropName ) )
2772
37.1k
    {
2773
37.1k
        Sequence< PropertyValue > aGrabBag;
2774
37.1k
        xSet->getPropertyValue( aGrabBagPropName ) >>= aGrabBag;
2775
2776
37.1k
        sal_Int32 length = aGrabBag.getLength();
2777
37.1k
        aGrabBag.realloc( length + 1 );
2778
37.1k
        aGrabBag.getArray()[length] = pProperty;
2779
2780
37.1k
        xSet->setPropertyValue( aGrabBagPropName, Any( aGrabBag ) );
2781
37.1k
    }
2782
76.0k
}
2783
2784
void Shape::putPropertiesToGrabBag( const Sequence< PropertyValue >& aProperties )
2785
63.4k
{
2786
63.4k
    Reference< XPropertySet > xSet( mxShape, UNO_QUERY );
2787
63.4k
    Reference< XPropertySetInfo > xSetInfo( xSet->getPropertySetInfo() );
2788
63.4k
    const OUString aGrabBagPropName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG;
2789
63.4k
    if( !(mxShape.is() && xSet.is() && xSetInfo.is() && xSetInfo->hasPropertyByName( aGrabBagPropName )) )
2790
38.9k
        return;
2791
2792
    // get existing grab bag
2793
24.5k
    Sequence< PropertyValue > aGrabBag;
2794
24.5k
    xSet->getPropertyValue( aGrabBagPropName ) >>= aGrabBag;
2795
2796
24.5k
    std::vector<PropertyValue> aVec;
2797
24.5k
    aVec.reserve(aProperties.getLength());
2798
2799
    // put the new items
2800
24.5k
    std::transform(aProperties.begin(), aProperties.end(), std::back_inserter(aVec),
2801
87.2k
        [](const PropertyValue& rProp) {
2802
87.2k
            PropertyValue aProp;
2803
87.2k
            aProp.Name = rProp.Name;
2804
87.2k
            aProp.Value = rProp.Value;
2805
87.2k
            return aProp;
2806
87.2k
        });
2807
2808
    // put it back to the shape
2809
24.5k
    xSet->setPropertyValue( aGrabBagPropName, Any( comphelper::concatSequences(aGrabBag, aVec) ) );
2810
24.5k
}
2811
2812
FillProperties Shape::getActualFillProperties(const Theme* pTheme, const FillProperties* pParentShapeFillProps) const
2813
86.9k
{
2814
86.9k
    FillProperties aFillProperties;
2815
86.9k
    aFillProperties.moFillType = XML_noFill;
2816
2817
    // Reference shape properties
2818
86.9k
    aFillProperties.assignUsed( *mpShapeRefFillPropPtr );
2819
2820
    // Theme
2821
86.9k
    if( pTheme != nullptr )
2822
61.5k
    {
2823
61.5k
        if( const ShapeStyleRef* pFillRef = getShapeStyleRef( XML_fillRef ) )
2824
3.16k
        {
2825
3.16k
            if( const FillProperties* pFillProps = pTheme->getFillStyle( pFillRef->mnThemedIdx ) )
2826
778
                aFillProperties.assignUsed( *pFillProps );
2827
3.16k
        }
2828
61.5k
    }
2829
2830
    // Properties specified directly for this shape
2831
86.9k
    aFillProperties.assignUsed(getFillProperties());
2832
2833
    // Parent shape's properties
2834
86.9k
    if ( pParentShapeFillProps != nullptr)
2835
64.0k
        if( getFillProperties().moFillType.has_value() && getFillProperties().moFillType.value() == XML_grpFill )
2836
6
            aFillProperties.assignUsed( *pParentShapeFillProps );
2837
2838
86.9k
    return aFillProperties;
2839
86.9k
}
2840
2841
LineProperties Shape::getActualLineProperties(const Theme* pTheme) const
2842
86.9k
{
2843
86.9k
    LineProperties aLineProperties;
2844
86.9k
    aLineProperties.maLineFill.moFillType = XML_noFill;
2845
2846
    // Reference shape properties
2847
86.9k
    aLineProperties.assignUsed( *mpShapeRefLinePropPtr );
2848
2849
    // Theme
2850
86.9k
    if( pTheme != nullptr )
2851
61.5k
    {
2852
61.5k
        if( const ShapeStyleRef* pLineRef = getShapeStyleRef( XML_lnRef ) )
2853
3.16k
        {
2854
3.16k
            if( const LineProperties* pLineProps = pTheme->getLineStyle( pLineRef->mnThemedIdx ) )
2855
954
                aLineProperties.assignUsed( *pLineProps );
2856
3.16k
        }
2857
61.5k
    }
2858
2859
    // Properties specified directly for this shape
2860
86.9k
    aLineProperties.assignUsed( getLineProperties() );
2861
2862
86.9k
    return aLineProperties;
2863
86.9k
}
2864
2865
EffectProperties Shape::getActualEffectProperties(const Theme* pTheme) const
2866
86.9k
{
2867
86.9k
    EffectProperties aEffectProperties;
2868
2869
    // Reference shape properties
2870
86.9k
    aEffectProperties.assignUsed( *mpShapeRefEffectPropPtr );
2871
2872
    // Theme
2873
86.9k
    if( pTheme != nullptr )
2874
61.5k
    {
2875
61.5k
        if( const ShapeStyleRef* pEffectRef = getShapeStyleRef( XML_effectRef ) )
2876
3.16k
        {
2877
3.16k
            if( const EffectProperties* pEffectProps = pTheme->getEffectStyle( pEffectRef->mnThemedIdx ) )
2878
51
                aEffectProperties.assignUsed( *pEffectProps );
2879
3.16k
        }
2880
61.5k
    }
2881
2882
    // Properties specified directly for this shape
2883
86.9k
    aEffectProperties.assignUsed ( getEffectProperties() );
2884
2885
86.9k
    return aEffectProperties;
2886
86.9k
}
2887
2888
uno::Sequence< uno::Sequence< uno::Any > >  Shape::resolveRelationshipsOfTypeFromOfficeDoc(core::XmlFilterBase& rFilter, const OUString& sFragment, std::u16string_view sType )
2889
812
{
2890
812
    uno::Sequence< uno::Sequence< uno::Any > > xRelListTemp;
2891
812
    sal_Int32 counter = 0;
2892
2893
812
    core::RelationsRef xRels = rFilter.importRelations( sFragment );
2894
812
    if ( xRels )
2895
812
    {
2896
812
        if (sType == u"image")
2897
406
        {
2898
406
            core::RelationsRef xImageRels = xRels->getRelationsFromTypeFromOfficeDoc(sType);
2899
406
            if (xImageRels)
2900
406
            {
2901
406
                xRelListTemp.realloc(xImageRels->size());
2902
406
                auto pxRelListTemp = xRelListTemp.getArray();
2903
406
                for (auto const& imageRel : *xImageRels)
2904
0
                {
2905
0
                    uno::Sequence<uno::Any> diagramRelTuple(3);
2906
0
                    auto pdiagramRelTuple = diagramRelTuple.getArray();
2907
                    // [0] => RID, [1] => InputStream [2] => extension
2908
0
                    OUString sRelId = imageRel.second.maId;
2909
2910
0
                    pdiagramRelTuple[0] <<= sRelId;
2911
0
                    OUString sTarget = xImageRels->getFragmentPathFromRelId(sRelId);
2912
2913
0
                    uno::Reference<io::XInputStream> xImageInputStrm(
2914
0
                        rFilter.openInputStream(sTarget), uno::UNO_SET_THROW);
2915
0
                    StreamDataSequence dataSeq;
2916
0
                    if (rFilter.importBinaryData(dataSeq, sTarget))
2917
0
                    {
2918
0
                        pdiagramRelTuple[1] <<= dataSeq;
2919
0
                    }
2920
2921
0
                    pdiagramRelTuple[2] <<= sTarget.copy(sTarget.lastIndexOf("."));
2922
2923
0
                    pxRelListTemp[counter] = std::move(diagramRelTuple);
2924
0
                    ++counter;
2925
0
                }
2926
406
            }
2927
406
        }
2928
406
        else if (sType == u"hlink")
2929
406
        {
2930
            // Hyperlink can be internal or external
2931
406
            core::RelationsRef xSlideRels = xRels->getRelationsFromTypeFromOfficeDoc(u"slide");
2932
406
            core::RelationsRef xHlinkRels = xRels->getRelationsFromTypeFromOfficeDoc(u"hyperlink");
2933
2934
406
            sal_Int32 totalSize
2935
406
                = (xSlideRels ? xSlideRels->size() : 0) + (xHlinkRels ? xHlinkRels->size() : 0);
2936
406
            xRelListTemp.realloc(totalSize);
2937
406
            auto pxRelListTemp = xRelListTemp.getArray();
2938
2939
            // Helper to create relation tuple
2940
406
            auto addRelation = [&](const auto& rel, const OUString& relType)
2941
406
            {
2942
0
                uno::Sequence<uno::Any> tuple(3);
2943
0
                auto pTuple = tuple.getArray();
2944
0
                pTuple[0] <<= rel.second.maId;
2945
0
                pTuple[1] <<= rel.second.maTarget;
2946
0
                pTuple[2] <<= relType;
2947
0
                pxRelListTemp[counter++] = std::move(tuple);
2948
0
            };
2949
2950
406
            if (xSlideRels)
2951
406
            {
2952
406
                for (auto const& slideRel : *xSlideRels)
2953
0
                    addRelation(slideRel, "slide");
2954
406
            }
2955
406
            if (xHlinkRels)
2956
406
            {
2957
406
                for (auto const& hlinkRel : *xHlinkRels)
2958
0
                    addRelation(hlinkRel, "hyperlink");
2959
406
            }
2960
406
        }
2961
812
        xRelListTemp.realloc(counter);
2962
812
    }
2963
812
    return xRelListTemp;
2964
812
}
2965
2966
void Shape::cloneFillProperties()
2967
532
{
2968
532
    auto pFillProperties = std::make_shared<FillProperties>();
2969
532
    pFillProperties->assignUsed(*mpFillPropertiesPtr);
2970
532
    mpFillPropertiesPtr = std::move(pFillProperties);
2971
532
}
2972
}
2973
2974
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */