Coverage Report

Created: 2026-08-14 10:22

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
20.5k
: mpDrawingPtr( std::make_shared<oox::vml::Drawing>( rFilter, rxPage, oox::vml::VMLDRAWING_POWERPOINT ) )
69
20.5k
, mxPage( rxPage )
70
20.5k
, maShapesPtr(std::move( pShapesPtr ))
71
20.5k
, mnLayoutValueToken( 0 )
72
20.5k
, mbMaster( bMaster )
73
20.5k
, mbNotes ( bNotes )
74
20.5k
, maDefaultTextStylePtr(std::move( pDefaultTextStyle ))
75
20.5k
, maTitleTextStylePtr( std::make_shared<oox::drawingml::TextListStyle>() )
76
20.5k
, maBodyTextStylePtr( std::make_shared<oox::drawingml::TextListStyle>() )
77
20.5k
, maNotesTextStylePtr( std::make_shared<oox::drawingml::TextListStyle>() )
78
20.5k
, maOtherTextStylePtr( std::make_shared<oox::drawingml::TextListStyle>() )
79
20.5k
{
80
#if OSL_DEBUG_LEVEL > 0
81
    mxDebugPage = mxPage;
82
#endif
83
20.5k
}
84
85
#if OSL_DEBUG_LEVEL > 0
86
css::uno::WeakReference< css::drawing::XDrawPage > SlidePersist::mxDebugPage;
87
#endif
88
89
SlidePersist::~SlidePersist()
90
20.5k
{
91
20.5k
}
92
93
void SlidePersist::releaseShapes()
94
4.37k
{
95
4.37k
    for (const auto& [sId, pShape] : maShapeMap)
96
5.28k
    {
97
5.28k
        if (pShape
98
5.28k
            && (pShape->getSubType() == XML_title || pShape->getSubType() == XML_ctrTitle))
99
293
        {
100
293
            css::uno::Reference<css::text::XTextRange> xText(pShape->getXShape(), css::uno::UNO_QUERY);
101
293
            if (xText.is())
102
293
                maTitleText = xText->getString();
103
293
            if (!maTitleText.isEmpty())
104
157
                break;
105
293
        }
106
5.28k
    }
107
4.37k
    maShapesPtr.reset();
108
4.37k
    maShapeMap.clear();
109
4.37k
    mpBackgroundPropertiesPtr.reset();
110
4.37k
}
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
18.3k
{
116
18.3k
    sal_Int16 nLayout = 20;     // 20 == blank (so many magic numbers :-( the description at com.sun.star.presentation.DrawPage.Layout does not help)
117
18.3k
    switch( mnLayoutValueToken )
118
18.3k
    {
119
1.59k
        case XML_blank:             nLayout = 20; break;
120
12
        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
443
        case XML_fourObj:           nLayout = 18; break;
125
980
        case XML_obj:               nLayout = 11; break;
126
0
        case XML_objAndTx:          nLayout = 13; break;
127
424
        case XML_objOverTx:         nLayout = 14; break;
128
0
        case XML_tbl:               nLayout =  8; break;
129
1.95k
        case XML_title:             nLayout =  0; break;
130
899
        case XML_titleOnly:         nLayout = 19; break;
131
845
        case XML_twoObj:
132
845
        case XML_twoColTx:          nLayout =  3; break;
133
437
        case XML_twoObjAndObj:
134
437
        case XML_twoObjAndTx:       nLayout = 15; break;
135
443
        case XML_twoObjOverTx:      nLayout = 16; break;
136
581
        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
434
        case XML_objAndTwoObj:
142
434
        case XML_txAndTwoObj:       nLayout = 12; break;
143
0
        case XML_txOverObj:         nLayout = 17; break;
144
404
        case XML_vertTitleAndTx:    nLayout = 28; break;
145
0
        case XML_vertTitleAndTxOverChart: nLayout = 27; break;
146
405
        case XML_vertTx:            nLayout = 29; break;
147
420
        case XML_objOnly:           nLayout = 32; break;
148
149
370
        case XML_twoTxTwoObj:
150
758
        case XML_objTx:
151
1.13k
        case XML_picTx:
152
1.53k
        case XML_secHead:
153
1.53k
        case XML_mediaAndTx:
154
1.53k
        case XML_dgm:
155
1.53k
        case XML_cust:
156
8.04k
        default:
157
8.04k
            nLayout = 20;
158
18.3k
    }
159
18.3k
    return nLayout;
160
18.3k
}
161
162
static void lcl_createShapeMap(oox::drawingml::ShapePtr rShapePtr,
163
                               oox::drawingml::ShapeIdMap& rShapeMap)
164
53.8k
{
165
53.8k
    std::vector<oox::drawingml::ShapePtr>& rChildren = rShapePtr->getChildren();
166
53.8k
    if (!rChildren.empty())
167
8
    {
168
8
        for (const auto& pIt : rChildren)
169
16
        {
170
16
            if (pIt->isConnectorShape())
171
4
            {
172
4
                rShapeMap[pIt->getId()] = pIt; // add child itself
173
4
                lcl_createShapeMap(pIt, rShapeMap); // and all its descendants
174
4
            }
175
16
        }
176
8
    }
177
53.8k
    else
178
53.8k
    {
179
53.8k
        if(rShapePtr->isConnectorShape())
180
167
            rShapeMap[rShapePtr->getId()] = rShapePtr;
181
53.8k
    }
182
53.8k
}
183
184
void SlidePersist::createXShapes( XmlFilterBase& rFilterBase )
185
20.2k
{
186
20.2k
    applyTextStyles( rFilterBase );
187
188
20.2k
    Reference< XShapes > xShapes( getPage() );
189
20.2k
    std::vector< oox::drawingml::ShapePtr >& rShapes( maShapesPtr->getChildren() );
190
20.2k
    oox::drawingml::ShapeIdMap aConnectorShapeMap;
191
192
20.2k
    for (auto const& shape : rShapes)
193
21.1k
    {
194
21.1k
        std::vector< oox::drawingml::ShapePtr >& rChildren( shape->getChildren() );
195
21.1k
        for (auto const& child : rChildren)
196
88.6k
        {
197
88.6k
            PPTShape* pPPTShape = dynamic_cast< PPTShape* >( child.get() );
198
88.6k
            basegfx::B2DHomMatrix aTransformation;
199
88.6k
            if ( pPPTShape )
200
88.6k
            {
201
88.6k
                pPPTShape->addShape( rFilterBase, *this, getTheme().get(), xShapes, aTransformation, &getShapeMap() );
202
203
88.6k
                const auto pIter = maShapeMap.find(pPPTShape->getId());
204
88.6k
                if (pIter != maShapeMap.end())
205
53.8k
                    lcl_createShapeMap(pIter->second, aConnectorShapeMap);
206
88.6k
            }
207
0
            else
208
0
                child->addShape( rFilterBase, getTheme().get(), xShapes, aTransformation, maShapesPtr->getFillProperties(), &getShapeMap() );
209
88.6k
        }
210
21.1k
    }
211
212
20.2k
    if (!aConnectorShapeMap.empty())
213
53
    {
214
53
        for (auto& pIt : aConnectorShapeMap)
215
167
        {
216
167
            ConnectorHelper::applyConnections(pIt.second, getShapeMap());
217
218
167
            SdrObject* pObj = SdrObject::getSdrObjectFromXShape(pIt.second->getXShape());
219
167
            SdrModel& rModel(pObj->getSdrModelFromSdrObject());
220
167
            rModel.setLock(false);
221
222
167
            if (pIt.second->getConnectorName() == u"bentConnector3"_ustr
223
167
                || pIt.second->getConnectorName() == u"bentConnector4"_ustr
224
167
                || pIt.second->getConnectorName() == u"bentConnector5"_ustr)
225
0
            {
226
0
                ConnectorHelper::applyBentHandleAdjustments(pIt.second);
227
0
            }
228
167
            else if (pIt.second->getConnectorName() == u"curvedConnector3"_ustr
229
167
                     || pIt.second->getConnectorName() == u"curvedConnector4"_ustr
230
167
                     || pIt.second->getConnectorName() == u"curvedConnector5"_ustr)
231
0
            {
232
0
                ConnectorHelper::applyCurvedHandleAdjustments(pIt.second);
233
0
            }
234
167
            else // bentConnector2
235
167
                createConnectorShapeConnection(pIt.second);
236
167
        }
237
53
    }
238
239
20.2k
    Reference< XAnimationNodeSupplier > xNodeSupplier( getPage(), UNO_QUERY);
240
20.2k
    if( !xNodeSupplier.is() )
241
116
        return;
242
243
20.1k
    Reference< XAnimationNode > xNode( xNodeSupplier->getAnimationNode() );
244
20.1k
    if( xNode.is() && !maTimeNodeList.empty() )
245
778
    {
246
778
        SlidePersistPtr pSlidePtr( shared_from_this() );
247
778
        TimeNodePtr pNode(maTimeNodeList.front());
248
778
        OSL_ENSURE( pNode, "pNode" );
249
250
778
        Reference<XAnimationNode> xDummy;
251
778
        pNode->setNode(rFilterBase, xNode, pSlidePtr, xDummy);
252
778
    }
253
20.1k
}
254
255
void SlidePersist::createBackground( const XmlFilterBase& rFilterBase )
256
20.2k
{
257
20.2k
    if ( mpBackgroundPropertiesPtr )
258
5.45k
    {
259
5.45k
        ::Color nPhClr = maBackgroundColor.isUsed() ?
260
3.54k
            maBackgroundColor.getColor( rFilterBase.getGraphicHelper() ) : API_RGB_TRANSPARENT;
261
262
5.45k
        css::awt::Size aSize;
263
5.45k
        Reference< css::beans::XPropertySet > xSet(mxPage, UNO_QUERY);
264
5.45k
        xSet->getPropertyValue(u"Width"_ustr) >>= aSize.Width;
265
5.45k
        xSet->getPropertyValue(u"Height"_ustr) >>= aSize.Height;
266
267
5.45k
        oox::drawingml::ShapePropertyIds aPropertyIds = oox::drawingml::ShapePropertyInfo::DEFAULT.mrPropertyIds;
268
5.45k
        aPropertyIds[oox::drawingml::ShapeProperty::FillGradient] = PROP_FillGradientName;
269
5.45k
        oox::drawingml::ShapePropertyInfo aPropInfo( aPropertyIds, true, false, true, false, false );
270
5.45k
        oox::drawingml::ShapePropertyMap aPropMap( rFilterBase.getModelObjectHelper(), aPropInfo );
271
5.45k
        mpBackgroundPropertiesPtr->pushToPropMap( aPropMap, rFilterBase.getGraphicHelper(), 0, nPhClr, aSize);
272
5.45k
        PropertySet( mxPage ).setProperty( PROP_Background, aPropMap.makePropertySet() );
273
5.45k
    }
274
20.2k
}
275
276
static void setTextStyle( Reference< beans::XPropertySet > const & rxPropSet, const XmlFilterBase& rFilter,
277
    oox::drawingml::TextListStylePtr const & pTextListStylePtr, int nLevel )
278
254k
{
279
254k
    ::oox::drawingml::TextParagraphProperties* pTextParagraphPropertiesPtr( &pTextListStylePtr->getListStyle()[ nLevel ] );
280
254k
    if( pTextParagraphPropertiesPtr == nullptr )
281
0
    {
282
        // no properties. return
283
0
        return;
284
0
    }
285
286
254k
    PropertyMap& rTextParagraphPropertyMap( pTextParagraphPropertiesPtr->getTextParagraphPropertyMap() );
287
288
254k
    PropertySet aPropSet( rxPropSet );
289
254k
    aPropSet.setProperties( rTextParagraphPropertyMap );
290
254k
    pTextParagraphPropertiesPtr->getTextCharacterProperties().pushToPropSet( aPropSet, rFilter );
291
254k
}
292
293
void SlidePersist::applyTextStyles( const XmlFilterBase& rFilterBase )
294
20.2k
{
295
20.2k
    if ( !mbMaster )
296
4.37k
        return;
297
298
15.8k
    try
299
15.8k
    {
300
15.8k
        Reference< style::XStyleFamiliesSupplier > aXStyleFamiliesSupplier( rFilterBase.getModel(), UNO_QUERY_THROW );
301
15.8k
        Reference< container::XNameAccess > aXNameAccess( aXStyleFamiliesSupplier->getStyleFamilies() );
302
15.8k
        Reference< container::XNamed > aXNamed( mxPage, UNO_QUERY_THROW );
303
304
15.8k
        if ( aXNameAccess.is() )
305
15.8k
        {
306
15.8k
            oox::drawingml::TextListStylePtr pTextListStylePtr;
307
15.8k
            OUString aStyle;
308
15.8k
            OUString aFamily;
309
310
15.8k
            static constexpr OUStringLiteral sOutline( u"outline1" );
311
15.8k
            static constexpr OUString sTitle( u"title"_ustr );
312
15.8k
            static constexpr OUStringLiteral sStandard( u"standard" );
313
15.8k
            static constexpr OUStringLiteral sSubtitle( u"subtitle" );
314
315
79.4k
            for( int i = 0; i < 4; i++ )    // todo: aggregation of bodystyle (subtitle)
316
63.5k
            {
317
63.5k
                switch( i )
318
63.5k
                {
319
15.8k
                    case 0 :    // title style
320
15.8k
                    {
321
15.8k
                        pTextListStylePtr = maTitleTextStylePtr;
322
15.8k
                        aStyle = sTitle;
323
15.8k
                        aFamily= aXNamed->getName();
324
15.8k
                        break;
325
0
                    }
326
15.8k
                    case 1 :    // body style
327
15.8k
                    {
328
15.8k
                        pTextListStylePtr = maBodyTextStylePtr;
329
15.8k
                        aStyle = sOutline;
330
15.8k
                        aFamily= aXNamed->getName();
331
15.8k
                        break;
332
0
                    }
333
15.8k
                    case 3 :    // notes style
334
15.8k
                    {
335
15.8k
                        pTextListStylePtr = maNotesTextStylePtr;
336
15.8k
                        aStyle = sTitle;
337
15.8k
                        aFamily= aXNamed->getName();
338
15.8k
                        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
63.5k
                }
355
63.5k
                Reference< container::XNameAccess > xFamilies;
356
63.5k
                if ( aXNameAccess->hasByName( aFamily ) )
357
63.5k
                {
358
63.5k
                    if( aXNameAccess->getByName( aFamily ) >>= xFamilies )
359
63.5k
                    {
360
63.5k
                        if ( xFamilies->hasByName( aStyle ) )
361
63.5k
                        {
362
63.5k
                            Reference< style::XStyle > aXStyle;
363
63.5k
                            if ( xFamilies->getByName( aStyle ) >>= aXStyle )
364
63.5k
                            {
365
63.5k
                                Reference< beans::XPropertySet > xPropSet( aXStyle, UNO_QUERY_THROW );
366
63.5k
                                setTextStyle( xPropSet, rFilterBase, maDefaultTextStylePtr, 0 );
367
63.5k
                                setTextStyle( xPropSet, rFilterBase, pTextListStylePtr, 0 );
368
63.5k
                                if ( i == 1 /* BodyStyle */ )
369
15.8k
                                {
370
79.4k
                                    for ( int nLevel = 1; nLevel < 5; nLevel++ )
371
63.5k
                                    {
372
63.5k
                                        {
373
63.5k
                                            char pOutline[ 9 ] = "outline1";
374
63.5k
                                            pOutline[ 7 ] = static_cast< char >( '0' + nLevel );
375
63.5k
                                            OUString sOutlineStyle( OUString::createFromAscii( pOutline ) );
376
63.5k
                                            if ( xFamilies->hasByName( sOutlineStyle ) )
377
63.5k
                                            {
378
63.5k
                                                xFamilies->getByName( sOutlineStyle ) >>= aXStyle;
379
63.5k
                                                if( aXStyle.is() )
380
63.5k
                                                    xPropSet.set( aXStyle, UNO_QUERY_THROW );
381
63.5k
                                            }
382
63.5k
                                        }
383
63.5k
                                        setTextStyle( xPropSet, rFilterBase, maDefaultTextStylePtr, nLevel );
384
63.5k
                                        setTextStyle( xPropSet, rFilterBase, pTextListStylePtr, nLevel );
385
63.5k
                                    }
386
15.8k
                                }
387
63.5k
                            }
388
63.5k
                        }
389
63.5k
                    }
390
63.5k
                }
391
63.5k
            }
392
15.8k
        }
393
15.8k
    }
394
15.8k
    catch( const Exception& )
395
15.8k
    {
396
0
    }
397
15.8k
}
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
46
{
447
46
    const auto pIter = maAnimNodesMap.find(sId);
448
46
    if (pIter != maAnimNodesMap.end())
449
46
        return pIter->second;
450
451
0
    Reference<XAnimationNode> aResult;
452
0
    return aResult;
453
46
}
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
167
{
545
167
    oox::drawingml::ConnectorShapePropertiesList aConnectorShapeProperties
546
167
        = pConnector->getConnectorShapeProperties();
547
167
    uno::Reference<drawing::XShape> xConnector(pConnector->getXShape(), uno::UNO_QUERY);
548
167
    uno::Reference<beans::XPropertySet> xPropertySet(xConnector, uno::UNO_QUERY);
549
550
167
    if (xConnector.is())
551
167
    {
552
167
        sal_Int32 nCount = aConnectorShapeProperties.size();
553
185
        for (sal_Int32 j = 0; j < nCount; j++)
554
18
        {
555
18
            OUString aDestShapeId = aConnectorShapeProperties[j].maDestShapeId;
556
18
            const auto pShape = maShapeMap.find(aDestShapeId);
557
18
            if (pShape == maShapeMap.end())
558
0
                continue;
559
18
            uno::Reference<drawing::XShape> xShape(pShape->second->getXShape(), uno::UNO_QUERY);
560
18
            if (xShape.is())
561
18
            {
562
18
                uno::Reference<drawing::XGluePointsSupplier> xSupplier(xShape, uno::UNO_QUERY);
563
18
                css::uno::Reference<css::container::XIdentifierContainer> xGluePoints(
564
18
                    xSupplier->getGluePoints(), uno::UNO_QUERY);
565
566
18
                sal_Int32 nCountGluePoints = xGluePoints->getIdentifiers().getLength();
567
18
                sal_Int32 nGlueId = aConnectorShapeProperties[j].mnDestGlueId;
568
569
                // The first 4 glue points belong to the bounding box.
570
18
                if (nCountGluePoints > 4)
571
0
                    nGlueId += 4;
572
18
                else
573
18
                {
574
18
                    bool bFlipH = pShape->second->getFlipH();
575
18
                    bool bFlipV = pShape->second->getFlipV();
576
18
                    if ((!bFlipH && !bFlipV) || (bFlipH && bFlipV))
577
18
                    {
578
                        // change id of the left and right glue points of the bounding box (1 <-> 3)
579
18
                        if (nGlueId == 1)
580
5
                            nGlueId = 3; // Right
581
13
                        else if (nGlueId == 3)
582
13
                            nGlueId = 1; // Left
583
18
                    }
584
18
                }
585
586
18
                bool bStart = aConnectorShapeProperties[j].mbStartShape;
587
18
                if (bStart)
588
9
                {
589
9
                    xPropertySet->setPropertyValue(u"StartShape"_ustr, uno::Any(xShape));
590
9
                    xPropertySet->setPropertyValue(u"StartGluePointIndex"_ustr, uno::Any(nGlueId));
591
9
                }
592
9
                else
593
9
                {
594
9
                    xPropertySet->setPropertyValue(u"EndShape"_ustr, uno::Any(xShape));
595
9
                    xPropertySet->setPropertyValue(u"EndGluePointIndex"_ustr, uno::Any(nGlueId));
596
9
                }
597
18
            }
598
18
        }
599
167
        uno::Reference<beans::XPropertySetInfo> xPropInfo = xPropertySet->getPropertySetInfo();
600
167
        if (xPropInfo->hasPropertyByName(u"EdgeKind"_ustr))
601
167
        {
602
167
            ConnectorType aConnectorType;
603
167
            xPropertySet->getPropertyValue(u"EdgeKind"_ustr) >>= aConnectorType;
604
167
            if (aConnectorType == ConnectorType_STANDARD)
605
0
                lcl_SetEdgeLineValue(xConnector, pConnector);
606
167
        }
607
167
    }
608
167
}
609
610
}
611
612
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */