You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

249 lines
7.4 KiB

  1. /**
  2. * @file gerber_file_image.cpp
  3. * a GERBER class handle for a given layer info about used D_CODES and how the layer is drawn
  4. */
  5. /*
  6. * This program source code file is part of KiCad, a free EDA CAD application.
  7. *
  8. * Copyright (C) 1992-2016 Jean-Pierre Charras jp.charras at wanadoo.fr
  9. * Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
  10. *
  11. * This program is free software; you can redistribute it and/or
  12. * modify it under the terms of the GNU General Public License
  13. * as published by the Free Software Foundation; either version 2
  14. * of the License, or (at your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program; if not, you may find one here:
  23. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  24. * or you may search the http://www.gnu.org website for the version 2 license,
  25. * or you may write to the Free Software Foundation, Inc.,
  26. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  27. */
  28. #include <fctsys.h>
  29. #include <gerbview.h>
  30. #include <gerbview_frame.h>
  31. #include <gerber_file_image.h>
  32. #include <gerber_file_image_list.h>
  33. #include <X2_gerber_attributes.h>
  34. #include <map>
  35. // The global image list:
  36. GERBER_FILE_IMAGE_LIST s_GERBER_List;
  37. // GERBER_FILE_IMAGE_LIST is a helper class to handle a list of GERBER_FILE_IMAGE files
  38. GERBER_FILE_IMAGE_LIST::GERBER_FILE_IMAGE_LIST()
  39. {
  40. m_GERBER_List.reserve( GERBER_DRAWLAYERS_COUNT );
  41. for( unsigned layer = 0; layer < GERBER_DRAWLAYERS_COUNT; ++layer )
  42. m_GERBER_List.push_back( nullptr );
  43. }
  44. GERBER_FILE_IMAGE_LIST::~GERBER_FILE_IMAGE_LIST()
  45. {
  46. DeleteAllImages();
  47. }
  48. GERBER_FILE_IMAGE_LIST& GERBER_FILE_IMAGE_LIST::GetImagesList()
  49. {
  50. return s_GERBER_List;
  51. }
  52. GERBER_FILE_IMAGE* GERBER_FILE_IMAGE_LIST::GetGbrImage( int aIdx )
  53. {
  54. if( (unsigned)aIdx < m_GERBER_List.size() )
  55. return m_GERBER_List[aIdx];
  56. return NULL;
  57. }
  58. /* creates a new, empty GERBER_FILE_IMAGE* at index aIdx
  59. * or at the first free location if aIdx < 0
  60. * aIdx = the index of graphic layer to use, or -1 to uses the first free graphic layer
  61. * return the index actually used, or -1 if no room to add image
  62. */
  63. int GERBER_FILE_IMAGE_LIST::AddGbrImage( GERBER_FILE_IMAGE* aGbrImage, int aIdx )
  64. {
  65. int idx = aIdx;
  66. if( idx < 0 )
  67. {
  68. for( idx = 0; idx < (int)m_GERBER_List.size(); idx++ )
  69. {
  70. if( m_GERBER_List[idx] == NULL )
  71. break;
  72. }
  73. }
  74. if( idx >= (int)m_GERBER_List.size() )
  75. return -1; // No room
  76. m_GERBER_List[idx] = aGbrImage;
  77. return idx;
  78. }
  79. void GERBER_FILE_IMAGE_LIST::DeleteAllImages()
  80. {
  81. for( unsigned idx = 0; idx < m_GERBER_List.size(); ++idx )
  82. DeleteImage( idx );
  83. }
  84. void GERBER_FILE_IMAGE_LIST::DeleteImage( int aIdx )
  85. {
  86. // Ensure the index is valid:
  87. if( aIdx < 0 || aIdx >= int( m_GERBER_List.size() ) )
  88. return;
  89. // delete image aIdx
  90. GERBER_FILE_IMAGE* gbr_image = GetGbrImage( aIdx );
  91. delete gbr_image;
  92. m_GERBER_List[ aIdx ] = nullptr;
  93. }
  94. // Build a name for image aIdx which can be used in layers manager
  95. const wxString GERBER_FILE_IMAGE_LIST::GetDisplayName( int aIdx, bool aNameOnly )
  96. {
  97. wxString name;
  98. GERBER_FILE_IMAGE* gerber = NULL;
  99. if( aIdx >= 0 && aIdx < (int)m_GERBER_List.size() )
  100. gerber = m_GERBER_List[aIdx];
  101. // if a file is loaded, build the name:
  102. // <id> <short filename> <X2 FileFunction info> if a X2 FileFunction info is found
  103. // or (if no FileFunction info)
  104. // <id> <short filename> *
  105. if( gerber )
  106. {
  107. wxFileName fn( gerber->m_FileName );
  108. wxString filename = fn.GetFullName();
  109. // if the filename is too long, display a shortened name:
  110. const int maxlen = 30;
  111. if( filename.Length() > maxlen )
  112. {
  113. wxString shortenedfn = filename.Left(2) + "..." + filename.Right(maxlen-5);
  114. filename = shortenedfn;
  115. }
  116. if( gerber->m_FileFunction )
  117. {
  118. if( gerber->m_FileFunction->IsCopper() )
  119. {
  120. name.Printf( "%s (%s, %s, %s)",
  121. filename.GetData(),
  122. GetChars( gerber->m_FileFunction->GetFileType() ),
  123. GetChars( gerber->m_FileFunction->GetBrdLayerId() ),
  124. GetChars( gerber->m_FileFunction->GetBrdLayerSide() ) );
  125. }
  126. if( gerber->m_FileFunction->IsDrillFile() )
  127. {
  128. name.Printf( "%s (%s,%s,%s,%s)",
  129. filename.GetData(),
  130. GetChars( gerber->m_FileFunction->GetFileType() ),
  131. GetChars( gerber->m_FileFunction->GetDrillLayerPair() ),
  132. GetChars( gerber->m_FileFunction->GetLPType() ),
  133. GetChars( gerber->m_FileFunction->GetRouteType() ) );
  134. }
  135. else
  136. {
  137. name.Printf( "%s (%s, %s)",
  138. filename.GetData(),
  139. GetChars( gerber->m_FileFunction->GetFileType() ),
  140. GetChars( gerber->m_FileFunction->GetBrdLayerId() ) );
  141. }
  142. }
  143. else
  144. name = filename;
  145. if( aNameOnly )
  146. return name;
  147. wxString fullname;
  148. fullname.Printf( "%d ", aIdx + 1 );
  149. fullname << name;
  150. return fullname;
  151. }
  152. else
  153. name.Printf( _( "Graphic layer %d" ), aIdx + 1 );
  154. return name;
  155. }
  156. // Helper function, for std::sort.
  157. // Sort loaded images by Z order priority, if they have the X2 FileFormat info
  158. // returns true if the first argument (ref) is ordered before the second (test).
  159. static bool sortZorder( const GERBER_FILE_IMAGE* const& ref, const GERBER_FILE_IMAGE* const& test )
  160. {
  161. if( !ref && !test )
  162. return false; // do not change order: no criteria to sort items
  163. if( !ref || !ref->m_InUse )
  164. return false; // Not used: ref ordered after
  165. if( !test || !test->m_InUse )
  166. return true; // Not used: ref ordered before
  167. if( !ref->m_FileFunction && !test->m_FileFunction )
  168. return false; // do not change order: no criteria to sort items
  169. if( !ref->m_FileFunction )
  170. return false;
  171. if( !test->m_FileFunction )
  172. return true;
  173. if( ref->m_FileFunction->GetZOrder() != test->m_FileFunction->GetZOrder() )
  174. return ref->m_FileFunction->GetZOrder() > test->m_FileFunction->GetZOrder();
  175. return ref->m_FileFunction->GetZSubOrder() > test->m_FileFunction->GetZSubOrder();
  176. }
  177. std::unordered_map<int, int> GERBER_FILE_IMAGE_LIST::SortImagesByZOrder()
  178. {
  179. std::sort( m_GERBER_List.begin(), m_GERBER_List.end(), sortZorder );
  180. // The image order has changed.
  181. // Graphic layer numbering must be updated to match the widgets layer order
  182. // Store the old/new graphic layer info:
  183. std::unordered_map<int, int> tab_lyr;
  184. for( unsigned layer = 0; layer < m_GERBER_List.size(); ++layer )
  185. {
  186. GERBER_FILE_IMAGE* gerber = m_GERBER_List[layer];
  187. if( !gerber )
  188. continue;
  189. tab_lyr[gerber->m_GraphicLayer] = layer;
  190. gerber->m_GraphicLayer = layer ;
  191. }
  192. return tab_lyr;
  193. }