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.

359 lines
13 KiB

  1. /** @file class_GERBER.cpp
  2. * a GERBER class handle for a given layer info about used D_CODES and how the layer is drawn
  3. */
  4. /*
  5. * This program source code file is part of KICAD, a free EDA CAD application.
  6. *
  7. * Copyright (C) 1992-2010 <Jean-Pierre Charras>
  8. * Copyright (C) 1992-2010 Kicad Developers, see change_log.txt for contributors.
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU General Public License
  12. * as published by the Free Software Foundation; either version 2
  13. * of the License, or (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, you may find one here:
  22. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  23. * or you may search the http://www.gnu.org website for the version 2 license,
  24. * or you may write to the Free Software Foundation, Inc.,
  25. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  26. */
  27. #include "fctsys.h"
  28. #include "common.h"
  29. #include "class_drawpanel.h"
  30. #include "confirm.h"
  31. #include "macros.h"
  32. #include "gerbview.h"
  33. #include "class_GERBER.h"
  34. /**
  35. * Function scale
  36. * converts a distance given in floating point to our deci-mils
  37. */
  38. extern int scale( double aCoord, bool isMetric ); // defined it rs274d.cpp
  39. /* Format Gerber: NOTES:
  40. * Tools and D_CODES
  41. * tool number (identification of shapes)
  42. * 1 to 999
  43. *
  44. * D_CODES:
  45. * D01 ... D9 = action codes:
  46. * D01 = activating light (lower pen) when di placement
  47. * D02 = light extinction (lift pen) when di placement
  48. * D03 Flash
  49. * D09 = VAPE Flash
  50. * D10 ... = Indentification Tool (Opening)
  51. *
  52. * For tools:
  53. * DCode min = D10
  54. * DCode max = 999
  55. */
  56. GERBER_LAYER::GERBER_LAYER()
  57. {
  58. ResetDefaultValues();
  59. }
  60. GERBER_LAYER::~GERBER_LAYER()
  61. {
  62. }
  63. void GERBER_LAYER::ResetDefaultValues()
  64. {
  65. m_LayerName = wxT( "no name" ); // Layer name from the LN command
  66. m_LayerNegative = false; // true = Negative Layer
  67. m_StepForRepeat.x = m_StepForRepeat.y = 0; // X and Y offsets for Step and Repeat command
  68. m_XRepeatCount = 1; // The repeat count on X axis
  69. m_YRepeatCount = 1; // The repeat count on Y axis
  70. m_StepForRepeatMetric = false; // false = Inches, true = metric
  71. }
  72. GERBER_IMAGE::GERBER_IMAGE( GERBVIEW_FRAME* aParent, int aLayer )
  73. {
  74. m_Parent = aParent;
  75. m_GraphicLayer = aLayer; // Graphic layer Number
  76. m_Selected_Tool = FIRST_DCODE;
  77. ResetDefaultValues();
  78. for( unsigned ii = 0; ii < DIM( m_Aperture_List ); ii++ )
  79. m_Aperture_List[ii] = 0;
  80. m_Pcb = aParent->GetBoard();
  81. }
  82. GERBER_IMAGE::~GERBER_IMAGE()
  83. {
  84. for( unsigned ii = 0; ii < DIM( m_Aperture_List ); ii++ )
  85. {
  86. delete m_Aperture_List[ii];
  87. // m_Aperture_List[ii] = NULL;
  88. }
  89. delete m_Pcb;
  90. }
  91. D_CODE* GERBER_IMAGE::GetDCODE( int aDCODE, bool create )
  92. {
  93. unsigned ndx = aDCODE - FIRST_DCODE;
  94. if( ndx < (unsigned) DIM( m_Aperture_List ) )
  95. {
  96. // lazily create the D_CODE if it does not exist.
  97. if( create )
  98. {
  99. if( m_Aperture_List[ndx] == NULL )
  100. m_Aperture_List[ndx] = new D_CODE( ndx + FIRST_DCODE );
  101. }
  102. return m_Aperture_List[ndx];
  103. }
  104. return NULL;
  105. }
  106. APERTURE_MACRO* GERBER_IMAGE::FindApertureMacro( const APERTURE_MACRO& aLookup )
  107. {
  108. APERTURE_MACRO_SET::iterator iter = m_aperture_macros.find( aLookup );
  109. if( iter != m_aperture_macros.end() )
  110. {
  111. APERTURE_MACRO* pam = (APERTURE_MACRO*) &(*iter);
  112. return pam;
  113. }
  114. return NULL; // not found
  115. }
  116. void GERBER_IMAGE::ResetDefaultValues()
  117. {
  118. m_InUse = false;
  119. m_GBRLayerParams.ResetDefaultValues();
  120. m_FileName.Empty();
  121. m_ImageName = wxT( "no name" ); // Image name from the IN command
  122. m_ImageNegative = false; // true = Negative image
  123. m_hasNegativeItems = -1; // set to uninitialized
  124. m_ImageJustifyOffset = wxPoint(0,0); // Image justify Offset
  125. m_ImageJustifyXCenter = false; // Image Justify Center on X axis (default = false)
  126. m_ImageJustifyYCenter = false; // Image Justify Center on Y axis (default = false)
  127. m_GerbMetric = false; // false = Inches (default), true = metric
  128. m_Relative = false; // false = absolute Coord,
  129. // true = relative Coord
  130. m_NoTrailingZeros = false; // true: trailing zeros deleted
  131. m_DecimalFormat = false; // true: use floating point notations for coordinates
  132. m_ImageOffset.x = m_ImageOffset.y = 0; // Coord Offset, from IO command
  133. m_ImageRotation = 0; // Allowed 0, 90, 180, 270 (in degree)
  134. m_LocalRotation = 0.0; // Layer totation from RO command (in 0.1 degree)
  135. m_Offset.x = 0;
  136. m_Offset.y = 0; // Coord Offset, from OF command
  137. m_Scale.x = m_Scale.y = 1.0; // scale (A and B) this layer
  138. m_MirrorA = false; // true: miror / axe A (default = X)
  139. m_MirrorB = false; // true: miror / axe B (default = Y)
  140. m_SwapAxis = false; // false if A = X, B = Y; true if A =Y, B = Y
  141. m_Has_DCode = false; // true = DCodes in file
  142. // false = no DCode->
  143. // search for separate DCode file
  144. m_FmtScale.x = m_FmtScale.y = 4; // Initialize default format to 3.4 => 4
  145. m_FmtLen.x = m_FmtLen.y = 3 + 4; // Initialize default format len = 3+4
  146. m_Iterpolation = GERB_INTERPOL_LINEAR_1X; // Linear, 90 arc, Circ.
  147. m_360Arc_enbl = false; // 360 deg circular
  148. // interpolation disable
  149. m_Current_Tool = 0; // Current Dcode selected
  150. m_CommandState = 0; // State of the current command
  151. m_CurrentPos.x = m_CurrentPos.y = 0; // current specified coord
  152. m_PreviousPos.x = m_PreviousPos.y = 0; // last specified coord
  153. m_IJPos.x = m_IJPos.y = 0; // current centre coord for
  154. // plot arcs & circles
  155. m_Current_File = NULL; // Gerger file to read
  156. m_FilesPtr = 0;
  157. m_PolygonFillMode = false;
  158. m_PolygonFillModeState = 0;
  159. m_Selected_Tool = FIRST_DCODE;
  160. }
  161. /* Function HasNegativeItems
  162. * return true if at least one item must be drawn in background color
  163. * used to optimize screen refresh
  164. */
  165. bool GERBER_IMAGE::HasNegativeItems()
  166. {
  167. if( m_hasNegativeItems < 0 ) // negative items are not yet searched: find them if any
  168. {
  169. if( m_ImageNegative ) // A negative layer is expected having always negative objects.
  170. m_hasNegativeItems = 1;
  171. else
  172. {
  173. m_hasNegativeItems = 0;
  174. for( BOARD_ITEM* item = m_Pcb->m_Drawings; item; item = item->Next() )
  175. {
  176. GERBER_DRAW_ITEM* gerb_item = (GERBER_DRAW_ITEM*) item;
  177. if( gerb_item->GetLayer() != m_GraphicLayer )
  178. continue;
  179. if( gerb_item->HasNegativeItems() )
  180. {
  181. m_hasNegativeItems = 1;
  182. break;
  183. }
  184. }
  185. // TODO search for items in list
  186. }
  187. }
  188. return m_hasNegativeItems == 1;
  189. }
  190. int GERBER_IMAGE::ReturnUsedDcodeNumber()
  191. {
  192. int count = 0;
  193. for( unsigned ii = 0; ii < DIM( m_Aperture_List ); ii++ )
  194. {
  195. if( m_Aperture_List[ii] )
  196. if( m_Aperture_List[ii]->m_InUse || m_Aperture_List[ii]->m_Defined )
  197. ++count;
  198. }
  199. return count;
  200. }
  201. void GERBER_IMAGE::InitToolTable()
  202. {
  203. for( int count = 0; count < TOOLS_MAX_COUNT; count++ )
  204. {
  205. if( m_Aperture_List[count] == NULL )
  206. continue;
  207. m_Aperture_List[count]->m_Num_Dcode = count + FIRST_DCODE;
  208. m_Aperture_List[count]->Clear_D_CODE_Data();
  209. }
  210. m_aperture_macros.clear();
  211. }
  212. /**
  213. * Function ReportMessage
  214. * Add a message (a string) in message list
  215. * for instance when reading a Gerber file
  216. * @param aMessage = the straing to add in list
  217. */
  218. void GERBER_IMAGE::ReportMessage( const wxString aMessage )
  219. {
  220. m_Parent->ReportMessage( aMessage );
  221. }
  222. /**
  223. * Function ClearMessageList
  224. * Clear the message list
  225. * Call it before reading a Gerber file
  226. */
  227. void GERBER_IMAGE::ClearMessageList()
  228. {
  229. m_Parent->ClearMessageList();
  230. }
  231. /**
  232. * Function StepAndRepeatItem
  233. * Gerber format has a command Step an Repeat
  234. * This function must be called when reading a gerber file and
  235. * after creating a new gerber item that must be repeated
  236. * (i.e when m_XRepeatCount or m_YRepeatCount are > 1)
  237. * @param aItem = the item to repeat
  238. */
  239. void GERBER_IMAGE::StepAndRepeatItem( const GERBER_DRAW_ITEM& aItem )
  240. {
  241. if( GetLayerParams().m_XRepeatCount < 2 &&
  242. GetLayerParams().m_YRepeatCount < 2 )
  243. return; // Nothing to repeat
  244. // Duplicate item:
  245. wxString msg;
  246. for( int ii = 0; ii < GetLayerParams().m_XRepeatCount; ii++ )
  247. {
  248. for( int jj = 0; jj < GetLayerParams().m_YRepeatCount; jj++ )
  249. {
  250. // the first gerber item already exists (this is the template)
  251. // create duplicate only if ii or jj > 0
  252. if( jj == 0 && ii == 0 )
  253. continue;
  254. GERBER_DRAW_ITEM* dupItem = new GERBER_DRAW_ITEM( aItem );
  255. wxPoint move_vector;
  256. move_vector.x = scale( ii * GetLayerParams().m_StepForRepeat.x,
  257. GetLayerParams().m_StepForRepeatMetric );
  258. move_vector.y = scale( jj * GetLayerParams().m_StepForRepeat.y,
  259. GetLayerParams().m_StepForRepeatMetric );
  260. dupItem->MoveXY( move_vector );
  261. m_Parent->GetBoard()->m_Drawings.Append( dupItem );
  262. }
  263. }
  264. }
  265. /**
  266. * Function DisplayImageInfo
  267. * has knowledge about the frame and how and where to put status information
  268. * about this object into the frame's message panel.
  269. * Display info about Image Parameters.
  270. * These parameters are valid for the entire file, and must set only once
  271. * (If more than once, only the last value is used)
  272. */
  273. void GERBER_IMAGE::DisplayImageInfo( void )
  274. {
  275. wxString msg;
  276. m_Parent->ClearMsgPanel();
  277. // Display Image name (Image specific)
  278. m_Parent->AppendMsgPanel( _( "Image name" ), m_ImageName, CYAN );
  279. // Display graphic layer number used to draw this Image
  280. // (not a Gerber parameter but is also image specific)
  281. msg.Printf( wxT( "%d" ), m_GraphicLayer + 1 );
  282. m_Parent->AppendMsgPanel( _( "Graphic layer" ), msg, BROWN );
  283. // Display Image rotation (Image specific)
  284. msg.Printf( wxT( "%d" ), m_ImageRotation );
  285. m_Parent->AppendMsgPanel( _( "Img Rot." ), msg, CYAN );
  286. // Display Image polarity (Image specific)
  287. msg = m_ImageNegative ? _("Negative") : _("Normal");
  288. m_Parent->AppendMsgPanel( _( "Polarity" ), msg, BROWN );
  289. // Display Image justification and offset for justification (Image specific)
  290. msg = m_ImageJustifyXCenter ? _("Center") : _("Normal");
  291. m_Parent->AppendMsgPanel( _( "X Justify" ), msg, DARKRED );
  292. msg = m_ImageJustifyYCenter ? _("Center") : _("Normal");
  293. m_Parent->AppendMsgPanel( _( "Y Justify" ), msg, DARKRED );
  294. if( g_UserUnit == INCHES )
  295. msg.Printf( wxT( "X=%f Y=%f" ), (double) m_ImageJustifyOffset.x/10000,
  296. (double) m_ImageJustifyOffset.y/10000 );
  297. else
  298. msg.Printf( wxT( "X=%f Y=%f" ), (double) m_ImageJustifyOffset.x*2.54/1000,
  299. (double) m_ImageJustifyOffset.y*2.54/1000 );
  300. m_Parent->AppendMsgPanel( _( "Image Justify Offset" ), msg, DARKRED );
  301. }