KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pads_layer_mapper.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
20#include "pads_layer_mapper.h"
21
22#include <algorithm>
23#include <cctype>
24
25#include <io/pads/pads_common.h>
26
27#include <wx/string.h>
28
29
32{
33 // Keys are normalized to lower case; ParseLayerName lower-cases before lookup.
39
45
51
57
60 m_layerNameMap["solder paste top"] = PADS_LAYER_TYPE::PASTE_TOP;
62
64 m_layerNameMap["paste mask bottom"] = PADS_LAYER_TYPE::PASTE_BOTTOM;
65 m_layerNameMap["solder paste bottom"] = PADS_LAYER_TYPE::PASTE_BOTTOM;
67
69 m_layerNameMap["assembly drawing top"] = PADS_LAYER_TYPE::ASSEMBLY_TOP;
72 m_layerNameMap["component outline top"] = PADS_LAYER_TYPE::ASSEMBLY_TOP;
73
75 m_layerNameMap["assembly drawing bottom"] = PADS_LAYER_TYPE::ASSEMBLY_BOTTOM;
78 m_layerNameMap["component outline bottom"] = PADS_LAYER_TYPE::ASSEMBLY_BOTTOM;
79
84
88
95
99}
100
101
103{
104 if( aLayerCount < 1 )
105 aLayerCount = 1;
106
107 m_copperLayerCount = aLayerCount;
108}
109
110
111std::string PADS_LAYER_MAPPER::normalizeLayerName( const std::string& aName ) const
112{
113 std::string normalized;
114 normalized.reserve( aName.size() );
115
116 for( char c : aName )
117 {
118 normalized += static_cast<char>( std::tolower( static_cast<unsigned char>( c ) ) );
119 }
120
121 return normalized;
122}
123
124
126{
127 if( aPadsLayer == LAYER_PAD_STACK_TOP )
129
130 if( aPadsLayer == LAYER_PAD_STACK_BOTTOM )
132
133 if( aPadsLayer == LAYER_PAD_STACK_INNER )
135
136 // Copper layers: 1 = Top, m_copperLayerCount = Bottom, 2 to N-1 = Inner
137 if( aPadsLayer == 1 )
139
140 if( aPadsLayer == m_copperLayerCount && m_copperLayerCount > 1 )
142
143 if( aPadsLayer > 1 && aPadsLayer < m_copperLayerCount )
145
146 if( aPadsLayer == LAYER_DRILL_DRAWING )
148
149 if( aPadsLayer == LAYER_DIMENSIONS || aPadsLayer == LAYER_PLACEMENT_OUTLINE )
151
152 if( aPadsLayer == LAYER_ASSEMBLY_TOP )
154
155 if( aPadsLayer == LAYER_ASSEMBLY_BOTTOM )
157
158 if( aPadsLayer == LAYER_SOLDERMASK_TOP )
160
161 if( aPadsLayer == LAYER_SILKSCREEN_TOP )
163
164 if( aPadsLayer == LAYER_SILKSCREEN_BOTTOM )
166
167 if( aPadsLayer == LAYER_SOLDERMASK_BOTTOM )
169
170 if( aPadsLayer == LAYER_PASTE_TOP )
172
173 if( aPadsLayer == LAYER_PASTE_BOTTOM )
175
177}
178
179
180PADS_LAYER_TYPE PADS_LAYER_MAPPER::ParseLayerName( const std::string& aLayerName ) const
181{
182 std::string normalized = normalizeLayerName( aLayerName );
183
184 auto it = m_layerNameMap.find( normalized );
185
186 if( it != m_layerNameMap.end() )
187 return it->second;
188
189 // Match the whole name, or an ordinal prefix for the numbered inner layers. A substring is not
190 // evidence of copper: "Top Notes", "Topology" and "Bot Assy Text" all contain one, and an
191 // unknown layer becomes documentation rather than silkscreen on F_Cu.
192 if( normalized == "top" || normalized == "layer 1" || normalized == "1" )
194
195 if( normalized == "bottom" || normalized == "bot" )
197
198 // An inner layer is the ordinal word alone or followed by its number. Requiring the boundary
199 // keeps "Internally Routed" and "Middle East Notes" out.
200 auto isOrdinalWord = []( const std::string& aName, const std::string& aWord )
201 {
202 if( !aName.starts_with( aWord ) )
203 return false;
204
205 if( aName.size() == aWord.size() )
206 return true;
207
208 char next = aName[aWord.size()];
209
210 return next == ' ' || next == '_' || next == '-'
211 || std::isdigit( static_cast<unsigned char>( next ) ) != 0;
212 };
213
214 if( isOrdinalWord( normalized, "internal" ) || isOrdinalWord( normalized, "inner" )
215 || isOrdinalWord( normalized, "mid" ) )
216 {
218 }
219
221}
222
223
225{
226 // PADS inner layers run 2..(count-1); KiCad In*_Cu IDs are spaced by 2.
227 int innerIndex = aPadsLayer - 2;
228
229 if( innerIndex < 0 )
230 innerIndex = 0;
231
232 if( innerIndex >= 30 )
233 innerIndex = 29;
234
235 return static_cast<PCB_LAYER_ID>( In1_Cu + innerIndex * 2 );
236}
237
238
240{
241 if( aType == PADS_LAYER_TYPE::UNKNOWN )
242 aType = GetLayerType( aPadsLayer );
243
244 switch( aType )
245 {
247 return F_Cu;
248
250 return B_Cu;
251
253 return mapInnerCopperLayer( aPadsLayer );
254
256 return F_SilkS;
257
259 return B_SilkS;
260
262 return F_Mask;
263
265 return B_Mask;
266
268 return F_Paste;
269
271 return B_Paste;
272
274 return F_Fab;
275
277 return B_Fab;
278
280 return Edge_Cuts;
281
283 return Cmts_User;
284
286 return Dwgs_User;
287
289 default:
290 return UNDEFINED_LAYER;
291 }
292}
293
294
296{
297 switch( aType )
298 {
302 return LSET::AllCuMask();
303
306 return LSET( { F_SilkS, B_SilkS } );
307
310 return LSET( { F_Mask, B_Mask } );
311
314 return LSET( { F_Paste, B_Paste } );
315
318 return LSET( { F_Fab, B_Fab, F_CrtYd, B_CrtYd } );
319
321 return LSET( { Edge_Cuts } );
322
324 return LSET::AllNonCuMask();
325
327 return LSET( { Dwgs_User, F_Fab, B_Fab, Cmts_User } );
328
330 default:
331 return LSET::AllLayersMask();
332 }
333}
334
335
337 const std::vector<PADS_LAYER_INFO>& aLayerInfos ) const
338{
339 std::vector<INPUT_LAYER_DESC> descs;
340 descs.reserve( aLayerInfos.size() );
341
342 for( const PADS_LAYER_INFO& info : aLayerInfos )
343 {
344 INPUT_LAYER_DESC desc;
345
346 desc.Name = PADS_COMMON::ConvertText( info.name );
348 desc.AutoMapLayer = GetAutoMapLayer( info.padsLayerNum, info.type );
349 desc.Required = info.required;
350
351 descs.push_back( desc );
352 }
353
354 return descs;
355}
356
357
358void PADS_LAYER_MAPPER::AddLayerNameMapping( const std::string& aName, PADS_LAYER_TYPE aType )
359{
360 std::string normalized = normalizeLayerName( aName );
361 m_layerNameMap[normalized] = aType;
362}
363
364
366{
367 switch( aType )
368 {
369 case PADS_LAYER_TYPE::COPPER_TOP: return "Copper Top";
370 case PADS_LAYER_TYPE::COPPER_BOTTOM: return "Copper Bottom";
371 case PADS_LAYER_TYPE::COPPER_INNER: return "Copper Inner";
372 case PADS_LAYER_TYPE::SILKSCREEN_TOP: return "Silkscreen Top";
373 case PADS_LAYER_TYPE::SILKSCREEN_BOTTOM: return "Silkscreen Bottom";
374 case PADS_LAYER_TYPE::SOLDERMASK_TOP: return "Solder Mask Top";
375 case PADS_LAYER_TYPE::SOLDERMASK_BOTTOM: return "Solder Mask Bottom";
376 case PADS_LAYER_TYPE::PASTE_TOP: return "Paste Top";
377 case PADS_LAYER_TYPE::PASTE_BOTTOM: return "Paste Bottom";
378 case PADS_LAYER_TYPE::ASSEMBLY_TOP: return "Assembly Top";
379 case PADS_LAYER_TYPE::ASSEMBLY_BOTTOM: return "Assembly Bottom";
380 case PADS_LAYER_TYPE::DOCUMENTATION: return "Documentation";
381 case PADS_LAYER_TYPE::BOARD_OUTLINE: return "Board Outline";
382 case PADS_LAYER_TYPE::DRILL_DRAWING: return "Drill Drawing";
384 default: return "Unknown";
385 }
386}
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
static const LSET & AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
Definition lset.cpp:604
static LSET AllNonCuMask()
Return a mask holding all layer minus CU layers.
Definition lset.cpp:623
static const LSET & AllLayersMask()
Definition lset.cpp:637
LSET GetPermittedLayers(PADS_LAYER_TYPE aType) const
PADS_LAYER_TYPE ParseLayerName(const std::string &aLayerName) const
static constexpr int LAYER_ASSEMBLY_TOP
static constexpr int LAYER_SILKSCREEN_BOTTOM
static constexpr int LAYER_PASTE_TOP
static constexpr int LAYER_SILKSCREEN_TOP
PADS_LAYER_TYPE GetLayerType(int aPadsLayer) const
static constexpr int LAYER_PLACEMENT_OUTLINE
static constexpr int LAYER_SOLDERMASK_TOP
static constexpr int LAYER_ASSEMBLY_BOTTOM
PCB_LAYER_ID mapInnerCopperLayer(int aPadsLayer) const
static constexpr int LAYER_DIMENSIONS
PCB_LAYER_ID GetAutoMapLayer(int aPadsLayer, PADS_LAYER_TYPE aType=PADS_LAYER_TYPE::UNKNOWN) const
Suggested KiCad layer for a PADS layer.
static constexpr int LAYER_PAD_STACK_BOTTOM
std::string normalizeLayerName(const std::string &aName) const
static constexpr int LAYER_PAD_STACK_TOP
static constexpr int LAYER_PASTE_BOTTOM
static std::string LayerTypeToString(PADS_LAYER_TYPE aType)
void SetCopperLayerCount(int aLayerCount)
static constexpr int LAYER_PAD_STACK_INNER
std::map< std::string, PADS_LAYER_TYPE > m_layerNameMap
std::vector< INPUT_LAYER_DESC > BuildInputLayerDescriptions(const std::vector< PADS_LAYER_INFO > &aLayerInfos) const
void AddLayerNameMapping(const std::string &aName, PADS_LAYER_TYPE aType)
static constexpr int LAYER_DRILL_DRAWING
static constexpr int LAYER_SOLDERMASK_BOTTOM
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
@ F_CrtYd
Definition layer_ids.h:112
@ Edge_Cuts
Definition layer_ids.h:108
@ Dwgs_User
Definition layer_ids.h:103
@ F_Paste
Definition layer_ids.h:100
@ Cmts_User
Definition layer_ids.h:104
@ B_Mask
Definition layer_ids.h:94
@ B_Cu
Definition layer_ids.h:61
@ F_Mask
Definition layer_ids.h:93
@ B_Paste
Definition layer_ids.h:101
@ F_Fab
Definition layer_ids.h:115
@ F_SilkS
Definition layer_ids.h:96
@ B_CrtYd
Definition layer_ids.h:111
@ UNDEFINED_LAYER
Definition layer_ids.h:57
@ In1_Cu
Definition layer_ids.h:62
@ B_SilkS
Definition layer_ids.h:97
@ F_Cu
Definition layer_ids.h:60
@ B_Fab
Definition layer_ids.h:114
wxString ConvertText(const std::string &aText)
Decode text from a PADS file, which uses an 8-bit codepage rather than UTF-8.
PADS_LAYER_TYPE
Functional categories of PADS layers, independent of specific layer numbers.
CITER next(CITER it)
Definition ptree.cpp:120
Describes an imported layer and how it could be mapped to KiCad Layers.
PCB_LAYER_ID AutoMapLayer
Best guess as to what the equivalent KiCad layer might be.
bool Required
Should we require the layer to be assigned?
LSET PermittedLayers
KiCad layers that the imported layer can be mapped onto.
wxString Name
Imported layer name as displayed in original application.