You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1378 lines
45 KiB

* KIWAY Milestone A): Make major modules into DLL/DSOs. ! The initial testing of this commit should be done using a Debug build so that all the wxASSERT()s are enabled. Also, be sure and keep enabled the USE_KIWAY_DLLs option. The tree won't likely build without it. Turning it off is senseless anyways. If you want stable code, go back to a prior version, the one tagged with "stable". * Relocate all functionality out of the wxApp derivative into more finely targeted purposes: a) DLL/DSO specific b) PROJECT specific c) EXE or process specific d) configuration file specific data e) configuration file manipulations functions. All of this functionality was blended into an extremely large wxApp derivative and that was incompatible with the desire to support multiple concurrently loaded DLL/DSO's ("KIFACE")s and multiple concurrently open projects. An amazing amount of organization come from simply sorting each bit of functionality into the proper box. * Switch to wxConfigBase from wxConfig everywhere except instantiation. * Add classes KIWAY, KIFACE, KIFACE_I, SEARCH_STACK, PGM_BASE, PGM_KICAD, PGM_SINGLE_TOP, * Remove "Return" prefix on many function names. * Remove obvious comments from CMakeLists.txt files, and from else() and endif()s. * Fix building boost for use in a DSO on linux. * Remove some of the assumptions in the CMakeLists.txt files that windows had to be the host platform when building windows binaries. * Reduce the number of wxStrings being constructed at program load time via static construction. * Pass wxConfigBase* to all SaveSettings() and LoadSettings() functions so that these functions are useful even when the wxConfigBase comes from another source, as is the case in the KICAD_MANAGER_FRAME. * Move the setting of the KIPRJMOD environment variable into class PROJECT, so that it can be moved into a project variable soon, and out of FP_LIB_TABLE. * Add the KIWAY_PLAYER which is associated with a particular PROJECT, and all its child wxFrames and wxDialogs now have a Kiway() member function which returns a KIWAY& that that window tree branch is in support of. This is like wxWindows DNA in that child windows get this member with proper value at time of construction. * Anticipate some of the needs for milestones B) and C) and make code adjustments now in an effort to reduce work in those milestones. * No testing has been done for python scripting, since milestone C) has that being largely reworked and re-thought-out.
12 years ago
16 years ago
16 years ago
16 years ago
16 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
18 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
18 years ago
14 years ago
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
14 years ago
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
16 years ago
16 years ago
14 years ago
16 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
16 years ago
16 years ago
* KIWAY Milestone A): Make major modules into DLL/DSOs. ! The initial testing of this commit should be done using a Debug build so that all the wxASSERT()s are enabled. Also, be sure and keep enabled the USE_KIWAY_DLLs option. The tree won't likely build without it. Turning it off is senseless anyways. If you want stable code, go back to a prior version, the one tagged with "stable". * Relocate all functionality out of the wxApp derivative into more finely targeted purposes: a) DLL/DSO specific b) PROJECT specific c) EXE or process specific d) configuration file specific data e) configuration file manipulations functions. All of this functionality was blended into an extremely large wxApp derivative and that was incompatible with the desire to support multiple concurrently loaded DLL/DSO's ("KIFACE")s and multiple concurrently open projects. An amazing amount of organization come from simply sorting each bit of functionality into the proper box. * Switch to wxConfigBase from wxConfig everywhere except instantiation. * Add classes KIWAY, KIFACE, KIFACE_I, SEARCH_STACK, PGM_BASE, PGM_KICAD, PGM_SINGLE_TOP, * Remove "Return" prefix on many function names. * Remove obvious comments from CMakeLists.txt files, and from else() and endif()s. * Fix building boost for use in a DSO on linux. * Remove some of the assumptions in the CMakeLists.txt files that windows had to be the host platform when building windows binaries. * Reduce the number of wxStrings being constructed at program load time via static construction. * Pass wxConfigBase* to all SaveSettings() and LoadSettings() functions so that these functions are useful even when the wxConfigBase comes from another source, as is the case in the KICAD_MANAGER_FRAME. * Move the setting of the KIPRJMOD environment variable into class PROJECT, so that it can be moved into a project variable soon, and out of FP_LIB_TABLE. * Add the KIWAY_PLAYER which is associated with a particular PROJECT, and all its child wxFrames and wxDialogs now have a Kiway() member function which returns a KIWAY& that that window tree branch is in support of. This is like wxWindows DNA in that child windows get this member with proper value at time of construction. * Anticipate some of the needs for milestones B) and C) and make code adjustments now in an effort to reduce work in those milestones. * No testing has been done for python scripting, since milestone C) has that being largely reworked and re-thought-out.
12 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
16 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
16 years ago
16 years ago
16 years ago
17 years ago
16 years ago
16 years ago
16 years ago
17 years ago
16 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
16 years ago
16 years ago
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
++PCBNew * Removed Pcb_Frame argument from BOARD() constructor, since it precludes having a BOARD being edited by more than one editor, it was a bad design. And this meant removing m_PcbFrame from BOARD. * removed BOARD::SetWindowFrame(), and BOARD::m_PcbFrame * Removed the global BOARD_DESIGN_SETTINGS which was in class_board.cpp * added BOARD_DESIGN_SETTINGS to the BOARD class, a full instance * a couple dialogs now only change BOARD_DESIGN_SETTINGS when OK is pressed, such as dialog_mask_clearance, dialog_drc, etc. * Removed common/pcbcommon.cpp's int g_CurrentVersionPCB = 1 and replaced it with build_version.h's #define BOARD_FILE_VERSION, although there may be a better place for this constant. * Made the public functions in PARAM_CFG_ARRAY be type const. void SaveParam(..) const and void ReadParam(..) const * PARAM_CFG_BASE now has virtual destructor since we have various way of destroying the derived class and boost::ptr_vector must be told about this. * Pass const PARAM_CFG_ARRAY& instead of PARAM_CFG_ARRAY so that we can use an automatic PARAM_CFG_ARRAY which is on the stack.\ * PCB_EDIT_FRAME::GetProjectFileParameters() may no longer cache the array, since it has to access the current BOARD and the BOARD can change. Remember BOARD_DESIGN_SETTINGS are now in the BOARD. * Made the m_BoundingBox member private, this was a brutally hard task, and indicative of the lack of commitment to accessors and object oriented design on the part of KiCad developers. We must do better. Added BOARD::GetBoundingBox, SetBoundingBox(), ComputeBoundingBox(). * Added PCB_BASE_FRAME::GetBoardBoundingBox() which calls BOARD::ComputeBoundingBox()
14 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2016 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
  5. * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
  6. * Copyright (C) 2012 Wayne Stambaugh <stambaughw@verizon.net>
  7. * Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License
  11. * as published by the Free Software Foundation; either version 2
  12. * of the License, or (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, you may find one here:
  21. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  22. * or you may search the http://www.gnu.org website for the version 2 license,
  23. * or you may write to the Free Software Foundation, Inc.,
  24. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  25. */
  26. /**
  27. * @file export_gencad.cpp
  28. * @brief Export GenCAD 1.4 format.
  29. */
  30. #include <fctsys.h>
  31. #include <class_drawpanel.h>
  32. #include <confirm.h>
  33. #include <gestfich.h>
  34. #include <pgm_base.h>
  35. #include <pcb_edit_frame.h>
  36. #include <trigo.h>
  37. #include <build_version.h>
  38. #include <macros.h>
  39. #include <pcbnew.h>
  40. #include <dialogs/dialog_gencad_export_options.h>
  41. #include <class_board.h>
  42. #include <class_module.h>
  43. #include <class_track.h>
  44. #include <class_edge_mod.h>
  45. #include <hash_eda.h>
  46. static bool CreateHeaderInfoData( FILE* aFile, PCB_EDIT_FRAME* frame );
  47. static void CreateArtworksSection( FILE* aFile );
  48. static void CreateTracksInfoData( FILE* aFile, BOARD* aPcb );
  49. static void CreateBoardSection( FILE* aFile, BOARD* aPcb );
  50. static void CreateComponentsSection( FILE* aFile, BOARD* aPcb );
  51. static void CreateDevicesSection( FILE* aFile, BOARD* aPcb );
  52. static void CreateRoutesSection( FILE* aFile, BOARD* aPcb );
  53. static void CreateSignalsSection( FILE* aFile, BOARD* aPcb );
  54. static void CreateShapesSection( FILE* aFile, BOARD* aPcb );
  55. static void CreatePadsShapesSection( FILE* aFile, BOARD* aPcb );
  56. static void FootprintWriteShape( FILE* File, MODULE* module, const wxString& aShapeName );
  57. // layer names for Gencad export
  58. #if 0 // was:
  59. static const wxString GenCADLayerName[] =
  60. {
  61. wxT( "BOTTOM" ), wxT( "INNER1" ), wxT( "INNER2" ),
  62. wxT( "INNER3" ), wxT( "INNER4" ), wxT( "INNER5" ),
  63. wxT( "INNER6" ), wxT( "INNER7" ), wxT( "INNER8" ),
  64. wxT( "INNER9" ), wxT( "INNER10" ), wxT( "INNER11" ),
  65. wxT( "INNER12" ), wxT( "INNER13" ), wxT( "INNER14" ),
  66. wxT( "TOP" ), wxT( "LAYER17" ), wxT( "LAYER18" ),
  67. wxT( "SOLDERPASTE_BOTTOM" ), wxT( "SOLDERPASTE_TOP" ),
  68. wxT( "SILKSCREEN_BOTTOM" ), wxT( "SILKSCREEN_TOP" ),
  69. wxT( "SOLDERMASK_BOTTOM" ), wxT( "SOLDERMASK_TOP" ), wxT( "LAYER25" ),
  70. wxT( "LAYER26" ), wxT( "LAYER27" ), wxT( "LAYER28" ),
  71. wxT( "LAYER29" ), wxT( "LAYER30" ), wxT( "LAYER31" ),
  72. wxT( "LAYER32" )
  73. };
  74. // flipped layer name for Gencad export (to make CAM350 imports correct)
  75. static const wxString GenCADLayerNameFlipped[32] =
  76. {
  77. wxT( "TOP" ), wxT( "INNER14" ), wxT( "INNER13" ),
  78. wxT( "INNER12" ), wxT( "INNER11" ), wxT( "INNER10" ),
  79. wxT( "INNER9" ), wxT( "INNER8" ), wxT( "INNER7" ),
  80. wxT( "INNER6" ), wxT( "INNER5" ), wxT( "INNER4" ),
  81. wxT( "INNER3" ), wxT( "INNER2" ), wxT( "INNER1" ),
  82. wxT( "BOTTOM" ), wxT( "LAYER17" ), wxT( "LAYER18" ),
  83. wxT( "SOLDERPASTE_TOP" ), wxT( "SOLDERPASTE_BOTTOM" ),
  84. wxT( "SILKSCREEN_TOP" ), wxT( "SILKSCREEN_BOTTOM" ),
  85. wxT( "SOLDERMASK_TOP" ), wxT( "SOLDERMASK_BOTTOM" ), wxT( "LAYER25" ),
  86. wxT( "LAYER26" ), wxT( "LAYER27" ), wxT( "LAYER28" ),
  87. wxT( "LAYER29" ), wxT( "LAYER30" ), wxT( "LAYER31" ),
  88. wxT( "LAYER32" )
  89. };
  90. #else
  91. static std::string GenCADLayerName( int aCuCount, PCB_LAYER_ID aId )
  92. {
  93. if( IsCopperLayer( aId ) )
  94. {
  95. if( aId == F_Cu )
  96. return "TOP";
  97. else if( aId == B_Cu )
  98. return "BOTTOM";
  99. else if( aId <= 14 )
  100. {
  101. return StrPrintf( "INNER%d", aCuCount - aId - 1 );
  102. }
  103. else
  104. {
  105. return StrPrintf( "LAYER%d", aId );
  106. }
  107. }
  108. else
  109. {
  110. const char* txt;
  111. // using a switch to clearly show mapping & catch out of bounds index.
  112. switch( aId )
  113. {
  114. // Technicals
  115. case B_Adhes: txt = "B.Adhes"; break;
  116. case F_Adhes: txt = "F.Adhes"; break;
  117. case B_Paste: txt = "SOLDERPASTE_BOTTOM"; break;
  118. case F_Paste: txt = "SOLDERPASTE_TOP"; break;
  119. case B_SilkS: txt = "SILKSCREEN_BOTTOM"; break;
  120. case F_SilkS: txt = "SILKSCREEN_TOP"; break;
  121. case B_Mask: txt = "SOLDERMASK_BOTTOM"; break;
  122. case F_Mask: txt = "SOLDERMASK_TOP"; break;
  123. // Users
  124. case Dwgs_User: txt = "Dwgs.User"; break;
  125. case Cmts_User: txt = "Cmts.User"; break;
  126. case Eco1_User: txt = "Eco1.User"; break;
  127. case Eco2_User: txt = "Eco2.User"; break;
  128. case Edge_Cuts: txt = "Edge.Cuts"; break;
  129. case Margin: txt = "Margin"; break;
  130. // Footprint
  131. case F_CrtYd: txt = "F_CrtYd"; break;
  132. case B_CrtYd: txt = "B_CrtYd"; break;
  133. case F_Fab: txt = "F_Fab"; break;
  134. case B_Fab: txt = "B_Fab"; break;
  135. default:
  136. wxASSERT_MSG( 0, wxT( "aId UNEXPECTED" ) );
  137. txt = "BAD-INDEX!"; break;
  138. }
  139. return txt;
  140. }
  141. }
  142. static const PCB_LAYER_ID gc_seq[] = {
  143. B_Cu,
  144. In30_Cu,
  145. In29_Cu,
  146. In28_Cu,
  147. In27_Cu,
  148. In26_Cu,
  149. In25_Cu,
  150. In24_Cu,
  151. In23_Cu,
  152. In22_Cu,
  153. In21_Cu,
  154. In20_Cu,
  155. In19_Cu,
  156. In18_Cu,
  157. In17_Cu,
  158. In16_Cu,
  159. In15_Cu,
  160. In14_Cu,
  161. In13_Cu,
  162. In12_Cu,
  163. In11_Cu,
  164. In10_Cu,
  165. In9_Cu,
  166. In8_Cu,
  167. In7_Cu,
  168. In6_Cu,
  169. In5_Cu,
  170. In4_Cu,
  171. In3_Cu,
  172. In2_Cu,
  173. In1_Cu,
  174. F_Cu,
  175. };
  176. // flipped layer name for Gencad export (to make CAM350 imports correct)
  177. static std::string GenCADLayerNameFlipped( int aCuCount, PCB_LAYER_ID aId )
  178. {
  179. if( 1<= aId && aId <= 14 )
  180. {
  181. return StrPrintf( "INNER%d", 14 - aId );
  182. }
  183. return GenCADLayerName( aCuCount, aId );
  184. }
  185. static wxString escapeString( const wxString& aString )
  186. {
  187. wxString copy( aString );
  188. copy.Replace( "\"", "\\\"" );
  189. return copy;
  190. }
  191. #endif
  192. static std::string fmt_mask( LSET aSet )
  193. {
  194. #if 0
  195. return aSet.FmtHex();
  196. #else
  197. return StrPrintf( "%08x", (unsigned) ( aSet & LSET::AllCuMask() ).to_ulong() );
  198. #endif
  199. }
  200. // Export options
  201. static bool flipBottomPads;
  202. static bool uniquePins;
  203. static bool individualShapes;
  204. static bool storeOriginCoords;
  205. // These are the export origin (the auxiliary axis)
  206. static int GencadOffsetX, GencadOffsetY;
  207. // Association between shape names (using shapeName index) and components
  208. static std::map<MODULE*, int> componentShapes;
  209. static std::map<int, wxString> shapeNames;
  210. static const wxString& getShapeName( MODULE* aModule )
  211. {
  212. static const wxString invalid( "invalid" );
  213. if( individualShapes )
  214. return aModule->GetReference();
  215. auto itShape = componentShapes.find( aModule );
  216. wxCHECK( itShape != componentShapes.end(), invalid );
  217. auto itName = shapeNames.find( itShape->second );
  218. wxCHECK( itName != shapeNames.end(), invalid );
  219. return itName->second;
  220. }
  221. // GerbTool chokes on units different than INCH so this is the conversion factor
  222. const static double SCALE_FACTOR = 1000.0 * IU_PER_MILS;
  223. /* Two helper functions to calculate coordinates of modules in gencad values
  224. * (GenCAD Y axis from bottom to top)
  225. */
  226. static double MapXTo( int aX )
  227. {
  228. return (aX - GencadOffsetX) / SCALE_FACTOR;
  229. }
  230. static double MapYTo( int aY )
  231. {
  232. return (GencadOffsetY - aY) / SCALE_FACTOR;
  233. }
  234. /* Driver function: processing starts here */
  235. void PCB_EDIT_FRAME::ExportToGenCAD( wxCommandEvent& aEvent )
  236. {
  237. DIALOG_GENCAD_EXPORT_OPTIONS optionsDialog( this );
  238. if( optionsDialog.ShowModal() == wxID_CANCEL )
  239. return;
  240. FILE* file = wxFopen( optionsDialog.GetFileName(), "wt" );
  241. if( !file )
  242. {
  243. DisplayError( this, wxString::Format( _( "Unable to create \"%s\"" ),
  244. GetChars( optionsDialog.GetFileName() ) ) );
  245. return;
  246. }
  247. // Get options
  248. flipBottomPads = optionsDialog.GetOption( FLIP_BOTTOM_PADS );
  249. uniquePins = optionsDialog.GetOption( UNIQUE_PIN_NAMES );
  250. individualShapes = optionsDialog.GetOption( INDIVIDUAL_SHAPES );
  251. storeOriginCoords = optionsDialog.GetOption( STORE_ORIGIN_COORDS );
  252. // Switch the locale to standard C (needed to print floating point numbers)
  253. LOCALE_IO toggle;
  254. // Update some board data, to ensure a reliable gencad export
  255. GetBoard()->ComputeBoundingBox();
  256. // Save the auxiliary origin for the rest of the module
  257. GencadOffsetX = optionsDialog.GetOption( USE_AUX_ORIGIN ) ? GetAuxOrigin().x : 0;
  258. GencadOffsetY = optionsDialog.GetOption( USE_AUX_ORIGIN ) ? GetAuxOrigin().y : 0;
  259. // No idea on *why* this should be needed... maybe to fix net names?
  260. Compile_Ratsnest( NULL, true );
  261. /* Temporary modification of footprints that are flipped (i.e. on bottom
  262. * layer) to convert them to non flipped footprints.
  263. * This is necessary to easily export shapes to GenCAD,
  264. * that are given as normal orientation (non flipped, rotation = 0))
  265. * these changes will be undone later
  266. */
  267. BOARD* pcb = GetBoard();
  268. MODULE* module;
  269. for( module = pcb->m_Modules; module; module = module->Next() )
  270. {
  271. module->SetFlag( 0 );
  272. if( module->GetLayer() == B_Cu )
  273. {
  274. module->Flip( module->GetPosition() );
  275. module->SetFlag( 1 );
  276. }
  277. }
  278. /* Gencad has some mandatory and some optional sections: some importer
  279. * need the padstack section (which is optional) anyway. Also the
  280. * order of the section *is* important */
  281. CreateHeaderInfoData( file, this ); // Gencad header
  282. CreateBoardSection( file, pcb ); // Board perimeter
  283. CreatePadsShapesSection( file, pcb ); // Pads and padstacks
  284. CreateArtworksSection( file ); // Empty but mandatory
  285. /* Gencad splits a component info in shape, component and device.
  286. * We don't do any sharing (it would be difficult since each module is
  287. * customizable after placement) */
  288. CreateShapesSection( file, pcb );
  289. CreateComponentsSection( file, pcb );
  290. CreateDevicesSection( file, pcb );
  291. // In a similar way the netlist is split in net, track and route
  292. CreateSignalsSection( file, pcb );
  293. CreateTracksInfoData( file, pcb );
  294. CreateRoutesSection( file, pcb );
  295. fclose( file );
  296. // Undo the footprints modifications (flipped footprints)
  297. for( module = pcb->m_Modules; module; module = module->Next() )
  298. {
  299. if( module->GetFlag() )
  300. {
  301. module->Flip( module->GetPosition() );
  302. module->SetFlag( 0 );
  303. }
  304. }
  305. componentShapes.clear();
  306. shapeNames.clear();
  307. }
  308. // Comparator for sorting pads with qsort
  309. static int PadListSortByShape( const void* aRefptr, const void* aObjptr )
  310. {
  311. const D_PAD* padref = *(D_PAD**) aRefptr;
  312. const D_PAD* padcmp = *(D_PAD**) aObjptr;
  313. return D_PAD::Compare( padref, padcmp );
  314. }
  315. // Sort vias for uniqueness
  316. static int ViaSort( const void* aRefptr, const void* aObjptr )
  317. {
  318. VIA* padref = *(VIA**) aRefptr;
  319. VIA* padcmp = *(VIA**) aObjptr;
  320. if( padref->GetWidth() != padcmp->GetWidth() )
  321. return padref->GetWidth() - padcmp->GetWidth();
  322. if( padref->GetDrillValue() != padcmp->GetDrillValue() )
  323. return padref->GetDrillValue() - padcmp->GetDrillValue();
  324. if( padref->GetLayerSet() != padcmp->GetLayerSet() )
  325. return padref->GetLayerSet().FmtBin().compare( padcmp->GetLayerSet().FmtBin() );
  326. return 0;
  327. }
  328. // The ARTWORKS section is empty but (officially) mandatory
  329. static void CreateArtworksSection( FILE* aFile )
  330. {
  331. /* The artworks section is empty */
  332. fputs( "$ARTWORKS\n", aFile );
  333. fputs( "$ENDARTWORKS\n\n", aFile );
  334. }
  335. // Emit PADS and PADSTACKS. They are sorted and emitted uniquely.
  336. // Via name is synthesized from their attributes, pads are numbered
  337. static void CreatePadsShapesSection( FILE* aFile, BOARD* aPcb )
  338. {
  339. std::vector<D_PAD*> pads;
  340. std::vector<D_PAD*> padstacks;
  341. std::vector<VIA*> vias;
  342. std::vector<VIA*> viastacks;
  343. padstacks.resize( 1 ); // We count pads from 1
  344. // The master layermask (i.e. the enabled layers) for padstack generation
  345. LSET master_layermask = aPcb->GetDesignSettings().GetEnabledLayers();
  346. int cu_count = aPcb->GetCopperLayerCount();
  347. fputs( "$PADS\n", aFile );
  348. // Enumerate and sort the pads
  349. if( aPcb->GetPadCount() > 0 )
  350. {
  351. pads = aPcb->GetPads();
  352. qsort( &pads[0], aPcb->GetPadCount(), sizeof( D_PAD* ),
  353. PadListSortByShape );
  354. }
  355. // The same for vias
  356. for( VIA* via = GetFirstVia( aPcb->m_Track ); via;
  357. via = GetFirstVia( via->Next() ) )
  358. {
  359. vias.push_back( via );
  360. }
  361. qsort( &vias[0], vias.size(), sizeof(VIA*), ViaSort );
  362. // Emit vias pads
  363. TRACK* old_via = 0;
  364. for( unsigned i = 0; i < vias.size(); i++ )
  365. {
  366. VIA* via = vias[i];
  367. if( old_via && 0 == ViaSort( &old_via, &via ) )
  368. continue;
  369. old_via = via;
  370. viastacks.push_back( via );
  371. fprintf( aFile, "PAD V%d.%d.%s ROUND %g\nCIRCLE 0 0 %g\n",
  372. via->GetWidth(), via->GetDrillValue(),
  373. fmt_mask( via->GetLayerSet() & master_layermask ).c_str(),
  374. via->GetDrillValue() / SCALE_FACTOR,
  375. via->GetWidth() / (SCALE_FACTOR * 2) );
  376. }
  377. // Emit component pads
  378. D_PAD* old_pad = 0;
  379. int pad_name_number = 0;
  380. for( unsigned i = 0; i<pads.size(); ++i )
  381. {
  382. D_PAD* pad = pads[i];
  383. const wxPoint& off = pad->GetOffset();
  384. pad->SetSubRatsnest( pad_name_number );
  385. if( old_pad && 0==D_PAD::Compare( old_pad, pad ) )
  386. continue; // already created
  387. old_pad = pad;
  388. pad_name_number++;
  389. pad->SetSubRatsnest( pad_name_number );
  390. fprintf( aFile, "PAD P%d", pad->GetSubRatsnest() );
  391. padstacks.push_back( pad ); // Will have its own padstack later
  392. int dx = pad->GetSize().x / 2;
  393. int dy = pad->GetSize().y / 2;
  394. switch( pad->GetShape() )
  395. {
  396. default:
  397. wxASSERT_MSG( false, "Pad type not implemented" );
  398. // fall-through
  399. case PAD_SHAPE_CIRCLE:
  400. fprintf( aFile, " ROUND %g\n",
  401. pad->GetDrillSize().x / SCALE_FACTOR );
  402. /* Circle is center, radius */
  403. fprintf( aFile, "CIRCLE %g %g %g\n",
  404. off.x / SCALE_FACTOR,
  405. -off.y / SCALE_FACTOR,
  406. pad->GetSize().x / (SCALE_FACTOR * 2) );
  407. break;
  408. case PAD_SHAPE_RECT:
  409. fprintf( aFile, " RECTANGULAR %g\n",
  410. pad->GetDrillSize().x / SCALE_FACTOR );
  411. // Rectangle is begin, size *not* begin, end!
  412. fprintf( aFile, "RECTANGLE %g %g %g %g\n",
  413. (-dx + off.x ) / SCALE_FACTOR,
  414. (-dy - off.y ) / SCALE_FACTOR,
  415. dx / (SCALE_FACTOR / 2), dy / (SCALE_FACTOR / 2) );
  416. break;
  417. case PAD_SHAPE_ROUNDRECT:
  418. case PAD_SHAPE_OVAL:
  419. {
  420. const wxSize& size = pad->GetSize();
  421. int radius;
  422. if( pad->GetShape() == PAD_SHAPE_ROUNDRECT )
  423. radius = pad->GetRoundRectCornerRadius();
  424. else
  425. radius = std::min( size.x, size.y ) / 2;
  426. int lineX = size.x / 2 - radius;
  427. int lineY = size.y / 2 - radius;
  428. fprintf( aFile, " POLYGON %g\n", pad->GetDrillSize().x / SCALE_FACTOR );
  429. // bottom left arc
  430. fprintf( aFile, "ARC %g %g %g %g %g %g\n",
  431. ( off.x - lineX - radius ) / SCALE_FACTOR,
  432. ( -off.y - lineY ) / SCALE_FACTOR, ( off.x - lineX ) / SCALE_FACTOR,
  433. ( -off.y - lineY - radius ) / SCALE_FACTOR,
  434. ( off.x - lineX ) / SCALE_FACTOR, ( -off.y - lineY ) / SCALE_FACTOR );
  435. // bottom line
  436. if( lineX > 0 )
  437. {
  438. fprintf( aFile, "LINE %g %g %g %g\n",
  439. ( off.x - lineX ) / SCALE_FACTOR,
  440. ( -off.y - lineY - radius ) / SCALE_FACTOR,
  441. ( off.x + lineX ) / SCALE_FACTOR,
  442. ( -off.y - lineY - radius ) / SCALE_FACTOR );
  443. }
  444. // bottom right arc
  445. fprintf( aFile, "ARC %g %g %g %g %g %g\n",
  446. ( off.x + lineX ) / SCALE_FACTOR,
  447. ( -off.y - lineY - radius ) / SCALE_FACTOR,
  448. ( off.x + lineX + radius ) / SCALE_FACTOR,
  449. ( -off.y - lineY ) / SCALE_FACTOR, ( off.x + lineX ) / SCALE_FACTOR,
  450. ( -off.y - lineY ) / SCALE_FACTOR );
  451. // right line
  452. if( lineY > 0 )
  453. {
  454. fprintf( aFile, "LINE %g %g %g %g\n",
  455. ( off.x + lineX + radius ) / SCALE_FACTOR,
  456. ( -off.y + lineY ) / SCALE_FACTOR,
  457. ( off.x + lineX + radius ) / SCALE_FACTOR,
  458. ( -off.y - lineY ) / SCALE_FACTOR );
  459. }
  460. // top right arc
  461. fprintf( aFile, "ARC %g %g %g %g %g %g\n",
  462. ( off.x + lineX + radius ) / SCALE_FACTOR,
  463. ( -off.y + lineY ) / SCALE_FACTOR, ( off.x + lineX ) / SCALE_FACTOR,
  464. ( -off.y + lineY + radius ) / SCALE_FACTOR,
  465. ( off.x + lineX ) / SCALE_FACTOR, ( -off.y + lineY ) / SCALE_FACTOR );
  466. // top line
  467. if( lineX > 0 )
  468. {
  469. fprintf( aFile, "LINE %g %g %g %g\n"
  470. , ( off.x - lineX ) / SCALE_FACTOR,
  471. ( -off.y + lineY + radius ) / SCALE_FACTOR,
  472. ( off.x + lineX ) / SCALE_FACTOR,
  473. ( -off.y + lineY + radius ) / SCALE_FACTOR );
  474. }
  475. // top left arc
  476. fprintf( aFile, "ARC %g %g %g %g %g %g\n",
  477. ( off.x - lineX ) / SCALE_FACTOR,
  478. ( -off.y + lineY + radius ) / SCALE_FACTOR,
  479. ( off.x - lineX - radius ) / SCALE_FACTOR,
  480. ( -off.y + lineY ) / SCALE_FACTOR, ( off.x - lineX ) / SCALE_FACTOR,
  481. ( -off.y + lineY ) / SCALE_FACTOR );
  482. // left line
  483. if( lineY > 0 )
  484. {
  485. fprintf( aFile, "LINE %g %g %g %g\n",
  486. ( off.x - lineX - radius ) / SCALE_FACTOR,
  487. ( -off.y - lineY ) / SCALE_FACTOR,
  488. ( off.x - lineX - radius ) / SCALE_FACTOR,
  489. ( -off.y + lineY ) / SCALE_FACTOR );
  490. }
  491. }
  492. break;
  493. case PAD_SHAPE_TRAPEZOID:
  494. {
  495. fprintf( aFile, " POLYGON %g\n", pad->GetDrillSize().x / SCALE_FACTOR );
  496. wxPoint poly[4];
  497. pad->BuildPadPolygon( poly, wxSize( 0, 0 ), 0 );
  498. for( int cur = 0; cur < 4; ++cur )
  499. {
  500. int next = ( cur + 1 ) % 4;
  501. fprintf( aFile, "LINE %g %g %g %g\n",
  502. ( off.x + poly[cur].x ) / SCALE_FACTOR,
  503. ( -off.y - poly[cur].y ) / SCALE_FACTOR,
  504. ( off.x + poly[next].x ) / SCALE_FACTOR,
  505. ( -off.y - poly[next].y ) / SCALE_FACTOR );
  506. }
  507. }
  508. break;
  509. case PAD_SHAPE_CUSTOM:
  510. {
  511. fprintf( aFile, " POLYGON %g\n", pad->GetDrillSize().x / SCALE_FACTOR );
  512. const SHAPE_POLY_SET& outline = pad->GetCustomShapeAsPolygon();
  513. for( int jj = 0; jj < outline.OutlineCount(); ++jj )
  514. {
  515. const SHAPE_LINE_CHAIN& poly = outline.COutline( jj );
  516. int pointCount = poly.PointCount();
  517. for( int ii = 0; ii < pointCount; ii++ )
  518. {
  519. int next = ( ii + 1 ) % pointCount;
  520. fprintf( aFile, "LINE %g %g %g %g\n",
  521. ( off.x + poly.CPoint( ii ).x ) / SCALE_FACTOR,
  522. ( -off.y - poly.CPoint( ii ).y ) / SCALE_FACTOR,
  523. ( off.x + poly.CPoint( next ).x ) / SCALE_FACTOR,
  524. ( -off.y - poly.CPoint( next ).y ) / SCALE_FACTOR );
  525. }
  526. }
  527. }
  528. break;
  529. }
  530. }
  531. fputs( "\n$ENDPADS\n\n", aFile );
  532. // Now emit the padstacks definitions, using the combined layer masks
  533. fputs( "$PADSTACKS\n", aFile );
  534. // Via padstacks
  535. for( unsigned i = 0; i < viastacks.size(); i++ )
  536. {
  537. VIA* via = viastacks[i];
  538. LSET mask = via->GetLayerSet() & master_layermask;
  539. fprintf( aFile, "PADSTACK VIA%d.%d.%s %g\n",
  540. via->GetWidth(), via->GetDrillValue(),
  541. fmt_mask( mask ).c_str(),
  542. via->GetDrillValue() / SCALE_FACTOR );
  543. for( LSEQ seq = mask.Seq( gc_seq, DIM( gc_seq ) ); seq; ++seq )
  544. {
  545. PCB_LAYER_ID layer = *seq;
  546. fprintf( aFile, "PAD V%d.%d.%s %s 0 0\n",
  547. via->GetWidth(), via->GetDrillValue(),
  548. fmt_mask( mask ).c_str(),
  549. GenCADLayerName( cu_count, layer ).c_str()
  550. );
  551. }
  552. }
  553. /* Component padstacks
  554. * Older versions of CAM350 don't apply correctly the FLIP semantics for
  555. * padstacks, i.e. doesn't swap the top and bottom layers... so I need to
  556. * define the shape as MIRRORX and define a separate 'flipped' padstack...
  557. * until it appears yet another noncompliant importer */
  558. for( unsigned i = 1; i < padstacks.size(); i++ )
  559. {
  560. D_PAD* pad = padstacks[i];
  561. // Straight padstack
  562. fprintf( aFile, "PADSTACK PAD%u %g\n", i, pad->GetDrillSize().x / SCALE_FACTOR );
  563. LSET pad_set = pad->GetLayerSet() & master_layermask;
  564. // the special gc_seq
  565. for( LSEQ seq = pad_set.Seq( gc_seq, DIM( gc_seq ) ); seq; ++seq )
  566. {
  567. PCB_LAYER_ID layer = *seq;
  568. fprintf( aFile, "PAD P%u %s 0 0\n", i, GenCADLayerName( cu_count, layer ).c_str() );
  569. }
  570. // Flipped padstack
  571. if( flipBottomPads )
  572. {
  573. fprintf( aFile, "PADSTACK PAD%uF %g\n", i, pad->GetDrillSize().x / SCALE_FACTOR );
  574. // the normal PCB_LAYER_ID sequence is inverted from gc_seq[]
  575. for( LSEQ seq = pad_set.Seq(); seq; ++seq )
  576. {
  577. PCB_LAYER_ID layer = *seq;
  578. fprintf( aFile, "PAD P%u %s 0 0\n", i, GenCADLayerNameFlipped( cu_count, layer ).c_str() );
  579. }
  580. }
  581. }
  582. fputs( "$ENDPADSTACKS\n\n", aFile );
  583. }
  584. /// Compute hashes for modules without taking into account their position, rotation or layer
  585. static size_t hashModule( const MODULE* aModule )
  586. {
  587. size_t ret = 0x11223344;
  588. constexpr int flags = HASH_FLAGS::POSITION | HASH_FLAGS::REL_COORD
  589. | HASH_FLAGS::ROTATION | HASH_FLAGS::LAYER;
  590. for( const BOARD_ITEM* i = aModule->GraphicalItemsList(); i; i = i->Next() )
  591. ret ^= hash_eda( i, flags );
  592. for( const D_PAD* i = aModule->PadsList(); i; i = i->Next() )
  593. ret ^= hash_eda( i, flags );
  594. return ret;
  595. }
  596. /* Creates the footprint shape list.
  597. * Since module shape is customizable after the placement we cannot share them;
  598. * instead we opt for the one-module-one-shape-one-component-one-device approach
  599. */
  600. static void CreateShapesSection( FILE* aFile, BOARD* aPcb )
  601. {
  602. MODULE* module;
  603. D_PAD* pad;
  604. const char* layer;
  605. wxString pinname;
  606. const char* mirror = "0";
  607. std::map<wxString, size_t> shapes;
  608. fputs( "$SHAPES\n", aFile );
  609. for( module = aPcb->m_Modules; module; module = module->Next() )
  610. {
  611. if( !individualShapes )
  612. {
  613. // Check if such shape has been already generated, and if so - reuse it
  614. // It is necessary to compute hash (i.e. check all children objects) as
  615. // certain components instances might have been modified on the board.
  616. // In such case the shape will be different despite the same LIB_ID.
  617. wxString shapeName = module->GetFPID().Format();
  618. auto shapeIt = shapes.find( shapeName );
  619. size_t modHash = hashModule( module );
  620. if( shapeIt != shapes.end() )
  621. {
  622. if( modHash != shapeIt->second )
  623. {
  624. // there is an entry for this footprint, but it has a modified shape,
  625. // so we need to create a new entry
  626. wxString newShapeName;
  627. int suffix = 0;
  628. // find an unused name or matching entry
  629. do
  630. {
  631. newShapeName = wxString::Format( "%s_%d", shapeName, suffix );
  632. shapeIt = shapes.find( newShapeName );
  633. ++suffix;
  634. }
  635. while( shapeIt != shapes.end() && shapeIt->second != modHash );
  636. shapeName = newShapeName;
  637. }
  638. if( shapeIt != shapes.end() && modHash == shapeIt->second )
  639. {
  640. // shape found, so reuse it
  641. componentShapes[module] = modHash;
  642. continue;
  643. }
  644. }
  645. // new shape
  646. componentShapes[module] = modHash;
  647. shapeNames[modHash] = shapeName;
  648. shapes[shapeName] = modHash;
  649. FootprintWriteShape( aFile, module, shapeName );
  650. }
  651. else // individual shape for each component
  652. {
  653. FootprintWriteShape( aFile, module, module->GetReference() );
  654. }
  655. // set of already emitted pins to check for duplicates
  656. std::set<wxString> pins;
  657. for( pad = module->PadsList(); pad; pad = pad->Next() )
  658. {
  659. /* Padstacks are defined using the correct layers for the pads, therefore to
  660. * all pads need to be marked as TOP to use the padstack information correctly.
  661. */
  662. layer = "TOP";
  663. pinname = pad->GetName();
  664. if( pinname.IsEmpty() )
  665. pinname = wxT( "none" );
  666. if( uniquePins )
  667. {
  668. int suffix = 0;
  669. wxString origPinname( pinname );
  670. auto it = pins.find( pinname );
  671. while( it != pins.end() )
  672. {
  673. pinname = wxString::Format( "%s_%d", origPinname, suffix );
  674. ++suffix;
  675. it = pins.find( pinname );
  676. }
  677. pins.insert( pinname );
  678. }
  679. double orient = pad->GetOrientation() - module->GetOrientation();
  680. NORMALIZE_ANGLE_POS( orient );
  681. // Bottom side modules use the flipped padstack
  682. fprintf( aFile, ( flipBottomPads && module->GetFlag() ) ?
  683. "PIN \"%s\" PAD%dF %g %g %s %g %s\n" :
  684. "PIN \"%s\" PAD%d %g %g %s %g %s\n",
  685. TO_UTF8( escapeString( pinname ) ), pad->GetSubRatsnest(),
  686. pad->GetPos0().x / SCALE_FACTOR,
  687. -pad->GetPos0().y / SCALE_FACTOR,
  688. layer, orient / 10.0, mirror );
  689. }
  690. }
  691. fputs( "$ENDSHAPES\n\n", aFile );
  692. }
  693. /* Creates the section $COMPONENTS (Footprints placement)
  694. * Bottom side components are difficult to handle: shapes must be mirrored or
  695. * flipped, silk layers need to be handled correctly and so on. Also it seems
  696. * that *noone* follows the specs...
  697. */
  698. static void CreateComponentsSection( FILE* aFile, BOARD* aPcb )
  699. {
  700. fputs( "$COMPONENTS\n", aFile );
  701. int cu_count = aPcb->GetCopperLayerCount();
  702. for( MODULE* module = aPcb->m_Modules; module; module = module->Next() )
  703. {
  704. const char* mirror;
  705. const char* flip;
  706. double fp_orient = module->GetOrientation();
  707. if( module->GetFlag() )
  708. {
  709. mirror = "MIRRORX";
  710. flip = "FLIP";
  711. NEGATE_AND_NORMALIZE_ANGLE_POS( fp_orient );
  712. }
  713. else
  714. {
  715. mirror = "0";
  716. flip = "0";
  717. }
  718. fprintf( aFile, "\nCOMPONENT \"%s\"\n",
  719. TO_UTF8( escapeString( module->GetReference() ) ) );
  720. fprintf( aFile, "DEVICE \"DEV_%s\"\n",
  721. TO_UTF8( escapeString( getShapeName( module ) ) ) );
  722. fprintf( aFile, "PLACE %g %g\n",
  723. MapXTo( module->GetPosition().x ),
  724. MapYTo( module->GetPosition().y ) );
  725. fprintf( aFile, "LAYER %s\n",
  726. module->GetFlag() ? "BOTTOM" : "TOP" );
  727. fprintf( aFile, "ROTATION %g\n",
  728. fp_orient / 10.0 );
  729. fprintf( aFile, "SHAPE \"%s\" %s %s\n",
  730. TO_UTF8( escapeString( getShapeName( module ) ) ),
  731. mirror, flip );
  732. // Text on silk layer: RefDes and value (are they actually useful?)
  733. TEXTE_MODULE *textmod = &module->Reference();
  734. for( int ii = 0; ii < 2; ii++ )
  735. {
  736. double txt_orient = textmod->GetTextAngle();
  737. std::string layer = GenCADLayerName( cu_count, module->GetFlag() ? B_SilkS : F_SilkS );
  738. fprintf( aFile, "TEXT %g %g %g %g %s %s \"%s\"",
  739. textmod->GetPos0().x / SCALE_FACTOR,
  740. -textmod->GetPos0().y / SCALE_FACTOR,
  741. textmod->GetTextWidth() / SCALE_FACTOR,
  742. txt_orient / 10.0,
  743. mirror,
  744. layer.c_str(),
  745. TO_UTF8( escapeString( textmod->GetText() ) ) );
  746. // Please note, the width is approx
  747. fprintf( aFile, " 0 0 %g %g\n",
  748. ( textmod->GetTextWidth() * textmod->GetLength() ) / SCALE_FACTOR,
  749. textmod->GetTextHeight() / SCALE_FACTOR );
  750. textmod = &module->Value(); // Dirty trick for the second iteration
  751. }
  752. // The SHEET is a 'generic description' for referencing the component
  753. fprintf( aFile, "SHEET \"RefDes: %s, Value: %s\"\n",
  754. TO_UTF8( module->GetReference() ),
  755. TO_UTF8( module->GetValue() ) );
  756. }
  757. fputs( "$ENDCOMPONENTS\n\n", aFile );
  758. }
  759. /* Emit the netlist (which is actually the thing for which GenCAD is used these
  760. * days!); tracks are handled later */
  761. static void CreateSignalsSection( FILE* aFile, BOARD* aPcb )
  762. {
  763. wxString msg;
  764. NETINFO_ITEM* net;
  765. D_PAD* pad;
  766. MODULE* module;
  767. int NbNoConn = 1;
  768. fputs( "$SIGNALS\n", aFile );
  769. for( unsigned ii = 0; ii < aPcb->GetNetCount(); ii++ )
  770. {
  771. net = aPcb->FindNet( ii );
  772. if( net->GetNetname() == wxEmptyString ) // dummy netlist (no connection)
  773. {
  774. msg.Printf( "NoConnection%d", NbNoConn++ );
  775. }
  776. if( net->GetNet() <= 0 ) // dummy netlist (no connection)
  777. continue;
  778. msg = wxT( "SIGNAL \"" ) + escapeString( net->GetNetname() ) + "\"";
  779. fputs( TO_UTF8( msg ), aFile );
  780. fputs( "\n", aFile );
  781. for( module = aPcb->m_Modules; module; module = module->Next() )
  782. {
  783. for( pad = module->PadsList(); pad; pad = pad->Next() )
  784. {
  785. if( pad->GetNetCode() != net->GetNet() )
  786. continue;
  787. msg.Printf( wxT( "NODE \"%s\" \"%s\"" ),
  788. GetChars( escapeString( module->GetReference() ) ),
  789. GetChars( escapeString( pad->GetName() ) ) );
  790. fputs( TO_UTF8( msg ), aFile );
  791. fputs( "\n", aFile );
  792. }
  793. }
  794. }
  795. fputs( "$ENDSIGNALS\n\n", aFile );
  796. }
  797. // Creates the header section
  798. static bool CreateHeaderInfoData( FILE* aFile, PCB_EDIT_FRAME* aFrame )
  799. {
  800. wxString msg;
  801. BOARD *board = aFrame->GetBoard();
  802. fputs( "$HEADER\n", aFile );
  803. fputs( "GENCAD 1.4\n", aFile );
  804. // Please note: GenCAD syntax requires quoted strings if they can contain spaces
  805. msg.Printf( wxT( "USER \"%s %s\"\n" ),
  806. GetChars( Pgm().App().GetAppName() ),
  807. GetChars( GetBuildVersion() ) );
  808. fputs( TO_UTF8( msg ), aFile );
  809. msg = wxT( "DRAWING \"" ) + board->GetFileName() + wxT( "\"\n" );
  810. fputs( TO_UTF8( msg ), aFile );
  811. const TITLE_BLOCK& tb = aFrame->GetTitleBlock();
  812. msg = wxT( "REVISION \"" ) + tb.GetRevision() + wxT( " " ) + tb.GetDate() + wxT( "\"\n" );
  813. fputs( TO_UTF8( msg ), aFile );
  814. fputs( "UNITS INCH\n", aFile );
  815. // giving 0 as the argument to Map{X,Y}To returns the scaled origin point
  816. msg.Printf( wxT( "ORIGIN %g %g\n" ),
  817. storeOriginCoords ? MapXTo( 0 ) : 0,
  818. storeOriginCoords ? MapYTo( 0 ) : 0 );
  819. fputs( TO_UTF8( msg ), aFile );
  820. fputs( "INTERTRACK 0\n", aFile );
  821. fputs( "$ENDHEADER\n\n", aFile );
  822. return true;
  823. }
  824. /*
  825. * Sort function used to sort tracks segments:
  826. * items are sorted by netcode, then by width then by layer
  827. */
  828. static int TrackListSortByNetcode( const void* refptr, const void* objptr )
  829. {
  830. const TRACK* ref, * cmp;
  831. int diff;
  832. ref = *( (TRACK**) refptr );
  833. cmp = *( (TRACK**) objptr );
  834. if( ( diff = ref->GetNetCode() - cmp->GetNetCode() ) )
  835. return diff;
  836. if( ( diff = ref->GetWidth() - cmp->GetWidth() ) )
  837. return diff;
  838. if( ( diff = ref->GetLayer() - cmp->GetLayer() ) )
  839. return diff;
  840. return 0;
  841. }
  842. /* Creates the section ROUTES
  843. * that handles tracks, vias
  844. * TODO: add zones
  845. * section:
  846. * $ROUTE
  847. * ...
  848. * $ENROUTE
  849. * Track segments must be sorted by nets
  850. */
  851. static void CreateRoutesSection( FILE* aFile, BOARD* aPcb )
  852. {
  853. TRACK* track, ** tracklist;
  854. int vianum = 1;
  855. int old_netcode, old_width, old_layer;
  856. int nbitems, ii;
  857. LSET master_layermask = aPcb->GetDesignSettings().GetEnabledLayers();
  858. int cu_count = aPcb->GetCopperLayerCount();
  859. // Count items
  860. nbitems = 0;
  861. for( track = aPcb->m_Track; track; track = track->Next() )
  862. nbitems++;
  863. tracklist = (TRACK**) operator new( (nbitems + 1)* sizeof( TRACK* ) );
  864. nbitems = 0;
  865. for( track = aPcb->m_Track; track; track = track->Next() )
  866. tracklist[nbitems++] = track;
  867. tracklist[nbitems] = NULL;
  868. qsort( tracklist, nbitems, sizeof(TRACK*), TrackListSortByNetcode );
  869. fputs( "$ROUTES\n", aFile );
  870. old_netcode = -1; old_width = -1; old_layer = -1;
  871. for( ii = 0; ii < nbitems; ii++ )
  872. {
  873. track = tracklist[ii];
  874. if( old_netcode != track->GetNetCode() )
  875. {
  876. old_netcode = track->GetNetCode();
  877. NETINFO_ITEM* net = track->GetNet();
  878. wxString netname;
  879. if( net && (net->GetNetname() != wxEmptyString) )
  880. netname = net->GetNetname();
  881. else
  882. netname = wxT( "_noname_" );
  883. fprintf( aFile, "ROUTE \"%s\"\n", TO_UTF8( escapeString( netname ) ) );
  884. }
  885. if( old_width != track->GetWidth() )
  886. {
  887. old_width = track->GetWidth();
  888. fprintf( aFile, "TRACK TRACK%d\n", track->GetWidth() );
  889. }
  890. if( (track->Type() == PCB_TRACE_T) || (track->Type() == PCB_ZONE_T) )
  891. {
  892. if( old_layer != track->GetLayer() )
  893. {
  894. old_layer = track->GetLayer();
  895. fprintf( aFile, "LAYER %s\n",
  896. GenCADLayerName( cu_count, track->GetLayer() ).c_str()
  897. );
  898. }
  899. fprintf( aFile, "LINE %g %g %g %g\n",
  900. MapXTo( track->GetStart().x ), MapYTo( track->GetStart().y ),
  901. MapXTo( track->GetEnd().x ), MapYTo( track->GetEnd().y ) );
  902. }
  903. if( track->Type() == PCB_VIA_T )
  904. {
  905. const VIA* via = static_cast<const VIA*>(track);
  906. LSET vset = via->GetLayerSet() & master_layermask;
  907. fprintf( aFile, "VIA VIA%d.%d.%s %g %g ALL %g via%d\n",
  908. via->GetWidth(), via->GetDrillValue(),
  909. fmt_mask( vset ).c_str(),
  910. MapXTo( via->GetStart().x ), MapYTo( via->GetStart().y ),
  911. via->GetDrillValue() / SCALE_FACTOR, vianum++ );
  912. }
  913. }
  914. fputs( "$ENDROUTES\n\n", aFile );
  915. delete tracklist;
  916. }
  917. /* Creates the section $DEVICES
  918. * This is a list of footprints properties
  919. * ( Shapes are in section $SHAPE )
  920. */
  921. static void CreateDevicesSection( FILE* aFile, BOARD* aPcb )
  922. {
  923. std::set<wxString> emitted;
  924. fputs( "$DEVICES\n", aFile );
  925. for( const auto& componentShape : componentShapes )
  926. {
  927. const wxString& shapeName = shapeNames[componentShape.second];
  928. bool newDevice;
  929. std::tie( std::ignore, newDevice ) = emitted.insert( shapeName );
  930. if( !newDevice ) // do not repeat device definitions
  931. continue;
  932. const MODULE* module = componentShape.first;
  933. fprintf( aFile, "\nDEVICE \"DEV_%s\"\n", TO_UTF8( escapeString( shapeName ) ) );
  934. fprintf( aFile, "PART \"%s\"\n", TO_UTF8( escapeString( module->GetValue() ) ) );
  935. fprintf( aFile, "PACKAGE \"%s\"\n", TO_UTF8( escapeString( module->GetFPID().Format() ) ) );
  936. // The TYPE attribute is almost freeform
  937. const char* ty = "TH";
  938. if( module->GetAttributes() & MOD_CMS )
  939. ty = "SMD";
  940. if( module->GetAttributes() & MOD_VIRTUAL )
  941. ty = "VIRTUAL";
  942. fprintf( aFile, "TYPE %s\n", ty );
  943. }
  944. fputs( "$ENDDEVICES\n\n", aFile );
  945. }
  946. /* Creates the section $BOARD.
  947. * We output here only the board perimeter
  948. */
  949. static void CreateBoardSection( FILE* aFile, BOARD* aPcb )
  950. {
  951. fputs( "$BOARD\n", aFile );
  952. // Extract the board edges
  953. for( auto drawing : aPcb->Drawings() )
  954. {
  955. if( drawing->Type() == PCB_LINE_T )
  956. {
  957. DRAWSEGMENT* drawseg = static_cast<DRAWSEGMENT*>( drawing );
  958. if( drawseg->GetLayer() == Edge_Cuts )
  959. {
  960. // XXX GenCAD supports arc boundaries but I've seen nothing that reads them
  961. fprintf( aFile, "LINE %g %g %g %g\n",
  962. MapXTo( drawseg->GetStart().x ), MapYTo( drawseg->GetStart().y ),
  963. MapXTo( drawseg->GetEnd().x ), MapYTo( drawseg->GetEnd().y ) );
  964. }
  965. }
  966. }
  967. fputs( "$ENDBOARD\n\n", aFile );
  968. }
  969. /* Creates the section "$TRACKS"
  970. * This sections give the list of widths (tools) used in tracks and vias
  971. * format:
  972. * $TRACK
  973. * TRACK <name> <width>
  974. * $ENDTRACK
  975. *
  976. * Each tool name is build like this: "TRACK" + track width.
  977. * For instance for a width = 120 : name = "TRACK120".
  978. */
  979. static void CreateTracksInfoData( FILE* aFile, BOARD* aPcb )
  980. {
  981. TRACK* track;
  982. int last_width = -1;
  983. // Find thickness used for traces
  984. // XXX could use the same sorting approach used for pads
  985. std::vector <int> trackinfo;
  986. unsigned ii;
  987. for( track = aPcb->m_Track; track; track = track->Next() )
  988. {
  989. if( last_width != track->GetWidth() ) // Find a thickness already used.
  990. {
  991. for( ii = 0; ii < trackinfo.size(); ii++ )
  992. {
  993. if( trackinfo[ii] == track->GetWidth() )
  994. break;
  995. }
  996. if( ii == trackinfo.size() ) // not found
  997. trackinfo.push_back( track->GetWidth() );
  998. last_width = track->GetWidth();
  999. }
  1000. }
  1001. // Write data
  1002. fputs( "$TRACKS\n", aFile );
  1003. for( ii = 0; ii < trackinfo.size(); ii++ )
  1004. {
  1005. fprintf( aFile, "TRACK TRACK%d %g\n", trackinfo[ii],
  1006. trackinfo[ii] / SCALE_FACTOR );
  1007. }
  1008. fputs( "$ENDTRACKS\n\n", aFile );
  1009. }
  1010. /* Creates the shape of a footprint (section SHAPE)
  1011. * The shape is always given "normal" (Orient 0, not mirrored)
  1012. * It's almost guaranteed that the silk layer will be imported wrong but
  1013. * the shape also contains the pads!
  1014. */
  1015. static void FootprintWriteShape( FILE* aFile, MODULE* module, const wxString& aShapeName )
  1016. {
  1017. EDGE_MODULE* PtEdge;
  1018. EDA_ITEM* PtStruct;
  1019. /* creates header: */
  1020. fprintf( aFile, "\nSHAPE \"%s\"\n", TO_UTF8( escapeString( aShapeName ) ) );
  1021. if( module->GetAttributes() & MOD_VIRTUAL )
  1022. {
  1023. fprintf( aFile, "INSERT SMD\n" );
  1024. }
  1025. else
  1026. {
  1027. if( module->GetAttributes() & MOD_CMS )
  1028. {
  1029. fprintf( aFile, "INSERT SMD\n" );
  1030. }
  1031. else
  1032. {
  1033. fprintf( aFile, "INSERT TH\n" );
  1034. }
  1035. }
  1036. #if 0 /* ATTRIBUTE name and value is unspecified and the original exporter
  1037. * got the syntax wrong, so CAM350 rejected the whole shape! */
  1038. if( module->m_Attributs != MOD_DEFAULT )
  1039. {
  1040. fprintf( aFile, "ATTRIBUTE" );
  1041. if( module->m_Attributs & MOD_CMS )
  1042. fprintf( aFile, " PAD_SMD" );
  1043. if( module->m_Attributs & MOD_VIRTUAL )
  1044. fprintf( aFile, " VIRTUAL" );
  1045. fprintf( aFile, "\n" );
  1046. }
  1047. #endif
  1048. // Silk outline; wildly interpreted by various importers:
  1049. // CAM350 read it right but only closed shapes
  1050. // ProntoPlace double-flip it (at least the pads are correct)
  1051. // GerberTool usually get it right...
  1052. for( PtStruct = module->GraphicalItemsList(); PtStruct; PtStruct = PtStruct->Next() )
  1053. {
  1054. switch( PtStruct->Type() )
  1055. {
  1056. case PCB_MODULE_TEXT_T:
  1057. // If we wanted to export text, this is not the correct section
  1058. break;
  1059. case PCB_MODULE_EDGE_T:
  1060. PtEdge = (EDGE_MODULE*) PtStruct;
  1061. if( PtEdge->GetLayer() == F_SilkS
  1062. || PtEdge->GetLayer() == B_SilkS )
  1063. {
  1064. switch( PtEdge->GetShape() )
  1065. {
  1066. case S_SEGMENT:
  1067. fprintf( aFile, "LINE %g %g %g %g\n",
  1068. PtEdge->m_Start0.x / SCALE_FACTOR,
  1069. -PtEdge->m_Start0.y / SCALE_FACTOR,
  1070. PtEdge->m_End0.x / SCALE_FACTOR,
  1071. -PtEdge->m_End0.y / SCALE_FACTOR );
  1072. break;
  1073. case S_CIRCLE:
  1074. {
  1075. int radius = KiROUND( GetLineLength( PtEdge->m_End0,
  1076. PtEdge->m_Start0 ) );
  1077. fprintf( aFile, "CIRCLE %g %g %g\n",
  1078. PtEdge->m_Start0.x / SCALE_FACTOR,
  1079. -PtEdge->m_Start0.y / SCALE_FACTOR,
  1080. radius / SCALE_FACTOR );
  1081. break;
  1082. }
  1083. case S_ARC:
  1084. {
  1085. int arcendx, arcendy;
  1086. arcendx = PtEdge->m_End0.x - PtEdge->m_Start0.x;
  1087. arcendy = PtEdge->m_End0.y - PtEdge->m_Start0.y;
  1088. RotatePoint( &arcendx, &arcendy, -PtEdge->GetAngle() );
  1089. arcendx += PtEdge->GetStart0().x;
  1090. arcendy += PtEdge->GetStart0().y;
  1091. fprintf( aFile, "ARC %g %g %g %g %g %g\n",
  1092. PtEdge->m_End0.x / SCALE_FACTOR,
  1093. -PtEdge->GetEnd0().y / SCALE_FACTOR,
  1094. arcendx / SCALE_FACTOR,
  1095. -arcendy / SCALE_FACTOR,
  1096. PtEdge->GetStart0().x / SCALE_FACTOR,
  1097. -PtEdge->GetStart0().y / SCALE_FACTOR );
  1098. break;
  1099. }
  1100. case S_POLYGON:
  1101. // Not exported (TODO)
  1102. break;
  1103. default:
  1104. DisplayError( NULL, wxString::Format( "Type Edge Module %d invalid.", PtStruct->Type() ) );
  1105. break;
  1106. }
  1107. }
  1108. break;
  1109. default:
  1110. break;
  1111. }
  1112. }
  1113. }