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.

401 lines
11 KiB

++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
  1. /**
  2. * @file export_to_pcbnew.cpp
  3. * @brief Export the layers to Pcbnew.
  4. */
  5. #include "fctsys.h"
  6. #include "common.h"
  7. #include "class_drawpanel.h"
  8. #include "confirm.h"
  9. #include "macros.h"
  10. #include "kicad_string.h"
  11. #include "gestfich.h"
  12. #include "trigo.h"
  13. #include "../pcbnew/class_track.h"
  14. #include "../pcbnew/class_drawsegment.h"
  15. #include "gerbview.h"
  16. #include "class_board_design_settings.h"
  17. #include "class_gerber_draw_item.h"
  18. #include "select_layers_to_pcb.h"
  19. #include "build_version.h" // BOARD_FILE_VERSION
  20. /* A helper class to export a Gerber set of files to Pcbnew
  21. */
  22. class GBR_TO_PCB_EXPORTER
  23. {
  24. GERBVIEW_FRAME* m_gerbview_frame; // the maint gerber frame
  25. FILE * m_file; // .brd file to write to
  26. BOARD* m_pcb; // the board to populate and export
  27. public:
  28. GBR_TO_PCB_EXPORTER(GERBVIEW_FRAME * aFrame, FILE * aFile );
  29. ~GBR_TO_PCB_EXPORTER();
  30. bool ExportPcb( int* LayerLookUpTable );
  31. BOARD* GetBoard() { return m_pcb; }
  32. private:
  33. bool WriteSetup( ); // Write the SETUP section data file
  34. bool WriteGeneralDescrPcb( );
  35. void export_non_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer );
  36. void export_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer );
  37. void export_flashed_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer );
  38. void export_segline_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer );
  39. void export_segarc_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer );
  40. void cleanBoard();
  41. };
  42. GBR_TO_PCB_EXPORTER::GBR_TO_PCB_EXPORTER( GERBVIEW_FRAME * aFrame, FILE * aFile )
  43. {
  44. m_gerbview_frame = aFrame;
  45. m_file = aFile;
  46. m_pcb = new BOARD();
  47. }
  48. GBR_TO_PCB_EXPORTER::~GBR_TO_PCB_EXPORTER()
  49. {
  50. delete m_pcb;
  51. }
  52. /* Export data in Pcbnew format
  53. * remember Pcbnew uses a Y reversed axis, so we must negate all Y coordinates
  54. */
  55. void GERBVIEW_FRAME::ExportDataInPcbnewFormat( wxCommandEvent& event )
  56. {
  57. int layercount = 0;
  58. // Count the Gerber layers which are actually currently used
  59. for( int ii = 0; ii < 32; ii++ )
  60. {
  61. if( g_GERBER_List[ii] != NULL )
  62. layercount++;
  63. }
  64. if( layercount == 0 )
  65. {
  66. DisplayInfoMessage( this,
  67. _( "None of the Gerber layers contain any data" ) );
  68. return;
  69. }
  70. wxString FullFileName, msg;
  71. wxString PcbExt( wxT( ".brd" ) );
  72. msg = wxT( "*" ) + PcbExt;
  73. FullFileName = EDA_FileSelector( _( "Board file name:" ),
  74. wxEmptyString,
  75. wxEmptyString,
  76. PcbExt,
  77. msg,
  78. this,
  79. wxFD_SAVE,
  80. FALSE
  81. );
  82. if( FullFileName == wxEmptyString )
  83. return;
  84. /* Install a dialog frame to choose the mapping
  85. * between gerber layers and Pcbnew layers
  86. */
  87. LAYERS_MAP_DIALOG* dlg = new LAYERS_MAP_DIALOG( this );
  88. int ok = dlg->ShowModal();
  89. dlg->Destroy();
  90. if( ok != wxID_OK )
  91. return;
  92. if( wxFileExists( FullFileName ) )
  93. {
  94. if( !IsOK( this, _( "Ok to change the existing file ?" ) ) )
  95. return;
  96. }
  97. FILE * file = wxFopen( FullFileName, wxT( "wt" ) );
  98. if( file == NULL )
  99. {
  100. msg = _( "Unable to create " ) + FullFileName;
  101. DisplayError( this, msg );
  102. return;
  103. }
  104. GBR_TO_PCB_EXPORTER gbr_exporter( this, file );
  105. gbr_exporter.ExportPcb( dlg->GetLayersLookUpTable() );
  106. fclose( file );
  107. }
  108. void GBR_TO_PCB_EXPORTER::cleanBoard()
  109. {
  110. // delete redundant vias
  111. for( TRACK * track = m_pcb->m_Track; track; track = track->Next() )
  112. {
  113. if( track->m_Shape != VIA_THROUGH )
  114. continue;
  115. // Search and delete others vias
  116. TRACK* next_track;
  117. TRACK* alt_track = track->Next();
  118. for( ; alt_track; alt_track = next_track )
  119. {
  120. next_track = alt_track->Next();
  121. if( alt_track->m_Shape != VIA_THROUGH )
  122. continue;
  123. if( alt_track->m_Start != track->m_Start )
  124. continue;
  125. // delete track
  126. alt_track->UnLink();
  127. delete alt_track;
  128. }
  129. }
  130. }
  131. bool GBR_TO_PCB_EXPORTER::WriteSetup( )
  132. {
  133. fprintf( m_file, "$SETUP\n" );
  134. fprintf( m_file, "InternalUnit %f INCH\n", 1.0 / PCB_INTERNAL_UNIT );
  135. fprintf( m_file, "Layers %d\n", m_pcb->GetCopperLayerCount() );
  136. fprintf( m_file, "$EndSETUP\n\n" );
  137. return true;
  138. }
  139. bool GBR_TO_PCB_EXPORTER::WriteGeneralDescrPcb( )
  140. {
  141. int nbLayers;
  142. // Print the copper layer count
  143. nbLayers = m_pcb->GetCopperLayerCount();
  144. if( nbLayers <= 1 ) // Minimal layers count in Pcbnew is 2
  145. {
  146. nbLayers = 2;
  147. m_pcb->SetCopperLayerCount(2);
  148. }
  149. fprintf( m_file, "$GENERAL\n" );
  150. fprintf( m_file, "encoding utf-8\n");
  151. fprintf( m_file, "LayerCount %d\n", nbLayers );
  152. // Compute and print the board bounding box
  153. EDA_RECT bbbox = m_pcb->ComputeBoundingBox();
  154. fprintf( m_file, "Di %d %d %d %d\n",
  155. bbbox.GetX(), bbbox.GetY(),
  156. bbbox.GetRight(),
  157. bbbox.GetBottom() );
  158. fprintf( m_file, "$EndGENERAL\n\n" );
  159. return true;
  160. }
  161. /* Routine to save the board
  162. * @param frame = pointer to the main frame
  163. * @param File = FILE * pointer to an already opened file
  164. * @param LayerLookUpTable = look up table: Pcbnew layer for each gerber layer
  165. * @return 1 if OK, 0 if fail
  166. */
  167. bool GBR_TO_PCB_EXPORTER::ExportPcb( int* LayerLookUpTable )
  168. {
  169. BOARD* gerberPcb = m_gerbview_frame->GetBoard();
  170. // create an image of gerber data
  171. BOARD_ITEM* item = gerberPcb->m_Drawings;
  172. for( ; item; item = item->Next() )
  173. {
  174. GERBER_DRAW_ITEM* gerb_item = (GERBER_DRAW_ITEM*) item;
  175. int layer = gerb_item->GetLayer();
  176. int pcb_layer_number = LayerLookUpTable[layer];
  177. if( pcb_layer_number < 0 || pcb_layer_number > LAST_NO_COPPER_LAYER )
  178. continue;
  179. if( pcb_layer_number > LAST_COPPER_LAYER )
  180. export_non_copper_item( gerb_item, pcb_layer_number );
  181. else
  182. export_copper_item( gerb_item, pcb_layer_number );
  183. }
  184. cleanBoard();
  185. m_pcb->SetCopperLayerCount( LayerLookUpTable[32] );
  186. // Switch the locale to standard C (needed to print floating point numbers)
  187. SetLocaleTo_C_standard();
  188. // write PCB header
  189. fprintf( m_file, "PCBNEW-BOARD Version %d date %s\n\n", BOARD_FILE_VERSION,
  190. TO_UTF8( DateAndTime() ) );
  191. WriteGeneralDescrPcb( );
  192. WriteSetup( );
  193. // write items on file
  194. m_pcb->Save( m_file );
  195. SetLocaleTo_Default(); // revert to the current locale
  196. return true;
  197. }
  198. void GBR_TO_PCB_EXPORTER::export_non_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer )
  199. {
  200. DRAWSEGMENT* drawitem = new DRAWSEGMENT( m_pcb, PCB_LINE_T );
  201. drawitem->SetLayer( aLayer );
  202. drawitem->m_Start = aGbrItem->m_Start;
  203. drawitem->m_End = aGbrItem->m_End;
  204. drawitem->m_Width = aGbrItem->m_Size.x;
  205. if( aGbrItem->m_Shape == GBR_ARC )
  206. {
  207. double a = atan2( (double)( aGbrItem->m_Start.y - aGbrItem->m_ArcCentre.y),
  208. (double)( aGbrItem->m_Start.x - aGbrItem->m_ArcCentre.x ) );
  209. double b = atan2( (double)( aGbrItem->m_End.y - aGbrItem->m_ArcCentre.y ),
  210. (double)( aGbrItem->m_End.x - aGbrItem->m_ArcCentre.x ) );
  211. drawitem->m_Shape = S_ARC;
  212. drawitem->m_Angle = wxRound( (a - b) / M_PI * 1800.0 );
  213. drawitem->m_Start = aGbrItem->m_ArcCentre;
  214. if( drawitem->m_Angle < 0 )
  215. {
  216. NEGATE( drawitem->m_Angle );
  217. drawitem->m_End = aGbrItem->m_Start;
  218. }
  219. }
  220. // Reverse Y axis:
  221. NEGATE( drawitem->m_Start.y );
  222. NEGATE( drawitem->m_End.y );
  223. m_pcb->Add( drawitem );
  224. }
  225. void GBR_TO_PCB_EXPORTER::export_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer )
  226. {
  227. switch( aGbrItem->m_Shape )
  228. {
  229. case GBR_SPOT_CIRCLE:
  230. case GBR_SPOT_RECT:
  231. case GBR_SPOT_OVAL:
  232. // replace spots with vias when possible
  233. export_flashed_copper_item( aGbrItem, aLayer );
  234. break;
  235. case GBR_ARC:
  236. export_segarc_copper_item( aGbrItem, aLayer );
  237. break;
  238. default:
  239. export_segline_copper_item( aGbrItem, aLayer );
  240. break;
  241. }
  242. }
  243. void GBR_TO_PCB_EXPORTER::export_segline_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer )
  244. {
  245. TRACK * newtrack = new TRACK( m_pcb );
  246. newtrack->SetLayer( aLayer );
  247. newtrack->m_Start = aGbrItem->m_Start;
  248. newtrack->m_End = aGbrItem->m_End;
  249. newtrack->m_Width = aGbrItem->m_Size.x;
  250. // Reverse Y axis:
  251. NEGATE( newtrack->m_Start.y );
  252. NEGATE( newtrack->m_End.y );
  253. m_pcb->Add( newtrack );
  254. }
  255. void GBR_TO_PCB_EXPORTER::export_segarc_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer )
  256. {
  257. #if 0 // TODO: does not work in all cases, so needs some work
  258. double a = atan2( (double)( aGbrItem->m_Start.y - aGbrItem->m_ArcCentre.y ),
  259. (double)( aGbrItem->m_Start.x - aGbrItem->m_ArcCentre.x ) );
  260. double b = atan2( (double)( aGbrItem->m_End.y - aGbrItem->m_ArcCentre.y ),
  261. (double)( aGbrItem->m_End.x - aGbrItem->m_ArcCentre.x ) );
  262. int arc_angle = wxRound( ( (a - b) / M_PI * 1800.0 ) );
  263. wxPoint start = aGbrItem->m_Start;
  264. wxPoint end = aGbrItem->m_End;
  265. /* Because Pcbnew does not know arcs in tracks,
  266. * approximate arc by segments (16 segment per 360 deg)
  267. */
  268. #define DELTA 3600/16
  269. if( arc_angle < 0 )
  270. {
  271. NEGATE( arc_angle );
  272. EXCHG( start, end );
  273. }
  274. wxPoint curr_start = start;
  275. for( int rot = DELTA; rot < (arc_angle - DELTA); rot += DELTA )
  276. {
  277. TRACK * newtrack = new TRACK( m_pcb );
  278. newtrack->SetLayer( aLayer );
  279. newtrack->m_Start = curr_start;
  280. wxPoint curr_end = start;
  281. RotatePoint( &curr_end, aGbrItem->m_ArcCentre, rot );
  282. newtrack->m_End = curr_end;
  283. newtrack->m_Width = aGbrItem->m_Size.x;
  284. // Reverse Y axis:
  285. NEGATE( newtrack->m_Start.y );
  286. NEGATE( newtrack->m_End.y );
  287. m_pcb->Add( newtrack );
  288. curr_start = curr_end;
  289. }
  290. if( end != curr_start )
  291. {
  292. TRACK * newtrack = new TRACK( m_pcb );
  293. newtrack->SetLayer( aLayer );
  294. newtrack->m_Start = curr_start;
  295. newtrack->m_End = end;
  296. newtrack->m_Width = aGbrItem->m_Size.x;
  297. // Reverse Y axis:
  298. NEGATE( newtrack->m_Start.y );
  299. NEGATE( newtrack->m_End.y );
  300. m_pcb->Add( newtrack );
  301. }
  302. #endif
  303. }
  304. /*
  305. * creates a via from a flashed gerber item.
  306. * Flashed items are usually pads or vias, so we try to export all of them
  307. * using vias
  308. */
  309. void GBR_TO_PCB_EXPORTER::export_flashed_copper_item( GERBER_DRAW_ITEM* aGbrItem, int aLayer )
  310. {
  311. SEGVIA * newtrack = new SEGVIA( m_pcb );
  312. newtrack->m_Shape = VIA_THROUGH;
  313. newtrack->SetLayer( 0x0F ); // Layers are 0 to 15 (Cu/Cmp)
  314. newtrack->SetDrillDefault();
  315. newtrack->m_Start = newtrack->m_End = aGbrItem->m_Start;
  316. newtrack->m_Width = (aGbrItem->m_Size.x + aGbrItem->m_Size.y) / 2;
  317. // Reverse Y axis:
  318. NEGATE( newtrack->m_Start.y );
  319. NEGATE( newtrack->m_End.y );
  320. m_pcb->Add( newtrack );
  321. }