Add Gerber job file writer in Pcbnew, and a basic reader in Gerbview. Currently disabled

Fix also very minor issues in Gerbview
This commit is contained in:
jean-pierre charras 2017-08-19 18:28:11 +02:00
parent 2e4c22f718
commit 50164e9968
30 changed files with 2134 additions and 78 deletions

View File

@ -238,6 +238,7 @@ set( BMAPS_MID
gbr_select_mode1
gbr_select_mode2
gerber_file
gerber_job_file
gerbview_show_negative_objects
gerbview_drill_file
gerbview_clear_layers

View File

@ -0,0 +1,146 @@
/* Do not modify this file, it was automatically generated by the
* PNG2cpp CMake script, using a *.png file as input.
*/
#include <bitmaps.h>
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, 0x08, 0x14, 0x49, 0x44, 0x41, 0x54, 0x48, 0xc7, 0xad, 0x56, 0x69, 0x6c, 0x53,
0xe9, 0x15, 0x35, 0x23, 0xa6, 0xaa, 0xda, 0x8a, 0xf9, 0x53, 0xca, 0x08, 0x5a, 0x44, 0x01, 0x01,
0x1a, 0x60, 0x40, 0x45, 0x2c, 0x65, 0xdf, 0x09, 0x61, 0x11, 0xbb, 0x10, 0xc3, 0xbe, 0xa9, 0x02,
0x04, 0xc3, 0x0f, 0x98, 0x16, 0x04, 0x65, 0x08, 0x59, 0x86, 0x84, 0x6c, 0x10, 0xb2, 0x2f, 0x64,
0x71, 0x20, 0x21, 0x8b, 0x1d, 0x12, 0x48, 0x1c, 0x27, 0x71, 0x56, 0xc7, 0xf6, 0xb3, 0x1d, 0xe3,
0x2d, 0x89, 0x63, 0x27, 0x4e, 0xf2, 0xfc, 0xbc, 0xc7, 0x8e, 0xf7, 0xed, 0xf6, 0x1a, 0x01, 0x22,
0x4c, 0xa7, 0x6a, 0xa5, 0x3e, 0xe9, 0xca, 0x7e, 0xcf, 0xcf, 0xf7, 0x7c, 0xf7, 0xdc, 0xf3, 0x9d,
0xfb, 0xd1, 0x68, 0x9f, 0x5d, 0xa7, 0x4f, 0x9f, 0x3e, 0x7c, 0xee, 0xdc, 0xb9, 0x98, 0x43, 0x87,
0x0e, 0xed, 0xde, 0xb3, 0x67, 0xcf, 0xef, 0xc3, 0xcf, 0x2e, 0x5e, 0xbc, 0xf8, 0xe5, 0xb1, 0x63,
0xc7, 0xfe, 0x79, 0xf8, 0xf0, 0xe1, 0x5d, 0x78, 0x3b, 0x89, 0xf6, 0xff, 0xb8, 0xb2, 0xb3, 0xb3,
0xe9, 0x81, 0x40, 0xe0, 0xe5, 0xd0, 0xd0, 0x10, 0x83, 0xcd, 0x66, 0x33, 0x93, 0x92, 0x92, 0xe8,
0x17, 0x2e, 0x5c, 0x28, 0x2b, 0x2d, 0x2d, 0x65, 0x0b, 0x44, 0xe2, 0xa6, 0x2a, 0x76, 0x87, 0x92,
0x23, 0xe9, 0x1f, 0xe0, 0xf6, 0x0e, 0xa9, 0xdb, 0xa4, 0x1a, 0x2e, 0x5b, 0xa4, 0xbe, 0xdd, 0xd3,
0xd3, 0xf3, 0xdb, 0xff, 0x09, 0x64, 0xdb, 0xb6, 0x6d, 0xd3, 0x3b, 0x3b, 0x3b, 0xab, 0x83, 0xc1,
0x60, 0xf4, 0xa9, 0x53, 0xa7, 0xca, 0x32, 0x32, 0x32, 0xf2, 0x48, 0x92, 0xcc, 0x31, 0x1a, 0x8d,
0x5c, 0xa2, 0x4f, 0x63, 0x6d, 0x93, 0x0f, 0x07, 0x98, 0x6f, 0x8d, 0xde, 0x8c, 0x36, 0xd2, 0xf9,
0x53, 0x9d, 0xca, 0x92, 0xd6, 0xae, 0xeb, 0xaf, 0x14, 0x92, 0x64, 0x13, 0xa1, 0xb4, 0xd6, 0x75,
0x29, 0xa2, 0xff, 0x6b, 0xa0, 0x03, 0x07, 0x0e, 0xec, 0x1d, 0x1e, 0x1e, 0xae, 0x1c, 0x1b, 0x1b,
0x8b, 0xb9, 0x73, 0xe7, 0xce, 0xb3, 0xb8, 0xb8, 0xb8, 0xbc, 0xe3, 0xc7, 0x8f, 0xb3, 0x1b, 0xba,
0x04, 0xae, 0x57, 0x52, 0x8b, 0xb7, 0x90, 0xb0, 0x8e, 0xd1, 0x25, 0xe3, 0x26, 0x46, 0x9f, 0xcf,
0x58, 0xdb, 0xe7, 0x35, 0x57, 0x4a, 0xac, 0xa6, 0xd4, 0x86, 0xbe, 0xd1, 0x18, 0xc6, 0x5b, 0x75,
0x45, 0xbb, 0x72, 0xbc, 0xec, 0x4d, 0x47, 0xdb, 0x2f, 0x52, 0x8b, 0x2b, 0xdf, 0x8e, 0x91, 0x18,
0x8e, 0x13, 0x27, 0x4e, 0xbc, 0x8e, 0x8d, 0x8d, 0x6d, 0xbd, 0x7c, 0xf9, 0x72, 0xd3, 0xc6, 0x8d,
0x1b, 0x85, 0x5b, 0xb7, 0x6e, 0x25, 0x52, 0xb2, 0x0a, 0x8c, 0x15, 0xbc, 0x41, 0x7f, 0x42, 0x5d,
0xaf, 0x35, 0xea, 0x25, 0xdf, 0x9a, 0x58, 0x27, 0x37, 0xff, 0x54, 0xc9, 0x33, 0x3d, 0xae, 0x93,
0x18, 0x32, 0x58, 0x32, 0x7d, 0x26, 0x4b, 0x66, 0xcc, 0x6e, 0x56, 0x19, 0xca, 0xc5, 0x66, 0xaa,
0xba, 0x43, 0xea, 0x2d, 0x78, 0x51, 0x23, 0x39, 0x72, 0xe4, 0xc8, 0x8e, 0x9f, 0x01, 0x61, 0xe2,
0x4c, 0x00, 0x60, 0x62, 0x54, 0xda, 0x6c, 0xb6, 0x2e, 0xfc, 0xec, 0xd4, 0xe9, 0x74, 0x3c, 0xb9,
0x5c, 0x2e, 0x92, 0xc9, 0x64, 0xe2, 0x66, 0x81, 0xd4, 0x5f, 0x22, 0xf7, 0xdb, 0x6a, 0x94, 0x4e,
0xf3, 0x2b, 0xac, 0xe2, 0x75, 0xaf, 0xd3, 0xd0, 0xa2, 0xf1, 0xe8, 0x39, 0x6a, 0x97, 0xbe, 0x93,
0x0c, 0x91, 0xdd, 0x64, 0x80, 0x2a, 0x69, 0x55, 0x91, 0xcd, 0x1a, 0x2f, 0xc9, 0x90, 0x98, 0xf5,
0x95, 0xac, 0x0e, 0x1f, 0xb2, 0x70, 0xeb, 0x67, 0x40, 0x8f, 0x1e, 0x3d, 0xca, 0xc2, 0xe4, 0x65,
0x7c, 0x3e, 0xbf, 0xbe, 0xb2, 0xb2, 0x92, 0xa8, 0xa9, 0xa9, 0xe1, 0x15, 0x15, 0x15, 0x09, 0xbb,
0xbb, 0xbb, 0x45, 0x95, 0xd5, 0x0c, 0x55, 0x0d, 0x5f, 0xe5, 0xa7, 0xf7, 0xd8, 0xcd, 0xa5, 0x7c,
0xca, 0xdc, 0xa8, 0x72, 0x53, 0x6f, 0x14, 0x76, 0xea, 0xf5, 0x5b, 0xa3, 0xbe, 0x51, 0x6e, 0xa6,
0x08, 0x0a, 0x46, 0xba, 0x87, 0xdd, 0xba, 0xf2, 0x2e, 0xd5, 0x28, 0xbb, 0x6f, 0x4c, 0xc5, 0xd5,
0x81, 0xb6, 0x8a, 0x23, 0xf1, 0xfe, 0x18, 0x9b, 0x28, 0xde, 0xbb, 0x77, 0xef, 0xa6, 0x7f, 0x0b,
0xd4, 0xda, 0xda, 0xda, 0x5c, 0x5c, 0x5c, 0x4c, 0x60, 0x08, 0x58, 0x2c, 0x16, 0x91, 0x9f, 0x9f,
0x2f, 0x62, 0xd6, 0xb1, 0x46, 0x2a, 0xb8, 0x6a, 0x1f, 0x5d, 0x64, 0x35, 0x96, 0xf0, 0x74, 0x06,
0xa6, 0x58, 0xa7, 0x67, 0xf7, 0xda, 0x75, 0x0c, 0x62, 0x84, 0xac, 0x97, 0x19, 0x48, 0x99, 0x09,
0x74, 0xfc, 0x21, 0x87, 0xae, 0x49, 0x4a, 0x92, 0xcd, 0x32, 0x72, 0x58, 0x6e, 0x01, 0x75, 0x6d,
0x97, 0xd2, 0x51, 0xf5, 0x8a, 0x33, 0x24, 0x91, 0x48, 0x18, 0x97, 0x2e, 0x5d, 0xca, 0xda, 0xbe,
0x7d, 0xfb, 0x82, 0x09, 0x40, 0x74, 0x3a, 0xbd, 0xfb, 0xc1, 0x83, 0x07, 0xa2, 0x70, 0x24, 0x24,
0x24, 0x88, 0x1a, 0x1a, 0x1a, 0x44, 0x79, 0x05, 0x25, 0x5a, 0x46, 0xb7, 0xca, 0x97, 0xcd, 0x19,
0x34, 0xbe, 0xe9, 0x75, 0xea, 0x0b, 0x5b, 0x94, 0x64, 0xe7, 0xa0, 0x83, 0x6a, 0x94, 0x51, 0xba,
0x6e, 0xb5, 0xd5, 0xa0, 0xb2, 0x81, 0x4e, 0x42, 0x3a, 0x0c, 0xbc, 0x7e, 0xca, 0xc0, 0x57, 0xe9,
0x75, 0xda, 0x71, 0x18, 0xae, 0xe7, 0xca, 0xc6, 0x53, 0x33, 0x8a, 0x75, 0x98, 0x33, 0xce, 0xeb,
0xf5, 0xd2, 0x1b, 0x1b, 0x1b, 0xab, 0x4e, 0x9e, 0x3c, 0x79, 0xe5, 0x53, 0x20, 0xfe, 0x07, 0xa0,
0x70, 0x20, 0x8d, 0xa2, 0xec, 0xec, 0x5c, 0x45, 0x75, 0x13, 0xdf, 0x97, 0xdf, 0xa1, 0x35, 0xd7,
0xf7, 0xda, 0xf5, 0xc5, 0x2d, 0x0a, 0xb2, 0xb5, 0xcf, 0x4a, 0xb2, 0x24, 0x5a, 0xaa, 0x67, 0xc4,
0xae, 0x1f, 0x1a, 0x0b, 0x18, 0x35, 0x66, 0xb7, 0x49, 0xaa, 0x35, 0x99, 0xe5, 0xc3, 0x46, 0xa3,
0xc1, 0x05, 0xd4, 0xab, 0x66, 0x9e, 0x3b, 0x25, 0xed, 0x99, 0x02, 0x73, 0x46, 0x85, 0x03, 0xf7,
0x24, 0xfd, 0xea, 0xd5, 0xab, 0xc9, 0x1f, 0x81, 0x9e, 0x3f, 0x7f, 0x4e, 0x7c, 0x0e, 0x54, 0x52,
0x52, 0xd2, 0x53, 0x5a, 0xd1, 0xe0, 0x2e, 0xe7, 0x0e, 0x39, 0x9b, 0x07, 0xdc, 0x86, 0x12, 0x8e,
0x9c, 0xec, 0xa1, 0x3c, 0x54, 0xbb, 0x7c, 0xc4, 0x20, 0x1f, 0xb5, 0x99, 0x06, 0x4d, 0x4e, 0xcb,
0x88, 0xd5, 0x65, 0xd5, 0xe8, 0xad, 0x63, 0xa4, 0xcd, 0x65, 0x32, 0x3a, 0xfd, 0x96, 0x82, 0x12,
0x86, 0x5f, 0x22, 0x51, 0x64, 0xbd, 0x07, 0x8a, 0xc3, 0x5e, 0x57, 0xef, 0xda, 0xb5, 0x6b, 0x19,
0x2d, 0x3e, 0x3e, 0x3e, 0x0b, 0x4b, 0xac, 0x2a, 0x2b, 0x2b, 0x9b, 0x00, 0x84, 0x96, 0x43, 0xae,
0x58, 0xb1, 0xc2, 0xbb, 0x62, 0xc5, 0x4a, 0x77, 0xe1, 0xcb, 0x06, 0x5f, 0x39, 0x31, 0x6c, 0x29,
0x66, 0xf7, 0x50, 0xe8, 0x04, 0x86, 0x16, 0x91, 0xca, 0x24, 0xd7, 0x9a, 0x2c, 0xc3, 0x16, 0xa7,
0x8d, 0xb2, 0x7b, 0xc6, 0x47, 0x4c, 0x63, 0x0e, 0x9b, 0x2f, 0x64, 0x15, 0x2a, 0x06, 0x3c, 0x09,
0x49, 0xd9, 0xf6, 0x4f, 0xaa, 0x29, 0xba, 0x76, 0xed, 0xda, 0xd3, 0x77, 0x3d, 0x0a, 0x03, 0x8d,
0x8f, 0x8f, 0xbf, 0x89, 0x89, 0x89, 0x21, 0x66, 0xce, 0x9c, 0xa9, 0x99, 0x3a, 0x75, 0xaa, 0x68,
0xfa, 0xf4, 0xe9, 0xa2, 0xc5, 0x8b, 0x17, 0xdb, 0x9b, 0x9a, 0x9a, 0x60, 0xf7, 0xee, 0xdd, 0xde,
0xb8, 0xf8, 0x64, 0xb2, 0x94, 0xc9, 0xf1, 0xde, 0x4f, 0xcd, 0x77, 0x70, 0x7a, 0x06, 0xcc, 0xdd,
0x0a, 0xad, 0x59, 0x3e, 0xa8, 0x1f, 0x1b, 0x35, 0xdb, 0xc7, 0xcd, 0x2e, 0xaf, 0x53, 0x6f, 0x73,
0xb8, 0x65, 0xaa, 0x41, 0x5f, 0x52, 0x72, 0x6e, 0x40, 0x2e, 0x55, 0x3c, 0xf9, 0x50, 0x0d, 0x97,
0xcb, 0xad, 0xde, 0xb1, 0x63, 0xc7, 0x5f, 0x3e, 0x02, 0xa1, 0xaf, 0xb1, 0x30, 0xb1, 0x75, 0xe7,
0xce, 0x9d, 0xa1, 0x69, 0xd3, 0xa6, 0x39, 0x10, 0xcc, 0xba, 0x7a, 0xf5, 0x6a, 0xbf, 0x42, 0xa1,
0x80, 0x1b, 0x37, 0x6e, 0x04, 0x67, 0xcd, 0x9a, 0xe5, 0x8a, 0x88, 0x88, 0x74, 0x1d, 0x3f, 0x7e,
0x22, 0xb4, 0x71, 0xd3, 0xe6, 0x50, 0x15, 0xab, 0xdd, 0xd5, 0x37, 0xa2, 0xc7, 0x4a, 0x6c, 0xce,
0x1e, 0xa5, 0xda, 0xf7, 0xa2, 0xe2, 0x75, 0x30, 0x39, 0x29, 0x27, 0xf0, 0x30, 0x3e, 0xd5, 0xfa,
0x69, 0x35, 0x57, 0xae, 0x5c, 0x49, 0xfb, 0x28, 0xef, 0x30, 0xd0, 0xe8, 0xe8, 0x28, 0x67, 0xc1,
0x82, 0x05, 0x4e, 0x14, 0x04, 0xe4, 0xe5, 0xe5, 0x41, 0x6e, 0x6e, 0x2e, 0xf4, 0xf7, 0xf7, 0x83,
0xd9, 0x6c, 0x06, 0xac, 0x16, 0x04, 0x02, 0x01, 0x20, 0xb5, 0xa0, 0x56, 0xab, 0x61, 0xeb, 0xd6,
0x6d, 0x81, 0x9b, 0x3f, 0x44, 0xd9, 0x1f, 0x26, 0x64, 0xb9, 0x1f, 0x25, 0xe6, 0xba, 0xd3, 0x9e,
0x3e, 0x73, 0x77, 0xf0, 0x44, 0xa1, 0x86, 0xa6, 0x8e, 0xe0, 0xcd, 0xbf, 0xff, 0x68, 0x44, 0x9f,
0xfc, 0xb4, 0x9a, 0x25, 0x1f, 0x81, 0xd0, 0xcf, 0x72, 0x4c, 0x26, 0x53, 0xe7, 0xe6, 0xcd, 0x9b,
0x25, 0x68, 0x3b, 0x01, 0x8d, 0x46, 0x03, 0x14, 0x45, 0x01, 0x1a, 0x29, 0x84, 0x2b, 0x0a, 0x7f,
0x47, 0xef, 0x03, 0x7c, 0x07, 0xf0, 0x5d, 0x38, 0x7a, 0xf4, 0x28, 0x85, 0x8e, 0x21, 0x40, 0xaa,
0x45, 0xa9, 0xa9, 0xa9, 0x04, 0x93, 0x59, 0xab, 0x2c, 0x2a, 0x29, 0x1f, 0x7b, 0xdb, 0xd7, 0x0f,
0x8f, 0xd3, 0x0a, 0xfc, 0xaf, 0xd3, 0x4e, 0x6a, 0x2c, 0xfc, 0x64, 0xce, 0x84, 0x6a, 0xc2, 0x57,
0x54, 0x54, 0xd4, 0x73, 0xa7, 0xd3, 0xd9, 0xb5, 0x72, 0xe5, 0xca, 0x91, 0x87, 0x0f, 0x1f, 0x86,
0xc2, 0x00, 0x62, 0xb1, 0x18, 0xd6, 0xac, 0x59, 0xe3, 0x5b, 0xb6, 0x6c, 0xd9, 0xf8, 0xaa, 0x55,
0xab, 0x3c, 0x4f, 0x9f, 0x3e, 0x0d, 0xa2, 0x2d, 0x41, 0x73, 0x73, 0x33, 0xe0, 0xbd, 0xf3, 0xc9,
0x93, 0x27, 0x02, 0x9c, 0x59, 0x42, 0x1c, 0x21, 0x04, 0x2e, 0xa4, 0xbb, 0xae, 0xae, 0x8e, 0x68,
0x62, 0xa4, 0x85, 0x94, 0xa5, 0x11, 0x60, 0xab, 0x58, 0x0c, 0xaa, 0xb8, 0x5f, 0x05, 0xff, 0x76,
0x60, 0xe9, 0x9a, 0x09, 0x40, 0xfb, 0xf6, 0xed, 0x93, 0x61, 0x35, 0x2e, 0x4c, 0xec, 0x57, 0x2a,
0x95, 0xe0, 0x72, 0xb9, 0x00, 0x4d, 0xd1, 0x3f, 0x7f, 0xfe, 0x7c, 0xf9, 0xd2, 0xa5, 0x4b, 0x85,
0x6d, 0x6d, 0x6d, 0xc4, 0xdc, 0xb9, 0x73, 0xdd, 0x58, 0x05, 0xa0, 0xff, 0xc1, 0xf5, 0xeb, 0xd7,
0x43, 0xcb, 0x97, 0x2f, 0xf7, 0xcd, 0x9e, 0x3d, 0xdb, 0x81, 0x8b, 0x14, 0x22, 0xbd, 0xbc, 0x97,
0x39, 0x51, 0x7d, 0x03, 0xa5, 0xab, 0x01, 0x82, 0x1e, 0x00, 0xe9, 0x35, 0xb0, 0xe7, 0xff, 0x11,
0xa4, 0xb1, 0xb4, 0xec, 0x09, 0x40, 0x6b, 0xd7, 0xae, 0xa5, 0x6a, 0x6b, 0x6b, 0x01, 0xfb, 0x04,
0x1e, 0x8f, 0x07, 0x1c, 0x0e, 0x07, 0x60, 0x75, 0x5e, 0x4c, 0x26, 0x8c, 0x88, 0x88, 0x20, 0xec,
0x76, 0x7b, 0x07, 0x82, 0x5a, 0x98, 0x4c, 0xe6, 0xbb, 0x5e, 0x85, 0xdf, 0xcd, 0xca, 0xca, 0x82,
0x6f, 0xbe, 0xf9, 0xc6, 0x8b, 0xcf, 0x78, 0xb8, 0x10, 0x11, 0x83, 0xc1, 0x10, 0x97, 0xdd, 0xfa,
0xf3, 0xb8, 0x47, 0x5d, 0x04, 0x60, 0xe6, 0x40, 0x80, 0xb3, 0x0d, 0xb4, 0xb1, 0x5f, 0x84, 0x88,
0x68, 0xda, 0xb7, 0x1f, 0x81, 0x70, 0xbf, 0xb0, 0xb6, 0x6c, 0xd9, 0x62, 0x42, 0x9a, 0x7c, 0x2a,
0x95, 0x0a, 0xac, 0x56, 0x2b, 0xe0, 0x38, 0x0f, 0xe0, 0x6c, 0xea, 0xc7, 0x7d, 0x24, 0x44, 0xfb,
0x10, 0x63, 0x52, 0x0f, 0x87, 0xc3, 0x81, 0x96, 0x96, 0x16, 0xd8, 0xb0, 0x61, 0x83, 0x7f, 0xde,
0xbc, 0x79, 0x36, 0x64, 0x60, 0xf4, 0xe0, 0xc1, 0x83, 0xc2, 0xfa, 0xfa, 0x7a, 0x02, 0xed, 0x4a,
0x78, 0xff, 0xf6, 0xf7, 0x75, 0x8a, 0xdc, 0x45, 0x81, 0xa0, 0x9b, 0x04, 0x50, 0xc5, 0x83, 0xbb,
0x7c, 0x21, 0x48, 0xee, 0xd1, 0xe4, 0x00, 0xef, 0xe7, 0x13, 0x36, 0x38, 0xbc, 0x8b, 0x33, 0xce,
0x9c, 0x39, 0xd3, 0x9a, 0x98, 0x98, 0x18, 0xd4, 0xeb, 0xf5, 0x20, 0x95, 0x4a, 0x01, 0xa5, 0xee,
0xc3, 0x7e, 0x38, 0xc2, 0xbd, 0x4a, 0x49, 0x49, 0x81, 0xf0, 0x9e, 0x42, 0xa3, 0x85, 0x25, 0x4b,
0x96, 0x38, 0xb0, 0x02, 0x1e, 0x3a, 0x07, 0x0f, 0x9d, 0x83, 0x87, 0x63, 0x9c, 0x8f, 0x3d, 0x12,
0xa2, 0x29, 0xa7, 0x97, 0x3e, 0x88, 0xec, 0xb3, 0x70, 0x6f, 0x02, 0x38, 0x07, 0x00, 0x04, 0x87,
0xc0, 0x90, 0x32, 0x05, 0xba, 0xee, 0xd0, 0x4e, 0x4f, 0x00, 0xc2, 0x86, 0x17, 0x44, 0x46, 0x46,
0x7a, 0x70, 0x4f, 0xbd, 0x93, 0x71, 0xb8, 0x27, 0x38, 0xd6, 0xa1, 0xbd, 0xbd, 0x1d, 0xd0, 0xcd,
0x21, 0x4c, 0x1d, 0xbe, 0x03, 0x48, 0xa9, 0x13, 0xcf, 0x15, 0x44, 0x41, 0x41, 0x01, 0x51, 0x58,
0x58, 0x48, 0x68, 0xb5, 0x5a, 0x1e, 0xfe, 0x46, 0xa0, 0x88, 0xe8, 0xdf, 0x7d, 0x77, 0x2c, 0xbf,
0xe5, 0xfe, 0x57, 0x5a, 0xbf, 0xb1, 0x13, 0x60, 0x94, 0x0e, 0xbe, 0xba, 0x55, 0xf0, 0xf6, 0xee,
0x24, 0x27, 0xeb, 0x07, 0xda, 0x57, 0x34, 0xb4, 0x9b, 0x4c, 0xbf, 0xdf, 0x5f, 0x8e, 0x94, 0x58,
0x90, 0x82, 0x77, 0xc9, 0xd2, 0xd3, 0xd3, 0xdf, 0xd1, 0x14, 0xa6, 0x0b, 0x57, 0x0b, 0x99, 0x99,
0x99, 0x80, 0x54, 0x06, 0xd2, 0xd2, 0xd2, 0xe0, 0xec, 0xd9, 0xb3, 0xc1, 0xe8, 0xe8, 0xe8, 0x21,
0xac, 0x9c, 0x8b, 0x63, 0x9f, 0x87, 0xbd, 0x25, 0x5e, 0xbc, 0x78, 0x21, 0x08, 0x1f, 0x64, 0xd6,
0xad, 0x5b, 0xf7, 0xed, 0x95, 0xcd, 0xb4, 0xc3, 0x83, 0xd5, 0x91, 0x21, 0x08, 0x7a, 0x51, 0x18,
0xdf, 0x03, 0x95, 0xfe, 0x35, 0xd4, 0xdc, 0x9c, 0xf2, 0x88, 0x86, 0x0a, 0xdb, 0x87, 0x52, 0x4d,
0x43, 0x85, 0xa9, 0x71, 0x74, 0x7b, 0x17, 0x2e, 0x5c, 0x38, 0xb8, 0x68, 0xd1, 0x22, 0x35, 0x86,
0x2b, 0x27, 0x27, 0x07, 0xce, 0x9f, 0x3f, 0x1f, 0x98, 0x33, 0x67, 0x8e, 0x09, 0x05, 0xc2, 0x42,
0xf5, 0x99, 0x71, 0x63, 0xdb, 0xf7, 0xef, 0xdf, 0xcf, 0x46, 0x47, 0xee, 0x42, 0xd5, 0xb5, 0xdf,
0xbd, 0x7b, 0xb7, 0x11, 0x29, 0x6f, 0xc4, 0x93, 0xd2, 0x87, 0x7d, 0xf3, 0x1b, 0xfa, 0xa5, 0x49,
0x0d, 0x63, 0x92, 0xc7, 0x20, 0x29, 0x3f, 0x0f, 0x65, 0x09, 0x27, 0xe1, 0xf6, 0x3f, 0x6e, 0x5e,
0xfd, 0x54, 0x80, 0x93, 0x26, 0x4f, 0x9e, 0xfc, 0xd7, 0x0f, 0x37, 0x33, 0x66, 0xcc, 0xb8, 0x8f,
0x49, 0x00, 0x55, 0xa9, 0xc3, 0xdb, 0xdf, 0xbd, 0x7f, 0xfc, 0x25, 0xc6, 0xb4, 0xf0, 0x17, 0xa4,
0xf0, 0x4f, 0x28, 0xa4, 0x64, 0xec, 0x4d, 0x35, 0x0a, 0xa2, 0x6a, 0xfd, 0xfa, 0xf5, 0x8b, 0x3f,
0xfc, 0x37, 0x72, 0x21, 0x6d, 0x69, 0xc1, 0xad, 0x4d, 0xdd, 0xed, 0x1d, 0x1c, 0x6f, 0x7a, 0x46,
0xde, 0xc8, 0xbd, 0x7b, 0xf7, 0xa6, 0xfc, 0xe2, 0x89, 0x08, 0x41, 0xd7, 0xa1, 0xc9, 0x92, 0x68,
0xb0, 0xe2, 0xff, 0x74, 0x72, 0xc2, 0x85, 0x2c, 0x41, 0xe1, 0xec, 0xfb, 0xec, 0xf1, 0x17, 0x18,
0xbf, 0xc6, 0xf8, 0xc3, 0xfb, 0x4f, 0xda, 0xbf, 0x00, 0xbc, 0x29, 0xf9, 0xf3, 0xe7, 0x0e, 0xc6,
0x86, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82,
};
const BITMAP_OPAQUE gerber_job_file_xpm[1] = {{ png, sizeof( png ), "gerber_job_file_xpm" }};
//EOF

