Gerber, Dialog plot: add option to disable Aperture Macro use.

Some broken Gerber readers cannot handle Aperture Macros without errors
although this feature exists since the beginning of RS274X format.
This commit is contained in:
jean-pierre charras 2020-10-10 14:39:54 +02:00
parent 1df13ce32b
commit 213a74cbe6
10 changed files with 162 additions and 39 deletions

View File

@ -1,4 +1,5 @@
creategerberjobfile creategerberjobfile
disableapertmacros
drillshape drillshape
excludeedgelayer excludeedgelayer
false false

View File

@ -40,6 +40,10 @@
// if GBR_USE_MACROS is defined, pads having a shape that is not a Gerber primitive // if GBR_USE_MACROS is defined, pads having a shape that is not a Gerber primitive
// will use a macro when possible // will use a macro when possible
// Old code will be removed only after many tests // Old code will be removed only after many tests
//
// Note also: setting m_gerberDisableApertMacros to true disable all aperture macros
// in Gerber files
//
#define GBR_USE_MACROS_FOR_CHAMFERED_RECT #define GBR_USE_MACROS_FOR_CHAMFERED_RECT
#define GBR_USE_MACROS_FOR_ROUNDRECT #define GBR_USE_MACROS_FOR_ROUNDRECT
#define GBR_USE_MACROS_FOR_TRAPEZOID #define GBR_USE_MACROS_FOR_TRAPEZOID
@ -64,6 +68,7 @@ GERBER_PLOTTER::GERBER_PLOTTER()
m_gerberUnitFmt = 6; m_gerberUnitFmt = 6;
m_useX2format = true; m_useX2format = true;
m_useNetAttributes = true; m_useNetAttributes = true;
m_gerberDisableApertMacros = false;
m_hasApertureRoundRect = false; // true is at least one round rect aperture is in use m_hasApertureRoundRect = false; // true is at least one round rect aperture is in use
m_hasApertureRotOval = false; // true is at least one oval rotated aperture is in use m_hasApertureRotOval = false; // true is at least one oval rotated aperture is in use
@ -1024,6 +1029,9 @@ void GERBER_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, doub
if( trace_mode == FILLED ) if( trace_mode == FILLED )
{ {
#ifdef GBR_USE_MACROS_FOR_ROTATED_OVAL #ifdef GBR_USE_MACROS_FOR_ROTATED_OVAL
if( !m_gerberDisableApertMacros )
#endif
{
m_hasApertureRotOval = true; m_hasApertureRotOval = true;
// We are using a aperture macro that expect size.y < size.x // We are using a aperture macro that expect size.y < size.x
// i.e draw a horizontal line for rotation = 0.0 // i.e draw a horizontal line for rotation = 0.0
@ -1045,13 +1053,13 @@ void GERBER_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, doub
formatNetAttribute( &gbr_metadata->m_NetlistMetadata ); formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
emitDcode( pos_dev, 3 ); emitDcode( pos_dev, 3 );
#else return;
}
// Draw the oval as round rect pad with a radius = 50% min size) // Draw the oval as round rect pad with a radius = 50% min size)
// In gerber file, it will be drawn as a region with arcs, and can be // In gerber file, it will be drawn as a region with arcs, and can be
// detected as pads (similar to a flashed pad) // detected as pads (similar to a flashed pad)
FlashPadRoundRect( pos, aSize, std::min( aSize.x, aSize.y ) /2, FlashPadRoundRect( pos, aSize, std::min( aSize.x, aSize.y ) /2,
orient, FILLED, aData ); orient, FILLED, aData );
#endif
} }
else // Non filled shape: plot outlines: else // Non filled shape: plot outlines:
{ {
@ -1116,7 +1124,7 @@ void GERBER_PLOTTER::FlashPadRect( const wxPoint& pos, const wxSize& aSize,
default: default:
#ifdef GBR_USE_MACROS_FOR_ROTATED_RECT #ifdef GBR_USE_MACROS_FOR_ROTATED_RECT
if( trace_mode != SKETCH ) if( trace_mode != SKETCH && !m_gerberDisableApertMacros )
{ {
m_hasApertureRotRect = true; m_hasApertureRotRect = true;
DPOINT pos_dev = userToDeviceCoordinates( pos ); DPOINT pos_dev = userToDeviceCoordinates( pos );
@ -1187,6 +1195,9 @@ void GERBER_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aS
else else
{ {
#ifdef GBR_USE_MACROS_FOR_ROUNDRECT #ifdef GBR_USE_MACROS_FOR_ROUNDRECT
if( !m_gerberDisableApertMacros )
#endif
{
m_hasApertureRoundRect = true; m_hasApertureRoundRect = true;
DPOINT pos_dev = userToDeviceCoordinates( aPadPos ); DPOINT pos_dev = userToDeviceCoordinates( aPadPos );
@ -1198,7 +1209,8 @@ void GERBER_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aS
formatNetAttribute( &gbr_metadata->m_NetlistMetadata ); formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
emitDcode( pos_dev, 3 ); emitDcode( pos_dev, 3 );
#else return;
}
// A Pad RoundRect is plotted as a Gerber region. // A Pad RoundRect is plotted as a Gerber region.
// Initialize region metadata: // Initialize region metadata:
bool clearTA_AperFunction = false; // true if a TA.AperFunction is used bool clearTA_AperFunction = false; // true if a TA.AperFunction is used
@ -1226,7 +1238,6 @@ void GERBER_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aS
else else
fputs( "G04 #@! TD.AperFunction*\n", outputFile ); fputs( "G04 #@! TD.AperFunction*\n", outputFile );
} }
#endif
} }
} }
@ -1420,7 +1431,8 @@ void GERBER_PLOTTER::FlashPadChamferRoundRect( const wxPoint& aShapePos, const w
bool hasRoundedCorner = aCornerRadius != 0 && aChamferPositions != 15; bool hasRoundedCorner = aCornerRadius != 0 && aChamferPositions != 15;
#ifdef GBR_USE_MACROS_FOR_CHAMFERED_RECT #ifdef GBR_USE_MACROS_FOR_CHAMFERED_RECT
if( aPlotMode != FILLED || hasRoundedCorner ) // Sketch mode or round rect shape // Sketch mode or round rect shape or Apert Macros disabled
if( aPlotMode != FILLED || hasRoundedCorner || m_gerberDisableApertMacros )
#endif #endif
{ {
TransformRoundChamferedRectToPolygon( outline, aShapePos, aPadSize, TransformRoundChamferedRectToPolygon( outline, aShapePos, aPadSize,
@ -1525,9 +1537,15 @@ void GERBER_PLOTTER::FlashPadTrapez( const wxPoint& aPadPos, const wxPoint* aCo
metadata = *gbr_metadata; metadata = *gbr_metadata;
if( aTrace_Mode == SKETCH ) if( aTrace_Mode == SKETCH )
{
PlotPoly( cornerList, NO_FILL, GetCurrentLineWidth(), &metadata ); PlotPoly( cornerList, NO_FILL, GetCurrentLineWidth(), &metadata );
else return;
}
// Plot a filled polygon:
#ifdef GBR_USE_MACROS_FOR_TRAPEZOID #ifdef GBR_USE_MACROS_FOR_TRAPEZOID
if( !m_gerberDisableApertMacros )
#endif
{ {
m_hasApertureOutline4P = true; m_hasApertureOutline4P = true;
DPOINT pos_dev = userToDeviceCoordinates( aPadPos ); DPOINT pos_dev = userToDeviceCoordinates( aPadPos );
@ -1540,10 +1558,10 @@ void GERBER_PLOTTER::FlashPadTrapez( const wxPoint& aPadPos, const wxPoint* aCo
formatNetAttribute( &gbr_metadata->m_NetlistMetadata ); formatNetAttribute( &gbr_metadata->m_NetlistMetadata );
emitDcode( pos_dev, 3 ); emitDcode( pos_dev, 3 );
return;
} }
#else
PlotGerberRegion( cornerList, &metadata ); PlotGerberRegion( cornerList, &metadata );
#endif
} }

View File

@ -197,6 +197,12 @@ public:
void UseX2format( bool aEnable ) { m_useX2format = aEnable; } void UseX2format( bool aEnable ) { m_useX2format = aEnable; }
void UseX2NetAttributes( bool aEnable ) { m_useNetAttributes = aEnable; } void UseX2NetAttributes( bool aEnable ) { m_useNetAttributes = aEnable; }
/** Disable Aperture Macro (AM) command, only for broken Gerber Readers
* Regions will be used instead of AM shapes to draw complex shapes
* @param aDisable = true to disable Aperture Macro (AM) command.
*/
void DisableApertMacros( bool aDisable ) { m_gerberDisableApertMacros = aDisable; }
/** /**
* calling this function allows one to define the beginning of a group * calling this function allows one to define the beginning of a group
* of drawing items (used in X2 format with netlist attributes) * of drawing items (used in X2 format with netlist attributes)
@ -351,6 +357,9 @@ protected:
bool m_gerberUnitInch; // true if the gerber units are inches, false for mm bool m_gerberUnitInch; // true if the gerber units are inches, false for mm
int m_gerberUnitFmt; // number of digits in mantissa. int m_gerberUnitFmt; // number of digits in mantissa.
// usually 6 in Inches and 5 or 6 in mm // usually 6 in Inches and 5 or 6 in mm
bool m_gerberDisableApertMacros; // True to disable Aperture Macro (AM) command,
// for broken Gerber Readers
// Regions will be used instead of AM shapes
bool m_useX2format; // Add X2 file header attributes. If false, attributes bool m_useX2format; // Add X2 file header attributes. If false, attributes
// will be added as comments. // will be added as comments.
bool m_useNetAttributes; // In recent gerber files, netlist info can be added. bool m_useNetAttributes; // In recent gerber files, netlist info can be added.

View File

@ -136,6 +136,9 @@ void DIALOG_PLOT::init_Dialog()
m_layerCheckListBox->Check( checkIndex ); m_layerCheckListBox->Check( checkIndex );
} }
// Option for disabling Gerber Aperture Macro (for broken Gerber readers)
m_disableApertMacros->SetValue( m_plotOpts.GetDisableGerberMacros() );
// Option for using proper Gerber extensions. Note also Protel extensions are // Option for using proper Gerber extensions. Note also Protel extensions are
// a broken feature. However, for now, we need to handle it. // a broken feature. However, for now, we need to handle it.
m_useGerberExtensions->SetValue( m_plotOpts.GetUseGerberProtelExtensions() ); m_useGerberExtensions->SetValue( m_plotOpts.GetUseGerberProtelExtensions() );
@ -720,6 +723,7 @@ void DIALOG_PLOT::applyPlotSettings()
tempOptions.SetFormat( getPlotFormat() ); tempOptions.SetFormat( getPlotFormat() );
tempOptions.SetDisableGerberMacros( m_disableApertMacros->GetValue() );
tempOptions.SetUseGerberProtelExtensions( m_useGerberExtensions->GetValue() ); tempOptions.SetUseGerberProtelExtensions( m_useGerberExtensions->GetValue() );
tempOptions.SetUseGerberX2format( m_useGerberX2Format->GetValue() ); tempOptions.SetUseGerberX2format( m_useGerberX2Format->GetValue() );
tempOptions.SetIncludeGerberNetlistInfo( m_useGerberNetAttributes->GetValue() ); tempOptions.SetIncludeGerberNetlistInfo( m_useGerberNetAttributes->GetValue() );

View File

@ -228,7 +228,7 @@ DIALOG_PLOT_BASE::DIALOG_PLOT_BASE( wxWindow* parent, wxWindowID id, const wxStr
m_coordFormatCtrl->SetSelection( 0 ); m_coordFormatCtrl->SetSelection( 0 );
gbSizer2->Add( m_coordFormatCtrl, wxGBPosition( 0, 2 ), wxGBSpan( 1, 1 ), wxEXPAND|wxRIGHT|wxLEFT, 5 ); gbSizer2->Add( m_coordFormatCtrl, wxGBPosition( 0, 2 ), wxGBSpan( 1, 1 ), wxEXPAND|wxRIGHT|wxLEFT, 5 );
m_useGerberX2Format = new wxCheckBox( m_GerberOptionsSizer->GetStaticBox(), wxID_ANY, _("Use extended X2 format"), wxDefaultPosition, wxDefaultSize, 0 ); m_useGerberX2Format = new wxCheckBox( m_GerberOptionsSizer->GetStaticBox(), wxID_ANY, _("Use extended X2 format (recommended)"), wxDefaultPosition, wxDefaultSize, 0 );
m_useGerberX2Format->SetToolTip( _("Use X2 Gerber file format.\nInclude mainly X2 attributes in Gerber headers.\nIf not checked, use X1 format.\nIn X1 format, these attributes are included as comments in files.") ); m_useGerberX2Format->SetToolTip( _("Use X2 Gerber file format.\nInclude mainly X2 attributes in Gerber headers.\nIf not checked, use X1 format.\nIn X1 format, these attributes are included as comments in files.") );
gbSizer2->Add( m_useGerberX2Format, wxGBPosition( 1, 1 ), wxGBSpan( 1, 2 ), wxALIGN_CENTER_VERTICAL|wxLEFT, 30 ); gbSizer2->Add( m_useGerberX2Format, wxGBPosition( 1, 1 ), wxGBSpan( 1, 2 ), wxALIGN_CENTER_VERTICAL|wxLEFT, 30 );
@ -238,6 +238,11 @@ DIALOG_PLOT_BASE::DIALOG_PLOT_BASE( wxWindow* parent, wxWindowID id, const wxStr
gbSizer2->Add( m_useGerberNetAttributes, wxGBPosition( 2, 1 ), wxGBSpan( 1, 2 ), wxLEFT|wxALIGN_CENTER_VERTICAL, 30 ); gbSizer2->Add( m_useGerberNetAttributes, wxGBPosition( 2, 1 ), wxGBSpan( 1, 2 ), wxLEFT|wxALIGN_CENTER_VERTICAL, 30 );
m_disableApertMacros = new wxCheckBox( m_GerberOptionsSizer->GetStaticBox(), wxID_ANY, _("Disable aperture macros (non recommended)"), wxDefaultPosition, wxDefaultSize, 0 );
m_disableApertMacros->SetToolTip( _("Disable aperture macros in Gerber files\nUse *only* for broken Gerber viewers.") );
gbSizer2->Add( m_disableApertMacros, wxGBPosition( 3, 1 ), wxGBSpan( 1, 2 ), wxLEFT|wxALIGN_CENTER_VERTICAL, 30 );
gbSizer2->AddGrowableCol( 2 ); gbSizer2->AddGrowableCol( 2 );

View File

@ -2345,7 +2345,7 @@
<property name="gripper">0</property> <property name="gripper">0</property>
<property name="hidden">0</property> <property name="hidden">0</property>
<property name="id">wxID_ANY</property> <property name="id">wxID_ANY</property>
<property name="label">Use extended X2 format</property> <property name="label">Use extended X2 format (recommended)</property>
<property name="max_size"></property> <property name="max_size"></property>
<property name="maximize_button">0</property> <property name="maximize_button">0</property>
<property name="maximum_size"></property> <property name="maximum_size"></property>
@ -2444,6 +2444,73 @@
<property name="window_style"></property> <property name="window_style"></property>
</object> </object>
</object> </object>
<object class="gbsizeritem" expanded="1">
<property name="border">30</property>
<property name="colspan">2</property>
<property name="column">1</property>
<property name="flag">wxLEFT|wxALIGN_CENTER_VERTICAL</property>
<property name="row">3</property>
<property name="rowspan">1</property>
<object class="wxCheckBox" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="checked">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Disable aperture macros (non recommended)</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_disableApertMacros</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass"></property>
<property name="toolbar_pane">0</property>
<property name="tooltip">Disable aperture macros in Gerber files&#x0A;Use *only* for broken Gerber viewers.</property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
</object> </object>
</object> </object>
</object> </object>

View File

@ -99,6 +99,7 @@ class DIALOG_PLOT_BASE : public DIALOG_SHIM
wxChoice* m_coordFormatCtrl; wxChoice* m_coordFormatCtrl;
wxCheckBox* m_useGerberX2Format; wxCheckBox* m_useGerberX2Format;
wxCheckBox* m_useGerberNetAttributes; wxCheckBox* m_useGerberNetAttributes;
wxCheckBox* m_disableApertMacros;
wxStaticBoxSizer* m_HPGLOptionsSizer; wxStaticBoxSizer* m_HPGLOptionsSizer;
wxStaticText* m_hpglPenLabel; wxStaticText* m_hpglPenLabel;
wxTextCtrl* m_hpglPenCtrl; wxTextCtrl* m_hpglPenCtrl;

View File

@ -98,6 +98,7 @@ static bool setDouble( double* aTarget, double aValue, double aMin, double aMax
PCB_PLOT_PARAMS::PCB_PLOT_PARAMS() PCB_PLOT_PARAMS::PCB_PLOT_PARAMS()
{ {
m_useGerberProtelExtensions = false; m_useGerberProtelExtensions = false;
m_gerberDisableApertMacros = false;
m_useGerberX2format = true; m_useGerberX2format = true;
m_includeGerberNetlistInfo = true; m_includeGerberNetlistInfo = true;
m_createGerberJobFile = true; m_createGerberJobFile = true;
@ -176,6 +177,9 @@ void PCB_PLOT_PARAMS::Format( OUTPUTFORMATTER* aFormatter,
aFormatter->Print( aNestLevel+1, "(%s 0x%s)\n", getTokenName( T_layerselection ), aFormatter->Print( aNestLevel+1, "(%s 0x%s)\n", getTokenName( T_layerselection ),
m_layerSelection.FmtHex().c_str() ); m_layerSelection.FmtHex().c_str() );
aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_disableapertmacros ),
m_gerberDisableApertMacros ? trueStr : falseStr );
aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_usegerberextensions ), aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_usegerberextensions ),
m_useGerberProtelExtensions ? trueStr : falseStr ); m_useGerberProtelExtensions ? trueStr : falseStr );
@ -262,6 +266,8 @@ bool PCB_PLOT_PARAMS::IsSameAs( const PCB_PLOT_PARAMS &aPcbPlotParams, bool aCom
return false; return false;
if( m_useGerberProtelExtensions != aPcbPlotParams.m_useGerberProtelExtensions ) if( m_useGerberProtelExtensions != aPcbPlotParams.m_useGerberProtelExtensions )
return false; return false;
if( m_gerberDisableApertMacros != aPcbPlotParams.m_gerberDisableApertMacros )
return false;
if( m_useGerberX2format != aPcbPlotParams.m_useGerberX2format ) if( m_useGerberX2format != aPcbPlotParams.m_useGerberX2format )
return false; return false;
if( m_includeGerberNetlistInfo != aPcbPlotParams.m_includeGerberNetlistInfo ) if( m_includeGerberNetlistInfo != aPcbPlotParams.m_includeGerberNetlistInfo )
@ -419,6 +425,10 @@ void PCB_PLOT_PARAMS_PARSER::Parse( PCB_PLOT_PARAMS* aPcbPlotParams )
} }
break; break;
case T_disableapertmacros:
aPcbPlotParams->m_gerberDisableApertMacros = parseBool();
break;
case T_usegerberextensions: case T_usegerberextensions:
aPcbPlotParams->m_useGerberProtelExtensions = parseBool(); aPcbPlotParams->m_useGerberProtelExtensions = parseBool();
break; break;

View File

@ -108,6 +108,10 @@ private:
/// Include attributes from the Gerber X2 format (chapter 5 in revision J2) /// Include attributes from the Gerber X2 format (chapter 5 in revision J2)
bool m_useGerberX2format; bool m_useGerberX2format;
/// Disable aperure macros in Gerber format (only for broken Gerber readers)
/// Ideally, should be never selected.
bool m_gerberDisableApertMacros;
/// Include netlist info (only in Gerber X2 format) (chapter ? in revision ?) /// Include netlist info (only in Gerber X2 format) (chapter ? in revision ?)
bool m_includeGerberNetlistInfo; bool m_includeGerberNetlistInfo;
@ -291,6 +295,9 @@ public:
void SetOutputDirectory( wxString aDir ) { m_outputDirectory = aDir; } void SetOutputDirectory( wxString aDir ) { m_outputDirectory = aDir; }
wxString GetOutputDirectory() const { return m_outputDirectory; } wxString GetOutputDirectory() const { return m_outputDirectory; }
void SetDisableGerberMacros( bool aDisable ) { m_gerberDisableApertMacros = aDisable; }
bool GetDisableGerberMacros() const { return m_gerberDisableApertMacros; }
void SetUseGerberX2format( bool aUse ) { m_useGerberX2format = aUse; } void SetUseGerberX2format( bool aUse ) { m_useGerberX2format = aUse; }
bool GetUseGerberX2format() const { return m_useGerberX2format; } bool GetUseGerberX2format() const { return m_useGerberX2format; }

View File

@ -1143,6 +1143,7 @@ PLOTTER* StartPlotBoard( BOARD *aBoard, PCB_PLOT_PARAMS *aPlotOpts, int aLayer,
bool useX2mode = plotOpts.GetUseGerberX2format(); bool useX2mode = plotOpts.GetUseGerberX2format();
GERBER_PLOTTER* gbrplotter = static_cast <GERBER_PLOTTER*> ( plotter ); GERBER_PLOTTER* gbrplotter = static_cast <GERBER_PLOTTER*> ( plotter );
gbrplotter->DisableApertMacros( plotOpts.GetDisableGerberMacros() );
gbrplotter->UseX2format( useX2mode ); gbrplotter->UseX2format( useX2mode );
gbrplotter->UseX2NetAttributes( plotOpts.GetIncludeGerberNetlistInfo() ); gbrplotter->UseX2NetAttributes( plotOpts.GetIncludeGerberNetlistInfo() );