2012-05-15 21:27:27 -05:00
/*
* This program source code file is part of KiCad , a free EDA CAD application .
*
* Copyright ( C ) 2012 SoftPLC Corporation , Dick Hollenbeck < dick @ softplc . com >
2017-07-01 15:16:51 +02:00
* Copyright ( C ) 2012 - 2017 KiCad Developers , see AUTHORS . txt for contributors .
2012-05-15 21:27:27 -05:00
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version 2
* of the License , or ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , you may find one here :
* http : //www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http : //www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation , Inc . ,
* 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA
*/
2012-05-20 08:14:46 -05:00
/*
2012-05-15 21:27:27 -05:00
2012-05-20 08:14:46 -05:00
Pcbnew PLUGIN for Eagle 6. x XML * . brd and footprint format .
2012-05-15 21:27:27 -05:00
2012-05-20 08:14:46 -05:00
XML parsing and converting :
Getting line numbers and byte offsets from the source XML file is not
possible using currently available XML libraries within KiCad project :
wxXmlDocument and boost : : property_tree .
2012-05-15 21:27:27 -05:00
2012-05-20 08:14:46 -05:00
property_tree will give line numbers but no byte offsets , and only during
document loading . This means that if we have a problem after the document is
successfully loaded , there is no way to correlate back to line number and byte
offset of the problem . So a different approach is taken , one which relies on the
XML elements themselves using an XPATH type of reporting mechanism . The path to
the problem is reported in the error messages . This means keeping track of that
path as we traverse the XML document for the sole purpose of accurate error
reporting .
2012-05-15 21:27:27 -05:00
2012-05-20 08:14:46 -05:00
User can load the source XML file into firefox or other xml browser and follow
our error message .
2012-05-15 21:27:27 -05:00
2012-05-23 20:18:30 -05:00
Load ( ) TODO ' s
2012-06-01 02:39:32 -05:00
* ) verify zone fill clearances are correct
2012-05-23 20:18:30 -05:00
2012-05-20 08:14:46 -05:00
*/
2012-05-15 21:27:27 -05:00
2012-05-20 08:14:46 -05:00
# include <errno.h>
# include <wx/string.h>
2017-04-07 13:40:34 +02:00
# include <wx/xml/xml.h>
2012-05-15 21:27:27 -05:00
2012-05-20 08:14:46 -05:00
# include <common.h>
# include <macros.h>
# include <fctsys.h>
2012-05-22 12:51:18 -05:00
# include <trigo.h>
2013-11-15 10:28:31 +01:00
# include <macros.h>
2013-11-29 13:29:41 -05:00
# include <kicad_string.h>
2016-07-06 05:22:56 -04:00
# include <properties.h>
2013-01-01 22:05:48 -06:00
# include <wx/filename.h>
2012-05-22 12:51:18 -05:00
2012-05-20 08:14:46 -05:00
# include <class_board.h>
# include <class_module.h>
# include <class_track.h>
# include <class_edge_mod.h>
2012-05-23 20:18:30 -05:00
# include <class_zone.h>
# include <class_pcb_text.h>
2015-12-02 09:47:02 +01:00
# include <class_dimension.h>
2012-05-15 21:27:27 -05:00
2017-04-07 13:40:34 +02:00
# include <eagle_plugin.h>
2012-05-22 12:51:18 -05:00
2017-04-07 13:40:34 +02:00
using namespace std ;
2012-06-01 02:39:32 -05:00
2017-04-07 13:40:34 +02:00
typedef MODULE_MAP : : iterator MODULE_ITER ;
typedef MODULE_MAP : : const_iterator MODULE_CITER ;
2012-06-01 02:39:32 -05:00
2013-03-14 17:54:47 -05:00
/// Parse an eagle distance which is either mm, or mils if there is "mil" suffix.
/// Return is in BIU.
2017-10-17 10:18:54 +02:00
static int parseEagle ( const wxString & aDistance )
2012-06-04 23:39:37 -05:00
{
2017-10-17 10:18:54 +02:00
ECOORD : : UNIT unit = ( aDistance . npos ! = aDistance . find ( " mil " ) )
? ECOORD : : UNIT : : MIL : ECOORD : : UNIT : : MM ;
ECOORD coord ( aDistance , unit ) ;
2012-06-04 23:39:37 -05:00
2017-10-17 10:18:54 +02:00
return coord . ToPcbUnits ( ) ;
2012-06-04 23:39:37 -05:00
}
2017-10-17 10:18:54 +02:00
2017-10-03 21:30:23 +11:00
/// Assemble a two part key as a simple concatenation of aFirst and aSecond parts,
/// using a separator.
static string makeKey ( const string & aFirst , const string & aSecond )
{
string key = aFirst + ' \x02 ' + aSecond ;
return key ;
}
2012-06-04 23:39:37 -05:00
2017-04-07 13:40:34 +02:00
void ERULES : : parse ( wxXmlNode * aRules )
2012-06-04 23:39:37 -05:00
{
2017-04-07 13:40:34 +02:00
wxXmlNode * child = aRules - > GetChildren ( ) ;
2012-06-04 23:39:37 -05:00
2017-04-07 13:40:34 +02:00
while ( child )
2012-06-04 23:39:37 -05:00
{
2017-04-07 13:40:34 +02:00
if ( child - > GetName ( ) = = " param " )
{
const wxString & name = child - > GetAttribute ( " name " ) ;
const wxString & value = child - > GetAttribute ( " value " ) ;
if ( name = = " psElongationLong " )
psElongationLong = wxAtoi ( value ) ;
else if ( name = = " psElongationOffset " )
psElongationOffset = wxAtoi ( value ) ;
else if ( name = = " rvPadTop " )
value . ToDouble ( & rvPadTop ) ;
else if ( name = = " rlMinPadTop " )
rlMinPadTop = parseEagle ( value ) ;
else if ( name = = " rlMaxPadTop " )
rlMaxPadTop = parseEagle ( value ) ;
else if ( name = = " rvViaOuter " )
value . ToDouble ( & rvViaOuter ) ;
else if ( name = = " rlMinViaOuter " )
rlMinViaOuter = parseEagle ( value ) ;
else if ( name = = " rlMaxViaOuter " )
rlMaxViaOuter = parseEagle ( value ) ;
else if ( name = = " mdWireWire " )
mdWireWire = parseEagle ( value ) ;
}
2012-06-04 23:39:37 -05:00
2017-04-07 13:40:34 +02:00
child = child - > GetNext ( ) ;
2012-06-04 23:39:37 -05:00
}
}
2012-06-02 12:07:30 -05:00
EAGLE_PLUGIN : : EAGLE_PLUGIN ( ) :
2012-06-04 23:39:37 -05:00
m_rules ( new ERULES ( ) ) ,
2013-09-21 20:28:02 -04:00
m_xpath ( new XPATH ( ) ) ,
m_mod_time ( wxDateTime : : Now ( ) )
2012-05-20 08:14:46 -05:00
{
init ( NULL ) ;
2013-03-13 11:38:54 -05:00
clear_cu_map ( ) ;
2012-05-20 08:14:46 -05:00
}
2012-05-15 21:27:27 -05:00
2012-05-20 08:14:46 -05:00
EAGLE_PLUGIN : : ~ EAGLE_PLUGIN ( )
{
2017-07-10 11:44:56 +02:00
deleteTemplates ( ) ;
2012-06-04 23:39:37 -05:00
delete m_rules ;
2012-06-02 12:07:30 -05:00
delete m_xpath ;
2012-05-20 08:14:46 -05:00
}
2012-05-15 21:27:27 -05:00
2013-11-27 00:04:04 -06:00
const wxString EAGLE_PLUGIN : : PluginName ( ) const
2012-05-15 21:27:27 -05:00
{
2013-11-27 00:04:04 -06:00
return wxT ( " Eagle " ) ;
2012-05-15 21:27:27 -05:00
}
2013-11-27 00:04:04 -06:00
const wxString EAGLE_PLUGIN : : GetFileExtension ( ) const
2012-05-15 21:27:27 -05:00
{
2013-11-27 00:04:04 -06:00
return wxT ( " brd " ) ;
2012-05-15 21:27:27 -05:00
}
2017-10-17 10:18:54 +02:00
wxSize inline EAGLE_PLUGIN : : kicad_fontz ( const ECOORD & d ) const
2012-05-23 20:18:30 -05:00
{
// texts seem to better match eagle when scaled down by 0.95
2017-10-17 10:18:54 +02:00
int kz = d . ToPcbUnits ( ) * 95 / 100 ;
2012-05-23 20:18:30 -05:00
return wxSize ( kz , kz ) ;
}
2013-09-25 14:17:06 -05:00
BOARD * EAGLE_PLUGIN : : Load ( const wxString & aFileName , BOARD * aAppendToMe , const PROPERTIES * aProperties )
2012-05-15 21:27:27 -05:00
{
2017-04-07 13:40:34 +02:00
LOCALE_IO toggle ; // toggles on, then off, the C locale.
wxXmlNode * doc ;
2012-05-20 08:14:46 -05:00
init ( aProperties ) ;
m_board = aAppendToMe ? aAppendToMe : new BOARD ( ) ;
2012-08-29 18:59:50 +02:00
// Give the filename to the board if it's new
if ( ! aAppendToMe )
m_board - > SetFileName ( aFileName ) ;
2016-05-29 17:02:34 +02:00
// delete on exception, if I own m_board, according to aAppendToMe
unique_ptr < BOARD > deleter ( aAppendToMe ? NULL : m_board ) ;
2012-05-20 08:14:46 -05:00
try
{
2017-04-07 13:40:34 +02:00
// Load the document
wxXmlDocument xmlDocument ;
wxFileName fn = aFileName ;
2012-05-20 08:14:46 -05:00
2017-04-07 13:40:34 +02:00
if ( ! xmlDocument . Load ( fn . GetFullPath ( ) ) )
THROW_IO_ERROR ( wxString : : Format ( _ ( " Unable to read file '%s' " ) ,
fn . GetFullPath ( ) ) ) ;
doc = xmlDocument . GetRoot ( ) ;
2012-05-20 08:14:46 -05:00
2013-03-14 17:54:47 -05:00
m_min_trace = INT_MAX ;
m_min_via = INT_MAX ;
m_min_via_hole = INT_MAX ;
2012-06-02 12:07:30 -05:00
loadAllSections ( doc ) ;
2014-05-13 11:22:51 +02:00
BOARD_DESIGN_SETTINGS & designSettings = m_board - > GetDesignSettings ( ) ;
2013-03-14 17:54:47 -05:00
if ( m_min_trace < designSettings . m_TrackMinWidth )
designSettings . m_TrackMinWidth = m_min_trace ;
if ( m_min_via < designSettings . m_ViasMinSize )
designSettings . m_ViasMinSize = m_min_via ;
if ( m_min_via_hole < designSettings . m_ViasMinDrill )
designSettings . m_ViasMinDrill = m_min_via_hole ;
if ( m_rules - > mdWireWire )
{
2014-05-20 11:29:37 +02:00
NETCLASSPTR defaultNetclass = designSettings . GetDefault ( ) ;
2013-03-14 17:54:47 -05:00
int clearance = KiROUND ( m_rules - > mdWireWire ) ;
if ( clearance < defaultNetclass - > GetClearance ( ) )
defaultNetclass - > SetClearance ( clearance ) ;
}
2012-06-02 12:07:30 -05:00
// should be empty, else missing m_xpath->pop()
wxASSERT ( m_xpath - > Contents ( ) . size ( ) = = 0 ) ;
2012-05-20 08:14:46 -05:00
}
2017-04-07 13:40:34 +02:00
// Catch all exceptions thrown from the parser.
catch ( const XML_PARSER_ERROR & exc )
2012-06-01 02:39:32 -05:00
{
2017-04-07 13:40:34 +02:00
string errmsg = exc . what ( ) ;
2012-06-01 02:39:32 -05:00
2017-04-07 13:40:34 +02:00
errmsg + = " \n @ " ;
2012-06-02 12:07:30 -05:00
errmsg + = m_xpath - > Contents ( ) ;
2012-06-01 02:39:32 -05:00
2012-06-02 12:07:30 -05:00
THROW_IO_ERROR ( errmsg ) ;
2012-06-01 02:39:32 -05:00
}
2012-06-02 12:07:30 -05:00
// IO_ERROR exceptions are left uncaught, they pass upwards from here.
2015-07-25 13:16:05 +02:00
// Ensure the copper layers count is a multiple of 2
// Pcbnew does not like boards with odd layers count
// (these boards cannot exist. they actually have a even layers count)
int lyrcnt = m_board - > GetCopperLayerCount ( ) ;
if ( ( lyrcnt % 2 ) ! = 0 )
{
lyrcnt + + ;
m_board - > SetCopperLayerCount ( lyrcnt ) ;
}
2012-06-02 12:07:30 -05:00
centerBoard ( ) ;
2012-06-01 02:39:32 -05:00
2012-05-20 08:14:46 -05:00
deleter . release ( ) ;
return m_board ;
2012-05-15 21:27:27 -05:00
}
2013-09-25 14:17:06 -05:00
void EAGLE_PLUGIN : : init ( const PROPERTIES * aProperties )
2012-05-15 21:27:27 -05:00
{
2015-02-22 16:25:29 -05:00
m_hole_count = 0 ;
m_min_trace = 0 ;
m_min_via = 0 ;
m_min_via_hole = 0 ;
2012-06-02 12:07:30 -05:00
m_xpath - > clear ( ) ;
2012-05-24 10:00:59 -05:00
m_pads_to_nets . clear ( ) ;
2017-09-07 13:01:12 +02:00
m_templates . clear ( ) ;
2012-05-15 21:27:27 -05:00
2012-05-20 08:14:46 -05:00
m_board = NULL ;
m_props = aProperties ;
2012-05-15 21:27:27 -05:00
2012-06-04 23:39:37 -05:00
delete m_rules ;
m_rules = new ERULES ( ) ;
2012-05-20 08:14:46 -05:00
}
2012-05-15 21:27:27 -05:00
2013-03-13 11:38:54 -05:00
void EAGLE_PLUGIN : : clear_cu_map ( )
{
// All cu layers are invalid until we see them in the <layers> section while
// loading either a board or library. See loadLayerDefs().
for ( unsigned i = 0 ; i < DIM ( m_cu_map ) ; + + i )
m_cu_map [ i ] = - 1 ;
}
2017-04-07 13:40:34 +02:00
void EAGLE_PLUGIN : : loadAllSections ( wxXmlNode * aDoc )
2012-05-20 08:14:46 -05:00
{
2017-04-07 13:40:34 +02:00
wxXmlNode * drawing = MapChildren ( aDoc ) [ " drawing " ] ;
NODE_MAP drawingChildren = MapChildren ( drawing ) ;
wxXmlNode * board = drawingChildren [ " board " ] ;
NODE_MAP boardChildren = MapChildren ( board ) ;
2012-06-04 23:39:37 -05:00
2012-06-02 12:07:30 -05:00
m_xpath - > push ( " eagle.drawing " ) ;
2012-06-01 02:39:32 -05:00
2012-06-04 23:39:37 -05:00
{
m_xpath - > push ( " board " ) ;
2017-04-07 13:40:34 +02:00
wxXmlNode * designrules = boardChildren [ " designrules " ] ;
2012-06-04 23:39:37 -05:00
loadDesignRules ( designrules ) ;
m_xpath - > pop ( ) ;
}
2012-06-01 02:39:32 -05:00
{
2013-03-13 11:38:54 -05:00
m_xpath - > push ( " layers " ) ;
2017-04-07 13:40:34 +02:00
wxXmlNode * layers = drawingChildren [ " layers " ] ;
2012-06-01 02:39:32 -05:00
loadLayerDefs ( layers ) ;
2013-03-13 11:38:54 -05:00
m_xpath - > pop ( ) ;
2012-06-01 02:39:32 -05:00
}
{
2012-06-02 12:07:30 -05:00
m_xpath - > push ( " board " ) ;
2017-04-07 13:40:34 +02:00
wxXmlNode * plain = boardChildren [ " plain " ] ;
2012-06-01 02:39:32 -05:00
loadPlain ( plain ) ;
2012-05-15 21:27:27 -05:00
2017-04-07 13:40:34 +02:00
wxXmlNode * signals = boardChildren [ " signals " ] ;
2012-06-01 02:39:32 -05:00
loadSignals ( signals ) ;
2012-05-22 12:51:18 -05:00
2017-04-07 13:40:34 +02:00
wxXmlNode * libs = boardChildren [ " libraries " ] ;
2012-06-01 02:39:32 -05:00
loadLibraries ( libs ) ;
2012-05-24 10:00:59 -05:00
2017-04-07 13:40:34 +02:00
wxXmlNode * elems = boardChildren [ " elements " ] ;
2012-06-01 02:39:32 -05:00
loadElements ( elems ) ;
2012-06-02 12:07:30 -05:00
m_xpath - > pop ( ) ; // "board"
2012-06-01 02:39:32 -05:00
}
2012-06-02 12:07:30 -05:00
m_xpath - > pop ( ) ; // "eagle.drawing"
2012-06-01 02:39:32 -05:00
}
2017-04-07 13:40:34 +02:00
void EAGLE_PLUGIN : : loadDesignRules ( wxXmlNode * aDesignRules )
2012-06-04 23:39:37 -05:00
{
m_xpath - > push ( " designrules " ) ;
m_rules - > parse ( aDesignRules ) ;
m_xpath - > pop ( ) ; // "designrules"
}
2017-04-07 13:40:34 +02:00
void EAGLE_PLUGIN : : loadLayerDefs ( wxXmlNode * aLayers )
2012-06-01 02:39:32 -05:00
{
typedef std : : vector < ELAYER > ELAYERS ;
typedef ELAYERS : : const_iterator EITER ;
ELAYERS cu ; // copper layers
2017-04-07 13:40:34 +02:00
// Get the first layer and iterate
wxXmlNode * layerNode = aLayers - > GetChildren ( ) ;
2012-06-01 02:39:32 -05:00
// find the subset of layers that are copper, and active
2017-04-07 13:40:34 +02:00
while ( layerNode )
2012-06-01 02:39:32 -05:00
{
2017-04-07 13:40:34 +02:00
ELAYER elayer ( layerNode ) ;
2012-06-01 02:39:32 -05:00
if ( elayer . number > = 1 & & elayer . number < = 16 & & ( ! elayer . active | | * elayer . active ) )
{
cu . push_back ( elayer ) ;
}
2017-04-07 13:40:34 +02:00
layerNode = layerNode - > GetNext ( ) ;
2012-05-22 12:51:18 -05:00
}
2013-03-13 11:17:16 -05:00
// establish cu layer map:
int ki_layer_count = 0 ;
2013-09-21 20:28:02 -04:00
2013-03-13 11:17:16 -05:00
for ( EITER it = cu . begin ( ) ; it ! = cu . end ( ) ; + + it , + + ki_layer_count )
{
if ( ki_layer_count = = 0 )
2014-06-24 11:17:18 -05:00
m_cu_map [ it - > number ] = F_Cu ;
2013-03-13 11:17:16 -05:00
else if ( ki_layer_count = = int ( cu . size ( ) - 1 ) )
2014-06-24 11:17:18 -05:00
m_cu_map [ it - > number ] = B_Cu ;
2013-03-13 11:17:16 -05:00
else
2014-06-24 11:17:18 -05:00
{
2013-03-13 11:17:16 -05:00
// some eagle boards do not have contiguous layer number sequences.
2014-06-24 11:17:18 -05:00
2017-03-12 23:19:33 -04:00
#if 0 // pre PCB_LAYER_ID & LSET:
2013-03-13 11:17:16 -05:00
m_cu_map [ it - > number ] = cu . size ( ) - 1 - ki_layer_count ;
2014-06-24 11:17:18 -05:00
# else
m_cu_map [ it - > number ] = ki_layer_count ;
# endif
}
2013-03-13 11:17:16 -05:00
}
#if 0 && defined(DEBUG)
printf ( " m_cu_map: \n " ) ;
for ( unsigned i = 0 ; i < DIM ( m_cu_map ) ; + + i )
{
printf ( " \t [%d]:%d \n " , i , m_cu_map [ i ] ) ;
}
# endif
2013-11-20 10:35:03 -06:00
// Set the layer names and cu count iff we're loading a board.
if ( m_board )
2012-05-22 12:51:18 -05:00
{
2013-11-20 10:35:03 -06:00
m_board - > SetCopperLayerCount ( cu . size ( ) ) ;
for ( EITER it = cu . begin ( ) ; it ! = cu . end ( ) ; + + it )
{
2017-03-12 23:19:33 -04:00
PCB_LAYER_ID layer = kicad_layer ( it - > number ) ;
2012-06-01 02:39:32 -05:00
2013-11-20 10:35:03 -06:00
// these function provide their own protection against UNDEFINED_LAYER:
m_board - > SetLayerName ( layer , FROM_UTF8 ( it - > name . c_str ( ) ) ) ;
m_board - > SetLayerType ( layer , LT_SIGNAL ) ;
2012-06-01 02:39:32 -05:00
2013-11-20 10:35:03 -06:00
// could map the colors here
}
2012-05-20 08:14:46 -05:00
}
}
2012-05-15 21:27:27 -05:00
2017-04-07 13:40:34 +02:00
void EAGLE_PLUGIN : : loadPlain ( wxXmlNode * aGraphics )
2012-05-20 08:14:46 -05:00
{
2012-06-02 12:07:30 -05:00
m_xpath - > push ( " plain " ) ;
2017-04-07 13:40:34 +02:00
// Get the first graphic and iterate
wxXmlNode * gr = aGraphics - > GetChildren ( ) ;
2012-05-22 12:51:18 -05:00
// (polygon | wire | text | circle | rectangle | frame | hole)*
2017-04-07 13:40:34 +02:00
while ( gr )
2012-05-22 12:51:18 -05:00
{
2017-04-07 13:40:34 +02:00
wxString grName = gr - > GetName ( ) ;
if ( grName = = " wire " )
2012-05-22 12:51:18 -05:00
{
2012-06-02 12:07:30 -05:00
m_xpath - > push ( " wire " ) ;
2013-11-03 20:09:28 -06:00
2017-04-07 13:40:34 +02:00
EWIRE w ( gr ) ;
2017-03-12 23:19:33 -04:00
PCB_LAYER_ID layer = kicad_layer ( w . layer ) ;
2012-05-22 12:51:18 -05:00
2014-12-19 17:02:02 -05:00
wxPoint start ( kicad_x ( w . x1 ) , kicad_y ( w . y1 ) ) ;
wxPoint end ( kicad_x ( w . x2 ) , kicad_y ( w . y2 ) ) ;
2013-03-31 15:27:46 +02:00
if ( layer ! = UNDEFINED_LAYER )
2012-08-11 00:50:17 -05:00
{
DRAWSEGMENT * dseg = new DRAWSEGMENT ( m_board ) ;
m_board - > Add ( dseg , ADD_APPEND ) ;
2014-12-19 17:02:02 -05:00
if ( ! w . curve )
{
dseg - > SetStart ( start ) ;
dseg - > SetEnd ( end ) ;
}
else
{
2017-10-03 21:30:23 +11:00
wxPoint center = ConvertArcCenter ( start , end , * w . curve ) ;
2014-12-19 17:02:02 -05:00
dseg - > SetShape ( S_ARC ) ;
dseg - > SetStart ( center ) ;
dseg - > SetEnd ( start ) ;
dseg - > SetAngle ( * w . curve * - 10.0 ) ; // KiCad rotates the other way
}
2017-10-03 21:30:23 +11:00
dseg - > SetTimeStamp ( EagleTimeStamp ( gr ) ) ;
2012-08-11 00:50:17 -05:00
dseg - > SetLayer ( layer ) ;
2015-10-04 12:56:59 -04:00
dseg - > SetWidth ( Millimeter2iu ( DEFAULT_PCB_EDGE_THICKNESS ) ) ;
2012-08-11 00:50:17 -05:00
}
2012-06-02 12:07:30 -05:00
m_xpath - > pop ( ) ;
2012-05-22 12:51:18 -05:00
}
2017-04-07 13:40:34 +02:00
else if ( grName = = " text " )
2012-05-22 12:51:18 -05:00
{
2012-06-02 12:07:30 -05:00
m_xpath - > push ( " text " ) ;
2012-05-30 16:40:32 -05:00
2017-04-07 13:40:34 +02:00
ETEXT t ( gr ) ;
2017-03-12 23:19:33 -04:00
PCB_LAYER_ID layer = kicad_layer ( t . layer ) ;
2013-11-03 20:09:28 -06:00
if ( layer ! = UNDEFINED_LAYER )
2012-08-11 00:50:17 -05:00
{
TEXTE_PCB * pcbtxt = new TEXTE_PCB ( m_board ) ;
m_board - > Add ( pcbtxt , ADD_APPEND ) ;
2012-05-23 20:18:30 -05:00
2012-08-11 00:50:17 -05:00
pcbtxt - > SetLayer ( layer ) ;
2017-10-03 21:30:23 +11:00
pcbtxt - > SetTimeStamp ( EagleTimeStamp ( gr ) ) ;
2012-08-11 00:50:17 -05:00
pcbtxt - > SetText ( FROM_UTF8 ( t . text . c_str ( ) ) ) ;
2017-01-23 14:30:11 -06:00
pcbtxt - > SetTextPos ( wxPoint ( kicad_x ( t . x ) , kicad_y ( t . y ) ) ) ;
2012-05-23 20:18:30 -05:00
2017-01-23 14:30:11 -06:00
pcbtxt - > SetTextSize ( kicad_fontz ( t . size ) ) ;
2012-05-23 20:18:30 -05:00
2017-10-17 10:18:54 +02:00
double ratio = t . ratio ? * t . ratio : 8 ; // DTD says 8 is default
2012-05-23 20:18:30 -05:00
2017-10-17 10:18:54 +02:00
pcbtxt - > SetThickness ( t . size . ToPcbUnits ( ) * ratio / 100 ) ;
2012-05-23 20:18:30 -05:00
2012-08-11 00:50:17 -05:00
int align = t . align ? * t . align : ETEXT : : BOTTOM_LEFT ;
2012-06-06 20:49:43 -05:00
2012-08-11 00:50:17 -05:00
if ( t . rot )
{
int sign = t . rot - > mirror ? - 1 : 1 ;
pcbtxt - > SetMirrored ( t . rot - > mirror ) ;
2012-05-23 20:18:30 -05:00
2012-08-11 00:50:17 -05:00
double degrees = t . rot - > degrees ;
2012-05-23 20:18:30 -05:00
2012-08-11 00:50:17 -05:00
if ( degrees = = 90 | | t . rot - > spin )
2017-01-23 14:30:11 -06:00
pcbtxt - > SetTextAngle ( sign * t . rot - > degrees * 10 ) ;
2012-08-11 00:50:17 -05:00
else if ( degrees = = 180 )
align = ETEXT : : TOP_RIGHT ;
else if ( degrees = = 270 )
{
2017-01-23 14:30:11 -06:00
pcbtxt - > SetTextAngle ( sign * 90 * 10 ) ;
2012-08-11 00:50:17 -05:00
align = ETEXT : : TOP_RIGHT ;
}
2017-04-14 08:30:57 -04:00
else // Ok so text is not at 90,180 or 270 so do some funny stuf to get placement right
{
if ( ( degrees > 0 ) & & ( degrees < 90 ) )
pcbtxt - > SetTextAngle ( sign * t . rot - > degrees * 10 ) ;
else if ( ( degrees > 90 ) & & ( degrees < 180 ) )
{
pcbtxt - > SetTextAngle ( sign * ( t . rot - > degrees + 180 ) * 10 ) ;
align = ETEXT : : TOP_RIGHT ;
}
else if ( ( degrees > 180 ) & & ( degrees < 270 ) )
{
pcbtxt - > SetTextAngle ( sign * ( t . rot - > degrees - 180 ) * 10 ) ;
align = ETEXT : : TOP_RIGHT ;
}
else if ( ( degrees > 270 ) & & ( degrees < 360 ) )
{
pcbtxt - > SetTextAngle ( sign * t . rot - > degrees * 10 ) ;
align = ETEXT : : BOTTOM_LEFT ;
}
}
2012-06-06 20:49:43 -05:00
}
2012-08-11 00:50:17 -05:00
switch ( align )
{
case ETEXT : : CENTER :
// this was the default in pcbtxt's constructor
break ;
case ETEXT : : CENTER_LEFT :
pcbtxt - > SetHorizJustify ( GR_TEXT_HJUSTIFY_LEFT ) ;
break ;
case ETEXT : : CENTER_RIGHT :
pcbtxt - > SetHorizJustify ( GR_TEXT_HJUSTIFY_RIGHT ) ;
break ;
case ETEXT : : TOP_CENTER :
pcbtxt - > SetVertJustify ( GR_TEXT_VJUSTIFY_TOP ) ;
break ;
case ETEXT : : TOP_LEFT :
pcbtxt - > SetHorizJustify ( GR_TEXT_HJUSTIFY_LEFT ) ;
pcbtxt - > SetVertJustify ( GR_TEXT_VJUSTIFY_TOP ) ;
break ;
case ETEXT : : TOP_RIGHT :
pcbtxt - > SetHorizJustify ( GR_TEXT_HJUSTIFY_RIGHT ) ;
pcbtxt - > SetVertJustify ( GR_TEXT_VJUSTIFY_TOP ) ;
break ;
case ETEXT : : BOTTOM_CENTER :
pcbtxt - > SetVertJustify ( GR_TEXT_VJUSTIFY_BOTTOM ) ;
break ;
case ETEXT : : BOTTOM_LEFT :
pcbtxt - > SetHorizJustify ( GR_TEXT_HJUSTIFY_LEFT ) ;
pcbtxt - > SetVertJustify ( GR_TEXT_VJUSTIFY_BOTTOM ) ;
break ;
case ETEXT : : BOTTOM_RIGHT :
pcbtxt - > SetHorizJustify ( GR_TEXT_HJUSTIFY_RIGHT ) ;
pcbtxt - > SetVertJustify ( GR_TEXT_VJUSTIFY_BOTTOM ) ;
break ;
}
2012-05-23 20:18:30 -05:00
}
2012-06-02 12:07:30 -05:00
m_xpath - > pop ( ) ;
2012-05-22 12:51:18 -05:00
}
2017-04-07 13:40:34 +02:00
else if ( grName = = " circle " )
2012-05-22 12:51:18 -05:00
{
2012-06-02 12:07:30 -05:00
m_xpath - > push ( " circle " ) ;
2013-11-03 20:09:28 -06:00
2017-04-07 13:40:34 +02:00
ECIRCLE c ( gr ) ;
2017-03-12 23:19:33 -04:00
PCB_LAYER_ID layer = kicad_layer ( c . layer ) ;
2012-05-22 12:51:18 -05:00
2013-03-31 15:27:46 +02:00
if ( layer ! = UNDEFINED_LAYER ) // unsupported layer
2012-08-11 00:50:17 -05:00
{
DRAWSEGMENT * dseg = new DRAWSEGMENT ( m_board ) ;
m_board - > Add ( dseg , ADD_APPEND ) ;
dseg - > SetShape ( S_CIRCLE ) ;
2017-10-03 21:30:23 +11:00
dseg - > SetTimeStamp ( EagleTimeStamp ( gr ) ) ;
2012-08-11 00:50:17 -05:00
dseg - > SetLayer ( layer ) ;
dseg - > SetStart ( wxPoint ( kicad_x ( c . x ) , kicad_y ( c . y ) ) ) ;
dseg - > SetEnd ( wxPoint ( kicad_x ( c . x + c . radius ) , kicad_y ( c . y ) ) ) ;
2017-10-17 10:18:54 +02:00
dseg - > SetWidth ( c . width . ToPcbUnits ( ) ) ;
2012-08-11 00:50:17 -05:00
}
2012-06-02 12:07:30 -05:00
m_xpath - > pop ( ) ;
2012-05-22 12:51:18 -05:00
}
2017-04-07 13:40:34 +02:00
else if ( grName = = " rectangle " )
2012-05-22 12:51:18 -05:00
{
2015-10-04 12:56:59 -04:00
// This seems to be a simplified rectangular [copper] zone, cannot find any
// net related info on it from the DTD.
2012-06-02 12:07:30 -05:00
m_xpath - > push ( " rectangle " ) ;
2013-11-03 20:09:28 -06:00
2017-04-07 13:40:34 +02:00
ERECT r ( gr ) ;
2017-03-12 23:19:33 -04:00
PCB_LAYER_ID layer = kicad_layer ( r . layer ) ;
2012-05-23 20:18:30 -05:00
2013-04-09 18:00:46 +02:00
if ( IsCopperLayer ( layer ) )
2012-05-23 20:18:30 -05:00
{
2012-05-29 13:10:56 -05:00
// use a "netcode = 0" type ZONE:
ZONE_CONTAINER * zone = new ZONE_CONTAINER ( m_board ) ;
m_board - > Add ( zone , ADD_APPEND ) ;
2012-05-23 20:18:30 -05:00
2017-10-03 21:30:23 +11:00
zone - > SetTimeStamp ( EagleTimeStamp ( gr ) ) ;
2012-05-29 13:10:56 -05:00
zone - > SetLayer ( layer ) ;
2014-02-25 11:40:34 +01:00
zone - > SetNetCode ( NETINFO_LIST : : UNCONNECTED ) ;
2012-05-23 20:18:30 -05:00
2017-03-07 13:06:00 +01:00
ZONE_CONTAINER : : HATCH_STYLE outline_hatch = ZONE_CONTAINER : : DIAGONAL_EDGE ;
2012-05-23 20:18:30 -05:00
2017-06-19 13:29:57 +02:00
const int outlineIdx = - 1 ; // this is the id of the copper zone main outline
zone - > AppendCorner ( wxPoint ( kicad_x ( r . x1 ) , kicad_y ( r . y1 ) ) , outlineIdx ) ;
zone - > AppendCorner ( wxPoint ( kicad_x ( r . x2 ) , kicad_y ( r . y1 ) ) , outlineIdx ) ;
zone - > AppendCorner ( wxPoint ( kicad_x ( r . x2 ) , kicad_y ( r . y2 ) ) , outlineIdx ) ;
zone - > AppendCorner ( wxPoint ( kicad_x ( r . x1 ) , kicad_y ( r . y2 ) ) , outlineIdx ) ;
2012-05-23 20:18:30 -05:00
2012-05-29 13:10:56 -05:00
// this is not my fault:
2017-07-01 15:16:51 +02:00
zone - > SetHatch ( outline_hatch , zone - > GetDefaultHatchPitch ( ) , true ) ;
2012-05-23 20:18:30 -05:00
}
2013-03-20 10:50:12 -04:00
2012-06-02 12:07:30 -05:00
m_xpath - > pop ( ) ;
2012-05-22 12:51:18 -05:00
}
2017-04-07 13:40:34 +02:00
else if ( grName = = " hole " )
2012-05-22 12:51:18 -05:00
{
2012-06-02 12:07:30 -05:00
m_xpath - > push ( " hole " ) ;
2017-04-07 13:40:34 +02:00
EHOLE e ( gr ) ;
2012-05-31 10:18:55 -05:00
2015-08-23 21:40:33 +02:00
// Fabricate a MODULE with a single PAD_ATTRIB_HOLE_NOT_PLATED pad.
2012-05-31 10:18:55 -05:00
// Use m_hole_count to gen up a unique name.
MODULE * module = new MODULE ( m_board ) ;
m_board - > Add ( module , ADD_APPEND ) ;
char temp [ 40 ] ;
sprintf ( temp , " @HOLE%d " , m_hole_count + + ) ;
module - > SetReference ( FROM_UTF8 ( temp ) ) ;
module - > Reference ( ) . SetVisible ( false ) ;
wxPoint pos ( kicad_x ( e . x ) , kicad_y ( e . y ) ) ;
module - > SetPosition ( pos ) ;
2015-08-23 21:40:33 +02:00
// Add a PAD_ATTRIB_HOLE_NOT_PLATED pad to this module.
2012-05-31 10:18:55 -05:00
D_PAD * pad = new D_PAD ( module ) ;
2017-04-25 11:06:24 +02:00
module - > PadsList ( ) . PushBack ( pad ) ;
2012-05-31 10:18:55 -05:00
2015-08-23 21:40:33 +02:00
pad - > SetShape ( PAD_SHAPE_CIRCLE ) ;
pad - > SetAttribute ( PAD_ATTRIB_HOLE_NOT_PLATED ) ;
2012-05-31 10:18:55 -05:00
/* pad's position is already centered on module at relative (0, 0)
wxPoint padpos ( kicad_x ( e . x ) , kicad_y ( e . y ) ) ;
pad - > SetPos0 ( padpos ) ;
pad - > SetPosition ( padpos + module - > GetPosition ( ) ) ;
*/
2017-10-17 10:18:54 +02:00
wxSize sz ( e . drill . ToPcbUnits ( ) , e . drill . ToPcbUnits ( ) ) ;
2012-05-31 10:18:55 -05:00
pad - > SetDrillSize ( sz ) ;
pad - > SetSize ( sz ) ;
2014-06-24 11:17:18 -05:00
pad - > SetLayerSet ( LSET : : AllCuMask ( ) ) ;
2012-06-02 12:07:30 -05:00
m_xpath - > pop ( ) ;
2012-05-22 12:51:18 -05:00
}
2017-04-07 13:40:34 +02:00
else if ( grName = = " frame " )
2012-05-22 12:51:18 -05:00
{
2012-05-24 10:00:59 -05:00
// picture this
2012-05-22 12:51:18 -05:00
}
2017-04-07 13:40:34 +02:00
else if ( grName = = " polygon " )
2012-05-22 12:51:18 -05:00
{
2012-06-02 12:07:30 -05:00
// could be on a copper layer, could be on another layer.
// copper layer would be done using netCode=0 type of ZONE_CONTAINER.
2012-05-22 12:51:18 -05:00
}
2017-04-07 13:40:34 +02:00
else if ( grName = = " dimension " )
2015-12-02 09:47:02 +01:00
{
2017-04-07 13:40:34 +02:00
EDIMENSION d ( gr ) ;
2017-05-08 11:03:07 +02:00
PCB_LAYER_ID layer = kicad_layer ( d . layer ) ;
2015-12-02 09:47:02 +01:00
2017-05-08 11:03:07 +02:00
if ( layer ! = UNDEFINED_LAYER )
{
DIMENSION * dimension = new DIMENSION ( m_board ) ;
m_board - > Add ( dimension , ADD_APPEND ) ;
dimension - > SetLayer ( layer ) ;
// The origin and end are assumed to always be in this order from eagle
dimension - > SetOrigin ( wxPoint ( kicad_x ( d . x1 ) , kicad_y ( d . y1 ) ) ) ;
dimension - > SetEnd ( wxPoint ( kicad_x ( d . x2 ) , kicad_y ( d . y2 ) ) ) ;
dimension - > Text ( ) . SetTextSize ( m_board - > GetDesignSettings ( ) . m_PcbTextSize ) ;
int width = m_board - > GetDesignSettings ( ) . m_PcbTextWidth ;
int maxThickness = Clamp_Text_PenSize ( width , dimension - > Text ( ) . GetTextSize ( ) ) ;
if ( width > maxThickness )
width = maxThickness ;
dimension - > Text ( ) . SetThickness ( width ) ;
dimension - > SetWidth ( width ) ;
// check which axis the dimension runs in
// because the "height" of the dimension is perpendicular to that axis
// Note the check is just if two axes are close enough to each other
// Eagle appears to have some rounding errors
2017-10-17 10:18:54 +02:00
if ( abs ( ( d . x1 - d . x2 ) . ToPcbUnits ( ) ) < 50000 ) // 50000 nm = 0.05 mm
2017-05-08 11:03:07 +02:00
dimension - > SetHeight ( kicad_x ( d . x1 - d . x3 ) ) ;
else
dimension - > SetHeight ( kicad_y ( d . y3 - d . y1 ) ) ;
2015-12-02 09:47:02 +01:00
2017-05-08 11:03:07 +02:00
dimension - > AdjustDimensionDetails ( ) ;
}
}
2017-04-07 13:40:34 +02:00
// Get next graphic
gr = gr - > GetNext ( ) ;
2012-05-22 12:51:18 -05:00
}
2012-06-02 12:07:30 -05:00
m_xpath - > pop ( ) ;
2012-05-22 12:51:18 -05:00
}
2012-05-15 21:27:27 -05:00
2017-04-07 13:40:34 +02:00
void EAGLE_PLUGIN : : loadLibrary ( wxXmlNode * aLib , const string * aLibName )
2012-05-22 12:51:18 -05:00
{
2013-01-01 22:05:48 -06:00
m_xpath - > push ( " packages " ) ;
2012-06-02 12:07:30 -05:00
2013-01-01 22:05:48 -06:00
// library will have <xmlattr> node, skip that and get the single packages node
2017-04-07 13:40:34 +02:00
wxXmlNode * packages = MapChildren ( aLib ) [ " packages " ] ;
2012-05-15 21:27:27 -05:00
2013-01-01 22:05:48 -06:00
// Create a MODULE for all the eagle packages, for use later via a copy constructor
// to instantiate needed MODULES in our BOARD. Save the MODULE templates in
// a MODULE_MAP using a single lookup key consisting of libname+pkgname.
2017-04-07 13:40:34 +02:00
// Get the first package and iterate
wxXmlNode * package = packages - > GetChildren ( ) ;
while ( package )
2013-01-01 22:05:48 -06:00
{
m_xpath - > push ( " package " , " name " ) ;
2012-05-20 08:14:46 -05:00
2017-04-07 13:40:34 +02:00
const wxString & pack_ref = package - > GetAttribute ( " name " ) ;
2013-11-06 10:53:44 -06:00
2017-04-07 13:40:34 +02:00
string pack_name ( pack_ref . ToStdString ( ) ) ;
2013-11-06 10:53:44 -06:00
2013-11-29 13:29:41 -05:00
ReplaceIllegalFileNameChars ( & pack_name ) ;
2013-11-06 10:53:44 -06:00
2013-01-01 22:05:48 -06:00
m_xpath - > Value ( pack_name . c_str ( ) ) ;
2012-05-20 08:14:46 -05:00
2013-11-06 10:53:44 -06:00
string key = aLibName ? makeKey ( * aLibName , pack_name ) : pack_name ;
2012-06-02 12:07:30 -05:00
2017-04-07 13:40:34 +02:00
MODULE * m = makeModule ( package , pack_name ) ;
2012-06-02 12:07:30 -05:00
2013-01-01 22:05:48 -06:00
// add the templating MODULE to the MODULE template factory "m_templates"
2017-04-07 13:40:34 +02:00
std : : pair < MODULE_ITER , bool > r = m_templates . insert ( { key , m } ) ;
2012-06-02 12:07:30 -05:00
2013-11-20 10:35:03 -06:00
if ( ! r . second
// && !( m_props && m_props->Value( "ignore_duplicates" ) )
2015-12-02 09:18:32 +01:00
)
2013-01-01 22:05:48 -06:00
{
wxString lib = aLibName ? FROM_UTF8 ( aLibName - > c_str ( ) ) : m_lib_path ;
wxString pkg = FROM_UTF8 ( pack_name . c_str ( ) ) ;
wxString emsg = wxString : : Format (
2013-11-20 10:35:03 -06:00
_ ( " <package> name: '%s' duplicated in eagle <library>: '%s' " ) ,
2013-01-01 22:05:48 -06:00
GetChars ( pkg ) ,
GetChars ( lib )
) ;
THROW_IO_ERROR ( emsg ) ;
}
2012-05-22 12:51:18 -05:00
2013-01-01 22:05:48 -06:00
m_xpath - > pop ( ) ;
2017-04-07 13:40:34 +02:00
package = package - > GetNext ( ) ;
2013-01-01 22:05:48 -06:00
}
2012-05-22 12:51:18 -05:00
2013-01-01 22:05:48 -06:00
m_xpath - > pop ( ) ; // "packages"
}
2012-05-22 12:51:18 -05:00
2017-04-07 13:40:34 +02:00
void EAGLE_PLUGIN : : loadLibraries ( wxXmlNode * aLibs )
2013-01-01 22:05:48 -06:00
{
m_xpath - > push ( " libraries.library " , " name " ) ;
2012-06-02 12:07:30 -05:00
2017-04-07 13:40:34 +02:00
// Get the first library and iterate
wxXmlNode * library = aLibs - > GetChildren ( ) ;
while ( library )
2013-01-01 22:05:48 -06:00
{
2017-04-07 13:40:34 +02:00
const string & lib_name = library - > GetAttribute ( " name " ) . ToStdString ( ) ;
2012-06-02 12:07:30 -05:00
2013-01-01 22:05:48 -06:00
m_xpath - > Value ( lib_name . c_str ( ) ) ;
2017-04-07 13:40:34 +02:00
loadLibrary ( library , & lib_name ) ;
library = library - > GetNext ( ) ;
2012-05-22 12:51:18 -05:00
}
2012-06-02 12:07:30 -05:00
m_xpath - > pop ( ) ;
2012-05-30 16:40:32 -05:00
}
2012-05-22 12:51:18 -05:00
2012-05-30 16:40:32 -05:00
2017-04-07 13:40:34 +02:00
void EAGLE_PLUGIN : : loadElements ( wxXmlNode * aElements )
2012-05-30 16:40:32 -05:00
{
2012-06-02 12:07:30 -05:00
m_xpath - > push ( " elements.element " , " name " ) ;
2012-06-06 20:49:43 -05:00
EATTR name ;
EATTR value ;
2015-12-02 09:18:32 +01:00
bool refanceNamePresetInPackageLayout ;
2015-12-02 12:46:55 +01:00
bool valueNamePresetInPackageLayout ;
2015-12-02 09:18:32 +01:00
2017-04-07 13:40:34 +02:00
// Get the first element and iterate
wxXmlNode * element = aElements - > GetChildren ( ) ;
2015-12-02 09:18:32 +01:00
2017-04-07 13:40:34 +02:00
while ( element )
2012-05-22 12:51:18 -05:00
{
2017-04-07 13:40:34 +02:00
if ( element - > GetName ( ) ! = " element " )
2017-07-01 16:59:07 +02:00
{
wxLogMessage ( " expected: <element> read <%s>. Skip it " , element - > GetName ( ) ) ;
// Get next item
element = element - > GetNext ( ) ;
2012-05-30 16:40:32 -05:00
continue ;
2017-07-01 16:59:07 +02:00
}
2012-05-22 12:51:18 -05:00
2017-04-07 13:40:34 +02:00
EELEMENT e ( element ) ;
2012-05-31 10:18:55 -05:00
2013-01-01 22:05:48 -06:00
// use "NULL-ness" as an indication of presence of the attribute:
2012-06-06 20:49:43 -05:00
EATTR * nameAttr = 0 ;
EATTR * valueAttr = 0 ;
2012-06-02 12:07:30 -05:00
m_xpath - > Value ( e . name . c_str ( ) ) ;
2016-05-29 17:02:34 +02:00
string pkg_key = makeKey ( e . library , e . package ) ;
2012-05-29 13:10:56 -05:00
2016-05-29 17:02:34 +02:00
MODULE_CITER mi = m_templates . find ( pkg_key ) ;
2012-05-29 13:10:56 -05:00
2012-05-30 16:40:32 -05:00
if ( mi = = m_templates . end ( ) )
{
wxString emsg = wxString : : Format ( _ ( " No '%s' package in library '%s' " ) ,
2015-12-02 09:18:32 +01:00
GetChars ( FROM_UTF8 ( e . package . c_str ( ) ) ) ,
GetChars ( FROM_UTF8 ( e . library . c_str ( ) ) ) ) ;
2012-05-30 16:40:32 -05:00
THROW_IO_ERROR ( emsg ) ;
}
2012-05-29 13:10:56 -05:00
2012-05-30 16:40:32 -05:00
// copy constructor to clone the template
MODULE * m = new MODULE ( * mi - > second ) ;
m_board - > Add ( m , ADD_APPEND ) ;
2012-05-29 13:10:56 -05:00
2012-05-30 16:40:32 -05:00
// update the nets within the pads of the clone
2017-04-25 11:06:24 +02:00
for ( D_PAD * pad = m - > PadsList ( ) ; pad ; pad = pad - > Next ( ) )
2012-05-30 16:40:32 -05:00
{
2017-08-11 11:22:13 +02:00
string pn_key = makeKey ( e . name , TO_UTF8 ( pad - > GetName ( ) ) ) ;
2012-05-29 13:10:56 -05:00
2016-05-29 17:02:34 +02:00
NET_MAP_CITER ni = m_pads_to_nets . find ( pn_key ) ;
2012-05-30 16:40:32 -05:00
if ( ni ! = m_pads_to_nets . end ( ) )
{
2012-05-31 10:18:55 -05:00
const ENET * enet = & ni - > second ;
2014-02-25 11:40:34 +01:00
pad - > SetNetCode ( enet - > netcode ) ;
2012-05-30 16:40:32 -05:00
}
}
2012-05-29 13:10:56 -05:00
2015-12-02 09:18:32 +01:00
refanceNamePresetInPackageLayout = true ;
2015-12-02 12:46:55 +01:00
valueNamePresetInPackageLayout = true ;
2012-05-31 10:18:55 -05:00
m - > SetPosition ( wxPoint ( kicad_x ( e . x ) , kicad_y ( e . y ) ) ) ;
2017-07-17 14:09:01 +02:00
2015-12-02 12:46:55 +01:00
// Is >NAME field set in package layout ?
2015-12-02 09:18:32 +01:00
if ( m - > GetReference ( ) . size ( ) = = 0 )
{
m - > Reference ( ) . SetVisible ( false ) ; // No so no show
refanceNamePresetInPackageLayout = false ;
}
2017-07-17 14:09:01 +02:00
2015-12-02 12:46:55 +01:00
// Is >VALUE field set in package layout
2015-12-02 09:18:32 +01:00
if ( m - > GetValue ( ) . size ( ) = = 0 )
{
m - > Value ( ) . SetVisible ( false ) ; // No so no show
2015-12-02 12:46:55 +01:00
valueNamePresetInPackageLayout = false ;
2015-12-02 09:18:32 +01:00
}
2017-07-17 14:09:01 +02:00
2012-05-31 10:18:55 -05:00
m - > SetReference ( FROM_UTF8 ( e . name . c_str ( ) ) ) ;
m - > SetValue ( FROM_UTF8 ( e . value . c_str ( ) ) ) ;
2012-05-29 13:10:56 -05:00
2015-12-02 09:18:32 +01:00
if ( ! e . smashed )
{ // Not smashed so show NAME & VALUE
2015-12-02 12:46:55 +01:00
if ( valueNamePresetInPackageLayout )
2015-12-02 09:18:32 +01:00
m - > Value ( ) . SetVisible ( true ) ; // Only if place holder in package layout
2017-07-17 14:09:01 +02:00
2015-12-02 09:18:32 +01:00
if ( refanceNamePresetInPackageLayout )
m - > Reference ( ) . SetVisible ( true ) ; // Only if place holder in package layout
}
else if ( * e . smashed = = true )
{ // Smasted so set default to no show for NAME and VALUE
m - > Value ( ) . SetVisible ( false ) ;
m - > Reference ( ) . SetVisible ( false ) ;
// initalize these to default values incase the <attribute> elements are not present.
m_xpath - > push ( " attribute " , " name " ) ;
// VALUE and NAME can have something like our text "effects" overrides
// in SWEET and new schematic. Eagle calls these XML elements "attribute".
// There can be one for NAME and/or VALUE both. Features present in the
// EATTR override the ones established in the package only if they are
// present here (except for rot, which if not present means angle zero).
// So the logic is a bit different than in packageText() and in plain text.
2017-04-07 13:40:34 +02:00
// Get the first attribute and iterate
wxXmlNode * attribute = element - > GetChildren ( ) ;
while ( attribute )
{
if ( attribute - > GetName ( ) ! = " attribute " )
2017-07-01 16:59:07 +02:00
{
wxLogMessage ( " expected: <attribute> read <%s>. Skip it " , attribute - > GetName ( ) ) ;
attribute = attribute - > GetNext ( ) ;
2015-12-02 09:18:32 +01:00
continue ;
2017-07-01 16:59:07 +02:00
}
2015-12-02 09:18:32 +01:00
2017-04-07 13:40:34 +02:00
EATTR a ( attribute ) ;
2015-12-02 09:18:32 +01:00
if ( a . name = = " NAME " )
{
name = a ;
nameAttr = & name ;
// do we have a display attribute ?
if ( a . display )
{
// Yes!
switch ( * a . display )
{
case EATTR : : VALUE :
nameAttr - > name = e . name ;
m - > SetReference ( e . name ) ;
if ( refanceNamePresetInPackageLayout )
m - > Reference ( ) . SetVisible ( true ) ;
break ;
case EATTR : : NAME :
if ( refanceNamePresetInPackageLayout )
{
m - > SetReference ( " NAME " ) ;
m - > Reference ( ) . SetVisible ( true ) ;
}
break ;
case EATTR : : BOTH :
if ( refanceNamePresetInPackageLayout )
m - > Reference ( ) . SetVisible ( true ) ;
nameAttr - > name = nameAttr - > name + " = " + e . name ;
m - > SetReference ( " NAME = " + e . name ) ;
break ;
case EATTR : : Off :
m - > Reference ( ) . SetVisible ( false ) ;
break ;
default :
nameAttr - > name = e . name ;
if ( refanceNamePresetInPackageLayout )
m - > Reference ( ) . SetVisible ( true ) ;
}
}
else
// No display, so default is visable, and show value of NAME
m - > Reference ( ) . SetVisible ( true ) ;
}
else if ( a . name = = " VALUE " )
{
value = a ;
valueAttr = & value ;
if ( a . display )
{
// Yes!
switch ( * a . display )
{
case EATTR : : VALUE :
valueAttr - > value = e . value ;
m - > SetValue ( e . value ) ;
2015-12-02 12:46:55 +01:00
if ( valueNamePresetInPackageLayout )
2015-12-02 09:18:32 +01:00
m - > Value ( ) . SetVisible ( true ) ;
break ;
case EATTR : : NAME :
2015-12-02 12:46:55 +01:00
if ( valueNamePresetInPackageLayout )
2015-12-02 09:18:32 +01:00
m - > Value ( ) . SetVisible ( true ) ;
m - > SetValue ( " VALUE " ) ;
break ;
case EATTR : : BOTH :
2015-12-02 12:46:55 +01:00
if ( valueNamePresetInPackageLayout )
2015-12-02 09:18:32 +01:00
m - > Value ( ) . SetVisible ( true ) ;
valueAttr - > value = " VALUE = " + e . value ;
m - > SetValue ( " VALUE = " + e . value ) ;
break ;
case EATTR : : Off :
m - > Value ( ) . SetVisible ( false ) ;
break ;
default :
valueAttr - > value = e . value ;
2015-12-02 12:46:55 +01:00
if ( valueNamePresetInPackageLayout )
2015-12-02 09:18:32 +01:00
m - > Value ( ) . SetVisible ( true ) ;
}
}
else
// No display, so default is visible, and show value of NAME
m - > Value ( ) . SetVisible ( true ) ;
}
2017-04-07 13:40:34 +02:00
attribute = attribute - > GetNext ( ) ;
2012-06-06 20:49:43 -05:00
}
2012-05-29 13:10:56 -05:00
2015-12-02 09:18:32 +01:00
m_xpath - > pop ( ) ; // "attribute"
}
2012-06-04 23:39:37 -05:00
2012-06-06 20:49:43 -05:00
orientModuleAndText ( m , e , nameAttr , valueAttr ) ;
2017-04-07 13:40:34 +02:00
// Get next element
element = element - > GetNext ( ) ;
2012-06-06 20:49:43 -05:00
}
m_xpath - > pop ( ) ; // "elements.element"
}
void EAGLE_PLUGIN : : orientModuleAndText ( MODULE * m , const EELEMENT & e ,
const EATTR * nameAttr , const EATTR * valueAttr )
{
if ( e . rot )
{
if ( e . rot - > mirror )
2012-06-04 23:39:37 -05:00
{
2012-08-11 00:50:17 -05:00
double orientation = e . rot - > degrees + 180.0 ;
m - > SetOrientation ( orientation * 10 ) ;
2012-06-06 20:49:43 -05:00
m - > Flip ( m - > GetPosition ( ) ) ;
}
2012-08-11 00:50:17 -05:00
else
m - > SetOrientation ( e . rot - > degrees * 10 ) ;
2012-06-06 20:49:43 -05:00
}
2012-06-04 23:39:37 -05:00
2012-06-06 20:49:43 -05:00
orientModuleText ( m , e , & m - > Reference ( ) , nameAttr ) ;
orientModuleText ( m , e , & m - > Value ( ) , valueAttr ) ;
}
2012-06-02 12:07:30 -05:00
2012-05-29 13:10:56 -05:00
2012-06-06 20:49:43 -05:00
void EAGLE_PLUGIN : : orientModuleText ( MODULE * m , const EELEMENT & e ,
TEXTE_MODULE * txt , const EATTR * aAttr )
{
2015-12-02 09:18:32 +01:00
// Smashed part ?
2012-06-06 20:49:43 -05:00
if ( aAttr )
2015-12-02 09:18:32 +01:00
{ // Yes
2012-06-06 20:49:43 -05:00
const EATTR & a = * aAttr ;
2012-05-29 13:10:56 -05:00
2012-06-06 20:49:43 -05:00
if ( a . value )
{
txt - > SetText ( FROM_UTF8 ( a . value - > c_str ( ) ) ) ;
}
2012-05-29 13:10:56 -05:00
2012-06-06 20:49:43 -05:00
if ( a . x & & a . y ) // boost::optional
{
wxPoint pos ( kicad_x ( * a . x ) , kicad_y ( * a . y ) ) ;
2017-01-23 14:30:11 -06:00
txt - > SetTextPos ( pos ) ;
2012-06-06 20:49:43 -05:00
}
2012-05-29 13:10:56 -05:00
2012-06-06 20:49:43 -05:00
// Even though size and ratio are both optional, I am not seeing
// a case where ratio is present but size is not.
double ratio = 8 ;
2017-01-23 14:30:11 -06:00
wxSize fontz = txt - > GetTextSize ( ) ;
2012-05-30 16:40:32 -05:00
2012-06-06 20:49:43 -05:00
if ( a . size )
{
fontz = kicad_fontz ( * a . size ) ;
2017-01-23 14:30:11 -06:00
txt - > SetTextSize ( fontz ) ;
2012-06-04 23:39:37 -05:00
2012-06-06 20:49:43 -05:00
if ( a . ratio )
ratio = * a . ratio ;
}
2012-06-01 02:39:32 -05:00
2017-10-17 10:18:54 +02:00
int lw = int ( fontz . y * ratio / 100 ) ;
2012-06-06 20:49:43 -05:00
txt - > SetThickness ( lw ) ;
2012-05-29 13:10:56 -05:00
2012-06-06 20:49:43 -05:00
int align = ETEXT : : BOTTOM_LEFT ; // bottom-left is eagle default
// The "rot" in a EATTR seems to be assumed to be zero if it is not
// present, and this zero rotation becomes an override to the
// package's text field. If they did not want zero, they specify
// what they want explicitly.
double degrees = a . rot ? a . rot - > degrees : 0 ;
double orient ; // relative to parent
int sign = 1 ;
bool spin = false ;
if ( a . rot )
{
spin = a . rot - > spin ;
sign = a . rot - > mirror ? - 1 : 1 ;
txt - > SetMirrored ( a . rot - > mirror ) ;
}
if ( degrees = = 90 | | degrees = = 0 | | spin )
{
orient = degrees - m - > GetOrientation ( ) / 10 ;
2017-01-23 14:30:11 -06:00
txt - > SetTextAngle ( sign * orient * 10 ) ;
2012-06-06 20:49:43 -05:00
}
else if ( degrees = = 180 )
{
orient = 0 - m - > GetOrientation ( ) / 10 ;
2017-01-23 14:30:11 -06:00
txt - > SetTextAngle ( sign * orient * 10 ) ;
2012-06-06 20:49:43 -05:00
align = ETEXT : : TOP_RIGHT ;
}
else if ( degrees = = 270 )
{
orient = 90 - m - > GetOrientation ( ) / 10 ;
align = ETEXT : : TOP_RIGHT ;
2017-01-23 14:30:11 -06:00
txt - > SetTextAngle ( sign * orient * 10 ) ;
2012-06-06 20:49:43 -05:00
}
2012-08-11 00:50:17 -05:00
else
{
2015-12-02 09:18:32 +01:00
orient = 90 - degrees - m - > GetOrientation ( ) / 10 ;
2017-01-23 14:30:11 -06:00
txt - > SetTextAngle ( sign * orient * 10 ) ;
2012-08-11 00:50:17 -05:00
}
2012-06-06 20:49:43 -05:00
switch ( align )
{
case ETEXT : : TOP_RIGHT :
txt - > SetHorizJustify ( GR_TEXT_HJUSTIFY_RIGHT ) ;
txt - > SetVertJustify ( GR_TEXT_VJUSTIFY_TOP ) ;
break ;
case ETEXT : : BOTTOM_LEFT :
txt - > SetHorizJustify ( GR_TEXT_HJUSTIFY_LEFT ) ;
txt - > SetVertJustify ( GR_TEXT_VJUSTIFY_BOTTOM ) ;
break ;
default :
;
2012-05-30 16:40:32 -05:00
}
}
2015-12-02 09:18:32 +01:00
else // Part is not smash so use Lib default for NAME/VALUE // the text is per the original package, sans <attribute>
2012-06-06 20:49:43 -05:00
{
2017-01-23 14:30:11 -06:00
double degrees = ( txt - > GetTextAngle ( ) + m - > GetOrientation ( ) ) / 10 ;
2012-06-06 20:49:43 -05:00
2012-08-11 00:50:17 -05:00
// @todo there are a few more cases than these to contend with:
2012-06-06 20:49:43 -05:00
if ( ( ! txt - > IsMirrored ( ) & & ( abs ( degrees ) = = 180 | | abs ( degrees ) = = 270 ) )
| | ( txt - > IsMirrored ( ) & & ( degrees = = 360 ) ) )
{
// ETEXT::TOP_RIGHT:
txt - > SetHorizJustify ( GR_TEXT_HJUSTIFY_RIGHT ) ;
txt - > SetVertJustify ( GR_TEXT_VJUSTIFY_TOP ) ;
}
}
2012-05-30 16:40:32 -05:00
}
2012-05-29 13:10:56 -05:00
2017-04-07 13:40:34 +02:00
MODULE * EAGLE_PLUGIN : : makeModule ( wxXmlNode * aPackage , const string & aPkgName ) const
2012-05-20 08:14:46 -05:00
{
2016-05-29 17:02:34 +02:00
std : : unique_ptr < MODULE > m ( new MODULE ( m_board ) ) ;
2012-05-20 08:14:46 -05:00
2017-07-25 14:14:31 -05:00
m - > SetFPID ( LIB_ID ( UTF8 ( aPkgName ) ) ) ;
2012-05-20 08:14:46 -05:00
2017-04-07 13:40:34 +02:00
// Get the first package item and iterate
wxXmlNode * packageItem = aPackage - > GetChildren ( ) ;
2012-05-20 08:14:46 -05:00
2017-04-07 13:40:34 +02:00
while ( packageItem )
2012-05-20 08:14:46 -05:00
{
2017-04-07 13:40:34 +02:00
const wxString & itemName = packageItem - > GetName ( ) ;
if ( itemName = = " description " )
m - > SetDescription ( FROM_UTF8 ( packageItem - > GetNodeContent ( ) . c_str ( ) ) ) ;
2012-05-20 08:14:46 -05:00
2017-04-07 13:40:34 +02:00
else if ( itemName = = " wire " )
packageWire ( m . get ( ) , packageItem ) ;
2012-05-20 08:14:46 -05:00
2017-04-07 13:40:34 +02:00
else if ( itemName = = " pad " )
packagePad ( m . get ( ) , packageItem ) ;
2012-05-20 08:14:46 -05:00
2017-04-07 13:40:34 +02:00
else if ( itemName = = " text " )
packageText ( m . get ( ) , packageItem ) ;
2012-05-20 08:14:46 -05:00
2017-04-07 13:40:34 +02:00
else if ( itemName = = " rectangle " )
packageRectangle ( m . get ( ) , packageItem ) ;
2012-05-15 21:27:27 -05:00
2017-04-07 13:40:34 +02:00
else if ( itemName = = " polygon " )
packagePolygon ( m . get ( ) , packageItem ) ;
2012-05-20 08:14:46 -05:00
2017-04-07 13:40:34 +02:00
else if ( itemName = = " circle " )
packageCircle ( m . get ( ) , packageItem ) ;
2012-05-20 08:14:46 -05:00
2017-04-07 13:40:34 +02:00
else if ( itemName = = " hole " )
packageHole ( m . get ( ) , packageItem ) ;
2012-05-20 08:14:46 -05:00
2017-04-07 13:40:34 +02:00
else if ( itemName = = " smd " )
packageSMD ( m . get ( ) , packageItem ) ;
packageItem = packageItem - > GetNext ( ) ;
2012-05-20 08:14:46 -05:00
}
return m . release ( ) ;
}
2017-04-07 13:40:34 +02:00
void EAGLE_PLUGIN : : packageWire ( MODULE * aModule , wxXmlNode * aTree ) const
2012-05-20 08:14:46 -05:00
{
2017-03-12 23:19:33 -04:00
EWIRE w ( aTree ) ;
PCB_LAYER_ID layer = kicad_layer ( w . layer ) ;
2012-05-22 12:51:18 -05:00
2017-10-11 23:24:14 +11:00
if ( IsCopperLayer ( layer ) ) // skip copper "package.circle"s
2012-05-23 20:18:30 -05:00
{
2017-10-17 10:18:54 +02:00
wxLogMessage ( wxString : : Format (
" Line on copper layer in package %s ( %d, %d ) ( %d, %d ) \n Moving to drawings layer " ,
aModule - > GetFPID ( ) . GetLibItemName ( ) . c_str ( ) , w . x1 . ToPcbUnits ( ) , w . y1 . ToPcbUnits ( ) ,
w . x2 . ToPcbUnits ( ) , w . y2 . ToPcbUnits ( ) ) ) ;
2017-10-11 23:24:14 +11:00
layer = Dwgs_User ;
}
2012-05-20 08:14:46 -05:00
2017-10-11 23:24:14 +11:00
wxPoint start ( kicad_x ( w . x1 ) , kicad_y ( w . y1 ) ) ;
wxPoint end ( kicad_x ( w . x2 ) , kicad_y ( w . y2 ) ) ;
2017-10-17 10:18:54 +02:00
int width = w . width . ToPcbUnits ( ) ;
2014-12-07 12:07:05 -05:00
2017-10-11 23:24:14 +11:00
// FIXME: the cap attribute is ignored because kicad can't create lines
// with flat ends.
EDGE_MODULE * dwg ;
if ( ! w . curve )
{
dwg = new EDGE_MODULE ( aModule , S_SEGMENT ) ;
2012-05-30 16:40:32 -05:00
2017-10-11 23:24:14 +11:00
dwg - > SetStart0 ( start ) ;
dwg - > SetEnd0 ( end ) ;
}
else
{
dwg = new EDGE_MODULE ( aModule , S_ARC ) ;
wxPoint center = ConvertArcCenter ( start , end , * w . curve ) ;
2014-12-07 12:07:05 -05:00
2017-10-11 23:24:14 +11:00
dwg - > SetStart0 ( center ) ;
dwg - > SetEnd0 ( start ) ;
dwg - > SetAngle ( * w . curve * - 10.0 ) ; // KiCad rotates the other way
2012-05-23 20:18:30 -05:00
}
2017-10-11 23:24:14 +11:00
dwg - > SetLayer ( layer ) ;
dwg - > SetWidth ( width ) ;
dwg - > SetDrawCoord ( ) ;
aModule - > GraphicalItemsList ( ) . PushBack ( dwg ) ;
2012-05-20 08:14:46 -05:00
}
2017-04-07 13:40:34 +02:00
void EAGLE_PLUGIN : : packagePad ( MODULE * aModule , wxXmlNode * aTree ) const
2012-05-20 08:14:46 -05:00
{
2012-05-29 13:10:56 -05:00
// this is thru hole technology here, no SMDs
2012-05-30 16:40:32 -05:00
EPAD e ( aTree ) ;
2012-05-22 12:51:18 -05:00
D_PAD * pad = new D_PAD ( aModule ) ;
2017-04-25 11:06:24 +02:00
aModule - > PadsList ( ) . PushBack ( pad ) ;
2012-05-22 12:51:18 -05:00
2017-08-11 11:22:13 +02:00
pad - > SetName ( FROM_UTF8 ( e . name . c_str ( ) ) ) ;
2012-05-22 12:51:18 -05:00
// pad's "Position" is not relative to the module's,
// whereas Pos0 is relative to the module's but is the unrotated coordinate.
2012-05-29 13:10:56 -05:00
wxPoint padpos ( kicad_x ( e . x ) , kicad_y ( e . y ) ) ;
2012-05-22 12:51:18 -05:00
pad - > SetPos0 ( padpos ) ;
RotatePoint ( & padpos , aModule - > GetOrientation ( ) ) ;
pad - > SetPosition ( padpos + aModule - > GetPosition ( ) ) ;
2017-10-17 10:18:54 +02:00
pad - > SetDrillSize ( wxSize ( e . drill . ToPcbUnits ( ) , e . drill . ToPcbUnits ( ) ) ) ;
2014-06-24 11:17:18 -05:00
pad - > SetLayerSet ( LSET : : AllCuMask ( ) . set ( B_Mask ) . set ( F_Mask ) ) ;
2012-05-22 12:51:18 -05:00
2012-05-31 10:18:55 -05:00
if ( e . shape )
{
switch ( * e . shape )
{
case EPAD : : ROUND :
2015-08-23 21:40:33 +02:00
wxASSERT ( pad - > GetShape ( ) = = PAD_SHAPE_CIRCLE ) ; // verify set in D_PAD constructor
2012-05-31 10:18:55 -05:00
break ;
2015-12-02 09:18:32 +01:00
2012-05-31 10:18:55 -05:00
case EPAD : : OCTAGON :
// no KiCad octagonal pad shape, use PAD_CIRCLE for now.
// pad->SetShape( PAD_OCTAGON );
2015-08-23 21:40:33 +02:00
wxASSERT ( pad - > GetShape ( ) = = PAD_SHAPE_CIRCLE ) ; // verify set in D_PAD constructor
2012-05-31 10:18:55 -05:00
break ;
2015-12-02 09:18:32 +01:00
2012-05-31 10:18:55 -05:00
case EPAD : : LONG :
2015-08-23 21:40:33 +02:00
pad - > SetShape ( PAD_SHAPE_OVAL ) ;
2012-05-31 10:18:55 -05:00
break ;
2015-12-02 09:18:32 +01:00
2012-05-31 10:18:55 -05:00
case EPAD : : SQUARE :
2015-08-23 21:40:33 +02:00
pad - > SetShape ( PAD_SHAPE_RECT ) ;
2012-05-31 10:18:55 -05:00
break ;
2015-12-02 09:18:32 +01:00
2012-05-31 10:18:55 -05:00
case EPAD : : OFFSET :
; // don't know what to do here.
}
}
else
{
// if shape is not present, our default is circle and that matches their default "round"
}
2012-05-29 13:10:56 -05:00
if ( e . diameter )
{
2017-10-17 10:18:54 +02:00
int diameter = e . diameter - > ToPcbUnits ( ) ;
2012-05-29 13:10:56 -05:00
pad - > SetSize ( wxSize ( diameter , diameter ) ) ;
}
else
2012-05-22 12:51:18 -05:00
{
2012-06-04 23:39:37 -05:00
double drillz = pad - > GetDrillSize ( ) . x ;
double annulus = drillz * m_rules - > rvPadTop ; // copper annulus, eagle "restring"
annulus = Clamp ( m_rules - > rlMinPadTop , annulus , m_rules - > rlMaxPadTop ) ;
int diameter = KiROUND ( drillz + 2 * annulus ) ;
pad - > SetSize ( wxSize ( KiROUND ( diameter ) , KiROUND ( diameter ) ) ) ;
2012-05-31 10:18:55 -05:00
}
2012-05-23 20:18:30 -05:00
2015-08-23 21:40:33 +02:00
if ( pad - > GetShape ( ) = = PAD_SHAPE_OVAL )
2012-05-31 10:18:55 -05:00
{
2012-06-04 23:39:37 -05:00
// The Eagle "long" pad is wider than it is tall,
// m_elongation is percent elongation
2012-05-31 10:18:55 -05:00
wxSize sz = pad - > GetSize ( ) ;
2012-06-04 23:39:37 -05:00
sz . x = ( sz . x * ( 100 + m_rules - > psElongationLong ) ) / 100 ;
2012-05-31 10:18:55 -05:00
pad - > SetSize ( sz ) ;
2012-05-22 12:51:18 -05:00
}
2012-05-31 10:18:55 -05:00
if ( e . rot )
2012-05-22 12:51:18 -05:00
{
2012-05-31 10:18:55 -05:00
pad - > SetOrientation ( e . rot - > degrees * 10 ) ;
2012-05-22 12:51:18 -05:00
}
2012-05-29 13:10:56 -05:00
// @todo: handle stop and thermal
2012-05-20 08:14:46 -05:00
}
2017-04-07 13:40:34 +02:00
void EAGLE_PLUGIN : : packageText ( MODULE * aModule , wxXmlNode * aTree ) const
2012-05-20 08:14:46 -05:00
{
2017-03-12 23:19:33 -04:00
ETEXT t ( aTree ) ;
PCB_LAYER_ID layer = kicad_layer ( t . layer ) ;
2013-11-03 20:09:28 -06:00
2017-10-11 23:24:14 +11:00
if ( IsCopperLayer ( layer ) ) // skip copper "package.circle"s
{
wxLogMessage ( wxString : : Format ( " Unsupported text on copper layer in package %s \n Moving to drawings layer. " , aModule - > GetFPID ( ) . GetLibItemName ( ) . c_str ( ) ) ) ;
layer = Dwgs_User ;
}
2013-11-03 20:09:28 -06:00
if ( layer = = UNDEFINED_LAYER )
{
2014-06-24 11:17:18 -05:00
layer = Cmts_User ;
2013-11-03 20:09:28 -06:00
}
2012-05-23 20:18:30 -05:00
TEXTE_MODULE * txt ;
2012-08-11 00:50:17 -05:00
if ( t . text = = " >NAME " | | t . text = = " >name " )
2012-05-23 20:18:30 -05:00
txt = & aModule - > Reference ( ) ;
2012-08-11 00:50:17 -05:00
else if ( t . text = = " >VALUE " | | t . text = = " >value " )
2012-05-23 20:18:30 -05:00
txt = & aModule - > Value ( ) ;
else
2012-05-30 16:40:32 -05:00
{
2015-10-04 12:56:59 -04:00
// FIXME: graphical text items are rotated for some reason.
2012-05-30 16:40:32 -05:00
txt = new TEXTE_MODULE ( aModule ) ;
2017-04-25 11:06:24 +02:00
aModule - > GraphicalItemsList ( ) . PushBack ( txt ) ;
2012-05-30 16:40:32 -05:00
}
2012-05-23 20:18:30 -05:00
2017-10-03 21:30:23 +11:00
txt - > SetTimeStamp ( EagleTimeStamp ( aTree ) ) ;
2012-05-23 20:18:30 -05:00
txt - > SetText ( FROM_UTF8 ( t . text . c_str ( ) ) ) ;
wxPoint pos ( kicad_x ( t . x ) , kicad_y ( t . y ) ) ;
2017-01-23 14:30:11 -06:00
txt - > SetTextPos ( pos ) ;
2012-05-23 20:18:30 -05:00
txt - > SetPos0 ( pos - aModule - > GetPosition ( ) ) ;
2012-05-30 16:40:32 -05:00
txt - > SetLayer ( layer ) ;
2017-01-23 14:30:11 -06:00
txt - > SetTextSize ( kicad_fontz ( t . size ) ) ;
2012-05-23 20:18:30 -05:00
2012-06-01 02:39:32 -05:00
double ratio = t . ratio ? * t . ratio : 8 ; // DTD says 8 is default
2012-05-23 20:18:30 -05:00
2017-10-17 10:18:54 +02:00
txt - > SetThickness ( t . size . ToPcbUnits ( ) * ratio / 100 ) ;
2012-05-23 20:18:30 -05:00
2012-06-06 20:49:43 -05:00
int align = t . align ? * t . align : ETEXT : : BOTTOM_LEFT ; // bottom-left is eagle default
2012-06-01 02:39:32 -05:00
// An eagle package is never rotated, the DTD does not allow it.
// angle -= aModule->GetOrienation();
if ( t . rot )
2012-05-23 20:18:30 -05:00
{
2012-06-06 20:49:43 -05:00
int sign = t . rot - > mirror ? - 1 : 1 ;
txt - > SetMirrored ( t . rot - > mirror ) ;
2012-05-23 20:18:30 -05:00
2012-06-06 20:49:43 -05:00
double degrees = t . rot - > degrees ;
2012-05-23 20:18:30 -05:00
2012-06-06 20:49:43 -05:00
if ( degrees = = 90 | | t . rot - > spin )
2017-01-23 14:30:11 -06:00
txt - > SetTextAngle ( sign * degrees * 10 ) ;
2012-06-06 20:49:43 -05:00
else if ( degrees = = 180 )
align = ETEXT : : TOP_RIGHT ;
else if ( degrees = = 270 )
{
align = ETEXT : : TOP_RIGHT ;
2017-01-23 14:30:11 -06:00
txt - > SetTextAngle ( sign * 90 * 10 ) ;
2012-06-06 20:49:43 -05:00
}
}
2012-05-23 20:18:30 -05:00
2012-06-06 20:49:43 -05:00
switch ( align )
2012-05-23 20:18:30 -05:00
{
case ETEXT : : CENTER :
// this was the default in pcbtxt's constructor
break ;
case ETEXT : : CENTER_LEFT :
txt - > SetHorizJustify ( GR_TEXT_HJUSTIFY_LEFT ) ;
break ;
case ETEXT : : CENTER_RIGHT :
txt - > SetHorizJustify ( GR_TEXT_HJUSTIFY_RIGHT ) ;
break ;
case ETEXT : : TOP_CENTER :
txt - > SetVertJustify ( GR_TEXT_VJUSTIFY_TOP ) ;
break ;
case ETEXT : : TOP_LEFT :
txt - > SetHorizJustify ( GR_TEXT_HJUSTIFY_LEFT ) ;
txt - > SetVertJustify ( GR_TEXT_VJUSTIFY_TOP ) ;
break ;
case ETEXT : : TOP_RIGHT :
txt - > SetHorizJustify ( GR_TEXT_HJUSTIFY_RIGHT ) ;
txt - > SetVertJustify ( GR_TEXT_VJUSTIFY_TOP ) ;
break ;
case ETEXT : : BOTTOM_CENTER :
txt - > SetVertJustify ( GR_TEXT_VJUSTIFY_BOTTOM ) ;
break ;
case ETEXT : : BOTTOM_LEFT :
txt - > SetHorizJustify ( GR_TEXT_HJUSTIFY_LEFT ) ;
txt - > SetVertJustify ( GR_TEXT_VJUSTIFY_BOTTOM ) ;
break ;
case ETEXT : : BOTTOM_RIGHT :
txt - > SetHorizJustify ( GR_TEXT_HJUSTIFY_RIGHT ) ;
txt - > SetVertJustify ( GR_TEXT_VJUSTIFY_BOTTOM ) ;
break ;
}
2012-05-20 08:14:46 -05:00
}
2017-04-07 13:40:34 +02:00
void EAGLE_PLUGIN : : packageRectangle ( MODULE * aModule , wxXmlNode * aTree ) const
2012-05-20 08:14:46 -05:00
{
2017-03-12 23:19:33 -04:00
ERECT r ( aTree ) ;
PCB_LAYER_ID layer = kicad_layer ( r . layer ) ;
2012-06-01 02:39:32 -05:00
2017-10-11 23:24:14 +11:00
// Rectangles are not supported yet in footprints as they are not editable.
2017-10-17 10:18:54 +02:00
wxLogMessage ( wxString : : Format ( " Unsupported rectangle in package %s (%d, %d) (%d, %d) " ,
aModule - > GetFPID ( ) . GetLibItemName ( ) . c_str ( ) , r . x1 . ToPcbUnits ( ) , r . y1 . ToPcbUnits ( ) ,
r . x2 . ToPcbUnits ( ) , r . y2 . ToPcbUnits ( ) ) ) ;
2017-10-11 23:24:14 +11:00
return ;
if ( IsCopperLayer ( layer ) ) // skip copper "package.circle"s
2012-06-01 02:39:32 -05:00
{
2017-10-11 23:24:14 +11:00
wxLogMessage ( wxString : : Format ( " Unsupported rectangle on copper layer in package %s \n Moving to drawings layer. " , aModule - > GetFPID ( ) . GetLibItemName ( ) . c_str ( ) ) ) ;
layer = Dwgs_User ;
}
2012-06-01 02:39:32 -05:00
2017-10-11 23:24:14 +11:00
EDGE_MODULE * dwg = new EDGE_MODULE ( aModule , S_POLYGON ) ;
aModule - > GraphicalItemsList ( ) . PushBack ( dwg ) ;
2012-06-01 02:39:32 -05:00
2017-10-11 23:24:14 +11:00
dwg - > SetLayer ( layer ) ;
dwg - > SetWidth ( 0 ) ;
2012-06-01 02:39:32 -05:00
2017-10-11 23:24:14 +11:00
dwg - > SetTimeStamp ( EagleTimeStamp ( aTree ) ) ;
2012-06-01 02:39:32 -05:00
2017-10-11 23:24:14 +11:00
std : : vector < wxPoint > pts ;
2012-06-01 02:39:32 -05:00
2017-10-11 23:24:14 +11:00
wxPoint start ( wxPoint ( kicad_x ( r . x1 ) , kicad_y ( r . y1 ) ) ) ;
wxPoint end ( wxPoint ( kicad_x ( r . x1 ) , kicad_y ( r . y2 ) ) ) ;
2012-06-01 02:39:32 -05:00
2017-10-11 23:24:14 +11:00
pts . push_back ( start ) ;
pts . push_back ( wxPoint ( kicad_x ( r . x2 ) , kicad_y ( r . y1 ) ) ) ;
pts . push_back ( wxPoint ( kicad_x ( r . x2 ) , kicad_y ( r . y2 ) ) ) ;
pts . push_back ( end ) ;
dwg - > SetPolyPoints ( pts ) ;
dwg - > SetStart0 ( start ) ;
dwg - > SetEnd0 ( end ) ;
2012-06-01 02:39:32 -05:00
2012-05-20 08:14:46 -05:00
}
2017-04-07 13:40:34 +02:00
void EAGLE_PLUGIN : : packagePolygon ( MODULE * aModule , wxXmlNode * aTree ) const
2012-05-20 08:14:46 -05:00
{
2012-06-01 02:39:32 -05:00
EPOLYGON p ( aTree ) ;
2017-03-12 23:19:33 -04:00
PCB_LAYER_ID layer = kicad_layer ( p . layer ) ;
2012-06-01 02:39:32 -05:00
2017-10-11 23:24:14 +11:00
if ( IsCopperLayer ( layer ) ) // skip copper "package.circle"s
2012-06-01 02:39:32 -05:00
{
2017-10-11 23:24:14 +11:00
wxLogMessage ( wxString : : Format ( " Unsupported polygon on copper layer in package %s \n Moving to drawings layer. " , aModule - > GetFPID ( ) . GetLibItemName ( ) . c_str ( ) ) ) ;
layer = Dwgs_User ;
}
2012-06-01 02:39:32 -05:00
2017-10-11 23:24:14 +11:00
EDGE_MODULE * dwg = new EDGE_MODULE ( aModule , S_POLYGON ) ;
aModule - > GraphicalItemsList ( ) . PushBack ( dwg ) ;
2012-06-01 02:39:32 -05:00
2017-10-11 23:24:14 +11:00
dwg - > SetWidth ( 0 ) ; // it's filled, no need for boundary width
2012-06-01 02:39:32 -05:00
2017-10-11 23:24:14 +11:00
dwg - > SetLayer ( layer ) ;
2012-06-01 02:39:32 -05:00
2017-10-11 23:24:14 +11:00
dwg - > SetTimeStamp ( EagleTimeStamp ( aTree ) ) ;
2017-10-03 21:30:23 +11:00
2017-10-11 23:24:14 +11:00
std : : vector < wxPoint > pts ;
// TODO: I think there's no way to know a priori the number of children in wxXmlNode :()
// pts.reserve( aTree.size() );
2012-06-01 02:39:32 -05:00
2017-10-11 23:24:14 +11:00
// Get the first vertex and iterate
wxXmlNode * vertex = aTree - > GetChildren ( ) ;
2012-06-01 02:39:32 -05:00
2017-10-11 23:24:14 +11:00
while ( vertex )
{
if ( vertex - > GetName ( ) ! = " vertex " ) // skip <xmlattr> node
continue ;
2017-04-07 13:40:34 +02:00
2017-10-11 23:24:14 +11:00
EVERTEX v ( vertex ) ;
2012-06-01 02:39:32 -05:00
2017-10-11 23:24:14 +11:00
pts . push_back ( wxPoint ( kicad_x ( v . x ) , kicad_y ( v . y ) ) ) ;
2012-06-01 02:39:32 -05:00
2017-10-11 23:24:14 +11:00
vertex = vertex - > GetNext ( ) ;
}
2017-04-07 13:40:34 +02:00
2017-10-11 23:24:14 +11:00
dwg - > SetPolyPoints ( pts ) ;
2012-06-01 02:39:32 -05:00
2017-10-11 23:24:14 +11:00
dwg - > SetStart0 ( * pts . begin ( ) ) ;
dwg - > SetEnd0 ( pts . back ( ) ) ;
dwg - > SetDrawCoord ( ) ;
2012-06-01 02:39:32 -05:00
2012-05-20 08:14:46 -05:00
}
2017-04-07 13:40:34 +02:00
void EAGLE_PLUGIN : : packageCircle ( MODULE * aModule , wxXmlNode * aTree ) const
2012-05-20 08:14:46 -05:00
{
2013-11-03 20:09:28 -06:00
ECIRCLE e ( aTree ) ;
2017-03-12 23:19:33 -04:00
PCB_LAYER_ID layer = kicad_layer ( e . layer ) ;
2017-10-11 23:24:14 +11:00
if ( IsCopperLayer ( layer ) ) // skip copper "package.circle"s
{
wxLogMessage ( wxString : : Format ( " Unsupported circle on copper layer in package %s \n Moving to drawings layer. " , aModule - > GetFPID ( ) . GetLibItemName ( ) . c_str ( ) ) ) ;
layer = Dwgs_User ;
}
2013-11-03 20:09:28 -06:00
EDGE_MODULE * gr = new EDGE_MODULE ( aModule , S_CIRCLE ) ;
2012-05-30 16:40:32 -05:00
2017-04-25 11:06:24 +02:00
aModule - > GraphicalItemsList ( ) . PushBack ( gr ) ;
2012-05-30 16:40:32 -05:00
2017-10-17 10:18:54 +02:00
gr - > SetWidth ( e . width . ToPcbUnits ( ) ) ;
2012-05-30 16:40:32 -05:00
2014-06-24 11:17:18 -05:00
switch ( ( int ) layer )
2012-05-30 16:40:32 -05:00
{
2014-06-24 11:17:18 -05:00
case UNDEFINED_LAYER : layer = Cmts_User ; break ;
2013-11-03 20:09:28 -06:00
/*
2014-06-24 11:17:18 -05:00
case Eco1_User : layer = F_SilkS ; break ;
case Eco2_User : layer = B_SilkS ; break ;
2012-06-01 02:39:32 -05:00
*/
2014-05-04 19:08:36 +02:00
default :
break ;
2013-11-03 20:09:28 -06:00
}
2012-05-30 16:40:32 -05:00
gr - > SetLayer ( layer ) ;
2017-10-03 21:30:23 +11:00
gr - > SetTimeStamp ( EagleTimeStamp ( aTree ) ) ;
2012-05-30 16:40:32 -05:00
gr - > SetStart0 ( wxPoint ( kicad_x ( e . x ) , kicad_y ( e . y ) ) ) ;
gr - > SetEnd0 ( wxPoint ( kicad_x ( e . x + e . radius ) , kicad_y ( e . y ) ) ) ;
2017-10-11 23:24:14 +11:00
gr - > SetDrawCoord ( ) ;
2012-05-20 08:14:46 -05:00
}
2017-04-07 13:40:34 +02:00
void EAGLE_PLUGIN : : packageHole ( MODULE * aModule , wxXmlNode * aTree ) const
2012-05-20 08:14:46 -05:00
{
2012-05-31 10:18:55 -05:00
EHOLE e ( aTree ) ;
2015-08-23 21:40:33 +02:00
// we add a PAD_ATTRIB_HOLE_NOT_PLATED pad to this module.
2012-05-31 10:18:55 -05:00
D_PAD * pad = new D_PAD ( aModule ) ;
2017-04-25 11:06:24 +02:00
aModule - > PadsList ( ) . PushBack ( pad ) ;
2012-05-31 10:18:55 -05:00
2015-08-23 21:40:33 +02:00
pad - > SetShape ( PAD_SHAPE_CIRCLE ) ;
pad - > SetAttribute ( PAD_ATTRIB_HOLE_NOT_PLATED ) ;
2012-05-31 10:18:55 -05:00
// Mechanical purpose only:
// no offset, no net name, no pad name allowed
// pad->SetOffset( wxPoint( 0, 0 ) );
2017-08-11 11:22:13 +02:00
// pad->SetName( wxEmptyString );
2012-05-31 10:18:55 -05:00
wxPoint padpos ( kicad_x ( e . x ) , kicad_y ( e . y ) ) ;
pad - > SetPos0 ( padpos ) ;
pad - > SetPosition ( padpos + aModule - > GetPosition ( ) ) ;
2017-10-17 10:18:54 +02:00
wxSize sz ( e . drill . ToPcbUnits ( ) , e . drill . ToPcbUnits ( ) ) ;
2012-05-31 10:18:55 -05:00
pad - > SetDrillSize ( sz ) ;
pad - > SetSize ( sz ) ;
2014-06-24 11:17:18 -05:00
pad - > SetLayerSet ( LSET : : AllCuMask ( ) /* | SOLDERMASK_LAYER_BACK | SOLDERMASK_LAYER_FRONT */ ) ;
2012-05-20 08:14:46 -05:00
}
2017-04-07 13:40:34 +02:00
void EAGLE_PLUGIN : : packageSMD ( MODULE * aModule , wxXmlNode * aTree ) const
2012-05-20 08:14:46 -05:00
{
2017-03-12 23:19:33 -04:00
ESMD e ( aTree ) ;
PCB_LAYER_ID layer = kicad_layer ( e . layer ) ;
2012-05-22 12:51:18 -05:00
2013-04-09 18:00:46 +02:00
if ( ! IsCopperLayer ( layer ) )
2012-05-24 10:00:59 -05:00
{
return ;
}
D_PAD * pad = new D_PAD ( aModule ) ;
2017-04-25 11:06:24 +02:00
aModule - > PadsList ( ) . PushBack ( pad ) ;
2012-05-24 10:00:59 -05:00
2017-08-11 11:22:13 +02:00
pad - > SetName ( FROM_UTF8 ( e . name . c_str ( ) ) ) ;
2015-08-23 21:40:33 +02:00
pad - > SetShape ( PAD_SHAPE_RECT ) ;
pad - > SetAttribute ( PAD_ATTRIB_SMD ) ;
2012-05-24 10:00:59 -05:00
2012-05-22 12:51:18 -05:00
// pad's "Position" is not relative to the module's,
// whereas Pos0 is relative to the module's but is the unrotated coordinate.
2012-05-29 13:10:56 -05:00
wxPoint padpos ( kicad_x ( e . x ) , kicad_y ( e . y ) ) ;
2012-05-22 12:51:18 -05:00
pad - > SetPos0 ( padpos ) ;
RotatePoint ( & padpos , aModule - > GetOrientation ( ) ) ;
pad - > SetPosition ( padpos + aModule - > GetPosition ( ) ) ;
2017-10-17 10:18:54 +02:00
pad - > SetSize ( wxSize ( e . dx . ToPcbUnits ( ) , e . dy . ToPcbUnits ( ) ) ) ;
2012-05-22 12:51:18 -05:00
2012-05-29 13:10:56 -05:00
pad - > SetLayer ( layer ) ;
2012-06-04 23:39:37 -05:00
2014-06-24 11:17:18 -05:00
static const LSET front ( 3 , F_Cu , F_Paste , F_Mask ) ;
static const LSET back ( 3 , B_Cu , B_Paste , B_Mask ) ;
if ( layer = = F_Cu )
pad - > SetLayerSet ( front ) ;
else if ( layer = = B_Cu )
pad - > SetLayerSet ( back ) ;
2012-05-22 12:51:18 -05:00
2012-05-23 20:18:30 -05:00
// Optional according to DTD
2015-08-23 21:40:33 +02:00
if ( e . roundness ) // set set shape to PAD_SHAPE_RECT above, in case roundness is not present
2012-05-22 12:51:18 -05:00
{
2012-05-29 13:10:56 -05:00
if ( * e . roundness > = 75 ) // roundness goes from 0-100% as integer
2012-05-22 12:51:18 -05:00
{
2012-05-29 13:10:56 -05:00
if ( e . dy = = e . dx )
2015-08-23 21:40:33 +02:00
pad - > SetShape ( PAD_SHAPE_CIRCLE ) ;
2012-05-22 12:51:18 -05:00
else
2015-08-23 21:40:33 +02:00
pad - > SetShape ( PAD_SHAPE_OVAL ) ;
2012-05-22 12:51:18 -05:00
}
}
2012-05-31 10:18:55 -05:00
if ( e . rot )
2012-05-22 12:51:18 -05:00
{
2012-05-31 10:18:55 -05:00
pad - > SetOrientation ( e . rot - > degrees * 10 ) ;
2012-05-22 12:51:18 -05:00
}
// don't know what stop, thermals, and cream should look like now.
2012-05-20 08:14:46 -05:00
}
2017-07-10 11:44:56 +02:00
void EAGLE_PLUGIN : : deleteTemplates ( )
{
for ( auto & t : m_templates )
delete t . second ;
m_templates . clear ( ) ;
}
2013-03-14 17:54:47 -05:00
/// non-owning container
typedef std : : vector < ZONE_CONTAINER * > ZONES ;
2012-05-20 08:14:46 -05:00
2017-04-07 13:40:34 +02:00
void EAGLE_PLUGIN : : loadSignals ( wxXmlNode * aSignals )
2012-05-20 08:14:46 -05:00
{
2013-03-14 17:54:47 -05:00
ZONES zones ; // per net
2012-06-02 12:07:30 -05:00
m_xpath - > push ( " signals.signal " , " name " ) ;
2012-05-20 08:14:46 -05:00
int netCode = 1 ;
2017-04-07 13:40:34 +02:00
// Get the first signal and iterate
wxXmlNode * net = aSignals - > GetChildren ( ) ;
while ( net )
2012-05-20 08:14:46 -05:00
{
2013-03-14 17:54:47 -05:00
bool sawPad = false ;
zones . clear ( ) ;
2017-04-07 13:40:34 +02:00
const string & nname = net - > GetAttribute ( " name " ) . ToStdString ( ) ;
2012-05-24 10:00:59 -05:00
wxString netName = FROM_UTF8 ( nname . c_str ( ) ) ;
2016-09-05 12:22:24 +02:00
m_board - > Add ( new NETINFO_ITEM ( m_board , netName , netCode ) ) ;
2012-05-20 08:14:46 -05:00
2012-06-02 12:07:30 -05:00
m_xpath - > Value ( nname . c_str ( ) ) ;
2017-04-07 13:40:34 +02:00
// Get the first net item and iterate
wxXmlNode * netItem = net - > GetChildren ( ) ;
2012-05-23 20:18:30 -05:00
// (contactref | polygon | wire | via)*
2017-04-07 13:40:34 +02:00
while ( netItem )
2012-05-20 08:14:46 -05:00
{
2017-04-07 13:40:34 +02:00
const wxString & itemName = netItem - > GetName ( ) ;
if ( itemName = = " wire " )
2012-05-23 20:18:30 -05:00
{
2012-06-02 12:07:30 -05:00
m_xpath - > push ( " wire " ) ;
2017-04-07 13:40:34 +02:00
EWIRE w ( netItem ) ;
2017-03-12 23:19:33 -04:00
PCB_LAYER_ID layer = kicad_layer ( w . layer ) ;
2012-05-23 20:18:30 -05:00
2013-04-09 18:00:46 +02:00
if ( IsCopperLayer ( layer ) )
2012-05-24 10:00:59 -05:00
{
TRACK * t = new TRACK ( m_board ) ;
2012-05-23 20:18:30 -05:00
2017-10-03 21:30:23 +11:00
t - > SetTimeStamp ( EagleTimeStamp ( netItem ) ) ;
2012-05-23 20:18:30 -05:00
2012-05-24 10:00:59 -05:00
t - > SetPosition ( wxPoint ( kicad_x ( w . x1 ) , kicad_y ( w . y1 ) ) ) ;
t - > SetEnd ( wxPoint ( kicad_x ( w . x2 ) , kicad_y ( w . y2 ) ) ) ;
2012-05-23 20:18:30 -05:00
2017-10-17 10:18:54 +02:00
int width = w . width . ToPcbUnits ( ) ;
2013-03-14 17:54:47 -05:00
if ( width < m_min_trace )
m_min_trace = width ;
t - > SetWidth ( width ) ;
2012-05-24 10:00:59 -05:00
t - > SetLayer ( layer ) ;
2014-02-25 11:40:34 +01:00
t - > SetNetCode ( netCode ) ;
2012-05-24 10:00:59 -05:00
m_board - > m_Track . Insert ( t , NULL ) ;
}
else
{
// put non copper wires where the sun don't shine.
}
2012-06-02 12:07:30 -05:00
m_xpath - > pop ( ) ;
2012-05-23 20:18:30 -05:00
}
2012-05-20 08:14:46 -05:00
2017-04-07 13:40:34 +02:00
else if ( itemName = = " via " )
2012-05-23 20:18:30 -05:00
{
2012-06-02 12:07:30 -05:00
m_xpath - > push ( " via " ) ;
2017-04-07 13:40:34 +02:00
EVIA v ( netItem ) ;
2012-05-23 20:18:30 -05:00
2017-03-12 23:19:33 -04:00
PCB_LAYER_ID layer_front_most = kicad_layer ( v . layer_front_most ) ;
PCB_LAYER_ID layer_back_most = kicad_layer ( v . layer_back_most ) ;
2012-05-23 20:18:30 -05:00
2013-04-09 18:00:46 +02:00
if ( IsCopperLayer ( layer_front_most ) & &
IsCopperLayer ( layer_back_most ) )
2012-05-24 10:00:59 -05:00
{
2014-04-25 08:00:04 +02:00
int kidiam ;
2017-10-17 10:18:54 +02:00
int drillz = v . drill . ToPcbUnits ( ) ;
2014-04-25 08:00:04 +02:00
VIA * via = new VIA ( m_board ) ;
2012-05-30 16:40:32 -05:00
m_board - > m_Track . Insert ( via , NULL ) ;
2012-05-23 20:18:30 -05:00
2012-06-01 02:39:32 -05:00
via - > SetLayerPair ( layer_front_most , layer_back_most ) ;
2012-05-24 10:00:59 -05:00
if ( v . diam )
{
2017-10-17 10:18:54 +02:00
kidiam = v . diam - > ToPcbUnits ( ) ;
2012-05-24 10:00:59 -05:00
via - > SetWidth ( kidiam ) ;
}
else
2012-05-30 16:40:32 -05:00
{
2012-06-04 23:39:37 -05:00
double annulus = drillz * m_rules - > rvViaOuter ; // eagle "restring"
annulus = Clamp ( m_rules - > rlMinViaOuter , annulus , m_rules - > rlMaxViaOuter ) ;
2013-03-14 17:54:47 -05:00
kidiam = KiROUND ( drillz + 2 * annulus ) ;
via - > SetWidth ( kidiam ) ;
2012-05-30 16:40:32 -05:00
}
2012-05-23 20:18:30 -05:00
2012-05-30 16:40:32 -05:00
via - > SetDrill ( drillz ) ;
2012-05-23 20:18:30 -05:00
2017-06-23 13:56:28 +02:00
// make sure the via diameter respects the restring rules
2017-05-04 15:47:28 +02:00
if ( ! v . diam | | via - > GetWidth ( ) < = via - > GetDrill ( ) )
{
2017-06-23 13:56:28 +02:00
double annulus = Clamp ( m_rules - > rlMinViaOuter ,
( double ) ( via - > GetWidth ( ) / 2 - via - > GetDrill ( ) ) , m_rules - > rlMaxViaOuter ) ;
2017-05-04 15:47:28 +02:00
via - > SetWidth ( drillz + 2 * annulus ) ;
}
2017-06-23 13:56:28 +02:00
2013-03-14 17:54:47 -05:00
if ( kidiam < m_min_via )
m_min_via = kidiam ;
if ( drillz < m_min_via_hole )
m_min_via_hole = drillz ;
2014-06-24 11:17:18 -05:00
if ( layer_front_most = = F_Cu & & layer_back_most = = B_Cu )
2014-04-25 08:00:04 +02:00
via - > SetViaType ( VIA_THROUGH ) ;
2014-06-24 11:17:18 -05:00
else if ( layer_front_most = = F_Cu | | layer_back_most = = B_Cu )
2014-04-25 08:00:04 +02:00
via - > SetViaType ( VIA_MICROVIA ) ;
2012-06-01 02:39:32 -05:00
else
2014-04-25 08:00:04 +02:00
via - > SetViaType ( VIA_BLIND_BURIED ) ;
2012-06-01 02:39:32 -05:00
2017-10-03 21:30:23 +11:00
via - > SetTimeStamp ( EagleTimeStamp ( netItem ) ) ;
2012-05-20 08:14:46 -05:00
2012-05-24 10:00:59 -05:00
wxPoint pos ( kicad_x ( v . x ) , kicad_y ( v . y ) ) ;
2012-05-20 08:14:46 -05:00
2012-05-24 10:00:59 -05:00
via - > SetPosition ( pos ) ;
via - > SetEnd ( pos ) ;
2012-05-20 08:14:46 -05:00
2014-02-25 11:40:34 +01:00
via - > SetNetCode ( netCode ) ;
2012-05-24 10:00:59 -05:00
}
2017-06-23 13:56:28 +02:00
2012-06-02 12:07:30 -05:00
m_xpath - > pop ( ) ;
2012-05-23 20:18:30 -05:00
}
2017-04-07 13:40:34 +02:00
else if ( itemName = = " contactref " )
2012-05-23 20:18:30 -05:00
{
2012-06-02 12:07:30 -05:00
m_xpath - > push ( " contactref " ) ;
2012-05-24 10:00:59 -05:00
// <contactref element="RN1" pad="7"/>
2017-04-07 13:40:34 +02:00
const string & reference = netItem - > GetAttribute ( " element " ) . ToStdString ( ) ;
const string & pad = netItem - > GetAttribute ( " pad " ) . ToStdString ( ) ;
2012-05-24 10:00:59 -05:00
2013-11-06 10:53:44 -06:00
string key = makeKey ( reference , pad ) ;
2012-05-24 10:00:59 -05:00
2012-05-29 13:10:56 -05:00
// D(printf( "adding refname:'%s' pad:'%s' netcode:%d netname:'%s'\n", reference.c_str(), pad.c_str(), netCode, nname.c_str() );)
2012-05-24 10:00:59 -05:00
m_pads_to_nets [ key ] = ENET ( netCode , nname ) ;
2012-06-02 12:07:30 -05:00
m_xpath - > pop ( ) ;
2013-03-14 17:54:47 -05:00
sawPad = true ;
2012-05-23 20:18:30 -05:00
}
2017-04-07 13:40:34 +02:00
else if ( itemName = = " polygon " )
2012-05-23 20:18:30 -05:00
{
2012-06-02 12:07:30 -05:00
m_xpath - > push ( " polygon " ) ;
2013-11-03 20:09:28 -06:00
2017-04-07 13:40:34 +02:00
EPOLYGON p ( netItem ) ;
2017-03-12 23:19:33 -04:00
PCB_LAYER_ID layer = kicad_layer ( p . layer ) ;
2012-05-29 13:10:56 -05:00
2013-04-09 18:00:46 +02:00
if ( IsCopperLayer ( layer ) )
2012-05-29 13:10:56 -05:00
{
// use a "netcode = 0" type ZONE:
ZONE_CONTAINER * zone = new ZONE_CONTAINER ( m_board ) ;
m_board - > Add ( zone , ADD_APPEND ) ;
2013-03-14 17:54:47 -05:00
zones . push_back ( zone ) ;
2012-05-29 13:10:56 -05:00
2017-10-03 21:30:23 +11:00
zone - > SetTimeStamp ( EagleTimeStamp ( netItem ) ) ;
2012-05-29 13:10:56 -05:00
zone - > SetLayer ( layer ) ;
2014-02-25 11:40:34 +01:00
zone - > SetNetCode ( netCode ) ;
2012-05-29 13:10:56 -05:00
2017-04-07 13:40:34 +02:00
// Get the first vertex and iterate
wxXmlNode * vertex = netItem - > GetChildren ( ) ;
while ( vertex )
2012-05-29 13:10:56 -05:00
{
2017-04-07 13:40:34 +02:00
if ( vertex - > GetName ( ) ! = " vertex " ) // skip <xmlattr> node
2012-05-29 13:10:56 -05:00
continue ;
2017-04-07 13:40:34 +02:00
EVERTEX v ( vertex ) ;
2012-05-29 13:10:56 -05:00
2017-03-07 13:06:00 +01:00
// Append the corner
2017-06-19 13:29:57 +02:00
zone - > AppendCorner ( wxPoint ( kicad_x ( v . x ) , kicad_y ( v . y ) ) , - 1 ) ;
2017-04-07 13:40:34 +02:00
vertex = vertex - > GetNext ( ) ;
2012-05-29 13:10:56 -05:00
}
2015-11-15 08:29:48 -05:00
// If the pour is a cutout it needs to be set to a keepout
if ( p . pour = = EPOLYGON : : CUTOUT )
2015-10-04 12:56:59 -04:00
{
2015-11-15 08:29:48 -05:00
zone - > SetIsKeepout ( true ) ;
zone - > SetDoNotAllowCopperPour ( true ) ;
2017-03-07 13:06:00 +01:00
zone - > SetHatchStyle ( ZONE_CONTAINER : : NO_HATCH ) ;
2015-11-15 08:29:48 -05:00
}
// if spacing is set the zone should be hatched
2017-07-01 15:16:51 +02:00
// However, use the default hatch step, p.spacing value has no meaning for Kicad
// TODO: see if this parameter is related to a grid fill option.
2015-11-15 08:29:48 -05:00
if ( p . spacing )
2017-07-01 15:16:51 +02:00
zone - > SetHatch ( ZONE_CONTAINER : : DIAGONAL_EDGE , zone - > GetDefaultHatchPitch ( ) , true ) ;
2012-06-01 02:39:32 -05:00
// clearances, etc.
2013-03-18 15:36:07 -04:00
zone - > SetArcSegmentCount ( 32 ) ; // @todo: should be a constructor default?
2017-10-17 10:18:54 +02:00
zone - > SetMinThickness ( p . width . ToPcbUnits ( ) ) ;
2012-06-01 02:39:32 -05:00
2015-10-04 12:56:59 -04:00
// FIXME: KiCad zones have very rounded corners compared to eagle.
// This means that isolation amounts that work well in eagle
// tend to make copper intrude in soldermask free areas around pads.
if ( p . isolate )
{
2017-10-17 10:18:54 +02:00
zone - > SetZoneClearance ( p . isolate - > ToPcbUnits ( ) ) ;
2017-07-01 15:16:51 +02:00
} else
{
2017-05-04 15:47:28 +02:00
zone - > SetZoneClearance ( 0 ) ;
2015-10-04 12:56:59 -04:00
}
2012-06-01 02:39:32 -05:00
// missing == yes per DTD.
bool thermals = ! p . thermals | | * p . thermals ;
2015-08-18 16:19:17 +02:00
zone - > SetPadConnection ( thermals ? PAD_ZONE_CONN_THERMAL : PAD_ZONE_CONN_FULL ) ;
2015-10-04 12:56:59 -04:00
if ( thermals )
{
// FIXME: eagle calculates dimensions for thermal spokes
// based on what the zone is connecting to.
// (i.e. width of spoke is half of the smaller side of an smd pad)
// This is a basic workaround
2017-10-17 10:18:54 +02:00
zone - > SetThermalReliefGap ( p . width . ToPcbUnits ( ) + 50000 ) ; // 50000nm == 0.05mm
zone - > SetThermalReliefCopperBridge ( p . width . ToPcbUnits ( ) + 50000 ) ;
2015-10-04 12:56:59 -04:00
}
2012-06-01 02:39:32 -05:00
2017-05-04 15:47:28 +02:00
int rank = p . rank ? ( p . max_priority - * p . rank ) : p . max_priority ;
2012-06-01 02:39:32 -05:00
zone - > SetPriority ( rank ) ;
2012-05-29 13:10:56 -05:00
}
2012-06-02 12:07:30 -05:00
m_xpath - > pop ( ) ; // "polygon"
2012-05-23 20:18:30 -05:00
}
2017-04-07 13:40:34 +02:00
netItem = netItem - > GetNext ( ) ;
2012-05-20 08:14:46 -05:00
}
2013-03-14 17:54:47 -05:00
if ( zones . size ( ) & & ! sawPad )
{
// KiCad does not support an unconnected zone with its own non-zero netcode,
// but only when assigned netcode = 0 w/o a name...
for ( ZONES : : iterator it = zones . begin ( ) ; it ! = zones . end ( ) ; + + it )
2014-02-25 11:40:34 +01:00
( * it ) - > SetNetCode ( NETINFO_LIST : : UNCONNECTED ) ;
2013-03-14 17:54:47 -05:00
// therefore omit this signal/net.
}
else
BOARD_CONNECTED_ITEMs do not store net code anymore (m_NetCode field), instead net info is stored using a pointer to NETINFO_ITEM.
GetNet() refers to the net code stored in the NETINFO_ITEM. SetNet() finds an appropriate NETINFO_ITEM and uses it.
Removing GetNet() & SetNet() (and the whole net code idea) requires too many changes in the code (~250 references to the mentioned functions).
BOARD_CONNECTED_ITEMs by default get a pointer to NETINFO_ITEM that stores unconnected items. This requires for all BOARD_CONNECTED_ITEMs to have a parent (so BOARD* is accessible). The only orphaned item is BOARD_DESIGN_SETTINGS::m_Pad_Master, but it does not cause any issues so far.
Items that do not have access to a BOARD (do not have set parents) and therefore cannot get net assigned, by default get const static NETINFO_LIST::ORPHANED.
Performed tests:
- loaded .kicad_pcb, KiCad legacy board, Eagle 6.0 board, P-CAD board - all ok
- load a simple project, reload netlist after changing connections in eeschema - ok
- save & reload a board - ok, but still contain empty nets
- remove everything, restore with undo - ok
- remove everything, reload netlist - ok
- changing net names (all possibilites: empty->existing, empty->not existing, existing->empty, existing->not existing) - all ok
- zones: when net is changed to a net that does not have any nodes besides the zone itself, it does not get filled
2014-01-15 18:03:06 +01:00
netCode + + ;
2017-04-07 13:40:34 +02:00
// Get next signal
net = net - > GetNext ( ) ;
2012-05-15 21:27:27 -05:00
}
2012-06-02 12:07:30 -05:00
m_xpath - > pop ( ) ; // "signals.signal"
2012-05-20 08:14:46 -05:00
}
2017-03-12 23:19:33 -04:00
PCB_LAYER_ID EAGLE_PLUGIN : : kicad_layer ( int aEagleLayer ) const
2012-05-20 08:14:46 -05:00
{
2012-05-24 10:00:59 -05:00
int kiLayer ;
// eagle copper layer:
2013-03-13 11:17:16 -05:00
if ( aEagleLayer > = 1 & & aEagleLayer < int ( DIM ( m_cu_map ) ) )
2012-05-24 10:00:59 -05:00
{
2014-06-24 11:17:18 -05:00
kiLayer = m_cu_map [ aEagleLayer ] ;
2012-05-24 10:00:59 -05:00
}
else
2012-05-22 12:51:18 -05:00
{
2012-05-24 10:00:59 -05:00
// translate non-copper eagle layer to pcbnew layer
switch ( aEagleLayer )
{
2017-07-01 15:16:51 +02:00
// Eagle says "Dimension" layer, but it's for board perimeter
case EAGLE_LAYER : : DIMENSION : kiLayer = Edge_Cuts ; break ;
case EAGLE_LAYER : : TPLACE : kiLayer = F_SilkS ; break ;
case EAGLE_LAYER : : BPLACE : kiLayer = B_SilkS ; break ;
case EAGLE_LAYER : : TNAMES : kiLayer = F_SilkS ; break ;
case EAGLE_LAYER : : BNAMES : kiLayer = B_SilkS ; break ;
case EAGLE_LAYER : : TVALUES : kiLayer = F_SilkS ; break ;
case EAGLE_LAYER : : BVALUES : kiLayer = B_SilkS ; break ;
case EAGLE_LAYER : : TSTOP : kiLayer = F_Mask ; break ;
case EAGLE_LAYER : : BSTOP : kiLayer = B_Mask ; break ;
case EAGLE_LAYER : : TCREAM : kiLayer = F_Paste ; break ;
case EAGLE_LAYER : : BCREAM : kiLayer = B_Paste ; break ;
case EAGLE_LAYER : : TFINISH : kiLayer = F_Mask ; break ;
case EAGLE_LAYER : : BFINISH : kiLayer = B_Mask ; break ;
case EAGLE_LAYER : : TGLUE : kiLayer = F_Adhes ; break ;
case EAGLE_LAYER : : BGLUE : kiLayer = B_Adhes ; break ;
case EAGLE_LAYER : : DOCUMENT : kiLayer = Cmts_User ; break ;
case EAGLE_LAYER : : REFERENCELC : kiLayer = Cmts_User ; break ;
case EAGLE_LAYER : : REFERENCELS : kiLayer = Cmts_User ; break ;
2012-06-01 02:39:32 -05:00
// Packages show the future chip pins on SMD parts using layer 51.
// This is an area slightly smaller than the PAD/SMD copper area.
2015-12-02 12:46:55 +01:00
// Carry those visual aids into the MODULE on the fabrication layer,
// not silkscreen. This is perhaps not perfect, but there is not a lot
// of other suitable paired layers
2017-07-01 15:16:51 +02:00
case EAGLE_LAYER : : TDOCU : kiLayer = F_Fab ; break ;
case EAGLE_LAYER : : BDOCU : kiLayer = B_Fab ; break ;
2012-06-01 02:39:32 -05:00
2015-11-05 19:38:19 +01:00
// thes layers are defined as user layers. put them on ECO layers
2017-07-01 15:16:51 +02:00
case EAGLE_LAYER : : USERLAYER1 : kiLayer = Eco1_User ; break ;
case EAGLE_LAYER : : USERLAYER2 : kiLayer = Eco2_User ; break ;
case EAGLE_LAYER : : UNROUTED :
case EAGLE_LAYER : : TKEEPOUT :
case EAGLE_LAYER : : BKEEPOUT :
case EAGLE_LAYER : : TTEST :
case EAGLE_LAYER : : BTEST :
case EAGLE_LAYER : : MILLING :
case EAGLE_LAYER : : HOLES :
2012-05-24 10:00:59 -05:00
default :
2013-11-03 20:09:28 -06:00
// some layers do not map to KiCad
2017-07-01 15:16:51 +02:00
wxLogMessage ( wxString : : Format ( " Unsupported Eagle layer %d. Use drawings layer " ,
aEagleLayer ) ) ;
kiLayer = Dwgs_User ; break ;
2012-05-24 10:00:59 -05:00
}
2012-05-22 12:51:18 -05:00
}
2017-03-12 23:19:33 -04:00
return PCB_LAYER_ID ( kiLayer ) ;
2012-05-24 10:00:59 -05:00
}
2012-06-02 12:07:30 -05:00
void EAGLE_PLUGIN : : centerBoard ( )
{
if ( m_props )
{
2014-01-01 20:17:07 -06:00
UTF8 page_width ;
UTF8 page_height ;
2012-06-02 12:07:30 -05:00
2013-11-01 19:24:38 -05:00
if ( m_props - > Value ( " page_width " , & page_width ) & &
m_props - > Value ( " page_height " , & page_height ) )
2012-06-02 12:07:30 -05:00
{
2017-02-22 23:31:26 -05:00
EDA_RECT bbbox = m_board - > GetBoardEdgesBoundingBox ( ) ;
2013-11-01 19:24:38 -05:00
int w = atoi ( page_width . c_str ( ) ) ;
int h = atoi ( page_height . c_str ( ) ) ;
int desired_x = ( w - bbbox . GetWidth ( ) ) / 2 ;
int desired_y = ( h - bbbox . GetHeight ( ) ) / 2 ;
2012-06-02 12:07:30 -05:00
2013-11-01 19:24:38 -05:00
DBG ( printf ( " bbox.width:%d bbox.height:%d w:%d h:%d desired_x:%d desired_y:%d \n " ,
bbbox . GetWidth ( ) , bbbox . GetHeight ( ) , w , h , desired_x , desired_y ) ; )
m_board - > Move ( wxPoint ( desired_x - bbbox . GetX ( ) , desired_y - bbbox . GetY ( ) ) ) ;
2012-06-02 12:07:30 -05:00
}
}
}
2013-01-01 22:05:48 -06:00
wxDateTime EAGLE_PLUGIN : : getModificationTime ( const wxString & aPath )
2012-05-24 10:00:59 -05:00
{
2013-01-01 22:05:48 -06:00
wxFileName fn ( aPath ) ;
2013-12-24 13:09:41 -06:00
// Do not call wxFileName::GetModificationTime() on a non-existent file, because
// if it fails, wx's implementation calls the crap wxLogSysError() which
// eventually infects our UI with an unwanted popup window, so don't let it fail.
if ( ! fn . IsFileReadable ( ) )
{
wxString msg = wxString : : Format (
_ ( " File '%s' is not readable. " ) ,
GetChars ( aPath ) ) ;
THROW_IO_ERROR ( msg ) ;
}
2013-01-01 22:05:48 -06:00
/*
// update the writable flag while we have a wxFileName, in a network this
// is possibly quite dynamic anyway.
m_writable = fn . IsFileWritable ( ) ;
*/
2013-09-21 20:28:02 -04:00
wxDateTime modTime = fn . GetModificationTime ( ) ;
if ( ! modTime . IsValid ( ) )
modTime . Now ( ) ;
return modTime ;
2012-05-24 10:00:59 -05:00
}
2013-01-01 22:05:48 -06:00
void EAGLE_PLUGIN : : cacheLib ( const wxString & aLibPath )
2012-05-24 10:00:59 -05:00
{
2013-01-01 22:05:48 -06:00
try
2012-05-24 10:00:59 -05:00
{
2013-09-22 13:20:46 -04:00
wxDateTime modtime = getModificationTime ( aLibPath ) ;
2013-01-01 22:05:48 -06:00
2013-09-22 13:20:46 -04:00
// Fixes assertions in wxWidgets debug builds for the wxDateTime object. Refresh the
// cache if either of the wxDateTime objects are invalid or the last file modification
// time differs from the current file modification time.
bool load = ! m_mod_time . IsValid ( ) | | ! modtime . IsValid ( ) | |
m_mod_time ! = modtime ;
2013-09-21 20:28:02 -04:00
2013-09-22 13:20:46 -04:00
if ( aLibPath ! = m_lib_path | | load )
2013-01-01 22:05:48 -06:00
{
2017-04-07 13:40:34 +02:00
wxXmlNode * doc ;
2013-01-01 22:05:48 -06:00
LOCALE_IO toggle ; // toggles on, then off, the C locale.
2012-05-24 10:00:59 -05:00
2017-07-10 11:44:56 +02:00
deleteTemplates ( ) ;
2013-01-01 22:05:48 -06:00
// Set this before completion of loading, since we rely on it for
// text of an exception. Delay setting m_mod_time until after successful load
// however.
m_lib_path = aLibPath ;
// 8 bit "filename" should be encoded according to disk filename encoding,
// (maybe this is current locale, maybe not, its a filesystem issue),
// and is not necessarily utf8.
2013-11-06 10:53:44 -06:00
string filename = ( const char * ) aLibPath . char_str ( wxConvFile ) ;
2013-01-01 22:05:48 -06:00
2017-04-07 13:40:34 +02:00
// Load the document
wxXmlDocument xmlDocument ;
wxFileName fn ( filename ) ;
if ( ! xmlDocument . Load ( fn . GetFullPath ( ) ) )
THROW_IO_ERROR ( wxString : : Format ( _ ( " Unable to read file '%s' " ) ,
fn . GetFullPath ( ) ) ) ;
doc = xmlDocument . GetRoot ( ) ;
wxXmlNode * drawing = MapChildren ( doc ) [ " drawing " ] ;
NODE_MAP drawingChildren = MapChildren ( drawing ) ;
2013-01-01 22:05:48 -06:00
2013-03-13 11:38:54 -05:00
// clear the cu map and then rebuild it.
clear_cu_map ( ) ;
2013-01-01 22:05:48 -06:00
2013-03-13 11:38:54 -05:00
m_xpath - > push ( " eagle.drawing.layers " ) ;
2017-04-07 13:40:34 +02:00
wxXmlNode * layers = drawingChildren [ " layers " ] ;
2013-03-13 11:38:54 -05:00
loadLayerDefs ( layers ) ;
m_xpath - > pop ( ) ;
2013-01-01 22:05:48 -06:00
2013-03-13 11:38:54 -05:00
m_xpath - > push ( " eagle.drawing.library " ) ;
2017-04-07 13:40:34 +02:00
wxXmlNode * library = drawingChildren [ " library " ] ;
2013-01-01 22:05:48 -06:00
loadLibrary ( library , NULL ) ;
m_xpath - > pop ( ) ;
m_mod_time = modtime ;
}
2012-05-24 10:00:59 -05:00
}
2017-04-07 13:40:34 +02:00
catch ( . . . ) { }
// TODO: Handle exceptions
// catch( file_parser_error fpe )
// {
// // for xml_parser_error, what() has the line number in it,
// // but no byte offset. That should be an adequate error message.
// THROW_IO_ERROR( fpe.what() );
// }
//
// // Class ptree_error is a base class for xml_parser_error & file_parser_error,
// // so one catch should be OK for all errors.
// catch( ptree_error pte )
// {
// string errmsg = pte.what();
//
// errmsg += " @\n";
// errmsg += m_xpath->Contents();
//
// THROW_IO_ERROR( errmsg );
// }
2012-05-24 10:00:59 -05:00
}
2017-06-11 16:20:44 -04:00
void EAGLE_PLUGIN : : FootprintEnumerate ( wxArrayString & aFootprintNames , const wxString & aLibraryPath ,
const PROPERTIES * aProperties )
2012-05-24 10:00:59 -05:00
{
2013-01-01 22:05:48 -06:00
init ( aProperties ) ;
2012-05-24 10:00:59 -05:00
2013-01-01 22:05:48 -06:00
cacheLib ( aLibraryPath ) ;
2012-05-24 10:00:59 -05:00
2013-01-01 22:05:48 -06:00
for ( MODULE_CITER it = m_templates . begin ( ) ; it ! = m_templates . end ( ) ; + + it )
2017-06-11 16:20:44 -04:00
aFootprintNames . Add ( FROM_UTF8 ( it - > first . c_str ( ) ) ) ;
2012-05-20 08:14:46 -05:00
}
2016-05-10 15:07:35 -04:00
MODULE * EAGLE_PLUGIN : : FootprintLoad ( const wxString & aLibraryPath , const wxString & aFootprintName ,
const PROPERTIES * aProperties )
2012-05-20 08:14:46 -05:00
{
2013-01-01 22:05:48 -06:00
init ( aProperties ) ;
cacheLib ( aLibraryPath ) ;
2013-11-06 10:53:44 -06:00
string key = TO_UTF8 ( aFootprintName ) ;
2013-01-01 22:05:48 -06:00
MODULE_CITER mi = m_templates . find ( key ) ;
if ( mi = = m_templates . end ( ) )
return NULL ;
// copy constructor to clone the template
MODULE * ret = new MODULE ( * mi - > second ) ;
return ret ;
2012-05-20 08:14:46 -05:00
}
2013-11-20 10:35:03 -06:00
void EAGLE_PLUGIN : : FootprintLibOptions ( PROPERTIES * aListToAppendTo ) const
{
2013-11-26 11:06:54 -06:00
PLUGIN : : FootprintLibOptions ( aListToAppendTo ) ;
2013-11-20 10:35:03 -06:00
/*
2014-01-01 20:17:07 -06:00
( * aListToAppendTo ) [ " ignore_duplicates " ] = UTF8 ( _ (
2013-11-20 10:35:03 -06:00
" Ignore duplicately named footprints within the same Eagle library. "
" Only the first similarly named footprint will be loaded. "
2014-01-01 20:17:07 -06:00
) ) ;
2013-11-20 10:35:03 -06:00
*/
}
2013-01-01 22:05:48 -06:00
/*
2013-09-25 14:17:06 -05:00
void EAGLE_PLUGIN : : Save ( const wxString & aFileName , BOARD * aBoard , const PROPERTIES * aProperties )
2012-05-20 08:14:46 -05:00
{
2013-01-01 22:05:48 -06:00
// Eagle lovers apply here.
2012-05-20 08:14:46 -05:00
}
2013-09-25 14:17:06 -05:00
void EAGLE_PLUGIN : : FootprintSave ( const wxString & aLibraryPath , const MODULE * aFootprint , const PROPERTIES * aProperties )
2012-05-20 08:14:46 -05:00
{
}
void EAGLE_PLUGIN : : FootprintDelete ( const wxString & aLibraryPath , const wxString & aFootprintName )
{
}
2013-09-25 14:17:06 -05:00
void EAGLE_PLUGIN : : FootprintLibCreate ( const wxString & aLibraryPath , const PROPERTIES * aProperties )
2012-05-20 08:14:46 -05:00
{
}
2013-09-25 14:17:06 -05:00
bool EAGLE_PLUGIN : : FootprintLibDelete ( const wxString & aLibraryPath , const PROPERTIES * aProperties )
2012-05-20 08:14:46 -05:00
{
}
bool EAGLE_PLUGIN : : IsFootprintLibWritable ( const wxString & aLibraryPath )
{
return true ;
}
2012-05-15 21:27:27 -05:00
2012-06-03 17:47:53 +02:00
*/