View File

@ -0,0 +1,818 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
height="26"
width="26"
version="1.1"
id="svg2"
inkscape:version="0.92.0 r15299"
sodipodi:docname="gerber_job_file.svg">
<metadata
id="metadata172">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1170"
inkscape:window-height="836"
id="namedview170"
showgrid="true"
inkscape:zoom="9.3622609"
inkscape:cx="13.030913"
inkscape:cy="4.5453342"
inkscape:window-x="413"
inkscape:window-y="162"
inkscape:window-maximized="0"
inkscape:current-layer="svg2"
showguides="false">
<inkscape:grid
type="xygrid"
id="grid3100"
empspacing="5"
visible="true"
enabled="true"
snapvisiblegridlinesonly="true"
originx="0"
originy="0"
spacingx="1.0666667"
spacingy="1.0666667" />
</sodipodi:namedview>
<defs
id="defs4">
<linearGradient
id="ab"
y2="4.2192998"
gradientUnits="userSpaceOnUse"
x2="7.5955"
gradientTransform="matrix(0.88924,0,0,0.78227,0.62292,7.6472)"
y1="43.993999"
x1="40.751999">
<stop
stop-color="#333"
offset="0"
id="stop7" />
<stop
stop-color="#474747"
offset="1"
id="stop9" />
</linearGradient>
<linearGradient
id="a"
y2="19500"
gradientUnits="userSpaceOnUse"
x2="15000"
y1="14100"
x1="10100">
<stop
stop-color="#f5fffa"
offset="0"
id="stop12" />
<stop
stop-color="#6f6d7f"
offset="1.2"
id="stop14" />
</linearGradient>
<linearGradient
id="b"
y2="19500"
gradientUnits="userSpaceOnUse"
x2="15000"
y1="14100"
x1="10100">
<stop
stop-color="#fff"
stop-opacity="0.698"
offset="0"
id="stop17" />
<stop
stop-color="#5db7ff"
stop-opacity="0.698"
offset="1.2"
id="stop19" />
</linearGradient>
<linearGradient
id="x"
y2="19500"
gradientUnits="userSpaceOnUse"
x2="15000"
y1="14100"
x1="10100">
<stop
stop-color="#f5ffff"
offset="0"
id="stop22" />
<stop
stop-color="#fff"
stop-opacity="0"
offset="1.2"
id="stop24" />
</linearGradient>
<radialGradient
id="ac"
xlink:href="#b"
gradientUnits="userSpaceOnUse"
cy="17526"
cx="18632"
gradientTransform="matrix(0.00205653,0,0,0.00205653,35.864533,-12.1536)"
r="40170" />
<radialGradient
id="ad"
xlink:href="#b"
gradientUnits="userSpaceOnUse"
cy="17831"
cx="18969"
r="23166"
gradientTransform="matrix(0.00191701,0,0,0.00191701,38.437333,-10.359467)" />
<radialGradient
id="ae"
xlink:href="#a"
gradientUnits="userSpaceOnUse"
cy="27370"
cx="25538"
gradientTransform="matrix(0.00194549,0,0,0.00194549,24.0288,-25.181866)"
r="3682.2" />
<radialGradient
id="af"
xlink:href="#x"
gradientUnits="userSpaceOnUse"
cy="17398"
cx="18401"
gradientTransform="matrix(0.00191701,0,0,0.00191701,38.242133,-10.359467)"
r="11888" />
<radialGradient
id="ag"
xlink:href="#a"
gradientUnits="userSpaceOnUse"
cy="15674"
cx="16467"
gradientTransform="matrix(0.00204277,0,0,0.00207051,35.864533,-12.1536)"
r="3055.2" />
<radialGradient
id="ah"
xlink:href="#b"
gradientUnits="userSpaceOnUse"
cy="17753"
cx="18300"
gradientTransform="matrix(0.00205653,0,0,0.00205653,35.864533,-12.1536)"
r="28430" />
<radialGradient
id="ai"
xlink:href="#a"
gradientUnits="userSpaceOnUse"
cy="33086"
cx="-2182.7"
gradientTransform="matrix(0.00349152,0,0,0.00121131,33.954133,16.765867)"
r="11540" />
<radialGradient
id="aj"
xlink:href="#a"
gradientUnits="userSpaceOnUse"
cy="18596"
cx="17070"
gradientTransform="matrix(0.00208203,0,0,0.00203136,35.864533,-12.1536)"
r="3734.6001" />
<linearGradient
id="ao"
y2="39368"
xlink:href="#x"
gradientUnits="userSpaceOnUse"
x2="2312.5"
gradientTransform="matrix(0.00349152,0,0,0.00121131,33.954133,16.765867)"
y1="39560"
x1="-1083.8" />
<radialGradient
id="ak"
xlink:href="#b"
gradientUnits="userSpaceOnUse"
cy="11246"
cx="13190"
gradientTransform="matrix(0.00173621,0,0,0.00173621,34.7392,-13.975467)"
r="16248" />
<linearGradient
id="ap"
y2="18951"
xlink:href="#a"
gradientUnits="userSpaceOnUse"
x2="12508"
gradientTransform="matrix(0.00205653,0,0,0.00205653,35.864533,-12.1536)"
y1="-85.142998"
x1="-1308.3" />
<radialGradient
id="al"
xlink:href="#a"
gradientUnits="userSpaceOnUse"
cy="29167"
cx="26631"
gradientTransform="matrix(0.00178912,0,0,0.00178912,42.586666,-6.9703469)"
r="4284.2002" />
<linearGradient
id="y"
y2="20482"
gradientUnits="userSpaceOnUse"
x2="6753.3999"
gradientTransform="matrix(0.00141995,0,0,0.00297856,33.954133,16.765867)"
y1="27356"
x1="850.32001">
<stop
stop-color="#a66500"
offset="0"
id="stop39" />
<stop
stop-color="#da8f00"
offset="1"
id="stop41" />
</linearGradient>
<linearGradient
id="z"
y2="21261"
gradientUnits="userSpaceOnUse"
x2="3741.1001"
gradientTransform="matrix(0.001344,0,0,0.00314709,33.954133,16.765867)"
y1="21261"
x1="-3478.8999">
<stop
stop-color="#eda700"
offset="0"
id="stop44" />
<stop
stop-color="#fff"
offset=".38824"
id="stop46" />
<stop
stop-color="#ffcb50"
offset="0.7"
id="stop48" />
<stop
stop-color="#ed8700"
offset="1"
id="stop50" />
</linearGradient>
<linearGradient
id="aa"
y2="29618"
xlink:href="#a"
gradientUnits="userSpaceOnUse"
x2="24590"
gradientTransform="matrix(0.00205653,0,0,0.00205653,35.864533,-12.1536)"
y1="405.03"
x1="389.39999" />
<radialGradient
id="am"
gradientUnits="userSpaceOnUse"
cy="10444"
cx="11715"
gradientTransform="matrix(0.00205653,0,0,0.00205653,35.864533,-12.1536)"
r="15132">
<stop
stop-color="#f5ffff"
stop-opacity=".49020"
offset="0"
id="stop54" />
<stop
stop-color="#fff"
stop-opacity="0"
offset="1.2"
id="stop56" />
</radialGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#ab"
id="linearGradient3191"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.94852267,0,0,0.83442133,0.664448,8.1570133)"
x1="40.751999"
y1="43.993999"
x2="7.5955"
y2="4.2192998" />
<linearGradient
inkscape:collect="always"
xlink:href="#ab"
id="linearGradient1016"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.94852267,0,0,0.83442133,0.664448,8.1570133)"
x1="40.751999"
y1="43.993999"
x2="7.5955"
y2="4.2192998" />
<linearGradient
id="a-6"
y2="39.685001"
gradientUnits="userSpaceOnUse"
x2="34.534"
gradientTransform="matrix(0.92673,0,0,0.84499,4.7271,52.187)"
y1="12.285"
x1="14.463">
<stop
stop-color="#c9c9c9"
offset="0"
id="stop1040" />
<stop
stop-color="#f8f8f8"
offset=".25"
id="stop1042" />
<stop
stop-color="#e2e2e2"
offset=".5"
id="stop1044" />
<stop
stop-color="#b0b0b0"
offset=".75"
id="stop1046" />
<stop
stop-color="#c9c9c9"
offset="1"
id="stop1048" />
</linearGradient>
</defs>
<g
id="g1010"
transform="matrix(0.96357902,0,0,0.99699248,-0.99217666,0.8052567)">
<g
style="opacity:0.81081082"
id="g99"
transform="matrix(0.54157884,0,0,0.5495207,0.11187994,-2.8442232)">
<g
style="stroke-linecap:round;stroke-linejoin:round"
id="use101"
transform="matrix(0.88516,0.46528,-0.46528,0.88516,20.799849,-8.6726939)">
<rect
style="color:#000000;display:block;fill:#ffffff;fill-opacity:0.63253;stroke:url(#linearGradient3191);stroke-width:1.06666672"
ry="0.95879465"
height="34.145069"
width="33.079464"
display="block"
y="11.2"
x="6.928"
id="rect3151" />
<rect
style="color:#000000;display:block;opacity:0.79120998;fill:none;stroke:#ffffff;stroke-width:1.06666672"
display="block"
rx="0.14066133"
ry="0.12247467"
height="32.004265"
width="30.9312"
y="12.262401"
x="8"
id="rect3153" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:block;fill:none;stroke:#000000;stroke-width:1.06666672"
d="m 10.862933,14.365867 5.6704,0.03413 3.2,3.2 v 8.533333"
display="block"
id="path3155" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:block;fill:none;stroke:#000000;stroke-width:1.06666672"
d="M 24,26.133333 V 17.6 l -3.2,-3.2"
display="block"
id="path3157" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:block;fill:none;stroke:#000000;stroke-width:1.06666672"
d="M 28.266667,26.133333 V 17.6 l -3.2,-3.2"
display="block"
id="path3159" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:block;fill:none;stroke:#000000;stroke-width:1.06666672"
d="M 32.533333,26.133333 V 14.4"
display="block"
id="path3161" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:block;fill:none;stroke:#000000;stroke-width:2.13333344"
d="m 19.733333,26.133333 v 2.133334"
display="block"
id="path3163" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:block;fill:none;stroke:#000000;stroke-width:2.13333344"
d="m 24,26.133333 v 2.133334"
display="block"
id="path3165" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:block;fill:none;stroke:#000000;stroke-width:2.13333344"
d="m 28.266667,26.133333 v 2.133334"
display="block"
id="path3167" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:block;fill:none;stroke:#000000;stroke-width:2.13333344"
d="m 32.533333,26.133333 v 2.133334"
display="block"
id="path3169" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:block;fill:none;stroke:#000000;stroke-width:2.13333344"
d="m 32.533333,33.6 v 2.133333"
display="block"
id="path3171" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:block;fill:none;stroke:#000000;stroke-width:2.13333344"
d="m 28.266667,33.6 v 2.133333"
display="block"
id="path3173" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:block;fill:none;stroke:#000000;stroke-width:2.13333344"
d="m 24,33.6 v 2.133333"
display="block"
id="path3175" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:block;fill:none;stroke:#000000;stroke-width:2.13333344"
d="m 19.733333,33.6 v 2.133333"
display="block"
id="path3177" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:block;fill:none;stroke:#000000;stroke-width:1.06666672"
d="m 19.733333,35.733333 v 3.2 L 17.6,41.066667 h -6.4"
display="block"
id="path3179" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:block;fill:none;stroke:#000000;stroke-width:1.06666672"
d="m 24,35.733333 v 5.333334"
display="block"
id="path3181" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:block;fill:none;stroke:#000000;stroke-width:1.06666672"
d="m 28.266667,35.733333 v 3.2 L 30.4,41.066667 h 6.4"
display="block"
id="path3183" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:block;fill:none;stroke:#000000;stroke-width:1.06666672"
d="m 32.533333,35.733333 2.133334,2.133334 H 36.8"
display="block"
id="path3185" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:block;stroke:#000000;stroke-width:1.06666672"
display="block"
d="m 11.2,16.533333 h 4.266667 L 17.6,18.666667 v 19.2 l -1.066667,1.066666 H 11.2 Z"
id="path3187" />
<rect
style="color:#000000;display:block;fill:none;stroke:#000000;stroke-width:1.06666672"
display="block"
ry="2.1632001"
height="13.866667"
width="17.066668"
y="24"
x="17.6"
id="rect3189" />
</g>
<use
id="use103"
x="0"
y="0"
width="48"
height="48"
transform="matrix(0.97367,0.22797,-0.22797,0.97367,10.729289,-7.9365122)"
xlink:href="#an" />
<g
style="stroke-linecap:round;stroke-linejoin:round"
id="an"
transform="translate(-4.2613333,1.0552224)">
<rect
style="color:#000000;display:block;fill:#ffffff;fill-opacity:0.63253;stroke:url(#linearGradient1016);stroke-width:1.06666672"
ry="0.95879465"
height="34.145069"
width="33.079464"
display="block"
y="11.2"
x="6.928"
id="rect3195" />
<rect
style="color:#000000;display:block;opacity:0.79120998;fill:none;stroke:#ffffff;stroke-width:1.06666672"
display="block"
rx="0.14066133"
ry="0.12247467"
height="32.004265"
width="30.9312"
y="12.262401"
x="8"
id="rect3197" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:block;fill:none;stroke:#000000;stroke-width:1.06666672"
d="m 10.862933,14.365867 5.6704,0.03413 3.2,3.2 v 8.533333"
display="block"
id="path3199" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:block;fill:none;stroke:#000000;stroke-width:1.06666672"
d="M 24,26.133333 V 17.6 l -3.2,-3.2"
display="block"
id="path3201" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:block;fill:none;stroke:#000000;stroke-width:1.06666672"
d="M 28.266667,26.133333 V 17.6 l -3.2,-3.2"
display="block"
id="path3203" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:block;fill:none;stroke:#000000;stroke-width:1.06666672"
d="M 32.533333,26.133333 V 14.4"
display="block"
id="path3205" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:block;fill:none;stroke:#000000;stroke-width:2.13333344"
d="m 19.733333,26.133333 v 2.133334"
display="block"
id="path3207" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:block;fill:none;stroke:#000000;stroke-width:2.13333344"
d="m 24,26.133333 v 2.133334"
display="block"
id="path3209" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:block;fill:none;stroke:#000000;stroke-width:2.13333344"
d="m 28.266667,26.133333 v 2.133334"
display="block"
id="path3211" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:block;fill:none;stroke:#000000;stroke-width:2.13333344"
d="m 32.533333,26.133333 v 2.133334"
display="block"
id="path3213" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:block;fill:none;stroke:#000000;stroke-width:2.13333344"
d="m 32.533333,33.6 v 2.133333"
display="block"
id="path3215" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:block;fill:none;stroke:#000000;stroke-width:2.13333344"
d="m 28.266667,33.6 v 2.133333"
display="block"
id="path3217" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:block;fill:none;stroke:#000000;stroke-width:2.13333344"
d="m 24,33.6 v 2.133333"
display="block"
id="path3219" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:block;fill:none;stroke:#000000;stroke-width:2.13333344"
d="m 19.733333,33.6 v 2.133333"
display="block"
id="path3221" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:block;fill:none;stroke:#000000;stroke-width:1.06666672"
d="m 19.733333,35.733333 v 3.2 L 17.6,41.066667 h -6.4"
display="block"
id="path3223" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:block;fill:none;stroke:#000000;stroke-width:1.06666672"
d="m 24,35.733333 v 5.333334"
display="block"
id="path3225" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:block;fill:none;stroke:#000000;stroke-width:1.06666672"
d="m 28.266667,35.733333 v 3.2 L 30.4,41.066667 h 6.4"
display="block"
id="path3227" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:block;fill:none;stroke:#000000;stroke-width:1.06666672"
d="m 32.533333,35.733333 2.133334,2.133334 H 36.8"
display="block"
id="path3229" />
<path
inkscape:connector-curvature="0"
style="color:#000000;display:block;stroke:#000000;stroke-width:1.06666672"
display="block"
d="m 11.2,16.533333 h 4.266667 L 17.6,18.666667 v 19.2 l -1.066667,1.066666 H 11.2 Z"
id="path3231" />
<rect
style="color:#000000;display:block;fill:none;stroke:#000000;stroke-width:1.06666672"
display="block"
ry="2.1632001"
height="13.866667"
width="17.066668"
y="24"
x="17.6"
id="rect3233" />
</g>
<path
style="fill:#ffffff;fill-opacity:0.51807;fill-rule:evenodd;stroke-width:1.06666672"
inkscape:connector-curvature="0"
id="path106"
d="M 4.2666667,27.733333 V 13.866667 H 34.133333 v 13.866666 c -7.466666,6.4 -19.2,-6.4 -29.8666663,0 z" />
</g>
<g
id="g114"
transform="matrix(0.37303414,0.10324413,-0.09465317,0.34403422,-4.4968508,-1.3805606)">
<g
style="opacity:0.18469998"
id="g116"
transform="matrix(0.001928,0,0,0.001928,35.5648,-10.49184)">
<path
style="fill-rule:evenodd;stroke-width:1.10570669"
inkscape:connector-curvature="0"
id="path118"
d="m 23872.83,21016.084 a 2527.3137,2527.3137 0 1 1 -5054.627,0 2527.3137,2527.3137 0 1 1 5054.627,0 z" />
<path
style="fill-rule:evenodd;stroke-width:1.06666672"
inkscape:connector-curvature="0"
id="path120"
d="m 20995.2,18544 c -494.848,-610.219 -685.771,-195.563 -944.715,-401.365 -198.73,-178.134 135.168,-459.222 -297.205,-926.87 l -2109.76,2098.454 c 360.523,355.733 558.496,97.792 779.307,400.128 165.578,240.64 -18.251,553.856 514.89,898.57 l 2057.494,-2068.906 z" />
<rect
style="fill-rule:evenodd;stroke-width:1.06666672"
id="rect122"
x="-2201.6001"
y="24636.801"
width="4977.8135"
height="1726.9333"
transform="rotate(-45)" />
<path
style="fill-rule:evenodd;stroke-width:1.06666672"
inkscape:connector-curvature="0"
id="path124"
d="m 20958.933,10346.987 c 0,5395.2 -4373.653,9768.96 -9768.96,9768.96 -5395.1997,0 -9768.9597,-4373.654 -9768.9597,-9768.96 0,-5395.2003 4373.6534,-9768.96033 9768.9597,-9768.96033 5395.2,0 9768.96,4373.65333 9768.96,9768.96033 z m -967.69,-0.01 c 0,4860.8 -3940.48,8801.28 -8801.28,8801.28 -4860.8003,0 -8801.1737,-3940.48 -8801.1737,-8801.28 0,-4860.8 3940.48,-8801.28 8801.1737,-8801.28 4860.8,0 8801.28,3940.48 8801.28,8801.28 z" />
<path
style="fill-rule:evenodd;stroke-width:1.0222187"
inkscape:connector-curvature="0"
id="path126"
d="m 31187.387,28241.364 a 2336.4855,2336.4855 0 1 1 -4672.971,0 2336.4855,2336.4855 0 1 1 4672.971,0 z" />
<rect
style="stroke-width:1.06666672"
id="rect128"
x="-2533.3333"
y="28601.6"
width="5890.3467"
height="12355.2"
transform="rotate(-45)" />
</g>
<path
style="opacity:0.29300005;fill:url(#ac);fill-rule:evenodd;stroke-width:1.06666672"
inkscape:connector-curvature="0"
id="path130"
d="m 72.802133,10.33856 c 0,7.183893 -5.82368,13.008 -13.008,13.008 -7.183786,0 -13.006933,-5.82368 -13.006933,-13.008 0,-7.1837867 5.82368,-13.008 13.006933,-13.008 7.183894,0 13.008,5.82368 13.008,13.008 z m 1.97152,-2.5621333 c 0,9.5886933 -7.77312,17.3621333 -17.362133,17.3621333 -9.588693,0 -17.362133,-7.773227 -17.362133,-17.3621333 0,-9.5886934 7.773226,-17.3621334 17.362133,-17.3621334 9.588693,0 17.362133,7.7732267 17.362133,17.3621334 z" />
<path
style="opacity:0.68790002;fill:url(#ad);fill-rule:evenodd;stroke-width:0.00191701"
inkscape:connector-curvature="0"
id="path132"
d="m 75.617807,7.5176412 a 17.686557,17.686557 0 1 1 -35.37273,0 17.686557,17.686557 0 1 1 35.37273,0 z" />
<path
style="fill:#717386;fill-rule:evenodd;stroke-width:0.00213184"
inkscape:connector-curvature="0"
id="path134"
d="m 81.892977,28.365297 a 4.8727467,4.8727467 0 1 1 -9.745493,0 4.8727467,4.8727467 0 1 1 9.745493,0 z" />
<path
style="fill:url(#ae);fill-rule:evenodd;stroke-width:0.00194549"
inkscape:connector-curvature="0"
id="path136"
d="m 81.467545,28.365892 a 4.4468141,4.4468141 0 1 1 -8.893628,0 4.4468141,4.4468141 0 1 1 8.893628,0 z" />
<path
style="fill:url(#af);fill-rule:evenodd;stroke-width:0.00191701"
inkscape:connector-curvature="0"
id="path138"
d="m 75.422607,7.5176412 a 17.686557,17.686557 0 1 1 -35.37273,0 17.686557,17.686557 0 1 1 35.37273,0 z" />
<path
style="fill:url(#ag);fill-rule:evenodd;stroke-width:1.06666672"
inkscape:connector-curvature="0"
id="path140"
d="m 76.343467,23.6 c -0.954091,-1.176533 -1.32224,-0.377056 -1.82144,-0.773845 -0.383158,-0.343446 0.260608,-0.885398 -0.573024,-1.787094 l -4.06784,4.045867 c 0.695104,0.685867 1.0768,0.188544 1.502506,0.771467 0.319243,0.463968 -0.03519,1.06784 0.992726,1.73248 l 3.96704,-3.988907 z" />
<path
style="fill:url(#ah);fill-rule:evenodd;stroke-width:1.06666672"
inkscape:connector-curvature="0"
id="path142"
d="m 74.241067,8.1754667 c 0,8.9271463 -7.184427,16.1642663 -16.046934,16.1642663 -8.8624,0 -16.046933,-7.236906 -16.046933,-16.1642663 0,-8.9271467 7.184427,-16.1642667 16.046933,-16.1642667 8.8624,0 16.046934,7.2368 16.046934,16.1642667 z m 1.31424,-0.6552107 c 0,10.01696 -8.12032,18.1376 -18.1376,18.1376 -10.01696,0 -18.1376,-8.12032 -18.1376,-18.1376 0,-10.01696 8.12032,-18.1376 18.1376,-18.1376 10.01696,0 18.1376,8.12032 18.1376,18.1376 z" />
<rect
style="opacity:0.9554;fill:url(#ai);fill-rule:evenodd;stroke-width:1.06666672"
id="rect144"
x="29.709867"
y="64.267731"
width="9.5974398"
height="3.3297067"
transform="rotate(-45)" />
<path
style="fill:url(#aj);fill-rule:evenodd;stroke-width:1.06666672"
inkscape:connector-curvature="0"
id="path146"
d="m 76.0992,23.943467 c -0.954091,-1.176534 -1.32224,-0.377056 -1.82144,-0.773846 -0.383157,-0.343445 0.211648,-1.1792 -0.866805,-2.227733 l -3.773974,3.703147 c 0.842006,0.832768 1.664427,0.286485 2.090134,0.869397 0.319242,0.463968 -0.03519,1.06784 0.992725,1.73248 l 3.379413,-3.30336 z" />
<rect
style="fill:url(#ao);fill-rule:evenodd;stroke-width:1.06666672"
id="rect148"
x="30.532267"
y="64"
width="7.9522138"
height="2.7589333"
transform="rotate(-45)" />
<path
style="opacity:0.21019999;fill:url(#ak);fill-rule:evenodd;stroke-width:0.00173621"
inkscape:connector-curvature="0"
id="path150"
d="m 58.124257,-0.35660928 a 6.1968926,6.1968926 0 1 1 -12.393785,0 6.1968926,6.1968926 0 1 1 12.393785,0 z" />
<path
style="fill:url(#ap);fill-rule:evenodd;stroke-width:1.06666672"
inkscape:connector-curvature="0"
id="path152"
d="m 76.274133,7.79552 c 0,10.40224 -8.43264,18.8352 -18.8352,18.8352 -10.40224,0 -18.8352,-8.43264 -18.8352,-18.8352 0,-10.40224 8.43264,-18.8352 18.8352,-18.8352 10.40224,0 18.8352,8.43264 18.8352,18.8352 z m -1.865706,-1.81e-5 c 0,9.3718401 -7.597334,16.9696001 -16.9696,16.9696001 -9.371734,0 -16.9696,-7.597333 -16.9696,-16.9696001 0,-9.37184 7.597333,-16.9696 16.9696,-16.9696 9.37184,0 16.9696,7.5973333 16.9696,16.9696 z" />
<path
style="fill:#808080;fill-rule:evenodd;stroke-width:0.00197088"
inkscape:connector-curvature="0"
id="path154"
d="m 95.995194,42.296634 a 4.5048404,4.5048404 0 1 1 -9.00968,0 4.5048404,4.5048404 0 1 1 9.00968,0 z" />
<path
style="fill:url(#al);fill-rule:evenodd;stroke-width:0.00178912"
inkscape:connector-curvature="0"
id="path156"
d="m 95.408646,42.273392 a 4.089392,4.089392 0 1 1 -8.178784,0 4.089392,4.089392 0 1 1 8.178784,0 z" />
<rect
style="fill:url(#y);stroke-width:1.06666672"
id="rect158"
x="29.069866"
y="71.911469"
width="11.3568"
height="23.821867"
transform="rotate(-45)" />
<rect
style="fill:url(#z);stroke-width:1.06666672"
id="rect160"
x="30.209066"
y="73.19146"
width="9.080533"
height="21.262934"
transform="rotate(-45)" />
<path
style="fill:url(#aa);fill-rule:evenodd;stroke-width:1.06666672"
inkscape:connector-curvature="0"
id="path162"
d="m 74.776533,7.6485333 c 0,9.5166937 -7.71488,17.2319997 -17.232,17.2319997 -9.516693,0 -17.232,-7.71488 -17.232,-17.2319997 0,-9.5166933 7.71488,-17.232 17.232,-17.232 9.516694,0 17.232,7.71488 17.232,17.232 z m -0.514368,6.4e-6 c 0,9.2326403 -7.484586,16.7168003 -16.7168,16.7168003 -9.23264,0 -16.7168,-7.484587 -16.7168,-16.7168003 0,-9.23264 7.484587,-16.7168 16.7168,-16.7168 9.23264,0 16.7168,7.4845867 16.7168,16.7168 z" />
<path
style="opacity:0.54140003;fill:url(#am);fill-rule:evenodd;stroke-width:1.06666672"
inkscape:connector-curvature="0"
id="path164"
d="m 60.269867,2.3768533 c 0,3.8557867 -3.12576,6.9815467 -6.98144,6.9815467 -3.855787,0 -6.98144,-3.12576 -6.98144,-6.9815467 0,-3.8557866 3.12576,-6.98144 6.98144,-6.98144 3.855786,0 6.98144,3.12576 6.98144,6.98144 z M 61.49472,1.641984 c 0,4.9381333 -4.003093,8.941227 -8.941227,8.941227 -4.938133,0 -8.941226,-4.0030937 -8.941226,-8.941227 0,-4.9381333 4.003093,-8.9412267 8.941226,-8.9412267 4.938134,0 8.941227,4.0030934 8.941227,8.9412267 z" />
<path
style="fill:#9a9ba9;fill-rule:evenodd;stroke-width:1.06666672"
inkscape:connector-curvature="0"
id="path166"
d="m 72.385067,27.006933 0.310048,0.25232 3.43712,-3.307946 -0.187648,-0.301291 -3.559467,3.356907 z" />
<path
style="fill:#8a92a0;fill-rule:evenodd;stroke-width:1.06666672"
inkscape:connector-curvature="0"
id="path168"
d="m 69.693867,24.718933 0.285653,0.210699 3.72416,-3.651093 -0.222336,-0.343243 -3.787413,3.78368 z" />
</g>
</g>
<g
style="stroke:#000000"
transform="matrix(0.4228008,0,0,0.47494899,-3.6057646,-15.908652)"
id="g1063">
<path
inkscape:connector-curvature="0"
style="color:#000000;fill:url(#a-6);stroke-width:1.30209994"
d="m 25.828,57.411 c -0.34731,0.02167 -0.68489,0.07071 -1.026,0.10631 h -0.02332 l -0.81616,4.061 c -1.3303,0.27623 -2.5818,0.74502 -3.7077,1.382 l -3.661,-2.402 c -0.98968,0.70058 -1.8903,1.5177 -2.6817,2.4026 l 2.5417,3.3807 c -0.77174,1.0754 -1.3521,2.3033 -1.679,3.5933 -5.2e-5,0.0061 -4.5e-5,0.0202 0,0.02126 l -4.4306,0.63786 c -0.081,0.60325 -0.11659,1.2267 -0.11659,1.8498 0,0.50981 0.0154,1.0128 0.0699,1.5096 l 4.4306,0.72291 c 0.31511,1.4029 0.91369,2.713 1.7489,3.8697 l -2.635,3.2956 c 0.75466,0.85424 1.6259,1.632 2.5651,2.3176 l 3.731,-2.3388 c 1.3039,0.75844 2.7595,1.2903 4.3373,1.5521 l 0.69956,4.0185 c 0.49711,0.04126 1.0069,0.04252 1.5157,0.04252 0.71836,-10e-7 1.4045,-0.02482 2.0987,-0.10631 l 0.83948,-4.1036 c 1.499,-0.341 2.906,-0.931 4.128,-1.723 l 3.5911,2.3813 c 0.93128,-0.72243 1.7829,-1.5528 2.5184,-2.4451 l -2.6117,-3.4444 c 0.70729,-1.1138 1.1974,-2.3427 1.4458,-3.6571 l 4.4073,-0.63786 c 0.03865,-0.41935 0.04663,-0.82605 0.04663,-1.2545 0,-0.74449 -0.09491,-1.4745 -0.20987,-2.19 l -4.476,-0.745 c -0.351,-1.181 -0.927,-2.283 -1.656,-3.274 l 2.635,-3.2956 c -0.817,-0.911 -1.749,-1.752 -2.775,-2.466 l -3.801,2.381 c -1.092,-0.589 -2.268,-1.041 -3.544,-1.297 l -0.7,-4.04 c -0.63673,-0.06829 -1.2787,-0.10631 -1.9355,-0.10631 -0.1775,0 -0.36018,-0.0051 -0.53633,0 -0.08587,0.0024 -0.17086,-0.0046 -0.25651,0 -0.0232,0.0012 -0.0468,-0.0014 -0.06996,0 z m 0.60629,10.333 c 0.08519,-0.0039 0.17025,0 0.25651,0 2.7603,0 5.0135,2.0545 5.0135,4.5713 1e-6,2.5168 -2.2532,4.5501 -5.0135,4.5501 -2.7603,1e-6 -4.9902,-2.0332 -4.9902,-4.5501 0,-2.4382 2.0928,-4.4491 4.7337,-4.5713 z"
id="path1057" />
<path
inkscape:connector-curvature="0"
style="color:#000000;opacity:0.34658999;fill:none;stroke-width:1.40030003"
d="m 25.311,58.215 -0.6553,3.932 c -1.2469,0.25892 -3.5405,1.0508 -4.5959,1.6479 l -3.4863,-2.3726 c -0.92766,0.65668 -0.99127,0.70121 -1.7331,1.5307 l 2.5207,3.4087 c -0.72338,1.008 -1.5922,2.8042 -1.9042,4.0878 0,0 -4.4171,0.67892 -4.4171,0.67892 -0.07593,0.56544 -0.03948,1.7757 0.01164,2.2413 l 4.2192,0.69303 c 0.29536,1.315 1.4006,3.4316 2.1835,4.5157 l -2.6681,3.2142 c 0.70736,0.8007 0.84892,0.87397 1.7292,1.5166 l 3.5677,-2.3833 c 1.2222,0.7109 3.6482,1.5757 5.1271,1.8211 l 0.58553,3.8824 c 0.46595,0.03867 1.7532,0.14715 2.4038,0.07077 l 0.65531,-4.0416 c 1.4042,-0.31862 3.8304,-1.2267 4.9759,-1.9697 l 3.5639,2.3479 c 0.87292,-0.67715 0.88074,-0.77919 1.5702,-1.6156 l -2.641,-3.4228 c 0.66296,-1.044 1.5202,-3.0857 1.753,-4.3177 l 4.324,-0.65416 c 0.03623,-0.39307 0.03799,-1.4892 -0.06977,-2.1599 l -4.4054,-0.69303 c -0.32887,-1.1073 -1.4575,-3.1025 -2.1409,-4.0314 l 2.8,-3.2142 c -0.76558,-0.85369 -1.0502,-0.97082 -2.0124,-1.6403 l -3.688,2.408 c -1.024,-0.553 -3.066,-1.394 -4.262,-1.634 l -0.65149,-3.8471 c -0.59683,-0.06401 -2.3187,-0.03559 -2.6598,0 z"
id="path1059" />
<path
inkscape:connector-curvature="0"
style="color:#000000;opacity:0.64772997;fill:none;stroke-width:0.71253002"
d="m 32.454,72.306 a 5.7605,5.2524 0 0 1 -11.521,0 5.7605,5.2524 0 1 1 11.521,0 z"
id="path1061" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 33 KiB

View File

@ -122,6 +122,41 @@ std::string GBR_APERTURE_METADATA::FormatAttribute( GBR_APERTURE_ATTRIB aAttribu
return attribute_string;
}
wxString FormatStringFromGerber( const wxString& aString )
{
// make the inverse conversion of formatStringToGerber()
// It converts a "normalized" gerber string and convert it to a 16 bits sequence unicode
// and return a wxString (unicode 16) from the gerber string
wxString txt;
for( unsigned ii = 0; ii < aString.Length(); ++ii )
{
unsigned code = aString[ii];
if( code == '\\' )
{
// Convert 4 hexadecimal digits to a 16 bit unicode
// (Gerber allows only 4 hexadecimal digits)
long value = 0;
for( int jj = 0; jj < 4; jj++ )
{
value <<= 4;
code = aString[++ii];
// Very basic conversion, but it expects a valid gerber file
int hexa = (code <= '9' ? code - '0' : code - 'A' + 10) & 0xF;
value += hexa;
}
txt.Append( wxChar( value ) );
}
else
txt.Append( aString[ii] );
}
return txt;
}
std::string formatStringToGerber( const wxString& aString )
{

View File

@ -1,3 +1,4 @@
creategerberjobfile
drillshape
excludeedgelayer
false

View File

@ -42,7 +42,8 @@ const wxString ProjectFileExtension( wxT( "pro" ) );
const wxString SchematicFileExtension( wxT( "sch" ) );
const wxString NetlistFileExtension( wxT( "net" ) );
const wxString ComponentFileExtension( wxT( "cmp" ) );
const wxString GerberFileExtension( wxT( ".((gbr|(gb|gt)[alops])|pho)" ) );
const wxString GerberFileExtension( "gbr" );
const wxString GerberJobFileExtension( "gbj" );
const wxString HtmlFileExtension( wxT( "html" ) );
const wxString LegacyPcbFileExtension( wxT( "brd" ) );

View File

@ -51,7 +51,7 @@ set( GERBVIEW_SRCS
gerbview_config.cpp
gerbview_frame.cpp
hotkeys.cpp
clear_gbr_drawlayers.cpp
job_file_reader.cpp
locate.cpp
menubar.cpp
onleftclick.cpp

View File

@ -54,6 +54,7 @@ BEGIN_EVENT_TABLE( GERBVIEW_FRAME, EDA_DRAW_FRAME )
EVT_TOOL( ID_GERBVIEW_ERASE_ALL, GERBVIEW_FRAME::Files_io )
EVT_TOOL( ID_GERBVIEW_LOAD_DRILL_FILE, GERBVIEW_FRAME::Files_io )
EVT_TOOL( ID_GERBVIEW_LOAD_ZIP_ARCHIVE_FILE, GERBVIEW_FRAME::Files_io )
EVT_TOOL( ID_GERBVIEW_LOAD_JOB_FILE, GERBVIEW_FRAME::Files_io )
EVT_TOOL( ID_NEW_BOARD, GERBVIEW_FRAME::Files_io )
EVT_TOOL( ID_GERBVIEW_SET_PAGE_BORDER, GERBVIEW_FRAME::Process_Special_Functions )
@ -70,6 +71,9 @@ BEGIN_EVENT_TABLE( GERBVIEW_FRAME, EDA_DRAW_FRAME )
EVT_MENU_RANGE( ID_GERBVIEW_ZIP_FILE1, ID_GERBVIEW_ZIP_FILE9,
GERBVIEW_FRAME::OnZipFileHistory )
EVT_MENU_RANGE( ID_GERBVIEW_JOB_FILE1, ID_GERBVIEW_JOB_FILE9,
GERBVIEW_FRAME::OnJobFileHistory )
EVT_MENU( wxID_EXIT, GERBVIEW_FRAME::OnQuit )
// menu Preferences

View File

@ -74,6 +74,7 @@ void GERBVIEW_FRAME::OnDrlFileHistory( wxCommandEvent& event )
}
}
void GERBVIEW_FRAME::OnZipFileHistory( wxCommandEvent& event )
{
wxString filename;
@ -87,6 +88,18 @@ void GERBVIEW_FRAME::OnZipFileHistory( wxCommandEvent& event )
}
void GERBVIEW_FRAME::OnJobFileHistory( wxCommandEvent& event )
{
wxString filename;
filename = GetFileFromHistory( event.GetId(), _( "Job files" ), &m_jobFileHistory );
if( !filename.IsEmpty() )
{
LoadGerberJobFile( filename );
}
}
/* File commands. */
void GERBVIEW_FRAME::Files_io( wxCommandEvent& event )
{
@ -116,6 +129,11 @@ void GERBVIEW_FRAME::Files_io( wxCommandEvent& event )
m_canvas->Refresh();
break;
case ID_GERBVIEW_LOAD_JOB_FILE:
LoadGerberJobFile( wxEmptyString );
m_canvas->Refresh();
break;
default:
wxFAIL_MSG( wxT( "File_io: unexpected command id" ) );
break;

View File

@ -29,7 +29,6 @@
*/
#include <fctsys.h>
#include <macros.h>
#include <id.h>
#include <common.h>
#include <class_drawpanel.h>
@ -41,9 +40,6 @@
#include <dialog_hotkeys_editor.h>
#define GROUP wxT("/gerbview")
void GERBVIEW_FRAME::Process_Config( wxCommandEvent& event )
{
int id = event.GetId();

View File

@ -37,6 +37,7 @@
#include <class_gbr_layer_box_selector.h>
#include <msgpanel.h>
#include <bitmaps.h>
#include <wildcards_and_files_ext.h>
#include <gerbview.h>
#include <gerbview_frame.h>
@ -81,6 +82,7 @@ GERBVIEW_FRAME::GERBVIEW_FRAME( KIWAY* aKiway, wxWindow* aParent ):
m_displayMode = 0;
m_drillFileHistory.SetBaseId( ID_GERBVIEW_DRILL_FILE1 );
m_zipFileHistory.SetBaseId( ID_GERBVIEW_ZIP_FILE1 );
m_jobFileHistory.SetBaseId( ID_GERBVIEW_JOB_FILE1 );
if( m_canvas )
m_canvas->SetEnableBlockCommands( true );
@ -230,8 +232,10 @@ bool GERBVIEW_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
wxFileName fn( aFileSet[i] );
wxString ext = fn.GetExt();
if( ext == "drl" )
if( ext == DrillFileExtension ) // In Excellon format
LoadExcellonFiles( aFileSet[i] );
else if( ext == GerberJobFileExtension )
LoadGerberJobFile( aFileSet[i] );
else
LoadGerberFiles( aFileSet[i] );
}
@ -307,6 +311,12 @@ void GERBVIEW_FRAME::LoadSettings( wxConfigBase* aCfg )
aCfg->SetPath( wxT( "zip_files" ) );
m_zipFileHistory.Load( *aCfg );
aCfg->SetPath( wxT( ".." ) );
// because we have more than one file history, we must read this one
// using a specific path
aCfg->SetPath( "job_files" );
m_jobFileHistory.Load( *aCfg );
aCfg->SetPath( wxT( ".." ) );
}
@ -334,6 +344,11 @@ void GERBVIEW_FRAME::SaveSettings( wxConfigBase* aCfg )
aCfg->SetPath( wxT( "zip_files" ) );
m_zipFileHistory.Save( *aCfg );
aCfg->SetPath( wxT( ".." ) );
// Save the job file history list.
aCfg->SetPath( "job_files" );
m_jobFileHistory.Save( *aCfg );
aCfg->SetPath( ".." );
}

View File

@ -163,6 +163,9 @@ protected:
// Auxiliary file history used to store drill files history.
wxFileHistory m_drillFileHistory;
// Auxiliary file history used to store job files history.
wxFileHistory m_jobFileHistory;
/// The last filename chosen to be proposed to the user
wxString m_lastFileName;
@ -606,6 +609,12 @@ public:
*/
void OnZipFileHistory( wxCommandEvent& event );
/**
* deletes the current data and load a gerber job file selected from the
* history list.
*/
void OnJobFileHistory( wxCommandEvent& event );
/**
* Extracts gerber and drill files from the zip archive, and load them
* @param aFullFileName is the full filename of the zip archive
@ -647,6 +656,17 @@ public:
*/
bool LoadZipArchiveFile( const wxString& aFileName );
/**
* Load a Gerber job file, and load gerber files found in job files.
* @param aFileName - void string or file name with full path to open or empty string to
* open a new file.
* if empty string: user will be prompted for filename(s)
* @return true if file(s) was opened successfully.
*/
bool LoadGerberJobFile( const wxString& aFileName );
bool GeneralControl( wxDC* aDC, const wxPoint& aPosition, EDA_KEY aHotKey = 0 ) override;
/**

View File

@ -41,6 +41,7 @@ enum gerbview_ids
ID_GERBVIEW_SHOW_LIST_DCODES,
ID_GERBVIEW_LOAD_DRILL_FILE,
ID_GERBVIEW_LOAD_JOB_FILE,
ID_GERBVIEW_LOAD_ZIP_ARCHIVE_FILE,
ID_GERBVIEW_ERASE_ALL,
ID_TOOLBARH_GERBER_SELECT_ACTIVE_DCODE,
@ -66,7 +67,19 @@ enum gerbview_ids
ID_GERBVIEW_DRILL_FILE8,
ID_GERBVIEW_DRILL_FILE9,
// IDs for drill file history (wxID_FILEnn is already in use)
// IDs for job file history (wxID_FILEnn is already in use)
ID_GERBVIEW_JOB_FILE,
ID_GERBVIEW_JOB_FILE1,
ID_GERBVIEW_JOB_FILE2,
ID_GERBVIEW_JOB_FILE3,
ID_GERBVIEW_JOB_FILE4,
ID_GERBVIEW_JOB_FILE5,
ID_GERBVIEW_JOB_FILE6,
ID_GERBVIEW_JOB_FILE7,
ID_GERBVIEW_JOB_FILE8,
ID_GERBVIEW_JOB_FILE9,
// IDs for zip file history (wxID_FILEnn is already in use)
ID_GERBVIEW_ZIP_FILE,
ID_GERBVIEW_ZIP_FILE1,
ID_GERBVIEW_ZIP_FILE2,

View File

@ -0,0 +1,245 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2007-2017 Jean-Pierre Charras jp.charras at wanadoo.fr
* Copyright (C) 1992-2017 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 job_file_reader.cpp
*/
#include <fctsys.h>
#include <wx/filename.h>
#include <gerbview.h>
#include <richio.h>
#include <class_drawpanel.h>
#include <class_gerber_file_image.h>
#include <class_gerber_file_image_list.h>
#include <gerbview_frame.h>
#include <reporter.h>
#include <plot_auxiliary_data.h>
#include <html_messagebox.h>
extern int ReadInt( char*& text, bool aSkipSeparator = true );
extern double ReadDouble( char*& text, bool aSkipSeparator = true );
extern bool GetEndOfBlock( char* buff, char*& text, FILE* gerber_file );
/**
* this class read and parse a Gerber job file to extract useful info
* for GerbView
*
* In a gerber job file, data lines start by
* %TF. (usual Gerber X2 info)
* %TJ.B. (board info)
* %TJ.D. (design info)
* %TJ.L. (layers info)
* some others are not yet handled by Kicad
* M02* is the last line
*/
class GERBER_JOBFILE_READER
{
public:
GERBER_JOBFILE_READER( const wxString& aFileName, REPORTER* aReporter )
{
m_filename = aFileName;
m_reporter = aReporter;
}
~GERBER_JOBFILE_READER() {}
bool ReadGerberJobFile(); /// read the .gbj file
wxArrayString& GetGerberFiles() { return m_GerberFiles; }
private:
/** parse a string starting by "%TJ.L" (layer gerber filename)
* and add the filename in m_GerberFiles
*/
bool parseTJLayerString( wxString& aText );
private:
REPORTER* m_reporter;
wxFileName m_filename;
wxArrayString m_GerberFiles; // List of gerber files in job
};
bool GERBER_JOBFILE_READER::ReadGerberJobFile()
{
// Read the gerber file */
FILE* jobFile = wxFopen( m_filename.GetFullPath(), wxT( "rt" ) );
if( jobFile == nullptr )
return false;
LOCALE_IO toggleIo;
FILE_LINE_READER jobfileReader( jobFile, m_filename.GetFullPath() ); // Will close jobFile
wxString msg;
wxString data;
while( true )
{
char* line = jobfileReader.ReadLine();
if( !line ) // end of file
break;
wxString text( line );
text.Trim( true );
text.Trim( false );
// Search for lines starting by '%', others are not usefull
if( text.StartsWith( "%TJ.L.", &data ) )
{
parseTJLayerString( data );
continue;
}
if( text.StartsWith( "M02" ) ) // End of file
break;
}
return true;
}
bool GERBER_JOBFILE_READER::parseTJLayerString( wxString& aText )
{
// Parse a line like:
// %TJ.L."Copper,L1,Top",Positive,kit-dev-coldfire-xilinx_5213-Top_layer.gbr*%
// and extract the .gbr filename
// The filename is between the last comma in string and the '*' char
// the filename cannot contain itself a comma:
// this is a not allowed char, that is transcoded in hexa sequence
// if found in filename
wxString name = aText.AfterLast( ',' ).BeforeFirst( '*' );
m_GerberFiles.Add( FormatStringFromGerber( name ) );
return true;
}
bool GERBVIEW_FRAME::LoadGerberJobFile( const wxString& aFullFileName )
{
#define jobFileWildcard _( "Gerber job file (*.gbj)|*.gbj;.gbj" )
wxFileName filename = aFullFileName;
wxString currentPath;
if( !filename.IsOk() )
{
// Use the current working directory if the file name path does not exist.
if( filename.DirExists() )
currentPath = filename.GetPath();
else
currentPath = m_mruPath;
wxFileDialog dlg( this, _( "Open Gerber Job File" ),
currentPath,
filename.GetFullName(),
jobFileWildcard,
wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_CHANGE_DIR );
if( dlg.ShowModal() == wxID_CANCEL )
return false;
filename = dlg.GetPath();
currentPath = wxGetCwd();
m_mruPath = currentPath;
}
else
{
currentPath = filename.GetPath();
m_mruPath = currentPath;
}
wxString msg;
WX_STRING_REPORTER reporter( &msg );
if( filename.IsOk() )
{
GERBER_JOBFILE_READER gbjReader( filename.GetFullPath(), &reporter );
if( gbjReader.ReadGerberJobFile() )
{
// Update the list of recent drill files.
UpdateFileHistory( filename.GetFullPath(), &m_jobFileHistory );
Clear_DrawLayers( false );
ClearMsgPanel();
wxArrayString& gbrfiles = gbjReader.GetGerberFiles();
wxFileName gbr_fn = filename;
bool read_ok;
int layer = 0;
setActiveLayer( layer, false );
for( unsigned ii = 0; ii < gbrfiles.GetCount(); ii++ )
{
gbr_fn.SetFullName( gbrfiles[ii] );
if( gbr_fn.FileExists() )
{
//LoadGerberFiles( gbr_fn.GetFullPath() );
read_ok = Read_GERBER_File( gbr_fn.GetFullPath() );
if( read_ok )
{
layer = getNextAvailableLayer( layer );
setActiveLayer( layer, false );
}
}
else
read_ok = false;
if( !read_ok )
{
wxString err;
err.Printf( _( "Can't load Gerber file:<br><i>%s</i><br>" ), gbr_fn.GetFullPath() );
reporter.Report( err, REPORTER::RPT_WARNING );
}
}
GetImagesList()->SortImagesByZOrder();
ReFillLayerWidget();
syncLayerBox( true );
GetCanvas()->Refresh();
}
}
Zoom_Automatique( false );
if( !msg.IsEmpty() )
{
wxSafeYield(); // Allows slice of time to redraw the screen
// to refresh widgets, before displaying messages
HTML_MESSAGE_BOX mbox( this, _( "Messages" ) );
mbox.ListSet( msg );
mbox.ShowModal();
}
return true;
}

