Undo changes from my last commit that caused a trace drag bug.

This commit is contained in:
Wayne Stambaugh 2011-09-14 11:08:44 -04:00
parent 134a935376
commit cb78c9452b
41 changed files with 2182 additions and 1807 deletions

View File

@ -8,19 +8,32 @@
static const 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, 0x00, 0xb1, 0x49, 0x44, 0x41, 0x54, 0x48, 0xc7, 0x63, 0xf8, 0xff, 0xff, 0x3f,
0x03, 0x3d, 0x30, 0x82, 0xd1, 0xc0, 0xc0, 0x24, 0x50, 0x20, 0x20, 0x40, 0x4d, 0xcc, 0x90, 0xc6,
0xc0, 0x8a, 0x61, 0x91, 0x50, 0x01, 0xd7, 0x6e, 0xa1, 0x7c, 0xce, 0x2f, 0x42, 0x05, 0x9c, 0x9f,
0xa8, 0x86, 0x73, 0x38, 0x9f, 0x30, 0x84, 0x32, 0xb0, 0xc1, 0x2d, 0x12, 0x49, 0x62, 0xe0, 0x15,
0xcc, 0xe1, 0xfc, 0xa1, 0x74, 0x56, 0xe8, 0xbf, 0xd2, 0x39, 0xea, 0x61, 0x91, 0x3a, 0xee, 0x77,
0x82, 0x99, 0x1c, 0xb6, 0x70, 0x8b, 0x40, 0xde, 0x14, 0xca, 0xe3, 0xfc, 0x46, 0x4d, 0x4b, 0x40,
0x58, 0xb4, 0x99, 0xe7, 0x9d, 0x40, 0x06, 0x87, 0xc3, 0xa8, 0x45, 0xa3, 0x16, 0x8d, 0x5a, 0x34,
0x6a, 0xd1, 0xa8, 0x45, 0xa3, 0x16, 0x8d, 0x4c, 0x8b, 0x04, 0xd3, 0x04, 0xf9, 0x69, 0x62, 0x51,
0x13, 0xd0, 0xa2, 0x4c, 0x0e, 0x7b, 0xb8, 0x45, 0x40, 0xc0, 0x08, 0xb4, 0xe8, 0xbe, 0x58, 0x3b,
0xcf, 0x27, 0xb1, 0x2e, 0x9e, 0x0f, 0xd4, 0xc2, 0x42, 0xb9, 0x5c, 0x1f, 0x79, 0xb3, 0x79, 0x85,
0x51, 0x5b, 0x41, 0x59, 0x9c, 0xb2, 0x02, 0x99, 0x5c, 0x01, 0xd4, 0xc4, 0x82, 0x99, 0xdc, 0x7a,
0x18, 0xcd, 0x2d, 0x5a, 0x63, 0x00, 0xe2, 0xb1, 0x17, 0xfe, 0x13, 0xe0, 0x61, 0xbb, 0x00, 0x00,
0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82,
0xce, 0x00, 0x00, 0x00, 0x09, 0x76, 0x70, 0x41, 0x67, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x00,
0x1a, 0x00, 0x07, 0xb2, 0x66, 0x2f, 0x00, 0x00, 0x01, 0x64, 0x49, 0x44, 0x41, 0x54, 0x48, 0xc7,
0xd5, 0x96, 0xb1, 0x4e, 0x02, 0x41, 0x10, 0x86, 0xbf, 0xb9, 0xbb, 0xa5, 0x38, 0xa3, 0x31, 0x21,
0xda, 0x28, 0x34, 0x1a, 0xe9, 0xa4, 0x35, 0x3c, 0x03, 0xa1, 0xb1, 0xb2, 0xb0, 0xf7, 0x21, 0xe4,
0x11, 0x78, 0x05, 0x0b, 0x5e, 0x81, 0xc6, 0xc6, 0x52, 0x63, 0x30, 0x34, 0x24, 0x58, 0x99, 0xa0,
0x84, 0x82, 0xc4, 0x12, 0x84, 0x53, 0xb8, 0x1d, 0x0b, 0x90, 0x28, 0x9c, 0xd1, 0x18, 0xee, 0x12,
0xff, 0x6e, 0x27, 0x9b, 0xf9, 0xb2, 0xff, 0xec, 0xce, 0x8e, 0x00, 0x04, 0x41, 0x50, 0x02, 0xca,
0x02, 0x79, 0x44, 0x0c, 0x9f, 0x24, 0x00, 0x22, 0x7c, 0x89, 0x2d, 0xac, 0xbf, 0x51, 0x08, 0xb4,
0x80, 0x8a, 0x31, 0xa6, 0x2a, 0xa3, 0xd1, 0xa8, 0x08, 0xd4, 0x54, 0x2d, 0xfd, 0xd7, 0xc1, 0xd2,
0xee, 0x48, 0xd0, 0x2f, 0xe1, 0x7e, 0xca, 0xc7, 0xb8, 0x06, 0xe0, 0x4c, 0x86, 0xc3, 0xe1, 0x35,
0x50, 0x38, 0xb9, 0x38, 0xa6, 0xf1, 0x54, 0xc7, 0x71, 0x1c, 0x56, 0xa5, 0x75, 0x6f, 0x83, 0xfa,
0x79, 0x93, 0x94, 0x97, 0xea, 0x7a, 0x6a, 0xed, 0xe1, 0xcb, 0xdb, 0x0b, 0xb7, 0x0f, 0x37, 0xac,
0x9d, 0xba, 0x20, 0xe1, 0xca, 0x40, 0xc1, 0x65, 0x40, 0xe3, 0xf1, 0x8e, 0xa3, 0xbd, 0xc2, 0xae,
0xa3, 0xaa, 0x66, 0x62, 0x43, 0x5c, 0xd7, 0x99, 0x79, 0xb2, 0x3a, 0x89, 0x11, 0x42, 0x1b, 0xa2,
0xaa, 0x38, 0xaa, 0x8a, 0xaa, 0x12, 0x97, 0x3e, 0xf2, 0x4f, 0x41, 0xd6, 0x26, 0x04, 0x4a, 0xea,
0x44, 0xc4, 0x06, 0x9a, 0xe6, 0x8e, 0xff, 0x44, 0x1a, 0x65, 0x9d, 0xc6, 0x68, 0x9d, 0xb5, 0x09,
0xd4, 0x68, 0x06, 0x8b, 0x1d, 0x34, 0xaf, 0x11, 0x89, 0xbe, 0xa3, 0x44, 0x40, 0xd6, 0xc6, 0x06,
0xd2, 0xa5, 0x1a, 0x41, 0xac, 0x35, 0x22, 0xf9, 0xce, 0x90, 0x64, 0xaf, 0xd3, 0xff, 0x7e, 0xeb,
0x48, 0x14, 0x34, 0x6b, 0x41, 0xe3, 0x18, 0x7d, 0x9b, 0xdb, 0xe7, 0xa9, 0x6a, 0xd3, 0x37, 0x7e,
0x21, 0xed, 0xa7, 0x19, 0x5c, 0xf5, 0x71, 0x3c, 0x89, 0x9a, 0x83, 0xfe, 0xa4, 0xf1, 0xf3, 0x84,
0xfd, 0xad, 0x03, 0x54, 0xb5, 0x2b, 0x9d, 0x76, 0xbb, 0x08, 0xd4, 0x7a, 0xfd, 0x1e, 0xf7, 0xbd,
0x56, 0xc4, 0xc7, 0x2f, 0x11, 0xa8, 0x08, 0xb8, 0x2c, 0x44, 0x45, 0xc8, 0x6c, 0x66, 0xc8, 0x6d,
0xe7, 0xa6, 0xe3, 0x16, 0x40, 0xa7, 0xdd, 0x2e, 0x01, 0x65, 0x20, 0x0f, 0x98, 0x9f, 0xa7, 0x8e,
0x08, 0xf8, 0x62, 0x4c, 0x24, 0x04, 0x5a, 0x02, 0x95, 0x9d, 0x6c, 0xb6, 0xfa, 0x0e, 0x74, 0x04,
0x22, 0x77, 0x71, 0x16, 0xc1, 0x16, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42,
0x60, 0x82,
};
const BITMAP_OPAQUE erc_green_xpm[1] = {{ png, sizeof( png ), "erc_green_xpm" }};

View File

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

View File

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

View File

@ -59,7 +59,7 @@ DISPLAY_FOOTPRINTS_FRAME::DISPLAY_FOOTPRINTS_FRAME( CVPCB_MAINFRAME* father,
icon.CopyFromBitmap( KiBitmap( icon_cvpcb_xpm ) );
SetIcon( icon );
SetBoard( new BOARD( NULL ) );
SetBoard( new BOARD( NULL, this ) );
SetScreen( new PCB_SCREEN() );
LoadSettings();
@ -68,7 +68,6 @@ DISPLAY_FOOTPRINTS_FRAME::DISPLAY_FOOTPRINTS_FRAME( CVPCB_MAINFRAME* father,
if( (m_LastGridSizeId <= 0) ||
(m_LastGridSizeId > (ID_POPUP_GRID_USER - ID_POPUP_GRID_LEVEL_1000)) )
m_LastGridSizeId = ID_POPUP_GRID_LEVEL_500 - ID_POPUP_GRID_LEVEL_1000;
GetScreen()->SetGrid( ID_POPUP_GRID_LEVEL_1000 + m_LastGridSizeId );
// Initialize some display options

View File

@ -41,11 +41,10 @@
#include "class_GERBER.h"
#define SHOW_BOUNDING_BOX 0 // Set to 1 to draw the bounding box for debugging purposes.
/**********************************************************/
GERBER_DRAW_ITEM::GERBER_DRAW_ITEM( BOARD_ITEM* aParent, GERBER_IMAGE* aGerberparams ) :
BOARD_ITEM( aParent, TYPE_GERBER_DRAW_ITEM )
/**********************************************************/
{
m_imageParams = aGerberparams;
m_Layer = 0;
@ -340,8 +339,10 @@ bool GERBER_DRAW_ITEM::HasNegativeItems()
}
/*********************************************************************/
void GERBER_DRAW_ITEM::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, int aDrawMode,
const wxPoint& aOffset )
/*********************************************************************/
{
static D_CODE dummyD_CODE( 0 ); // used when a D_CODE is not found. default D_CODE to draw a flashed item
int color, alt_color;
@ -485,14 +486,6 @@ void GERBER_DRAW_ITEM::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, int aDrawMode,
}
break;
}
#if SHOW_BOUNDING_BOX
/* Draw the component boundary box */
{
EDA_RECT boundaryBox = GetBoundingBox();
GRRect( &aPanel->m_ClipBox, aDC, boundaryBox, 0, BROWN );
}
#endif
}
/**

View File

@ -139,7 +139,6 @@ void BOARD::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, int aDrawMode, const wxPoin
// this is due to negative objects (drawn using background color) that create artefacct
// on other images when drawn on screen
bool useBufferBitmap = false;
if( (aDrawMode == GR_COPY) || ( aDrawMode == GR_OR ) )
useBufferBitmap = true;
@ -174,11 +173,9 @@ void BOARD::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, int aDrawMode, const wxPoin
bool doBlit = false; // this flag requests an image transfert to actual screen when true.
bool end = false;
for( int layer = 0; !end; layer++ )
{
int active_layer = ( (GERBVIEW_FRAME*) aPanel->GetParent() )->getActiveLayer();
int active_layer = ( (GERBVIEW_FRAME*) m_PcbFrame )->getActiveLayer();
if( layer == active_layer ) // active layer will be drawn after other layers
continue;
@ -208,7 +205,6 @@ void BOARD::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, int aDrawMode, const wxPoin
layerDC.SetDeviceOrigin(0,0);
layerDC.SetLogicalOrigin( 0, 0 );
layerDC.SetUserScale( 1, 1 );
if( aDrawMode == GR_COPY )
{
// Use the layer bitmap itself as a mask when blitting. The bitmap
@ -216,7 +212,8 @@ void BOARD::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, int aDrawMode, const wxPoin
layerDC.SelectObject( wxNullBitmap );
layerBitmap->SetMask( new wxMask( *layerBitmap, bgColor ) );
layerDC.SelectObject( *layerBitmap );
screenDC.Blit( 0, 0, bitmapWidth, bitmapHeight, &layerDC, 0, 0, wxCOPY, true );
screenDC.Blit( 0, 0, bitmapWidth, bitmapHeight,
&layerDC, 0, 0, wxCOPY, true );
}
else if( aDrawMode == GR_OR )
{
@ -227,9 +224,9 @@ void BOARD::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, int aDrawMode, const wxPoin
// the cpu cycles needed to create the monochromatic bitmap above, and
// the extra time needed to do bit indexing into the monochromatic bitmap
// on the blit above.
screenDC.Blit( 0, 0, bitmapWidth, bitmapHeight, &layerDC, 0, 0, wxOR );
screenDC.Blit( 0, 0, bitmapWidth, bitmapHeight,
&layerDC, 0, 0, wxOR );
}
// Restore actual values and clear bitmpap for next drawing
layerDC.SetDeviceOrigin( dev_org.x, dev_org.y );
layerDC.SetLogicalOrigin( logical_org.x, logical_org.y );
@ -259,7 +256,7 @@ void BOARD::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, int aDrawMode, const wxPoin
int dcode_highlight = 0;
if( layer == ( (GERBVIEW_FRAME*) aPanel->GetParent() )->getActiveLayer() )
if( layer == ( (GERBVIEW_FRAME*) m_PcbFrame )->getActiveLayer() )
dcode_highlight = gerber->m_Selected_Tool;
int layerdrawMode = GR_COPY;
@ -280,7 +277,6 @@ void BOARD::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, int aDrawMode, const wxPoin
if( dcode_highlight && dcode_highlight == gerb_item->m_DCode )
drawMode |= GR_SURBRILL;
gerb_item->Draw( aPanel, plotDC, drawMode );
doBlit = true;
}
@ -301,12 +297,14 @@ void BOARD::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, int aDrawMode, const wxPoin
layerDC.SelectObject( wxNullBitmap );
layerBitmap->SetMask( new wxMask( *layerBitmap, bgColor ) );
layerDC.SelectObject( *layerBitmap );
screenDC.Blit( 0, 0, bitmapWidth, bitmapHeight, &layerDC, 0, 0, wxCOPY, true );
screenDC.Blit( 0, 0, bitmapWidth, bitmapHeight,
&layerDC, 0, 0, wxCOPY, true );
}
else if( aDrawMode == GR_OR )
{
screenDC.Blit( 0, 0, bitmapWidth, bitmapHeight, &layerDC, 0, 0, wxOR );
screenDC.Blit( 0, 0, bitmapWidth, bitmapHeight,
&layerDC, 0, 0, wxOR );
}
}

View File

@ -47,7 +47,7 @@ GBR_TO_PCB_EXPORTER::GBR_TO_PCB_EXPORTER( GERBVIEW_FRAME * aFrame, FILE * aFile
{
m_gerbview_frame = aFrame;
m_file = aFile;
m_pcb = new BOARD( NULL );
m_pcb = new BOARD( NULL, m_gerbview_frame );
}
GBR_TO_PCB_EXPORTER::~GBR_TO_PCB_EXPORTER()

View File

@ -44,7 +44,7 @@ GERBVIEW_FRAME::GERBVIEW_FRAME( wxWindow* father,
m_SelLayerBox = NULL;
m_DCodeSelector = NULL;
m_displayMode = 0;
m_drillFileHistory.SetBaseId( ID_GERBVIEW_DRILL_FILE1 );
m_drillFileHistory.SetBaseId(ID_GERBVIEW_DRILL_FILE1);
if( DrawPanel )
DrawPanel->m_Block_Enable = true;
@ -56,7 +56,7 @@ GERBVIEW_FRAME::GERBVIEW_FRAME( wxWindow* father,
SetScreen( ScreenPcb );
SetBoard( new BOARD( NULL ) );
SetBoard( new BOARD( NULL, this ) );
GetBoard()->SetEnabledLayers( FULL_LAYERS ); // All 32 layers enabled at first.
GetBoard()->SetVisibleLayers( FULL_LAYERS ); // All 32 layers visible.
@ -144,6 +144,34 @@ void GERBVIEW_FRAME::OnCloseWindow( wxCloseEvent& Event )
}
double GERBVIEW_FRAME::BestZoom()
{
// gives a minimal value to zoom, if no item in list
if( GetBoard()->m_Drawings == NULL )
return 160.0;
EDA_RECT bbox;
BOARD_ITEM* item = GetBoard()->m_Drawings;
bbox = ( (GERBER_DRAW_ITEM*) item )->GetBoundingBox();
for( ; item; item = item->Next() )
{
GERBER_DRAW_ITEM* gerb_item = (GERBER_DRAW_ITEM*) item;
bbox.Merge( gerb_item->GetBoundingBox() );
}
wxSize size = DrawPanel->GetClientSize();
double x = (double) bbox.GetWidth() / (double) size.x;
double y = (double) bbox.GetHeight() / (double) size.y;
GetScreen()->SetScrollCenterPosition( bbox.Centre() );
double best_zoom = MAX( x, y );
return best_zoom;
}
void GERBVIEW_FRAME::LoadSettings()
{
wxConfig* config = wxGetApp().m_EDA_Config;

View File

@ -68,6 +68,7 @@ public: GERBVIEW_FRAME( wxWindow* father, const wxString& title,
void OnLeftClick( wxDC* DC, const wxPoint& MousePos );
void OnLeftDClick( wxDC* DC, const wxPoint& MousePos );
bool OnRightClick( const wxPoint& MousePos, wxMenu* PopMenu );
double BestZoom();
/**
* Function ReportMessage

View File

@ -357,7 +357,8 @@ public:
int m_Flags; // flags for editing and other uses.
unsigned long m_TimeStamp; // Time stamp used for logical links
int m_Selected; /* Used by block commands, and selective editing */
int m_Selected; /* Used by block commands, and selective
* editing */
// member used in undo/redo function
EDA_ITEM* m_Image; // Link to an image copy to save a copy of

View File

@ -182,6 +182,7 @@ set(PCBNEW_SRCS
tool_pcb.cpp
toolbars_update_user_interface.cpp
tracepcb.cpp
track.cpp
tr_modif.cpp
trpiste.cpp
work.cpp

View File

@ -39,7 +39,7 @@ void PCB_EDIT_FRAME::Attribut_Track( TRACK* track, wxDC* DC, bool Flag_On )
return;
DrawPanel->CrossHairOff( DC ); // Erase cursor shape
Track = GetBoard()->MarkTrace( track, &nb_segm, NULL, NULL, true );
Track = MarkTrace( GetBoard(), track, &nb_segm, NULL, NULL, true );
DrawTraces( DrawPanel, DC, Track, nb_segm, GR_OR | GR_SURBRILL );
for( ; (Track != NULL) && (nb_segm > 0); nb_segm-- )

View File

@ -105,48 +105,32 @@ void PCB_BASE_FRAME::SetBoard( BOARD* aBoard )
double PCB_BASE_FRAME::BestZoom( void )
{
int dx, dy;
double zx, zy;
double ii, jj;
wxSize size;
wxPoint center;
if( m_Pcb != NULL && m_Pcb->ComputeBoundingBox() )
{
if( m_Pcb == NULL )
return 32.0;
m_Pcb->ComputeBoundingBox();
dx = m_Pcb->m_BoundaryBox.GetWidth();
dy = m_Pcb->m_BoundaryBox.GetHeight();
center = m_Pcb->m_BoundaryBox.Centre();
}
else
{
if( m_Draw_Sheet_Ref )
{
dx = GetScreen()->ReturnPageSize().x;
dy = GetScreen()->ReturnPageSize().y;
}
else
{
dx = GetScreen()->ReturnPageSize().x;
dy = GetScreen()->ReturnPageSize().y;
}
center = wxPoint( dx / 2, dy / 2 );
}
size = DrawPanel->GetClientSize();
if( size.x )
zx = (double) dx / (double) size.x;
ii = (double)(dx + ( size.x / 2) ) / (double) size.x;
else
zx = 32.0;
ii = 32.0;
if ( size.y )
zy = (double) dy / (double) size.y;
jj = (double)( dy + (size.y / 2) ) / (double) size.y;
else
zy = 32.0;
jj = 32.0;
double bestzoom = MAX( zx, zy );
GetScreen()->SetScrollCenterPosition( center );
double bestzoom = MAX( ii, jj );
GetScreen()->SetScrollCenterPosition( m_Pcb->m_BoundaryBox.Centre() );
return bestzoom;
return bestzoom ;
}

View File

@ -19,67 +19,26 @@ wxPoint BOARD_ITEM::ZeroOffset( 0, 0 );
BOARD_DESIGN_SETTINGS boardDesignSettings;
/**
* Function SortPadsByXCoord
* is used to sort a pad list by x coordinate value.
*/
static int SortPadsByXCoord( const void* aRef, const void* aComp )
{
D_PAD* ref = *(LISTE_PAD*) aRef;
D_PAD* comp = *(LISTE_PAD*) aComp;
return ref->m_Pos.x - comp->m_Pos.x;
}
TRACK* GetTraceByEndPoint( TRACK* aStartTrace, TRACK* aEndTrace,
const wxPoint& aPosition, int aLayerMask )
{
if( aStartTrace == NULL )
return NULL;
for( TRACK* trace = aStartTrace; trace != NULL; trace = trace->Next() )
{
if( trace->GetState( IS_DELETED | BUSY ) == 0 )
{
if( aPosition == trace->m_Start )
{
if( aLayerMask & trace->ReturnMaskLayer() )
return trace;
}
if( aPosition == trace->m_End )
{
if( aLayerMask & trace->ReturnMaskLayer() )
return trace;
}
}
if( trace == aEndTrace )
break;
}
return NULL;
}
/*****************/
/* Class BOARD: */
/*****************/
BOARD::BOARD( EDA_ITEM* aParent ) :
BOARD_ITEM( (BOARD_ITEM*) aParent, TYPE_PCB ),
BOARD::BOARD( EDA_ITEM* parent, PCB_BASE_FRAME* frame ) :
BOARD_ITEM( (BOARD_ITEM*)parent, TYPE_PCB ),
m_NetClasses( this )
{
m_PcbFrame = frame;
m_Status_Pcb = 0; // Status word: bit 1 = calculate.
SetBoardDesignSettings( &boardDesignSettings );
SetColorsSettings( &g_ColorsSettings );
SetBoardDesignSettings(&boardDesignSettings);
SetColorsSettings(&g_ColorsSettings);
m_NbNodes = 0; // Number of connected pads.
m_NbNoconnect = 0; // Number of unconnected nets.
m_CurrentZoneContour = NULL; // This ZONE_CONTAINER handle the
// zone contour currently in progress
m_NetInfo = new NETINFO_LIST( this ); // handle nets info list (name, design constraints ..
// zone contour currently in
// progress
m_NetInfo = new NETINFO_LIST( this ); // handle nets info list (name,
// design constraints ..
m_NetInfo->BuildListOfNets(); // prepare pads and nets lists containers.
for( int layer = 0; layer < NB_COPPER_LAYERS; ++layer )
@ -88,10 +47,12 @@ BOARD::BOARD( EDA_ITEM* aParent ) :
m_Layer[layer].m_Type = LT_SIGNAL;
}
// Initial parameters for the default NETCLASS come from the global preferences
// within g_DesignSettings via the NETCLASS() constructor. Should the user
// eventually load a board from a disk file, then these defaults will get
// overwritten during load.
// Initial parameters for the default NETCLASS come from the global
// preferences
// within g_DesignSettings via the NETCLASS() constructor.
// Should user eventually load a board from a disk file, then these
// defaults
// will get overwritten during load.
m_NetClasses.GetDefault()->SetDescription( _( "This is the default net class." ) );
m_ViaSizeSelector = 0;
m_TrackWidthSelector = 0;
@ -103,6 +64,9 @@ BOARD::BOARD( EDA_ITEM* aParent ) :
BOARD::~BOARD()
{
if( m_PcbFrame->GetScreen() )
m_PcbFrame->GetScreen()->ClearUndoRedoList();
while( m_ZoneDescriptorList.size() )
{
ZONE_CONTAINER* area_to_remove = m_ZoneDescriptorList[0];
@ -123,124 +87,20 @@ BOARD::~BOARD()
}
void BOARD::chainMarkedSegments( wxPoint& aPosition, int aLayerMask, TRACK_PTRS* aList )
{
TRACK* pt_segm; // The current segment being analyzed.
TRACK* pt_via; // The via identified, eventually destroy
TRACK* SegmentCandidate; // The end segment to destroy (or NULL = pt_segm
int NbSegm;
if( m_Track == NULL )
return;
/* Set the BUSY flag of all connected segments, first search starting at
* aPosition
* Search ends when:
* - a pad is found (end of a track)
* - a segment end has more than one other segment end connected
* - and obviously when no connected item found
* Vias are a special case, because we must see others segment connected
* on others layers and they change the layer mask. They can be a track
* end or not
* They will be analyzer later, and vias on terminal points of the track
* will be considered as part of this track if they do not connect segments
* of an other track together and will be considered as part of an other
* track if when removing the via, the segments of that other track are
* disconnected
/*
* Function PushHightLight
* save current hight light info for later use
*/
for( ; ; )
{
if( GetPadFast( aPosition, aLayerMask ) != NULL )
return;
/* Test for a via: a via changes the layer mask and can connect a lot
* of segments at location aPosition. When found, the via is just
* pushed in list. Vias will be examined later, when all connected
* segment are found and push in list. This is because when a via
* is found we do not know at this time the number of connected items
* and we do not know if this via is on the track or finish the track
*/
pt_via = m_Track->GetVia( NULL, aPosition, aLayerMask );
if( pt_via )
{
aLayerMask = pt_via->ReturnMaskLayer();
aList->push_back( pt_via );
}
/* Now we search all segments connected to point aPosition
* if only 1 segment: this segment is candidate
* if > 1 segment:
* end of track (more than 2 segment connected at this location)
*/
pt_segm = m_Track;
SegmentCandidate = NULL;
NbSegm = 0;
while( ( pt_segm = GetTraceByEndPoint( pt_segm, NULL, aPosition, aLayerMask ) ) != NULL )
{
if( pt_segm->GetState( BUSY ) ) // already found and selected: skip it
{
pt_segm = pt_segm->Next();
continue;
}
if( pt_segm == pt_via ) // just previously found: skip it
{
pt_segm = pt_segm->Next();
continue;
}
NbSegm++;
if( NbSegm == 1 ) /* First time we found a connected item: pt_segm is candidate */
{
SegmentCandidate = pt_segm;
pt_segm = pt_segm->Next();
}
else /* More than 1 segment connected -> this location is an end of the track */
{
return;
}
}
if( SegmentCandidate ) // A candidate is found: flag it an push it in list
{
/* Initialize parameters to search items connected to this
* candidate:
* we must analyze connections to its other end
*/
aLayerMask = SegmentCandidate->ReturnMaskLayer();
if( aPosition == SegmentCandidate->m_Start )
{
aPosition = SegmentCandidate->m_End;
}
else
{
aPosition = SegmentCandidate->m_Start;
}
pt_segm = m_Track; /* restart list of tracks to analyze */
/* flag this item an push it in list of selected items */
aList->push_back( SegmentCandidate );
SegmentCandidate->SetState( BUSY, ON );
}
else
{
return;
}
}
}
void BOARD::PushHightLight()
{
m_hightLightPrevious = m_hightLight;
}
/*
* Function PopHightLight
* retrieve a previously saved hight light info
*/
void BOARD::PopHightLight()
{
m_hightLight = m_hightLightPrevious;
@ -248,6 +108,15 @@ void BOARD::PopHightLight()
}
/**
* Function SetCurrentNetClass
* Must be called after a netclass selection (or after a netclass parameter
* change
* Initialize vias and tracks values displayed in combo boxes of the auxiliary
* toolbar and some other parameters (netclass name ....)
* @param aNetClassName = the new netclass name
* @return true if lists of tracks and vias sizes are modified
*/
bool BOARD::SetCurrentNetClass( const wxString& aNetClassName )
{
NETCLASS* netClass = m_NetClasses.Find( aNetClassName );
@ -296,6 +165,10 @@ bool BOARD::SetCurrentNetClass( const wxString& aNetClassName )
}
/**
* Function GetBiggestClearanceValue
* @return the biggest clearance value found in NetClasses list
*/
int BOARD::GetBiggestClearanceValue()
{
int clearance = m_NetClasses.GetDefault()->GetClearance();
@ -311,6 +184,11 @@ int BOARD::GetBiggestClearanceValue()
}
/**
* Function GetCurrentMicroViaSize
* @return the current micro via size,
* that is the current netclass value
*/
int BOARD::GetCurrentMicroViaSize()
{
NETCLASS* netclass = m_NetClasses.Find( m_CurrentNetClassName );
@ -319,6 +197,11 @@ int BOARD::GetCurrentMicroViaSize()
}
/**
* Function GetCurrentMicroViaDrill
* @return the current micro via drill,
* that is the current netclass value
*/
int BOARD::GetCurrentMicroViaDrill()
{
NETCLASS* netclass = m_NetClasses.Find( m_CurrentNetClassName );
@ -497,13 +380,11 @@ LAYER_T LAYER::ParseType( const char* aType )
return LAYER_T( -1 );
}
int BOARD::GetCopperLayerCount() const
{
return GetBoardDesignSettings()->GetCopperLayerCount();
}
void BOARD::SetCopperLayerCount( int aCount )
{
GetBoardDesignSettings()->SetCopperLayerCount( aCount );
@ -667,6 +548,13 @@ int BOARD::GetLayerColor( int aLayer )
}
/**
* Function IsModuleLayerVisible
* expects either of the two layers on which a module can reside, and returns
* whether that layer is visible.
* @param layer One of the two allowed layers for modules: LAYER_N_FRONT or LAYER_N_BACK
* @return bool - true if the layer is visible, else false.
*/
bool BOARD::IsModuleLayerVisible( int layer )
{
if( layer==LAYER_N_FRONT )
@ -946,6 +834,23 @@ bool BOARD::ComputeBoundingBox( bool aBoardEdgesOnly )
}
}
if( !hasItems && m_PcbFrame )
{
if( m_PcbFrame->m_Draw_Sheet_Ref )
{
area.SetOrigin( 0, 0 );
area.SetEnd( m_PcbFrame->GetScreen()->ReturnPageSize().x,
m_PcbFrame->GetScreen()->ReturnPageSize().y );
}
else
{
area.SetOrigin( -m_PcbFrame->GetScreen()->ReturnPageSize().x / 2,
-m_PcbFrame->GetScreen()->ReturnPageSize().y / 2 );
area.SetEnd( m_PcbFrame->GetScreen()->ReturnPageSize().x / 2,
m_PcbFrame->GetScreen()->ReturnPageSize().y / 2 );
}
}
m_BoundaryBox = area;
return hasItems;
@ -953,6 +858,9 @@ bool BOARD::ComputeBoundingBox( bool aBoardEdgesOnly )
// virtual, see pcbstruct.h
/* Display board statistics: pads, nets, connections.. count
*/
void BOARD::DisplayInfo( EDA_DRAW_FRAME* frame )
{
wxString txt;
@ -1266,6 +1174,12 @@ SEARCH_RESULT BOARD::Visit( INSPECTOR* inspector, const void* testData,
*/
/**
* Function FindNet
* searches for a net with the given netcode.
* @param aNetcode The netcode to search for.
* @return NETINFO_ITEM* - the net or NULL if not found.
*/
NETINFO_ITEM* BOARD::FindNet( int aNetcode ) const
{
// the first valid netcode is 1 and the last is m_NetInfo->GetCount()-1.
@ -1288,6 +1202,12 @@ NETINFO_ITEM* BOARD::FindNet( int aNetcode ) const
}
/**
* Function FindNet overlaid
* searches for a net with the given name.
* @param aNetname A Netname to search for.
* @return NETINFO_ITEM* - the net or NULL if not found.
*/
NETINFO_ITEM* BOARD::FindNet( const wxString& aNetname ) const
{
// the first valid netcode is 1.
@ -1366,125 +1286,6 @@ NETINFO_ITEM* BOARD::FindNet( const wxString& aNetname ) const
}
TRACK* BOARD::CreateLockPoint( wxPoint& aPosition, TRACK* aSegment,
PICKED_ITEMS_LIST* aItemsListPicker )
{
if( aSegment->m_Start == aPosition || aSegment->m_End == aPosition )
return NULL;
/* A via is a good lock point */
if( aSegment->Type() == TYPE_VIA )
{
aPosition = aSegment->m_Start;
return aSegment;
}
/* Calculation coordinate of intermediate point relative to
* the start point of aSegment
*/
wxPoint delta = aSegment->m_End - aSegment->m_Start;
// Not yet in use:
#if 0
int ox, oy, fx, fy;
if( aRefSegm )
{
ox = aRefSegm->m_Start.x - aSegment->m_Start.x;
oy = aRefSegm->m_Start.y - aSegment->m_Start.y;
fx = aRefSegm->m_End.x - aSegment->m_Start.x;
fy = aRefSegm->m_End.y - aSegment->m_Start.y;
}
#endif
// calculate coordinates of aPosition relative to aSegment->m_Start
wxPoint newPoint = aPosition - aSegment->m_Start;
// newPoint must be on aSegment:
// Ensure newPoint.y/newPoint.y = delta.y/delta.x
if( delta.x == 0 )
newPoint.x = 0; /* horizontal segment*/
else
newPoint.y = wxRound(( (double)newPoint.x * delta.y ) / delta.x);
/* Create the intermediate point (that is to say creation of a new
* segment, beginning at the intermediate point.
*/
newPoint.x += aSegment->m_Start.x;
newPoint.y += aSegment->m_Start.y;
TRACK* newTrack = aSegment->Copy();
if( aItemsListPicker )
{
ITEM_PICKER picker( newTrack, UR_NEW );
aItemsListPicker->PushItem( picker );
}
DLIST<TRACK>* list = (DLIST<TRACK>*)aSegment->GetList();
wxASSERT( list );
list->Insert( newTrack, aSegment->Next() );
if( aItemsListPicker )
{
ITEM_PICKER picker( aSegment, UR_CHANGED );
picker.m_Link = aSegment->Copy();
aItemsListPicker->PushItem( picker );
}
/* Correct pointer at the end of the new segment. */
newTrack->end = aSegment->end;
newTrack->SetState( END_ONPAD, aSegment->GetState( END_ONPAD ) );
/* Set connections info relative to the new point
*/
/* Old segment now ends at new point. */
aSegment->m_End = newPoint;
aSegment->end = newTrack;
aSegment->SetState( END_ONPAD, OFF );
/* The new segment begins at the new point. */
newTrack->m_Start = newPoint;
newTrack->start = aSegment;
newTrack->SetState( BEGIN_ONPAD, OFF );
D_PAD * pad = GetPad( newTrack, START );
if ( pad )
{
newTrack->start = pad;
newTrack->SetState( BEGIN_ONPAD, ON );
aSegment->end = pad;
aSegment->SetState( END_ONPAD, ON );
}
aPosition = newPoint;
return newTrack;
}
BOARD_ITEM* BOARD::GetLockPoint( const wxPoint& aPosition, int aLayerMask )
{
for( MODULE* module = m_Modules; module; module = module->Next() )
{
D_PAD* pad = module->GetPad( aPosition, aLayerMask );
if( pad )
return pad;
}
/* No pad has been located so check for a segment of the trace. */
TRACK* trace = GetTraceByEndPoint( m_Track, NULL, aPosition, aLayerMask );
if( trace == NULL )
trace = GetTrace( aPosition, aLayerMask );
return trace;
}
MODULE* BOARD::FindModuleByReference( const wxString& aReference ) const
{
struct FindModule : public INSPECTOR
@ -1519,185 +1320,20 @@ MODULE* BOARD::FindModuleByReference( const wxString& aReference ) const
}
MODULE* BOARD::GetModule( const wxPoint& aPosition, int aActiveLayer,
bool aVisibleOnly, bool aIgnoreLocked )
{
MODULE* pt_module;
MODULE* module = NULL;
MODULE* Altmodule = NULL;
int min_dim = 0x7FFFFFFF;
int alt_min_dim = 0x7FFFFFFF;
int layer;
pt_module = m_Modules;
for( ; pt_module; pt_module = (MODULE*) pt_module->Next() )
{
// is the ref point within the module's bounds?
if( !pt_module->HitTest( aPosition ) )
continue;
// if caller wants to ignore locked modules, and this one is locked, skip it.
if( aIgnoreLocked && pt_module->IsLocked() )
continue;
/* Calculate priority: the priority is given to the layer of the
* module and the copper layer if the module layer is indelible,
* adhesive copper, a layer if cmp module layer is indelible,
* adhesive component.
*/
layer = pt_module->GetLayer();
if( layer==ADHESIVE_N_BACK || layer==SILKSCREEN_N_BACK )
layer = LAYER_N_BACK;
else if( layer==ADHESIVE_N_FRONT || layer==SILKSCREEN_N_FRONT )
layer = LAYER_N_FRONT;
/* Test of minimum size to choosing the best candidate. */
EDA_RECT bb = pt_module->GetFootPrintRect();
int offx = bb.GetX() + bb.GetWidth() / 2;
int offy = bb.GetY() + bb.GetHeight() / 2;
//off x & offy point to the middle of the box.
int dist = abs( aPosition.x - offx ) + abs( aPosition.y - offy );
//int dist = MIN(lx, ly); // to pick the smallest module (kinda
// screwy with same-sized modules -- this is bad!)
if( aActiveLayer == layer )
{
if( dist <= min_dim )
{
/* better footprint shown on the active layer */
module = pt_module;
min_dim = dist;
}
}
else if( aVisibleOnly && IsModuleLayerVisible( layer ) )
{
if( dist <= alt_min_dim )
{
/* better footprint shown on other layers */
Altmodule = pt_module;
alt_min_dim = dist;
}
}
}
if( module )
{
return module;
}
if( Altmodule )
{
return Altmodule;
}
return NULL;
}
TRACK* BOARD::GetTrace( const wxPoint& aPosition, int aLayer )
{
return m_Track->GetTrace( aPosition, aLayer );
}
TRACK* BOARD::GetVia( const wxPoint& aPosition, int aLayer )
{
TRACK* track;
for( track = m_Track; track; track = track->Next() )
{
if( track->Type() != TYPE_VIA
|| track->m_Start != aPosition
|| track->GetState( BUSY | IS_DELETED ) )
continue;
if( aLayer < 0 || track->IsOnLayer( aLayer ) )
break;
}
return track;
}
D_PAD* BOARD::GetPad( TRACK* aTrace, int aEnd )
{
D_PAD* pad = NULL;
wxPoint pos;
int aLayerMask = g_TabOneLayerMask[ aTrace->GetLayer() ];
if( aEnd == START )
{
pos = aTrace->m_Start;
}
else
{
pos = aTrace->m_End;
}
for( MODULE* module = m_Modules; module; module = module->Next() )
{
pad = module->GetPad( pos, aLayerMask );
if( pad != NULL )
break;
}
return pad;
}
D_PAD* BOARD::GetPad( const wxPoint& aPosition, int aLayerMask )
{
D_PAD* pad = NULL;
for( MODULE* module = m_Modules; module && ( pad == NULL ); module = module->Next() )
{
pad = module->GetPad( aPosition, aLayerMask );
}
return pad;
}
D_PAD* BOARD::GetPadFast( const wxPoint& aPosition, int aLayerMask )
{
for( unsigned i=0; i<GetPadsCount(); ++i )
{
D_PAD* pad = m_NetInfo->GetPad(i);
if( pad->m_Pos != aPosition )
continue;
/* Pad found, it must be on the correct layer */
if( pad->m_layerMask & aLayerMask )
return pad;
}
return NULL;
}
void BOARD::CreateSortedPadListByXCoord( std::vector<D_PAD*>* aVector )
{
aVector->insert( aVector->end(), m_NetInfo->m_PadsFullList.begin(),
m_NetInfo->m_PadsFullList.end() );
qsort( &(*aVector)[0], GetPadsCount(), sizeof( D_PAD*), SortPadsByXCoord );
}
// Sort nets by decreasing pad count
static bool s_SortByNodes( const NETINFO_ITEM* a, const NETINFO_ITEM* b )
{
return b->GetNodesCount() < a->GetNodesCount();
}
/**
* Function ReturnSortedNetnamesList
* @param aNames An array string to fill with net names.
* @param aSortbyPadsCount : true = sort by active pads count, false = no sort
* (i.e. leave the sort by net names)
* @return int - net names count.
*/
int BOARD::ReturnSortedNetnamesList( wxArrayString& aNames, bool aSortbyPadsCount )
{
if( m_NetInfo->GetCount() == 0 )
@ -1803,6 +1439,10 @@ out:
}
/*
* Function RedrawAreasOutlines
* Redraw all areas outlines on layer aLayer ( redraw all if aLayer < 0 )
*/
void BOARD::RedrawAreasOutlines( EDA_DRAW_PANEL* panel, wxDC* aDC, int aDrawMode, int aLayer )
{
if( !aDC )
@ -1818,6 +1458,10 @@ void BOARD::RedrawAreasOutlines( EDA_DRAW_PANEL* panel, wxDC* aDC, int aDrawMode
}
/**
* Function RedrawFilledAreas
* Redraw all areas outlines on layer aLayer ( redraw all if aLayer < 0 )
*/
void BOARD::RedrawFilledAreas( EDA_DRAW_PANEL* panel, wxDC* aDC, int aDrawMode, int aLayer )
{
if( !aDC )
@ -1833,6 +1477,18 @@ void BOARD::RedrawFilledAreas( EDA_DRAW_PANEL* panel, wxDC* aDC, int aDrawMode,
}
/**
* Function HitTestForAnyFilledArea
* tests if the given wxPoint is within the bounds of a filled area of this
* zone.
* the test is made on zones on layer from aStartLayer to aEndLayer
* Note: if a zone has its flag BUSY (in .m_State) is set, it is ignored.
* @param aRefPos A wxPoint to test
* @param aStartLayer the first layer to test
* @param aEndLayer the last layer (-1 to ignore it) to test
* @return ZONE_CONTAINER* return a pointer to the ZONE_CONTAINER found, else
* NULL
*/
ZONE_CONTAINER* BOARD::HitTestForAnyFilledArea( const wxPoint& aRefPos,
int aStartLayer,
int aEndLayer )
@ -1863,6 +1519,19 @@ ZONE_CONTAINER* BOARD::HitTestForAnyFilledArea( const wxPoint& aRefPos,
}
/**
* Function SetAreasNetCodesFromNetNames
* Set the .m_NetCode member of all copper areas, according to the area Net
* Name
* The SetNetCodesFromNetNames is an equivalent to net name, for fast
* comparisons.
* However the Netcode is an arbitrary equivalence, it must be set after each
* netlist read
* or net change
* Must be called after pad netcodes are calculated
* @return : error count
* For non copper areas, netcode is set to 0
*/
int BOARD::SetAreasNetCodesFromNetNames( void )
{
int error_count = 0;
@ -1896,248 +1565,15 @@ int BOARD::SetAreasNetCodesFromNetNames( void )
}
TRACK* BOARD::MarkTrace( TRACK* aTrace, int* aCount, int* aLength, int* aLengthDie, bool aReorder )
{
wxCHECK( aTrace != NULL, NULL );
int NbSegmBusy;
TRACK_PTRS trackList;
if( aCount )
*aCount = 0;
if( aLength )
*aLength = 0;
// Ensure the flag BUSY of all tracks of the board is cleared
// because we use it to mark segments of the track
for( TRACK* track = m_Track; track; track = track->Next() )
track->SetState( BUSY, OFF );
/* Set flags of the initial track segment */
aTrace->SetState( BUSY, ON );
int layerMask = aTrace->ReturnMaskLayer();
trackList.push_back( aTrace );
/* Examine the initial track segment : if it is really a segment, this is
* easy.
* If it is a via, one must search for connected segments.
* If <=2, this via connect 2 segments (or is connected to only one
* segment) and this via and these 2 segments are a part of a track.
* If > 2 only this via is flagged (the track has only this via)
*/
if( aTrace->Type() == TYPE_VIA )
{
TRACK* Segm1, * Segm2 = NULL, * Segm3 = NULL;
Segm1 = GetTraceByEndPoint( m_Track, NULL, aTrace->m_Start, layerMask );
if( Segm1 )
{
Segm2 = GetTraceByEndPoint( Segm1->Next(), NULL, aTrace->m_Start, layerMask );
}
if( Segm2 )
{
Segm3 = GetTraceByEndPoint( Segm2->Next(), NULL, aTrace->m_Start, layerMask );
}
if( Segm3 ) // More than 2 segments are connected to this via. the track" is only this via
{
if( aCount )
*aCount = 1;
return aTrace;
}
if( Segm1 ) // search for others segments connected to the initial segment start point
{
layerMask = Segm1->ReturnMaskLayer();
chainMarkedSegments( aTrace->m_Start, layerMask, &trackList );
}
if( Segm2 ) // search for others segments connected to the initial segment end point
{
layerMask = Segm2->ReturnMaskLayer();
chainMarkedSegments( aTrace->m_Start, layerMask, &trackList );
}
}
else // mark the chain using both ends of the initial segment
{
chainMarkedSegments( aTrace->m_Start, layerMask, &trackList );
chainMarkedSegments( aTrace->m_End, layerMask, &trackList );
}
// Now examine selected vias and flag them if they are on the track
// If a via is connected to only one or 2 segments, it is flagged (is on
// the track)
// If a via is connected to more than 2 segments, it is a track end, and it
// is removed from the list
// go through the list backwards.
for( int i = trackList.size() - 1; i>=0; --i )
{
TRACK* via = trackList[i];
if( via->Type() != TYPE_VIA )
continue;
if( via == aTrace )
continue;
via->SetState( BUSY, ON ); // Try to flag it. the flag will be cleared later if needed
layerMask = via->ReturnMaskLayer();
TRACK* track = GetTraceByEndPoint( m_Track, NULL, via->m_Start, layerMask );
// GetTrace does not consider tracks flagged BUSY.
// So if no connected track found, this via is on the current track
// only: keep it
if( track == NULL )
continue;
/* If a track is found, this via connects also others segments of an
* other track. This case happens when the vias ends the selected
* track but must we consider this via is on the selected track, or
* on an other track.
* (this is important when selecting a track for deletion: must this
* via be deleted or not?)
* We consider here this via on the track if others segment connected
* to this via remain connected when removing this via.
* We search for all others segment connected together:
* if there are on the same layer, the via is on the selected track
* if there are on different layers, the via is on an other track
*/
int layer = track->GetLayer();
while( ( track = GetTraceByEndPoint( track->Next(), NULL,
via->m_Start, layerMask ) ) != NULL )
{
if( layer != track->GetLayer() )
{
// The via connects segments of an other track: it is removed
// from list because it is member of an other track
via->SetState( BUSY, OFF );
break;
}
}
}
/* Rearrange the track list in order to have flagged segments linked
* from firstTrack so the NbSegmBusy segments are consecutive segments
* in list, the first item in the full track list is firstTrack, and
* the NbSegmBusy-1 next items (NbSegmBusy when including firstTrack)
* are the flagged segments
*/
NbSegmBusy = 0;
TRACK* firstTrack;
for( firstTrack = m_Track; firstTrack; firstTrack = firstTrack->Next() )
{
// Search for the first flagged BUSY segments
if( firstTrack->GetState( BUSY ) )
{
NbSegmBusy = 1;
break;
}
}
if( firstTrack == NULL )
return NULL;
double full_len = 0;
double lenDie = 0;
if( aReorder )
{
DLIST<TRACK>* list = (DLIST<TRACK>*)firstTrack->GetList();
wxASSERT( list );
/* Rearrange the chain starting at firstTrack
* All others flagged items are moved from their position to the end
* of the flagged list
*/
TRACK* next;
for( TRACK* track = firstTrack->Next(); track; track = next )
{
next = track->Next();
if( track->GetState( BUSY ) ) // move it!
{
NbSegmBusy++;
track->UnLink();
list->Insert( track, firstTrack->Next() );
if( aLength )
full_len += track->GetLength();
if( aLengthDie ) // Add now length die.
{
// In fact only 2 pads (maximum) will be taken in account:
// that are on each end of the track, if any
if( track->GetState( BEGIN_ONPAD ) )
{
D_PAD * pad = (D_PAD *) track->start;
lenDie += (double) pad->m_LengthDie;
}
if( track->GetState( END_ONPAD ) )
{
D_PAD * pad = (D_PAD *) track->end;
lenDie += (double) pad->m_LengthDie;
}
}
}
}
}
else if( aLength )
{
NbSegmBusy = 0;
for( TRACK* track = firstTrack; track; track = track->Next() )
{
if( track->GetState( BUSY ) )
{
NbSegmBusy++;
track->SetState( BUSY, OFF );
full_len += track->GetLength();
// Add now length die.
// In fact only 2 pads (maximum) will be taken in account:
// that are on each end of the track, if any
if( track->GetState( BEGIN_ONPAD ) )
{
D_PAD * pad = (D_PAD *) track->start;
lenDie += (double) pad->m_LengthDie;
}
if( track->GetState( END_ONPAD ) )
{
D_PAD * pad = (D_PAD *) track->end;
lenDie += (double) pad->m_LengthDie;
}
}
}
}
if( aLength )
*aLength = wxRound( full_len );
if( aLengthDie )
*aLengthDie = wxRound( lenDie );
if( aCount )
*aCount = NbSegmBusy;
return firstTrack;
}
#if defined(DEBUG)
/**
* Function Show
* is used to output the object tree, currently for debugging only.
* @param nestLevel An aid to prettier tree indenting, and is the level
* of nesting of this object within the overall tree.
* @param os The ostream& to output to.
*/
void BOARD::Show( int nestLevel, std::ostream& os )
{
BOARD_ITEM* p;

View File

@ -1,7 +1,6 @@
/**
* @file class_board.h
* @brief Class BOARD to handle a board
*/
/*************************************************/
/* class_board.h - Class BOARD to handle a board */
/*************************************************/
#ifndef CLASS_BOARD_H
#define CLASS_BOARD_H
@ -13,29 +12,8 @@
class ZONE_CONTAINER;
class TRACK;
#define HISTORY_MAX_COUNT 8
// Used to buffer item candidates when search for items on the same track
typedef std::vector<TRACK*> TRACK_PTRS;
/**
* Function GetTraceByEndPoint
* returns a trace starting at \a aStartTrace and ending at \a aEndTrace that has an
* end point at \a aPosition on \a aLayerMask.
*
* @param aStartTrace Pointer to the TRACK object to begin the search.
* @param aEndTrace Pointer to the TRACK object to end then search.
* @param aPosition The wxPoint to check the trace end points against.
* @param aLayerMask The layer or layers to search.
* @return A pointer to the TRACK or SEGVIA object if found, else NULL.
*/
TRACK* GetTraceByEndPoint( TRACK* aStartTrace, TRACK* aEndTrace,
const wxPoint& aPosition, int aLayerMask );
/**
* Enum LAYER_T
* gives the allowed types of layers, same as Specctra DSN spec.
@ -63,6 +41,7 @@ struct LAYER
// int m_Color;
// bool m_Visible; // ? use flags in m_Color instead ?
/**
* Function ShowType
* converts a LAYER_T enum to a const char*
@ -99,7 +78,8 @@ public:
bool operator ==( const VIA_DIMENSION& other ) const
{
return (m_Diameter == other.m_Diameter) && (m_Drill == other.m_Drill);
return (m_Diameter == other.m_Diameter)
&& (m_Drill == other.m_Drill);
}
@ -107,17 +87,14 @@ public:
{
if( m_Diameter != other.m_Diameter )
return m_Diameter < other.m_Diameter;
return m_Drill < other.m_Drill;
}
};
// Helper class to handle hight light nets
class HIGHT_LIGHT_INFO
{
friend class BOARD;
protected:
int m_netCode; // net selected for hightlight (-1 when no net selected )
bool m_hightLightOn; // hightlight active
@ -135,22 +112,20 @@ protected:
}
};
/**
* Class BOARD
* holds information pertinent to a PCBNEW printed circuit board.
*/
#define HISTORY_MAX_COUNT 8
class BOARD : public BOARD_ITEM
{
friend class PCB_EDIT_FRAME;
private:
typedef std::vector<MARKER_PCB*> MARKERS; // @todo: switch to boost:ptr_vector, and change ~BOARD()
MARKERS m_markers; ///< MARKER_PCBs for clearance problems, owned by pointer
typedef std::vector<ZONE_CONTAINER*> ZONE_CONTAINERS; // @todo: switch to boost::ptr_vector, and change ~BOARD()
ZONE_CONTAINERS m_ZoneDescriptorList; ///< edge zone descriptors, owned by pointer
LAYER m_Layer[NB_COPPER_LAYERS];
@ -159,6 +134,7 @@ private:
HIGHT_LIGHT_INFO m_hightLightPrevious; // a previously stored hight light data
public:
PCB_BASE_FRAME* m_PcbFrame; // Window of visualization
EDA_RECT m_BoundaryBox; // Board size and position
int m_Status_Pcb; // Flags used in ratsnet calculation and update
int m_NbNodes; // Active pads (pads attached to a net ) count
@ -171,8 +147,8 @@ public:
NETINFO_LIST* m_NetInfo; // nets info list (name, design constraints ..
std::vector<RATSNEST_ITEM> m_FullRatsnest; // Ratsnest list for the BOARD
std::vector<RATSNEST_ITEM> m_LocalRatsnest; /* Ratsnest list relative to a given footprint
std::vector<RATSNEST_ITEM> m_FullRatsnest; // Rastnest list for the BOARD
std::vector<RATSNEST_ITEM> m_LocalRatsnest; /* Rastnest list relative to a given footprint
* (used while moving a footprint) */
ZONE_CONTAINER* m_CurrentZoneContour; // zone contour currently in progress
@ -191,7 +167,6 @@ public:
std::vector <int> m_TrackWidthList; // tracks widths (max count = HISTORY_MAX_COUNT)
// The first value is the current netclass track width
unsigned m_ViaSizeSelector; // index for m_ViaSizeList to select the value
// 0 is the index selection of the default value Netclass
unsigned m_TrackWidthSelector; // index for m_TrackWidthList to select the value
@ -199,25 +174,9 @@ private:
BOARD_DESIGN_SETTINGS* m_boardDesignSettings; // Link to current design settings
COLORS_DESIGN_SETTINGS* m_colorsSettings; // Link to current colors settings
/**
* Function chainMarkedSegments
* add all trace segments to \a aList attached to a trace found at \a aPosition on
* \a aLayerMask.
* <p>
* The BUSY flag of all connected segments is set. Vias are also put in list but
* their flags BUSY is not set.
* </p>
* @param aPosition A wxPoint object contatining thhe reference coordinate of the
* to search.
* @param aLayerMask The allowed layers for segments to search (1 layer when starting
* point is on a segment, but more than one when starting point is
* on a via)
* @param aList The track list to fill with flagged segments.
*/
void chainMarkedSegments( wxPoint& aPosition, int aLayerMask, TRACK_PTRS* aList );
/**********************************/
public:
BOARD( EDA_ITEM* aParent );
BOARD( EDA_ITEM* aParent, PCB_BASE_FRAME* frame );
~BOARD();
/**
@ -260,8 +219,7 @@ public:
*/
void Delete( BOARD_ITEM* aBoardItem )
{
wxASSERT( aBoardItem ); // developers should run DEBUG versions and fix calls with NULL
wxASSERT( aBoardItem ); // developers should run DEBUG versions and fix such calls with NULL
if( aBoardItem )
delete Remove( aBoardItem );
}
@ -269,7 +227,8 @@ public:
/**
* Function Remove
* removes \a aBoardItem from this BOARD and returns it to caller without deleting it.
* removes \a aBoardItem from this BOARD and returns it to caller without
* deleting it.
* @param aBoardItem The item to remove from this board.
* @return BOARD_ITEM* \a aBoardItem which was passed in.
*/
@ -288,6 +247,7 @@ public:
*/
void DeleteZONEOutlines();
/**
* Function GetMARKER
* returns the MARKER at a given index.
@ -298,7 +258,6 @@ public:
{
if( (unsigned) index < m_markers.size() )
return m_markers[index];
return NULL;
}
@ -497,9 +456,9 @@ public:
* @see enum PCB_VISIBLE
*/
int GetVisibleElementColor( int aPCB_VISIBLE );
void SetVisibleElementColor( int aPCB_VISIBLE, int aColor );
/**
* Function GetBoardDesignSettings
* @return the current BOARD_DESIGN_SETTINGS in use
@ -592,9 +551,7 @@ public:
/* Functions to get some items count */
int GetNumSegmTrack();
int GetNumSegmZone();
unsigned GetNoconnectCount(); // Return the number of missing links.
/**
@ -694,36 +651,6 @@ public:
*/
NETINFO_ITEM* FindNet( const wxString& aNetname ) const;
/**
* Function CreateLockPoint
* creates an intermediate point on \a aSegment
* aSegm segment is broken into 2 segments connecting point pX, pY
* After insertion:
* The new segment starts from to new point, and ends to initial aSegm ending point
* the old segment aSegm ends to new point
* Returns:
* NULL if no new point (ie if aRefPoint already corresponded at one end of aSegm
* or
* Pointer to the segment created
* Returns the exact value of aRefPoint
* If aSegm points to a via:
* Returns the exact value of aRefPoint and a pointer to the via,
* But does not create extra point
*/
TRACK* CreateLockPoint( wxPoint& aRefPoint, TRACK* aSegment,
PICKED_ITEMS_LIST* aItemsListPicker );
/**
* Function GetLockPoint
* returns the object at the end of a trace locacted at \a aPosition on \a aLayer.
*
* @param aPosition A wxPoint object containing the position to hit test.
* @param aLayerMask A layer or layers to mask the hit test.
* @return A pointer to the board item if found or NULL if not found.
*/
BOARD_ITEM* GetLockPoint( const wxPoint& aPosition, int aLayerMask );
/**
* Function FindModuleByReference
* searches for a MODULE within this board with the given
@ -735,94 +662,14 @@ public:
*/
MODULE* FindModuleByReference( const wxString& aReference ) const;
/**
* Function Locate_Prefered_Module
* locates a footprint at \a aPosition on \a aActiveLayer.
* <p>
* If several footprints are are at \a aPosition, then the priority is the closest on the
* active layer, then closest to \a aPosition. The distance is calculatedvia manhattan
* distance from the center of the bounding rectangle to \a aposition.
* </p>
* @param aPosition A wxPoint object containing the position to hit test.
* @param aActiveLayer The layer to test.
* @param aVisibleOnly Search only the visible layers if true.
* @param aIgnoreLocked Ignore locked modules when true.
* @return MODULE* The best module or NULL if none.
*/
MODULE* GetModule( const wxPoint& aPosition, int aActiveLayer,
bool aVisibleOnly, bool aIgnoreLocked = false );
/**
* Function GetTrace
* returns a trace segment or via at \a aPosition on \a aLayer.
*
* @param aPosition The wxPoint to HitTest() against.
* @param aLayer The layer to search. Use -1 for a don't care.
* @return A pointer to the TRACK or SEGVIA object if found, else NULL.
*/
TRACK* GetTrace( const wxPoint& aPosition, int aLayer );
/**
* Function GetVia
* finds the first via at \a aPosition on \a aLayer.
* @param aPosition The wxPoint to HitTest() against.
* @param aLayer The layer to search. Use -1 for a don't care.
* @return TRACK* A point a to the SEGVIA object if found, else NULL.
*/
TRACK* GetVia( const wxPoint& aPosition, int aLayer = -1 );
/**
* Function GetPad
* returns the pad connected to the beginning or end of \a aTrace at \a aEnd
*
* @param aTrace A pointer to the trace to test for a pad connection.
* @param aEnd The end point of \a aTrace to test for a pad connection.
* @return A pointer to a D_PAD object if connection found or NULL if not found.
*/
D_PAD* GetPad( TRACK* aTrace, int aEnd );
/**
* Function GetPad
* finds a pad \a aPosition on \a aLayer.
*
* @param aPosition A wxPoint object containing the position to hit test.
* @param aLayerMask A layer or layers to mask the hit test.
* @return A pointer to a D_PAD object if found or NULL if not found.
*/
D_PAD* GetPad( const wxPoint& aPosition, int aLayerMask = ALL_LAYERS );
/**
* Function GetPadFast
* return pad found at \a aPosition on \a aLayer uning the fast search method.
* <p>
* The fast search method only works if the pad list has already exists.
* </p>
* @param aPosition A wxPoint object containing the position to hit test.
* @param aLayer A layer or layers to mask the hit test.
* @return A pointer to a D_PAD object if found or NULL if not found.
*/
D_PAD* GetPadFast( const wxPoint& aPosition, int aLayer );
/**
* Function ReturnSortedNetnamesList
* @param aNames An array string to fill with net names.
* @param aSortbyPadsCount : true = sort by active pads count, false = no sort (i.e.
* leave the sort by net names)
* @param aSortbyPadsCount : true = sort by active pads count, false = no sort (i.e. leave the sort by net names)
* @return int - net names count.
*/
int ReturnSortedNetnamesList( wxArrayString& aNames, bool aSortbyPadsCount );
/**
* Function CreateSortedPadListByXCoord
* clears then fills \a aVector with all pads on the board and sorts them by
* increasing x coordinate.
*
* @note Do not delete any pointers in \a aVector. The pointers are only references to
* pads which are owned by the BOARD.
* @param aVector Where to put the pad pointers.
*/
void CreateSortedPadListByXCoord( std::vector<D_PAD*>* aVector );
/**************************************/
/**
* Function relative to NetClasses: **/
@ -831,9 +678,9 @@ public:
/**
* Function SynchronizeNetsAndNetClasses
* copies NETCLASS info to each NET, based on NET membership in a NETCLASS.
* Must be called after a Design Rules edition, or after reading a netlist (or editing
* the list of nets). Also this function removes the non existing nets in netclasses
* and add net nets in default netclass (this happens after reading a netlist)
* Must be called after a Design Rules edition, or after reading a netlist (or editing the list of nets)
* Also this function removes the non existing nets in netclasses and add net nets in default netclass
* (this happens after reading a netlist)
*/
void SynchronizeNetsAndNetClasses();
@ -914,6 +761,7 @@ public:
*/
bool Save( FILE* aFile ) const;
/**
* Function GetClass
* returns the class name.
@ -1117,8 +965,8 @@ public:
/**
* Function CombineAllAreasInNet
* Checks all copper areas in net for intersections, combining them if found
* @param aDeletedList = a PICKED_ITEMS_LIST * where to store deleted areas (useful in
* undo commands can be NULL
* @param aDeletedList = a PICKED_ITEMS_LIST * where to store deleted areas (useful in undo commands
* can be NULL
* @param aNetCode = net to consider
* @param bMessageBox : if true display warning message box
* @param bUseUtility : if true, don't check areas if both utility flags are 0
@ -1133,8 +981,8 @@ public:
/**
* Function RemoveArea
* remove copper area from net, and put it in a deleted list (if exists)
* @param aDeletedList = a PICKED_ITEMS_LIST * where to store deleted areas (useful in
* undo commands can be NULL
* @param aDeletedList = a PICKED_ITEMS_LIST * where to store deleted areas (useful in undo commands
* can be NULL
* @param area_to_remove = area to delete or put in deleted list
*/
void RemoveArea( PICKED_ITEMS_LIST* aDeletedList, ZONE_CONTAINER* area_to_remove );
@ -1161,8 +1009,8 @@ public:
/**
* Function CombineAreas
* If possible, combine 2 copper areas
* @param aDeletedList = a PICKED_ITEMS_LIST * where to store deleted areas (useful in
* undo commands can be NULL
* @param aDeletedList = a PICKED_ITEMS_LIST * where to store deleted areas (useful in undo commands
* can be NULL
* @param area_ref = the main area (zone)
* @param area_to_combine = the zone that can be merged with area_ref
* area_ref must be BEFORE area_to_combine
@ -1197,29 +1045,6 @@ public:
* @param aNetcode = netcode to analyze. if -1, analyze all nets
*/
void Test_Connections_To_Copper_Areas( int aNetcode = -1 );
/**
* Function MarkTrace
* marks a chain of track segments connected to aTrace.
* Each segment is marked by setting the BUSY bit into m_Flags. Electrical
* continuity is detected by walking each segment, and finally the segments
* are rearranged into a contiguous chain within the given list.
*
* @param aTrace The trace segment to test for connections.
* @param aCount A pointer to an integer where to return the number of interesting
* segments.
* @param aLength A pointer to an integer where to return the length of the track
* @param aLengthDie A pointer to an integer where to return the extra lengths
* inside integrated circuits from the pads connected to this
* track to the die (if any)
* @param aReorder True to reorder the interesting segments (useful for track
* edition or deletion) in this case the flag BUSY is set (the
* user is responsible for flag clearing). False for no reorder:
* useful when we want just calculate the track length in this
* case, flags are reset
* @return A point to a TRACK object that is the first in the chain of interesting segments.
*/
TRACK* MarkTrace( TRACK* aTrace, int* aCount, int* aLength, int* aLengthDie, bool aReorder );
};
#endif // #ifndef CLASS_BOARD_H

View File

@ -819,22 +819,6 @@ D_PAD* MODULE::FindPadByName( const wxString& aPadName ) const
}
D_PAD* MODULE::GetPad( const wxPoint& aPosition, int aLayerMask )
{
for( D_PAD* pad = m_Pads; pad; pad = pad->Next() )
{
/* ... and on the correct layer. */
if( ( pad->m_layerMask & aLayerMask ) == 0 )
continue;
if( pad->HitTest( aPosition ) )
return pad;
}
return NULL;
}
// see class_module.h
SEARCH_RESULT MODULE::Visit( INSPECTOR* inspector, const void* testData,
const KICAD_T scanTypes[] )

View File

@ -298,16 +298,6 @@ public:
D_PAD* FindPadByName( const wxString& aPadName ) const;
/**
* Function GetPad
* return a pad at \a aPosition on \a aLayerMask
*
* @param aPosition A wxPoint object containing the position to hit test.
* @param aLayerMask A layer or layers to mask the hit test.
* @return A pointer to a D_PAD object if found or NULL if not found.
*/
D_PAD* GetPad( const wxPoint& aPosition, int aLayerMask = ALL_LAYERS );
/**
* Function Visit
* should be re-implemented for each derived class in order to handle

View File

@ -152,15 +152,14 @@ TRACK::TRACK( const TRACK& Source ) :
}
/* Because of the way SEGVIA and SEGZONE are derived from TRACK and because there are
* virtual functions being used, we can no longer simply copy a TRACK and
* expect it to be a via or zone. We must construct a true SEGVIA or SEGZONE so its constructor
* can initialize the virtual function table properly. This factory type of
* function called Copy() can duplicate either a TRACK, SEGVIA, or SEGZONE.
*/
TRACK* TRACK::Copy() const
{
/* Because of the way SEGVIA and SEGZONE are derived from TRACK and because
* there are virtual functions being used, we can no longer simply copy a
* TRACK and expect it to be a via or zone. We must construct a true SEGVIA
* or SEGZONE so its constructor can initialize the virtual function table
* properly. This factory type of function called Copy() can duplicate either
* a TRACK, SEGVIA, or SEGZONE.
*/
if( Type() == TYPE_TRACK )
return new TRACK( *this );
@ -174,14 +173,30 @@ TRACK* TRACK::Copy() const
}
/**
* Function GetClearance (virtual)
* returns the clearance in internal units. If \a aItem is not NULL then the
* returned clearance is the greater of this object's clearance and
* aItem's clearance. If \a aItem is NULL, then this objects
* clearance
* is returned.
* @param aItem is another BOARD_CONNECTED_ITEM or NULL
* @return int - the clearance in internal units.
*/
int TRACK::GetClearance( BOARD_CONNECTED_ITEM* aItem ) const
{
// Currently tracks have no specific clearance parameter on a per track or per
// segment basis. The NETCLASS clearance is used
// Currently tracks have no specific clearance parameter
// on a per track or per segment basis.
// the NETCLASS clearance is used
return BOARD_CONNECTED_ITEM::GetClearance( aItem );
}
/**
* Function GetDrillValue
* calculate the drill value for vias (m_Drill if > 0, or default drill value for the Netclass
* @return real drill_value
*/
int TRACK::GetDrillValue() const
{
if( Type() != TYPE_VIA )
@ -200,6 +215,7 @@ int TRACK::GetDrillValue() const
}
// return true if segment length = 0
bool TRACK::IsNull()
{
if( ( Type() != TYPE_VIA ) && ( m_Start == m_End ) )
@ -209,17 +225,24 @@ bool TRACK::IsNull()
}
int TRACK::IsPointOnEnds( const wxPoint& aPosition, int aDistance )
/* Return:
* STARTPOINT if point if near (dist = min_dist) star point
* ENDPOINT if point if near (dist = min_dist) end point
* STARTPOINT|ENDPOINT if point if near (dist = min_dist) both ends
* 0 if no
* if min_dist < 0: min_dist = track_width/2
*/
int TRACK::IsPointOnEnds( const wxPoint& point, int min_dist )
{
int result = 0;
if( aDistance < 0 )
aDistance = m_Width / 2;
if( min_dist < 0 )
min_dist = m_Width / 2;
int dx = m_Start.x - aPosition.x;
int dy = m_Start.y - aPosition.y;
int dx = m_Start.x - point.x;
int dy = m_Start.y - point.y;
if( aDistance == 0 )
if( min_dist == 0 )
{
if( (dx == 0) && (dy == 0 ) )
result |= STARTPOINT;
@ -228,14 +251,14 @@ int TRACK::IsPointOnEnds( const wxPoint& aPosition, int aDistance )
{
double dist = hypot( (double)dx, (double) dy );
if( aDistance >= (int) dist )
if( min_dist >= (int) dist )
result |= STARTPOINT;
}
dx = m_End.x - aPosition.x;
dy = m_End.y - aPosition.y;
dx = m_End.x - point.x;
dy = m_End.y - point.y;
if( aDistance == 0 )
if( min_dist == 0 )
{
if( (dx == 0) && (dy == 0 ) )
result |= ENDPOINT;
@ -244,7 +267,7 @@ int TRACK::IsPointOnEnds( const wxPoint& aPosition, int aDistance )
{
double dist = hypot( (double) dx, (double) dy );
if( aDistance >= (int) dist )
if( min_dist >= (int) dist )
result |= ENDPOINT;
}
@ -308,6 +331,12 @@ EDA_RECT TRACK::GetBoundingBox() const
}
/**
* Function Rotate
* Rotate this object.
* @param aRotCentre - the rotation point.
* @param aAngle - the rotation angle in 0.1 degree.
*/
void TRACK::Rotate( const wxPoint& aRotCentre, int aAngle )
{
RotatePoint( &m_Start, aRotCentre, aAngle );
@ -315,18 +344,29 @@ void TRACK::Rotate( const wxPoint& aRotCentre, int aAngle )
}
/**
* Function Flip
* Flip this object, i.e. change the board side for this object
* @param aCentre - the rotation point.
*/
void TRACK::Flip( const wxPoint& aCentre )
{
m_Start.y = aCentre.y - (m_Start.y - aCentre.y);
m_End.y = aCentre.y - (m_End.y - aCentre.y);
if( Type() != TYPE_VIA )
if( Type() == TYPE_VIA )
{
// Huh? Wouldn't it be better to us Type() != VIA and get rid of these brackets?
}
else
{
SetLayer( ChangeSideNumLayer( GetLayer() ) );
}
}
// see class_track.h
// SEGVIA and SEGZONE inherit this version
SEARCH_RESULT TRACK::Visit( INSPECTOR* inspector, const void* testData,
const KICAD_T scanTypes[] )
{
@ -360,6 +400,9 @@ bool SEGVIA::IsOnLayer( int layer_number ) const
}
/* Return the mask layer for this.
* for a via, there is more than one layer used
*/
int TRACK::ReturnMaskLayer()
{
if( Type() == TYPE_VIA )
@ -392,6 +435,14 @@ int TRACK::ReturnMaskLayer()
}
/** Set the .m_Layer member param:
* For a via m_Layer contains the 2 layers :
* top layer and bottom layer used by the via.
* The via connect all layers from top layer to bottom layer
* 4 bits for the first layer and 4 next bits for the secaon layer
* @param top_layer = first layer connected by the via
* @param bottom_layer = last layer connected by the via
*/
void SEGVIA::SetLayerPair( int top_layer, int bottom_layer )
{
if( Shape() == VIA_THROUGH )
@ -407,6 +458,13 @@ void SEGVIA::SetLayerPair( int top_layer, int bottom_layer )
}
/**
* Function ReturnLayerPair
* Return the 2 layers used by the via (the via actually uses
* all layers between these 2 layers)
* @param top_layer = pointer to the first layer (can be null)
* @param bottom_layer = pointer to the last layer (can be null)
*/
void SEGVIA::ReturnLayerPair( int* top_layer, int* bottom_layer ) const
{
int b_layer = LAYER_N_BACK;
@ -448,6 +506,9 @@ TRACK* TRACK::GetBestInsertPoint( BOARD* aPcb )
}
/* Search (within the track linked list) the first segment matching the netcode
* ( the linked list is always sorted by net codes )
*/
TRACK* TRACK::GetStartNetCode( int NetCode )
{
TRACK* Track = this;
@ -477,6 +538,9 @@ TRACK* TRACK::GetStartNetCode( int NetCode )
}
/* Search (within the track linked list) the last segment matching the netcode
* ( the linked list is always sorted by net codes )
*/
TRACK* TRACK::GetEndNetCode( int NetCode )
{
TRACK* NextS, * Track = this;
@ -696,226 +760,6 @@ void TRACK::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, int draw_mode, const wxPoint&
}
int TRACK::GetEndSegments( int aCount, TRACK** aStartTrack, TRACK** aEndTrack )
{
TRACK* Track, * via, * segm, * TrackListEnd;
int NbEnds, layerMask, ii, ok = 0;
if( aCount <= 1 )
{
*aStartTrack = *aEndTrack = this;
return 1;
}
/* Calculation of the limit analysis. */
*aStartTrack = *aEndTrack = NULL;
TrackListEnd = Track = this;
ii = 0;
for( ; ( Track != NULL ) && ( ii < aCount ); ii++, Track = Track->Next() )
{
TrackListEnd = Track;
Track->m_Param = 0;
}
/* Calculate the extremes. */
NbEnds = 0;
Track = this;
ii = 0;
for( ; ( Track != NULL ) && ( ii < aCount ); ii++, Track = Track->Next() )
{
if( Track->Type() == TYPE_VIA )
continue;
layerMask = Track->ReturnMaskLayer();
via = GetVia( TrackListEnd, Track->m_Start, layerMask );
if( via )
{
layerMask |= via->ReturnMaskLayer();
via->SetState( BUSY, ON );
}
Track->SetState( BUSY, ON );
segm = GetTraceByEndPoint( this, TrackListEnd, Track->m_Start, layerMask );
Track->SetState( BUSY, OFF );
if( via )
via->SetState( BUSY, OFF );
if( segm == NULL )
{
switch( NbEnds )
{
case 0:
*aStartTrack = Track; NbEnds++;
break;
case 1:
int BeginPad, EndPad;
*aEndTrack = Track;
/* Swap ox, oy with fx, fy */
BeginPad = Track->GetState( BEGIN_ONPAD );
EndPad = Track->GetState( END_ONPAD );
Track->SetState( BEGIN_ONPAD | END_ONPAD, OFF );
if( BeginPad )
Track->SetState( END_ONPAD, ON );
if( EndPad )
Track->SetState( BEGIN_ONPAD, ON );
EXCHG( Track->m_Start, Track->m_End );
EXCHG( Track->start, Track->end );
ok = 1;
return ok;
}
}
layerMask = Track->ReturnMaskLayer();
via = GetVia( TrackListEnd, Track->m_End, layerMask );
if( via )
{
layerMask |= via->ReturnMaskLayer();
via->SetState( BUSY, ON );
}
Track->SetState( BUSY, ON );
segm = GetTraceByEndPoint( this, TrackListEnd, Track->m_End, layerMask );
Track->SetState( BUSY, OFF );
if( via )
via->SetState( BUSY, OFF );
if( segm == NULL )
{
switch( NbEnds )
{
case 0:
int BeginPad, EndPad;
*aStartTrack = Track;
NbEnds++;
/* Swap ox, oy with fx, fy */
BeginPad = Track->GetState( BEGIN_ONPAD );
EndPad = Track->GetState( END_ONPAD );
Track->SetState( BEGIN_ONPAD | END_ONPAD, OFF );
if( BeginPad )
Track->SetState( END_ONPAD, ON );
if( EndPad )
Track->SetState( BEGIN_ONPAD, ON );
EXCHG( Track->m_Start, Track->m_End );
EXCHG( Track->start, Track->end );
break;
case 1:
*aEndTrack = Track;
ok = 1;
return ok;
}
}
}
return ok;
}
TRACK* TRACK::GetTrace( const wxPoint& aPosition, int aLayer )
{
for( TRACK* track = this; track; track = track->Next() )
{
int layer = track->GetLayer();
if( track->GetState( BUSY | IS_DELETED ) )
{
// D( printf( "track %p is BUSY | IS_DELETED. BUSY=%d IS_DELETED=%d\n",
// track, track->GetState( BUSY ),
// track->GetState( IS_DELETED ) );)
continue;
}
if( GetBoard()->GetBoardDesignSettings()->IsLayerVisible( layer ) == false )
continue;
if( track->Type() == TYPE_VIA ) /* VIA encountered. */
{
if( track->HitTest( aPosition ) )
return track;
}
else
{
if( (g_TabOneLayerMask[layer] & aLayer) == 0 )
continue; /* Segments on different layers. */
if( track->HitTest( aPosition ) )
return track;
}
}
return NULL;
}
TRACK* TRACK::GetVia( const wxPoint& aPosition, int aLayer )
{
TRACK* track;
for( track = this; track; track = track->Next() )
{
if( track->Type() != TYPE_VIA )
continue;
if( !track->HitTest( aPosition ) )
continue;
if( track->GetState( BUSY | IS_DELETED ) )
continue;
if( aLayer < 0 )
break;
if( track->IsOnLayer( aLayer ) )
break;
}
return track;
}
TRACK* TRACK::GetVia( TRACK* aEndTrace, const wxPoint& aPosition, int aLayer )
{
TRACK* trace;
for( trace = this; trace != NULL; trace = trace->Next() )
{
if( trace->Type() == TYPE_VIA )
{
if( aPosition == trace->m_Start )
{
if( trace->GetState( BUSY | IS_DELETED ) == 0 )
{
if( aLayer & trace->ReturnMaskLayer() )
return trace;
}
}
}
if( trace == aEndTrace )
break;
}
return NULL;
}
void SEGVIA::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, int draw_mode, const wxPoint& aOffset )
{
int color;
@ -986,10 +830,8 @@ void SEGVIA::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, int draw_mode, const wxPoint
else
{
GRCircle( &panel->m_ClipBox, DC, m_Start + aOffset,radius, 0, color );
if ( fast_draw )
return;
GRCircle( &panel->m_ClipBox, DC, m_Start + aOffset, inner_radius, 0, color );
}
@ -997,8 +839,8 @@ void SEGVIA::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, int draw_mode, const wxPoint
if( DisplayOpt.m_DisplayViaMode != VIA_HOLE_NOT_SHOW )
{
if( (DisplayOpt.m_DisplayViaMode == ALL_VIA_HOLE_SHOW) // Display all drill holes requested
|| ( (drill_radius > 0 ) && !IsDrillDefault() ) ) // Or Display non default holes
{ // requested.
|| ( (drill_radius > 0 ) && !IsDrillDefault() ) ) // Or Display non default holes requested
{
if( fillvia )
{
bool blackpenstate = false;
@ -1135,6 +977,7 @@ void SEGVIA::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, int draw_mode, const wxPoint
}
// see class_track.h
void TRACK::DisplayInfo( EDA_DRAW_FRAME* frame )
{
wxString msg;
@ -1148,7 +991,7 @@ void TRACK::DisplayInfo( EDA_DRAW_FRAME* frame )
{
int trackLen = 0;
int lenDie = 0;
board->MarkTrace( this, NULL, &trackLen, &lenDie, false );
MarkTrace( board, this, NULL, &trackLen, &lenDie, false );
msg = frame->CoordinateToString( trackLen );
frame->AppendMsgPanel( _( "Track Len" ), msg, DARKCYAN );
@ -1183,6 +1026,13 @@ void TRACK::DisplayInfo( EDA_DRAW_FRAME* frame )
}
/*
* Function DisplayInfoBase
* has knowledge about the frame and how and where to put status information
* about this object into the frame's message panel.
* Display info about the track segment only, and does not calculate the full track length
* @param frame A EDA_DRAW_FRAME in which to print status information.
*/
void TRACK::DisplayInfoBase( EDA_DRAW_FRAME* frame )
{
wxString msg;
@ -1298,6 +1148,12 @@ void TRACK::DisplayInfoBase( EDA_DRAW_FRAME* frame )
}
/**
* Function HitTest
* tests if the given wxPoint is within the bounds of this object.
* @param refPos A wxPoint to test
* @return bool - true if a hit, else false
*/
bool TRACK::HitTest( const wxPoint& refPos )
{
int radius = m_Width >> 1;
@ -1324,6 +1180,13 @@ bool TRACK::HitTest( const wxPoint& refPos )
}
/**
* Function HitTest (overlaid)
* tests if the given EDA_RECT intersect this object.
* For now, an ending point must be inside this rect.
* @param refArea an EDA_RECT to test
* @return bool - true if a hit, else false
*/
bool TRACK::HitTest( EDA_RECT& refArea )
{
if( refArea.Contains( m_Start ) )
@ -1368,6 +1231,13 @@ wxString TRACK::GetSelectMenuText() const
#if defined(DEBUG)
/**
* Function Show
* is used to output the object tree, currently for debugging only.
* @param nestLevel An aid to prettier tree indenting, and is the level
* of nesting of this object within the overall tree.
* @param os The ostream& to output to.
*/
void TRACK::Show( int nestLevel, std::ostream& os )
{
NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str() <<
@ -1388,6 +1258,13 @@ void TRACK::Show( int nestLevel, std::ostream& os )
}
/**
* Function Show
* is used to output the object tree, currently for debugging only.
* @param nestLevel An aid to prettier tree indenting, and is the level
* of nesting of this object within the overall tree.
* @param os The ostream& to output to.
*/
void SEGVIA::Show( int nestLevel, std::ostream& os )
{
const char* cp;

View File

@ -1,7 +1,6 @@
/**
* @file class_track.h
* @brief Class definitions for tracks, vias, and zones.
*/
/*******************************************************************/
/* class_track.h: definitions relatives to tracks, vias and zones */
/*******************************************************************/
#ifndef CLASS_TRACK_H
#define CLASS_TRACK_H
@ -17,9 +16,6 @@
* to the near neighbor internal layer */
#define VIA_NOT_DEFINED 0 /* not yet used */
#define IGNORE_LAYERS -1
/***/
class TRACK : public BOARD_CONNECTED_ITEM
@ -145,50 +141,6 @@ public:
}
/**
* Function GetEndSegments
* get the end points connected to the track.
*
* @param aCount The maximum number of connected segments to test.
* @param aStartTrack The beginning segment connected to the trace.
* @param aEndTrack The end segment connected to the trace.
* @return A 1 if the end points are valid or a 0 when a trace is a closed loop.
*/
int GetEndSegments( int aCount, TRACK** aStartTrack, TRACK** aEndTrack );
/**
* Function GetTrace
* returns a trace segment or via at \a aPosition on \a aLayer starting from this
* trace.
*
* @param aPosition The wxPoint to HitTest() against.
* @param aLayer The layer to search. Use -1 for a don't care.
* @return A pointer to the TRACK or SEGVIA object if found, else NULL.
*/
TRACK* GetTrace( const wxPoint& aPosition, int aLayer );
/**
* Function GetVia
* finds the first SEGVIA object at \a aPosition on \a aLayer starting at the trace.
*
* @param aPosition The wxPoint to HitTest() against.
* @param aLayer The layer to match, pass -1 for a don't care.
* @return A pointer to a TRACK object ( actually a SEGVIA ) if found, else NULL.
*/
TRACK* GetVia( const wxPoint& aPosition, int aLayer = IGNORE_LAYERS );
/**
* Function GetVia
* finds the first SEGVIA object at \a aPosition on \a aLayer starting at the trace
* and ending at \a aEndTrace.
*
* @param aEndTrace Pointer to the last TRACK object to end search.
* @param aPosition The wxPoint to HitTest() against.
* @param aLayer The layer to match, pass -1 for a don't care.
* @return A pointer to a TRACK object ( actually a SEGVIA ) if found, else NULL.
*/
TRACK* GetVia( TRACK* aEndTrace, const wxPoint& aPosition, int aLayer );
/* Display on screen: */
void Draw( EDA_DRAW_PANEL* panel, wxDC* DC, int aDrawMode,
const wxPoint& aOffset = ZeroOffset );
@ -246,12 +198,7 @@ public:
*/
int ReturnMaskLayer();
/**
* Function IsPointOnEnds
* returns #STARTPOINT or #ENDPOINT if the start or end point is within \a aDistance
* of \a aPosition otherwise 0 is returned.
*/
int IsPointOnEnds( const wxPoint& aPosition, int aDistance = 0 );
int IsPointOnEnds( const wxPoint& point, int min_dist = 0 );
/**
* Function IsNull
@ -404,6 +351,7 @@ public:
void Draw( EDA_DRAW_PANEL* panel, wxDC* DC, int aDrawMode,
const wxPoint& aOffset = ZeroOffset );
/**
* Function IsOnLayer
* tests to see if this object is on the given layer. Is virtual
@ -413,25 +361,7 @@ public:
*/
bool IsOnLayer( int aLayer ) const;
/**
* Function SetLayerPair
* set the .m_Layer member for a via m_Layer contains the 2 layers :
* top layer and bottom layer used by the via.
* The via connect all layers from top layer to bottom layer
* 4 bits for the first layer and 4 next bits for the second layer
* @param top_layer = first layer connected by the via
* @param bottom_layer = last layer connected by the via
*/
void SetLayerPair( int top_layer, int bottom_layer );
/**
* Function ReturnLayerPair
* return the 2 layers used by the via (the via actually uses all layers between
* these 2 layers)
*
* @param top_layer = pointer to the first layer (can be null)
* @param bottom_layer = pointer to the last layer (can be null)
*/
void ReturnLayerPair( int* top_layer, int* bottom_layer ) const;
/**

View File

@ -857,26 +857,43 @@ bool ZONE_CONTAINER::HitTest( const wxPoint& refPos )
}
bool ZONE_CONTAINER::HitTestForCorner( const wxPoint& aPosition, int aMinDistance )
/**
* Function HitTestForCorner
* tests if the given wxPoint near a corner, or near the segment define by 2 corners.
* Choose the nearest corner
* "near" means grid size (or CORNER_MIN_DIST if grid is not known)
* Set m_CornerSelection to corner index in .m_Poly-&gtcorner or -1 if no corner found
* @return true if a corner found
* @param refPos : A wxPoint to test
*/
bool ZONE_CONTAINER::HitTestForCorner( const wxPoint& refPos )
{
m_CornerSelection = -1; // Set to not found
int x, y;
int closestDistance = aMinDistance;
#define CORNER_MIN_DIST 100 // distance (in internal units) to detect a corner in a zone outline
int min_dist = CORNER_MIN_DIST + 1;
if( GetBoard() && GetBoard()->m_PcbFrame )
{
// Use grid size because it is known
wxRealPoint grid = GetBoard()->m_PcbFrame->DrawPanel->GetGrid();
min_dist = wxRound( MIN( grid.x, grid.y ) );
}
wxPoint delta;
unsigned lim = m_Poly->corner.size();
for( unsigned item_pos = 0; item_pos < lim; item_pos++ )
{
x = aPosition.x - m_Poly->corner[item_pos].x;
y = aPosition.y - m_Poly->corner[item_pos].y;
delta.x = refPos.x - m_Poly->corner[item_pos].x;
delta.y = refPos.y - m_Poly->corner[item_pos].y;
// Calculate a distance:
int dist = MAX( abs( x ), abs( y ) );
int dist = MAX( abs( delta.x ), abs( delta.y ) );
if( dist < closestDistance ) // this corner is a candidate:
if( dist < min_dist ) // this corner is a candidate:
{
m_CornerSelection = item_pos;
closestDistance = dist;
min_dist = dist;
}
}
@ -884,13 +901,31 @@ bool ZONE_CONTAINER::HitTestForCorner( const wxPoint& aPosition, int aMinDistanc
}
bool ZONE_CONTAINER::HitTestForEdge( const wxPoint& aPosition, int aMinDistance )
/**
* Function HitTestForEdge
* tests if the given wxPoint near a corner, or near the segment define by 2 corners.
* choose the nearest segment
* "near" means grid size (or EDGE_MIN_DIST if grid is not known)
* Set m_CornerSelection to -1 if nothing found, or index of the starting corner of edge
* in .m_Poly-&gtcorner
* @return true if found
* @param refPos : A wxPoint to test
*/
bool ZONE_CONTAINER::HitTestForEdge( const wxPoint& refPos )
{
unsigned lim = m_Poly->corner.size();
m_CornerSelection = -1; // Set to not found
int closestDistance = aMinDistance;
#define EDGE_MIN_DIST 200 // distance (in internal units) to detect a zone outline
int min_dist = EDGE_MIN_DIST+1;
if( GetBoard() && GetBoard()->m_PcbFrame )
{
// Use grid size because it is known
wxRealPoint grid = GetBoard()->m_PcbFrame->DrawPanel->GetGrid();
min_dist = wxRound( MIN( grid.x, grid.y ) );
}
unsigned first_corner_pos = 0;
@ -910,17 +945,17 @@ bool ZONE_CONTAINER::HitTestForEdge( const wxPoint& aPosition, int aMinDistance
}
/* test the dist between segment and ref point */
int dist = (int) GetPointToLineSegmentDistance( aPosition.x,
aPosition.y,
int dist = (int) GetPointToLineSegmentDistance( refPos.x,
refPos.y,
m_Poly->corner[item_pos].x,
m_Poly->corner[item_pos].y,
m_Poly->corner[end_segm].x,
m_Poly->corner[end_segm].y );
if( dist < closestDistance )
if( dist < min_dist )
{
m_CornerSelection = item_pos;
closestDistance = dist;
min_dist = dist;
}
}

View File

@ -12,10 +12,6 @@
#include "class_zone_setting.h"
#define CORNER_MIN_DIST 100 // distance (in internal units) to detect a corner in a zone outline
#define EDGE_MIN_DIST 200 // distance (in internal units) to detect a zone outline
/* a small class used when filling areas with segments */
class SEGMENT
{
@ -250,23 +246,21 @@ public:
/**
* Function HitTestForCorner
* tests if \a aPosition is with \a aDistance a zone corner.
* tests if the given wxPoint near a corner
* Set m_CornerSelection to -1 if nothing found, or index of corner
* @return true if found
* @param aPosition A wxPoint to test
* @param aMinDistance The minimum distance with \a aPosition that will still yield a hit.
* @param refPos : A wxPoint to test
*/
bool HitTestForCorner( const wxPoint& aPosition, int aMinDistance = CORNER_MIN_DIST );
bool HitTestForCorner( const wxPoint& refPos );
/**
* Function HitTestForEdge
* tests if the given wxPoint is near a segment defined by 2 corners.
* Set m_CornerSelection to -1 if nothing found, or index of the starting corner of vertice
* @return true if found
* @param aPosition A wxPoint to test
* @param aMinDistance The minimum distance with \a aPosition that will still yield a hit.
* @param refPos : A wxPoint to test
*/
bool HitTestForEdge( const wxPoint& aPosition, int aMinDistance = EDGE_MIN_DIST );
bool HitTestForEdge( const wxPoint& refPos );
/**
* Function HitTest (overlayed)

View File

@ -153,7 +153,7 @@ void clean_vias( BOARD * aPcb )
if( track->m_Shape != VIA_THROUGH )
continue;
D_PAD* pad = aPcb->GetPadFast( track->m_Start, ALL_CU_LAYERS );
D_PAD* pad = Fast_Locate_Pad_Connecte( aPcb, track->m_Start, ALL_CU_LAYERS );
if( pad && (pad->m_layerMask & EXTERNAL_LAYERS) == EXTERNAL_LAYERS ) // redundant Via
{
@ -225,7 +225,7 @@ static void DeleteUnconnectedTracks( PCB_EDIT_FRAME* frame, wxDC* DC )
D_PAD* pad;
pad = frame->GetBoard()->GetPadFast( segment->m_Start, masklayer );
pad = Fast_Locate_Pad_Connecte( frame->GetBoard(), segment->m_Start, masklayer );
if( pad != NULL )
{
@ -233,7 +233,7 @@ static void DeleteUnconnectedTracks( PCB_EDIT_FRAME* frame, wxDC* DC )
type_end |= START_ON_PAD;
}
pad = frame->GetBoard()->GetPadFast( segment->m_End, masklayer );
pad = Fast_Locate_Pad_Connecte( frame->GetBoard(), segment->m_End, masklayer );
if( pad != NULL )
{
@ -601,7 +601,8 @@ static TRACK* AlignSegment( BOARD* Pcb, TRACK* pt_ref, TRACK* pt_segm, int extre
if( extremite == START )
{
/* We do not have a pad */
if( Pcb->GetPadFast( pt_ref->m_Start, g_TabOneLayerMask[pt_ref->GetLayer()] ) )
if( Fast_Locate_Pad_Connecte( Pcb, pt_ref->m_Start,
g_TabOneLayerMask[pt_ref->GetLayer()] ) )
return NULL;
/* change the common point coordinate of pt_segm tu use the other point
@ -620,7 +621,8 @@ static TRACK* AlignSegment( BOARD* Pcb, TRACK* pt_ref, TRACK* pt_segm, int extre
else /* extremite == END */
{
/* We do not have a pad */
if( Pcb->GetPadFast( pt_ref->m_End, g_TabOneLayerMask[pt_ref->GetLayer()] ) )
if( Fast_Locate_Pad_Connecte( Pcb, pt_ref->m_End,
g_TabOneLayerMask[pt_ref->GetLayer()] ) )
return NULL;
/* change the common point coordinate of pt_segm tu use the other point
@ -780,7 +782,7 @@ static void Gen_Raccord_Track( PCB_EDIT_FRAME* frame, wxDC* DC )
{
TRACK* newTrack;
other = frame->GetBoard()->GetTrace( other, segment->m_Start, layerMask );
other = GetTrace( other, segment->m_Start, layerMask );
if( other == NULL )
break;
@ -829,7 +831,7 @@ static void Gen_Raccord_Track( PCB_EDIT_FRAME* frame, wxDC* DC )
{
TRACK* newTrack;
other = frame->GetBoard()->GetTrace( other, segment->m_End, layerMask );
other = GetTrace( other, segment->m_End, layerMask );
if( other == NULL )
break;
@ -978,7 +980,7 @@ void ConnectDanglingEndToPad( PCB_EDIT_FRAME* frame, wxDC* DC )
if( frame->DrawPanel->m_AbortRequest )
return;
pad = frame->GetBoard()->GetPad( segment, START );
pad = Locate_Pad_Connecte( frame->GetBoard(), segment, START );
if( pad )
{
@ -1002,7 +1004,7 @@ void ConnectDanglingEndToPad( PCB_EDIT_FRAME* frame, wxDC* DC )
}
}
pad = frame->GetBoard()->GetPad( segment, END );
pad = Locate_Pad_Connecte( frame->GetBoard(), segment, END );
if( pad )
{

View File

@ -562,6 +562,28 @@ static D_PAD* SuperFast_Locate_Pad_Connecte( BOARD* aPcb, LISTE_PAD* pt_liste,
}
/**
* Function SortPadsByXCoord
* is used to Sort a pad list by x coordinate value.
*/
static int SortPadsByXCoord( const void* pt_ref, const void* pt_comp )
{
D_PAD* ref = *(LISTE_PAD*) pt_ref;
D_PAD* comp = *(LISTE_PAD*) pt_comp;
return ref->m_Pos.x - comp->m_Pos.x;
}
void CreateSortedPadListByXCoord( BOARD* aBoard, std::vector<D_PAD*>* aVector )
{
aVector->insert( aVector->end(), aBoard->m_NetInfo->m_PadsFullList.begin(),
aBoard->m_NetInfo->m_PadsFullList.end() );
qsort( &(*aVector)[0], aBoard->GetPadsCount(), sizeof( D_PAD*), SortPadsByXCoord );
}
/* search connections between tracks and pads, and propagate pad net codes to the track segments
* This is a 2 pass computation.
* First:
@ -600,7 +622,7 @@ void PCB_BASE_FRAME::RecalculateAllTracksNetcode()
/**************************************************************/
/* Pass 1: search the connections between track ends and pads */
/**************************************************************/
m_Pcb->CreateSortedPadListByXCoord( &sortedPads );
CreateSortedPadListByXCoord( m_Pcb, &sortedPads );
/* Reset variables and flags used in computation */
pt_trace = m_Pcb->m_Track;

View File

@ -176,7 +176,7 @@ void PCB_EDIT_FRAME::Remove_One_Track( wxDC* DC, TRACK* pt_segm )
if( pt_segm == NULL )
return;
TRACK* trackList = GetBoard()->MarkTrace( pt_segm, &segments_to_delete_count,
TRACK* trackList = MarkTrace( GetBoard(), pt_segm, &segments_to_delete_count,
NULL, NULL, true );
if( segments_to_delete_count == 0 )

View File

@ -411,7 +411,7 @@ void DRC::testPad2Pad()
{
std::vector<D_PAD*> sortedPads;
m_pcb->CreateSortedPadListByXCoord( &sortedPads );
CreateSortedPadListByXCoord( m_pcb, &sortedPads );
// find the max size of the pads (used to stop the test)
int max_size = 0;
@ -420,8 +420,7 @@ void DRC::testPad2Pad()
{
D_PAD* pad = sortedPads[i];
// m_ShapeMaxRadius is the radius value of the circle containing the pad.
if( pad->m_ShapeMaxRadius > max_size )
if( pad->m_ShapeMaxRadius > max_size ) // m_ShapeMaxRadius is the radius value of the circle containing the pad
max_size = pad->m_ShapeMaxRadius;
}

View File

@ -1002,7 +1002,7 @@ void PCB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
wxPoint pos = GetScreen()->GetCrossHairPosition();
track->Draw( DrawPanel, &dc, GR_XOR );
PICKED_ITEMS_LIST itemsListPicker;
TRACK* newtrack = GetBoard()->CreateLockPoint( pos, track, &itemsListPicker );
TRACK* newtrack = CreateLockPoint( GetBoard(), pos, track, &itemsListPicker );
SaveCopyInUndoList( itemsListPicker, UR_UNSPECIFIED );
track->Draw( DrawPanel, &dc, GR_XOR );
newtrack->Draw( DrawPanel, &dc, GR_XOR );

View File

@ -166,7 +166,7 @@ void PCB_EDIT_FRAME::Edit_Track_Width( wxDC* aDC, TRACK* aTrackSegment )
if( aTrackSegment == NULL )
return;
pt_track = GetBoard()->MarkTrace( aTrackSegment, &nb_segm, NULL, NULL, true );
pt_track = MarkTrace( GetBoard(), aTrackSegment, &nb_segm, NULL, NULL, true );
PICKED_ITEMS_LIST itemsListPicker;
bool change = false;

View File

@ -33,7 +33,7 @@ void PCB_EDIT_FRAME::ExChange_Track_Layer( TRACK* pt_segm, wxDC* DC )
l1 = Route_Layer_TOP; l2 = Route_Layer_BOTTOM;
pt_track = GetBoard()->MarkTrace( pt_segm, &nb_segm, NULL, NULL, true );
pt_track = MarkTrace( GetBoard(), pt_segm, &nb_segm, NULL, NULL, true );
if ( DC )
DrawTraces( DrawPanel, DC, pt_track, nb_segm, GR_XOR );
@ -87,8 +87,8 @@ void PCB_EDIT_FRAME::ExChange_Track_Layer( TRACK* pt_segm, wxDC* DC )
for( ; ii < nb_segm; pt_segm = pt_segm->Next(), ii++ )
{
pt_segm->start = GetBoard()->GetPad( pt_segm, START );
pt_segm->end = GetBoard()->GetPad( pt_segm, END );
pt_segm->start = Locate_Pad_Connecte( GetBoard(), pt_segm, START );
pt_segm->end = Locate_Pad_Connecte( GetBoard(), pt_segm, END );
}
test_1_net_connexion( DC, pt_track->GetNet() );
@ -113,7 +113,7 @@ bool PCB_EDIT_FRAME::Other_Layer_Route( TRACK* aTrack, wxDC* DC )
}
/* Avoid more than one via on the current location: */
if( GetBoard()->GetVia( g_CurrentTrackSegment->m_End, g_CurrentTrackSegment->GetLayer() ) )
if( Locate_Via( GetBoard(), g_CurrentTrackSegment->m_End, g_CurrentTrackSegment->GetLayer() ) )
return false;
for( TRACK* segm = g_FirstTrackSegment; segm; segm = segm->Next() )
@ -277,7 +277,7 @@ void PCB_EDIT_FRAME::DisplayNetStatus( wxDC* DC )
int layerMask = (1 << getActiveLayer());
wxPoint pos = GetScreen()->RefPos( true );
pt_segm = GetBoard()->GetTrace( pos, layerMask );
pt_segm = GetTrace( GetBoard(), GetBoard()->m_Track, pos, layerMask );
if( pt_segm == NULL )
GetBoard()->DisplayInfo( this );

View File

@ -104,7 +104,7 @@ TRACK* PCB_EDIT_FRAME::Begin_Route( TRACK* aTrack, wxDC* DC )
GetBoard()->SetHightLightNet(0);
// Search for a starting point of the new track, a track or pad
LockPoint = GetBoard()->GetLockPoint( pos, layerMask );
LockPoint = LocateLockPoint( GetBoard(), pos, layerMask );
if( LockPoint ) // An item (pad or track) is found
{
@ -120,7 +120,7 @@ TRACK* PCB_EDIT_FRAME::Begin_Route( TRACK* aTrack, wxDC* DC )
{
TrackOnStartPoint = (TRACK*) LockPoint;
GetBoard()->SetHightLightNet( TrackOnStartPoint->GetNet() );
GetBoard()->CreateLockPoint( pos, TrackOnStartPoint, &s_ItemsListPicker );
CreateLockPoint( GetBoard(), pos, TrackOnStartPoint, &s_ItemsListPicker );
}
}
else // no starting point, but a filled zone area can exist. This is
@ -247,7 +247,7 @@ TRACK* PCB_EDIT_FRAME::Begin_Route( TRACK* aTrack, wxDC* DC )
newTrack->SetState( BEGIN_ONPAD | END_ONPAD, OFF );
oneBeforeLatest->end = GetBoard()->GetPad( oneBeforeLatest, END );
oneBeforeLatest->end = Locate_Pad_Connecte( GetBoard(), oneBeforeLatest, END );
if( oneBeforeLatest->end )
{
@ -451,7 +451,7 @@ bool PCB_EDIT_FRAME::End_Route( TRACK* aTrack, wxDC* DC )
* This helps to reduce the computing time */
/* Attaching the end of the track. */
BOARD_ITEM* LockPoint = GetBoard()->GetLockPoint( pos, layerMask );
BOARD_ITEM* LockPoint = LocateLockPoint( GetBoard(), pos, layerMask );
if( LockPoint ) /* End of trace is on a pad. */
{
@ -466,7 +466,8 @@ bool PCB_EDIT_FRAME::End_Route( TRACK* aTrack, wxDC* DC )
GetBoard()->SetHightLightNet( adr_buf->GetNet() );
/* Possible establishment of a hanging point. */
LockPoint = GetBoard()->CreateLockPoint( g_CurrentTrackSegment->m_End,
LockPoint = CreateLockPoint( GetBoard(),
g_CurrentTrackSegment->m_End,
adr_buf,
&s_ItemsListPicker );
}
@ -1049,7 +1050,7 @@ void DeleteNullTrackSegments( BOARD* pcb, DLIST<TRACK>& aTrackList )
while( track != NULL )
{
TRACK* next_track = track->Next();
LockPoint = pcb->GetPad( track, END );
LockPoint = Locate_Pad_Connecte( pcb, track, END );
if( LockPoint )
{

View File

@ -555,7 +555,7 @@ void PCB_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotkeyCode, const wxPoint& aPosit
if( !itemCurrentlyEdited )
{
pos = screen->RefPos( true );
module = GetBoard()->GetModule( pos, screen->m_Active_Layer, true );
module = Locate_Prefered_Module( GetBoard(), pos, screen->m_Active_Layer, true );
}
else if( GetCurItem()->Type() == TYPE_MODULE )
{
@ -641,7 +641,7 @@ bool PCB_EDIT_FRAME::OnHotkeyDeleteItem( wxDC* aDC )
if( ItemFree )
{
wxPoint pos = GetScreen()->RefPos( false );
MODULE* module = GetBoard()->GetModule( pos, ALL_LAYERS, false );
MODULE* module = Locate_Prefered_Module( GetBoard(), pos, ALL_LAYERS, false );
if( module == NULL )
return false;
@ -659,20 +659,15 @@ bool PCB_EDIT_FRAME::OnHotkeyDeleteItem( wxDC* aDC )
if( ItemFree )
{
item = PcbGeneralLocateAndDisplay();
if( item == NULL )
return false;
if( (item->Type() == TYPE_MODULE) && !IsOK( this, _( "Delete module?" ) ) )
return false;
RemoveStruct( item, aDC );
}
else
{
return false;
}
}
OnModify();
SetCurItem( NULL );

View File

@ -40,7 +40,7 @@ bool PCB_EDIT_FRAME::Clear_Pcb( bool aQuery )
// delete the old BOARD and create a new BOARD so that the default
// layer names are put into the BOARD.
SetBoard( new BOARD( NULL ) );
SetBoard( new BOARD( NULL, this ) );
SetCurItem( NULL );
/* clear filename, to avoid overwriting an old file */

View File

@ -13,6 +13,246 @@
/* Locates a via point pX, pY
* If layer < 0 will be located via whatever layer
* If layer = 0 .. 15 Via will be located according to its type:
* - Traverse: all layers
* - = Blind between layers useful
* - Blind idem
* Entry: coord point of reference, layer
* Output: NULL if not via
* (* TRACK) address via
*/
TRACK* Locate_Via( BOARD* Pcb, const wxPoint& pos, int layer )
{
TRACK* track;
for( track = Pcb->m_Track; track; track = track->Next() )
{
if( track->Type() != TYPE_VIA )
continue;
if( track->m_Start != pos )
continue;
if( track->GetState( BUSY | IS_DELETED ) )
continue;
if( layer < 0 )
break;
if( track->IsOnLayer( layer ) )
break;
}
return track;
}
TRACK* Locate_Via_Area( TRACK* aStart, const wxPoint& pos, int layer )
{
TRACK* track;
for( track = aStart; track; track = track->Next() )
{
if( track->Type() != TYPE_VIA )
continue;
if( !track->HitTest(pos) )
continue;
if( track->GetState( BUSY | IS_DELETED ) )
continue;
if( layer < 0 )
break;
if( track->IsOnLayer( layer ) )
break;
}
return track;
}
/* Locate the pad CONNECTED to a track
* input: ptr_trace: pointer to the segment of track
* Extr = flag = START -> beginning of the test segment
* END -> end of the segment to be tested
* Returns:
* A pointer to the description of the pad if found.
* NULL pointer if pad NOT FOUND
*/
D_PAD* Locate_Pad_Connecte( BOARD* Pcb, TRACK* ptr_trace, int extr )
{
D_PAD* ptr_pad = NULL;
wxPoint ref_pos;
int aLayerMask = g_TabOneLayerMask[ptr_trace->GetLayer()];
if( extr == START )
{
ref_pos = ptr_trace->m_Start;
}
else
{
ref_pos = ptr_trace->m_End;
}
for( MODULE* module = Pcb->m_Modules; module; module = module->Next() )
{
ptr_pad = Locate_Pads( module, ref_pos, aLayerMask );
if( ptr_pad != NULL )
break;
}
return ptr_pad;
}
/*
* Locate a pad pointed to by the coordinates ref_pos.x, ref_pos.y
* aLayerMask is allowed layers ( bitmap mask)
* Returns:
* Pointer to a pad if found or NULL
*/
D_PAD* Locate_Any_Pad( BOARD* Pcb, const wxPoint& ref_pos, int aLayerMask )
{
D_PAD* pad = NULL;
for( MODULE* module=Pcb->m_Modules; module && ( pad == NULL ); module = module->Next() )
{
if( aLayerMask )
pad = Locate_Pads( module, ref_pos, aLayerMask );
else
pad = Locate_Pads( module, ref_pos, ALL_LAYERS );
}
return pad;
}
/* Locate the pad pointed to by the coordinate ref_pos.x,, ref_pos.y
* Input:
* - the footprint to test
* - masque_layer layer(s) (bit_masque) which must be the pad
* Returns:
* A pointer to the pad if found or NULL
*/
D_PAD* Locate_Pads( MODULE* module, const wxPoint& ref_pos, int aLayerMask )
{
for( D_PAD* pt_pad = module->m_Pads; pt_pad; pt_pad = pt_pad->Next() )
{
/* ... and on the correct layer. */
if( ( pt_pad->m_layerMask & aLayerMask ) == 0 )
continue;
if( pt_pad->HitTest( ref_pos ) )
return pt_pad;
}
return NULL;
}
/**
* Function Locate_Prefered_Module
* locates a footprint by its bounding rectangle. If several footprints
* are possible, then the priority is: the closest on the active layer, then
* closest.
* The current mouse or cursor coordinates are grabbed from the active window
* to perform hit-testing.
* distance is calculated via manhattan distance from the center of the
* bounding rectangle to the cursor position.
*
* @param aPcb The BOARD to search within.
* @param aPosition Flag bits, tuning the search, see pcbnew.h
* @param aActiveLayer Layer to test.
* @param aVisibleOnly Search only the visible layers if true.
* @param aIgnoreLocked Ignore locked modules when true.
* @return MODULE* The best module or NULL if none.
*/
MODULE* Locate_Prefered_Module( BOARD* aPcb, const wxPoint& aPosition, int aActiveLayer,
bool aVisibleOnly, bool aIgnoreLocked )
{
MODULE* pt_module;
MODULE* module = NULL;
MODULE* Altmodule = NULL;
int min_dim = 0x7FFFFFFF;
int alt_min_dim = 0x7FFFFFFF;
int layer;
pt_module = aPcb->m_Modules;
for( ; pt_module; pt_module = (MODULE*) pt_module->Next() )
{
// is the ref point within the module's bounds?
if( !pt_module->HitTest( aPosition ) )
continue;
// if caller wants to ignore locked modules, and this one is locked, skip it.
if( aIgnoreLocked && pt_module->IsLocked() )
continue;
/* Calculate priority: the priority is given to the layer of the
* module and the copper layer if the module layer is indelible,
* adhesive copper, a layer if cmp module layer is indelible,
* adhesive component.
*/
layer = pt_module->GetLayer();
if( layer==ADHESIVE_N_BACK || layer==SILKSCREEN_N_BACK )
layer = LAYER_N_BACK;
else if( layer==ADHESIVE_N_FRONT || layer==SILKSCREEN_N_FRONT )
layer = LAYER_N_FRONT;
/* Test of minimum size to choosing the best candidate. */
EDA_RECT bb = pt_module->GetFootPrintRect();
int offx = bb.GetX() + bb.GetWidth() / 2;
int offy = bb.GetY() + bb.GetHeight() / 2;
//off x & offy point to the middle of the box.
int dist = abs( aPosition.x - offx ) + abs( aPosition.y - offy );
//int dist = MIN(lx, ly); // to pick the smallest module (kinda
// screwy with same-sized modules -- this is bad!)
if( aActiveLayer == layer )
{
if( dist <= min_dim )
{
/* better footprint shown on the active layer */
module = pt_module;
min_dim = dist;
}
}
else if( aVisibleOnly && aPcb->IsModuleLayerVisible( layer ) )
{
if( dist <= alt_min_dim )
{
/* better footprint shown on other layers */
Altmodule = pt_module;
alt_min_dim = dist;
}
}
}
if( module )
{
return module;
}
if( Altmodule )
{
return Altmodule;
}
return NULL;
}
/*
* return true if the dist between p1 and p2 < max_dist
* Currently in test (currently rasnest algos work only if p1 == p2)
@ -25,9 +265,7 @@ int dist;
dist = abs(p1.x - p2.x) + abs (p1.y - p2.y);
dist *= 7;
dist /= 10;
if ( dist < max_dist )
return true;
if ( dist < max_dist ) return true;
}
#else
if ( p1 == p2 ) return true;
@ -181,3 +419,168 @@ suite1:
return NULL;
}
/*
* 1 - Locate segment of track leading from the mouse.
* 2 - Locate segment of track point by point
* ref_pos.x, ref_pos.y.r
*
* The search begins to address start_adresse
*/
TRACK* GetTrace( BOARD* aPcb, TRACK* start_adresse, const wxPoint& ref_pos, int LayerMask )
{
for( TRACK* track = start_adresse; track; track = track->Next() )
{
int layer = track->GetLayer();
if( track->GetState( BUSY | IS_DELETED ) )
{
// D( printf( "track %p is BUSY | IS_DELETED. BUSY=%d IS_DELETED=%d\n",
// track, track->GetState( BUSY ),
// track->GetState( IS_DELETED ) );)
continue;
}
if( aPcb->GetBoardDesignSettings()->IsLayerVisible( layer ) == false )
continue;
if( track->Type() == TYPE_VIA ) /* VIA encountered. */
{
if( track->HitTest( ref_pos ) )
return track;
}
else
{
if( (g_TabOneLayerMask[layer] & LayerMask) == 0 )
continue; /* Segments on different layers. */
if( track->HitTest( ref_pos ) )
return track;
}
}
return NULL;
}
/*
* 1 - Locate zone area by the mouse.
* 2 - Locate zone area by point
* def_pos.x, ref_pos.y.r
*
* If layer == -1, tst layer is not
*
* The search begins to address start_adresse
*/
TRACK* Locate_Zone( TRACK* start_adresse, const wxPoint& ref_pos, int layer )
{
for( TRACK* Zone = start_adresse; Zone; Zone = Zone->Next() )
{
if( (layer != -1) && (Zone->GetLayer() != layer) )
continue;
if( Zone->HitTest( ref_pos ) )
return Zone;
}
return NULL;
}
/* Find the pad center px, py,
* The layer INDICATED BY aLayerMask (bitwise)
* (Runway end)
* The list of pads must already exist.
*
* Returns:
* NULL if no pad located.
* Pointer to the structure corresponding descr_pad if pad found
* (Good position and good layer).
*/
D_PAD* Fast_Locate_Pad_Connecte( BOARD* Pcb, const wxPoint& ref_pos, int aLayerMask )
{
for( unsigned i=0; i<Pcb->GetPadsCount(); ++i )
{
D_PAD* pad = Pcb->m_NetInfo->GetPad(i);
if( pad->m_Pos != ref_pos )
continue;
/* Pad found, it must be on the correct layer */
if( pad->m_layerMask & aLayerMask )
return pad;
}
return NULL;
}
/* Locate segment with one end that coincides with the point x, y
* Data on layers by masklayer
* Research is done to address start_adr has end_adr
* If end_adr = NULL, end search list
* The segments of track marks with the flag are not IS_DELETED or taken
* into account
*/
TRACK* GetTrace( TRACK* start_adr, TRACK* end_adr, const wxPoint& ref_pos, int MaskLayer )
{
TRACK* PtSegm;
if( start_adr == NULL )
return NULL;
for( PtSegm = start_adr; PtSegm != NULL; PtSegm = PtSegm->Next() )
{
if( PtSegm->GetState( IS_DELETED | BUSY ) == 0 )
{
if( ref_pos == PtSegm->m_Start )
{
if( MaskLayer & PtSegm->ReturnMaskLayer() )
return PtSegm;
}
if( ref_pos == PtSegm->m_End )
{
if( MaskLayer & PtSegm->ReturnMaskLayer() )
return PtSegm;
}
}
if( PtSegm == end_adr )
break;
}
return NULL;
}
/* Locates via through the point x, y, on layer data by masklayer.
* Search is done to address start_adr has end_adr.
* If end_adr = NULL, end search list
* Vias whose parameter has the State or IS_DELETED bit BUSY = 1 are ignored
*/
TRACK* Fast_Locate_Via( TRACK* start_adr, TRACK* end_adr, const wxPoint& pos, int MaskLayer )
{
TRACK* PtSegm;
for( PtSegm = start_adr; PtSegm != NULL; PtSegm = PtSegm->Next() )
{
if( PtSegm->Type() == TYPE_VIA )
{
if( pos == PtSegm->m_Start )
{
if( PtSegm->GetState( BUSY | IS_DELETED ) == 0 )
{
if( MaskLayer & PtSegm->ReturnMaskLayer() )
return PtSegm;
}
}
}
if( PtSegm == end_adr )
break;
}
return NULL;
}

View File

@ -153,7 +153,7 @@ bool Magnetize( BOARD* m_Pcb, PCB_EDIT_FRAME* frame, int aCurrentTool, wxSize gr
if( doPad )
{
int layer_mask = g_TabOneLayerMask[screen->m_Active_Layer];
D_PAD* pad = m_Pcb->GetPad( pos, layer_mask );
D_PAD* pad = Locate_Any_Pad( m_Pcb, pos, layer_mask );
if( pad )
{
@ -171,7 +171,7 @@ bool Magnetize( BOARD* m_Pcb, PCB_EDIT_FRAME* frame, int aCurrentTool, wxSize gr
int layer = screen->m_Active_Layer;
for( TRACK* via = m_Pcb->m_Track;
via && (via = via->GetVia( *curpos, layer )) != NULL;
via && (via = Locate_Via_Area( via, *curpos, layer )) != NULL;
via = via->Next() )
{
if( via != currTrack ) // a via cannot influence itself
@ -193,7 +193,7 @@ bool Magnetize( BOARD* m_Pcb, PCB_EDIT_FRAME* frame, int aCurrentTool, wxSize gr
{
int layer_mask = g_TabOneLayerMask[layer];
TRACK* track = m_Pcb->m_Track->GetTrace( pos, layer_mask );
TRACK* track = GetTrace( m_Pcb, m_Pcb->m_Track, pos, layer_mask );
if( !track || track->Type() != TYPE_TRACK )
{

View File

@ -127,9 +127,10 @@ FOOTPRINT_EDIT_FRAME::FOOTPRINT_EDIT_FRAME( wxWindow* father,
UpdateTitle();
if( g_ModuleEditor_Pcb == NULL )
g_ModuleEditor_Pcb = new BOARD( NULL );
g_ModuleEditor_Pcb = new BOARD( NULL, this );
SetBoard( g_ModuleEditor_Pcb );
GetBoard()->m_PcbFrame = this;
if( s_screenModule == NULL )
s_screenModule = new PCB_SCREEN();

View File

@ -1019,15 +1019,14 @@ bool PCB_EDIT_FRAME::PlaceDraggedOrMovedTrackSegment( TRACK* Track, wxDC* DC )
* (only pad connection must be tested, track connection will be
* tested by test_1_net_connexion() ) */
int layerMask = g_TabOneLayerMask[Track->GetLayer()];
Track->start = GetBoard()->GetPadFast( Track->m_Start, layerMask );
Track->start = Fast_Locate_Pad_Connecte( GetBoard(), Track->m_Start, layerMask );
if( Track->start )
Track->SetState( BEGIN_ONPAD, ON );
else
Track->SetState( BEGIN_ONPAD, OFF );
Track->end = GetBoard()->GetPadFast( Track->m_End, layerMask );
Track->end = Fast_Locate_Pad_Connecte( GetBoard(), Track->m_End, layerMask );
if( Track->end )
Track->SetState( END_ONPAD, ON );
else
@ -1055,3 +1054,147 @@ bool PCB_EDIT_FRAME::PlaceDraggedOrMovedTrackSegment( TRACK* Track, wxDC* DC )
return true;
}
/* Find the point "attachment" of the end of a trace.
* This may be a TBP or another segment of the trace
* Returns:
* - Pointer to the PAD or:
* - Pointer to the segment or:
* - NULL
* Parameters:
* - position to test
* - mask layers to be tested
*/
BOARD_ITEM* LocateLockPoint( BOARD* Pcb, wxPoint pos, int LayerMask )
{
for( MODULE* module = Pcb->m_Modules; module; module = module->Next() )
{
D_PAD* pad = Locate_Pads( module, pos, LayerMask );
if( pad )
return pad;
}
/* No pad has been located so check for a segment of the trace. */
TRACK* ptsegm = GetTrace( Pcb->m_Track, NULL, pos, LayerMask );
if( ptsegm == NULL )
ptsegm = GetTrace( Pcb, Pcb->m_Track, pos, LayerMask );
return ptsegm;
}
/* Create an intermediate point on a segment
* aSegm segment is broken into 2 segments connecting point pX, pY
* After insertion:
* The new segment starts from to new point, and ends to initial aSegm ending point
* the old segment aSegm ends to new point
* Returns:
* NULL if no new point (ie if aRefPoint already corresponded at one end of aSegm
* or
* Pointer to the segment created
* Returns the exact value of aRefPoint
* If aSegm points to a via:
* Returns the exact value of aRefPoint and a pointer to the via,
* But does not create extra point
*/
TRACK* CreateLockPoint( BOARD* aPcb,
wxPoint& aRefPoint,
TRACK* aSegm,
PICKED_ITEMS_LIST* aItemsListPicker )
{
if( aSegm->m_Start == aRefPoint || aSegm->m_End == aRefPoint )
return NULL;
/* A via is a good lock point */
if( aSegm->Type() == TYPE_VIA )
{
aRefPoint = aSegm->m_Start;
return aSegm;
}
/* Calculation coordinate of intermediate point relative to
* the start point of aSegm
*/
wxPoint delta = aSegm->m_End - aSegm->m_Start;
// Not yet in use:
#if 0
int ox, oy, fx, fy;
if( aRefSegm )
{
ox = aRefSegm->m_Start.x - aSegm->m_Start.x;
oy = aRefSegm->m_Start.y - aSegm->m_Start.y;
fx = aRefSegm->m_End.x - aSegm->m_Start.x;
fy = aRefSegm->m_End.y - aSegm->m_Start.y;
}
#endif
// calculate coordinates of aRefPoint relative to aSegm->m_Start
wxPoint newPoint = aRefPoint - aSegm->m_Start;
// newPoint must be on aSegm:
// Ensure newPoint.y/newPoint.y = delta.y/delta.x
if( delta.x == 0 )
newPoint.x = 0; /* horizontal segment*/
else
newPoint.y = wxRound(( (double)newPoint.x * delta.y ) / delta.x);
/* Create the intermediate point (that is to say creation of a new
* segment, beginning at the intermediate point.
*/
newPoint.x += aSegm->m_Start.x;
newPoint.y += aSegm->m_Start.y;
TRACK* newTrack = aSegm->Copy();
if( aItemsListPicker )
{
ITEM_PICKER picker( newTrack, UR_NEW );
aItemsListPicker->PushItem( picker );
}
DLIST<TRACK>* list = (DLIST<TRACK>*)aSegm->GetList();
wxASSERT( list );
list->Insert( newTrack, aSegm->Next() );
if( aItemsListPicker )
{
ITEM_PICKER picker( aSegm, UR_CHANGED );
picker.m_Link = aSegm->Copy();
aItemsListPicker->PushItem( picker );
}
/* Correct pointer at the end of the new segment. */
newTrack->end = aSegm->end;
newTrack->SetState( END_ONPAD, aSegm->GetState( END_ONPAD ) );
/* Set connections info relative to the new point
*/
/* Old segment now ends at new point. */
aSegm->m_End = newPoint;
aSegm->end = newTrack;
aSegm->SetState( END_ONPAD, OFF );
/* The new segment begins at the new point. */
newTrack->m_Start = newPoint;
newTrack->start = aSegm;
newTrack->SetState( BEGIN_ONPAD, OFF );
D_PAD * pad = Locate_Pad_Connecte( aPcb, newTrack, START );
if ( pad )
{
newTrack->start = pad;
newTrack->SetState( BEGIN_ONPAD, ON );
aSegm->end = pad;
aSegm->SetState( END_ONPAD, ON );
}
aRefPoint = newPoint;
return newTrack;
}

View File

@ -48,8 +48,7 @@ bool PCB_EDIT_FRAME::OnRightClick( const wxPoint& aMousePos, wxMenu* aPopMenu )
{
if( item && item->m_Flags )
{
AddMenuItem( aPopMenu, ID_POPUP_CANCEL_CURRENT_COMMAND, _( "Cancel" ),
KiBitmap( cancel_xpm ) );
AddMenuItem( aPopMenu, ID_POPUP_CANCEL_CURRENT_COMMAND, _( "Cancel" ), KiBitmap( cancel_xpm ) );
}
else
{
@ -167,8 +166,7 @@ bool PCB_EDIT_FRAME::OnRightClick( const wxPoint& aMousePos, wxMenu* aPopMenu )
HK_MOVE_ITEM );
AddMenuItem( aPopMenu, ID_POPUP_PCB_MOVE_DRAWING_REQUEST,
msg, KiBitmap( move_xpm ) );
AddMenuItem( aPopMenu, ID_POPUP_PCB_EDIT_DRAWING, _( "Edit Drawing" ),
KiBitmap( edit_xpm ) );
AddMenuItem( aPopMenu, ID_POPUP_PCB_EDIT_DRAWING, _( "Edit Drawing" ), KiBitmap( edit_xpm ) );
AddMenuItem( aPopMenu, ID_POPUP_PCB_DELETE_DRAWING,
_( "Delete Drawing" ), KiBitmap( delete_xpm ) );
@ -295,8 +293,7 @@ bool PCB_EDIT_FRAME::OnRightClick( const wxPoint& aMousePos, wxMenu* aPopMenu )
case ID_TRACK_BUTT:
if ( ! locate_track ) // This menu is already added when a track is located
AddMenuItem( aPopMenu, Append_Track_Width_List( GetBoard() ),
ID_POPUP_PCB_SELECT_WIDTH, _( "Select Track Width" ),
KiBitmap( width_track_xpm ) );
ID_POPUP_PCB_SELECT_WIDTH, _( "Select Track Width" ), KiBitmap( width_track_xpm ) );
AddMenuItem( aPopMenu, ID_POPUP_PCB_SELECT_CU_LAYER,
_( "Select Working Layer" ), KiBitmap( select_w_layer_xpm ) );
@ -378,8 +375,7 @@ bool PCB_EDIT_FRAME::OnRightClick( const wxPoint& aMousePos, wxMenu* aPopMenu )
*/
void PCB_EDIT_FRAME::createPopUpBlockMenu( wxMenu* menu )
{
AddMenuItem( menu, ID_POPUP_CANCEL_CURRENT_COMMAND, _( "Cancel Block" ),
KiBitmap( cancel_xpm ) );
AddMenuItem( menu, ID_POPUP_CANCEL_CURRENT_COMMAND, _( "Cancel Block" ), KiBitmap( cancel_xpm ) );
AddMenuItem( menu, ID_POPUP_ZOOM_BLOCK, _( "Zoom Block" ), KiBitmap( zoom_area_xpm ) );
menu->AppendSeparator();
AddMenuItem( menu, ID_POPUP_PLACE_BLOCK, _( "Place Block" ), KiBitmap( apply_xpm ) );
@ -408,8 +404,7 @@ void PCB_EDIT_FRAME::createPopupMenuForTracks( TRACK* Track, wxMenu* PopMenu )
{
if( Track->Type() == TYPE_VIA )
{
AddMenuItem( PopMenu, ID_POPUP_PCB_MOVE_TRACK_NODE, _( "Drag Via" ),
KiBitmap( move_xpm ) );
AddMenuItem( PopMenu, ID_POPUP_PCB_MOVE_TRACK_NODE, _( "Drag Via" ), KiBitmap( move_xpm ) );
}
else
{
@ -490,10 +485,10 @@ void PCB_EDIT_FRAME::createPopupMenuForTracks( TRACK* Track, wxMenu* PopMenu )
// Delete control:
PopMenu->AppendSeparator();
wxMenu* track_mnu = new wxMenu;
AddMenuItem( PopMenu, track_mnu, ID_POPUP_PCB_DELETE_TRACK_MNU, _( "Delete" ),
KiBitmap( delete_xpm ) );
AddMenuItem( PopMenu, track_mnu, ID_POPUP_PCB_DELETE_TRACK_MNU, _( "Delete" ), KiBitmap( delete_xpm ) );
msg = AddHotkeyName( Track->Type()==TYPE_VIA ? _( "Delete Via" ) : _( "Delete Segment" ),
msg = AddHotkeyName( Track->Type()==TYPE_VIA ?
_( "Delete Via" ) : _( "Delete Segment" ),
g_Board_Editor_Hokeys_Descr, HK_BACK_SPACE );
AddMenuItem( track_mnu, ID_POPUP_PCB_DELETE_TRACKSEG, msg, KiBitmap( delete_line_xpm ) );
@ -502,8 +497,7 @@ void PCB_EDIT_FRAME::createPopupMenuForTracks( TRACK* Track, wxMenu* PopMenu )
{
msg = AddHotkeyName( _( "Delete Track" ), g_Board_Editor_Hokeys_Descr, HK_DELETE );
AddMenuItem( track_mnu, ID_POPUP_PCB_DELETE_TRACK, msg, KiBitmap( delete_track_xpm ) );
AddMenuItem( track_mnu, ID_POPUP_PCB_DELETE_TRACKNET, _( "Delete Net" ),
KiBitmap( delete_net_xpm ) );
AddMenuItem( track_mnu, ID_POPUP_PCB_DELETE_TRACKNET, _( "Delete Net" ), KiBitmap( delete_net_xpm ) );
}
// Add global edition command
@ -517,8 +511,7 @@ void PCB_EDIT_FRAME::createPopupMenuForTracks( TRACK* Track, wxMenu* PopMenu )
// Add lock/unlock flags menu:
track_mnu = new wxMenu;
AddMenuItem( PopMenu, track_mnu, ID_POPUP_PCB_SETFLAGS_TRACK_MNU, _( "Set Flags" ),
KiBitmap( flag_xpm ) );
AddMenuItem( PopMenu, track_mnu, ID_POPUP_PCB_SETFLAGS_TRACK_MNU, _( "Set Flags" ), KiBitmap( flag_xpm ) );
track_mnu->Append( ID_POPUP_PCB_LOCK_ON_TRACKSEG, _( "Locked: Yes" ), wxEmptyString, true );
track_mnu->Append( ID_POPUP_PCB_LOCK_OFF_TRACKSEG, _( "Locked: No" ), wxEmptyString, true );
@ -564,19 +557,14 @@ void PCB_EDIT_FRAME::createPopUpMenuForZones( ZONE_CONTAINER* edge_zone, wxMenu*
AddMenuItem( aPopMenu, zones_menu, -1, _( "Zones" ), KiBitmap( add_zone_xpm ) );
// Use grid size because it is known
wxRealPoint grid = DrawPanel->GetGrid();
if( edge_zone->HitTestForCorner( GetScreen()->RefPos( true ),
wxRound( MIN( grid.x, grid.y ) ) ) )
if( edge_zone->HitTestForCorner( GetScreen()->RefPos( true ) ) )
{
AddMenuItem( zones_menu, ID_POPUP_PCB_MOVE_ZONE_CORNER,
_( "Move Corner" ), KiBitmap( move_xpm ) );
AddMenuItem( zones_menu, ID_POPUP_PCB_DELETE_ZONE_CORNER,
_( "Delete Corner" ), KiBitmap( delete_xpm ) );
}
else if( edge_zone->HitTestForEdge( GetScreen()->RefPos( true ),
wxRound( MIN( grid.x, grid.y ) ) ) )
else if( edge_zone->HitTestForEdge( GetScreen()->RefPos( true ) ) )
{
AddMenuItem( zones_menu, ID_POPUP_PCB_ADD_ZONE_CORNER,
_( "Create Corner" ), KiBitmap( add_corner_xpm ) );
@ -594,8 +582,7 @@ void PCB_EDIT_FRAME::createPopUpMenuForZones( ZONE_CONTAINER* edge_zone, wxMenu*
_( "Add Cutout Area" ), KiBitmap( add_zone_cutout_xpm ) );
zones_menu->AppendSeparator();
AddMenuItem( zones_menu, ID_POPUP_PCB_FILL_ZONE, _( "Fill Zone" ),
KiBitmap( fill_zone_xpm ) );
AddMenuItem( zones_menu, ID_POPUP_PCB_FILL_ZONE, _( "Fill Zone" ), KiBitmap( fill_zone_xpm ) );
if( edge_zone->m_FilledPolysList.size() > 0 )
{
@ -658,8 +645,7 @@ void PCB_EDIT_FRAME::createPopUpMenuForFootprints( MODULE* aModule, wxMenu* menu
if( !flags )
{
msg = AddHotkeyName( _( "Edit" ), g_Board_Editor_Hokeys_Descr, HK_EDIT_ITEM );
AddMenuItem( sub_menu_footprint, ID_POPUP_PCB_EDIT_MODULE, msg,
KiBitmap( edit_module_xpm ) );
AddMenuItem( sub_menu_footprint, ID_POPUP_PCB_EDIT_MODULE, msg, KiBitmap( edit_module_xpm ) );
sub_menu_footprint->AppendSeparator();
AddMenuItem( sub_menu_footprint, ID_POPUP_PCB_DELETE_MODULE,
_( "Delete Module" ), KiBitmap( delete_module_xpm ) );
@ -739,10 +725,8 @@ void PCB_EDIT_FRAME::createPopUpMenuForFpPads( D_PAD* Pad, wxMenu* menu )
sub_menu_Pad = new wxMenu;
AddMenuItem( menu, sub_menu_Pad, -1, msg, KiBitmap( pad_xpm ) );
AddMenuItem( sub_menu_Pad, ID_POPUP_PCB_MOVE_PAD_REQUEST, _( "Move" ),
KiBitmap( move_pad_xpm ) );
AddMenuItem( sub_menu_Pad, ID_POPUP_PCB_DRAG_PAD_REQUEST, _( "Drag" ),
KiBitmap( drag_pad_xpm ) );
AddMenuItem( sub_menu_Pad, ID_POPUP_PCB_MOVE_PAD_REQUEST, _( "Move" ), KiBitmap( move_pad_xpm ) );
AddMenuItem( sub_menu_Pad, ID_POPUP_PCB_DRAG_PAD_REQUEST, _( "Drag" ), KiBitmap( drag_pad_xpm ) );
AddMenuItem( sub_menu_Pad, ID_POPUP_PCB_EDIT_PAD, _( "Edit" ), KiBitmap( options_pad_xpm ) );
sub_menu_Pad->AppendSeparator();
@ -806,17 +790,14 @@ void PCB_EDIT_FRAME::createPopUpMenuForTexts( TEXTE_PCB* Text, wxMenu* menu )
_( "Reset Size" ), KiBitmap( reset_text_xpm ) );
sub_menu_Text->AppendSeparator();
AddMenuItem( sub_menu_Text, ID_POPUP_PCB_DELETE_TEXTEPCB, _( "Delete" ),
KiBitmap( delete_text_xpm ) );
AddMenuItem( sub_menu_Text, ID_POPUP_PCB_DELETE_TEXTEPCB, _( "Delete" ), KiBitmap( delete_text_xpm ) );
}
void PCB_EDIT_FRAME::createPopUpMenuForMarkers( MARKER_PCB* aMarker, wxMenu* aPopMenu )
{
AddMenuItem( aPopMenu, ID_POPUP_PCB_DELETE_MARKER, _( "Delete Marker" ),
KiBitmap( delete_xpm ) );
AddMenuItem( aPopMenu, ID_POPUP_PCB_GETINFO_MARKER, _( "Marker Error Info" ),
KiBitmap( info_xpm ) );
AddMenuItem( aPopMenu, ID_POPUP_PCB_DELETE_MARKER, _( "Delete Marker" ), KiBitmap( delete_xpm ) );
AddMenuItem( aPopMenu, ID_POPUP_PCB_GETINFO_MARKER, _( "Marker Error Info" ), KiBitmap( info_xpm ) );
}

View File

@ -277,11 +277,10 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( wxWindow* parent, const wxString& title,
m_HotkeysZoomAndGridList = g_Board_Editor_Hokeys_Descr;
m_RecordingMacros = -1;
for ( int i = 0; i < 10; i++ )
m_Macros[i].m_Record.clear();
SetBoard( new BOARD( NULL ) );
SetBoard( new BOARD( NULL, this ) );
// Create the PCB_LAYER_WIDGET *after* SetBoard():
@ -418,7 +417,6 @@ PCB_EDIT_FRAME::PCB_EDIT_FRAME( wxWindow* parent, const wxString& title,
PCB_EDIT_FRAME::~PCB_EDIT_FRAME()
{
m_RecordingMacros = -1;
for( int i = 0; i < 10; i++ )
m_Macros[i].m_Record.clear();

View File

@ -1,11 +1,16 @@
/**
* @file pcbnew/protos.h
*/
/***********/
/* protos.h */
/***********/
#ifndef PROTO_H
#define PROTO_H
#include <vector>
class COMMAND;
/**
* Function SwapData
* Used in undo / redo command:
@ -17,6 +22,24 @@
void SwapData( BOARD_ITEM* aItem, BOARD_ITEM* aImage );
/*******************/
/* PAD_CONNECT.CPP */
/*******************/
class D_PAD;
/**
* Function CreateSortedPadListByXCoord
* first empties then fills the vector with all pads and sorts them by
* increasing x coordinate. The vector only holds pointers to the pads and
* those pointers are only references to pads which are owned by the BOARD
* through other links.
* @param aBoard Which board to gather pads from.
* @param aVector Where to put the pad pointers.
*/
void CreateSortedPadListByXCoord( BOARD* aBoard, std::vector<D_PAD*>* aVector );
/***************/
/* TRPISTE.CPP */
/***************/
@ -43,6 +66,31 @@ void DrawTraces( EDA_DRAW_PANEL* panel,
/* LOCATE.CPP : */
/****************/
/* Find a pad by it's name om the module. */
TRACK* Locate_Via( BOARD* Pcb, const wxPoint& pos, int layer = -1 );
/**
* Function Locate_Via_Area
* finds the first SEGVIA which covers the given aPos with a matching layer.
* @param aStart The starting TRACK or SEGVIA in the BOARD's list.
* @param aPos The wxPoint to HitTest() against.
* @param aLayer The layer to match, pass -1 for a don't care.
* @return TRACK* - actually a SEGVIA* if found, else NULL.
*/
TRACK* Locate_Via_Area( TRACK* aStart, const wxPoint& aPos, int aLayer = ALL_LAYERS );
/* Locates the center through the point x, y, on layer data
* by masquelayer.
* Search is done to address start_adr has end_adr (not included)
*/
TRACK* Fast_Locate_Via( TRACK* start_adr, TRACK* end_adr, const wxPoint& pos, int masquelayer );
/* Locates the center through the point x, y, on layer data
* by masquelayer.
* Search is done to address start_adr has end_adr (not included)
*/
TRACK* GetTrace( TRACK* start_adr, TRACK* end_adr, const wxPoint& ref_pos, int masquelayer );
/* Search for segment connected to the segment edge by
* Ptr_piste:
* If int = START, the point of beginning of the segment is used
@ -52,6 +100,86 @@ void DrawTraces( EDA_DRAW_PANEL* panel,
*/
TRACK* GetConnectedTrace( TRACK* aTrace, TRACK* pt_base, TRACK* pt_lim, int extr );
/*
* 1 - Locate segment of track leading from the mouse.
* 2 - Locate segment of track point by point.
* Ref_pX, ref_pY.
*
* If layer <0 the layer is not tested.
*
* The search begins to address start_adresse
*/
TRACK* GetTrace( BOARD* aPcb, TRACK* start_adresse, const wxPoint& ref_pos, int layer );
/* Locate pad connected to the beginning or end of a segment
* Input: pointer to the segment, and flag = START or END
* Returns:
* A pointer to the description of the patch if pad was found.
* NULL pointer if pad was not found.
*/
D_PAD* Locate_Pad_Connecte( BOARD* aPcb, TRACK* ptr_segment, int extr );
/*
* Locate pad pointed to by the coordinate ref_pX,, ref_pY or the current
* cursor position, search done on all tracks.
* Entry:
* - Mouse coord (Curseur_X and Curseur_Y)
* Or ref_pX, ref_pY
* Returns:
* Pointer to the pad if found
* NULL pointer if pad not found
*/
D_PAD* Locate_Any_Pad( BOARD* aPcb, const wxPoint& aPosition, int aLayerMask = ALL_LAYERS );
/* Locate pad pointed to by the coordinate ref_pX,, ref_pY or the cursor
* position of the current footprint.
* Input:
* - The module to search.
* - Layer to search or -1 to search all layers.
* Returns:
* A pointer to the pad if found otherwise NULL.
*/
D_PAD* Locate_Pads( MODULE* Module, const wxPoint& ref_pos, int layer );
/* Locate a footprint by its bounding rectangle. */
MODULE* Locate_Prefered_Module( BOARD* aPcb, const wxPoint& aPosition, int aActiveLayer,
bool aVisibleOnly, bool aIgnoreLocked = false );
/* Locate a pad pointed to by the cursor on the footprint.
* Module.
* Input:
* - Module to search.
* Returns:
* A pointer to the pad if found otherwise NULL.
*/
D_PAD* Locate_Pads( MODULE* Module, int typeloc );
/* Locate a trace segment at the current cursor position.
* The search begins to address start_adresse.
*/
TRACK* GetTrace( TRACK* start_adresse, int typeloc );
DRAWSEGMENT* Locate_Segment_Pcb( BOARD* Pcb, int LayerSearch, int typeloc );
/* Locate pad containing the point px, py, layer on layer.
*
* The list of pads must already exist.
*
* Returns:
* Pointer to the pad if found, otherwise NULL.
*/
D_PAD* Fast_Locate_Pad_Connecte( BOARD* Pcb, const wxPoint& ref_pos, int layer );
/*
* 1 - Locate trace segment at the current cursor position.
* 2 - Locate trace segment at the given coordinates ref_pos.
*
* If layer == -1, check all layers.
*
* The search begins to address start_adresse
*/
TRACK* Locate_Zone( TRACK* start_adresse, const wxPoint& ref_pos, int layer );
/*************/
/* MODULES.C */
@ -76,9 +204,84 @@ void ShowNewTrackWhenMovingCursor( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPo
void CalculateSegmentEndPoint( const wxPoint& aPosition, int ox, int oy, int* fx, int* fy );
/*****************/
/* TRACK.CPP : */
/*****************/
/**
* Function MarkTrace
* marks a chain of track segments, connected to aTrackList.
* Each segment is marked by setting the BUSY bit into m_Flags. Electrical
* continuity is detected by walking each segment, and finally the segments
* are rearranged into a contiguous chain within the given list.
*
* @param aPcb = the board to analyze
* @param aStartSegm - The first interesting segment within a list of track
* segment of aPcb
* @param aSegmCount = a pointer to an integer where to return the number of
* interesting segments
* @param aTrackLen = a pointer to an integer where to return the lenght of the
* track
* @param aLengthDie = a pointer to an integer where to return the extra lengths inside
* integrated circuits from the pads connected to this track to the
* die (if any)
* @param aReorder = true for reorder the interesting segments (useful for
* track edition/deletion) in this case the flag BUSY is
* set (the user is responsible of flag clearing). False
* for no reorder : useful when we want just calculate the
* track length in this case, flags are reset
* @return TRACK* the first in the chain of interesting segments.
*/
TRACK* MarkTrace( BOARD* aPcb,
TRACK* aStartSegm,
int* aSegmCount,
int* aTrackLen,
int* aLengthDie,
bool aReorder );
/* Calculate end coordinate of a trace.
* Returns 1 if OK, 0 if trace looped back on itself.
* The coord are returned StartTrack-> ox, oy
* And EndTrack-> fx, fy if OK
* The segments are drawn consecutively.
*/
int ReturnEndsTrack( TRACK* RefTrack, int NbSegm, TRACK** StartTrack, TRACK** EndTrack );
/***************/
/***************/
/* Routine to find the point "attachment" at the end of a trace.
* This may be a PAD or another trace segment.
* Returns:
* - Pointer to the PAD or:
* - Pointer to the segment or:
* - NULL
* Parameters:
* - aPos - coordinate point test
* ALayerMask of mask layers to be tested
*/
BOARD_ITEM* LocateLockPoint( BOARD* aPcb, wxPoint aPos, int aLayerMask );
/* Create an intermediate point on a segment
* aSegm segment is broken into 2 segments connecting point pX, pY
* After insertion:
* The new segment starts from to new point, and ends to initial aSegm ending point
* the old segment aSegm ends to new point
* Returns:
* NULL if no new point (ie if aRefPoint already corresponded at one end of aSegm
* or
* Pointer to the segment created
* Returns the exact value of aRefPoint
* If aSegm points to a via:
* Returns the exact value of aRefPoint and a pointer to the via,
* But does not create extra point
*/
TRACK* CreateLockPoint( BOARD* aPcb,
wxPoint& aRefPoint,
TRACK* aSegm,
PICKED_ITEMS_LIST* aItemsListPicker );
/****************/
/* CONTROLE.CPP */

View File

@ -1268,12 +1268,14 @@ static void AddNewTrace( PCB_EDIT_FRAME* pcbframe, wxDC* DC )
g_CurrentTrackList.PushBack( newTrack );
}
g_FirstTrackSegment->start = pcbframe->GetBoard()->GetPad( g_FirstTrackSegment, START );
g_FirstTrackSegment->start = Locate_Pad_Connecte( pcbframe->GetBoard(),
g_FirstTrackSegment, START );
if( g_FirstTrackSegment->start )
g_FirstTrackSegment->SetState( BEGIN_ONPAD, ON );
g_CurrentTrackSegment->end = pcbframe->GetBoard()->GetPad( g_CurrentTrackSegment, END );
g_CurrentTrackSegment->end = Locate_Pad_Connecte( pcbframe->GetBoard(),
g_CurrentTrackSegment, END );
if( g_CurrentTrackSegment->end )
g_CurrentTrackSegment->SetState( END_ONPAD, ON );

View File

@ -10,6 +10,8 @@
#include "protos.h"
static void ListSetState( EDA_ITEM* Start, int NbItem, int State, int onoff );
extern int ReturnEndsTrack( TRACK* RefTrack, int NbSegm,
TRACK** StartTrack, TRACK** EndTrack );
/**
@ -52,7 +54,7 @@ int PCB_EDIT_FRAME::EraseRedundantTrack( wxDC* aDC,
if( aNewTrack->Type() == TYPE_VIA && ( aNewTrackSegmentsCount > 1 ) )
aNewTrack = aNewTrack->Next();
aNewTrack = GetBoard()->MarkTrace( aNewTrack, &aNewTrackSegmentsCount, NULL, NULL, true );
aNewTrack = MarkTrace( GetBoard(), aNewTrack, &aNewTrackSegmentsCount, NULL, NULL, true );
wxASSERT( aNewTrack );
#if 0 && defined(DEBUG)
@ -90,7 +92,7 @@ int PCB_EDIT_FRAME::EraseRedundantTrack( wxDC* aDC,
break;
}
if( aNewTrack->GetEndSegments( aNewTrackSegmentsCount, &StartTrack, &EndTrack ) == 0 )
if( ReturnEndsTrack( aNewTrack, aNewTrackSegmentsCount, &StartTrack, &EndTrack ) == 0 )
return 0;
if( ( StartTrack == NULL ) || ( EndTrack == NULL ) )
@ -108,7 +110,7 @@ int PCB_EDIT_FRAME::EraseRedundantTrack( wxDC* aDC,
endmasklayer = EndTrack->ReturnMaskLayer();
/* There may be a via or a pad on the end points. */
pt_segm = m_Pcb->m_Track->GetVia( NULL, start, startmasklayer );
pt_segm = Fast_Locate_Via( m_Pcb->m_Track, NULL, start, startmasklayer );
if( pt_segm )
startmasklayer |= pt_segm->ReturnMaskLayer();
@ -120,7 +122,7 @@ int PCB_EDIT_FRAME::EraseRedundantTrack( wxDC* aDC,
startmasklayer |= pt_pad->m_layerMask;
}
pt_segm = m_Pcb->m_Track->GetVia( NULL, end, endmasklayer );
pt_segm = Fast_Locate_Via( m_Pcb->m_Track, NULL, end, endmasklayer );
if( pt_segm )
endmasklayer |= pt_segm->ReturnMaskLayer();
@ -139,7 +141,7 @@ int PCB_EDIT_FRAME::EraseRedundantTrack( wxDC* aDC,
/* A segment must be connected to the starting point, otherwise
* it is unnecessary to analyze the other point
*/
pt_segm = GetTraceByEndPoint( bufStart, bufEnd, start, startmasklayer );
pt_segm = GetTrace( bufStart, bufEnd, start, startmasklayer );
if( pt_segm == NULL ) /* Not connected to the track starting point. */
{
@ -154,7 +156,7 @@ int PCB_EDIT_FRAME::EraseRedundantTrack( wxDC* aDC,
*/
for( pt_del = bufStart, nbconnect = 0; ; )
{
pt_segm = GetTraceByEndPoint( pt_del, bufEnd, end, endmasklayer );
pt_segm = GetTrace( pt_del, bufEnd, end, endmasklayer );
if( pt_segm == NULL )
break;
@ -209,7 +211,7 @@ int PCB_EDIT_FRAME::EraseRedundantTrack( wxDC* aDC,
nbconnect--;
pt_del->SetState( IS_LINKED, OFF );
pt_del = GetBoard()->MarkTrace( pt_del, &nb_segm, NULL, NULL, true );
pt_del = MarkTrace( GetBoard(), pt_del, &nb_segm, NULL, NULL, true );
/* Test if the marked track is redundant, i.e. if one of marked segments
* is connected to the starting point of the new track.

541
pcbnew/track.cpp Normal file
View File

@ -0,0 +1,541 @@
/*****************
* track.cpp
*****************/
#include "fctsys.h"
#include "common.h"
#include "pcbnew.h"
#include "protos.h"
/* Functions to recognize a track.
* A track is a list of connected segments (or/and vias)
* from a starting to an ending point
* starting and ending points are a pad or a point with more than 2 segments
*connected
* (and obviously a dangling segment end)
*/
typedef std::vector<TRACK*> TRACK_PTRS; // buffer of item candidates when
// search for items on the same track
/* Local functions */
static void ChainMarkedSegments( BOARD* Pcb,
wxPoint ref_pos,
int masklayer,
TRACK_PTRS* aList );
TRACK* MarkTrace( BOARD* aPcb,
TRACK* aStartSegm,
int* aSegmCount,
int* aTrackLen,
int* aLengthDie,
bool aReorder )
{
int NbSegmBusy;
TRACK_PTRS trackList;
if( aSegmCount )
*aSegmCount = 0;
if( aTrackLen )
*aTrackLen = 0;
if( aStartSegm == NULL )
return NULL;
// Ensure the flag BUSY of all tracks of the board is cleared
// because we use it to mark segments of the track
for( TRACK* track = aPcb->m_Track; track; track = track->Next() )
track->SetState( BUSY, OFF );
/* Set flags of the initial track segment */
aStartSegm->SetState( BUSY, ON );
int layerMask = aStartSegm->ReturnMaskLayer();
trackList.push_back( aStartSegm );
/* Examine the initial track segment : if it is really a segment, this is
* easy.
* If it is a via, one must search for connected segments.
* If <=2, this via connect 2 segments (or is connected to only one
* segment) and this via and these 2 segments are a part of a track.
* If > 2 only this via is flagged (the track has only this via)
*/
if( aStartSegm->Type() == TYPE_VIA )
{
TRACK* Segm1, * Segm2 = NULL, * Segm3 = NULL;
Segm1 = GetTrace( aPcb->m_Track, NULL, aStartSegm->m_Start, layerMask );
if( Segm1 )
{
Segm2 = GetTrace( Segm1->Next(), NULL, aStartSegm->m_Start, layerMask );
}
if( Segm2 )
{
Segm3 = GetTrace( Segm2->Next(), NULL, aStartSegm->m_Start, layerMask );
}
if( Segm3 ) // More than 2 segments are connected to this via. the track" is only this via
{
if( aSegmCount )
*aSegmCount = 1;
return aStartSegm;
}
if( Segm1 ) // search for others segments connected to the initial segment start point
{
layerMask = Segm1->ReturnMaskLayer();
ChainMarkedSegments( aPcb, aStartSegm->m_Start, layerMask, &trackList );
}
if( Segm2 ) // search for others segments connected to the initial segment end point
{
layerMask = Segm2->ReturnMaskLayer();
ChainMarkedSegments( aPcb, aStartSegm->m_Start, layerMask, &trackList );
}
}
else // mark the chain using both ends of the initial segment
{
ChainMarkedSegments( aPcb, aStartSegm->m_Start, layerMask, &trackList );
ChainMarkedSegments( aPcb, aStartSegm->m_End, layerMask, &trackList );
}
// Now examine selected vias and flag them if they are on the track
// If a via is connected to only one or 2 segments, it is flagged (is on
// the track)
// If a via is connected to more than 2 segments, it is a track end, and it
// is removed from the list
// go through the list backwards.
for( int i = trackList.size() - 1; i>=0; --i )
{
TRACK* via = trackList[i];
if( via->Type() != TYPE_VIA )
continue;
if( via == aStartSegm )
continue;
via->SetState( BUSY, ON ); // Try to flag it. the flag will be cleared later if needed
layerMask = via->ReturnMaskLayer();
TRACK* track = GetTrace( aPcb->m_Track, NULL, via->m_Start, layerMask );
// GetTrace does not consider tracks flagged BUSY.
// So if no connected track found, this via is on the current track
// only: keep it
if( track == NULL )
continue;
/* If a track is found, this via connects also others segments of an
* other track. This case happens when the vias ends the selected
* track but must we consider this via is on the selected track, or
* on an other track.
* (this is important when selecting a track for deletion: must this
* via be deleted or not?)
* We consider here this via on the track if others segment connected
* to this via remain connected when removing this via.
* We search for all others segment connected together:
* if there are on the same layer, the via is on the selected track
* if there are on different layers, the via is on an other track
*/
int layer = track->GetLayer();
while( ( track = GetTrace( track->Next(), NULL, via->m_Start, layerMask ) ) != NULL )
{
if( layer != track->GetLayer() )
{
// The via connects segments of an other track: it is removed
// from list because it is member of an other track
via->SetState( BUSY, OFF );
break;
}
}
}
/* Rearrange the track list in order to have flagged segments linked
* from firstTrack so the NbSegmBusy segments are consecutive segments
* in list, the first item in the full track list is firstTrack, and
* the NbSegmBusy-1 next items (NbSegmBusy when including firstTrack)
* are the flagged segments
*/
NbSegmBusy = 0;
TRACK* firstTrack;
for( firstTrack = aPcb->m_Track; firstTrack; firstTrack = firstTrack->Next() )
{
// Search for the first flagged BUSY segments
if( firstTrack->GetState( BUSY ) )
{
NbSegmBusy = 1;
break;
}
}
if( firstTrack == NULL )
return NULL;
double full_len = 0;
double lenDie = 0;
if( aReorder )
{
DLIST<TRACK>* list = (DLIST<TRACK>*)firstTrack->GetList();
wxASSERT( list );
/* Rearrange the chain starting at firstTrack
* All others flagged items are moved from their position to the end
* of the flagged list
*/
TRACK* next;
for( TRACK* track = firstTrack->Next(); track; track = next )
{
next = track->Next();
if( track->GetState( BUSY ) ) // move it!
{
NbSegmBusy++;
track->UnLink();
list->Insert( track, firstTrack->Next() );
if( aTrackLen )
full_len += track->GetLength();
if( aLengthDie ) // Add now length die.
{
// In fact only 2 pads (maximum) will be taken in account:
// that are on each end of the track, if any
if( track->GetState( BEGIN_ONPAD ) )
{
D_PAD * pad = (D_PAD *) track->start;
lenDie += (double) pad->m_LengthDie;
}
if( track->GetState( END_ONPAD ) )
{
D_PAD * pad = (D_PAD *) track->end;
lenDie += (double) pad->m_LengthDie;
}
}
}
}
}
else if( aTrackLen )
{
NbSegmBusy = 0;
for( TRACK* track = firstTrack; track; track = track->Next() )
{
if( track->GetState( BUSY ) )
{
NbSegmBusy++;
track->SetState( BUSY, OFF );
full_len += track->GetLength();
// Add now length die.
// In fact only 2 pads (maximum) will be taken in account:
// that are on each end of the track, if any
if( track->GetState( BEGIN_ONPAD ) )
{
D_PAD * pad = (D_PAD *) track->start;
lenDie += (double) pad->m_LengthDie;
}
if( track->GetState( END_ONPAD ) )
{
D_PAD * pad = (D_PAD *) track->end;
lenDie += (double) pad->m_LengthDie;
}
}
}
}
if( aTrackLen )
*aTrackLen = wxRound( full_len );
if( aLengthDie )
*aLengthDie = wxRound( lenDie );
if( aSegmCount )
*aSegmCount = NbSegmBusy;
return firstTrack;
}
/**
* Function used by MarkTrace
* - Set the BUSY flag of connected segments, the first search point is
* ref_pos on layers allowed in masque_layer
* - Put segments fount in aList
* Vias are put in list but their flags BUSY is not set
* @param aPcb = the board
* @param aRef_pos = the reference coordinate of the starting search
* @param aLayerMask = the allowed layers for segments to search
* (1 layer when starting point is on a segment, but more than one when
* starting point is on a via)
* @param aList = the track list to fill with points of segments flagged
*/
static void ChainMarkedSegments( BOARD* aPcb,
wxPoint aRef_pos,
int aLayerMask,
TRACK_PTRS* aList )
{
TRACK* pt_segm, // The current segment being analyzed.
* pt_via, // The via identified, eventually destroy
* SegmentCandidate; // The end segment to destroy (or NULL =
// pt_segm
int NbSegm;
if( aPcb->m_Track == NULL )
return;
/* Set the BUSY flag of all connected segments, first search starting at
* aRef_pos
* Search ends when:
* - a pad is found (end of a track)
* - a segment end has more than one other segment end connected
* - and obviously when no connected item found
* Vias are a special case, because we must see others segment connected
* on others layers and they change the layer mask. They can be a track
* end or not
* They will be analyzer later, and vias on terminal points of the track
* will be considered as part of this track if they do not connect segments
* of an other track together and will be considered as part of an other
* track if when removing the via, the segments of that other track are
* disconnected
*/
for( ; ; )
{
if( Fast_Locate_Pad_Connecte( aPcb, aRef_pos, aLayerMask ) != NULL )
return;
/* Test for a via: a via changes the layer mask and can connect a lot
* of segments at location aRef_pos. When found, the via is just
* pushed in list. Vias will be examined later, when all connected
* segment are found and push in list. This is because when a via
* is found we do not know at this time the number of connected items
* and we do not know if this via is on the track or finish the track
*/
pt_via = Fast_Locate_Via( aPcb->m_Track, NULL, aRef_pos, aLayerMask );
if( pt_via )
{
aLayerMask = pt_via->ReturnMaskLayer();
aList->push_back( pt_via );
}
/* Now we search all segments connected to point aRef_pos
* if only 1 segment: this segment is candidate
* if > 1 segment:
* end of track (more than 2 segment connected at this location)
*/
pt_segm = aPcb->m_Track; SegmentCandidate = NULL;
NbSegm = 0;
while( ( pt_segm = GetTrace( pt_segm, NULL, aRef_pos, aLayerMask ) ) != NULL )
{
if( pt_segm->GetState( BUSY ) ) // already found and selected: skip it
{
pt_segm = pt_segm->Next();
continue;
}
if( pt_segm == pt_via ) // just previously found: skip it
{
pt_segm = pt_segm->Next();
continue;
}
NbSegm++;
if( NbSegm == 1 ) /* First time we found a connected item: pt_segm is candidate */
{
SegmentCandidate = pt_segm;
pt_segm = pt_segm->Next();
}
else /* More than 1 segment connected -> this location is an end of the track */
{
return;
}
}
if( SegmentCandidate ) // A candidate is found: flag it an push it in list
{
/* Initialize parameters to search items connected to this
* candidate:
* we must analyze connections to its other end
*/
aLayerMask = SegmentCandidate->ReturnMaskLayer();
if( aRef_pos == SegmentCandidate->m_Start )
{
aRef_pos = SegmentCandidate->m_End;
}
else
{
aRef_pos = SegmentCandidate->m_Start;
}
pt_segm = aPcb->m_Track; /* restart list of tracks to analyze */
/* flag this item an push it in list of selected items */
aList->push_back( SegmentCandidate );
SegmentCandidate->SetState( BUSY, ON );
}
else
{
return;
}
}
}
/* Calculate the end points coordinates of a track (a list of connected
* segments)
* RefTrack is a segment of the track
* return 1 if OK, 0 when a track is a closed loop
* and the beginning and the end of the track in *StartTrack and *EndTrack
* Modify *StartTrack en *EndTrack :
* (*StartTrack)->m_Start coordinate is the beginning of the track
* (*EndTrack)->m_End coordinate is the end of the track
* Segments connected must be consecutive in list
*/
int ReturnEndsTrack( TRACK* RefTrack, int NbSegm, TRACK** StartTrack, TRACK** EndTrack )
{
TRACK* Track, * via, * segm, * TrackListEnd;
int NbEnds, layerMask, ii, ok = 0;
if( NbSegm <= 1 )
{
*StartTrack = *EndTrack = RefTrack;
return 1;
}
/* Calculation of the limit analysis. */
*StartTrack = *EndTrack = NULL;
TrackListEnd = Track = RefTrack; ii = 0;
for( ; ( Track != NULL ) && ( ii < NbSegm ); ii++, Track = Track->Next() )
{
TrackListEnd = Track;
Track->m_Param = 0;
}
/* Calculate the extremes. */
NbEnds = 0; Track = RefTrack; ii = 0;
for( ; ( Track != NULL ) && ( ii < NbSegm ); ii++, Track = Track->Next() )
{
if( Track->Type() == TYPE_VIA )
continue;
layerMask = Track->ReturnMaskLayer();
via = Fast_Locate_Via( RefTrack, TrackListEnd, Track->m_Start, layerMask );
if( via )
{
layerMask |= via->ReturnMaskLayer();
via->SetState( BUSY, ON );
}
Track->SetState( BUSY, ON );
segm = GetTrace( RefTrack, TrackListEnd, Track->m_Start, layerMask );
Track->SetState( BUSY, OFF );
if( via )
via->SetState( BUSY, OFF );
if( segm == NULL )
{
switch( NbEnds )
{
case 0:
*StartTrack = Track; NbEnds++;
break;
case 1:
int BeginPad, EndPad;
*EndTrack = Track;
/* Swap ox, oy with fx, fy */
BeginPad = Track->GetState( BEGIN_ONPAD );
EndPad = Track->GetState( END_ONPAD );
Track->SetState( BEGIN_ONPAD | END_ONPAD, OFF );
if( BeginPad )
Track->SetState( END_ONPAD, ON );
if( EndPad )
Track->SetState( BEGIN_ONPAD, ON );
EXCHG( Track->m_Start, Track->m_End );
EXCHG( Track->start, Track->end );
ok = 1;
return ok;
}
}
layerMask = Track->ReturnMaskLayer();
via = Fast_Locate_Via( RefTrack, TrackListEnd, Track->m_End, layerMask );
if( via )
{
layerMask |= via->ReturnMaskLayer();
via->SetState( BUSY, ON );
}
Track->SetState( BUSY, ON );
segm = GetTrace( RefTrack, TrackListEnd, Track->m_End, layerMask );
Track->SetState( BUSY, OFF );
if( via )
via->SetState( BUSY, OFF );
if( segm == NULL )
{
switch( NbEnds )
{
case 0:
int BeginPad, EndPad;
*StartTrack = Track;
NbEnds++;
/* Swap ox, oy with fx, fy */
BeginPad = Track->GetState( BEGIN_ONPAD );
EndPad = Track->GetState( END_ONPAD );
Track->SetState( BEGIN_ONPAD | END_ONPAD, OFF );
if( BeginPad )
Track->SetState( END_ONPAD, ON );
if( EndPad )
Track->SetState( BEGIN_ONPAD, ON );
EXCHG( Track->m_Start, Track->m_End );
EXCHG( Track->start, Track->end );
break;
case 1:
*EndTrack = Track;
ok = 1;
return ok;
}
}
}
return ok;
}