Coverage Report

Created: 2026-04-09 11:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/oox/source/drawingml/textparagraph.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 <com/sun/star/text/WritingMode2.hpp>
21
#include <drawingml/textparagraph.hxx>
22
#include <oox/drawingml/drawingmltypes.hxx>
23
#include <drawingml/textcharacterproperties.hxx>
24
#include <svtools/unitconv.hxx>
25
26
#include <rtl/ustring.hxx>
27
#include <sal/log.hxx>
28
#include <tools/fldunit.hxx>
29
#include <oox/mathml/importutils.hxx>
30
#include <oox/helper/propertyset.hxx>
31
#include <com/sun/star/text/XText.hpp>
32
#include <com/sun/star/text/XTextCursor.hpp>
33
#include <com/sun/star/text/ControlCharacter.hpp>
34
#include <oox/token/properties.hxx>
35
36
using namespace ::com::sun::star;
37
using namespace ::com::sun::star::text;
38
using namespace ::com::sun::star::uno;
39
using namespace ::com::sun::star::beans;
40
41
namespace oox::drawingml {
42
43
TextParagraph::TextParagraph()
44
159k
    : mbHasProperties( false )
45
159k
{
46
159k
}
47
48
TextParagraph::~TextParagraph()
49
159k
{
50
159k
}
51
52
TextCharacterProperties TextParagraph::getCharacterStyle (
53
    const TextCharacterProperties& rTextStyleProperties,
54
    const TextListStyle& rMasterTextListStyle,
55
    const TextListStyle& rTextListStyle) const
56
159k
{
57
159k
    const TextParagraphProperties* pMasterTextParagraphStyle = getParagraphStyle(rMasterTextListStyle);
58
159k
    const TextParagraphProperties* pTextParagraphStyle = getParagraphStyle(rTextListStyle);
59
60
159k
    TextCharacterProperties aTextCharacterStyle;
61
159k
    if (pMasterTextParagraphStyle)
62
159k
        aTextCharacterStyle.assignUsed(pMasterTextParagraphStyle->getTextCharacterProperties());
63
159k
    aTextCharacterStyle.assignUsed(rTextStyleProperties);
64
159k
    if (pTextParagraphStyle)
65
159k
        aTextCharacterStyle.assignUsed(pTextParagraphStyle->getTextCharacterProperties());
66
159k
    aTextCharacterStyle.assignUsed(maProperties.getTextCharacterProperties());
67
159k
    return aTextCharacterStyle;
68
159k
}
69
70
TextParagraphProperties* TextParagraph::getParagraphStyle(
71
    const TextListStyle& rTextListStyle) const
72
467k
{
73
467k
    sal_Int16 nLevel = maProperties.getLevel();
74
75
467k
    SAL_INFO("oox", "TextParagraph::getParagraphStyle - level " << nLevel);
76
77
467k
    const TextParagraphPropertiesArray& rListStyle = rTextListStyle.getListStyle();
78
467k
    if (nLevel >= static_cast< sal_Int16 >(rListStyle.size()))
79
0
        nLevel = 0;
80
467k
    const TextParagraphProperties* pTextParagraphStyle = nullptr;
81
467k
    if (!rListStyle.empty())
82
467k
        pTextParagraphStyle = &rListStyle[nLevel];
83
84
467k
    return const_cast<TextParagraphProperties*>(pTextParagraphStyle);
85
467k
}
86
87
void TextParagraph::insertAt(
88
        const ::oox::core::XmlFilterBase& rFilterBase,
89
        const Reference < XText > &xText,
90
        const Reference < XTextCursor > &xAt,
91
        const TextCharacterProperties& rTextStyleProperties,
92
        const TextListStyle& rMasterTextListStyle,
93
        const TextListStyle& rTextListStyle, bool bFirst,
94
        float nDefaultCharHeight) const
95
59.6k
{
96
59.6k
    try {
97
59.6k
        sal_Int32 nParagraphSize = 0;
98
59.6k
        TextCharacterProperties aTextCharacterStyle
99
59.6k
            = getCharacterStyle(rTextStyleProperties, rMasterTextListStyle, rTextListStyle);
100
101
59.6k
        if( !bFirst )
102
17.9k
        {
103
17.9k
            xText->insertControlCharacter( xAt, ControlCharacter::APPEND_PARAGRAPH, false );
104
17.9k
            xAt->gotoEnd( true );
105
17.9k
        }
106
107
59.6k
        sal_Int32 nCharHeight = 0;
108
59.6k
        sal_Int32 nCharHeightFirst = 0;
109
59.6k
        if ( maRuns.empty() )
110
12.3k
        {
111
12.3k
            PropertySet aPropSet( xAt );
112
113
12.3k
            TextCharacterProperties aTextCharacterProps( aTextCharacterStyle );
114
12.3k
            aTextCharacterProps.assignUsed( maEndProperties );
115
12.3k
            if ( aTextCharacterProps.moHeight.has_value() )
116
7.30k
                nCharHeight = nCharHeightFirst = aTextCharacterProps.moHeight.value();
117
12.3k
            aTextCharacterProps.pushToPropSet( aPropSet, rFilterBase );
118
12.3k
        }
119
47.2k
        else
120
47.2k
        {
121
110k
            for( TextRunVector::const_iterator aIt = maRuns.begin(), aEnd = maRuns.end(); aIt != aEnd; ++aIt )
122
63.0k
            {
123
63.0k
                sal_Int32 nLen = (*aIt)->getText().getLength();
124
                // n#759180: Force use, maEndProperties for the last segment
125
                // This is currently applied to only empty runs
126
63.0k
                if( !nLen && ( ( aIt + 1 ) == aEnd ) )
127
172
                    (*aIt)->getTextCharacterProperties().assignUsed( maEndProperties );
128
63.0k
                sal_Int32 nCharHeightCurrent = (*aIt)->insertAt( rFilterBase, xText, xAt, aTextCharacterStyle, nDefaultCharHeight );
129
63.0k
                if(aIt == maRuns.begin())
130
47.2k
                    nCharHeightFirst = nCharHeightCurrent;
131
63.0k
                nCharHeight = std::max< sal_Int32 >( nCharHeight, nCharHeightCurrent);
132
63.0k
                nParagraphSize += nLen;
133
63.0k
            }
134
47.2k
        }
135
59.6k
        xAt->gotoEnd( true );
136
137
59.6k
        PropertyMap aioBulletList;
138
59.6k
        Reference< XPropertySet > xProps( xAt, UNO_QUERY);
139
140
59.6k
        TextListStyle aCombinedTextStyle;
141
59.6k
        aCombinedTextStyle.apply(rMasterTextListStyle);
142
59.6k
        aCombinedTextStyle.apply(rTextListStyle);
143
59.6k
        TextParagraphProperties* pTextParagraphStyle = getParagraphStyle(aCombinedTextStyle);
144
59.6k
        if ( pTextParagraphStyle )
145
59.6k
        {
146
59.6k
            TextParagraphProperties aParaProp;
147
59.6k
            aParaProp.apply( *pTextParagraphStyle );
148
59.6k
            aParaProp.apply( maProperties );
149
150
            // bullets have same color as following texts by default
151
59.6k
            if( !aioBulletList.hasProperty( PROP_BulletColor ) && !maRuns.empty()
152
47.2k
                && (*maRuns.begin())->getTextCharacterProperties().maFillProperties.moFillType.has_value() )
153
4.52k
                aioBulletList.setProperty( PROP_BulletColor, (*maRuns.begin())->getTextCharacterProperties().maFillProperties.getBestSolidColor().getColor( rFilterBase.getGraphicHelper() ));
154
59.6k
            if( !aioBulletList.hasProperty( PROP_BulletColor ) && aTextCharacterStyle.maFillProperties.moFillType.has_value() )
155
30.6k
                aioBulletList.setProperty( PROP_BulletColor, aTextCharacterStyle.maFillProperties.getBestSolidColor().getColor( rFilterBase.getGraphicHelper() ));
156
59.6k
            if( !aioBulletList.hasProperty( PROP_GraphicSize ) && !maRuns.empty()
157
47.2k
                && aParaProp.getBulletList().maGraphic.hasValue())
158
0
            {
159
0
                tools::Long nFirstCharHeightMm = TransformMetric(nCharHeightFirst > 0 ? nCharHeightFirst : 1200, FieldUnit::POINT, FieldUnit::MM);
160
0
                float fBulletSizeRel = 1.f;
161
0
                double fBulletAspectRatio = 1.0;
162
163
0
                if( aParaProp.getBulletList().mnSize.hasValue() )
164
0
                    fBulletSizeRel = aParaProp.getBulletList().mnSize.get<sal_Int16>() / 100.f;
165
166
0
                if( aParaProp.getBulletList().mnAspectRatio.hasValue() )
167
0
                    fBulletAspectRatio = aParaProp.getBulletList().mnAspectRatio.get<double>();
168
169
0
                css::awt::Size aBulletSize;
170
0
                if( fBulletAspectRatio != 1.0 )
171
0
                {
172
0
                    aBulletSize.Height = std::lround(fBulletSizeRel * nFirstCharHeightMm * OOX_BULLET_LIST_SCALE_FACTOR);
173
0
                    aBulletSize.Width = aBulletSize.Height * fBulletAspectRatio;
174
0
                }
175
0
                else
176
0
                    aBulletSize.Width = aBulletSize.Height = std::lround(fBulletSizeRel * nFirstCharHeightMm * OOX_BULLET_LIST_SCALE_FACTOR);
177
178
0
                aioBulletList.setProperty( PROP_GraphicSize, aBulletSize);
179
0
            }
180
181
            // If the shape is Stacked then set Stacked into the TextParagraphProperties
182
59.6k
            Reference<XPropertySet> xProps2(xText, UNO_QUERY);
183
59.6k
            sal_Int16 nWritingMode = xProps2->getPropertyValue(u"WritingMode"_ustr).get<sal_Int16>();
184
59.6k
            if (nWritingMode == text::WritingMode2::STACKED)
185
0
            {
186
0
                aParaProp.getTextParagraphPropertyMap().setProperty(PROP_WritingMode, nWritingMode);
187
0
            }
188
189
59.6k
            float fCharacterSize = nCharHeight > 0 ? GetFontHeight ( nCharHeight ) : pTextParagraphStyle->getCharHeightPoints( 12 );
190
59.6k
            aParaProp.pushToPropSet( &rFilterBase, xProps, aioBulletList, &pTextParagraphStyle->getBulletList(), true, fCharacterSize, true, &aCombinedTextStyle );
191
59.6k
        }
192
193
        // empty paragraphs do not have bullets in ppt
194
59.6k
        if ( !nParagraphSize )
195
12.5k
        {
196
12.5k
            xProps->setPropertyValue( u"NumberingLevel"_ustr, Any( static_cast< sal_Int16 >( -1 ) ) );
197
12.5k
        }
198
199
// FIXME this is causing a lot of disruption (ie does not work). I wonder what to do -- Hub
200
//          Reference< XTextRange > xEnd( xAt, UNO_QUERY );
201
//      Reference< XPropertySet > xProps2( xEnd, UNO_QUERY );
202
//          mpEndProperties->pushToPropSet( xProps2 );
203
59.6k
    }
204
59.6k
    catch( Exception & )
205
59.6k
    {
206
0
        SAL_INFO("oox", "exception in TextParagraph::insertAt");
207
0
    }
208
59.6k
}
209
210
formulaimport::XmlStreamBuilder & TextParagraph::GetMathXml()
211
0
{
212
0
    if (!m_pMathXml)
213
0
    {
214
0
        m_pMathXml.reset(new formulaimport::XmlStreamBuilder);
215
0
    }
216
0
    return *m_pMathXml;
217
0
}
218
219
bool TextParagraph::hasVisualRunProperties() const
220
23
{
221
23
   for ( auto& pTextRun : getRuns() )
222
23
   {
223
23
       if ( pTextRun->hasVisualRunProperties() )
224
23
           return true;
225
23
   }
226
0
   return false;
227
23
}
228
229
}
230
231
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */