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