Coverage Report

Created: 2026-08-14 10:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/oox/source/drawingml/textbodycontext.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 <drawingml/textbodycontext.hxx>
21
#include <drawingml/textbodypropertiescontext.hxx>
22
#include <drawingml/textparagraph.hxx>
23
#include <drawingml/textparagraphpropertiescontext.hxx>
24
#include <drawingml/textcharacterpropertiescontext.hxx>
25
#include <drawingml/textliststylecontext.hxx>
26
#include <drawingml/textfield.hxx>
27
#include <drawingml/textfieldcontext.hxx>
28
#include <oox/drawingml/shape.hxx>
29
#include <oox/token/namespaces.hxx>
30
#include <oox/helper/attributelist.hxx>
31
#include <sax/fastattribs.hxx>
32
#include "hyperlinkcontext.hxx"
33
34
#include <oox/mathml/imexport.hxx>
35
36
#include <sal/log.hxx>
37
#include <utility>
38
39
using namespace ::oox::core;
40
using namespace ::com::sun::star::uno;
41
using namespace ::com::sun::star::text;
42
using namespace ::com::sun::star::xml::sax;
43
44
namespace oox::drawingml {
45
46
namespace {
47
48
// CT_TextParagraph
49
class TextParagraphContext : public ContextHandler2
50
{
51
public:
52
    TextParagraphContext( ContextHandler2Helper const & rParent, TextParagraph& rPara, uint16_t& rListNumberingMask );
53
54
    virtual ContextHandlerRef onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs ) override;
55
56
protected:
57
    TextParagraph& mrParagraph;
58
    uint16_t& mrListNumberingMask;
59
};
60
61
}
62
63
TextParagraphContext::TextParagraphContext( ContextHandler2Helper const & rParent, TextParagraph& rPara, uint16_t& rListNumberingMask )
64
149k
: ContextHandler2( rParent )
65
149k
, mrParagraph( rPara )
66
149k
, mrListNumberingMask( rListNumberingMask )
67
149k
{
68
149k
    mbEnableTrimSpace = false;
69
149k
}
70
71
ContextHandlerRef TextParagraphContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs )
72
345k
{
73
    // EG_TextRun
74
345k
    switch( aElementToken )
75
345k
    {
76
114k
        case A_TOKEN( r ):      // "CT_RegularTextRun" Regular Text Run.
77
114k
        case W_TOKEN( r ):
78
114k
        {
79
114k
            TextRunPtr pRun = std::make_shared<TextRun>();
80
114k
            mrParagraph.addRun( pRun );
81
114k
            return new RegularTextRunContext( *this, std::move(pRun) );
82
114k
        }
83
69
        case A_TOKEN( br ): // "CT_TextLineBreak" Soft return line break (vertical tab).
84
69
        {
85
69
            TextRunPtr pRun = std::make_shared<TextRun>();
86
69
            pRun->setLineBreak();
87
69
            mrParagraph.addRun( pRun );
88
69
            return new RegularTextRunContext( *this, std::move(pRun) );
89
114k
        }
90
20.3k
        case A_TOKEN( fld ):    // "CT_TextField" Text Field.
91
20.3k
        {
92
20.3k
            auto pField = std::make_shared<TextField>();
93
20.3k
            mrParagraph.addRun( pField );
94
20.3k
            return new TextFieldContext( *this, rAttribs, *pField );
95
114k
        }
96
96.0k
        case A_TOKEN( pPr ):
97
96.0k
        case W_TOKEN( pPr ):
98
96.0k
            mrParagraph.setHasProperties();
99
96.0k
            return new TextParagraphPropertiesContext( *this, rAttribs, mrParagraph.getProperties(), &mrListNumberingMask );
100
114k
        case A_TOKEN( endParaRPr ):
101
114k
            return new TextCharacterPropertiesContext( *this, rAttribs, mrParagraph.getEndProperties() );
102
0
        case W_TOKEN( sdt ):
103
0
        case W_TOKEN( sdtContent ):
104
0
            return this;
105
0
        case W_TOKEN( del ):
106
0
        break;
107
0
        case W_TOKEN( ins ):
108
0
            return this;
109
0
        case OOX_TOKEN(a14, m):
110
0
            return CreateLazyMathBufferingContext(*this, mrParagraph);
111
0
        case W_TOKEN( hyperlink ):
112
0
        {
113
0
            TextRunPtr pRun = std::make_shared<TextRun>();
114
0
            mrParagraph.addRun(pRun);
115
            // parse hyperlink attributes: use HyperLinkContext for that
116
0
            rtl::Reference<HyperLinkContext> pContext(new HyperLinkContext(
117
0
                *this, rAttribs, pRun->getTextCharacterProperties().maHyperlinkPropertyMap));
118
            // but create text run context because HyperLinkContext can't process internal w:r, w:t, etc
119
0
            return new RegularTextRunContext(*this, std::move(pRun));
120
0
        }
121
0
        default:
122
0
            SAL_WARN("oox", "TextParagraphContext::onCreateContext: unhandled element: " << getBaseToken(aElementToken));
123
345k
    }
124
125
0
    return nullptr;
126
345k
}
127
128
RegularTextRunContext::RegularTextRunContext( ContextHandler2Helper const & rParent, TextRunPtr pRunPtr )
129
114k
: ContextHandler2( rParent )
130
114k
, mpRunPtr(std::move( pRunPtr ))
131
114k
, mbIsInText( false )
132
114k
{
133
114k
}
134
135
void RegularTextRunContext::onEndElement( )
136
229k
{
137
229k
    switch( getCurrentElement() )
138
229k
    {
139
114k
        case A_TOKEN( t ):
140
114k
        case W_TOKEN( t ):
141
114k
        {
142
114k
            mbIsInText = false;
143
114k
            break;
144
114k
        }
145
114k
        case A_TOKEN( r ):
146
114k
        break;
147
229k
    }
148
229k
}
149
150
void RegularTextRunContext::onCharacters( const OUString& aChars )
151
114k
{
152
114k
    if( mbIsInText )
153
114k
    {
154
114k
        mpRunPtr->getText() += aChars;
155
114k
    }
156
114k
}
157
158
ContextHandlerRef RegularTextRunContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs)
159
229k
{
160
229k
    switch( aElementToken )
161
229k
    {
162
114k
        case A_TOKEN( rPr ):    // "CT_TextCharPropertyBag" The text char properties of this text run.
163
114k
        case W_TOKEN( rPr ):
164
114k
            return new TextCharacterPropertiesContext( *this, rAttribs, mpRunPtr->getTextCharacterProperties() );
165
114k
        case A_TOKEN( t ):      // "xsd:string" minOccurs="1" The actual text string.
166
114k
        case W_TOKEN( t ):
167
114k
            mbIsInText = true;
168
114k
        break;
169
0
        case W_TOKEN( drawing ):
170
0
        break;
171
0
        default:
172
0
            SAL_WARN("oox", "RegularTextRunContext::onCreateContext: unhandled element: " << getBaseToken(aElementToken));
173
0
        break;
174
229k
    }
175
176
114k
    return this;
177
229k
}
178
179
TextBodyContext::TextBodyContext( ContextHandler2Helper const & rParent, TextBody& rTextBody )
180
88.4k
: ContextHandler2( rParent )
181
88.4k
, mrTextBody( rTextBody )
182
88.4k
, mListNumberingMask(0)
183
88.4k
{
184
88.4k
}
185
186
TextBodyContext::TextBodyContext(ContextHandler2Helper const& rParent, const ShapePtr& pShapePtr)
187
83.2k
    : TextBodyContext(rParent, *pShapePtr->getTextBody())
