kicad/pcbnew/pcb_io/ipc2581/pcb_io_ipc2581.h

354 lines
13 KiB
C++

/**
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PCB_IO_IPC2581_H_
#define PCB_IO_IPC2581_H_
#include <pcb_io/pcb_io.h>
#include <pcb_io/pcb_io_mgr.h>
#include <pcb_io/common/plugin_common_layer_mapping.h>
#include <eda_shape.h>
#include <layer_ids.h> // PCB_LAYER_ID
#include <font/font.h>
#include <geometry/shape_segment.h>
#include <stroke_params.h>
#include <wx/xml/xml.h>
#include <memory>
class BOARD;
class BOARD_ITEM;
class EDA_TEXT;
class FOOTPRINT;
class PROGRESS_REPORTER;
class NETINFO_ITEM;
class PAD;
class PCB_SHAPE;
class PCB_VIA;
class PROGRESS_REPORTER;
class SHAPE_POLY_SET;
class SHAPE_SEGMENT;
class PCB_IO_IPC2581 : public PCB_IO, public LAYER_REMAPPABLE_PLUGIN
{
public:
/**
* @brief PCB_IO_IPC2581
*
*/
PCB_IO_IPC2581() : PCB_IO( wxS( "IPC-2581" ) )
{
m_show_layer_mapping_warnings = false;
m_total_bytes = 0;
m_scale = 1.0;
m_sigfig = 3;
m_version = 'B';
m_enterpriseNode = nullptr;
m_board = nullptr;
m_props = nullptr;
m_shape_user_node = nullptr;
m_shape_std_node = nullptr;
m_line_node = nullptr;
m_last_padstack = nullptr;
m_progress_reporter = nullptr;
m_xml_doc = nullptr;
m_xml_root = nullptr;
}
~PCB_IO_IPC2581() override;
/**
*
*/
// BOARD* LoadBoard( const wxString& aFileName, BOARD* aAppendToMe,
// const STRING_UTF8_MAP* aProperties = nullptr, PROJECT* aProject = nullptr ) override;
void SaveBoard( const wxString& aFileName, BOARD* aBoard,
const STRING_UTF8_MAP* aProperties = nullptr ) override;
const IO_BASE::IO_FILE_DESC GetBoardFileDesc() const override
{
return IO_BASE::IO_FILE_DESC( _HKI( "IPC-2581 Production File" ), { "xml" } );
}
const IO_BASE::IO_FILE_DESC GetLibraryDesc() const override
{
// No library description for this plugin
return IO_BASE::IO_FILE_DESC( wxEmptyString, {} );
}
std::vector<FOOTPRINT*> GetImportedCachedLibraryFootprints() override;
long long GetLibraryTimestamp( const wxString& aLibraryPath ) const override
{
return 0;
}
// Reading currently disabled
bool CanReadBoard( const wxString& aFileName ) const override
{
return false;
}
// Reading currently disabled
bool CanReadFootprint( const wxString& aFileName ) const override
{
return false;
}
// Reading currently disabled
bool CanReadLibrary( const wxString& aFileName ) const override
{
return false;
}
/**
* Return the automapped layers.
*
* @param aInputLayerDescriptionVector
* @return Auto-mapped layers
*/
// static std::map<wxString, PCB_LAYER_ID> DefaultLayerMappingCallback(
// const std::vector<INPUT_LAYER_DESC>& aInputLayerDescriptionVector );
/**
* Register a different handler to be called when mapping of IPC2581 to KiCad layers occurs.
*
* @param aLayerMappingHandler
*/
// void RegisterLayerMappingCallback( LAYER_MAPPING_HANDLER aLayerMappingHandler ) override
// {};
private:
/**
* Frees the memory allocated for the loaded footprints in #m_loaded_footprints.
*
*/
void clearLoadedFootprints();
/**
* Creates the XML header for IPC-2581
*
*/
wxXmlNode* generateXmlHeader();
/**
* Creates the Content section of the XML file. This holds the overview of
* the rest of the board data. Includes references to the step, bom, and layers
* as well as the content dictionaries
*/
wxXmlNode* generateContentSection();
/**
* Creates the logistical data header. This section defines the organization and person
* creating the file. Can be used for contact information and config management
*/
wxXmlNode* generateLogisticSection();
/**
* Creates the history section. This section defines the history of the file, the revision
* number, and the date of the revision as well as software used to create the file. Optionally,
* the data could include information about the git revision and tag
*/
wxXmlNode* generateHistorySection();
/**
* Creates the BOM section. This section defines the BOM data for the board. This includes
* the part number, manufacturer, and distributor information for each component on the board.
*/
wxXmlNode* generateBOMSection( wxXmlNode* aEcadNode );
/**
* Creates the ECAD section. This describes the layout, layers, and design as well as
* component placement and netlist information
*/
wxXmlNode* generateEcadSection();
/**
* Creates the Approved Vendor List section. If the user chooses, this will associate
* BOM items with vendor numbers and names.
*/
wxXmlNode* generateAvlSection();
void generateCadLayers( wxXmlNode* aCadLayerNode );
void generateDrillLayers( wxXmlNode* aCadLayerNode );
void generateStepSection( wxXmlNode* aCadNode );
void generateProfile( wxXmlNode* aStepNode );
void generateLogicalNets( wxXmlNode* aStepNode );
void generatePhyNetGroup( wxXmlNode* aStepNode );
void generateLayerFeatures( wxXmlNode* aStepNode );
void generateLayerSetDrill( wxXmlNode* aStepNode );
void generateLayerSetNet( wxXmlNode* aLayerNode, PCB_LAYER_ID aLayer, std::vector<BOARD_ITEM*>& aItems );
wxXmlNode* generateContentStackup( wxXmlNode* aContentNode );
void generateComponents( wxXmlNode* aStepNode );
void addCadHeader( wxXmlNode* aEcadNode );
wxXmlNode* addPackage( wxXmlNode* aStepNode, FOOTPRINT* aFootprint );
void addPad( wxXmlNode* aContentNode, const PAD* aPad, PCB_LAYER_ID aLayer );
void addVia( wxXmlNode* aContentNode, const PCB_VIA* aVia, PCB_LAYER_ID aLayer );
void addPadStack( wxXmlNode* aContentNode, const PAD* aPad );
void addPadStack( wxXmlNode* aContentNode, const PCB_VIA* aVia );
void addLocationNode( wxXmlNode* aContentNode, double aX, double aY );
void addLocationNode( wxXmlNode* aContentNode, const PAD& aPad, bool aRelative );
void addLocationNode( wxXmlNode* aContentNode, const PCB_SHAPE& aShape );
void addShape( wxXmlNode* aContentNode, const PCB_SHAPE& aShape );
void addShape( wxXmlNode* aContentNode, const PAD& aPad, PCB_LAYER_ID aLayer );
void addSlotCavity( wxXmlNode* aContentNode, const PAD& aPad, const wxString& aName );
void addText( wxXmlNode* aContentNode, EDA_TEXT* aShape, const KIFONT::METRICS& aFontMetrics );
void addLineDesc( wxXmlNode* aNode, int aWidth, LINE_STYLE aDashType, bool aForce = false );
void addFillDesc( wxXmlNode* aNode, FILL_T aFillType, bool aForce = false );
bool addPolygonNode( wxXmlNode* aParentNode, const SHAPE_POLY_SET::POLYGON& aPolygon,
FILL_T aFillType = FILL_T::FILLED_SHAPE, int aWidth = 0,
LINE_STYLE aDashType = LINE_STYLE::SOLID );
bool addPolygonCutouts( wxXmlNode* aParentNode, const SHAPE_POLY_SET::POLYGON& aPolygon );
bool addOutlineNode( wxXmlNode* aParentNode, const SHAPE_POLY_SET& aPolySet, int aWidth = 0,
LINE_STYLE aDashType = LINE_STYLE::SOLID );
bool addContourNode( wxXmlNode* aParentNode, const SHAPE_POLY_SET& aPolySet, int aOutline = 0,
FILL_T aFillType = FILL_T::FILLED_SHAPE, int aWidth = 0,
LINE_STYLE aDashType = LINE_STYLE::SOLID );
size_t lineHash( int aWidth, LINE_STYLE aDashType );
size_t shapeHash( const PCB_SHAPE& aShape );
wxString genString( const wxString& aStr, const char* aPrefix = nullptr ) const;
wxString floatVal( double aVal );
wxString pinName( const PAD* aPad ) const;
wxString componentName( FOOTPRINT* aFootprint );
void addXY( wxXmlNode* aNode, const VECTOR2I& aVec, const char* aXName = nullptr,
const char* aYName = nullptr );
void addAttribute( wxXmlNode* aNode, const wxString& aName, const wxString& aValue );
wxXmlNode* insertNode( wxXmlNode* aParent, const wxString& aName );
wxXmlNode* appendNode( wxXmlNode* aParent, const wxString& aName );
void insertNode( wxXmlNode* aParent, wxXmlNode* aNode );
void insertNodeAfter( wxXmlNode* aPrev, wxXmlNode* aNode );
void addLayerAttributes( wxXmlNode* aNode, PCB_LAYER_ID aLayer );
bool isValidLayerFor2581( PCB_LAYER_ID aLayer );
private:
LAYER_MAPPING_HANDLER m_layerMappingHandler;
bool m_show_layer_mapping_warnings;
size_t m_total_bytes; //<! Total number of bytes to be written
wxString m_units_str; //<! Output string for units
double m_scale; //<! Scale factor from IU to IPC2581 units (mm, micron, in)
int m_sigfig; //<! Max number of digits past the decimal point
char m_version; //<! Currently, either 'B' or 'C' for the IPC2581 version
wxString m_OEMRef; //<! If set, field name containing the internal ID of parts
wxString m_mpn; //<! If set, field name containing the manufacturer part number
wxString m_mfg; //<! If set, field name containing the part manufacturer
wxString m_distpn; //<! If set, field name containing the distributor part number
wxString m_dist; //<! If set, field name containing the distributor name
// Node pointer to the main enterprise node to be used for adding
// enterprises later when forming the AVL
wxXmlNode* m_enterpriseNode;
BOARD* m_board;
std::vector<FOOTPRINT*> m_loaded_footprints;
const STRING_UTF8_MAP* m_props;
std::map<size_t, wxString> m_user_shape_dict; //<! Map between shape hash values and reference id string
wxXmlNode* m_shape_user_node; //<! Output XML node for reference shapes in UserDict
std::map<size_t, wxString> m_std_shape_dict; //<! Map between shape hash values and reference id string
wxXmlNode* m_shape_std_node; //<! Output XML node for reference shapes in StandardDict
std::map<size_t, wxString> m_line_dict; //<! Map between line hash values and reference id string
wxXmlNode* m_line_node; //<! Output XML node for reference lines in LineDict
std::map<size_t, wxString> m_padstack_dict; //<! Map between padstack hash values and reference id string (PADSTACK_##)
std::vector<wxXmlNode*> m_padstacks; //<! Holding vector for padstacks. These need to be inserted prior to the components
wxXmlNode* m_last_padstack; //<! Pointer to padstack list where we can insert the VIA padstacks once we process tracks
std::map<size_t, wxString>
m_footprint_dict; //<! Map between the footprint hash values and reference id string (<fpid>_##)
std::map<wxString, FOOTPRINT*>
m_footprint_refdes_dict; //<! Map between sanitized refdes and footprint pointer
std::map<FOOTPRINT*, wxString>
m_footprint_refdes_reverse_dict; //<! Reverse lookup for
std::map<FOOTPRINT*, wxString>
m_OEMRef_dict; //<! Reverse map from the footprint pointer to the reference id string assigned for components
std::map<int, std::vector<std::pair<wxString, wxString>>>
m_net_pin_dict; //<! Map from netcode to the component/pin pairs in the net
std::map<PCB_LAYER_ID, wxString>
m_layer_name_map; //<! Mapping layer name in 2581 to the internal layer id
std::map<std::pair<PCB_LAYER_ID, PCB_LAYER_ID>, std::vector<BOARD_ITEM*>>
m_drill_layers; //<! Drill sets are output as layers (to/from pairs)
std::map<std::pair<PCB_LAYER_ID, PCB_LAYER_ID>, std::vector<PAD*>>
m_slot_holes; //<! Storage vector of slotted holes that need to be output as cutouts
PROGRESS_REPORTER* m_progress_reporter;
std::set<wxUniChar> m_acceptable_chars; //<! IPC2581B and C have differing sets of allowed characters in names
wxXmlDocument* m_xml_doc;
wxXmlNode* m_xml_root;
};
#endif // PCB_IO_IPC2581_H_