diff --git a/.bzrignore b/.bzrignore index c981d28c7f..de41d5eea9 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1,11 +1,14 @@ common/netlist_keywords.* common/netlist_lexer.h +common/pcb_plot_params_lexer.h include/netlist_lexer.h eeschema/cmp_library_lexer.h eeschema/cmp_library_keywords.* eeschema/template_fieldnames_keywords.* eeschema/template_fieldnames_lexer.h pcbnew/dialogs/dialog_freeroute_exchange_help_html.h +pcbnew/pcb_plot_params_keywords.cpp +pcbnew/pcb_plot_params_lexer.h Makefile CMakeFiles CMakeCache.txt @@ -30,3 +33,5 @@ new/sweet_keywords.cpp new/sweet_lexer.h bitmaps_png/png* bitmaps_png/tmp +common/pcb_keywords.cpp +include/pcb_lexer.h diff --git a/3d-viewer/3d_draw.cpp b/3d-viewer/3d_draw.cpp index 422b4822f9..0c0a6b05d8 100644 --- a/3d-viewer/3d_draw.cpp +++ b/3d-viewer/3d_draw.cpp @@ -177,7 +177,7 @@ GLuint EDA_3D_CANVAS::CreateDrawGL_List() // because all boards thickness no not match with this setup: // double epoxy_width = 1.6; // epoxy width in mm - g_Parm_3D_Visu.m_Epoxy_Width = pcb->GetDesignSettings().m_BoardThickness + g_Parm_3D_Visu.m_Epoxy_Width = pcb->GetDesignSettings().GetBoardThickness() * g_Parm_3D_Visu.m_BoardScale; // calculate z position for each layer diff --git a/CMakeLists.txt b/CMakeLists.txt index fe6907cfc8..a518154595 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -80,11 +80,11 @@ else (KICAD_STABLE_VERSION ) endif(KICAD_STABLE_VERSION ) # Nanometers must be enabled when USE_PCBNEW_SEXPR_FILE_FORMAT=ON. -if( USE_PCBNEW_SEXPR_FILE_FORMAT AND NOT USE_PCBNEW_NANOMETRES ) - set( TMP "The Pcbnew s-expression file format requires nano-meter internal units to be " ) - set( TMP "${TMP} enabled using -DUSE_PCBNEW_NANOMETRES=ON." ) - message( FATAL_ERROR ${TMP} ) -endif( USE_PCBNEW_SEXPR_FILE_FORMAT AND NOT USE_PCBNEW_NANOMETRES ) +#if( USE_PCBNEW_SEXPR_FILE_FORMAT AND NOT USE_PCBNEW_NANOMETRES ) +# set( TMP "The Pcbnew s-expression file format requires nano-meter internal units to be " ) +# set( TMP "${TMP} enabled using -DUSE_PCBNEW_NANOMETRES=ON." ) +# message( FATAL_ERROR ${TMP} ) +#endif( USE_PCBNEW_SEXPR_FILE_FORMAT AND NOT USE_PCBNEW_NANOMETRES ) #================================================ # Set flags for GCC. diff --git a/bitmaps_png/CMakeLists.txt b/bitmaps_png/CMakeLists.txt index 92e8e3fe9f..7fdbe66c8c 100644 --- a/bitmaps_png/CMakeLists.txt +++ b/bitmaps_png/CMakeLists.txt @@ -496,6 +496,7 @@ set( BMAPS_MID window_close zip_tool zip + zone_duplicate zone_unfill zoom zoom_area diff --git a/bitmaps_png/cpp_26/zone_duplicate.cpp b/bitmaps_png/cpp_26/zone_duplicate.cpp new file mode 100644 index 0000000000..de53cc2cf9 --- /dev/null +++ b/bitmaps_png/cpp_26/zone_duplicate.cpp @@ -0,0 +1,106 @@ + +/* Do not modify this file, it was automatically generated by the + * PNG2cpp CMake script, using a *.png file as input. + */ + +#include + +static const unsigned char png[] = { + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, + 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x1a, 0x08, 0x06, 0x00, 0x00, 0x00, 0xa9, 0x4a, 0x4c, + 0xce, 0x00, 0x00, 0x05, 0x8a, 0x49, 0x44, 0x41, 0x54, 0x48, 0xc7, 0xb5, 0x95, 0x7b, 0x4c, 0x53, + 0x57, 0x18, 0xc0, 0xbf, 0x16, 0x6c, 0xa1, 0x2d, 0x85, 0x96, 0xd2, 0x42, 0x2d, 0xe5, 0xf6, 0x71, + 0x6f, 0x1f, 0x3c, 0x0a, 0x02, 0xe5, 0xa1, 0x2d, 0x2d, 0xe5, 0xa1, 0xb0, 0x29, 0x0e, 0x11, 0xe2, + 0x98, 0x8f, 0xf9, 0x16, 0x9c, 0x4f, 0x06, 0xe8, 0x1c, 0x3a, 0x75, 0x8b, 0x9a, 0x0c, 0x33, 0x27, + 0xd9, 0x12, 0xa3, 0x59, 0xe6, 0x8c, 0xca, 0x36, 0x70, 0x33, 0xd1, 0xcd, 0x6c, 0x46, 0x9d, 0x3a, + 0x35, 0x1a, 0x23, 0x33, 0x9b, 0x8a, 0x32, 0xcc, 0x14, 0x50, 0x1e, 0xbe, 0x26, 0x2f, 0xe5, 0xdb, + 0xb9, 0x9d, 0x45, 0x34, 0x2a, 0x98, 0xcd, 0x3f, 0x7e, 0x39, 0x37, 0xe7, 0xe4, 0x7e, 0xbf, 0xf3, + 0x7d, 0xf7, 0x9c, 0xef, 0x82, 0xc1, 0x65, 0xb8, 0xa9, 0x1f, 0xad, 0x7f, 0x69, 0xb4, 0x2e, 0x73, + 0xab, 0xc2, 0x92, 0x76, 0x47, 0x95, 0x90, 0xd4, 0x41, 0x39, 0x2c, 0x6d, 0xfa, 0xd1, 0xf4, 0x4d, + 0x26, 0x9d, 0xbe, 0x6d, 0x4e, 0x35, 0xe4, 0x21, 0x22, 0x3c, 0x0d, 0xe8, 0x33, 0xf5, 0x2d, 0xb0, + 0x02, 0x70, 0x20, 0x9c, 0xe5, 0x1c, 0xf4, 0x5d, 0xe8, 0x83, 0xfc, 0x25, 0x7c, 0x7c, 0x7a, 0xad, + 0x9f, 0xb9, 0x32, 0xf2, 0xf6, 0xca, 0xc7, 0xc8, 0x8a, 0x50, 0xec, 0x4c, 0xe8, 0x31, 0x39, 0x4c, + 0xf9, 0x83, 0x8a, 0xbc, 0x4b, 0xbd, 0x31, 0x2c, 0x47, 0xdd, 0xca, 0x64, 0xd2, 0x0d, 0x64, 0xbe, + 0x86, 0xce, 0xd4, 0x1d, 0xa0, 0x33, 0xf4, 0xd7, 0xe4, 0x85, 0xf2, 0xbb, 0x83, 0x8a, 0x1e, 0x21, + 0x08, 0x28, 0xfa, 0xe6, 0x85, 0x22, 0xde, 0x52, 0x1e, 0x92, 0xa0, 0xcd, 0x66, 0x27, 0xe3, 0x82, + 0x95, 0x10, 0x41, 0xe6, 0x8a, 0x09, 0x6f, 0xc3, 0x32, 0x08, 0x61, 0x32, 0xf4, 0x9b, 0xf5, 0x63, + 0xb4, 0x6d, 0x9a, 0xb1, 0x54, 0x8b, 0x7a, 0xbc, 0xba, 0x8d, 0xdd, 0x10, 0x94, 0x13, 0xf2, 0x4c, + 0x08, 0xb6, 0x54, 0x04, 0xed, 0x5b, 0x8f, 0x65, 0x9c, 0x8a, 0x1e, 0x32, 0x6a, 0x9f, 0x2b, 0xa2, + 0xc6, 0x85, 0xb5, 0x99, 0x9d, 0xe6, 0x04, 0xf2, 0x5c, 0x46, 0x78, 0x38, 0x60, 0xf7, 0x1d, 0xb0, + 0x1c, 0xec, 0x7a, 0x9b, 0x3e, 0x28, 0xdc, 0x11, 0x1e, 0x6c, 0x4c, 0x35, 0x66, 0x68, 0xb3, 0xb4, + 0x6d, 0xdc, 0x72, 0xee, 0x93, 0x19, 0xc6, 0x65, 0x0f, 0xc8, 0x6c, 0x55, 0xd1, 0x33, 0x45, 0xec, + 0x0e, 0x49, 0x36, 0x75, 0xe4, 0x85, 0x70, 0x56, 0xe2, 0xbb, 0xc0, 0xb7, 0x31, 0x22, 0x4b, 0xbd, + 0xdf, 0xf4, 0xba, 0xea, 0x17, 0x2a, 0x5f, 0xde, 0x4d, 0xe8, 0xd5, 0x4d, 0x08, 0xbe, 0xae, 0xcb, + 0x53, 0xb4, 0x58, 0x32, 0xa8, 0xea, 0x38, 0x3b, 0xbd, 0x2f, 0x2a, 0x4d, 0xd7, 0x45, 0x15, 0xc8, + 0x91, 0x2a, 0x08, 0x72, 0x13, 0x9c, 0x1a, 0xdd, 0x2f, 0x92, 0xca, 0xa6, 0x9f, 0x49, 0xb0, 0xd1, + 0x9f, 0x78, 0x18, 0x61, 0x67, 0x96, 0xbb, 0x45, 0xc2, 0x62, 0x21, 0x32, 0xa3, 0xf5, 0x5b, 0x1e, + 0x95, 0x0b, 0x95, 0xf9, 0xca, 0xaa, 0xc5, 0xe1, 0xca, 0xfa, 0xef, 0x15, 0x7e, 0x47, 0x3e, 0x33, + 0x08, 0x9b, 0xd6, 0x5b, 0x04, 0xe8, 0x61, 0x43, 0x94, 0xa0, 0xb7, 0x5a, 0x25, 0x3a, 0xfd, 0x45, + 0x68, 0x40, 0x43, 0x81, 0x62, 0xd4, 0xc3, 0x08, 0xff, 0x49, 0x68, 0x16, 0x17, 0xa2, 0x56, 0x38, + 0xfd, 0xb1, 0x88, 0x5b, 0xd2, 0x19, 0xcb, 0x9f, 0x72, 0x93, 0x25, 0x9e, 0x3f, 0xf9, 0x46, 0x64, + 0x74, 0xe2, 0x5f, 0x6e, 0x91, 0xe0, 0x1d, 0x01, 0x92, 0x23, 0xbb, 0x9d, 0x94, 0xc8, 0xca, 0x8a, + 0x14, 0x93, 0x14, 0x3b, 0x37, 0x6a, 0x65, 0x67, 0x3b, 0xbd, 0xa0, 0xe6, 0x47, 0x0d, 0xb4, 0x7c, + 0x65, 0xe6, 0x62, 0xb1, 0x55, 0x8a, 0x19, 0x0e, 0x25, 0xc6, 0xbb, 0x28, 0xcc, 0xb6, 0x2b, 0x7b, + 0x2a, 0xf5, 0x81, 0x67, 0x8f, 0x4b, 0x7c, 0x1b, 0xf2, 0xc5, 0xe9, 0x0f, 0x39, 0x50, 0xf1, 0xcc, + 0x83, 0xe1, 0x07, 0xe5, 0xdd, 0xdb, 0xb8, 0x91, 0x47, 0x47, 0x8e, 0xa2, 0x2f, 0xba, 0x45, 0xdc, + 0x65, 0x5c, 0xa4, 0x33, 0xf5, 0xf5, 0xee, 0x5a, 0xbe, 0x0f, 0xa7, 0x02, 0x66, 0xf9, 0x77, 0x57, + 0x44, 0x4a, 0x5b, 0x0f, 0x68, 0xa0, 0xe9, 0xe3, 0x28, 0x1f, 0xb4, 0xba, 0xa8, 0x5e, 0x65, 0x61, + 0xd0, 0x4f, 0x3e, 0x8b, 0x7d, 0xb6, 0xf2, 0xcb, 0xe1, 0x16, 0x7b, 0xec, 0xc3, 0xf2, 0x15, 0xad, + 0x39, 0x56, 0xea, 0xf2, 0x66, 0x8d, 0xb4, 0x7d, 0x5a, 0x68, 0x4c, 0x9f, 0xc0, 0xab, 0xf4, 0x09, + 0x09, 0x0d, 0xf3, 0x3b, 0xce, 0x70, 0xe5, 0x3f, 0xb0, 0x9b, 0xed, 0x17, 0xb1, 0x59, 0x84, 0xe6, + 0xaa, 0x6e, 0x19, 0xd2, 0x0c, 0x13, 0xc9, 0x73, 0xa4, 0x64, 0x86, 0xa4, 0xa9, 0x24, 0x36, 0x00, + 0x77, 0x98, 0x39, 0x68, 0x4d, 0xd5, 0x74, 0xca, 0xa7, 0x04, 0xc5, 0xec, 0x0a, 0xf1, 0x7f, 0xf7, + 0x8e, 0x37, 0xe7, 0xcb, 0x2b, 0x62, 0x38, 0xbc, 0x29, 0x0e, 0x1e, 0x44, 0xcf, 0x00, 0x94, 0xcc, + 0x16, 0x9f, 0x8f, 0x4b, 0xa1, 0x2b, 0x2d, 0x4e, 0xba, 0x39, 0x32, 0x29, 0xaa, 0x4f, 0xcd, 0x9f, + 0xd7, 0xc7, 0x4a, 0xc6, 0x72, 0x0a, 0x1a, 0xda, 0xbc, 0x78, 0x7b, 0x58, 0x09, 0x4b, 0xf2, 0x28, + 0xfa, 0x52, 0xbf, 0xc8, 0xab, 0xcc, 0x8b, 0xcd, 0xaa, 0x95, 0x71, 0x31, 0x39, 0x26, 0xa7, 0x71, + 0xda, 0x7a, 0x26, 0xf0, 0x8f, 0xd5, 0xc6, 0xa0, 0xba, 0x58, 0x3b, 0xb3, 0xe0, 0x03, 0x83, 0xac, + 0x72, 0x5f, 0xb0, 0xa0, 0x67, 0xbf, 0x42, 0xd8, 0x7e, 0x9b, 0xcb, 0x59, 0xfd, 0x5b, 0x20, 0x1c, + 0xdb, 0xc3, 0x40, 0x5f, 0x6e, 0x3e, 0xe0, 0xd8, 0x37, 0xe1, 0xc8, 0x11, 0x8a, 0x9f, 0xc4, 0x64, + 0x30, 0x57, 0x13, 0x47, 0x32, 0x7d, 0xeb, 0x84, 0xd1, 0x97, 0x3c, 0x82, 0x01, 0xa2, 0x8b, 0x4f, + 0x5c, 0x58, 0xaf, 0x72, 0x2f, 0x54, 0x8f, 0x0f, 0x6d, 0x37, 0xa4, 0x33, 0x2d, 0xab, 0x0c, 0xf2, + 0x5b, 0xa4, 0x34, 0xf7, 0x48, 0x5b, 0x69, 0xde, 0x64, 0x14, 0x75, 0xee, 0x30, 0x93, 0x2b, 0x30, + 0x39, 0xa0, 0x8b, 0xdc, 0xa9, 0x9f, 0xaf, 0xf3, 0x80, 0xfe, 0xd3, 0x1f, 0x1a, 0x4f, 0xa9, 0x01, + 0xab, 0x63, 0x01, 0x0f, 0x9b, 0xa0, 0xe1, 0xa0, 0x46, 0x98, 0x65, 0x4a, 0x35, 0xdc, 0x49, 0x4f, + 0xd2, 0x35, 0xb5, 0xf3, 0xb8, 0xdf, 0xbd, 0x50, 0xe4, 0x41, 0x32, 0x33, 0x00, 0x4b, 0xa3, 0xa5, + 0x38, 0xd2, 0x19, 0x86, 0xec, 0xf7, 0xdb, 0x90, 0x08, 0x48, 0xca, 0xe5, 0x5e, 0x93, 0x4d, 0x91, + 0xdd, 0x8b, 0x4a, 0xd7, 0x7d, 0xdd, 0xe5, 0x0d, 0xbf, 0x36, 0x06, 0x42, 0x2b, 0x2b, 0x62, 0x39, + 0x66, 0x80, 0xf3, 0x55, 0xe6, 0xa0, 0x6c, 0x4b, 0x8a, 0x61, 0x4d, 0x6e, 0x1c, 0x75, 0xe1, 0x6f, + 0x6f, 0xa8, 0x1d, 0x54, 0xe4, 0x3f, 0xcb, 0x1f, 0xd9, 0x6f, 0xf4, 0x86, 0x5d, 0x81, 0xbe, 0x8b, + 0x7c, 0x70, 0x4c, 0x01, 0xe0, 0x2e, 0x13, 0xe0, 0x6b, 0xa4, 0x54, 0xd2, 0xa5, 0x80, 0x0b, 0xad, + 0xe2, 0xfb, 0x97, 0x45, 0xc3, 0x5a, 0xba, 0x04, 0x70, 0xf2, 0x90, 0x19, 0xae, 0x7a, 0x64, 0x27, + 0x69, 0x38, 0x81, 0x81, 0x30, 0x3c, 0xde, 0xc6, 0x2c, 0x9b, 0x69, 0x51, 0xd5, 0x0d, 0x59, 0xb4, + 0x72, 0x84, 0x08, 0x35, 0xf9, 0x72, 0x14, 0x96, 0x01, 0x7e, 0x1a, 0xfb, 0xaf, 0xcc, 0xc3, 0x56, + 0x9d, 0xb0, 0x2b, 0xde, 0xa1, 0xab, 0x10, 0x17, 0xf9, 0xf1, 0xc2, 0x16, 0xc2, 0xc1, 0x2d, 0xc9, + 0x6e, 0x59, 0x5f, 0xbd, 0x1a, 0x6a, 0x6e, 0x8b, 0x41, 0x6a, 0xb5, 0xd1, 0x9f, 0xaf, 0x30, 0x06, + 0x9f, 0x1e, 0x92, 0x68, 0x37, 0x09, 0x98, 0xea, 0x54, 0xa1, 0xa8, 0x48, 0xe8, 0x96, 0x8d, 0xcb, + 0x03, 0x2c, 0xce, 0x04, 0xcc, 0x21, 0xa3, 0x6f, 0x19, 0x07, 0x99, 0x2c, 0xcd, 0xdd, 0x98, 0x14, + 0xa6, 0x79, 0x78, 0xbe, 0x92, 0x32, 0x17, 0xc1, 0xb9, 0xed, 0x56, 0xc0, 0x0b, 0x61, 0x70, 0xa2, + 0x47, 0x0a, 0x1b, 0x2f, 0x69, 0xf8, 0x22, 0x22, 0xdb, 0x5b, 0x45, 0x05, 0x1e, 0x1f, 0x92, 0x68, + 0x5b, 0xb8, 0x17, 0xba, 0x1c, 0x2a, 0xd4, 0x4c, 0x54, 0xa0, 0x70, 0xbe, 0x00, 0x79, 0x25, 0x3c, + 0xf4, 0x9b, 0x27, 0x42, 0xd2, 0x8e, 0x70, 0x8c, 0x5d, 0x89, 0x95, 0x7a, 0x69, 0x2f, 0x29, 0x55, + 0x43, 0xc0, 0x1c, 0x7f, 0xad, 0x75, 0x26, 0x5c, 0xfd, 0x3d, 0x0c, 0x8e, 0x77, 0x4b, 0xa0, 0x86, + 0xb0, 0x66, 0x15, 0x13, 0xcc, 0xca, 0x4e, 0x90, 0xf5, 0xc6, 0x41, 0x45, 0x1e, 0xd6, 0x46, 0x8b, + 0x70, 0x6a, 0xb2, 0x0c, 0xb3, 0x53, 0x42, 0x70, 0x4e, 0x82, 0x14, 0xd7, 0x91, 0x76, 0xc4, 0x96, + 0x70, 0xb7, 0x91, 0x83, 0xeb, 0x68, 0x59, 0x0f, 0x09, 0x76, 0x8e, 0xb7, 0x84, 0x67, 0xdc, 0x68, + 0x83, 0x45, 0x8f, 0x44, 0x35, 0xbd, 0x12, 0x28, 0x21, 0xf3, 0x92, 0x08, 0x87, 0xa1, 0x76, 0xc8, + 0xa2, 0x17, 0x51, 0x6d, 0xe0, 0xe0, 0x0a, 0x93, 0x82, 0x95, 0x1d, 0x22, 0x77, 0x90, 0xdb, 0x2d, + 0x85, 0x09, 0x1e, 0x59, 0x97, 0x14, 0x66, 0x91, 0x39, 0x3f, 0xa0, 0xd3, 0xe9, 0x0e, 0x36, 0xf0, + 0x40, 0x42, 0x0a, 0x82, 0xb1, 0xcc, 0x12, 0x88, 0xdf, 0x6a, 0x87, 0x0d, 0x99, 0x5a, 0x8a, 0x8f, + 0x0b, 0x22, 0x94, 0x0f, 0x88, 0xac, 0x9a, 0x6d, 0x65, 0x3d, 0x12, 0x98, 0xed, 0x91, 0x11, 0x71, + 0x2e, 0x98, 0x5c, 0x4c, 0x91, 0x31, 0xcd, 0xb8, 0x74, 0x20, 0xa6, 0x54, 0xe3, 0xce, 0x0f, 0x69, + 0xf9, 0xb5, 0x3a, 0x31, 0xbf, 0xee, 0x65, 0x99, 0x1b, 0xa5, 0xba, 0x62, 0xb5, 0x31, 0x6b, 0x49, + 0xc3, 0xe3, 0x90, 0xd2, 0x95, 0xba, 0xb3, 0x92, 0xc0, 0x66, 0x78, 0xd6, 0x6f, 0x97, 0xa4, 0x3a, + 0xd5, 0xd3, 0xbd, 0x5f, 0x96, 0xfb, 0x84, 0xc2, 0x11, 0xea, 0xf3, 0x71, 0x76, 0xa6, 0x98, 0xc8, + 0x86, 0x75, 0x4a, 0xe0, 0x23, 0x92, 0x5d, 0xd5, 0xff, 0x2e, 0x62, 0x21, 0xcd, 0xb7, 0x36, 0x27, + 0x9e, 0xba, 0x10, 0x63, 0x67, 0x26, 0xdc, 0x08, 0x02, 0x51, 0x77, 0x00, 0xbc, 0xf7, 0x4a, 0x44, + 0x2c, 0x6d, 0xa4, 0xdf, 0x65, 0x26, 0x6a, 0xeb, 0xa3, 0x1c, 0x06, 0x27, 0x2a, 0x41, 0xf0, 0xca, + 0x44, 0x2c, 0xd7, 0x7c, 0xbd, 0xf7, 0x3a, 0x93, 0x75, 0xf5, 0x24, 0x9e, 0xe5, 0x79, 0xa2, 0xf1, + 0x89, 0x36, 0xfa, 0x0a, 0x7b, 0xa3, 0xff, 0x2b, 0x6c, 0x1c, 0xd2, 0x68, 0x8f, 0xfe, 0x03, 0x4a, + 0x94, 0x41, 0xc0, 0x1e, 0x6f, 0x7c, 0x33, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, + 0x42, 0x60, 0x82, +}; + +const BITMAP_OPAQUE zone_duplicate_xpm[1] = {{ png, sizeof( png ), "zone_duplicate_xpm" }}; + +//EOF diff --git a/bitmaps_png/sources/module_ratsnest.svg b/bitmaps_png/sources/module_ratsnest.svg index c84a817c39..9f37b94232 100644 --- a/bitmaps_png/sources/module_ratsnest.svg +++ b/bitmaps_png/sources/module_ratsnest.svg @@ -1,36 +1,181 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bitmaps_png/sources/zone_duplicate.svg b/bitmaps_png/sources/zone_duplicate.svg new file mode 100644 index 0000000000..dd4fbe5d36 --- /dev/null +++ b/bitmaps_png/sources/zone_duplicate.svg @@ -0,0 +1,106 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index ff5252b2ba..a5b4c5e417 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -121,6 +121,8 @@ set(PCB_COMMON_SRCS ../pcbnew/legacy_plugin.cpp ../pcbnew/kicad_plugin.cpp pcb_plot_params_keywords.cpp + pcb_keywords.cpp + ../pcbnew/pcb_parser.cpp ) @@ -148,6 +150,14 @@ make_lexer( PCBPLOTPARAMS_T ) +# auto-generate pcbnew_sexpr.h and pcbnew_sexpr.cpp +make_lexer( ${CMAKE_CURRENT_SOURCE_DIR}/pcb.keywords + ${PROJECT_SOURCE_DIR}/include/pcb_lexer.h + ${CMAKE_CURRENT_SOURCE_DIR}/pcb_keywords.cpp + PCB + ) + + # The dsntest may not build properly using MS Visual Studio. if(NOT MSVC) # This one gets made only when testing. diff --git a/common/base_screen.cpp b/common/base_screen.cpp index c9a2c8cade..5d802f322e 100644 --- a/common/base_screen.cpp +++ b/common/base_screen.cpp @@ -1,9 +1,10 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2009 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2009 Wayne Stambaugh - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2012 Wayne Stambaugh + * Copyright (C) 1992-2012 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 @@ -285,7 +286,7 @@ GRID_TYPE& BASE_SCREEN::GetGrid( size_t aIndex ) } -wxPoint BASE_SCREEN::GetNearestGridPosition( const wxPoint& aPosition, +wxPoint BASE_SCREEN::GetNearestGridPosition( const wxPoint& aPosition, wxRealPoint* aGridSize ) const { wxPoint pt; diff --git a/common/common_plotPDF_functions.cpp b/common/common_plotPDF_functions.cpp index bffdf049e6..a410441a3f 100644 --- a/common/common_plotPDF_functions.cpp +++ b/common/common_plotPDF_functions.cpp @@ -3,6 +3,30 @@ * @brief Kicad: Common plot PDF Routines */ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2012 Lorenzo Marcantonio, l.marcantonio@logossrl.com + * Copyright (C) 1992-2012 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 + */ + #include #include #include diff --git a/common/common_plot_functions.cpp b/common/common_plot_functions.cpp index aa8be550de..1bfecab7a1 100644 --- a/common/common_plot_functions.cpp +++ b/common/common_plot_functions.cpp @@ -19,7 +19,7 @@ /* Plot sheet references * margin is in mils (1/1000 inch) */ -void EDA_DRAW_FRAME::PlotWorkSheet( PLOTTER* plotter, BASE_SCREEN* screen ) +void EDA_DRAW_FRAME::PlotWorkSheet( PLOTTER* plotter, BASE_SCREEN* screen, int aLineWidth ) { #define WSTEXTSIZE 50 // Text size in mils @@ -46,10 +46,11 @@ void EDA_DRAW_FRAME::PlotWorkSheet( PLOTTER* plotter, BASE_SCREEN* screen ) #endif bool italic = false; - bool thickness = 0; //@todo : use current pen + int thickness = aLineWidth; color = BLACK; plotter->SetColor( color ); + plotter->SetCurrentLineWidth( thickness ); // Plot edge. ref.x = pageInfo.GetLeftMarginMils() * iusPerMil; diff --git a/common/dialogs/dialog_image_editor.fbp b/common/dialogs/dialog_image_editor.fbp index 27ec5a178e..a7ae6141bb 100644 --- a/common/dialogs/dialog_image_editor.fbp +++ b/common/dialogs/dialog_image_editor.fbp @@ -1,8 +1,8 @@ - + - + C++ 1 source_name @@ -15,9 +15,9 @@ none 1 dialog_image_editor - + . - + 1 1 0 @@ -28,15 +28,15 @@ 1 1 0 - - - - + + + + 1 wxBOTH 0 1 - + 1 0 Dock @@ -44,82 +44,82 @@ Left 1 impl_virtual - - + + 1 - + 0 0 wxID_ANY - - + + 0 - - + + 0 - + 1 DIALOG_IMAGE_EDITOR_BASE 1 - - + + 1 - - + + Resizable - + 1 340,299 wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER - + Image Editor 0 - - + + wxFILTER_NONE wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + bSizerMain wxVERTICAL none @@ -128,7 +128,7 @@ wxEXPAND 1 - + bUpperSizer wxVERTICAL none @@ -137,7 +137,7 @@ wxEXPAND 1 - + bSizerLeft wxHORIZONTAL none @@ -150,79 +150,79 @@ 1 1 1 - - - - + + + + 1 0 1 - + 1 0 Dock 0 Left 1 - + 1 - + 0 0 wxID_ANY - - + + 0 - - + + 0 256,256 1 m_panelDraw 1 - - + + protected 1 - - + + Resizable - + 1 - - + + 0 - - + + wxFILTER_NONE wxDefaultValidator - - - + + + wxFULL_REPAINT_ON_RESIZE|wxSIMPLE_BORDER|wxTAB_TRAVERSAL - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + OnRedrawPanel - - - - - - + + + + + + @@ -230,7 +230,7 @@ wxEXPAND 0 - + bSizerRight wxVERTICAL none @@ -243,14 +243,14 @@ 1 1 1 - - - - + + + + 1 0 1 - + 1 0 0 @@ -258,68 +258,68 @@ 0 Left 1 - + 1 - + 0 0 wxID_ANY Mirror X - - + + 0 - - + + 0 - + 1 m_buttonMirrorX 1 - - + + protected 1 - - + + Resizable - + 1 - - - + + + 0 - - + + wxFILTER_NONE wxDefaultValidator - - - - + + + + OnMirrorX_click - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + @@ -331,14 +331,14 @@ 1 1 1 - - - - + + + + 1 0 1 - + 1 0 0 @@ -346,68 +346,68 @@ 0 Left 1 - + 1 - + 0 0 wxID_ANY Mirror Y - - + + 0 - - + + 0 - + 1 m_buttonMirrorY 1 - - + + protected 1 - - + + Resizable - + 1 - - - + + + 0 - - + + wxFILTER_NONE wxDefaultValidator - - - - + + + + OnMirrorY_click - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + @@ -419,14 +419,14 @@ 1 1 1 - - - - + + + + 1 0 1 - + 1 0 0 @@ -434,68 +434,68 @@ 0 Left 1 - + 1 - + 0 0 wxID_ANY Rotate - - + + 0 - - + + 0 - + 1 m_buttonRotate 1 - - + + protected 1 - - + + Resizable - + 1 - - - + + + 0 - - + + wxFILTER_NONE wxDefaultValidator - - - - + + + + OnRotateClick - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + @@ -507,14 +507,14 @@ 1 1 1 - - - - + + + + 1 0 1 - + 1 0 0 @@ -522,68 +522,68 @@ 0 Left 1 - + 1 - + 0 0 wxID_ANY Grey - - + + 0 - - + + 0 - + 1 m_buttonGrey 1 - - + + protected 1 - - + + Resizable - + 1 - - - + + + 0 - - + + wxFILTER_NONE wxDefaultValidator - - - - + + + + OnGreyScaleConvert - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + @@ -595,14 +595,14 @@ 1 1 1 - - - - + + + + 1 0 1 - + 1 1 0 @@ -610,68 +610,68 @@ 0 Left 1 - + 1 - + 0 0 wxID_ANY Half Size - - + + 0 - - + + 0 - + 1 m_buttonHalfSize 1 - - + + protected 1 - - + + Resizable - + 1 - - - + + + 0 - - + + wxFILTER_NONE wxDefaultValidator - - - - + + + + OnHalfSize - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + @@ -683,14 +683,14 @@ 1 1 1 - - - - + + + + 1 0 1 - + 1 0 0 @@ -698,68 +698,68 @@ 0 Left 1 - + 1 - + 0 0 wxID_ANY Undo Last - - + + 0 - - + + 0 - + 1 m_buttonUndoLast 1 - - + + protected 1 - - + + Resizable - + 1 - - - + + + 0 - - + + wxFILTER_NONE wxDefaultValidator - - - - + + + + OnUndoLastChange - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + @@ -771,82 +771,82 @@ 1 1 1 - - - - + + + + 1 0 1 - + 1 0 Dock 0 Left 1 - + 1 - + 0 0 wxID_ANY Image Scale: - - + + 0 - - + + 0 - + 1 m_staticTextScale 1 - - + + protected 1 - - + + Resizable - + 1 - - - + + + 0 - - + + wxFILTER_NONE wxDefaultValidator - - - - + + + + -1 - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + @@ -858,86 +858,86 @@ 1 1 1 - - - - + + + + 1 0 1 - + 1 0 Dock 0 Left 1 - + 1 - + 0 0 wxID_ANY - - + + 0 - + 0 - + 0 - + 1 m_textCtrlScale 1 - - + + protected 1 - - + + Resizable - + 1 - - - + + + 0 - - + + wxFILTER_NONE wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -959,17 +959,17 @@ 1 0 0 - + m_sdbSizer1 protected - + OnCancel_Button - - - + + + OnOK_Button - - + + diff --git a/common/drawpanel.cpp b/common/drawpanel.cpp index 85a8ed3cf4..938d72185c 100644 --- a/common/drawpanel.cpp +++ b/common/drawpanel.cpp @@ -83,7 +83,7 @@ END_EVENT_TABLE() EDA_DRAW_PANEL::EDA_DRAW_PANEL( EDA_DRAW_FRAME* parent, int id, const wxPoint& pos, const wxSize& size ) : - wxScrolledWindow( parent, id, pos, size, wxBORDER | wxHSCROLL | wxVSCROLL ) + wxScrolledWindow( parent, id, pos, size, wxBORDER | wxHSCROLL | wxVSCROLL | wxALWAYS_SHOW_SB ) { wxASSERT( parent ); diff --git a/common/drawtxt.cpp b/common/drawtxt.cpp index 27865f2db7..9d2c1c892c 100644 --- a/common/drawtxt.cpp +++ b/common/drawtxt.cpp @@ -2,6 +2,33 @@ * Functions to draw and plot text on screen * @file drawtxt.cpp */ + +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2012 Wayne Stambaugh + * Copyright (C) 1992-2012 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 + */ + #include #include #include @@ -526,15 +553,17 @@ void PLOTTER::Text( const wxPoint& aPos, bool aItalic, bool aBold ) { - if( aWidth == 0 && aBold ) // Use default values if aWidth == 0 - aWidth = GetPenSizeForBold( MIN( aSize.x, aSize.y ) ); + int textPensize = aWidth; - if( aWidth >= 0 ) - aWidth = Clamp_Text_PenSize( aWidth, aSize, aBold ); + if( textPensize == 0 && aBold ) // Use default values if aWidth == 0 + textPensize = GetPenSizeForBold( MIN( aSize.x, aSize.y ) ); + + if( textPensize >= 0 ) + textPensize = Clamp_Text_PenSize( aWidth, aSize, aBold ); else - aWidth = -Clamp_Text_PenSize( -aWidth, aSize, aBold ); + textPensize = -Clamp_Text_PenSize( -aWidth, aSize, aBold ); - SetCurrentLineWidth( aWidth ); + SetCurrentLineWidth( textPensize ); if( aColor >= 0 ) @@ -543,8 +572,11 @@ void PLOTTER::Text( const wxPoint& aPos, DrawGraphicText( NULL, NULL, aPos, aColor, aText, aOrient, aSize, aH_justify, aV_justify, - aWidth, aItalic, + textPensize, aItalic, aBold, NULL, this ); + + if( aWidth != textPensize ) + SetCurrentLineWidth( aWidth ); } diff --git a/common/dsnlexer.cpp b/common/dsnlexer.cpp index cfa298427d..6f8f6d064c 100644 --- a/common/dsnlexer.cpp +++ b/common/dsnlexer.cpp @@ -374,8 +374,13 @@ int DSNLEXER::NeedNUMBER( const char* aExpectation ) throw( IO_ERROR ) */ static inline bool isSpace( int cc ) { - // make sure int passed to ::isspace() is 0-255 - return ::isspace( cc & 0xff ); + // Warning: we are using UTF8 char, so values are coded from 0x01 to 0xFF + // isspace( int value ) works fine under Linux, + // but seems use only a 7 bits value under mingw, in comparisons. + // (for instance 0xA0 is seen as 0x20) + // So we need to test if the value is ASCII ( <= 127) and a space ( ' ', \t, \n ... ) + // and not just a space: + return ( (unsigned) cc <= 127 ) && ::isspace( cc ); } diff --git a/common/eda_text.cpp b/common/eda_text.cpp index 6cbae0800f..1c364eff20 100644 --- a/common/eda_text.cpp +++ b/common/eda_text.cpp @@ -1,391 +1,395 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2004 Jean-Pierre Charras, jean-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2004-2011 KiCad Developers, see change_log.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 eda_text.cpp - * @brief Implementation of base KiCad text object. - */ - -#include -#include -#include // MAX -#include // RotatePoint -#include // EDA_DRAW_PANEL - - -// Conversion to application internal units defined at build time. -#if defined( PCBNEW ) -#include -#define MILS_TO_IU( x ) ( x * IU_PER_MILS ); -#elif defined( EESCHEMA ) -#include -#define MILS_TO_IU( x ) ( x ) -#else -#error "Cannot resolve units formatting due to no definition of EESCHEMA or PCBNEW." -#endif - - -EDA_TEXT::EDA_TEXT( const wxString& text ) -{ - m_Size.x = m_Size.y = MILS_TO_IU( DEFAULT_SIZE_TEXT ); // Width and height of font. - m_Orient = 0; // Rotation angle in 0.1 degrees. - m_Attributs = 0; - m_Mirror = false; // display mirror if true - m_HJustify = GR_TEXT_HJUSTIFY_CENTER; // Default horizontal justification is centered. - m_VJustify = GR_TEXT_VJUSTIFY_CENTER; // Default vertical justification is centered. - m_Thickness = 0; // thickness - m_Italic = false; // true = italic shape. - m_Bold = false; - m_MultilineAllowed = false; // Set to true for multiline text. - m_Text = text; -} - - -EDA_TEXT::EDA_TEXT( const EDA_TEXT& aText ) -{ - m_Pos = aText.m_Pos; - m_Size = aText.m_Size; - m_Orient = aText.m_Orient; - m_Attributs = aText.m_Attributs; - m_Mirror = aText.m_Mirror; - m_HJustify = aText.m_HJustify; - m_VJustify = aText.m_VJustify; - m_Thickness = aText.m_Thickness; - m_Italic = aText.m_Italic; - m_Bold = aText.m_Bold; - m_MultilineAllowed = aText.m_MultilineAllowed; - m_Text = aText.m_Text; -} - - -EDA_TEXT::~EDA_TEXT() -{ -} - - -int EDA_TEXT::LenSize( const wxString& aLine ) const -{ - return ReturnGraphicTextWidth( aLine, m_Size.x, m_Italic, m_Bold ); -} - - -EDA_RECT EDA_TEXT::GetTextBox( int aLine, int aThickness, bool aInvertY ) const -{ - EDA_RECT rect; - wxPoint pos; - wxArrayString* list = NULL; - wxString text = m_Text; - int thickness = ( aThickness < 0 ) ? m_Thickness : aThickness; - - if( m_MultilineAllowed ) - { - list = wxStringSplit( m_Text, '\n' ); - - if ( list->GetCount() ) // GetCount() == 0 for void strings - { - if( aLine >= 0 && (aLine < (int)list->GetCount()) ) - text = list->Item( aLine ); - else - text = list->Item( 0 ); - } - } - - // calculate the H and V size - int dx = LenSize( text ); - int dy = GetInterline(); - - /* Creates bounding box (rectangle) for an horizontal text */ - wxSize textsize = wxSize( dx, dy ); - - if( aInvertY ) - rect.SetOrigin( m_Pos.x, -m_Pos.y ); - else - rect.SetOrigin( m_Pos ); - - // extra dy interval for letters like j and y and ] - int extra_dy = dy - m_Size.y; - rect.Move( wxPoint( 0, -extra_dy / 2 ) ); // move origin by the half extra interval - - // for multiline texts and aLine < 0, merge all rectangles - if( m_MultilineAllowed && list && aLine < 0 ) - { - for( unsigned ii = 1; ii < list->GetCount(); ii++ ) - { - text = list->Item( ii ); - dx = LenSize( text ); - textsize.x = MAX( textsize.x, dx ); - textsize.y += dy; - } - } - - delete list; - - rect.SetSize( textsize ); - - /* Now, calculate the rect origin, according to text justification - * At this point the rectangle origin is the text origin (m_Pos). - * This is true only for left and top text justified texts (using top to bottom Y axis - * orientation). and must be recalculated for others justifications - * also, note the V justification is relative to the first line - */ - switch( m_HJustify ) - { - case GR_TEXT_HJUSTIFY_LEFT: - if( m_Mirror ) - rect.SetX( rect.GetX() - rect.GetWidth() ); - break; - - case GR_TEXT_HJUSTIFY_CENTER: - rect.SetX( rect.GetX() - (rect.GetWidth() / 2) ); - break; - - case GR_TEXT_HJUSTIFY_RIGHT: - if( !m_Mirror ) - rect.SetX( rect.GetX() - rect.GetWidth() ); - break; - } - - dy = m_Size.y + thickness; - - switch( m_VJustify ) - { - case GR_TEXT_VJUSTIFY_TOP: - break; - - case GR_TEXT_VJUSTIFY_CENTER: - rect.SetY( rect.GetY() - (dy / 2) ); - break; - - case GR_TEXT_VJUSTIFY_BOTTOM: - rect.SetY( rect.GetY() - dy ); - break; - } - - rect.Inflate( thickness / 2 ); - rect.Normalize(); // Make h and v sizes always >= 0 - - return rect; -} - - -bool EDA_TEXT::TextHitTest( const wxPoint& aPoint, int aAccuracy ) const -{ - EDA_RECT rect = GetTextBox( -1 ); // Get the full text area. - wxPoint location = aPoint; - - rect.Inflate( aAccuracy ); - RotatePoint( &location, m_Pos, -m_Orient ); - - return rect.Contains( location ); -} - - -bool EDA_TEXT::TextHitTest( const EDA_RECT& aRect, bool aContains, int aAccuracy ) const -{ - EDA_RECT rect = aRect; - - rect.Inflate( aAccuracy ); - - if( aContains ) - return rect.Contains( GetTextBox( -1 ) ); - - return rect.Intersects( GetTextBox( -1 ) ); -} - - -void EDA_TEXT::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aOffset, - EDA_COLOR_T aColor, int aDrawMode, - EDA_DRAW_MODE_T aFillMode, EDA_COLOR_T aAnchor_color ) -{ - if( m_MultilineAllowed ) - { - wxPoint pos = m_Pos; - wxArrayString* list = wxStringSplit( m_Text, '\n' ); - wxPoint offset; - - offset.y = GetInterline(); - - RotatePoint( &offset, m_Orient ); - - for( unsigned i = 0; iCount(); i++ ) - { - wxString txt = list->Item( i ); - DrawOneLineOfText( aPanel, - aDC, - aOffset, - aColor, - aDrawMode, - aFillMode, - i ? UNSPECIFIED : aAnchor_color, - txt, - pos ); - pos += offset; - } - - delete (list); - } - else - DrawOneLineOfText( aPanel, - aDC, - aOffset, - aColor, - aDrawMode, - aFillMode, - aAnchor_color, - m_Text, - m_Pos ); -} - - -void EDA_TEXT::DrawOneLineOfText( EDA_DRAW_PANEL* aPanel, wxDC* aDC, - const wxPoint& aOffset, EDA_COLOR_T aColor, - int aDrawMode, EDA_DRAW_MODE_T aFillMode, - EDA_COLOR_T aAnchor_color, - wxString& aText, wxPoint aPos ) -{ - int width = m_Thickness; - - if( aFillMode == LINE ) - width = 0; - - if( aDrawMode != -1 ) - GRSetDrawMode( aDC, aDrawMode ); - - /* Draw text anchor, if allowed */ - if( aAnchor_color != UNSPECIFIED ) - { - - int anchor_size = aDC->DeviceToLogicalXRel( 2 ); - - aAnchor_color = (EDA_COLOR_T) ( aAnchor_color & MASKCOLOR ); - - int cX = aPos.x + aOffset.x; - int cY = aPos.y + aOffset.y; - - GRLine( aPanel->GetClipBox(), aDC, cX - anchor_size, cY, - cX + anchor_size, cY, 0, aAnchor_color ); - - GRLine( aPanel->GetClipBox(), aDC, cX, cY - anchor_size, - cX, cY + anchor_size, 0, aAnchor_color ); - } - - if( aFillMode == SKETCH ) - width = -width; - - wxSize size = m_Size; - - if( m_Mirror ) - size.x = -size.x; - - DrawGraphicText( aPanel, aDC, aOffset + aPos, aColor, aText, m_Orient, size, - m_HJustify, m_VJustify, width, m_Italic, m_Bold ); -} - - -wxString EDA_TEXT::GetTextStyleName() -{ - int style = 0; - - if( m_Italic ) - style = 1; - - if( m_Bold ) - style += 2; - - wxString stylemsg[4] = { - _("Normal"), - _("Italic"), - _("Bold"), - _("Bold+Italic") - }; - - return stylemsg[style]; -} - - -bool EDA_TEXT::IsDefaultFormatting() const -{ - return ( ( m_Size.x == DEFAULT_SIZE_TEXT ) - && ( m_Size.y == DEFAULT_SIZE_TEXT ) - && ( m_Attributs == 0 ) - && ( m_Mirror == false ) - && ( m_HJustify == GR_TEXT_HJUSTIFY_CENTER ) - && ( m_VJustify == GR_TEXT_VJUSTIFY_CENTER ) - && ( m_Thickness == 0 ) - && ( m_Italic == false ) - && ( m_Bold == false ) - && ( m_MultilineAllowed == false ) ); -} - - -void EDA_TEXT::Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const - throw( IO_ERROR ) -{ - if( !IsDefaultFormatting() ) - { - aFormatter->Print( aNestLevel+1, "(effects\n" ); - - if( ( m_Size.x != DEFAULT_SIZE_TEXT ) || ( m_Size.y != DEFAULT_SIZE_TEXT ) || m_Bold - || m_Italic ) - { - aFormatter->Print( aNestLevel+2, "(font" ); - - // Add font support here at some point in the future. - - if( ( m_Size.x != DEFAULT_SIZE_TEXT ) || ( m_Size.y != DEFAULT_SIZE_TEXT ) ) - aFormatter->Print( 0, " (size %s)", FMT_IU( m_Size ).c_str() ); - - if( m_Bold ) - aFormatter->Print( 0, " bold" ); - - if( m_Bold ) - aFormatter->Print( 0, " italic" ); - - aFormatter->Print( 0, ")\n"); - } - - if( m_Mirror || ( m_HJustify != GR_TEXT_HJUSTIFY_CENTER ) - || ( m_VJustify != GR_TEXT_VJUSTIFY_CENTER ) ) - { - aFormatter->Print( aNestLevel+2, "(justify"); - - if( m_HJustify != GR_TEXT_HJUSTIFY_CENTER ) - aFormatter->Print( 0, (m_HJustify == GR_TEXT_HJUSTIFY_LEFT) ? " left" : " right" ); - - if( m_VJustify != GR_TEXT_VJUSTIFY_CENTER ) - aFormatter->Print( 0, (m_VJustify == GR_TEXT_VJUSTIFY_TOP) ? " top" : " bottom" ); - - if( m_Mirror ) - aFormatter->Print( 0, " mirror" ); - - aFormatter->Print( 0, ")\n" ); - } - - // As of now the only place this is used is in Eeschema to hide or show the text. - if( m_Attributs ) - aFormatter->Print( aNestLevel+2, "hide\n" ); - - aFormatter->Print( aNestLevel+1, ")\n" ); - } -} +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2004 Jean-Pierre Charras, jean-pierre.charras@gipsa-lab.inpg.com + * Copyright (C) 2004-2011 KiCad Developers, see change_log.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 eda_text.cpp + * @brief Implementation of base KiCad text object. + */ + +#include +#include +#include // MAX +#include // RotatePoint +#include // EDA_DRAW_PANEL + + +// Conversion to application internal units defined at build time. +#if defined( PCBNEW ) +#include +#define MILS_TO_IU( x ) ( x * IU_PER_MILS ); +#elif defined( EESCHEMA ) +#include +#define MILS_TO_IU( x ) ( x ) +#else +#error "Cannot resolve units formatting due to no definition of EESCHEMA or PCBNEW." +#endif + + +EDA_TEXT::EDA_TEXT( const wxString& text ) +{ + m_Size.x = m_Size.y = MILS_TO_IU( DEFAULT_SIZE_TEXT ); // Width and height of font. + m_Orient = 0; // Rotation angle in 0.1 degrees. + m_Attributs = 0; + m_Mirror = false; // display mirror if true + m_HJustify = GR_TEXT_HJUSTIFY_CENTER; // Default horizontal justification is centered. + m_VJustify = GR_TEXT_VJUSTIFY_CENTER; // Default vertical justification is centered. + m_Thickness = 0; // thickness + m_Italic = false; // true = italic shape. + m_Bold = false; + m_MultilineAllowed = false; // Set to true for multiline text. + m_Text = text; +} + + +EDA_TEXT::EDA_TEXT( const EDA_TEXT& aText ) +{ + m_Pos = aText.m_Pos; + m_Size = aText.m_Size; + m_Orient = aText.m_Orient; + m_Attributs = aText.m_Attributs; + m_Mirror = aText.m_Mirror; + m_HJustify = aText.m_HJustify; + m_VJustify = aText.m_VJustify; + m_Thickness = aText.m_Thickness; + m_Italic = aText.m_Italic; + m_Bold = aText.m_Bold; + m_MultilineAllowed = aText.m_MultilineAllowed; + m_Text = aText.m_Text; +} + + +EDA_TEXT::~EDA_TEXT() +{ +} + + +int EDA_TEXT::LenSize( const wxString& aLine ) const +{ + return ReturnGraphicTextWidth( aLine, m_Size.x, m_Italic, m_Bold ); +} + + +EDA_RECT EDA_TEXT::GetTextBox( int aLine, int aThickness, bool aInvertY ) const +{ + EDA_RECT rect; + wxPoint pos; + wxArrayString* list = NULL; + wxString text = m_Text; + int thickness = ( aThickness < 0 ) ? m_Thickness : aThickness; + + if( m_MultilineAllowed ) + { + list = wxStringSplit( m_Text, '\n' ); + + if ( list->GetCount() ) // GetCount() == 0 for void strings + { + if( aLine >= 0 && (aLine < (int)list->GetCount()) ) + text = list->Item( aLine ); + else + text = list->Item( 0 ); + } + } + + // calculate the H and V size + int dx = LenSize( text ); + int dy = GetInterline(); + + /* Creates bounding box (rectangle) for an horizontal text */ + wxSize textsize = wxSize( dx, dy ); + + if( aInvertY ) + rect.SetOrigin( m_Pos.x, -m_Pos.y ); + else + rect.SetOrigin( m_Pos ); + + // extra dy interval for letters like j and y and ] + int extra_dy = dy - m_Size.y; + rect.Move( wxPoint( 0, -extra_dy / 2 ) ); // move origin by the half extra interval + + // for multiline texts and aLine < 0, merge all rectangles + if( m_MultilineAllowed && list && aLine < 0 ) + { + for( unsigned ii = 1; ii < list->GetCount(); ii++ ) + { + text = list->Item( ii ); + dx = LenSize( text ); + textsize.x = MAX( textsize.x, dx ); + textsize.y += dy; + } + } + + delete list; + + rect.SetSize( textsize ); + + /* Now, calculate the rect origin, according to text justification + * At this point the rectangle origin is the text origin (m_Pos). + * This is true only for left and top text justified texts (using top to bottom Y axis + * orientation). and must be recalculated for others justifications + * also, note the V justification is relative to the first line + */ + switch( m_HJustify ) + { + case GR_TEXT_HJUSTIFY_LEFT: + if( m_Mirror ) + rect.SetX( rect.GetX() - rect.GetWidth() ); + break; + + case GR_TEXT_HJUSTIFY_CENTER: + rect.SetX( rect.GetX() - (rect.GetWidth() / 2) ); + break; + + case GR_TEXT_HJUSTIFY_RIGHT: + if( !m_Mirror ) + rect.SetX( rect.GetX() - rect.GetWidth() ); + break; + } + + dy = m_Size.y + thickness; + + switch( m_VJustify ) + { + case GR_TEXT_VJUSTIFY_TOP: + break; + + case GR_TEXT_VJUSTIFY_CENTER: + rect.SetY( rect.GetY() - (dy / 2) ); + break; + + case GR_TEXT_VJUSTIFY_BOTTOM: + rect.SetY( rect.GetY() - dy ); + break; + } + + rect.Inflate( thickness / 2 ); + rect.Normalize(); // Make h and v sizes always >= 0 + + return rect; +} + + +bool EDA_TEXT::TextHitTest( const wxPoint& aPoint, int aAccuracy ) const +{ + EDA_RECT rect = GetTextBox( -1 ); // Get the full text area. + wxPoint location = aPoint; + + rect.Inflate( aAccuracy ); + RotatePoint( &location, m_Pos, -m_Orient ); + + return rect.Contains( location ); +} + + +bool EDA_TEXT::TextHitTest( const EDA_RECT& aRect, bool aContains, int aAccuracy ) const +{ + EDA_RECT rect = aRect; + + rect.Inflate( aAccuracy ); + + if( aContains ) + return rect.Contains( GetTextBox( -1 ) ); + + return rect.Intersects( GetTextBox( -1 ) ); +} + + +void EDA_TEXT::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aOffset, + EDA_COLOR_T aColor, int aDrawMode, + EDA_DRAW_MODE_T aFillMode, EDA_COLOR_T aAnchor_color ) +{ + if( m_MultilineAllowed ) + { + wxPoint pos = m_Pos; + wxArrayString* list = wxStringSplit( m_Text, '\n' ); + wxPoint offset; + + offset.y = GetInterline(); + + RotatePoint( &offset, m_Orient ); + + for( unsigned i = 0; iCount(); i++ ) + { + wxString txt = list->Item( i ); + DrawOneLineOfText( aPanel, + aDC, + aOffset, + aColor, + aDrawMode, + aFillMode, + i ? UNSPECIFIED : aAnchor_color, + txt, + pos ); + pos += offset; + } + + delete (list); + } + else + DrawOneLineOfText( aPanel, + aDC, + aOffset, + aColor, + aDrawMode, + aFillMode, + aAnchor_color, + m_Text, + m_Pos ); +} + + +void EDA_TEXT::DrawOneLineOfText( EDA_DRAW_PANEL* aPanel, wxDC* aDC, + const wxPoint& aOffset, EDA_COLOR_T aColor, + int aDrawMode, EDA_DRAW_MODE_T aFillMode, + EDA_COLOR_T aAnchor_color, + wxString& aText, wxPoint aPos ) +{ + int width = m_Thickness; + + if( aFillMode == LINE ) + width = 0; + + if( aDrawMode != -1 ) + GRSetDrawMode( aDC, aDrawMode ); + + /* Draw text anchor, if allowed */ + if( aAnchor_color != UNSPECIFIED ) + { + + int anchor_size = aDC->DeviceToLogicalXRel( 2 ); + + aAnchor_color = (EDA_COLOR_T) ( aAnchor_color & MASKCOLOR ); + + int cX = aPos.x + aOffset.x; + int cY = aPos.y + aOffset.y; + + GRLine( aPanel->GetClipBox(), aDC, cX - anchor_size, cY, + cX + anchor_size, cY, 0, aAnchor_color ); + + GRLine( aPanel->GetClipBox(), aDC, cX, cY - anchor_size, + cX, cY + anchor_size, 0, aAnchor_color ); + } + + if( aFillMode == SKETCH ) + width = -width; + + wxSize size = m_Size; + + if( m_Mirror ) + size.x = -size.x; + + DrawGraphicText( aPanel, aDC, aOffset + aPos, aColor, aText, m_Orient, size, + m_HJustify, m_VJustify, width, m_Italic, m_Bold ); +} + + +wxString EDA_TEXT::GetTextStyleName() +{ + int style = 0; + + if( m_Italic ) + style = 1; + + if( m_Bold ) + style += 2; + + wxString stylemsg[4] = { + _("Normal"), + _("Italic"), + _("Bold"), + _("Bold+Italic") + }; + + return stylemsg[style]; +} + + +bool EDA_TEXT::IsDefaultFormatting() const +{ + return ( ( m_Size.x == DEFAULT_SIZE_TEXT ) + && ( m_Size.y == DEFAULT_SIZE_TEXT ) + && ( m_Attributs == 0 ) + && ( m_Mirror == false ) + && ( m_HJustify == GR_TEXT_HJUSTIFY_CENTER ) + && ( m_VJustify == GR_TEXT_VJUSTIFY_CENTER ) + && ( m_Thickness == 0 ) + && ( m_Italic == false ) + && ( m_Bold == false ) + && ( m_MultilineAllowed == false ) ); +} + + +void EDA_TEXT::Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const + throw( IO_ERROR ) +{ + if( !IsDefaultFormatting() ) + { + aFormatter->Print( aNestLevel+1, "(effects\n" ); + + if( ( m_Size.x != DEFAULT_SIZE_TEXT ) || ( m_Size.y != DEFAULT_SIZE_TEXT ) || m_Bold + || m_Italic ) + { + aFormatter->Print( aNestLevel+2, "(font" ); + + // Add font support here at some point in the future. + + if( ( m_Size.x != DEFAULT_SIZE_TEXT ) || ( m_Size.y != DEFAULT_SIZE_TEXT ) ) + aFormatter->Print( 0, " (size %s %s)", FMT_IU( m_Size.GetHeight() ).c_str(), + FMT_IU( m_Size.GetWidth() ).c_str() ); + + if( m_Thickness != 0 ) + aFormatter->Print( 0, " (thickness %s)", FMT_IU( GetThickness() ).c_str() ); + + if( m_Bold ) + aFormatter->Print( 0, " bold" ); + + if( IsItalic() ) + aFormatter->Print( 0, " italic" ); + + aFormatter->Print( 0, ")\n"); + } + + if( m_Mirror || ( m_HJustify != GR_TEXT_HJUSTIFY_CENTER ) + || ( m_VJustify != GR_TEXT_VJUSTIFY_CENTER ) ) + { + aFormatter->Print( aNestLevel+2, "(justify"); + + if( m_HJustify != GR_TEXT_HJUSTIFY_CENTER ) + aFormatter->Print( 0, (m_HJustify == GR_TEXT_HJUSTIFY_LEFT) ? " left" : " right" ); + + if( m_VJustify != GR_TEXT_VJUSTIFY_CENTER ) + aFormatter->Print( 0, (m_VJustify == GR_TEXT_VJUSTIFY_TOP) ? " top" : " bottom" ); + + if( m_Mirror ) + aFormatter->Print( 0, " mirror" ); + + aFormatter->Print( 0, ")\n" ); + } + + // As of now the only place this is used is in Eeschema to hide or show the text. + if( m_Attributs ) + aFormatter->Print( aNestLevel+2, "hide\n" ); + + aFormatter->Print( aNestLevel+1, ")\n" ); + } +} diff --git a/common/pcb.keywords b/common/pcb.keywords new file mode 100644 index 0000000000..ec20b0b7ae --- /dev/null +++ b/common/pcb.keywords @@ -0,0 +1,196 @@ +# +# This program source code file is part of KiCad, a free EDA CAD application. +# +# Copyright (C) 2012 CERN. +# +# 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 +# + +# These are the keywords for the Pcbnew s-expression file format. + +add_net +angle +arc +arc_segments +area +arrow1a +arrow1b +arrow2a +arrow2b +at +attr +autoplace_cost90 +autoplace_cost180 +aux_axis_origin +blind +bold +bottom +center +chamfer +circle +clearance +comment +company +connect +connect_pads +crossbar +date +descr +die_length +dimension +drawings +drill +edge +edge_width +effects +end +feature1 +feature2 +fill +fill_segments +filled_polygon +fillet +font +fp_arc +fp_circle +fp_curve +fp_line +fp_poly +fp_text +full +general +gr_arc +gr_circle +gr_curve +gr_line +gr_poly +gr_text +hatch +hide +italic +justify +kicad_pcb +last_trace_width +layer +layers +left +links +locked +micro +min_thickness +mirror +mod_edge_width +mod_text_size +mod_text_width +mode +model +module +net +net_class +net_name +nets +no +no_connects +none +np_thru_hole +offset +oval +pad +pad_drill +pad_size +pad_to_mask_clearance +pad_to_paste_clearance +pad_to_paste_clearance_ratio +page +path +pcb_text_size +pcb_text_width +pcbplotparams +placed +plus +polygon +portrait +priority +pts +radius +rev +rect +rect_delta +reference +right +rotate +scale +segment +segment_width +setup +size +smd +smoothing +solder_mask_margin +solder_paste_margin +solder_paste_margin_ratio +solder_paste_ratio +start +status +tags +target +title +title_block +tedit +thermal_width +thermal_gap +thermal_bridge_width +thickness +top +trace_width +tracks +trace_min +trace_clearance +trapezoid +thru +thru_hole +tstamp +user +user_trace_width +user_via +uvia_dia +uvia_drill +uvia_min_drill +uvia_min_size +uvia_size +uvias_allowed +value +version +via +via_dia +via_drill +via_min_drill +via_min_size +via_size +virtual +visible_elements +width +x +xy +xyz +yes +zone +zone_45_only +zone_clearance +zone_connect +zones diff --git a/common/worksheet.cpp b/common/worksheet.cpp index 6d44ef801c..356bbb6740 100644 --- a/common/worksheet.cpp +++ b/common/worksheet.cpp @@ -1673,28 +1673,36 @@ void TITLE_BLOCK::Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aCont aFormatter->Print( aNestLevel, "(title_block\n" ); if( !m_title.IsEmpty() ) - aFormatter->Print( aNestLevel+1, "(title %s)\n", EscapedUTF8( m_title ).c_str() ); + aFormatter->Print( aNestLevel+1, "(title %s)\n", + aFormatter->Quotew( m_title ).c_str() ); if( !m_date.IsEmpty() ) - aFormatter->Print( aNestLevel+1, "(date %s)\n", EscapedUTF8( m_date ).c_str() ); + aFormatter->Print( aNestLevel+1, "(date %s)\n", + aFormatter->Quotew( m_date ).c_str() ); if( !m_revision.IsEmpty() ) - aFormatter->Print( aNestLevel+1, "(rev %s)\n", EscapedUTF8( m_revision ).c_str() ); + aFormatter->Print( aNestLevel+1, "(rev %s)\n", + aFormatter->Quotew( m_revision ).c_str() ); if( !m_company.IsEmpty() ) - aFormatter->Print( aNestLevel+1, "(company %s)\n", EscapedUTF8( m_company ).c_str() ); + aFormatter->Print( aNestLevel+1, "(company %s)\n", + aFormatter->Quotew( m_company ).c_str() ); if( !m_comment1.IsEmpty() ) - aFormatter->Print( aNestLevel+1, "(comment1 %s)\n", EscapedUTF8( m_comment1 ).c_str() ); + aFormatter->Print( aNestLevel+1, "(comment 1 %s)\n", + aFormatter->Quotew( m_comment1 ).c_str() ); if( !m_comment2.IsEmpty() ) - aFormatter->Print( aNestLevel+1, "(comment2 %s)\n", EscapedUTF8( m_comment2 ).c_str() ); + aFormatter->Print( aNestLevel+1, "(comment 2 %s)\n", + aFormatter->Quotew( m_comment2 ).c_str() ); if( !m_comment3.IsEmpty() ) - aFormatter->Print( aNestLevel+1, "(comment3 %s)\n", EscapedUTF8( m_comment3 ).c_str() ); + aFormatter->Print( aNestLevel+1, "(comment 3 %s)\n", + aFormatter->Quotew( m_comment3 ).c_str() ); if( !m_comment4.IsEmpty() ) - aFormatter->Print( aNestLevel+1, "(comment4 %s)\n", EscapedUTF8( m_comment4 ).c_str() ); + aFormatter->Print( aNestLevel+1, "(comment 4 %s)\n", + aFormatter->Quotew( m_comment4 ).c_str() ); aFormatter->Print( aNestLevel, ")\n\n" ); } diff --git a/eeschema/bus-wire-junction.cpp b/eeschema/bus-wire-junction.cpp index ce1de8d5b4..8f642869e6 100644 --- a/eeschema/bus-wire-junction.cpp +++ b/eeschema/bus-wire-junction.cpp @@ -255,14 +255,7 @@ void SCH_EDIT_FRAME::EndSegment( wxDC* DC ) screen->SetCurItem( NULL ); m_canvas->EndMouseCapture( -1, -1, wxEmptyString, false ); - DLIST< SCH_ITEM > tmp; - - for( item = s_wires.begin(); item != NULL; item = item->Next() ) - tmp.PushBack( (SCH_ITEM*) item->Clone() ); - - // Temporarily add the new segments to the schematic item list to test if any - // junctions are required. - screen->Append( tmp ); + screen->Append( s_wires ); // Correct and remove segments that need merged. screen->SchematicCleanUp( NULL, DC ); @@ -271,27 +264,15 @@ void SCH_EDIT_FRAME::EndSegment( wxDC* DC ) // removed by a cleanup, a junction may be needed to connect the segment's end point // which is also the same as the previous segment's start point. if( screen->IsJunctionNeeded( segment->GetEndPoint() ) ) - s_wires.Append( AddJunction( DC, segment->GetEndPoint() ) ); + screen->Append( AddJunction( DC, segment->GetEndPoint() ) ); else if( screen->IsJunctionNeeded( segment->GetStartPoint() ) ) - s_wires.Append( AddJunction( DC, segment->GetStartPoint() ) ); + screen->Append( AddJunction( DC, segment->GetStartPoint() ) ); // Automatically place a junction on the start point if necessary because the cleanup // can suppress intermediate points by merging wire segments. if( screen->IsJunctionNeeded( s_startPoint ) ) - s_wires.Append( AddJunction( DC, s_startPoint ) ); + screen->Append( AddJunction( DC, s_startPoint ) ); - // Make a copy of the original wires, buses, and junctions. - for( item = s_oldWires.begin(); item != NULL; item = item->Next() ) - tmp.PushBack( (SCH_ITEM*) item->Clone() ); - - // Restore the old wires. - if( tmp.GetCount() != 0 ) - screen->ReplaceWires( tmp ); - - // Now add the new wires and any required junctions to the schematic item list. - screen->Append( s_wires ); - - screen->SchematicCleanUp( NULL, DC ); m_canvas->Refresh(); // Put the snap shot of the previous wire, buses, and junctions in the undo/redo list. diff --git a/eeschema/class_libentry.cpp b/eeschema/class_libentry.cpp index abe6917bdb..27d014277e 100644 --- a/eeschema/class_libentry.cpp +++ b/eeschema/class_libentry.cpp @@ -300,7 +300,7 @@ void LIB_COMPONENT::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDc, const wxPoint& aOff if( drawItem.m_Flags & IS_MOVED ) continue; - /* Do not draw items not attached to the current part */ + // Do not draw items not attached to the current part if( aMulti && drawItem.m_Unit && ( drawItem.m_Unit != aMulti ) ) continue; @@ -330,7 +330,7 @@ void LIB_COMPONENT::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDc, const wxPoint& aOff if( drawItem.m_Flags & IS_MOVED ) continue; - /* Do not draw items not attached to the current part */ + // Do not draw items not attached to the current part if( aMulti && drawItem.m_Unit && ( drawItem.m_Unit != aMulti ) ) continue; @@ -358,7 +358,7 @@ void LIB_COMPONENT::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDc, const wxPoint& aOff } - /* Enable this to draw the anchor of the component. */ + // Enable this to draw the anchor of the component. #if 0 int len = aDc->DeviceToLogicalXRel( 3 ); @@ -534,10 +534,10 @@ bool LIB_COMPONENT::Save( OUTPUTFORMATTER& aFormatter ) size_t i; LIB_FIELD& value = GetValueField(); - /* First line: it s a comment (component name for readers) */ + // First line: it s a comment (component name for readers) aFormatter.Print( 0, "#\n# %s\n#\n", TO_UTF8( value.m_Text ) ); - /* Save data */ + // Save data aFormatter.Print( 0, "DEF" ); if( value.IsVisible() ) @@ -618,7 +618,7 @@ bool LIB_COMPONENT::Save( OUTPUTFORMATTER& aFormatter ) aFormatter.Print( 0, "\n" ); } - /* Write the footprint filter list */ + // Write the footprint filter list if( m_FootprintList.GetCount() != 0 ) { aFormatter.Print( 0, "$FPLIST\n" ); @@ -631,7 +631,7 @@ bool LIB_COMPONENT::Save( OUTPUTFORMATTER& aFormatter ) aFormatter.Print( 0, "$ENDFPLIST\n" ); } - /* Save graphics items (including pins) */ + // Save graphics items (including pins) if( !drawings.empty() ) { /* we sort the draw items, in order to have an edition more easy, @@ -680,21 +680,21 @@ bool LIB_COMPONENT::Load( LINE_READER& aLineReader, wxString& aErrorMsg ) return false; } - /* Read DEF line: */ + // Read DEF line: char drawnum = 0; char drawname = 0; - if( ( componentName = strtok( NULL, " \t\n" ) ) == NULL /* Part name: */ - || ( prefix = strtok( NULL, " \t\n" ) ) == NULL /* Prefix name: */ - || ( p = strtok( NULL, " \t\n" ) ) == NULL /* NumOfPins: */ + if( ( componentName = strtok( NULL, " \t\n" ) ) == NULL // Part name: + || ( prefix = strtok( NULL, " \t\n" ) ) == NULL // Prefix name: + || ( p = strtok( NULL, " \t\n" ) ) == NULL // NumOfPins: || sscanf( p, "%d", &unused ) != 1 - || ( p = strtok( NULL, " \t\n" ) ) == NULL /* TextInside: */ + || ( p = strtok( NULL, " \t\n" ) ) == NULL // TextInside: || sscanf( p, "%d", &m_pinNameOffset ) != 1 - || ( p = strtok( NULL, " \t\n" ) ) == NULL /* DrawNums: */ + || ( p = strtok( NULL, " \t\n" ) ) == NULL // DrawNums: || sscanf( p, "%c", &drawnum ) != 1 - || ( p = strtok( NULL, " \t\n" ) ) == NULL /* DrawNums: */ + || ( p = strtok( NULL, " \t\n" ) ) == NULL // DrawNums: || sscanf( p, "%c", &drawname ) != 1 - || ( p = strtok( NULL, " \t\n" ) ) == NULL /* m_unitCount: */ + || ( p = strtok( NULL, " \t\n" ) ) == NULL // m_unitCount: || sscanf( p, "%d", &m_unitCount ) != 1 ) { aErrorMsg.Printf( wxT( "Wrong DEF format in line %d, skipped." ), @@ -720,7 +720,7 @@ bool LIB_COMPONENT::Load( LINE_READER& aLineReader, wxString& aErrorMsg ) m_showPinNumbers = ( drawnum == 'N' ) ? false : true; m_showPinNames = ( drawname == 'N' ) ? false : true; - /* Copy part name and prefix. */ + // Copy part name and prefix. LIB_FIELD& value = GetValueField(); if( componentName[0] != '~' ) @@ -763,7 +763,7 @@ bool LIB_COMPONENT::Load( LINE_READER& aLineReader, wxString& aErrorMsg ) p = strtok( line, " \t\r\n" ); - /* This is the error flag ( if an error occurs, Res = false) */ + // This is the error flag ( if an error occurs, Res = false) Res = true; if( *line == '#' ) // a comment @@ -785,7 +785,7 @@ bool LIB_COMPONENT::Load( LINE_READER& aLineReader, wxString& aErrorMsg ) else if( strncmp( p, "$FPLIST", 5 ) == 0 ) Res = LoadFootprints( aLineReader, Msg ); - /* End line or block analysis: test for an error */ + // End line or block analysis: test for an error if( !Res ) { if( Msg.IsEmpty() ) @@ -798,7 +798,7 @@ bool LIB_COMPONENT::Load( LINE_READER& aLineReader, wxString& aErrorMsg ) } } - /* If we are here, this part is O.k. - put it in: */ + // If we are here, this part is O.k. - put it in: drawings.sort(); return true; @@ -827,34 +827,37 @@ bool LIB_COMPONENT::LoadDrawEntries( LINE_READER& aLineReader, wxString& aErrorM switch( line[0] ) { - case 'A': /* Arc */ + case 'A': // Arc newEntry = ( LIB_ITEM* ) new LIB_ARC( this ); break; - case 'C': /* Circle */ + case 'C': // Circle newEntry = ( LIB_ITEM* ) new LIB_CIRCLE( this ); break; - case 'T': /* Text */ + case 'T': // Text newEntry = ( LIB_ITEM* ) new LIB_TEXT( this ); break; - case 'S': /* Square */ + case 'S': // Square newEntry = ( LIB_ITEM* ) new LIB_RECTANGLE( this ); break; - case 'X': /* Pin Description */ + case 'X': // Pin Description newEntry = ( LIB_ITEM* ) new LIB_PIN( this ); break; - case 'P': /* Polyline */ + case 'P': // Polyline newEntry = ( LIB_ITEM* ) new LIB_POLYLINE( this ); break; - case 'B': /* Bezier Curves */ + case 'B': // Bezier Curves newEntry = ( LIB_ITEM* ) new LIB_BEZIER( this ); break; + case '#': // Comment + continue; + default: aErrorMsg.Printf( wxT( "undefined DRAW command %c" ), line[0] ); return false; @@ -866,7 +869,7 @@ bool LIB_COMPONENT::LoadDrawEntries( LINE_READER& aLineReader, wxString& aErrorM GetChars( aErrorMsg ), line[0] ); SAFE_DELETE( newEntry ); - /* Flush till end of draw section */ + // Flush till end of draw section do { if( !aLineReader.ReadLine() ) @@ -1469,7 +1472,7 @@ void LIB_COMPONENT::SetConversion( bool aSetConvert ) { BOOST_FOREACH( LIB_ITEM& item, drawings ) { - /* Only pins are duplicated. */ + // Only pins are duplicated. if( item.Type() != LIB_PIN_T ) continue; @@ -1548,7 +1551,7 @@ void LIB_COMPONENT::SetAliases( const wxArrayString& aAliasList ) m_aliases.push_back( new LIB_ALIAS( aAliasList[ i ], this ) ); } - /* Remove names in the current component that are not in the new alias list. */ + // Remove names in the current component that are not in the new alias list. LIB_ALIASES::iterator it; for( it = m_aliases.begin(); it < m_aliases.end(); it++ ) diff --git a/eeschema/dialogs/dialog_plot_schematic_DXF.cpp b/eeschema/dialogs/dialog_plot_schematic_DXF.cpp index 5bc384974c..7427f23457 100644 --- a/eeschema/dialogs/dialog_plot_schematic_DXF.cpp +++ b/eeschema/dialogs/dialog_plot_schematic_DXF.cpp @@ -241,7 +241,7 @@ void DIALOG_PLOT_SCHEMATIC_DXF::PlotOneSheetDXF( const wxString& FileName, if( m_plot_Sheet_Ref ) { plotter->SetColor( BLACK ); - m_Parent->PlotWorkSheet( plotter, screen ); + m_Parent->PlotWorkSheet( plotter, screen, g_DrawDefaultLineThickness ); } screen->Plot( plotter ); diff --git a/eeschema/dialogs/dialog_plot_schematic_HPGL.cpp b/eeschema/dialogs/dialog_plot_schematic_HPGL.cpp index 7ce19b0212..69a22ee85e 100644 --- a/eeschema/dialogs/dialog_plot_schematic_HPGL.cpp +++ b/eeschema/dialogs/dialog_plot_schematic_HPGL.cpp @@ -395,7 +395,7 @@ void DIALOG_PLOT_SCHEMATIC_HPGL::Plot_1_Page_HPGL( const wxString& FileName, plotter->SetColor( BLACK ); if( s_plot_Sheet_Ref ) - m_Parent->PlotWorkSheet( plotter, screen ); + m_Parent->PlotWorkSheet( plotter, screen, g_DrawDefaultLineThickness ); screen->Plot( plotter ); diff --git a/eeschema/dialogs/dialog_plot_schematic_PDF.cpp b/eeschema/dialogs/dialog_plot_schematic_PDF.cpp index c33b7ed50f..1902fb323a 100644 --- a/eeschema/dialogs/dialog_plot_schematic_PDF.cpp +++ b/eeschema/dialogs/dialog_plot_schematic_PDF.cpp @@ -220,7 +220,7 @@ void DIALOG_PLOT_SCHEMATIC_PDF::createPDFFile() if( first_page ) { wxString msg; - wxString plotFileName = m_Parent->GetUniqueFilenameForCurrentSheet() + wxString plotFileName = m_Parent->GetUniqueFilenameForCurrentSheet() + wxT( ".pdf" ); msg.Printf( _( "Plot: %s " ), GetChars( plotFileName ) ); m_MsgBox->AppendText( msg ); @@ -241,8 +241,8 @@ void DIALOG_PLOT_SCHEMATIC_PDF::createPDFFile() plotSetupPage( plotter, screen ); plotter->StartPlot( output_file ); first_page = false; - } - else + } + else { /* For the following pages you need to close the (finished) page, reconfigure, and then start a new one */ @@ -301,7 +301,7 @@ void DIALOG_PLOT_SCHEMATIC_PDF::plotOneSheet( PDF_PLOTTER* plotter, if( m_plot_Sheet_Ref ) { plotter->SetColor( BLACK ); - m_Parent->PlotWorkSheet( plotter, screen ); + m_Parent->PlotWorkSheet( plotter, screen, g_DrawDefaultLineThickness ); } screen->Plot( plotter ); diff --git a/eeschema/dialogs/dialog_plot_schematic_PS.cpp b/eeschema/dialogs/dialog_plot_schematic_PS.cpp index 4fdce575e1..2b7034bf24 100644 --- a/eeschema/dialogs/dialog_plot_schematic_PS.cpp +++ b/eeschema/dialogs/dialog_plot_schematic_PS.cpp @@ -294,7 +294,7 @@ void DIALOG_PLOT_SCHEMATIC_PS::plotOneSheetPS( const wxString& FileName, if( m_plot_Sheet_Ref ) { plotter->SetColor( BLACK ); - m_Parent->PlotWorkSheet( plotter, screen ); + m_Parent->PlotWorkSheet( plotter, screen, g_DrawDefaultLineThickness ); } screen->Plot( plotter ); diff --git a/eeschema/general.h b/eeschema/general.h index 826bc4c80b..40a3ec4e4c 100644 --- a/eeschema/general.h +++ b/eeschema/general.h @@ -33,8 +33,6 @@ class TRANSFORM; #define HIGHLIGHT_COLOR WHITE -#define TEXT_NO_VISIBLE 1 - //#define GR_DEFAULT_DRAWMODE GR_COPY #define GR_DEFAULT_DRAWMODE GR_COPY diff --git a/eeschema/onleftclick.cpp b/eeschema/onleftclick.cpp index 2fc952c46e..1fcd2085b9 100644 --- a/eeschema/onleftclick.cpp +++ b/eeschema/onleftclick.cpp @@ -86,6 +86,7 @@ void SCH_EDIT_FRAME::OnLeftClick( wxDC* aDC, const wxPoint& aPosition ) wxFAIL_MSG( wxT( "SCH_EDIT_FRAME::OnLeftClick error. Item type <" ) + item->GetClass() + wxT( "> is already being edited." ) ); item->ClearFlags(); + break; } } else @@ -124,9 +125,12 @@ void SCH_EDIT_FRAME::OnLeftClick( wxDC* aDC, const wxPoint& aPosition ) case ID_NOCONN_BUTT: if( ( item == NULL ) || ( item->GetFlags() == 0 ) ) { - m_itemToRepeat = AddNoConnect( aDC, gridPosition ); - GetScreen()->SetCurItem( m_itemToRepeat ); - m_canvas->SetAutoPanRequest( true ); + if( false == GetScreen()->GetItem( gridPosition, 0, SCH_NO_CONNECT_T ) ) + { + m_itemToRepeat = AddNoConnect( aDC, gridPosition ); + GetScreen()->SetCurItem( m_itemToRepeat ); + m_canvas->SetAutoPanRequest( true ); + } } else { @@ -138,9 +142,12 @@ void SCH_EDIT_FRAME::OnLeftClick( wxDC* aDC, const wxPoint& aPosition ) case ID_JUNCTION_BUTT: if( ( item == NULL ) || ( item->GetFlags() == 0 ) ) { - m_itemToRepeat = AddJunction( aDC, gridPosition, true ); - GetScreen()->SetCurItem( m_itemToRepeat ); - m_canvas->SetAutoPanRequest( true ); + if( false == GetScreen()->GetItem( gridPosition, 0, SCH_JUNCTION_T ) ) + { + m_itemToRepeat = AddJunction( aDC, gridPosition, true ); + GetScreen()->SetCurItem( m_itemToRepeat ); + m_canvas->SetAutoPanRequest( true ); + } } else { diff --git a/eeschema/sch_screen.cpp b/eeschema/sch_screen.cpp index 70687437d7..4426612cfb 100644 --- a/eeschema/sch_screen.cpp +++ b/eeschema/sch_screen.cpp @@ -434,14 +434,14 @@ bool SCH_SCREEN::SchematicCleanUp( EDA_DRAW_PANEL* aCanvas, wxDC* aDC ) for( ; item != NULL; item = item->Next() ) { - if( item->Type() != SCH_LINE_T ) + if( ( item->Type() != SCH_LINE_T ) && ( item->Type() != SCH_JUNCTION_T ) ) continue; testItem = item->Next(); while( testItem ) { - if( testItem->Type() == SCH_LINE_T ) + if( ( item->Type() == SCH_LINE_T ) && ( testItem->Type() == SCH_LINE_T ) ) { SCH_LINE* line = (SCH_LINE*) item; @@ -458,6 +458,21 @@ bool SCH_SCREEN::SchematicCleanUp( EDA_DRAW_PANEL* aCanvas, wxDC* aDC ) testItem = testItem->Next(); } } + else if ( ( ( item->Type() == SCH_JUNCTION_T ) && ( testItem->Type() == SCH_JUNCTION_T ) ) && ( testItem != item ) ) + { + if ( testItem->HitTest( item->GetPosition() ) ) + { + // Keep the current flags, because the deleted segment can be flagged. + item->SetFlags( testItem->GetFlags() ); + DeleteItem( testItem ); + testItem = m_drawList.begin(); + modified = true; + } + else + { + testItem = testItem->Next(); + } + } else { testItem = testItem->Next(); diff --git a/gerbview/dialogs/dialog_select_one_pcb_layer.cpp b/gerbview/dialogs/dialog_select_one_pcb_layer.cpp index e34e07f4e5..14afd18e1a 100644 --- a/gerbview/dialogs/dialog_select_one_pcb_layer.cpp +++ b/gerbview/dialogs/dialog_select_one_pcb_layer.cpp @@ -185,42 +185,39 @@ const wxString GetPCBDefaultLayerName( int aLayerNumber ) { const wxChar* txt; - // These are only default layer names. For Pcbnew the copper names - // may be over-ridden in the BOARD (*.brd) file. - // Use a switch to explicitly show the mapping more clearly switch( aLayerNumber ) { - case LAYER_N_FRONT: txt = _( "Front" ); break; - case LAYER_N_2: txt = _( "Inner2" ); break; - case LAYER_N_3: txt = _( "Inner3" ); break; - case LAYER_N_4: txt = _( "Inner4" ); break; - case LAYER_N_5: txt = _( "Inner5" ); break; - case LAYER_N_6: txt = _( "Inner6" ); break; - case LAYER_N_7: txt = _( "Inner7" ); break; - case LAYER_N_8: txt = _( "Inner8" ); break; - case LAYER_N_9: txt = _( "Inner9" ); break; - case LAYER_N_10: txt = _( "Inner10" ); break; - case LAYER_N_11: txt = _( "Inner11" ); break; - case LAYER_N_12: txt = _( "Inner12" ); break; - case LAYER_N_13: txt = _( "Inner13" ); break; - case LAYER_N_14: txt = _( "Inner14" ); break; - case LAYER_N_15: txt = _( "Inner15" ); break; - case LAYER_N_BACK: txt = _( "Back" ); break; - case ADHESIVE_N_BACK: txt = _( "Adhes_Back" ); break; - case ADHESIVE_N_FRONT: txt = _( "Adhes_Front" ); break; - case SOLDERPASTE_N_BACK: txt = _( "SoldP_Back" ); break; - case SOLDERPASTE_N_FRONT: txt = _( "SoldP_Front" ); break; - case SILKSCREEN_N_BACK: txt = _( "SilkS_Back" ); break; - case SILKSCREEN_N_FRONT: txt = _( "SilkS_Front" ); break; - case SOLDERMASK_N_BACK: txt = _( "Mask_Back" ); break; - case SOLDERMASK_N_FRONT: txt = _( "Mask_Front" ); break; - case DRAW_N: txt = _( "Drawings" ); break; - case COMMENT_N: txt = _( "Comments" ); break; - case ECO1_N: txt = _( "Eco1" ); break; - case ECO2_N: txt = _( "Eco2" ); break; - case EDGE_N: txt = _( "PCB_Edges" ); break; - default: txt = _( "BAD INDEX" ); break; + case LAYER_N_FRONT: txt = _( "Front" ); break; + case LAYER_N_2: txt = _( "Inner1" ); break; + case LAYER_N_3: txt = _( "Inner2" ); break; + case LAYER_N_4: txt = _( "Inner3" ); break; + case LAYER_N_5: txt = _( "Inner4" ); break; + case LAYER_N_6: txt = _( "Inner5" ); break; + case LAYER_N_7: txt = _( "Inner6" ); break; + case LAYER_N_8: txt = _( "Inner7" ); break; + case LAYER_N_9: txt = _( "Inner8" ); break; + case LAYER_N_10: txt = _( "Inner9" ); break; + case LAYER_N_11: txt = _( "Inner10" ); break; + case LAYER_N_12: txt = _( "Inner11" ); break; + case LAYER_N_13: txt = _( "Inner12" ); break; + case LAYER_N_14: txt = _( "Inner13" ); break; + case LAYER_N_15: txt = _( "Inner14" ); break; + case LAYER_N_BACK: txt = _( "Back" ); break; + case ADHESIVE_N_BACK: txt = _( "Adhes_Back" ); break; + case ADHESIVE_N_FRONT: txt = _( "Adhes_Front" ); break; + case SOLDERPASTE_N_BACK: txt = _( "SoldP_Back" ); break; + case SOLDERPASTE_N_FRONT: txt = _( "SoldP_Front" ); break; + case SILKSCREEN_N_BACK: txt = _( "SilkS_Back" ); break; + case SILKSCREEN_N_FRONT: txt = _( "SilkS_Front" ); break; + case SOLDERMASK_N_BACK: txt = _( "Mask_Back" ); break; + case SOLDERMASK_N_FRONT: txt = _( "Mask_Front" ); break; + case DRAW_N: txt = _( "Drawings" ); break; + case COMMENT_N: txt = _( "Comments" ); break; + case ECO1_N: txt = _( "Eco1" ); break; + case ECO2_N: txt = _( "Eco2" ); break; + case EDGE_N: txt = _( "PCB_Edges" ); break; + default: txt = wxT( "BAD INDEX" ); break; } return wxString( txt ); diff --git a/include/bitmaps.h b/include/bitmaps.h index c27dec8456..54749693b3 100644 --- a/include/bitmaps.h +++ b/include/bitmaps.h @@ -109,7 +109,7 @@ EXTERN_BITMAP( cursor_shape_xpm ) EXTERN_BITMAP( cursor_xpm ) EXTERN_BITMAP( cut_button_xpm ) EXTERN_BITMAP( cvpcb_xpm ) -EXTERN_BITMAP( dashedline_xpm ) +EXTERN_BITMAP( dashline_xpm ) EXTERN_BITMAP( datasheet_xpm ) EXTERN_BITMAP( delete_arc_xpm ) EXTERN_BITMAP( delete_association_xpm ) @@ -253,7 +253,7 @@ EXTERN_BITMAP( leave_sheet_xpm ) EXTERN_BITMAP( left_xpm ) EXTERN_BITMAP( libedit_icon_xpm ) EXTERN_BITMAP( libedit_xpm ) -EXTERN_BITMAP( libedit_part_xpm ) +EXTERN_BITMAP( libedprt_xpm ) EXTERN_BITMAP( lib_next_xpm ) EXTERN_BITMAP( lib_previous_xpm ) EXTERN_BITMAP( library_browse_xpm ) @@ -271,7 +271,7 @@ EXTERN_BITMAP( mirror_h_xpm ) EXTERN_BITMAP( mirror_v_xpm ) EXTERN_BITMAP( mode_module_xpm ) EXTERN_BITMAP( mode_track_xpm ) -EXTERN_BITMAP( mod_ratsnest_xpm ) +EXTERN_BITMAP( modratsnest_xpm ) EXTERN_BITMAP( module_check_xpm ) EXTERN_BITMAP( module_edit_xpm ) EXTERN_BITMAP( module_wizard_xpm ) @@ -470,6 +470,7 @@ EXTERN_BITMAP( width_vias_xpm ) EXTERN_BITMAP( window_close_xpm ) EXTERN_BITMAP( zip_tool_xpm ) EXTERN_BITMAP( zip_xpm ) +EXTERN_BITMAP( zone_duplicate_xpm ) EXTERN_BITMAP( zone_unfill_xpm ) EXTERN_BITMAP( zoom_area_xpm ) EXTERN_BITMAP( zoom_center_on_screen_xpm ) diff --git a/include/class_board_design_settings.h b/include/class_board_design_settings.h index 53c3a40812..aad0e2b64b 100644 --- a/include/class_board_design_settings.h +++ b/include/class_board_design_settings.h @@ -37,7 +37,6 @@ public: int m_SolderPasteMargin; ///< Solder paste margin absolute value double m_SolderPasteMarginRatio; ///< Solder pask margin ratio value of pad size ///< The final margin is the sum of these 2 values - int m_BoardThickness; ///< Board Thickness for 3D viewer // Variables used in footprint handling wxSize m_ModuleTextSize; ///< Default footprint texts size @@ -188,11 +187,15 @@ public: */ void AppendConfigs( PARAM_CFG_ARRAY* aResult ); + int GetBoardThickness() const { return m_boardThickness; } + void SetBoardThickness( int aThickness ) { m_boardThickness = aThickness; } + private: int m_CopperLayerCount; ///< Number of copper layers for this design int m_EnabledLayers; ///< Bit-mask for layer enabling int m_VisibleLayers; ///< Bit-mask for layer visibility int m_VisibleElements; ///< Bit-mask for element category visibility + int m_boardThickness; ///< Board thickness for 3D viewer }; #endif // BOARD_DESIGN_SETTINGS_H_ diff --git a/include/convert_from_iu.h b/include/convert_from_iu.h new file mode 100644 index 0000000000..8e2b787d84 --- /dev/null +++ b/include/convert_from_iu.h @@ -0,0 +1,84 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 CERN + * + * 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 convert_from_iu.h + * @brief Definitions and functions to convert from internal units to user units + * depending upon the application and/or build options. + */ + + +#ifndef _CONVERT_FROM_IU_ +#define _CONVERT_FROM_IU_ + +#include // USE_PCBNEW_NANOMETRES is defined here + +/// Convert from internal units to user units. +#if defined(PCBNEW) || defined(CVPCB) || defined(GERBVIEW) + #if defined( USE_PCBNEW_NANOMETRES ) + #if defined(GERBVIEW) + #define MM_PER_IU 1.0 / 1e5 // Gerbview uses 10 micrometer. + #else + #define MM_PER_IU 1.0 / 1e6 // Pcbnew in nanometers. + #endif + #define MILS_PER_IU ( MM_PER_IU * 0.0254 ) + #define DECIMILS_PER_IU (MM_PER_IU * 0.00254 ) + #else // Pcbnew in deci-mils. + #define DECIMILS_PER_IU 1 + #define MILS_PER_IU 10.0 + #define MM_PER_IU (1e4 / 25.4) + #endif + +/// Convert PCBNEW internal units (iu) to mils. +inline int Iu2Mils( int iu ) +{ +#if defined( USE_PCBNEW_NANOMETRES ) + double x = iu * MILS_PER_IU; + return int( x < 0 ? x - 0.5 : x + 0.5 ); +#else + return iu * MILS_PER_IU; +#endif +} + +/// Convert PCBNEW internal units (iu) to deci-mils. +inline int Iu2DMils( int iu ) +{ +#if defined( USE_PCBNEW_NANOMETRES ) + double x = iu * DECIMILS_PER_IU; + return int( x < 0 ? x - 0.5 : x + 0.5 ); +#else + return iu; +#endif +} + +#else // Eeschema and anything else. +#define MILS_PER_IU 1.0 +#define MM_PER_IU (MILS_PER_IU / 0.0254) + +inline int Iu2Mils( int iu ) +{ + return iu; +} +#endif + +#endif // #define _CONVERT_FROM_IU_ diff --git a/include/eda_text.h b/include/eda_text.h index 529733bb3c..ad44c3e48e 100644 --- a/include/eda_text.h +++ b/include/eda_text.h @@ -57,7 +57,10 @@ enum EDA_DRAW_MODE_T { SKETCH // sketch mode: segments have thickness, but are not filled }; + #define DEFAULT_SIZE_TEXT 60 /* default text height (in mils or 1/1000") */ +#define TEXT_NO_VISIBLE 1 //< EDA_TEXT::m_Attribut(e?) visibility flag. + /** * Class EDA_TEXT @@ -110,6 +113,15 @@ public: void SetItalic( bool isItalic ) { m_Italic = isItalic; } bool IsItalic() const { return m_Italic; } + void SetBold( bool aBold ) { m_Bold = aBold; } + bool IsBold() const { return m_Bold; } + + void SetVisible( bool aVisible ) + { + ( aVisible ) ? m_Attributs &= ~TEXT_NO_VISIBLE : m_Attributs |= TEXT_NO_VISIBLE; + } + bool IsVisible() const { return !( m_Attributs & TEXT_NO_VISIBLE ); } + void SetMirrored( bool isMirrored ) { m_Mirror = isMirrored; } bool IsMirrored() const { return m_Mirror; } diff --git a/include/layers_id_colors_and_visibility.h b/include/layers_id_colors_and_visibility.h index ca35fcf0bd..6b7fd7ef38 100644 --- a/include/layers_id_colors_and_visibility.h +++ b/include/layers_id_colors_and_visibility.h @@ -7,6 +7,7 @@ #define _LAYERS_ID_AND_VISIBILITY_H_ /* Layer identification (layer number) */ +#define UNDEFINED_LAYER -1 #define FIRST_COPPER_LAYER 0 #define LAYER_N_BACK 0 #define LAYER_N_2 1 diff --git a/include/wxPcbStruct.h b/include/wxPcbStruct.h index 3cf5496d1e..99867a7a33 100644 --- a/include/wxPcbStruct.h +++ b/include/wxPcbStruct.h @@ -171,30 +171,12 @@ protected: virtual bool isAutoSaveRequired() const; /** - * Function propagate - * Used now only in autoplace calculations - * Uses the routing matrix to fill the cells within the zone - * Search and mark cells within the zone, and agree with DRC options. - * Requirements: - * Start from an initial point, to fill zone - * The zone must have no "copper island" - * Algorithm: - * If the current cell has a neighbor flagged as "cell in the zone", it - * become a cell in the zone - * The first point in the zone is the starting point - * 4 searches within the matrix are made: - * 1 - Left to right and top to bottom - * 2 - Right to left and top to bottom - * 3 - bottom to top and Right to left - * 4 - bottom to top and Left to right - * Given the current cell, for each search, we consider the 2 neighbor cells - * the previous cell on the same line and the previous cell on the same column. - * - * This function can request some iterations - * Iterations are made until no cell is added to the zone. - * @return: added cells count (i.e. which the attribute CELL_is_ZONE is set) + * Function duplicateZone + * duplicates the given zone. + * @param aDC is the current Device Context. + * @param aZone is the zone to duplicate */ - int propagate(); + void duplicateZone( wxDC* aDC, ZONE_CONTAINER* aZone ); public: PCB_LAYER_BOX_SELECTOR* m_SelLayerBox; // a combo box to display and select active layer @@ -1452,7 +1434,7 @@ public: * The cost is the longest ratsnest distance with penalty for connections * approaching 45 degrees. */ - float Compute_Ratsnest_PlaceModule( wxDC* DC ); + double Compute_Ratsnest_PlaceModule( wxDC* DC ); /** * Function GenPlaceBoard diff --git a/include/wxstruct.h b/include/wxstruct.h index 3cfd5427bf..b50bc105f2 100644 --- a/include/wxstruct.h +++ b/include/wxstruct.h @@ -686,7 +686,7 @@ public: int aNScr, int aScr, int aLnW, double aScalar, EDA_COLOR_T aClr1 = RED, EDA_COLOR_T aClr2 = RED ); - void PlotWorkSheet( PLOTTER* aPlotter, BASE_SCREEN* aScreen ); + void PlotWorkSheet( PLOTTER* aPlotter, BASE_SCREEN* aScreen, int aLineWidth ); /** * Function GetXYSheetReferences diff --git a/kicad/tree_project_frame.cpp b/kicad/tree_project_frame.cpp index e7e4dd7037..bcc750fabf 100644 --- a/kicad/tree_project_frame.cpp +++ b/kicad/tree_project_frame.cpp @@ -539,7 +539,10 @@ bool TREE_PROJECT_FRAME::AddFileToTree( const wxString& aName, bool addFile = false; for( unsigned i = 0; i < m_Filters.size(); i++ ) { - reg.Compile( m_Filters[i], wxRE_ICASE ); + wxCHECK2_MSG( reg.Compile( m_Filters[i], wxRE_ICASE ), continue, + wxT( "Regular expression " ) + m_Filters[i] + + wxT( " failed to compile." ) ); + if( reg.Matches( aName ) ) { addFile = true; diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index f61fb483ba..f45d242228 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -20,6 +20,7 @@ endif() include_directories(BEFORE ${INC_BEFORE}) include_directories( ./dialogs + ./autorouter ../3d-viewer ../common ${Boost_INCLUDE_DIR} @@ -107,30 +108,38 @@ set(PCBNEW_DIALOGS dialogs/dialog_footprint_wizard_list.cpp ) -# some of the files here may be going to the dialog srcs in fact.... +set(PCBNEW_AUTOROUTER_SRCS + autorouter/automove.cpp + autorouter/autoplac.cpp + autorouter/autorout.cpp + autorouter/routing_matrix.cpp + autorouter/dist.cpp + autorouter/queue.cpp + autorouter/solve.cpp + autorouter/graphpcb.cpp + autorouter/work.cpp + ) + set(PCBNEW_CLASS_SRCS tool_modview.cpp modview.cpp modview_frame.cpp pcbframe.cpp attribut.cpp - automove.cpp - autoplac.cpp - autorout.cpp - board.cpp board_items_to_polygon_shape_transform.cpp board_undo_redo.cpp block.cpp block_module_editor.cpp build_BOM_from_board.cpp class_pcb_layer_widget.cpp + class_pcb_layer_box_selector.cpp clean.cpp connect.cpp controle.cpp dimension.cpp cross-probing.cpp deltrack.cpp - dist.cpp + ${PCBNEW_DIALOGS} dragsegm.cpp drc.cpp drc_clearance_test_functions.cpp @@ -154,7 +163,6 @@ set(PCBNEW_CLASS_SRCS gendrill.cpp globaleditpad.cpp gpcb_exchange.cpp - graphpcb.cpp highlight.cpp hotkeys.cpp hotkeys_board_editor.cpp @@ -194,10 +202,8 @@ set(PCBNEW_CLASS_SRCS plot_rtn.cpp print_board_functions.cpp printout_controler.cpp - queue.cpp ratsnest.cpp set_grid.cpp - solve.cpp specctra.cpp specctra_export.cpp specctra_import.cpp @@ -210,7 +216,6 @@ set(PCBNEW_CLASS_SRCS tracepcb.cpp tr_modif.cpp trpiste.cpp - work.cpp xchgmod.cpp zones_convert_brd_items_to_polygons_with_Boost.cpp zones_convert_to_polygons_aux_functions.cpp @@ -225,7 +230,7 @@ set(PCBNEW_CLASS_SRCS class_footprint_wizard.cpp ) -set(PCBNEW_SRCS ${PCBNEW_CLASS_SRCS} ${PCBNEW_DIALOGS}) +set(PCBNEW_SRCS ${PCBNEW_AUTOROUTER_SRCS} ${PCBNEW_CLASS_SRCS} ${PCBNEW_DIALOGS}) ### # We need some extra sources from common diff --git a/pcbnew/ar_protos.h b/pcbnew/ar_protos.h deleted file mode 100644 index bfee375510..0000000000 --- a/pcbnew/ar_protos.h +++ /dev/null @@ -1,85 +0,0 @@ -/** - * @file ar_protos.h - */ - - -#ifndef _AR_PROTOS_H_ -#define _AR_PROTOS_H_ - - -#include - - -class PCB_EDIT_FRAME; -class BOARD; -class D_PAD; -class RATSNEST_ITEM; -class TRACK; - - -int Propagation( PCB_EDIT_FRAME* frame ); - -/* Initialize a color value, the cells included in the board edge of the - * pad surface by pt_pad, with the margin reserved for isolation and the - * half width of the runway - * Parameters: - * Pt_pad: pointer to the description of the pad - * color: mask write in cells - * margin: add a value to the radius or half the score pad - * op_logic: type of writing in the cell (WRITE, OR) - */ -void PlacePad( BOARD* Pcb, D_PAD* pt_pad, int type, int marge, int op_logic ); - -/* Draws a segment of track on the board. */ -void TraceSegmentPcb( BOARD* Pcb, TRACK* pt_segm, int type, int marge, int op_logic ); - -/* Uses the color value of all cells included in the board - * coord of the rectangle ux0, uy0 (top right corner) - * a ux1, uy1 (lower left corner) (coord PCB) - * the rectangle is horizontal (or vertical) - * masque_layer = mask layers; - * op_logic = WRITE_CELL, WRITE_OR_CELL, WRITE_XOR_CELL, WRITE_AND_CELL - */ -void TraceFilledRectangle( BOARD* Pcb, int ux0, int uy0, int ux1, int uy1, - int side, int color, int op_logic); - - -/* Same as above, but the rectangle is inclined angle angle. */ -void TraceFilledRectangle( BOARD* Pcb, int ux0, int uy0, int ux1, int uy1, - int angle, int masque_layer, int color, int op_logic ); - -/* QUEUE.CPP */ -void FreeQueue(); -void InitQueue(); -void GetQueue( int *, int *, int *, int *, int * ); -int SetQueue( int, int, int, int, int, int, int ); -void ReSetQueue( int, int, int, int, int, int, int ); - -/* WORK.CPP */ -void InitWork(); -void ReInitWork(); -int SetWork( int, int, int , int, int, RATSNEST_ITEM *, int ); -void GetWork( int *, int *, int *, int *, int *, RATSNEST_ITEM ** ); -void SortWork(); /* order the work items; shortest first */ - -/* DIST.CPP */ -int GetApxDist( int, int, int, int ); -int CalcDist( int, int, int ,int ); - -/* BOARD.CPP */ -int Build_Work( BOARD * Pcb ); -void PlaceCells( BOARD * Pcb, int net_code, int flag = 0 ); - -MATRIX_CELL GetCell( int aRow, int aCol, int aSide); -void SetCell( int aRow, int aCol, int aSide, MATRIX_CELL aCell); -void OrCell( int aRow, int aCol, int aSide, MATRIX_CELL aCell); -void XorCell( int aRow, int aCol, int aSide, MATRIX_CELL aCell); -void AndCell( int aRow, int aCol, int aSide, MATRIX_CELL aCell); -void AddCell( int aRow, int aCol, int aSide, MATRIX_CELL aCell); -DIST_CELL GetDist( int aRow, int aCol, int aSide ); -void SetDist( int aRow, int aCol, int aSide, DIST_CELL ); -int GetDir( int aRow, int aCol, int aSide ); -void SetDir( int aRow, int aCol, int aSide, int aDir); - - -#endif // _AR_PROTOS_H_ diff --git a/pcbnew/attribut.cpp b/pcbnew/attribut.cpp index f51fb6c86a..fdac1a24b9 100644 --- a/pcbnew/attribut.cpp +++ b/pcbnew/attribut.cpp @@ -1,7 +1,8 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2006 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck * Copyright (C) 2011 Wayne Stambaugh * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. * diff --git a/pcbnew/autorout.h b/pcbnew/autorout.h deleted file mode 100644 index f9fd61bf44..0000000000 --- a/pcbnew/autorout.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2011 Wayne Stambaugh - * Copyright (C) 2004-2011 KiCad Developers, see change_log.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 autorout.h - */ - -#ifndef AUTOROUT_H -#define AUTOROUT_H - - -#include - - -class BOARD; - - -#define TOP 0 -#define BOTTOM 1 -#define EMPTY 0 -#define ILLEGAL -1 - - -/* Autorouter commands. */ -enum CommandOpt { - PLACE_ALL, - PLACE_OUT_OF_BOARD, - PLACE_INCREMENTAL, - PLACE_1_MODULE, - - ROUTE_ALL, - ROUTE_NET, - ROUTE_MODULE, - ROUTE_PAD -}; - - -extern int E_scale; /* Scaling factor of distance tables. */ - -#define ONE_SIDE 0 -#define TWO_SIDES 1 - -#define MAX_SIDES_COUNT 2 - -extern int Nb_Sides; /* Number of layers for autorouting (0 or 1) */ - -#define FORCE_PADS 1 /* Force placement of pads for any Netcode */ - -/* board dimensions */ -extern int Nrows; -extern int Ncols; -extern int Ntotal; - -/* search statistics */ -extern int OpenNodes; /* total number of nodes opened */ -extern int ClosNodes; /* total number of nodes closed */ -extern int MoveNodes; /* total number of nodes moved */ -extern int MaxNodes; /* maximum number of nodes opened at one time */ - - -/* Structures useful to the generation of board as bitmap. */ -typedef char MATRIX_CELL; -typedef int DIST_CELL; -typedef char DIR_CELL; - - -/** - * class MATRIX_ROUTING_HEAD - */ -class MATRIX_ROUTING_HEAD /* header of blocks of MATRIX_CELL */ -{ -public: - MATRIX_CELL* m_BoardSide[MAX_SIDES_COUNT]; /* ptr to block of memory: 2-sided board */ - DIST_CELL* m_DistSide[MAX_SIDES_COUNT]; /* ptr to block of memory: path distance to - * cells */ - DIR_CELL* m_DirSide[MAX_SIDES_COUNT]; /* header of blocks of chars:pointers back to - * source */ - bool m_InitBoardDone; - int m_Layers; - int m_GridRouting; // Size of grid for autoplace/autoroute - EDA_RECT m_BrdBox; // Actual board bounding box - int m_Nrows, m_Ncols; - int m_MemSize; - -public: - MATRIX_ROUTING_HEAD(); - ~MATRIX_ROUTING_HEAD(); - - /** - * Function ComputeMatrixSize - * calculates the number of rows and columns of dimensions of \a aPcb for routing and - * automatic calculation of area. - */ - bool ComputeMatrixSize( BOARD* aPcb ); - - /** - * Function InitBoard - * initializes the data structures. - * - * @return the amount of memory used or -1 if default. - */ - int InitBoard(); - - void UnInitBoard(); -}; - -extern MATRIX_ROUTING_HEAD Board; /* 2-sided board */ - - -/* Constants used to trace the cells on the BOARD */ -#define WRITE_CELL 0 -#define WRITE_OR_CELL 1 -#define WRITE_XOR_CELL 2 -#define WRITE_AND_CELL 3 -#define WRITE_ADD_CELL 4 - - -#endif // AUTOROUT_H diff --git a/pcbnew/automove.cpp b/pcbnew/autorouter/automove.cpp similarity index 97% rename from pcbnew/automove.cpp rename to pcbnew/autorouter/automove.cpp index 0b211e9d95..154fdcc831 100644 --- a/pcbnew/automove.cpp +++ b/pcbnew/autorouter/automove.cpp @@ -1,9 +1,11 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2009 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck * Copyright (C) 2011 Wayne Stambaugh - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * + * Copyright (C) 1992-2012 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 diff --git a/pcbnew/autoplac.cpp b/pcbnew/autorouter/autoplac.cpp similarity index 65% rename from pcbnew/autoplac.cpp rename to pcbnew/autorouter/autoplac.cpp index 0214d976a1..f943e8116e 100644 --- a/pcbnew/autoplac.cpp +++ b/pcbnew/autorouter/autoplac.cpp @@ -1,9 +1,16 @@ +/** + * @file autoplac.cpp + * @brief Routiness to automatically place MODULES on a board. + */ + /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2008-2011 Wayne Stambaugh - * Copyright (C) 1992-2011 KiCad Developers, see change_log.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2011 Wayne Stambaugh + * + * Copyright (C) 1992-2012 KiCad Developers, see change_log.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 @@ -23,11 +30,6 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ -/** - * @file autoplac.cpp - * @brief Routiness to automatically place MODULES on a board. - */ - #include #include #include @@ -38,7 +40,7 @@ #include #include -#include +#include #include #include @@ -46,6 +48,7 @@ #include #include #include +#include #define GAIN 16 @@ -56,7 +59,7 @@ * graduated from 0 (rotation allowed) to 10 (rotation count null) * the count is increased. */ -static const float OrientPenality[11] = +static const double OrientPenality[11] = { 2.0f, /* CntRot = 0 rotation prohibited */ 1.9f, /* CntRot = 1 */ @@ -76,37 +79,25 @@ static const float OrientPenality[11] = #define OCCUPED_By_MODULE -1 -static EDA_RECT bbbox; // boards bounding box - static wxPoint CurrPosition; // Current position of the current module placement static bool AutoPlaceShowAll = true; -float MinCout; +double MinCout; static int TstModuleOnBoard( BOARD* Pcb, MODULE* Module, bool TstOtherSide ); -static void CreateKeepOutRectangle( BOARD* Pcb, - int ux0, - int uy0, - int ux1, - int uy1, - int marge, - int aKeepOut, - int aLayerMask ); +static void CreateKeepOutRectangle( int ux0, int uy0, int ux1, int uy1, + int marge, int aKeepOut, int aLayerMask ); static MODULE* PickModule( PCB_EDIT_FRAME* pcbframe, wxDC* DC ); - +static int propagate(); void PCB_EDIT_FRAME::AutoPlaceModule( MODULE* Module, int place_mode, wxDC* DC ) { - int ii, activ; - MODULE* ThisModule = NULL; + MODULE* currModule = NULL; wxPoint PosOK; wxPoint memopos; int error; - int NbModules = 0; - int NbTotalModules = 0; - float Pas; int lay_tmp_TOP, lay_tmp_BOTTOM; // Undo: init list @@ -121,27 +112,27 @@ void PCB_EDIT_FRAME::AutoPlaceModule( MODULE* Module, int place_mode, wxDC* DC ) switch( place_mode ) { - case PLACE_1_MODULE: - ThisModule = Module; + case PLACE_1_MODULE: + currModule = Module; - if( ThisModule == NULL ) - return; + if( currModule == NULL ) + return; - ThisModule->m_ModuleStatus &= ~(MODULE_is_PLACED | MODULE_to_PLACE); - break; + currModule->m_ModuleStatus &= ~(MODULE_is_PLACED | MODULE_to_PLACE); + break; - case PLACE_OUT_OF_BOARD: - break; + case PLACE_OUT_OF_BOARD: + break; - case PLACE_ALL: - if( !IsOK( this, _( "Footprints NOT LOCKED will be moved" ) ) ) - return; + case PLACE_ALL: + if( !IsOK( this, _( "Footprints NOT LOCKED will be moved" ) ) ) + return; - break; + break; - case PLACE_INCREMENTAL: - if( !IsOK( this, _( "Footprints NOT PLACED will be moved" ) ) ) - return; + case PLACE_INCREMENTAL: + if( !IsOK( this, _( "Footprints NOT PLACED will be moved" ) ) ) + return; break; } @@ -150,25 +141,17 @@ void PCB_EDIT_FRAME::AutoPlaceModule( MODULE* Module, int place_mode, wxDC* DC ) lay_tmp_BOTTOM = Route_Layer_BOTTOM; lay_tmp_TOP = Route_Layer_TOP; - Board.m_GridRouting = (int) GetScreen()->GetGridSize().x; + RoutingMatrix.m_GridRouting = (int) GetScreen()->GetGridSize().x; // Ensure Board.m_GridRouting has a reasonable value: - if( Board.m_GridRouting < 10 ) - Board.m_GridRouting = 10; // Min value = 1/1000 inch + if( RoutingMatrix.m_GridRouting < 10*IU_PER_MILS ) + RoutingMatrix.m_GridRouting = 10*IU_PER_MILS; // Min value = 1/1000 inch /* Compute module parameters used in auto place */ - Module = GetBoard()->m_Modules; - NbTotalModules = 0; - - for( ; Module != NULL; Module = Module->Next() ) - { - Module->CalculateBoundingBox(); - NbTotalModules ++; - } - if( GenPlaceBoard() == 0 ) return; + int moduleCount = 0; Module = GetBoard()->m_Modules; for( ; Module != NULL; Module = Module->Next() ) @@ -178,10 +161,10 @@ void PCB_EDIT_FRAME::AutoPlaceModule( MODULE* Module, int place_mode, wxDC* DC ) switch( place_mode ) { case PLACE_1_MODULE: - if( ThisModule == Module ) + if( currModule == Module ) { // Module will be placed, add to undo. - picker.SetItem( ThisModule ); + picker.SetItem( currModule ); newList.PushItem( picker ); Module->m_ModuleStatus |= MODULE_to_PLACE; @@ -190,12 +173,12 @@ void PCB_EDIT_FRAME::AutoPlaceModule( MODULE* Module, int place_mode, wxDC* DC ) break; case PLACE_OUT_OF_BOARD: - Module->m_ModuleStatus &= ~MODULE_is_PLACED; + Module->SetIsPlaced( false ); - if( Module->m_ModuleStatus & MODULE_is_LOCKED ) + if( Module->IsLocked() ) break; - if( !bbbox.Contains( Module->m_Pos ) ) + if( !RoutingMatrix.m_BrdBox.Contains( Module->m_Pos ) ) { // Module will be placed, add to undo. picker.SetItem( Module ); @@ -207,9 +190,9 @@ void PCB_EDIT_FRAME::AutoPlaceModule( MODULE* Module, int place_mode, wxDC* DC ) break; case PLACE_ALL: - Module->m_ModuleStatus &= ~MODULE_is_PLACED; + Module->SetIsPlaced( false ); - if( Module->m_ModuleStatus & MODULE_is_LOCKED ) + if( Module->IsLocked() ) break; // Module will be placed, add to undo. @@ -220,9 +203,9 @@ void PCB_EDIT_FRAME::AutoPlaceModule( MODULE* Module, int place_mode, wxDC* DC ) break; case PLACE_INCREMENTAL: - if( Module->m_ModuleStatus & MODULE_is_LOCKED ) + if( Module->IsLocked() ) { - Module->m_ModuleStatus &= ~MODULE_is_PLACED; + Module->SetIsPlaced( false ); break; } @@ -241,7 +224,7 @@ void PCB_EDIT_FRAME::AutoPlaceModule( MODULE* Module, int place_mode, wxDC* DC ) if( Module->m_ModuleStatus & MODULE_to_PLACE ) // Erase from screen { - NbModules++; + moduleCount++; Module->Draw( m_canvas, DC, GR_XOR ); } else @@ -250,26 +233,25 @@ void PCB_EDIT_FRAME::AutoPlaceModule( MODULE* Module, int place_mode, wxDC* DC ) } } - // Undo: commit + // Undo command: commit list if( newList.GetCount() ) SaveCopyInUndoList( newList, UR_CHANGED ); - activ = 0; - Pas = 100.0; - - if( NbModules ) - Pas = 100.0 / (float) NbModules; + int cnt = 0; + int ii; + wxString msg; while( ( Module = PickModule( this, DC ) ) != NULL ) { - float BestScore; - DisplayActivity( (int) (activ * Pas), wxEmptyString ); activ++; + // Display some info about activity, module placement can take a while: + msg.Printf( _("Place module %d of %d"), cnt, moduleCount ); + SetStatusText( msg ); /* Display fill area of interest, barriers, penalties. */ DrawInfoPlace( DC ); error = GetOptimalModulePlacement( Module, DC ); - BestScore = MinCout; + double BestScore = MinCout; PosOK = CurrPosition; if( error == ESC ) @@ -365,13 +347,13 @@ end_of_tst: Module->CalculateBoundingBox(); GenModuleOnBoard( Module ); - Module->m_ModuleStatus |= MODULE_is_PLACED; + Module->SetIsPlaced( true ); Module->m_ModuleStatus &= ~MODULE_to_PLACE; } CurrPosition = memopos; - Board.UnInitBoard(); + RoutingMatrix.UnInitRoutingMatrix(); Route_Layer_TOP = lay_tmp_TOP; Route_Layer_BOTTOM = lay_tmp_BOTTOM; @@ -397,17 +379,17 @@ void PCB_EDIT_FRAME::DrawInfoPlace( wxDC* DC ) GRSetDrawMode( DC, GR_COPY ); - for( ii = 0; ii < Board.m_Nrows; ii++ ) + for( ii = 0; ii < RoutingMatrix.m_Nrows; ii++ ) { - oy = bbbox.GetY() + ( ii * Board.m_GridRouting ); + oy = RoutingMatrix.m_BrdBox.GetY() + ( ii * RoutingMatrix.m_GridRouting ); - for( jj = 0; jj < Board.m_Ncols; jj++ ) + for( jj = 0; jj < RoutingMatrix.m_Ncols; jj++ ) { - ox = bbbox.GetX() + (jj * Board.m_GridRouting); + ox = RoutingMatrix.m_BrdBox.GetX() + (jj * RoutingMatrix.m_GridRouting); color = BLACK; - top_state = GetCell( ii, jj, TOP ); - bottom_state = GetCell( ii, jj, BOTTOM ); + top_state = RoutingMatrix.GetCell( ii, jj, TOP ); + bottom_state = RoutingMatrix.GetCell( ii, jj, BOTTOM ); if( top_state & CELL_is_ZONE ) color = BLUE; @@ -421,7 +403,8 @@ void PCB_EDIT_FRAME::DrawInfoPlace( wxDC* DC ) color = LIGHTGREEN; else /* Display the filling and keep out regions. */ { - if( GetDist( ii, jj, TOP ) || GetDist( ii, jj, BOTTOM ) ) + if( RoutingMatrix.GetDist( ii, jj, TOP ) || + RoutingMatrix.GetDist( ii, jj, BOTTOM ) ) color = DARKGRAY; } @@ -433,57 +416,36 @@ void PCB_EDIT_FRAME::DrawInfoPlace( wxDC* DC ) int PCB_EDIT_FRAME::GenPlaceBoard() { - int jj, ii; - int NbCells; - EDA_ITEM* PtStruct; wxString msg; - Board.UnInitBoard(); + RoutingMatrix.UnInitRoutingMatrix(); - bbbox = GetBoard()->ComputeBoundingBox( true ); + EDA_RECT bbox = GetBoard()->ComputeBoundingBox( true ); - if( bbbox.GetWidth() == 0 && bbbox.GetHeight() == 0 ) + if( bbox.GetWidth() == 0 || bbox.GetHeight() == 0 ) { DisplayError( this, _( "No PCB edge found, unknown board size!" ) ); return 0; } - /* The boundary box must have its start point on placing grid: */ - bbbox.SetX( bbbox.GetX() - ( bbbox.GetX() % Board.m_GridRouting ) ); - bbbox.SetY( bbbox.GetY() - ( bbbox.GetY() % Board.m_GridRouting ) ); - - /* The boundary box must have its end point on placing grid: */ - wxPoint end = bbbox.GetEnd(); - end.x -= end.x % Board.m_GridRouting; - end.x += Board.m_GridRouting; - end.y -= end.y % Board.m_GridRouting; - end.y += Board.m_GridRouting; - bbbox.SetEnd( end ); - - Nrows = bbbox.GetHeight() / Board.m_GridRouting; - Ncols = bbbox.GetWidth() / Board.m_GridRouting; - /* get a small margin for memory allocation: */ - Ncols += 2; Nrows += 2; - NbCells = Ncols * Nrows; + RoutingMatrix.ComputeMatrixSize( GetBoard(), true ); + int nbCells = RoutingMatrix.m_Ncols * RoutingMatrix.m_Nrows; m_messagePanel->EraseMsgBox(); - msg.Printf( wxT( "%d" ), Ncols ); + msg.Printf( wxT( "%d" ), RoutingMatrix.m_Ncols ); m_messagePanel->SetMessage( 1, _( "Cols" ), msg, GREEN ); - msg.Printf( wxT( "%d" ), Nrows ); + msg.Printf( wxT( "%d" ), RoutingMatrix.m_Nrows ); m_messagePanel->SetMessage( 7, _( "Lines" ), msg, GREEN ); - msg.Printf( wxT( "%d" ), NbCells ); + msg.Printf( wxT( "%d" ), nbCells ); m_messagePanel->SetMessage( 14, _( "Cells." ), msg, YELLOW ); /* Choose the number of board sides. */ Nb_Sides = TWO_SIDES; - m_messagePanel->SetMessage( 22, wxT( "S" ), - ( Nb_Sides == TWO_SIDES ) ? wxT( "2" ) : wxT( "1" ), WHITE ); - - Board.InitBoard(); + RoutingMatrix.InitRoutingMatrix(); /* Display memory usage. */ - msg.Printf( wxT( "%d" ), Board.m_MemSize / 1024 ); + msg.Printf( wxT( "%d" ), RoutingMatrix.m_MemSize / 1024 ); m_messagePanel->SetMessage( 24, wxT( "Mem(Kb)" ), msg, CYAN ); Route_Layer_BOTTOM = LAYER_N_FRONT; @@ -494,12 +456,13 @@ int PCB_EDIT_FRAME::GenPlaceBoard() Route_Layer_TOP = LAYER_N_FRONT; /* Place the edge layer segments */ - PtStruct = GetBoard()->m_Drawings; TRACK TmpSegm( NULL ); TmpSegm.SetLayer( -1 ); TmpSegm.SetNet( -1 ); - TmpSegm.m_Width = Board.m_GridRouting / 2; + TmpSegm.m_Width = RoutingMatrix.m_GridRouting / 2; + + EDA_ITEM* PtStruct = GetBoard()->m_Drawings; for( ; PtStruct != NULL; PtStruct = PtStruct->Next() ) { @@ -518,8 +481,8 @@ int PCB_EDIT_FRAME::GenPlaceBoard() TmpSegm.SetShape( DrawSegm->GetShape() ); TmpSegm.m_Param = DrawSegm->GetAngle(); - TraceSegmentPcb( GetBoard(), &TmpSegm, HOLE | CELL_is_EDGE, - Board.m_GridRouting, WRITE_CELL ); + TraceSegmentPcb( &TmpSegm, HOLE | CELL_is_EDGE, + RoutingMatrix.m_GridRouting, WRITE_CELL ); break; case PCB_TEXT_T: @@ -528,24 +491,20 @@ int PCB_EDIT_FRAME::GenPlaceBoard() } } - /* Init the point of attachment to the area. */ - OrCell( Nrows / 2, Ncols / 2, BOTTOM, CELL_is_ZONE ); + // Mark cells of the routing matrix to CELL_is_ZONE + // (i.e. availlable cell to place a module ) + // Init a starting point of attachment to the area. + RoutingMatrix.OrCell( RoutingMatrix.m_Nrows / 2, RoutingMatrix.m_Ncols / 2, + BOTTOM, CELL_is_ZONE ); - /* Fill bottom layer zones. */ - ii = 1; - jj = 1; - - while( ii ) - { - msg.Printf( wxT( "%d" ), jj++ ); - m_messagePanel->SetMessage( 50, _( "Loop" ), msg, CYAN ); + // find and mark all other availlable cells: + for( int ii = 1; ii != 0; ) ii = propagate(); - } - /* Initialize top layer. */ - if( Board.m_BoardSide[TOP] ) - memcpy( Board.m_BoardSide[TOP], Board.m_BoardSide[BOTTOM], - NbCells * sizeof(MATRIX_CELL) ); + // Initialize top layer. to the same value as the bottom layer + if( RoutingMatrix.m_BoardSide[TOP] ) + memcpy( RoutingMatrix.m_BoardSide[TOP], RoutingMatrix.m_BoardSide[BOTTOM], + nbCells * sizeof(MATRIX_CELL) ); return 1; } @@ -556,7 +515,7 @@ int PCB_EDIT_FRAME::GenPlaceBoard() void PCB_EDIT_FRAME::GenModuleOnBoard( MODULE* Module ) { int ox, oy, fx, fy; - int marge = Board.m_GridRouting / 2; + int marge = RoutingMatrix.m_GridRouting / 2; int layerMask; D_PAD* Pad; @@ -565,29 +524,29 @@ void PCB_EDIT_FRAME::GenModuleOnBoard( MODULE* Module ) oy = Module->m_BoundaryBox.GetY() - marge; fy = Module->m_BoundaryBox.GetBottom() + marge; - if( ox < bbbox.GetX() ) - ox = bbbox.GetX(); + if( ox < RoutingMatrix.m_BrdBox.GetX() ) + ox = RoutingMatrix.m_BrdBox.GetX(); - if( ox > bbbox.GetRight() ) - ox = bbbox.GetRight(); + if( ox > RoutingMatrix.m_BrdBox.GetRight() ) + ox = RoutingMatrix.m_BrdBox.GetRight(); - if( fx < bbbox.GetX() ) - fx = bbbox.GetX(); + if( fx < RoutingMatrix.m_BrdBox.GetX() ) + fx = RoutingMatrix.m_BrdBox.GetX(); - if( fx > bbbox.GetRight() ) - fx = bbbox.GetRight(); + if( fx > RoutingMatrix.m_BrdBox.GetRight() ) + fx = RoutingMatrix.m_BrdBox.GetRight(); - if( oy < bbbox.GetY() ) - oy = bbbox.GetY(); + if( oy < RoutingMatrix.m_BrdBox.GetY() ) + oy = RoutingMatrix.m_BrdBox.GetY(); - if( oy > bbbox.GetBottom() ) - oy = bbbox.GetBottom(); + if( oy > RoutingMatrix.m_BrdBox.GetBottom() ) + oy = RoutingMatrix.m_BrdBox.GetBottom(); - if( fy < bbbox.GetY() ) - fy = bbbox.GetY(); + if( fy < RoutingMatrix.m_BrdBox.GetY() ) + fy = RoutingMatrix.m_BrdBox.GetY(); - if( fy > bbbox.GetBottom() ) - fy = bbbox.GetBottom(); + if( fy > RoutingMatrix.m_BrdBox.GetBottom() ) + fy = RoutingMatrix.m_BrdBox.GetBottom(); layerMask = 0; @@ -597,7 +556,7 @@ void PCB_EDIT_FRAME::GenModuleOnBoard( MODULE* Module ) if( Module->GetLayer() == LAYER_N_BACK ) layerMask = LAYER_BACK; - TraceFilledRectangle( GetBoard(), ox, oy, fx, fy, layerMask, + TraceFilledRectangle( ox, oy, fx, fy, layerMask, CELL_is_MODULE, WRITE_OR_CELL ); int trackWidth = GetBoard()->m_NetClasses.GetDefault()->GetTrackWidth(); @@ -608,12 +567,12 @@ void PCB_EDIT_FRAME::GenModuleOnBoard( MODULE* Module ) for( Pad = Module->m_Pads; Pad != NULL; Pad = Pad->Next() ) { - ::PlacePad( GetBoard(), Pad, CELL_is_MODULE, marge, WRITE_OR_CELL ); + ::PlacePad( Pad, CELL_is_MODULE, marge, WRITE_OR_CELL ); } /* Trace clearance. */ - marge = ( Board.m_GridRouting * Module->m_PadNum ) / GAIN; - CreateKeepOutRectangle( GetBoard(), ox, oy, fx, fy, marge, KEEP_OUT_MARGIN, layerMask ); + marge = ( RoutingMatrix.m_GridRouting * Module->m_PadNum ) / GAIN; + CreateKeepOutRectangle( ox, oy, fx, fy, marge, KEEP_OUT_MARGIN, layerMask ); } @@ -624,14 +583,17 @@ int PCB_EDIT_FRAME::GetOptimalModulePlacement( MODULE* aModule, wxDC* aDC ) int error = 1; int showRat = 0; wxPoint LastPosOK; - float mincout, cout, Score; + double mincout, cout, Score; int keepOut; bool TstOtherSide; + bool showRats = g_Show_Module_Ratsnest; + + g_Show_Module_Ratsnest = false; aModule->DisplayInfo( this ); - LastPosOK.x = bbbox.GetX(); - LastPosOK.y = bbbox.GetY(); + LastPosOK.x = RoutingMatrix.m_BrdBox.GetX(); + LastPosOK.y = RoutingMatrix.m_BrdBox.GetY(); cx = aModule->m_Pos.x; cy = aModule->m_Pos.y; ox = aModule->m_BoundaryBox.GetX() - cx; @@ -639,12 +601,12 @@ int PCB_EDIT_FRAME::GetOptimalModulePlacement( MODULE* aModule, wxDC* aDC ) oy = aModule->m_BoundaryBox.GetY() - cy; fy = aModule->m_BoundaryBox.GetHeight() + oy; - CurrPosition.x = bbbox.GetX() - ox; - CurrPosition.y = bbbox.GetY() - oy; + CurrPosition.x = RoutingMatrix.m_BrdBox.GetX() - ox; + CurrPosition.y = RoutingMatrix.m_BrdBox.GetY() - oy; /* Module placement on grid. */ - CurrPosition.x -= CurrPosition.x % Board.m_GridRouting; - CurrPosition.y -= CurrPosition.y % Board.m_GridRouting; + CurrPosition.x -= CurrPosition.x % RoutingMatrix.m_GridRouting; + CurrPosition.y -= CurrPosition.y % RoutingMatrix.m_GridRouting; g_Offset_Module.x = cx - CurrPosition.x; g_Offset_Module.y = cy - CurrPosition.y; @@ -679,8 +641,8 @@ int PCB_EDIT_FRAME::GetOptimalModulePlacement( MODULE* aModule, wxDC* aDC ) mincout = -1.0; SetStatusText( wxT( "Score ??, pos ??" ) ); - for( ; CurrPosition.x < bbbox.GetRight() - fx; - CurrPosition.x += Board.m_GridRouting ) + for( ; CurrPosition.x < RoutingMatrix.m_BrdBox.GetRight() - fx; + CurrPosition.x += RoutingMatrix.m_GridRouting ) { wxYield(); @@ -699,15 +661,15 @@ int PCB_EDIT_FRAME::GetOptimalModulePlacement( MODULE* aModule, wxDC* aDC ) DrawModuleOutlines( m_canvas, aDC, aModule ); g_Offset_Module.x = cx - CurrPosition.x; - CurrPosition.y = bbbox.GetY() - oy; + CurrPosition.y = RoutingMatrix.m_BrdBox.GetY() - oy; /* Placement on grid. */ - CurrPosition.y -= CurrPosition.y % Board.m_GridRouting; + CurrPosition.y -= CurrPosition.y % RoutingMatrix.m_GridRouting; DrawModuleOutlines( m_canvas, aDC, aModule ); - for( ; CurrPosition.y < bbbox.GetBottom() - fy; - CurrPosition.y += Board.m_GridRouting ) + for( ; CurrPosition.y < RoutingMatrix.m_BrdBox.GetBottom() - fy; + CurrPosition.y += RoutingMatrix.m_GridRouting ) { /* Erase traces. */ DrawModuleOutlines( m_canvas, aDC, aModule ); @@ -723,23 +685,23 @@ int PCB_EDIT_FRAME::GetOptimalModulePlacement( MODULE* aModule, wxDC* aDC ) DrawModuleOutlines( m_canvas, aDC, aModule ); keepOut = TstModuleOnBoard( GetBoard(), aModule, TstOtherSide ); - if( keepOut >= 0 ) /* c a d if the module can be placed. */ + if( keepOut >= 0 ) // i.e. if the module can be put here { error = 0; build_ratsnest_module( aModule ); cout = Compute_Ratsnest_PlaceModule( aDC ); showRat = 1; - Score = cout + (float) keepOut; + Score = cout + keepOut; if( (mincout >= Score ) || (mincout < 0 ) ) { LastPosOK = CurrPosition; mincout = Score; wxString msg; - msg.Printf( wxT( "Score %d, pos %3.4f, %3.4f" ), - (int) mincout, - (float) LastPosOK.x / 10000, - (float) LastPosOK.y / 10000 ); + msg.Printf( wxT( "Score %g, pos %3.4g, %3.4g" ), + mincout, + (double) LastPosOK.x / 10000, + (double) LastPosOK.y / 10000 ); SetStatusText( msg ); } } @@ -753,6 +715,8 @@ int PCB_EDIT_FRAME::GetOptimalModulePlacement( MODULE* aModule, wxDC* aDC ) DrawModuleOutlines( m_canvas, aDC, aModule ); /* erasing the last traces */ + g_Show_Module_Ratsnest = showRats; + if( showRat ) Compute_Ratsnest_PlaceModule( aDC ); @@ -785,35 +749,35 @@ int TstRectangle( BOARD* Pcb, int ux0, int uy0, int ux1, int uy1, int side ) ux1 -= Pcb->GetBoundingBox().GetX(); uy1 -= Pcb->GetBoundingBox().GetY(); - row_max = uy1 / Board.m_GridRouting; - col_max = ux1 / Board.m_GridRouting; - row_min = uy0 / Board.m_GridRouting; + row_max = uy1 / RoutingMatrix.m_GridRouting; + col_max = ux1 / RoutingMatrix.m_GridRouting; + row_min = uy0 / RoutingMatrix.m_GridRouting; - if( uy0 > row_min * Board.m_GridRouting ) + if( uy0 > row_min * RoutingMatrix.m_GridRouting ) row_min++; - col_min = ux0 / Board.m_GridRouting; + col_min = ux0 / RoutingMatrix.m_GridRouting; - if( ux0 > col_min * Board.m_GridRouting ) + if( ux0 > col_min * RoutingMatrix.m_GridRouting ) col_min++; if( row_min < 0 ) row_min = 0; - if( row_max >= ( Nrows - 1 ) ) - row_max = Nrows - 1; + if( row_max >= ( RoutingMatrix.m_Nrows - 1 ) ) + row_max = RoutingMatrix.m_Nrows - 1; if( col_min < 0 ) col_min = 0; - if( col_max >= ( Ncols - 1 ) ) - col_max = Ncols - 1; + if( col_max >= ( RoutingMatrix.m_Ncols - 1 ) ) + col_max = RoutingMatrix.m_Ncols - 1; for( row = row_min; row <= row_max; row++ ) { for( col = col_min; col <= col_max; col++ ) { - data = GetCell( row, col, side ); + data = RoutingMatrix.GetCell( row, col, side ); if( ( data & CELL_is_ZONE ) == 0 ) return OUT_OF_BOARD; @@ -831,40 +795,40 @@ int TstRectangle( BOARD* Pcb, int ux0, int uy0, int ux1, int uy1, int side ) * (ux, ux .. y0, y1): * (Sum of cells in terms of distance) */ -unsigned int CalculateKeepOutArea( BOARD* Pcb, int ux0, int uy0, int ux1, int uy1, int side ) +unsigned int CalculateKeepOutArea( int ux0, int uy0, int ux1, int uy1, int side ) { int row, col; int row_min, row_max, col_min, col_max; unsigned int keepOut; - ux0 -= Pcb->GetBoundingBox().GetX(); - uy0 -= Pcb->GetBoundingBox().GetY(); - ux1 -= Pcb->GetBoundingBox().GetX(); - uy1 -= Pcb->GetBoundingBox().GetY(); + ux0 -= RoutingMatrix.m_BrdBox.GetX(); + uy0 -= RoutingMatrix.m_BrdBox.GetY(); + ux1 -= RoutingMatrix.m_BrdBox.GetX(); + uy1 -= RoutingMatrix.m_BrdBox.GetY(); - row_max = uy1 / Board.m_GridRouting; - col_max = ux1 / Board.m_GridRouting; - row_min = uy0 / Board.m_GridRouting; + row_max = uy1 / RoutingMatrix.m_GridRouting; + col_max = ux1 / RoutingMatrix.m_GridRouting; + row_min = uy0 / RoutingMatrix.m_GridRouting; - if( uy0 > row_min * Board.m_GridRouting ) + if( uy0 > row_min * RoutingMatrix.m_GridRouting ) row_min++; - col_min = ux0 / Board.m_GridRouting; + col_min = ux0 / RoutingMatrix.m_GridRouting; - if( ux0 > col_min * Board.m_GridRouting ) + if( ux0 > col_min * RoutingMatrix.m_GridRouting ) col_min++; if( row_min < 0 ) row_min = 0; - if( row_max >= ( Nrows - 1 ) ) - row_max = Nrows - 1; + if( row_max >= ( RoutingMatrix.m_Nrows - 1 ) ) + row_max = RoutingMatrix.m_Nrows - 1; if( col_min < 0 ) col_min = 0; - if( col_max >= ( Ncols - 1 ) ) - col_max = Ncols - 1; + if( col_max >= ( RoutingMatrix.m_Ncols - 1 ) ) + col_max = RoutingMatrix.m_Ncols - 1; keepOut = 0; @@ -872,7 +836,7 @@ unsigned int CalculateKeepOutArea( BOARD* Pcb, int ux0, int uy0, int ux1, int uy { for( col = col_min; col <= col_max; col++ ) { - keepOut += (int) GetDist( row, col, side ); + keepOut += RoutingMatrix.GetDist( row, col, side ); } } @@ -914,17 +878,17 @@ int TstModuleOnBoard( BOARD* Pcb, MODULE* Module, bool TstOtherSide ) return error; } - marge = ( Board.m_GridRouting * Module->m_PadNum ) / GAIN; + marge = ( RoutingMatrix.m_GridRouting * Module->m_PadNum ) / GAIN; - return CalculateKeepOutArea( Pcb, ox - marge, oy - marge, fx + marge, fy + marge, side ); + return CalculateKeepOutArea( ox - marge, oy - marge, fx + marge, fy + marge, side ); } -float PCB_EDIT_FRAME::Compute_Ratsnest_PlaceModule( wxDC* DC ) +double PCB_EDIT_FRAME::Compute_Ratsnest_PlaceModule( wxDC* DC ) { double cout, icout; - int ox, oy; - int fx, fy; + wxPoint start; // start point of a ratsnest + wxPoint end; // end point of a ratsnest int dx, dy; if( ( GetBoard()->m_Status_Pcb & RATSNEST_ITEM_LOCAL_OK ) == 0 ) @@ -941,60 +905,58 @@ float PCB_EDIT_FRAME::Compute_Ratsnest_PlaceModule( wxDC* DC ) { RATSNEST_ITEM* pt_local_rats_nest = &GetBoard()->m_LocalRatsnest[ii]; - if( !( pt_local_rats_nest->m_Status & LOCAL_RATSNEST_ITEM ) ) + if( ( pt_local_rats_nest->m_Status & LOCAL_RATSNEST_ITEM ) ) + continue; // Skip ratsnest between 2 pads of the current module + + // Skip modules not inside the board area + MODULE * module = pt_local_rats_nest->m_PadEnd->GetParent(); + if( !RoutingMatrix.m_BrdBox.Contains( module->GetPosition() ) ) + continue; + + start = pt_local_rats_nest->m_PadStart->GetPosition() - g_Offset_Module; + end = pt_local_rats_nest->m_PadEnd->GetPosition(); + + if( AutoPlaceShowAll ) { - ox = pt_local_rats_nest->m_PadStart->GetPosition().x - g_Offset_Module.x; - oy = pt_local_rats_nest->m_PadStart->GetPosition().y - g_Offset_Module.y; - fx = pt_local_rats_nest->m_PadEnd->GetPosition().x; - fy = pt_local_rats_nest->m_PadEnd->GetPosition().y; - - if( AutoPlaceShowAll ) - { - GRLine( m_canvas->GetClipBox(), DC, ox, oy, fx, fy, 0, color ); - } - - /* Cost of the ratsnest. */ - dx = fx - ox; - dy = fy - oy; - - dx = abs( dx ); - dy = abs( dy ); - - if( dx < dy ) - EXCHG( dx, dy ); /* dx >= dy */ - - /* Cost of the longest connection. */ - icout = (float) dx * dx; - - /* Cost of inclination. */ - icout += 3 * (float) dy * dy; - icout = sqrt( icout ); - cout += icout; /* Total cost = sum of costs of each connection. */ + GRLine( m_canvas->GetClipBox(), DC, start, end, 0, color ); } + + /* Cost of the ratsnest. */ + dx = end.x - start.x; + dy = end.y - start.y; + + dx = abs( dx ); + dy = abs( dy ); + + // ttry to have always dx >= dy to calculate the cost of the rastsnet + if( dx < dy ) + EXCHG( dx, dy ); + + // Cost of the connection = lenght + penalty due to the slope + // dx is the biggest lenght relative to the X or Y axis + // the penalty is max for 45 degrees ratsnests, + // and 0 for horizontal or vertical ratsnests. + // For Horizontal and Vertical ratsnests, dy = 0; + icout = hypot( (double) dx, (double) dy * 2.0 ); + cout += icout; /* Total cost = sum of costs of each connection. */ } - return (float) cout; + return cout; } /** * Function CreateKeepOutRectangle - * builds the cost map. - * Cells ( in Dist mao ) inside the rect x0,y0 a x1,y1 are + * builds the cost map: + * Cells ( in Dist map ) inside the rect x0,y0 a x1,y1 are * incremented by value aKeepOut * Cell outside this rectangle, but inside the rectangle - * x0,y0 -marge to x1,y1 + marge sont incrementede by a decreasing value + * x0,y0 -marge to x1,y1 + marge are incremented by a decreasing value * (aKeepOut ... 0). The decreasing value de pends on the distance to the first rectangle * Therefore the cost is high in rect x0,y0 a x1,y1, and decrease outside this rectangle */ -static void CreateKeepOutRectangle( BOARD* Pcb, - int ux0, - int uy0, - int ux1, - int uy1, - int marge, - int aKeepOut, - int aLayerMask ) +void CreateKeepOutRectangle( int ux0, int uy0, int ux1, int uy1, + int marge, int aKeepOut, int aLayerMask ) { int row, col; int row_min, row_max, col_min, col_max, pmarge; @@ -1011,43 +973,43 @@ static void CreateKeepOutRectangle( BOARD* Pcb, if( trace == 0 ) return; - ux0 -= Pcb->GetBoundingBox().GetX(); - uy0 -= Pcb->GetBoundingBox().GetY(); - ux1 -= Pcb->GetBoundingBox().GetX(); - uy1 -= Pcb->GetBoundingBox().GetY(); + ux0 -= RoutingMatrix.m_BrdBox.GetX(); + uy0 -= RoutingMatrix.m_BrdBox.GetY(); + ux1 -= RoutingMatrix.m_BrdBox.GetX(); + uy1 -= RoutingMatrix.m_BrdBox.GetY(); ux0 -= marge; ux1 += marge; uy0 -= marge; uy1 += marge; - pmarge = marge / Board.m_GridRouting; + pmarge = marge / RoutingMatrix.m_GridRouting; if( pmarge < 1 ) pmarge = 1; /* Calculate the coordinate limits of the rectangle. */ - row_max = uy1 / Board.m_GridRouting; - col_max = ux1 / Board.m_GridRouting; - row_min = uy0 / Board.m_GridRouting; + row_max = uy1 / RoutingMatrix.m_GridRouting; + col_max = ux1 / RoutingMatrix.m_GridRouting; + row_min = uy0 / RoutingMatrix.m_GridRouting; - if( uy0 > row_min * Board.m_GridRouting ) + if( uy0 > row_min * RoutingMatrix.m_GridRouting ) row_min++; - col_min = ux0 / Board.m_GridRouting; + col_min = ux0 / RoutingMatrix.m_GridRouting; - if( ux0 > col_min * Board.m_GridRouting ) + if( ux0 > col_min * RoutingMatrix.m_GridRouting ) col_min++; if( row_min < 0 ) row_min = 0; - if( row_max >= (Nrows - 1) ) - row_max = Nrows - 1; + if( row_max >= (RoutingMatrix.m_Nrows - 1) ) + row_max = RoutingMatrix.m_Nrows - 1; if( col_min < 0 ) col_min = 0; - if( col_max >= (Ncols - 1) ) - col_max = Ncols - 1; + if( col_max >= (RoutingMatrix.m_Ncols - 1) ) + col_max = RoutingMatrix.m_Ncols - 1; for( row = row_min; row <= row_max; row++ ) { @@ -1075,15 +1037,15 @@ static void CreateKeepOutRectangle( BOARD* Pcb, if( trace & 1 ) { - data = GetDist( row, col, BOTTOM ) + LocalKeepOut; - SetDist( row, col, BOTTOM, data ); + data = RoutingMatrix.GetDist( row, col, BOTTOM ) + LocalKeepOut; + RoutingMatrix.SetDist( row, col, BOTTOM, data ); } if( trace & 2 ) { - data = GetDist( row, col, TOP ); + data = RoutingMatrix.GetDist( row, col, TOP ); data = MAX( data, LocalKeepOut ); - SetDist( row, col, TOP, data ); + RoutingMatrix.SetDist( row, col, TOP, data ); } } } @@ -1186,7 +1148,31 @@ static MODULE* PickModule( PCB_EDIT_FRAME* pcbframe, wxDC* DC ) } -int PCB_EDIT_FRAME::propagate() +/** + * Function propagate + * Used only in autoplace calculations + * Uses the routing matrix to fill the cells within the zone + * Search and mark cells within the zone, and agree with DRC options. + * Requirements: + * Start from an initial point, to fill zone + * The zone must have no "copper island" + * Algorithm: + * If the current cell has a neighbor flagged as "cell in the zone", it + * become a cell in the zone + * The first point in the zone is the starting point + * 4 searches within the matrix are made: + * 1 - Left to right and top to bottom + * 2 - Right to left and top to bottom + * 3 - bottom to top and Right to left + * 4 - bottom to top and Left to right + * Given the current cell, for each search, we consider the 2 neighbor cells + * the previous cell on the same line and the previous cell on the same column. + * + * This function can request some iterations + * Iterations are made until no cell is added to the zone. + * @return: added cells count (i.e. which the attribute CELL_is_ZONE is set) + */ +int propagate() { int row, col; long current_cell, old_cell_H; @@ -1194,28 +1180,24 @@ int PCB_EDIT_FRAME::propagate() int nbpoints = 0; #define NO_CELL_ZONE (HOLE | CELL_is_EDGE | CELL_is_ZONE) - wxString msg; - m_messagePanel->SetMessage( 57, wxT( "Detect" ), msg, CYAN ); - m_messagePanel->SetMessage( -1, wxEmptyString, wxT( "1" ), CYAN ); - - pt_cell_V.reserve( MAX( Nrows, Ncols ) ); + pt_cell_V.reserve( MAX( RoutingMatrix.m_Nrows, RoutingMatrix.m_Ncols ) ); fill( pt_cell_V.begin(), pt_cell_V.end(), 0 ); // Search from left to right and top to bottom. - for( row = 0; row < Nrows; row++ ) + for( row = 0; row < RoutingMatrix.m_Nrows; row++ ) { old_cell_H = 0; - for( col = 0; col < Ncols; col++ ) + for( col = 0; col < RoutingMatrix.m_Ncols; col++ ) { - current_cell = GetCell( row, col, BOTTOM ) & NO_CELL_ZONE; + current_cell = RoutingMatrix.GetCell( row, col, BOTTOM ) & NO_CELL_ZONE; if( current_cell == 0 ) /* a free cell is found */ { if( (old_cell_H & CELL_is_ZONE) || (pt_cell_V[col] & CELL_is_ZONE) ) { - OrCell( row, col, BOTTOM, CELL_is_ZONE ); + RoutingMatrix.OrCell( row, col, BOTTOM, CELL_is_ZONE ); current_cell = CELL_is_ZONE; nbpoints++; } @@ -1226,22 +1208,21 @@ int PCB_EDIT_FRAME::propagate() } // Search from right to left and top to bottom/ - m_messagePanel->SetMessage( -1, wxEmptyString, wxT( "2" ), CYAN ); fill( pt_cell_V.begin(), pt_cell_V.end(), 0 ); - for( row = 0; row < Nrows; row++ ) + for( row = 0; row < RoutingMatrix.m_Nrows; row++ ) { old_cell_H = 0; - for( col = Ncols - 1; col >= 0; col-- ) + for( col = RoutingMatrix.m_Ncols - 1; col >= 0; col-- ) { - current_cell = GetCell( row, col, BOTTOM ) & NO_CELL_ZONE; + current_cell = RoutingMatrix.GetCell( row, col, BOTTOM ) & NO_CELL_ZONE; if( current_cell == 0 ) /* a free cell is found */ { if( (old_cell_H & CELL_is_ZONE) || (pt_cell_V[col] & CELL_is_ZONE) ) { - OrCell( row, col, BOTTOM, CELL_is_ZONE ); + RoutingMatrix.OrCell( row, col, BOTTOM, CELL_is_ZONE ); current_cell = CELL_is_ZONE; nbpoints++; } @@ -1252,22 +1233,21 @@ int PCB_EDIT_FRAME::propagate() } // Search from bottom to top and right to left. - m_messagePanel->SetMessage( -1, wxEmptyString, wxT( "3" ), CYAN ); fill( pt_cell_V.begin(), pt_cell_V.end(), 0 ); - for( col = Ncols - 1; col >= 0; col-- ) + for( col = RoutingMatrix.m_Ncols - 1; col >= 0; col-- ) { old_cell_H = 0; - for( row = Nrows - 1; row >= 0; row-- ) + for( row = RoutingMatrix.m_Nrows - 1; row >= 0; row-- ) { - current_cell = GetCell( row, col, BOTTOM ) & NO_CELL_ZONE; + current_cell = RoutingMatrix.GetCell( row, col, BOTTOM ) & NO_CELL_ZONE; if( current_cell == 0 ) /* a free cell is found */ { if( (old_cell_H & CELL_is_ZONE) || (pt_cell_V[row] & CELL_is_ZONE) ) { - OrCell( row, col, BOTTOM, CELL_is_ZONE ); + RoutingMatrix.OrCell( row, col, BOTTOM, CELL_is_ZONE ); current_cell = CELL_is_ZONE; nbpoints++; } @@ -1278,22 +1258,21 @@ int PCB_EDIT_FRAME::propagate() } // Search from bottom to top and left to right. - m_messagePanel->SetMessage( -1, wxEmptyString, wxT( "4" ), CYAN ); fill( pt_cell_V.begin(), pt_cell_V.end(), 0 ); - for( col = 0; col < Ncols; col++ ) + for( col = 0; col < RoutingMatrix.m_Ncols; col++ ) { old_cell_H = 0; - for( row = Nrows - 1; row >= 0; row-- ) + for( row = RoutingMatrix.m_Nrows - 1; row >= 0; row-- ) { - current_cell = GetCell( row, col, BOTTOM ) & NO_CELL_ZONE; + current_cell = RoutingMatrix.GetCell( row, col, BOTTOM ) & NO_CELL_ZONE; if( current_cell == 0 ) /* a free cell is found */ { if( (old_cell_H & CELL_is_ZONE) || (pt_cell_V[row] & CELL_is_ZONE) ) { - OrCell( row, col, BOTTOM, CELL_is_ZONE ); + RoutingMatrix.OrCell( row, col, BOTTOM, CELL_is_ZONE ); current_cell = CELL_is_ZONE; nbpoints++; } diff --git a/pcbnew/autorout.cpp b/pcbnew/autorouter/autorout.cpp similarity index 71% rename from pcbnew/autorout.cpp rename to pcbnew/autorouter/autorout.cpp index 72aa513b71..4819575575 100644 --- a/pcbnew/autorout.cpp +++ b/pcbnew/autorouter/autorout.cpp @@ -3,6 +3,33 @@ * @brief Autorouting command and control. */ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2011 Wayne Stambaugh + * + * Copyright (C) 1992-2012 KiCad Developers, see change_log.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 + */ + #include #include #include @@ -11,25 +38,22 @@ #include #include #include -#include #include #include #include +#include + +#include -int E_scale; /* Scaling factor of distance tables. */ int Nb_Sides; /* Number of layer for autorouting (0 or 1) */ -int Nrows = ILLEGAL; -int Ncols = ILLEGAL; -int Ntotal; int OpenNodes; /* total number of nodes opened */ int ClosNodes; /* total number of nodes closed */ int MoveNodes; /* total number of nodes moved */ int MaxNodes; /* maximum number of nodes opened at one time */ -MATRIX_ROUTING_HEAD Board; /* 2-sided board */ - +MATRIX_ROUTING_HEAD RoutingMatrix; // routing matrix (grid) to route 2-sided boards /* init board, route traces*/ void PCB_EDIT_FRAME::Autoroute( wxDC* DC, int mode ) @@ -139,18 +163,14 @@ void PCB_EDIT_FRAME::Autoroute( wxDC* DC, int mode ) start = time( NULL ); /* Calculation of no fixed routing to 5 mils and more. */ - Board.m_GridRouting = (int)GetScreen()->GetGridSize().x; + RoutingMatrix.m_GridRouting = (int)GetScreen()->GetGridSize().x; - if( Board.m_GridRouting < 50 ) - Board.m_GridRouting = 50; + if( RoutingMatrix.m_GridRouting < (5*IU_PER_MILS) ) + RoutingMatrix.m_GridRouting = 5*IU_PER_MILS; - E_scale = Board.m_GridRouting / 50; - - if( E_scale < 1 ) - E_scale = 1; /* Calculated ncol and nrow, matrix size for routing. */ - Board.ComputeMatrixSize( GetBoard() ); + RoutingMatrix.ComputeMatrixSize( GetBoard() ); m_messagePanel->EraseMsgBox(); @@ -160,10 +180,10 @@ void PCB_EDIT_FRAME::Autoroute( wxDC* DC, int mode ) if( Route_Layer_TOP != Route_Layer_BOTTOM ) Nb_Sides = TWO_SIDES; - if( Board.InitBoard() < 0 ) + if( RoutingMatrix.InitRoutingMatrix() < 0 ) { wxMessageBox( _( "No memory for autorouting" ) ); - Board.UnInitBoard(); /* Free memory. */ + RoutingMatrix.UnInitRoutingMatrix(); /* Free memory. */ return; } @@ -171,9 +191,9 @@ void PCB_EDIT_FRAME::Autoroute( wxDC* DC, int mode ) PlaceCells( GetBoard(), -1, FORCE_PADS ); /* Construction of the track list for router. */ - Build_Work( GetBoard() ); + RoutingMatrix.m_RouteCount = Build_Work( GetBoard() ); - // DisplayBoard(m_canvas, DC); + // DisplayRoutingMatrix( m_canvas, DC ); if( Nb_Sides == TWO_SIDES ) Solve( DC, TWO_SIDES ); /* double face */ @@ -183,7 +203,7 @@ void PCB_EDIT_FRAME::Autoroute( wxDC* DC, int mode ) /* Free memory. */ FreeQueue(); InitWork(); /* Free memory for the list of router connections. */ - Board.UnInitBoard(); + RoutingMatrix.UnInitRoutingMatrix(); stop = time( NULL ) - start; msg.Printf( wxT( "time = %d second%s" ), stop, ( stop == 1 ) ? wxT( "" ) : wxT( "s" ) ); SetStatusText( msg ); @@ -207,13 +227,11 @@ void PCB_EDIT_FRAME::Reset_Noroutable( wxDC* DC ) /* DEBUG Function: displays the routing matrix */ -void DisplayBoard( EDA_DRAW_PANEL* panel, wxDC* DC ) +void DisplayRoutingMatrix( EDA_DRAW_PANEL* panel, wxDC* DC ) { - int row, col, i, j; int dcell0, dcell1 = 0, color; - int maxi; - maxi = 600 / Ncols; + int maxi = 600 / RoutingMatrix.m_Ncols; maxi = ( maxi * 3 ) / 4; if( !maxi ) @@ -221,12 +239,12 @@ void DisplayBoard( EDA_DRAW_PANEL* panel, wxDC* DC ) GRSetDrawMode( DC, GR_COPY ); - for( col = 0; col < Ncols; col++ ) + for( int col = 0; col < RoutingMatrix.m_Ncols; col++ ) { - for( row = 0; row < Nrows; row++ ) + for( int row = 0; row < RoutingMatrix.m_Nrows; row++ ) { color = 0; - dcell0 = GetCell( row, col, BOTTOM ); + dcell0 = RoutingMatrix.GetCell( row, col, BOTTOM ); if( dcell0 & HOLE ) color = GREEN; @@ -251,8 +269,8 @@ void DisplayBoard( EDA_DRAW_PANEL* panel, wxDC* DC ) #define DRAW_OFFSET_Y 20 // if( color ) { - for( i = 0; i < maxi; i++ ) - for( j = 0; j < maxi; j++ ) + for( int i = 0; i < maxi; i++ ) + for( int j = 0; j < maxi; j++ ) GRPutPixel( panel->GetClipBox(), DC, ( col * maxi ) + i + DRAW_OFFSET_X, ( row * maxi ) + j + DRAW_OFFSET_Y, color ); diff --git a/pcbnew/autorouter/autorout.h b/pcbnew/autorouter/autorout.h new file mode 100644 index 0000000000..c6c01f431d --- /dev/null +++ b/pcbnew/autorouter/autorout.h @@ -0,0 +1,232 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2012 Wayne Stambaugh + * + * Copyright (C) 1992-2012 KiCad Developers, see change_log.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 autorout.h + */ + +#ifndef AUTOROUT_H +#define AUTOROUT_H + + +#include + + +class BOARD; + + +#define TOP 0 +#define BOTTOM 1 +#define EMPTY 0 +#define ILLEGAL -1 + + +/* Autorouter commands. */ +enum CommandOpt { + PLACE_ALL, + PLACE_OUT_OF_BOARD, + PLACE_INCREMENTAL, + PLACE_1_MODULE, + + ROUTE_ALL, + ROUTE_NET, + ROUTE_MODULE, + ROUTE_PAD +}; + + +#define ONE_SIDE 0 +#define TWO_SIDES 1 + +#define MAX_SIDES_COUNT 2 + +extern int Nb_Sides; /* Number of layers for autorouting (0 or 1) */ + +#define FORCE_PADS 1 /* Force placement of pads for any Netcode */ + +/* search statistics */ +extern int OpenNodes; /* total number of nodes opened */ +extern int ClosNodes; /* total number of nodes closed */ +extern int MoveNodes; /* total number of nodes moved */ +extern int MaxNodes; /* maximum number of nodes opened at one time */ + + +/* Structures useful to the generation of board as bitmap. */ +typedef char MATRIX_CELL; +typedef int DIST_CELL; +typedef char DIR_CELL; + + +/** + * class MATRIX_ROUTING_HEAD + * handle the matrix routing that describes the actual board + */ +class MATRIX_ROUTING_HEAD +{ +public: + MATRIX_CELL* m_BoardSide[MAX_SIDES_COUNT]; // the image map of 2 board sides + DIST_CELL* m_DistSide[MAX_SIDES_COUNT]; // the image map of 2 board sides: distance to + // cells + DIR_CELL* m_DirSide[MAX_SIDES_COUNT]; // the image map of 2 board sides: pointers back to + // source + bool m_InitMatrixDone; + int m_Layers; // Layer count (1 2 ) + int m_GridRouting; // Size of grid for autoplace/autoroute + EDA_RECT m_BrdBox; // Actual board bounding box + int m_Nrows, m_Ncols; // Matrix size + int m_MemSize; // Memory requirement, just for statistics + int m_RouteCount; // Number of routes +private: + void (MATRIX_ROUTING_HEAD::* m_opWriteCell)( int aRow, int aCol, int aSide, MATRIX_CELL aCell); // a pointeur to the current selected cell op + +public: + MATRIX_ROUTING_HEAD(); + ~MATRIX_ROUTING_HEAD(); + + void WriteCell( int aRow, int aCol, int aSide, MATRIX_CELL aCell) + { + (*this.*m_opWriteCell)( aRow, aCol, aSide, aCell ); + } + + /** + * function GetBrdCoordOrigin + * @returns the board coordinate corresponding to the + * routing matrix origin ( board coordinate offset ) + */ + wxPoint GetBrdCoordOrigin() + { + return m_BrdBox.GetOrigin(); + } + + /** + * Function ComputeMatrixSize + * calculates the number of rows and columns of dimensions of \a aPcb for routing and + * automatic calculation of area. + * @param aPcb = the physical board + * @param aUseBoardEdgesOnly = true to use board edges only, + * = false to use the full board bounding box (default) + */ + bool ComputeMatrixSize( BOARD* aPcb, bool aUseBoardEdgesOnly = false ); + + /** + * Function InitBoard + * initializes the data structures. + * + * @return the amount of memory used or -1 if default. + */ + int InitRoutingMatrix(); + + void UnInitRoutingMatrix(); + + // Initialize WriteCell to make the aLogicOp + void SetCellOperation( int aLogicOp ); + + // functions to read/write one cell ( point on grid routing matrix: + MATRIX_CELL GetCell( int aRow, int aCol, int aSide); + void SetCell( int aRow, int aCol, int aSide, MATRIX_CELL aCell); + void OrCell( int aRow, int aCol, int aSide, MATRIX_CELL aCell); + void XorCell( int aRow, int aCol, int aSide, MATRIX_CELL aCell); + void AndCell( int aRow, int aCol, int aSide, MATRIX_CELL aCell); + void AddCell( int aRow, int aCol, int aSide, MATRIX_CELL aCell); + DIST_CELL GetDist( int aRow, int aCol, int aSide ); + void SetDist( int aRow, int aCol, int aSide, DIST_CELL ); + int GetDir( int aRow, int aCol, int aSide ); + void SetDir( int aRow, int aCol, int aSide, int aDir); +}; + +extern MATRIX_ROUTING_HEAD RoutingMatrix; /* 2-sided board */ + + +/* Constants used to trace the cells on the BOARD */ +#define WRITE_CELL 0 +#define WRITE_OR_CELL 1 +#define WRITE_XOR_CELL 2 +#define WRITE_AND_CELL 3 +#define WRITE_ADD_CELL 4 + +// Functions: + +class PCB_EDIT_FRAME; +class BOARD; +class D_PAD; +class RATSNEST_ITEM; +class TRACK; + + +/* Initialize a color value, the cells included in the board edge of the + * pad surface by pt_pad, with the margin reserved for isolation and the + * half width of the runway + * Parameters: + * Pt_pad: pointer to the description of the pad + * color: mask write in cells + * margin: add a value to the radius or half the score pad + * op_logic: type of writing in the cell (WRITE, OR) + */ +void PlacePad( D_PAD* pt_pad, int type, int marge, int op_logic ); + +/* Draws a segment of track on the board. */ +void TraceSegmentPcb( TRACK* pt_segm, int type, int marge, int op_logic ); + +/* Uses the color value of all cells included in the board + * coord of the rectangle ux0, uy0 (top right corner) + * a ux1, uy1 (lower left corner) (coord PCB) + * the rectangle is horizontal (or vertical) + * masque_layer = mask layers; + * op_logic = WRITE_CELL, WRITE_OR_CELL, WRITE_XOR_CELL, WRITE_AND_CELL + */ +void TraceFilledRectangle( int ux0, int uy0, int ux1, int uy1, + int side, int color, int op_logic); + + +/* Same as above, but the rectangle is inclined angle angle. */ +void TraceFilledRectangle( int ux0, int uy0, int ux1, int uy1, + int angle, int masque_layer, int color, int op_logic ); + +/* QUEUE.CPP */ +void FreeQueue(); +void InitQueue(); +void GetQueue( int *, int *, int *, int *, int * ); +int SetQueue( int, int, int, int, int, int, int ); +void ReSetQueue( int, int, int, int, int, int, int ); + +/* WORK.CPP */ +void InitWork(); +void ReInitWork(); +int SetWork( int, int, int , int, int, RATSNEST_ITEM *, int ); +void GetWork( int *, int *, int *, int *, int *, RATSNEST_ITEM ** ); +void SortWork(); /* order the work items; shortest first */ + +/* DIST.CPP */ +int GetApxDist( int r1, int c1, int r2, int c2 ); +int CalcDist(int x,int y,int z ,int side ); + +/* routing_matrix.cpp */ +int Build_Work( BOARD * Pcb ); +void PlaceCells( BOARD * Pcb, int net_code, int flag = 0 ); + + +#endif // AUTOROUT_H diff --git a/pcbnew/cell.h b/pcbnew/autorouter/cell.h similarity index 73% rename from pcbnew/cell.h rename to pcbnew/autorouter/cell.h index a4116362c0..63b76aeddb 100644 --- a/pcbnew/cell.h +++ b/pcbnew/autorouter/cell.h @@ -2,6 +2,36 @@ * @file cell.h */ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2011 Wayne Stambaugh + * + * Copyright (C) 1992-2012 KiCad Developers, see change_log.txt for contributors. + * + * First copyright (C) Randy Nevin, 1989 (see PCBCA package) + * + * 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 + */ + + #ifndef _CELL_H_ #define _CELL_H_ diff --git a/pcbnew/dist.cpp b/pcbnew/autorouter/dist.cpp similarity index 70% rename from pcbnew/dist.cpp rename to pcbnew/autorouter/dist.cpp index e5359d5842..8bc91921cf 100644 --- a/pcbnew/dist.cpp +++ b/pcbnew/autorouter/dist.cpp @@ -3,20 +3,41 @@ * @brief Routines to calculate PCB editor auto routing distances. */ -#include -#include -#include -#include +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors. + * + * First copyright (C) Randy Nevin, 1989 (see PCBCA package) + * + * 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 + */ #include #include -/* The tables of distances and keep out areas are established on the basis of not - * routing of 50 units (the pitch between the cells is 50 units) The true distance - * is computed by a scaling factor +/* The tables of distances and keep out areas are established on the basis of a + * 50 units grid size (the pitch between the cells is 50 units). + * The actual distance could be computed by a scaling factor, but this is + * not needed, we can use only reduced values */ - /* calculate approximate distance + /* calculate approximate distance (manhattan distance) */ int GetApxDist( int r1, int c1, int r2, int c2 ) { @@ -28,27 +49,13 @@ int GetApxDist( int r1, int c1, int r2, int c2 ) if( ( d2 = c1 - c2 ) < 0 ) /* get absolute column delta */ d2 = -d2; - return ( d1+d2 ) * 50 * E_scale; - - if( !d1 ) /* in same row? */ - return d2 * 50 * E_scale; /* 50 mils per cell */ - - if( !d2 ) /* in same column? */ - return d1 *50 * E_scale; /* 50 mils per cell */ - - if( d1 > d2 ) /* get smaller into d1 */ - { - EXCHG(d1,d2); - } - - d2 -= d1; /* get non-diagonal part of approximate "route" */ - - return ( ( ( d1 * 71 ) + ( d2 * 50 ) ) * E_scale ); /* 71 mils diagonally per cell */ + return ( d1+d2 ) * 50; } /* distance to go thru a cell (en mils) */ -static int dist[10][10] = { /* OT=Otherside, OR=Origin (source) cell */ +static const int dist[10][10] = +{ /* OT=Otherside, OR=Origin (source) cell */ /*..........N, NE, E, SE, S, SW, W, NW, OT, OR */ /* N */ { 50, 60, 35, 60, 99, 60, 35, 60, 12, 12 }, /* NE */ { 60, 71, 60, 71, 60, 99, 60, 71, 23, 23 }, @@ -61,10 +68,11 @@ static int dist[10][10] = { /* OT=Otherside, OR=Origin (source) cell */ /* OT */ { 12, 23, 12, 23, 12, 23, 12, 23, 99, 99 }, /* OR */ { 99, 99, 99, 99, 99, 99, 99, 99, 99, 99 } - }; +}; /* penalty for extraneous holes and corners, scaled by sharpness of turn */ -static int penalty[10][10] = { /* OT=Otherside, OR=Origin (source) cell */ +static const int penalty[10][10] = +{ /* OT=Otherside, OR=Origin (source) cell */ /*......... N, NE, E, SE, S, SW, W, NW, OT, OR */ /* N */ { 0, 5, 10, 15, 20, 15, 10, 5, 50, 0 }, /* NE */ { 5, 0, 5, 10, 15, 20, 15, 10, 50, 0 }, @@ -77,11 +85,12 @@ static int penalty[10][10] = { /* OT=Otherside, OR=Origin (source) cell */ /* OT */ { 50, 50, 50, 50, 50, 50, 50, 50, 100, 0 }, /* OR */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } - }; +}; /* penalty pour directions preferencielles */ #define PN 20 -static int dir_penalty_TOP[10][10] = { +static const int dir_penalty_TOP[10][10] = +{ /* OT=Otherside, OR=Origin (source) cell */ /*......... N, NE, E, SE, S, SW, W, NW, OT, OR */ /* N */ { PN, 0, 0, 0, PN, 0, 0, 0, 0, 0 }, @@ -95,9 +104,10 @@ static int dir_penalty_TOP[10][10] = { /* OT */ { PN, 0, 0, 0, PN, 0, 0, 0, 0, 0 }, /* OR */ { PN, 0, 0, 0, PN, 0, 0, 0, 0, 0 } - }; +}; -static int dir_penalty_BOTTOM[10][10] = { +static int dir_penalty_BOTTOM[10][10] = +{ /* OT=Otherside, OR=Origin (source) cell */ /*......... N, NE, E, SE, S, SW, W, NW, OT, OR */ /* N */ { 0, 0, PN, 0, 0, 0, PN, 0, 0, 0 }, @@ -111,7 +121,7 @@ static int dir_penalty_BOTTOM[10][10] = { /* OT */ { 0, 0, PN, 0, 0, 0, PN, 0, 0, 0 }, /* OR */ { 0, 0, PN, 0, 0, 0, PN, 0, 0, 0 } - }; +}; /* ** x is the direction to enter the cell of interest. @@ -122,11 +132,9 @@ static int dir_penalty_BOTTOM[10][10] = { ** the calculation is driven by the tables above. */ -/************************************/ -/* int CalcDist(int x,int y,int z ) */ -/************************************/ - /* calculate distance of a trace through a cell */ +/* calculate distance (with penalty) of a trace through a cell +*/ int CalcDist(int x,int y,int z ,int side ) { int adjust, ldist; diff --git a/pcbnew/graphpcb.cpp b/pcbnew/autorouter/graphpcb.cpp similarity index 61% rename from pcbnew/graphpcb.cpp rename to pcbnew/autorouter/graphpcb.cpp index 90204e1390..77d137ab55 100644 --- a/pcbnew/graphpcb.cpp +++ b/pcbnew/autorouter/graphpcb.cpp @@ -3,6 +3,33 @@ * @brief PCB editor autorouting and "graphics" routines. */ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2011 Wayne Stambaugh + * + * Copyright (C) 1992-2012 KiCad Developers, see change_log.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 + */ + #include #include #include @@ -13,38 +40,24 @@ #include #include +#include #include -#include - - -int ToMatrixCoordinate( int aPhysicalCoordinate ); void TracePcbLine( int x0, int y0, int x1, int y1, int layer, int color ); -void TraceArc( int ux0, - int uy0, - int ux1, - int uy1, +void TraceArc( int ux0, int uy0, + int ux1, int uy1, int ArcAngle, - int lg, - int layer, - int color, + int lg, int layer, int color, int op_logic ); -static void DrawSegmentQcq( int ux0, - int uy0, - int ux1, - int uy1, - int lg, - int layer, - int color, +static void DrawSegmentQcq( int ux0, int uy0, + int ux1, int uy1, + int lg, int layer, int color, int op_logic ); -static void TraceFilledCircle( BOARD* aPcb, - int cx, - int cy, - int radius, +static void TraceFilledCircle( int cx, int cy, int radius, int aLayerMask, int color, int op_logic ); @@ -57,34 +70,21 @@ static void TraceCircle( int ux0, int uy0, int ux1, int uy1, int lg, int layer, { \ if( layer < 0 ) \ { \ - WriteCell( dy, dx, BOTTOM, color ); \ + RoutingMatrix.WriteCell( dy, dx, BOTTOM, color ); \ if( Nb_Sides ) \ - WriteCell( dy, dx, TOP, color ); \ + RoutingMatrix.WriteCell( dy, dx, TOP, color ); \ } \ else \ { \ if( layer == Route_Layer_BOTTOM ) \ - WriteCell( dy, dx, BOTTOM, color ); \ + RoutingMatrix.WriteCell( dy, dx, BOTTOM, color ); \ if( Nb_Sides ) \ if( layer == Route_Layer_TOP ) \ - WriteCell( dy, dx, TOP, color ); \ + RoutingMatrix.WriteCell( dy, dx, TOP, color ); \ } \ } - -/** - * Function ToMatrixCoordinate - * compute the coordinate in the routing matrix from the real (board) value - * @param aPhysicalCoordinate = value to convert - * @return the coordinate relative to the matrix - */ -int ToMatrixCoordinate( int aPhysicalCoordinate ) -{ - return aPhysicalCoordinate / Board.m_GridRouting; -} - - -void PlacePad( BOARD* aPcb, D_PAD* aPad, int color, int marge, int op_logic ) +void PlacePad( D_PAD* aPad, int color, int marge, int op_logic ) { int dx, dy; wxPoint shape_pos = aPad->ReturnShapePos(); @@ -94,7 +94,7 @@ void PlacePad( BOARD* aPcb, D_PAD* aPad, int color, int marge, int op_logic ) if( aPad->GetShape() == PAD_CIRCLE ) { - TraceFilledCircle( aPcb, shape_pos.x, shape_pos.y, dx, + TraceFilledCircle( shape_pos.x, shape_pos.y, dx, aPad->GetLayerMask(), color, op_logic ); return; } @@ -108,7 +108,7 @@ void PlacePad( BOARD* aPcb, D_PAD* aPad, int color, int marge, int op_logic ) dy += abs( aPad->GetDelta().x ) / 2; } - // The pad is a rectangle horizontally or vertically. + // The pad is a rectangle ( horizontal or vertical ) if( int( aPad->GetOrientation() ) % 900 == 0 ) { // Orientation turned 90 deg. @@ -117,13 +117,13 @@ void PlacePad( BOARD* aPcb, D_PAD* aPad, int color, int marge, int op_logic ) EXCHG( dx, dy ); } - TraceFilledRectangle( aPcb, shape_pos.x - dx, shape_pos.y - dy, + TraceFilledRectangle( shape_pos.x - dx, shape_pos.y - dy, shape_pos.x + dx, shape_pos.y + dy, aPad->GetLayerMask(), color, op_logic ); } else { - TraceFilledRectangle( aPcb, shape_pos.x - dx, shape_pos.y - dy, + TraceFilledRectangle( shape_pos.x - dx, shape_pos.y - dy, shape_pos.x + dx, shape_pos.y + dy, (int) aPad->GetOrientation(), aPad->GetLayerMask(), color, op_logic ); @@ -131,18 +131,15 @@ void PlacePad( BOARD* aPcb, D_PAD* aPad, int color, int marge, int op_logic ) } -/* Initialize a color value, the cells included in the board area of the - * circle center cx, cy. +/* Set to color the cells included in the circle * Parameters: + * center: cx, cy. * radius: a value add to the radius or half the score pad * aLayerMask: layer occupied * color: mask write in cells * op_logic: type of writing in the cell (WRITE, OR) */ -void TraceFilledCircle( BOARD* aPcb, - int cx, - int cy, - int radius, +void TraceFilledCircle( int cx, int cy, int radius, int aLayerMask, int color, int op_logic ) @@ -151,17 +148,10 @@ void TraceFilledCircle( BOARD* aPcb, int ux0, uy0, ux1, uy1; int row_max, col_max, row_min, col_min; int trace = 0; - float fdistmin, fdistx, fdisty; - - void (* WriteCell)( int, int, int, MATRIX_CELL ); + double fdistmin, fdistx, fdisty; int tstwrite = 0; int distmin; - // Determine occupied layer. - - /* Single routing layer on bitmap and BOTTOM - * Route_Layer_B = Route_Layer_A */ - if( aLayerMask & GetLayerMask( Route_Layer_BOTTOM ) ) trace = 1; // Trace on BOTTOM @@ -172,32 +162,10 @@ void TraceFilledCircle( BOARD* aPcb, if( trace == 0 ) return; - switch( op_logic ) - { - default: - case WRITE_CELL: - WriteCell = SetCell; - break; + RoutingMatrix.SetCellOperation( op_logic ); - case WRITE_OR_CELL: - WriteCell = OrCell; - break; - - case WRITE_XOR_CELL: - WriteCell = XorCell; - break; - - case WRITE_AND_CELL: - WriteCell = AndCell; - break; - - case WRITE_ADD_CELL: - WriteCell = AddCell; - break; - } - - cx -= aPcb->GetBoundingBox().GetX(); - cy -= aPcb->GetBoundingBox().GetY(); + cx -= RoutingMatrix.GetBrdCoordOrigin().x; + cy -= RoutingMatrix.GetBrdCoordOrigin().y; distmin = radius; @@ -208,22 +176,22 @@ void TraceFilledCircle( BOARD* aPcb, uy1 = cy + radius; // Calculate limit coordinates of cells belonging to the rectangle. - row_max = uy1 / Board.m_GridRouting; - col_max = ux1 / Board.m_GridRouting; - row_min = uy0 / Board.m_GridRouting; // if (uy0 > row_min*Board.m_GridRouting) row_min++; - col_min = ux0 / Board.m_GridRouting; // if (ux0 > col_min*Board.m_GridRouting) col_min++; + row_max = uy1 / RoutingMatrix.m_GridRouting; + col_max = ux1 / RoutingMatrix.m_GridRouting; + row_min = uy0 / RoutingMatrix.m_GridRouting; // if (uy0 > row_min*Board.m_GridRouting) row_min++; + col_min = ux0 / RoutingMatrix.m_GridRouting; // if (ux0 > col_min*Board.m_GridRouting) col_min++; if( row_min < 0 ) row_min = 0; - if( row_max >= (Nrows - 1) ) - row_max = Nrows - 1; + if( row_max >= (RoutingMatrix.m_Nrows - 1) ) + row_max = RoutingMatrix.m_Nrows - 1; if( col_min < 0 ) col_min = 0; - if( col_max >= (Ncols - 1) ) - col_max = Ncols - 1; + if( col_max >= (RoutingMatrix.m_Ncols - 1) ) + col_max = RoutingMatrix.m_Ncols - 1; // Calculate coordinate limits of cell belonging to the rectangle. if( row_min > row_max ) @@ -232,26 +200,26 @@ void TraceFilledCircle( BOARD* aPcb, if( col_min > col_max ) col_max = col_min; - fdistmin = (float) distmin * distmin; + fdistmin = (double) distmin * distmin; for( row = row_min; row <= row_max; row++ ) { - fdisty = (float) ( cy - ( row * Board.m_GridRouting ) ); + fdisty = (double) ( cy - ( row * RoutingMatrix.m_GridRouting ) ); fdisty *= fdisty; for( col = col_min; col <= col_max; col++ ) { - fdistx = (float) ( cx - ( col * Board.m_GridRouting ) ); + fdistx = (double) ( cx - ( col * RoutingMatrix.m_GridRouting ) ); fdistx *= fdistx; if( fdistmin <= ( fdistx + fdisty ) ) continue; if( trace & 1 ) - WriteCell( row, col, BOTTOM, color ); + RoutingMatrix.WriteCell( row, col, BOTTOM, color ); if( trace & 2 ) - WriteCell( row, col, TOP, color ); + RoutingMatrix.WriteCell( row, col, TOP, color ); tstwrite = 1; } @@ -263,33 +231,33 @@ void TraceFilledCircle( BOARD* aPcb, /* If no cell has been written, it affects the 4 neighboring diagonal * (Adverse event: pad off grid in the center of the 4 neighboring * diagonal) */ - distmin = Board.m_GridRouting / 2 + 1; - fdistmin = ( (float) distmin * distmin ) * 2; // Distance to center point diagonally + distmin = RoutingMatrix.m_GridRouting / 2 + 1; + fdistmin = ( (double) distmin * distmin ) * 2; // Distance to center point diagonally for( row = row_min; row <= row_max; row++ ) { - fdisty = (float) ( cy - ( row * Board.m_GridRouting ) ); + fdisty = (double) ( cy - ( row * RoutingMatrix.m_GridRouting ) ); fdisty *= fdisty; for( col = col_min; col <= col_max; col++ ) { - fdistx = (float) ( cx - ( col * Board.m_GridRouting ) ); + fdistx = (double) ( cx - ( col * RoutingMatrix.m_GridRouting ) ); fdistx *= fdistx; if( fdistmin <= ( fdistx + fdisty ) ) continue; if( trace & 1 ) - WriteCell( row, col, BOTTOM, color ); + RoutingMatrix.WriteCell( row, col, BOTTOM, color ); if( trace & 2 ) - WriteCell( row, col, TOP, color ); + RoutingMatrix.WriteCell( row, col, TOP, color ); } } } -void TraceSegmentPcb( BOARD* aPcb, TRACK* pt_segm, int color, int marge, int op_logic ) +void TraceSegmentPcb( TRACK* pt_segm, int color, int marge, int op_logic ) { int half_width; int ux0, uy0, ux1, uy1; @@ -297,10 +265,10 @@ void TraceSegmentPcb( BOARD* aPcb, TRACK* pt_segm, int color, int marge, int op_ half_width = ( pt_segm->m_Width / 2 ) + marge; // Calculate the bounding rectangle of the segment (if H, V or Via) - ux0 = pt_segm->m_Start.x - aPcb->GetBoundingBox().GetX(); - uy0 = pt_segm->m_Start.y - aPcb->GetBoundingBox().GetY(); - ux1 = pt_segm->m_End.x - aPcb->GetBoundingBox().GetX(); - uy1 = pt_segm->m_End.y - aPcb->GetBoundingBox().GetY(); + ux0 = pt_segm->m_Start.x - RoutingMatrix.GetBrdCoordOrigin().x; + uy0 = pt_segm->m_Start.y - RoutingMatrix.GetBrdCoordOrigin().y; + ux1 = pt_segm->m_End.x - RoutingMatrix.GetBrdCoordOrigin().x; + uy1 = pt_segm->m_End.y - RoutingMatrix.GetBrdCoordOrigin().y; // Test if VIA (filled circle was drawn) if( pt_segm->Type() == PCB_VIA_T ) @@ -322,7 +290,7 @@ void TraceSegmentPcb( BOARD* aPcb, TRACK* pt_segm, int color, int marge, int op_ mask_layer = -1; if( mask_layer ) - TraceFilledCircle( aPcb, pt_segm->m_Start.x, pt_segm->m_Start.y, + TraceFilledCircle( pt_segm->m_Start.x, pt_segm->m_Start.y, half_width, mask_layer, color, op_logic ); return; } @@ -365,45 +333,26 @@ void TracePcbLine( int x0, int y0, int x1, int y1, int layer, int color, int op_ int dx, dy, lim; int cumul, inc, il, delta; - void (* WriteCell)( int, int, int, MATRIX_CELL ); - - switch( op_logic ) - { - default: - case WRITE_CELL: - WriteCell = SetCell; break; - - case WRITE_OR_CELL: - WriteCell = OrCell; break; - - case WRITE_XOR_CELL: - WriteCell = XorCell; break; - - case WRITE_AND_CELL: - WriteCell = AndCell; break; - - case WRITE_ADD_CELL: - WriteCell = AddCell; break; - } + RoutingMatrix.SetCellOperation( op_logic ); if( x0 == x1 ) // Vertical. { if( y1 < y0 ) EXCHG( y0, y1 ); - dy = y0 / Board.m_GridRouting; - lim = y1 / Board.m_GridRouting; - dx = x0 / Board.m_GridRouting; + dy = y0 / RoutingMatrix.m_GridRouting; + lim = y1 / RoutingMatrix.m_GridRouting; + dx = x0 / RoutingMatrix.m_GridRouting; // Clipping limits of board. - if( ( dx < 0 ) || ( dx >= Ncols ) ) + if( ( dx < 0 ) || ( dx >= RoutingMatrix.m_Ncols ) ) return; if( dy < 0 ) dy = 0; - if( lim >= Nrows ) - lim = Nrows - 1; + if( lim >= RoutingMatrix.m_Nrows ) + lim = RoutingMatrix.m_Nrows - 1; for( ; dy <= lim; dy++ ) { @@ -418,19 +367,19 @@ void TracePcbLine( int x0, int y0, int x1, int y1, int layer, int color, int op_ if( x1 < x0 ) EXCHG( x0, x1 ); - dx = x0 / Board.m_GridRouting; - lim = x1 / Board.m_GridRouting; - dy = y0 / Board.m_GridRouting; + dx = x0 / RoutingMatrix.m_GridRouting; + lim = x1 / RoutingMatrix.m_GridRouting; + dy = y0 / RoutingMatrix.m_GridRouting; // Clipping limits of board. - if( ( dy < 0 ) || ( dy >= Nrows ) ) + if( ( dy < 0 ) || ( dy >= RoutingMatrix.m_Nrows ) ) return; if( dx < 0 ) dx = 0; - if( lim >= Ncols ) - lim = Ncols - 1; + if( lim >= RoutingMatrix.m_Ncols ) + lim = RoutingMatrix.m_Ncols - 1; for( ; dx <= lim; dx++ ) { @@ -448,20 +397,20 @@ void TracePcbLine( int x0, int y0, int x1, int y1, int layer, int color, int op_ EXCHG( x1, x0 ); EXCHG( y1, y0 ); } - dx = x0 / Board.m_GridRouting; - lim = x1 / Board.m_GridRouting; - dy = y0 / Board.m_GridRouting; + dx = x0 / RoutingMatrix.m_GridRouting; + lim = x1 / RoutingMatrix.m_GridRouting; + dy = y0 / RoutingMatrix.m_GridRouting; inc = 1; if( y1 < y0 ) inc = -1; il = lim - dx; cumul = il / 2; - delta = abs( y1 - y0 ) / Board.m_GridRouting; + delta = abs( y1 - y0 ) / RoutingMatrix.m_GridRouting; for( ; dx <= lim; ) { - if( ( dx >= 0 ) && ( dy >= 0 ) && ( dx < Ncols ) && ( dy < Nrows ) ) + if( ( dx >= 0 ) && ( dy >= 0 ) && ( dx < RoutingMatrix.m_Ncols ) && ( dy < RoutingMatrix.m_Nrows ) ) { OP_CELL( layer, dy, dx ); } @@ -484,20 +433,21 @@ void TracePcbLine( int x0, int y0, int x1, int y1, int layer, int color, int op_ EXCHG( y1, y0 ); } - dy = y0 / Board.m_GridRouting; - lim = y1 / Board.m_GridRouting; - dx = x0 / Board.m_GridRouting; + dy = y0 / RoutingMatrix.m_GridRouting; + lim = y1 / RoutingMatrix.m_GridRouting; + dx = x0 / RoutingMatrix.m_GridRouting; inc = 1; if( x1 < x0 ) inc = -1; - il = lim - dy; cumul = il / 2; - delta = abs( x1 - x0 ) / Board.m_GridRouting; + il = lim - dy; + cumul = il / 2; + delta = abs( x1 - x0 ) / RoutingMatrix.m_GridRouting; for( ; dy <= lim; ) { - if( ( dx >= 0 ) && ( dy >= 0 ) && ( dx < Ncols ) && ( dy < Nrows ) ) + if( ( dx >= 0 ) && ( dy >= 0 ) && ( dx < RoutingMatrix.m_Ncols ) && ( dy < RoutingMatrix.m_Nrows ) ) { OP_CELL( layer, dy, dx ); } @@ -515,15 +465,13 @@ void TracePcbLine( int x0, int y0, int x1, int y1, int layer, int color, int op_ } -void TraceFilledRectangle( BOARD* aPcb, int ux0, int uy0, int ux1, int uy1, +void TraceFilledRectangle( int ux0, int uy0, int ux1, int uy1, int aLayerMask, int color, int op_logic ) { int row, col; int row_min, row_max, col_min, col_max; int trace = 0; - void (* WriteCell)( int, int, int, MATRIX_CELL ); - if( ( aLayerMask & GetLayerMask( Route_Layer_BOTTOM ) ) ) trace = 1; // Trace on BOTTOM @@ -533,75 +481,53 @@ void TraceFilledRectangle( BOARD* aPcb, int ux0, int uy0, int ux1, int uy1, if( trace == 0 ) return; - switch( op_logic ) - { - default: - case WRITE_CELL: - WriteCell = SetCell; - break; + RoutingMatrix.SetCellOperation( op_logic ); - case WRITE_OR_CELL: - WriteCell = OrCell; - break; - - case WRITE_XOR_CELL: - WriteCell = XorCell; - break; - - case WRITE_AND_CELL: - WriteCell = AndCell; - break; - - case WRITE_ADD_CELL: - WriteCell = AddCell; - break; - } - - ux0 -= aPcb->GetBoundingBox().GetX(); - uy0 -= aPcb->GetBoundingBox().GetY(); - ux1 -= aPcb->GetBoundingBox().GetX(); - uy1 -= aPcb->GetBoundingBox().GetY(); + ux0 -= RoutingMatrix.GetBrdCoordOrigin().x; + uy0 -= RoutingMatrix.GetBrdCoordOrigin().y; + ux1 -= RoutingMatrix.GetBrdCoordOrigin().x; + uy1 -= RoutingMatrix.GetBrdCoordOrigin().y; // Calculating limits coord cells belonging to the rectangle. - row_max = uy1 / Board.m_GridRouting; - col_max = ux1 / Board.m_GridRouting; - row_min = uy0 / Board.m_GridRouting; + row_max = uy1 / RoutingMatrix.m_GridRouting; + col_max = ux1 / RoutingMatrix.m_GridRouting; + row_min = uy0 / RoutingMatrix.m_GridRouting; - if( uy0 > row_min * Board.m_GridRouting ) + if( uy0 > row_min * RoutingMatrix.m_GridRouting ) row_min++; - col_min = ux0 / Board.m_GridRouting; + col_min = ux0 / RoutingMatrix.m_GridRouting; - if( ux0 > col_min * Board.m_GridRouting ) + if( ux0 > col_min * RoutingMatrix.m_GridRouting ) col_min++; if( row_min < 0 ) row_min = 0; - if( row_max >= ( Nrows - 1 ) ) - row_max = Nrows - 1; + if( row_max >= ( RoutingMatrix.m_Nrows - 1 ) ) + row_max = RoutingMatrix.m_Nrows - 1; if( col_min < 0 ) col_min = 0; - if( col_max >= ( Ncols - 1 ) ) - col_max = Ncols - 1; + if( col_max >= ( RoutingMatrix.m_Ncols - 1 ) ) + col_max = RoutingMatrix.m_Ncols - 1; for( row = row_min; row <= row_max; row++ ) { for( col = col_min; col <= col_max; col++ ) { if( trace & 1 ) - WriteCell( row, col, BOTTOM, color ); + RoutingMatrix.WriteCell( row, col, BOTTOM, color ); if( trace & 2 ) - WriteCell( row, col, TOP, color ); + RoutingMatrix.WriteCell( row, col, TOP, color ); } } } -void TraceFilledRectangle( BOARD* aPcb, int ux0, int uy0, int ux1, int uy1, +void TraceFilledRectangle( int ux0, int uy0, int ux1, int uy1, int angle, int aLayerMask, int color, int op_logic ) { int row, col; @@ -611,8 +537,6 @@ void TraceFilledRectangle( BOARD* aPcb, int ux0, int uy0, int ux1, int uy1, int rotrow, rotcol; int trace = 0; - void (* WriteCell)( int, int, int, MATRIX_CELL ); - if( aLayerMask & GetLayerMask( Route_Layer_BOTTOM ) ) trace = 1; // Trace on BOTTOM @@ -625,34 +549,12 @@ void TraceFilledRectangle( BOARD* aPcb, int ux0, int uy0, int ux1, int uy1, if( trace == 0 ) return; - switch( op_logic ) - { - default: - case WRITE_CELL: - WriteCell = SetCell; - break; + RoutingMatrix.SetCellOperation( op_logic ); - case WRITE_OR_CELL: - WriteCell = OrCell; - break; - - case WRITE_XOR_CELL: - WriteCell = XorCell; - break; - - case WRITE_AND_CELL: - WriteCell = AndCell; - break; - - case WRITE_ADD_CELL: - WriteCell = AddCell; - break; - } - - ux0 -= aPcb->GetBoundingBox().GetX(); - uy0 -= aPcb->GetBoundingBox().GetY(); - ux1 -= aPcb->GetBoundingBox().GetX(); - uy1 -= aPcb->GetBoundingBox().GetY(); + ux0 -= RoutingMatrix.GetBrdCoordOrigin().x; + uy0 -= RoutingMatrix.GetBrdCoordOrigin().y; + ux1 -= RoutingMatrix.GetBrdCoordOrigin().x; + uy1 -= RoutingMatrix.GetBrdCoordOrigin().y; cx = (ux0 + ux1) / 2; cy = (uy0 + uy1) / 2; @@ -660,36 +562,36 @@ void TraceFilledRectangle( BOARD* aPcb, int ux0, int uy0, int ux1, int uy1, + (double) ( cy - uy0 ) * ( cy - uy0 ) ); // Calculating coordinate limits belonging to the rectangle. - row_max = ( cy + radius ) / Board.m_GridRouting; - col_max = ( cx + radius ) / Board.m_GridRouting; - row_min = ( cy - radius ) / Board.m_GridRouting; + row_max = ( cy + radius ) / RoutingMatrix.m_GridRouting; + col_max = ( cx + radius ) / RoutingMatrix.m_GridRouting; + row_min = ( cy - radius ) / RoutingMatrix.m_GridRouting; - if( uy0 > row_min * Board.m_GridRouting ) + if( uy0 > row_min * RoutingMatrix.m_GridRouting ) row_min++; - col_min = ( cx - radius ) / Board.m_GridRouting; + col_min = ( cx - radius ) / RoutingMatrix.m_GridRouting; - if( ux0 > col_min * Board.m_GridRouting ) + if( ux0 > col_min * RoutingMatrix.m_GridRouting ) col_min++; if( row_min < 0 ) row_min = 0; - if( row_max >= ( Nrows - 1 ) ) - row_max = Nrows - 1; + if( row_max >= ( RoutingMatrix.m_Nrows - 1 ) ) + row_max = RoutingMatrix.m_Nrows - 1; if( col_min < 0 ) col_min = 0; - if( col_max >= ( Ncols - 1 ) ) - col_max = Ncols - 1; + if( col_max >= ( RoutingMatrix.m_Ncols - 1 ) ) + col_max = RoutingMatrix.m_Ncols - 1; for( row = row_min; row <= row_max; row++ ) { for( col = col_min; col <= col_max; col++ ) { - rotrow = row * Board.m_GridRouting; - rotcol = col * Board.m_GridRouting; + rotrow = row * RoutingMatrix.m_GridRouting; + rotcol = col * RoutingMatrix.m_GridRouting; RotatePoint( &rotcol, &rotrow, cx, cy, -angle ); if( rotrow <= uy0 ) @@ -705,19 +607,18 @@ void TraceFilledRectangle( BOARD* aPcb, int ux0, int uy0, int ux1, int uy1, continue; if( trace & 1 ) - WriteCell( row, col, BOTTOM, color ); + RoutingMatrix.WriteCell( row, col, BOTTOM, color ); if( trace & 2 ) - WriteCell( row, col, TOP, color ); + RoutingMatrix.WriteCell( row, col, TOP, color ); } } } /* Fills all cells inside a segment - * half-width lg, org ux, ux end y0, y1 - * is set to color. - * coordinates are in PCB units (0.1 mil) are relative to the Board + * half-width = lg, org = ux0,uy0 end = ux1,uy1 + * coordinates are in PCB units */ void DrawSegmentQcq( int ux0, int uy0, int ux1, int uy1, int lg, int layer, int color, int op_logic ) @@ -727,33 +628,10 @@ void DrawSegmentQcq( int ux0, int uy0, int ux1, int uy1, int lg, int layer, int row_max, col_max, row_min, col_min; int demi_pas; - void (* WriteCell)( int, int, int, MATRIX_CELL ); int angle; int cx, cy, dx, dy; - switch( op_logic ) - { - default: - case WRITE_CELL: - WriteCell = SetCell; - break; - - case WRITE_OR_CELL: - WriteCell = OrCell; - break; - - case WRITE_XOR_CELL: - WriteCell = XorCell; - break; - - case WRITE_AND_CELL: - WriteCell = AndCell; - break; - - case WRITE_ADD_CELL: - WriteCell = AddCell; - break; - } + RoutingMatrix.SetCellOperation( op_logic ); // Make coordinate ux1 tj > ux0 to simplify calculations if( ux1 < ux0 ) @@ -768,40 +646,40 @@ void DrawSegmentQcq( int ux0, int uy0, int ux1, int uy1, int lg, int layer, if( uy1 < uy0 ) inc = -1; - demi_pas = Board.m_GridRouting / 2; + demi_pas = RoutingMatrix.m_GridRouting / 2; - col_min = ( ux0 - lg ) / Board.m_GridRouting; + col_min = ( ux0 - lg ) / RoutingMatrix.m_GridRouting; if( col_min < 0 ) col_min = 0; - col_max = ( ux1 + lg + demi_pas ) / Board.m_GridRouting; + col_max = ( ux1 + lg + demi_pas ) / RoutingMatrix.m_GridRouting; - if( col_max > ( Ncols - 1 ) ) - col_max = Ncols - 1; + if( col_max > ( RoutingMatrix.m_Ncols - 1 ) ) + col_max = RoutingMatrix.m_Ncols - 1; if( inc > 0 ) { - row_min = ( uy0 - lg ) / Board.m_GridRouting; - row_max = ( uy1 + lg + demi_pas ) / Board.m_GridRouting; + row_min = ( uy0 - lg ) / RoutingMatrix.m_GridRouting; + row_max = ( uy1 + lg + demi_pas ) / RoutingMatrix.m_GridRouting; } else { - row_min = ( uy1 - lg ) / Board.m_GridRouting; - row_max = ( uy0 + lg + demi_pas ) / Board.m_GridRouting; + row_min = ( uy1 - lg ) / RoutingMatrix.m_GridRouting; + row_max = ( uy0 + lg + demi_pas ) / RoutingMatrix.m_GridRouting; } if( row_min < 0 ) row_min = 0; - if( row_min > ( Nrows - 1 ) ) - row_min = Nrows - 1; + if( row_min > ( RoutingMatrix.m_Nrows - 1 ) ) + row_min = RoutingMatrix.m_Nrows - 1; if( row_max < 0 ) row_max = 0; - if( row_max > ( Nrows - 1 ) ) - row_max = Nrows - 1; + if( row_max > ( RoutingMatrix.m_Nrows - 1 ) ) + row_max = RoutingMatrix.m_Nrows - 1; dx = ux1 - ux0; dy = uy1 - uy0; @@ -823,11 +701,11 @@ void DrawSegmentQcq( int ux0, int uy0, int ux1, int uy1, int lg, int layer, for( col = col_min; col <= col_max; col++ ) { int cxr; - cxr = ( col * Board.m_GridRouting ) - ux0; + cxr = ( col * RoutingMatrix.m_GridRouting ) - ux0; for( row = row_min; row <= row_max; row++ ) { - cy = (row * Board.m_GridRouting) - uy0; + cy = (row * RoutingMatrix.m_GridRouting) - uy0; cx = cxr; RotatePoint( &cx, &cy, angle ); @@ -864,10 +742,9 @@ void DrawSegmentQcq( int ux0, int uy0, int ux1, int uy1, int lg, int layer, } -/* Fills all cells BOARD contained in the circle - * half-width lg center ux, ux through y0, y1 is set to color. - * coord in PCB units (0.1 million) relating to the origin - * pt_pcb-> m_PcbBox.m_Xmin, Y's board. +/* Fills all cells of the routing matrix contained in the circle + * half-width = lg, center = ux0, uy0, ux1,uy1 is a point on the circle. + * coord are in PCB units. */ void TraceCircle( int ux0, int uy0, int ux1, int uy1, int lg, int layer, int color, int op_logic ) @@ -908,9 +785,10 @@ void TraceCircle( int ux0, int uy0, int ux1, int uy1, int lg, int layer, } -/* Fills all BOARD cells contained in the arc of "L" angle half-width lg - * ux center, starting in ux y0, y1 is set to color. Coordinates are in - * PCB units (0.1 mil) relating to the origin pt_pcb-> Pcb_oX, Y's board. +/* Fills all routing matrix cells contained in the arc + * angle = ArcAngle, half-width lg + * center = ux0,uy0, starting at ux1, uy1. Coordinates are in + * PCB units. */ void TraceArc( int ux0, int uy0, int ux1, int uy1, int ArcAngle, int lg, int layer, int color, int op_logic ) diff --git a/pcbnew/queue.cpp b/pcbnew/autorouter/queue.cpp similarity index 94% rename from pcbnew/queue.cpp rename to pcbnew/autorouter/queue.cpp index eb9384de41..cf82a63633 100644 --- a/pcbnew/queue.cpp +++ b/pcbnew/autorouter/queue.cpp @@ -1,9 +1,13 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck * Copyright (C) 2011 Wayne Stambaugh - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * + * Copyright (C) 1992-2012 KiCad Developers, see change_log.txt for contributors. + * + * First copyright (C) Randy Nevin, 1989 (see PCBCA package) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -23,6 +27,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ + /** * @file queue.cpp */ diff --git a/pcbnew/board.cpp b/pcbnew/autorouter/routing_matrix.cpp similarity index 68% rename from pcbnew/board.cpp rename to pcbnew/autorouter/routing_matrix.cpp index 34647529fe..e48c35ab37 100644 --- a/pcbnew/board.cpp +++ b/pcbnew/autorouter/routing_matrix.cpp @@ -1,9 +1,11 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2008-2011 Wayne Stambaugh - * Copyright (C) 2004-2011 KiCad Developers, see change_log.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2011 Wayne Stambaugh + * + * Copyright (C) 1992-2012 KiCad Developers, see change_log.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 @@ -34,7 +36,7 @@ #include #include -#include +#include #include #include @@ -44,14 +46,15 @@ #include -bool MATRIX_ROUTING_HEAD::ComputeMatrixSize( BOARD* aPcb ) +bool MATRIX_ROUTING_HEAD::ComputeMatrixSize( BOARD* aPcb, bool aUseBoardEdgesOnly ) { - aPcb->ComputeBoundingBox(); + aPcb->ComputeBoundingBox( aUseBoardEdgesOnly ); // The boundary box must have its start point on routing grid: m_BrdBox = aPcb->GetBoundingBox(); - m_BrdBox.Offset( -(m_BrdBox.GetX() % m_GridRouting), -(m_BrdBox.GetY() % m_GridRouting) ); + m_BrdBox.SetX( m_BrdBox.GetX() - ( m_BrdBox.GetX() % m_GridRouting ) ); + m_BrdBox.SetY( m_BrdBox.GetY() - ( m_BrdBox.GetY() % m_GridRouting ) ); // The boundary box must have its end point on routing grid: wxPoint end = m_BrdBox.GetEnd(); @@ -66,12 +69,12 @@ bool MATRIX_ROUTING_HEAD::ComputeMatrixSize( BOARD* aPcb ) aPcb->SetBoundingBox( m_BrdBox ); - m_Nrows = Nrows = m_BrdBox.GetHeight() / m_GridRouting; - m_Ncols = Ncols = m_BrdBox.GetWidth() / m_GridRouting; + m_Nrows = m_BrdBox.GetHeight() / m_GridRouting; + m_Ncols = m_BrdBox.GetWidth() / m_GridRouting; - /* get a small margin for memory allocation: */ - Ncols += 1; - Nrows += 1; + // gives a small margin + m_Ncols += 1; + m_Nrows += 1; return true; } @@ -79,10 +82,10 @@ bool MATRIX_ROUTING_HEAD::ComputeMatrixSize( BOARD* aPcb ) MATRIX_ROUTING_HEAD::MATRIX_ROUTING_HEAD() { - m_BoardSide[0] = m_BoardSide[1] = NULL; - m_DistSide[0] = m_DistSide[1] = NULL; - m_DirSide[0] = m_DirSide[1] = NULL; - m_InitBoardDone = false; + m_BoardSide[0] = m_BoardSide[1] = NULL; + m_DistSide[0] = m_DistSide[1] = NULL; + m_DirSide[0] = m_DirSide[1] = NULL; + m_InitMatrixDone = false; m_Layers = MAX_SIDES_COUNT; m_Nrows = m_Ncols = 0; m_MemSize = 0; @@ -94,18 +97,17 @@ MATRIX_ROUTING_HEAD::~MATRIX_ROUTING_HEAD() } -int MATRIX_ROUTING_HEAD::InitBoard() +int MATRIX_ROUTING_HEAD::InitRoutingMatrix() { int ii, kk; - if( Nrows <= 0 || Ncols <= 0 ) + if( m_Nrows <= 0 || m_Ncols <= 0 ) return 0; - m_Nrows = Nrows; - m_Ncols = Ncols; - m_InitBoardDone = true; /* we have been called */ + m_InitMatrixDone = true; // we have been called - ii = (Nrows + 1) * (Ncols + 1); + // give a small margin for memory allocation: + ii = (RoutingMatrix.m_Nrows + 1) * (RoutingMatrix.m_Ncols + 1); for( kk = 0; kk < m_Layers; kk++ ) { @@ -113,21 +115,21 @@ int MATRIX_ROUTING_HEAD::InitBoard() m_DistSide[kk] = NULL; m_DirSide[kk] = NULL; - /* allocate Board & initialize everything to empty */ + /* allocate matrix & initialize everything to empty */ m_BoardSide[kk] = (MATRIX_CELL*) operator new( ii * sizeof(MATRIX_CELL) ); memset( m_BoardSide[kk], 0, ii * sizeof(MATRIX_CELL) ); if( m_BoardSide[kk] == NULL ) return -1; - /***** allocate Distances *****/ + // allocate Distances m_DistSide[kk] = (DIST_CELL*) operator new( ii * sizeof(DIST_CELL) ); memset( m_DistSide[kk], 0, ii * sizeof(DIST_CELL) ); if( m_DistSide[kk] == NULL ) return -1; - /***** allocate Dir (chars) *****/ + // allocate Dir (chars) m_DirSide[kk] = (char*) operator new( ii ); memset( m_DirSide[kk], 0, ii ); @@ -141,29 +143,29 @@ int MATRIX_ROUTING_HEAD::InitBoard() } -void MATRIX_ROUTING_HEAD::UnInitBoard() +void MATRIX_ROUTING_HEAD::UnInitRoutingMatrix() { int ii; - m_InitBoardDone = false; + m_InitMatrixDone = false; for( ii = 0; ii < MAX_SIDES_COUNT; ii++ ) { - /***** de-allocate Dir matrix *****/ + // de-allocate Dir matrix if( m_DirSide[ii] ) { delete m_DirSide[ii]; m_DirSide[ii] = NULL; } - /***** de-allocate Distances matrix *****/ + // de-allocate Distances matrix if( m_DistSide[ii] ) { delete m_DistSide[ii]; m_DistSide[ii] = NULL; } - /**** de-allocate cells matrix *****/ + // de-allocate cells matrix if( m_BoardSide[ii] ) { delete m_BoardSide[ii]; @@ -209,10 +211,10 @@ void PlaceCells( BOARD* aPcb, int net_code, int flag ) if( net_code != pad->GetNet() || (flag & FORCE_PADS) ) { - ::PlacePad( aPcb, pad, HOLE, marge, WRITE_CELL ); + ::PlacePad( pad, HOLE, marge, WRITE_CELL ); } - ::PlacePad( aPcb, pad, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL ); + ::PlacePad( pad, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL ); } // Place outlines of modules on matrix routing, if they are on a copper layer @@ -241,8 +243,8 @@ void PlaceCells( BOARD* aPcb, int net_code, int flag ) tmpSegm.m_Param = edge->GetAngle(); tmpSegm.SetNet( -1 ); - TraceSegmentPcb( aPcb, &tmpSegm, HOLE, marge, WRITE_CELL ); - TraceSegmentPcb( aPcb, &tmpSegm, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL ); + TraceSegmentPcb( &tmpSegm, HOLE, marge, WRITE_CELL ); + TraceSegmentPcb( &tmpSegm, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL ); } break; @@ -278,7 +280,7 @@ void PlaceCells( BOARD* aPcb, int net_code, int flag ) tmpSegm.m_Param = DrawSegm->GetAngle(); tmpSegm.SetNet( -1 ); - TraceSegmentPcb( aPcb, &tmpSegm, type_cell, marge, WRITE_CELL ); + TraceSegmentPcb( &tmpSegm, type_cell, marge, WRITE_CELL ); } break; @@ -308,11 +310,11 @@ void PlaceCells( BOARD* aPcb, int net_code, int flag ) layerMask = GetLayerMask( PtText->GetLayer() ); - TraceFilledRectangle( aPcb, ux0 - marge, uy0 - marge, ux1 + marge, + TraceFilledRectangle( ux0 - marge, uy0 - marge, ux1 + marge, uy1 + marge, (int) (PtText->m_Orient), layerMask, HOLE, WRITE_CELL ); - TraceFilledRectangle( aPcb, ux0 - via_marge, uy0 - via_marge, + TraceFilledRectangle( ux0 - via_marge, uy0 - via_marge, ux1 + via_marge, uy1 + via_marge, (int) (PtText->m_Orient), layerMask, VIA_IMPOSSIBLE, WRITE_OR_CELL ); @@ -330,8 +332,8 @@ void PlaceCells( BOARD* aPcb, int net_code, int flag ) if( net_code == track->GetNet() ) continue; - TraceSegmentPcb( aPcb, track, HOLE, marge, WRITE_CELL ); - TraceSegmentPcb( aPcb, track, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL ); + TraceSegmentPcb( track, HOLE, marge, WRITE_CELL ); + TraceSegmentPcb( track, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL ); } } @@ -342,13 +344,13 @@ int Build_Work( BOARD* Pcb ) D_PAD* pt_pad; int r1, r2, c1, c2, current_net_code; RATSNEST_ITEM* pt_ch; - int demi_pas = Board.m_GridRouting / 2; + int demi_pas = RoutingMatrix.m_GridRouting / 2; wxString msg; EDA_RECT bbbox = Pcb->GetBoundingBox(); InitWork(); /* clear work list */ - Ntotal = 0; + int cellCount = 0; for( unsigned ii = 0; ii < Pcb->GetRatsnestsCount(); ii++ ) { @@ -371,9 +373,9 @@ int Build_Work( BOARD* Pcb ) current_net_code = pt_pad->GetNet(); pt_ch = pt_rats; - r1 = ( pt_pad->GetPosition().y - bbbox.GetY() + demi_pas ) / Board.m_GridRouting; + r1 = ( pt_pad->GetPosition().y - bbbox.GetY() + demi_pas ) / RoutingMatrix.m_GridRouting; - if( r1 < 0 || r1 >= Nrows ) + if( r1 < 0 || r1 >= RoutingMatrix.m_Nrows ) { msg.Printf( wxT( "error : row = %d ( padY %d pcbY %d) " ), r1, pt_pad->GetPosition().y, bbbox.GetY() ); @@ -381,9 +383,9 @@ int Build_Work( BOARD* Pcb ) return 0; } - c1 = ( pt_pad->GetPosition().x - bbbox.GetX() + demi_pas ) / Board.m_GridRouting; + c1 = ( pt_pad->GetPosition().x - bbbox.GetX() + demi_pas ) / RoutingMatrix.m_GridRouting; - if( c1 < 0 || c1 >= Ncols ) + if( c1 < 0 || c1 >= RoutingMatrix.m_Ncols ) { msg.Printf( wxT( "error : col = %d ( padX %d pcbX %d) " ), c1, pt_pad->GetPosition().x, bbbox.GetX() ); @@ -394,9 +396,9 @@ int Build_Work( BOARD* Pcb ) pt_pad = pt_rats->m_PadEnd; r2 = ( pt_pad->GetPosition().y - bbbox.GetY() - + demi_pas ) / Board.m_GridRouting; + + demi_pas ) / RoutingMatrix.m_GridRouting; - if( r2 < 0 || r2 >= Nrows ) + if( r2 < 0 || r2 >= RoutingMatrix.m_Nrows ) { msg.Printf( wxT( "error : row = %d ( padY %d pcbY %d) " ), r2, pt_pad->GetPosition().y, bbbox.GetY() ); @@ -404,9 +406,9 @@ int Build_Work( BOARD* Pcb ) return 0; } - c2 = ( pt_pad->GetPosition().x - bbbox.GetX() + demi_pas ) / Board.m_GridRouting; + c2 = ( pt_pad->GetPosition().x - bbbox.GetX() + demi_pas ) / RoutingMatrix.m_GridRouting; - if( c2 < 0 || c2 >= Ncols ) + if( c2 < 0 || c2 >= RoutingMatrix.m_Ncols ) { msg.Printf( wxT( "error : col = %d ( padX %d pcbX %d) " ), c2, pt_pad->GetPosition().x, bbbox.GetX() ); @@ -415,115 +417,143 @@ int Build_Work( BOARD* Pcb ) } SetWork( r1, c1, current_net_code, r2, c2, pt_ch, 0 ); - Ntotal++; + cellCount++; } SortWork(); - return Ntotal; + return cellCount; +} + +// Initialize WriteCell to make the aLogicOp +void MATRIX_ROUTING_HEAD::SetCellOperation( int aLogicOp ) +{ + switch( aLogicOp ) + { + default: + case WRITE_CELL: + m_opWriteCell = &MATRIX_ROUTING_HEAD::SetCell; + break; + + case WRITE_OR_CELL: + m_opWriteCell = &MATRIX_ROUTING_HEAD::OrCell; + break; + + case WRITE_XOR_CELL: + m_opWriteCell = &MATRIX_ROUTING_HEAD::XorCell; + break; + + case WRITE_AND_CELL: + m_opWriteCell = &MATRIX_ROUTING_HEAD::AndCell; + break; + + case WRITE_ADD_CELL: + m_opWriteCell = &MATRIX_ROUTING_HEAD::AddCell; + break; + } } /* return the value stored in a cell */ -MATRIX_CELL GetCell( int aRow, int aCol, int aSide ) +MATRIX_CELL MATRIX_ROUTING_HEAD::GetCell( int aRow, int aCol, int aSide ) { MATRIX_CELL* p; - p = Board.m_BoardSide[aSide]; - return p[aRow * Ncols + aCol]; + p = RoutingMatrix.m_BoardSide[aSide]; + return p[aRow * m_Ncols + aCol]; } /* basic cell operation : WRITE operation */ -void SetCell( int aRow, int aCol, int aSide, MATRIX_CELL x ) +void MATRIX_ROUTING_HEAD::SetCell( int aRow, int aCol, int aSide, MATRIX_CELL x ) { MATRIX_CELL* p; - p = Board.m_BoardSide[aSide]; - p[aRow * Ncols + aCol] = x; + p = RoutingMatrix.m_BoardSide[aSide]; + p[aRow * m_Ncols + aCol] = x; } /* basic cell operation : OR operation */ -void OrCell( int aRow, int aCol, int aSide, MATRIX_CELL x ) +void MATRIX_ROUTING_HEAD::OrCell( int aRow, int aCol, int aSide, MATRIX_CELL x ) { MATRIX_CELL* p; - p = Board.m_BoardSide[aSide]; - p[aRow * Ncols + aCol] |= x; + p = RoutingMatrix.m_BoardSide[aSide]; + p[aRow * m_Ncols + aCol] |= x; } /* basic cell operation : XOR operation */ -void XorCell( int aRow, int aCol, int aSide, MATRIX_CELL x ) +void MATRIX_ROUTING_HEAD::XorCell( int aRow, int aCol, int aSide, MATRIX_CELL x ) { MATRIX_CELL* p; - p = Board.m_BoardSide[aSide]; - p[aRow * Ncols + aCol] ^= x; + p = RoutingMatrix.m_BoardSide[aSide]; + p[aRow * m_Ncols + aCol] ^= x; } /* basic cell operation : AND operation */ -void AndCell( int aRow, int aCol, int aSide, MATRIX_CELL x ) +void MATRIX_ROUTING_HEAD::AndCell( int aRow, int aCol, int aSide, MATRIX_CELL x ) { MATRIX_CELL* p; - p = Board.m_BoardSide[aSide]; - p[aRow * Ncols + aCol] &= x; + p = RoutingMatrix.m_BoardSide[aSide]; + p[aRow * m_Ncols + aCol] &= x; } /* basic cell operation : ADD operation */ -void AddCell( int aRow, int aCol, int aSide, MATRIX_CELL x ) +void MATRIX_ROUTING_HEAD::AddCell( int aRow, int aCol, int aSide, MATRIX_CELL x ) { MATRIX_CELL* p; - p = Board.m_BoardSide[aSide]; - p[aRow * Ncols + aCol] += x; + p = RoutingMatrix.m_BoardSide[aSide]; + p[aRow * m_Ncols + aCol] += x; } /* fetch distance cell */ -DIST_CELL GetDist( int aRow, int aCol, int aSide ) /* fetch distance cell */ +DIST_CELL MATRIX_ROUTING_HEAD::GetDist( int aRow, int aCol, int aSide ) /* fetch distance cell */ { DIST_CELL* p; - p = Board.m_DistSide[aSide]; - return p[aRow * Ncols + aCol]; + p = RoutingMatrix.m_DistSide[aSide]; + return p[aRow * m_Ncols + aCol]; } /* store distance cell */ -void SetDist( int aRow, int aCol, int aSide, DIST_CELL x ) +void MATRIX_ROUTING_HEAD::SetDist( int aRow, int aCol, int aSide, DIST_CELL x ) { DIST_CELL* p; - p = Board.m_DistSide[aSide]; - p[aRow * Ncols + aCol] = x; + p = RoutingMatrix.m_DistSide[aSide]; + p[aRow * m_Ncols + aCol] = x; } /* fetch direction cell */ -int GetDir( int aRow, int aCol, int aSide ) +int MATRIX_ROUTING_HEAD::GetDir( int aRow, int aCol, int aSide ) { DIR_CELL* p; - p = Board.m_DirSide[aSide]; - return (int) (p[aRow * Ncols + aCol]); + p = RoutingMatrix.m_DirSide[aSide]; + return (int) (p[aRow * m_Ncols + aCol]); } /* store direction cell */ -void SetDir( int aRow, int aCol, int aSide, int x ) +void MATRIX_ROUTING_HEAD::SetDir( int aRow, int aCol, int aSide, int x ) { DIR_CELL* p; - p = Board.m_DirSide[aSide]; - p[aRow * Ncols + aCol] = (char) x; + p = RoutingMatrix.m_DirSide[aSide]; + p[aRow * m_Ncols + aCol] = (char) x; } diff --git a/pcbnew/solve.cpp b/pcbnew/autorouter/solve.cpp similarity index 89% rename from pcbnew/solve.cpp rename to pcbnew/autorouter/solve.cpp index 5403938be6..8ef2af3e7d 100644 --- a/pcbnew/solve.cpp +++ b/pcbnew/autorouter/solve.cpp @@ -1,9 +1,12 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2006 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2011 Wayne Stambaugh - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * + * Copyright (C) 1992-2012 KiCad Developers, see change_log.txt for contributors. + * + * First copyright (C) Randy Nevin, 1989 (see PCBCA package) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -23,6 +26,9 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ +/* see "Autorouting With the A* Algorithm" (Dr.Dobbs journal) +*/ + /** * @file solve.cpp */ @@ -40,7 +46,7 @@ #include #include -#include +#include #include @@ -76,7 +82,6 @@ static int segm_oX, segm_oY; static int segm_fX, segm_fY; /* Origin and position of the current * trace segment. */ static RATSNEST_ITEM* pt_cur_ch; -static int Ncurrent; /* measures of progress */ static int s_Clearance; // Clearance value used in autorouter static PICKED_ITEMS_LIST s_ItemsListPicker; @@ -104,7 +109,7 @@ static PICKED_ITEMS_LIST s_ItemsListPicker; * [] [0] = row [] (1] = col was added to the coord of the midpoint for * Get the coord of the 8 neighboring points. */ -static int delta[8][2] = +static const int delta[8][2] = { { 1, -1 }, /* northwest */ { 1, 0 }, /* north */ @@ -116,7 +121,7 @@ static int delta[8][2] = { -1, 1 } /* southeast */ }; -static int ndir[8] = +static const int ndir[8] = { /* for building paths back to source */ FROM_SOUTHEAST, FROM_SOUTH, FROM_SOUTHWEST, @@ -266,13 +271,12 @@ int PCB_EDIT_FRAME::Solve( wxDC* DC, int two_sides ) NETINFO_ITEM* net; bool stop = false; wxString msg; + int routedCount = 0; // routed ratsnest count m_canvas->SetAbortRequest( false ); s_Clearance = GetBoard()->m_NetClasses.GetDefault()->GetClearance(); - Ncurrent = 0; - // Prepare the undo command info s_ItemsListPicker.ClearListAndDeleteItems(); // Should not be necessary, but... @@ -304,43 +308,33 @@ int PCB_EDIT_FRAME::Solve( wxDC* DC, int two_sides ) EraseMsgBox(); - Ncurrent++; + routedCount++; net = GetBoard()->FindNet( current_net_code ); if( net ) { msg.Printf( wxT( "[%8.8s]" ), GetChars( net->GetNetname() ) ); AppendMsgPanel( wxT( "Net route" ), msg, BROWN ); - msg.Printf( wxT( "%d / %d" ), Ncurrent, Ntotal ); + msg.Printf( wxT( "%d / %d" ), routedCount, RoutingMatrix.m_RouteCount ); AppendMsgPanel( wxT( "Activity" ), msg, BROWN ); } pt_cur_ch = pt_cur_ch; - segm_oX = GetBoard()->GetBoundingBox().GetX() + (Board.m_GridRouting * col_source); - segm_oY = GetBoard()->GetBoundingBox().GetY() + (Board.m_GridRouting * row_source); - segm_fX = GetBoard()->GetBoundingBox().GetX() + (Board.m_GridRouting * col_target); - segm_fY = GetBoard()->GetBoundingBox().GetY() + (Board.m_GridRouting * row_target); + segm_oX = GetBoard()->GetBoundingBox().GetX() + (RoutingMatrix.m_GridRouting * col_source); + segm_oY = GetBoard()->GetBoundingBox().GetY() + (RoutingMatrix.m_GridRouting * row_source); + segm_fX = GetBoard()->GetBoundingBox().GetX() + (RoutingMatrix.m_GridRouting * col_target); + segm_fY = GetBoard()->GetBoundingBox().GetY() + (RoutingMatrix.m_GridRouting * row_target); /* Draw segment. */ - GRLine( m_canvas->GetClipBox(), - DC, - segm_oX, - segm_oY, - segm_fX, - segm_fY, - 0, - WHITE | GR_XOR ); + GRLine( m_canvas->GetClipBox(), DC, + segm_oX, segm_oY, segm_fX, segm_fY, + 0, WHITE | GR_XOR ); pt_cur_ch->m_PadStart->Draw( m_canvas, DC, GR_OR | GR_HIGHLIGHT ); pt_cur_ch->m_PadEnd->Draw( m_canvas, DC, GR_OR | GR_HIGHLIGHT ); - success = Autoroute_One_Track( this, - DC, - two_sides, - row_source, - col_source, - row_target, - col_target, - pt_cur_ch ); + success = Autoroute_One_Track( this, DC, + two_sides, row_source, col_source, + row_target, col_target, pt_cur_ch ); switch( success ) { @@ -433,9 +427,9 @@ static int Autoroute_One_Track( PCB_EDIT_FRAME* pcbframe, marge = s_Clearance + ( pcbframe->GetBoard()->GetCurrentTrackWidth() / 2 ); /* clear direction flags */ - i = Nrows * Ncols * sizeof(DIR_CELL); - memset( Board.m_DirSide[TOP], FROM_NOWHERE, i ); - memset( Board.m_DirSide[BOTTOM], FROM_NOWHERE, i ); + i = RoutingMatrix.m_Nrows * RoutingMatrix.m_Ncols * sizeof(DIR_CELL); + memset( RoutingMatrix.m_DirSide[TOP], FROM_NOWHERE, i ); + memset( RoutingMatrix.m_DirSide[BOTTOM], FROM_NOWHERE, i ); lastopen = lastclos = lastmove = 0; @@ -467,9 +461,9 @@ static int Autoroute_One_Track( PCB_EDIT_FRAME* pcbframe, * On the routing grid (1 grid point must be in the pad) */ { - int cX = ( Board.m_GridRouting * col_source ) + int cX = ( RoutingMatrix.m_GridRouting * col_source ) + pcbframe->GetBoard()->GetBoundingBox().GetX(); - int cY = ( Board.m_GridRouting * row_source ) + int cY = ( RoutingMatrix.m_GridRouting * row_source ) + pcbframe->GetBoard()->GetBoundingBox().GetY(); int dx = pt_cur_ch->m_PadStart->GetSize().x / 2; int dy = pt_cur_ch->m_PadStart->GetSize().y / 2; @@ -482,9 +476,9 @@ static int Autoroute_One_Track( PCB_EDIT_FRAME* pcbframe, if( ( abs( cX - px ) > dx ) || ( abs( cY - py ) > dy ) ) goto end_of_route; - cX = ( Board.m_GridRouting * col_target ) + cX = ( RoutingMatrix.m_GridRouting * col_target ) + pcbframe->GetBoard()->GetBoundingBox().GetX(); - cY = ( Board.m_GridRouting * row_target ) + cY = ( RoutingMatrix.m_GridRouting * row_target ) + pcbframe->GetBoard()->GetBoundingBox().GetY(); dx = pt_cur_ch->m_PadEnd->GetSize().x / 2; dy = pt_cur_ch->m_PadEnd->GetSize().y / 2; @@ -510,8 +504,8 @@ static int Autoroute_One_Track( PCB_EDIT_FRAME* pcbframe, /* Placing the bit to remove obstacles on 2 pads to a link. */ pcbframe->SetStatusText( wxT( "Gen Cells" ) ); - PlacePad( pcbframe->GetBoard(), pt_cur_ch->m_PadStart, CURRENT_PAD, marge, WRITE_OR_CELL ); - PlacePad( pcbframe->GetBoard(), pt_cur_ch->m_PadEnd, CURRENT_PAD, marge, WRITE_OR_CELL ); + PlacePad( pt_cur_ch->m_PadStart, CURRENT_PAD, marge, WRITE_OR_CELL ); + PlacePad( pt_cur_ch->m_PadEnd, CURRENT_PAD, marge, WRITE_OR_CELL ); /* Regenerates the remaining barriers (which may encroach on the placement bits precedent) */ @@ -523,7 +517,7 @@ static int Autoroute_One_Track( PCB_EDIT_FRAME* pcbframe, if( ( pt_cur_ch->m_PadStart != ptr ) && ( pt_cur_ch->m_PadEnd != ptr ) ) { - PlacePad( pcbframe->GetBoard(), ptr, ~CURRENT_PAD, marge, WRITE_AND_CELL ); + PlacePad( ptr, ~CURRENT_PAD, marge, WRITE_AND_CELL ); } } @@ -597,7 +591,7 @@ static int Autoroute_One_Track( PCB_EDIT_FRAME* pcbframe, for( ; r != ILLEGAL; GetQueue( &r, &c, &side, &d, &apx_dist ) ) { - curcell = GetCell( r, c, side ); + curcell = RoutingMatrix.GetCell( r, c, side ); if( curcell & CURRENT_PAD ) curcell &= ~HOLE; @@ -669,13 +663,14 @@ static int Autoroute_One_Track( PCB_EDIT_FRAME* pcbframe, nc = c + delta[i][1]; /* off the edge? */ - if( nr < 0 || nr >= Nrows || nc < 0 || nc >= Ncols ) + if( nr < 0 || nr >= RoutingMatrix.m_Nrows || + nc < 0 || nc >= RoutingMatrix.m_Ncols ) continue; /* off the edge */ if( _self == 5 && selfok2[i].present ) continue; - newcell = GetCell( nr, nc, side ); + newcell = RoutingMatrix.GetCell( nr, nc, side ); if( newcell & CURRENT_PAD ) newcell &= ~HOLE; @@ -696,7 +691,7 @@ static int Autoroute_One_Track( PCB_EDIT_FRAME* pcbframe, if( delta[i][0] && delta[i][1] ) { /* check first buddy */ - buddy = GetCell( r + blocking[i].r1, c + blocking[i].c1, side ); + buddy = RoutingMatrix.GetCell( r + blocking[i].r1, c + blocking[i].c1, side ); if( buddy & CURRENT_PAD ) buddy &= ~HOLE; @@ -706,7 +701,7 @@ static int Autoroute_One_Track( PCB_EDIT_FRAME* pcbframe, // if (buddy & (blocking[i].b1)) continue; /* check second buddy */ - buddy = GetCell( r + blocking[i].r2, c + blocking[i].c2, side ); + buddy = RoutingMatrix.GetCell( r + blocking[i].r2, c + blocking[i].c2, side ); if( buddy & CURRENT_PAD ) buddy &= ~HOLE; @@ -717,17 +712,17 @@ static int Autoroute_One_Track( PCB_EDIT_FRAME* pcbframe, // if (buddy & (blocking[i].b2)) continue; } - olddir = GetDir( r, c, side ); + olddir = RoutingMatrix.GetDir( r, c, side ); newdist = d + CalcDist( ndir[i], olddir, ( olddir == FROM_OTHERSIDE ) ? - GetDir( r, c, 1 - side ) : 0, side ); + RoutingMatrix.GetDir( r, c, 1 - side ) : 0, side ); /* if (a) not visited yet, or (b) we have */ /* found a better path, add it to queue */ - if( !GetDir( nr, nc, side ) ) + if( !RoutingMatrix.GetDir( nr, nc, side ) ) { - SetDir( nr, nc, side, ndir[i] ); - SetDist( nr, nc, side, newdist ); + RoutingMatrix.SetDir( nr, nc, side, ndir[i] ); + RoutingMatrix.SetDist( nr, nc, side, newdist ); if( SetQueue( nr, nc, side, newdist, GetApxDist( nr, nc, row_target, col_target ), @@ -736,10 +731,10 @@ static int Autoroute_One_Track( PCB_EDIT_FRAME* pcbframe, return ERR_MEMORY; } } - else if( newdist < GetDist( nr, nc, side ) ) + else if( newdist < RoutingMatrix.GetDist( nr, nc, side ) ) { - SetDir( nr, nc, side, ndir[i] ); - SetDist( nr, nc, side, newdist ); + RoutingMatrix.SetDir( nr, nc, side, ndir[i] ); + RoutingMatrix.SetDist( nr, nc, side, newdist ); ReSetQueue( nr, nc, side, newdist, GetApxDist( nr, nc, row_target, col_target ), row_target, col_target ); @@ -749,7 +744,7 @@ static int Autoroute_One_Track( PCB_EDIT_FRAME* pcbframe, /** Test the other layer. **/ if( two_sides ) { - olddir = GetDir( r, c, side ); + olddir = RoutingMatrix.GetDir( r, c, side ); if( olddir == FROM_OTHERSIDE ) continue; /* useless move, so don't bother */ @@ -758,7 +753,7 @@ static int Autoroute_One_Track( PCB_EDIT_FRAME* pcbframe, continue; /* check for holes or traces on other side */ - if( ( newcell = GetCell( r, c, 1 - side ) ) != 0 ) + if( ( newcell = RoutingMatrix.GetCell( r, c, 1 - side ) ) != 0 ) continue; /* check for nearby holes or traces on both sides */ @@ -766,16 +761,17 @@ static int Autoroute_One_Track( PCB_EDIT_FRAME* pcbframe, { nr = r + delta[i][0]; nc = c + delta[i][1]; - if( nr < 0 || nr >= Nrows || nc < 0 || nc >= Ncols ) + if( nr < 0 || nr >= RoutingMatrix.m_Nrows || + nc < 0 || nc >= RoutingMatrix.m_Ncols ) continue; /* off the edge !! */ - if( GetCell( nr, nc, side ) /* & blocking2[i]*/ ) + if( RoutingMatrix.GetCell( nr, nc, side ) /* & blocking2[i]*/ ) { skip = 1; /* can't drill via here */ break; } - if( GetCell( nr, nc, 1 - side ) /* & blocking2[i]*/ ) + if( RoutingMatrix.GetCell( nr, nc, 1 - side ) /* & blocking2[i]*/ ) { skip = 1; /* can't drill via here */ break; @@ -790,22 +786,21 @@ static int Autoroute_One_Track( PCB_EDIT_FRAME* pcbframe, /* if (a) not visited yet, * or (b) we have found a better path, * add it to queue */ - if( !GetDir( r, c, 1 - side ) ) + if( !RoutingMatrix.GetDir( r, c, 1 - side ) ) { - SetDir( r, c, 1 - side, FROM_OTHERSIDE ); - SetDist( r, c, 1 - side, newdist ); + RoutingMatrix.SetDir( r, c, 1 - side, FROM_OTHERSIDE ); + RoutingMatrix.SetDist( r, c, 1 - side, newdist ); if( SetQueue( r, c, 1 - side, newdist, apx_dist, row_target, col_target ) == 0 ) { return ERR_MEMORY; } } - else if( newdist < GetDist( r, c, 1 - side ) ) + else if( newdist < RoutingMatrix.GetDist( r, c, 1 - side ) ) { - SetDir( r, c, 1 - side, FROM_OTHERSIDE ); - SetDist( r, c, 1 - side, newdist ); - ReSetQueue( r, - c, + RoutingMatrix.SetDir( r, c, 1 - side, FROM_OTHERSIDE ); + RoutingMatrix.SetDist( r, c, 1 - side, newdist ); + ReSetQueue( r, c, 1 - side, newdist, apx_dist, @@ -816,8 +811,8 @@ static int Autoroute_One_Track( PCB_EDIT_FRAME* pcbframe, } end_of_route: - PlacePad( pcbframe->GetBoard(), pt_cur_ch->m_PadStart, ~CURRENT_PAD, marge, WRITE_AND_CELL ); - PlacePad( pcbframe->GetBoard(), pt_cur_ch->m_PadEnd, ~CURRENT_PAD, marge, WRITE_AND_CELL ); + PlacePad( pt_cur_ch->m_PadStart, ~CURRENT_PAD, marge, WRITE_AND_CELL ); + PlacePad( pt_cur_ch->m_PadEnd, ~CURRENT_PAD, marge, WRITE_AND_CELL ); msg.Printf( wxT( "Activity: Open %d Closed %d Moved %d"), OpenNodes, ClosNodes, MoveNodes ); @@ -966,7 +961,7 @@ static int Retrace( PCB_EDIT_FRAME* pcbframe, wxDC* DC, { /* find where we came from to get here */ r2 = r1; c2 = c1; s2 = s1; - x = GetDir( r1, c1, s1 ); + x = RoutingMatrix.GetDir( r1, c1, s1 ); switch( x ) { @@ -1011,12 +1006,12 @@ static int Retrace( PCB_EDIT_FRAME* pcbframe, wxDC* DC, break; default: - DisplayError( pcbframe, wxT( "Retrace: internal error: no way back" ) ); + wxMessageBox( wxT( "Retrace: internal error: no way back" ) ); return 0; } if( r0 != ILLEGAL ) - y = GetDir( r0, c0, s0 ); + y = RoutingMatrix.GetDir( r0, c0, s0 ); /* see if target or hole */ if( ( ( r1 == row_target ) && ( c1 == col_target ) ) || ( s1 != s0 ) ) @@ -1085,7 +1080,7 @@ static int Retrace( PCB_EDIT_FRAME* pcbframe, wxDC* DC, } else { - DisplayError( pcbframe, wxT( "Retrace: error 2" ) ); + wxMessageBox( wxT( "Retrace: error 2" ) ); return 0; } } @@ -1130,7 +1125,7 @@ static int Retrace( PCB_EDIT_FRAME* pcbframe, wxDC* DC, case FROM_OTHERSIDE: default: - DisplayError( pcbframe, wxT( "Retrace: error 3" ) ); + wxMessageBox( wxT( "Retrace: error 3" ) ); return 0; } @@ -1171,11 +1166,11 @@ static void OrCell_Trace( BOARD* pcb, int col, int row, g_CurrentTrackSegment->m_Start.x = g_CurrentTrackSegment->m_End.x = pcb->GetBoundingBox().GetX() + - ( Board.m_GridRouting * row ); + ( RoutingMatrix.m_GridRouting * row ); g_CurrentTrackSegment->m_Start.y = g_CurrentTrackSegment->m_End.y = pcb->GetBoundingBox().GetY() + - ( Board.m_GridRouting * col ); + ( RoutingMatrix.m_GridRouting * col ); g_CurrentTrackSegment->m_Width = pcb->GetCurrentViaSize(); g_CurrentTrackSegment->m_Shape = pcb->GetDesignSettings().m_CurrentViaType; @@ -1195,9 +1190,9 @@ static void OrCell_Trace( BOARD* pcb, int col, int row, g_CurrentTrackSegment->SetState( TRACK_AR, ON ); g_CurrentTrackSegment->m_End.x = pcb->GetBoundingBox().GetX() + - ( Board.m_GridRouting * row ); + ( RoutingMatrix.m_GridRouting * row ); g_CurrentTrackSegment->m_End.y = pcb->GetBoundingBox().GetY() + - ( Board.m_GridRouting * col ); + ( RoutingMatrix.m_GridRouting * col ); g_CurrentTrackSegment->SetNet( current_net_code ); if( g_CurrentTrackSegment->Back() == NULL ) /* Start trace. */ @@ -1315,9 +1310,8 @@ static void AddNewTrace( PCB_EDIT_FRAME* pcbframe, wxDC* DC ) /* Out the new track on the matrix board */ for( TRACK* track = g_FirstTrackSegment; track; track = track->Next() ) { - TraceSegmentPcb( pcbframe->GetBoard(), track, HOLE, marge, WRITE_CELL ); - TraceSegmentPcb( pcbframe->GetBoard(), track, VIA_IMPOSSIBLE, - via_marge, WRITE_OR_CELL ); + TraceSegmentPcb( track, HOLE, marge, WRITE_CELL ); + TraceSegmentPcb( track, VIA_IMPOSSIBLE, via_marge, WRITE_OR_CELL ); } // Insert new segments in real board diff --git a/pcbnew/autorouter/work.cpp b/pcbnew/autorouter/work.cpp new file mode 100644 index 0000000000..0db5dad007 --- /dev/null +++ b/pcbnew/autorouter/work.cpp @@ -0,0 +1,238 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2011 Wayne Stambaugh + * + * Copyright (C) 1992-2012 KiCad Developers, see change_log.txt for contributors. + * + * First copyright (C) Randy Nevin, 1989 (see PCBCA package) + * + * 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 work.cpp + * @brief Automatic routing routines + */ + +#include +#include + +#include +#include +#include + + +struct CWORK // a unit of work is a source-target (a ratsnet item) to connect +{ + struct CWORK* m_Next; + int m_FromRow; // source row + int m_FromCol; // source column + int m_ToRow; // target row + int m_ToCol; // target column + RATSNEST_ITEM* m_Ratsnest; // Corresponding ratsnest + int m_NetCode; // m_NetCode + int m_ApxDist; // approximate distance + int m_Cost; // cost for sort by length + int m_Priority; // route priority +}; + + +// pointers to the first and last item of work to do +static CWORK* Head = NULL; +static CWORK* Tail = NULL; +static CWORK* Current = NULL; + + +// initialize the work list +void InitWork() +{ + CWORK* ptr; + + while( ( ptr = Head ) != NULL ) + { + Head = ptr->m_Next; + delete ptr; + } + + Tail = Current = NULL; +} + + +// initialize the work list +void ReInitWork() +{ + Current = Head; +} + + +/* add a unit of work to the work list + * Return: + * 1 if OK + * 0 if memory allocation failed + */ +static int GetCost( int r1, int c1, int r2, int c2 ); + +int SetWork( int r1, int c1, + int n_c, + int r2, int c2, + RATSNEST_ITEM* pt_ch, int pri ) +{ + CWORK* p; + + if( ( p = (CWORK*) operator new( sizeof(CWORK), std::nothrow ) ) != NULL ) + { + p->m_FromRow = r1; + p->m_FromCol = c1; + p->m_NetCode = n_c; + p->m_ToRow = r2; + p->m_ToCol = c2; + p->m_Ratsnest = pt_ch; + p->m_ApxDist = GetApxDist( r1, c1, r2, c2 ); + p->m_Cost = GetCost( r1, c1, r2, c2 ); + p->m_Priority = pri; + p->m_Next = NULL; + + if( Head ) /* attach at end */ + Tail->m_Next = p; + else /* first in list */ + Head = Current = p; + + Tail = p; + return 1; + } + else /* can't get any more memory */ + { + return 0; + } +} + + +/* fetch a unit of work from the work list */ +void GetWork( int* r1, int* c1, + int* n_c, + int* r2, int* c2, + RATSNEST_ITEM** pt_ch ) +{ + if( Current ) + { + *r1 = Current->m_FromRow; + *c1 = Current->m_FromCol; + *n_c = Current->m_NetCode; + *r2 = Current->m_ToRow; + *c2 = Current->m_ToCol; + *pt_ch = Current->m_Ratsnest; + Current = Current->m_Next; + } + else /* none left */ + { + *r1 = *c1 = *r2 = *c2 = ILLEGAL; + *n_c = 0; + *pt_ch = NULL; + } +} + + +/* order the work items; shortest (low cost) first */ +void SortWork() +{ + CWORK* p; + CWORK* q0; /* put PRIORITY PAD_CONNECTs in q0 */ + CWORK* q1; /* sort other PAD_CONNECTs in q1 */ + CWORK* r; + + q0 = q1 = NULL; + + while( (p = Head) != NULL ) /* prioritize each work item */ + { + Head = Head->m_Next; + + if( p->m_Priority ) /* put at end of priority list */ + { + p->m_Next = NULL; + + if( (r = q0) == NULL ) /* empty list? */ + { + q0 = p; + } + else /* attach at end */ + { + while( r->m_Next ) /* search for end */ + r = r->m_Next; + + r->m_Next = p; /* attach */ + } + } + else if( ( ( r = q1 ) == NULL ) || ( p->m_Cost < q1->m_Cost ) ) + { + p->m_Next = q1; + q1 = p; + } + else /* find proper position in list */ + { + while( r->m_Next && p->m_Cost >= r->m_Next->m_Cost ) + r = r->m_Next; + + p->m_Next = r->m_Next; + r->m_Next = p; + } + } + + if( (p = q0) != NULL ) /* any priority PAD_CONNECTs? */ + { + while( q0->m_Next ) + q0 = q0->m_Next; + + q0->m_Next = q1; + } + else + p = q1; + + /* reposition Head and Tail */ + for( Head = Current = Tail = p; Tail && Tail->m_Next; Tail = Tail->m_Next ) + ; +} + + +/* Calculate the cost of a ratsnest: + * cost = (| dx | + | dy |) * disability + * disability = 1 if dx or dy = 0, max if | dx | # | dy | + */ +static int GetCost( int r1, int c1, int r2, int c2 ) +{ + int dx, dy, mx, my; + double incl = 1.0; + + dx = abs( c2 - c1 ); + dy = abs( r2 - r1 ); + mx = dx; + my = dy; + + if( mx < my ) + { + mx = dy; my = dx; + } + + if( mx ) + incl += (2 * (double) my / mx); + + return (int) ( ( dx + dy ) * incl ); +} diff --git a/pcbnew/basepcbframe.cpp b/pcbnew/basepcbframe.cpp index 87eecffca8..eda2eff44a 100644 --- a/pcbnew/basepcbframe.cpp +++ b/pcbnew/basepcbframe.cpp @@ -1,7 +1,8 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2009 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck * Copyright (C) 2011 Wayne Stambaugh * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. * diff --git a/pcbnew/block.cpp b/pcbnew/block.cpp index 4caaa7700e..a95a6c159e 100644 --- a/pcbnew/block.cpp +++ b/pcbnew/block.cpp @@ -1,7 +1,8 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck * Copyright (C) 2011 Wayne Stambaugh * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. * diff --git a/pcbnew/block_module_editor.cpp b/pcbnew/block_module_editor.cpp index 3a6e174b9f..d139c38f28 100644 --- a/pcbnew/block_module_editor.cpp +++ b/pcbnew/block_module_editor.cpp @@ -1,9 +1,10 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2011 Wayne Stambaugh - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2012 Wayne Stambaugh + * Copyright (C) 1992-2012 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 diff --git a/pcbnew/board_undo_redo.cpp b/pcbnew/board_undo_redo.cpp index 79303bcac4..35f9415c2e 100644 --- a/pcbnew/board_undo_redo.cpp +++ b/pcbnew/board_undo_redo.cpp @@ -2,6 +2,31 @@ /* board editor: undo and redo functions for board editor */ /*************************************************************/ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 1992-2012 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 + */ + #include #include #include diff --git a/pcbnew/class_board.cpp b/pcbnew/class_board.cpp index c3a38201a3..33715ce3da 100644 --- a/pcbnew/class_board.cpp +++ b/pcbnew/class_board.cpp @@ -3,6 +3,33 @@ * @brief BOARD class functions. */ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2011 Wayne Stambaugh + * + * Copyright (C) 1992-2012 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 + */ + #include #include @@ -47,10 +74,14 @@ BOARD::BOARD() : BuildListOfNets(); // prepare pad and netlist containers. - for( int layer = 0; layer < NB_COPPER_LAYERS; ++layer ) + for( int layer = 0; layer < LAYER_COUNT; ++layer ) { m_Layer[layer].m_Name = GetDefaultLayerName( layer ); - m_Layer[layer].m_Type = LT_SIGNAL; + + if( layer <= LAST_COPPER_LAYER ) + m_Layer[layer].m_Type = LT_SIGNAL; + else + m_Layer[layer].m_Type = LT_UNDEFINED; } m_NetClasses.GetDefault()->SetDescription( _( "This is the default net class." ) ); @@ -312,13 +343,25 @@ int BOARD::GetCurrentMicroViaDrill() } +bool BOARD::SetLayer( int aIndex, const LAYER& aLayer ) +{ + if( aIndex < NB_COPPER_LAYERS ) + { + m_Layer[ aIndex ] = aLayer; + return true; + } + + return false; +} + + wxString BOARD::GetLayerName( int aLayerIndex ) const { if( !IsValidLayerIndex( aLayerIndex ) ) return wxEmptyString; - // copper layer names are stored in the BOARD. - if( IsValidCopperLayerIndex( aLayerIndex ) && IsLayerEnabled( aLayerIndex ) ) + // All layer names are stored in the BOARD. + if( IsLayerEnabled( aLayerIndex ) ) { // default names were set in BOARD::BOARD() but they may be // over-ridden by BOARD::SetLayerName() @@ -380,7 +423,7 @@ bool BOARD::SetLayerName( int aLayerIndex, const wxString& aLayerName ) if( !IsValidCopperLayerIndex( aLayerIndex ) ) return false; - if( aLayerName == wxEmptyString || aLayerName.Len() > 20 ) + if( aLayerName == wxEmptyString || aLayerName.Len() > 20 ) return false; // no quote chars in the name allowed @@ -479,14 +522,65 @@ LAYER_T LAYER::ParseType( const char* aType ) else if( strcmp( aType, "jumper" ) == 0 ) return LT_JUMPER; else - return LAYER_T( -1 ); + return LT_UNDEFINED; } + +int LAYER::GetDefaultIndex( const wxString& aName ) +{ + static LAYER_INDEX_HASH_MAP layerIndices; + + if( layerIndices.empty() ) + { + // These are only default layer names. The copper names may be over-ridden in + // the BOARD (*.brd) file. + + layerIndices[ _( "Front" ) ] = LAYER_N_FRONT; + layerIndices[ _( "Inner2" ) ] = LAYER_N_2; + layerIndices[ _( "Inner3" ) ] = LAYER_N_3; + layerIndices[ _( "Inner4" ) ] = LAYER_N_4; + layerIndices[ _( "Inner5" ) ] = LAYER_N_5; + layerIndices[ _( "Inner6" ) ] = LAYER_N_6; + layerIndices[ _( "Inner7" ) ] = LAYER_N_7; + layerIndices[ _( "Inner8" ) ] = LAYER_N_8; + layerIndices[ _( "Inner9" ) ] = LAYER_N_9; + layerIndices[ _( "Inner10" ) ] = LAYER_N_10; + layerIndices[ _( "Inner11" ) ] = LAYER_N_11; + layerIndices[ _( "Inner12" ) ] = LAYER_N_12; + layerIndices[ _( "Inner13" ) ] = LAYER_N_13; + layerIndices[ _( "Inner14" ) ] = LAYER_N_14; + layerIndices[ _( "Inner15" ) ] = LAYER_N_15; + layerIndices[ _( "Back" ) ] = LAYER_N_BACK; + layerIndices[ _( "Adhes_Back" ) ] = ADHESIVE_N_BACK; + layerIndices[ _( "Adhes_Front" ) ] = ADHESIVE_N_FRONT; + layerIndices[ _( "SoldP_Back" ) ] = SOLDERPASTE_N_BACK; + layerIndices[ _( "SoldP_Front" ) ] = SOLDERPASTE_N_FRONT; + layerIndices[ _( "SilkS_Back" ) ] = SILKSCREEN_N_BACK; + layerIndices[ _( "SilkS_Front" ) ] = SILKSCREEN_N_FRONT; + layerIndices[ _( "Mask_Back" ) ] = SOLDERMASK_N_BACK; + layerIndices[ _( "Mask_Front" ) ] = SOLDERMASK_N_FRONT; + layerIndices[ _( "Drawings" ) ] = DRAW_N; + layerIndices[ _( "Comments" ) ] = COMMENT_N; + layerIndices[ _( "Eco1" ) ] = ECO1_N; + layerIndices[ _( "Eco2" ) ] = ECO2_N; + layerIndices[ _( "PCB_Edges" ) ] = EDGE_N; + } + + const LAYER_INDEX_HASH_MAP::iterator it = layerIndices.find( aName ); + + if( it == layerIndices.end() ) + return UNDEFINED_LAYER; + + return layerIndices[ aName ]; +} + + int BOARD::GetCopperLayerCount() const { return m_designSettings.GetCopperLayerCount(); } + void BOARD::SetCopperLayerCount( int aCount ) { m_designSettings.SetCopperLayerCount( aCount ); diff --git a/pcbnew/class_board.h b/pcbnew/class_board.h index 3ea070f1ac..d1bd06e832 100644 --- a/pcbnew/class_board.h +++ b/pcbnew/class_board.h @@ -19,6 +19,9 @@ #include #include +#include + + class PCB_BASE_FRAME; class PCB_EDIT_FRAME; class PICKED_ITEMS_LIST; @@ -43,6 +46,7 @@ typedef std::vector< TRACK* > TRACK_PTRS; */ enum LAYER_T { + LT_UNDEFINED = -1, LT_SIGNAL, LT_POWER, LT_MIXED, @@ -51,11 +55,27 @@ enum LAYER_T /** - * Struct LAYER + * Class LAYER * holds information pertinent to a layer of a BOARD. */ -struct LAYER +class LAYER { +public: + LAYER( const wxString& aName = wxEmptyString, LAYER_T aType = LT_SIGNAL, + bool aVisible = true ) : + m_Name( aName ), + m_Type( aType ), + m_visible( aVisible ), + m_fixedListIndex( UNDEFINED_LAYER ) + { + } + + void SetVisible( bool aEnable ) { m_visible = aEnable; } + bool IsVisible() const { return m_visible; } + + void SetFixedListIndex( int aIndex ) { m_fixedListIndex = aIndex; } + int GetFixedListIndex() const { return m_fixedListIndex; } + /** The name of the layer, there should be no spaces in this name. */ wxString m_Name; @@ -63,7 +83,6 @@ struct LAYER LAYER_T m_Type; // int m_Color; -// bool m_Visible; // ? use flags in m_Color instead ? /** * Function ShowType @@ -81,9 +100,25 @@ struct LAYER * LAYER_T(-1) if the string is invalid */ static LAYER_T ParseType( const char* aType ); + + /** + * Function GetDefaultIndex + * returns the layer index of the layer \a aName. + * + * @param aName A reference to a wxString object containing the default layer name. + * @return The index of the layer \a aName if found otherwise #UNDEFINED_LAYER_INDEX. + */ + static int GetDefaultIndex( const wxString& aName ); + +private: + bool m_visible; + int m_fixedListIndex; }; +WX_DECLARE_STRING_HASH_MAP( int, LAYER_INDEX_HASH_MAP ); + + /** * Struct VIA_DIMENSION * is a small helper container to handle a stock of specific vias each with @@ -164,7 +199,7 @@ private: /// edge zone descriptors, owned by pointer. ZONE_CONTAINERS m_ZoneDescriptorList; - LAYER m_Layer[NB_COPPER_LAYERS]; + LAYER m_Layer[LAYER_COUNT]; // if true m_highLight_NetCode is used HIGH_LIGHT_INFO m_highLight; // current high light data HIGH_LIGHT_INFO m_highLightPrevious; // a previously stored high light data @@ -600,6 +635,8 @@ public: */ bool SetLayerName( int aLayerIndex, const wxString& aLayerName ); + bool SetLayer( int aIndex, const LAYER& aLayer ); + /** * Function GetLayerType * returns the type of the copper layer given by aLayerIndex. diff --git a/pcbnew/class_board_connected_item.cpp b/pcbnew/class_board_connected_item.cpp index b48776d9f3..8f829e8387 100644 --- a/pcbnew/class_board_connected_item.cpp +++ b/pcbnew/class_board_connected_item.cpp @@ -3,6 +3,31 @@ * @brief BOARD_CONNECTED_ITEM class functions. */ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 1992-2012 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 + */ + #include #include diff --git a/pcbnew/class_board_design_settings.cpp b/pcbnew/class_board_design_settings.cpp index 5a8eeec5bb..8fcdeae7ed 100644 --- a/pcbnew/class_board_design_settings.cpp +++ b/pcbnew/class_board_design_settings.cpp @@ -62,7 +62,7 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS() : m_ModuleSegmentWidth = DMils2iu( 100 ); // Layer thickness for 3D viewer - m_BoardThickness = DMils2iu( DEFAULT_BOARD_THICKNESS_DMILS ); + m_boardThickness = DMils2iu( DEFAULT_BOARD_THICKNESS_DMILS ); } @@ -70,7 +70,7 @@ void BOARD_DESIGN_SETTINGS::AppendConfigs( PARAM_CFG_ARRAY* aResult ) { m_Pad_Master.AppendConfigs( aResult ); - aResult->push_back( new PARAM_CFG_INT( wxT( "BoardThickness" ), &m_BoardThickness, + aResult->push_back( new PARAM_CFG_INT( wxT( "BoardThickness" ), &m_boardThickness, DMils2iu( DEFAULT_BOARD_THICKNESS_DMILS ), 0, 0xFFFF ) ); aResult->push_back( new PARAM_CFG_INT( wxT( "TxtPcbV" ), &m_PcbTextSize.y, diff --git a/pcbnew/class_board_item.cpp b/pcbnew/class_board_item.cpp index e9639b4fbb..be9891554f 100644 --- a/pcbnew/class_board_item.cpp +++ b/pcbnew/class_board_item.cpp @@ -3,6 +3,31 @@ * @brief Class BOARD_ITEM definition and some basic functions. */ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 1992-2012 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 + */ + #include #include #include @@ -66,20 +91,15 @@ wxString BOARD_ITEM::GetLayerName() const std::string BOARD_ITEM::FormatInternalUnits( int aValue ) { - char buf[50]; + char buf[50]; -#if defined( USE_PCBNEW_NANOMETRES ) - double engUnits = aValue / 1000000.0; -#else - double engUnits = ( aValue * 10000.0 ) / 25.4 / 1000000.0; -#endif + double mm = aValue / IU_PER_MM; int len; - if( engUnits != 0.0 && fabs( engUnits ) <= 0.0001 ) + if( mm != 0.0 && fabs( mm ) <= 0.0001 ) { - // printf( "f: " ); - len = snprintf( buf, 49, "%.10f", engUnits ); + len = sprintf( buf, "%.10f", mm ); while( --len > 0 && buf[len] == '0' ) buf[len] = '\0'; @@ -88,8 +108,7 @@ std::string BOARD_ITEM::FormatInternalUnits( int aValue ) } else { - // printf( "g: " ); - len = snprintf( buf, 49, "%.10g", engUnits ); + len = sprintf( buf, "%.10g", mm ); } return std::string( buf, len ); diff --git a/pcbnew/class_dimension.cpp b/pcbnew/class_dimension.cpp index 49083ed105..02e7ecdd13 100644 --- a/pcbnew/class_dimension.cpp +++ b/pcbnew/class_dimension.cpp @@ -1,9 +1,10 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2011 Wayne Stambaugh - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2012 Wayne Stambaugh + * Copyright (C) 1992-2012 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 @@ -239,14 +240,14 @@ void DIMENSION::Mirror( const wxPoint& axis_pos ) void DIMENSION::AdjustDimensionDetails( bool aDoNotChangeText ) { - #define ARROW_SIZE 500 //size of arrows - int ii; - int mesure, deltax, deltay; // value of the measure on X and Y axes - int arrow_up_X = 0, arrow_up_Y = 0; // coordinates of arrow line / - int arrow_dw_X = 0, arrow_dw_Y = 0; // coordinates of arrow line '\' - int hx, hy; // dimension line interval - double angle, angle_f; - wxString msg; + const int arrowz = DMils2iu( 500 ); // size of arrows + int ii; + int measure, deltax, deltay; // value of the measure on X and Y axes + int arrow_up_X = 0, arrow_up_Y = 0; // coordinates of arrow line / + int arrow_dw_X = 0, arrow_dw_Y = 0; // coordinates of arrow line '\' + int hx, hy; // dimension line interval + double angle, angle_f; + wxString msg; // Init layer : m_Text.SetLayer( GetLayer() ); @@ -259,7 +260,7 @@ void DIMENSION::AdjustDimensionDetails( bool aDoNotChangeText ) deltay = m_featureLineDOy - m_featureLineGOy; // Calculate dimension value - mesure = KiROUND( hypot( (double) deltax, (double) deltay ) ); + measure = KiROUND( hypot( (double) deltax, (double) deltay ) ); if( deltax || deltay ) angle = atan2( (double) deltay, (double) deltax ); @@ -270,10 +271,10 @@ void DIMENSION::AdjustDimensionDetails( bool aDoNotChangeText ) hx = hy = ii; // Taking into account the slope of the side lines. - if( mesure ) + if( measure ) { - hx = (abs) ( (int) ( ( (double) deltay * hx ) / mesure ) ); - hy = (abs) ( (int) ( ( (double) deltax * hy ) / mesure ) ); + hx = (abs) ( (int) ( ( (double) deltay * hx ) / measure ) ); + hy = (abs) ( (int) ( ( (double) deltax * hy ) / measure ) ); if( m_featureLineGOx > m_crossBarOx ) hx = -hx; @@ -288,14 +289,13 @@ void DIMENSION::AdjustDimensionDetails( bool aDoNotChangeText ) hy = 0; angle_f = angle + (M_PI * 27.5 / 180); - arrow_up_X = (int) ( ARROW_SIZE * cos( angle_f ) ); - arrow_up_Y = (int) ( ARROW_SIZE * sin( angle_f ) ); + arrow_up_X = (int) ( arrowz * cos( angle_f ) ); + arrow_up_Y = (int) ( arrowz * sin( angle_f ) ); angle_f = angle - (M_PI * 27.5 / 180); - arrow_dw_X = (int) ( ARROW_SIZE * cos( angle_f ) ); - arrow_dw_Y = (int) ( ARROW_SIZE * sin( angle_f ) ); + arrow_dw_X = (int) ( arrowz * cos( angle_f ) ); + arrow_dw_Y = (int) ( arrowz * sin( angle_f ) ); } - m_arrowG1Ox = m_crossBarOx; m_arrowG1Oy = m_crossBarOy; m_arrowG1Fx = m_crossBarOx + arrow_up_X; @@ -344,7 +344,7 @@ void DIMENSION::AdjustDimensionDetails( bool aDoNotChangeText ) if( !aDoNotChangeText ) { - m_Value = mesure; + m_Value = measure; msg = ::CoordinateToString( m_Value ); SetText( msg ); } diff --git a/pcbnew/class_dimension.h b/pcbnew/class_dimension.h index e10b925f83..ef449c32cf 100644 --- a/pcbnew/class_dimension.h +++ b/pcbnew/class_dimension.h @@ -32,6 +32,7 @@ #include +#include class LINE_READER; diff --git a/pcbnew/class_drawsegment.cpp b/pcbnew/class_drawsegment.cpp index 04f360b4d1..2984d7c6c1 100644 --- a/pcbnew/class_drawsegment.cpp +++ b/pcbnew/class_drawsegment.cpp @@ -2,6 +2,7 @@ * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2004 Jean-Pierre Charras, jean-pierre.charras@gipsa-lab.inpg.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck * Copyright (C) 2011 Wayne Stambaugh * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. * diff --git a/pcbnew/class_edge_mod.cpp b/pcbnew/class_edge_mod.cpp index 241f6182e0..dde127d5e3 100644 --- a/pcbnew/class_edge_mod.cpp +++ b/pcbnew/class_edge_mod.cpp @@ -1,9 +1,10 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2011 Wayne Stambaugh - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2012 Wayne Stambaugh + * Copyright (C) 1992-2012 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 diff --git a/pcbnew/class_marker_pcb.cpp b/pcbnew/class_marker_pcb.cpp index bdc42ab9c4..5c115e1aa4 100644 --- a/pcbnew/class_marker_pcb.cpp +++ b/pcbnew/class_marker_pcb.cpp @@ -1,8 +1,32 @@ -/*****************************************************************************/ -/* Functions to handle markers used to show something (usually a drc problem) */ -/*****************************************************************************/ +/** + * @file class_marker_pcb.cpp + * @brief Functions to handle markers used to show something (usually a drc problem) + */ -/* file class_marker.cpp */ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 1992-2012 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 + */ #include #include diff --git a/pcbnew/class_mire.cpp b/pcbnew/class_mire.cpp index 21f0840cd1..459458ae39 100644 --- a/pcbnew/class_mire.cpp +++ b/pcbnew/class_mire.cpp @@ -1,9 +1,10 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2011 Wayne Stambaugh - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2012 Wayne Stambaugh + * Copyright (C) 1992-2012 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 diff --git a/pcbnew/class_module.cpp b/pcbnew/class_module.cpp index 51ee5ce91b..d8beb467ff 100644 --- a/pcbnew/class_module.cpp +++ b/pcbnew/class_module.cpp @@ -1,9 +1,10 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2009 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2011 Wayne Stambaugh - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2012 Wayne Stambaugh + * Copyright (C) 1992-2012 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 @@ -571,6 +572,20 @@ D_PAD* MODULE::GetPad( const wxPoint& aPosition, int aLayerMask ) } +void MODULE::Add3DModel( S3D_MASTER* a3DModel ) +{ + a3DModel->SetParent( this ); + m_3D_Drawings.PushBack( a3DModel ); +} + + +void MODULE::AddPad( D_PAD* aPad ) +{ + aPad->SetParent( this ); + m_Pads.PushBack( aPad ); +} + + // see class_module.h SEARCH_RESULT MODULE::Visit( INSPECTOR* inspector, const void* testData, const KICAD_T scanTypes[] ) diff --git a/pcbnew/class_module.h b/pcbnew/class_module.h index 1c715f15f4..5ca97a8cf5 100644 --- a/pcbnew/class_module.h +++ b/pcbnew/class_module.h @@ -323,6 +323,22 @@ public: */ unsigned GetPadCount() const { return m_Pads.GetCount() ; } + /** + * Function Add3DModel + * adds \a a3DModel definition to the end of the 3D model list. + * + * @param a3DModel A pointer to a #S3D_MASTER to add to the list. + */ + void Add3DModel( S3D_MASTER* a3DModel ); + + /** + * Function AddPad + * adds \a aPad to the end of the pad list. + * + * @param aPad A pointer to a #D_PAD to add to the list. + */ + void AddPad( D_PAD* aPad ); + SEARCH_RESULT Visit( INSPECTOR* inspector, const void* testData, const KICAD_T scanTypes[] ); diff --git a/pcbnew/class_netinfo_item.cpp b/pcbnew/class_netinfo_item.cpp index acf67bf47e..c6498fc51b 100644 --- a/pcbnew/class_netinfo_item.cpp +++ b/pcbnew/class_netinfo_item.cpp @@ -1,6 +1,31 @@ -/*************************************************************************/ -/* NETINFO_ITEM class, to handle info on nets (netnames, net constraints */ -/*************************************************************************/ +/** + * @brief NETINFO_ITEM class, to handle info on nets: netnames, net constraints + */ + +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 1992-2012 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 + */ #include #include diff --git a/pcbnew/class_pad.cpp b/pcbnew/class_pad.cpp index 86aa6c60cf..5b338ebeca 100644 --- a/pcbnew/class_pad.cpp +++ b/pcbnew/class_pad.cpp @@ -1,8 +1,9 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 1992-2012 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 diff --git a/pcbnew/class_pad_draw_functions.cpp b/pcbnew/class_pad_draw_functions.cpp index 8587d71808..639e25fc03 100644 --- a/pcbnew/class_pad_draw_functions.cpp +++ b/pcbnew/class_pad_draw_functions.cpp @@ -1,9 +1,10 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2006 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2011 Wayne Stambaugh - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2012 Wayne Stambaugh + * Copyright (C) 1992-2012 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 diff --git a/pcbnew/class_pcb_text.cpp b/pcbnew/class_pcb_text.cpp index ed98248d9d..b365cf2a12 100644 --- a/pcbnew/class_pcb_text.cpp +++ b/pcbnew/class_pcb_text.cpp @@ -1,8 +1,9 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 1992-2012 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 diff --git a/pcbnew/class_text_mod.cpp b/pcbnew/class_text_mod.cpp index 9a4f5f7590..67837dcff6 100644 --- a/pcbnew/class_text_mod.cpp +++ b/pcbnew/class_text_mod.cpp @@ -1,8 +1,9 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 1992-2012 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 diff --git a/pcbnew/class_track.cpp b/pcbnew/class_track.cpp index e69eceb527..788072f471 100644 --- a/pcbnew/class_track.cpp +++ b/pcbnew/class_track.cpp @@ -1,9 +1,10 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2009 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2009 Wayne Stambaugh - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2012 Wayne Stambaugh + * Copyright (C) 1992-2012 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 @@ -185,6 +186,7 @@ wxString SEGZONE::GetSelectMenuText() const SEGVIA::SEGVIA( BOARD_ITEM* aParent ) : TRACK( aParent, PCB_VIA_T ) { + SetShape( VIA_THROUGH ); } @@ -873,8 +875,10 @@ void SEGVIA::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, int draw_mode, const wxPoint } } - if( DisplayOpt.ShowTrackClearanceMode == SHOW_CLEARANCE_ALWAYS ) + if( ShowClearance( this ) ) + { GRCircle( panel->GetClipBox(), DC, m_Start + aOffset, radius + GetClearance(), 0, color ); + } // for Micro Vias, draw a partial cross : X on component layer, or + on copper layer // (so we can see 2 superimposed microvias ): diff --git a/pcbnew/class_zone.cpp b/pcbnew/class_zone.cpp index 635d08160b..d23a58cce2 100644 --- a/pcbnew/class_zone.cpp +++ b/pcbnew/class_zone.cpp @@ -1,8 +1,9 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2006 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 1992-2012 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 @@ -484,28 +485,17 @@ bool ZONE_CONTAINER::HitTest( const wxPoint& aPosition ) return false; } +// Zones outlines have no thickness, so it Hit Test functions +// we must have a default distance between the test point +// and a corner or a zone edge: +#define MIN_DIST_IN_MILS 10 bool ZONE_CONTAINER::HitTestForCorner( const wxPoint& refPos ) { m_CornerSelection = -1; // Set to not found // distance (in internal units) to detect a corner in a zone outline. - // @todo use a scaling factor here of actual screen coordinates, so that - // when nanometers come, it still works. - #define CORNER_MIN_DIST 100 - - int min_dist = CORNER_MIN_DIST + 1; - -#if 0 - // Dick: I don't see this as reasonable. The mouse distance from the zone is - // not a function of the grid, it is a fixed number of pixels, regardless of zoom. - if( GetBoard() && GetBoard()->m_PcbFrame ) - { - // Use grid size because it is known - wxRealPoint grid = GetBoard()->m_PcbFrame->GetCanvas()->GetGrid(); - min_dist = KiROUND( MIN( grid.x, grid.y ) ); - } -#endif + int min_dist = MIN_DIST_IN_MILS*IU_PER_MILS; wxPoint delta; unsigned lim = m_Poly->corner.size(); @@ -535,23 +525,8 @@ bool ZONE_CONTAINER::HitTestForEdge( const wxPoint& refPos ) m_CornerSelection = -1; // Set to not found - // @todo use a scaling factor here of actual screen coordinates, so that - // when nanometers come, it still works. This should be done in screen coordinates - // not internal units. - #define EDGE_MIN_DIST 200 // distance (in internal units) to detect a zone outline - int min_dist = EDGE_MIN_DIST+1; - - -#if 0 - // Dick: I don't see this as reasonable. The mouse distance from the zone is - // not a function of the grid, it is a fixed number of pixels, regardless of zoom. - if( GetBoard() && GetBoard()->m_PcbFrame ) - { - // Use grid size because it is known - wxRealPoint grid = GetBoard()->m_PcbFrame->GetCanvas()->GetGrid(); - min_dist = KiROUND( MIN( grid.x, grid.y ) ); - } -#endif + // distance (in internal units) to detect a zone outline + int min_dist = MIN_DIST_IN_MILS*IU_PER_MILS; unsigned first_corner_pos = 0; @@ -915,6 +890,24 @@ ZoneConnection ZONE_CONTAINER::GetPadConnection( D_PAD* aPad ) const } +void ZONE_CONTAINER::AddPolygon( std::vector< wxPoint >& aPolygon ) +{ + if( aPolygon.empty() ) + return; + + for( unsigned i = 0; i < aPolygon.size(); i++ ) + { + if( i == 0 ) + m_Poly->Start( GetLayer(), aPolygon[i].x, aPolygon[i].y, GetHatchStyle() ); + else + AppendCorner( aPolygon[i] ); + } + + m_Poly->Close(); +} + + + wxString ZONE_CONTAINER::GetSelectMenuText() const { wxString text; diff --git a/pcbnew/class_zone.h b/pcbnew/class_zone.h index 8c81c296f9..b4d3f6aefa 100644 --- a/pcbnew/class_zone.h +++ b/pcbnew/class_zone.h @@ -209,6 +209,7 @@ public: const wxString& GetNetName() const { return m_Netname; }; void SetNetName( const wxString& aName ) { m_Netname = aName; } + /// How to fill areas: 0 = use filled polygons, 1 => fill with segments. void SetFillMode( int aFillMode ) { m_FillMode = aFillMode; } int GetFillMode() const { return m_FillMode; } @@ -429,6 +430,11 @@ public: return m_Poly->GetHatchStyle(); } + void SetHatchStyle( CPolyLine::hatch_style aStyle ) + { + m_Poly->SetHatchStyle( aStyle ); + } + /** * Function TransformShapeWithClearanceToPolygon * Convert the track shape to a closed polygon @@ -505,16 +511,25 @@ public: void SetCornerRadius( unsigned int aRadius ) { - if( aRadius > MAX_ZONE_CORNER_RADIUS ) - cornerRadius = MAX_ZONE_CORNER_RADIUS; - else if( aRadius < 0 ) - cornerRadius = 0; - else - cornerRadius = aRadius; + cornerRadius = aRadius; + if( cornerRadius > (unsigned int) Mils2iu( MAX_ZONE_CORNER_RADIUS_MILS ) ) + cornerRadius = Mils2iu( MAX_ZONE_CORNER_RADIUS_MILS ); }; unsigned int GetCornerRadius() const { return cornerRadius; }; + void AddPolygon( std::vector< wxPoint >& aPolygon ); + + void AddFilledPolygon( std::vector< CPolyPt >& aPolygon ) + { + m_FilledPolysList.insert( m_FilledPolysList.end(), aPolygon.begin(), aPolygon.end() ); + } + + void AddFillSegments( std::vector< SEGMENT >& aSegments ) + { + m_FillSegmList.insert( m_FillSegmList.end(), aSegments.begin(), aSegments.end() ); + } + virtual wxString GetSelectMenuText() const; virtual BITMAP_DEF GetMenuImage() const { return add_zone_xpm; } @@ -533,7 +548,7 @@ public: int m_ZoneClearance; // clearance value int m_ZoneMinThickness; // Min thickness value in filled areas - // How to fill areas: 0 = use filled polygons, != 0 fill with segments. + /// How to fill areas: 0 => use filled polygons, 1 => fill with segments. int m_FillMode; // number of segments to convert a circle to a polygon (uses diff --git a/pcbnew/class_zone_settings.cpp b/pcbnew/class_zone_settings.cpp index 845f8b4b50..09f98f60c9 100644 --- a/pcbnew/class_zone_settings.cpp +++ b/pcbnew/class_zone_settings.cpp @@ -1,18 +1,31 @@ -/******************************************************/ -/* class ZONE_SETTINGS used to handle zones parameters */ -/******************************************************/ - -#ifndef WX_PRECOMP -#include -#endif - -/* For compilers that support precompilation: +/** + * @brief class ZONE_SETTINGS used to handle zones parameters */ -#include -#ifdef __BORLANDC__ -#pragma hdrstop -#endif +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 1992-2012 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 + */ #include @@ -86,5 +99,6 @@ void ZONE_SETTINGS::ExportSetting( ZONE_CONTAINER& aTarget, bool aFullExport ) c aTarget.SetPriority( m_ZonePriority ); aTarget.SetNet( m_NetcodeSelection ); aTarget.SetLayer( m_CurrentZone_Layer ); + aTarget.m_Poly->SetLayer( m_CurrentZone_Layer ); } } diff --git a/pcbnew/class_zone_settings.h b/pcbnew/class_zone_settings.h index 2d6985d8be..2b2760d462 100644 --- a/pcbnew/class_zone_settings.h +++ b/pcbnew/class_zone_settings.h @@ -12,7 +12,7 @@ class ZONE_CONTAINER; -#define MAX_ZONE_CORNER_RADIUS 4000 +#define MAX_ZONE_CORNER_RADIUS_MILS 400 /** @@ -83,8 +83,8 @@ public: void SetCornerRadius( int aRadius ) { - if( aRadius > MAX_ZONE_CORNER_RADIUS ) - cornerRadius = MAX_ZONE_CORNER_RADIUS; + if( aRadius > Mils2iu( MAX_ZONE_CORNER_RADIUS_MILS ) ) + cornerRadius = Mils2iu( MAX_ZONE_CORNER_RADIUS_MILS ); else if( aRadius < 0 ) cornerRadius = 0; else diff --git a/pcbnew/classpcb.cpp b/pcbnew/classpcb.cpp index a41abd50f2..b9e205e203 100644 --- a/pcbnew/classpcb.cpp +++ b/pcbnew/classpcb.cpp @@ -4,6 +4,32 @@ * except for tracks (see class_track.cpp). */ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2012 Wayne Stambaugh + * Copyright (C) 1992-2012 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 + */ + #include #include #include diff --git a/pcbnew/connect.cpp b/pcbnew/connect.cpp index 8f82c1bf7c..c7afdbfb95 100644 --- a/pcbnew/connect.cpp +++ b/pcbnew/connect.cpp @@ -6,8 +6,9 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2011 Jean-Pierre Charras, jean-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2004-2011 KiCad Developers, see change_log.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 1992-2012 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 @@ -1074,6 +1075,10 @@ void PCB_BASE_FRAME::RecalculateAllTracksNetcode() */ static bool SortTracksByNetCode( const TRACK* const & ref, const TRACK* const & compare ) { + // For items having the same Net, keep the order in list + if( ref->GetNet() == compare->GetNet()) + return ref->m_Param < compare->m_Param; + return ref->GetNet() < compare->GetNet(); } @@ -1081,6 +1086,7 @@ static bool SortTracksByNetCode( const TRACK* const & ref, const TRACK* const & * Helper function RebuildTrackChain * rebuilds the track segment linked list in order to have a chain * sorted by increasing netcodes. + * We try to keep order of track segments in list, when possible * @param pcb = board to rebuild */ static void RebuildTrackChain( BOARD* pcb ) @@ -1093,8 +1099,19 @@ static void RebuildTrackChain( BOARD* pcb ) std::vector trackList; trackList.reserve( item_count ); - for( int i = 0; i < item_count; ++i ) + // Put track list in a temporary list to sort tracks by netcode + // We try to keep the initial order of track segments in list, when possible + // so we use m_Param (a member variable used for temporary storage) + // to temporary keep trace of the order of segments + // The sort function uses this variable to sort items that + // have the same net code. + // Without this, during sorting, the initial order is sometimes lost + // by the sort algorithm + for( int ii = 0; ii < item_count; ++ii ) + { + pcb->m_Track->m_Param = ii; trackList.push_back( pcb->m_Track.PopFront() ); + } // the list is empty now wxASSERT( pcb->m_Track == NULL && pcb->m_Track.GetCount()==0 ); diff --git a/pcbnew/controle.cpp b/pcbnew/controle.cpp index 3e8b52b9e4..74f697e8e0 100644 --- a/pcbnew/controle.cpp +++ b/pcbnew/controle.cpp @@ -1,9 +1,10 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2009 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2011 Wayne Stambaugh - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2012 Wayne Stambaugh + * Copyright (C) 1992-2012 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 diff --git a/pcbnew/deltrack.cpp b/pcbnew/deltrack.cpp index da680175e1..8fbea30913 100644 --- a/pcbnew/deltrack.cpp +++ b/pcbnew/deltrack.cpp @@ -1,10 +1,11 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2009 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2011 Wayne Stambaugh - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. - * + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2012 Wayne Stambaugh + * Copyright (C) 1992-2012 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 diff --git a/pcbnew/dialogs/dialog_copper_zones.cpp b/pcbnew/dialogs/dialog_copper_zones.cpp index ac4f324cf1..970da8c103 100644 --- a/pcbnew/dialogs/dialog_copper_zones.cpp +++ b/pcbnew/dialogs/dialog_copper_zones.cpp @@ -370,7 +370,7 @@ bool DIALOG_COPPER_ZONE::AcceptOptions( bool aPromptForErrors, bool aUseExportab // Test if this is a reasonable value for this parameter // A too large value can hang Pcbnew - #define CLEARANCE_MAX_VALUE 5000 // in 1/10000 inch + #define CLEARANCE_MAX_VALUE 100*IU_PER_MILS if( m_settings.m_ZoneClearance > CLEARANCE_MAX_VALUE ) { DisplayError( this, _( "Clearance must be smaller than 0.5\" / 12.7 mm." ) ); @@ -380,7 +380,7 @@ bool DIALOG_COPPER_ZONE::AcceptOptions( bool aPromptForErrors, bool aUseExportab txtvalue = m_ZoneMinThicknessCtrl->GetValue(); m_settings.m_ZoneMinThickness = ReturnValueFromString( g_UserUnit, txtvalue ); - if( m_settings.m_ZoneMinThickness < 10 ) + if( m_settings.m_ZoneMinThickness < (1*IU_PER_MILS) ) { DisplayError( this, _( "Minimum width must be larger than 0.001\" / 0.0254 mm." ) ); diff --git a/pcbnew/dialogs/dialog_edit_module_for_BoardEditor.cpp b/pcbnew/dialogs/dialog_edit_module_for_BoardEditor.cpp index 192ed40598..573abddc7a 100644 --- a/pcbnew/dialogs/dialog_edit_module_for_BoardEditor.cpp +++ b/pcbnew/dialogs/dialog_edit_module_for_BoardEditor.cpp @@ -2,6 +2,32 @@ * Module editor: Dialog box for editing module properties in the pcb editor. * ******************************************************************************/ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2011 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com + * Copyright (C) 2012 Dick Hollenbeck, dick@softplc.com + * Copyright (C) 2004-2011 KiCad Developers, see change_log.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 + */ + + #include #include #include diff --git a/pcbnew/dialogs/dialog_find_base.cpp b/pcbnew/dialogs/dialog_find_base.cpp index ce3209a7ea..eb7ff2c278 100644 --- a/pcbnew/dialogs/dialog_find_base.cpp +++ b/pcbnew/dialogs/dialog_find_base.cpp @@ -1,70 +1,73 @@ -/////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Aug 24 2011) -// http://www.wxformbuilder.org/ -// -// PLEASE DO "NOT" EDIT THIS FILE! -/////////////////////////////////////////////////////////////////////////// - -#include "dialog_find_base.h" - -/////////////////////////////////////////////////////////////////////////// - -DIALOG_FIND_BASE::DIALOG_FIND_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style ) -{ - this->SetSizeHints( wxDefaultSize, wxDefaultSize ); - - wxBoxSizer* bSizerMain; - bSizerMain = new wxBoxSizer( wxHORIZONTAL ); - - wxBoxSizer* bSizer3; - bSizer3 = new wxBoxSizer( wxVERTICAL ); - - m_staticText1 = new wxStaticText( this, wxID_ANY, _("Search for:"), wxDefaultPosition, wxDefaultSize, 0 ); - m_staticText1->Wrap( -1 ); - bSizer3->Add( m_staticText1, 0, wxALL, 5 ); - - m_SearchTextCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 200,-1 ), 0 ); - bSizer3->Add( m_SearchTextCtrl, 0, wxALL|wxEXPAND, 5 ); - - m_NoMouseWarpCheckBox = new wxCheckBox( this, wxID_ANY, _("Do not warp mouse pointer"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer3->Add( m_NoMouseWarpCheckBox, 0, wxALL, 5 ); - - bSizerMain->Add( bSizer3, 1, 0, 5 ); - - wxBoxSizer* bSizer4; - bSizer4 = new wxBoxSizer( wxVERTICAL ); - - m_button1 = new wxButton( this, wxID_ANY, _("Find Item"), wxDefaultPosition, wxDefaultSize, 0 ); - m_button1->SetDefault(); - bSizer4->Add( m_button1, 0, wxALL, 5 ); - - m_button2 = new wxButton( this, wxID_ANY, _("Find Marker"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer4->Add( m_button2, 0, wxALL, 5 ); - - m_button3 = new wxButton( this, wxID_CANCEL, _("Close"), wxDefaultPosition, wxDefaultSize, 0 ); - bSizer4->Add( m_button3, 0, wxALL, 5 ); - - bSizerMain->Add( bSizer4, 0, 0, 5 ); - - this->SetSizer( bSizerMain ); - this->Layout(); - bSizerMain->Fit( this ); - - this->Centre( wxBOTH ); - - // Connect Events - this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_FIND_BASE::onClose ) ); - m_button1->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_FIND_BASE::onButtonFindItemClick ), NULL, this ); - m_button2->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_FIND_BASE::onButtonFindMarkerClick ), NULL, this ); - m_button3->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_FIND_BASE::onButtonCloseClick ), NULL, this ); -} - -DIALOG_FIND_BASE::~DIALOG_FIND_BASE() -{ - // Disconnect Events - this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_FIND_BASE::onClose ) ); - m_button1->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_FIND_BASE::onButtonFindItemClick ), NULL, this ); - m_button2->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_FIND_BASE::onButtonFindMarkerClick ), NULL, this ); - m_button3->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_FIND_BASE::onButtonCloseClick ), NULL, this ); - -} +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Apr 10 2012) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#include "dialog_find_base.h" + +/////////////////////////////////////////////////////////////////////////// + +DIALOG_FIND_BASE::DIALOG_FIND_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style ) +{ + this->SetSizeHints( wxDefaultSize, wxDefaultSize ); + + wxBoxSizer* bSizerMain; + bSizerMain = new wxBoxSizer( wxHORIZONTAL ); + + wxBoxSizer* bSizer3; + bSizer3 = new wxBoxSizer( wxVERTICAL ); + + m_staticText1 = new wxStaticText( this, wxID_ANY, _("Search for:"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText1->Wrap( -1 ); + bSizer3->Add( m_staticText1, 0, wxTOP|wxRIGHT|wxLEFT, 5 ); + + m_SearchTextCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 200,-1 ), 0 ); + bSizer3->Add( m_SearchTextCtrl, 0, wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT, 5 ); + + m_NoMouseWarpCheckBox = new wxCheckBox( this, wxID_ANY, _("Do not warp mouse pointer"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer3->Add( m_NoMouseWarpCheckBox, 1, wxALL|wxEXPAND, 5 ); + + + bSizerMain->Add( bSizer3, 1, wxEXPAND|wxTOP|wxBOTTOM, 5 ); + + wxBoxSizer* bSizer4; + bSizer4 = new wxBoxSizer( wxVERTICAL ); + + m_button1 = new wxButton( this, wxID_ANY, _("Find Item"), wxDefaultPosition, wxDefaultSize, 0 ); + m_button1->SetDefault(); + bSizer4->Add( m_button1, 1, wxALL|wxEXPAND, 5 ); + + m_button2 = new wxButton( this, wxID_ANY, _("Find Marker"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer4->Add( m_button2, 1, wxALL|wxEXPAND, 5 ); + + m_button3 = new wxButton( this, wxID_CANCEL, _("Close"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer4->Add( m_button3, 1, wxALL|wxEXPAND, 5 ); + + + bSizerMain->Add( bSizer4, 0, wxALL, 5 ); + + + this->SetSizer( bSizerMain ); + this->Layout(); + bSizerMain->Fit( this ); + + this->Centre( wxBOTH ); + + // Connect Events + this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_FIND_BASE::onClose ) ); + m_button1->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_FIND_BASE::onButtonFindItemClick ), NULL, this ); + m_button2->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_FIND_BASE::onButtonFindMarkerClick ), NULL, this ); + m_button3->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_FIND_BASE::onButtonCloseClick ), NULL, this ); +} + +DIALOG_FIND_BASE::~DIALOG_FIND_BASE() +{ + // Disconnect Events + this->Disconnect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( DIALOG_FIND_BASE::onClose ) ); + m_button1->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_FIND_BASE::onButtonFindItemClick ), NULL, this ); + m_button2->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_FIND_BASE::onButtonFindMarkerClick ), NULL, this ); + m_button3->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( DIALOG_FIND_BASE::onButtonCloseClick ), NULL, this ); + +} diff --git a/pcbnew/dialogs/dialog_find_base.fbp b/pcbnew/dialogs/dialog_find_base.fbp index 76ebf5b651..e324765420 100644 --- a/pcbnew/dialogs/dialog_find_base.fbp +++ b/pcbnew/dialogs/dialog_find_base.fbp @@ -1,681 +1,645 @@ - - - - - - C++ - 1 - source_name - 0 - res - UTF-8 - connect - dialog_find_base - 1000 - none - 1 - dialog_find - - . - - 1 - 1 - 0 - 0 - - 1 - 1 - 1 - 1 - 0 - - - - - 1 - wxBOTH - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - impl_virtual - - - 1 - - 0 - 0 - wxID_ANY - - - 0 - - - 0 - - 1 - DIALOG_FIND_BASE - 1 - - - 1 - - - Resizable - - 1 - -1,-1 - wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER - DIALOG_SHIM; dialog_shim.h - Find - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - onClose - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bSizerMain - wxHORIZONTAL - none - - 5 - - 1 - - - bSizer3 - wxVERTICAL - none - - 5 - wxALL - 0 - - 1 - 1 - 1 - 1 - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Search for: - - - 0 - - - 0 - - 1 - m_staticText1 - 1 - - - protected - 1 - - - Resizable - - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - -1 - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxALL|wxEXPAND - 0 - - 1 - 1 - 1 - 1 - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - - 0 - - 0 - - 0 - - 1 - m_SearchTextCtrl - 1 - - - protected - 1 - - - Resizable - - 1 - 200,-1 - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxALL - 0 - - 1 - 1 - 1 - 1 - - - - - 1 - 0 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Do not warp mouse pointer - - - 0 - - - 0 - - 1 - m_NoMouseWarpCheckBox - 1 - - - protected - 1 - - - Resizable - - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - - 0 - - - bSizer4 - wxVERTICAL - none - - 5 - wxALL - 0 - - 1 - 1 - 1 - 1 - - - - - 1 - 0 - 1 - - 1 - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Find Item - - - 0 - - - 0 - - 1 - m_button1 - 1 - - - protected - 1 - - - Resizable - - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - onButtonFindItemClick - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxALL - 0 - - 1 - 1 - 1 - 1 - - - - - 1 - 0 - 1 - - 1 - 0 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Find Marker - - - 0 - - - 0 - - 1 - m_button2 - 1 - - - protected - 1 - - - Resizable - - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - onButtonFindMarkerClick - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxALL - 0 - - 1 - 1 - 1 - 1 - - - - - 1 - 0 - 1 - - 1 - 0 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_CANCEL - Close - - - 0 - - - 0 - - 1 - m_button3 - 1 - - - protected - 1 - - - Resizable - - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - onButtonCloseClick - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + C++ + 1 + source_name + 0 + 0 + res + UTF-8 + connect + dialog_find_base + 1000 + none + 1 + dialog_find + + . + + 1 + 1 + 1 + 0 + 0 + + 0 + wxAUI_MGR_DEFAULT + + wxBOTH + + 1 + 1 + impl_virtual + + + + 0 + wxID_ANY + + + DIALOG_FIND_BASE + + -1,-1 + wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER + DIALOG_SHIM; dialog_shim.h + Find + + + + + + + + + + + + + + onClose + + + + + + + + + + + + + + + + + + + + + + + + + + + + + bSizerMain + wxHORIZONTAL + none + + 5 + wxEXPAND|wxTOP|wxBOTTOM + 1 + + + bSizer3 + wxVERTICAL + none + + 5 + wxTOP|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Search for: + + 0 + + + 0 + + 1 + m_staticText1 + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + 0 + + 0 + + 1 + m_SearchTextCtrl + 1 + + + protected + 1 + + Resizable + 1 + 200,-1 + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL|wxEXPAND + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Do not warp mouse pointer + + 0 + + + 0 + + 1 + m_NoMouseWarpCheckBox + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL + 0 + + + bSizer4 + wxVERTICAL + none + + 5 + wxALL|wxEXPAND + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Find Item + + 0 + + + 0 + + 1 + m_button1 + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + onButtonFindItemClick + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL|wxEXPAND + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Find Marker + + 0 + + + 0 + + 1 + m_button2 + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + onButtonFindMarkerClick + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL|wxEXPAND + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_CANCEL + Close + + 0 + + + 0 + + 1 + m_button3 + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + onButtonCloseClick + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pcbnew/dialogs/dialog_find_base.h b/pcbnew/dialogs/dialog_find_base.h index 63ba7a9e6b..48a35e53cf 100644 --- a/pcbnew/dialogs/dialog_find_base.h +++ b/pcbnew/dialogs/dialog_find_base.h @@ -1,61 +1,59 @@ -/////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Aug 24 2011) -// http://www.wxformbuilder.org/ -// -// PLEASE DO "NOT" EDIT THIS FILE! -/////////////////////////////////////////////////////////////////////////// - -#ifndef __DIALOG_FIND_BASE_H__ -#define __DIALOG_FIND_BASE_H__ - -#include -#include -#include -class DIALOG_SHIM; - -#include "dialog_shim.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/////////////////////////////////////////////////////////////////////////// - - -/////////////////////////////////////////////////////////////////////////////// -/// Class DIALOG_FIND_BASE -/////////////////////////////////////////////////////////////////////////////// -class DIALOG_FIND_BASE : public DIALOG_SHIM -{ - private: - - protected: - wxStaticText* m_staticText1; - wxTextCtrl* m_SearchTextCtrl; - wxCheckBox* m_NoMouseWarpCheckBox; - wxButton* m_button1; - wxButton* m_button2; - wxButton* m_button3; - - // Virtual event handlers, overide them in your derived class - virtual void onClose( wxCloseEvent& event ) { event.Skip(); } - virtual void onButtonFindItemClick( wxCommandEvent& event ) { event.Skip(); } - virtual void onButtonFindMarkerClick( wxCommandEvent& event ) { event.Skip(); } - virtual void onButtonCloseClick( wxCommandEvent& event ) { event.Skip(); } - - - public: - - DIALOG_FIND_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Find"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); - ~DIALOG_FIND_BASE(); - -}; - -#endif //__DIALOG_FIND_BASE_H__ +/////////////////////////////////////////////////////////////////////////// +// C++ code generated with wxFormBuilder (version Apr 10 2012) +// http://www.wxformbuilder.org/ +// +// PLEASE DO "NOT" EDIT THIS FILE! +/////////////////////////////////////////////////////////////////////////// + +#ifndef __DIALOG_FIND_BASE_H__ +#define __DIALOG_FIND_BASE_H__ + +#include +#include +#include +#include "dialog_shim.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////////////////// +/// Class DIALOG_FIND_BASE +/////////////////////////////////////////////////////////////////////////////// +class DIALOG_FIND_BASE : public DIALOG_SHIM +{ + private: + + protected: + wxStaticText* m_staticText1; + wxTextCtrl* m_SearchTextCtrl; + wxCheckBox* m_NoMouseWarpCheckBox; + wxButton* m_button1; + wxButton* m_button2; + wxButton* m_button3; + + // Virtual event handlers, overide them in your derived class + virtual void onClose( wxCloseEvent& event ) { event.Skip(); } + virtual void onButtonFindItemClick( wxCommandEvent& event ) { event.Skip(); } + virtual void onButtonFindMarkerClick( wxCommandEvent& event ) { event.Skip(); } + virtual void onButtonCloseClick( wxCommandEvent& event ) { event.Skip(); } + + + public: + + DIALOG_FIND_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Find"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + ~DIALOG_FIND_BASE(); + +}; + +#endif //__DIALOG_FIND_BASE_H__ diff --git a/pcbnew/dialogs/dialog_layers_setup.cpp b/pcbnew/dialogs/dialog_layers_setup.cpp index a652200e29..8057409c45 100644 --- a/pcbnew/dialogs/dialog_layers_setup.cpp +++ b/pcbnew/dialogs/dialog_layers_setup.cpp @@ -660,8 +660,8 @@ bool DIALOG_LAYERS_SETUP::testLayerNames() // 3) cannot have " chars // 4) cannot be 'signal' // 5) must be unique. - - static const wxString badchars( wxT("%$\" ") ); + // 6) cannot have illegal chars in filenames ( some filenames are built from layer names ) + static const wxString badchars( wxT("%$\" /\\.") ); if( name == wxEmptyString ) { diff --git a/pcbnew/dialogs/dialog_plot_base.fbp b/pcbnew/dialogs/dialog_plot_base.fbp index 7d05f7dd72..c6d0626b0b 100644 --- a/pcbnew/dialogs/dialog_plot_base.fbp +++ b/pcbnew/dialogs/dialog_plot_base.fbp @@ -1,4301 +1,4219 @@ - - - - - - C++ - 1 - source_name - 0 - 0 - res - UTF-8 - connect - dialog_plot_base - 1000 - none - 1 - Dialog_Plot_base - - . - - 1 - 1 - 1 - 1 - 0 - - 1 - 1 - 1 - 1 - - 0 - - - - - - - 1 - wxBOTH - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - impl_virtual - - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - 0 - -1,-1 - 1 - DIALOG_PLOT_BASE - 1 - - - 1 - - Resizable - 1 - -1,-1 - wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER - DIALOG_SHIM; dialog_shim.h - Plot - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - OnClose - - - - - - OnInitDialog - - - - - - - - - - - - - - - - - - - - - - - m_MainSizer - wxHORIZONTAL - protected - - 5 - wxALL|wxEXPAND - 1 - - - bSizer12 - wxVERTICAL - none - - 5 - wxEXPAND - 0 - - - bSizer26 - wxHORIZONTAL - none - - 5 - wxEXPAND|wxRIGHT|wxLEFT - 0 - - - bSizer27 - wxVERTICAL - none - - 5 - wxTOP - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Plot format: - - 0 - - - 0 - - 1 - m_staticText121 - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - -1 - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - "HPGL" "Gerber" "Postscript" "DXF" - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - 0 - - 1 - m_plotFormatOpt - 1 - - - protected - 1 - - Resizable - 0 - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - SetPlotFormat - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - - 1 - - - bSizer28 - wxVERTICAL - none - - 5 - wxEXPAND|wxTOP|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Output directory: - - 0 - - - 0 - - 1 - m_staticTextDir - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - -1 - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxEXPAND - 1 - - - bSizer29 - wxHORIZONTAL - none - - 5 - wxALIGN_CENTER_VERTICAL|wxEXPAND|wxRIGHT|wxLEFT - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - 0 - - 0 - - 1 - m_outputDirectoryName - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - Target directory for plot files. Can be absolute or relative to the board file location. - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Browse... - - 0 - - - 0 - - 1 - m_browseButton - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - OnOutputDirectoryBrowseClicked - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxEXPAND - 0 - - - bUpperSizer - wxHORIZONTAL - none - - 3 - wxALL|wxEXPAND - 1 - - wxID_ANY - Layers - - m_LayersSizer - wxHORIZONTAL - protected - - - 5 - wxEXPAND - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - 0 - - 1 - m_layerCheckListBox - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - - 0 - - - m_PlotOptionsSizer - wxVERTICAL - protected - - 3 - wxALL|wxEXPAND - 0 - - wxID_ANY - Options - - sbOptionsSizer - wxVERTICAL - none - - - 5 - wxEXPAND - 0 - - - bSizer192 - wxHORIZONTAL - none - - 5 - wxEXPAND - 0 - - - bSizerPlotItems - wxVERTICAL - none - - 2 - wxTOP|wxRIGHT|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Plot sheet reference on all layers - - 0 - - - 0 - - 1 - m_plotSheetRef - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 - wxTOP|wxRIGHT|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - ID_ALLOW_PRINT_PAD_ON_SILKSCREEN - Plot pads on silkscreen - - 0 - - - 0 - - 1 - m_plotPads_on_Silkscreen - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - Enable/disable print/plot pads on silkscreen layers When disable, pads are never potted on silkscreen layers When enable, pads are potted only if they appear on silkscreen layers - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 - wxTOP|wxRIGHT|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Plot module value on silkscreen - - 0 - - - 0 - - 1 - m_plotModuleValueOpt - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 - wxTOP|wxRIGHT|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - ID_PRINT_REF - Plot module reference on silkscreen - - 0 - - - 0 - - 1 - m_plotModuleRefOpt - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 - wxTOP|wxRIGHT|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Plot other module texts on silkscreen - - 0 - - - 0 - - 1 - m_plotTextOther - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - Enable/disable print/plot module field texts on silkscreen layers - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 - wxALL - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Plot invisible texts on silkscreen - - 0 - - - 0 - - 1 - m_plotInvisibleText - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - Force print/plot module invisible texts on silkscreen layers - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 - wxALL - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Do not tent vias - - 0 - - - 0 - - 1 - m_plotNoViaOnMaskOpt - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - Remove soldermask on vias. - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 - wxALL - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - ID_MIROR_OPT - Mirrored plot - - 0 - - - 0 - - 1 - m_plotMirrorOpt - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3 - wxRIGHT|wxLEFT - 1 - - - bSizer14 - wxVERTICAL - none - - 5 - wxRIGHT|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Drill marks: - - 0 - - - 0 - - 1 - m_staticText11 - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - -1 - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxEXPAND|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - "None" "Small" "Actual size" - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - 0 - - 1 - m_drillShapeOpt - 1 - - - protected - 1 - - Resizable - 0 - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxTOP|wxRIGHT|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Scaling: - - 0 - - - 0 - - 1 - m_staticText12 - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - -1 - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxEXPAND|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - "Auto" "1:1" "3:2" "2:1" "3:1" - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - 0 - - 1 - m_scaleOpt - 1 - - - protected - 1 - - Resizable - 0 - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - OnSetScaleOpt - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxTOP|wxRIGHT|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Plot mode: - - 0 - - - 0 - - 1 - m_staticText13 - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - -1 - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxEXPAND|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - "Line" "Filled" "Sketch" - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - - 0 - - 1 - m_plotModeOpt - 1 - - - protected - 1 - - Resizable - 0 - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxTOP|wxRIGHT|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Default linewidth - - 0 - - - 0 - - 1 - m_textDefaultPenSize - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - Pen size used to draw items that have no pen size specified. Used mainly to draw items in sketch mode. - - wxFILTER_NONE - wxDefaultValidator - - - - - -1 - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxBOTTOM|wxEXPAND|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - 0 - - 0 - - 1 - m_linesWidth - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - Line width for, e.g., sheet references. - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3 - wxALL|wxEXPAND - 0 - - wxID_ANY - Gerber Options - - m_GerberOptionsSizer - wxVERTICAL - protected - - - 2 - wxLEFT|wxRIGHT|wxTOP - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Use proper filename extensions - - 0 - - - 0 - - 1 - m_useGerberExtensions - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - Use proper Gerber extensions - .GBL, .GTL, etc... - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 - wxTOP|wxRIGHT|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Exclude PCB edge layer from other layers - - 0 - - - 0 - - 1 - m_excludeEdgeLayerOpt - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - Exclude contents of the pcb edge layer from all other layers - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 - wxTOP|wxRIGHT|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Subtract soldermask from silkscreen - - 0 - - - 0 - - 1 - m_subtractMaskFromSilk - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - Remove silkscreen from areas without soldermask - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 - wxALL - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Use auxiliary axis as origin - - 0 - - - 0 - - 1 - m_useAuxOriginCheckBox - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - Use auxiliary axis as coordinates origin in Gerber files. - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3 - wxALL|wxEXPAND - 0 - - wxID_ANY - HPGL Options - - m_HPGLOptionsSizer - wxVERTICAL - protected - - - 5 - wxEXPAND - 1 - - - bSizer22 - wxHORIZONTAL - none - - 5 - wxEXPAND - 1 - - - bSizer20 - wxVERTICAL - none - - 5 - wxLEFT|wxRIGHT|wxTOP - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Pen size - - 0 - - - 0 - - 1 - m_textPenSize - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - -1 - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - 0 - - 0 - - 1 - m_HPGLPenSizeOpt - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxTOP|wxRIGHT|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Pen overlay - - 0 - - - 0 - - 1 - m_textPenOvr - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - -1 - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - 0 - - 0 - - 1 - m_HPGLPenOverlayOpt - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - Set plot overlay for filling - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxEXPAND - 1 - - - bSizer21 - wxVERTICAL - none - - 5 - wxTOP|wxRIGHT|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Pen speed (cm/s): - - 0 - - - 0 - - 1 - m_textPenSpeed - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - -1 - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - 0 - - 0 - - 1 - m_HPGLPenSpeedOpt - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - Set pen speed in cm/s - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 3 - wxALL|wxEXPAND - 0 - - wxID_ANY - Postscript Options - - m_PSOptionsSizer - wxVERTICAL - protected - - - 5 - wxEXPAND - 1 - - - bSizer17 - wxHORIZONTAL - none - - 5 - wxEXPAND - 1 - - - bSizer18 - wxVERTICAL - none - - 5 - wxTOP|wxRIGHT|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - X scale: - - 0 - - - 0 - - 1 - m_staticText7 - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - -1 - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - 0 - - 0 - - 1 - m_fineAdjustXscaleOpt - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - Set global X scale adjust for exact scale postscript output. - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxEXPAND - 1 - - - bSizer19 - wxVERTICAL - none - - 5 - wxTOP|wxRIGHT|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Y scale: - - 0 - - - 0 - - 1 - m_staticText8 - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - -1 - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - 0 - - 0 - - 1 - m_fineAdjustYscaleOpt - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - Set global Y scale adjust for exact scale postscript output. - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxEXPAND - 1 - - - bSizer191 - wxVERTICAL - none - - 5 - wxLEFT|wxRIGHT|wxTOP - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Width correction - - 0 - - - 0 - - 1 - m_textPSFineAdjustWidth - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - -1 - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - 0 - - 0 - - 1 - m_PSFineAdjustWidthOpt - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - Set global width correction for exact width postscript output. These width correction is intended to compensate tracks width and also pads and vias size errors. The reasonable width correction value must be in a range of [-(MinTrackWidth-1), +(MinClearanceValue-1)] in decimils. - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 - wxALL - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Negative plot - - 0 - - - 0 - - 1 - m_plotPSNegativeOpt - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 - wxALL - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Force A4 output - - 0 - - - 0 - - 1 - m_forcePSA4OutputOpt - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxEXPAND - 1 - - wxID_ANY - Messages: - - sbSizerMsg - wxVERTICAL - none - - - 5 - wxEXPAND - 1 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - - 0 - - 0 - - 0 - -1,70 - 1 - m_messagesBox - 1 - - - protected - 1 - - Resizable - 1 - - wxTE_MULTILINE|wxTE_READONLY - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxALIGN_RIGHT|wxRIGHT|wxLEFT - 0 - - - bSizerButtons - wxHORIZONTAL - none - - 5 - wxALL - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Plot - - 0 - - - 0 - - 1 - m_plotButton - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - Plot - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxALL - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - ID_CREATE_DRILL_FILE - Generate Drill File - - 0 - - - 0 - - 1 - m_buttonDrill - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - CreateDrillFile - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxALL - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_CANCEL - Close - - 0 - - - 0 - - 1 - m_buttonQuit - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - OnQuit - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + C++ + 1 + source_name + 0 + 0 + res + UTF-8 + connect + dialog_plot_base + 1000 + none + 1 + Dialog_Plot_base + + . + + 1 + 1 + 1 + 1 + 0 + + 0 + wxAUI_MGR_DEFAULT + + wxBOTH + + 1 + 1 + impl_virtual + + + + 0 + wxID_ANY + + -1,-1 + DIALOG_PLOT_BASE + + -1,-1 + wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER + DIALOG_SHIM; dialog_shim.h + Plot + + + + + + + + + + + + + + OnClose + + + + + + OnInitDialog + + + + + + + + + + + + + + + + + + + + + + + m_MainSizer + wxHORIZONTAL + protected + + 5 + wxALL|wxEXPAND + 1 + + + bSizer12 + wxVERTICAL + none + + 5 + wxEXPAND + 0 + + + bSizer26 + wxHORIZONTAL + none + + 5 + wxEXPAND|wxRIGHT|wxLEFT + 0 + + + bSizer27 + wxVERTICAL + none + + 5 + wxTOP + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Plot format: + + 0 + + + 0 + + 1 + m_staticText121 + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + "HPGL" "Gerber" "Postscript" "DXF" + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_plotFormatOpt + 1 + + + protected + 1 + + Resizable + 0 + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + SetPlotFormat + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + + 1 + + + bSizer28 + wxVERTICAL + none + + 5 + wxEXPAND|wxTOP|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Output directory: + + 0 + + + 0 + + 1 + m_staticTextDir + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND + 1 + + + bSizer29 + wxHORIZONTAL + none + + 5 + wxALIGN_CENTER_VERTICAL|wxEXPAND|wxRIGHT|wxLEFT + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + 0 + + 0 + + 1 + m_outputDirectoryName + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + Target directory for plot files. Can be absolute or relative to the board file location. + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Browse... + + 0 + + + 0 + + 1 + m_browseButton + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnOutputDirectoryBrowseClicked + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND + 0 + + + bUpperSizer + wxHORIZONTAL + none + + 3 + wxALL|wxEXPAND + 1 + + wxID_ANY + Layers + + m_LayersSizer + wxHORIZONTAL + protected + + + 5 + wxEXPAND + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_layerCheckListBox + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + + 0 + + + m_PlotOptionsSizer + wxVERTICAL + protected + + 3 + wxALL|wxEXPAND + 0 + + wxID_ANY + Options + + sbOptionsSizer + wxVERTICAL + none + + + 5 + wxEXPAND + 0 + + + bSizer192 + wxHORIZONTAL + none + + 5 + wxEXPAND + 0 + + + bSizerPlotItems + wxVERTICAL + none + + 2 + wxTOP|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Plot sheet reference on all layers + + 0 + + + 0 + + 1 + m_plotSheetRef + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + wxTOP|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + ID_ALLOW_PRINT_PAD_ON_SILKSCREEN + Plot pads on silkscreen + + 0 + + + 0 + + 1 + m_plotPads_on_Silkscreen + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + Enable/disable print/plot pads on silkscreen layers When disable, pads are never potted on silkscreen layers When enable, pads are potted only if they appear on silkscreen layers + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + wxTOP|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Plot module value on silkscreen + + 0 + + + 0 + + 1 + m_plotModuleValueOpt + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + wxTOP|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + ID_PRINT_REF + Plot module reference on silkscreen + + 0 + + + 0 + + 1 + m_plotModuleRefOpt + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + wxTOP|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Plot other module texts on silkscreen + + 0 + + + 0 + + 1 + m_plotTextOther + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + Enable/disable print/plot module field texts on silkscreen layers + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Plot invisible texts on silkscreen + + 0 + + + 0 + + 1 + m_plotInvisibleText + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + Force print/plot module invisible texts on silkscreen layers + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Do not tent vias + + 0 + + + 0 + + 1 + m_plotNoViaOnMaskOpt + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + Remove soldermask on vias. + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + ID_MIROR_OPT + Mirrored plot + + 0 + + + 0 + + 1 + m_plotMirrorOpt + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + wxRIGHT|wxLEFT + 1 + + + bSizer14 + wxVERTICAL + none + + 5 + wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Drill marks: + + 0 + + + 0 + + 1 + m_staticText11 + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + "None" "Small" "Actual size" + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_drillShapeOpt + 1 + + + protected + 1 + + Resizable + 0 + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxTOP|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Scaling: + + 0 + + + 0 + + 1 + m_staticText12 + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + "Auto" "1:1" "3:2" "2:1" "3:1" + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_scaleOpt + 1 + + + protected + 1 + + Resizable + 0 + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + OnSetScaleOpt + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxTOP|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Plot mode: + + 0 + + + 0 + + 1 + m_staticText13 + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + "Line" "Filled" "Sketch" + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + + 0 + + 1 + m_plotModeOpt + 1 + + + protected + 1 + + Resizable + 0 + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxTOP|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Default linewidth + + 0 + + + 0 + + 1 + m_textDefaultPenSize + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + Pen size used to draw items that have no pen size specified. Used mainly to draw items in sketch mode. + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxBOTTOM|wxEXPAND|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + 0 + + 0 + + 1 + m_linesWidth + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + Line width for, e.g., sheet references. + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + wxALL|wxEXPAND + 0 + + wxID_ANY + Gerber Options + + m_GerberOptionsSizer + wxVERTICAL + protected + + + 2 + wxLEFT|wxRIGHT|wxTOP + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Use proper filename extensions + + 0 + + + 0 + + 1 + m_useGerberExtensions + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + Use proper Gerber extensions - .GBL, .GTL, etc... + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + wxTOP|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Exclude PCB edge layer from other layers + + 0 + + + 0 + + 1 + m_excludeEdgeLayerOpt + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + Exclude contents of the pcb edge layer from all other layers + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + wxTOP|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Subtract soldermask from silkscreen + + 0 + + + 0 + + 1 + m_subtractMaskFromSilk + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + Remove silkscreen from areas without soldermask + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Use auxiliary axis as origin + + 0 + + + 0 + + 1 + m_useAuxOriginCheckBox + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + Use auxiliary axis as coordinates origin in Gerber files. + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + wxALL|wxEXPAND + 0 + + wxID_ANY + HPGL Options + + m_HPGLOptionsSizer + wxVERTICAL + protected + + + 5 + wxEXPAND + 1 + + + bSizer22 + wxHORIZONTAL + none + + 5 + wxEXPAND + 1 + + + bSizer20 + wxVERTICAL + none + + 5 + wxLEFT|wxRIGHT|wxTOP + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Pen size + + 0 + + + 0 + + 1 + m_textPenSize + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + 0 + + 0 + + 1 + m_HPGLPenSizeOpt + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxTOP|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Pen overlay + + 0 + + + 0 + + 1 + m_textPenOvr + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + 0 + + 0 + + 1 + m_HPGLPenOverlayOpt + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + Set plot overlay for filling + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND + 1 + + + bSizer21 + wxVERTICAL + none + + 5 + wxTOP|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Pen speed (cm/s): + + 0 + + + 0 + + 1 + m_textPenSpeed + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxBOTTOM|wxRIGHT|wxLEFT|wxEXPAND + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + 0 + + 0 + + 1 + m_HPGLPenSpeedOpt + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + Set pen speed in cm/s + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 3 + wxALL|wxEXPAND + 0 + + wxID_ANY + Postscript Options + + m_PSOptionsSizer + wxVERTICAL + protected + + + 5 + wxEXPAND + 1 + + + bSizer17 + wxHORIZONTAL + none + + 5 + wxEXPAND + 1 + + + bSizer18 + wxVERTICAL + none + + 5 + wxTOP|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + X scale: + + 0 + + + 0 + + 1 + m_staticText7 + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + 0 + + 0 + + 1 + m_fineAdjustXscaleOpt + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + Set global X scale adjust for exact scale postscript output. + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND + 1 + + + bSizer19 + wxVERTICAL + none + + 5 + wxTOP|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Y scale: + + 0 + + + 0 + + 1 + m_staticText8 + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND|wxBOTTOM|wxRIGHT|wxLEFT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + 0 + + 0 + + 1 + m_fineAdjustYscaleOpt + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + Set global Y scale adjust for exact scale postscript output. + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND + 1 + + + bSizer191 + wxVERTICAL + none + + 5 + wxLEFT|wxRIGHT|wxTOP + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Width correction + + 0 + + + 0 + + 1 + m_textPSFineAdjustWidth + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + 0 + + 0 + + 1 + m_PSFineAdjustWidthOpt + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + Set global width correction for exact width postscript output. These width correction is intended to compensate tracks width and also pads and vias size errors. The reasonable width correction value must be in a range of [-(MinTrackWidth-1), +(MinClearanceValue-1)] in decimils. + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Negative plot + + 0 + + + 0 + + 1 + m_plotPSNegativeOpt + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Force A4 output + + 0 + + + 0 + + 1 + m_forcePSA4OutputOpt + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxEXPAND + 1 + + wxID_ANY + Messages: + + sbSizerMsg + wxVERTICAL + none + + + 5 + wxEXPAND + 1 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + + 0 + + 0 + + 0 + -1,70 + 1 + m_messagesBox + 1 + + + protected + 1 + + Resizable + 1 + + wxTE_MULTILINE|wxTE_READONLY + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALIGN_RIGHT|wxRIGHT|wxLEFT + 0 + + + bSizerButtons + wxHORIZONTAL + none + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Plot + + 0 + + + 0 + + 1 + m_plotButton + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + Plot + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + ID_CREATE_DRILL_FILE + Generate Drill File + + 0 + + + 0 + + 1 + m_buttonDrill + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + CreateDrillFile + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_CANCEL + Close + + 0 + + + 0 + + 1 + m_buttonQuit + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + OnQuit + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pcbnew/dimension.cpp b/pcbnew/dimension.cpp index 45d614ac3c..adb895ad12 100644 --- a/pcbnew/dimension.cpp +++ b/pcbnew/dimension.cpp @@ -3,6 +3,31 @@ * @brief Dialog and code for editing a dimension object. */ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 1992-2012 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 + */ + #include #include #include diff --git a/pcbnew/eagle_plugin.cpp b/pcbnew/eagle_plugin.cpp index e3924f5b30..4a00e9b711 100644 --- a/pcbnew/eagle_plugin.cpp +++ b/pcbnew/eagle_plugin.cpp @@ -77,6 +77,20 @@ Load() TODO's using namespace boost::property_tree; +typedef EAGLE_PLUGIN::BIU BIU; +typedef PTREE::const_assoc_iterator CA_ITER; +typedef PTREE::const_iterator CITER; +typedef std::pair CA_ITER_RANGE; + +typedef MODULE_MAP::iterator MODULE_ITER; +typedef MODULE_MAP::const_iterator MODULE_CITER; + +typedef boost::optional opt_string; +typedef boost::optional opt_int; +typedef boost::optional opt_double; +typedef boost::optional opt_bool; + + /// segment (element) of our XPATH into the Eagle XML document tree in PTREE form. struct TRIPLET { @@ -160,20 +174,6 @@ public: }; -typedef EAGLE_PLUGIN::BIU BIU; -typedef PTREE::const_assoc_iterator CA_ITER; -typedef PTREE::const_iterator CITER; -typedef std::pair CA_ITER_RANGE; - -typedef MODULE_MAP::iterator MODULE_ITER; -typedef MODULE_MAP::const_iterator MODULE_CITER; - -typedef boost::optional opt_string; -typedef boost::optional opt_int; -typedef boost::optional opt_double; -typedef boost::optional opt_bool; - - /** * Function parseOptionalBool * returns an opt_bool and sets it true or false according to the presence @@ -205,13 +205,23 @@ struct EROT bool spin; double degrees; - EROT() : mirror( false ), spin( false ), degrees( 0 ) {} + EROT() : + mirror( false ), + spin( false ), + degrees( 0 ) + {} + + EROT( double aDegrees ) : + mirror( false ), + spin( false ), + degrees( aDegrees ) + {} }; typedef boost::optional opt_erot; /// parse an Eagle XML "rot" field. Unfortunately the DTD seems not to explain -/// this format very well. R[S][M]. Examples: "R90", "MR180", "SR180" +/// this format very well. [S][M]R. Examples: "R90", "MR180", "SR180" static EROT erot( const std::string& aRot ) { EROT rot; @@ -239,12 +249,30 @@ static opt_erot parseOptionalEROT( CPTREE& attribs ) /// Eagle wire struct EWIRE { - double x1; - double y1; - double x2; - double y2; - double width; - int layer; + double x1; + double y1; + double x2; + double y2; + double width; + int layer; + + // for style: (continuous | longdash | shortdash | dashdot) + enum { + CONTINUOUS, + LONGDASH, + SHORTDASH, + DASHDOT, + }; + opt_int style; + opt_double curve; ///< range is -359.9..359.9 + + // for cap: (flat | round) + enum { + FLAT, + ROUND, + }; + opt_int cap; + EWIRE( CPTREE& aWire ); }; @@ -280,7 +308,30 @@ EWIRE::EWIRE( CPTREE& aWire ) width = attribs.get( "width" ); layer = attribs.get( "layer" ); - // ignoring extent, style, curve and cap + curve = attribs.get_optional( "curve" ); + + opt_string s = attribs.get_optional( "style" ); + if( s ) + { + if( !s->compare( "continuous" ) ) + style = EWIRE::CONTINUOUS; + else if( !s->compare( "longdash" ) ) + style = EWIRE::LONGDASH; + else if( !s->compare( "shortdash" ) ) + style = EWIRE::SHORTDASH; + else if( !s->compare( "dashdot" ) ) + style = EWIRE::DASHDOT; + } + + s = attribs.get_optional( "cap" ); + if( s ) + { + if( !s->compare( "round" ) ) + cap = EWIRE::ROUND; + else if( !s->compare( "flat" ) ) + cap = EWIRE::FLAT; + } + // ignoring extent } @@ -411,16 +462,17 @@ struct EATTR opt_int layer; opt_double ratio; opt_erot rot; - opt_int display; - enum { // for 'display' field above + enum { // for 'display' Off, VALUE, NAME, BOTH, }; + opt_int display; EATTR( CPTREE& aTree ); + EATTR() {} }; /** @@ -900,6 +952,85 @@ ELAYER::ELAYER( CPTREE& aLayer ) } +/// parse an eagle distance which is either straight mm or mils if there is "mil" suffix. +static double parseEagle( const std::string& aDistance ) +{ + double ret = strtod( aDistance.c_str(), NULL ); + if( aDistance.npos != aDistance.find( "mil" ) ) + ret = IU_PER_MILS * ret; + else + ret = IU_PER_MM * ret; + + return ret; +} + + +/// subset of eagle.drawing.board.designrules in the XML document +struct ERULES +{ + int psElongationLong; ///< percent over 100%. 0-> not elongated, 100->twice as wide as is tall + ///< Goes into making a scaling factor for "long" pads. + + int psElongationOffset; ///< the offset of the hole within the "long" pad. + + double rvPadTop; ///< top pad size as percent of drill size + // double rvPadBottom; ///< bottom pad size as percent of drill size + + double rlMinPadTop; ///< minimum copper annulus on through hole pads + double rlMaxPadTop; ///< maximum copper annulus on through hole pads + + double rvViaOuter; ///< copper annulus is this percent of via hole + double rlMinViaOuter; ///< minimum copper annulus on via + double rlMaxViaOuter; ///< maximum copper annulus on via + + + ERULES() : + psElongationLong ( 100 ), + rvPadTop ( 0.25 ), + // rvPadBottom ( 0.25 ), + rlMinPadTop ( Mils2iu( 10 ) ), + rlMaxPadTop ( Mils2iu( 20 ) ), + + rvViaOuter ( 0.25 ), + rlMinViaOuter ( Mils2iu( 10 ) ), + rlMaxViaOuter ( Mils2iu( 20 ) ) + {} + + void parse( CPTREE& aRules ); +}; + +void ERULES::parse( CPTREE& aRules ) +{ + for( CITER it = aRules.begin(); it != aRules.end(); ++it ) + { + if( it->first.compare( "param" ) ) + continue; + + CPTREE& attribs = it->second.get_child( "" ); + + const std::string& name = attribs.get( "name" ); + + if( !name.compare( "psElongationLong" ) ) + psElongationLong = attribs.get( "value" ); + else if( !name.compare( "psElongationOffset" ) ) + psElongationOffset = attribs.get( "value" ); + else if( !name.compare( "rvPadTop" ) ) + rvPadTop = attribs.get( "value" ); + else if( !name.compare( "rlMinPadTop" ) ) + rlMinPadTop = parseEagle( attribs.get( "value" ) ); + else if( !name.compare( "rlMaxPadTop" ) ) + rlMaxPadTop = parseEagle( attribs.get( "value" ) ); + + else if( !name.compare( "rvViaOuter" ) ) + rvViaOuter = attribs.get( "value" ); + else if( !name.compare( "rlMinViaOuter" ) ) + rlMinViaOuter = parseEagle( attribs.get( "value" ) ); + else if( !name.compare( "rlMaxViaOuter" ) ) + rlMaxViaOuter = parseEagle( attribs.get( "value" ) ); + } +} + + /// Assemble a two part key as a simple concatonation of aFirst and aSecond parts, /// using a separator. static inline std::string makeKey( const std::string& aFirst, const std::string& aSecond ) @@ -918,6 +1049,7 @@ static inline unsigned long timeStamp( CPTREE& aTree ) EAGLE_PLUGIN::EAGLE_PLUGIN() : + m_rules( new ERULES() ), m_xpath( new XPATH() ) { init( NULL ); @@ -926,6 +1058,7 @@ EAGLE_PLUGIN::EAGLE_PLUGIN() : EAGLE_PLUGIN::~EAGLE_PLUGIN() { + delete m_rules; delete m_xpath; } @@ -1026,21 +1159,34 @@ void EAGLE_PLUGIN::init( PROPERTIES* aProperties ) mm_per_biu = 1/IU_PER_MM; biu_per_mm = IU_PER_MM; + + delete m_rules; + m_rules = new ERULES(); } void EAGLE_PLUGIN::loadAllSections( CPTREE& aDoc ) { CPTREE& drawing = aDoc.get_child( "eagle.drawing" ); + CPTREE& board = drawing.get_child( "board" ); + m_xpath->push( "eagle.drawing" ); + { + m_xpath->push( "board" ); + + CPTREE& designrules = board.get_child( "designrules" ); + loadDesignRules( designrules ); + + m_xpath->pop(); + } + { CPTREE& layers = drawing.get_child( "layers" ); loadLayerDefs( layers ); } { - CPTREE& board = drawing.get_child( "board" ); m_xpath->push( "board" ); CPTREE& plain = board.get_child( "plain" ); @@ -1062,6 +1208,14 @@ void EAGLE_PLUGIN::loadAllSections( CPTREE& aDoc ) } +void EAGLE_PLUGIN::loadDesignRules( CPTREE& aDesignRules ) +{ + m_xpath->push( "designrules" ); + m_rules->parse( aDesignRules ); + m_xpath->pop(); // "designrules" +} + + void EAGLE_PLUGIN::loadLayerDefs( CPTREE& aLayers ) { m_xpath->push( "layers.layer" ); @@ -1134,8 +1288,6 @@ void EAGLE_PLUGIN::loadPlain( CPTREE& aGraphics ) ETEXT t( gr->second ); int layer = kicad_layer( t.layer ); - int sign = 1; - TEXTE_PCB* pcbtxt = new TEXTE_PCB( m_board ); m_board->Add( pcbtxt, ADD_APPEND ); @@ -1150,34 +1302,29 @@ void EAGLE_PLUGIN::loadPlain( CPTREE& aGraphics ) pcbtxt->SetThickness( kicad( t.size * ratio / 100 ) ); - if( t.rot ) - { -#if 0 - if( t.rot->spin || ( t.rot->degrees != 180 && t.rot->degrees != 270 ) ) - pcbtxt->SetOrientation( t.rot->degrees * 10 ); - - else - // flip the justification to opposite - sign = -1; -#else - // eagles does not rotate text spun to 180 degrees unless spin is set. - if( t.rot->spin || t.rot->degrees != 180 ) - pcbtxt->SetOrientation( t.rot->degrees * 10 ); - - else - // flip the justification to opposite - sign = -1; - - if( t.rot->degrees == 270 ) - sign = -1; -#endif - pcbtxt->SetMirrored( t.rot->mirror ); - - } - int align = t.align ? *t.align : ETEXT::BOTTOM_LEFT; - switch( align * sign ) // if negative, opposite is chosen + if( t.rot ) + { + int sign = t.rot->mirror ? -1 : 1; + pcbtxt->SetMirrored( t.rot->mirror ); + + double degrees = t.rot->degrees; + + if( degrees == 90 || t.rot->spin ) + pcbtxt->SetOrientation( sign * t.rot->degrees * 10 ); + + else if( degrees == 180 ) + align = ETEXT::TOP_RIGHT; + + else if( degrees == 270 ) + { + pcbtxt->SetOrientation( sign * 90 * 10 ); + align = ETEXT::TOP_RIGHT; + } + } + + switch( align ) { case ETEXT::CENTER: // this was the default in pcbtxt's constructor @@ -1398,6 +1545,9 @@ void EAGLE_PLUGIN::loadElements( CPTREE& aElements ) { m_xpath->push( "elements.element", "name" ); + EATTR name; + EATTR value; + for( CITER it = aElements.begin(); it != aElements.end(); ++it ) { if( it->first.compare( "element" ) ) @@ -1405,6 +1555,10 @@ void EAGLE_PLUGIN::loadElements( CPTREE& aElements ) EELEMENT e( it->second ); + // use "NULL-ness" as an indiation of presence of the attribute: + EATTR* nameAttr = 0; + EATTR* valueAttr = 0; + m_xpath->Value( e.name.c_str() ); #if 1 && defined(DEBUG) @@ -1428,13 +1582,12 @@ void EAGLE_PLUGIN::loadElements( CPTREE& aElements ) } #if defined(DEBUG) - if( !e.name.compare( "ATMEGA328" ) ) + if( !e.name.compare( "IC3" ) ) { int breakhere = 1; (void) breakhere; } #endif - // copy constructor to clone the template MODULE* m = new MODULE( *mi->second ); m_board->Add( m, ADD_APPEND ); @@ -1458,16 +1611,7 @@ void EAGLE_PLUGIN::loadElements( CPTREE& aElements ) m->SetValue( FROM_UTF8( e.value.c_str() ) ); // m->Value().SetVisible( false ); - if( e.rot ) - { - m->SetOrientation( e.rot->degrees * 10 ); - - if( e.rot->mirror ) - { - m->Flip( m->GetPosition() ); - } - } - + // initalize these to default values incase the elements are not present. m_xpath->push( "attribute", "name" ); // VALUE and NAME can have something like our text "effects" overrides @@ -1483,82 +1627,154 @@ void EAGLE_PLUGIN::loadElements( CPTREE& aElements ) EATTR a( ait->second ); - TEXTE_MODULE* txt; - if( !a.name.compare( "NAME" ) ) - txt = &m->Reference(); + { + name = a; + nameAttr = &name; + } else if( !a.name.compare( "VALUE" ) ) - txt = &m->Value(); - else { - // our understanding of file format is incomplete? - continue; + value = a; + valueAttr = &value; } - - m_xpath->Value( a.name.c_str() ); - - if( a.value ) - { - txt->SetText( FROM_UTF8( a.value->c_str() ) ); - } - - if( a.x && a.y ) // boost::optional - { - wxPoint pos( kicad_x( *a.x ), kicad_y( *a.y ) ); - wxPoint pos0 = pos - m->GetPosition(); - - txt->SetPosition( pos ); - txt->SetPos0( pos0 ); - } - - // Even though size and ratio are both optional, I am not seeing - // a case where ratio is present but size is not. - - if( a.size ) - { - wxSize fontz = kicad_fontz( *a.size ); - txt->SetSize( fontz ); - - if( a.ratio ) - { - double ratio = *a.ratio; - int lw = int( fontz.y * ratio / 100.0 ); - txt->SetThickness( lw ); - } - } - - // The "rot" in a EATTR seems to be assumed to be zero if it is not - // present, and this zero rotation becomes an override to the - // package's text field. If they did not want zero, they specify - // what they want explicitly. - EROT rot; - - if( a.rot ) - rot = *a.rot; - - if( rot.spin || (rot.degrees != 180 && rot.degrees != 270) ) - { - double angle = rot.degrees * 10; - angle -= m->GetOrientation(); // subtract module's angle - txt->SetOrientation( angle ); - } - else - { - // ETEXT::TOP_RIGHT: - txt->SetHorizJustify( GR_TEXT_HJUSTIFY_RIGHT ); - txt->SetVertJustify( GR_TEXT_VJUSTIFY_TOP ); - } - - txt->SetMirrored( rot.mirror ); } m_xpath->pop(); // "attribute" + + orientModuleAndText( m, e, nameAttr, valueAttr ); } m_xpath->pop(); // "elements.element" } +void EAGLE_PLUGIN::orientModuleAndText( MODULE* m, const EELEMENT& e, + const EATTR* nameAttr, const EATTR* valueAttr ) +{ + if( e.rot ) + { + if( e.rot->mirror ) + { + m->Flip( m->GetPosition() ); + } + m->SetOrientation( e.rot->degrees * 10 ); + } + + orientModuleText( m, e, &m->Reference(), nameAttr ); + orientModuleText( m, e, &m->Value(), valueAttr ); +} + + +void EAGLE_PLUGIN::orientModuleText( MODULE* m, const EELEMENT& e, + TEXTE_MODULE* txt, const EATTR* aAttr ) +{ + if( aAttr ) + { + const EATTR& a = *aAttr; + + if( a.value ) + { + txt->SetText( FROM_UTF8( a.value->c_str() ) ); + } + + if( a.x && a.y ) // boost::optional + { + wxPoint pos( kicad_x( *a.x ), kicad_y( *a.y ) ); + wxPoint pos0 = pos - m->GetPosition(); + + txt->SetPosition( pos ); + txt->SetPos0( pos0 ); + } + + // Even though size and ratio are both optional, I am not seeing + // a case where ratio is present but size is not. + double ratio = 8; + wxSize fontz = txt->GetSize(); + + if( a.size ) + { + fontz = kicad_fontz( *a.size ); + txt->SetSize( fontz ); + + if( a.ratio ) + ratio = *a.ratio; + } + + int lw = int( fontz.y * ratio / 100.0 ); + txt->SetThickness( lw ); + + int align = ETEXT::BOTTOM_LEFT; // bottom-left is eagle default + + // The "rot" in a EATTR seems to be assumed to be zero if it is not + // present, and this zero rotation becomes an override to the + // package's text field. If they did not want zero, they specify + // what they want explicitly. + double degrees = a.rot ? a.rot->degrees : 0; + double orient; // relative to parent + + int sign = 1; + bool spin = false; + + if( a.rot ) + { + spin = a.rot->spin; + sign = a.rot->mirror ? -1 : 1; + txt->SetMirrored( a.rot->mirror ); + } + + if( degrees == 90 || degrees == 0 || spin ) + { + orient = degrees - m->GetOrientation() / 10; + txt->SetOrientation( sign * orient * 10 ); + } + + else if( degrees == 180 ) + { + orient = 0 - m->GetOrientation() / 10; + txt->SetOrientation( sign * orient * 10 ); + align = ETEXT::TOP_RIGHT; + } + + else if( degrees == 270 ) + { + orient = 90 - m->GetOrientation() / 10; + align = ETEXT::TOP_RIGHT; + txt->SetOrientation( sign * orient * 10 ); + } + + switch( align ) + { + case ETEXT::TOP_RIGHT: + txt->SetHorizJustify( GR_TEXT_HJUSTIFY_RIGHT ); + txt->SetVertJustify( GR_TEXT_VJUSTIFY_TOP ); + break; + + case ETEXT::BOTTOM_LEFT: + txt->SetHorizJustify( GR_TEXT_HJUSTIFY_LEFT ); + txt->SetVertJustify( GR_TEXT_VJUSTIFY_BOTTOM ); + break; + + default: + ; + } + } + + else // the text is per the original package, sans + { + double degrees = ( txt->GetOrientation() + m->GetOrientation() ) / 10; + + // @todo there are a few more cases than theses to contend with: + if( (!txt->IsMirrored() && ( abs( degrees ) == 180 || abs( degrees ) == 270 )) + || ( txt->IsMirrored() && ( degrees == 360 ) ) ) + { + // ETEXT::TOP_RIGHT: + txt->SetHorizJustify( GR_TEXT_HJUSTIFY_RIGHT ); + txt->SetVertJustify( GR_TEXT_VJUSTIFY_TOP ); + } + } +} + + MODULE* EAGLE_PLUGIN::makeModule( CPTREE& aPackage, const std::string& aPkgName ) const { std::auto_ptr m( new MODULE( NULL ) ); @@ -1684,31 +1900,19 @@ void EAGLE_PLUGIN::packagePad( MODULE* aModule, CPTREE& aTree ) const } else { - // The pad size is optional in the eagle DTD, so we must guess. - // Supply something here that is a minimum copper surround, or otherwise - // 120% of drillz whichever is greater. But for PAD_OVAL, we can use - // a smaller minimum than for a round pad, since there is a larger copper - // body on the elongated ends. - - int min_copper; - - if( pad->GetShape() == PAD_OVAL ) - min_copper = Mils2iu( 4 ); - else - min_copper = Mils2iu( 6 ); - - // minz copper surround as a minimum, otherwise 110% of drillz. - int drillz = pad->GetDrillSize().x; - int diameter = std::max( drillz + 2 * min_copper, int( drillz * 1.2 ) ); - - pad->SetSize( wxSize( diameter, diameter ) ); + double drillz = pad->GetDrillSize().x; + double annulus = drillz * m_rules->rvPadTop; // copper annulus, eagle "restring" + annulus = Clamp( m_rules->rlMinPadTop, annulus, m_rules->rlMaxPadTop ); + int diameter = KiROUND( drillz + 2 * annulus ); + pad->SetSize( wxSize( KiROUND( diameter ), KiROUND( diameter ) ) ); } if( pad->GetShape() == PAD_OVAL ) { - // The Eagle "long" pad seems to be tall, "width = height x 4/3" apparently. + // The Eagle "long" pad is wider than it is tall, + // m_elongation is percent elongation wxSize sz = pad->GetSize(); - sz.x = (sz.x * 4)/3; + sz.x = ( sz.x * ( 100 + m_rules->psElongationLong ) ) / 100; pad->SetSize( sz ); } @@ -1746,13 +1950,6 @@ void EAGLE_PLUGIN::packageText( MODULE* aModule, CPTREE& aTree ) const txt->SetPosition( pos ); txt->SetPos0( pos - aModule->GetPosition() ); - /* - switch( layer ) - { - case COMMENT_N: layer = SILKSCREEN_N_FRONT; break; - } - */ - txt->SetLayer( layer ); txt->SetSize( kicad_fontz( t.size ) ); @@ -1761,26 +1958,32 @@ void EAGLE_PLUGIN::packageText( MODULE* aModule, CPTREE& aTree ) const txt->SetThickness( kicad( t.size * ratio / 100 ) ); - double angle = t.rot ? t.rot->degrees * 10 : 0; + int align = t.align ? *t.align : ETEXT::BOTTOM_LEFT; // bottom-left is eagle default // An eagle package is never rotated, the DTD does not allow it. // angle -= aModule->GetOrienation(); - int sign = 1; if( t.rot ) { - if( t.rot->spin || (angle != 1800 && angle != 2700) ) - txt->SetOrientation( angle ); - - else // 180 or 270 degrees, reverse justification below, don't spin - sign = -1; - + int sign = t.rot->mirror ? -1 : 1; txt->SetMirrored( t.rot->mirror ); + + double degrees = t.rot->degrees; + + if( degrees == 90 || t.rot->spin ) + txt->SetOrientation( sign * degrees * 10 ); + + else if( degrees == 180 ) + align = ETEXT::TOP_RIGHT; + + else if( degrees == 270 ) + { + align = ETEXT::TOP_RIGHT; + txt->SetOrientation( sign * 90 * 10 ); + } } - int align = t.align ? *t.align : ETEXT::BOTTOM_LEFT; // bottom-left is eagle default - - switch( align * sign ) // when negative, opposites are chosen + switch( align ) { case ETEXT::CENTER: // this was the default in pcbtxt's constructor @@ -1995,7 +2198,11 @@ void EAGLE_PLUGIN::packageSMD( MODULE* aModule, CPTREE& aTree ) const pad->SetSize( wxSize( kicad( e.dx ), kicad( e.dy ) ) ); pad->SetLayer( layer ); - pad->SetLayerMask( LAYER_FRONT | SOLDERPASTE_LAYER_FRONT | SOLDERMASK_LAYER_FRONT ); + + if( layer == LAYER_N_FRONT ) + pad->SetLayerMask( LAYER_FRONT | SOLDERPASTE_LAYER_FRONT | SOLDERMASK_LAYER_FRONT ); + else if( layer == LAYER_N_BACK ) + pad->SetLayerMask( LAYER_BACK | SOLDERPASTE_LAYER_BACK | SOLDERMASK_LAYER_BACK ); // Optional according to DTD if( e.roundness ) // set set shape to PAD_RECT above, in case roundness is not present @@ -2082,8 +2289,6 @@ void EAGLE_PLUGIN::loadSignals( CPTREE& aSignals ) via->SetLayerPair( layer_front_most, layer_back_most ); - // via diameters are externally controllable, not usually in a board: - // http://www.eaglecentral.ca/forums/index.php/mv/msg/34704/119478/ if( v.diam ) { int kidiam = kicad( *v.diam ); @@ -2091,7 +2296,9 @@ void EAGLE_PLUGIN::loadSignals( CPTREE& aSignals ) } else { - int diameter = std::max( drillz + 2 * Mils2iu( 6 ), int( drillz * 2.0 ) ); + double annulus = drillz * m_rules->rvViaOuter; // eagle "restring" + annulus = Clamp( m_rules->rlMinViaOuter, annulus, m_rules->rlMaxViaOuter ); + int diameter = KiROUND( drillz + 2 * annulus ); via->SetWidth( diameter ); } diff --git a/pcbnew/eagle_plugin.h b/pcbnew/eagle_plugin.h index 25bf85a5d1..41ea4af6d9 100644 --- a/pcbnew/eagle_plugin.h +++ b/pcbnew/eagle_plugin.h @@ -62,7 +62,12 @@ typedef NET_MAP::const_iterator NET_MAP_CITER; typedef boost::property_tree::ptree PTREE; typedef const PTREE CPTREE; +class EELEMENT; class XPATH; +struct ERULES; +struct EATTR; +class TEXTE_MODULE; + /** * Class EAGLE_PLUGIN @@ -107,6 +112,7 @@ public: private: + ERULES* m_rules; ///< Eagle design rules. XPATH* m_xpath; ///< keeps track of what we are working on within ///< XML document during a Load(). @@ -173,12 +179,17 @@ private: // all these loadXXX() throw IO_ERROR or ptree_error exceptions: void loadAllSections( CPTREE& aDocument ); + void loadDesignRules( CPTREE& aDesignRules ); void loadLayerDefs( CPTREE& aLayers ); void loadPlain( CPTREE& aPlain ); void loadSignals( CPTREE& aSignals ); void loadLibraries( CPTREE& aLibs ); void loadElements( CPTREE& aElements ); + void orientModuleAndText( MODULE* m, const EELEMENT& e, const EATTR* nameAttr, const EATTR* valueAttr ); + void orientModuleText( MODULE* m, const EELEMENT& e, TEXTE_MODULE* txt, const EATTR* a ); + + /// move the BOARD into the center of the page void centerBoard(); diff --git a/pcbnew/edgemod.cpp b/pcbnew/edgemod.cpp index ac959dec6d..7757094c5b 100644 --- a/pcbnew/edgemod.cpp +++ b/pcbnew/edgemod.cpp @@ -1,9 +1,10 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2011 Wayne Stambaugh - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2012 Wayne Stambaugh + * Copyright (C) 1992-2012 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 diff --git a/pcbnew/edit.cpp b/pcbnew/edit.cpp index 4f1bd33441..194d94b742 100644 --- a/pcbnew/edit.cpp +++ b/pcbnew/edit.cpp @@ -1,9 +1,10 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2007 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2011 Wayne Stambaugh - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2012 Wayne Stambaugh + * Copyright (C) 1992-2012 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 @@ -467,6 +468,13 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event ) SetCurItem( NULL ); // Outlines can have changed break; + case ID_POPUP_PCB_ZONE_DUPLICATE: + { + ZONE_CONTAINER* zone = (ZONE_CONTAINER*) GetCurItem(); + duplicateZone( &dc, zone ); + } + break; + case ID_POPUP_PCB_ZONE_ADD_SIMILAR_ZONE: m_canvas->MoveCursorToCrossHair(); m_canvas->SetAutoPanRequest( true ); diff --git a/pcbnew/edit_pcb_text.cpp b/pcbnew/edit_pcb_text.cpp index 249c223b65..c04f6556fa 100644 --- a/pcbnew/edit_pcb_text.cpp +++ b/pcbnew/edit_pcb_text.cpp @@ -1,8 +1,9 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 1992-2012 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 diff --git a/pcbnew/editedge.cpp b/pcbnew/editedge.cpp index 66a5171ac2..9969e83e2d 100644 --- a/pcbnew/editedge.cpp +++ b/pcbnew/editedge.cpp @@ -1,8 +1,9 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 1992-2012 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 diff --git a/pcbnew/editrack-part2.cpp b/pcbnew/editrack-part2.cpp index c9f265a5b9..467cb6b999 100644 --- a/pcbnew/editrack-part2.cpp +++ b/pcbnew/editrack-part2.cpp @@ -1,9 +1,10 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2006 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2011 Wayne Stambaugh - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2012 Wayne Stambaugh + * Copyright (C) 1992-2012 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 diff --git a/pcbnew/editrack.cpp b/pcbnew/editrack.cpp index ca3e87cd43..472e1ca18d 100644 --- a/pcbnew/editrack.cpp +++ b/pcbnew/editrack.cpp @@ -1,9 +1,10 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2009 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2011 Wayne Stambaugh - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2012 Wayne Stambaugh + * Copyright (C) 1992-2012 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 diff --git a/pcbnew/export_gencad.cpp b/pcbnew/export_gencad.cpp index 5bcc2ce502..9ae7d4bef0 100644 --- a/pcbnew/export_gencad.cpp +++ b/pcbnew/export_gencad.cpp @@ -1,9 +1,10 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2008-2011 Wayne Stambaugh - * Copyright (C) 2004-2011 KiCad Developers, see change_log.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2012 Wayne Stambaugh + * Copyright (C) 1992-2012 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 diff --git a/pcbnew/export_vrml.cpp b/pcbnew/export_vrml.cpp index d1c2cfebcf..093070d2a8 100644 --- a/pcbnew/export_vrml.cpp +++ b/pcbnew/export_vrml.cpp @@ -1,7 +1,5 @@ #include -#include #include -#include #include #include #include @@ -21,6 +19,8 @@ #include +#define SEGM_COUNT_PER_360 32 // Number of segments to approximate a circle per segments + /* helper function: * some characters cannot be used in names, * this function change them to "_" @@ -43,8 +43,9 @@ private: wxConfig* m_config; int m_unitsOpt; // to remember last option int m_3DFilesOpt; // to remember last option - virtual void OnCancelClick( wxCommandEvent& event ){ EndModal( wxID_CANCEL ); } - virtual void OnOkClick( wxCommandEvent& event ){ EndModal( wxID_OK ); } + + void OnCancelClick( wxCommandEvent& event ){ EndModal( wxID_CANCEL ); } + void OnOkClick( wxCommandEvent& event ){ EndModal( wxID_OK ); } public: DIALOG_EXPORT_3DFILE( PCB_EDIT_FRAME* parent ) : @@ -104,8 +105,9 @@ struct VRMLPt }; struct FlatPt { - FlatPt( double _x = 0, double _y = 0 ) : x( _x ), y( _y ) { } - double x, y; + FlatPt( double _x = 0, double _y = 0 ) : x( _x ), y( _y ) + { } + double x, y; }; struct Triangle { @@ -277,7 +279,7 @@ static void write_triangle_bag( FILE* output_file, int color_index, //{{{ " }\n", " }\n", " geometry IndexedFaceSet {\n", - " solid true\n", + " solid TRUE\n", " coord Coordinate {\n", " point [\n", 0, // Coordinates marker @@ -369,7 +371,7 @@ static void compute_layer_Zs( BOARD* pcb ) //{{{ int copper_layers = pcb->GetCopperLayerCount( ); // We call it 'layer' thickness, but it's the whole board thickness! - double board_thickness = pcb->GetDesignSettings().m_BoardThickness; + double board_thickness = pcb->GetDesignSettings().GetBoardThickness(); double half_thickness = board_thickness / 2; // Compute each layer's Z value, more or less like the 3d view @@ -383,7 +385,7 @@ static void compute_layer_Zs( BOARD* pcb ) //{{{ /* To avoid rounding interference, we apply an epsilon to each * successive layer */ - const double epsilon_z = 10; // That's 1 mils, about 1/50 mm + const double epsilon_z = 1 * IU_PER_MILS; // That's 1 mils, about 1/50 mm layer_z[SOLDERPASTE_N_BACK] = -half_thickness - epsilon_z * 4; layer_z[ADHESIVE_N_BACK] = -half_thickness - epsilon_z * 3; layer_z[SILKSCREEN_N_BACK] = -half_thickness - epsilon_z * 2; @@ -429,8 +431,8 @@ static void export_vrml_line( int layer, double startx, double starty, //{{{ } -static void export_vrml_circle( int layer, double startx, double starty, //{{{ - double endx, double endy, double width, int divisions ) +static void export_vrml_circle( int layer, double startx, double starty, + double endx, double endy, double width ) { double hole, radius; FlatRing ring; @@ -438,7 +440,7 @@ static void export_vrml_circle( int layer, double startx, double starty, //{{{ radius = hypot( startx - endx, starty - endy ) + ( width / 2); hole = radius - width; - for( double alpha = 0; alpha < M_PI * 2; alpha += M_PI * 2 / divisions ) + for( double alpha = 0; alpha < M_PI * 2; alpha += M_PI * 2 / SEGM_COUNT_PER_360 ) { ring.add_inner( startx + hole * cos( alpha ), starty + hole * sin( alpha ) ); ring.add_outer( startx + radius * cos( alpha ), starty + radius * sin( alpha ) ); @@ -450,10 +452,11 @@ static void export_vrml_circle( int layer, double startx, double starty, //{{{ static void export_vrml_slot( TriangleBag& triangles, //{{{ int top_layer, int bottom_layer, double xc, double yc, - double dx, double dy, int orient, int divisions ) + double dx, double dy, int orient ) { double capx, capy; // Cap center VLoop loop; + int divisions = SEGM_COUNT_PER_360 / 2; loop.z_top = layer_z[top_layer]; loop.z_bottom = layer_z[bottom_layer]; @@ -491,45 +494,23 @@ static void export_vrml_slot( TriangleBag& triangles, //{{{ } -static void export_vrml_hole( TriangleBag& triangles, //{{{ - int top_layer, int bottom_layer, double xc, double yc, double hole, - int divisions ) +static void export_vrml_hole( TriangleBag& triangles, int top_layer, int bottom_layer, + double xc, double yc, double hole ) { VLoop loop; loop.z_top = layer_z[top_layer]; loop.z_bottom = layer_z[bottom_layer]; - for( double alpha = 0; alpha < M_PI * 2; alpha += M_PI * 2 / divisions ) + for( double alpha = 0; alpha < M_PI * 2; alpha += M_PI * 2 / SEGM_COUNT_PER_360 ) loop.add( xc + cos( alpha ) * hole, yc + sin( alpha ) * hole ); loop.bag( triangles ); } -static void export_vrml_varc( TriangleBag& triangles, //{{{ - int top_layer, int bottom_layer, double startx, double starty, - double endx, double endy, int divisions ) -{ - VLoop loop; - - loop.z_top = layer_z[top_layer]; - loop.z_bottom = layer_z[bottom_layer]; - double angle = atan2( endx - startx, endy - starty ); - double radius = hypot( startx - endx, starty - endy ); - - for( double alpha = angle; alpha < angle + PI2; alpha += PI2 / divisions ) - { - loop.add( startx + cos( alpha ) * radius, starty + sin( alpha ) * radius ); - } - - loop.bag( triangles ); -} - - -static void export_vrml_oval_pad( int layer, //{{{ - double xc, double yc, - double dx, double dy, int orient, int divisions ) +static void export_vrml_oval_pad( int layer, double xc, double yc, + double dx, double dy, int orient ) { double capx, capy; // Cap center FlatFan fan; @@ -537,6 +518,7 @@ static void export_vrml_oval_pad( int layer, //{{{ fan.c.x = xc; fan.c.y = yc; double angle = orient / 1800.0 * M_PI; + int divisions = SEGM_COUNT_PER_360 / 2; if( dy > dx ) { @@ -570,25 +552,68 @@ static void export_vrml_oval_pad( int layer, //{{{ } -static void export_vrml_arc( int layer, double startx, double starty, //{{{ - double endx, double endy, double width, int divisions ) +static void export_vrml_arc( int layer, double centerx, double centery, + double arc_startx, double arc_starty, + double width, double arc_angle ) { FlatRing ring; - double hole, radius; - double angle = atan2( endx - startx, endy - starty ); + double start_angle = atan2( arc_starty - centery, arc_startx - centerx ); - radius = hypot( startx - endx, starty - endy ) + ( width / 2); - hole = radius - width; + int count = KiROUND( arc_angle / 360.0 * SEGM_COUNT_PER_360 ); + if( count < 0 ) + count = -count; + if( count == 0 ) + count = 1; + double divisions = arc_angle*M_PI/180.0 / count; - for( double alpha = angle; alpha < angle + PI2; alpha += PI2 / divisions ) + double outer_radius = hypot( arc_starty - centery, arc_startx - centerx ) + + ( width / 2); + double inner_radius = outer_radius - width; + + double alpha = 0; + for( int ii = 0; ii <= count; alpha += divisions, ii++ ) { - ring.add_inner( startx + cos( alpha ) * hole, starty + sin( alpha ) * hole ); - ring.add_outer( startx + cos( alpha ) * radius, starty + sin( alpha ) * radius ); + double angle_rot = start_angle + alpha; + ring.add_inner( centerx + cos( angle_rot ) * inner_radius, + centery + sin( angle_rot ) * inner_radius ); + ring.add_outer( centerx + cos( angle_rot ) * outer_radius, + centery + sin( angle_rot ) * outer_radius ); } ring.bag( layer, false ); } +static void export_vrml_varc( TriangleBag& triangles, + int top_layer, int bottom_layer, + double centerx, double centery, + double arc_startx, double arc_starty, + double arc_angle ) +{ + VLoop loop; + + loop.z_top = layer_z[top_layer]; + loop.z_bottom = layer_z[bottom_layer]; + + double start_angle = atan2( arc_starty - centery, arc_startx - centerx ); + double radius = hypot( arc_starty - centery, arc_startx - centerx ); + + int count = KiROUND( arc_angle / 360.0 * SEGM_COUNT_PER_360 ); + if( count < 0 ) + count = -count; + if( count == 0 ) + count = 1; + double divisions = arc_angle*M_PI/180.0 / count; + + double alpha = 0; + for( int ii = 0; ii <= count; alpha += divisions, ii++ ) + { + double angle_rot = start_angle + alpha; + loop.add( centerx + cos( angle_rot ) * radius, centery + sin( angle_rot ) * radius ); + } + + loop.bag( triangles ); +} + static void export_vrml_drawsegment( DRAWSEGMENT* drawseg ) //{{{ { @@ -608,14 +633,14 @@ static void export_vrml_drawsegment( DRAWSEGMENT* drawseg ) //{{{ case S_ARC: export_vrml_varc( layer_triangles[layer], FIRST_COPPER_LAYER, LAST_COPPER_LAYER, - x, y, xf, yf, 4 ); + x, y, xf, yf, drawseg->GetAngle()/10 ); break; // Circles on edge are usually important holes case S_CIRCLE: export_vrml_hole( layer_triangles[layer], FIRST_COPPER_LAYER, LAST_COPPER_LAYER, x, y, - hypot( xf - x, yf - y ) / 2, 12 ); + hypot( xf - x, yf - y ) / 2 ); break; default: @@ -633,11 +658,16 @@ static void export_vrml_drawsegment( DRAWSEGMENT* drawseg ) //{{{ switch( drawseg->GetShape() ) { case S_ARC: - export_vrml_arc( layer, x, y, xf, yf, w, 3 ); + export_vrml_arc( layer, + (double) drawseg->GetCenter().x, + (double) drawseg->GetCenter().y, + (double) drawseg->GetArcStart().x, + (double) drawseg->GetArcStart().y, + w, drawseg->GetAngle()/10 ); break; case S_CIRCLE: - export_vrml_circle( layer, x, y, xf, yf, w, 12 ); + export_vrml_circle( layer, x, y, xf, yf, w ); break; default: @@ -727,7 +757,7 @@ static void export_vrml_drawings( BOARD* pcb ) //{{{ static void export_round_padstack( BOARD* pcb, double x, double y, double r, //{{{ - int bottom_layer, int top_layer, int divisions ) + int bottom_layer, int top_layer ) { int copper_layers = pcb->GetCopperLayerCount( ); @@ -738,7 +768,7 @@ static void export_round_padstack( BOARD* pcb, double x, double y, double r, //{ layer = LAST_COPPER_LAYER; if( layer <= top_layer ) - export_vrml_circle( layer, x, y, x + r / 2, y, r, divisions ); + export_vrml_circle( layer, x, y, x + r / 2, y, r ); } } @@ -755,10 +785,10 @@ static void export_vrml_via( BOARD* pcb, SEGVIA* via ) //{{{ via->ReturnLayerPair( &top_layer, &bottom_layer ); // Export the via padstack - export_round_padstack( pcb, x, y, r, bottom_layer, top_layer, 8 ); + export_round_padstack( pcb, x, y, r, bottom_layer, top_layer ); - // Drill a rough hole - export_vrml_hole( via_triangles[via->m_Shape], top_layer, bottom_layer, x, y, hole, 8 ); + // Drill a hole + export_vrml_hole( via_triangles[via->m_Shape], top_layer, bottom_layer, x, y, hole ); } @@ -853,23 +883,23 @@ static void export_vrml_text_module( TEXTE_MODULE* module ) //{{{ } -static void export_vrml_edge_module( EDGE_MODULE* module ) //{{{ +static void export_vrml_edge_module( EDGE_MODULE* aOutline ) //{{{ { - int layer = module->GetLayer(); - double x = module->GetStart().x; - double y = module->GetStart().y; - double xf = module->GetEnd().x; - double yf = module->GetEnd().y; - double w = module->GetWidth(); + int layer = aOutline->GetLayer(); + double x = aOutline->GetStart().x; + double y = aOutline->GetStart().y; + double xf = aOutline->GetEnd().x; + double yf = aOutline->GetEnd().y; + double w = aOutline->GetWidth(); - switch( module->GetShape() ) + switch( aOutline->GetShape() ) { case S_ARC: - export_vrml_arc( layer, x, y, xf, yf, w, 3 ); + export_vrml_arc( layer, x, y, xf, yf, w, aOutline->GetAngle()/10 ); break; case S_CIRCLE: - export_vrml_circle( layer, x, y, xf, yf, w, 12 ); + export_vrml_circle( layer, x, y, xf, yf, w ); break; default: @@ -895,14 +925,14 @@ static void export_vrml_pad( BOARD* pcb, D_PAD* aPad ) //{{{ // Oblong hole (slot) export_vrml_slot( layer_triangles[EDGE_N], FIRST_COPPER_LAYER, LAST_COPPER_LAYER, - hole_x, hole_y, hole_drill_w, hole_drill_h, aPad->GetOrientation(), 6 ); + hole_x, hole_y, hole_drill_w, hole_drill_h, aPad->GetOrientation() ); } else { // Drill a round hole export_vrml_hole( layer_triangles[EDGE_N], FIRST_COPPER_LAYER, LAST_COPPER_LAYER, - hole_x, hole_y, hole_drill, 12 ); + hole_x, hole_y, hole_drill ); } } @@ -935,13 +965,12 @@ static void export_vrml_pad( BOARD* pcb, D_PAD* aPad ) //{{{ { case PAD_CIRCLE: export_vrml_circle( layer, pad_x, pad_y, - pad_x + pad_w / 2, pad_y, pad_w, 12 ); + pad_x + pad_w / 2, pad_y, pad_w ); break; case PAD_OVAL: - export_vrml_oval_pad( layer, - pad_x, pad_y, - pad_w * 2, pad_h * 2, aPad->GetOrientation(), 4 ); + export_vrml_oval_pad( layer, pad_x, pad_y, + pad_w * 2, pad_h * 2, aPad->GetOrientation() ); break; case PAD_RECT: @@ -1192,7 +1221,7 @@ wxBusyCursor dummy; if( ! ExportVRML_File( fullFilename, scale, export3DFiles, subDirFor3Dshapes ) ) { wxString msg = _( "Unable to create " ) + fullFilename; - DisplayError( this, msg ); + wxMessageBox( msg ); return; } } diff --git a/pcbnew/files.cpp b/pcbnew/files.cpp index 6d5d6bd4b8..9be277668e 100644 --- a/pcbnew/files.cpp +++ b/pcbnew/files.cpp @@ -176,10 +176,12 @@ the changes?" ) ) ) // load a BOARD. Order is subject to change as KICAD plugin matures. // User may occasionally use the wrong plugin to load a *.brd file, // but eventually *.kicad_pcb will be more common than legacy *.brd files. - static const struct { + static const struct + { const wxString& filter; IO_MGR::PCB_FILE_T pluginType; - } loaders[] = { + } loaders[] = + { { LegacyPcbFileWildcard, IO_MGR::LEGACY }, { PcbFileWildcard, IO_MGR::KICAD }, { EaglePcbFileWildcard, IO_MGR::EAGLE }, @@ -216,6 +218,12 @@ the changes?" ) ) ) int chosenFilter = dlg.GetFilterIndex(); pluginType = loaders[chosenFilter].pluginType; } + else // if a filename is given, force IO_MGR::KICAD if the file est is kicad_pcb + // for instance if the filename comes from file history + { + if( fileName.GetExt() == IO_MGR::GetFileExtension( IO_MGR::KICAD ) ) + pluginType = IO_MGR::KICAD; + } PLUGIN::RELEASER pi( IO_MGR::PluginFind( pluginType ) ); diff --git a/pcbnew/find.pjd b/pcbnew/find.pjd deleted file mode 100644 index f079ddc8ba..0000000000 --- a/pcbnew/find.pjd +++ /dev/null @@ -1,842 +0,0 @@ - - -
- 0 - "" - "" - "" - "" - "" - 0 - 0 - 0 - 1 - 1 - 1 - 1 - 0 - "jean-pierre Charras" - "License GNU" - "" - 0 - 0 - 0 - "<All platforms>" - "<Any>" - "///////////////////////////////////////////////////////////////////////////// -// Name: %HEADER-FILENAME% -// Purpose: -// Author: %AUTHOR% -// Modified by: -// Created: %DATE% -// RCS-ID: -// Copyright: %COPYRIGHT% -// Licence: -///////////////////////////////////////////////////////////////////////////// - -" - "///////////////////////////////////////////////////////////////////////////// -// Name: %SOURCE-FILENAME% -// Purpose: -// Author: %AUTHOR% -// Modified by: -// Created: %DATE% -// RCS-ID: -// Copyright: %COPYRIGHT% -// Licence: -///////////////////////////////////////////////////////////////////////////// - -" - "///////////////////////////////////////////////////////////////////////////// -// Name: %SYMBOLS-FILENAME% -// Purpose: Symbols file -// Author: %AUTHOR% -// Modified by: -// Created: %DATE% -// RCS-ID: -// Copyright: %COPYRIGHT% -// Licence: -///////////////////////////////////////////////////////////////////////////// - -" - "#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) -#pragma interface "%HEADER-FILENAME%" -#endif - -" - "#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) -#pragma implementation "%HEADER-FILENAME%" -#endif - -// For compilers that support precompilation, includes "wx/wx.h". -#include "wx/wxprec.h" - -#ifdef __BORLANDC__ -#pragma hdrstop -#endif - -#ifndef WX_PRECOMP -#include "wx/wx.h" -#endif - -" - " /// %BODY% -" - " -/*! - * %BODY% - */ - -" - "app_resources.h" - "app_resources.cpp" - "AppResources" - "app.h" - "app.cpp" - "Application" - 0 - "" - "<None>" - "<System>" - "utf-8" - "<System>" - "" - 0 - 0 - 4 - " " - "" - 0 - 0 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 -
- - - "" - "data-document" - "" - "" - 0 - 1 - 0 - 0 - - "Configurations" - "config-data-document" - "" - "" - 0 - 1 - 0 - 0 - "" - 1 - 0 - "" - "Debug" - "ANSI" - "Static" - "Modular" - "GUI" - "wxMSW" - "Dynamic" - "Yes" - "No" - "No" - "%WXVERSION%" - "%EXECUTABLE%" - "" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - "%AUTO%" - 0 - 1 - "" - - - - - - - "Projects" - "root-document" - "" - "project" - 1 - 1 - 0 - 1 - - "Windows" - "html-document" - "" - "dialogsfolder" - 1 - 1 - 0 - 1 - - "Find" - "dialog-document" - "" - "dialog" - 0 - 1 - 0 - 0 - "4/3/2006" - "wbDialogProxy" - 10000 - 0 - "" - 0 - "" - 0 - 0 - "ID_DIALOG" - 10000 - "WinEDA_PcbFindFrame" - "wxDialog" - "wxDialog" - "find.cpp" - "find.h" - "" - "Find" - 1 - "" - 0 - "" - "" - "" - "" - "" - 0 - 1 - "<Any platform>" - "" - "" - "" - "" - "" - "" - "Tiled" - 0 - 1 - 0 - 1 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - "MAYBE_RESIZE_BORDER" - 0 - 1 - -1 - -1 - 400 - 300 - 0 - "" - - "wxBoxSizer V" - "dialog-control-document" - "" - "sizer" - 0 - 1 - 0 - 0 - "wbBoxSizerProxy" - "Vertical" - "" - 0 - 0 - 0 - "<Any platform>" - - "wxStaticText: wxID_STATIC" - "dialog-control-document" - "" - "statictext" - 0 - 1 - 0 - 0 - "4/3/2006" - "wbStaticTextProxy" - "wxID_STATIC" - 5105 - "" - "wxStaticText" - "wxStaticText" - 1 - 0 - "" - "" - "" - "Item to find:" - -1 - "" - "" - "" - "" - "" - 0 - 1 - "<Any platform>" - "" - "" - "" - "" - "" - "" - "" - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - "" - -1 - -1 - -1 - -1 - "Expand" - "Centre" - 0 - 5 - 1 - 1 - 1 - 0 - 0 - 1 - 0 - "" - "" - - - "wxTextCtrl: ID_TEXTCTRL" - "dialog-control-document" - "" - "textctrl" - 0 - 1 - 0 - 0 - "4/3/2006" - "wbTextCtrlProxy" - "ID_TEXTCTRL" - 10001 - "" - "wxTextCtrl" - "wxTextCtrl" - 1 - 0 - "" - "" - "m_NewText" - "" - 0 - "" - "" - "" - "" - "" - 0 - 1 - "<Any platform>" - "" - "" - "" - "" - "" - "" - "" - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - "" - -1 - -1 - -1 - -1 - "Expand" - "Centre" - 0 - 5 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - "" - "" - 0 - - - "wxBoxSizer H" - "dialog-control-document" - "" - "sizer" - 0 - 1 - 0 - 0 - "4/3/2006" - "wbBoxSizerProxy" - "Horizontal" - "" - "Centre" - "Centre" - 0 - 5 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - "<Any platform>" - - "wxBoxSizer V" - "dialog-control-document" - "" - "sizer" - 0 - 1 - 0 - 0 - "4/3/2006" - "wbBoxSizerProxy" - "Vertical" - "" - "Centre" - "Centre" - 0 - 5 - 1 - 1 - 0 - 0 - 0 - 0 - 0 - "<Any platform>" - - "wxButton: ID_FIND_ITEM" - "dialog-control-document" - "" - "dialogcontrol" - 0 - 1 - 0 - 0 - "4/3/2006" - "wbButtonProxy" - "wxEVT_COMMAND_BUTTON_CLICKED|OnFindItemClick" - "ID_FIND_ITEM" - 10002 - "" - "wxButton" - "wxButton" - 1 - 0 - "" - "" - "" - "Find Item" - 1 - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - 0 - 1 - "<Any platform>" - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - "" - -1 - -1 - -1 - -1 - "Expand" - "Centre" - 0 - 5 - 1 - 1 - 1 - 0 - 0 - 0 - 0 - "" - "" - - - "wxButton: ID_FIND_NEXT_ITEM" - "dialog-control-document" - "" - "dialogcontrol" - 0 - 1 - 0 - 0 - "4/3/2006" - "wbButtonProxy" - "wxEVT_COMMAND_BUTTON_CLICKED|OnFindNextItemClick" - "ID_FIND_NEXT_ITEM" - 10003 - "" - "wxButton" - "wxButton" - 1 - 0 - "" - "" - "" - "Find Next Item" - 0 - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "6F0000" - "" - 0 - 1 - "<Any platform>" - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - "" - -1 - -1 - -1 - -1 - "Expand" - "Centre" - 0 - 5 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - "" - "" - - - - "wxBoxSizer V" - "dialog-control-document" - "" - "sizer" - 0 - 1 - 0 - 0 - "4/3/2006" - "wbBoxSizerProxy" - "Vertical" - "" - "Centre" - "Centre" - 0 - 5 - 1 - 1 - 0 - 0 - 0 - 0 - 0 - "<Any platform>" - - "wxButton: ID_FIND_MARKER" - "dialog-control-document" - "" - "dialogcontrol" - 0 - 1 - 0 - 0 - "4/3/2006" - "wbButtonProxy" - "wxEVT_COMMAND_BUTTON_CLICKED|OnFindMarkerClick" - "ID_FIND_MARKER" - 10004 - "" - "wxButton" - "wxButton" - 1 - 0 - "" - "" - "" - "Find Marker" - 0 - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - 0 - 1 - "<Any platform>" - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - "" - -1 - -1 - -1 - -1 - "Expand" - "Centre" - 0 - 5 - 1 - 1 - 1 - 0 - 0 - 0 - 0 - "" - "" - - - "wxButton: ID_FIND_NEXT_MARKER" - "dialog-control-document" - "" - "dialogcontrol" - 0 - 1 - 0 - 0 - "4/3/2006" - "wbButtonProxy" - "wxEVT_COMMAND_BUTTON_CLICKED|OnFindNextMarkerClick" - "ID_FIND_NEXT_MARKER" - 10005 - "" - "wxButton" - "wxButton" - 1 - 0 - "" - "" - "" - "Find Next Marker" - 0 - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - 0 - 1 - "<Any platform>" - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - "" - -1 - -1 - -1 - -1 - "Expand" - "Centre" - 0 - 5 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - "" - "" - - - - - - - - "Sources" - "html-document" - "" - "sourcesfolder" - 1 - 1 - 0 - 1 - - "find.rc" - "source-editor-document" - "find.rc" - "source-editor" - 0 - 0 - 1 - 0 - "4/3/2006" - "" - - - - "Images" - "html-document" - "" - "bitmapsfolder" - 1 - 1 - 0 - 1 - - - - -
diff --git a/pcbnew/gpcb_exchange.cpp b/pcbnew/gpcb_exchange.cpp index 4649825972..878ff12422 100644 --- a/pcbnew/gpcb_exchange.cpp +++ b/pcbnew/gpcb_exchange.cpp @@ -3,6 +3,30 @@ * @brief Import functions to import footprints from a gpcb (Newlib) library. */ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 1992-2012 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 + */ + #include #include #include @@ -16,6 +40,7 @@ #include #include +#include /* read parameters from a line, and return all params in a wxArrayString @@ -155,9 +180,9 @@ static bool TestFlags( const wxString& flg_string, long flg_mask, const wxChar* */ bool MODULE::Read_GPCB_Descr( const wxString& CmpFullFileName ) { - #define TEXT_DEFAULT_SIZE 400 - #define OLD_GPCB_UNIT_CONV 10 - #define NEW_GPCB_UNIT_CONV 0.1 + #define TEXT_DEFAULT_SIZE (40*IU_PER_MILS) + #define OLD_GPCB_UNIT_CONV IU_PER_MILS + #define NEW_GPCB_UNIT_CONV (0.01*IU_PER_MILS) FILE* cmpfile; double conv_unit = NEW_GPCB_UNIT_CONV; // GPCB unit = 0.01 mils and Pcbnew 0.1 @@ -253,7 +278,7 @@ bool MODULE::Read_GPCB_Descr( const wxString& CmpFullFileName ) m_Reference->SetPos0( pos ); m_Reference->SetOrientation( ibuf[idx+2] ? 900 : 0 ); - // Calculate size: default is 40 mils (400 pcb units) + // Calculate size: default is 40 mils // real size is: default * ibuf[idx+3] / 100 (size in gpcb is given in percent of default size int tsize = ( ibuf[idx+3] * TEXT_DEFAULT_SIZE ) / 100; int thickness = m_Reference->m_Size.x / 6; diff --git a/pcbnew/highlight.cpp b/pcbnew/highlight.cpp index 1a918893e1..ef7d7cd599 100644 --- a/pcbnew/highlight.cpp +++ b/pcbnew/highlight.cpp @@ -1,8 +1,9 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2007 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 1992-2012 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 diff --git a/pcbnew/kicad_plugin.cpp b/pcbnew/kicad_plugin.cpp index 0303c807a0..48f17ed166 100644 --- a/pcbnew/kicad_plugin.cpp +++ b/pcbnew/kicad_plugin.cpp @@ -1,1019 +1,1206 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2012 CERN - * Copyright (C) 1992-2011 KiCad Developers, see change_log.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 - */ - -#include -#include -#include -#include // LEGACY_BOARD_FILE_VERSION - -#include <3d_struct.h> - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define FMTIU BOARD_ITEM::FormatInternalUnits - - -void PCB_IO::Save( const wxString& aFileName, BOARD* aBoard, PROPERTIES* aProperties ) -{ - LOCALE_IO toggle; // toggles on, then off, the C locale. - - m_board = aBoard; - - wxFileOutputStream fs( aFileName ); - - if( !fs.IsOk() ) - { - m_error.Printf( _( "cannot open file '%s'" ), aFileName.GetData() ); - THROW_IO_ERROR( m_error ); - } - - STREAM_OUTPUTFORMATTER formatter( fs ); - - formatter.Print( 0, "(kicad-board (version %d) (host pcbnew %s)\n", SEXPR_BOARD_FILE_VERSION, - formatter.Quotew( GetBuildVersion() ).c_str() ); - Format( aBoard, (OUTPUTFORMATTER*) &formatter, 1, 0 ); - formatter.Print( 0, ")\n" ); -} - - -void PCB_IO::Format( BOARD_ITEM* aItem, OUTPUTFORMATTER* aFormatter, int aNestLevel, - int aControlBits ) const - throw( IO_ERROR ) -{ - switch( aItem->Type() ) - { - case PCB_T: - format( (BOARD*) aItem, aFormatter, aNestLevel, aControlBits ); - break; - - case PCB_DIMENSION_T: - format( ( DIMENSION*) aItem, aFormatter, aNestLevel, aControlBits ); - break; - - case PCB_LINE_T: - format( (DRAWSEGMENT*) aItem, aFormatter, aNestLevel, aControlBits ); - break; - - case PCB_MODULE_EDGE_T: - format( (EDGE_MODULE*) aItem, aFormatter, aNestLevel, aControlBits ); - break; - - case PCB_TARGET_T: - format( (PCB_TARGET*) aItem, aFormatter, aNestLevel, aControlBits ); - break; - - case PCB_MODULE_T: - format( (MODULE*) aItem, aFormatter, aNestLevel, aControlBits ); - break; - - case PCB_PAD_T: - format( (D_PAD*) aItem, aFormatter, aNestLevel, aControlBits ); - break; - - case PCB_TEXT_T: - format( (TEXTE_PCB*) aItem, aFormatter, aNestLevel, aControlBits ); - break; - - case PCB_MODULE_TEXT_T: - format( (TEXTE_MODULE*) aItem, aFormatter, aNestLevel, aControlBits ); - break; - - case PCB_TRACE_T: - case PCB_VIA_T: - format( (TRACK*) aItem, aFormatter, aNestLevel, aControlBits ); - break; - - case PCB_ZONE_AREA_T: - format( (ZONE_CONTAINER*) aItem, aFormatter, aNestLevel, aControlBits ); - break; - - default: - wxFAIL_MSG( wxT( "Cannot format item " ) + aItem->GetClass() ); - } -} - - -void PCB_IO::format( BOARD* aBoard, OUTPUTFORMATTER* aFormatter, int aNestLevel, - int aControlBits ) const - throw( IO_ERROR ) -{ - aFormatter->Print( aNestLevel, ")\n" ); - aFormatter->Print( 0, "\n" ); - - aFormatter->Print( aNestLevel, "(general\n" ); - aFormatter->Print( aNestLevel+1, "(links %d)\n", aBoard->GetRatsnestsCount() ); - aFormatter->Print( aNestLevel+1, "(no_connects %d)\n", aBoard->m_NbNoconnect ); - - // Write Bounding box info - aFormatter->Print( aNestLevel+1, "(area %s %s %s %s)\n", - FMTIU( aBoard->GetBoundingBox().GetX() ).c_str(), - FMTIU( aBoard->GetBoundingBox().GetY() ).c_str(), - FMTIU( aBoard->GetBoundingBox().GetRight() ).c_str(), - FMTIU( aBoard->GetBoundingBox().GetBottom() ).c_str() ); - aFormatter->Print( aNestLevel+1, "(thickness %s)\n", - FMTIU( aBoard->GetDesignSettings().m_BoardThickness ).c_str() ); - - aFormatter->Print( aNestLevel+1, "(drawings %d)\n", aBoard->m_Drawings.GetCount() ); - aFormatter->Print( aNestLevel+1, "(tracks %d)\n", aBoard->GetNumSegmTrack() ); - aFormatter->Print( aNestLevel+1, "(zones %d)\n", aBoard->GetNumSegmZone() ); - aFormatter->Print( aNestLevel+1, "(modules %d)\n", aBoard->m_Modules.GetCount() ); - aFormatter->Print( aNestLevel+1, "(nets %d)\n", aBoard->GetNetCount() ); - aFormatter->Print( aNestLevel, ")\n\n" ); - - aBoard->GetPageSettings().Format( aFormatter, aNestLevel, aControlBits ); - aBoard->GetTitleBlock().Format( aFormatter, aNestLevel, aControlBits ); - - // Layers. - aFormatter->Print( aNestLevel, "(layers %d %08X", aBoard->GetCopperLayerCount(), - aBoard->GetEnabledLayers() ); - - if( aBoard->GetEnabledLayers() != aBoard->GetVisibleLayers() ) - aFormatter->Print( 0, " %08X", aBoard->GetVisibleLayers() ); - - aFormatter->Print( 0, "\n" ); - - unsigned layerMask = ALL_CU_LAYERS & aBoard->GetEnabledLayers(); - - for( int layer = 0; layerMask; ++layer, layerMask >>= 1 ) - { - if( layerMask & 1 ) - { - aFormatter->Print( aNestLevel+1, "(layer%d %s %s)\n", layer, - aFormatter->Quotew( aBoard->GetLayerName( layer ) ).c_str(), - LAYER::ShowType( aBoard->GetLayerType( layer ) ) ); - } - } - - aFormatter->Print( aNestLevel, ")\n\n" ); - - // Setup - aFormatter->Print( aNestLevel, "(setup\n" ); - - // Save current default track width, for compatibility with older Pcbnew version; - aFormatter->Print( aNestLevel+1, "(last_trace_width %s)\n", - FMTIU( aBoard->m_TrackWidthList[aBoard->m_TrackWidthSelector] ).c_str() ); - - // Save custom tracks width list (the first is not saved here: this is the netclass value - for( unsigned ii = 1; ii < aBoard->m_TrackWidthList.size(); ii++ ) - aFormatter->Print( aNestLevel+1, "(user_trace_width%d %s)\n", - ii+1, FMTIU( aBoard->m_TrackWidthList[ii] ).c_str() ); - - aFormatter->Print( aNestLevel+1, "(trace_clearance %s)\n", - FMTIU( aBoard->m_NetClasses.GetDefault()->GetClearance() ).c_str() ); - - // ZONE_SETTINGS - aFormatter->Print( aNestLevel+1, "(zone_clearance %s)\n", - FMTIU( aBoard->GetZoneSettings().m_ZoneClearance ).c_str() ); - aFormatter->Print( aNestLevel+1, "(zone_45_only %d)\n", - aBoard->GetZoneSettings().m_Zone_45_Only ); - - aFormatter->Print( aNestLevel+1, "(trace_min %s)\n", - FMTIU( aBoard->GetDesignSettings().m_TrackMinWidth ).c_str() ); - - aFormatter->Print( aNestLevel+1, "(segment_width %s)\n", - FMTIU( aBoard->GetDesignSettings().m_DrawSegmentWidth ).c_str() ); - aFormatter->Print( aNestLevel+1, "(edge_width %s)\n", - FMTIU( aBoard->GetDesignSettings().m_EdgeSegmentWidth ).c_str() ); - - // Save current default via size, for compatibility with older Pcbnew version; - aFormatter->Print( aNestLevel+1, "(via_size %s)\n", - FMTIU( aBoard->m_NetClasses.GetDefault()->GetViaDiameter() ).c_str() ); - aFormatter->Print( aNestLevel+1, "(via_drill %s)\n", - FMTIU( aBoard->m_NetClasses.GetDefault()->GetViaDrill() ).c_str() ); - aFormatter->Print( aNestLevel+1, "(via_min_size %s)\n", - FMTIU( aBoard->GetDesignSettings().m_ViasMinSize ).c_str() ); - aFormatter->Print( aNestLevel+1, "(via_min_drill %s)\n", - FMTIU( aBoard->GetDesignSettings().m_ViasMinDrill ).c_str() ); - - // Save custom vias diameters list (the first is not saved here: this is - // the netclass value - for( unsigned ii = 1; ii < aBoard->m_ViasDimensionsList.size(); ii++ ) - aFormatter->Print( aNestLevel+1, "(user_via%d %s %s)\n", ii, - FMTIU( aBoard->m_ViasDimensionsList[ii].m_Diameter ).c_str(), - FMTIU( aBoard->m_ViasDimensionsList[ii].m_Drill ).c_str() ); - - // for old versions compatibility: - aFormatter->Print( aNestLevel+1, "(uvia_size %s)\n", - FMTIU( aBoard->m_NetClasses.GetDefault()->GetuViaDiameter() ).c_str() ); - aFormatter->Print( aNestLevel+1, "(uvia_drill %s)\n", - FMTIU( aBoard->m_NetClasses.GetDefault()->GetuViaDrill() ).c_str() ); - aFormatter->Print( aNestLevel+1, "(uvias_allow %s)\n", - FMTIU( aBoard->GetDesignSettings().m_MicroViasAllowed ).c_str() ); - aFormatter->Print( aNestLevel+1, "(uvia_min_size %s)\n", - FMTIU( aBoard->GetDesignSettings().m_MicroViasMinSize ).c_str() ); - aFormatter->Print( aNestLevel+1, "(uvia_min_drill %s)\n", - FMTIU( aBoard->GetDesignSettings().m_MicroViasMinDrill ).c_str() ); - - aFormatter->Print( aNestLevel+1, "(pcb_text_width %s)\n", - FMTIU( aBoard->GetDesignSettings().m_PcbTextWidth ).c_str() ); - aFormatter->Print( aNestLevel+1, "(pcb_text_size %s %s)\n", - FMTIU( aBoard->GetDesignSettings().m_PcbTextSize.x ).c_str(), - FMTIU( aBoard->GetDesignSettings().m_PcbTextSize.y ).c_str() ); - - aFormatter->Print( aNestLevel+1, "(mod_edge_width %s)\n", - FMTIU( aBoard->GetDesignSettings().m_ModuleSegmentWidth ).c_str() ); - aFormatter->Print( aNestLevel+1, "(mod_text_size %s %s)\n", - FMTIU( aBoard->GetDesignSettings().m_ModuleTextSize.x ).c_str(), - FMTIU( aBoard->GetDesignSettings().m_ModuleTextSize.y ).c_str() ); - aFormatter->Print( aNestLevel+1, "(mod_text_width %s)\n", - FMTIU( aBoard->GetDesignSettings().m_ModuleTextWidth ).c_str() ); - - aFormatter->Print( aNestLevel+1, "(pad_size %s %s)\n", - FMTIU( aBoard->GetDesignSettings().m_Pad_Master.GetSize().x ).c_str(), - FMTIU( aBoard->GetDesignSettings().m_Pad_Master.GetSize().x ).c_str() ); - aFormatter->Print( aNestLevel+1, "(pad_drill %s)\n", - FMTIU( aBoard->GetDesignSettings().m_Pad_Master.GetDrillSize().x ).c_str() ); - - aFormatter->Print( aNestLevel+1, "(pad_to_mask_clearance %s)\n", - FMTIU( aBoard->GetDesignSettings().m_SolderMaskMargin ).c_str() ); - - if( aBoard->GetDesignSettings().m_SolderPasteMargin != 0 ) - aFormatter->Print( aNestLevel+1, "(pad_to_paste_clearance %s)\n", - FMTIU( aBoard->GetDesignSettings().m_SolderPasteMargin ).c_str() ); - - if( aBoard->GetDesignSettings().m_SolderPasteMarginRatio != 0 ) - aFormatter->Print( aNestLevel+1, "(pad_to_paste_clearance_ratio %g)\n", - aBoard->GetDesignSettings().m_SolderPasteMarginRatio ); - - aFormatter->Print( aNestLevel+1, "(aux_axis_origin %s %s)\n", - FMTIU( aBoard->GetOriginAxisPosition().x ).c_str(), - FMTIU( aBoard->GetOriginAxisPosition().y ).c_str() ); - - aFormatter->Print( aNestLevel+1, "(visible_elements %X)\n", - aBoard->GetDesignSettings().GetVisibleElements() ); - - aFormatter->Print( aNestLevel, ")\n\n" ); - - - int netcount = aBoard->GetNetCount(); - - for( int i = 0; i < netcount; ++i ) - aFormatter->Print( aNestLevel, "(net %d %s)\n", - aBoard->FindNet( i )->GetNet(), - aFormatter->Quotew( aBoard->FindNet( i )->GetNetname() ).c_str() ); - - aFormatter->Print( 0, "\n" ); - - // Save the default net class first. - aBoard->m_NetClasses.GetDefault()->Format( aFormatter, aNestLevel, aControlBits ); - - // Save the rest of the net classes alphabetically. - for( NETCLASSES::const_iterator it = aBoard->m_NetClasses.begin(); - it != aBoard->m_NetClasses.end(); - ++it ) - { - NETCLASS* netclass = it->second; - netclass->Format( aFormatter, aNestLevel, aControlBits ); - } - - // Save the graphical items on the board (not owned by a module) - for( BOARD_ITEM* item = aBoard->m_Drawings; item; item = item->Next() ) - Format( item, aFormatter, aNestLevel, aControlBits ); - - aFormatter->Print( 0, "\n" ); - - // Save the modules. - for( MODULE* module = aBoard->m_Modules; module; module = (MODULE*) module->Next() ) - { - Format( module, aFormatter, aNestLevel, aControlBits ); - aFormatter->Print( 0, "\n" ); - } - - // Do not save MARKER_PCBs, they can be regenerated easily. - - // Save the tracks and vias. - for( TRACK* track = aBoard->m_Track; track; track = track->Next() ) - Format( track, aFormatter, aNestLevel, aControlBits ); - - /// @todo Add warning here that the old segment filed zones are no longer supported and - /// will not be saved. - - aFormatter->Print( 0, "\n" ); - - // Save the polygon (which are the newer technology) zones. - for( int i=0; i < aBoard->GetAreaCount(); ++i ) - Format( aBoard->GetArea( i ), aFormatter, aNestLevel, aControlBits ); -} - - -void PCB_IO::format( DIMENSION* aDimension, OUTPUTFORMATTER* aFormatter, int aNestLevel, - int aControlBits ) const - throw( IO_ERROR ) -{ - aFormatter->Print( aNestLevel, "(dimension %s (width %s) (layer %s)", - FMT_IU( aDimension->m_Value ).c_str(), - FMT_IU( aDimension->m_Width ).c_str(), - aFormatter->Quotew( aDimension->GetLayerName() ).c_str() ); - - if( aDimension->GetTimeStamp() ) - aFormatter->Print( 0, " (tstamp %lX)", aDimension->GetTimeStamp() ); - - aFormatter->Print( 0, "\n" ); - - Format( (TEXTE_PCB*) &aDimension->m_Text, aFormatter, aNestLevel+1, aControlBits ); - - aFormatter->Print( aNestLevel+1, "(feature1 pts((xy %s %s) (xy %s %s)))\n", - FMT_IU( aDimension->m_featureLineDOx ).c_str(), - FMT_IU( aDimension->m_featureLineDOy ).c_str(), - FMT_IU( aDimension->m_featureLineDFx ).c_str(), - FMT_IU( aDimension->m_featureLineDFy ).c_str() ); - - aFormatter->Print( aNestLevel+1, "(feature2 pts((xy %s %s) (xy %s %s)))\n", - FMT_IU( aDimension->m_featureLineGOx ).c_str(), - FMT_IU( aDimension->m_featureLineGOy ).c_str(), - FMT_IU( aDimension->m_featureLineGFx ).c_str(), - FMT_IU( aDimension->m_featureLineGFy ).c_str() ); - - aFormatter->Print( aNestLevel+1, "(crossbar pts((xy %s %s) (xy %s %s)))\n", - FMT_IU( aDimension->m_crossBarOx ).c_str(), - FMT_IU( aDimension->m_crossBarOy ).c_str(), - FMT_IU( aDimension->m_crossBarFx ).c_str(), - FMT_IU( aDimension->m_crossBarFy ).c_str() ); - - aFormatter->Print( aNestLevel+1, "(arrow1a pts((xy %s %s) (xy %s %s)))\n", - FMT_IU( aDimension->m_arrowD1Ox ).c_str(), - FMT_IU( aDimension->m_arrowD1Oy ).c_str(), - FMT_IU( aDimension->m_arrowD1Fx ).c_str(), - FMT_IU( aDimension->m_arrowD1Fy ).c_str() ); - - aFormatter->Print( aNestLevel+1, "(arrow1b pts((xy %s %s) (xy %s %s)))\n", - FMT_IU( aDimension->m_arrowD2Ox ).c_str(), - FMT_IU( aDimension->m_arrowD2Oy ).c_str(), - FMT_IU( aDimension->m_arrowD2Fx ).c_str(), - FMT_IU( aDimension->m_arrowD2Fy ).c_str() ); - - aFormatter->Print( aNestLevel+1, "(arrow2a pts((xy %s %s) (xy %s %s)))\n", - FMT_IU( aDimension->m_arrowG1Ox ).c_str(), - FMT_IU( aDimension->m_arrowG1Oy ).c_str(), - FMT_IU( aDimension->m_arrowG1Fx ).c_str(), - FMT_IU( aDimension->m_arrowG1Fy ).c_str() ); - - aFormatter->Print( aNestLevel+1, "(arrow2b pts((xy %s %s) (xy %s %s)))\n", - FMT_IU( aDimension->m_arrowG2Ox ).c_str(), - FMT_IU( aDimension->m_arrowG2Oy ).c_str(), - FMT_IU( aDimension->m_arrowG2Fx ).c_str(), - FMT_IU( aDimension->m_arrowG2Fy ).c_str() ); - - aFormatter->Print( aNestLevel, ")\n" ); - } - - - void PCB_IO::format( DRAWSEGMENT* aSegment, OUTPUTFORMATTER* aFormatter, int aNestLevel, - int aControlBits ) const - throw( IO_ERROR ) - { - unsigned i; - - switch( aSegment->GetShape() ) - { - case S_SEGMENT: // Line - aFormatter->Print( aNestLevel, "(gr_line (pts (xy %s) (xy %s))", - FMT_IU( aSegment->GetStart() ).c_str(), - FMT_IU( aSegment->GetEnd() ).c_str() ); - break; - - case S_CIRCLE: // Circle - aFormatter->Print( aNestLevel, "(gr_circle (center (xy %s)) (end (xy %s))", - FMT_IU( aSegment->GetStart() ).c_str(), - FMT_IU( aSegment->GetEnd() ).c_str() ); - break; - - case S_ARC: // Arc - aFormatter->Print( aNestLevel, "(gr_arc (start (xy %s)) (end (xy %s)) (angle %s)", - FMT_IU( aSegment->GetStart() ).c_str(), - FMT_IU( aSegment->GetEnd() ).c_str(), - FMT_ANGLE( aSegment->GetAngle() ).c_str() ); - break; - - case S_POLYGON: // Polygon - aFormatter->Print( aNestLevel, "(gr_line (pts" ); - - for( i = 0; i < aSegment->GetPolyPoints().size(); ++i ) - aFormatter->Print( 0, " (xy %s)", FMT_IU( aSegment->GetPolyPoints()[i] ).c_str() ); - - aFormatter->Print( 0, ")" ); - break; - - case S_CURVE: // Bezier curve - aFormatter->Print( aNestLevel, "(gr_curve pts(xy(%s) xy(%s) xy(%s) xy(%s))", - FMT_IU( aSegment->GetStart() ).c_str(), - FMT_IU( aSegment->GetBezControl1() ).c_str(), - FMT_IU( aSegment->GetBezControl2() ).c_str(), - FMT_IU( aSegment->GetEnd() ).c_str() ); - break; - - default: - wxFAIL_MSG( wxT( "Cannot format invalid DRAWSEGMENT type." ) ); - }; - - aFormatter->Print( 0, " (layer %s)", aFormatter->Quotew( aSegment->GetLayerName() ).c_str() ); - - if( aSegment->GetWidth() != 0 ) - aFormatter->Print( 0, " (width %s)", FMT_IU( aSegment->GetWidth() ).c_str() ); - - if( aSegment->GetTimeStamp() ) - aFormatter->Print( 0, " (tstamp %lX)", aSegment->GetTimeStamp() ); - - if( aSegment->GetStatus() ) - aFormatter->Print( 0, " (status %X)", aSegment->GetStatus() ); - - aFormatter->Print( 0, ")\n" ); -} - - -void PCB_IO::format( EDGE_MODULE* aModuleDrawing, OUTPUTFORMATTER* aFormatter, int aNestLevel, - int aControlBits ) const - throw( IO_ERROR ) -{ - switch( aModuleDrawing->GetShape() ) - { - case S_SEGMENT: // Line - aFormatter->Print( aNestLevel, "(fp_line (pts (xy %s) (xy %s)", - FMT_IU( aModuleDrawing->GetStart0() ).c_str(), - FMT_IU( aModuleDrawing->GetEnd0() ).c_str() ); - break; - - case S_CIRCLE: // Circle - aFormatter->Print( aNestLevel, "(fp_circle (center (xy %s)) (end (xy %s)", - FMT_IU( aModuleDrawing->GetStart0() ).c_str(), - FMT_IU( aModuleDrawing->GetEnd0() ).c_str() ); - break; - - case S_ARC: // Arc - aFormatter->Print( aNestLevel, "(fp_arc (start (xy %s)) (end (xy %s)) (angle %s)", - FMT_IU( aModuleDrawing->GetStart0() ).c_str(), - FMT_IU( aModuleDrawing->GetEnd0() ).c_str(), - FMT_ANGLE( aModuleDrawing->GetAngle() ).c_str() ); - break; - - case S_POLYGON: // Polygon - aFormatter->Print( aNestLevel, "(fp_poly (pts" ); - - for( unsigned i = 0; i < aModuleDrawing->GetPolyPoints().size(); ++i ) - aFormatter->Print( 0, " (xy %s)", - FMT_IU( aModuleDrawing->GetPolyPoints()[i] ).c_str() ); - - break; - - case S_CURVE: // Bezier curve - aFormatter->Print( aNestLevel, "(fp_curve pts(xy(%s) xy(%s) xy(%s) xy(%s))", - FMT_IU( aModuleDrawing->GetStart0() ).c_str(), - FMT_IU( aModuleDrawing->GetBezControl1() ).c_str(), - FMT_IU( aModuleDrawing->GetBezControl2() ).c_str(), - FMT_IU( aModuleDrawing->GetEnd0() ).c_str() ); - break; - - default: - wxFAIL_MSG( wxT( "Cannot format invalid DRAWSEGMENT type." ) ); - }; - - aFormatter->Print( 0, " (layer %s)", - aFormatter->Quotew( aModuleDrawing->GetLayerName() ).c_str() ); - - if( aModuleDrawing->GetWidth() != 0 ) - aFormatter->Print( 0, " (width %s)", FMT_IU( aModuleDrawing->GetWidth() ).c_str() ); - - if( aModuleDrawing->GetTimeStamp() ) - aFormatter->Print( 0, " (tstamp %lX)", aModuleDrawing->GetTimeStamp() ); - - if( aModuleDrawing->GetStatus() ) - aFormatter->Print( 0, " (status %X)", aModuleDrawing->GetStatus() ); - - aFormatter->Print( 0, ")\n" ); -} - - -void PCB_IO::format( PCB_TARGET* aTarget, OUTPUTFORMATTER* aFormatter, int aNestLevel, - int aControlBits ) const - throw( IO_ERROR ) -{ - aFormatter->Print( aNestLevel, "(target %c (pos (xy %s)) (size %s)", - ( aTarget->GetShape() ) ? 'x' : '+', - FMT_IU( aTarget->GetPosition() ).c_str(), - FMT_IU( aTarget->GetSize() ).c_str() ); - - if( aTarget->GetWidth() != 0 ) - aFormatter->Print( aNestLevel, " (width %s)", FMT_IU( aTarget->GetWidth() ).c_str() ); - - aFormatter->Print( aNestLevel, " (layer %d)", aTarget->GetLayer() ); - - if( aTarget->GetTimeStamp() ) - aFormatter->Print( aNestLevel, " (tstamp %lX)", aTarget->GetTimeStamp() ); - - aFormatter->Print( aNestLevel, ")\n" ); -} - - -void PCB_IO::format( MODULE* aModule, OUTPUTFORMATTER* aFormatter, int aNestLevel, - int aControlBits ) const - throw( IO_ERROR ) -{ - aFormatter->Print( aNestLevel, "(module %s", aFormatter->Quotew( aModule->m_LibRef ).c_str() ); - - if( aModule->IsLocked() ) - aFormatter->Print( aNestLevel, " locked" ); - - if( aModule->IsPlaced() ) - aFormatter->Print( aNestLevel, " placed" ); - - aFormatter->Print( 0, " (tedit %lX) (tstamp %lX)\n", - aModule->GetLastEditTime(), aModule->GetTimeStamp() ); - - aFormatter->Print( aNestLevel+1, "(at %s", FMT_IU( aModule->m_Pos ).c_str() ); - - if( aModule->m_Orient != 0.0 ) - aFormatter->Print( 0, " %s", FMT_ANGLE( aModule->m_Orient ).c_str() ); - - aFormatter->Print( 0, ")\n" ); - - if( !aModule->m_Doc.IsEmpty() ) - aFormatter->Print( aNestLevel+1, "(descr %s)\n", - aFormatter->Quotew( aModule->m_Doc ).c_str() ); - - if( !aModule->m_KeyWord.IsEmpty() ) - aFormatter->Print( aNestLevel+1, "(tags %s)\n", - aFormatter->Quotew( aModule->m_KeyWord ).c_str() ); - - if( !aModule->m_Path.IsEmpty() ) - aFormatter->Print( aNestLevel+1, "(path %s)\n", - aFormatter->Quotew( aModule->m_Path ).c_str() ); - - if( aModule->m_CntRot90 != 0 ) - aFormatter->Print( aNestLevel+1, "(autoplace_cost90 %d)\n", aModule->m_CntRot90 ); - - if( aModule->m_CntRot180 != 0 ) - aFormatter->Print( aNestLevel+1, "(autoplace_cost180 %d)\n", aModule->m_CntRot180 ); - - if( aModule->GetLocalSolderMaskMargin() != 0 ) - aFormatter->Print( aNestLevel+1, "(solder_mask_margin %s)\n", - FMT_IU( aModule->GetLocalSolderMaskMargin() ).c_str() ); - - if( aModule->GetLocalSolderPasteMargin() != 0 ) - aFormatter->Print( aNestLevel+1, "(solder_paste_margin %s)\n", - FMT_IU( aModule->GetLocalSolderPasteMargin() ).c_str() ); - - if( aModule->GetLocalSolderPasteMarginRatio() != 0 ) - aFormatter->Print( aNestLevel+1, "(solder_paste_ratio %g)\n", - aModule->GetLocalSolderPasteMarginRatio() ); - - if( aModule->GetLocalClearance() != 0 ) - aFormatter->Print( aNestLevel+1, "(clearance %s)\n", - FMT_IU( aModule->GetLocalClearance() ).c_str() ); - - if( aModule->m_ZoneConnection != UNDEFINED_CONNECTION ) - aFormatter->Print( aNestLevel+1, "(zone_connect %d)\n", aModule->m_ZoneConnection ); - - if( aModule->m_ThermalWidth != 0 ) - aFormatter->Print( aNestLevel+1, "(thermal_width %s)\n", - FMT_IU( aModule->m_ThermalWidth ).c_str() ); - - if( aModule->m_ThermalGap != 0 ) - aFormatter->Print( aNestLevel+1, "(thermal_gap %s)\n", - FMT_IU( aModule->m_ThermalGap ).c_str() ); - - // Attributes - if( aModule->m_Attributs != MOD_DEFAULT ) - { - aFormatter->Print( aNestLevel+1, "(attr " ); - - if( aModule->m_Attributs & MOD_CMS ) - aFormatter->Print( 0, " smd" ); - - if( aModule->m_Attributs & MOD_VIRTUAL ) - aFormatter->Print( 0, " virtual" ); - - aFormatter->Print( 0, ")\n" ); - } - - Format( (BOARD_ITEM*) aModule->m_Reference, aFormatter, aNestLevel+1, aControlBits ); - Format( (BOARD_ITEM*) aModule->m_Value, aFormatter, aNestLevel+1, aControlBits ); - - // Save drawing elements. - for( BOARD_ITEM* gr = aModule->m_Drawings; gr; gr = gr->Next() ) - Format( gr, aFormatter, aNestLevel+1, aControlBits ); - - // Save pads. - for( D_PAD* pad = aModule->m_Pads; pad; pad = pad->Next() ) - Format( pad, aFormatter, aNestLevel+1, aControlBits ); - - // Save 3D info. - for( S3D_MASTER* t3D = aModule->m_3D_Drawings; t3D; t3D = t3D->Next() ) - { - if( !t3D->m_Shape3DName.IsEmpty() ) - { - aFormatter->Print( aNestLevel+1, "(3d_shape %s\n", - aFormatter->Quotew( t3D->m_Shape3DName ).c_str() ); - - aFormatter->Print( aNestLevel+2, "(at (xyz %.16g %.16g %.16g))\n", - t3D->m_MatPosition.x, - t3D->m_MatPosition.y, - t3D->m_MatPosition.z ); - - aFormatter->Print( aNestLevel+2, "(scale (xyz %.16g %.16g %.16g))\n", - t3D->m_MatScale.x, - t3D->m_MatScale.y, - t3D->m_MatScale.z ); - - aFormatter->Print( aNestLevel+2, "(rotate (xyz %.16g %.16g %.16g))\n", - t3D->m_MatRotation.x, - t3D->m_MatRotation.y, - t3D->m_MatRotation.z ); - - aFormatter->Print( aNestLevel+1, ")\n" ); - } - } - - aFormatter->Print( aNestLevel, ")\n" ); -} - - - - -void PCB_IO::format( D_PAD* aPad, OUTPUTFORMATTER* aFormatter, int aNestLevel, - int aControlBits ) const - throw( IO_ERROR ) -{ - std::string shape; - - switch( aPad->GetShape() ) - { - case PAD_CIRCLE: shape = "circle"; break; - case PAD_RECT: shape = "rectangle"; break; - case PAD_OVAL: shape = "oval"; break; - case PAD_TRAPEZOID: shape = "trapezoid"; break; - - default: - THROW_IO_ERROR( wxString::Format( _( "unknown pad type: %d"), aPad->GetShape() ) ); - } - - std::string type; - - switch( aPad->GetAttribute() ) - { - case PAD_STANDARD: type = "thru_hole"; break; - case PAD_SMD: type = "smd"; break; - case PAD_CONN: type = "connect"; break; - case PAD_HOLE_NOT_PLATED: type = "np_thru_hole"; break; - - default: - THROW_IO_ERROR( wxString::Format( _( "unknown pad attribute: %d" ), - aPad->GetAttribute() ) ); - } - - aFormatter->Print( aNestLevel, "(pad %s %s %s (size %s)\n", - aFormatter->Quotew( aPad->GetPadName() ).c_str(), - type.c_str(), shape.c_str(), - FMT_IU( aPad->GetSize() ).c_str() ); - aFormatter->Print( aNestLevel+1, "(at %s", FMT_IU( aPad->GetPos0() ).c_str() ); - - if( aPad->GetOrientation() != 0.0 ) - aFormatter->Print( 0, " %s", FMT_ANGLE( aPad->GetOrientation() ).c_str() ); - - aFormatter->Print( 0, ")\n" ); - - if( (aPad->GetDrillSize().GetWidth() > 0) || (aPad->GetDrillSize().GetHeight() > 0) ) - { - std::string drill = (aPad->GetDrillSize().GetHeight() > 0) ? - FMT_IU( aPad->GetDrillSize() ).c_str() : - FMT_IU( aPad->GetDrillSize().GetWidth() ).c_str(); - aFormatter->Print( aNestLevel+1, "(drill %s", drill.c_str() ); - - if( (aPad->GetOffset().x > 0) || (aPad->GetOffset().y > 0) ) - { - std::string drillOffset = ( aPad->GetOffset().x > 0 ) ? - FMT_IU( aPad->GetOffset() ).c_str() : - FMT_IU( aPad->GetOffset().x ).c_str(); - aFormatter->Print( 0, " (offset %s)", drillOffset.c_str() ); - } - - aFormatter->Print( 0, ")\n" ); - } - - aFormatter->Print( aNestLevel+1, "(layers %08X)\n", aPad->GetLayerMask() ); - - aFormatter->Print( aNestLevel+1, "(net %d %s)\n", - aPad->GetNet(), aFormatter->Quotew( aPad->GetNetname() ).c_str() ); - - if( aPad->GetDieLength() != 0 ) - aFormatter->Print( aNestLevel+1, "(die_length %s)\n", - FMT_IU( aPad->GetDieLength() ).c_str() ); - - if( aPad->GetLocalSolderMaskMargin() != 0 ) - aFormatter->Print( aNestLevel+1, "(solder_mask_margin %s)\n", - FMT_IU( aPad->GetLocalSolderMaskMargin() ).c_str() ); - - if( aPad->GetLocalSolderPasteMargin() != 0 ) - aFormatter->Print( aNestLevel+1, "(solder_paste_margin %s)\n", - FMT_IU( aPad->GetLocalSolderPasteMargin() ).c_str() ); - - if( aPad->GetLocalSolderPasteMarginRatio() != 0 ) - aFormatter->Print( aNestLevel+1, "(solder_paste_margin_ratio %g)\n", - aPad->GetLocalSolderPasteMarginRatio() ); - - if( aPad->GetLocalClearance() != 0 ) - aFormatter->Print( aNestLevel+1, "(clearance %s)\n", - FMT_IU( aPad->GetLocalClearance() ).c_str() ); - - if( aPad->GetZoneConnection() != UNDEFINED_CONNECTION ) - aFormatter->Print( aNestLevel+1, "(zone_connect %d)\n", aPad->GetZoneConnection() ); - - if( aPad->GetThermalWidth() != 0 ) - aFormatter->Print( aNestLevel+1, "(thermal_width %s)\n", - FMT_IU( aPad->GetThermalWidth() ).c_str() ); - - if( aPad->GetThermalGap() != 0 ) - aFormatter->Print( aNestLevel+1, "(thermal_gap %s)\n", - FMT_IU( aPad->GetThermalGap() ).c_str() ); - - aFormatter->Print( aNestLevel, ")\n" ); -} - - -void PCB_IO::format( TEXTE_PCB* aText, OUTPUTFORMATTER* aFormatter, int aNestLevel, - int aControlBits ) const - throw( IO_ERROR ) -{ - aFormatter->Print( aNestLevel, "(gr_text %s (at %s %s) (layer %s)", - aFormatter->Quotew( aText->GetText() ).c_str(), - FMT_IU( aText->GetPosition() ).c_str(), - FMT_ANGLE( aText->GetOrientation() ).c_str(), - aFormatter->Quotew( aText->GetLayerName() ).c_str() ); - - if( aText->GetTimeStamp() ) - aFormatter->Print( 0, " (tstamp %lX)", aText->GetTimeStamp() ); - - aFormatter->Print( 0, "\n" ); - - aText->EDA_TEXT::Format( aFormatter, aNestLevel, aControlBits ); - - aFormatter->Print( aNestLevel, ")\n" ); -} - - -void PCB_IO::format( TEXTE_MODULE* aText, OUTPUTFORMATTER* aFormatter, int aNestLevel, - int aControlBits ) const - throw( IO_ERROR ) -{ - MODULE* parent = (MODULE*) aText->GetParent(); - double orient = aText->GetOrientation(); - wxString type; - - switch( aText->GetType() ) - { - case 0: type = wxT( "reference" ); break; - case 1: type = wxT( "value" ); break; - default: type = wxT( "user" ); - } - - // Due to the Pcbnew history, m_Orient is saved in screen value - // but it is handled as relative to its parent footprint - if( parent ) - orient += parent->GetOrientation(); - - aFormatter->Print( aNestLevel, "(fp_text %s %s (at %s %s)%s\n", - aFormatter->Quotew( type ).c_str(), - aFormatter->Quotew( aText->GetText() ).c_str(), - FMT_IU( aText->GetPos0() ).c_str(), FMT_ANGLE( orient ).c_str(), - (!aText->IsVisible()) ? " hide" : "" ); - - aText->EDA_TEXT::Format( aFormatter, aNestLevel, aControlBits ); - - aFormatter->Print( aNestLevel, ")\n" ); -} - - -void PCB_IO::format( TRACK* aTrack, OUTPUTFORMATTER* aFormatter, int aNestLevel, - int aControlBits ) const - throw( IO_ERROR ) -{ - if( aTrack->Type() == PCB_VIA_T ) - { - std::string type; - int layer1, layer2; - - SEGVIA* via = (SEGVIA*) aTrack; - BOARD* board = (BOARD*) via->GetParent(); - - wxCHECK_RET( board != 0, wxT( "Via " ) + via->GetSelectMenuText() + - wxT( " has no parent." ) ); - - via->ReturnLayerPair( &layer1, &layer2 ); - - switch( aTrack->GetShape() ) - { - case VIA_THROUGH: type = "thru"; break; - case VIA_BLIND_BURIED: type = "blind"; break; - case VIA_MICROVIA: type = "micro"; break; - default: - THROW_IO_ERROR( wxString::Format( _( "unknown via type %d" ), aTrack->GetShape() ) ); - } - - aFormatter->Print( aNestLevel, "(via %s (at %s) (size %s)", type.c_str(), - FMT_IU( aTrack->GetStart() ).c_str(), - FMT_IU( aTrack->GetWidth() ).c_str() ); - - if( aTrack->GetDrill() != UNDEFINED_DRILL_DIAMETER ) - aFormatter->Print( 0, " (drill %s)", FMT_IU( aTrack->GetDrill() ).c_str() ); - - aFormatter->Print( 0, " (layers %s %s) (net %d)", - aFormatter->Quotew( board->GetLayerName( layer1 ) ).c_str(), - aFormatter->Quotew( board->GetLayerName( layer2 ) ).c_str(), - aTrack->GetNet() ); - } - else - { - aFormatter->Print( aNestLevel, "(segment (start %s) (end %s) (width %s)", - FMT_IU( aTrack->GetStart() ).c_str(), FMT_IU( aTrack->GetEnd() ).c_str(), - FMT_IU( aTrack->GetWidth() ).c_str() ); - - aFormatter->Print( 0, " (layer %s) (net %d)", - aFormatter->Quotew( aTrack->GetLayerName() ).c_str(), - aTrack->GetNet() ); - } - - if( aTrack->GetTimeStamp() != 0 ) - aFormatter->Print( 0, " (tstamp %lX)", aTrack->GetTimeStamp() ); - - if( aTrack->GetStatus() != 0 ) - aFormatter->Print( 0, " (status %X)", aTrack->GetStatus() ); - - aFormatter->Print( 0, ")\n" ); -} - - -void PCB_IO::format( ZONE_CONTAINER* aZone, OUTPUTFORMATTER* aFormatter, int aNestLevel, - int aControlBits ) const - throw( IO_ERROR ) -{ - aFormatter->Print( aNestLevel, "(zone (net %d %s) (layer %s) (tstamp %lX)\n", - aZone->GetNet(), aFormatter->Quotew( aZone->GetNetName() ).c_str(), - aFormatter->Quotew( aZone->GetLayerName() ).c_str(), - aZone->GetTimeStamp() ); - - - // Save the outline aux info - std::string hatch; - - switch( aZone->GetHatchStyle() ) - { - default: - case CPolyLine::NO_HATCH: hatch = "none"; break; - case CPolyLine::DIAGONAL_EDGE: hatch = "edge"; break; - case CPolyLine::DIAGONAL_FULL: hatch = "full"; break; - } - - aFormatter->Print( aNestLevel+1, "(hatch %s)\n", hatch.c_str() ); - - if( aZone->GetPriority() > 0 ) - aFormatter->Print( aNestLevel+1, "(priority %d)\n", aZone->GetPriority() ); - - // Save pad option and clearance - std::string padoption; - - switch( aZone->GetPadConnection() ) - { - default: - case PAD_IN_ZONE: padoption = "yes"; break; - case THERMAL_PAD: padoption = "use_thermal"; break; - case PAD_NOT_IN_ZONE: padoption = "no"; break; - } - - aFormatter->Print( aNestLevel+1, "(connect_pads %s (clearance %s))\n", - padoption.c_str(), FMT_IU( aZone->GetZoneClearance() ).c_str() ); - - aFormatter->Print( aNestLevel+1, "(min_thickness %s)\n", - FMT_IU( aZone->GetMinThickness() ).c_str() ); - - aFormatter->Print( aNestLevel+1, - "(fill %s (mode %s) (arc_segments %d) (thermal_gap %s) (thermal_bridge_width %s)\n", - (aZone->IsFilled()) ? "yes" : "no", - (aZone->GetFillMode()) ? "segment" : "polygon", - aZone->m_ArcToSegmentsCount, - FMT_IU( aZone->GetThermalReliefGap() ).c_str(), - FMT_IU( aZone->GetThermalReliefCopperBridge() ).c_str() ); - - std::string smoothing; - - switch( aZone->GetCornerSmoothingType() ) - { - case ZONE_SETTINGS::SMOOTHING_NONE: smoothing = "none"; break; - case ZONE_SETTINGS::SMOOTHING_CHAMFER: smoothing = "chamfer"; break; - case ZONE_SETTINGS::SMOOTHING_FILLET: smoothing = "fillet"; break; - default: - THROW_IO_ERROR( wxString::Format( _( "unknown zone corner smoothing type %d" ), - aZone->GetCornerSmoothingType() ) ); - } - - aFormatter->Print( aNestLevel+1, "(smoothing %s (radius %s))\n", - smoothing.c_str(), FMT_IU( aZone->GetCornerRadius() ).c_str() ); - - const std::vector< CPolyPt >& cv = aZone->m_Poly->corner; - - if( cv.size() ) - { - aFormatter->Print( aNestLevel+1, "(polygon\n"); - aFormatter->Print( aNestLevel+2, "(pts\n" ); - - for( std::vector< CPolyPt >::const_iterator it = cv.begin(); it != cv.end(); ++it ) - { - aFormatter->Print( aNestLevel+3, "(xy %s %s)\n", - FMT_IU( it->x ).c_str(), FMT_IU( it->y ).c_str() ); - - if( it->end_contour ) - { - aFormatter->Print( aNestLevel+2, ")\n" ); - - if( it+1 != cv.end() ) - { - aFormatter->Print( aNestLevel+1, ")\n" ); - aFormatter->Print( aNestLevel+1, "(polygon\n" ); - aFormatter->Print( aNestLevel+2, "(pts\n" ); - } - } - } - - aFormatter->Print( aNestLevel+1, ")\n" ); - } - - // Save the PolysList - const std::vector< CPolyPt >& fv = aZone->GetFilledPolysList(); - - if( fv.size() ) - { - aFormatter->Print( aNestLevel+1, "(filled_polygon\n" ); - aFormatter->Print( aNestLevel+2, "(pts\n" ); - - for( std::vector< CPolyPt >::const_iterator it = fv.begin(); it != fv.end(); ++it ) - { - aFormatter->Print( aNestLevel+3, "(xy %s %s)\n", - FMT_IU( it->x ).c_str(), FMT_IU( it->y ).c_str() ); - - if( it->end_contour ) - { - aFormatter->Print( aNestLevel+2, ")\n" ); - - if( it+1 != fv.end() ) - { - aFormatter->Print( aNestLevel+1, ")\n" ); - aFormatter->Print( aNestLevel+1, "(filled_polygon\n" ); - aFormatter->Print( aNestLevel+2, "(pts\n" ); - } - } - } - - aFormatter->Print( aNestLevel+1, ")\n" ); - } - - // Save the filling segments list - const std::vector< SEGMENT >& segs = aZone->m_FillSegmList; - - if( segs.size() ) - { - aFormatter->Print( aNestLevel+1, "(fill_segments\n" ); - - for( std::vector< SEGMENT >::const_iterator it = segs.begin(); it != segs.end(); ++it ) - { - aFormatter->Print( aNestLevel+2, "(pts (xy %s) (xy %s))\n", - FMT_IU( it->m_Start ).c_str(), - FMT_IU( it->m_End ).c_str() ); - } - - aFormatter->Print( aNestLevel+1, ")\n" ); - } - - aFormatter->Print( aNestLevel, ")\n" ); -} +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 CERN + * Copyright (C) 1992-2011 KiCad Developers, see change_log.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 + */ + +#include +#include +#include +#include // LEGACY_BOARD_FILE_VERSION +#include +#include <3d_struct.h> + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define FMTIU BOARD_ITEM::FormatInternalUnits + + +void PCB_IO::Save( const wxString& aFileName, BOARD* aBoard, PROPERTIES* aProperties ) +{ + LOCALE_IO toggle; // toggles on, then off, the C locale. + + m_board = aBoard; + + wxFileOutputStream fs( aFileName ); + + if( !fs.IsOk() ) + { + m_error.Printf( _( "cannot open file '%s'" ), aFileName.GetData() ); + THROW_IO_ERROR( m_error ); + } + + STREAM_OUTPUTFORMATTER formatter( fs ); + + m_out = &formatter; // no ownership + + m_out->Print( 0, "(kicad_pcb (version %d) (host pcbnew %s)\n", SEXPR_BOARD_FILE_VERSION, + formatter.Quotew( GetBuildVersion() ).c_str() ); + + Format( aBoard, 1 ); + + m_out->Print( 0, ")\n" ); +} + + +void PCB_IO::Format( BOARD_ITEM* aItem, int aNestLevel ) const + throw( IO_ERROR ) +{ + switch( aItem->Type() ) + { + case PCB_T: + format( (BOARD*) aItem, aNestLevel ); + break; + + case PCB_DIMENSION_T: + format( ( DIMENSION*) aItem, aNestLevel ); + break; + + case PCB_LINE_T: + format( (DRAWSEGMENT*) aItem, aNestLevel ); + break; + + case PCB_MODULE_EDGE_T: + format( (EDGE_MODULE*) aItem, aNestLevel ); + break; + + case PCB_TARGET_T: + format( (PCB_TARGET*) aItem, aNestLevel ); + break; + + case PCB_MODULE_T: + format( (MODULE*) aItem, aNestLevel ); + break; + + case PCB_PAD_T: + format( (D_PAD*) aItem, aNestLevel ); + break; + + case PCB_TEXT_T: + format( (TEXTE_PCB*) aItem, aNestLevel ); + break; + + case PCB_MODULE_TEXT_T: + format( (TEXTE_MODULE*) aItem, aNestLevel ); + break; + + case PCB_TRACE_T: + case PCB_VIA_T: + format( (TRACK*) aItem, aNestLevel ); + break; + + case PCB_ZONE_AREA_T: + format( (ZONE_CONTAINER*) aItem, aNestLevel ); + break; + + default: + wxFAIL_MSG( wxT( "Cannot format item " ) + aItem->GetClass() ); + } +} + + +void PCB_IO::formatLayer( const BOARD_ITEM* aItem ) const +{ +#if 1 + m_out->Print( 0, " (layer %s)", m_out->Quotew( aItem->GetLayerName() ).c_str() ); +#else + m_out->Print( 0, " (layer %d)", aItem->GetLayer() ); +#endif +} + + +void PCB_IO::format( BOARD* aBoard, int aNestLevel ) const + throw( IO_ERROR ) +{ + m_out->Print( 0, "\n" ); + + m_out->Print( aNestLevel, "(general\n" ); + m_out->Print( aNestLevel+1, "(links %d)\n", aBoard->GetRatsnestsCount() ); + m_out->Print( aNestLevel+1, "(no_connects %d)\n", aBoard->m_NbNoconnect ); + + // Write Bounding box info + m_out->Print( aNestLevel+1, "(area %s %s %s %s)\n", + FMTIU( aBoard->GetBoundingBox().GetX() ).c_str(), + FMTIU( aBoard->GetBoundingBox().GetY() ).c_str(), + FMTIU( aBoard->GetBoundingBox().GetRight() ).c_str(), + FMTIU( aBoard->GetBoundingBox().GetBottom() ).c_str() ); + m_out->Print( aNestLevel+1, "(thickness %s)\n", + FMTIU( aBoard->GetDesignSettings().GetBoardThickness() ).c_str() ); + + m_out->Print( aNestLevel+1, "(drawings %d)\n", aBoard->m_Drawings.GetCount() ); + m_out->Print( aNestLevel+1, "(tracks %d)\n", aBoard->GetNumSegmTrack() ); + m_out->Print( aNestLevel+1, "(zones %d)\n", aBoard->GetNumSegmZone() ); + m_out->Print( aNestLevel+1, "(modules %d)\n", aBoard->m_Modules.GetCount() ); + m_out->Print( aNestLevel+1, "(nets %d)\n", aBoard->GetNetCount() ); + m_out->Print( aNestLevel, ")\n\n" ); + + aBoard->GetPageSettings().Format( m_out, aNestLevel, m_ctl ); + aBoard->GetTitleBlock().Format( m_out, aNestLevel, m_ctl ); + + // Layers. + m_out->Print( aNestLevel, "(layers\n" ); + + unsigned mask = LAYER_FRONT; + unsigned layer = LAYER_N_FRONT; + + // Save only the used copper layers from front to back. + while( mask != 0 ) + { + if( mask & aBoard->GetEnabledLayers() ) + { +#if USE_LAYER_NAMES + m_out->Print( aNestLevel+1, "(%d %s %s", layer, + m_out->Quotew( aBoard->GetLayerName( layer ) ).c_str(), + LAYER::ShowType( aBoard->GetLayerType( layer ) ) ); +#else + m_out->Print( aNestLevel+1, "(%d %s %s", layer, + m_out->Quotew( aBoard->GetLayerName( layer ) ).c_str(), + LAYER::ShowType( aBoard->GetLayerType( layer ) ) ); +#endif + + if( !( aBoard->GetVisibleLayers() & mask ) ) + m_out->Print( 0, "hide" ); + + m_out->Print( 0, ")\n" ); + } + + mask >>= 1; + layer--; + } + + mask = ADHESIVE_LAYER_BACK; + layer = ADHESIVE_N_BACK; + + // Save used non-copper layers in the order they are defined. + while( layer < LAYER_COUNT ) + { + if( mask & aBoard->GetEnabledLayers() ) + { +#if USE_LAYER_NAMES + m_out->Print( aNestLevel+1, "(%d %s user", layer, + m_out->Quotew( aBoard->GetLayerName( layer ) ).c_str() ); +#else + m_out->Print( aNestLevel+1, "(%d %s user", layer, + m_out->Quotew( aBoard->GetLayerName( layer ) ).c_str() ); +#endif + + if( !( aBoard->GetVisibleLayers() & mask ) ) + m_out->Print( 0, "hide" ); + + m_out->Print( 0, ")\n" ); + } + + mask <<= 1; + layer++; + } + + m_out->Print( aNestLevel, ")\n\n" ); + + // Setup + m_out->Print( aNestLevel, "(setup\n" ); + + // Save current default track width, for compatibility with older Pcbnew version; + m_out->Print( aNestLevel+1, "(last_trace_width %s)\n", + FMTIU( aBoard->GetCurrentTrackWidth() ).c_str() ); + + // Save custom tracks width list (the first is not saved here: this is the netclass value + for( unsigned ii = 1; ii < aBoard->m_TrackWidthList.size(); ii++ ) + m_out->Print( aNestLevel+1, "(user_trace_width %s)\n", + FMTIU( aBoard->m_TrackWidthList[ii] ).c_str() ); + + m_out->Print( aNestLevel+1, "(trace_clearance %s)\n", + FMTIU( aBoard->m_NetClasses.GetDefault()->GetClearance() ).c_str() ); + + // ZONE_SETTINGS + m_out->Print( aNestLevel+1, "(zone_clearance %s)\n", + FMTIU( aBoard->GetZoneSettings().m_ZoneClearance ).c_str() ); + m_out->Print( aNestLevel+1, "(zone_45_only %s)\n", + aBoard->GetZoneSettings().m_Zone_45_Only ? "yes" : "no" ); + + m_out->Print( aNestLevel+1, "(trace_min %s)\n", + FMTIU( aBoard->GetDesignSettings().m_TrackMinWidth ).c_str() ); + + m_out->Print( aNestLevel+1, "(segment_width %s)\n", + FMTIU( aBoard->GetDesignSettings().m_DrawSegmentWidth ).c_str() ); + m_out->Print( aNestLevel+1, "(edge_width %s)\n", + FMTIU( aBoard->GetDesignSettings().m_EdgeSegmentWidth ).c_str() ); + + // Save current default via size, for compatibility with older Pcbnew version; + m_out->Print( aNestLevel+1, "(via_size %s)\n", + FMTIU( aBoard->m_NetClasses.GetDefault()->GetViaDiameter() ).c_str() ); + m_out->Print( aNestLevel+1, "(via_drill %s)\n", + FMTIU( aBoard->m_NetClasses.GetDefault()->GetViaDrill() ).c_str() ); + m_out->Print( aNestLevel+1, "(via_min_size %s)\n", + FMTIU( aBoard->GetDesignSettings().m_ViasMinSize ).c_str() ); + m_out->Print( aNestLevel+1, "(via_min_drill %s)\n", + FMTIU( aBoard->GetDesignSettings().m_ViasMinDrill ).c_str() ); + + // Save custom vias diameters list (the first is not saved here: this is + // the netclass value + for( unsigned ii = 1; ii < aBoard->m_ViasDimensionsList.size(); ii++ ) + m_out->Print( aNestLevel+1, "(user_via %s %s)\n", + FMTIU( aBoard->m_ViasDimensionsList[ii].m_Diameter ).c_str(), + FMTIU( aBoard->m_ViasDimensionsList[ii].m_Drill ).c_str() ); + + // for old versions compatibility: + m_out->Print( aNestLevel+1, "(uvia_size %s)\n", + FMTIU( aBoard->m_NetClasses.GetDefault()->GetuViaDiameter() ).c_str() ); + m_out->Print( aNestLevel+1, "(uvia_drill %s)\n", + FMTIU( aBoard->m_NetClasses.GetDefault()->GetuViaDrill() ).c_str() ); + m_out->Print( aNestLevel+1, "(uvias_allowed %s)\n", + ( aBoard->GetDesignSettings().m_MicroViasAllowed ) ? "yes" : "no" ); + m_out->Print( aNestLevel+1, "(uvia_min_size %s)\n", + FMTIU( aBoard->GetDesignSettings().m_MicroViasMinSize ).c_str() ); + m_out->Print( aNestLevel+1, "(uvia_min_drill %s)\n", + FMTIU( aBoard->GetDesignSettings().m_MicroViasMinDrill ).c_str() ); + + m_out->Print( aNestLevel+1, "(pcb_text_width %s)\n", + FMTIU( aBoard->GetDesignSettings().m_PcbTextWidth ).c_str() ); + m_out->Print( aNestLevel+1, "(pcb_text_size %s %s)\n", + FMTIU( aBoard->GetDesignSettings().m_PcbTextSize.x ).c_str(), + FMTIU( aBoard->GetDesignSettings().m_PcbTextSize.y ).c_str() ); + + m_out->Print( aNestLevel+1, "(mod_edge_width %s)\n", + FMTIU( aBoard->GetDesignSettings().m_ModuleSegmentWidth ).c_str() ); + m_out->Print( aNestLevel+1, "(mod_text_size %s %s)\n", + FMTIU( aBoard->GetDesignSettings().m_ModuleTextSize.x ).c_str(), + FMTIU( aBoard->GetDesignSettings().m_ModuleTextSize.y ).c_str() ); + m_out->Print( aNestLevel+1, "(mod_text_width %s)\n", + FMTIU( aBoard->GetDesignSettings().m_ModuleTextWidth ).c_str() ); + + m_out->Print( aNestLevel+1, "(pad_size %s %s)\n", + FMTIU( aBoard->GetDesignSettings().m_Pad_Master.GetSize().x ).c_str(), + FMTIU( aBoard->GetDesignSettings().m_Pad_Master.GetSize().y ).c_str() ); + m_out->Print( aNestLevel+1, "(pad_drill %s)\n", + FMTIU( aBoard->GetDesignSettings().m_Pad_Master.GetDrillSize().x ).c_str() ); + + m_out->Print( aNestLevel+1, "(pad_to_mask_clearance %s)\n", + FMTIU( aBoard->GetDesignSettings().m_SolderMaskMargin ).c_str() ); + + if( aBoard->GetDesignSettings().m_SolderPasteMargin != 0 ) + m_out->Print( aNestLevel+1, "(pad_to_paste_clearance %s)\n", + FMTIU( aBoard->GetDesignSettings().m_SolderPasteMargin ).c_str() ); + + if( aBoard->GetDesignSettings().m_SolderPasteMarginRatio != 0 ) + m_out->Print( aNestLevel+1, "(pad_to_paste_clearance_ratio %g)\n", + aBoard->GetDesignSettings().m_SolderPasteMarginRatio ); + + m_out->Print( aNestLevel+1, "(aux_axis_origin %s %s)\n", + FMTIU( aBoard->GetOriginAxisPosition().x ).c_str(), + FMTIU( aBoard->GetOriginAxisPosition().y ).c_str() ); + + m_out->Print( aNestLevel+1, "(visible_elements %X)\n", + aBoard->GetDesignSettings().GetVisibleElements() ); + +#if SAVE_PCB_PLOT_PARAMS + aBoard->GetPlotOptions().Format( m_out, aNestLevel+1 ); +#endif + + m_out->Print( aNestLevel, ")\n\n" ); + + + int netcount = aBoard->GetNetCount(); + + for( int i = 0; i < netcount; ++i ) + m_out->Print( aNestLevel, "(net %d %s)\n", + aBoard->FindNet( i )->GetNet(), + m_out->Quotew( aBoard->FindNet( i )->GetNetname() ).c_str() ); + + m_out->Print( 0, "\n" ); + + // Save the default net class first. + aBoard->m_NetClasses.GetDefault()->Format( m_out, aNestLevel, m_ctl ); + + // Save the rest of the net classes alphabetically. + for( NETCLASSES::const_iterator it = aBoard->m_NetClasses.begin(); + it != aBoard->m_NetClasses.end(); + ++it ) + { + NETCLASS* netclass = it->second; + netclass->Format( m_out, aNestLevel, m_ctl ); + } + + // Save the modules. + for( MODULE* module = aBoard->m_Modules; module; module = (MODULE*) module->Next() ) + { + Format( module, aNestLevel ); + m_out->Print( 0, "\n" ); + } + + // Save the graphical items on the board (not owned by a module) + for( BOARD_ITEM* item = aBoard->m_Drawings; item; item = item->Next() ) + Format( item, aNestLevel ); + + m_out->Print( 0, "\n" ); + m_out->Print( 0, "\n" ); + + // Do not save MARKER_PCBs, they can be regenerated easily. + + // Save the tracks and vias. + for( TRACK* track = aBoard->m_Track; track; track = track->Next() ) + Format( track, aNestLevel ); + + /// @todo Add warning here that the old segment filed zones are no longer supported and + /// will not be saved. + + m_out->Print( 0, "\n" ); + + // Save the polygon (which are the newer technology) zones. + for( int i=0; i < aBoard->GetAreaCount(); ++i ) + Format( aBoard->GetArea( i ), aNestLevel ); +} + + +void PCB_IO::format( DIMENSION* aDimension, int aNestLevel ) const + throw( IO_ERROR ) +{ + m_out->Print( aNestLevel, "(dimension %s (width %s)", + FMT_IU( aDimension->m_Value ).c_str(), + FMT_IU( aDimension->m_Width ).c_str() ); + + formatLayer( aDimension ); + + if( aDimension->GetTimeStamp() ) + m_out->Print( 0, " (tstamp %lX)", aDimension->GetTimeStamp() ); + + m_out->Print( 0, "\n" ); + + Format( (TEXTE_PCB*) &aDimension->m_Text, aNestLevel+1 ); + + m_out->Print( aNestLevel+1, "(feature1 (pts (xy %s %s) (xy %s %s)))\n", + FMT_IU( aDimension->m_featureLineDOx ).c_str(), + FMT_IU( aDimension->m_featureLineDOy ).c_str(), + FMT_IU( aDimension->m_featureLineDFx ).c_str(), + FMT_IU( aDimension->m_featureLineDFy ).c_str() ); + + m_out->Print( aNestLevel+1, "(feature2 (pts (xy %s %s) (xy %s %s)))\n", + FMT_IU( aDimension->m_featureLineGOx ).c_str(), + FMT_IU( aDimension->m_featureLineGOy ).c_str(), + FMT_IU( aDimension->m_featureLineGFx ).c_str(), + FMT_IU( aDimension->m_featureLineGFy ).c_str() ); + + m_out->Print( aNestLevel+1, "(crossbar (pts (xy %s %s) (xy %s %s)))\n", + FMT_IU( aDimension->m_crossBarOx ).c_str(), + FMT_IU( aDimension->m_crossBarOy ).c_str(), + FMT_IU( aDimension->m_crossBarFx ).c_str(), + FMT_IU( aDimension->m_crossBarFy ).c_str() ); + + m_out->Print( aNestLevel+1, "(arrow1a (pts (xy %s %s) (xy %s %s)))\n", + FMT_IU( aDimension->m_arrowD1Ox ).c_str(), + FMT_IU( aDimension->m_arrowD1Oy ).c_str(), + FMT_IU( aDimension->m_arrowD1Fx ).c_str(), + FMT_IU( aDimension->m_arrowD1Fy ).c_str() ); + + m_out->Print( aNestLevel+1, "(arrow1b (pts (xy %s %s) (xy %s %s)))\n", + FMT_IU( aDimension->m_arrowD2Ox ).c_str(), + FMT_IU( aDimension->m_arrowD2Oy ).c_str(), + FMT_IU( aDimension->m_arrowD2Fx ).c_str(), + FMT_IU( aDimension->m_arrowD2Fy ).c_str() ); + + m_out->Print( aNestLevel+1, "(arrow2a (pts (xy %s %s) (xy %s %s)))\n", + FMT_IU( aDimension->m_arrowG1Ox ).c_str(), + FMT_IU( aDimension->m_arrowG1Oy ).c_str(), + FMT_IU( aDimension->m_arrowG1Fx ).c_str(), + FMT_IU( aDimension->m_arrowG1Fy ).c_str() ); + + m_out->Print( aNestLevel+1, "(arrow2b (pts (xy %s %s) (xy %s %s)))\n", + FMT_IU( aDimension->m_arrowG2Ox ).c_str(), + FMT_IU( aDimension->m_arrowG2Oy ).c_str(), + FMT_IU( aDimension->m_arrowG2Fx ).c_str(), + FMT_IU( aDimension->m_arrowG2Fy ).c_str() ); + + m_out->Print( aNestLevel, ")\n" ); +} + + +void PCB_IO::format( DRAWSEGMENT* aSegment, int aNestLevel ) const + throw( IO_ERROR ) +{ + unsigned i; + + switch( aSegment->GetShape() ) + { + case S_SEGMENT: // Line + m_out->Print( aNestLevel, "(gr_line (start %s) (end %s)", + FMT_IU( aSegment->GetStart() ).c_str(), + FMT_IU( aSegment->GetEnd() ).c_str() ); + + if( aSegment->GetAngle() != 0.0 ) + m_out->Print( 0, " (angle %s)", FMT_ANGLE( aSegment->GetAngle() ).c_str() ); + + break; + + case S_CIRCLE: // Circle + m_out->Print( aNestLevel, "(gr_circle (center %s) (end %s)", + FMT_IU( aSegment->GetStart() ).c_str(), + FMT_IU( aSegment->GetEnd() ).c_str() ); + break; + + case S_ARC: // Arc + m_out->Print( aNestLevel, "(gr_arc (start %s) (end %s) (angle %s)", + FMT_IU( aSegment->GetStart() ).c_str(), + FMT_IU( aSegment->GetEnd() ).c_str(), + FMT_ANGLE( aSegment->GetAngle() ).c_str() ); + break; + + case S_POLYGON: // Polygon + m_out->Print( aNestLevel, "(gr_poly (pts" ); + + for( i = 0; i < aSegment->GetPolyPoints().size(); ++i ) + m_out->Print( 0, " (xy %s)", FMT_IU( aSegment->GetPolyPoints()[i] ).c_str() ); + + m_out->Print( 0, ")" ); + break; + + case S_CURVE: // Bezier curve + m_out->Print( aNestLevel, "(gr_curve (pts (xy %s) (xy %s) (xy %s) (xy %s))", + FMT_IU( aSegment->GetStart() ).c_str(), + FMT_IU( aSegment->GetBezControl1() ).c_str(), + FMT_IU( aSegment->GetBezControl2() ).c_str(), + FMT_IU( aSegment->GetEnd() ).c_str() ); + break; + + default: + wxFAIL_MSG( wxT( "Cannot format invalid DRAWSEGMENT type." ) ); + }; + + formatLayer( aSegment ); + + if( aSegment->GetWidth() != 0 ) + m_out->Print( 0, " (width %s)", FMT_IU( aSegment->GetWidth() ).c_str() ); + + if( aSegment->GetTimeStamp() ) + m_out->Print( 0, " (tstamp %lX)", aSegment->GetTimeStamp() ); + + if( aSegment->GetStatus() ) + m_out->Print( 0, " (status %X)", aSegment->GetStatus() ); + + m_out->Print( 0, ")\n" ); +} + + +void PCB_IO::format( EDGE_MODULE* aModuleDrawing, int aNestLevel ) const + throw( IO_ERROR ) +{ + switch( aModuleDrawing->GetShape() ) + { + case S_SEGMENT: // Line + m_out->Print( aNestLevel, "(fp_line (start %s) (end %s)", + FMT_IU( aModuleDrawing->GetStart0() ).c_str(), + FMT_IU( aModuleDrawing->GetEnd0() ).c_str() ); + break; + + case S_CIRCLE: // Circle + m_out->Print( aNestLevel, "(fp_circle (center %s) (end %s)", + FMT_IU( aModuleDrawing->GetStart0() ).c_str(), + FMT_IU( aModuleDrawing->GetEnd0() ).c_str() ); + break; + + case S_ARC: // Arc + m_out->Print( aNestLevel, "(fp_arc (start %s) (end %s) (angle %s)", + FMT_IU( aModuleDrawing->GetStart0() ).c_str(), + FMT_IU( aModuleDrawing->GetEnd0() ).c_str(), + FMT_ANGLE( aModuleDrawing->GetAngle() ).c_str() ); + break; + + case S_POLYGON: // Polygon + m_out->Print( aNestLevel, "(fp_poly (pts" ); + + for( unsigned i = 0; i < aModuleDrawing->GetPolyPoints().size(); ++i ) + m_out->Print( 0, " (xy %s)", + FMT_IU( aModuleDrawing->GetPolyPoints()[i] ).c_str() ); + + m_out->Print( 0, ")\n" ); + break; + + case S_CURVE: // Bezier curve + m_out->Print( aNestLevel, "(fp_curve (pts (xy %s) (xy %s) (xy %s) (xy %s))", + FMT_IU( aModuleDrawing->GetStart0() ).c_str(), + FMT_IU( aModuleDrawing->GetBezControl1() ).c_str(), + FMT_IU( aModuleDrawing->GetBezControl2() ).c_str(), + FMT_IU( aModuleDrawing->GetEnd0() ).c_str() ); + break; + + default: + wxFAIL_MSG( wxT( "Cannot format invalid DRAWSEGMENT type." ) ); + }; + + formatLayer( aModuleDrawing ); + + if( aModuleDrawing->GetWidth() != 0 ) + m_out->Print( 0, " (width %s)", FMT_IU( aModuleDrawing->GetWidth() ).c_str() ); + + if( aModuleDrawing->GetTimeStamp() ) + m_out->Print( 0, " (tstamp %lX)", aModuleDrawing->GetTimeStamp() ); + + if( aModuleDrawing->GetStatus() ) + m_out->Print( 0, " (status %X)", aModuleDrawing->GetStatus() ); + + m_out->Print( 0, ")\n" ); +} + + +void PCB_IO::format( PCB_TARGET* aTarget, int aNestLevel ) const + throw( IO_ERROR ) +{ + m_out->Print( aNestLevel, "(target %s (at %s) (size %s)", + ( aTarget->GetShape() ) ? "x" : "plus", + FMT_IU( aTarget->GetPosition() ).c_str(), + FMT_IU( aTarget->GetSize() ).c_str() ); + + if( aTarget->GetWidth() != 0 ) + m_out->Print( 0, " (width %s)", FMT_IU( aTarget->GetWidth() ).c_str() ); + + formatLayer( aTarget ); + + if( aTarget->GetTimeStamp() ) + m_out->Print( 0, " (tstamp %lX)", aTarget->GetTimeStamp() ); + + m_out->Print( 0, ")\n" ); +} + + +void PCB_IO::format( MODULE* aModule, int aNestLevel ) const + throw( IO_ERROR ) +{ + m_out->Print( aNestLevel, "(module %s", m_out->Quotew( aModule->m_LibRef ).c_str() ); + + if( aModule->IsLocked() ) + m_out->Print( aNestLevel, " locked" ); + + if( aModule->IsPlaced() ) + m_out->Print( aNestLevel, " placed" ); + + formatLayer( aModule ); + + m_out->Print( 0, " (tedit %lX) (tstamp %lX)\n", + aModule->GetLastEditTime(), aModule->GetTimeStamp() ); + + m_out->Print( aNestLevel+1, "(at %s", FMT_IU( aModule->m_Pos ).c_str() ); + + if( aModule->m_Orient != 0.0 ) + m_out->Print( 0, " %s", FMT_ANGLE( aModule->m_Orient ).c_str() ); + + m_out->Print( 0, ")\n" ); + + if( !aModule->m_Doc.IsEmpty() ) + m_out->Print( aNestLevel+1, "(descr %s)\n", + m_out->Quotew( aModule->m_Doc ).c_str() ); + + if( !aModule->m_KeyWord.IsEmpty() ) + m_out->Print( aNestLevel+1, "(tags %s)\n", + m_out->Quotew( aModule->m_KeyWord ).c_str() ); + + if( !aModule->m_Path.IsEmpty() ) + m_out->Print( aNestLevel+1, "(path %s)\n", + m_out->Quotew( aModule->m_Path ).c_str() ); + + if( aModule->m_CntRot90 != 0 ) + m_out->Print( aNestLevel+1, "(autoplace_cost90 %d)\n", aModule->m_CntRot90 ); + + if( aModule->m_CntRot180 != 0 ) + m_out->Print( aNestLevel+1, "(autoplace_cost180 %d)\n", aModule->m_CntRot180 ); + + if( aModule->GetLocalSolderMaskMargin() != 0 ) + m_out->Print( aNestLevel+1, "(solder_mask_margin %s)\n", + FMT_IU( aModule->GetLocalSolderMaskMargin() ).c_str() ); + + if( aModule->GetLocalSolderPasteMargin() != 0 ) + m_out->Print( aNestLevel+1, "(solder_paste_margin %s)\n", + FMT_IU( aModule->GetLocalSolderPasteMargin() ).c_str() ); + + if( aModule->GetLocalSolderPasteMarginRatio() != 0 ) + m_out->Print( aNestLevel+1, "(solder_paste_ratio %g)\n", + aModule->GetLocalSolderPasteMarginRatio() ); + + if( aModule->GetLocalClearance() != 0 ) + m_out->Print( aNestLevel+1, "(clearance %s)\n", + FMT_IU( aModule->GetLocalClearance() ).c_str() ); + + if( aModule->m_ZoneConnection != UNDEFINED_CONNECTION ) + m_out->Print( aNestLevel+1, "(zone_connect %d)\n", aModule->m_ZoneConnection ); + + if( aModule->m_ThermalWidth != 0 ) + m_out->Print( aNestLevel+1, "(thermal_width %s)\n", + FMT_IU( aModule->m_ThermalWidth ).c_str() ); + + if( aModule->m_ThermalGap != 0 ) + m_out->Print( aNestLevel+1, "(thermal_gap %s)\n", + FMT_IU( aModule->m_ThermalGap ).c_str() ); + + // Attributes + if( aModule->m_Attributs != MOD_DEFAULT ) + { + m_out->Print( aNestLevel+1, "(attr" ); + + if( aModule->m_Attributs & MOD_CMS ) + m_out->Print( 0, " smd" ); + + if( aModule->m_Attributs & MOD_VIRTUAL ) + m_out->Print( 0, " virtual" ); + + m_out->Print( 0, ")\n" ); + } + + Format( (BOARD_ITEM*) aModule->m_Reference, aNestLevel+1 ); + Format( (BOARD_ITEM*) aModule->m_Value, aNestLevel+1 ); + + // Save drawing elements. + for( BOARD_ITEM* gr = aModule->m_Drawings; gr; gr = gr->Next() ) + Format( gr, aNestLevel+1 ); + + // Save pads. + for( D_PAD* pad = aModule->m_Pads; pad; pad = pad->Next() ) + Format( pad, aNestLevel+1 ); + + // Save 3D info. + for( S3D_MASTER* t3D = aModule->m_3D_Drawings; t3D; t3D = t3D->Next() ) + { + if( !t3D->m_Shape3DName.IsEmpty() ) + { + m_out->Print( aNestLevel+1, "(model %s\n", + m_out->Quotew( t3D->m_Shape3DName ).c_str() ); + + m_out->Print( aNestLevel+2, "(at (xyz %.16g %.16g %.16g))\n", + t3D->m_MatPosition.x, + t3D->m_MatPosition.y, + t3D->m_MatPosition.z ); + + m_out->Print( aNestLevel+2, "(scale (xyz %.16g %.16g %.16g))\n", + t3D->m_MatScale.x, + t3D->m_MatScale.y, + t3D->m_MatScale.z ); + + m_out->Print( aNestLevel+2, "(rotate (xyz %.16g %.16g %.16g))\n", + t3D->m_MatRotation.x, + t3D->m_MatRotation.y, + t3D->m_MatRotation.z ); + + m_out->Print( aNestLevel+1, ")\n" ); + } + } + + m_out->Print( aNestLevel, ")\n" ); +} + + +void PCB_IO::format( D_PAD* aPad, int aNestLevel ) const + throw( IO_ERROR ) +{ + std::string shape; + + switch( aPad->GetShape() ) + { + case PAD_CIRCLE: shape = "circle"; break; + case PAD_RECT: shape = "rect"; break; + case PAD_OVAL: shape = "oval"; break; + case PAD_TRAPEZOID: shape = "trapezoid"; break; + + default: + THROW_IO_ERROR( wxString::Format( _( "unknown pad type: %d"), aPad->GetShape() ) ); + } + + std::string type; + + switch( aPad->GetAttribute() ) + { + case PAD_STANDARD: type = "thru_hole"; break; + case PAD_SMD: type = "smd"; break; + case PAD_CONN: type = "connect"; break; + case PAD_HOLE_NOT_PLATED: type = "np_thru_hole"; break; + + default: + THROW_IO_ERROR( wxString::Format( _( "unknown pad attribute: %d" ), + aPad->GetAttribute() ) ); + } + + m_out->Print( aNestLevel, "(pad %s %s %s", + m_out->Quotew( aPad->GetPadName() ).c_str(), + type.c_str(), shape.c_str() ); + m_out->Print( 0, " (at %s", FMT_IU( aPad->GetPos0() ).c_str() ); + + if( aPad->GetOrientation() != 0.0 ) + m_out->Print( 0, " %s", FMT_ANGLE( aPad->GetOrientation() ).c_str() ); + + m_out->Print( 0, ")" ); + m_out->Print( 0, " (size %s)", FMT_IU( aPad->GetSize() ).c_str() ); + + if( (aPad->GetDelta().GetWidth()) != 0 || (aPad->GetDelta().GetHeight() != 0 ) ) + m_out->Print( 0, " (rect_delta %s )", FMT_IU( aPad->GetDelta() ).c_str() ); + + wxSize sz = aPad->GetDrillSize(); + + if( (sz.GetWidth() > 0) || (sz.GetHeight() > 0) ) + { + m_out->Print( 0, " (drill" ); + + if( aPad->GetDrillShape() == PAD_OVAL ) + m_out->Print( 0, " oval" ); + + m_out->Print( 0, " (size %s)", (sz.GetHeight() != sz.GetWidth()) ? FMT_IU( sz ).c_str() : + FMT_IU( sz.GetWidth() ).c_str() ); + + if( (aPad->GetOffset().x != 0) || (aPad->GetOffset().y != 0) ) + m_out->Print( 0, " (offset %s)", FMT_IU( aPad->GetOffset() ).c_str() ); + + m_out->Print( 0, ")" ); + } + + m_out->Print( 0, "\n" ); + + m_out->Print( aNestLevel+1, "(layers" ); + + unsigned layerMask = aPad->GetLayerMask() & m_board->GetEnabledLayers(); + + for( int layer = 0; layerMask; ++layer, layerMask >>= 1 ) + { + if( layerMask & 1 ) + { +#if 1 + m_out->Print( 0, " %s", m_out->Quotew( m_board->GetLayerName( layer ) ).c_str() ); +#else + m_out->Print( 0, " %d", layer ); +#endif + } + } + + m_out->Print( 0, ")\n" ); + + m_out->Print( aNestLevel+1, "(net %d %s)\n", + aPad->GetNet(), m_out->Quotew( aPad->GetNetname() ).c_str() ); + + if( aPad->GetDieLength() != 0 ) + m_out->Print( aNestLevel+1, "(die_length %s)\n", + FMT_IU( aPad->GetDieLength() ).c_str() ); + + if( aPad->GetLocalSolderMaskMargin() != 0 ) + m_out->Print( aNestLevel+1, "(solder_mask_margin %s)\n", + FMT_IU( aPad->GetLocalSolderMaskMargin() ).c_str() ); + + if( aPad->GetLocalSolderPasteMargin() != 0 ) + m_out->Print( aNestLevel+1, "(solder_paste_margin %s)\n", + FMT_IU( aPad->GetLocalSolderPasteMargin() ).c_str() ); + + if( aPad->GetLocalSolderPasteMarginRatio() != 0 ) + m_out->Print( aNestLevel+1, "(solder_paste_margin_ratio %g)\n", + aPad->GetLocalSolderPasteMarginRatio() ); + + if( aPad->GetLocalClearance() != 0 ) + m_out->Print( aNestLevel+1, "(clearance %s)\n", + FMT_IU( aPad->GetLocalClearance() ).c_str() ); + + if( aPad->GetZoneConnection() != UNDEFINED_CONNECTION ) + m_out->Print( aNestLevel+1, "(zone_connect %d)\n", aPad->GetZoneConnection() ); + + if( aPad->GetThermalWidth() != 0 ) + m_out->Print( aNestLevel+1, "(thermal_width %s)\n", + FMT_IU( aPad->GetThermalWidth() ).c_str() ); + + if( aPad->GetThermalGap() != 0 ) + m_out->Print( aNestLevel+1, "(thermal_gap %s)\n", + FMT_IU( aPad->GetThermalGap() ).c_str() ); + + m_out->Print( aNestLevel, ")\n" ); +} + + +void PCB_IO::format( TEXTE_PCB* aText, int aNestLevel ) const + throw( IO_ERROR ) +{ + m_out->Print( aNestLevel, "(gr_text %s (at %s", + m_out->Quotew( aText->GetText() ).c_str(), + FMT_IU( aText->GetPosition() ).c_str() ); + + if( aText->GetOrientation() != 0.0 ) + m_out->Print( 0, " %s", FMT_ANGLE( aText->GetOrientation() ).c_str() ); + + m_out->Print( 0, ")" ); + + formatLayer( aText ); + + if( aText->GetTimeStamp() ) + m_out->Print( 0, " (tstamp %lX)", aText->GetTimeStamp() ); + + m_out->Print( 0, "\n" ); + + aText->EDA_TEXT::Format( m_out, aNestLevel, m_ctl ); + + m_out->Print( aNestLevel, ")\n" ); +} + + +void PCB_IO::format( TEXTE_MODULE* aText, int aNestLevel ) const + throw( IO_ERROR ) +{ + MODULE* parent = (MODULE*) aText->GetParent(); + double orient = aText->GetOrientation(); + wxString type; + + switch( aText->GetType() ) + { + case 0: type = wxT( "reference" ); break; + case 1: type = wxT( "value" ); break; + default: type = wxT( "user" ); + } + + // Due to the Pcbnew history, m_Orient is saved in screen value + // but it is handled as relative to its parent footprint + if( parent ) + orient += parent->GetOrientation(); + + m_out->Print( aNestLevel, "(fp_text %s %s (at %s", + m_out->Quotew( type ).c_str(), + m_out->Quotew( aText->GetText() ).c_str(), + FMT_IU( aText->GetPos0() ).c_str() ); + + if( orient != 0.0 ) + m_out->Print( 0, " %s", FMT_ANGLE( orient ).c_str() ); + + m_out->Print( 0, ")" ); + formatLayer( aText ); + + if( !aText->IsVisible() ) + m_out->Print( 0, " hide" ); + + m_out->Print( 0, "\n" ); + + aText->EDA_TEXT::Format( m_out, aNestLevel, m_ctl ); + + m_out->Print( aNestLevel, ")\n" ); +} + + +void PCB_IO::format( TRACK* aTrack, int aNestLevel ) const + throw( IO_ERROR ) +{ + if( aTrack->Type() == PCB_VIA_T ) + { + int layer1, layer2; + + SEGVIA* via = (SEGVIA*) aTrack; + BOARD* board = (BOARD*) via->GetParent(); + + wxCHECK_RET( board != 0, wxT( "Via " ) + via->GetSelectMenuText() + + wxT( " has no parent." ) ); + + m_out->Print( aNestLevel, "(via" ); + + via->ReturnLayerPair( &layer1, &layer2 ); + + switch( aTrack->GetShape() ) + { + case VIA_THROUGH: // Default shape not saved. + break; + + case VIA_BLIND_BURIED: + m_out->Print( 0, " blind" ); + break; + + case VIA_MICROVIA: + m_out->Print( 0, " micro" ); + break; + + default: + THROW_IO_ERROR( wxString::Format( _( "unknown via type %d" ), aTrack->GetShape() ) ); + } + + m_out->Print( 0, " (at %s) (size %s)", + FMT_IU( aTrack->GetStart() ).c_str(), + FMT_IU( aTrack->GetWidth() ).c_str() ); + + if( aTrack->GetDrill() != UNDEFINED_DRILL_DIAMETER ) + m_out->Print( 0, " (drill %s)", FMT_IU( aTrack->GetDrill() ).c_str() ); + +#if 1 + m_out->Print( 0, " (layers %s %s)", + m_out->Quotew( m_board->GetLayerName( layer1 ) ).c_str(), + m_out->Quotew( m_board->GetLayerName( layer2 ) ).c_str() ); +#else + m_out->Print( 0, " (layers %d %d)", layer1, layer2 ); +#endif + } + else + { + m_out->Print( aNestLevel, "(segment (start %s) (end %s) (width %s)", + FMT_IU( aTrack->GetStart() ).c_str(), FMT_IU( aTrack->GetEnd() ).c_str(), + FMT_IU( aTrack->GetWidth() ).c_str() ); + +#if 1 + m_out->Print( 0, " (layer %s)", m_out->Quotew( aTrack->GetLayerName() ).c_str() ); +#else + m_out->Print( 0, " (layer %d)", aTrack->GetLayer() ); +#endif + } + + m_out->Print( 0, " (net %d)", aTrack->GetNet() ); + + if( aTrack->GetTimeStamp() != 0 ) + m_out->Print( 0, " (tstamp %lX)", aTrack->GetTimeStamp() ); + + if( aTrack->GetStatus() != 0 ) + m_out->Print( 0, " (status %X)", aTrack->GetStatus() ); + + m_out->Print( 0, ")\n" ); +} + + +void PCB_IO::format( ZONE_CONTAINER* aZone, int aNestLevel ) const + throw( IO_ERROR ) +{ + m_out->Print( aNestLevel, "(zone (net %d) (net_name %s)", + aZone->GetNet(), m_out->Quotew( aZone->GetNetName() ).c_str() ); + + formatLayer( aZone ); + + m_out->Print( 0, " (tstamp %lX)", aZone->GetTimeStamp() ); + + // Save the outline aux info + std::string hatch; + + switch( aZone->GetHatchStyle() ) + { + default: + case CPolyLine::NO_HATCH: hatch = "none"; break; + case CPolyLine::DIAGONAL_EDGE: hatch = "edge"; break; + case CPolyLine::DIAGONAL_FULL: hatch = "full"; break; + } + + m_out->Print( 0, " (hatch %s %s)\n", hatch.c_str(), + FMT_IU( aZone->m_Poly->GetHatchPitch() ).c_str() ); + + if( aZone->GetPriority() > 0 ) + m_out->Print( aNestLevel+1, " (priority %d)\n", aZone->GetPriority() ); + + m_out->Print( aNestLevel+1, "(connect_pads" ); + + switch( aZone->GetPadConnection() ) + { + default: + case THERMAL_PAD: // Default option not saved or loaded. + break; + + case PAD_IN_ZONE: + m_out->Print( 0, " yes" ); + break; + + case PAD_NOT_IN_ZONE: + m_out->Print( 0, " no" ); + break; + } + + m_out->Print( 0, " (clearance %s))\n", + FMT_IU( aZone->GetZoneClearance() ).c_str() ); + + m_out->Print( aNestLevel+1, "(min_thickness %s)\n", + FMT_IU( aZone->GetMinThickness() ).c_str() ); + + m_out->Print( aNestLevel+1, "(fill" ); + + // Default is not filled. + if( aZone->IsFilled() ) + m_out->Print( 0, " yes" ); + + // Default is polygon filled. + if( aZone->GetFillMode() ) + m_out->Print( 0, " (mode segment)" ); + + m_out->Print( 0, " (arc_segments %d) (thermal_gap %s) (thermal_bridge_width %s)", + aZone->GetArcSegCount(), + FMT_IU( aZone->GetThermalReliefGap() ).c_str(), + FMT_IU( aZone->GetThermalReliefCopperBridge() ).c_str() ); + + if( aZone->GetCornerSmoothingType() != ZONE_SETTINGS::SMOOTHING_NONE ) + { + m_out->Print( 0, " (smoothing" ); + + switch( aZone->GetCornerSmoothingType() ) + { + case ZONE_SETTINGS::SMOOTHING_CHAMFER: + m_out->Print( 0, " chamfer" ); + break; + + case ZONE_SETTINGS::SMOOTHING_FILLET: + m_out->Print( 0, " fillet" ); + break; + + default: + THROW_IO_ERROR( wxString::Format( _( "unknown zone corner smoothing type %d" ), + aZone->GetCornerSmoothingType() ) ); + } + m_out->Print( 0, ")" ); + + if( aZone->GetCornerRadius() != 0 ) + m_out->Print( 0, " (radius %s)", + FMT_IU( aZone->GetCornerRadius() ).c_str() ); + } + + m_out->Print( 0, ")\n" ); + + const std::vector< CPolyPt >& cv = aZone->m_Poly->corner; + int newLine = 0; + + if( cv.size() ) + { + m_out->Print( aNestLevel+1, "(polygon\n"); + m_out->Print( aNestLevel+2, "(pts\n" ); + + for( std::vector< CPolyPt >::const_iterator it = cv.begin(); it != cv.end(); ++it ) + { + if( newLine == 0 ) + m_out->Print( aNestLevel+3, "(xy %s %s)", + FMT_IU( it->x ).c_str(), FMT_IU( it->y ).c_str() ); + else + m_out->Print( 0, " (xy %s %s)", + FMT_IU( it->x ).c_str(), FMT_IU( it->y ).c_str() ); + + if( newLine < 4 ) + { + newLine += 1; + } + else + { + newLine = 0; + m_out->Print( 0, "\n" ); + } + + if( it->end_contour ) + { + if( newLine != 0 ) + m_out->Print( 0, "\n" ); + + m_out->Print( aNestLevel+2, ")\n" ); + + if( it+1 != cv.end() ) + { + newLine = 0; + m_out->Print( aNestLevel+1, ")\n" ); + m_out->Print( aNestLevel+1, "(polygon\n" ); + m_out->Print( aNestLevel+2, "(pts" ); + } + } + } + + m_out->Print( aNestLevel+1, ")\n" ); + } + + // Save the PolysList + const std::vector< CPolyPt >& fv = aZone->GetFilledPolysList(); + newLine = 0; + + if( fv.size() ) + { + m_out->Print( aNestLevel+1, "(filled_polygon\n" ); + m_out->Print( aNestLevel+2, "(pts\n" ); + + for( std::vector< CPolyPt >::const_iterator it = fv.begin(); it != fv.end(); ++it ) + { + if( newLine == 0 ) + m_out->Print( aNestLevel+3, "(xy %s %s)", + FMT_IU( it->x ).c_str(), FMT_IU( it->y ).c_str() ); + else + m_out->Print( 0, " (xy %s %s)", + FMT_IU( it->x ).c_str(), FMT_IU( it->y ).c_str() ); + + if( newLine < 4 ) + { + newLine += 1; + } + else + { + newLine = 0; + m_out->Print( 0, "\n" ); + } + + if( it->end_contour ) + { + if( newLine != 0 ) + m_out->Print( 0, "\n" ); + + m_out->Print( aNestLevel+2, ")\n" ); + + if( it+1 != fv.end() ) + { + newLine = 0; + m_out->Print( aNestLevel+1, ")\n" ); + m_out->Print( aNestLevel+1, "(filled_polygon\n" ); + m_out->Print( aNestLevel+2, "(pts\n" ); + } + } + } + + m_out->Print( aNestLevel+1, ")\n" ); + } + + // Save the filling segments list + const std::vector< SEGMENT >& segs = aZone->m_FillSegmList; + + if( segs.size() ) + { + m_out->Print( aNestLevel+1, "(fill_segments\n" ); + + for( std::vector< SEGMENT >::const_iterator it = segs.begin(); it != segs.end(); ++it ) + { + m_out->Print( aNestLevel+2, "(pts (xy %s) (xy %s))\n", + FMT_IU( it->m_Start ).c_str(), + FMT_IU( it->m_End ).c_str() ); + } + + m_out->Print( aNestLevel+1, ")\n" ); + } + + m_out->Print( aNestLevel, ")\n" ); +} + + +PCB_IO::PCB_IO() +{ + m_out = &m_sf; +} + + +BOARD* PCB_IO::Load( const wxString& aFileName, BOARD* aAppendToMe, PROPERTIES* aProperties ) +{ + wxFFile file( aFileName, wxT("r") ); + + if( !file.IsOpened() ) + { + THROW_IO_ERROR( _( "Unable to read file \"" ) + aFileName + wxT( "\"" ) ); + } + + PCB_PARSER parser( new FILE_LINE_READER( file.fp(), aFileName ), aAppendToMe ); + + return (BOARD*) parser.Parse(); +} diff --git a/pcbnew/kicad_plugin.h b/pcbnew/kicad_plugin.h index 8805066bf5..98fb908a2e 100644 --- a/pcbnew/kicad_plugin.h +++ b/pcbnew/kicad_plugin.h @@ -1,137 +1,149 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) CERN. - * - * 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 - */ - -#ifndef KICAD_PLUGIN_H_ -#define KICAD_PLUGIN_H_ - -#include -#include - -class BOARD; -class BOARD_ITEM; - - -/** Current s-expression file format version. 2 was the last legacy format version. */ -#define SEXPR_BOARD_FILE_VERSION 3 - -/** Format output for the clipboard instead of a file. */ -#define CTL_CLIPBOARD (1 << 0) - - -/** - * Class PCB_IO - * is a PLUGIN derivation for saving and loading Pcbnew s-expression formatted files. - * - * @note This class is not thread safe, but it is re-entrant multiple times in sequence. - */ -class PCB_IO : public PLUGIN -{ - -public: - const wxString& PluginName() const - { - static const wxString name = wxT( "KiCad" ); - return name; - } - - const wxString& GetFileExtension() const - { - static const wxString extension = wxT( "kicad_pcb" ); - return extension; - } - - void Save( const wxString& aFileName, BOARD* aBoard, - PROPERTIES* aProperties = NULL ); // overload - - /** - * Function Format - * outputs \a aItem to \a aFormatter in s-expression format. - * - * @param aItem A pointer the an #BOARD_ITEM object to format. - * @param aFormatter The #OUTPUTFORMATTER object to write to. - * @param aNestLevel The indentation nest level. - * @param aControlBits The control bit definition for object specific formatting. - * @throw IO_ERROR on write error. - */ - void Format( BOARD_ITEM* aItem, OUTPUTFORMATTER* aFormatter, int aNestLevel, - int aControlBits ) const - throw( IO_ERROR ); - -protected: - - wxString m_error; ///< for throwing exceptions - BOARD* m_board; ///< which BOARD, no ownership here - PROPERTIES* m_props; ///< passed via Save() or Load(), no ownership, may be NULL. - - LINE_READER* m_reader; ///< no ownership here. - wxString m_filename; ///< for saves only, name is in m_reader for loads - - int m_loading_format_version; ///< which BOARD_FORMAT_VERSION am I Load()ing? - -private: - void format( BOARD* aBoard, OUTPUTFORMATTER* aFormatter, int aNestLevel, - int aControlBits ) const - throw( IO_ERROR ); - - void format( DIMENSION* aDimension, OUTPUTFORMATTER* aFormatter, int aNestLevel, - int aControlBits ) const - throw( IO_ERROR ); - - void format( EDGE_MODULE* aModuleDrawing, OUTPUTFORMATTER* aFormatter, int aNestLevel, - int aControlBits ) const - throw( IO_ERROR ); - - void format( DRAWSEGMENT* aSegment, OUTPUTFORMATTER* aFormatter, int aNestLevel, - int aControlBits ) const - throw( IO_ERROR ); - - void format( PCB_TARGET* aTarget, OUTPUTFORMATTER* aFormatter, int aNestLevel, - int aControlBits ) const - throw( IO_ERROR ); - - void format( MODULE* aModule, OUTPUTFORMATTER* aFormatter, int aNestLevel, - int aControlBits ) const - throw( IO_ERROR ); - - void format( D_PAD* aPad, OUTPUTFORMATTER* aFormatter, int aNestLevel, - int aControlBits ) const - throw( IO_ERROR ); - - void format( TEXTE_PCB* aText, OUTPUTFORMATTER* aFormatter, int aNestLevel, - int aControlBits ) const - throw( IO_ERROR ); - - void format( TEXTE_MODULE* aText, OUTPUTFORMATTER* aFormatter, int aNestLevel, - int aControlBits ) const - throw( IO_ERROR ); - - void format( TRACK* aTrack, OUTPUTFORMATTER* aFormatter, int aNestLevel, - int aControlBits ) const - throw( IO_ERROR ); - - void format( ZONE_CONTAINER* aZone, OUTPUTFORMATTER* aFormatter, int aNestLevel, - int aControlBits ) const - throw( IO_ERROR ); -}; - -#endif // KICAD_PLUGIN_H_ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 CERN. + * + * 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 + */ + +#ifndef KICAD_PLUGIN_H_ +#define KICAD_PLUGIN_H_ + +#include +#include + +class BOARD; +class BOARD_ITEM; + + +/** Current s-expression file format version. 2 was the last legacy format version. */ +#define SEXPR_BOARD_FILE_VERSION 3 + +/** Format output for the clipboard instead of a file. */ +#define CTL_CLIPBOARD (1 << 0) + + +/** + * Class PCB_IO + * is a PLUGIN derivation for saving and loading Pcbnew s-expression formatted files. + * + * @note This class is not thread safe, but it is re-entrant multiple times in sequence. + */ +class PCB_IO : public PLUGIN +{ + +public: + + //-------------------------------------------------------------- + + const wxString& PluginName() const + { + static const wxString name = wxT( "KiCad" ); + return name; + } + + const wxString& GetFileExtension() const + { + static const wxString extension = wxT( "kicad_pcb" ); + return extension; + } + + void Save( const wxString& aFileName, BOARD* aBoard, + PROPERTIES* aProperties = NULL ); // overload + + BOARD* Load( const wxString& aFileName, BOARD* aAppendToMe, PROPERTIES* aProperties = NULL ); + + //------------------------------------------------------------- + + PCB_IO(); + + /** + * Function Format + * outputs \a aItem to \a aFormatter in s-expression format. + * + * @param aItem A pointer the an #BOARD_ITEM object to format. + * @param aNestLevel The indentation nest level. + * @throw IO_ERROR on write error. + */ + void Format( BOARD_ITEM* aItem, int aNestLevel = 0 ) const + throw( IO_ERROR ); + + std::string GetStringOutput( bool doClear ) + { + std::string ret = m_sf.GetString(); + if( doClear ) + m_sf.Clear(); + + return ret; + } + + +protected: + + wxString m_error; ///< for throwing exceptions + BOARD* m_board; ///< which BOARD, no ownership here + PROPERTIES* m_props; ///< passed via Save() or Load(), no ownership, may be NULL. + + LINE_READER* m_reader; ///< no ownership here. + wxString m_filename; ///< for saves only, name is in m_reader for loads + + int m_loading_format_version; ///< which BOARD_FORMAT_VERSION am I Load()ing? + + STRING_FORMATTER m_sf; + OUTPUTFORMATTER* m_out; ///< output any Format()s to this, no ownership + int m_ctl; + + +private: + void format( BOARD* aBoard, int aNestLevel = 0 ) const + throw( IO_ERROR ); + + void format( DIMENSION* aDimension, int aNestLevel = 0 ) const + throw( IO_ERROR ); + + void format( EDGE_MODULE* aModuleDrawing, int aNestLevel = 0 ) const + throw( IO_ERROR ); + + void format( DRAWSEGMENT* aSegment, int aNestLevel = 0 ) const + throw( IO_ERROR ); + + void format( PCB_TARGET* aTarget, int aNestLevel = 0 ) const + throw( IO_ERROR ); + + void format( MODULE* aModule, int aNestLevel = 0 ) const + throw( IO_ERROR ); + + void format( D_PAD* aPad, int aNestLevel = 0 ) const + throw( IO_ERROR ); + + void format( TEXTE_PCB* aText, int aNestLevel = 0 ) const + throw( IO_ERROR ); + + void format( TEXTE_MODULE* aText, int aNestLevel = 0 ) const + throw( IO_ERROR ); + + void format( TRACK* aTrack, int aNestLevel = 0 ) const + throw( IO_ERROR ); + + void format( ZONE_CONTAINER* aZone, int aNestLevel = 0 ) const + throw( IO_ERROR ); + + void formatLayer( const BOARD_ITEM* aItem ) const; +}; + +#endif // KICAD_PLUGIN_H_ diff --git a/pcbnew/legacy_plugin.cpp b/pcbnew/legacy_plugin.cpp index a1636740ee..3f25ce71e3 100644 --- a/pcbnew/legacy_plugin.cpp +++ b/pcbnew/legacy_plugin.cpp @@ -244,8 +244,7 @@ void LEGACY_PLUGIN::loadAllSections( bool doAppend ) else if( TESTLINE( "$TRACK" ) ) { - TRACK* insertBeforeMe = doAppend ? NULL : m_board->m_Track.GetFirst(); - loadTrackList( insertBeforeMe, PCB_TRACE_T ); + loadTrackList( PCB_TRACE_T ); } else if( TESTLINE( "$NCLASS" ) ) @@ -270,8 +269,7 @@ void LEGACY_PLUGIN::loadAllSections( bool doAppend ) else if( TESTLINE( "$ZONE" ) ) { - SEGZONE* insertBeforeMe = doAppend ? NULL : m_board->m_Zone.GetFirst(); - loadTrackList( insertBeforeMe, PCB_ZONE_T ); + loadTrackList( PCB_ZONE_T ); } else if( TESTLINE( "$GENERAL" ) ) @@ -356,12 +354,12 @@ void LEGACY_PLUGIN::loadGENERAL() if( !strcmp( data, "mm" ) ) { #if defined( USE_PCBNEW_NANOMETRES ) - diskToBiu = 1000000.0; + diskToBiu = IU_PER_MM; #elif defined(DEBUG) // mm to deci-mils: // advanced testing of round tripping only, not supported in non DEBUG build - diskToBiu = 10000/25.4; + diskToBiu = IU_PER_MM; #else THROW_IO_ERROR( _( "May not load millimeter *.brd file into 'Pcbnew compiled for deci-mils'" ) ); @@ -403,7 +401,7 @@ void LEGACY_PLUGIN::loadGENERAL() else if( TESTLINE( "BoardThickness" ) ) { BIU thickn = biuParse( line + SZ( "BoardThickness" ) ); - m_board->GetDesignSettings().m_BoardThickness = thickn; + m_board->GetDesignSettings().SetBoardThickness( thickn ); } /* @@ -1888,7 +1886,7 @@ void LEGACY_PLUGIN::loadPCB_TEXT() } -void LEGACY_PLUGIN::loadTrackList( TRACK* aInsertBeforeMe, int aStructType ) +void LEGACY_PLUGIN::loadTrackList( int aStructType ) { while( READLINE( m_reader ) ) { @@ -1961,17 +1959,17 @@ void LEGACY_PLUGIN::loadTrackList( TRACK* aInsertBeforeMe, int aStructType ) default: case PCB_TRACE_T: newTrack = new TRACK( m_board ); - m_board->m_Track.Insert( newTrack, aInsertBeforeMe ); + m_board->m_Track.Append( newTrack ); break; case PCB_VIA_T: newTrack = new SEGVIA( m_board ); - m_board->m_Track.Insert( newTrack, aInsertBeforeMe ); + m_board->m_Track.Append( newTrack ); break; case PCB_ZONE_T: // this is now deprecated, but exist in old boards newTrack = new SEGZONE( m_board ); - m_board->m_Zone.Insert( (SEGZONE*) newTrack, (SEGZONE*) aInsertBeforeMe ); + m_board->m_Zone.Append( (SEGZONE*) newTrack ); break; } @@ -2720,8 +2718,8 @@ void LEGACY_PLUGIN::init( PROPERTIES* aProperties ) // then, during the file loading process, to start a conversion from // mm to nanometers. - diskToBiu = IU_PER_DECIMILS; // BIUs are nanometers if USE_PCBNEW_NANOMETRES - // or BIUs are deci-mils + diskToBiu = IU_PER_DECIMILS; // BIUs are nanometers if USE_PCBNEW_NANOMETRES + // or BIUs are deci-mils } @@ -2825,7 +2823,7 @@ void LEGACY_PLUGIN::saveGENERAL( const BOARD* aBoard ) const fprintf( m_fp, "Ndraw %d\n", aBoard->m_Drawings.GetCount() ); fprintf( m_fp, "Ntrack %d\n", aBoard->GetNumSegmTrack() ); fprintf( m_fp, "Nzone %d\n", aBoard->GetNumSegmZone() ); - fprintf( m_fp, "BoardThickness %s\n", fmtBIU( aBoard->GetDesignSettings().m_BoardThickness ).c_str() ); + fprintf( m_fp, "BoardThickness %s\n", fmtBIU( aBoard->GetDesignSettings().GetBoardThickness() ).c_str() ); fprintf( m_fp, "Nmodule %d\n", aBoard->m_Modules.GetCount() ); fprintf( m_fp, "Nnets %d\n", aBoard->GetNetCount() ); fprintf( m_fp, "$EndGENERAL\n\n" ); @@ -3393,7 +3391,7 @@ void LEGACY_PLUGIN::SaveModule3D( const MODULE* me ) const // using "diff", then switch to more concise form for release builds. "Sc %lf %lf %lf\n", #else - "Sc %.16g %.16g %.16g\n", + "Sc %.10g %.10g %.10g\n", #endif t3D->m_MatScale.x, t3D->m_MatScale.y, @@ -3403,7 +3401,7 @@ void LEGACY_PLUGIN::SaveModule3D( const MODULE* me ) const #if defined(DEBUG) "Of %lf %lf %lf\n", #else - "Of %.16g %.16g %.16g\n", + "Of %.10g %.10g %.10g\n", #endif t3D->m_MatPosition.x, t3D->m_MatPosition.y, @@ -3413,7 +3411,7 @@ void LEGACY_PLUGIN::SaveModule3D( const MODULE* me ) const #if defined(DEBUG) "Ro %lf %lf %lf\n", #else - "Ro %.16g %.16g %.16g\n", + "Ro %.10g %.10g %.10g\n", #endif t3D->m_MatRotation.x, t3D->m_MatRotation.y, @@ -3619,7 +3617,7 @@ void LEGACY_PLUGIN::saveDIMENTION( const DIMENSION* me ) const fprintf( m_fp, "Ge %d %d %lX\n", me->GetShape(), me->GetLayer(), me->GetTimeStamp() ); - fprintf( m_fp, "Va %d\n", me->m_Value ); + fprintf( m_fp, "Va %s\n", fmtBIU( me->m_Value ).c_str() ); if( !me->m_Text.GetText().IsEmpty() ) fprintf( m_fp, "Te %s\n", EscapedUTF8( me->m_Text.GetText() ).c_str() ); @@ -3858,12 +3856,12 @@ void FPL_CACHE::ReadAndVerifyHeader( LINE_READER* aReader ) if( !strcmp( units, "mm" ) ) { #if defined( USE_PCBNEW_NANOMETRES ) - m_owner->diskToBiu = 1000000.0; + m_owner->diskToBiu = IU_PER_MM; #elif defined(DEBUG) // mm to deci-mils: // advanced testing of round tripping only, not supported in non DEBUG build - m_owner->diskToBiu = 10000/25.4; + m_owner->diskToBiu = IU_PER_MM; #else THROW_IO_ERROR( _( "May not load millimeter legacy library file into 'Pcbnew compiled for deci-mils'" ) ); diff --git a/pcbnew/legacy_plugin.h b/pcbnew/legacy_plugin.h index a1c3fb8d9d..96f8380b33 100644 --- a/pcbnew/legacy_plugin.h +++ b/pcbnew/legacy_plugin.h @@ -189,13 +189,10 @@ protected: * Function loadTrackList * reads a list of segments (Tracks and Vias, or Segzones) * - * @param aInsertBeforeMe may be either NULL indicating append, or it may - * be an insertion point before which all the segments are inserted. - * * @param aStructType is either PCB_TRACE_T to indicate tracks and vias, or * PCB_ZONE_T to indicate oldschool zone segments (before polygons came to be). */ - void loadTrackList( TRACK* aInsertBeforeMe, int aStructType ); + void loadTrackList( int aStructType ); void loadZONE_CONTAINER(); // "$CZONE_OUTLINE" void loadDIMENSION(); // "$COTATION" diff --git a/pcbnew/loadcmp.cpp b/pcbnew/loadcmp.cpp index 615ac1a322..5c261d2b11 100644 --- a/pcbnew/loadcmp.cpp +++ b/pcbnew/loadcmp.cpp @@ -1,8 +1,9 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2009 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 1992-2012 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 diff --git a/pcbnew/menubar_modedit.cpp b/pcbnew/menubar_modedit.cpp index ff4c0afb37..731a584390 100644 --- a/pcbnew/menubar_modedit.cpp +++ b/pcbnew/menubar_modedit.cpp @@ -1,10 +1,11 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2007 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2009-2011 Wayne Stambaugh - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. - * + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2012 Wayne Stambaugh + * Copyright (C) 1992-2012 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 diff --git a/pcbnew/menubar_pcbframe.cpp b/pcbnew/menubar_pcbframe.cpp index 8e8877dab9..64389263e0 100644 --- a/pcbnew/menubar_pcbframe.cpp +++ b/pcbnew/menubar_pcbframe.cpp @@ -1,9 +1,10 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2007 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2010-2011 Wayne Stambaugh - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2012 Wayne Stambaugh + * Copyright (C) 1992-2012 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 diff --git a/pcbnew/modeditoptions.cpp b/pcbnew/modeditoptions.cpp index a8d1de43f2..97a24151bc 100644 --- a/pcbnew/modeditoptions.cpp +++ b/pcbnew/modeditoptions.cpp @@ -1,10 +1,11 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2011 Wayne Stambaugh - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. - * + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2012 Wayne Stambaugh + * Copyright (C) 1992-2012 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 diff --git a/pcbnew/moduleframe.cpp b/pcbnew/moduleframe.cpp index 7103043235..39bc4e11ab 100644 --- a/pcbnew/moduleframe.cpp +++ b/pcbnew/moduleframe.cpp @@ -1,9 +1,10 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2008-2011 Wayne Stambaugh - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2012 Wayne Stambaugh + * Copyright (C) 1992-2012 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 diff --git a/pcbnew/modules.cpp b/pcbnew/modules.cpp index 379189e01a..2770048f4e 100644 --- a/pcbnew/modules.cpp +++ b/pcbnew/modules.cpp @@ -1,9 +1,10 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2008-2011 Wayne Stambaugh - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2012 Wayne Stambaugh + * Copyright (C) 1992-2012 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 @@ -515,20 +516,16 @@ void DrawModuleOutlines( EDA_DRAW_PANEL* panel, wxDC* DC, MODULE* module ) module->DrawEdgesOnly( panel, DC, g_Offset_Module, GR_XOR ); - if( g_Show_Pads_Module_in_Move ) - { - pad_fill_tmp = DisplayOpt.DisplayPadFill; - DisplayOpt.DisplayPadFill = true; + // Show pads in sketch mode to speedu up drawings + pad_fill_tmp = DisplayOpt.DisplayPadFill; + DisplayOpt.DisplayPadFill = true; - pt_pad = module->m_Pads; + pt_pad = module->m_Pads; - for( ; pt_pad != NULL; pt_pad = pt_pad->Next() ) - { - pt_pad->Draw( panel, DC, GR_XOR, g_Offset_Module ); - } + for( ; pt_pad != NULL; pt_pad = pt_pad->Next() ) + pt_pad->Draw( panel, DC, GR_XOR, g_Offset_Module ); - DisplayOpt.DisplayPadFill = pad_fill_tmp; - } + DisplayOpt.DisplayPadFill = pad_fill_tmp; if( g_Show_Module_Ratsnest && panel ) { diff --git a/pcbnew/move_or_drag_track.cpp b/pcbnew/move_or_drag_track.cpp index f99f26c12b..b72387ccfe 100644 --- a/pcbnew/move_or_drag_track.cpp +++ b/pcbnew/move_or_drag_track.cpp @@ -1,9 +1,10 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2006 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2011 Wayne Stambaugh - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2012 Wayne Stambaugh + * Copyright (C) 1992-2012 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 diff --git a/pcbnew/muonde.cpp b/pcbnew/muonde.cpp index 6f85dbe20b..8f07a6e430 100644 --- a/pcbnew/muonde.cpp +++ b/pcbnew/muonde.cpp @@ -1,9 +1,10 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2009 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2011 Wayne Stambaugh - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2012 Wayne Stambaugh + * Copyright (C) 1992-2012 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 diff --git a/pcbnew/onleftclick.cpp b/pcbnew/onleftclick.cpp index 8749239c11..15b8e1f5ea 100644 --- a/pcbnew/onleftclick.cpp +++ b/pcbnew/onleftclick.cpp @@ -298,7 +298,8 @@ void PCB_EDIT_FRAME::OnLeftClick( wxDC* aDC, const wxPoint& aPosition ) */ if( (DrawStruct == NULL) || (DrawStruct->GetFlags() == 0) ) { - // there is no current item, try to find something under mouse +#if 0 // Set to 1 to automatically edit a zone found under the mouse + // there is no current item, try to find something under the mouse cursor DrawStruct = PcbGeneralLocateAndDisplay(); bool hit_on_corner = false; @@ -319,7 +320,9 @@ void PCB_EDIT_FRAME::OnLeftClick( wxDC* aDC, const wxPoint& aPosition ) m_canvas->SetAutoPanRequest( true ); Start_Move_Zone_Corner( aDC, zone_cont, zone_cont->m_CornerSelection, false ); } - else if( Begin_Zone( aDC ) ) + else +#endif + if( Begin_Zone( aDC ) ) { m_canvas->SetAutoPanRequest( true ); DrawStruct = GetBoard()->m_CurrentZoneContour; diff --git a/pcbnew/onrightclick.cpp b/pcbnew/onrightclick.cpp index d33c08b470..51d8dc87ed 100644 --- a/pcbnew/onrightclick.cpp +++ b/pcbnew/onrightclick.cpp @@ -626,6 +626,10 @@ void PCB_EDIT_FRAME::createPopUpMenuForZones( ZONE_CONTAINER* edge_zone, wxMenu* AddMenuItem( zones_menu, ID_POPUP_PCB_ZONE_ADD_CUTOUT_ZONE, _( "Add Cutout Area" ), KiBitmap( add_zone_cutout_xpm ) ); + + AddMenuItem( zones_menu, ID_POPUP_PCB_ZONE_DUPLICATE, + _( "Duplicate Zone" ), KiBitmap( zone_duplicate_xpm ) ); + zones_menu->AppendSeparator(); AddMenuItem( zones_menu, ID_POPUP_PCB_FILL_ZONE, _( "Fill Zone" ), diff --git a/pcbnew/pcb_parser.cpp b/pcbnew/pcb_parser.cpp new file mode 100644 index 0000000000..16492fd168 --- /dev/null +++ b/pcbnew/pcb_parser.cpp @@ -0,0 +1,2603 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 CERN + * + * 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 pcb_parser.cpp + * @brief Pcbnew s-expression file format parser implementation. + */ + +#include +#include +#include +#include +#include +#include <3d_struct.h> +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +double PCB_PARSER::parseDouble() throw( IO_ERROR ) +{ + char* tmp; + + errno = 0; + + double fval = strtod( CurText(), &tmp ); + + if( errno ) + { + wxString error; + error.Printf( _( "invalid floating point number in\nfile: '%s'\nline: %d\noffset: %d" ), + GetChars( CurSource() ), CurLineNumber(), CurOffset() ); + + THROW_IO_ERROR( error ); + } + + if( CurText() == tmp ) + { + wxString error; + error.Printf( _( "missing floating point number in\nfile: '%s'\nline: %d\noffset: %d" ), + GetChars( CurSource() ), CurLineNumber(), CurOffset() ); + + THROW_IO_ERROR( error ); + } + + return fval; +} + + +bool PCB_PARSER::parseBool() throw( PARSE_ERROR ) +{ + T token = NextTok(); + + if( token == T_yes ) + return true; + else if( token == T_no ) + return false; + else + Expecting( "yes or no" ); + + return false; +} + + +wxPoint PCB_PARSER::parseXY() throw( PARSE_ERROR ) +{ + if( CurTok() != T_LEFT ) + NeedLEFT(); + + wxPoint pt; + T token = NextTok(); + + if( token != T_xy ) + Expecting( T_xy ); + + pt.x = parseBoardUnits( "X coordinate" ); + pt.y = parseBoardUnits( "Y coordinate" ); + + NeedRIGHT(); + + return pt; +} + + +void PCB_PARSER::parseXY( int* aX, int* aY ) throw( PARSE_ERROR ) +{ + wxPoint pt = parseXY(); + + if( aX ) + *aX = pt.x; + + if( aY ) + *aY = pt.y; +} + + +void PCB_PARSER::parseEDA_TEXT( EDA_TEXT* aText ) throw( PARSE_ERROR ) +{ + wxCHECK_RET( CurTok() == T_effects, + wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as EDA_TEXT." ) ); + + T token; + + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token != T_LEFT ) + Expecting( T_LEFT ); + + token = NextTok(); + + switch( token ) + { + case T_font: + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token == T_LEFT ) + continue; + + switch( token ) + { + case T_size: + { + wxSize sz; + sz.SetHeight( parseBoardUnits( "text height" ) ); + sz.SetWidth( parseBoardUnits( "text width" ) ); + aText->SetSize( sz ); + NeedRIGHT(); + break; + } + + case T_thickness: + aText->SetThickness( parseBoardUnits( "text thickness" ) ); + NeedRIGHT(); + break; + + case T_bold: + aText->SetBold( true ); + break; + + case T_italic: + aText->SetItalic( true ); + break; + + default: + Expecting( "size, bold, or italic" ); + } + } + + break; + + case T_justify: + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token == T_LEFT ) + continue; + + switch( token ) + { + case T_left: + aText->SetHorizJustify( GR_TEXT_HJUSTIFY_LEFT ); + break; + + case T_right: + aText->SetHorizJustify( GR_TEXT_HJUSTIFY_RIGHT ); + break; + + case T_top: + aText->SetVertJustify( GR_TEXT_VJUSTIFY_TOP ); + break; + + case T_bottom: + aText->SetVertJustify( GR_TEXT_VJUSTIFY_BOTTOM ); + break; + + case T_mirror: + aText->SetMirrored( true ); + break; + + default: + Expecting( "left, right, top, bottom, or mirror" ); + } + + } + break; + + case T_hide: + aText->SetVisible( false ); + break; + + default: + Expecting( "font, justify, or hide" ); + } + } +} + + +S3D_MASTER* PCB_PARSER::parse3DModel() throw( PARSE_ERROR ) +{ + wxCHECK_MSG( CurTok() == T_model, NULL, + wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as S3D_MASTER." ) ); + + T token; + + auto_ptr< S3D_MASTER > n3D( new S3D_MASTER( NULL ) ); + + NeedSYMBOL(); + n3D->m_Shape3DName = FromUTF8(); + + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token != T_LEFT ) + Expecting( T_LEFT ); + + token = NextTok(); + + switch( token ) + { + case T_at: + NeedLEFT(); + token = NextTok(); + + if( token != T_xyz ) + Expecting( T_xyz ); + + n3D->m_MatPosition.x = parseDouble( "x value" ); + n3D->m_MatPosition.y = parseDouble( "y value" ); + n3D->m_MatPosition.z = parseDouble( "z value" ); + NeedRIGHT(); + break; + + case T_scale: + NeedLEFT(); + token = NextTok(); + + if( token != T_xyz ) + Expecting( T_xyz ); + + n3D->m_MatScale.x = parseDouble( "x value" ); + n3D->m_MatScale.y = parseDouble( "y value" ); + n3D->m_MatScale.z = parseDouble( "z value" ); + NeedRIGHT(); + break; + + case T_rotate: + NeedLEFT(); + token = NextTok(); + + if( token != T_xyz ) + Expecting( T_xyz ); + + n3D->m_MatRotation.x = parseDouble( "x value" ); + n3D->m_MatRotation.y = parseDouble( "y value" ); + n3D->m_MatRotation.z = parseDouble( "z value" ); + NeedRIGHT(); + break; + + default: + Expecting( "at, scale, or rotate" ); + } + + NeedRIGHT(); + } + + return n3D.release(); +} + + +BOARD_ITEM* PCB_PARSER::Parse() throw( IO_ERROR, PARSE_ERROR ) +{ + T token; + BOARD_ITEM* item; + LOCALE_IO toggle; // toggles on, then off, the C locale. + + token = NextTok(); + + if( token != T_LEFT ) + Expecting( T_LEFT ); + + switch( NextTok() ) + { + case T_kicad_pcb: + if( m_board == NULL ) + m_board = new BOARD(); + + item = (BOARD_ITEM*) parseBOARD(); + break; + + default: + wxString err; + err.Printf( _( "unknown token \"%s\" " ), GetChars( FromUTF8() ) ); + THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() ); + } + + return item; +} + + +BOARD* PCB_PARSER::parseBOARD() throw( IO_ERROR, PARSE_ERROR ) +{ + T token; + + parseHeader(); + + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token != T_LEFT ) + Expecting( T_LEFT ); + + token = NextTok(); + + switch( token ) + { + case T_general: + parseGeneralSection(); + break; + + case T_page: + parsePAGE_INFO(); + break; + + case T_title_block: + parseTITLE_BLOCK(); + break; + + case T_layers: + parseLayers(); + break; + + case T_setup: + parseSetup(); + break; + + case T_net: + parseNETINFO_ITEM(); + break; + + case T_net_class: + parseNETCLASS(); + break; + + case T_gr_arc: + case T_gr_circle: + case T_gr_curve: + case T_gr_line: + case T_gr_poly: + m_board->Add( parseDRAWSEGMENT(), ADD_APPEND ); + break; + + case T_gr_text: + m_board->Add( parseTEXTE_PCB(), ADD_APPEND ); + break; + + case T_dimension: + m_board->Add( parseDIMENSION(), ADD_APPEND ); + break; + + case T_module: + m_board->Add( parseMODULE(), ADD_APPEND ); + break; + + case T_segment: + m_board->m_Track.Append( parseTRACK() ); + break; + + case T_via: + m_board->m_Track.Append( parseSEGVIA() ); + break; + + case T_zone: + m_board->Add( parseZONE_CONTAINER(), ADD_APPEND ); + break; + + case T_target: + m_board->Add( parsePCB_TARGET(), ADD_APPEND ); + break; + + default: + wxString err; + err.Printf( _( "unknown token \"%s\"" ), GetChars( FromUTF8() ) ); + THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() ); + } + } + + return m_board; +} + + +void PCB_PARSER::parseHeader() throw( IO_ERROR, PARSE_ERROR ) +{ + wxCHECK_RET( CurTok() == T_kicad_pcb, + wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a header." ) ); + + T token; + + NeedLEFT(); + token = NextTok(); + + if( token != T_version ) + Expecting( GetTokenText( T_version ) ); + + // Get the file version. + m_board->SetFileFormatVersionAtLoad( NeedNUMBER( GetTokenText( T_version ) ) ); + + // Skip the host name and host build version information. + NeedRIGHT(); + NeedLEFT(); + NeedSYMBOL(); + NeedSYMBOL(); + NeedSYMBOL(); + NeedRIGHT(); +} + + +void PCB_PARSER::parseGeneralSection() throw( IO_ERROR, PARSE_ERROR ) +{ + wxCHECK_RET( CurTok() == T_general, + wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + + wxT( " as a general section." ) ); + + T token; + + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token != T_LEFT ) + Expecting( T_LEFT ); + + token = NextTok(); + + switch( token ) + { + case T_thickness: + m_board->GetDesignSettings().SetBoardThickness( parseBoardUnits( T_thickness ) ); + NeedRIGHT(); + break; + + case T_no_connects: + m_board->m_NbNoconnect = parseInt( "no connect count" ); + NeedRIGHT(); + break; + + default: // Skip everything but the board thickness. + wxLogDebug( wxT( "Skipping general section token %s " ), GetTokenString( token ) ); + + while( ( token = NextTok() ) != T_RIGHT ) + { + if( !IsSymbol( token ) && token != T_NUMBER ) + Expecting( "symbol or number" ); + } + } + } +} + + +void PCB_PARSER::parsePAGE_INFO() throw( IO_ERROR, PARSE_ERROR ) +{ + wxCHECK_RET( CurTok() == T_page, + wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a PAGE_INFO." ) ); + + T token; + bool isPortrait = false; + + NeedSYMBOL(); + + wxString pageType = FromUTF8(); + + if( pageType == PAGE_INFO::Custom ) + { + PAGE_INFO::SetCustomWidthMils( Iu2Mils( NeedNUMBER( "width" ) ) ); + PAGE_INFO::SetCustomHeightMils( Iu2Mils( NeedNUMBER( "height" ) ) ); + } + + token = NextTok(); + + if( token == T_portrait ) + { + isPortrait = true; + NeedRIGHT(); + } + else if( token != T_RIGHT ) + { + Expecting( "portrait|)" ); + } + + PAGE_INFO pageInfo; + + if( !pageInfo.SetType( pageType, isPortrait ) ) + { + wxString err; + err.Printf( _( "page type \"%s\" is not valid " ), GetChars( FromUTF8() ) ); + THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() ); + } + + m_board->SetPageSettings( pageInfo ); +} + + +void PCB_PARSER::parseTITLE_BLOCK() throw( IO_ERROR, PARSE_ERROR ) +{ + wxCHECK_RET( CurTok() == T_title_block, + wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + + wxT( " as TITLE_BLOCK." ) ); + + T token; + TITLE_BLOCK titleBlock; + + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token != T_LEFT ) + Expecting( T_LEFT ); + + token = NextTok(); + + switch( token ) + { + case T_title: + NeedSYMBOL(); + titleBlock.SetTitle( FromUTF8() ); + break; + + case T_date: + NeedSYMBOL(); + titleBlock.SetDate( FromUTF8() ); + break; + + case T_rev: + NextTok(); + titleBlock.SetRevision( FromUTF8() ); + break; + + case T_company: + NextTok(); + titleBlock.SetCompany( FromUTF8() ); + break; + + case T_comment: + { + int commentNumber = NeedNUMBER( "comment" ); + + switch( commentNumber ) + { + case 1: + NextTok(); + titleBlock.SetComment1( FromUTF8() ); + break; + + case 2: + NextTok(); + titleBlock.SetComment2( FromUTF8() ); + break; + + case 3: + NextTok(); + titleBlock.SetComment3( FromUTF8() ); + break; + + case 4: + NextTok(); + titleBlock.SetComment4( FromUTF8() ); + break; + + default: + wxString err; + err.Printf( _( "%d is not a valid title block comment number" ), commentNumber ); + THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() ); + } + + break; + } + + default: + Expecting( "title, date, rev, company, or comment" ); + } + + NeedRIGHT(); + } + + m_board->SetTitleBlock( titleBlock ); +} + + +void PCB_PARSER::parseLayers() throw( IO_ERROR, PARSE_ERROR ) +{ + wxCHECK_RET( CurTok() == T_layers, + wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as layers." ) ); + + T token; + wxString name; + wxString type; + int layerIndex; + bool isVisible = true; + int visibleLayers = 0; + int enabledLayers = 0; + int copperLayerCount = 0; + + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token != T_LEFT ) + Expecting( T_LEFT ); + + layerIndex = parseInt( "layer index" ); + + NeedSYMBOL(); + name = FromUTF8(); + NeedSYMBOL(); + type = FromUTF8(); + + token = NextTok(); + + if( token == T_hide ) + { + isVisible = false; + NeedRIGHT(); + } + else if( token == T_RIGHT ) + { + isVisible = true; + } + else + { + Expecting( "hide or )" ); + } + + enabledLayers |= 1 << layerIndex; + + if( isVisible ) + visibleLayers |= 1 << layerIndex; + + enum LAYER_T layerType = LAYER::ParseType( TO_UTF8( type ) ); + LAYER layer( name, layerType, isVisible ); + layer.SetFixedListIndex( layerIndex ); + m_board->SetLayer( layerIndex, layer ); + m_layerMap[ name ] = layerIndex; + wxLogDebug( wxT( "Mapping layer %s index index %d" ), + GetChars( name ), layerIndex ); + + if( layerType != LT_UNDEFINED ) + copperLayerCount++; + } + + // We need at least 2 copper layers and there must be an even number of them. + if( (copperLayerCount < 2) || ((copperLayerCount % 2) != 0) ) + { + wxString err; + err.Printf( _( "%d is not a valid layer count" ), copperLayerCount ); + THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() ); + } + + m_board->SetCopperLayerCount( copperLayerCount ); + m_board->SetVisibleLayers( visibleLayers ); + m_board->SetEnabledLayers( enabledLayers ); +} + + +int PCB_PARSER::lookUpLayer() throw( PARSE_ERROR, IO_ERROR ) +{ +#if USE_LAYER_NAMES + wxString name = FromUTF8(); + const LAYER_HASH_MAP::iterator it = m_layerMap.find( name ); + + if( it == m_layerMap.end() ) + { + wxString error; + error.Printf( _( "Layer '%s' in file <%s> at line %d, position %d was not defined in the layers section" ), + GetChars( name ), GetChars( CurSource() ), CurLineNumber(), CurOffset() ); + THROW_IO_ERROR( error ); + } + + return m_layerMap[ name ]; +#else + if( CurTok() != T_NUMBER ) + Expecting( T_NUMBER ); + + int layerIndex = parseInt(); + + if( !m_board->IsLayerEnabled( layerIndex ) ) + { + wxString error; + error.Printf( _( "Layer index %d in file <%s> at line %d, offset %d was not defined in the layers section" ), + layerIndex, GetChars( CurSource() ), CurLineNumber(), CurOffset() ); + THROW_IO_ERROR( error ); + } + + return layerIndex; +#endif +} + + +int PCB_PARSER::parseBoardItemLayer() throw( PARSE_ERROR, IO_ERROR ) +{ + wxCHECK_MSG( CurTok() == T_layer, UNDEFINED_LAYER, + wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as layer." ) ); + + NextTok(); + + int layerIndex = lookUpLayer(); + + // Handle closing ) in object parser. + + return layerIndex; +} + + +int PCB_PARSER::parseBoardItemLayersAsMask() throw( PARSE_ERROR, IO_ERROR ) +{ + wxCHECK_MSG( CurTok() == T_layers, 0, + wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + + wxT( " as item layer mask." ) ); + + int layerIndex; + int layerMask = 0; + T token; + + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + layerIndex = lookUpLayer(); + layerMask |= ( 1 << layerIndex ); + } + + return layerMask; +} + + +void PCB_PARSER::parseSetup() throw( IO_ERROR, PARSE_ERROR ) +{ + wxCHECK_RET( CurTok() == T_setup, + wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as setup." ) ); + + T token; + int lastTraceWidth; + NETCLASS* defaultNetclass = m_board->m_NetClasses.GetDefault(); + BOARD_DESIGN_SETTINGS designSettings = m_board->GetDesignSettings(); + ZONE_SETTINGS zoneSettings = m_board->GetZoneSettings(); + + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token != T_LEFT ) + Expecting( T_LEFT ); + + token = NextTok(); + + switch( token ) + { + case T_last_trace_width: + lastTraceWidth = parseBoardUnits( T_last_trace_width ); + NeedRIGHT(); + break; + + case T_user_trace_width: + m_board->m_TrackWidthList.push_back( parseBoardUnits( T_user_trace_width ) ); + NeedRIGHT(); + break; + + case T_trace_clearance: + defaultNetclass->SetClearance( parseBoardUnits( T_trace_clearance ) ); + NeedRIGHT(); + break; + + case T_zone_clearance: + zoneSettings.m_ZoneClearance = parseBoardUnits( T_zone_clearance ); + NeedRIGHT(); + break; + + case T_zone_45_only: + zoneSettings.m_Zone_45_Only = parseBool(); + NeedRIGHT(); + break; + + case T_trace_min: + designSettings.m_TrackMinWidth = parseBoardUnits( T_trace_min ); + NeedRIGHT(); + break; + + case T_segment_width: + designSettings.m_DrawSegmentWidth = parseBoardUnits( T_segment_width ); + NeedRIGHT(); + break; + + case T_edge_width: + designSettings.m_EdgeSegmentWidth = parseBoardUnits( T_edge_width ); + NeedRIGHT(); + break; + + case T_via_size: + defaultNetclass->SetViaDiameter( parseBoardUnits( T_via_size ) ); + NeedRIGHT(); + break; + + case T_via_drill: + defaultNetclass->SetViaDrill( parseBoardUnits( T_via_drill ) ); + NeedRIGHT(); + break; + + case T_via_min_size: + designSettings.m_ViasMinSize = parseBoardUnits( T_via_min_size ); + NeedRIGHT(); + break; + + case T_via_min_drill: + designSettings.m_ViasMinDrill = parseBoardUnits( T_via_min_drill ); + NeedRIGHT(); + break; + + case T_user_via: + { + int viaSize = parseBoardUnits( "user via size" ); + int viaDrill = parseBoardUnits( "user via drill" ); + m_board->m_ViasDimensionsList.push_back( VIA_DIMENSION( viaSize, viaDrill ) ); + NeedRIGHT(); + } + break; + + case T_uvia_size: + defaultNetclass->SetuViaDiameter( parseBoardUnits( T_uvia_size ) ); + NeedRIGHT(); + break; + + case T_uvia_drill: + defaultNetclass->SetuViaDrill( parseBoardUnits( T_uvia_drill ) ); + NeedRIGHT(); + break; + + case T_uvias_allowed: + designSettings.m_MicroViasAllowed = parseBool(); + NeedRIGHT(); + break; + + case T_uvia_min_size: + designSettings.m_MicroViasMinSize = parseBoardUnits( T_uvia_min_size ); + NeedRIGHT(); + break; + + case T_uvia_min_drill: + designSettings.m_MicroViasMinDrill = parseBoardUnits( T_uvia_min_drill ); + NeedRIGHT(); + break; + + case T_pcb_text_width: + designSettings.m_PcbTextWidth = parseBoardUnits( T_pcb_text_width ); + NeedRIGHT(); + break; + + case T_pcb_text_size: + designSettings.m_PcbTextSize.x = parseBoardUnits( "pcb text width" ); + designSettings.m_PcbTextSize.y = parseBoardUnits( "pcb text height" ); + NeedRIGHT(); + break; + + case T_mod_edge_width: + designSettings.m_ModuleSegmentWidth = parseBoardUnits( T_mod_edge_width ); + NeedRIGHT(); + break; + + case T_mod_text_size: + designSettings.m_ModuleTextSize.x = parseBoardUnits( "module text width" ); + designSettings.m_ModuleTextSize.y = parseBoardUnits( "module text height" ); + NeedRIGHT(); + break; + + case T_mod_text_width: + designSettings.m_ModuleTextWidth = parseBoardUnits( T_mod_text_width ); + NeedRIGHT(); + break; + + case T_pad_size: + { + wxSize sz; + sz.SetWidth( parseBoardUnits( "master pad width" ) ); + sz.SetHeight( parseBoardUnits( "master pad height" ) ); + designSettings.m_Pad_Master.SetSize( sz ); + NeedRIGHT(); + break; + } + + case T_pad_drill: + { + int drillSize = parseBoardUnits( T_pad_drill ); + designSettings.m_Pad_Master.SetDrillSize( wxSize( drillSize, drillSize ) ); + NeedRIGHT(); + } + break; + + case T_pad_to_mask_clearance: + designSettings.m_SolderMaskMargin = parseBoardUnits( T_pad_to_mask_clearance ); + NeedRIGHT(); + break; + + case T_pad_to_paste_clearance: + designSettings.m_SolderPasteMargin = parseBoardUnits( T_pad_to_paste_clearance ); + NeedRIGHT(); + break; + + case T_pad_to_paste_clearance_ratio: + designSettings.m_SolderPasteMarginRatio = parseDouble( T_pad_to_paste_clearance_ratio ); + NeedRIGHT(); + break; + + case T_aux_axis_origin: + { + int x = parseBoardUnits( "auxilary origin X" ); + int y = parseBoardUnits( "auxilary origin Y" ); + // x, y are not evaluated left to right, since they are push on stack right to left + m_board->SetOriginAxisPosition( wxPoint( x, y ) ); + NeedRIGHT(); + break; + } + + case T_visible_elements: + designSettings.SetVisibleElements( parseHex() ); + NeedRIGHT(); + break; + +#if SAVE_PCB_PLOT_PARAMS + case T_pcbplotparams: + { + PCB_PLOT_PARAMS plotParams; + PCB_PLOT_PARAMS_PARSER parser( reader ); + + plotParams.Parse( &parser ); + m_board->SetPlotOptions( plotParams ); + break; + } +#endif + + default: + Unexpected( CurText() ); + } + } + + m_board->SetDesignSettings( designSettings ); + m_board->SetZoneSettings( zoneSettings ); + + // Until such time as the *.brd file does not have the + // global parameters: + // "last_trace_width", "trace_min_width", "via_size", "via_drill", + // "via_min_size", and "via_clearance", put those same global + // values into the default NETCLASS until later board load + // code should override them. *.kicad_brd files which have been + // saved with knowledge of NETCLASSes will override these + // defaults, old boards will not. + // + // @todo: I expect that at some point we can remove said global + // parameters from the *.brd file since the ones in the + // default netclass serve the same purpose. If needed + // at all, the global defaults should go into a preferences + // file instead so they are there to start new board + // projects. + m_board->m_NetClasses.GetDefault()->SetParams(); +} + + +void PCB_PARSER::parseNETINFO_ITEM() throw( IO_ERROR, PARSE_ERROR ) +{ + wxCHECK_RET( CurTok() == T_net, + wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as net." ) ); + + int number = parseInt( "net number" ); + NeedSYMBOL(); + wxString name = FromUTF8(); + NeedRIGHT(); + + NETINFO_ITEM* net = new NETINFO_ITEM( m_board ); + net->SetNet( number ); + net->SetNetname( name ); + m_board->AppendNet( net ); +} + + +void PCB_PARSER::parseNETCLASS() throw( IO_ERROR, PARSE_ERROR ) +{ + wxCHECK_RET( CurTok() == T_net_class, + wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as net class." ) ); + + T token; + + auto_ptr nc( new NETCLASS( m_board, wxEmptyString ) ); + + NeedSYMBOL(); + nc->SetName( FromUTF8() ); + NeedSYMBOL(); + nc->SetDescription( FromUTF8() ); + + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token != T_LEFT ) + Expecting( T_LEFT ); + + token = NextTok(); + + switch( token ) + { + case T_clearance: + nc->SetClearance( parseBoardUnits( T_clearance ) ); + break; + + case T_trace_width: + nc->SetTrackWidth( parseBoardUnits( T_trace_width ) ); + break; + + case T_via_dia: + nc->SetViaDiameter( parseBoardUnits( T_via_dia ) ); + break; + + case T_via_drill: + nc->SetViaDrill( parseBoardUnits( T_via_drill ) ); + break; + + case T_uvia_dia: + nc->SetuViaDiameter( parseBoardUnits( T_uvia_dia ) ); + break; + + case T_uvia_drill: + nc->SetuViaDrill( parseBoardUnits( T_uvia_drill ) ); + break; + + case T_add_net: + NeedSYMBOL(); + nc->Add( FromUTF8() ); + break; + + default: + Expecting( "clearance, trace_width, via_dia, via_drill, uvia_dia, uvia_drill, or add_net" ); + } + + NeedRIGHT(); + } + + if( m_board->m_NetClasses.Add( nc.get() ) ) + { + nc.release(); + } + else + { + // Must have been a name conflict, this is a bad board file. + // User may have done a hand edit to the file. + + // auto_ptr will delete nc on this code path + + wxString error; + error.Printf( _( "duplicate NETCLASS name '%s' in file %s at line %d, offset %d" ), + nc->GetName().GetData(), CurSource().GetData(), CurLineNumber(), CurOffset() ); + THROW_IO_ERROR( error ); + } +} + + +DRAWSEGMENT* PCB_PARSER::parseDRAWSEGMENT() throw( IO_ERROR, PARSE_ERROR ) +{ + wxCHECK_MSG( CurTok() == T_gr_arc || CurTok() == T_gr_circle || CurTok() == T_gr_curve || + CurTok() == T_gr_line || CurTok() == T_gr_poly, NULL, + wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as DRAWSEGMENT." ) ); + + T token; + wxPoint pt; + auto_ptr< DRAWSEGMENT > segment( new DRAWSEGMENT( NULL ) ); + + switch( CurTok() ) + { + case T_gr_arc: + segment->SetShape( S_ARC ); + NeedLEFT(); + token = NextTok(); + + if( token != T_start ) + Expecting( T_start ); + + pt.x = parseBoardUnits( "X coordinate" ); + pt.y = parseBoardUnits( "Y coordinate" ); + segment->SetStart( pt ); + NeedRIGHT(); + NeedLEFT(); + token = NextTok(); + + if( token != T_end ) + Expecting( T_end ); + + pt.x = parseBoardUnits( "X coordinate" ); + pt.y = parseBoardUnits( "Y coordinate" ); + segment->SetEnd( pt ); + NeedRIGHT(); + break; + + case T_gr_circle: + segment->SetShape( S_CIRCLE ); + NeedLEFT(); + token = NextTok(); + + if( token != T_center ) + Expecting( T_center ); + + pt.x = parseBoardUnits( "X coordinate" ); + pt.y = parseBoardUnits( "Y coordinate" ); + segment->SetStart( pt ); + NeedRIGHT(); + NeedLEFT(); + + token = NextTok(); + + if( token != T_end ) + Expecting( T_end ); + + pt.x = parseBoardUnits( "X coordinate" ); + pt.y = parseBoardUnits( "Y coordinate" ); + segment->SetEnd( pt ); + NeedRIGHT(); + break; + + case T_gr_curve: + segment->SetShape( S_CURVE ); + NeedLEFT(); + token = NextTok(); + + if( token != T_pts ) + Expecting( T_pts ); + + segment->SetStart( parseXY() ); + segment->SetBezControl1( parseXY() ); + segment->SetBezControl2( parseXY() ); + segment->SetEnd( parseXY() ); + NeedRIGHT(); + break; + + case T_gr_line: + // Default DRAWSEGMENT type is S_SEGMENT. + NeedLEFT(); + token = NextTok(); + + if( token != T_start ) + Expecting( T_start ); + + pt.x = parseBoardUnits( "X coordinate" ); + pt.y = parseBoardUnits( "Y coordinate" ); + segment->SetStart( pt ); + NeedRIGHT(); + NeedLEFT(); + token = NextTok(); + + if( token != T_end ) + Expecting( T_end ); + + pt.x = parseBoardUnits( "X coordinate" ); + pt.y = parseBoardUnits( "Y coordinate" ); + segment->SetEnd( pt ); + NeedRIGHT(); + break; + + case T_gr_poly: + { + segment->SetShape( S_POLYGON ); + NeedLEFT(); + token = NextTok(); + + if( token != T_pts ) + Expecting( T_pts ); + + std::vector< wxPoint > pts; + + while( (token = NextTok()) != T_RIGHT ) + pts.push_back( parseXY() ); + + segment->SetPolyPoints( pts ); + } + break; + + default: + Expecting( "gr_arc, gr_circle, gr_curve, gr_line, or gr_poly" ); + } + + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token != T_LEFT ) + Expecting( T_LEFT ); + + token = NextTok(); + + switch( token ) + { + case T_angle: + segment->SetAngle( parseDouble( "segment angle" ) * 10.0 ); + break; + + case T_layer: + segment->SetLayer( parseBoardItemLayer() ); + break; + + case T_width: + segment->SetWidth( parseBoardUnits( T_width ) ); + break; + + case T_tstamp: + segment->SetTimeStamp( parseHex() ); + break; + + case T_status: + segment->SetStatus( parseHex() ); + break; + + default: + Expecting( "layer, width, tstamp, or status" ); + } + + NeedRIGHT(); + } + + return segment.release(); +} + + +TEXTE_PCB* PCB_PARSER::parseTEXTE_PCB() throw( IO_ERROR, PARSE_ERROR ) +{ + wxCHECK_MSG( CurTok() == T_gr_text, NULL, + wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as TEXTE_PCB." ) ); + + T token; + + auto_ptr< TEXTE_PCB > text( new TEXTE_PCB( m_board ) ); + NeedSYMBOLorNUMBER(); + + text->SetText( FromUTF8() ); + NeedLEFT(); + token = NextTok(); + + if( token != T_at ) + Expecting( T_at ); + + wxPoint pt; + + pt.x = parseBoardUnits( "X coordinate" ); + pt.y = parseBoardUnits( "Y coordinate" ); + text->SetPosition( pt ); + + // If there is no orientation defined, then it is the default value of 0 degrees. + token = NextTok(); + + if( token == T_NUMBER ) + { + text->SetOrientation( parseDouble() * 10.0 ); + NeedRIGHT(); + } + else if( token != T_RIGHT ) + { + Unexpected( CurText() ); + } + + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token != T_LEFT ) + Expecting( T_LEFT ); + + token = NextTok(); + + switch( token ) + { + case T_layer: + text->SetLayer( parseBoardItemLayer() ); + NeedRIGHT(); + break; + + case T_tstamp: + text->SetTimeStamp( parseHex() ); + NeedRIGHT(); + break; + + case T_effects: + parseEDA_TEXT( (EDA_TEXT*) text.get() ); + break; + + default: + Expecting( "layer, tstamp or effects" ); + } + } + + return text.release(); +} + + +DIMENSION* PCB_PARSER::parseDIMENSION() throw( IO_ERROR, PARSE_ERROR ) +{ + wxCHECK_MSG( CurTok() == T_dimension, NULL, + wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as DIMENSION." ) ); + + T token; + + auto_ptr< DIMENSION > dimension( new DIMENSION( NULL ) ); + + dimension->m_Value = parseBoardUnits( "dimension value" ); + NeedLEFT(); + token = NextTok(); + + if( token != T_width ) + Expecting( T_width ); + + dimension->SetWidth( parseBoardUnits( "dimension width value" ) ); + NeedRIGHT(); + + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token != T_LEFT ) + Expecting( T_LEFT ); + + token = NextTok(); + + switch( token ) + { + case T_layer: + dimension->SetLayer( parseBoardItemLayer() ); + NeedRIGHT(); + break; + + case T_tstamp: + dimension->SetTimeStamp( parseHex() ); + NeedRIGHT(); + break; + + case T_gr_text: + { + TEXTE_PCB* text = parseTEXTE_PCB(); + dimension->m_Text = *text; + delete text; + break; + } + + case T_feature1: + NeedLEFT(); + token = NextTok(); + + if( token != T_pts ) + Expecting( T_pts ); + + parseXY( &dimension->m_featureLineDOx, &dimension->m_featureLineDOy ); + parseXY( &dimension->m_featureLineDFx, &dimension->m_featureLineDFy ); + NeedRIGHT(); + NeedRIGHT(); + break; + + case T_feature2: + NeedLEFT(); + token = NextTok(); + + if( token != T_pts ) + Expecting( T_pts ); + + parseXY( &dimension->m_featureLineGOx, &dimension->m_featureLineGOy ); + parseXY( &dimension->m_featureLineGFx, &dimension->m_featureLineGFy ); + NeedRIGHT(); + NeedRIGHT(); + break; + + + case T_crossbar: + NeedLEFT(); + token = NextTok(); + + if( token != T_pts ) + Expecting( T_pts ); + + parseXY( &dimension->m_crossBarOx, &dimension->m_crossBarOy ); + parseXY( &dimension->m_crossBarFx, &dimension->m_crossBarFy ); + NeedRIGHT(); + NeedRIGHT(); + break; + + case T_arrow1a: + NeedLEFT(); + token = NextTok(); + + if( token != T_pts ) + Expecting( T_pts ); + + parseXY( &dimension->m_arrowD1Ox, &dimension->m_arrowD1Oy ); + parseXY( &dimension->m_arrowD1Fx, &dimension->m_arrowD1Fy ); + NeedRIGHT(); + NeedRIGHT(); + break; + + case T_arrow1b: + NeedLEFT(); + token = NextTok(); + + if( token != T_pts ) + Expecting( T_pts ); + + parseXY( &dimension->m_arrowD2Ox, &dimension->m_arrowD2Oy ); + parseXY( &dimension->m_arrowD2Fx, &dimension->m_arrowD2Fy ); + NeedRIGHT(); + NeedRIGHT(); + break; + + case T_arrow2a: + NeedLEFT(); + token = NextTok(); + + if( token != T_pts ) + Expecting( T_pts ); + + parseXY( &dimension->m_arrowG1Ox, &dimension->m_arrowG1Oy ); + parseXY( &dimension->m_arrowG1Fx, &dimension->m_arrowG1Fy ); + NeedRIGHT(); + NeedRIGHT(); + break; + + case T_arrow2b: + NeedLEFT(); + token = NextTok(); + + if( token != T_pts ) + Expecting( T_pts ); + + parseXY( &dimension->m_arrowG2Ox, &dimension->m_arrowG2Oy ); + parseXY( &dimension->m_arrowG2Fx, &dimension->m_arrowG2Fy ); + NeedRIGHT(); + NeedRIGHT(); + break; + + default: + Expecting( "layer, tstamp, gr_text, feature1, feature2 crossbar, arrow1a, " + "arrow1b, arrow2a, or arrow2b" ); + } + } + + return dimension.release(); +} + + +MODULE* PCB_PARSER::parseMODULE() throw( IO_ERROR, PARSE_ERROR ) +{ + wxCHECK_MSG( CurTok() == T_module, NULL, + wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as MODULE." ) ); + + wxPoint pt; + T token; + + auto_ptr< MODULE > module( new MODULE( m_board ) ); + + NeedSYMBOL(); + module->SetLibRef( FromUTF8() ); + + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token == T_LEFT ) + token = NextTok(); + + switch( token ) + { + case T_locked: + module->SetLocked( true ); + break; + + case T_placed: + module->SetIsPlaced( true ); + break; + + case T_layer: + module->SetLayer( parseBoardItemLayer() ); + NeedRIGHT(); + break; + + case T_tedit: + module->SetLastEditTime( parseHex() ); + NeedRIGHT(); + break; + + case T_tstamp: + module->SetTimeStamp( parseHex() ); + NeedRIGHT(); + break; + + case T_at: + pt.x = parseBoardUnits( "X coordinate" ); + pt.y = parseBoardUnits( "Y coordinate" ); + module->SetPosition( pt ); + token = NextTok(); + + if( token == T_NUMBER ) + { + module->SetOrientation( parseDouble() * 10.0 ); + NeedRIGHT(); + } + else if( token != T_RIGHT ) + { + Expecting( T_RIGHT ); + } + + break; + + case T_descr: + NeedSYMBOL(); + module->SetDescription( FromUTF8() ); + NeedRIGHT(); + break; + + case T_tags: + NeedSYMBOL(); + module->SetKeywords( FromUTF8() ); + NeedRIGHT(); + break; + + case T_path: + NeedSYMBOL(); + module->SetPath( FromUTF8() ); + NeedRIGHT(); + break; + + case T_autoplace_cost90: + module->m_CntRot90 = parseInt( "auto place cost at 90 degrees" ); + NeedRIGHT(); + break; + + case T_autoplace_cost180: + module->m_CntRot180 = parseInt( "auto place cost at 180 degrees" ); + NeedRIGHT(); + break; + + case T_solder_mask_margin: + module->SetLocalSolderMaskMargin( parseBoardUnits( "local solder mask margin value" ) ); + NeedRIGHT(); + break; + + case T_solder_paste_margin: + module->SetLocalSolderPasteMargin( + parseBoardUnits( "local solder paste margin value" ) ); + NeedRIGHT(); + break; + + case T_solder_paste_ratio: + module->SetLocalSolderPasteMarginRatio( + parseDouble( "local solder paste margin ratio value" ) ); + NeedRIGHT(); + break; + + case T_clearance: + module->SetLocalClearance( parseBoardUnits( "local clearance value" ) ); + NeedRIGHT(); + break; + + case T_zone_connect: + module->SetZoneConnection( (ZoneConnection) parseInt( "zone connection value" ) ); + NeedRIGHT(); + break; + + case T_thermal_width: + module->SetThermalWidth( parseBoardUnits( "thermal width value" ) ); + NeedRIGHT(); + break; + + case T_thermal_gap: + module->SetThermalGap( parseBoardUnits( "thermal gap value" ) ); + NeedRIGHT(); + break; + + case T_attr: + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + switch( token ) + { + case T_smd: + module->SetAttributes( module->GetAttributes() | MOD_CMS ); + break; + + case T_virtual: + module->SetAttributes( module->GetAttributes() | MOD_VIRTUAL ); + break; + + default: + Expecting( "smd and/or virtual" ); + } + } + + break; + + case T_fp_text: + { + TEXTE_MODULE* text = parseTEXTE_MODULE(); + text->SetParent( module.get() ); + double orientation = text->GetOrientation(); + orientation -= module->GetOrientation(); + text->SetOrientation( orientation ); + text->SetDrawCoord(); + + if( text->GetType() == TEXT_is_REFERENCE ) + { + module->Reference() = *text; + delete text; + } + else if( text->GetType() == TEXT_is_VALUE ) + { + module->Value() = *text; + delete text; + } + else + { + module->m_Drawings.PushBack( text ); + } + + break; + } + + case T_fp_arc: + case T_fp_circle: + case T_fp_curve: + case T_fp_line: + case T_fp_poly: + { + EDGE_MODULE* em = parseEDGE_MODULE(); + em->SetParent( module.get() ); + em->SetDrawCoord(); + module->m_Drawings.PushBack( em ); + break; + } + + case T_pad: + { + D_PAD* pad = parseD_PAD(); + wxPoint pt = pad->GetPos0(); + RotatePoint( &pt, module->GetOrientation() ); + pad->SetPosition( pt + module->GetPosition() ); + module->AddPad( pad ); + break; + } + + case T_model: + module->Add3DModel( parse3DModel() ); + break; + + default: + Expecting( "locked, placed, tedit, tstamp, at, descr, tags, path, " + "autoplace_cost90, autoplace_cost180, solder_mask_margin, " + "solder_paste_margin, solder_paste_ratio, clearance, " + "zone_connect, thermal_width, thermal_gap, attr, fp_text, " + "fp_arc, fp_circle, fp_curve, fp_line, fp_poly, pad, or model" ); + } + } + + return module.release(); +} + + +TEXTE_MODULE* PCB_PARSER::parseTEXTE_MODULE() throw( IO_ERROR, PARSE_ERROR ) +{ + wxCHECK_MSG( CurTok() == T_fp_text, NULL, + wxString::Format( wxT( "Cannot parse %s as TEXTE_MODULE at line %d, offset %d." ), + GetTokenString( CurTok() ), CurLineNumber(), CurOffset() ) ); + + T token = NextTok(); + + auto_ptr< TEXTE_MODULE > text( new TEXTE_MODULE( NULL ) ); + + switch( token ) + { + case T_reference: + text->SetType( TEXT_is_REFERENCE ); + break; + + case T_value: + text->SetType( TEXT_is_VALUE ); + break; + + case T_user: + break; // Default type is user text. + + default: + THROW_IO_ERROR( wxString::Format( _( "cannot handle module text type %s" ), + GetChars( FromUTF8() ) ) ); + } + + NeedSYMBOLorNUMBER(); + + text->SetText( FromUTF8() ); + NeedLEFT(); + token = NextTok(); + + if( token != T_at ) + Expecting( T_at ); + + wxPoint pt; + + pt.x = parseBoardUnits( "X coordinate" ); + pt.y = parseBoardUnits( "Y coordinate" ); + text->SetPos0( pt ); + token = NextTok(); + + // If there is no orientation defined, then it is the default value of 0 degrees. + if( token == T_NUMBER ) + { + text->SetOrientation( parseDouble() * 10.0 ); + NeedRIGHT(); + } + else if( token != T_RIGHT ) + { + Unexpected( CurText() ); + } + + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token == T_LEFT ) + token = NextTok(); + + switch( token ) + { + case T_layer: + text->SetLayer( parseBoardItemLayer() ); + NeedRIGHT(); + break; + + case T_hide: + text->SetVisible( false ); + break; + + case T_effects: + parseEDA_TEXT( (EDA_TEXT*) text.get() ); + break; + + default: + Expecting( "hide or effects" ); + } + } + + return text.release(); +} + + +EDGE_MODULE* PCB_PARSER::parseEDGE_MODULE() throw( IO_ERROR, PARSE_ERROR ) +{ + wxCHECK_MSG( CurTok() == T_fp_arc || CurTok() == T_fp_circle || CurTok() == T_fp_curve || + CurTok() == T_fp_line || CurTok() == T_fp_poly, NULL, + wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as EDGE_MODULE." ) ); + + wxPoint pt; + T token; + + auto_ptr< EDGE_MODULE > segment( new EDGE_MODULE( NULL ) ); + + switch( CurTok() ) + { + case T_fp_arc: + segment->SetShape( S_ARC ); + NeedLEFT(); + token = NextTok(); + + if( token != T_start ) + Expecting( T_start ); + + pt.x = parseBoardUnits( "X coordinate" ); + pt.y = parseBoardUnits( "Y coordinate" ); + segment->SetStart0( pt ); + NeedRIGHT(); + token = NextTok(); + + if( token != T_end ) + Expecting( T_end ); + + pt.x = parseBoardUnits( "X coordinate" ); + pt.y = parseBoardUnits( "Y coordinate" ); + segment->SetEnd0( pt ); + NeedRIGHT(); + NeedLEFT(); + token = NextTok(); + + if( token != T_angle ) + Expecting( T_angle ); + + segment->SetAngle( parseDouble( "segment angle" ) ); + NeedRIGHT(); + break; + + case T_fp_circle: + segment->SetShape( S_CIRCLE ); + NeedLEFT(); + token = NextTok(); + + if( token != T_center ) + Expecting( T_center ); + + pt.x = parseBoardUnits( "X coordinate" ); + pt.y = parseBoardUnits( "Y coordinate" ); + segment->SetStart0( pt ); + NeedRIGHT(); + NeedLEFT(); + token = NextTok(); + + if( token != T_end ) + Expecting( T_end ); + + pt.x = parseBoardUnits( "X coordinate" ); + pt.y = parseBoardUnits( "Y coordinate" ); + segment->SetEnd0( pt ); + NeedRIGHT(); + break; + + case T_fp_curve: + segment->SetShape( S_CURVE ); + NeedLEFT(); + token = NextTok(); + + if( token != T_pts ) + Expecting( T_pts ); + + segment->SetStart0( parseXY() ); + segment->SetBezControl1( parseXY() ); + segment->SetBezControl2( parseXY() ); + segment->SetEnd0( parseXY() ); + NeedRIGHT(); + break; + + case T_fp_line: + // Default DRAWSEGMENT type is S_SEGMENT. + NeedLEFT(); + token = NextTok(); + + if( token != T_start ) + Expecting( T_start ); + + pt.x = parseBoardUnits( "X coordinate" ); + pt.y = parseBoardUnits( "Y coordinate" ); + segment->SetStart0( pt ); + + NeedRIGHT(); + NeedLEFT(); + token = NextTok(); + + if( token != T_end ) + Expecting( T_end ); + + pt.x = parseBoardUnits( "X coordinate" ); + pt.y = parseBoardUnits( "Y coordinate" ); + segment->SetEnd0( pt ); + NeedRIGHT(); + break; + + case T_fp_poly: + { + segment->SetShape( S_POLYGON ); + NeedLEFT(); + token = NextTok(); + + if( token != T_pts ) + Expecting( T_pts ); + + std::vector< wxPoint > pts; + + while( (token = NextTok()) != T_RIGHT ) + pts.push_back( parseXY() ); + + segment->SetPolyPoints( pts ); + } + break; + + default: + Expecting( "fp_arc, fp_circle, fp_curve, fp_line, or fp_poly" ); + } + + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token != T_LEFT ) + Expecting( T_LEFT ); + + token = NextTok(); + + switch( token ) + { + case T_layer: + segment->SetLayer( parseBoardItemLayer() ); + break; + + case T_width: + segment->SetWidth( parseBoardUnits( T_width ) ); + break; + + case T_tstamp: + segment->SetTimeStamp( parseHex() ); + break; + + case T_status: + segment->SetStatus( parseHex() ); + break; + + default: + Expecting( "layer, width, tstamp, or status" ); + } + + NeedRIGHT(); + } + + return segment.release(); +} + + +D_PAD* PCB_PARSER::parseD_PAD() throw( IO_ERROR, PARSE_ERROR ) +{ + wxCHECK_MSG( CurTok() == T_pad, NULL, + wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as D_PAD." ) ); + + wxSize sz; + wxPoint pt; + auto_ptr< D_PAD > pad( new D_PAD( NULL ) ); + + NeedSYMBOLorNUMBER(); + pad->SetPadName( FromUTF8() ); + + T token = NextTok(); + + switch( token ) + { + case T_thru_hole: + pad->SetAttribute( PAD_STANDARD ); + break; + + case T_smd: + pad->SetAttribute( PAD_SMD ); + break; + + case T_connect: + pad->SetAttribute( PAD_CONN ); + break; + + case T_np_thru_hole: + pad->SetAttribute( PAD_HOLE_NOT_PLATED ); + break; + + default: + Expecting( "thru_hole, smd, connect, or np_thru_hole" ); + } + + token = NextTok(); + + switch( token ) + { + case T_circle: + pad->SetShape( PAD_CIRCLE ); + break; + + case T_rect: + pad->SetShape( PAD_RECT ); + break; + + case T_oval: + pad->SetShape( PAD_OVAL ); + break; + + case T_trapezoid: + pad->SetShape( PAD_TRAPEZOID ); + break; + + default: + Expecting( "circle, rectangle, oval, or trapezoid" ); + } + + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token != T_LEFT ) + Expecting( T_LEFT ); + + token = NextTok(); + + switch( token ) + { + case T_size: + sz.SetWidth( parseBoardUnits( "width value" ) ); + sz.SetHeight( parseBoardUnits( "height value" ) ); + pad->SetSize( sz ); + NeedRIGHT(); + break; + + case T_at: + pt.x = parseBoardUnits( "X coordinate" ); + pt.y = parseBoardUnits( "Y coordinate" ); + pad->SetPos0( pt ); + token = NextTok(); + + if( token == T_NUMBER ) + { + pad->SetOrientation( parseDouble() * 10.0 ); + NeedRIGHT(); + } + else if( token != T_RIGHT ) + { + Expecting( ") or angle value" ); + } + + break; + + case T_rect_delta: + { + wxSize delta; + delta.SetWidth( parseBoardUnits( "rectangle delta width" ) ); + delta.SetHeight( parseBoardUnits( "rectangle delta height" ) ); + pad->SetDelta( delta ); + NeedRIGHT(); + break; + } + + case T_drill: + { + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token == T_LEFT ) + token = NextTok(); + + switch( token ) + { + case T_oval: + pad->SetDrillShape( PAD_OVAL ); + break; + + case T_size: + { + int width = parseBoardUnits( "drill width" ); + int height = width; + token = NextTok(); + + if( token == T_NUMBER ) + { + height = parseBoardUnits(); + NeedRIGHT(); + } + else if( token != T_RIGHT ) + { + Expecting( ") or number" ); + } + + pad->SetDrillSize( wxSize( width, height ) ); + break; + } + + case T_offset: + pad->SetOffset( wxPoint( parseBoardUnits( "drill offset x" ), + parseBoardUnits( "drill offset y" ) ) ); + NeedRIGHT(); + break; + + default: + Expecting( "oval, size, or offset" ); + } + } + + break; + } + + case T_layers: + { + int layerMask = parseBoardItemLayersAsMask(); + + // Only the layers that are used are saved so we need to enable all the copper + // layers to prevent any problems with the current design. At some point in + // the future, the layer handling should be improved. + if( pad->GetAttribute() == PAD_STANDARD ) + layerMask |= ALL_CU_LAYERS; + + pad->SetLayerMask( layerMask ); + break; + } + + case T_net: + pad->SetNet( parseInt( "net number" ) ); + NeedSYMBOL(); + pad->SetNetname( FromUTF8() ); + NeedRIGHT(); + break; + + case T_die_length: + pad->SetDieLength( parseBoardUnits( T_die_length ) ); + NeedRIGHT(); + break; + + case T_solder_mask_margin: + pad->SetLocalSolderMaskMargin( parseBoardUnits( T_solder_mask_margin ) ); + NeedRIGHT(); + break; + + case T_solder_paste_margin: + pad->SetLocalSolderPasteMargin( parseBoardUnits( T_solder_paste_margin ) ); + NeedRIGHT(); + break; + + case T_solder_paste_margin_ratio: + pad->SetLocalSolderPasteMarginRatio( parseBoardUnits( T_solder_paste_margin_ratio ) ); + NeedRIGHT(); + break; + + case T_clearance: + pad->SetLocalClearance( parseBoardUnits( "local clearance value" ) ); + NeedRIGHT(); + break; + + case T_zone_connect: + pad->SetZoneConnection( (ZoneConnection) parseInt( "zone connection value" ) ); + NeedRIGHT(); + break; + + case T_thermal_width: + pad->SetThermalWidth( parseBoardUnits( T_thermal_width ) ); + NeedRIGHT(); + break; + + case T_thermal_gap: + pad->SetThermalGap( parseBoardUnits( T_thermal_gap ) ); + NeedRIGHT(); + break; + + default: + Expecting( "at, drill, layers, net, die_length, solder_mask_margin, " + "solder_paste_margin, solder_paste_margin_ratio, clearance, " + "zone_connect, thermal_width, or thermal_gap" ); + } + } + + return pad.release(); +} + + +TRACK* PCB_PARSER::parseTRACK() throw( IO_ERROR, PARSE_ERROR ) +{ + wxCHECK_MSG( CurTok() == T_segment, NULL, + wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as TRACK." ) ); + + wxPoint pt; + T token; + + auto_ptr< TRACK > track( new TRACK( m_board ) ); + + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token != T_LEFT ) + Expecting( T_LEFT ); + + token = NextTok(); + + switch( token ) + { + case T_start: + pt.x = parseBoardUnits( "start x" ); + pt.y = parseBoardUnits( "start y" ); + track->SetStart( pt ); + break; + + case T_end: + pt.x = parseBoardUnits( "end x" ); + pt.y = parseBoardUnits( "end y" ); + track->SetEnd( pt ); + break; + + case T_width: + track->SetWidth( parseBoardUnits( "width" ) ); + break; + + case T_layer: + track->SetLayer( parseBoardItemLayer() ); + break; + + case T_net: + track->SetNet( parseInt( "net number" ) ); + break; + + case T_tstamp: + track->SetTimeStamp( parseHex() ); + break; + + case T_status: + track->SetStatus( parseHex() ); + break; + + default: + Expecting( "start, end, width, layer, net, tstamp, or status" ); + } + + NeedRIGHT(); + } + + return track.release(); +} + + +SEGVIA* PCB_PARSER::parseSEGVIA() throw( IO_ERROR, PARSE_ERROR ) +{ + wxCHECK_MSG( CurTok() == T_via, NULL, + wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as SEGVIA." ) ); + + wxPoint pt; + T token; + + auto_ptr< SEGVIA > via( new SEGVIA( m_board ) ); + + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token == T_LEFT ) + token = NextTok(); + + switch( token ) + { + case T_blind: + via->SetShape( VIA_BLIND_BURIED ); + break; + + case T_micro: + via->SetShape( VIA_MICROVIA ); + break; + + case T_at: + pt.x = parseBoardUnits( "start x" ); + pt.y = parseBoardUnits( "start y" ); + via->SetStart( pt ); + via->SetEnd( pt ); + NeedRIGHT(); + break; + + case T_size: + via->SetWidth( parseBoardUnits( "via width" ) ); + NeedRIGHT(); + break; + + case T_drill: + via->SetDrill( parseBoardUnits( "drill diameter" ) ); + NeedRIGHT(); + break; + + case T_layers: + { + int layer1, layer2; + NextTok(); + layer1 = lookUpLayer(); + NextTok(); + layer2 = lookUpLayer(); + via->SetLayerPair( layer1, layer2 ); + NeedRIGHT(); + } + break; + + case T_net: + via->SetNet( parseInt( "net number" ) ); + NeedRIGHT(); + break; + + case T_tstamp: + via->SetTimeStamp( parseHex() ); + NeedRIGHT(); + break; + + case T_status: + via->SetStatus( parseHex() ); + NeedRIGHT(); + break; + + default: + Expecting( "blind, micro, at, size, drill, layers, net, tstamp, or status" ); + } + } + + return via.release(); +} + + +ZONE_CONTAINER* PCB_PARSER::parseZONE_CONTAINER() throw( IO_ERROR, PARSE_ERROR ) +{ + wxCHECK_MSG( CurTok() == T_zone, NULL, + wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + + wxT( " as ZONE_CONTAINER." ) ); + + int hatchStyle = CPolyLine::NO_HATCH; // Fix compil warning + int hatchPitch = 0; // Fix compil warning + wxPoint pt; + T token; + + // bigger scope since each filled_polygon is concatonated in here + std::vector< CPolyPt > pts; + + auto_ptr< ZONE_CONTAINER > zone( new ZONE_CONTAINER( m_board ) ); + + zone->SetPriority( 0 ); + + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token == T_LEFT ) + token = NextTok(); + + switch( token ) + { + case T_net: + zone->SetNet( parseInt( "net number" ) ); + NeedRIGHT(); + break; + + case T_net_name: + NeedSYMBOL(); + zone->SetNetName( FromUTF8() ); + NeedRIGHT(); + break; + + case T_layer: + zone->SetLayer( parseBoardItemLayer() ); + NeedRIGHT(); + break; + + case T_tstamp: + zone->SetTimeStamp( parseHex() ); + NeedRIGHT(); + break; + + case T_hatch: + token = NextTok(); + + if( token != T_none && token != T_edge && token != T_full ) + Expecting( "none, edge, or full" ); + + switch( token ) + { + default: + case T_none: hatchStyle = CPolyLine::NO_HATCH; break; + case T_edge: hatchStyle = CPolyLine::DIAGONAL_EDGE; break; + case T_full: hatchStyle = CPolyLine::DIAGONAL_FULL; + } + + hatchPitch = parseBoardUnits( "hatch pitch" ); + NeedRIGHT(); + break; + + case T_priority: + zone->SetPriority( parseInt( "zone priority" ) ); + NeedRIGHT(); + break; + + case T_connect_pads: + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token == T_LEFT ) + token = NextTok(); + + switch( token ) + { + case T_yes: + zone->SetPadConnection( PAD_IN_ZONE ); + break; + + case T_no: + zone->SetPadConnection( PAD_NOT_IN_ZONE ); + break; + + case T_clearance: + zone->SetZoneClearance( parseBoardUnits( "zone clearance" ) ); + NeedRIGHT(); + break; + + default: + Expecting( "yes, no, or clearance" ); + } + } + + break; + + case T_min_thickness: + zone->SetMinThickness( parseBoardUnits( T_min_thickness ) ); + NeedRIGHT(); + break; + + case T_fill: + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token == T_LEFT ) + token = NextTok(); + + switch( token ) + { + case T_yes: + zone->SetIsFilled( true ); + break; + + case T_mode: + token = NextTok(); + + if( token != T_segment && token != T_polygon ) + Expecting( "segment or polygon" ); + + // @todo Create an enum for fill modes. + zone->SetFillMode( token == T_polygon ? 0 : 1 ); + break; + + case T_arc_segments: + zone->SetArcSegCount( parseInt( "arc segment count" ) ); + break; + + case T_thermal_gap: + zone->SetThermalReliefGap( parseBoardUnits( T_thermal_gap ) ); + break; + + case T_thermal_bridge_width: + zone->SetThermalReliefCopperBridge( parseBoardUnits( T_thermal_bridge_width ) ); + break; + + case T_smoothing: + switch( NextTok() ) + { + case T_none: + zone->SetCornerSmoothingType( ZONE_SETTINGS::SMOOTHING_NONE ); + break; + + case T_chamfer: + zone->SetCornerSmoothingType( ZONE_SETTINGS::SMOOTHING_CHAMFER ); + break; + + case T_fillet: + zone->SetCornerSmoothingType( ZONE_SETTINGS::SMOOTHING_FILLET ); + break; + + default: + Expecting( "none, chamfer, or fillet" ); + } + + break; + + case T_radius: + zone->SetCornerRadius( parseBoardUnits( "corner radius" ) ); + break; + + default: + Expecting( "mode, arc_segments, thermal_gap, thermal_bridge_width, " + "smoothing, or radius" ); + } + + NeedRIGHT(); + } + + break; + + case T_polygon: + { + std::vector< wxPoint > corners; + + NeedLEFT(); + token = NextTok(); + + if( token != T_pts ) + Expecting( T_pts ); + + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + corners.push_back( parseXY() ); + } + + NeedRIGHT(); + zone->AddPolygon( corners ); + } + + break; + + case T_filled_polygon: + { + // "(filled_polygon (pts" + NeedLEFT(); + token = NextTok(); + + if( token != T_pts ) + Expecting( T_pts ); + + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + pts.push_back( CPolyPt( parseXY() ) ); + } + + NeedRIGHT(); + pts.back().end_contour = true; + } + + break; + + case T_fill_segments: + { + std::vector< SEGMENT > segs; + + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token != T_LEFT ) + Expecting( T_LEFT ); + + token = NextTok(); + + if( token != T_pts ) + Expecting( T_pts ); + + SEGMENT segment( parseXY(), parseXY() ); + NeedRIGHT(); + segs.push_back( segment ); + } + + zone->AddFillSegments( segs ); + } + + break; + + default: + Expecting( "net, layer, tstamp, hatch, priority, connect_pads, min_thickness, " + "fill, polygon, filled_polygon, or fill_segments" ); + } + } + + if( zone->GetNumCorners() > 2 ) + { + if( !zone->IsOnCopperLayer() ) + { + zone->SetFillMode( 0 ); + zone->SetNet( 0 ); + } + + // Set hatch here, after outlines corners are read + zone->m_Poly->SetHatch( hatchStyle, hatchPitch ); + } + + if( pts.size() ) + zone->AddFilledPolysList( pts ); + + return zone.release(); +} + + +PCB_TARGET* PCB_PARSER::parsePCB_TARGET() throw( IO_ERROR, PARSE_ERROR ) +{ + wxCHECK_MSG( CurTok() == T_target, NULL, + wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as PCB_TARGET." ) ); + + wxPoint pt; + T token; + + auto_ptr< PCB_TARGET > target( new PCB_TARGET( NULL ) ); + + + for( token = NextTok(); token != T_RIGHT; token = NextTok() ) + { + if( token == T_LEFT ) + token = NextTok(); + + switch( token ) + { + case T_x: + target->SetShape( 1 ); + break; + + case T_plus: + target->SetShape( 0 ); + break; + + case T_at: + pt.x = parseBoardUnits( "target x position" ); + pt.y = parseBoardUnits( "target y position" ); + target->SetPosition( pt ); + NeedRIGHT(); + break; + + case T_size: + target->SetSize( parseBoardUnits( "target size" ) ); + NeedRIGHT(); + break; + + case T_width: + target->SetWidth( parseBoardUnits( "target thickness" ) ); + NeedRIGHT(); + break; + + case T_layer: + target->SetLayer( parseBoardItemLayer() ); + NeedRIGHT(); + break; + + case T_tstamp: + target->SetTimeStamp( parseHex() ); + NeedRIGHT(); + break; + + default: + Expecting( "x, plus, at, size, width, layer or tstamp" ); + } + } + + return target.release(); +} diff --git a/pcbnew/pcb_parser.h b/pcbnew/pcb_parser.h new file mode 100644 index 0000000000..f94d9c558e --- /dev/null +++ b/pcbnew/pcb_parser.h @@ -0,0 +1,219 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 CERN + * + * 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 pcb_parser.h + * @brief Pcbnew s-expression file format parser definition. + */ + +#ifndef _PCBNEW_PARSER_H_ +#define _PCBNEW_PARSER_H_ + +#include + +#include + + +using namespace PCB; + + +class BOARD; +class BOARD_ITEM; +class D_PAD; +class DIMENSION; +class DRAWSEGMENT; +class EDGE_MODULE; +class TEXTE_MODULE; +class TEXTE_PCB; +class MODULE; +class PCB_TARGET; +class S3D_MASTER; +class ZONE_CONTAINER; + + +WX_DECLARE_STRING_HASH_MAP( int, LAYER_HASH_MAP ); + + +#define USE_LAYER_NAMES 1 // Set to 0 to format and parse layers by index number. +#define SAVE_PCB_PLOT_PARAMS 0 // Set to 1 to save and load the PCB plot dialog data. + +/** + * Class PCB_PARSER + * reads a Pcbnew s-expression fromatted #LINE_READER object and returns the appropriate + * #BOARD_ITEM object. + */ +class PCB_PARSER : public PCB_LEXER +{ + BOARD* m_board; + LAYER_HASH_MAP m_layerMap; //< Map layer name to it's index saved in BOARD::m_Layer. + + void parseHeader() throw( IO_ERROR, PARSE_ERROR ); + void parseGeneralSection() throw( IO_ERROR, PARSE_ERROR ); + void parsePAGE_INFO() throw( IO_ERROR, PARSE_ERROR ); + void parseTITLE_BLOCK() throw( IO_ERROR, PARSE_ERROR ); + void parseLayers() throw( IO_ERROR, PARSE_ERROR ); + void parseSetup() throw( IO_ERROR, PARSE_ERROR ); + void parseNETINFO_ITEM() throw( IO_ERROR, PARSE_ERROR ); + void parseNETCLASS() throw( IO_ERROR, PARSE_ERROR ); + DRAWSEGMENT* parseDRAWSEGMENT() throw( IO_ERROR, PARSE_ERROR ); + TEXTE_PCB* parseTEXTE_PCB() throw( IO_ERROR, PARSE_ERROR ); + DIMENSION* parseDIMENSION() throw( IO_ERROR, PARSE_ERROR ); + MODULE* parseMODULE() throw( IO_ERROR, PARSE_ERROR ); + TEXTE_MODULE* parseTEXTE_MODULE() throw( IO_ERROR, PARSE_ERROR ); + EDGE_MODULE* parseEDGE_MODULE() throw( IO_ERROR, PARSE_ERROR ); + D_PAD* parseD_PAD() throw( IO_ERROR, PARSE_ERROR ); + TRACK* parseTRACK() throw( IO_ERROR, PARSE_ERROR ); + SEGVIA* parseSEGVIA() throw( IO_ERROR, PARSE_ERROR ); + ZONE_CONTAINER* parseZONE_CONTAINER() throw( IO_ERROR, PARSE_ERROR ); + PCB_TARGET* parsePCB_TARGET() throw( IO_ERROR, PARSE_ERROR ); + BOARD* parseBOARD() throw( IO_ERROR, PARSE_ERROR ); + + + /** + * Function lookUpLayer + * parses the current token for the layer definition of a #BOARD_ITEM object. + * + * @throw IO_ERROR if the layer is not valid. + * @throw PARSE_ERROR if the layer syntax is incorrect. + * @return The index the parsed #BOARD_ITEM layer. + */ + int lookUpLayer() throw( PARSE_ERROR, IO_ERROR ); + + /** + * Function parseBoardItemLayer + * parses the layer definition of a #BOARD_ITEM object. + * + * @throw IO_ERROR if the layer is not valid. + * @throw PARSE_ERROR if the layer syntax is incorrect. + * @return The index the parsed #BOARD_ITEM layer. + */ + int parseBoardItemLayer() throw( IO_ERROR, PARSE_ERROR ); + + /** + * Function parseBoardItemLayersAsMask + * parses the layers definition of a #BOARD_ITEM object. + * + * @throw IO_ERROR if any of the layers is not valid. + * @throw PARSE_ERROR if the layers syntax is incorrect. + * @return The mask of layers the parsed #BOARD_ITEM is on. + */ + int parseBoardItemLayersAsMask() throw( PARSE_ERROR, IO_ERROR ); + + /** + * Function parseXY + * parses a coordinate pair (xy X Y) in board units (mm). + * + * The parser checks if the previous token was T_LEFT and parses the remainder of + * the token syntax. This is used when parsing a list of coorinate points. This + * way the parser can be used in either case. + * + * @throw PARSE_ERROR if the coordinate pair syntax is incorrect. + * @return A wxPoint object containing the coordinate pair. + */ + wxPoint parseXY() throw( PARSE_ERROR ); + + void parseXY( int* aX, int* aY ) throw( PARSE_ERROR ); + + /** + * Function parseEDA_TEXT + * parses the common settings for any object derived from #EDA_TEXT. + * + * @throw PARSE_ERROR if the text syntax is not valid. + * @param aText A point to the #EDA_TEXT object to save the parsed settings into. + */ + void parseEDA_TEXT( EDA_TEXT* aText ) throw( PARSE_ERROR ); + + S3D_MASTER* parse3DModel() throw( PARSE_ERROR ); + + /** + * Function parseDouble + * parses the current token as an ASCII numeric string with possible leading whitespace into + * a double precision floating point number. + * + * @throw IO_ERROR if an error occurs attempting to convert the current token. + * @return The result of the parsed token. + */ + double parseDouble() throw( IO_ERROR ); + + inline double parseDouble( const char* aExpected ) throw( IO_ERROR ) + { + NeedNUMBER( aExpected ); + return parseDouble(); + } + + inline double parseDouble( T aToken ) throw( IO_ERROR ) + { + return parseDouble( GetTokenText( aToken ) ); + } + + inline int parseBoardUnits() throw( IO_ERROR ) + { + // There should be no rounding issues here, since the values in the file are in mm + // and get converted to nano-meters. This product should be an integer, exactly. + return int( parseDouble() * IU_PER_MM ); + } + + inline int parseBoardUnits( const char* aExpected ) throw( PARSE_ERROR ) + { + // Use here KiROUND, not KIROUND (see comments about them) + // when having a function as argument, because it will be called twice + // with KIROUND + return KiROUND( parseDouble( aExpected ) * IU_PER_MM ); + } + + inline int parseBoardUnits( T aToken ) throw( PARSE_ERROR ) + { + return parseBoardUnits( GetTokenText( aToken ) ); + } + + inline int parseInt() throw( PARSE_ERROR ) + { + return (int)strtol( CurText(), NULL, 10 ); + } + + inline int parseInt( const char* aExpected ) throw( PARSE_ERROR ) + { + NeedNUMBER( aExpected ); + return parseInt(); + } + + inline long parseHex() throw( PARSE_ERROR ) + { + NextTok(); + return strtol( CurText(), NULL, 16 ); + } + + bool parseBool() throw( PARSE_ERROR ); + +public: + PCB_PARSER( LINE_READER* aReader, BOARD* aBoard = NULL ) : + PCB_LEXER( aReader ), + m_board( aBoard ) + { + } + + BOARD_ITEM* Parse() throw( IO_ERROR, PARSE_ERROR ); +}; + + +#endif // _PCBNEW_PARSER_H_ diff --git a/pcbnew/pcb_plot_params.cpp b/pcbnew/pcb_plot_params.cpp index 8f9dc45a8c..bf601d5992 100644 --- a/pcbnew/pcb_plot_params.cpp +++ b/pcbnew/pcb_plot_params.cpp @@ -28,18 +28,19 @@ #include #include #include +#include #define PLOT_LINEWIDTH_MIN 0 -#define PLOT_LINEWIDTH_MAX (200*IU_PER_DECIMILS) +#define PLOT_LINEWIDTH_MAX (200*IU_PER_MILS) #define HPGL_PEN_DIAMETER_MIN 0 -#define HPGL_PEN_DIAMETER_MAX (100*IU_PER_DECIMILS) -#define HPGL_PEN_SPEED_MIN 0 -#define HPGL_PEN_SPEED_MAX 1000 +#define HPGL_PEN_DIAMETER_MAX 100 // Unit = mil +#define HPGL_PEN_SPEED_MIN 1 // this param is always in cm/s +#define HPGL_PEN_SPEED_MAX 99 // this param is always in cm/s #define HPGL_PEN_NUMBER_MIN 1 #define HPGL_PEN_NUMBER_MAX 16 -#define HPGL_PEN_OVERLAY_MIN 0 -#define HPGL_PEN_OVERLAY_MAX 0x100 +#define HPGL_PEN_OVERLAP_MIN 0 +#define HPGL_PEN_OVERLAP_MAX 50 // Unit = mil /** @@ -47,7 +48,7 @@ * default thickness line value (Frame references) (i.e. = 0 ). * 0 = single pixel line width. */ -int g_DrawDefaultLineThickness = 60; +int g_DrawDefaultLineThickness = 6*IU_PER_MILS; using namespace PCBPLOTPARAMS_T; @@ -88,9 +89,9 @@ PCB_PLOT_PARAMS::PCB_PLOT_PARAMS() m_PlotMode = FILLED; useAuxOrigin = false; m_HPGLPenNum = 1; - m_HPGLPenSpeed = 20; - m_HPGLPenDiam = 15; - m_HPGLPenOvr = 2; + m_HPGLPenSpeed = 20; // this param is always in cm/s + m_HPGLPenDiam = 15; // in mils + m_HPGLPenOvr = 2; // in mils m_PlotPSColorOpt = true; m_PlotPSNegative = false; psA4Output = false; @@ -119,7 +120,7 @@ void PCB_PLOT_PARAMS::Format( OUTPUTFORMATTER* aFormatter, const char* falseStr = getTokenName( T_false ); const char* trueStr = getTokenName( T_true ); - aFormatter->Print( aNestLevel, "(%s", getTokenName( T_pcbplotparams ) ); + aFormatter->Print( aNestLevel, "(%s\n", getTokenName( T_pcbplotparams ) ); aFormatter->Print( aNestLevel+1, "(%s %ld)\n", getTokenName( T_layerselection ), layerSelection ); aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_usegerberextensions ), @@ -170,7 +171,7 @@ void PCB_PLOT_PARAMS::Format( OUTPUTFORMATTER* aFormatter, m_DrillShapeOpt ); aFormatter->Print( aNestLevel+1, "(%s %d)\n", getTokenName( T_scaleselection ), scaleSelection ); - aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_outputdirectory ), + aFormatter->Print( aNestLevel+1, "(%s %s)", getTokenName( T_outputdirectory ), aFormatter->Quotew( outputDirectory ).c_str() ); aFormatter->Print( 0, ")\n" ); } @@ -260,7 +261,7 @@ bool PCB_PLOT_PARAMS::SetHpglPenSpeed( int aValue ) bool PCB_PLOT_PARAMS::SetHpglPenOverlay( int aValue ) { - return setInt( &m_HPGLPenOvr, aValue, HPGL_PEN_OVERLAY_MIN, HPGL_PEN_OVERLAY_MAX ); + return setInt( &m_HPGLPenOvr, aValue, HPGL_PEN_OVERLAP_MIN, HPGL_PEN_OVERLAP_MAX ); } @@ -344,8 +345,8 @@ void PCB_PLOT_PARAMS_PARSER::Parse( PCB_PLOT_PARAMS* aPcbPlotParams ) throw( IO_ HPGL_PEN_DIAMETER_MAX ); break; case T_hpglpenoverlay: - aPcbPlotParams->m_HPGLPenOvr = ParseInt( HPGL_PEN_OVERLAY_MIN, - HPGL_PEN_OVERLAY_MIN ); + aPcbPlotParams->m_HPGLPenOvr = ParseInt( HPGL_PEN_OVERLAP_MIN, + HPGL_PEN_OVERLAP_MAX ); break; case T_pscolor: aPcbPlotParams->m_PlotPSColorOpt = ParseBool(); diff --git a/pcbnew/pcb_plot_params.h b/pcbnew/pcb_plot_params.h index 342547f8db..b7676ab8a0 100644 --- a/pcbnew/pcb_plot_params.h +++ b/pcbnew/pcb_plot_params.h @@ -47,10 +47,10 @@ public: ///< (ie protected by mask) EDA_DRAW_MODE_T m_PlotMode; ///< LINE, FILLED or SKETCH: select how to plot filled objects. ///< depending on plot format or layers, all options are not always allowed - int m_HPGLPenNum; - int m_HPGLPenSpeed; - int m_HPGLPenDiam; - int m_HPGLPenOvr; + int m_HPGLPenNum; ///< HPGL only: pen number selection(1 to 9) + int m_HPGLPenSpeed; ///< HPGL only: pen speed, always in cm/s (1 to 99 cm/s) + int m_HPGLPenDiam; ///< HPGL only: pen diameter in MILS, usefull to fill areas + int m_HPGLPenOvr; ///< HPGL only: pen overlay in MILS, usefull only to fill areas int m_PlotPSColorOpt; ///< True for color Postscript output bool m_PlotPSNegative; ///< True to create a negative board ps plot diff --git a/pcbnew/pcbnew.cpp b/pcbnew/pcbnew.cpp index e20552f91d..73f39159db 100644 --- a/pcbnew/pcbnew.cpp +++ b/pcbnew/pcbnew.cpp @@ -1,8 +1,9 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2009 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 1992-2012 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 @@ -58,7 +59,6 @@ bool Drc_On = true; bool g_AutoDeleteOldTrack = true; bool g_Drag_Pistes_On; bool g_Show_Module_Ratsnest; -bool g_Show_Pads_Module_in_Move = true; bool g_Raccord_45_Auto = true; bool g_Alternate_Track_Posture = false; bool g_Track_45_Only_Allowed = true; // True to allow horiz, vert. and 45deg only tracks diff --git a/pcbnew/pcbnew.h b/pcbnew/pcbnew.h index cf39455997..bc5df44334 100644 --- a/pcbnew/pcbnew.h +++ b/pcbnew/pcbnew.h @@ -53,7 +53,6 @@ extern bool Drc_On; extern bool g_AutoDeleteOldTrack; extern bool g_Drag_Pistes_On; extern bool g_Show_Module_Ratsnest; -extern bool g_Show_Pads_Module_in_Move; extern bool g_Raccord_45_Auto; extern bool g_Track_45_Only_Allowed; extern bool g_Alternate_Track_Posture; diff --git a/pcbnew/pcbnew_config.cpp b/pcbnew/pcbnew_config.cpp index 709d16e51b..99c9a4dfa2 100644 --- a/pcbnew/pcbnew_config.cpp +++ b/pcbnew/pcbnew_config.cpp @@ -1,9 +1,10 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2009 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2011 Wayne Stambaugh - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2012 Wayne Stambaugh + * Copyright (C) 1992-2012 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 diff --git a/pcbnew/pcbnew_id.h b/pcbnew/pcbnew_id.h index 832d9970d4..8397c0f5e2 100644 --- a/pcbnew/pcbnew_id.h +++ b/pcbnew/pcbnew_id.h @@ -92,6 +92,7 @@ enum pcbnew_ids ID_POPUP_PCB_FILL_ALL_ZONES, ID_POPUP_PCB_FILL_ZONE, ID_POPUP_PCB_DELETE_ZONE_CONTAINER, + ID_POPUP_PCB_ZONE_DUPLICATE, ID_POPUP_PCB_ZONE_ADD_SIMILAR_ZONE, ID_POPUP_PCB_ZONE_ADD_CUTOUT_ZONE, ID_POPUP_PCB_DELETE_ZONE_CUTOUT, diff --git a/pcbnew/pcbplot.cpp b/pcbnew/pcbplot.cpp index 57603b3ce8..d5e8678f8b 100644 --- a/pcbnew/pcbplot.cpp +++ b/pcbnew/pcbplot.cpp @@ -2,6 +2,31 @@ * @file pcbnew/pcbplot.cpp */ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 1992-2012 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 + */ + #include #include #include @@ -119,18 +144,20 @@ void DIALOG_PLOT::Init_Dialog() m_plotFormatOpt->SetSelection( m_plotOpts.GetPlotFormat() ); - // Set units and value for HPGL pen size. + // Set units and value for HPGL pen size (this param in in mils). AddUnitSymbol( *m_textPenSize, g_UserUnit ); - msg = ReturnStringFromValue( g_UserUnit, m_plotOpts.GetHpglPenDiameter() * 10 ); + msg = ReturnStringFromValue( g_UserUnit, + m_plotOpts.GetHpglPenDiameter() * IU_PER_MILS ); m_HPGLPenSizeOpt->AppendText( msg ); - // Set units to cm/s for standard HPGL pen speed. - msg = ReturnStringFromValue( UNSCALED_UNITS, m_plotOpts.GetHpglPenSpeed() * 10000 ); + // Units are *always* cm/s for HPGL pen speed, from 1 to 99. + msg = ReturnStringFromValue( UNSCALED_UNITS, m_plotOpts.GetHpglPenSpeed() ); m_HPGLPenSpeedOpt->AppendText( msg ); - // Set units and value for HPGL pen overlay. + // Set units and value for HPGL pen overlay (this param in in mils). AddUnitSymbol( *m_textPenOvr, g_UserUnit ); - msg = ReturnStringFromValue( g_UserUnit, m_plotOpts.GetHpglPenOverlay() * 10 ); + msg = ReturnStringFromValue( g_UserUnit, + m_plotOpts.GetHpglPenOverlay() * IU_PER_MILS ); m_HPGLPenOverlayOpt->AppendText( msg ); AddUnitSymbol( *m_textDefaultPenSize, g_UserUnit ); @@ -448,37 +475,39 @@ void DIALOG_PLOT::applyPlotSettings() // Update settings from text fields. Rewrite values back to the fields, // since the values may have been constrained by the setters. - // HPLG pen size + + // read HPLG pen size (this param is stored in mils) wxString msg = m_HPGLPenSizeOpt->GetValue(); - int tmp = ReturnValueFromString( g_UserUnit, msg ); + int tmp = ReturnValueFromString( g_UserUnit, msg ) / IU_PER_MILS; if( !tempOptions.SetHpglPenDiameter( tmp ) ) { - msg = ReturnStringFromValue( g_UserUnit, tempOptions.GetHpglPenDiameter() * 10 ); + msg = ReturnStringFromValue( g_UserUnit, tempOptions.GetHpglPenDiameter() * IU_PER_MILS ); m_HPGLPenSizeOpt->SetValue( msg ); msg.Printf( _( "HPGL pen size constrained!\n" ) ); m_messagesBox->AppendText( msg ); } - // HPGL pen speed + // read HPGL pen speed (this param is stored in cm/s) msg = m_HPGLPenSpeedOpt->GetValue(); tmp = ReturnValueFromString( UNSCALED_UNITS, msg ); if( !tempOptions.SetHpglPenSpeed( tmp ) ) { - msg = ReturnStringFromValue( UNSCALED_UNITS, tempOptions.GetHpglPenSpeed() * 1000 ); + msg = ReturnStringFromValue( UNSCALED_UNITS, tempOptions.GetHpglPenSpeed() ); m_HPGLPenSpeedOpt->SetValue( msg ); msg.Printf( _( "HPGL pen speed constrained!\n" ) ); m_messagesBox->AppendText( msg ); } - // HPGL pen overlay + // Read HPGL pen overlay (this param is stored in mils) msg = m_HPGLPenOverlayOpt->GetValue(); - tmp = ReturnValueFromString( g_UserUnit, msg ); + tmp = ReturnValueFromString( g_UserUnit, msg ) / IU_PER_MILS; if( !tempOptions.SetHpglPenOverlay( tmp ) ) { - msg = ReturnStringFromValue( g_UserUnit, tempOptions.GetHpglPenOverlay() * 10 ); + msg = ReturnStringFromValue( g_UserUnit, + tempOptions.GetHpglPenOverlay() * IU_PER_MILS ); m_HPGLPenOverlayOpt->SetValue( msg ); msg.Printf( _( "HPGL pen overlay constrained!\n" ) ); m_messagesBox->AppendText( msg ); diff --git a/pcbnew/plotdxf.cpp b/pcbnew/plotdxf.cpp index 68eb1109fe..b28ddbf733 100644 --- a/pcbnew/plotdxf.cpp +++ b/pcbnew/plotdxf.cpp @@ -37,7 +37,7 @@ bool PCB_BASE_FRAME::ExportToDxfFile( const wxString& aFullFileName, int aLayer, plotter->StartPlot( output_file ); if( plot_opts.m_PlotFrameRef ) - PlotWorkSheet( plotter, GetScreen() ); + PlotWorkSheet( plotter, GetScreen(), plot_opts.GetPlotLineWidth() ); Plot_Layer( plotter, aLayer, aTraceMode ); plotter->EndPlot(); diff --git a/pcbnew/plotgerb.cpp b/pcbnew/plotgerb.cpp index cd28252698..21cd95081b 100644 --- a/pcbnew/plotgerb.cpp +++ b/pcbnew/plotgerb.cpp @@ -70,7 +70,7 @@ bool PCB_BASE_FRAME::ExportToGerberFile( const wxString& aFullFileName, int aLay // Sheet refs on gerber CAN be useful... and they're always 1:1 if( plot_opts.m_PlotFrameRef ) - PlotWorkSheet( plotter, GetScreen() ); + PlotWorkSheet( plotter, GetScreen(), plot_opts.GetPlotLineWidth() ); Plot_Layer( plotter, aLayer, aTraceMode ); diff --git a/pcbnew/plothpgl.cpp b/pcbnew/plothpgl.cpp index 3c8faca4c6..93fc748147 100644 --- a/pcbnew/plothpgl.cpp +++ b/pcbnew/plothpgl.cpp @@ -2,19 +2,39 @@ * @file plothpgl.cpp */ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 KiCad Developers, see change_log.txt for contributors. + * Copyright (C) 2012 Dick Hollenbeck, dick@softplc.com + * + * 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 + */ + + #include #include #include -#include -#include #include -#include - #include - #include -#include #include +#include bool PCB_BASE_FRAME::ExportToHpglFile( const wxString& aFullFileName, int aLayer, @@ -35,20 +55,21 @@ bool PCB_BASE_FRAME::ExportToHpglFile( const wxString& aFullFileName, int aLayer PCB_PLOT_PARAMS plot_opts = GetPlotSettings(); - // Compute pen_dim (from g_m_HPGLPenDiam in mils) in pcb units, - // with plot scale (if Scale is 2, pen diameter is always g_m_HPGLPenDiam + // Compute pen_dim (from m_HPGLPenDiam in mils) in pcb units, + // with plot scale (if Scale is 2, pen diameter value is always m_HPGLPenDiam // so apparent pen diam is real pen diam / Scale - int pen_diam = KiROUND( plot_opts.m_HPGLPenDiam / + int pen_diam = KiROUND( plot_opts.m_HPGLPenDiam * IU_PER_MILS / plot_opts.m_PlotScale ); - // compute pen_overlay (from g_m_HPGLPenOvr in mils) with plot scale + // compute pen_overlay (from m_HPGLPenOvr in mils) in pcb units + // with plot scale if( plot_opts.m_HPGLPenOvr < 0 ) plot_opts.m_HPGLPenOvr = 0; if( plot_opts.m_HPGLPenOvr >= plot_opts.m_HPGLPenDiam ) plot_opts.m_HPGLPenOvr = plot_opts.m_HPGLPenDiam - 1; - int pen_overlay = KiROUND( plot_opts.m_HPGLPenOvr * 10.0 / + int pen_overlay = KiROUND( plot_opts.m_HPGLPenOvr * IU_PER_MILS / plot_opts.m_PlotScale ); @@ -72,7 +93,7 @@ bool PCB_BASE_FRAME::ExportToHpglFile( const wxString& aFullFileName, int aLayer // Fit to 80% of the page double Xscale = ( ( pageSizeIU.x * 0.8 ) / boardSize.x ); double Yscale = ( ( pageSizeIU.y * 0.8 ) / boardSize.y ); - scale = MIN( Xscale, Yscale ); + scale = std::min( Xscale, Yscale ); } else { @@ -100,7 +121,7 @@ bool PCB_BASE_FRAME::ExportToHpglFile( const wxString& aFullFileName, int aLayer // why did we have to change these settings above? SetPlotSettings( plot_opts ); - plotter->SetViewport( offset, IU_PER_DECIMILS, scale, + plotter->SetViewport( offset, IU_PER_DECIMILS, scale, plot_opts.m_PlotMirror ); plotter->SetDefaultLineWidth( plot_opts.m_PlotLineWidth ); plotter->SetCreator( wxT( "PCBNEW-HPGL" ) ); @@ -113,7 +134,7 @@ bool PCB_BASE_FRAME::ExportToHpglFile( const wxString& aFullFileName, int aLayer // The worksheet is not significant with scale!=1... It is with paperscale!=1, anyway if( plot_opts.m_PlotFrameRef && !center ) - PlotWorkSheet( plotter, GetScreen() ); + PlotWorkSheet( plotter, GetScreen(), plot_opts.GetPlotLineWidth() ); Plot_Layer( plotter, aLayer, aTraceMode ); plotter->EndPlot(); diff --git a/pcbnew/plotps.cpp b/pcbnew/plotps.cpp index 835930200f..4781c40fd8 100644 --- a/pcbnew/plotps.cpp +++ b/pcbnew/plotps.cpp @@ -111,7 +111,7 @@ bool PCB_BASE_FRAME::ExportToPostScriptFile( const wxString& aFullFileName, int plotter->SetScaleAdjust( plotOpts.m_FineScaleAdjustX, plotOpts.m_FineScaleAdjustY ); plotter->SetPlotWidthAdj( plotOpts.m_FineWidthAdjust ); - plotter->SetViewport( offset, IU_PER_DECIMILS, scale, + plotter->SetViewport( offset, IU_PER_DECIMILS, scale, plotOpts.m_PlotMirror ); plotter->SetDefaultLineWidth( plotOpts.m_PlotLineWidth ); plotter->SetCreator( wxT( "PCBNEW-PS" ) ); @@ -121,7 +121,7 @@ bool PCB_BASE_FRAME::ExportToPostScriptFile( const wxString& aFullFileName, int /* The worksheet is not significant with scale!=1... It is with paperscale!=1, anyway */ if( plotOpts.m_PlotFrameRef && !center ) - PlotWorkSheet( plotter, GetScreen() ); + PlotWorkSheet( plotter, GetScreen(), plotOpts.GetPlotLineWidth() ); // If plot a negative board: // Draw a black rectangle (background for plot board in white) diff --git a/pcbnew/tool_modedit.cpp b/pcbnew/tool_modedit.cpp index 3c20eb7afd..afd11ddb98 100644 --- a/pcbnew/tool_modedit.cpp +++ b/pcbnew/tool_modedit.cpp @@ -1,9 +1,10 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2005 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2011 Wayne Stambaugh - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2012 Wayne Stambaugh + * Copyright (C) 1992-2012 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 diff --git a/pcbnew/tool_modview.cpp b/pcbnew/tool_modview.cpp index 3d0967caad..85237ce72c 100644 --- a/pcbnew/tool_modview.cpp +++ b/pcbnew/tool_modview.cpp @@ -1,9 +1,10 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2008-2011 Wayne Stambaugh - * Copyright (C) 2004-2011 KiCad Developers, see change_log.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2012 Wayne Stambaugh + * Copyright (C) 1992-2012 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 diff --git a/pcbnew/tool_onrightclick.cpp b/pcbnew/tool_onrightclick.cpp index dcdbadba12..0ec61d8d74 100644 --- a/pcbnew/tool_onrightclick.cpp +++ b/pcbnew/tool_onrightclick.cpp @@ -1,6 +1,31 @@ -/*************************/ -/* tool_onrightclick.cpp */ -/*************************/ +/** + * @file tool_onrightclick.cpp + */ + +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 1992-2012 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 + */ #include #include diff --git a/pcbnew/tool_pcb.cpp b/pcbnew/tool_pcb.cpp index f8f346594c..5d0c5a60d1 100644 --- a/pcbnew/tool_pcb.cpp +++ b/pcbnew/tool_pcb.cpp @@ -1,9 +1,10 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2005 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2011 Wayne Stambaugh - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2012 Wayne Stambaugh + * Copyright (C) 1992-2012 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 diff --git a/pcbnew/toolbars_update_user_interface.cpp b/pcbnew/toolbars_update_user_interface.cpp index a325d66711..ba8f651f29 100644 --- a/pcbnew/toolbars_update_user_interface.cpp +++ b/pcbnew/toolbars_update_user_interface.cpp @@ -1,9 +1,10 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2009 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2007-2011 Wayne Stambaugh - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2012 Wayne Stambaugh + * Copyright (C) 1992-2012 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 diff --git a/pcbnew/tr_modif.cpp b/pcbnew/tr_modif.cpp index 11eac8c990..2bfa2e5725 100644 --- a/pcbnew/tr_modif.cpp +++ b/pcbnew/tr_modif.cpp @@ -1,9 +1,10 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2006 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2011 Wayne Stambaugh - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2012 Wayne Stambaugh + * Copyright (C) 1992-2012 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 diff --git a/pcbnew/tracepcb.cpp b/pcbnew/tracepcb.cpp index f1c26eb47f..ec9e1a1c1d 100644 --- a/pcbnew/tracepcb.cpp +++ b/pcbnew/tracepcb.cpp @@ -1,9 +1,10 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2006 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2011 Wayne Stambaugh - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2012 Wayne Stambaugh + * Copyright (C) 1992-2012 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 diff --git a/pcbnew/work.cpp b/pcbnew/work.cpp deleted file mode 100644 index 3436fe3077..0000000000 --- a/pcbnew/work.cpp +++ /dev/null @@ -1,247 +0,0 @@ -/* - * This program source code file is part of KiCad, a free EDA CAD application. - * - * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2011 Wayne Stambaugh - * Copyright (C) 1992-2011 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 work.cpp - * @brief Automatic routing routines - */ - -#include -#include - -#include -#include -#include - - -struct CWORK /* a unit of work is a hole-pair to connect */ -{ - struct CWORK* Next; - int FromRow; /* source row */ - int FromCol; /* source column */ - int net_code; /* net_code */ - int ToRow; /* target row */ - int ToCol; /* target column */ - RATSNEST_ITEM* pt_rats; /* Corresponding ratsnest */ - int ApxDist; /* approximate distance */ - int Cost; /* cost for sort by length */ - int Priority; /* route priority */ -}; - - -/* pointers to the first and last item of work to do */ -static CWORK* Head = NULL; -static CWORK* Tail = NULL; -static CWORK* Current = NULL; - - -void InitWork(); -void ReInitWork(); -int SetWork( int, int, int, int, int, RATSNEST_ITEM*, int ); -void GetWork( int*, int*, int*, int*, int*, RATSNEST_ITEM** ); -void SortWork(); - - -/* initialize the work list */ -void InitWork() -{ - CWORK* ptr; - - while( ( ptr = Head ) != NULL ) - { - Head = ptr->Next; - delete ptr; - } - - Tail = Current = NULL; -} - - -/* initialize the work list */ -void ReInitWork() -{ - Current = Head; -} - - -/* add a unit of work to the work list - * Return: - * 1 if OK - * 0 if memory allocation failed - */ -static int GetCost( int r1, int c1, int r2, int c2 ); - -int SetWork( int r1, - int c1, - int n_c, - int r2, - int c2, - RATSNEST_ITEM* pt_ch, - int pri ) -{ - CWORK* p; - - if( ( p = (CWORK*) operator new( sizeof(CWORK), std::nothrow ) ) != NULL ) - { - p->FromRow = r1; - p->FromCol = c1; - p->net_code = n_c; - p->ToRow = r2; - p->ToCol = c2; - p->pt_rats = pt_ch; - p->ApxDist = GetApxDist( r1, c1, r2, c2 ); - p->Cost = GetCost( r1, c1, r2, c2 ); - p->Priority = pri; - p->Next = NULL; - - if( Head ) /* attach at end */ - - Tail->Next = p; - else /* first in list */ - Head = Current = p; - - Tail = p; - return 1; - } - else /* can't get any more memory */ - { - return 0; - } -} - - -/* fetch a unit of work from the work list */ -void GetWork( int* r1, - int* c1, - int* n_c, - int* r2, - int* c2, - RATSNEST_ITEM** pt_ch ) -{ - if( Current ) - { - *r1 = Current->FromRow; - *c1 = Current->FromCol; - *n_c = Current->net_code; - *r2 = Current->ToRow; - *c2 = Current->ToCol; - *pt_ch = Current->pt_rats; - Current = Current->Next; - } - else /* none left */ - { - *r1 = *c1 = *r2 = *c2 = ILLEGAL; - *n_c = 0; - *pt_ch = NULL; - } -} - - -/* order the work items; shortest (low cost) first */ -void SortWork() -{ - CWORK* p; - CWORK* q0; /* put PRIORITY PAD_CONNECTs in q0 */ - CWORK* q1; /* sort other PAD_CONNECTs in q1 */ - CWORK* r; - - q0 = q1 = NULL; - - while( (p = Head) != NULL ) /* prioritize each work item */ - { - Head = Head->Next; - - if( p->Priority ) /* put at end of priority list */ - { - p->Next = NULL; - - if( (r = q0) == NULL ) /* empty list? */ - { - q0 = p; - } - else /* attach at end */ - { - while( r->Next ) /* search for end */ - r = r->Next; - - r->Next = p; /* attach */ - } - } - else if( ( ( r = q1 ) == NULL ) || ( p->Cost < q1->Cost ) ) - { - p->Next = q1; - q1 = p; - } - else /* find proper position in list */ - { - while( r->Next && p->Cost >= r->Next->Cost ) - r = r->Next; - - p->Next = r->Next; - r->Next = p; - } - } - - if( (p = q0) != NULL ) /* any priority PAD_CONNECTs? */ - { - while( q0->Next ) - q0 = q0->Next; - - q0->Next = q1; - } - else - p = q1; - - /* reposition Head and Tail */ - for( Head = Current = Tail = p; Tail && Tail->Next; Tail = Tail->Next ) - ; -} - - -/* Calculate the cost of a net: - * cost = (| dx | + | dy |) * disability - * disability = 1 if dx or dy = 0, max if | dx | # | dy | - */ -static int GetCost( int r1, int c1, int r2, int c2 ) -{ - int dx, dy, mx, my; - float incl; - - dx = abs( c2 - c1 ); - dy = abs( r2 - r1 ); - incl = 1.0; - mx = dx; - my = dy; - - if( mx < my ) - { - mx = dy; my = dx; - } - - if( mx ) - incl += (2 * (float) my / mx); - - return (int) ( ( dx + dy ) * incl ); -} diff --git a/pcbnew/xchgmod.cpp b/pcbnew/xchgmod.cpp index f32fe805f9..3dd711c60f 100644 --- a/pcbnew/xchgmod.cpp +++ b/pcbnew/xchgmod.cpp @@ -2,6 +2,30 @@ * @file xchgmod.cpp */ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 1992-2012 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 + */ + #include #include #include @@ -15,7 +39,6 @@ #include #include -#include #include static char* quiet_gcc_4_4_3; // GCC 4.4.3 and next .. diff --git a/pcbnew/zone_filling_algorithm.cpp b/pcbnew/zone_filling_algorithm.cpp index 38e626c46c..aadd43472c 100644 --- a/pcbnew/zone_filling_algorithm.cpp +++ b/pcbnew/zone_filling_algorithm.cpp @@ -2,6 +2,29 @@ * @file zone_filling_algorithm.cpp: * Algorithms used to fill a zone defined by a polygon and a filling starting point. */ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 1992-2012 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 + */ #include // sort diff --git a/pcbnew/zones_by_polygon.cpp b/pcbnew/zones_by_polygon.cpp index b543640cb5..daf585f210 100644 --- a/pcbnew/zones_by_polygon.cpp +++ b/pcbnew/zones_by_polygon.cpp @@ -1,9 +1,10 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2007 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com - * Copyright (C) 2011 Wayne Stambaugh - * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2012 Wayne Stambaugh + * Copyright (C) 1992-2012 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 @@ -107,6 +108,53 @@ void PCB_EDIT_FRAME::Add_Zone_Cutout( wxDC* DC, ZONE_CONTAINER* aZone ) } +void PCB_EDIT_FRAME::duplicateZone( wxDC* aDC, ZONE_CONTAINER* aZone ) +{ + ZONE_CONTAINER* newZone = new ZONE_CONTAINER( GetBoard() ); + newZone->Copy( aZone ); + newZone->UnFill(); + ZONE_SETTINGS zoneSettings; + zoneSettings << *aZone; + + if( InvokeCopperZonesEditor( this, &zoneSettings ) ) + { + zoneSettings.ExportSetting( *newZone ); + newZone->m_Poly->Hatch(); + + _AuxiliaryList.ClearListAndDeleteItems(); + s_PickedList.ClearListAndDeleteItems(); + SaveCopyOfZones( s_PickedList, GetBoard(), newZone->GetNet(), newZone->GetLayer() ); + GetBoard()->Add( newZone ); + + ITEM_PICKER picker( newZone, UR_NEW ); + s_PickedList.PushItem( picker ); + + GetScreen()->SetCurItem( NULL ); // This outline may be deleted when merging outlines + + // Combine zones if possible + GetBoard()->AreaPolygonModified( &_AuxiliaryList, newZone, true, s_Verbose ); + + // Redraw zones + GetBoard()->RedrawAreasOutlines( m_canvas, aDC, GR_OR, newZone->GetLayer() ); + GetBoard()->RedrawFilledAreas( m_canvas, aDC, GR_OR, newZone->GetLayer() ); + + if( GetBoard()->GetAreaIndex( newZone ) >= 0 + && GetBoard()->Test_Drc_Areas_Outlines_To_Areas_Outlines( newZone, true ) ) + { + DisplayError( this, _( "Duplicate Zone: The outline of the duplicated zone fails DRC check!" ) ); + } + + UpdateCopyOfZonesList( s_PickedList, _AuxiliaryList, GetBoard() ); + SaveCopyInUndoList( s_PickedList, UR_UNSPECIFIED ); + s_PickedList.ClearItemsList(); + + OnModify(); + } + else + delete newZone; +} + + int PCB_EDIT_FRAME::Delete_LastCreatedCorner( wxDC* DC ) { ZONE_CONTAINER* zone = GetBoard()->m_CurrentZoneContour; diff --git a/pcbnew/zones_convert_brd_items_to_polygons_with_Boost.cpp b/pcbnew/zones_convert_brd_items_to_polygons_with_Boost.cpp index f844b5a6a4..20edbff31d 100644 --- a/pcbnew/zones_convert_brd_items_to_polygons_with_Boost.cpp +++ b/pcbnew/zones_convert_brd_items_to_polygons_with_Boost.cpp @@ -1,6 +1,29 @@ /** * @file zones_convert_brd_items_to_polygons_with_Boost.cpp */ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 1992-2012 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 + */ /* Functions to convert some board items to polygons * (pads, tracks ..) diff --git a/pcbnew/zones_convert_to_polygons_aux_functions.cpp b/pcbnew/zones_convert_to_polygons_aux_functions.cpp index f65a296d68..8b3376fe63 100644 --- a/pcbnew/zones_convert_to_polygons_aux_functions.cpp +++ b/pcbnew/zones_convert_to_polygons_aux_functions.cpp @@ -2,6 +2,30 @@ * @file zones_convert_to_polygons_aux_functions.cpp */ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 1992-2012 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 + */ + #include #include #include diff --git a/pcbnew/zones_polygons_insulated_copper_islands.cpp b/pcbnew/zones_polygons_insulated_copper_islands.cpp index f0f81e1ca0..d0a0d09970 100644 --- a/pcbnew/zones_polygons_insulated_copper_islands.cpp +++ b/pcbnew/zones_polygons_insulated_copper_islands.cpp @@ -1,8 +1,29 @@ /** * @file zones_polygons_insulated_copper_islands.cpp */ - -using namespace std; +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 1992-2012 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 + */ #include #include diff --git a/pcbnew/zones_polygons_test_connections.cpp b/pcbnew/zones_polygons_test_connections.cpp index 91b4695717..5ee92ff48e 100644 --- a/pcbnew/zones_polygons_test_connections.cpp +++ b/pcbnew/zones_polygons_test_connections.cpp @@ -2,7 +2,29 @@ * @file zones_polygons_test_connections.cpp */ -using namespace std; +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 1992-2012 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 + */ #include // sort diff --git a/pcbnew/zones_test_and_combine_areas.cpp b/pcbnew/zones_test_and_combine_areas.cpp index c9b1bf5fc0..b22ea9c4a2 100644 --- a/pcbnew/zones_test_and_combine_areas.cpp +++ b/pcbnew/zones_test_and_combine_areas.cpp @@ -4,6 +4,32 @@ * some pieces of code come from FreePCB. */ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr + * Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors. + * + * Some code comes from FreePCB. + * + * 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 + */ + #include #include #include diff --git a/polygon/PolyLine.h b/polygon/PolyLine.h index 3aa6ba60f3..2a6ac81220 100644 --- a/polygon/PolyLine.h +++ b/polygon/PolyLine.h @@ -88,8 +88,20 @@ public: class CPolyPt : public wxPoint { public: - CPolyPt( int qx = 0, int qy = 0, bool qf = false, int aUtility = 0 ) - { x = qx; y = qy; end_contour = qf; utility = aUtility; }; + CPolyPt( int aX = 0, int aY = 0, bool aEnd = false, int aUtility = 0 ) : + wxPoint( aX, aY ), end_contour( aEnd ), utility( aUtility ) + {} + + /// Pure copy constructor is here to dis-ambiguate from the + /// specialized CPolyPt( const wxPoint& ) constructor version below. + CPolyPt( const CPolyPt& aPt ) : + wxPoint( aPt.x, aPt.y ), end_contour( aPt.end_contour ), utility( aPt.utility ) + {} + + CPolyPt( const wxPoint& aPoint ) : + wxPoint( aPoint ), end_contour( false ), utility( 0 ) + {} + bool end_contour; int utility; @@ -159,6 +171,7 @@ public: void AppendArc( int xi, int yi, int xf, int yf, int xc, int yc, int num ); // access functions + void SetLayer( int aLayer ) { m_layer = aLayer; } int GetLayer() { return m_layer; } int GetNumCorners(); int GetNumSides();