Coverage Report

Created: 2025-07-07 10:01

/src/libreoffice/svgio/source/svguno/xsvgparser.cxx
Line
Count
Source (jump to first uncovered line)
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 <sal/config.h>
21
22
#include <com/sun/star/graphic/XSvgParser.hpp>
23
#include <com/sun/star/lang/XServiceInfo.hpp>
24
#include <com/sun/star/lang/XInitialization.hpp>
25
#include <comphelper/processfactory.hxx>
26
#include <cppuhelper/implbase.hxx>
27
#include <cppuhelper/supportsservice.hxx>
28
#include <com/sun/star/xml/sax/XParser.hpp>
29
#include <com/sun/star/xml/sax/Parser.hpp>
30
#include <com/sun/star/xml/sax/InputSource.hpp>
31
#include <svgdocumenthandler.hxx>
32
#include <comphelper/diagnose_ex.hxx>
33
#include <rtl/ref.hxx>
34
#include <tools/stream.hxx>
35
#include <unotools/streamwrap.hxx>
36
37
#include <svgvisitor.hxx>
38
#include <utility>
39
40
using namespace ::com::sun::star;
41
42
namespace svgio::svgreader
43
{
44
        namespace {
45
46
        class XSvgParser : public ::cppu::WeakImplHelper< graphic::XSvgParser, lang::XServiceInfo >
47
        {
48
        private:
49
            std::shared_ptr<SvgDrawVisitor> mpVisitor;
50
51
            uno::Reference< uno::XComponentContext > context_;
52
            bool parseSvgXML(uno::Reference<io::XInputStream> const & xSVGStream,
53
                             uno::Reference<xml::sax::XDocumentHandler> const & xSvgDocHdl);
54
        public:
55
            explicit XSvgParser(
56
                uno::Reference< uno::XComponentContext > context);
57
            XSvgParser(const XSvgParser&) = delete;
58
            XSvgParser& operator=(const XSvgParser&) = delete;
59
60
            // XSvgParser
61
            virtual uno::Sequence< uno::Reference< ::graphic::XPrimitive2D > > SAL_CALL getDecomposition(
62
                const uno::Reference< ::io::XInputStream >& xSVGStream,
63
                const OUString& aAbsolutePath) override;
64
65
            virtual uno::Any SAL_CALL getDrawCommands(
66
                uno::Reference<io::XInputStream> const & xSvgStream,
67
                const OUString& aAbsolutePath) override;
68
69
            // XServiceInfo
70
            virtual OUString SAL_CALL getImplementationName() override;
71
            virtual sal_Bool SAL_CALL supportsService(const OUString&) override;
72
            virtual uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
73
        };
74
75
        }
76
77
        XSvgParser::XSvgParser(
78
            uno::Reference< uno::XComponentContext > context):
79
11.6k
            context_(std::move(context))
80
11.6k
        {
81
11.6k
        }
82
83
        bool XSvgParser::parseSvgXML(uno::Reference<io::XInputStream> const & xSVGStream, uno::Reference<xml::sax::XDocumentHandler> const & xSvgDocHdl)
84
11.6k
        {
85
11.6k
            try
86
11.6k
            {
87
                // prepare ParserInputSource
88
11.6k
                xml::sax::InputSource myInputSource;
89
11.6k
                myInputSource.aInputStream = xSVGStream;
90
91
                // get parser
92
11.6k
                uno::Reference< xml::sax::XParser > xParser(
93
11.6k
                    xml::sax::Parser::create(context_));
94
                // fdo#60471 need to enable internal entities because
95
                // certain ... popular proprietary products write SVG files
96
                // that use entities to define XML namespaces.
97
11.6k
                uno::Reference<lang::XInitialization> const xInit(xParser,
98
11.6k
                        uno::UNO_QUERY_THROW);
99
11.6k
                uno::Sequence<uno::Any> args{ uno::Any(u"DoSmeplease"_ustr) };
100
11.6k
                xInit->initialize(args);
101
102
                // connect parser and filter
103
11.6k
                xParser->setDocumentHandler(xSvgDocHdl);
104
105
                // finally, parse the stream to a hierarchy of
106
                // SVGGraphicPrimitive2D which will be embedded to the
107
                // primitive sequence. Their decompositions will in the
108
                // end create local low-level primitives, thus SVG will
109
                // be processable from all our processors
110
11.6k
                xParser->parseStream(myInputSource);
111
11.6k
            }
112
11.6k
            catch(const uno::Exception&)
113
11.6k
            {
114
11.6k
                TOOLS_INFO_EXCEPTION( "svg", "Parse error");
115
11.6k
                return false;
116
11.6k
            }
117
118
0
            return true;
119
11.6k
        }
120
121
        uno::Sequence< uno::Reference< ::graphic::XPrimitive2D > > XSvgParser::getDecomposition(
122
            const uno::Reference< ::io::XInputStream >& xSVGStream,
123
            const OUString& aAbsolutePath )
124
11.6k
        {
125
11.6k
            drawinglayer::primitive2d::Primitive2DContainer aRetval;
126
127
11.6k
            if(xSVGStream.is())
128
11.6k
            {
129
                // local document handler
130
11.6k
                rtl::Reference<SvgDocHdl> pSvgDocHdl = new SvgDocHdl(aAbsolutePath);
131
11.6k
                parseSvgXML(xSVGStream, pSvgDocHdl);
132
133
                // decompose to primitives
134
11.6k
                for(std::unique_ptr<SvgNode> const & pCandidate : pSvgDocHdl->getSvgDocument().getSvgNodeVector())
135
28
                {
136
28
                    if (Display::None != pCandidate->getDisplay())
137
8
                    {
138
8
                        pCandidate->decomposeSvgNode(aRetval, false);
139
8
                    }
140
28
                }
141
11.6k
            }
142
0
            else
143
0
            {
144
0
                OSL_ENSURE(false, "Invalid stream (!)");
145
0
            }
146
147
11.6k
            return aRetval.toSequence();
148
11.6k
        }
149
150
        uno::Any SAL_CALL XSvgParser::getDrawCommands(
151
                uno::Reference<io::XInputStream> const & xSvgStream,
152
                const OUString& aAbsolutePath)
153
0
        {
154
0
            uno::Any aAnyResult;
155
156
0
            if (!xSvgStream.is())
157
0
                return aAnyResult;
158
159
0
            rtl::Reference<SvgDocHdl> pSvgDocHdl = new SvgDocHdl(aAbsolutePath);
160
0
            parseSvgXML(xSvgStream, pSvgDocHdl);
161
162
            // decompose to primitives
163
0
            for (std::unique_ptr<SvgNode> const & pCandidate : pSvgDocHdl->getSvgDocument().getSvgNodeVector())
164
0
            {
165
0
                if (Display::None != pCandidate->getDisplay())
166
0
                {
167
0
                    mpVisitor = std::make_shared<SvgDrawVisitor>();
168
0
                    pCandidate->accept(*mpVisitor);
169
0
                    std::shared_ptr<gfx::DrawRoot> pDrawRoot(mpVisitor->getDrawRoot());
170
0
                    sal_uInt64 nPointer = reinterpret_cast<sal_uInt64>(pDrawRoot.get());
171
0
                    aAnyResult <<= sal_uInt64(nPointer);
172
0
                }
173
0
            }
174
175
0
            return aAnyResult;
176
0
        }
177
178
        OUString SAL_CALL XSvgParser::getImplementationName()
179
0
        {
180
0
            return u"svgio::svgreader::XSvgParser"_ustr;
181
0
        }
182
183
        sal_Bool SAL_CALL XSvgParser::supportsService(const OUString& rServiceName)
184
0
        {
185
0
            return cppu::supportsService(this, rServiceName);
186
0
        }
187
188
        uno::Sequence< OUString > SAL_CALL XSvgParser::getSupportedServiceNames()
189
0
        {
190
0
            return { u"com.sun.star.graphic.SvgTools"_ustr };
191
0
        }
192
193
} // end of namespace svgio::svgreader
194
195
extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
196
svgio_XSvgParser_get_implementation(
197
    css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
198
11.6k
{
199
11.6k
    return cppu::acquire(new svgio::svgreader::XSvgParser(context));
200
11.6k
}
201
202
extern "C" bool TestImportSVG(SvStream& rStream)
203
2
{
204
2
    css::uno::Reference<css::io::XInputStream> xStream(new utl::OInputStreamWrapper(rStream));
205
2
    rtl::Reference<svgio::svgreader::XSvgParser> xSvgParser(new svgio::svgreader::XSvgParser(comphelper::getProcessComponentContext()));
206
2
    return xSvgParser->getDecomposition(xStream, OUString()).getLength() != 0;
207
2
}
208
209
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */