diff --git a/gerbview/CMakeLists.txt b/gerbview/CMakeLists.txt index 4ffae72958..a4c5c28ae5 100644 --- a/gerbview/CMakeLists.txt +++ b/gerbview/CMakeLists.txt @@ -50,12 +50,13 @@ set( GERBVIEW_SRCS gerbview_config.cpp gerbview_frame.cpp hotkeys.cpp - initpcb.cpp + init_gbr_drawlayers.cpp locate.cpp menubar.cpp onleftclick.cpp onrightclick.cpp pcbplot.cpp + printout_control.cpp readgerb.cpp rs274_read_XY_and_IJ_coordinates.cpp rs274d.cpp @@ -71,7 +72,6 @@ set( GERBVIEW_EXTRA_SRCS ../common/class_layer_box_selector.cpp ../common/class_page_info.cpp ../pcbnew/layer_widget.cpp - ../pcbnew/printout_controler.cpp ) if( MINGW ) diff --git a/gerbview/dialogs/dialog_select_one_pcb_layer.cpp b/gerbview/dialogs/dialog_select_one_pcb_layer.cpp index 00dcc9b657..7c3fd4b345 100644 --- a/gerbview/dialogs/dialog_select_one_pcb_layer.cpp +++ b/gerbview/dialogs/dialog_select_one_pcb_layer.cpp @@ -7,8 +7,12 @@ #include #include +#define NB_PCB_LAYERS LAYER_ID_COUNT +#define FIRST_COPPER_LAYER 0 +#define LAST_COPPER_LAYER 31 + // Exported function -const wxString GetPCBDefaultLayerName( int aLayerNumber ); +const wxString GetPCBDefaultLayerName( int aLayerId ); enum layer_sel_id { @@ -21,9 +25,8 @@ enum layer_sel_id { class SELECT_LAYER_DIALOG : public wxDialog { private: - GERBVIEW_FRAME* m_Parent; - wxRadioBox* m_LayerList; - int m_LayerId[int(GERBER_DRAWLAYERS_COUNT) + 1]; // One extra element for "(Deselect)" radiobutton + wxRadioBox* m_layerList; + std::vector m_layerId; public: // Constructor and destructor @@ -64,12 +67,11 @@ END_EVENT_TABLE() int GERBVIEW_FRAME::SelectPCBLayer( int aDefaultLayer, int aCopperLayerCount, bool aShowDeselectOption ) { - int layer; SELECT_LAYER_DIALOG* frame = new SELECT_LAYER_DIALOG( this, aDefaultLayer, aCopperLayerCount, aShowDeselectOption ); - layer = frame->ShowModal(); + int layer = frame->ShowModal(); frame->Destroy(); return layer; } @@ -88,85 +90,73 @@ SELECT_LAYER_DIALOG::SELECT_LAYER_DIALOG( GERBVIEW_FRAME* parent, wxSize( 470, 250 ), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ) { - #define NB_PCB_LAYERS 64 - #define FIRST_COPPER_LAYER 0 - #define LAST_COPPER_LAYER 31 - wxButton* Button; + wxButton* button; int ii; - wxString LayerList[NB_PCB_LAYERS + 1]; // One extra element for "(Deselect)" - // radiobutton - int LayerCount, LayerSelect = -1; - - m_Parent = parent; + wxArrayString layerList; + int layerSelect = -1; // Build the layer list; first build copper layers list - LayerCount = 0; + int layerCount = 0; for( ii = FIRST_COPPER_LAYER; ii <= LAST_COPPER_LAYER; ++ii ) { - m_LayerId[ii] = 0; - if( ii == FIRST_COPPER_LAYER || ii == LAST_COPPER_LAYER || ii < aCopperLayerCount-1 ) { - LayerList[LayerCount] = GetPCBDefaultLayerName( ii ); + layerList.Add( GetPCBDefaultLayerName( ii ) ); if( ii == aDefaultLayer ) - LayerSelect = LayerCount; + layerSelect = layerCount; - m_LayerId[LayerCount] = ii; - LayerCount++; + m_layerId.push_back( ii ); + layerCount++; } } // Build the layer list; build non copper layers list for( ; ii < NB_PCB_LAYERS; ++ii ) { - m_LayerId[ii] = 0; - - LayerList[LayerCount] = GetPCBDefaultLayerName( ii ); + layerList.Add( GetPCBDefaultLayerName( ii ) ); if( ii == aDefaultLayer ) - LayerSelect = LayerCount; + layerSelect = layerCount; - m_LayerId[LayerCount] = ii; - LayerCount++; + m_layerId.push_back( ii ); + layerCount++; } // When appropriate, also provide a "(Deselect)" radiobutton if( aShowDeselectOption ) { - LayerList[LayerCount] = _( "(Deselect)" ); + layerList.Add( _( "Do not export" ) ); - if( NB_PCB_LAYERS == aDefaultLayer ) - LayerSelect = LayerCount; + if( UNSELECTED_LAYER == aDefaultLayer ) + layerSelect = layerCount; - m_LayerId[LayerCount] = NB_PCB_LAYERS; - LayerCount++; + m_layerId.push_back( UNSELECTED_LAYER ); + layerCount++; } - m_LayerList = new wxRadioBox( this, ID_LAYER_SELECT, _( "Layer" ), + m_layerList = new wxRadioBox( this, ID_LAYER_SELECT, _( "Layer" ), wxPoint( -1, -1 ), wxSize( -1, -1 ), - LayerCount, LayerList, - (LayerCount < 8) ? LayerCount : 8, + layerList, + (layerCount < 8) ? layerCount : 8, wxRA_SPECIFY_ROWS ); - if( LayerSelect >= 0 ) - m_LayerList->SetSelection( LayerSelect ); + if( layerSelect >= 0 ) + m_layerList->SetSelection( layerSelect ); wxBoxSizer* FrameBoxSizer = new wxBoxSizer( wxHORIZONTAL ); SetSizer( FrameBoxSizer ); - FrameBoxSizer->Add( m_LayerList, 0, wxALIGN_TOP | wxALL, 5 ); + FrameBoxSizer->Add( m_layerList, 0, wxALIGN_TOP | wxALL, 5 ); wxBoxSizer* ButtonBoxSizer = new wxBoxSizer( wxVERTICAL ); FrameBoxSizer->Add( ButtonBoxSizer, 0, wxALIGN_BOTTOM | wxALL, 0 ); - Button = new wxButton( this, wxID_OK, _( "OK" ) ); - Button->SetDefault(); - ButtonBoxSizer->Add( Button, 0, wxGROW | wxALL, 5 ); + button = new wxButton( this, wxID_OK, _( "OK" ) ); + button->SetDefault(); + ButtonBoxSizer->Add( button, 0, wxGROW | wxALL, 5 ); - Button = new wxButton( this, wxID_CANCEL, _( "Cancel" ) ); - ButtonBoxSizer->Add( Button, 0, wxGROW | wxALL, 5 ); - - SetFocus(); + button = new wxButton( this, wxID_CANCEL, _( "Cancel" ) ); + ButtonBoxSizer->Add( button, 0, wxGROW | wxALL, 5 ); GetSizer()->SetSizeHints( this ); @@ -176,7 +166,7 @@ SELECT_LAYER_DIALOG::SELECT_LAYER_DIALOG( GERBVIEW_FRAME* parent, void SELECT_LAYER_DIALOG::OnLayerSelected( wxCommandEvent& event ) { - int ii = m_LayerId[m_LayerList->GetSelection()]; + int ii = m_layerId[m_layerList->GetSelection()]; EndModal( ii ); } @@ -187,43 +177,76 @@ void SELECT_LAYER_DIALOG::OnCancelClick( wxCommandEvent& event ) EndModal( -1 ); } -const wxString GetPCBDefaultLayerName( int aLayerNumber ) +// This function is a duplicate of +// const wxChar* LSET::Name( LAYER_ID aLayerId ) +// However it avoids a dependency to Pcbnew code. +const wxString GetPCBDefaultLayerName( int aLayerId ) { const wxChar* txt; - // Use a switch to explicitly show the mapping more clearly - switch( aLayerNumber ) + // using a switch to explicitly show the mapping more clearly + switch( aLayerId ) { - case F_Cu: txt = wxT( "F.Cu" ); break; - case In1_Cu: txt = wxT( "In1.Cu" ); break; - case In2_Cu: txt = wxT( "In2.Cu" ); break; - case In3_Cu: txt = wxT( "In3.Cu" ); break; - case In4_Cu: txt = wxT( "In4.Cu" ); break; - case In5_Cu: txt = wxT( "In5.Cu" ); break; - case In6_Cu: txt = wxT( "In6.Cu" ); break; - case In7_Cu: txt = wxT( "In7.Cu" ); break; - case In8_Cu: txt = wxT( "In8.Cu" ); break; - case In9_Cu: txt = wxT( "In9.Cu" ); break; - case In10_Cu: txt = wxT( "In10.Cu" ); break; - case In11_Cu: txt = wxT( "In11.Cu" ); break; - case In12_Cu: txt = wxT( "In12.Cu" ); break; - case In13_Cu: txt = wxT( "In13.Cu" ); break; - case In14_Cu: txt = wxT( "In14.Cu" ); break; - case B_Cu: txt = wxT( "B.Cu" ); break; - case B_Adhes: txt = wxT( "B.Adhes" ); break; - case F_Adhes: txt = wxT( "F.Adhes" ); break; - case B_Paste: txt = wxT( "B.Paste" ); break; - case F_Paste: txt = wxT( "F.Paste" ); break; - case B_SilkS: txt = wxT( "B.SilkS" ); break; - case F_SilkS: txt = wxT( "F.SilkS" ); break; - case B_Mask: txt = wxT( "B.Mask" ); break; - case F_Mask: txt = wxT( "F.Mask" ); break; - case Dwgs_User: txt = wxT( "Dwgs.User" ); break; - case Cmts_User: txt = wxT( "Cmts.User" ); break; - case Eco1_User: txt = wxT( "Eco1.User" ); break; - case Eco2_User: txt = wxT( "Eco2.User" ); break; - case Edge_Cuts: txt = wxT( "Edge.Cuts" ); break; - default: txt = wxT( "BAD_INDEX" ); break; + case F_Cu: txt = wxT( "F.Cu" ); break; + case In1_Cu: txt = wxT( "In1.Cu" ); break; + case In2_Cu: txt = wxT( "In2.Cu" ); break; + case In3_Cu: txt = wxT( "In3.Cu" ); break; + case In4_Cu: txt = wxT( "In4.Cu" ); break; + case In5_Cu: txt = wxT( "In5.Cu" ); break; + case In6_Cu: txt = wxT( "In6.Cu" ); break; + case In7_Cu: txt = wxT( "In7.Cu" ); break; + case In8_Cu: txt = wxT( "In8.Cu" ); break; + case In9_Cu: txt = wxT( "In9.Cu" ); break; + case In10_Cu: txt = wxT( "In10.Cu" ); break; + case In11_Cu: txt = wxT( "In11.Cu" ); break; + case In12_Cu: txt = wxT( "In12.Cu" ); break; + case In13_Cu: txt = wxT( "In13.Cu" ); break; + case In14_Cu: txt = wxT( "In14.Cu" ); break; + case In15_Cu: txt = wxT( "In15.Cu" ); break; + case In16_Cu: txt = wxT( "In16.Cu" ); break; + case In17_Cu: txt = wxT( "In17.Cu" ); break; + case In18_Cu: txt = wxT( "In18.Cu" ); break; + case In19_Cu: txt = wxT( "In19.Cu" ); break; + case In20_Cu: txt = wxT( "In20.Cu" ); break; + case In21_Cu: txt = wxT( "In21.Cu" ); break; + case In22_Cu: txt = wxT( "In22.Cu" ); break; + case In23_Cu: txt = wxT( "In23.Cu" ); break; + case In24_Cu: txt = wxT( "In24.Cu" ); break; + case In25_Cu: txt = wxT( "In25.Cu" ); break; + case In26_Cu: txt = wxT( "In26.Cu" ); break; + case In27_Cu: txt = wxT( "In27.Cu" ); break; + case In28_Cu: txt = wxT( "In28.Cu" ); break; + case In29_Cu: txt = wxT( "In29.Cu" ); break; + case In30_Cu: txt = wxT( "In30.Cu" ); break; + case B_Cu: txt = wxT( "B.Cu" ); break; + + // Technicals + case B_Adhes: txt = wxT( "B.Adhes" ); break; + case F_Adhes: txt = wxT( "F.Adhes" ); break; + case B_Paste: txt = wxT( "B.Paste" ); break; + case F_Paste: txt = wxT( "F.Paste" ); break; + case B_SilkS: txt = wxT( "B.SilkS" ); break; + case F_SilkS: txt = wxT( "F.SilkS" ); break; + case B_Mask: txt = wxT( "B.Mask" ); break; + case F_Mask: txt = wxT( "F.Mask" ); break; + + // Users + case Dwgs_User: txt = wxT( "Dwgs.User" ); break; + case Cmts_User: txt = wxT( "Cmts.User" ); break; + case Eco1_User: txt = wxT( "Eco1.User" ); break; + case Eco2_User: txt = wxT( "Eco2.User" ); break; + case Edge_Cuts: txt = wxT( "Edge.Cuts" ); break; + case Margin: txt = wxT( "Margin" ); break; + + // Footprint + case F_CrtYd: txt = wxT( "F.CrtYd" ); break; + case B_CrtYd: txt = wxT( "B.CrtYd" ); break; + case F_Fab: txt = wxT( "F.Fab" ); break; + case B_Fab: txt = wxT( "B.Fab" ); break; + + default: + wxASSERT_MSG( 0, wxT( "aLayerId out of range" ) ); + txt = wxT( "BAD INDEX!" ); break; } return wxString( txt ); diff --git a/gerbview/events_called_functions.cpp b/gerbview/events_called_functions.cpp index bfbff86459..c735424a4c 100644 --- a/gerbview/events_called_functions.cpp +++ b/gerbview/events_called_functions.cpp @@ -164,7 +164,7 @@ void GERBVIEW_FRAME::Process_Special_Functions( wxCommandEvent& event ) break; case ID_GERBVIEW_GLOBAL_DELETE: - Erase_Current_Layer( true ); + Erase_Current_DrawLayer( true ); ClearMsgPanel(); break; diff --git a/gerbview/export_to_pcbnew.cpp b/gerbview/export_to_pcbnew.cpp index f770256667..86347eb349 100644 --- a/gerbview/export_to_pcbnew.cpp +++ b/gerbview/export_to_pcbnew.cpp @@ -19,10 +19,12 @@ #include #include -#define TO_PCB_UNIT( x ) KiROUND( x / IU_PER_DECIMILS ) +// Imported function +extern const wxString GetPCBDefaultLayerName( LAYER_NUM aLayerNumber ); + +#define TO_PCB_UNIT( x ) ( x / IU_PER_MM) #define TRACK_TYPE 0 -#define VIA_TYPE 1 /* A helper class to export a Gerber set of files to Pcbnew */ @@ -44,7 +46,7 @@ public: * Function ExportPcb * saves a board from a set of Gerber images. */ - bool ExportPcb( LAYER_NUM* LayerLookUpTable, int aCopperLayers ); + bool ExportPcb( LAYER_NUM* aLayerLookUpTable, int aCopperLayers ); private: /** @@ -89,17 +91,25 @@ private: /** * function writePcbLineItem - * basic write function to write a DRAWSEGMENT item or a TRACK/VIA item - * to the board file + * basic write function to write a DRAWSEGMENT item or a TRACK item + * to the board file, from a non flashed item */ - void writePcbLineItem( int aShape, int aType, wxPoint& aStart, wxPoint& aEnd, - int aWidth, LAYER_NUM aLayer, int aDrill, int aAngle = 0 ); + void writePcbLineItem( bool aIsArc, wxPoint& aStart, wxPoint& aEnd, + int aWidth, LAYER_NUM aLayer, double aAngle = 0 ); + + /** + * function writeCopperLineItem + * basic write function to write a a TRACK item + * to the board file, from a non flashed item + */ + void writeCopperLineItem( wxPoint& aStart, wxPoint& aEnd, + int aWidth, LAYER_NUM aLayer ); /** * function writePcbHeader * Write a very basic header to the board file */ - void writePcbHeader(); + void writePcbHeader( LAYER_NUM* aLayerLookUpTable ); }; @@ -140,7 +150,7 @@ void GERBVIEW_FRAME::ExportDataInPcbnewFormat( wxCommandEvent& event ) wxString path = wxGetCwd();; wxFileDialog filedlg( this, _( "Board file name:" ), - path, fileName, LegacyPcbFileWildcard, + path, fileName, PcbFileWildcard, wxFD_SAVE ); if( filedlg.ShowModal() == wxID_CANCEL ) @@ -171,21 +181,23 @@ void GERBVIEW_FRAME::ExportDataInPcbnewFormat( wxCommandEvent& event ) } -bool GBR_TO_PCB_EXPORTER::ExportPcb( LAYER_NUM* LayerLookUpTable, int aCopperLayers ) +bool GBR_TO_PCB_EXPORTER::ExportPcb( LAYER_NUM* aLayerLookUpTable, int aCopperLayers ) { + LOCALE_IO toggle; // toggles on, then off, the C locale. + m_fp = wxFopen( m_pcb_file_name, wxT( "wt" ) ); if( m_fp == NULL ) { wxString msg; - msg.Printf( _( "Cannot create file <%s>" ), GetChars( m_pcb_file_name ) ); + msg.Printf( _( "Cannot create file '%s'" ), GetChars( m_pcb_file_name ) ); DisplayError( m_gerbview_frame, msg ); return false; } m_pcbCopperLayersCount = aCopperLayers; - writePcbHeader(); + writePcbHeader( aLayerLookUpTable ); // create an image of gerber data // First: non copper layers: @@ -195,7 +207,7 @@ bool GBR_TO_PCB_EXPORTER::ExportPcb( LAYER_NUM* LayerLookUpTable, int aCopperLay for( ; gerb_item; gerb_item = gerb_item->Next() ) { int layer = gerb_item->GetLayer(); - LAYER_NUM pcb_layer_number = LayerLookUpTable[layer]; + LAYER_NUM pcb_layer_number = aLayerLookUpTable[layer]; if( !IsPcbLayer( pcb_layer_number ) ) continue; @@ -205,13 +217,12 @@ bool GBR_TO_PCB_EXPORTER::ExportPcb( LAYER_NUM* LayerLookUpTable, int aCopperLay } // Copper layers - fprintf( m_fp, "$TRACK\n" ); gerb_item = m_gerbview_frame->GetItemsList(); for( ; gerb_item; gerb_item = gerb_item->Next() ) { int layer = gerb_item->GetLayer(); - LAYER_NUM pcb_layer_number = LayerLookUpTable[layer]; + LAYER_NUM pcb_layer_number = aLayerLookUpTable[layer]; if( pcb_layer_number < 0 || pcb_layer_number > pcbCopperLayerMax ) continue; @@ -220,8 +231,7 @@ bool GBR_TO_PCB_EXPORTER::ExportPcb( LAYER_NUM* LayerLookUpTable, int aCopperLay export_copper_item( gerb_item, pcb_layer_number ); } - fprintf( m_fp, "$EndTRACK\n" ); - fprintf( m_fp, "$EndBOARD\n" ); + fprintf( m_fp, ")\n" ); fclose( m_fp ); m_fp = NULL; @@ -231,16 +241,11 @@ bool GBR_TO_PCB_EXPORTER::ExportPcb( LAYER_NUM* LayerLookUpTable, int aCopperLay void GBR_TO_PCB_EXPORTER::export_non_copper_item( GERBER_DRAW_ITEM* aGbrItem, LAYER_NUM aLayer ) { - #define SEG_SHAPE 0 - #define ARC_SHAPE 2 - int shape = SEG_SHAPE; + bool isArc = false; - // please note: the old PCB format only has integer support for angles - int angle = 0; - wxPoint seg_start, seg_end; - - seg_start = aGbrItem->m_Start; - seg_end = aGbrItem->m_End; + double angle = 0; + wxPoint seg_start = aGbrItem->m_Start; + wxPoint seg_end = aGbrItem->m_End; if( aGbrItem->m_Shape == GBR_ARC ) { @@ -249,21 +254,19 @@ void GBR_TO_PCB_EXPORTER::export_non_copper_item( GERBER_DRAW_ITEM* aGbrItem, LA double b = atan2( (double) ( aGbrItem->m_End.y - aGbrItem->m_ArcCentre.y ), (double) ( aGbrItem->m_End.x - aGbrItem->m_ArcCentre.x ) ); - shape = ARC_SHAPE; - angle = KiROUND( RAD2DECIDEG(a - b) ); + isArc = true; + angle = RAD2DEG(b - a); seg_start = aGbrItem->m_ArcCentre; + // Ensure arc orientation is CCW if( angle < 0 ) - { - NEGATE( angle ); - seg_end = aGbrItem->m_Start; - } + angle += 360.0; } // Reverse Y axis: NEGATE( seg_start.y ); NEGATE( seg_end.y ); - writePcbLineItem( shape, 0, seg_start, seg_end, aGbrItem->m_Size.x, aLayer, -2, angle ); + writePcbLineItem( isArc, seg_start, seg_end, aGbrItem->m_Size.x, aLayer, angle ); } @@ -300,7 +303,20 @@ void GBR_TO_PCB_EXPORTER::export_segline_copper_item( GERBER_DRAW_ITEM* aGbrItem NEGATE( seg_start.y ); NEGATE( seg_end.y ); - writePcbLineItem( 0, TRACK_TYPE, seg_start, seg_end, aGbrItem->m_Size.x, aLayer, -1 ); + writeCopperLineItem( seg_start, seg_end, aGbrItem->m_Size.x, aLayer ); +} + + +void GBR_TO_PCB_EXPORTER::writeCopperLineItem( wxPoint& aStart, wxPoint& aEnd, + int aWidth, LAYER_NUM aLayer ) +{ + fprintf( m_fp, "(segment (start %s %s) (end %s %s) (width %s) (layer %s) (net 0))\n", + Double2Str( TO_PCB_UNIT(aStart.x) ).c_str(), + Double2Str( TO_PCB_UNIT(aStart.y) ).c_str(), + Double2Str( TO_PCB_UNIT(aEnd.x) ).c_str(), + Double2Str( TO_PCB_UNIT(aEnd.y) ).c_str(), + Double2Str( TO_PCB_UNIT( aWidth ) ).c_str(), + TO_UTF8( GetPCBDefaultLayerName( aLayer ) ) ); } @@ -316,7 +332,7 @@ void GBR_TO_PCB_EXPORTER::export_segarc_copper_item( GERBER_DRAW_ITEM* aGbrItem, /* Because Pcbnew does not know arcs in tracks, * approximate arc by segments (SEG_COUNT__CIRCLE segment per 360 deg) - * The arc is drawn in an anticlockwise direction from the start point to the end point. + * The arc is drawn anticlockwise from the start point to the end point. */ #define SEG_COUNT_CIRCLE 16 #define DELTA_ANGLE 2 * M_PI / SEG_COUNT_CIRCLE @@ -341,7 +357,7 @@ void GBR_TO_PCB_EXPORTER::export_segarc_copper_item( GERBER_DRAW_ITEM* aGbrItem, // Reverse Y axis: NEGATE( seg_start.y ); NEGATE( seg_end.y ); - writePcbLineItem( 0, TRACK_TYPE, seg_start, seg_end, aGbrItem->m_Size.x, aLayer, -1 ); + writeCopperLineItem( seg_start, seg_end, aGbrItem->m_Size.x, aLayer ); curr_start = curr_end; } @@ -352,7 +368,7 @@ void GBR_TO_PCB_EXPORTER::export_segarc_copper_item( GERBER_DRAW_ITEM* aGbrItem, // Reverse Y axis: NEGATE( seg_start.y ); NEGATE( seg_end.y ); - writePcbLineItem( 0, TRACK_TYPE, seg_start, seg_end, aGbrItem->m_Size.x, aLayer, -1 ); + writeCopperLineItem( seg_start, seg_end, aGbrItem->m_Size.x, aLayer ); } } @@ -373,59 +389,84 @@ void GBR_TO_PCB_EXPORTER::export_flashed_copper_item( GERBER_DRAW_ITEM* aGbrItem m_vias_coordinates.push_back( aGbrItem->m_Start ); - wxPoint via_pos; - int width; - - via_pos = aGbrItem->m_Start; - width = (aGbrItem->m_Size.x + aGbrItem->m_Size.y) / 2; + wxPoint via_pos = aGbrItem->m_Start; + int width = (aGbrItem->m_Size.x + aGbrItem->m_Size.y) / 2; // Reverse Y axis: NEGATE( via_pos.y ); - // Layers are 0 to 15 (Cu/Cmp) = 0x0F - #define IS_VIA 1 - #define SHAPE_VIA_THROUGH 3 - // XXX EVIL usage of LAYER - writePcbLineItem( SHAPE_VIA_THROUGH, IS_VIA, via_pos, via_pos, width, - 0x0F, -1 ); + + // Layers are Front to Back + fprintf( m_fp, " (via (at %s %s) (size %s)", + Double2Str( TO_PCB_UNIT(via_pos.x) ).c_str(), + Double2Str( TO_PCB_UNIT(via_pos.y) ).c_str(), + Double2Str( TO_PCB_UNIT( width ) ).c_str() ); + + fprintf( m_fp, " (layers %s %s))\n", + TO_UTF8( GetPCBDefaultLayerName( F_Cu ) ), + TO_UTF8( GetPCBDefaultLayerName( B_Cu ) ) ); } - -void GBR_TO_PCB_EXPORTER::writePcbHeader() +void GBR_TO_PCB_EXPORTER::writePcbHeader( LAYER_NUM* aLayerLookUpTable ) { - fprintf( m_fp, "PCBNEW-BOARD Version 1 date %s\n\n# Created by GerbView %s\n\n", - TO_UTF8( DateAndTime() ), TO_UTF8( GetBuildVersion() ) ); - fprintf( m_fp, "$GENERAL\n" ); - fprintf( m_fp, "encoding utf-8\n" ); - fprintf( m_fp, "Units deci-mils\n" ); + fprintf( m_fp, "(kicad_pcb (version 4) (host Gerbview \"%s\")\n\n", + TO_UTF8( GetBuildVersion() ) ); - // Write copper layer count - fprintf( m_fp, "LayerCount %d\n", m_pcbCopperLayersCount ); + // Write layers section + fprintf( m_fp, " (layers \n" ); - fprintf( m_fp, "$EndGENERAL\n\n" ); + for( int ii = 0; ii < m_pcbCopperLayersCount; ii++ ) + { + int id = ii; - // Creates void setup - fprintf( m_fp, "$SETUP\n" ); - fprintf( m_fp, "$EndSETUP\n\n" ); + if( ii == m_pcbCopperLayersCount-1) + id = B_Cu; + + fprintf( m_fp, " (%d %s signal)\n", id, TO_UTF8( GetPCBDefaultLayerName( id ) ) ); + } + + for( int ii = B_Adhes; ii < LAYER_ID_COUNT; ii++ ) + { + fprintf( m_fp, " (%d %s user)\n", ii, TO_UTF8( GetPCBDefaultLayerName( ii ) ) ); + } + + fprintf( m_fp, " )\n\n" ); } -void GBR_TO_PCB_EXPORTER::writePcbLineItem( int aShape, int aType, wxPoint& aStart, wxPoint& aEnd, - int aWidth, LAYER_NUM aLayer, int aDrill, int aAngle ) +void GBR_TO_PCB_EXPORTER::writePcbLineItem( bool aIsArc, wxPoint& aStart, wxPoint& aEnd, + int aWidth, LAYER_NUM aLayer, double aAngle ) { - if( aDrill <= -2 ) - fprintf( m_fp, "$DRAWSEGMENT\n" ); - - fprintf( m_fp, "Po %d %d %d %d %d %d\n", aShape, - TO_PCB_UNIT( aStart.x ), TO_PCB_UNIT( aStart.y ), - TO_PCB_UNIT( aEnd.x ), TO_PCB_UNIT( aEnd.y ), - TO_PCB_UNIT( aWidth ) ); - fprintf( m_fp, "De %d %d %d %lX %X", - aLayer, aType, aAngle, 0l, 0 ); - - if( aDrill > -2 ) - fprintf( m_fp, " %d", aDrill ); - - fprintf( m_fp, "\n" ); - - if( aDrill <= -2 ) - fprintf( m_fp, "$EndDRAWSEGMENT\n" ); + if( aIsArc && ( aAngle == 360.0 || aAngle == 0 ) ) + { + fprintf( m_fp, "(gr_circle (center %s %s) (end %s %s)(layer %s) (width %s))\n", + Double2Str( TO_PCB_UNIT(aStart.x) ).c_str(), + Double2Str( TO_PCB_UNIT(aStart.y) ).c_str(), + Double2Str( TO_PCB_UNIT(aEnd.x) ).c_str(), + Double2Str( TO_PCB_UNIT(aEnd.y) ).c_str(), + TO_UTF8( GetPCBDefaultLayerName( aLayer ) ), + Double2Str( TO_PCB_UNIT( aWidth ) ).c_str() + ); + } + else if( aIsArc ) + { + fprintf( m_fp, "(gr_arc (start %s %s) (end %s %s) (angle %s)(layer %s) (width %s))\n", + Double2Str( TO_PCB_UNIT(aStart.x) ).c_str(), + Double2Str( TO_PCB_UNIT(aStart.y) ).c_str(), + Double2Str( TO_PCB_UNIT(aEnd.x) ).c_str(), + Double2Str( TO_PCB_UNIT(aEnd.y) ).c_str(), + Double2Str( aAngle ).c_str(), + TO_UTF8( GetPCBDefaultLayerName( aLayer ) ), + Double2Str( TO_PCB_UNIT( aWidth ) ).c_str() + ); + } + else + { + fprintf( m_fp, "(gr_line (start %s %s) (end %s %s)(layer %s) (width %s))\n", + Double2Str( TO_PCB_UNIT(aStart.x) ).c_str(), + Double2Str( TO_PCB_UNIT(aStart.y) ).c_str(), + Double2Str( TO_PCB_UNIT(aEnd.x) ).c_str(), + Double2Str( TO_PCB_UNIT(aEnd.y) ).c_str(), + TO_UTF8( GetPCBDefaultLayerName( aLayer ) ), + Double2Str( TO_PCB_UNIT( aWidth ) ).c_str() + ); + } } diff --git a/gerbview/files.cpp b/gerbview/files.cpp index 7daa9d9b80..5b5aaf7bb1 100644 --- a/gerbview/files.cpp +++ b/gerbview/files.cpp @@ -47,7 +47,7 @@ void GERBVIEW_FRAME::OnGbrFileHistory( wxCommandEvent& event ) if( !fn.IsEmpty() ) { - Erase_Current_Layer( false ); + Erase_Current_DrawLayer( false ); LoadGerberFiles( fn ); } } @@ -61,7 +61,7 @@ void GERBVIEW_FRAME::OnDrlFileHistory( wxCommandEvent& event ) if( !fn.IsEmpty() ) { - Erase_Current_Layer( false ); + Erase_Current_DrawLayer( false ); LoadExcellonFiles( fn ); } } @@ -75,12 +75,12 @@ void GERBVIEW_FRAME::Files_io( wxCommandEvent& event ) switch( id ) { case wxID_FILE: - Erase_Current_Layer( false ); + Erase_Current_DrawLayer( false ); LoadGerberFiles( wxEmptyString ); break; case ID_GERBVIEW_ERASE_ALL: - Clear_Pcb( true ); + Clear_DrawLayers( true ); Zoom_Automatique( false ); m_canvas->Refresh(); ClearMsgPanel(); diff --git a/gerbview/gerbview_frame.cpp b/gerbview/gerbview_frame.cpp index ccb7cbf431..d4163f7dfe 100644 --- a/gerbview/gerbview_frame.cpp +++ b/gerbview/gerbview_frame.cpp @@ -138,6 +138,7 @@ GERBVIEW_FRAME::GERBVIEW_FRAME( KIWAY* aKiway, wxWindow* aParent ): lyrs.MinSize( m_LayersManager->GetBestSize() ); lyrs.BestSize( m_LayersManager->GetBestSize() ); lyrs.Caption( _( "Visibles" ) ); + lyrs.TopDockable( false ).BottomDockable( false ); if( m_mainToolBar ) diff --git a/gerbview/gerbview_frame.h b/gerbview/gerbview_frame.h index fc35c3d4a5..20d549dd59 100644 --- a/gerbview/gerbview_frame.h +++ b/gerbview/gerbview_frame.h @@ -630,8 +630,8 @@ public: void Liste_D_Codes(); // PCB handling - bool Clear_Pcb( bool query ); - void Erase_Current_Layer( bool query ); + bool Clear_DrawLayers( bool query ); + void Erase_Current_DrawLayer( bool query ); // Conversion function void ExportDataInPcbnewFormat( wxCommandEvent& event ); diff --git a/gerbview/initpcb.cpp b/gerbview/init_gbr_drawlayers.cpp similarity index 95% rename from gerbview/initpcb.cpp rename to gerbview/init_gbr_drawlayers.cpp index f428dd9a54..3f7c6a8145 100644 --- a/gerbview/initpcb.cpp +++ b/gerbview/init_gbr_drawlayers.cpp @@ -23,7 +23,7 @@ */ /** - * @file gerbview/initpcb.cpp + * @file init_gbr_drawlayers.cpp */ #include @@ -38,7 +38,7 @@ #include #include -bool GERBVIEW_FRAME::Clear_Pcb( bool query ) +bool GERBVIEW_FRAME::Clear_DrawLayers( bool query ) { int layer; @@ -73,7 +73,7 @@ bool GERBVIEW_FRAME::Clear_Pcb( bool query ) } -void GERBVIEW_FRAME::Erase_Current_Layer( bool query ) +void GERBVIEW_FRAME::Erase_Current_DrawLayer( bool query ) { int layer = getActiveLayer(); wxString msg; diff --git a/gerbview/printout_control.cpp b/gerbview/printout_control.cpp new file mode 100644 index 0000000000..1ae5d969da --- /dev/null +++ b/gerbview/printout_control.cpp @@ -0,0 +1,270 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2014 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 1992-2014 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file printout_controller.cpp + * @brief Board print handler implementation file. + */ + + +// Set this to 1 if you want to test PostScript printing under MSW. +#define wxTEST_POSTSCRIPT_IN_MSW 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + + + +PRINT_PARAMETERS::PRINT_PARAMETERS() +{ + m_PenDefaultSize = Millimeter2iu( 0.2 ); // A reasonable default value to draw items + // which do not have a specified line width + m_PrintScale = 1.0; + m_XScaleAdjust = 1.0; + m_YScaleAdjust = 1.0; + m_Print_Sheet_Ref = false; + m_PrintMaskLayer.set(); + m_PrintMirror = false; + m_Print_Black_and_White = true; + m_OptionPrintPage = 1; + m_PageCount = 1; + m_ForceCentered = false; + m_Flags = 0; + m_DrillShapeOpt = PRINT_PARAMETERS::SMALL_DRILL_SHAPE; + m_PageSetupData = NULL; +} + + +BOARD_PRINTOUT_CONTROLLER::BOARD_PRINTOUT_CONTROLLER( const PRINT_PARAMETERS& aParams, + EDA_DRAW_FRAME* aParent, + const wxString& aTitle ) : + wxPrintout( aTitle ) +{ + m_PrintParams = aParams; // Make a local copy of the print parameters. + m_Parent = aParent; +} + + +bool BOARD_PRINTOUT_CONTROLLER::OnPrintPage( int aPage ) +{ + // in gerbview, draw layers are always printed on separate pages + // because handling negative objects when using only one page is tricky + m_PrintParams.m_Flags = aPage-1; // = gerber draw layer id + DrawPage(); + + return true; +} + + +void BOARD_PRINTOUT_CONTROLLER::GetPageInfo( int* minPage, int* maxPage, + int* selPageFrom, int* selPageTo ) +{ + *minPage = 1; + *selPageFrom = 1; + + int icnt = 1; + + if( m_PrintParams.m_OptionPrintPage == 0 ) + icnt = m_PrintParams.m_PageCount; + + *maxPage = icnt; + *selPageTo = icnt; +} + + +void BOARD_PRINTOUT_CONTROLLER::DrawPage() +{ + wxPoint offset; + double userscale; + EDA_RECT boardBoundingBox; + EDA_RECT drawRect; + wxDC* dc = GetDC(); + BASE_SCREEN* screen = m_Parent->GetScreen(); + bool printMirror = m_PrintParams.m_PrintMirror; + wxSize pageSizeIU = m_Parent->GetPageSizeIU(); + + wxBusyCursor dummy; + + boardBoundingBox = ((GERBVIEW_FRAME*) m_Parent)->GetGerberLayoutBoundingBox(); + wxString titleblockFilename; // TODO see if we uses the gerber file name + + // Use the page size as the drawing area when the board is shown or the user scale + // is less than 1. + if( m_PrintParams.PrintBorderAndTitleBlock() ) + boardBoundingBox = EDA_RECT( wxPoint( 0, 0 ), pageSizeIU ); + + // Compute the PCB size in internal units + userscale = m_PrintParams.m_PrintScale; + + if( m_PrintParams.m_PrintScale == 0 ) // fit in page option + { + if(boardBoundingBox.GetWidth() && boardBoundingBox.GetHeight()) + { + int margin = Millimeter2iu( 10.0 ); // add a margin around the drawings + double scaleX = (double)(pageSizeIU.x - (2 * margin)) / + boardBoundingBox.GetWidth(); + double scaleY = (double)(pageSizeIU.y - (2 * margin)) / + boardBoundingBox.GetHeight(); + userscale = (scaleX < scaleY) ? scaleX : scaleY; + } + else + userscale = 1.0; + } + + wxSize scaledPageSize = pageSizeIU; + drawRect.SetSize( scaledPageSize ); + scaledPageSize.x = wxRound( scaledPageSize.x / userscale ); + scaledPageSize.y = wxRound( scaledPageSize.y / userscale ); + + + if( m_PrintParams.m_PageSetupData ) + { + // Always scale to the size of the paper. + FitThisSizeToPageMargins( scaledPageSize, *m_PrintParams.m_PageSetupData ); + } + + // Compute Accurate scale 1 + if( m_PrintParams.m_PrintScale == 1.0 ) + { + // We want a 1:1 scale, regardless the page setup + // like page size, margin ... + MapScreenSizeToPaper(); // set best scale and offset (scale is not used) + int w, h; + GetPPIPrinter( &w, &h ); + double accurate_Xscale = (double) w / (IU_PER_MILS*1000); + double accurate_Yscale = (double) h / (IU_PER_MILS*1000); + + if( IsPreview() ) // Scale must take in account the DC size in Preview + { + // Get the size of the DC in pixels + wxSize PlotAreaSize; + dc->GetSize( &PlotAreaSize.x, &PlotAreaSize.y ); + GetPageSizePixels( &w, &h ); + accurate_Xscale *= (double)PlotAreaSize.x / w; + accurate_Yscale *= (double)PlotAreaSize.y / h; + } + // Fine scale adjust + accurate_Xscale *= m_PrintParams.m_XScaleAdjust; + accurate_Yscale *= m_PrintParams.m_YScaleAdjust; + + // Set print scale for 1:1 exact scale + dc->SetUserScale( accurate_Xscale, accurate_Yscale ); + } + + // Get the final size of the DC in pixels + wxSize PlotAreaSizeInPixels; + dc->GetSize( &PlotAreaSizeInPixels.x, &PlotAreaSizeInPixels.y ); + + double scalex, scaley; + dc->GetUserScale( &scalex, &scaley ); + + wxSize PlotAreaSizeInUserUnits; + PlotAreaSizeInUserUnits.x = KiROUND( PlotAreaSizeInPixels.x / scalex ); + PlotAreaSizeInUserUnits.y = KiROUND( PlotAreaSizeInPixels.y / scaley ); + + // In some cases the plot origin is the centre of the board outline rather than the center + // of the selected paper size. + if( m_PrintParams.CenterOnBoardOutline() ) + { + // Here we are only drawing the board and it's contents. + drawRect = boardBoundingBox; + offset.x += wxRound( (double) -scaledPageSize.x / 2.0 ); + offset.y += wxRound( (double) -scaledPageSize.y / 2.0 ); + + wxPoint center = boardBoundingBox.Centre(); + + if( printMirror ) + { + // Calculate the mirrored center of the board. + center.x = m_Parent->GetPageSizeIU().x - boardBoundingBox.Centre().x; + } + + offset += center; + } + + GRResetPenAndBrush( dc ); + + EDA_DRAW_PANEL* panel = m_Parent->GetCanvas(); + EDA_RECT tmp = *panel->GetClipBox(); + + // Set clip box to the max size + #define MAX_VALUE (INT_MAX/2) // MAX_VALUE is the max we can use in an integer + // and that allows calculations without overflow + panel->SetClipBox( EDA_RECT( wxPoint( 0, 0 ), wxSize( MAX_VALUE, MAX_VALUE ) ) ); + + screen->m_IsPrinting = true; + EDA_COLOR_T bg_color = m_Parent->GetDrawBgColor(); + + // Print frame reference, if requested, before printing draw layers + if( m_PrintParams.m_Print_Black_and_White ) + GRForceBlackPen( true ); + + if( m_PrintParams.PrintBorderAndTitleBlock() ) + m_Parent->DrawWorkSheet( dc, screen, m_PrintParams.m_PenDefaultSize, + IU_PER_MILS, titleblockFilename ); + + if( printMirror ) + { + // To plot mirror, we reverse the x axis, and modify the plot x origin + dc->SetAxisOrientation( false, false); + + /* Plot offset x is moved by the x plot area size in order to have + * the old draw area in the new draw area, because the draw origin has not moved + * (this is the upper left corner) but the X axis is reversed, therefore the plotting area + * is the x coordinate values from - PlotAreaSize.x to 0 */ + int x_dc_offset = PlotAreaSizeInPixels.x; + x_dc_offset = KiROUND( x_dc_offset * userscale ); + dc->SetDeviceOrigin( x_dc_offset, 0 ); + + panel->SetClipBox( EDA_RECT( wxPoint( -MAX_VALUE/2, -MAX_VALUE/2 ), + panel->GetClipBox()->GetSize() ) ); + } + + // screen->m_DrawOrg = offset; + dc->SetLogicalOrigin( offset.x, offset.y ); + m_Parent->SetDrawBgColor( WHITE ); + + // Never force black pen to print draw layers + // because negative objects need a white pen, not a black pen + // B&W mode is handled in print page function + GRForceBlackPen( false ); + + m_Parent->PrintPage( dc, m_PrintParams.m_PrintMaskLayer, printMirror, + &m_PrintParams ); + + m_Parent->SetDrawBgColor( bg_color ); + screen->m_IsPrinting = false; + panel->SetClipBox( tmp ); +} diff --git a/gerbview/rs274_read_XY_and_IJ_coordinates.cpp b/gerbview/rs274_read_XY_and_IJ_coordinates.cpp index d2b53fd86f..260b16c483 100644 --- a/gerbview/rs274_read_XY_and_IJ_coordinates.cpp +++ b/gerbview/rs274_read_XY_and_IJ_coordinates.cpp @@ -19,7 +19,7 @@ // depending on the gerber file format // this scale list assumes gerber units are imperial. // for metric gerber units, the imperial to metric conversion is made in read functions -#define SCALE_LIST_SIZE 10 +#define SCALE_LIST_SIZE 9 static double scale_list[SCALE_LIST_SIZE] = { 1000.0 * IU_PER_MILS, // x.1 format (certainly useless) @@ -28,9 +28,9 @@ static double scale_list[SCALE_LIST_SIZE] = 1.0 * IU_PER_MILS, // x.4 format 0.1 * IU_PER_MILS, // x.5 format 0.01 * IU_PER_MILS, // x.6 format - 0.0001 * IU_PER_MILS, // x.7 format + 0.001 * IU_PER_MILS, // x.7 format (currently the max allowed precision) + 0.0001 * IU_PER_MILS, // provided, but not used 0.00001 * IU_PER_MILS, // provided, but not used - 0.000001 * IU_PER_MILS }; /* diff --git a/gerbview/select_layers_to_pcb.cpp b/gerbview/select_layers_to_pcb.cpp index 03e48aa3c9..40c9f4e018 100644 --- a/gerbview/select_layers_to_pcb.cpp +++ b/gerbview/select_layers_to_pcb.cpp @@ -359,17 +359,19 @@ void LAYERS_MAP_DIALOG::OnSelectLayer( wxCommandEvent& event ) } LAYER_NUM jj = m_layersLookUpTable[m_buttonTable[ii]]; - if( !IsValidLayer( jj ) ) + + if( jj != UNSELECTED_LAYER && !IsValidLayer( jj ) ) jj = B_Cu; // (Defaults to "Copper" layer.) jj = m_Parent->SelectPCBLayer( jj, m_exportBoardCopperLayersCount, true ); - if( !IsValidLayer( jj ) ) + if( jj != UNSELECTED_LAYER && !IsValidLayer( jj ) ) return; if( jj != m_layersLookUpTable[m_buttonTable[ii]] ) { m_layersLookUpTable[m_buttonTable[ii]] = jj; + if( jj == UNSELECTED_LAYER ) { m_layersList[ii]->SetLabel( _( "Do not export" ) ); diff --git a/pcbnew/printout_controler.cpp b/pcbnew/printout_controler.cpp index 3b982fe2bf..f9b78102a3 100644 --- a/pcbnew/printout_controler.cpp +++ b/pcbnew/printout_controler.cpp @@ -37,16 +37,10 @@ #include #include #include -#ifdef PCBNEW - #include - #include - #include -#else - #include - #include - #include - #include -#endif +#include +#include +#include + #include @@ -89,7 +83,6 @@ BOARD_PRINTOUT_CONTROLLER::BOARD_PRINTOUT_CONTROLLER( const PRINT_PARAMETERS& aP bool BOARD_PRINTOUT_CONTROLLER::OnPrintPage( int aPage ) { -#ifdef PCBNEW LSET lset = m_PrintParams.m_PrintMaskLayer; // compute layer mask from page number if we want one page per layer @@ -115,11 +108,6 @@ bool BOARD_PRINTOUT_CONTROLLER::OnPrintPage( int aPage ) DrawPage(); m_PrintParams.m_PrintMaskLayer = lset; -#else // GERBVIEW - // in gerbview, draw layers are printed on separate pages - m_PrintParams.m_Flags = aPage-1; // = gerber draw layer id - DrawPage(); -#endif return true; } @@ -154,16 +142,9 @@ void BOARD_PRINTOUT_CONTROLLER::DrawPage() wxBusyCursor dummy; -#if defined (PCBNEW) BOARD * brd = ((PCB_BASE_FRAME*) m_Parent)->GetBoard(); boardBoundingBox = brd->ComputeBoundingBox(); wxString titleblockFilename = brd->GetFileName(); -#elif defined (GERBVIEW) - boardBoundingBox = ((GERBVIEW_FRAME*) m_Parent)->GetGerberLayoutBoundingBox(); - wxString titleblockFilename; // TODO see if we uses the gerber file name -#else - #error BOARD_PRINTOUT_CONTROLLER::DrawPage() works only for PCBNEW or GERBVIEW -#endif // Use the page size as the drawing area when the board is shown or the user scale // is less than 1. @@ -362,12 +343,6 @@ void BOARD_PRINTOUT_CONTROLLER::DrawPage() GRForceBlackPen( true ); -#if defined (GERBVIEW) - // In B&W mode, do not force black pen for Gerbview - // because negative objects need a white pen, not a black pen - // B&W mode is handled in print page - GRForceBlackPen( false ); -#endif m_Parent->PrintPage( dc, m_PrintParams.m_PrintMaskLayer, printMirror, &m_PrintParams );