From f892ebbb495ba0aa787caa7a3231cb202d96f4a2 Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Thu, 17 Oct 2019 12:41:42 +0200 Subject: [PATCH] Fix issues in Gerber attributes --- common/gbr_metadata.cpp | 36 +++++++++++++++++--- common/plotters/GERBER_plotter.cpp | 4 +-- include/gbr_netlist_metadata.h | 9 ++++- pcbnew/exporters/gerber_placefile_writer.cpp | 3 ++ 4 files changed, 45 insertions(+), 7 deletions(-) diff --git a/common/gbr_metadata.cpp b/common/gbr_metadata.cpp index f26344d047..410a73d113 100644 --- a/common/gbr_metadata.cpp +++ b/common/gbr_metadata.cpp @@ -493,17 +493,28 @@ bool FormatNetAttribute( std::string& aPrintedText, std::string& aLastNetAttribu // (only modified or new attributes are stored here): std::string short_attribute_string; + // Attributes have changed: update attribute string, and see if the previous attribute + // list (dictionary in Gerber language) must be cleared if( aLastNetAttributes != full_attribute_string ) { - // first, remove no more existing attributes. + // first, remove no longer existing attributes. // Because in Kicad the full attribute list is evaluated for each object, // the entire dictionary is cleared + // If m_TryKeepPreviousAttributes is true, only the no longer existing attribute + // is cleared. + // Note: to avoid interaction beteween clear attributes and set attributes + // the clear attribute is inserted first. bool clearDict = false; if( aLastNetAttributes.find( "TO.P," ) != std::string::npos ) { if( pad_attribute_string.empty() ) // No more this attribute - clearDict = true; + { + if( aData->m_TryKeepPreviousAttributes ) // Clear only this attribute + short_attribute_string.insert( 0, prepend_string + "TO.P" + eol_string ); + else + clearDict = true; + } else if( aLastNetAttributes.find( pad_attribute_string ) == std::string::npos ) // This attribute has changed short_attribute_string += pad_attribute_string; @@ -514,7 +525,12 @@ bool FormatNetAttribute( std::string& aPrintedText, std::string& aLastNetAttribu if( aLastNetAttributes.find( "TO.N," ) != std::string::npos ) { if( net_attribute_string.empty() ) // No more this attribute - clearDict = true; + { + if( aData->m_TryKeepPreviousAttributes ) // Clear only this attribute + short_attribute_string.insert( 0, prepend_string + "TO.N" + eol_string ); + else + clearDict = true; + } else if( aLastNetAttributes.find( net_attribute_string ) == std::string::npos ) // This attribute has changed short_attribute_string += net_attribute_string; @@ -525,7 +541,19 @@ bool FormatNetAttribute( std::string& aPrintedText, std::string& aLastNetAttribu if( aLastNetAttributes.find( "TO.C," ) != std::string::npos ) { if( cmp_attribute_string.empty() ) // No more this attribute - clearDict = true; + { + if( aData->m_TryKeepPreviousAttributes ) // Clear only this attribute + { + // Refinement: + // the attribute will be cleared only if there is no pad attribute. + // If a pad attribute exists, the component name exists so the old + // TO.C value will be updated, therefore no need to clear it before updating + if( pad_attribute_string.empty() ) + short_attribute_string.insert( 0, prepend_string + "TO.C" + eol_string ); + } + else + clearDict = true; + } else if( aLastNetAttributes.find( cmp_attribute_string ) == std::string::npos ) // This attribute has changed short_attribute_string += cmp_attribute_string; diff --git a/common/plotters/GERBER_plotter.cpp b/common/plotters/GERBER_plotter.cpp index 2df250c2a8..03655dd92d 100644 --- a/common/plotters/GERBER_plotter.cpp +++ b/common/plotters/GERBER_plotter.cpp @@ -574,11 +574,11 @@ void GERBER_PLOTTER::PlotGerberRegion( const std::vector< wxPoint >& aCornerList { if( m_useX2format ) { - fputs( "%TD,.AperFunction*%\n", outputFile ); + fputs( "%TD.AperFunction*%\n", outputFile ); } else { - fputs( "G04 #@! TD,.AperFunction*\n", outputFile ); + fputs( "G04 #@! TD.AperFunction*\n", outputFile ); } } } diff --git a/include/gbr_netlist_metadata.h b/include/gbr_netlist_metadata.h index 31eb7eb6ec..120d1868ab 100644 --- a/include/gbr_netlist_metadata.h +++ b/include/gbr_netlist_metadata.h @@ -125,9 +125,16 @@ public: wxString m_ExtraData; ///< a string to print after %TO object attributes, if not empty ///< it is printed "as this" + /** If true, do not clear all attributes when a atribute has changed + * Usefull when some attributes need to be persistant. + * If false, attributes will be cleared if only one attribute cleared + * This is a more secure way to set attributes, when all attribute changess are not safely managed + */ + bool m_TryKeepPreviousAttributes; - GBR_NETLIST_METADATA(): m_NetAttribType( GBR_NETINFO_UNSPECIFIED ), m_NotInNet( false ) + GBR_NETLIST_METADATA(): m_NetAttribType( GBR_NETINFO_UNSPECIFIED ), + m_NotInNet( false ), m_TryKeepPreviousAttributes( false ) { } diff --git a/pcbnew/exporters/gerber_placefile_writer.cpp b/pcbnew/exporters/gerber_placefile_writer.cpp index 0d7c73894f..8d8f2c2257 100644 --- a/pcbnew/exporters/gerber_placefile_writer.cpp +++ b/pcbnew/exporters/gerber_placefile_writer.cpp @@ -161,6 +161,9 @@ int PLACEFILE_GERBER_WRITER::CreatePlaceFile( wxString& aFullFilename, plotter.FlashPadCircle( flash_pos, flash_diam, FILLED, &gbr_metadata ); gbr_metadata.m_NetlistMetadata.ClearExtraData(); + // Now some extra metadata is output, avoid blindly clearing the full metadata list + gbr_metadata.m_NetlistMetadata.m_TryKeepPreviousAttributes = true; + if( footprint->BuildPolyCourtyard() ) { int thickness = Millimeter2iu( 0.1 ); // arbitrary but reasonable value