Coverage Report

Created: 2026-06-30 11:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/oox/source/ppt/slidepersist.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 <basegfx/matrix/b2dhommatrix.hxx>
21
#include <com/sun/star/drawing/XDrawPage.hpp>
22
#include <com/sun/star/text/XTextRange.hpp>
23
#include <com/sun/star/drawing/XShapes.hpp>
24
#include <com/sun/star/frame/XModel.hpp>
25
#include <oox/ppt/timenode.hxx>
26
#include <oox/ppt/pptshape.hxx>
27
#include <oox/ppt/slidepersist.hxx>
28
#include <drawingml/fillproperties.hxx>
29
#include <oox/drawingml/shapepropertymap.hxx>
30
#include <oox/helper/propertymap.hxx>
31
#include <oox/helper/propertyset.hxx>
32
#include <oox/vml/vmldrawing.hxx>
33
#include <oox/token/properties.hxx>
34
#include <oox/token/tokens.hxx>
35
#include <oox/core/xmlfilterbase.hxx>
36
#include <drawingml/textbody.hxx>
37
#include <drawingml/textliststyle.hxx>
38
#include <drawingml/textparagraphproperties.hxx>
39
#include <drawingml/connectorhelper.hxx>
40
41
#include <osl/diagnose.h>
42
43
#include <com/sun/star/style/XStyle.hpp>
44
#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
45
#include <com/sun/star/container/XNamed.hpp>
46
#include <com/sun/star/animations/XAnimationNodeSupplier.hpp>
47
#include <com/sun/star/drawing/XGluePointsSupplier.hpp>
48
#include <com/sun/star/container/XIdentifierContainer.hpp>
49
#include <com/sun/star/drawing/EnhancedCustomShapeGluePointType.hpp>
50
#include <com/sun/star/drawing/ConnectorType.hpp>
51
#include <utility>
52
#include <svx/svdobj.hxx>
53
#include <svx/svdmodel.hxx>
54
55
using namespace ::com::sun::star;
56
using namespace ::oox::core;
57
using namespace ::com::sun::star::uno;
58
using namespace ::com::sun::star::drawing;
59
using namespace ::com::sun::star::container;
60
using namespace ::com::sun::star::animations;
61
62
63
namespace oox::ppt {
64
65
SlidePersist::SlidePersist( XmlFilterBase& rFilter, bool bMaster, bool bNotes,
66
    const css::uno::Reference< css::drawing::XDrawPage >& rxPage,
67
        oox::drawingml::ShapePtr pShapesPtr, drawingml::TextListStylePtr pDefaultTextStyle )
68
22.0k
: mpDrawingPtr( std::make_shared<oox::vml::Drawing>( rFilter, rxPage, oox::vml::VMLDRAWING_POWERPOINT ) )
69
22.0k
, mxPage( rxPage )
70
22.0k
, maShapesPtr(std::move( pShapesPtr ))
71
22.0k
, mnLayoutValueToken( 0 )
72
22.0k
, mbMaster( bMaster )
73
22.0k
, mbNotes ( bNotes )
74
22.0k
, maDefaultTextStylePtr(std::move( pDefaultTextStyle ))
75
22.0k
, maTitleTextStylePtr( std::make_shared<oox::drawingml::TextListStyle>() )
76
22.0k
, maBodyTextStylePtr( std::make_shared<oox::drawingml::TextListStyle>() )
77
22.0k
, maNotesTextStylePtr( std::make_shared<oox::drawingml::TextListStyle>() )
78
22.0k
, maOtherTextStylePtr( std::make_shared<oox::drawingml::TextListStyle>() )
79
22.0k
{
80
#if OSL_DEBUG_LEVEL > 0
81
    mxDebugPage = mxPage;
82
#endif
83
22.0k
}
84
85
#if OSL_DEBUG_LEVEL > 0
86
css::uno::WeakReference< css::drawing::XDrawPage > SlidePersist::mxDebugPage;
87
#endif
88
89
SlidePersist::~SlidePersist()
90
22.0k
{
91
22.0k
}
92
93
void SlidePersist::releaseShapes()
94
4.78k
{
95
4.78k
    for (const auto& [sId, pShape] : maShapeMap)
96
5.68k
    {
97
5.68k
        if (pShape
98
5.68k
            && (pShape->getSubType() == XML_title || pShape->getSubType() == XML_ctrTitle))
99
300
        {
100
300
            css::uno::Reference<css::text::XTextRange> xText(pShape->getXShape(), css::uno::UNO_QUERY);
101
300
            if (xText.is())
102
300
                maTitleText = xText->getString();
103
300
            if (!maTitleText.isEmpty())
104
146
                break;
105
300
        }
106
5.68k
    }
107
4.78k
    maShapesPtr.reset();
108
4.78k
    maShapeMap.clear();
109
4.78k
    mpBackgroundPropertiesPtr.reset();
110
4.78k
}
111
112
// the list 'const PPTXLayoutInfo aLayoutInfo[...]' used in PowerPointExport
113
// likely needs to be updated after any changes here
114
sal_Int16 SlidePersist::getLayoutFromValueToken() const
115
19.5k
{
116
19.5k
    sal_Int16 nLayout = 20;     // 20 == blank (so many magic numbers :-( the description at com.sun.star.presentation.DrawPage.Layout does not help)
117
19.5k
    switch( mnLayoutValueToken )
118
19.5k
    {
119
1.69k
        case XML_blank:             nLayout = 20; break;
120
15
        case XML_chart:             nLayout =  2; break;
121
0
        case XML_chartAndTx:        nLayout =  7; break;
122
0
        case XML_clipArtAndTx:      nLayout =  9; break;
123
0
        case XML_clipArtAndVertTx:  nLayout = 30; break;
124
473
        case XML_fourObj:           nLayout = 18; break;
125
1.08k
        case XML_obj:               nLayout = 11; break;
126
0
        case XML_objAndTx:          nLayout = 13; break;
127
450
        case XML_objOverTx:         nLayout = 14; break;
128
0
        case XML_tbl:               nLayout =  8; break;
129
2.09k
        case XML_title:             nLayout =  0; break;
130
962
        case XML_titleOnly:         nLayout = 19; break;
131
877
        case XML_twoObj:
132
877
        case XML_twoColTx:          nLayout =  3; break;
133
471
        case XML_twoObjAndObj:
134
471
        case XML_twoObjAndTx:       nLayout = 15; break;
135
471
        case XML_twoObjOverTx:      nLayout = 16; break;
136
621
        case XML_tx:                nLayout =  1; break;
137
0
        case XML_txAndChart:        nLayout =  4; break;
138
0
        case XML_txAndClipArt:
139
0
        case XML_txAndMedia:        nLayout =  6; break;
140
0
        case XML_txAndObj:          nLayout = 10; break;
141
460
        case XML_objAndTwoObj:
142
460
        case XML_txAndTwoObj:       nLayout = 12; break;
143
0
        case XML_txOverObj:         nLayout = 17; break;
144
442
        case XML_vertTitleAndTx:    nLayout = 28; break;
145
0
        case XML_vertTitleAndTxOverChart: nLayout = 27; break;
146
410
        case XML_vertTx:            nLayout = 29; break;
147
439
        case XML_objOnly:           nLayout = 32; break;
148
149
390
        case XML_twoTxTwoObj:
150
819
        case XML_objTx:
151
1.21k
        case XML_picTx:
152
1.64k
        case XML_secHead:
153
1.64k
        case XML_mediaAndTx:
154
1.64k
        case XML_dgm:
155
1.64k
        case XML_cust:
156
8.56k
        default:
157
8.56k
            nLayout = 20;
158
19.5k
    }
159
19.5k
    return nLayout;
160
19.5k
}
161
162
static void lcl_createShapeMap(oox::drawingml::ShapePtr rShapePtr,
163
                               oox::drawingml::ShapeIdMap& rShapeMap)
164
57.3k
{
165
57.3k
    std::vector<oox::drawingml::ShapePtr>& rChildren = rShapePtr->getChildren();
166
57.3k
    if (!rChildren.empty())
167
12
    {
168
12
        for (const auto& pIt : rChildren)
169
24
        {
170
24
            if (pIt->isConnectorShape())
171
6
            {
172
6
                rShapeMap[pIt->getId()] = pIt; // add child itself
173
6
                lcl_createShapeMap(pIt, rShapeMap); // and all its descendants
174
6
            }
175
24
        }
176
12
    }
177
57.3k
    else
178
57.3k
    {
179
57.3k
        if(rShapePtr->isConnectorShape())
180
159
            rShapeMap[rShapePtr->getId()] = rShapePtr;
181
57.3k
    }
182
57.3k
}
183
184
void SlidePersist::createXShapes( XmlFilterBase& rFilterBase )
185
21.6k
{
186
21.6k
    applyTextStyles( rFilterBase );
187
188
21.6k
    Reference< XShapes > xShapes( getPage() );
189
21.6k
    std::vector< oox::drawingml::ShapePtr >& rShapes( maShapesPtr->getChildren() );
190
21.6k
    oox::drawingml::ShapeIdMap aConnectorShapeMap;
191
192
21.6k
    for (auto const& shape : rShapes)
193
22.5k
    {
194
22.5k
        std::vector< oox::drawingml::ShapePtr >& rChildren( shape->getChildren() );
195
22.5k
        for (auto const& child : rChildren)
196
93.8k
        {
197
93.8k
            PPTShape* pPPTShape = dynamic_cast< PPTShape* >( child.get() );
198
93.8k
            basegfx::B2DHomMatrix aTransformation;
199
93.8k
            if ( pPPTShape )
200
93.8k
            {
201
93.8k
                pPPTShape->addShape( rFilterBase, *this, getTheme().get(), xShapes, aTransformation, &getShapeMap() );
202
203
93.8k
                const auto pIter = maShapeMap.find(pPPTShape->getId());
204
93.8k
                if (pIter != maShapeMap.end())
205
57.3k
                    lcl_createShapeMap(pIter->second, aConnectorShapeMap);
206
93.8k
            }
207
0
            else
208
0
                child->addShape( rFilterBase, getTheme().get(), xShapes, aTransformation, maShapesPtr->getFillProperties(), &getShapeMap() );
209
93.8k
        }
210
22.5k
    }
211
212
21.6k
    if (!aConnectorShapeMap.empty())
213
55
    {
214
55
        for (auto& pIt : aConnectorShapeMap)
215
159
        {
216
159
            ConnectorHelper::applyConnections(pIt.second, getShapeMap());
217
218
159
            SdrObject* pObj = SdrObject::getSdrObjectFromXShape(pIt.second->getXShape());
219
159
            SdrModel& rModel(pObj->getSdrModelFromSdrObject());
220
159
            rModel.setLock(false);
221
222
159
            if (pIt.second->getConnectorName() == u"bentConnector3"_ustr
223
159
                || pIt.second->getConnectorName() == u"bentConnector4"_ustr
224
159
                || pIt.second->getConnectorName() == u"bentConnector5"_ustr)
225
0
            {
226
0
                ConnectorHelper::applyBentHandleAdjustments(pIt.second);
227
0
            }
228
159
            else if (pIt.second->getConnectorName() == u"curvedConnector3"_ustr
229
159
                     || pIt.second->getConnectorName() == u"curvedConnector4"_ustr
230
159
                     || pIt.second->getConnectorName() == u"curvedConnector5"_ustr)
231
0
            {
232
0
                ConnectorHelper::applyCurvedHandleAdjustments(pIt.second);
233
0
            }
234
159
            else // bentConnector2
235
159
                createConnectorShapeConnection(pIt.second);
236
159
        }
237
55
    }
238
239
21.6k
    Reference< XAnimationNodeSupplier > xNodeSupplier( getPage(), UNO_QUERY);
240
21.6k
    if( !xNodeSupplier.is() )
241
117
        return;
242
243
21.5k
    Reference< XAnimationNode > xNode( xNodeSupplier->getAnimationNode() );
244
21.5k
    if( xNode.is() && !maTimeNodeList.empty() )
245
815
    {
246
815
        SlidePersistPtr pSlidePtr( shared_from_this() );
247
815
        TimeNodePtr pNode(maTimeNodeList.front());
248
815
        OSL_ENSURE( pNode, "pNode" );
249
250
815
        Reference<XAnimationNode> xDummy;
251
815
        pNode->setNode(rFilterBase, xNode, pSlidePtr, xDummy);
252
815
    }
253
21.5k
}
254
255
void SlidePersist::createBackground( const XmlFilterBase& rFilterBase )
256
21.6k
{
257
21.6k
    if ( mpBackgroundPropertiesPtr )
258
5.77k
    {
259
5.77k
        ::Color nPhClr = maBackgroundColor.isUsed() ?
260
3.68k
            maBackgroundColor.getColor( rFilterBase.getGraphicHelper() ) : API_RGB_TRANSPARENT;
261
262
5.77k
        css::awt::Size aSize;
263
5.77k
        Reference< css::beans::XPropertySet > xSet(mxPage, UNO_QUERY);
264
5.77k
        xSet->getPropertyValue(u"Width"_ustr) >>= aSize.Width;
265
5.77k
        xSet->getPropertyValue(u"Height"_ustr) >>= aSize.Height;
266
267
5.77k
        oox::drawingml::ShapePropertyIds aPropertyIds = oox::drawingml::ShapePropertyInfo::DEFAULT.mrPropertyIds;
268
5.77k
        aPropertyIds[oox::drawingml::ShapeProperty::FillGradient] = PROP_FillGradientName;
269
5.77k
        oox::drawingml::ShapePropertyInfo aPropInfo( aPropertyIds, true, false, true, false, false );
270
5.77k
        oox::drawingml::ShapePropertyMap aPropMap( rFilterBase.getModelObjectHelper(), aPropInfo );
271
5.77k
        mpBackgroundPropertiesPtr->pushToPropMap( aPropMap, rFilterBase.getGraphicHelper(), 0, nPhClr, aSize);
272
5.77k
        PropertySet( mxPage ).setProperty( PROP_Background, aPropMap.makePropertySet() );
273
5.77k
    }
274
21.6k
}
275
276
static void setTextStyle( Reference< beans::XPropertySet > const & rxPropSet, const XmlFilterBase& rFilter,
277
    oox::drawingml::TextListStylePtr const & pTextListStylePtr, int nLevel )
278
270k
{
279
270k
    ::oox::drawingml::TextParagraphProperties* pTextParagraphPropertiesPtr( &pTextListStylePtr->getListStyle()[ nLevel ] );
280
270k
    if( pTextParagraphPropertiesPtr == nullptr )
281
0
    {
282
        // no properties. return
283
0
        return;
284
0
    }
285
286
270k
    PropertyMap& rTextParagraphPropertyMap( pTextParagraphPropertiesPtr->getTextParagraphPropertyMap() );
287
288
270k
    PropertySet aPropSet( rxPropSet );
289
270k
    aPropSet.setProperties( rTextParagraphPropertyMap );
290
270k
    pTextParagraphPropertiesPtr->getTextCharacterProperties().pushToPropSet( aPropSet, rFilter );
291
270k
}
292
293
void SlidePersist::applyTextStyles( const XmlFilterBase& rFilterBase )
294
21.6k
{
295
21.6k
    if ( !mbMaster )
296
4.78k
        return;
297
298
16.9k
    try
299
16.9k
    {
300
16.9k
        Reference< style::XStyleFamiliesSupplier > aXStyleFamiliesSupplier( rFilterBase.getModel(), UNO_QUERY_THROW );
301
16.9k
        Reference< container::XNameAccess > aXNameAccess( aXStyleFamiliesSupplier->getStyleFamilies() );
302
16.9k
        Reference< container::XNamed > aXNamed( mxPage, UNO_QUERY_THROW );
303
304
16.9k
        if ( aXNameAccess.is() )
305
16.9k
        {
306
16.9k
            oox::drawingml::TextListStylePtr pTextListStylePtr;
307
16.9k
            OUString aStyle;
308
16.9k
            OUString aFamily;
309
310
16.9k
            static constexpr OUStringLiteral sOutline( u"outline1" );
311
16.9k
            static constexpr OUString sTitle( u"title"_ustr );
312
16.9k
            static constexpr OUStringLiteral sStandard( u"standard" );
313
16.9k
            static constexpr OUStringLiteral sSubtitle( u"subtitle" );
314
315
84.5k
            for( int i = 0; i < 4; i++ )    // todo: aggregation of bodystyle (subtitle)
316
67.6k
            {
317
67.6k
                switch( i )
318
67.6k
                {
319
16.9k
                    case 0 :    // title style
320
16.9k
                    {
321
16.9k
                        pTextListStylePtr = maTitleTextStylePtr;
322
16.9k
                        aStyle = sTitle;
323
16.9k
                        aFamily= aXNamed->getName();
324
16.9k
                        break;
325
0
                    }
326
16.9k
                    case 1 :    // body style
327
16.9k
                    {
328
16.9k
                        pTextListStylePtr = maBodyTextStylePtr;
329
16.9k
                        aStyle = sOutline;
330
16.9k
                        aFamily= aXNamed->getName();
331
16.9k
                        break;
332
0
                    }
333
16.9k
                    case 3 :    // notes style
334
16.9k
                    {
335
16.9k
                        pTextListStylePtr = maNotesTextStylePtr;
336
16.9k
                        aStyle = sTitle;
337
16.9k
                        aFamily= aXNamed->getName();
338
16.9k
                        break;
339
0
                    }
340
0
                    case 4 :    // standard style
341
0
                    {
342
0
                        pTextListStylePtr = maOtherTextStylePtr;
343
0
                        aStyle = sStandard;
344
0
                        aFamily = "graphics";
345
0
                        break;
346
0
                    }
347
0
                    case 5 :    // subtitle
348
0
                    {
349
0
                        pTextListStylePtr = maBodyTextStylePtr;
350
0
                        aStyle = sSubtitle;
351
0
                        aFamily = aXNamed->getName();
352
0
                        break;
353
0
                    }
354
67.6k
                }
355
67.6k
                Reference< container::XNameAccess > xFamilies;
356
67.6k
                if ( aXNameAccess->hasByName( aFamily ) )
357
67.6k
                {
358
67.6k
                    if( aXNameAccess->getByName( aFamily ) >>= xFamilies )
359
67.6k
                    {
360
67.6k
                        if ( xFamilies->hasByName( aStyle ) )
361
67.6k
                        {
362
67.6k
                            Reference< style::XStyle > aXStyle;
363
67.6k
                            if ( xFamilies->getByName( aStyle ) >>= aXStyle )
364
67.6k
                            {
365
67.6k
                                Reference< beans::XPropertySet > xPropSet( aXStyle, UNO_QUERY_THROW );
366
67.6k
                                setTextStyle( xPropSet, rFilterBase, maDefaultTextStylePtr, 0 );
367
67.6k
                                setTextStyle( xPropSet, rFilterBase, pTextListStylePtr, 0 );
368
67.6k
                                if ( i == 1 /* BodyStyle */ )
369
16.9k
                                {
370
84.5k
                                    for ( int nLevel = 1; nLevel < 5; nLevel++ )
371
67.6k
                                    {
372
67.6k
                                        {
373
67.6k
                                            char pOutline[ 9 ] = "outline1";
374
67.6k
                                            pOutline[ 7 ] = static_cast< char >( '0' + nLevel );
375
67.6k
                                            OUString sOutlineStyle( OUString::createFromAscii( pOutline ) );
376
67.6k
                                            if ( xFamilies->hasByName( sOutlineStyle ) )
377
67.6k
                                            {
378
67.6k
                                                xFamilies->getByName( sOutlineStyle ) >>= aXStyle;
379
67.6k
                                                if( aXStyle.is() )
380
67.6k
                                                    xPropSet.set( aXStyle, UNO_QUERY_THROW );
381
67.6k
                                            }
382
67.6k
                                        }
383
67.6k
                                        setTextStyle( xPropSet, rFilterBase, maDefaultTextStylePtr, nLevel );
384
67.6k
                                        setTextStyle( xPropSet, rFilterBase, pTextListStylePtr, nLevel );
385
67.6k
                                    }
386
16.9k
                                }
387
67.6k
                            }
388
67.6k
                        }
389
67.6k
                    }
390
67.6k
                }
391
67.6k
            }
392
16.9k
        }
393
16.9k
    }
394
16.9k
    catch( const Exception& )
395
16.9k
    {
396
0
    }
397
16.9k
}
398
399
void SlidePersist::hideShapesAsMasterShapes()
400
5
{
401
5
    std::vector< oox::drawingml::ShapePtr >& rShapes( maShapesPtr->getChildren() );
402
5
    for (auto const& shape : rShapes)
403
3
    {
404
3
        std::vector< oox::drawingml::ShapePtr >& rChildren( shape->getChildren() );
405
3
        for (auto const& child : rChildren)
406
0
        {
407
0
            PPTShape* pPPTShape = dynamic_cast< PPTShape* >( child.get() );
408
0
            if (!pPPTShape)
409
0
                continue;
410
0
            pPPTShape->setHiddenMasterShape( true );
411
0
        }
412
3
    }
413
5
}
414
415
// This angle determines in the direction of the line
416
static sal_Int32 lcl_GetAngle(const uno::Reference<drawing::XShape>& rXShape, const awt::Point& rPt)
417
0
{
418
0
    SdrObject* pObj = SdrObject::getSdrObjectFromXShape(rXShape);
419
0
    tools::Rectangle aR(pObj->GetSnapRect());
420
0
    sal_Int32 nLeftX = rPt.X - aR.Left();
421
0
    sal_Int32 nTopY = rPt.Y - aR.Top();
422
0
    sal_Int32 nRightX = aR.Right() - rPt.X;
423
0
    sal_Int32 nBottomY = aR.Bottom() - rPt.Y;
424
0
    sal_Int32 nX = std::min(nLeftX, nRightX);
425
0
    sal_Int32 nY = std::min(nTopY, nBottomY);
426
427
0
    sal_Int32 nAngle;
428
0
    if (nX < nY)
429
0
    {
430
0
        if (nLeftX < nRightX)
431
0
            nAngle = 180; // Left
432
0
        else
433
0
            nAngle = 0; // Right
434
0
    }
435
0
    else
436
0
    {
437
0
        if (nTopY < nBottomY)
438
0
            nAngle = 270; // Top
439
0
        else
440
0
            nAngle = 90; // Bottom
441
0
    }
442
0
    return nAngle;
443
0
}
444
445
Reference<XAnimationNode> SlidePersist::getAnimationNode(const OUString& sId) const
446
52
{
447
52
    const auto pIter = maAnimNodesMap.find(sId);
448
52
    if (pIter != maAnimNodesMap.end())
449
52
        return pIter->second;
450
451
0
    Reference<XAnimationNode> aResult;
452
0
    return aResult;
453
52
}
454
455
static void lcl_SetEdgeLineValue(const uno::Reference<drawing::XShape>& rXConnector,
456
                                 const oox::drawingml::ShapePtr& rShapePtr)
457
0
{
458
0
    sal_Int32 nEdge = 0;
459
0
    awt::Point aStartPt, aEndPt;
460
0
    tools::Rectangle aS, aE; // Start, End rectangle
461
0
    uno::Reference<drawing::XShape> xStartSp, xEndSp;
462
0
    uno::Reference<beans::XPropertySet> xPropSet(rXConnector, uno::UNO_QUERY);
463
0
    xPropSet->getPropertyValue(u"EdgeStartPoint"_ustr) >>= aStartPt;
464
0
    xPropSet->getPropertyValue(u"EdgeEndPoint"_ustr) >>= aEndPt;
465
0
    xPropSet->getPropertyValue(u"StartShape"_ustr) >>= xStartSp;
466
0
    xPropSet->getPropertyValue(u"EndShape"_ustr) >>= xEndSp;
467
0
    xPropSet->setPropertyValue(u"EdgeNode1HorzDist"_ustr, Any(sal_Int32(0)));
468
0
    xPropSet->setPropertyValue(u"EdgeNode1VertDist"_ustr, Any(sal_Int32(0)));
469
0
    xPropSet->setPropertyValue(u"EdgeNode2HorzDist"_ustr, Any(sal_Int32(0)));
470
0
    xPropSet->setPropertyValue(u"EdgeNode2VertDist"_ustr, Any(sal_Int32(0)));
471
472
0
    SdrObject* pStartObj = xStartSp.is() ? SdrObject::getSdrObjectFromXShape(xStartSp) : nullptr;
473
0
    SdrObject* pEndObj = xEndSp.is() ? SdrObject::getSdrObjectFromXShape(xEndSp) : nullptr;
474
475
0
    sal_Int32 nStartA = -1;
476
0
    sal_Int32 nEndA = -1;
477
0
    if (pStartObj)
478
0
    {
479
0
        aS = pStartObj->GetSnapRect();
480
0
        nStartA = lcl_GetAngle(xStartSp, aStartPt);
481
0
    }
482
0
    if (pEndObj)
483
0
    {
484
0
        aE = pEndObj->GetSnapRect();
485
0
        nEndA = lcl_GetAngle(xEndSp, aEndPt);
486
0
    }
487
488
0
    const OUString sConnectorName = rShapePtr->getConnectorName();
489
0
    if (sConnectorName == "bentConnector2")
490
0
    {
491
0
        awt::Size aConnSize = rXConnector->getSize();
492
0
        if (xStartSp.is() || xEndSp.is())
493
0
        {
494
0
            if (nStartA >= 0)
495
0
            {
496
0
                switch (nStartA)
497
0
                {
498
0
                    case 0:   nEdge = aEndPt.X - aS.Right();  break;
499
0
                    case 180: nEdge = aEndPt.X - aS.Left();   break;
500
0
                    case 90:  nEdge = aEndPt.Y - aS.Bottom(); break;
501
0
                    case 270: nEdge = aEndPt.Y - aS.Top();    break;
502
0
                }
503
0
            }
504
0
            else
505
0
            {
506
0
                switch (nEndA)
507
0
                {
508
0
                    case 0:   nEdge = aStartPt.X - aE.Right();  break;
509
0
                    case 180: nEdge = aStartPt.X - aE.Left();   break;
510
0
                    case 90:  nEdge = aStartPt.Y - aE.Bottom(); break;
511
0
                    case 270: nEdge = aStartPt.Y - aE.Top();    break;
512
0
                }
513
0
            }
514
0
        }
515
0
        else
516
0
        {
517
0
            bool bFlipH = rShapePtr->getFlipH();
518
0
            bool bFlipV = rShapePtr->getFlipV();
519
0
            sal_Int32 nConnectorAngle = rShapePtr->getRotation() / 60000;
520
0
            if (aConnSize.Height < aConnSize.Width)
521
0
            {
522
0
                if ((nConnectorAngle == 90 && bFlipH && bFlipV) || (nConnectorAngle == 180)
523
0
                    || (nConnectorAngle == 270 && bFlipH))
524
0
                    nEdge -= aConnSize.Width;
525
0
                else
526
0
                    nEdge += aConnSize.Width;
527
0
            }
528
0
            else
529
0
            {
530
0
                if ((nConnectorAngle == 180 && bFlipV) || (nConnectorAngle == 270 && bFlipV)
531
0
                    || (nConnectorAngle == 90 && bFlipH && bFlipV)
532
0
                    || (nConnectorAngle == 0 && !bFlipV))
533
0
                    nEdge -= aConnSize.Height;
534
0
                else
535
0
                    nEdge += aConnSize.Height;
536
0
            }
537
0
        }
538
0
        xPropSet->setPropertyValue(u"EdgeLine1Delta"_ustr, Any(nEdge / 2));
539
0
    }
540
0
}
541
542
// create connection between two shape with a connector shape.
543
void SlidePersist::createConnectorShapeConnection(const oox::drawingml::ShapePtr& pConnector)
544
159
{
545
159
    oox::drawingml::ConnectorShapePropertiesList aConnectorShapeProperties
546
159
        = pConnector->getConnectorShapeProperties();
547
159
    uno::Reference<drawing::XShape> xConnector(pConnector->getXShape(), uno::UNO_QUERY);
548
159
    uno::Reference<beans::XPropertySet> xPropertySet(xConnector, uno::UNO_QUERY);
549
550
159
    if (xConnector.is())
551
159
    {
552
159
        sal_Int32 nCount = aConnectorShapeProperties.size();
553
181
        for (sal_Int32 j = 0; j < nCount; j++)
554
22
        {
555
22
            OUString aDestShapeId = aConnectorShapeProperties[j].maDestShapeId;
556
22
            const auto pShape = maShapeMap.find(aDestShapeId);
557
22
            if (pShape == maShapeMap.end())
558
0
                continue;
559
22
            uno::Reference<drawing::XShape> xShape(pShape->second->getXShape(), uno::UNO_QUERY);
560
22
            if (xShape.is())
561
22
            {
562
22
                uno::Reference<drawing::XGluePointsSupplier> xSupplier(xShape, uno::UNO_QUERY);
563
22
                css::uno::Reference<css::container::XIdentifierContainer> xGluePoints(
564
22
                    xSupplier->getGluePoints(), uno::UNO_QUERY);
565
566
22
                sal_Int32 nCountGluePoints = xGluePoints->getIdentifiers().getLength();
567
22
                sal_Int32 nGlueId = aConnectorShapeProperties[j].mnDestGlueId;
568
569
                // The first 4 glue points belong to the bounding box.
570
22
                if (nCountGluePoints > 4)
571
0
                    nGlueId += 4;
572
22
                else
573
22
                {
574
22
                    bool bFlipH = pShape->second->getFlipH();
575
22
                    bool bFlipV = pShape->second->getFlipV();
576
22
                    if ((!bFlipH && !bFlipV) || (bFlipH && bFlipV))
577
22
                    {
578
                        // change id of the left and right glue points of the bounding box (1 <-> 3)
579
22
                        if (nGlueId == 1)
580
7
                            nGlueId = 3; // Right
581
15
                        else if (nGlueId == 3)
582
15
                            nGlueId = 1; // Left
583
22
                    }
584
22
                }
585
586
22
                bool bStart = aConnectorShapeProperties[j].mbStartShape;
587
22
                if (bStart)
588
11
                {
589
11
                    xPropertySet->setPropertyValue(u"StartShape"_ustr, uno::Any(xShape));
590
11
                    xPropertySet->setPropertyValue(u"StartGluePointIndex"_ustr, uno::Any(nGlueId));
591
11
                }
592
11
                else
593
11
                {
594
11
                    xPropertySet->setPropertyValue(u"EndShape"_ustr, uno::Any(xShape));
595
11
                    xPropertySet->setPropertyValue(u"EndGluePointIndex"_ustr, uno::Any(nGlueId));
596
11
                }
597
22
            }
598
22
        }
599
159
        uno::Reference<beans::XPropertySetInfo> xPropInfo = xPropertySet->getPropertySetInfo();
600
159
        if (xPropInfo->hasPropertyByName(u"EdgeKind"_ustr))
601
159
        {
602
159
            ConnectorType aConnectorType;
603
159
            xPropertySet->getPropertyValue(u"EdgeKind"_ustr) >>= aConnectorType;
604
159
            if (aConnectorType == ConnectorType_STANDARD)
605
0
                lcl_SetEdgeLineValue(xConnector, pConnector);
606
159
        }
607
159
    }
608
159
}
609
610
}
611
612
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */