KiCad PCB EDA Suite
Loading...
Searching...
No Matches
altium_props_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 (C) 2019-2020 Thomas Pointhuber <[email protected]>
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21#include "altium_props_utils.h"
22
23#include <limits>
24#include <sstream>
25#include <math/util.h>
26
27#include <wx/crt.h>
28#include <wx/log.h>
29#include <wx/translation.h>
30
31
32int32_t ALTIUM_PROPS_UTILS::ConvertToKicadUnit( const double aValue, bool* aOutOfRange )
33{
34 constexpr double int_limit = ( std::numeric_limits<int>::max() - 10 ) / 2.54;
35
36 if( aOutOfRange )
37 *aOutOfRange = !( aValue >= -int_limit && aValue <= int_limit );
38
39 int32_t iu = KiROUND( std::clamp( aValue, -int_limit, int_limit ) * 2.54 );
40
41 // Altium's internal precision is 0.1uinch. KiCad's is 1nm. Round to nearest 10nm to clean
42 // up most rounding errors. This allows lossless conversion of increments of 0.05mils and
43 // 0.01um.
44 return KiROUND( (double) iu / 10.0 ) * 10;
45}
46
47
48int ALTIUM_PROPS_UTILS::ReadInt( const std::map<wxString, wxString>& aProps, const wxString& aKey,
49 int aDefault )
50{
51 const std::map<wxString, wxString>::const_iterator& value = aProps.find( aKey );
52 return value == aProps.end() ? aDefault : wxAtoi( value->second );
53}
54
55
56double ALTIUM_PROPS_UTILS::ReadDouble( const std::map<wxString, wxString>& aProps,
57 const wxString& aKey, double aDefault )
58{
59 const std::map<wxString, wxString>::const_iterator& value = aProps.find( aKey );
60
61 if( value == aProps.end() )
62 return aDefault;
63
64 // Locale independent str -> double conversation
65 std::istringstream istr( (const char*) value->second.mb_str() );
66 istr.imbue( std::locale::classic() );
67
68 double doubleValue;
69 istr >> doubleValue;
70 return doubleValue;
71}
72
73
74bool ALTIUM_PROPS_UTILS::ReadBool( const std::map<wxString, wxString>& aProps, const wxString& aKey,
75 bool aDefault )
76{
77 const std::map<wxString, wxString>::const_iterator& value = aProps.find( aKey );
78
79 if( value == aProps.end() )
80 return aDefault;
81 else
82 return value->second == "T" || value->second == "TRUE";
83}
84
85
86int32_t ALTIUM_PROPS_UTILS::ReadKicadUnit( const std::map<wxString, wxString>& aProps,
87 const wxString& aKey, const wxString& aDefault,
88 bool* aOutOfRange )
89{
90 if( aOutOfRange )
91 *aOutOfRange = false;
92
93 const wxString& value = ReadString( aProps, aKey, aDefault );
94
95 wxString prefix;
96
97 if( !value.EndsWith( "mil", &prefix ) )
98 {
99 wxLogTrace( "ALTIUM", wxT( "Unit '%s' does not end with 'mil'." ), value );
100 return 0;
101 }
102
103 prefix.StartsWith( "+", &prefix );
104
105 double mils;
106
107 if( !prefix.ToCDouble( &mils ) )
108 {
109 wxLogTrace( "ALTIUM", wxT( "Cannot convert '%s' to double." ), prefix );
110 return 0;
111 }
112
113 return ConvertToKicadUnit( mils * 10000, aOutOfRange );
114}
115
116
117wxString ALTIUM_PROPS_UTILS::ReadString( const std::map<wxString, wxString>& aProps,
118 const wxString& aKey, const wxString& aDefault )
119{
120 const auto& utf8Value = aProps.find( wxString( "%UTF8%" ) + aKey );
121
122 if( utf8Value != aProps.end() )
123 return utf8Value->second;
124
125 const auto& value = aProps.find( aKey );
126
127 if( value != aProps.end() )
128 return value->second;
129
130 return aDefault;
131}
132
133
134wxString ALTIUM_PROPS_UTILS::ReadUnicodeString( const std::map<wxString, wxString>& aProps,
135 const wxString& aKey, const wxString& aDefault )
136{
137 const auto& unicodeFlag = aProps.find( wxS( "UNICODE" ) );
138
139 if( unicodeFlag != aProps.end() && unicodeFlag->second.Contains( wxS( "EXISTS" ) ) )
140 {
141 const auto& unicodeValue = aProps.find( wxString( "UNICODE__" ) + aKey );
142
143 if( unicodeValue != aProps.end() )
144 {
145 wxArrayString arr = wxSplit( unicodeValue->second, ',', '\0' );
146 wxString out;
147
148 for( wxString part : arr )
149 out += wxString( wchar_t( wxAtoi( part ) ) );
150
151 return out;
152 }
153 }
154
155 return ReadString( aProps, aKey, aDefault );
156}
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:995
static int ReadInt(const std::map< wxString, wxString > &aProps, const wxString &aKey, int aDefault)
static int32_t ConvertToKicadUnit(const double aValue, bool *aOutOfRange=nullptr)
Convert a value in Altium's internal unit (0.1 uinch) to KiCad IU, clamped to the representable range...
static bool ReadBool(const std::map< wxString, wxString > &aProps, const wxString &aKey, bool aDefault)
static wxString ReadUnicodeString(const std::map< wxString, wxString > &aProps, const wxString &aKey, const wxString &aDefault)
static wxString ReadString(const std::map< wxString, wxString > &aProps, const wxString &aKey, const wxString &aDefault)
static int32_t ReadKicadUnit(const std::map< wxString, wxString > &aProps, const wxString &aKey, const wxString &aDefault, bool *aOutOfRange=nullptr)
static double ReadDouble(const std::map< wxString, wxString > &aProps, const wxString &aKey, double aDefault)