Coverage Report

Created: 2026-07-10 11:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/oox/source/drawingml/diagram/datamodelcontext.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 "datamodelcontext.hxx"
21
#include <oox/helper/attributelist.hxx>
22
#include <drawingml/misccontexts.hxx>
23
#include <drawingml/shapepropertiescontext.hxx>
24
#include <drawingml/linepropertiescontext.hxx>
25
#include <drawingml/textbodycontext.hxx>
26
#include <oox/token/namespaces.hxx>
27
#include <oox/token/tokens.hxx>
28
29
using namespace ::oox::core;
30
using namespace ::com::sun::star::uno;
31
32
namespace oox::drawingml {
33
34
namespace {
35
36
// CT_CxnList
37
class CxnListContext
38
    : public ContextHandler2
39
{
40
public:
41
    CxnListContext( ContextHandler2Helper const & rParent,
42
                    svx::diagram::Connections & aConnections )
43
728
        : ContextHandler2( rParent )
44
728
        , mrConnection( aConnections )
45
728
        {
46
728
        }
47
48
    virtual ContextHandlerRef
49
    onCreateContext( sal_Int32 aElementToken,
50
                     const AttributeList& rAttribs ) override
51
6.56k
        {
52
6.56k
            switch( aElementToken )
53
6.56k
            {
54
6.56k
                case DGM_TOKEN( cxn ):
55
6.56k
                {
56
6.56k
                    mrConnection.emplace_back( );
57
6.56k
                    svx::diagram::Connection& rConnection=mrConnection.back();
58
59
6.56k
                    rConnection.mnXMLType = static_cast<svx::diagram::TypeConstant>(rAttribs.getToken( XML_type, XML_parOf ));
60
6.56k
                    rConnection.msModelId = rAttribs.getStringDefaulted( XML_modelId );
61
6.56k
                    rConnection.msSourceId = rAttribs.getStringDefaulted( XML_srcId );
62
6.56k
                    rConnection.msDestId  = rAttribs.getStringDefaulted( XML_destId );
63
6.56k
                    rConnection.msPresId  = rAttribs.getStringDefaulted( XML_presId );
64
6.56k
                    rConnection.msSibTransId  = rAttribs.getStringDefaulted( XML_sibTransId );
65
6.56k
                    rConnection.msParTransId  = rAttribs.getStringDefaulted( XML_parTransId );
66
6.56k
                    rConnection.mnSourceOrder = rAttribs.getInteger( XML_srcOrd, 0 );
67
6.56k
                    rConnection.mnDestOrder = rAttribs.getInteger( XML_destOrd, 0 );
68
69
                    // skip CT_extLst
70
6.56k
                    return nullptr;
71
0
                }
72
0
                default:
73
0
                    break;
74
6.56k
            }
75
76
0
            return this;
77
6.56k
        }
78
private:
79
    svx::diagram::Connections& mrConnection;
80
};
81
82
// CT_presLayoutVars
83
class PresLayoutVarsContext
84
    : public ContextHandler2
85
{
86
public:
87
    PresLayoutVarsContext( ContextHandler2Helper const & rParent,
88
                           svx::diagram::Point & rPoint ) :
89
1.39k
        ContextHandler2( rParent ),
90
1.39k
        mrPoint( rPoint )
91
1.39k
    {
92
1.39k
    }
93
    virtual ContextHandlerRef
94
    onCreateContext( sal_Int32 aElementToken,
95
                     const AttributeList& rAttribs ) override
96
2.87k
    {
97
2.87k
        switch( aElementToken )
98
2.87k
        {
99
            // TODO
100
164
            case DGM_TOKEN( animLvl ):
101
176
            case DGM_TOKEN( animOne ):
102
176
                break;
103
966
            case DGM_TOKEN( bulletEnabled ):
104
966
                mrPoint.mbBulletEnabled = rAttribs.getBool( XML_val, false );
105
966
                break;
106
523
            case DGM_TOKEN( chMax ):
107
523
                mrPoint.mnMaxChildren = rAttribs.getInteger( XML_val, -1 );
108
523
                break;
109
500
            case DGM_TOKEN( chPref ):
110
500
                mrPoint.mnPreferredChildren = rAttribs.getInteger( XML_val, -1 );
111
500
                break;
112
350
            case DGM_TOKEN( dir ):
113
350
                mrPoint.mnDirection = rAttribs.getToken( XML_val, XML_norm );
114
350
                break;
115
0
            case DGM_TOKEN( hierBranch ):
116
0
            {
117
                // need to convert from oox::OptValue to std::optional since 1st is not available in svx
118
0
                const std::optional< sal_Int32 > aOptVal(rAttribs.getToken( XML_val ));
119
0
                if(aOptVal.has_value())
120
0
                    mrPoint.moHierarchyBranch = aOptVal.value();
121
0
                break;
122
164
            }
123
0
            case DGM_TOKEN( orgChart ):
124
0
                mrPoint.mbOrgChartEnabled = rAttribs.getBool( XML_val, false );
125
0
                break;
126
359
            case DGM_TOKEN( resizeHandles ):
127
359
                mrPoint.msResizeHandles = rAttribs.getStringDefaulted( XML_val );
128
359
                break;
129
0
            default:
130
0
                break;
131
2.87k
        }
132
133
2.87k
        return this;
134
2.87k
    }
135
136
private:
137
    svx::diagram::Point& mrPoint;
138
};
139
140
// CT_prSet
141
class PropertiesContext
142
    : public ContextHandler2
143
{
144
public:
145
    PropertiesContext( ContextHandler2Helper const & rParent,
146
                       svx::diagram::Point & rPoint,
147
                       const AttributeList& rAttribs ) :
148
6.75k
        ContextHandler2( rParent ),
149
6.75k
        mrPoint( rPoint )
150
6.75k
    {
151
6.75k
        mrPoint.msColorTransformCategoryId = rAttribs.getStringDefaulted( XML_csCatId);
152
6.75k
        mrPoint.msColorTransformTypeId = rAttribs.getStringDefaulted( XML_csTypeId);
153
6.75k
        mrPoint.msLayoutCategoryId = rAttribs.getStringDefaulted( XML_loCatId);
154
6.75k
        mrPoint.msLayoutTypeId = rAttribs.getStringDefaulted( XML_loTypeId);
155
6.75k
        mrPoint.msPlaceholderText = rAttribs.getStringDefaulted( XML_phldrT);
156
6.75k
        mrPoint.msPresentationAssociationId = rAttribs.getStringDefaulted( XML_presAssocID);
157
6.75k
        mrPoint.msPresentationLayoutName = rAttribs.getStringDefaulted( XML_presName);
158
6.75k
        mrPoint.msPresentationLayoutStyleLabel = rAttribs.getStringDefaulted( XML_presStyleLbl);
159
6.75k
        mrPoint.msQuickStyleCategoryId = rAttribs.getStringDefaulted( XML_qsCatId);
160
6.75k
        mrPoint.msQuickStyleTypeId = rAttribs.getStringDefaulted( XML_qsTypeId);
161
162
6.75k
        mrPoint.mnCustomAngle = rAttribs.getInteger( XML_custAng, -1 );
163
6.75k
        mrPoint.mnPercentageNeighbourWidth = rAttribs.getInteger( XML_custLinFactNeighborX, -1 );
164
6.75k
        mrPoint.mnPercentageNeighbourHeight = rAttribs.getInteger( XML_custLinFactNeighborY, -1 );
165
6.75k
        mrPoint.mnPercentageOwnWidth = rAttribs.getInteger( XML_custLinFactX, -1 );
166
6.75k
        mrPoint.mnPercentageOwnHeight = rAttribs.getInteger( XML_custLinFactY, -1 );
167
6.75k
        mrPoint.mnIncludeAngleScale = rAttribs.getInteger( XML_custRadScaleInc, -1 );
168
6.75k
        mrPoint.mnRadiusScale = rAttribs.getInteger( XML_custRadScaleRad, -1 );
169
6.75k
        mrPoint.mnWidthScale = rAttribs.getInteger( XML_custScaleX, -1 );
170
6.75k
        mrPoint.mnHeightScale = rAttribs.getInteger( XML_custScaleY, -1 );
171
6.75k
        mrPoint.mnWidthOverride = rAttribs.getInteger( XML_custSzX, -1 );
172
6.75k
        mrPoint.mnHeightOverride = rAttribs.getInteger( XML_custSzY, -1 );
173
6.75k
        mrPoint.mnLayoutStyleCount = rAttribs.getInteger( XML_presStyleCnt, -1 );
174
6.75k
        mrPoint.mnLayoutStyleIndex = rAttribs.getInteger( XML_presStyleIdx, -1 );
175
176
6.75k
        mrPoint.mbCoherent3DOffset = rAttribs.getBool( XML_coherent3DOff, false );
177
6.75k
        mrPoint.mbCustomHorizontalFlip = rAttribs.getBool( XML_custFlipHor, false );
178
6.75k
        mrPoint.mbCustomVerticalFlip = rAttribs.getBool( XML_custFlipVert, false );
179
6.75k
        mrPoint.mbCustomText = rAttribs.getBool( XML_custT, false );
180
6.75k
        mrPoint.mbIsPlaceholder = rAttribs.getBool( XML_phldr, false );
181
6.75k
    }
182
183
    virtual ContextHandlerRef
184
    onCreateContext( sal_Int32 aElementToken,
185
                     const AttributeList& ) override
186
1.39k
        {
187
1.39k
            switch( aElementToken )
188
1.39k
            {
189
1.39k
            case DGM_TOKEN( presLayoutVars ):
190
1.39k
                return new PresLayoutVarsContext( *this, mrPoint );
191
0
            case DGM_TOKEN( style ):
192
                // skip CT_shapeStyle
193
0
                return nullptr;
194
0
            default:
195
0
                break;
196
1.39k
            }
197
0
            return this;
198
1.39k
        }
199
200
private:
201
    svx::diagram::Point& mrPoint;
202
};
203
204
// CL_Pt
205
class PtContext
206
    : public ContextHandler2
207
{
208
public:
209
    PtContext( ContextHandler2Helper const& rParent,
210
               const AttributeList& rAttribs,
211
               svx::diagram::Point& rPoint,
212
               DiagramData_oox& rDiagramData):
213
7.67k
        ContextHandler2( rParent ),
214
7.67k
        mrPoint( rPoint ),
215
7.67k
        mrDiagramData( rDiagramData )
216
7.67k
    {
217
7.67k
        mrPoint.msModelId = rAttribs.getStringDefaulted( XML_modelId );
218
219
        // the default type is XML_node
220
7.67k
        const sal_Int32 nType  = rAttribs.getToken( XML_type, XML_node );
221
7.67k
        mrPoint.mnXMLType = static_cast<svx::diagram::TypeConstant>(nType);
222
223
        // ignore the cxnId unless it is this type. See 5.15.3.1.3 in Primer
224
7.67k
        if( ( nType == XML_parTrans ) || ( nType == XML_sibTrans ) )
225
2.11k
            mrPoint.msCnxId = rAttribs.getStringDefaulted( XML_cxnId );
226
7.67k
    }
227
228
    virtual ContextHandlerRef
229
    onCreateContext( sal_Int32 aElementToken,
230
                     const AttributeList& rAttribs ) override
231
16.8k
        {
232
16.8k
            switch( aElementToken )
233
16.8k
            {
234
0
            case DGM_TOKEN( extLst ):
235
0
                return nullptr;
236
6.75k
            case DGM_TOKEN( prSet ):
237
6.75k
                return new PropertiesContext( *this, mrPoint, rAttribs );
238
6.20k
            case DGM_TOKEN( spPr ):
239
6.20k
            {
240
6.20k
                Shape* pShape(mrDiagramData.getOrCreateAssociatedShape(mrPoint, true));
241
6.20k
                return new ShapePropertiesContext( *this, *pShape );
242
0
            }
243
3.88k
            case DGM_TOKEN( t ):
244
3.88k
            {
245
3.88k
                Shape* pShape(mrDiagramData.getOrCreateAssociatedShape(mrPoint, true));
246
3.88k
                TextBodyPtr xTextBody = std::make_shared<TextBody>();
247
3.88k
                pShape->setTextBody( xTextBody );
248
3.88k
                return new TextBodyContext( *this, *xTextBody );
249
0
            }
250
0
            default:
251
0
                break;
252
16.8k
            }
253
0
            return this;
254
16.8k
        }
255
256
private:
257
    svx::diagram::Point& mrPoint;
258
    DiagramData_oox& mrDiagramData;
259
};
260
261
// CT_PtList
262
class PtListContext
263
    : public ContextHandler2
264
{
265
public:
266
    PtListContext( ContextHandler2Helper const & rParent,  svx::diagram::Points& rPoints, DiagramData_oox& rDiagramData) :
267
907
        ContextHandler2( rParent ),
268
907
        mrPoints( rPoints ),
269
907
        mrDiagramData( rDiagramData )
270
907
    {}
271
    virtual ContextHandlerRef
272
    onCreateContext( sal_Int32 aElementToken,
273
                     const AttributeList& rAttribs ) override
274
7.67k
        {
275
7.67k
            switch( aElementToken )
276
7.67k
            {
277
7.67k
            case DGM_TOKEN( pt ):
278
7.67k
            {
279
                // CT_Pt
280
7.67k
                mrPoints.emplace_back( );
281
7.67k
                return new PtContext( *this, rAttribs, mrPoints.back(), mrDiagramData );
282
0
            }
283
0
            default:
284
0
                break;
285
7.67k
            }
286
0
            return this;
287
7.67k
        }
288
289
private:
290
    svx::diagram::Points& mrPoints;
291
    DiagramData_oox& mrDiagramData;
292
};
293
294
// CT_BackgroundFormatting
295
class BackgroundFormattingContext
296
    : public ContextHandler2
297
{
298
public:
299
    BackgroundFormattingContext( ContextHandler2Helper const & rParent, OoxDiagramDataPtr const& pModel )
300
915
        : ContextHandler2( rParent )
301
915
        , mpDataModel( pModel )
302
915
        {
303
915
            assert( pModel && "the data model MUST NOT be NULL" );
304
915
        }
305
306
    virtual ContextHandlerRef
307
    onCreateContext( sal_Int32 aElementToken,
308
                     const AttributeList& rAttribs ) override
309
0
        {
310
0
            switch( aElementToken )
311
0
            {
312
0
            case A_TOKEN( blipFill ):
313
0
            case A_TOKEN( gradFill ):
314
0
            case A_TOKEN( grpFill ):
315
0
            case A_TOKEN( noFill ):
316
0
            case A_TOKEN( pattFill ):
317
0
            case A_TOKEN( solidFill ):
318
                // EG_FillProperties
319
0
                return FillPropertiesContext::createFillContext(*this, aElementToken, rAttribs, *mpDataModel->getBackgroundShapeFillProperties(), nullptr);
320
0
            case A_TOKEN( effectDag ):
321
0
            case A_TOKEN( effectLst ):
322
                // TODO
323
                // EG_EffectProperties
324
0
                break;
325
0
            default:
326
0
                break;
327
0
            }
328
0
            return this;
329
0
        }
330
private:
331
    OoxDiagramDataPtr mpDataModel;
332
};
333
334
// CT_WholeFormatting (Line attributes for BackgroundShape)
335
class WholeFormattingContext
336
    : public ContextHandler2
337
{
338
public:
339
    WholeFormattingContext( ContextHandler2Helper const & rParent, OoxDiagramDataPtr const& pModel )
340
915
        : ContextHandler2( rParent )
341
915
        , mpDataModel( pModel )
342
915
        {
343
915
            assert( pModel && "the data model MUST NOT be NULL" );
344
915
        }
345
346
    virtual ContextHandlerRef
347
    onCreateContext( sal_Int32 aElementToken,
348
                     const AttributeList& rAttribs ) override
349
0
        {
350
0
            switch( aElementToken )
351
0
            {
352
0
            case A_TOKEN( ln ):
353
0
                return new LinePropertiesContext( *this, rAttribs, *mpDataModel->getBackgroundShapeLineProperties(), nullptr, false );
354
0
            default:
355
0
                break;
356
0
            }
357
0
            return this;
358
0
        }
359
private:
360
    OoxDiagramDataPtr mpDataModel;
361
};
362
363
}
364
365
DataModelContext::DataModelContext( ContextHandler2Helper const& rParent,
366
                                    const OoxDiagramDataPtr& pDataModel )
367
936
    : ContextHandler2( rParent )
368
936
    , mpDataModel( pDataModel )
369
936
{
370
936
    assert( pDataModel && "Data Model must not be NULL" );
371
936
}
372
373
DataModelContext::~DataModelContext()
374
936
{
375
    // some debug
376
#ifdef DBG_UTIL
377
    mpDataModel->dump();
378
#endif
379
936
}
380
381
ContextHandlerRef
382
DataModelContext::onCreateContext( ::sal_Int32 aElement,
383
                                   const AttributeList& rAttribs )
384
5.01k
{
385
5.01k
    switch( aElement )
386
5.01k
    {
387
728
    case DGM_TOKEN( cxnLst ):
388
        // CT_CxnList
389
728
        return new CxnListContext( *this, mpDataModel->getConnections() );
390
907
    case DGM_TOKEN( ptLst ):
391
        // CT_PtList
392
907
        return new PtListContext( *this, mpDataModel->getPoints(), *mpDataModel );
393
915
    case DGM_TOKEN( bg ):
394
        // CT_BackgroundFormatting
395
915
        return new BackgroundFormattingContext( *this, mpDataModel );
396
915
    case DGM_TOKEN( whole ):
397
        // CT_WholeE2oFormatting
398
915
        return new WholeFormattingContext( *this, mpDataModel );
399
334
    case DGM_TOKEN( extLst ):
400
668
    case A_TOKEN( ext ):
401
668
        break;
402
334
    case DSP_TOKEN( dataModelExt ):
403
334
        mpDataModel->getExtDrawings().push_back( rAttribs.getStringDefaulted( XML_relId ) );
404
334
        break;
405
548
    default:
406
548
        break;
407
5.01k
    }
408
409
1.55k
    return this;
410
5.01k
}
411
412
}
413
414
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */