Files
kicad-source-mirror/common/gbr_metadata.cpp
T
jean-pierre charras 6edee2ae1d Prepare Plot Gerber file to include advanced aperture and net attributes.
This option is not yet activated because the net attributes are not yet fully fixed by Ucamco, in Gerber file format specifications.
(To activate it, see dialog_plot.cpp, line 43)
2016-09-19 13:01:36 +02:00

292 lines
11 KiB
C++

/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2016 KiCad Developers, see CHANGELOG.TXT for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @file gbr_metadata.cpp
* @brief helper functions to handle the gerber metadata in files,
* related to the netlist info and aperture attribute.
*/
#include <fctsys.h>
#include <plot_auxiliary_data.h>
std::string GBR_APERTURE_METADATA::FormatAttribute( GBR_APERTURE_ATTRIB aAttribute )
{
std::string attribute_string;
// generate a string to print a Gerber Aperture attribute
switch( aAttribute )
{
case GBR_APERTURE_ATTRIB_END: // Dummy value (aAttribute must be < GBR_APERTURE_ATTRIB_END)
case GBR_APERTURE_ATTRIB_NONE: // idle command: do nothing
break;
case GBR_APERTURE_ATTRIB_ETCHEDCMP: // print info associated to an item
// which connects 2 different nets
// (Net tees, microwave component)
attribute_string = "%TA.AperFunction,EtchedComponent*%\n";
break;
case GBR_APERTURE_ATTRIB_CONDUCTOR: // print info associated to a track
attribute_string = "%TA.AperFunction,Conductor*%\n";
break;
case GBR_APERTURE_ATTRIB_CUTOUT: // print info associated to a outline
attribute_string = "%TA.AperFunction,CutOut*%\n";
break;
case GBR_APERTURE_ATTRIB_VIAPAD: // print info associated to a flashed via
attribute_string = "%TA.AperFunction,ViaPad*%\n";
break;
case GBR_APERTURE_ATTRIB_NONCONDUCTOR: // print info associated to a flashed pad
attribute_string = "%TA.AperFunction,NonConductor*%\n";
break;
case GBR_APERTURE_ATTRIB_COMPONENTPAD: // print info associated to a flashed
// through hole component on outer layer
attribute_string = "%TA.AperFunction,ComponentPad*%\n";
break;
case GBR_APERTURE_ATTRIB_SMDPAD_SMDEF: // print info associated to a flashed for SMD pad.
// with solder mask defined from the copper shape
// Excluded BGA pads which have their own type
attribute_string = "%TA.AperFunction,SMDPad,SMDef*%\n";
break;
case GBR_APERTURE_ATTRIB_SMDPAD_CUDEF: // print info associated to a flashed SMD pad with
// a solder mask defined by the solder mask
attribute_string = "%TA.AperFunction,SMDPad,CuDef*%\n";
break;
case GBR_APERTURE_ATTRIB_BGAPAD_SMDEF: // print info associated to flashed BGA pads with
// a solder mask defined by the copper shape
attribute_string = "%TA.AperFunction,BGAPad,SMDef*%\n";
break;
case GBR_APERTURE_ATTRIB_BGAPAD_CUDEF: // print info associated to a flashed BGA pad with
// a solder mask defined by the solder mask
attribute_string = "%TA.AperFunction,BGAPad,CuDef*%\n";
break;
case GBR_APERTURE_ATTRIB_CONNECTORPAD: // print info associated to a flashed edge connector pad (outer layers)
attribute_string = "%TA.AperFunction,ConnectorPad*%\n";
break;
case GBR_APERTURE_ATTRIB_WASHERPAD: // print info associated to flashed mechanical pads (NPTH)
attribute_string = "%TA.AperFunction,WasherPad*%\n";
break;
case GBR_APERTURE_ATTRIB_HEATSINKPAD: // print info associated to a flashed heat sink pad (typically for SMDs)
attribute_string = "%TA.AperFunction,HeatsinkPad*%\n";
break;
}
return attribute_string;
}
std::string formatStringToGerber( const wxString& aString )
{
/* format string means convert any code > 0x7F and unautorized code to a hexadecimal
* 16 bits sequence unicode
* unautorized codes are ',' '*' '%' '\'
*/
std::string txt;
txt.reserve( aString.Length() );
for( unsigned ii = 0; ii < aString.Length(); ++ii )
{
unsigned code = aString[ii];
bool convert = false;
switch( code )
{
case '\\':
case '%':
case '*':
case ',':
convert = true;
break;
default:
break;
}
if( convert || code > 0x7F )
{
txt += '\\';
// Convert code to 4 hexadecimal digit
// (Gerber allows only 4 hexadecimal digit)
char hexa[32];
sprintf( hexa,"%4.4X", code & 0xFFFF);
txt += hexa;
}
else
txt += char( code );
}
return txt;
}
// Netname and Pan num fields cannot be empty in Gerber files
// Normalized names must be used, if any
#define NO_NET_NAME wxT( "N/C" ) // net name of not connected pads (one pad net) (normalized)
#define NO_PAD_NAME wxT( "" ) // pad name of pads without pad name/number (not normalized)
bool FormatNetAttribute( std::string& aPrintedText, std::string& aLastNetAttributes,
GBR_NETLIST_METADATA* aData, bool& aClearPreviousAttributes )
{
aClearPreviousAttributes = false;
// print a Gerber net attribute record.
// it is added to the object attributes dictionnary
// On file, only modified or new attributes are printed.
if( aData == NULL )
return false;
std::string pad_attribute_string;
std::string net_attribute_string;
std::string cmp_attribute_string;
if( aData->m_NetAttribType == GBR_NETLIST_METADATA::GBR_NETINFO_UNSPECIFIED )
return false; // idle command: do nothing
if( ( aData->m_NetAttribType & GBR_NETLIST_METADATA::GBR_NETINFO_PAD ) )
{
// print info associated to a flashed pad (cmpref, pad name)
// example: %TO.P,R5,3*%
pad_attribute_string = "%TO.P,";
pad_attribute_string += formatStringToGerber( aData->m_Cmpref ) + ",";
if( aData->m_Padname.IsEmpty() )
// Happens for "mechanical" or never connected pads
pad_attribute_string += formatStringToGerber( NO_PAD_NAME );
else
pad_attribute_string += formatStringToGerber( aData->m_Padname );
pad_attribute_string += "*%\n";
}
if( ( aData->m_NetAttribType & GBR_NETLIST_METADATA::GBR_NETINFO_NET ) )
{
// print info associated to a net
// example: %TO.N,Clk3*%
net_attribute_string = "%TO.N,";
if( aData->m_Netname.IsEmpty() )
{
if( aData->m_NotInNet )
{
// Happens for not connectable pads: mechanical pads
// and pads with no padname/num
// In this case the net name must be left empty
}
else
{
// Happens for not connected pads: use a normalized
// dummy name
net_attribute_string += formatStringToGerber( NO_NET_NAME );
}
}
else
net_attribute_string += formatStringToGerber( aData->m_Netname );
net_attribute_string += "*%\n";
}
if( ( aData->m_NetAttribType & GBR_NETLIST_METADATA::GBR_NETINFO_CMP ) &&
!( aData->m_NetAttribType & GBR_NETLIST_METADATA::GBR_NETINFO_PAD ) )
{
// print info associated to a footprint
// example: %TO.C,R2*%
// Because GBR_NETINFO_PAD option already contains this info, it is not
// created here for a GBR_NETINFO_PAD attribute
cmp_attribute_string = "%TO.C,";
cmp_attribute_string += formatStringToGerber( aData->m_Cmpref ) + "*%\n";
}
// the full list of requested attributes:
std::string full_attribute_string = pad_attribute_string + net_attribute_string
+ cmp_attribute_string;
// the short list of requested attributes
// (only modified or new attributes are stored here):
std::string short_attribute_string;
if( aLastNetAttributes != full_attribute_string )
{
// first, remove no more existing attributes.
// Because in Kicad the full attribute list is evaluated for each object,
// the entire dictionnary is cleared
bool clearDict = false;
if( aLastNetAttributes.find( "%TO.P," ) != std::string::npos )
{
if( pad_attribute_string.empty() ) // No more this attribute
clearDict = true;
else if( aLastNetAttributes.find( pad_attribute_string )
== std::string::npos ) // This attribute has changed
short_attribute_string += pad_attribute_string;
}
else // New attribute
short_attribute_string += pad_attribute_string;
if( aLastNetAttributes.find( "%TO.N," ) != std::string::npos )
{
if( net_attribute_string.empty() ) // No more this attribute
clearDict = true;
else if( aLastNetAttributes.find( net_attribute_string )
== std::string::npos ) // This attribute has changed
short_attribute_string += net_attribute_string;
}
else // New attribute
short_attribute_string += net_attribute_string;
if( aLastNetAttributes.find( "%TO.C," ) != std::string::npos )
{
if( cmp_attribute_string.empty() ) // No more this attribute
clearDict = true;
else if( aLastNetAttributes.find( cmp_attribute_string )
== std::string::npos ) // This attribute has changed
short_attribute_string += cmp_attribute_string;
}
else // New attribute
short_attribute_string += cmp_attribute_string;
aClearPreviousAttributes = clearDict;
aLastNetAttributes = full_attribute_string;
if( clearDict )
aPrintedText = full_attribute_string;
else
aPrintedText = short_attribute_string;
}
return true;
}