188
83.2k
{
189
83.2k
    mpShapePtr = pShapePtr;
190
83.2k
}
191
192
ContextHandlerRef TextBodyContext::onCreateContext( sal_Int32 aElementToken, const AttributeList& rAttribs )
193
289k
{
194
289k
    switch( aElementToken )
195
289k
    {
196
88.4k
        case A_TOKEN( bodyPr ):     // CT_TextBodyPropertyBag
197
88.4k
            if (sax_fastparser::castToFastAttributeList(rAttribs.getFastAttributeList()).getFastAttributeTokens().size() > 0)
198
63.4k
                mrTextBody.setHasNoninheritedBodyProperties();
199
88.4k
            if ( mpShapePtr )
200
83.2k
                return new TextBodyPropertiesContext( *this, rAttribs, mpShapePtr );
201
5.13k
            else
202
5.13k
                return new TextBodyPropertiesContext( *this, rAttribs, mrTextBody.getTextProperties() );
203
51.2k
        case A_TOKEN( lstStyle ):   // CT_TextListStyle
204
51.2k
            return new TextListStyleContext( *this, mrTextBody.getTextListStyle() );
205
149k
        case A_TOKEN( p ):          // CT_TextParagraph
206
149k
        case W_TOKEN( p ):
207
149k
            return new TextParagraphContext( *this, mrTextBody.addParagraph(), mListNumberingMask );
208
0
        case W_TOKEN( sdt ):
209
0
        case W_TOKEN( sdtContent ):
210
0
            return this;
211
0
        case W_TOKEN( sdtPr ):
212
0
        case W_TOKEN( sdtEndPr ):
213
0
        break;
214
0
        case W_TOKEN( tbl ):
215
0
        break;
216
0
        default:
217
0
            SAL_WARN("oox", "TextBodyContext::onCreateContext: unhandled element: " << getBaseToken(aElementToken));
218
289k
    }
219
220
0
    return nullptr;
221
289k
}
222
223
}
224
225
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */