Coverage Report

Created: 2026-03-31 11:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/svgio/source/svgreader/svgrectnode.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 <svgrectnode.hxx>
21
#include <basegfx/polygon/b2dpolygon.hxx>
22
#include <basegfx/polygon/b2dpolygontools.hxx>
23
#include <basegfx/polygon/b2dpolypolygon.hxx>
24
25
namespace svgio::svgreader
26
{
27
        SvgRectNode::SvgRectNode(
28
            SvgDocument& rDocument,
29
            SvgNode* pParent)
30
0
        :   SvgNode(SVGToken::Rect, rDocument, pParent),
31
0
            maSvgStyleAttributes(*this),
32
0
            maX(0),
33
0
            maY(0),
34
0
            maWidth(0),
35
0
            maHeight(0)
36
0
        {
37
0
        }
38
39
        SvgRectNode::~SvgRectNode()
40
0
        {
41
0
        }
42
43
        const SvgStyleAttributes* SvgRectNode::getSvgStyleAttributes() const
44
0
        {
45
0
            return checkForCssStyle(maSvgStyleAttributes);
46
0
        }
47
48
        void SvgRectNode::parseAttribute(SVGToken aSVGToken, const OUString& aContent)
49
0
        {
50
            // call parent
51
0
            SvgNode::parseAttribute(aSVGToken, aContent);
52
53
            // read style attributes
54
0
            maSvgStyleAttributes.parseStyleAttribute(aSVGToken, aContent);
55
56
            // parse own
57
0
            switch(aSVGToken)
58
0
            {
59
0
                case SVGToken::Style:
60
0
                {
61
0
                    readLocalCssStyle(aContent);
62
0
                    break;
63
0
                }
64
0
                case SVGToken::X:
65
0
                {
66
0
                    SvgNumber aNum;
67
68
0
                    if(readSingleNumber(aContent, aNum))
69
0
                    {
70
0
                        maX = aNum;
71
0
                    }
72
0
                    break;
73
0
                }
74
0
                case SVGToken::Y:
75
0
                {
76
0
                    SvgNumber aNum;
77
78
0
                    if(readSingleNumber(aContent, aNum))
79
0
                    {
80
0
                        maY = aNum;
81
0
                    }
82
0
                    break;
83
0
                }
84
0
                case SVGToken::Width:
85
0
                {
86
0
                    SvgNumber aNum;
87
88
0
                    if(readSingleNumber(aContent, aNum))
89
0
                    {
90
0
                        if(aNum.isPositive())
91
0
                        {
92
0
                            maWidth = aNum;
93
0
                        }
94
0
                    }
95
0
                    break;
96
0
                }
97
0
                case SVGToken::Height:
98
0
                {
99
0
                    SvgNumber aNum;
100
101
0
                    if(readSingleNumber(aContent, aNum))
102
0
                    {
103
0
                        if(aNum.isPositive())
104
0
                        {
105
0
                            maHeight = aNum;
106
0
                        }
107
0
                    }
108
0
                    break;
109
0
                }
110
0
                case SVGToken::Rx:
111
0
                {
112
0
                    SvgNumber aNum;
113
114
0
                    if(readSingleNumber(aContent, aNum))
115
0
                    {
116
0
                        if(aNum.isPositive())
117
0
                        {
118
0
                            maRx = aNum;
119
0
                        }
120
0
                    }
121
0
                    break;
122
0
                }
123
0
                case SVGToken::Ry:
124
0
                {
125
0
                    SvgNumber aNum;
126
127
0
                    if(readSingleNumber(aContent, aNum))
128
0
                    {
129
0
                        if(aNum.isPositive())
130
0
                        {
131
0
                            maRy = aNum;
132
0
                        }
133
0
                    }
134
0
                    break;
135
0
                }
136
0
                case SVGToken::Transform:
137
0
                {
138
0
                    const basegfx::B2DHomMatrix aMatrix(readTransform(aContent, *this));
139
140
0
                    if(!aMatrix.isIdentity())
141
0
                    {
142
0
                        setTransform(aMatrix);
143
0
                    }
144
0
                    break;
145
0
                }
146
0
                default:
147
0
                {
148
0
                    break;
149
0
                }
150
0
            }
151
0
        }
152
153
        void SvgRectNode::decomposeSvgNode(drawinglayer::primitive2d::Primitive2DContainer& rTarget, bool /*bReferenced*/) const
154
0
        {
155
            // get size range and create path
156
0
            const SvgStyleAttributes* pStyle = getSvgStyleAttributes();
157
158
0
            if(!(pStyle && getWidth().isSet() && getHeight().isSet()))
159
0
                return;
160
161
0
            const double fWidth(getWidth().solve(*this, NumberType::xcoordinate));
162
0
            const double fHeight(getHeight().solve(*this, NumberType::ycoordinate));
163
164
0
            if(fWidth <= 0.0 || fHeight <= 0.0)
165
0
                return;
166
167
0
            const double fX(getX().isSet() ? getX().solve(*this, NumberType::xcoordinate) : 0.0);
168
0
            const double fY(getY().isSet() ? getY().solve(*this, NumberType::ycoordinate) : 0.0);
169
0
            const basegfx::B2DRange aRange(fX, fY, fX + fWidth, fY + fHeight);
170
0
            basegfx::B2DPolygon aPath;
171
172
0
            if(getRx().isSet() || getRy().isSet())
173
0
            {
174
0
                double frX(getRx().isSet() ? getRx().solve(*this, NumberType::xcoordinate) : 0.0);
175
0
                double frY(getRy().isSet() ? getRy().solve(*this, NumberType::ycoordinate) : 0.0);
176
177
0
                if(!getRy().isSet() && 0.0 == frY && frX > 0.0)
178
0
                {
179
0
                    frY = frX;
180
0
                }
181
0
                else if(!getRx().isSet() && 0.0 == frX && frY > 0.0)
182
0
                {
183
0
                    frX = frY;
184
0
                }
185
186
0
                assert(fWidth != 0 && fHeight != 0 && "help coverity see it's not zero");
187
188
0
                frX /= fWidth;
189
0
                frY /= fHeight;
190
191
0
                frX = std::min(0.5, frX);
192
0
                frY = std::min(0.5, frY);
193
194
0
                aPath = basegfx::utils::createPolygonFromRect(aRange, frX * 2.0, frY * 2.0);
195
0
            }
196
0
            else
197
0
            {
198
0
                aPath = basegfx::utils::createPolygonFromRect(aRange);
199
0
            }
200
201
0
            drawinglayer::primitive2d::Primitive2DContainer aNewTarget;
202
203
0
            pStyle->add_path(basegfx::B2DPolyPolygon(aPath), aNewTarget, nullptr);
204
205
0
            if(!aNewTarget.empty())
206
0
            {
207
0
                pStyle->add_postProcess(rTarget, std::move(aNewTarget), getTransform());
208
0
            }
209
0
        }
210
} // end of namespace svgio::svgreader
211
212
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */