KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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#include <wx/filename.h>
36
37#include <map>
38
39
40// The global image list:
42
43
45{
47
48 for( unsigned layer = 0; layer < GERBER_DRAWLAYERS_COUNT; ++layer )
49 m_GERBER_List.push_back( nullptr );
50}
51
52
54{
56}
57
58
60{
61 return s_GERBER_List;
62}
63
64
66{
67 if( (unsigned)aIdx < m_GERBER_List.size() )
68 return m_GERBER_List[aIdx];
69
70 return nullptr;
71}
72
73
75{
76 auto notNull = []( GERBER_FILE_IMAGE* image )
77 {
78 return image != nullptr;
79 };
80 return std::count_if( m_GERBER_List.begin(), m_GERBER_List.end(), notNull );
81}
82
83
85{
86 int idx = aIdx;
87
88 if( idx < 0 )
89 {
90 for( idx = 0; idx < (int)m_GERBER_List.size(); idx++ )
91 {
92 if( m_GERBER_List[idx] == nullptr )
93 break;
94 }
95 }
96
97 if( idx >= (int)m_GERBER_List.size() )
98 return -1; // No room
99
100 m_GERBER_List[idx] = aGbrImage;
101
102 return idx;
103}
104
105
107{
108 for( unsigned idx = 0; idx < m_GERBER_List.size(); ++idx )
109 DeleteImage( idx );
110}
111
112
113void GERBER_FILE_IMAGE_LIST::DeleteImage( unsigned int aIdx )
114{
115 // Ensure the index is valid:
116 if( aIdx >= m_GERBER_List.size() )
117 return;
118
119 // delete image aIdx
120 GERBER_FILE_IMAGE* gbr_image = GetGbrImage( static_cast<int>( aIdx ) );
121
122 delete gbr_image;
123 m_GERBER_List[ aIdx ] = nullptr;
124}
125
126
127const wxString GERBER_FILE_IMAGE_LIST::GetDisplayName( int aIdx, bool aNameOnly, bool aFullName )
128{
129 wxString name;
130
131 GERBER_FILE_IMAGE* gerber = nullptr;
132
133 if( aIdx >= 0 && aIdx < (int)m_GERBER_List.size() )
134 gerber = m_GERBER_List[aIdx];
135
136 // if a file is loaded, build the name:
137 // <id> <short filename> <X2 FileFunction info> if a X2 FileFunction info is found
138 // or (if no FileFunction info)
139 // <id> <short filename> *
140 if( gerber )
141 {
142 wxFileName fn( gerber->m_FileName );
143 wxString filename = fn.GetFullName();
144
145 // If the filename is too long, display a shortened name if requested
146 const int maxlen = 30;
147
148 if( !aFullName && filename.Length() > maxlen )
149 {
150 wxString shortenedfn = filename.Left(2) + wxT( "..." ) + filename.Right(maxlen-5);
151 filename = shortenedfn;
152 }
153
154 if( gerber->m_FileFunction )
155 {
156 if( gerber->m_FileFunction->IsCopper() )
157 {
158 name.Printf( wxT( "%s (%s, %s, %s)" ),
159 filename.GetData(),
160 gerber->m_FileFunction->GetFileType(),
161 gerber->m_FileFunction->GetBrdLayerId(),
162 gerber->m_FileFunction->GetBrdLayerSide() );
163 }
164 if( gerber->m_FileFunction->IsDrillFile() )
165 {
166 name.Printf( wxT( "%s (%s,%s,%s,%s)" ),
167 filename.GetData(),
168 gerber->m_FileFunction->GetFileType(),
170 gerber->m_FileFunction->GetLPType(),
171 gerber->m_FileFunction->GetRouteType() );
172 }
173 else
174 {
175 name.Printf( wxT( "%s (%s, %s)" ),
176 filename.GetData(),
177 gerber->m_FileFunction->GetFileType(),
178 gerber->m_FileFunction->GetBrdLayerId() );
179 }
180 }
181 else
182 {
183 name = filename;
184 }
185
186 if( aNameOnly )
187 return name;
188
189 wxString fullname;
190
191 fullname.Printf( wxT( "%d " ), aIdx + 1 );
192 fullname << name;
193 return fullname;
194 }
195 else
196 {
197 name.Printf( _( "Graphic layer %d" ), aIdx + 1 );
198 }
199
200 return name;
201}
202
203
205{
206 std::string m_FilenameMask;
208};
209
210
211// clang-format off
213{
222
224
227
235
242
249
256
264
270
277
284
291
292 // EAGLE CAD file to explicitly ignore that can match some other
293 // layers otherwise
295
296 // Inner copper layers need to come last so the wildcard
297 // number matching doesn't pick up other specific layer names.
304};
305// clang-format on
306
307
309 enum GERBER_ORDER_ENUM& order,
310 wxString& matchedExtension )
311{
312 order = GERBER_ORDER_ENUM::GERBER_LAYER_UNKNOWN;
313 matchedExtension = "";
314
315 for( struct GERBER_ORDER o : gerberFileExtensionOrder )
316 {
317 wxString ext = filename.Right( o.m_FilenameMask.length() ).Upper();
318
319 if( ext.Matches( o.m_FilenameMask ) )
320 {
321 order = o.m_Order;
322 matchedExtension = ext;
323 return;
324 }
325 }
326}
327
328
329static bool sortFileExtension( const GERBER_FILE_IMAGE* const& ref,
330 const GERBER_FILE_IMAGE* const& test )
331{
332 // Do not change order: no criteria to sort items
333 if( !ref && !test )
334 return false;
335
336 // Not used: ref ordered after
337 if( !ref || !ref->m_InUse )
338 return false;
339
340 // Not used: ref ordered before
341 if( !test || !test->m_InUse )
342 return true;
343
344 enum GERBER_ORDER_ENUM ref_layer;
345 enum GERBER_ORDER_ENUM test_layer;
346 wxString ref_extension;
347 wxString test_extension;
348
350 ref_extension );
352 test_extension );
353
354 // Inner layers have a numeric code that we can compare against
355 if( ref_layer == GERBER_ORDER_ENUM::GERBER_INNER
356 && test_layer == GERBER_ORDER_ENUM::GERBER_INNER )
357 {
358 unsigned long ref_layer_number = 0;
359 unsigned long test_layer_number = 0;
360
361 // Strip extensions down to only the numbers in it. Later conversion to int will
362 // automatically skip the spaces
363 for( wxString::iterator it = ref_extension.begin(); it != ref_extension.end(); ++it )
364 {
365 if( !isdigit( *it ) )
366 *it = ' ';
367 }
368
369 for( wxString::iterator it = test_extension.begin(); it != test_extension.end(); ++it )
370 {
371 if( !isdigit( *it ) )
372 *it = ' ';
373 }
374
375 ref_extension.ToULong( &ref_layer_number );
376 test_extension.ToULong( &test_layer_number );
377
378 return ref_layer_number < test_layer_number;
379 }
380
381 return (int) ref_layer < (int) test_layer;
382}
383
384
385// Helper function, for std::sort.
386// Sort loaded images by Z order priority, if they have the X2 FileFormat info
387// returns true if the first argument (ref) is ordered before the second (test).
388static bool sortZorder( const GERBER_FILE_IMAGE* const& ref, const GERBER_FILE_IMAGE* const& test )
389{
390 if( !ref && !test )
391 return false; // do not change order: no criteria to sort items
392
393 if( !ref || !ref->m_InUse )
394 return false; // Not used: ref ordered after
395
396 if( !test || !test->m_InUse )
397 return true; // Not used: ref ordered before
398
399 if( !ref->m_FileFunction && !test->m_FileFunction )
400 return false; // do not change order: no criteria to sort items
401
402 if( !ref->m_FileFunction )
403 return false;
404
405 if( !test->m_FileFunction )
406 return true;
407
408 if( ref->m_FileFunction->GetZOrder() != test->m_FileFunction->GetZOrder() )
409 return ref->m_FileFunction->GetZOrder() > test->m_FileFunction->GetZOrder();
410
411 return ref->m_FileFunction->GetZSubOrder() > test->m_FileFunction->GetZSubOrder();
412}
413
414
415std::unordered_map<int, int> GERBER_FILE_IMAGE_LIST::GetLayerRemap()
416{
417 // The image order has changed.
418 // Graphic layer numbering must be updated to match the widgets layer order
419
420 // Store the old/new graphic layer info:
421 std::unordered_map<int, int> tab_lyr;
422
423 for( unsigned layer = 0; layer < m_GERBER_List.size(); ++layer )
424 {
425 GERBER_FILE_IMAGE* gerber = m_GERBER_List[layer];
426
427 if( !gerber )
428 continue;
429
430 tab_lyr[gerber->m_GraphicLayer] = layer;
431 gerber->m_GraphicLayer = layer ;
432 }
433
434 return tab_lyr;
435}
436
437
438std::unordered_map<int, int>
440{
441 std::sort( m_GERBER_List.begin(), m_GERBER_List.end(), sortFunction );
442 return GetLayerRemap();
443}
444
445
447{
449}
450
451
452std::unordered_map<int, int> GERBER_FILE_IMAGE_LIST::SortImagesByZOrder()
453{
455}
456
457
458std::unordered_map<int, int> GERBER_FILE_IMAGE_LIST::SwapImages( unsigned int layer1,
459 unsigned int layer2 )
460{
461 if( ( layer1 >= m_GERBER_List.size() ) || ( layer2 >= m_GERBER_List.size() ) )
462 return std::unordered_map<int, int>();
463
464 std::swap( m_GERBER_List[layer1], m_GERBER_List[layer2] );
465 return GetLayerRemap();
466}
467
468std::unordered_map<int, int> GERBER_FILE_IMAGE_LIST::RemoveImage( unsigned int layer )
469{
470 if( layer >= m_GERBER_List.size() )
471 return std::unordered_map<int, int>();
472
473 DeleteImage( layer );
474 // Move deleted image to end of list, move all other images up
475 std::rotate( m_GERBER_List.begin() + layer, m_GERBER_List.begin() + layer + 1,
476 m_GERBER_List.end() );
477 return GetLayerRemap();
478}
const char * name
Definition: DXF_plotter.cpp:57
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:419
GERBER_ORDER_ENUM m_Order