View File

@ -59,22 +59,25 @@ void GERBVIEW_FRAME::ReCreateMenuBar()
wxMenu* fileMenu = new wxMenu;
// Load Gerber files
AddMenuItem( fileMenu,
wxID_FILE,
AddMenuItem( fileMenu, wxID_FILE,
_( "Load &Gerber File" ),
_( "Load a new Gerber file on the current layer. Previous data will be deleted" ),
KiBitmap( gerber_file_xpm ) );
// Load Excellon drill files
AddMenuItem( fileMenu,
ID_GERBVIEW_LOAD_DRILL_FILE,
AddMenuItem( fileMenu, ID_GERBVIEW_LOAD_DRILL_FILE,
_( "Load &EXCELLON Drill File" ),
_( "Load excellon drill file" ),
KiBitmap( gerbview_drill_file_xpm ) );
// Load Gerber job files
AddMenuItem( fileMenu, ID_GERBVIEW_LOAD_JOB_FILE,
_( "Load Gerber &Job File" ),
_( "Load a Gerber job file, and load gerber files depending on the job" ),
KiBitmap( gerber_job_file_xpm ) );
// Load Zip archive files
AddMenuItem( fileMenu,
ID_GERBVIEW_LOAD_ZIP_ARCHIVE_FILE,
AddMenuItem( fileMenu, ID_GERBVIEW_LOAD_ZIP_ARCHIVE_FILE,
_( "Load &Zip Archive File" ),
_( "Load a zipped archive (Gerber and drill) file" ),
KiBitmap( zip_xpm ) );
@ -92,8 +95,7 @@ void GERBVIEW_FRAME::ReCreateMenuBar()
Kiface().GetFileHistory().UseMenu( openRecentGbrMenu );
Kiface().GetFileHistory().AddFilesToMenu();
AddMenuItem( fileMenu, openRecentGbrMenu,
wxID_ANY,
AddMenuItem( fileMenu, openRecentGbrMenu, wxID_ANY,
_( "Open &Recent Gerber File" ),
_( "Open a recent opened Gerber file" ),
KiBitmap( recent_xpm ) );
@ -107,8 +109,7 @@ void GERBVIEW_FRAME::ReCreateMenuBar()
openRecentDrlMenu = new wxMenu();
m_drillFileHistory.UseMenu( openRecentDrlMenu );
m_drillFileHistory.AddFilesToMenu( );
AddMenuItem( fileMenu, openRecentDrlMenu,
wxID_ANY,
AddMenuItem( fileMenu, openRecentDrlMenu, wxID_ANY,
_( "Open Recent Dri&ll File" ),
_( "Open a recent opened drill file" ),
KiBitmap( recent_xpm ) );
@ -122,12 +123,25 @@ void GERBVIEW_FRAME::ReCreateMenuBar()
openRecentZipArchiveMenu = new wxMenu();
m_zipFileHistory.UseMenu( openRecentZipArchiveMenu );
m_zipFileHistory.AddFilesToMenu( );
AddMenuItem( fileMenu, openRecentZipArchiveMenu,
wxID_ANY,
AddMenuItem( fileMenu, openRecentZipArchiveMenu, wxID_ANY,
_( "Open Recent Zip &Archive File" ),
_( "Open a recent opened zip archive file" ),
KiBitmap( recent_xpm ) );
// Recent job files
static wxMenu* openRecentJobFilesMenu;
if( openRecentJobFilesMenu )
m_jobFileHistory.RemoveMenu( openRecentJobFilesMenu );
openRecentJobFilesMenu = new wxMenu();
m_jobFileHistory.UseMenu( openRecentJobFilesMenu );
m_jobFileHistory.AddFilesToMenu( );
AddMenuItem( fileMenu, openRecentJobFilesMenu, wxID_ANY,
_( "Open Recent &Job File" ),
_( "Open a recent opened gerber job file" ),
KiBitmap( recent_xpm ) );
// Separator
fileMenu->AppendSeparator();
@ -152,40 +166,33 @@ void GERBVIEW_FRAME::ReCreateMenuBar()
fileMenu->AppendSeparator();
// Print
AddMenuItem( fileMenu,
wxID_PRINT,
_( "&Print" ),
_( "Print gerber" ),
AddMenuItem( fileMenu, wxID_PRINT,
_( "&Print" ), _( "Print gerber" ),
KiBitmap( print_button_xpm ) );
// Separator
fileMenu->AppendSeparator();
// Exit
AddMenuItem( fileMenu,
wxID_EXIT,
_( "&Close" ),
_( "Close GerbView" ),
AddMenuItem( fileMenu, wxID_EXIT,
_( "&Close" ), _( "Close GerbView" ),
KiBitmap( exit_xpm ) );
// Menu for configuration and preferences
wxMenu* configMenu = new wxMenu;
// Hide layer manager
AddMenuItem( configMenu,
ID_MENU_GERBVIEW_SHOW_HIDE_LAYERS_MANAGER_DIALOG,
AddMenuItem( configMenu, ID_MENU_GERBVIEW_SHOW_HIDE_LAYERS_MANAGER_DIALOG,
_( "Hide &Layers Manager" ),
m_show_layer_manager_tools ?
_( "Hide &Layers Manager" ) : _("Show &Layers Manager" ),
KiBitmap( layers_manager_xpm ) );
// Options (Preferences on WXMAC)
#ifdef __WXMAC__
configMenu->Append(wxID_PREFERENCES);
#else
AddMenuItem( configMenu,
wxID_PREFERENCES,
AddMenuItem( configMenu, wxID_PREFERENCES,
_( "&Options" ),
_( "Set options to draw items" ),
KiBitmap( preference_xpm ) );
@ -204,15 +211,13 @@ void GERBVIEW_FRAME::ReCreateMenuBar()
wxMenu* miscellaneousMenu = new wxMenu;
// List dcodes
AddMenuItem( miscellaneousMenu,
ID_GERBVIEW_SHOW_LIST_DCODES,
AddMenuItem( miscellaneousMenu, ID_GERBVIEW_SHOW_LIST_DCODES,
_( "&List DCodes" ),
_( "List D-codes defined in Gerber files" ),
KiBitmap( show_dcodenumber_xpm ) );
// Show source
AddMenuItem( miscellaneousMenu,
ID_GERBVIEW_SHOW_SOURCE,
AddMenuItem( miscellaneousMenu, ID_GERBVIEW_SHOW_SOURCE,
_( "&Show Source" ),
_( "Show source file for the current layer" ),
KiBitmap( tools_xpm ) );
@ -221,8 +226,7 @@ void GERBVIEW_FRAME::ReCreateMenuBar()
miscellaneousMenu->AppendSeparator();
// Erase graphic layer
AddMenuItem( miscellaneousMenu,
ID_GERBVIEW_ERASE_CURR_LAYER,
AddMenuItem( miscellaneousMenu, ID_GERBVIEW_ERASE_CURR_LAYER,
_( "&Clear Current Layer" ),
_( "Erase the graphic layer currently selected" ),
KiBitmap( delete_sheet_xpm ) );
@ -231,8 +235,7 @@ void GERBVIEW_FRAME::ReCreateMenuBar()
miscellaneousMenu->AppendSeparator();
// Text editor (usefull to browse source files)
AddMenuItem( miscellaneousMenu,
ID_MENU_GERBVIEW_SELECT_PREFERED_EDITOR,
AddMenuItem( miscellaneousMenu, ID_MENU_GERBVIEW_SELECT_PREFERED_EDITOR,
_( "&Text Editor" ),
_( "Select your preferred text editor" ),
KiBitmap( editor_xpm ) );
@ -240,14 +243,12 @@ void GERBVIEW_FRAME::ReCreateMenuBar()
// Help menu
wxMenu* helpMenu = new wxMenu;
AddMenuItem( helpMenu,
wxID_HELP,
AddMenuItem( helpMenu, wxID_HELP,
_( "Gerbview &Manual" ),
_( "Open the GerbView Manual" ),
KiBitmap( online_help_xpm ) );
AddMenuItem( helpMenu,
ID_PREFERENCES_HOTKEY_SHOW_CURRENT_LIST,
AddMenuItem( helpMenu, ID_PREFERENCES_HOTKEY_SHOW_CURRENT_LIST,
_( "&List Hotkeys" ),
_( "Displays the current hotkeys list and corresponding commands" ),
KiBitmap( hotkeys_xpm ) );
@ -264,10 +265,8 @@ void GERBVIEW_FRAME::ReCreateMenuBar()
helpMenu->AppendSeparator();
// About Kicad
AddMenuItem( helpMenu,
wxID_ABOUT,
_( "&About Kicad" ),
_( "About KiCad" ),
AddMenuItem( helpMenu, wxID_ABOUT,
_( "&About Kicad" ), _( "About KiCad" ),
KiBitmap( about_xpm ) );
// Append menus to the menubar

View File

@ -69,9 +69,9 @@ bool GERBVIEW_FRAME::Read_GERBER_File( const wxString& GERBER_FullFileName )
}
/* if the gerber file is only a RS274D file
* (i.e. without any aperture information), wran the user:
* (i.e. without any aperture information, but with items), warn the user:
*/
if( !gerber->m_Has_DCode )
if( !gerber->m_Has_DCode && gerber->GetItemsList() )
{
msg = _("Warning: this file has no D-Code definition\n"
"It is perhaps an old RS274D file\n"
@ -101,12 +101,6 @@ bool GERBER_FILE_IMAGE::LoadGerberFile( const wxString& aFullFileName )
m_FileName = aFullFileName;
wxString path = wxPathOnly( aFullFileName );
// This change is needed to load included files, if exists:
if( path != wxEmptyString )
wxSetWorkingDirectory( path );
LOCALE_IO toggleIo;
wxString msg;

View File

@ -169,6 +169,7 @@ EXTERN_BITMAP( gbr_select_mode0_xpm )
EXTERN_BITMAP( gbr_select_mode1_xpm )
EXTERN_BITMAP( gbr_select_mode2_xpm )
EXTERN_BITMAP( gerbview_drill_file_xpm )
EXTERN_BITMAP( gerber_job_file_xpm )
EXTERN_BITMAP( gerber_file_xpm )
EXTERN_BITMAP( gerbview_clear_layers_xpm )
EXTERN_BITMAP( gerbview_show_negative_objects_xpm )

View File

@ -151,6 +151,7 @@ private:
bool m_isCopper;
};
/**
* This helper function "normalize" aString and convert it to a Gerber std::string
* Normalisation means convert any code > 0x7F and unautorized code to a hexadecimal
@ -161,6 +162,14 @@ private:
*/
std::string formatStringToGerber( const wxString& aString );
/**
* This helper function make the inverse conversion of formatStringToGerber()
* It converts a "normalized" gerber string and convert it to a 16 bits sequence unicode
* @param aString = the wxString compliant with a gerber string format
* @return a wxString (unicode 16) from the gerber string
*/
wxString FormatStringFromGerber( const wxString& aString );
/**
* Generates the string to print to a gerber file, to set a net attribute
* for a graphic object.

View File

@ -51,6 +51,7 @@ extern const wxString ProjectFileExtension;
extern const wxString SchematicFileExtension;
extern const wxString NetlistFileExtension;
extern const wxString GerberFileExtension;
extern const wxString GerberJobFileExtension;
extern const wxString HtmlFileExtension;
extern const wxString LegacyPcbFileExtension;

View File

@ -75,9 +75,10 @@ static const wxChar* s_allowedExtensionsToList[] =
wxT( "^.*\\.txt$" ),
wxT( "^.*\\.pho$" ), // Gerber file (Old Kicad extension)
wxT( "^.*\\.gbr$" ), // Gerber file
wxT( "^.*\\.gb[alops]$" ), // Gerber back (or bottom) layer file
wxT( "^.*\\.gt[alops]$" ), // Gerber front (or top) layer file
wxT( "^.*\\.g[0-9]{1,2}$" ), // Gerber inner layer file
wxT( "^.*\\.gbj$" ), // Gerber job file
wxT( "^.*\\.gb[alops]$" ), // Gerber back (or bottom) layer file (deprecated Protel ext)
wxT( "^.*\\.gt[alops]$" ), // Gerber front (or top) layer file (deprecated Protel ext)
wxT( "^.*\\.g[0-9]{1,2}$" ), // Gerber inner layer file (deprecated Protel ext)
wxT( "^.*\\.odt$" ),
wxT( "^.*\\.htm$" ),
wxT( "^.*\\.html$" ),
@ -102,6 +103,9 @@ const wxChar TextFileExtension[] = wxT( "txt" );
// File wildcard definitions.
const wxChar TextFileWildcard[] = wxT( "Text files (*.txt)|*.txt" );
// Gerber file extension wildcard.
const wxString GerberFileExtensionWildCard( ".((gbr|gbj|(gb|gt)[alops])|pho)" );
/**
* @brief class TREE_PROJECT_FRAME is the frame that shows the tree list
@ -255,7 +259,7 @@ wxString TREE_PROJECT_FRAME::GetFileExt( TreeFileType type )
break;
case TREE_GERBER:
ext = GerberFileExtension;
ext = GerberFileExtensionWildCard;
break;
case TREE_HTML:

View File

@ -182,6 +182,7 @@ set( PCBNEW_EXPORTERS
exporters/gendrill_Excellon_writer.cpp
exporters/gendrill_file_writer_base.cpp
exporters/gendrill_gerber_writer.cpp
exporters/gerber_jobfile_writer.cpp
)
set( PCBNEW_MICROWAVE_SRCS

View File

@ -31,9 +31,11 @@
#include <confirm.h>
#include <wxPcbStruct.h>
#include <pcbplot.h>
#include <gerber_jobfile_writer.h>
#include <base_units.h>
#include <macros.h>
#include <reporter.h>
#include <wildcards_and_files_ext.h>
#include <class_board.h>
#include <wx/ffile.h>
@ -164,6 +166,9 @@ void DIALOG_PLOT::init_Dialog()
// Grey out if m_useGerberX2Attributes is not checked
m_useGerberNetAttributes->Enable( m_useGerberX2Attributes->GetValue() );
// Option to generate a Gerber job file
m_generateGerberJobFile->SetValue( m_plotOpts.GetCreateGerberJobFile() );
// Gerber precision for coordinates
m_rbGerberFormat->SetSelection( m_plotOpts.GetGerberPrecision() == 5 ? 0 : 1 );
@ -682,6 +687,8 @@ void DIALOG_PLOT::applyPlotSettings()
tempOptions.SetUseGerberProtelExtensions( m_useGerberExtensions->GetValue() );
tempOptions.SetUseGerberAttributes( m_useGerberX2Attributes->GetValue() );
tempOptions.SetIncludeGerberNetlistInfo( m_useGerberNetAttributes->GetValue() );
tempOptions.SetCreateGerberJobFile( m_generateGerberJobFile->GetValue() );
tempOptions.SetGerberPrecision( m_rbGerberFormat->GetSelection() == 0 ? 5 : 6 );
LSET selectedLayers;
@ -740,6 +747,14 @@ void DIALOG_PLOT::Plot( wxCommandEvent& event )
{
applyPlotSettings();
// If no layer selected, we have nothing plotted.
// Prompt user if it happens because he could think there is a bug in Pcbnew.
if( !m_plotOpts.GetLayerSelection().any() )
{
DisplayError( this, _( "No layer selected, Nothing to plot" ) );
return;
}
// Create output directory if it does not exist (also transform it in
// absolute form). Bail if it fails
wxFileName outputDir = wxFileName::DirName( m_plotOpts.GetOutputDirectory() );
@ -781,7 +796,7 @@ void DIALOG_PLOT::Plot( wxCommandEvent& event )
}
/* If the scale factor edit controls are disabled or the scale value
* is 0, don't adjust the base scale factor. This fixes a bug when
* is 0, don't adjust the base scale factor. This fixes a bug when
* the default scale adjust is initialized to 0 and saved in program
* settings resulting in a divide by zero fault.
*/
@ -807,6 +822,8 @@ void DIALOG_PLOT::Plot( wxCommandEvent& event )
DisplayInfoMessage( this,
_( "Warning: Scale option set to a very large value" ) );
GERBER_JOBFILE_WRITER jobfile_writer( m_board, &reporter );
// Save the current plot options in the board
m_parent->SetPlotSettings( m_plotOpts );
@ -833,9 +850,9 @@ void DIALOG_PLOT::Plot( wxCommandEvent& event )
if( m_plotOpts.GetFormat() == PLOT_FORMAT_GERBER && m_useGerberExtensions->GetValue() )
file_ext = GetGerberProtelExtension( layer );
BuildPlotFileName( &fn, outputDir.GetPath(),
m_board->GetLayerName( layer ),
file_ext );
BuildPlotFileName( &fn, outputDir.GetPath(), m_board->GetLayerName( layer ), file_ext );
wxString fullname = fn.GetFullName();
jobfile_writer.AddGbrFile( layer, fullname );
LOCALE_IO toggle;
@ -861,10 +878,14 @@ void DIALOG_PLOT::Plot( wxCommandEvent& event )
}
}
// If no layer selected, we have nothing plotted.
// Prompt user if it happens because he could think there is a bug in Pcbnew.
if( !m_plotOpts.GetLayerSelection().any() )
DisplayError( this, _( "No layer selected" ) );
if( m_plotOpts.GetFormat() == PLOT_FORMAT_GERBER && m_plotOpts.GetCreateGerberJobFile() )
{
// Pick the basename from the board file
wxFileName fn( boardFilename );
// Build gerber job file from basename
BuildPlotFileName( &fn, outputDir.GetPath(), "job", GerberJobFileExtension );
jobfile_writer.CreateJobFile( fn.GetFullPath() );
}
}
#include <drc_stuff.h>

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Jul 2 2017)
// C++ code generated with wxFormBuilder (version May 6 2016)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
@ -238,6 +238,11 @@ DIALOG_PLOT_BASE::DIALOG_PLOT_BASE( wxWindow* parent, wxWindowID id, const wxStr
bSizerGbrOpt->Add( m_useGerberNetAttributes, 0, wxALL, 2 );
m_generateGerberJobFile = new wxCheckBox( m_GerberOptionsSizer->GetStaticBox(), wxID_ANY, _("Generate Gerber job file"), wxDefaultPosition, wxDefaultSize, 0 );
m_generateGerberJobFile->SetToolTip( _("Generate a Gerber job file that contains info about the board,\nand the list of generated Gerber plot files") );
bSizerGbrOpt->Add( m_generateGerberJobFile, 0, wxALL, 2 );
m_subtractMaskFromSilk = new wxCheckBox( m_GerberOptionsSizer->GetStaticBox(), wxID_ANY, _("Subtract soldermask from silkscreen"), wxDefaultPosition, wxDefaultSize, 0 );
m_subtractMaskFromSilk->SetToolTip( _("Remove silkscreen from areas without soldermask") );

View File

@ -2958,6 +2958,94 @@
<event name="OnUpdateUI"></event>
</object>
</object>
<object class="sizeritem" expanded="1">
<property name="border">2</property>
<property name="flag">wxALL</property>
<property name="proportion">0</property>
<object class="wxCheckBox" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="checked">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Generate Gerber job file</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_generateGerberJobFile</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass"></property>
<property name="toolbar_pane">0</property>
<property name="tooltip">Generate a Gerber job file that contains info about the board,&#x0A;and the list of generated Gerber plot files</property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnChar"></event>
<event name="OnCheckBox"></event>
<event name="OnEnterWindow"></event>
<event name="OnEraseBackground"></event>
<event name="OnKeyDown"></event>
<event name="OnKeyUp"></event>
<event name="OnKillFocus"></event>
<event name="OnLeaveWindow"></event>
<event name="OnLeftDClick"></event>
<event name="OnLeftDown"></event>
<event name="OnLeftUp"></event>
<event name="OnMiddleDClick"></event>
<event name="OnMiddleDown"></event>
<event name="OnMiddleUp"></event>
<event name="OnMotion"></event>
<event name="OnMouseEvents"></event>
<event name="OnMouseWheel"></event>
<event name="OnPaint"></event>
<event name="OnRightDClick"></event>
<event name="OnRightDown"></event>
<event name="OnRightUp"></event>
<event name="OnSetFocus"></event>
<event name="OnSize"></event>
<event name="OnUpdateUI"></event>
</object>
</object>
<object class="sizeritem" expanded="0">
<property name="border">2</property>
<property name="flag">wxALL</property>

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version Jul 2 2017)
// C++ code generated with wxFormBuilder (version May 6 2016)
// http://www.wxformbuilder.org/
//
// PLEASE DO "NOT" EDIT THIS FILE!
@ -94,6 +94,7 @@ class DIALOG_PLOT_BASE : public DIALOG_SHIM
wxCheckBox* m_useGerberExtensions;
wxCheckBox* m_useGerberX2Attributes;
wxCheckBox* m_useGerberNetAttributes;
wxCheckBox* m_generateGerberJobFile;
wxCheckBox* m_subtractMaskFromSilk;
wxRadioBox* m_rbGerberFormat;
wxStaticBoxSizer* m_HPGLOptionsSizer;

View File

@ -0,0 +1,388 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2017 Jean_Pierre Charras <jp.charras at wanadoo.fr>
* Copyright (C) 1992-2017 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 gendrill_gerber_writer.cpp
* @brief Functions to create drill files in gerber X2 format.
*/
#include <fctsys.h>
#include <vector>
#include <plot_common.h>
#include <wxPcbStruct.h>
#include <build_version.h>
#include <class_board.h>
#include <class_zone.h>
#include <class_module.h>
#include <pcbplot.h>
#include <pcbnew.h>
#include <gerber_jobfile_writer.h>
#include <wildcards_and_files_ext.h>
#include <reporter.h>
#include <plot_auxiliary_data.h>
GERBER_JOBFILE_WRITER::GERBER_JOBFILE_WRITER( BOARD* aPcb, REPORTER* aReporter )
{
m_pcb = aPcb;
m_reporter = aReporter;
m_conversionUnits = 1.0 / IU_PER_MM; // Gerber units = mm
}
enum ONSIDE GERBER_JOBFILE_WRITER::hasSilkLayers()
{
int flag = SIDE_NONE;
for( unsigned ii = 0; ii < m_params.m_LayerId.size(); ii++ )
{
if( m_params.m_LayerId[ii] == B_SilkS )
flag |= SIDE_BOTTOM;
if( m_params.m_LayerId[ii] == F_SilkS )
flag |= SIDE_TOP;
}
return (enum ONSIDE)flag;
}
enum ONSIDE GERBER_JOBFILE_WRITER::hasSolderMasks()
{
int flag = SIDE_NONE;
for( unsigned ii = 0; ii < m_params.m_LayerId.size(); ii++ )
{
if( m_params.m_LayerId[ii] == B_Mask )
flag |= SIDE_BOTTOM;
if( m_params.m_LayerId[ii] == F_Mask )
flag |= SIDE_TOP;
}
return (enum ONSIDE)flag;
}
const char* GERBER_JOBFILE_WRITER::sideKeyValue( enum ONSIDE aValue )
{
// return the key associated to sides used for some layers
// "No, TopOnly, BotOnly or Both"
const char* value = nullptr;
switch( aValue )
{
case SIDE_NONE:
value = "No"; break;
case SIDE_TOP:
value = "TopOnly"; break;
case SIDE_BOTTOM:
value = "BotOnly"; break;
case SIDE_BOTH:
value = "Both"; break;
}
return value;
}
extern void BuildGerberX2Header( const BOARD *aBoard, wxArrayString& aHeader );
bool GERBER_JOBFILE_WRITER::CreateJobFile( const wxString& aFullFilename )
{
// Note: in Gerber job file, dimensions are in mm, and are floating numbers
FILE* jobFile = wxFopen( aFullFilename, "wt" );
wxString msg;
if( jobFile == nullptr )
{
if( m_reporter )
{
msg.Printf( _( "Unable to create job file '%s'" ), aFullFilename );
m_reporter->Report( msg, REPORTER::RPT_ERROR );
}
return false;
}
LOCALE_IO dummy;
// output the job file header
bool hasInnerLayers = m_pcb->GetCopperLayerCount() > 2;
wxArrayString header;
fputs( "G04 Gerber job file with board parameters*\n"
"%TF.FileFunction,JobInfo*%\n"
"%TF.Part,SinglePCB*%\n", jobFile );
fputs( "G04 Single PCB fabrication instructions*\n", jobFile );
BuildGerberX2Header( m_pcb, header );
for( unsigned ii = 0; ii < header.GetCount(); ii++ )
{
if( header[ii].Contains( "TF.SameCoordinates" ) )
continue; // This attribute is not useful in job file, skip it
fputs( header[ii], jobFile );
fputs( "\n", jobFile );
}
fputs( "%MOMM*%\n", jobFile );
fputs( "G04 Overall board parameters*\n", jobFile );
// output the bord size in mm:
EDA_RECT brect = m_pcb->GetBoardEdgesBoundingBox();
fprintf( jobFile, "%%TJ.B.Size.X,%.3f*%%\n", brect.GetWidth()*m_conversionUnits );
fprintf( jobFile, "%%TJ.B.Size.Y,%.3f*%%\n", brect.GetHeight()*m_conversionUnits );
// number of copper layers
fprintf( jobFile, "%%TJ.B.LayerNum,%d*%%\n", m_pcb->GetCopperLayerCount() );
// Board thickness
fprintf( jobFile, "%%TJ.B.Overall.Thickness,%.3f*%%\n",
m_pcb->GetDesignSettings().GetBoardThickness()*m_conversionUnits );
fprintf( jobFile, "%%TJ.B.Legend.Present,%s*%%\n", sideKeyValue( hasSilkLayers() ) );
fprintf( jobFile, "%%TJ.B.SolderMask.Present,%s*%%\n", sideKeyValue( hasSolderMasks() ) );
// Job file support a few design rules:
fputs( "G04 board design rules*\n", jobFile );
const BOARD_DESIGN_SETTINGS& dsnSettings = m_pcb->GetDesignSettings();
NETCLASS defaultNC = *dsnSettings.GetDefault();
int minclearanceOuter = defaultNC.GetClearance();
// Search a smaller clearance in other net classes, if any.
for( NETCLASSES::const_iterator it = dsnSettings.m_NetClasses.begin();
it != dsnSettings.m_NetClasses.end();
++it )
{
NETCLASS netclass = *it->second;
minclearanceOuter = std::min( minclearanceOuter, netclass.GetClearance() );
}
// job file knows different clearance types.
// Kicad knows only one clearance for pads and tracks
// However, pads can have a specific clearance defined for a pad or a footprint,
// and min clearance can be dependent on layers.
// Search for a minimal pad clearance:
int minPadClearanceOuter = defaultNC.GetClearance();
int minPadClearanceInner = defaultNC.GetClearance();
for( MODULE* module : m_pcb->Modules() )
{
for( auto& pad : module->Pads() )
{
if( ( pad->GetLayerSet() & LSET::InternalCuMask() ).any() )
minPadClearanceInner = std::min( minPadClearanceInner, pad->GetClearance() );
if( ( pad->GetLayerSet() & LSET::ExternalCuMask() ).any() )
minPadClearanceOuter = std::min( minPadClearanceOuter, pad->GetClearance() );
}
}
fprintf( jobFile, "%%TJ.D.PadToPad.Outer,%.3f*%%\n", minPadClearanceOuter*m_conversionUnits );
if( hasInnerLayers )
fprintf( jobFile, "%%TJ.D.PadToPad.Inner,%.3f*%%\n", minPadClearanceInner*m_conversionUnits );
fprintf( jobFile, "%%TJ.D.PadToTrack.Outer,%.3f*%%\n", minPadClearanceOuter*m_conversionUnits );
if( hasInnerLayers )
fprintf( jobFile, "%%TJ.D.PadToTrack.Inner,%.3f*%%\n", minPadClearanceInner*m_conversionUnits );
// Until this is changed in Kicad, use the same value for internal tracks
int minclearanceInner = minclearanceOuter;
fprintf( jobFile, "%%TJ.D.TrackToTrack.Outer,%.3f*%%\n", minclearanceOuter*m_conversionUnits );
if( hasInnerLayers )
fprintf( jobFile, "%%TJ.D.TrackToTrack.Inner,%.3f*%%\n", minclearanceInner*m_conversionUnits );
// Output the minimal track width
int mintrackWidthOuter = INT_MAX;
int mintrackWidthInner = INT_MAX;
for( TRACK* track : m_pcb->Tracks() )
{
if( track->Type() == PCB_VIA_T )
continue;
if( track->GetLayer() == B_Cu || track->GetLayer() == F_Cu )
mintrackWidthOuter = std::min( mintrackWidthOuter, track->GetWidth() );
else
mintrackWidthInner = std::min( mintrackWidthInner, track->GetWidth() );
}
if( mintrackWidthOuter != INT_MAX )
fprintf( jobFile, "%%TJ.D.MinLineWidth.Outer,%.3f*%%\n", mintrackWidthOuter*m_conversionUnits );
if( mintrackWidthInner != INT_MAX )
fprintf( jobFile, "%%TJ.D.MinLineWidth.Inner,%.3f*%%\n", mintrackWidthInner*m_conversionUnits );
// Output the minimal zone to xx clearance
// Note: zones can have a zone clearance set to 0
// if happens, the actual zone clearance is the clearance of its class
minclearanceOuter = INT_MAX;
minclearanceInner = INT_MAX;
for( int ii = 0; ii < m_pcb->GetAreaCount(); ii++ )
{
ZONE_CONTAINER* zone = m_pcb->GetArea( ii );
if( zone->GetIsKeepout() || !zone->IsOnCopperLayer() )
continue;
int zclerance = zone->GetClearance();
if( zone->GetLayer() == B_Cu || zone->GetLayer() == F_Cu )
minclearanceOuter = std::min( minclearanceOuter, zclerance );
else
minclearanceInner = std::min( minclearanceInner, zclerance );
}
if( minclearanceOuter != INT_MAX )
fprintf( jobFile, "%%TJ.D.TrackToRegion.Outer,%.3f*%%\n", minclearanceOuter*m_conversionUnits );
if( hasInnerLayers && minclearanceInner != INT_MAX )
fprintf( jobFile, "%%TJ.D.TrackToRegion.Inner,%.3f*%%\n", minclearanceInner*m_conversionUnits );
if( minclearanceOuter != INT_MAX )
fprintf( jobFile, "%%TJ.D.RegionToRegion.Outer,%.3f*%%\n", minclearanceOuter*m_conversionUnits );
if( hasInnerLayers && minclearanceInner != INT_MAX )
fprintf( jobFile, "%%TJ.D.RegionToRegion.Inner,%.3f*%%\n", minclearanceInner*m_conversionUnits );
// output the gerber file list:
fputs( "G04 Layer Structure*\n", jobFile );
for( unsigned ii = 0; ii < m_params.m_GerberFileList.GetCount(); ii ++ )
{
wxString& name = m_params.m_GerberFileList[ii];
PCB_LAYER_ID layer = m_params.m_LayerId[ii];
wxString gbr_layer_id;
bool skip_file = false; // true to skip files which should not be in job file
const char* polarity = "Positive";
if( layer <= B_Cu )
{
gbr_layer_id = "Copper,L";
if( layer == B_Cu )
gbr_layer_id << m_pcb->GetCopperLayerCount();
else
gbr_layer_id << layer+1;
gbr_layer_id << ",";
if( layer == B_Cu )
gbr_layer_id << "Bottom";
else if( layer == F_Cu )
gbr_layer_id << "Top";
else
gbr_layer_id << "Inner";
}
else
{
switch( layer )
{
case B_Adhes:
gbr_layer_id = "Glue,Bottom"; break;
case F_Adhes:
gbr_layer_id = "Glue,Top"; break;
case B_Paste:
gbr_layer_id = "SolderPaste,Bottom"; break;
case F_Paste:
gbr_layer_id = "SolderPaste,Top"; break;
case B_SilkS:
gbr_layer_id = "Legend,Bottom"; break;
case F_SilkS:
gbr_layer_id = "Legend,Top"; break;
case B_Mask:
gbr_layer_id = "SolderMask,Bottom"; polarity = "Negative"; break;
case F_Mask:
gbr_layer_id = "SolderMask,Top"; polarity = "Negative"; break;
case Edge_Cuts:
gbr_layer_id = "Profile"; break;
case B_Fab:
gbr_layer_id = "AssemblyDrawing,Bottom"; break;
case F_Fab:
gbr_layer_id = "AssemblyDrawing,Top"; break;
case Dwgs_User:
case Cmts_User:
case Eco1_User:
case Eco2_User:
case Margin:
case B_CrtYd:
case F_CrtYd:
skip_file = true; break;
default:
skip_file = true;
m_reporter->Report( "Unexpected layer id in job file",
REPORTER::RPT_ERROR );
break;
}
}
if( !skip_file )
{
// name can contain non ASCII7 chars.
// Only ASCII7 chars are accepted in gerber files. others must be converted to
// a gerber hexa sequence.
std::string strname = formatStringToGerber( name );
fprintf( jobFile, "%%TJ.L.\"%s\",%s,%s*%%\n", TO_UTF8( gbr_layer_id ),
polarity, strname.c_str() );
}
}
// Close job file
fputs( "M02*\n", jobFile );
fclose( jobFile );
if( m_reporter )
{
msg.Printf( _( "Create Gerber job file '%s'" ), aFullFilename );
m_reporter->Report( msg, REPORTER::RPT_ACTION );
}
return true;
}

View File

@ -0,0 +1,125 @@
/**
* @file gerber_jobfile_writer.h
* @brief Classes used in drill files, map files and report files generation.
*/
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 1992-2017 Jean_Pierre Charras <jp.charras at wanadoo.fr>
* Copyright (C) 1992-2017 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
*/
#ifndef GERBER_JOBFILE_WRITER_H
#define GERBER_JOBFILE_WRITER_H
// A helper enum to handle sides of some layers (silk, mask)
enum ONSIDE
{
SIDE_NONE = 0, // layers not present
SIDE_TOP = 1, // top layer only
SIDE_BOTTOM = 2, // bottom layer only
SIDE_BOTH = SIDE_TOP|SIDE_BOTTOM // both layers
};
class BOARD;
/**
* class JOBFILE_PARAMS store the list of parameters written in Gerber job file
* especialy list of .gbr filenames and the corresponding layer id belonging the job
*/
class JOBFILE_PARAMS
{
public:
wxArrayString m_GerberFileList; // the list of gerber filenames (without path)
std::vector<PCB_LAYER_ID> m_LayerId; // the list of corresponding layer id
};
/**
* GERBER_JOBFILE_WRITER is a class used to create Gerber job file
* a Gerber job file stores info to make a board:
* list of gerber files
* info about the board itsel:
* size, number of copper layers
* thickness of the board, copper and dielectric
* and some other info (colors, finish type ...)
*
* note: dimensions are always in mm in Kicad job file (can be also in inches in a job file)
* and they are in floating point notation
*/
class GERBER_JOBFILE_WRITER
{
public:
GERBER_JOBFILE_WRITER( BOARD* aPcb, REPORTER* aReporter = nullptr );
virtual ~GERBER_JOBFILE_WRITER()
{
}
/**
* add a gerber file name and type in job file list
* @param aLayer is the PCB_LAYER_ID corresponding to the gerber file
* @param aFilename is the filename (without path) of the gerber file
*/
void AddGbrFile( PCB_LAYER_ID aLayer, wxString& aFilename )
{
m_params.m_GerberFileList.Add( aFilename );
m_params.m_LayerId.push_back( aLayer );
}
/**
* Creates an Excellon drill file
* @param aFullFilename = the full filename
* @param aParams = true for a NPTH file, false for a PTH file
* @return true, or false if the file cannot be created
*/
bool CreateJobFile( const wxString& aFullFilename );
private:
/** @return SIDE_NONE if no silk screen layer is in list
* SIDE_TOP if top silk screen layer is in list
* SIDE_BOTTOM if bottom silk screen layer is in list
* SIDE_BOTH if top and bottom silk screen layers are in list
*/
enum ONSIDE hasSilkLayers();
/** @return SIDE_NONE if no soldermask layer is in list
* SIDE_TOP if top soldermask layer is in list
* SIDE_BOTTOM if bottom soldermask layer is in list
* SIDE_BOTH if top and bottom soldermask layers are in list
*/
enum ONSIDE hasSolderMasks();
/** @return the key associated to sides used for some layers
* No TopOnly BotOnly Both
*/
const char* sideKeyValue( enum ONSIDE aValue );
private:
BOARD* m_pcb; // The board
REPORTER* m_reporter; // a reporter for messages (can be null)
JOBFILE_PARAMS m_params; // the list of various prms and data to write in a job file
double m_conversionUnits; // scaling factor to convert brd units to gerber units (mm)
};
#endif // #ifndef GERBER_JOBFILE_WRITER_H

View File

@ -82,6 +82,7 @@ PCB_PLOT_PARAMS::PCB_PLOT_PARAMS()
m_useGerberProtelExtensions = false;
m_useGerberAttributes = false;
m_includeGerberNetlistInfo = false;
m_createGerberJobFile = false;
m_gerberPrecision = gbrDefaultPrecision;
m_excludeEdgeLayer = true;
m_lineWidth = g_DrawDefaultLineThickness;
@ -146,14 +147,11 @@ void PCB_PLOT_PARAMS::Format( OUTPUTFORMATTER* aFormatter,
aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_usegerberextensions ),
m_useGerberProtelExtensions ? trueStr : falseStr );
if( m_useGerberAttributes ) // save this option only if active,
// to avoid incompatibility with older Pcbnew version
{
aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_usegerberattributes ), trueStr );
aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_usegerberattributes ), trueStr );
if( GetIncludeGerberNetlistInfo() )
aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_usegerberadvancedattributes ), trueStr );
}
aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_usegerberadvancedattributes ), trueStr );
aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_creategerberjobfile ), trueStr );
if( m_gerberPrecision != gbrDefaultPrecision ) // save this option only if it is not the default value,
// to avoid incompatibility with older Pcbnew version
@ -228,6 +226,8 @@ bool PCB_PLOT_PARAMS::IsSameAs( const PCB_PLOT_PARAMS &aPcbPlotParams, bool aCom
return false;
if( m_useGerberAttributes && m_includeGerberNetlistInfo != aPcbPlotParams.m_includeGerberNetlistInfo )
return false;
if( m_createGerberJobFile != aPcbPlotParams.m_createGerberJobFile )
return false;
if( m_gerberPrecision != aPcbPlotParams.m_gerberPrecision )
return false;
if( m_excludeEdgeLayer != aPcbPlotParams.m_excludeEdgeLayer )
@ -392,6 +392,10 @@ void PCB_PLOT_PARAMS_PARSER::Parse( PCB_PLOT_PARAMS* aPcbPlotParams )
aPcbPlotParams->m_includeGerberNetlistInfo = parseBool();
break;
case T_creategerberjobfile:
aPcbPlotParams->m_createGerberJobFile = parseBool();
break;
case T_gerberprecision:
aPcbPlotParams->m_gerberPrecision =
parseInt( gbrDefaultPrecision-1, gbrDefaultPrecision);

View File

@ -108,6 +108,9 @@ private:
/// Include netlist info (only in Gerber X2 format) (chapter ? in revision ?)
bool m_includeGerberNetlistInfo;
/// generate the auxiliary "job file" in gerber format
bool m_createGerberJobFile;
/// precision of coordinates in Gerber files: accepted 5 or 6
/// when units are in mm (6 or 7 in inches, but Pcbnew uses mm).
/// 6 is the internal resolution of Pcbnew, but not alwys accepted by board maker
@ -245,6 +248,9 @@ public:
void SetIncludeGerberNetlistInfo( bool aUse ) { m_includeGerberNetlistInfo = aUse; }
bool GetIncludeGerberNetlistInfo() const { return m_includeGerberNetlistInfo; }
void SetCreateGerberJobFile( bool aCreate ) { m_createGerberJobFile = aCreate; }
bool GetCreateGerberJobFile() const { return m_createGerberJobFile; }
void SetUseGerberProtelExtensions( bool aUse ) { m_useGerberProtelExtensions = aUse; }
bool GetUseGerberProtelExtensions() const { return m_useGerberProtelExtensions; }

View File

@ -270,6 +270,102 @@ static wxString& makeStringCompatX1( wxString& aText, bool aUseX1CompatibilityMo
}
void BuildGerberX2Header( const BOARD *aBoard, wxArrayString& aHeader )
{
wxString text;
// Creates the TF,.GenerationSoftware. Format is:
// %TF,.GenerationSoftware,<vendor>,<application name>[,<application version>]*%
text.Printf( wxT( "%%TF.GenerationSoftware,KiCad,Pcbnew,%s*%%" ), GetBuildVersion() );
aHeader.Add( text );
// creates the TF.CreationDate ext:
// The attribute value must conform to the full version of the ISO 8601
// date and time format, including time and time zone. Note that this is
// the date the Gerber file was effectively created,
// not the time the project of PCB was started
wxDateTime date( wxDateTime::GetTimeNow() );
// Date format: see http://www.cplusplus.com/reference/ctime/strftime
wxString msg = date.Format( wxT( "%z" ) ); // Extract the time zone offset
// The time zone offset format is + (or -) mm or hhmm (mm = number of minutes, hh = number of hours)
// we want +(or -) hh:mm
if( msg.Len() > 3 )
msg.insert( 3, ":", 1 ),
text.Printf( wxT( "%%TF.CreationDate,%s%s*%%" ), GetChars( date.FormatISOCombined() ), GetChars( msg ) );
aHeader.Add( text );
// Creates the TF,.ProjectId. Format is (from Gerber file format doc):
// %TF.ProjectId,<project id>,<project GUID>,<revision id>*%
// <project id> is the name of the project, restricted to basic ASCII symbols only,
// and comma not accepted
// All illegal chars will be replaced by underscore
// <project GUID> is a 32 hexadecimal digits string which is an unique id of a project.
// This is a random 128-bit number expressed in 32 hexadecimal digits.
// See en.wikipedia.org/wiki/GUID for more information
// However Kicad does not handle such a project GUID, so it is built from the board name
// Rem: <project id> accepts only ASCII 7 code (only basic ASCII codes are allowed in gerber files).
wxFileName fn = aBoard->GetFileName();
msg = fn.GetFullName();
wxString guid;
// Build a 32 digits GUID from the board name:
for( unsigned ii = 0; ii < msg.Len(); ii++ )
{
int cc1 = int( msg[ii] ) & 0x0F;
int cc2 = ( int( msg[ii] ) >> 4) & 0x0F;
guid << wxString::Format( wxT( "%X%X" ), cc2, cc1 );
if( guid.Len() >= 32 )
break;
}
// guid has 32 digits, so add missing digits
int cnt = 32 - guid.Len();
if( cnt > 0 )
guid.Append( '0', cnt );
// build the <project id> string: this is the board short filename (without ext)
// and all non ASCII chars and comma are replaced by '_'
msg = fn.GetName();
msg.Replace( wxT( "," ), wxT( "_" ) );
// build the <rec> string. All non ASCII chars and comma are replaced by '_'
wxString rev = ((BOARD*)aBoard)->GetTitleBlock().GetRevision();
rev.Replace( wxT( "," ), wxT( "_" ) );
if( rev.IsEmpty() )
rev = wxT( "rev?" );
text.Printf( wxT( "%%TF.ProjectId,%s,%s,%s*%%" ), msg.ToAscii(), GetChars( guid ), rev.ToAscii() );
aHeader.Add( text );
// Add the TF.SameCoordinates, that specify all gerber files uses the same
// origin and orientation, and the registration between files is OK.
// The parameter of TF.SameCoordinates is a string that is common
// to all files using the same registration and has no special meaning:
// this is just a key
// Because there is no mirroring/rotation in Kicad, only the plot offset origin
// can create incorrect registration.
// So we create a key from plot offset options.
// and therefore for a given board, all Gerber files having the same key have the same
// plot origin and use the same registration
//
// Currently the key is "Original" when using absolute Pcbnew coordinates,
// and te PY ans PY position od auxiliary axis, when using it.
// Please, if absolute Pcbnew coordinates, one day, are set by user, change the way
// the key is built to ensure file only using the *same* axis have the same key.
wxString registration_id = "Original";
wxPoint auxOrigin = aBoard->GetAuxOrigin();
if( aBoard->GetPlotOptions().GetUseAuxOrigin() && auxOrigin.x && auxOrigin.y )
registration_id.Printf( "PX%xPY%x", auxOrigin.x, auxOrigin.y );
text.Printf( "%%TF.SameCoordinates,%s*%%", registration_id.GetData() );
aHeader.Add( text );
}
void AddGerberX2Header( PLOTTER * aPlotter,
const BOARD *aBoard, bool aUseX1CompatibilityMode )
{