KiCad PCB EDA Suite
gerber_file_image_list.cpp
Go to the documentation of this file.
1
6/*
7 * This program source code file is part of KiCad, a free EDA CAD application.
8 *
9 * Copyright (C) 1992-2016 Jean-Pierre Charras jp.charras at wanadoo.fr
10 * Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, you may find one here:
24 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
25 * or you may search the http://www.gnu.org website for the version 2 license,
26 * or you may write to the Free Software Foundation, Inc.,
27 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
28 */
29
30#include <gerbview.h>
31#include <gerbview_frame.h>
32#include <gerber_file_image.h>
35
36#include <map>
37
38
39// The global image list:
41
42
44{
46
47 for( unsigned layer = 0; layer < GERBER_DRAWLAYERS_COUNT; ++layer )
48 m_GERBER_List.push_back( nullptr );
49}
50
51
53{
55}
56
57
59{
60 return s_GERBER_List;
61}
62
63
65{
66 if( (unsigned)aIdx < m_GERBER_List.size() )
67 return m_GERBER_List[aIdx];
68
69 return nullptr;
70}
71
72
74{
75 auto notNull = []( GERBER_FILE_IMAGE* image )
76 {
77 return image != nullptr;
78 };
79 return std::count_if( m_GERBER_List.begin(), m_GERBER_List.end(), notNull );
80}
81
82
84{
85 int idx = aIdx;
86
87 if( idx < 0 )
88 {
89 for( idx = 0; idx < (int)m_GERBER_List.size(); idx++ )
90 {
91 if( m_GERBER_List[idx] == nullptr )
92 break;
93 }
94 }
95
96 if( idx >= (int)m_GERBER_List.size() )
97 return -1; // No room
98
99 m_GERBER_List[idx] = aGbrImage;
100
101 return idx;
102}
103
104
106{
107 for( unsigned idx = 0; idx < m_GERBER_List.size(); ++idx )
108 DeleteImage( idx );
109}
110
111
112void GERBER_FILE_IMAGE_LIST::DeleteImage( unsigned int aIdx )
113{
114 // Ensure the index is valid:
115 if( aIdx >= m_GERBER_List.size() )
116 return;
117
118 // delete image aIdx
119 GERBER_FILE_IMAGE* gbr_image = GetGbrImage( static_cast<int>( aIdx ) );
120
121 delete gbr_image;
122 m_GERBER_List[ aIdx ] = nullptr;
123}
124
125
126const wxString GERBER_FILE_IMAGE_LIST::GetDisplayName( int aIdx, bool aNameOnly, bool aFullName )
127{
128 wxString name;
129
130 GERBER_FILE_IMAGE* gerber = nullptr;
131
132 if( aIdx >= 0 && aIdx < (int)m_GERBER_List.size() )
133 gerber = m_GERBER_List[aIdx];
134
135 // if a file is loaded, build the name:
136 // <id> <short filename> <X2 FileFunction info> if a X2 FileFunction info is found
137 // or (if no FileFunction info)
138 // <id> <short filename> *
139 if( gerber )
140 {
141 wxFileName fn( gerber->m_FileName );
142 wxString filename = fn.GetFullName();
143
144 // If the filename is too long, display a shortened name if requested
145 const int maxlen = 30;
146
147 if( !aFullName && filename.Length() > maxlen )
148 {
149 wxString shortenedfn = filename.Left(2) + wxT( "..." ) + filename.Right(maxlen-5);
150 filename = shortenedfn;
151 }
152
153 if( gerber->m_FileFunction )
154 {
155 if( gerber->m_FileFunction->IsCopper() )
156 {
157 name.Printf( wxT( "%s (%s, %s, %s)" ),
158 filename.GetData(),
159 gerber->m_FileFunction->GetFileType(),
160 gerber->m_FileFunction->GetBrdLayerId(),
161 gerber->m_FileFunction->GetBrdLayerSide() );
162 }
163 if( gerber->m_FileFunction->IsDrillFile() )
164 {
165 name.Printf( wxT( "%s (%s,%s,%s,%s)" ),
166 filename.GetData(),
167 gerber->m_FileFunction->GetFileType(),
169 gerber->m_FileFunction->GetLPType(),
170 gerber->m_FileFunction->GetRouteType() );
171 }
172 else
173 {
174 name.Printf( wxT( "%s (%s, %s)" ),
175 filename.GetData(),
176 gerber->m_FileFunction->GetFileType(),
177 gerber->m_FileFunction->GetBrdLayerId() );
178 }
179 }
180 else
181 {
182 name = filename;
183 }
184
185 if( aNameOnly )
186 return name;
187
188 wxString fullname;
189
190 fullname.Printf( wxT( "%d " ), aIdx + 1 );
191 fullname << name;
192 return fullname;
193 }
194 else
195 {
196 name.Printf( _( "Graphic layer %d" ), aIdx + 1 );
197 }
198
199 return name;
200}
201
202
204{
205 std::string m_FilenameMask;
207};
208
209
210// clang-format off
212{
221
223
226
234
241
248
255
263
269
276
283
290
291 // EAGLE CAD file to explicitly ignore that can match some other
292 // layers otherwise
294
295 // Inner copper layers need to come last so the wildcard
296 // number matching doesn't pick up other specific layer names.
303};
304// clang-format on
305
306
308 enum GERBER_ORDER_ENUM& order,
309 wxString& matchedExtension )
310{
312 matchedExtension = "";
313
314 for( struct GERBER_ORDER o : gerberFileExtensionOrder )
315 {
316 wxString ext = filename.Right( o.m_FilenameMask.length() ).Upper();
317
318 if( ext.Matches( o.m_FilenameMask ) )
319 {
320 order = o.m_Order;
321 matchedExtension = ext;
322 return;
323 }
324 }
325}
326
327
328static bool sortFileExtension( const GERBER_FILE_IMAGE* const& ref,
329 const GERBER_FILE_IMAGE* const& test )
330{
331 // Do not change order: no criteria to sort items
332 if( !ref && !test )
333 return false;
334
335 // Not used: ref ordered after
336 if( !ref || !ref->m_InUse )
337 return false;
338
339 // Not used: ref ordered before
340 if( !test || !test->m_InUse )
341 return true;
342
343 enum GERBER_ORDER_ENUM ref_layer;
344 enum GERBER_ORDER_ENUM test_layer;
345 wxString ref_extension;
346 wxString test_extension;
347
349 ref_extension );
351 test_extension );
352
353 // Inner layers have a numeric code that we can compare against
354 if( ref_layer == GERBER_ORDER_ENUM::GERBER_INNER
355 && test_layer == GERBER_ORDER_ENUM::GERBER_INNER )
356 {
357 unsigned long ref_layer_number = 0;
358 unsigned long test_layer_number = 0;
359
360 // Strip extensions down to only the numbers in it. Later conversion to int will
361 // automatically skip the spaces
362 for( wxString::iterator it = ref_extension.begin(); it != ref_extension.end(); ++it )
363 {
364 if( !isdigit( *it ) )
365 *it = ' ';
366 }
367
368 for( wxString::iterator it = test_extension.begin(); it != test_extension.end(); ++it )
369 {
370 if( !isdigit( *it ) )
371 *it = ' ';
372 }
373
374 ref_extension.ToULong( &ref_layer_number );
375 test_extension.ToULong( &test_layer_number );
376
377 return ref_layer_number < test_layer_number;
378 }
379
380 return (int) ref_layer < (int) test_layer;
381}
382
383
384// Helper function, for std::sort.
385// Sort loaded images by Z order priority, if they have the X2 FileFormat info
386// returns true if the first argument (ref) is ordered before the second (test).
387static bool sortZorder( const GERBER_FILE_IMAGE* const& ref, const GERBER_FILE_IMAGE* const& test )
388{
389 if( !ref && !test )
390 return false; // do not change order: no criteria to sort items
391
392 if( !ref || !ref->m_InUse )
393 return false; // Not used: ref ordered after
394
395 if( !test || !test->m_InUse )
396 return true; // Not used: ref ordered before
397
398 if( !ref->m_FileFunction && !test->m_FileFunction )
399 return false; // do not change order: no criteria to sort items
400
401 if( !ref->m_FileFunction )
402 return false;
403
404 if( !test->m_FileFunction )
405 return true;
406
407 if( ref->m_FileFunction->GetZOrder() != test->m_FileFunction->GetZOrder() )
408 return ref->m_FileFunction->GetZOrder() > test->m_FileFunction->GetZOrder();
409
410 return ref->m_FileFunction->GetZSubOrder() > test->m_FileFunction->GetZSubOrder();
411}
412
413
414std::unordered_map<int, int> GERBER_FILE_IMAGE_LIST::GetLayerRemap()
415{
416 // The image order has changed.
417 // Graphic layer numbering must be updated to match the widgets layer order
418
419 // Store the old/new graphic layer info:
420 std::unordered_map<int, int> tab_lyr;
421
422 for( unsigned layer = 0; layer < m_GERBER_List.size(); ++layer )
423 {
424 GERBER_FILE_IMAGE* gerber = m_GERBER_List[layer];
425
426 if( !gerber )
427 continue;
428
429 tab_lyr[gerber->m_GraphicLayer] = layer;
430 gerber->m_GraphicLayer = layer ;
431 }
432
433 return tab_lyr;
434}
435
436
437std::unordered_map<int, int>
439{
440 std::sort( m_GERBER_List.begin(), m_GERBER_List.end(), sortFunction );
441 return GetLayerRemap();
442}
443
444
446{
448}
449
450
451std::unordered_map<int, int> GERBER_FILE_IMAGE_LIST::SortImagesByZOrder()
452{
454}
455
456
457std::unordered_map<int, int> GERBER_FILE_IMAGE_LIST::SwapImages( unsigned int layer1,
458 unsigned int layer2 )
459{
460 if( ( layer1 >= m_GERBER_List.size() ) || ( layer2 >= m_GERBER_List.size() ) )
461 return std::unordered_map<int, int>();
462
463 std::swap( m_GERBER_List[layer1], m_GERBER_List[layer2] );
464 return GetLayerRemap();
465}
466
467std::unordered_map<int, int> GERBER_FILE_IMAGE_LIST::RemoveImage( unsigned int layer )
468{
469 if( layer >= m_GERBER_List.size() )
470 return std::unordered_map<int, int>();
471
472 DeleteImage( layer );
473 // Move deleted image to end of list, move all other images up
474 std::rotate( m_GERBER_List.begin() + layer, m_GERBER_List.begin() + layer + 1,
475 m_GERBER_List.end() );
476 return GetLayerRemap();
477}
const char * name
Definition: DXF_plotter.cpp:56
GERBER_FILE_IMAGE_LIST is a helper class to handle a list of GERBER_FILE_IMAGE files which are loaded...
int AddGbrImage(GERBER_FILE_IMAGE *aGbrImage, int aIdx)
Add a GERBER_FILE_IMAGE* at index aIdx or at the first free location if aIdx < 0.
std::unordered_map< int, int > SwapImages(unsigned int layer1, unsigned int layer2)
Swap two images and their orders.
unsigned GetLoadedImageCount()
Get number of loaded images.
static void GetGerberLayerFromFilename(const wxString &filename, enum GERBER_ORDER_ENUM &order, wxString &matchedExtension)
Utility function to guess which PCB layer of a gerber/drill file corresponds to based on its file ext...
std::unordered_map< int, int > SortImagesByZOrder()
Sort loaded images by Z order priority, if they have the X2 FileFormat info (SortImagesByZOrder updat...
void DeleteImage(unsigned int aIdx)
Delete the loaded data of image aIdx, freeing the memory.
std::unordered_map< int, int > SortImagesByFileExtension()
Sort loaded images by file extension matching.
static GERBER_FILE_IMAGE_LIST & GetImagesList()
const wxString GetDisplayName(int aIdx, bool aNameOnly=false, bool aFullName=false)
Get the display name for the layer at aIdx.
void DeleteAllImages()
Remove all loaded data in list, and delete all images, freeing the memory.
std::vector< GERBER_FILE_IMAGE * > m_GERBER_List
std::unordered_map< int, int > RemoveImage(unsigned int layer)
Removes (and deletes) an image, rotating the removed image to the end.
std::unordered_map< int, int > GetLayerRemap()
When the image order has changed, call this to get a mapping to pass to the frame's Remap() function ...
std::unordered_map< int, int > SortImagesByFunction(LayerSortFunction sortFunction)
Sort loaded images by file extension matching.
GERBER_FILE_IMAGE * GetGbrImage(int aIdx)
Hold the image data and parameters for one gerber file and layer parameters.
X2_ATTRIBUTE_FILEFUNCTION * m_FileFunction
file function parameters, found in a TF command or a G04
wxString m_FileName
Full File Name for this layer.
bool m_InUse
true if this image is currently in use (a file is loaded in it) false if it must be not drawn
int m_GraphicLayer
Graphic layer Number.
bool IsCopper()
return true if the filefunction type is "Copper"
const wxString & GetBrdLayerSide()
the brd layer Pos: Top, Bot, Inr same as GetBrdLayerId() for non copper type
const wxString & GetFileType()
the type of layer (Copper, Soldermask ... )
int GetZSubOrder()
the Order of the bdr copper layer, from front (Top) side to back (Bot) side
const wxString & GetBrdLayerId()
the brd layer identifier: Ln, only for Copper type or Top, Bot for other types
int GetZOrder()
the Order of the board layer, from front (Top) side to back (Bot) side
#define _(s)
static struct GERBER_ORDER gerberFileExtensionOrder[]
static bool sortZorder(const GERBER_FILE_IMAGE *const &ref, const GERBER_FILE_IMAGE *const &test)
GERBER_FILE_IMAGE_LIST s_GERBER_List
static bool sortFileExtension(const GERBER_FILE_IMAGE *const &ref, const GERBER_FILE_IMAGE *const &test)
bool() LayerSortFunction(const GERBER_FILE_IMAGE *const &ref, const GERBER_FILE_IMAGE *const &test)
#define GERBER_DRAWLAYERS_COUNT
Definition: layer_ids.h:402
GERBER_ORDER_ENUM m_Order