KiCad PCB EDA Suite
Loading...
Searching...
No Matches
svg_test_utils.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
21
22#include <nanosvg.h>
23
24#include <wx/mstream.h>
25#include <wx/xml/xml.h>
26
27#include <fast_float/fast_float.h>
28
29
30tl::expected<wxXmlDocument, wxString> KI_TEST::LoadSvg( const wxString& aSvg )
31{
32 const wxCharBuffer utf8 = aSvg.ToUTF8();
33 wxMemoryInputStream input( utf8.data(), utf8.length() );
34 wxXmlDocument doc;
35
36 if( !doc.Load( input ) )
37 return tl::make_unexpected( wxString( wxS( "Failed to load SVG XML" ) ) );
38
39 if( doc.GetRoot()->GetName() != wxT( "svg" ) )
40 return tl::make_unexpected( wxString( wxS( "Root element is not <svg>" ) ) );
41
42 return doc;
43}
44
45
46tl::expected<KI_TEST::SVG_VIEWBOX, wxString> KI_TEST::ParseViewBox( const wxXmlNode& aRoot )
47{
48 if( aRoot.GetName() != wxT( "svg" ) )
49 return tl::make_unexpected( wxS( "Root element is not <svg>" ) );
50
51 wxString viewBox;
52
53 if( !aRoot.GetAttribute( wxT( "viewBox" ), &viewBox ) )
54 return tl::make_unexpected( wxS( "Missing viewBox attribute" ) );
55
56 // The viewBox is four whitespace-separated numbers: min-x, min-y, width, height.
57 const std::string values = viewBox.ToStdString();
58 SVG_VIEWBOX parsed{};
59 double* const valuesToParse[] = { &parsed.m_X, &parsed.m_Y, &parsed.m_Width, &parsed.m_Height };
60 size_t pos = 0;
61
62 for( double* value : valuesToParse )
63 {
64 while( pos < values.size() && ( values[pos] == ' ' || values[pos] == '\t' ) )
65 pos++;
66
67 if( pos >= values.size() )
68 return tl::make_unexpected( wxS( "viewBox must contain four numbers" ) );
69
70 const auto [ptr, ec] = fast_float::from_chars( values.data() + pos, values.data() + values.size(), *value );
71
72 if( ec != std::errc() )
73 return tl::make_unexpected( wxS( "Invalid viewBox number" ) );
74
75 pos = ptr - values.data();
76 }
77
78 while( pos < values.size() && ( values[pos] == ' ' || values[pos] == '\t' ) )
79 pos++;
80
81 if( pos != values.size() )
82 return tl::make_unexpected( wxS( "viewBox must contain exactly four numbers" ) );
83
84 return parsed;
85}
86
87
88const wxXmlNode* KI_TEST::FindFirstRect( const wxXmlNode& aNode )
89{
90 for( const wxXmlNode* child = aNode.GetChildren(); child; child = child->GetNext() )
91 {
92 if( child->GetName() == wxT( "rect" ) )
93 return child;
94
95 if( const wxXmlNode* rect = FindFirstRect( *child ) )
96 return rect;
97 }
98
99 return nullptr;
100}
const wxXmlNode * FindFirstRect(const wxXmlNode &aNode)
Find the first <rect> element in the given XML node's descendants.
tl::expected< wxXmlDocument, wxString > LoadSvg(const wxString &aSvg)
tl::expected< SVG_VIEWBOX, wxString > ParseViewBox(const wxXmlNode &aRoot)
Parse the four numbers of the SVG viewBox attribute (min-x, min-y, width, height).