Coverage Report

Created: 2026-11-06 11:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/xmloff/source/style/FillStyleContext.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 "FillStyleContext.hxx"
21
22
#include <TransGradientStyle.hxx>
23
24
#include <com/sun/star/awt/ColorStop.hpp>
25
#include <com/sun/star/awt/Gradient2.hpp>
26
#include <com/sun/star/awt/XBitmap.hpp>
27
#include <com/sun/star/container/XNameContainer.hpp>
28
#include <com/sun/star/graphic/XGraphic.hpp>
29
#include <com/sun/star/rendering/RGBColor.hpp>
30
31
#include <comphelper/sequence.hxx>
32
#include <sax/tools/converter.hxx>
33
#include <xmloff/xmlimp.hxx>
34
#include <xmloff/xmltoken.hxx>
35
#include <xmloff/GradientStyle.hxx>
36
#include <xmloff/HatchStyle.hxx>
37
#include <xmloff/ImageStyle.hxx>
38
#include <xmloff/MarkerStyle.hxx>
39
#include <xmloff/DashStyle.hxx>
40
#include <xmloff/xmlnamespace.hxx>
41
#include <xmloff/XMLBase64ImportContext.hxx>
42
43
using namespace ::com::sun::star;
44
45
46
XMLGradientStyleContext::XMLGradientStyleContext( SvXMLImport& rImport, sal_Int32 ,
47
                                              const uno::Reference< xml::sax::XFastAttributeList >& xAttrList)
48
0
:   SvXMLStyleContext(rImport)
49
0
{
50
    // start import
51
0
    XMLGradientStyleImport aGradientStyle( GetImport() );
52
0
    aGradientStyle.importXML( xAttrList, maAny, maStrName );
53
0
}
54
55
XMLGradientStyleContext::~XMLGradientStyleContext()
56
0
{
57
0
}
58
59
css::uno::Reference<css::xml::sax::XFastContextHandler> XMLGradientStyleContext::createFastChildContext(
60
        sal_Int32 nElement,
61
        const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList)
62
0
{
63
0
    if (nElement == XML_ELEMENT(LO_EXT, xmloff::token::XML_GRADIENT_STOP))
64
0
        return new XMLGradientStopContext(GetImport(), nElement, xAttrList, maColorStopVec);
65
66
0
    return nullptr;
67
0
}
68
69
void XMLGradientStyleContext::endFastElement(sal_Int32 )
70
0
{
71
    // correcting invalid StopOffset values is done at the model. Therefore we import them here
72
    // without any change.
73
0
    if (!maColorStopVec.empty())
74
0
    {
75
0
        awt::Gradient2 aGradient;
76
0
        maAny >>= aGradient;
77
0
        aGradient.ColorStops = comphelper::containerToSequence(maColorStopVec);
78
0
        maAny <<= aGradient;
79
0
    }
80
81
0
    uno::Reference< container::XNameContainer > xGradient( GetImport().GetGradientHelper() );
82
0
    try
83
0
    {
84
0
        if(xGradient.is())
85
0
        {
86
0
            if( xGradient->hasByName( maStrName ) )
87
0
            {
88
0
                xGradient->replaceByName( maStrName, maAny );
89
0
            }
90
0
            else
91
0
            {
92
0
                xGradient->insertByName( maStrName, maAny );
93
0
            }
94
0
        }
95
0
    }
96
0
    catch( container::ElementExistException& )
97
0
    {}
98
0
}
99
100
bool XMLGradientStyleContext::IsTransient() const
101
0
{
102
0
    return true;
103
0
}
104
105
XMLHatchStyleContext::XMLHatchStyleContext( SvXMLImport& rImport, sal_Int32 /*nElement*/,
106
                                            const uno::Reference< xml::sax::XFastAttributeList >& xAttrList)
107
0
:   SvXMLStyleContext(rImport)
108
0
{
109
    // start import
110
0
    XMLHatchStyleImport aHatchStyle( GetImport() );
111
0
    aHatchStyle.importXML( xAttrList, maAny, maStrName );
112
0
}
113
114
XMLHatchStyleContext::~XMLHatchStyleContext()
115
0
{
116
0
}
117
118
void XMLHatchStyleContext::endFastElement(sal_Int32 )
119
0
{
120
0
    uno::Reference< container::XNameContainer > xHatch( GetImport().GetHatchHelper() );
121
122
0
    try
123
0
    {
124
0
        if(xHatch.is())
125
0
        {
126
0
            if( xHatch->hasByName( maStrName ) )
127
0
            {
128
0
                xHatch->replaceByName( maStrName, maAny );
129
0
            }
130
0
            else
131
0
            {
132
0
                xHatch->insertByName( maStrName, maAny );
133
0
            }
134
0
        }
135
0
    }
136
0
    catch( container::ElementExistException& )
137
0
    {}
138
0
}
139
140
bool XMLHatchStyleContext::IsTransient() const
141
0
{
142
0
    return true;
143
0
}
144
145
146
XMLBitmapStyleContext::XMLBitmapStyleContext( SvXMLImport& rImport, sal_Int32 /*nElement*/,
147
                                              const uno::Reference< xml::sax::XFastAttributeList >& xAttrList)
148
0
:   SvXMLStyleContext(rImport)
149
0
{
150
    // start import
151
0
    XMLImageStyle::importXML( xAttrList, maAny, maStrName, rImport );
152
0
}
153
154
XMLBitmapStyleContext::~XMLBitmapStyleContext()
155
0
{
156
0
}
157
158
css::uno::Reference< css::xml::sax::XFastContextHandler > XMLBitmapStyleContext::createFastChildContext(
159
    sal_Int32 nElement,
160
    const css::uno::Reference< css::xml::sax::XFastAttributeList >&  )
161
0
{
162
0
    if( nElement == XML_ELEMENT(OFFICE, xmloff::token::XML_BINARY_DATA) )
163
0
    {
164
0
        OUString sURL;
165
0
        maAny >>= sURL;
166
0
        if( sURL.isEmpty() && !mxBase64Stream.is() )
167
0
        {
168
0
            mxBase64Stream = GetImport().GetStreamForGraphicObjectURLFromBase64();
169
0
            if( mxBase64Stream.is() )
170
0
                return new XMLBase64ImportContext( GetImport(), mxBase64Stream );
171
0
        }
172
0
    }
173
174
0
    return nullptr;
175
0
}
176
177
void XMLBitmapStyleContext::endFastElement(sal_Int32 )
178
0
{
179
0
    if (!maAny.has<uno::Reference<graphic::XGraphic>>() && mxBase64Stream.is())
180
0
    {
181
        // No graphic so far? Then see if it's inline.
182
0
        uno::Reference<graphic::XGraphic> xGraphic = GetImport().loadGraphicFromBase64(mxBase64Stream);
183
0
        if (xGraphic.is())
184
0
        {
185
0
            maAny <<= xGraphic;
186
0
        }
187
0
    }
188
189
0
    if (!maAny.has<uno::Reference<graphic::XGraphic>>())
190
0
        return;
191
192
0
    uno::Reference<container::XNameContainer> xBitmapContainer(GetImport().GetBitmapHelper());
193
194
0
    uno::Reference<graphic::XGraphic> xGraphic = maAny.get<uno::Reference<graphic::XGraphic>>();
195
0
    uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
196
197
0
    try
198
0
    {
199
0
        if (xBitmapContainer.is())
200
0
        {
201
0
            if (xBitmapContainer->hasByName(maStrName))
202
0
            {
203
0
                xBitmapContainer->replaceByName(maStrName, uno::Any(xBitmap));
204
0
            }
205
0
            else
206
0
            {
207
0
                xBitmapContainer->insertByName(maStrName, uno::Any(xBitmap));
208
0
            }
209
0
        }
210
0
    }
211
0
    catch (container::ElementExistException&)
212
0
    {}
213
0
}
214
215
bool XMLBitmapStyleContext::IsTransient() const
216
0
{
217
0
    return true;
218
0
}
219
220
221
XMLTransGradientStyleContext::XMLTransGradientStyleContext( SvXMLImport& rImport, sal_Int32 /*nElement*/,
222
                                              const uno::Reference< xml::sax::XFastAttributeList >& xAttrList)
223
5
:   SvXMLStyleContext(rImport)
224
5
{
225
    // start import
226
5
    XMLTransGradientStyleImport aTransGradientStyle( GetImport() );
227
5
    aTransGradientStyle.importXML( xAttrList, maAny, maStrName );
228
5
}
229
230
XMLTransGradientStyleContext::~XMLTransGradientStyleContext()
231
5
{
232
5
}
233
234
css::uno::Reference<css::xml::sax::XFastContextHandler> XMLTransGradientStyleContext::createFastChildContext(
235
        sal_Int32 nElement,
236
        const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttrList)
237
6
{
238
6
    if (nElement == XML_ELEMENT(LO_EXT, xmloff::token::XML_OPACITY_STOP))
239
0
        return new XMLTransparencyStopContext(GetImport(), nElement, xAttrList, maColorStopVec);
240
241
6
    return nullptr;
242
6
}
243
244
void XMLTransGradientStyleContext::endFastElement(sal_Int32 )
245
0
{
246
0
    uno::Reference< container::XNameContainer > xTransGradient( GetImport().GetTransGradientHelper() );
247
248
    // correcting invalid StopOffset values is done at the model. Therefore we import them here
249
    // without any change.
250
0
    if (!maColorStopVec.empty())
251
0
    {
252
0
        awt::Gradient2 aGradient;
253
0
        maAny >>= aGradient;
254
0
        aGradient.ColorStops = comphelper::containerToSequence(maColorStopVec);
255
0
        maAny <<= aGradient;
256
0
    }
257
258
0
    try
259
0
    {
260
0
        if(xTransGradient.is())
261
0
        {
262
0
            if( xTransGradient->hasByName( maStrName ) )
263
0
            {
264
0
                xTransGradient->replaceByName( maStrName, maAny );
265
0
            }
266
0
            else
267
0
            {
268
0
                xTransGradient->insertByName( maStrName, maAny );
269
0
            }
270
0
        }
271
0
    }
272
0
    catch( container::ElementExistException& )
273
0
    {}
274
0
}
275
276
bool XMLTransGradientStyleContext::IsTransient() const
277
5
{
278
5
    return true;
279
5
}
280
281
XMLTransparencyStopContext::XMLTransparencyStopContext(
282
    SvXMLImport& rImport, sal_Int32 nElement,
283
    const uno::Reference< xml::sax::XFastAttributeList >& xAttrList,
284
    std::vector<awt::ColorStop>& rColorStopVec)
285
0
:   SvXMLStyleContext(rImport)
286
0
{
287
0
    if(nElement != XML_ELEMENT(LO_EXT, xmloff::token::XML_OPACITY_STOP))
288
0
        return;
289
290
0
    double fOffset = -1.0;
291
0
    css::rendering::RGBColor aRGBColor; // transparency is handled as gray color
292
0
    for (auto &aIter : sax_fastparser::castToFastAttributeList(xAttrList))
293
0
    {
294
0
        switch(aIter.getToken())
295
0
        {
296
0
        case XML_ELEMENT(SVG, xmloff::token::XML_OFFSET): // needed??
297
0
        case XML_ELEMENT(SVG_COMPAT, xmloff::token::XML_OFFSET):
298
0
            if (!::sax::Converter::convertDouble(fOffset, aIter.toView()))
299
0
                return;
300
0
            break;
301
0
        case XML_ELEMENT(SVG, xmloff::token::XML_STOP_OPACITY):
302
0
        case XML_ELEMENT(SVG_COMPAT, xmloff::token::XML_STOP_OPACITY):
303
0
            {
304
0
                double fOpacity = 1.0;
305
0
                if (!::sax::Converter::convertDouble(fOpacity, aIter.toView()))
306
0
                    return;
307
                // Transparency is gray, full transparent is (1|1|1).
308
0
                double fGrayComponent = std::clamp<double>(1.0 - fOpacity, 0.0, 1.0);
309
0
                aRGBColor.Red = fGrayComponent;
310
0
                aRGBColor.Green = fGrayComponent;
311
0
                aRGBColor.Blue = fGrayComponent;
312
0
            }
313
0
            break;
314
0
        default:
315
0
            XMLOFF_WARN_UNKNOWN("xmloff.style", aIter);
316
0
        }
317
0
    }
318
319
0
    awt::ColorStop aColorStop;
320
0
    aColorStop.StopOffset = fOffset;
321
0
    aColorStop.StopColor = aRGBColor;
322
0
    rColorStopVec.push_back(aColorStop);
323
0
}
324
325
XMLTransparencyStopContext::~XMLTransparencyStopContext()
326
0
{
327
0
}
328
329
XMLMarkerStyleContext::XMLMarkerStyleContext( SvXMLImport& rImport, sal_Int32 /*nElement*/,
330
                                              const uno::Reference< xml::sax::XFastAttributeList >& xAttrList)
331
63
:   SvXMLStyleContext(rImport)
332
63
{
333
    // start import
334
63
    XMLMarkerStyleImport aMarkerStyle( GetImport() );
335
63
    aMarkerStyle.importXML( xAttrList, maAny, maStrName );
336
63
}
337
338
XMLMarkerStyleContext::~XMLMarkerStyleContext()
339
63
{
340
63
}
341
342
void XMLMarkerStyleContext::endFastElement(sal_Int32 )
343
62
{
344
62
    uno::Reference< container::XNameContainer > xMarker( GetImport().GetMarkerHelper() );
345
346
62
    try
347
62
    {
348
62
        if(xMarker.is())
349
62
        {
350
62
            if( xMarker->hasByName( maStrName ) )
351
0
            {
352
0
                xMarker->replaceByName( maStrName, maAny );
353
0
            }
354
62
            else
355
62
            {
356
62
                xMarker->insertByName( maStrName, maAny );
357
62
            }
358
62
        }
359
62
    }
360
62
    catch( container::ElementExistException& )
361
62
    {}
362
62
}
363
364
bool XMLMarkerStyleContext::IsTransient() const
365
63
{
366
63
    return true;
367
63
}
368
369
370
XMLDashStyleContext::XMLDashStyleContext( SvXMLImport& rImport, sal_Int32 /*nElement*/,
371
                                          const uno::Reference< xml::sax::XFastAttributeList >& xAttrList)
372
544
:   SvXMLStyleContext(rImport)
373
544
{
374
    // start import
375
544
    XMLDashStyleImport aDashStyle( GetImport() );
376
544
    aDashStyle.importXML( xAttrList, maAny, maStrName );
377
544
}
378
379
XMLDashStyleContext::~XMLDashStyleContext()
380
544
{
381
544
}
382
383
void XMLDashStyleContext::endFastElement(sal_Int32 )
384
541
{
385
541
    uno::Reference< container::XNameContainer > xDashes( GetImport().GetDashHelper() );
386
387
541
    try
388
541
    {
389
541
        if(xDashes.is())
390
541
        {
391
541
            if( xDashes->hasByName( maStrName ) )
392
16
            {
393
16
                xDashes->replaceByName( maStrName, maAny );
394
16
            }
395
525
            else
396
525
            {
397
525
                xDashes->insertByName( maStrName, maAny );
398
525
            }
399
541
        }
400
541
    }
401
541
    catch( container::ElementExistException& )
402
541
    {}
403
541
}
404
405
bool XMLDashStyleContext::IsTransient() const
406
544
{
407
544
    return true;
408
544
}
409
410
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */