diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 2791ae821d..6b6e1feb7c 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -227,6 +227,7 @@ set( COMMON_SRCS eda_pattern_match.cpp filter_reader.cpp # findkicadhelppath.cpp.notused deprecated, use searchhelpfilefullpath.cpp + gbr_metadata.cpp gestfich.cpp getrunningmicrosecs.cpp grid_tricks.cpp diff --git a/common/class_plotter.cpp b/common/class_plotter.cpp index 3150d2cedd..72220a93fa 100644 --- a/common/class_plotter.cpp +++ b/common/class_plotter.cpp @@ -393,7 +393,7 @@ void PLOTTER::segmentAsOval( const wxPoint& start, const wxPoint& end, int width size.x = KiROUND( EuclideanNorm( size ) ) + width; size.y = width; - FlashPadOval( center, size, orient, tracemode ); + FlashPadOval( center, size, orient, tracemode, NULL ); } @@ -446,7 +446,7 @@ void PLOTTER::sketchOval( const wxPoint& pos, const wxSize& aSize, double orient void PLOTTER::ThickSegment( const wxPoint& start, const wxPoint& end, int width, - EDA_DRAW_MODE_T tracemode ) + EDA_DRAW_MODE_T tracemode, void* aData ) { if( tracemode == FILLED ) { @@ -463,7 +463,7 @@ void PLOTTER::ThickSegment( const wxPoint& start, const wxPoint& end, int width, void PLOTTER::ThickArc( const wxPoint& centre, double StAngle, double EndAngle, - int radius, int width, EDA_DRAW_MODE_T tracemode ) + int radius, int width, EDA_DRAW_MODE_T tracemode, void* aData ) { if( tracemode == FILLED ) Arc( centre, StAngle, EndAngle, radius, NO_FILL, width ); @@ -479,7 +479,7 @@ void PLOTTER::ThickArc( const wxPoint& centre, double StAngle, double EndAngle, void PLOTTER::ThickRect( const wxPoint& p1, const wxPoint& p2, int width, - EDA_DRAW_MODE_T tracemode ) + EDA_DRAW_MODE_T tracemode, void* aData ) { if( tracemode == FILLED ) Rect( p1, p2, NO_FILL, width ); @@ -500,7 +500,7 @@ void PLOTTER::ThickRect( const wxPoint& p1, const wxPoint& p2, int width, } -void PLOTTER::ThickCircle( const wxPoint& pos, int diametre, int width, EDA_DRAW_MODE_T tracemode ) +void PLOTTER::ThickCircle( const wxPoint& pos, int diametre, int width, EDA_DRAW_MODE_T tracemode, void* aData ) { if( tracemode == FILLED ) Circle( pos, diametre, NO_FILL, width ); diff --git a/common/common_plotDXF_functions.cpp b/common/common_plotDXF_functions.cpp index 4da335b052..84917a81a4 100644 --- a/common/common_plotDXF_functions.cpp +++ b/common/common_plotDXF_functions.cpp @@ -347,7 +347,7 @@ void DXF_PLOTTER::Circle( const wxPoint& centre, int diameter, FILL_T fill, int * are converted to inflated polygon by aWidth/2 */ void DXF_PLOTTER::PlotPoly( const std::vector& aCornerList, - FILL_T aFill, int aWidth) + FILL_T aFill, int aWidth, void * aData ) { if( aCornerList.size() <= 1 ) return; @@ -383,7 +383,7 @@ void DXF_PLOTTER::PlotPoly( const std::vector& aCornerList, for( unsigned ii = 1; ii < aCornerList.size(); ii++ ) ThickSegment( aCornerList[ii-1], aCornerList[ii], - aWidth, FILLED ); + aWidth, FILLED, NULL ); return; } @@ -481,7 +481,7 @@ void DXF_PLOTTER::SetDash( bool dashed ) void DXF_PLOTTER::ThickSegment( const wxPoint& aStart, const wxPoint& aEnd, int aWidth, - EDA_DRAW_MODE_T aPlotMode ) + EDA_DRAW_MODE_T aPlotMode, void* aData ) { segmentAsOval( aStart, aEnd, aWidth, aPlotMode ); } @@ -521,7 +521,7 @@ void DXF_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, i * DXF oval pad: always done in sketch mode */ void DXF_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, double orient, - EDA_DRAW_MODE_T trace_mode ) + EDA_DRAW_MODE_T trace_mode, void* aData ) { wxASSERT( outputFile ); wxSize size( aSize ); @@ -543,7 +543,7 @@ void DXF_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, double * pretty if other kinds of pad aren't... */ void DXF_PLOTTER::FlashPadCircle( const wxPoint& pos, int diametre, - EDA_DRAW_MODE_T trace_mode ) + EDA_DRAW_MODE_T trace_mode, void* aData ) { wxASSERT( outputFile ); Circle( pos, diametre, NO_FILL ); @@ -554,7 +554,7 @@ void DXF_PLOTTER::FlashPadCircle( const wxPoint& pos, int diametre, * DXF rectangular pad: alwayd done in sketch mode */ void DXF_PLOTTER::FlashPadRect( const wxPoint& pos, const wxSize& padsize, - double orient, EDA_DRAW_MODE_T trace_mode ) + double orient, EDA_DRAW_MODE_T trace_mode, void* aData ) { wxASSERT( outputFile ); wxSize size; @@ -619,7 +619,7 @@ void DXF_PLOTTER::FlashPadRect( const wxPoint& pos, const wxSize& padsize, void DXF_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize, int aCornerRadius, double aOrient, - EDA_DRAW_MODE_T aTraceMode ) + EDA_DRAW_MODE_T aTraceMode, void* aData ) { SHAPE_POLY_SET outline; const int segmentToCircleCount = 64; @@ -639,7 +639,7 @@ void DXF_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize void DXF_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize, SHAPE_POLY_SET* aPolygons, - EDA_DRAW_MODE_T aTraceMode ) + EDA_DRAW_MODE_T aTraceMode, void* aData ) { for( int cnt = 0; cnt < aPolygons->OutlineCount(); ++cnt ) { @@ -659,7 +659,7 @@ void DXF_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize, * DXF trapezoidal pad: only sketch mode is supported */ void DXF_PLOTTER::FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners, - double aPadOrient, EDA_DRAW_MODE_T aTrace_Mode ) + double aPadOrient, EDA_DRAW_MODE_T aTrace_Mode, void* aData ) { wxASSERT( outputFile ); wxPoint coord[4]; /* coord actual corners of a trapezoidal trace */ @@ -708,7 +708,8 @@ void DXF_PLOTTER::Text( const wxPoint& aPos, int aWidth, bool aItalic, bool aBold, - bool aMultilineAllowed ) + bool aMultilineAllowed, + void* aData ) { // Fix me: see how to use DXF text mode for multiline texts if( aMultilineAllowed && !aText.Contains( wxT( "\n" ) ) ) diff --git a/common/common_plotGERBER_functions.cpp b/common/common_plotGERBER_functions.cpp index 4d8e28ee0f..8ce8b432a9 100644 --- a/common/common_plotGERBER_functions.cpp +++ b/common/common_plotGERBER_functions.cpp @@ -40,12 +40,15 @@ #include +#include + GERBER_PLOTTER::GERBER_PLOTTER() { - workFile = 0; - finalFile = 0; + workFile = NULL; + finalFile = NULL; currentAperture = apertures.end(); + m_apertureAttribute = 0; // number of digits after the point (number of digits of the mantissa // Be carefull: the Gerber coordinates are stored in an integer @@ -56,6 +59,8 @@ GERBER_PLOTTER::GERBER_PLOTTER() // happen easily. m_gerberUnitInch = false; m_gerberUnitFmt = 6; + m_useX2Attributes = false; + m_useNetAttributes = true; } @@ -102,6 +107,56 @@ void GERBER_PLOTTER::emitDcode( const DPOINT& pt, int dcode ) } +void GERBER_PLOTTER::clearNetAttribute() +{ + // disable a Gerber net attribute (exists only in X2 with net attributes mode). + if( m_objectAttributesDictionnary.empty() ) // No net attribute or not X2 mode + return; + + // Remove all net attributes from object attributes dictionnary + fputs( "%TD*%\n", outputFile ); + + m_objectAttributesDictionnary.clear(); +} + + +void GERBER_PLOTTER::StartBlock( void* aData ) +{ + // Currently, it is the same as EndBlock(): clear all aperture net attributes + EndBlock( aData ); +} + + +void GERBER_PLOTTER::EndBlock( void* aData ) +{ + // Remove all net attributes from object attributes dictionnary + clearNetAttribute(); +} + + +void GERBER_PLOTTER::formatNetAttribute( GBR_NETLIST_METADATA* aData ) +{ + // 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 || !m_useX2Attributes || !m_useNetAttributes ) + return; + + bool clearDict; + std::string short_attribute_string; + + if( !FormatNetAttribute( short_attribute_string, m_objectAttributesDictionnary, + aData, clearDict ) ) + return; + + if( clearDict ) + clearNetAttribute(); + + if( !short_attribute_string.empty() ) + fputs( short_attribute_string.c_str(), outputFile ); +} + + bool GERBER_PLOTTER::StartPlot() { wxASSERT( outputFile ); @@ -156,7 +211,7 @@ bool GERBER_PLOTTER::StartPlot() fputs( "G04 APERTURE LIST*\n", outputFile ); /* Select the default aperture */ - SetCurrentLineWidth( -1 ); + SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH, 0 ); return true; } @@ -206,8 +261,11 @@ void GERBER_PLOTTER::SetDefaultLineWidth( int width ) } -void GERBER_PLOTTER::SetCurrentLineWidth( int width ) +void GERBER_PLOTTER::SetCurrentLineWidth( int width, void* aData ) { + if( width == DO_NOT_SET_LINE_WIDTH ) + return; + int pen_width; if( width > 0 ) @@ -215,13 +273,16 @@ void GERBER_PLOTTER::SetCurrentLineWidth( int width ) else pen_width = defaultPenWidth; - selectAperture( wxSize( pen_width, pen_width ), APERTURE::Plotting ); + GBR_METADATA* gbr_metadata = static_cast( aData ); + int aperture_attribute = gbr_metadata ? gbr_metadata->GetApertureAttrib() : 0; + + selectAperture( wxSize( pen_width, pen_width ), APERTURE::Plotting, aperture_attribute ); currentPenWidth = pen_width; } -std::vector::iterator GERBER_PLOTTER::getAperture( const wxSize& size, - APERTURE::APERTURE_TYPE type ) +std::vector::iterator GERBER_PLOTTER::getAperture( const wxSize& aSize, + APERTURE::APERTURE_TYPE aType, int aApertureAttribute ) { int last_D_code = 9; @@ -230,36 +291,45 @@ std::vector::iterator GERBER_PLOTTER::getAperture( const wxSize& while( tool != apertures.end() ) { - last_D_code = tool->DCode; + last_D_code = tool->m_DCode; - if( (tool->Type == type) && (tool->Size == size) ) + if( (tool->m_Type == aType) && (tool->m_Size == aSize) && (tool->m_ApertureAttribute == aApertureAttribute) ) return tool; - tool++; + ++tool; } // Allocate a new aperture APERTURE new_tool; - new_tool.Size = size; - new_tool.Type = type; - new_tool.DCode = last_D_code + 1; + new_tool.m_Size = aSize; + new_tool.m_Type = aType; + new_tool.m_DCode = last_D_code + 1; + new_tool.m_ApertureAttribute = aApertureAttribute; + apertures.push_back( new_tool ); + return apertures.end() - 1; } -void GERBER_PLOTTER::selectAperture( const wxSize& size, - APERTURE::APERTURE_TYPE type ) +void GERBER_PLOTTER::selectAperture( const wxSize& aSize, + APERTURE::APERTURE_TYPE aType, + int aApertureAttribute ) { - wxASSERT( outputFile ); + bool change = ( currentAperture == apertures.end() ) || + ( currentAperture->m_Type != aType ) || + ( currentAperture->m_Size != aSize ); - if( ( currentAperture == apertures.end() ) - || ( currentAperture->Type != type ) - || ( currentAperture->Size != size ) ) + if( !m_useX2Attributes || !m_useNetAttributes ) + aApertureAttribute = 0; + else + change = change || ( currentAperture->m_ApertureAttribute != aApertureAttribute ); + + if( change ) { // Pick an existing aperture or create a new one - currentAperture = getAperture( size, type ); - fprintf( outputFile, "D%d*\n", currentAperture->DCode ); + currentAperture = getAperture( aSize, aType, aApertureAttribute ); + fprintf( outputFile, "D%d*\n", currentAperture->m_DCode ); } } @@ -271,7 +341,7 @@ void GERBER_PLOTTER::writeApertureList() // Init for( std::vector::iterator tool = apertures.begin(); - tool != apertures.end(); tool++ ) + tool != apertures.end(); ++tool ) { // apertude sizes are in inch or mm, regardless the // coordinates format @@ -280,7 +350,13 @@ void GERBER_PLOTTER::writeApertureList() if(! m_gerberUnitInch ) fscale *= 25.4; // size in mm - char* text = cbuf + sprintf( cbuf, "%%ADD%d", tool->DCode ); + int attribute = tool->m_ApertureAttribute; + + if( attribute != m_apertureAttribute ) + fputs( GBR_APERTURE_METADATA::FormatAttribute( + (GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB) attribute ).c_str(), outputFile ); + + char* text = cbuf + sprintf( cbuf, "%%ADD%d", tool->m_DCode ); /* Please note: the Gerber specs for mass parameters say that exponential syntax is *not* allowed and the decimal point should @@ -289,30 +365,41 @@ void GERBER_PLOTTER::writeApertureList() can't remove trailing zeros but thats not a problem, since nothing forbid it (the file is only slightly longer) */ - switch( tool->Type ) + switch( tool->m_Type ) { case APERTURE::Circle: - sprintf( text, "C,%#f*%%\n", tool->Size.x * fscale ); + sprintf( text, "C,%#f*%%\n", tool->m_Size.x * fscale ); break; case APERTURE::Rect: sprintf( text, "R,%#fX%#f*%%\n", - tool->Size.x * fscale, - tool->Size.y * fscale ); + tool->m_Size.x * fscale, + tool->m_Size.y * fscale ); break; case APERTURE::Plotting: - sprintf( text, "C,%#f*%%\n", tool->Size.x * fscale ); + sprintf( text, "C,%#f*%%\n", tool->m_Size.x * fscale ); break; case APERTURE::Oval: sprintf( text, "O,%#fX%#f*%%\n", - tool->Size.x * fscale, - tool->Size.y * fscale ); + tool->m_Size.x * fscale, + tool->m_Size.y * fscale ); break; } fputs( cbuf, outputFile ); + + m_apertureAttribute = attribute; + + // Currently reset the aperture attribute. Perhaps a better optimization + // is to store the last attribute + if( attribute ) + { + fputs( "%TD*%\n", outputFile ); + m_apertureAttribute = 0; + } + } } @@ -366,11 +453,11 @@ void GERBER_PLOTTER::Circle( const wxPoint& aCenter, int aDiameter, FILL_T aFill void GERBER_PLOTTER::Arc( const wxPoint& aCenter, double aStAngle, double aEndAngle, int aRadius, FILL_T aFill, int aWidth ) { - wxASSERT( outputFile ); + SetCurrentLineWidth( aWidth ); + wxPoint start, end; start.x = aCenter.x + KiROUND( cosdecideg( aRadius, aStAngle ) ); start.y = aCenter.y - KiROUND( sindecideg( aRadius, aStAngle ) ); - SetCurrentLineWidth( aWidth ); MoveTo( start ); end.x = aCenter.x + KiROUND( cosdecideg( aRadius, aEndAngle ) ); end.y = aCenter.y - KiROUND( sindecideg( aRadius, aEndAngle ) ); @@ -392,7 +479,7 @@ void GERBER_PLOTTER::Arc( const wxPoint& aCenter, double aStAngle, double aEndAn void GERBER_PLOTTER:: PlotPoly( const std::vector< wxPoint >& aCornerList, - FILL_T aFill, int aWidth ) + FILL_T aFill, int aWidth, void * aData ) { if( aCornerList.size() <= 1 ) return; @@ -400,8 +487,12 @@ void GERBER_PLOTTER:: PlotPoly( const std::vector< wxPoint >& aCornerList, // Gerber format does not know filled polygons with thick outline // Therefore, to plot a filled polygon with outline having a thickness, // one should plot outline as thick segments + GBR_METADATA* gbr_metadata = static_cast( aData ); - SetCurrentLineWidth( aWidth ); + SetCurrentLineWidth( aWidth, gbr_metadata ); + + if( gbr_metadata ) + formatNetAttribute( &gbr_metadata->m_NetlistMetadata ); if( aFill ) { @@ -433,31 +524,137 @@ void GERBER_PLOTTER:: PlotPoly( const std::vector< wxPoint >& aCornerList, } -void GERBER_PLOTTER::FlashPadCircle( const wxPoint& pos, int diametre, EDA_DRAW_MODE_T trace_mode ) +void GERBER_PLOTTER::ThickSegment( const wxPoint& start, const wxPoint& end, int width, + EDA_DRAW_MODE_T tracemode, void* aData ) +{ + if( tracemode == FILLED ) + { + GBR_METADATA *gbr_metadata = static_cast( aData ); + SetCurrentLineWidth( width, gbr_metadata ); + + if( gbr_metadata ) + formatNetAttribute( &gbr_metadata->m_NetlistMetadata ); + + MoveTo( start ); + FinishTo( end ); + } + else + { + SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH ); + segmentAsOval( start, end, width, tracemode ); + } +} + +void GERBER_PLOTTER::ThickArc( const wxPoint& centre, double StAngle, double EndAngle, + int radius, int width, EDA_DRAW_MODE_T tracemode, void* aData ) +{ + GBR_METADATA *gbr_metadata = static_cast( aData ); + SetCurrentLineWidth( width, gbr_metadata ); + + if( gbr_metadata ) + formatNetAttribute( &gbr_metadata->m_NetlistMetadata ); + + if( tracemode == FILLED ) + Arc( centre, StAngle, EndAngle, radius, NO_FILL, DO_NOT_SET_LINE_WIDTH ); + else + { + SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH ); + Arc( centre, StAngle, EndAngle, + radius - ( width - currentPenWidth ) / 2, + NO_FILL, DO_NOT_SET_LINE_WIDTH ); + Arc( centre, StAngle, EndAngle, + radius + ( width - currentPenWidth ) / 2, NO_FILL, + DO_NOT_SET_LINE_WIDTH ); + } +} + + +void GERBER_PLOTTER::ThickRect( const wxPoint& p1, const wxPoint& p2, int width, + EDA_DRAW_MODE_T tracemode, void* aData ) +{ + GBR_METADATA *gbr_metadata = static_cast( aData ); + SetCurrentLineWidth( width, gbr_metadata ); + + if( gbr_metadata ) + formatNetAttribute( &gbr_metadata->m_NetlistMetadata ); + + if( tracemode == FILLED ) + Rect( p1, p2, NO_FILL, DO_NOT_SET_LINE_WIDTH ); + else + { + SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH ); + wxPoint offsetp1( p1.x - (width - currentPenWidth) / 2, + p1.y - (width - currentPenWidth) / 2 ); + wxPoint offsetp2( p2.x + (width - currentPenWidth) / 2, + p2.y + (width - currentPenWidth) / 2 ); + Rect( offsetp1, offsetp2, NO_FILL, -1 ); + offsetp1.x += (width - currentPenWidth); + offsetp1.y += (width - currentPenWidth); + offsetp2.x -= (width - currentPenWidth); + offsetp2.y -= (width - currentPenWidth); + Rect( offsetp1, offsetp2, NO_FILL, DO_NOT_SET_LINE_WIDTH ); + } +} + + +void GERBER_PLOTTER::ThickCircle( const wxPoint& pos, int diametre, int width, + EDA_DRAW_MODE_T tracemode, void* aData ) +{ + GBR_METADATA *gbr_metadata = static_cast( aData ); + SetCurrentLineWidth( width, gbr_metadata ); + + if( gbr_metadata ) + formatNetAttribute( &gbr_metadata->m_NetlistMetadata ); + + if( tracemode == FILLED ) + Circle( pos, diametre, NO_FILL, DO_NOT_SET_LINE_WIDTH ); + else + { + SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH, gbr_metadata ); + Circle( pos, diametre - (width - currentPenWidth), + NO_FILL, DO_NOT_SET_LINE_WIDTH ); + Circle( pos, diametre + (width - currentPenWidth), + NO_FILL, DO_NOT_SET_LINE_WIDTH ); + } +} + + +void GERBER_PLOTTER::FlashPadCircle( const wxPoint& pos, int diametre, EDA_DRAW_MODE_T trace_mode, void* aData ) { - wxASSERT( outputFile ); wxSize size( diametre, diametre ); + GBR_METADATA* gbr_metadata = static_cast( aData ); if( trace_mode == SKETCH ) { - SetCurrentLineWidth( -1 ); - Circle( pos, diametre - currentPenWidth, NO_FILL ); + SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH, gbr_metadata ); + + if( gbr_metadata ) + formatNetAttribute( &gbr_metadata->m_NetlistMetadata ); + + Circle( pos, diametre - currentPenWidth, NO_FILL, DO_NOT_SET_LINE_WIDTH ); } else { DPOINT pos_dev = userToDeviceCoordinates( pos ); - selectAperture( size, APERTURE::Circle ); + + int aperture_attrib = gbr_metadata ? gbr_metadata->GetApertureAttrib() : 0; + selectAperture( size, APERTURE::Circle, aperture_attrib ); + + if( gbr_metadata ) + formatNetAttribute( &gbr_metadata->m_NetlistMetadata ); + emitDcode( pos_dev, 3 ); } } void GERBER_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, double orient, - EDA_DRAW_MODE_T trace_mode ) + EDA_DRAW_MODE_T trace_mode, void* aData ) { wxASSERT( outputFile ); int x0, y0, x1, y1, delta; wxSize size( aSize ); + GBR_METADATA* gbr_metadata = static_cast( aData ); /* Plot a flashed shape. */ if( ( orient == 0 || orient == 900 || orient == 1800 || orient == 2700 ) @@ -467,7 +664,12 @@ void GERBER_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, doub std::swap( size.x, size.y ); DPOINT pos_dev = userToDeviceCoordinates( pos ); - selectAperture( size, APERTURE::Oval ); + int aperture_attrib = gbr_metadata ? gbr_metadata->GetApertureAttrib() : 0; + selectAperture( size, APERTURE::Oval, aperture_attrib ); + + if( gbr_metadata ) + formatNetAttribute( &gbr_metadata->m_NetlistMetadata ); + emitDcode( pos_dev, 3 ); } else /* Plot pad as a segment. */ @@ -494,9 +696,24 @@ void GERBER_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, doub y1 = delta / 2; RotatePoint( &x0, &y0, orient ); RotatePoint( &x1, &y1, orient ); + GBR_METADATA metadata; + + if( gbr_metadata ) + { + metadata = *gbr_metadata; + metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_CONDUCTOR ); + + wxString attrname( ".P" ); + metadata.m_NetlistMetadata.ClearAttribute( &attrname ); // not allowed on inner layers + } + ThickSegment( wxPoint( pos.x + x0, pos.y + y0 ), wxPoint( pos.x + x1, pos.y + y1 ), - size.x, trace_mode ); + size.x, trace_mode, &metadata ); + + // Now, flash a pad anchor, if a netlist attribute is set + if( aData ) + FlashPadCircle( pos, size.x, trace_mode, aData ); } else { @@ -507,11 +724,12 @@ void GERBER_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, doub void GERBER_PLOTTER::FlashPadRect( const wxPoint& pos, const wxSize& aSize, - double orient, EDA_DRAW_MODE_T trace_mode ) + double orient, EDA_DRAW_MODE_T trace_mode, void* aData ) { wxASSERT( outputFile ); wxSize size( aSize ); + GBR_METADATA* gbr_metadata = static_cast( aData ); // Plot as an aperture flash switch( int( orient ) ) @@ -525,7 +743,11 @@ void GERBER_PLOTTER::FlashPadRect( const wxPoint& pos, const wxSize& aSize, case 1800: if( trace_mode == SKETCH ) { - SetCurrentLineWidth( -1 ); + SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH, gbr_metadata ); + + if( gbr_metadata ) + formatNetAttribute( &gbr_metadata->m_NetlistMetadata ); + Rect( wxPoint( pos.x - (size.x - currentPenWidth) / 2, pos.y - (size.y - currentPenWidth) / 2 ), wxPoint( pos.x + (size.x - currentPenWidth) / 2, @@ -535,7 +757,12 @@ void GERBER_PLOTTER::FlashPadRect( const wxPoint& pos, const wxSize& aSize, else { DPOINT pos_dev = userToDeviceCoordinates( pos ); - selectAperture( size, APERTURE::Rect ); + int aperture_attrib = gbr_metadata ? gbr_metadata->GetApertureAttrib() : 0; + selectAperture( size, APERTURE::Rect, aperture_attrib ); + + if( gbr_metadata ) + formatNetAttribute( &gbr_metadata->m_NetlistMetadata ); + emitDcode( pos_dev, 3 ); } break; @@ -559,7 +786,7 @@ void GERBER_PLOTTER::FlashPadRect( const wxPoint& pos, const wxSize& aSize, coord[3].x = size.x/2; // lower right coord[3].y = size.y/2; - FlashPadTrapez( pos, coord, orient, trace_mode ); + FlashPadTrapez( pos, coord, orient, trace_mode, aData ); } break; } @@ -567,7 +794,7 @@ void GERBER_PLOTTER::FlashPadRect( const wxPoint& pos, const wxSize& aSize, void GERBER_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize, int aCornerRadius, double aOrient, - EDA_DRAW_MODE_T aTraceMode ) + EDA_DRAW_MODE_T aTraceMode, void* aData ) { // Currently, a Pad RoundRect is plotted as polygon. @@ -588,22 +815,50 @@ void GERBER_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aS // Close polygon cornerList.push_back( cornerList[0] ); - PlotPoly( cornerList, ( aTraceMode == FILLED ) ? FILLED_SHAPE : NO_FILL ); + GBR_METADATA gbr_metadata; + + if( aData ) + { + gbr_metadata = *static_cast( aData ); + gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_CONDUCTOR ); + + wxString attrname( ".P" ); + gbr_metadata.m_NetlistMetadata.ClearAttribute( &attrname ); // not allowed on inner layers + } + + PlotPoly( cornerList, ( aTraceMode == FILLED ) ? FILLED_SHAPE : NO_FILL, USE_DEFAULT_LINE_WIDTH, &gbr_metadata ); + + // Now, flash a pad anchor, if a netlist attribute is set + // (remove me when a Aperture macro will be used) + if( aData && aTraceMode == FILLED ) + { + int diameter = std::min( aSize.x, aSize.y ); + FlashPadCircle( aPadPos, diameter, aTraceMode , aData ); + } } void GERBER_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize, SHAPE_POLY_SET* aPolygons, - EDA_DRAW_MODE_T aTraceMode ) + EDA_DRAW_MODE_T aTraceMode, void* aData ) { // A Pad custom is plotted as polygon. -#if 1 + // A flashed circle @aPadPos is added (anchor pad) // However, because the anchor pad can be circle or rect, we use only - // a circle not bigger tahn the rect. - // the main purpose is to show a flashed DCode as pad anchor - FlashPadCircle( aPadPos, std::min( aSize.x, aSize.x ), aTraceMode ); -#endif + // a circle not bigger than the rect. + // the main purpose is to print a flashed DCode as pad anchor + FlashPadCircle( aPadPos, std::min( aSize.x, aSize.x ), aTraceMode, aData ); + GBR_METADATA gbr_metadata; + + if( aData ) + { + gbr_metadata = *static_cast( aData ); + gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_CONDUCTOR ); + + wxString attrname( ".P" ); + gbr_metadata.m_NetlistMetadata.ClearAttribute( &attrname ); // not allowed on inner layers + } std::vector< wxPoint > cornerList; @@ -618,13 +873,13 @@ void GERBER_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize // Close polygon cornerList.push_back( cornerList[0] ); - PlotPoly( cornerList, ( aTraceMode == FILLED ) ? FILLED_SHAPE : NO_FILL ); + PlotPoly( cornerList, ( aTraceMode == FILLED ) ? FILLED_SHAPE : NO_FILL, USE_DEFAULT_LINE_WIDTH, &gbr_metadata ); } } void GERBER_PLOTTER::FlashPadTrapez( const wxPoint& aPadPos, const wxPoint* aCorners, - double aPadOrient, EDA_DRAW_MODE_T aTrace_Mode ) + double aPadOrient, EDA_DRAW_MODE_T aTrace_Mode, void* aData ) { // Currently, a Pad Trapezoid is plotted as polygon. @@ -636,6 +891,25 @@ void GERBER_PLOTTER::FlashPadTrapez( const wxPoint& aPadPos, const wxPoint* aCo for( int ii = 0; ii < 4; ii++ ) cornerList.push_back( aCorners[ii] ); + // Now, flash a pad anchor, if a netlist attribute is set + // (remove me when a Aperture macro will be used) + if( aData && (aTrace_Mode==FILLED) ) + { + // Calculate the radius of the circle inside the shape + // It is the smaller dist from shape pos to edges + int radius = INT_MAX; + + for( unsigned ii = 0, jj = cornerList.size()-1; ii < cornerList.size(); + jj = ii, ii++ ) + { + SEG segment( aCorners[ii], aCorners[jj] ); + int dist = segment.LineDistance( VECTOR2I( 0, 0) ); + radius = std::min( radius, dist ); + } + + FlashPadCircle( aPadPos, radius*2, aTrace_Mode, aData ); + } + // Draw the polygon and fill the interior as required for( unsigned ii = 0; ii < 4; ii++ ) { @@ -645,9 +919,36 @@ void GERBER_PLOTTER::FlashPadTrapez( const wxPoint& aPadPos, const wxPoint* aCo // Close the polygon cornerList.push_back( cornerList[0] ); + GBR_METADATA* gbr_metadata = static_cast( aData ); - SetCurrentLineWidth( -1 ); - PlotPoly( cornerList, aTrace_Mode==FILLED ? FILLED_SHAPE : NO_FILL ); + GBR_METADATA metadata; + + if( gbr_metadata ) + { + metadata = *gbr_metadata; + metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_CONDUCTOR ); + wxString attrname( ".P" ); + metadata.m_NetlistMetadata.ClearAttribute( &attrname ); // not allowed on inner layers + } + + SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH, &metadata ); + PlotPoly( cornerList, aTrace_Mode==FILLED ? FILLED_SHAPE : NO_FILL, USE_DEFAULT_LINE_WIDTH, &metadata ); +} + + +void GERBER_PLOTTER::Text( const wxPoint& aPos, enum EDA_COLOR_T aColor, + const wxString& aText, double aOrient, const wxSize& aSize, + enum EDA_TEXT_HJUSTIFY_T aH_justify, enum EDA_TEXT_VJUSTIFY_T aV_justify, + int aWidth, bool aItalic, bool aBold, bool aMultilineAllowed, + void* aData ) +{ + GBR_METADATA* gbr_metadata = static_cast( aData ); + + if( gbr_metadata ) + formatNetAttribute( &gbr_metadata->m_NetlistMetadata ); + + PLOTTER::Text( aPos, aColor, aText, aOrient, aSize, + aH_justify, aV_justify, aWidth, aItalic, aBold, aMultilineAllowed, aData ); } diff --git a/common/common_plotHPGL_functions.cpp b/common/common_plotHPGL_functions.cpp index ba9bb8ad96..7d8f61a658 100644 --- a/common/common_plotHPGL_functions.cpp +++ b/common/common_plotHPGL_functions.cpp @@ -315,7 +315,7 @@ void HPGL_PLOTTER::Circle( const wxPoint& centre, int diameter, FILL_T fill, */ void HPGL_PLOTTER::PlotPoly( const std::vector& aCornerList, - FILL_T aFill, int aWidth ) + FILL_T aFill, int aWidth, void * aData ) { if( aCornerList.size() <= 1 ) return; @@ -433,7 +433,7 @@ void HPGL_PLOTTER::SetDash( bool dashed ) void HPGL_PLOTTER::ThickSegment( const wxPoint& start, const wxPoint& end, - int width, EDA_DRAW_MODE_T tracemode ) + int width, EDA_DRAW_MODE_T tracemode, void* aData ) { wxASSERT( outputFile ); wxPoint center; @@ -496,7 +496,7 @@ void HPGL_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, /* Plot oval pad. */ void HPGL_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, double orient, - EDA_DRAW_MODE_T trace_mode ) + EDA_DRAW_MODE_T trace_mode, void* aData ) { wxASSERT( outputFile ); int deltaxy, cx, cy; @@ -516,13 +516,13 @@ void HPGL_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, double if( trace_mode == FILLED ) { FlashPadRect( pos, wxSize( size.x, deltaxy + KiROUND( penDiameter ) ), - orient, trace_mode ); + orient, trace_mode, aData ); cx = 0; cy = deltaxy / 2; RotatePoint( &cx, &cy, orient ); - FlashPadCircle( wxPoint( cx + pos.x, cy + pos.y ), size.x, trace_mode ); + FlashPadCircle( wxPoint( cx + pos.x, cy + pos.y ), size.x, trace_mode, aData ); cx = 0; cy = -deltaxy / 2; RotatePoint( &cx, &cy, orient ); - FlashPadCircle( wxPoint( cx + pos.x, cy + pos.y ), size.x, trace_mode ); + FlashPadCircle( wxPoint( cx + pos.x, cy + pos.y ), size.x, trace_mode, aData ); } else // Plot in outline mode. { @@ -534,7 +534,7 @@ void HPGL_PLOTTER::FlashPadOval( const wxPoint& pos, const wxSize& aSize, double /* Plot round pad or via. */ void HPGL_PLOTTER::FlashPadCircle( const wxPoint& pos, int diametre, - EDA_DRAW_MODE_T trace_mode ) + EDA_DRAW_MODE_T trace_mode, void* aData ) { wxASSERT( outputFile ); DPOINT pos_dev = userToDeviceCoordinates( pos ); @@ -574,7 +574,7 @@ void HPGL_PLOTTER::FlashPadCircle( const wxPoint& pos, int diametre, void HPGL_PLOTTER::FlashPadRect( const wxPoint& pos, const wxSize& padsize, - double orient, EDA_DRAW_MODE_T trace_mode ) + double orient, EDA_DRAW_MODE_T trace_mode, void* aData ) { // Build rect polygon: std::vector corners; @@ -611,7 +611,7 @@ void HPGL_PLOTTER::FlashPadRect( const wxPoint& pos, const wxSize& padsize, void HPGL_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize, int aCornerRadius, double aOrient, - EDA_DRAW_MODE_T aTraceMode ) + EDA_DRAW_MODE_T aTraceMode, void* aData ) { SHAPE_POLY_SET outline; const int segmentToCircleCount = 32; @@ -647,7 +647,7 @@ void HPGL_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSiz void HPGL_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize, SHAPE_POLY_SET* aPolygons, - EDA_DRAW_MODE_T aTraceMode ) + EDA_DRAW_MODE_T aTraceMode, void* aData ) { std::vector< wxPoint > cornerList; @@ -667,7 +667,7 @@ void HPGL_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize, void HPGL_PLOTTER::FlashPadTrapez( const wxPoint& aPadPos, const wxPoint* aCorners, - double aPadOrient, EDA_DRAW_MODE_T aTrace_Mode ) + double aPadOrient, EDA_DRAW_MODE_T aTrace_Mode, void* aData ) { std::vector< wxPoint > cornerList; cornerList.reserve( 4 ); diff --git a/common/common_plotPDF_functions.cpp b/common/common_plotPDF_functions.cpp index 3fc8c4fca7..8621004cd5 100644 --- a/common/common_plotPDF_functions.cpp +++ b/common/common_plotPDF_functions.cpp @@ -94,7 +94,7 @@ void PDF_PLOTTER::SetViewport( const wxPoint& aOffset, double aIusPerDecimil, * no outline thickness * use in this case pen width = 1 does not actally change the polygon */ -void PDF_PLOTTER::SetCurrentLineWidth( int width ) +void PDF_PLOTTER::SetCurrentLineWidth( int width, void* aData ) { wxASSERT( workFile ); int pen_width; @@ -263,7 +263,7 @@ void PDF_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, i * Polygon plotting for PDF. Everything is supported */ void PDF_PLOTTER::PlotPoly( const std::vector< wxPoint >& aCornerList, - FILL_T aFill, int aWidth ) + FILL_T aFill, int aWidth, void * aData ) { wxASSERT( workFile ); if( aCornerList.size() <= 1 ) @@ -756,7 +756,8 @@ void PDF_PLOTTER::Text( const wxPoint& aPos, int aWidth, bool aItalic, bool aBold, - bool aMultilineAllowed ) + bool aMultilineAllowed, + void* aData ) { // PDF files do not like 0 sized texts which create broken files. if( aSize.x == 0 || aSize.y == 0 ) @@ -781,7 +782,7 @@ void PDF_PLOTTER::Text( const wxPoint& aPos, &ctm_d, &ctm_e, &ctm_f, &heightFactor ); SetColor( aColor ); - SetCurrentLineWidth( aWidth ); + SetCurrentLineWidth( aWidth, aData ); /* We use the full CTM instead of the text matrix because the same coordinate system will be used for the overlining. Also the %f diff --git a/common/common_plotPS_functions.cpp b/common/common_plotPS_functions.cpp index 2aa83be026..4a245511b6 100644 --- a/common/common_plotPS_functions.cpp +++ b/common/common_plotPS_functions.cpp @@ -90,7 +90,7 @@ void PSLIKE_PLOTTER::SetColor( EDA_COLOR_T color ) void PSLIKE_PLOTTER::FlashPadOval( const wxPoint& aPadPos, const wxSize& aSize, - double aPadOrient, EDA_DRAW_MODE_T aTraceMode ) + double aPadOrient, EDA_DRAW_MODE_T aTraceMode, void* aData ) { wxASSERT( outputFile ); int x0, y0, x1, y1, delta; @@ -113,14 +113,14 @@ void PSLIKE_PLOTTER::FlashPadOval( const wxPoint& aPadPos, const wxSize& aSize, if( aTraceMode == FILLED ) ThickSegment( wxPoint( aPadPos.x + x0, aPadPos.y + y0 ), - wxPoint( aPadPos.x + x1, aPadPos.y + y1 ), size.x, aTraceMode ); + wxPoint( aPadPos.x + x1, aPadPos.y + y1 ), size.x, aTraceMode, NULL ); else sketchOval( aPadPos, size, aPadOrient, -1 ); } void PSLIKE_PLOTTER::FlashPadCircle( const wxPoint& aPadPos, int aDiameter, - EDA_DRAW_MODE_T aTraceMode ) + EDA_DRAW_MODE_T aTraceMode, void* aData ) { if( aTraceMode == FILLED ) Circle( aPadPos, aDiameter, FILLED_SHAPE, 0 ); @@ -141,7 +141,7 @@ void PSLIKE_PLOTTER::FlashPadCircle( const wxPoint& aPadPos, int aDiameter, void PSLIKE_PLOTTER::FlashPadRect( const wxPoint& aPadPos, const wxSize& aSize, - double aPadOrient, EDA_DRAW_MODE_T aTraceMode ) + double aPadOrient, EDA_DRAW_MODE_T aTraceMode, void* aData ) { static std::vector< wxPoint > cornerList; wxSize size( aSize ); @@ -191,7 +191,7 @@ void PSLIKE_PLOTTER::FlashPadRect( const wxPoint& aPadPos, const wxSize& aSize, void PSLIKE_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize, int aCornerRadius, double aOrient, - EDA_DRAW_MODE_T aTraceMode ) + EDA_DRAW_MODE_T aTraceMode, void* aData ) { wxSize size( aSize ); @@ -228,7 +228,7 @@ void PSLIKE_PLOTTER::FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aS void PSLIKE_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize, SHAPE_POLY_SET* aPolygons, - EDA_DRAW_MODE_T aTraceMode ) + EDA_DRAW_MODE_T aTraceMode, void* aData ) { wxSize size( aSize ); @@ -261,7 +261,7 @@ void PSLIKE_PLOTTER::FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize } void PSLIKE_PLOTTER::FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners, - double aPadOrient, EDA_DRAW_MODE_T aTraceMode ) + double aPadOrient, EDA_DRAW_MODE_T aTraceMode, void* aData ) { static std::vector< wxPoint > cornerList; cornerList.clear(); @@ -515,7 +515,7 @@ void PSLIKE_PLOTTER::computeTextParameters( const wxPoint& aPos, /* Set the current line width (in IUs) for the next plot */ -void PS_PLOTTER::SetCurrentLineWidth( int width ) +void PS_PLOTTER::SetCurrentLineWidth( int width, void* aData ) { wxASSERT( outputFile ); int pen_width; @@ -614,7 +614,7 @@ void PS_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, void PS_PLOTTER::PlotPoly( const std::vector< wxPoint >& aCornerList, - FILL_T aFill, int aWidth ) + FILL_T aFill, int aWidth, void * aData ) { if( aCornerList.size() <= 1 ) return; @@ -936,7 +936,8 @@ void PS_PLOTTER::Text( const wxPoint& aPos, int aWidth, bool aItalic, bool aBold, - bool aMultilineAllowed ) + bool aMultilineAllowed, + void* aData ) { SetCurrentLineWidth( aWidth ); SetColor( aColor ); diff --git a/common/common_plotSVG_functions.cpp b/common/common_plotSVG_functions.cpp index fa05f306c9..5c0973bc19 100644 --- a/common/common_plotSVG_functions.cpp +++ b/common/common_plotSVG_functions.cpp @@ -244,7 +244,7 @@ void SVG_PLOTTER::setSVGPlotStyle() /* Set the current line width (in IUs) for the next plot */ -void SVG_PLOTTER::SetCurrentLineWidth( int width ) +void SVG_PLOTTER::SetCurrentLineWidth( int width, void* aData ) { int pen_width; @@ -439,7 +439,7 @@ void SVG_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, i void SVG_PLOTTER::PlotPoly( const std::vector& aCornerList, - FILL_T aFill, int aWidth ) + FILL_T aFill, int aWidth, void * aData ) { if( aCornerList.size() <= 1 ) return; @@ -611,7 +611,8 @@ void SVG_PLOTTER::Text( const wxPoint& aPos, int aWidth, bool aItalic, bool aBold, - bool aMultilineAllowed ) + bool aMultilineAllowed, + void* aData ) { setFillMode( NO_FILL ); SetColor( aColor ); diff --git a/common/drawtxt.cpp b/common/drawtxt.cpp index 7ab163f8d4..85e6449015 100644 --- a/common/drawtxt.cpp +++ b/common/drawtxt.cpp @@ -206,7 +206,7 @@ void DrawGraphicHaloText( EDA_RECT* aClipBox, wxDC * aDC, } /** - * Function PlotGraphicText + * Function PLOTTER::Text * same as DrawGraphicText, but plot graphic text insteed of draw it * @param aPos = text position (according to aH_justify, aV_justify) * @param aColor (enum EDA_COLOR_T) = text color @@ -232,7 +232,8 @@ void PLOTTER::Text( const wxPoint& aPos, int aWidth, bool aItalic, bool aBold, - bool aMultilineAllowed ) + bool aMultilineAllowed, + void* aData ) { int textPensize = aWidth; @@ -244,7 +245,7 @@ void PLOTTER::Text( const wxPoint& aPos, else textPensize = -Clamp_Text_PenSize( -aWidth, aSize, aBold ); - SetCurrentLineWidth( textPensize ); + SetCurrentLineWidth( textPensize, aData ); if( aColor >= 0 ) SetColor( aColor ); @@ -255,5 +256,5 @@ void PLOTTER::Text( const wxPoint& aPos, textPensize, aItalic, aBold, NULL, this ); if( aWidth != textPensize ) - SetCurrentLineWidth( aWidth ); + SetCurrentLineWidth( aWidth, aData ); } diff --git a/common/gbr_metadata.cpp b/common/gbr_metadata.cpp new file mode 100644 index 0000000000..65609f3601 --- /dev/null +++ b/common/gbr_metadata.cpp @@ -0,0 +1,291 @@ +/* + * 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 +#include + + +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; +} diff --git a/common/lset.cpp b/common/lset.cpp index 4e4248dd7f..a6f8c2ede2 100644 --- a/common/lset.cpp +++ b/common/lset.cpp @@ -665,6 +665,13 @@ LSET LSET::AllNonCuMask() } +LSET LSET::ExternalCuMask() +{ + static const LSET saved( 2, F_Cu, B_Cu ); + return saved; +} + + LSET LSET::AllLayersMask() { static const LSET saved = LSET().set(); @@ -674,20 +681,30 @@ LSET LSET::AllLayersMask() LSET LSET::BackTechMask() { - // (SILKSCREEN_LAYER_BACK | SOLDERMASK_LAYER_BACK | ADHESIVE_LAYER_BACK | SOLDERPASTE_LAYER_BACK) static const LSET saved( 6, B_SilkS, B_Mask, B_Adhes, B_Paste, B_CrtYd, B_Fab ); return saved; } +LSET LSET::BackBoardTechMask() +{ + static const LSET saved( 4, B_SilkS, B_Mask, B_Adhes, B_Paste ); + return saved; +} LSET LSET::FrontTechMask() { - // (SILKSCREEN_LAYER_FRONT | SOLDERMASK_LAYER_FRONT | ADHESIVE_LAYER_FRONT | SOLDERPASTE_LAYER_FRONT) static const LSET saved( 6, F_SilkS, F_Mask, F_Adhes, F_Paste, F_CrtYd, F_Fab ); return saved; } +LSET LSET::FrontBoardTechMask() +{ + static const LSET saved( 4, F_SilkS, F_Mask, F_Adhes, F_Paste ); + return saved; +} + + LSET LSET::AllTechMask() { static const LSET saved = BackTechMask() | FrontTechMask(); @@ -695,6 +712,13 @@ LSET LSET::AllTechMask() } +LSET LSET::AllBoardTechMask() +{ + static const LSET saved = BackBoardTechMask() | FrontBoardTechMask(); + return saved; +} + + LSET LSET::UserMask() { static const LSET saved( 6, diff --git a/common/pcb_plot_params.keywords b/common/pcb_plot_params.keywords index c64f70bca6..12ff3db2b3 100644 --- a/common/pcb_plot_params.keywords +++ b/common/pcb_plot_params.keywords @@ -28,3 +28,4 @@ useauxorigin usegerberextensions viasonmask usegerberattributes +usegerberadvancedattributes diff --git a/include/layers_id_colors_and_visibility.h b/include/layers_id_colors_and_visibility.h index db72495293..24d819eef2 100644 --- a/include/layers_id_colors_and_visibility.h +++ b/include/layers_id_colors_and_visibility.h @@ -270,6 +270,12 @@ public: */ static LSET AllCuMask( int aCuLayerCount = MAX_CU_LAYERS ); + /** + * Function ExternalCuMask + * returns a mask holding the Front and Bottom layers. + */ + static LSET ExternalCuMask(); + /** * Function AllNonCuMask * returns a mask holding all layer minus CU layers. @@ -284,13 +290,38 @@ public: */ static LSET FrontTechMask(); + /** + * Function FrontBoardTechMask + * returns a mask holding technical layers used in a board fabrication + * (no CU layer) on front side. + */ + static LSET FrontBoardTechMask(); + /** * Function BackTechMask * returns a mask holding all technical layers (no CU layer) on back side. */ static LSET BackTechMask(); + + /** + * Function BackBoardTechMask + * returns a mask holding technical layers used in a board fabrication + * (no CU layer) on Back side. + */ + static LSET BackBoardTechMask(); + + /** + * Function AllTechMask + * returns a mask holding all technical layers (no CU layer) on both side. + */ static LSET AllTechMask(); + /** + * Function AllTechMask + * returns a mask holding board technical layers (no CU layer) on both side. + */ + static LSET AllBoardTechMask(); + /** * Function FrontMask * returns a mask holding all technical layers and the external CU layer on front side. diff --git a/include/plot_auxiliary_data.h b/include/plot_auxiliary_data.h new file mode 100644 index 0000000000..acda36d5b1 --- /dev/null +++ b/include/plot_auxiliary_data.h @@ -0,0 +1,154 @@ +/* + * 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 AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 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 + */ + +/** + * a class to handle special data during plot. + * used in Gerber plotter to generate auxiliary data during plot + * (for instance info associated to flashed pads) + * + * @file plot_extra_data.h + */ + +#ifndef PLOT_EXTRA_DATA_H +#define PLOT_EXTRA_DATA_H + +#include + + +// this class handle info which can be added in a gerber file as attribute +// of an aperture, by the %TA.AperFunction command +// This attribute is added when creating a new aperture (command %ADDxx) +// Only one aperture attribute can be added to a given aperture +// +class GBR_APERTURE_METADATA +{ +public: + enum GBR_APERTURE_ATTRIB + { + GBR_APERTURE_ATTRIB_NONE, ///< uninitialized attribute + GBR_APERTURE_ATTRIB_ETCHEDCMP, ///< aperture used for etched components + GBR_APERTURE_ATTRIB_CONDUCTOR, ///< aperture used for connected items like tracks (not vias) + GBR_APERTURE_ATTRIB_CUTOUT, ///< aperture used for board cutout + GBR_APERTURE_ATTRIB_NONCONDUCTOR, ///< aperture used for not connected items (texts, outlines on copper) + GBR_APERTURE_ATTRIB_VIAPAD, ///< aperture used for vias + GBR_APERTURE_ATTRIB_COMPONENTPAD, ///< aperture used for through hole component on outer layer + GBR_APERTURE_ATTRIB_SMDPAD_SMDEF, ///< aperture used for SMD pad. Excluded BGA pads which have their own type + GBR_APERTURE_ATTRIB_SMDPAD_CUDEF, ///< aperture used for SMD pad with a solder mask defined by the solder mask + GBR_APERTURE_ATTRIB_BGAPAD_SMDEF, ///< aperture used for BGA pads with a solder mask defined by the copper shape + GBR_APERTURE_ATTRIB_BGAPAD_CUDEF, ///< aperture used for BGA pad with a solder mask defined by the solder mask + GBR_APERTURE_ATTRIB_CONNECTORPAD, ///< aperture used for edge connecto pad (outer layers) + GBR_APERTURE_ATTRIB_WASHERPAD, ///< aperture used for mechanical pads (NPTH) + GBR_APERTURE_ATTRIB_HEATSINKPAD, ///< aperture used for heat sink pad (typically for SMDs) + GBR_APERTURE_ATTRIB_END ///< sentinel: max value + }; + + GBR_APERTURE_METADATA() + :m_ApertAttribute( GBR_APERTURE_ATTRIB_NONE ) + {} + + /** + * @return the string corresponding to the aperture attribute + */ + static std::string GetAttributeName( GBR_APERTURE_ATTRIB aAttribute ); + std::string GetAttributeName() + { + return GetAttributeName( m_ApertAttribute ); + } + + /** + * @return the full command string corresponding to the aperture attribute + * like "%TA.AperFunction,*%" + */ + static std::string FormatAttribute( GBR_APERTURE_ATTRIB aAttribute ); + std::string FormatAttribute() + { + return FormatAttribute( m_ApertAttribute ); + } + + // The id of the aperture attribute + GBR_APERTURE_ATTRIB m_ApertAttribute; +}; + +// this class handle metadata which can be added in a gerber file as attribute +// in X2 format +class GBR_METADATA +{ +public: + GBR_METADATA() {} + + void SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB aApertAttribute ) + { + m_ApertureMetadata.m_ApertAttribute = aApertAttribute; + } + + GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB GetApertureAttrib() + { + return m_ApertureMetadata.m_ApertAttribute; + } + + void SetNetAttribType( int aNetAttribType ) + { + m_NetlistMetadata.m_NetAttribType = aNetAttribType; + } + + int GetNetAttribType() const + { + return m_NetlistMetadata.m_NetAttribType; + } + + void SetNetName( const wxString& aNetname ) { m_NetlistMetadata.m_Netname = aNetname; } + void SetPadName( const wxString& aPadname ) { m_NetlistMetadata.m_Padname = aPadname; } + void SetCmpReference( const wxString& aComponentRef ) { m_NetlistMetadata.m_Cmpref = aComponentRef; } + + GBR_APERTURE_METADATA m_ApertureMetadata; + GBR_NETLIST_METADATA m_NetlistMetadata; +}; + +/** + * This helper function "normalize" aString and convert it to a Gerber std::string + * Normalisation means convert any code > 0x7F and unautorized code to a hexadecimal + * 16 bits sequence unicode + * unautorized codes are ',' '*' '%' '\' + * @param aString = the wxString to convert + * @return a std::string (ASCII7 coded) compliant with a gerber string + */ +std::string formatStringToGerber( const wxString& aString ); + +/** + * Generates the string to print to a gerber file, to set a net attribute + * for a graphic object. + * @param aPrintedText is the string to print + * @param aLastNetAttributes is the current full set of attributes. + * @param aClearPreviousAttributes returns true if the full set of attributes + * must be deleted from file before adding new attribute (happens when a previous + * attribute does not exist no more). + * @return false if nothing can be done (GBR_NETLIST_METADATA has GBR_APERTURE_ATTRIB_NONE, + * and true if OK + * if the new attribute(s) is the same as current attribute(s), aPrintedText + * will be empty + */ +bool FormatNetAttribute( std::string& aPrintedText, std::string& aLastNetAttributes, + GBR_NETLIST_METADATA* aData, bool& aClearPreviousAttributes ); + +#endif // PLOT_EXTRA_DATA_H diff --git a/include/plot_common.h b/include/plot_common.h index 4b33c3d07f..9914aae4ab 100644 --- a/include/plot_common.h +++ b/include/plot_common.h @@ -1,8 +1,8 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr - * Copyright (C) 2015 KiCad Developers, see CHANGELOG.TXT for contributors. + * Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr + * Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -39,6 +39,7 @@ #include // FILL_T class SHAPE_POLY_SET; +class GBR_NETLIST_METADATA; /** * Enum PlotFormat @@ -89,7 +90,9 @@ private: double m_dashGapLength_mm; ///< Dashed line parameter in mm: gap public: - static const int USE_DEFAULT_LINE_WIDTH = -1; + // These values are used as flag for pen or aperture selection + static const int DO_NOT_SET_LINE_WIDTH = -2; // Skip selection + static const int USE_DEFAULT_LINE_WIDTH = -1; // use the default pen PLOTTER(); @@ -125,8 +128,9 @@ public: /** * Set the line width for the next drawing. * @param width is specified in IUs + * @param aData is an auxiliary parameter, mainly used in gerber plotter */ - virtual void SetCurrentLineWidth( int width ) = 0; + virtual void SetCurrentLineWidth( int width, void* aData = NULL ) = 0; /** * Set the default line width. Used at the beginning and when a width @@ -247,9 +251,10 @@ public: * @param aCornerList = corners list * @param aFill = type of fill * @param aWidth = line width + * @param aData an auxiliary info (mainly for gerber format) */ virtual void PlotPoly( const std::vector< wxPoint >& aCornerList, FILL_T aFill, - int aWidth = USE_DEFAULT_LINE_WIDTH ) = 0; + int aWidth = USE_DEFAULT_LINE_WIDTH, void * aData = NULL ) = 0; /** * Function PlotImage @@ -266,21 +271,51 @@ public: // Higher level primitives -- can be drawn as line, sketch or 'filled' virtual void ThickSegment( const wxPoint& start, const wxPoint& end, int width, - EDA_DRAW_MODE_T tracemode ); + EDA_DRAW_MODE_T tracemode, void* aData ); virtual void ThickArc( const wxPoint& centre, double StAngle, double EndAngle, - int rayon, int width, EDA_DRAW_MODE_T tracemode ); + int rayon, int width, EDA_DRAW_MODE_T tracemode, void* aData ); virtual void ThickRect( const wxPoint& p1, const wxPoint& p2, int width, - EDA_DRAW_MODE_T tracemode ); + EDA_DRAW_MODE_T tracemode, void* aData ); virtual void ThickCircle( const wxPoint& pos, int diametre, int width, - EDA_DRAW_MODE_T tracemode ); + EDA_DRAW_MODE_T tracemode, void* aData ); // Flash primitives + + /** + * virtual function FlashPadCircle + * @param aPadPos Position of the shape (center of the rectangle + * @param aSize = size of rounded rect + * @param cornerRadius Radius of the rounded corners + * @param aOrient The rotation of the shape + * @param aTraceMode FILLED or SKETCH + * @param aData an auxiliary info (mainly for gerber format) + */ virtual void FlashPadCircle( const wxPoint& aPadPos, int aDiameter, - EDA_DRAW_MODE_T aTraceMode ) = 0; + EDA_DRAW_MODE_T aTraceMode, void* aData ) = 0; + + /** + * virtual function FlashPadOval + * @param aPadPos Position of the shape (center of the rectangle + * @param aSize = size of rounded rect + * @param cornerRadius Radius of the rounded corners + * @param aOrient The rotation of the shape + * @param aTraceMode FILLED or SKETCH + * @param aData an auxiliary info (mainly for gerber format) + */ virtual void FlashPadOval( const wxPoint& aPadPos, const wxSize& aSize, double aPadOrient, - EDA_DRAW_MODE_T aTraceMode ) = 0; + EDA_DRAW_MODE_T aTraceMode, void* aData ) = 0; + + /** + * virtual function FlashPadRect + * @param aPadPos Position of the shape (center of the rectangle + * @param aSize = size of rounded rect + * @param cornerRadius Radius of the rounded corners + * @param aOrient The rotation of the shape + * @param aTraceMode FILLED or SKETCH + * @param aData an auxuliary info (mainly for gerber format) + */ virtual void FlashPadRect( const wxPoint& aPadPos, const wxSize& aSize, - double aPadOrient, EDA_DRAW_MODE_T aTraceMode ) = 0; + double aPadOrient, EDA_DRAW_MODE_T aTraceMode, void* aData ) = 0; /** * virtual function FlashPadRoundRect @@ -289,10 +324,11 @@ public: * @param cornerRadius Radius of the rounded corners * @param aOrient The rotation of the shape * @param aTraceMode FILLED or SKETCH + * @param aData an auxiliary info (mainly for gerber format) */ virtual void FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize, int aCornerRadius, double aOrient, - EDA_DRAW_MODE_T aTraceMode ) = 0; + EDA_DRAW_MODE_T aTraceMode, void* aData ) = 0; /** * virtual function FlashPadCustom @@ -300,10 +336,11 @@ public: * @param aSize = size of round reference pad * @param aPolygons the shape as polygon set * @param aTraceMode FILLED or SKETCH + * @param aData an auxiliary info (mainly for gerber format) */ virtual void FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize, SHAPE_POLY_SET* aPolygons, - EDA_DRAW_MODE_T aTraceMode ) = 0; + EDA_DRAW_MODE_T aTraceMode, void* aData ) = 0; /** virtual function FlashPadTrapez * flash a trapezoidal pad @@ -314,11 +351,12 @@ public: * @param aTrace_Mode = FILLED or SKETCH */ virtual void FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners, - double aPadOrient, EDA_DRAW_MODE_T aTraceMode ) = 0; + double aPadOrient, EDA_DRAW_MODE_T aTraceMode, void* aData ) = 0; /** * Draws text with the plotter. For convenience it accept the color to use + * for specific plotters (GERBER) aData is used to pass extra parameters */ virtual void Text( const wxPoint& aPos, enum EDA_COLOR_T aColor, @@ -330,7 +368,8 @@ public: int aWidth, bool aItalic, bool aBold, - bool aMultilineAllowed = false ); + bool aMultilineAllowed = false, + void* aData = NULL ); /** * Draw a marker (used for the drill map) @@ -373,6 +412,25 @@ public: // NOP for most plotters. Only for Gerber plotter } + /** + * calling this function allows to define the beginning of a group + * of drawing items, for instance in SVG or Gerber format. + * (example: group all segments of a letter or a text) + * @param aData can define any parameter + * for most of plotters: do nothing + */ + virtual void StartBlock( void* aData ) {} + + /** + * calling this function allows to define the end of a group of drawing items + * for instance in SVG or Gerber format. + * the group is started by StartBlock() + * @param aData can define any parameter + * for most of plotters: do nothing + */ + virtual void EndBlock( void* aData ) {} + + protected: // These are marker subcomponents /** @@ -508,7 +566,7 @@ public: virtual bool EndPlot(); /// HPGL doesn't handle line thickness or color - virtual void SetCurrentLineWidth( int width ) + virtual void SetCurrentLineWidth( int width, void* aData = NULL ) override { // This is the truth currentPenWidth = userToDeviceSize( penDiameter ); @@ -538,27 +596,28 @@ public: virtual void Circle( const wxPoint& pos, int diametre, FILL_T fill, int width = USE_DEFAULT_LINE_WIDTH ); virtual void PlotPoly( const std::vector< wxPoint >& aCornerList, - FILL_T aFill, int aWidth = USE_DEFAULT_LINE_WIDTH); + FILL_T aFill, int aWidth = USE_DEFAULT_LINE_WIDTH, + void * aData = NULL) override; virtual void ThickSegment( const wxPoint& start, const wxPoint& end, int width, - EDA_DRAW_MODE_T tracemode ); + EDA_DRAW_MODE_T tracemode, void* aData ) override; virtual void Arc( const wxPoint& centre, double StAngle, double EndAngle, int rayon, FILL_T fill, int width = USE_DEFAULT_LINE_WIDTH ); virtual void PenTo( const wxPoint& pos, char plume ); virtual void FlashPadCircle( const wxPoint& pos, int diametre, - EDA_DRAW_MODE_T trace_mode ); + EDA_DRAW_MODE_T trace_mode, void* aData ) override; virtual void FlashPadOval( const wxPoint& pos, const wxSize& size, double orient, - EDA_DRAW_MODE_T trace_mode ); + EDA_DRAW_MODE_T trace_mode, void* aData ) override; virtual void FlashPadRect( const wxPoint& pos, const wxSize& size, - double orient, EDA_DRAW_MODE_T trace_mode ); + double orient, EDA_DRAW_MODE_T trace_mode, void* aData ) override; virtual void FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize, int aCornerRadius, double aOrient, - EDA_DRAW_MODE_T aTraceMode ); + EDA_DRAW_MODE_T aTraceMode, void* aData ) override; virtual void FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize, SHAPE_POLY_SET* aPolygons, - EDA_DRAW_MODE_T aTraceMode ); + EDA_DRAW_MODE_T aTraceMode, void* aData ) override; virtual void FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners, - double aPadOrient, EDA_DRAW_MODE_T aTrace_Mode ); + double aPadOrient, EDA_DRAW_MODE_T aTrace_Mode, void* aData ) override; protected: void penControl( char plume ); @@ -603,19 +662,19 @@ public: // Pad routines are handled with lower level primitives virtual void FlashPadCircle( const wxPoint& pos, int diametre, - EDA_DRAW_MODE_T trace_mode ); + EDA_DRAW_MODE_T trace_mode, void* aData ) override; virtual void FlashPadOval( const wxPoint& pos, const wxSize& size, double orient, - EDA_DRAW_MODE_T trace_mode ); + EDA_DRAW_MODE_T trace_mode, void* aData ) override; virtual void FlashPadRect( const wxPoint& pos, const wxSize& size, - double orient, EDA_DRAW_MODE_T trace_mode ); + double orient, EDA_DRAW_MODE_T trace_mode, void* aData ) override; virtual void FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize, int aCornerRadius, double aOrient, - EDA_DRAW_MODE_T aTraceMode ); + EDA_DRAW_MODE_T aTraceMode, void* aData ) override; virtual void FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize, SHAPE_POLY_SET* aPolygons, - EDA_DRAW_MODE_T aTraceMode ); + EDA_DRAW_MODE_T aTraceMode, void* aData ) override; virtual void FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners, - double aPadOrient, EDA_DRAW_MODE_T aTrace_Mode ); + double aPadOrient, EDA_DRAW_MODE_T aTrace_Mode, void* aData ) override; /** The SetColor implementation is split with the subclasses: * The PSLIKE computes the rgb values, the subclass emits the @@ -685,7 +744,7 @@ public: virtual bool StartPlot(); virtual bool EndPlot(); - virtual void SetCurrentLineWidth( int width ); + virtual void SetCurrentLineWidth( int width, void* aData = NULL ) override; virtual void SetDash( bool dashed ); virtual void SetViewport( const wxPoint& aOffset, double aIusPerDecimil, @@ -698,7 +757,8 @@ public: int rayon, FILL_T fill, int width = USE_DEFAULT_LINE_WIDTH ); virtual void PlotPoly( const std::vector< wxPoint >& aCornerList, - FILL_T aFill, int aWidth = USE_DEFAULT_LINE_WIDTH ); + FILL_T aFill, int aWidth = USE_DEFAULT_LINE_WIDTH, + void * aData = NULL ) override; virtual void PlotImage( const wxImage& aImage, const wxPoint& aPos, double aScaleFactor ); @@ -714,7 +774,8 @@ public: int aWidth, bool aItalic, bool aBold, - bool aMultilineAllowed = false ); + bool aMultilineAllowed = false, + void* aData = NULL ) override; protected: virtual void emitSetRGBColor( double r, double g, double b ); }; @@ -753,7 +814,7 @@ public: virtual bool EndPlot(); virtual void StartPage(); virtual void ClosePage(); - virtual void SetCurrentLineWidth( int width ); + virtual void SetCurrentLineWidth( int width, void* aData = NULL ) override; virtual void SetDash( bool dashed ); /** PDF can have multiple pages, so SetPageSettings can be called @@ -769,7 +830,8 @@ public: int rayon, FILL_T fill, int width = USE_DEFAULT_LINE_WIDTH ); virtual void PlotPoly( const std::vector< wxPoint >& aCornerList, - FILL_T aFill, int aWidth = USE_DEFAULT_LINE_WIDTH); + FILL_T aFill, int aWidth = USE_DEFAULT_LINE_WIDTH, + void * aData = NULL ) override; virtual void PenTo( const wxPoint& pos, char plume ); @@ -783,7 +845,8 @@ public: int aWidth, bool aItalic, bool aBold, - bool aMultilineAllowed = false ); + bool aMultilineAllowed = false, + void* aData = NULL ) override; virtual void PlotImage( const wxImage& aImage, const wxPoint& aPos, double aScaleFactor ); @@ -824,7 +887,7 @@ public: virtual void SetColor( EDA_COLOR_T color ); virtual bool StartPlot(); virtual bool EndPlot(); - virtual void SetCurrentLineWidth( int width ); + virtual void SetCurrentLineWidth( int width, void* aData = NULL ) override; virtual void SetDash( bool dashed ); virtual void SetViewport( const wxPoint& aOffset, double aIusPerDecimil, @@ -837,7 +900,8 @@ public: int rayon, FILL_T fill, int width = USE_DEFAULT_LINE_WIDTH ); virtual void PlotPoly( const std::vector< wxPoint >& aCornerList, - FILL_T aFill, int aWidth = USE_DEFAULT_LINE_WIDTH ); + FILL_T aFill, int aWidth = USE_DEFAULT_LINE_WIDTH, + void * aData = NULL ) override; virtual void PlotImage( const wxImage& aImage, const wxPoint& aPos, double aScaleFactor ); @@ -853,7 +917,8 @@ public: int aWidth, bool aItalic, bool aBold, - bool aMultilineAllowed = false ); + bool aMultilineAllowed = false, + void* aData = NULL ) override; protected: FILL_T m_fillMode; // true if the current contour @@ -892,8 +957,9 @@ protected: /* Class to handle a D_CODE when plotting a board : */ #define FIRST_DCODE_VALUE 10 // D_CODE < 10 is a command, D_CODE >= 10 is a tool -struct APERTURE +class APERTURE { +public: enum APERTURE_TYPE { Circle = 1, Rect = 2, @@ -901,12 +967,12 @@ struct APERTURE Oval = 4 }; - wxSize Size; // horiz and Vert size - APERTURE_TYPE Type; // Type ( Line, rect , circulaire , ovale .. ) - int DCode; // code number ( >= 10 ); - - /* Trivia question: WHY Gerber decided to use D instead of the usual T for - * tool change? */ + wxSize m_Size; // horiz and Vert size + APERTURE_TYPE m_Type; // Type ( Line, rect , circulaire , ovale .. ) + int m_DCode; // code number ( >= 10 ); + int m_ApertureAttribute; // the attribute attached to this aperture + // Only one attribute is allowed by aperture + // 0 = no specific aperture attribute }; @@ -932,7 +998,7 @@ public: */ virtual bool StartPlot(); virtual bool EndPlot(); - virtual void SetCurrentLineWidth( int width ); + virtual void SetCurrentLineWidth( int width, void* aData = NULL ) override; virtual void SetDefaultLineWidth( int width ); // RS274X has no dashing, nor colours @@ -948,34 +1014,56 @@ public: virtual void Arc( const wxPoint& aCenter, double aStAngle, double aEndAngle, int aRadius, FILL_T aFill, int aWidth = USE_DEFAULT_LINE_WIDTH ); + virtual void ThickSegment( const wxPoint& start, const wxPoint& end, int width, + EDA_DRAW_MODE_T tracemode, void* aData ) override; + + virtual void ThickArc( const wxPoint& centre, double StAngle, double EndAngle, + int rayon, int width, EDA_DRAW_MODE_T tracemode, void* aData ) override; + virtual void ThickRect( const wxPoint& p1, const wxPoint& p2, int width, + EDA_DRAW_MODE_T tracemode, void* aData ) override; + virtual void ThickCircle( const wxPoint& pos, int diametre, int width, + EDA_DRAW_MODE_T tracemode, void* aData ) override; /** * Gerber polygon: they can (and *should*) be filled with the * appropriate G36/G37 sequence */ virtual void PlotPoly( const std::vector< wxPoint >& aCornerList, - FILL_T aFill, int aWidth = USE_DEFAULT_LINE_WIDTH ); + FILL_T aFill, int aWidth = USE_DEFAULT_LINE_WIDTH, + void * aData = NULL ) override; virtual void PenTo( const wxPoint& pos, char plume ); + virtual void Text( const wxPoint& aPos, + enum EDA_COLOR_T aColor, + const wxString& aText, + double aOrient, + const wxSize& aSize, + enum EDA_TEXT_HJUSTIFY_T aH_justify, + enum EDA_TEXT_VJUSTIFY_T aV_justify, + int aWidth, + bool aItalic, + bool aBold, + bool aMultilineAllowed = false, + void* aData = NULL ) override; + /** * Filled circular flashes are stored as apertures */ virtual void FlashPadCircle( const wxPoint& pos, int diametre, - EDA_DRAW_MODE_T trace_mode ); + EDA_DRAW_MODE_T trace_mode, void* aData ) override; /** * Filled oval flashes are handled as aperture in the 90 degree positions only */ virtual void FlashPadOval( const wxPoint& pos, const wxSize& size, double orient, - EDA_DRAW_MODE_T trace_mode ); - + EDA_DRAW_MODE_T trace_mode, void* aData ) override; /** * Filled rect flashes are handled as aperture in the 0 90 180 or 270 degree orientation only * and as polygon for other orientations * TODO: always use flashed shapes (aperture macros) */ virtual void FlashPadRect( const wxPoint& pos, const wxSize& size, - double orient, EDA_DRAW_MODE_T trace_mode ); + double orient, EDA_DRAW_MODE_T trace_mode, void* aData ) override; /** * Roundrect pad at the moment are not handled as aperture, since @@ -984,17 +1072,17 @@ public: */ virtual void FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize, int aCornerRadius, double aOrient, - EDA_DRAW_MODE_T aTraceMode ); + EDA_DRAW_MODE_T aTraceMode, void* aData ) override; virtual void FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize, SHAPE_POLY_SET* aPolygons, - EDA_DRAW_MODE_T aTraceMode ); + EDA_DRAW_MODE_T aTraceMode, void* aData ) override; /** * Trapezoidal pad at the moment are *never* handled as aperture, since * they require aperture macros * TODO: always use flashed shapes (aperture macros) */ virtual void FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners, - double aPadOrient, EDA_DRAW_MODE_T aTrace_Mode ); + double aPadOrient, EDA_DRAW_MODE_T aTrace_Mode, void* aData ) override; /** * Change the plot polarity and begin a new layer @@ -1014,8 +1102,32 @@ public: */ virtual void SetGerberCoordinatesFormat( int aResolution, bool aUseInches = false ); + void UseX2Attributes( bool aEnable ) { m_useX2Attributes = aEnable; } + void UseX2NetAttributes( bool aEnable ) { m_useNetAttributes = aEnable; } + + /** + * calling this function allows to define the beginning of a group + * of drawing items (used in X2 format with netlist attributes) + * @param aData can define any parameter + */ + virtual void StartBlock( void* aData ) override; + + /** + * calling this function allows to define the end of a group of drawing items + * the group is started by StartBlock() + * (used in X2 format with netlist attributes) + * @param aData can define any parameter + */ + virtual void EndBlock( void* aData ) override; + protected: - void selectAperture( const wxSize& size, APERTURE::APERTURE_TYPE type ); + /** + * Pick an existing aperture or create a new one, matching the + * size, type and attributes. + * write the DCode selection on gerber file + */ + void selectAperture( const wxSize& aSize, APERTURE::APERTURE_TYPE aType, + int aApertureAttribute ); /** * Emit a D-Code record, using proper conversions @@ -1024,8 +1136,43 @@ protected: */ void emitDcode( const DPOINT& pt, int dcode ); - std::vector::iterator - getAperture( const wxSize& size, APERTURE::APERTURE_TYPE type ); + /** + * print a Gerber net attribute object record. + * In a gerber file, a net attribute is owned by a graphic object + * formatNetAttribute must be called before creating the object + * @param aData contains the dato to format. + * the generated string depends on the type of netlist info + */ + void formatNetAttribute( GBR_NETLIST_METADATA* aData ); + + /** + * clear a Gerber net attribute record (clear object attribute dictionnary) + * and output the clear object attribute dictionnary command to gerber file + */ + void clearNetAttribute(); + + /** + * Function getAperture returns a reference to the aperture which meets the size anf type of tool + * if the aperture does not exist, it is created and entered in aperture list + * @param aSize = the size of tool + * @param aType = the type ( shape ) of tool + * @param aApertureAttribute = an aperture attribute of the tool (a tool can have onlu one attribute) + * 0 = no specific attribute + */ + std::vector::iterator getAperture( const wxSize& aSize, + APERTURE::APERTURE_TYPE aType, int aApertureAttribute ); + + // the attributes dictionnary created/modifed by %TO, attached the objects, when they are created + // by D01, D03 G36/G37 commands + // standard attributes are .P, .C and .N + // this is used by gerber readers when creating a new object. Cleared by %TD command + // Note: m_objectAttributesDictionnary can store more than one attribute + // the string stores the line(s) actually written to the gerber file + // it can store a .P, .C or .N attribute, or 2 or 3 attributes, separated by a \n char (EOL) + std::string m_objectAttributesDictionnary; + + // The last aperture attribute generated (only one aperture attribute can be set) + int m_apertureAttribute; FILE* workFile; FILE* finalFile; @@ -1042,6 +1189,11 @@ protected: bool m_gerberUnitInch; // true if the gerber units are inches, false for mm int m_gerberUnitFmt; // number of digits in mantissa. // usually 6 in Inches and 5 or 6 in mm + bool m_useX2Attributes; // In recent gerber files, attributes can be added. + // It will be added if this parm is true + bool m_useNetAttributes; // In recent gerber files, netlist info can be added. + // It will be added if this parm is true + // (imply m_useX2Attributes == true) }; @@ -1077,7 +1229,7 @@ public: virtual bool EndPlot(); // For now we don't use 'thick' primitives, so no line width - virtual void SetCurrentLineWidth( int width ) + virtual void SetCurrentLineWidth( int width, void* aData = NULL ) override { currentPenWidth = 0; } @@ -1099,26 +1251,27 @@ public: virtual void Circle( const wxPoint& pos, int diametre, FILL_T fill, int width = USE_DEFAULT_LINE_WIDTH ); virtual void PlotPoly( const std::vector< wxPoint >& aCornerList, - FILL_T aFill, int aWidth = USE_DEFAULT_LINE_WIDTH ); + FILL_T aFill, int aWidth = USE_DEFAULT_LINE_WIDTH, void * aData = NULL ) override; virtual void ThickSegment( const wxPoint& start, const wxPoint& end, int width, - EDA_DRAW_MODE_T tracemode ); + EDA_DRAW_MODE_T tracemode, void* aData ) override; virtual void Arc( const wxPoint& centre, double StAngle, double EndAngle, int rayon, FILL_T fill, int width = USE_DEFAULT_LINE_WIDTH ); virtual void PenTo( const wxPoint& pos, char plume ); + virtual void FlashPadCircle( const wxPoint& pos, int diametre, - EDA_DRAW_MODE_T trace_mode ); + EDA_DRAW_MODE_T trace_mode, void* aData ) override; virtual void FlashPadOval( const wxPoint& pos, const wxSize& size, double orient, - EDA_DRAW_MODE_T trace_mode ); + EDA_DRAW_MODE_T trace_mode, void* aData ) override; virtual void FlashPadRect( const wxPoint& pos, const wxSize& size, - double orient, EDA_DRAW_MODE_T trace_mode ); + double orient, EDA_DRAW_MODE_T trace_mode, void* aData ) override; virtual void FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize, int aCornerRadius, double aOrient, - EDA_DRAW_MODE_T aTraceMode ); + EDA_DRAW_MODE_T aTraceMode, void* aData ) override; virtual void FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize, SHAPE_POLY_SET* aPolygons, - EDA_DRAW_MODE_T aTraceMode ); + EDA_DRAW_MODE_T aTraceMode, void* aData ) override; virtual void FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners, - double aPadOrient, EDA_DRAW_MODE_T aTrace_Mode ); + double aPadOrient, EDA_DRAW_MODE_T aTrace_Mode, void* aData ) override; virtual void Text( const wxPoint& aPos, enum EDA_COLOR_T aColor, @@ -1130,7 +1283,8 @@ public: int aWidth, bool aItalic, bool aBold, - bool aMultilineAllowed = false ); + bool aMultilineAllowed = false, + void* aData = NULL ) override; protected: bool textAsLines; diff --git a/pcbnew/dialogs/dialog_plot.cpp b/pcbnew/dialogs/dialog_plot.cpp index fe648bd44e..0b72a705fa 100644 --- a/pcbnew/dialogs/dialog_plot.cpp +++ b/pcbnew/dialogs/dialog_plot.cpp @@ -5,7 +5,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 1992-2015 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -40,6 +40,9 @@ #include #include +// Uncomment this line to allow experimetal net attributes in Gerber files: +//#define KICAD_USE_GBR_NETATTRIBUTES + DIALOG_PLOT::DIALOG_PLOT( PCB_EDIT_FRAME* aParent ) : DIALOG_PLOT_BASE( aParent ), m_parent( aParent ), m_board( aParent->GetBoard() ), @@ -158,8 +161,15 @@ void DIALOG_PLOT::Init_Dialog() m_useGerberExtensions->SetValue( m_plotOpts.GetUseGerberProtelExtensions() ); // Option for including Gerber attributes (from Gerber X2 format) in the output - m_useGerberAttributes->SetValue( m_plotOpts.GetUseGerberAttributes() ); + m_useGerberX2Attributes->SetValue( m_plotOpts.GetUseGerberAttributes() ); + // Option for including Gerber netlist info (from Gerber X2 format) in the output +#ifdef KICAD_USE_GBR_NETATTRIBUTES + m_useGerberNetAttributes->SetValue( m_plotOpts.GetIncludeGerberNetlistInfo() ); +#else + m_plotOpts.SetIncludeGerberNetlistInfo( false ); + m_useGerberNetAttributes->SetValue( false ); +#endif // Gerber precision for coordinates m_rbGerberFormat->SetSelection( m_plotOpts.GetGerberPrecision() == 5 ? 0 : 1 ); @@ -362,12 +372,6 @@ void DIALOG_PLOT::SetPlotFormat( wxCommandEvent& event ) m_linesWidth->Enable( true ); m_HPGLPenSizeOpt->Enable( false ); m_excludeEdgeLayerOpt->Enable( true ); - m_subtractMaskFromSilk->Enable( false ); - m_subtractMaskFromSilk->SetValue( false ); - m_useGerberExtensions->Enable( false ); - m_useGerberExtensions->SetValue( false ); - m_useGerberAttributes->Enable( false ); - m_useGerberAttributes->SetValue( false ); m_scaleOpt->Enable( false ); m_scaleOpt->SetSelection( 1 ); m_fineAdjustXscaleOpt->Enable( false ); @@ -391,12 +395,6 @@ void DIALOG_PLOT::SetPlotFormat( wxCommandEvent& event ) m_linesWidth->Enable( true ); m_HPGLPenSizeOpt->Enable( false ); m_excludeEdgeLayerOpt->Enable( true ); - m_subtractMaskFromSilk->Enable( false ); - m_subtractMaskFromSilk->SetValue( false ); - m_useGerberExtensions->Enable( false ); - m_useGerberExtensions->SetValue( false ); - m_useGerberAttributes->Enable( false ); - m_useGerberAttributes->SetValue( false ); m_scaleOpt->Enable( true ); m_fineAdjustXscaleOpt->Enable( true ); m_fineAdjustYscaleOpt->Enable( true ); @@ -420,9 +418,6 @@ void DIALOG_PLOT::SetPlotFormat( wxCommandEvent& event ) m_linesWidth->Enable( true ); m_HPGLPenSizeOpt->Enable( false ); m_excludeEdgeLayerOpt->Enable( true ); - m_subtractMaskFromSilk->Enable( true ); - m_useGerberExtensions->Enable( true ); - m_useGerberAttributes->Enable( true ); m_scaleOpt->Enable( false ); m_scaleOpt->SetSelection( 1 ); m_fineAdjustXscaleOpt->Enable( false ); @@ -436,6 +431,9 @@ void DIALOG_PLOT::SetPlotFormat( wxCommandEvent& event ) m_PlotOptionsSizer->Show( m_GerberOptionsSizer ); m_PlotOptionsSizer->Hide( m_HPGLOptionsSizer ); m_PlotOptionsSizer->Hide( m_PSOptionsSizer ); +#ifndef KICAD_USE_GBR_NETATTRIBUTES + m_useGerberNetAttributes->Show( false ); +#endif break; case PLOT_FORMAT_HPGL: @@ -447,12 +445,6 @@ void DIALOG_PLOT::SetPlotFormat( wxCommandEvent& event ) m_linesWidth->Enable( false ); m_HPGLPenSizeOpt->Enable( true ); m_excludeEdgeLayerOpt->Enable( true ); - m_subtractMaskFromSilk->Enable( false ); - m_subtractMaskFromSilk->SetValue( false ); - m_useGerberExtensions->Enable( false ); - m_useGerberExtensions->SetValue( false ); - m_useGerberAttributes->Enable( false ); - m_useGerberAttributes->SetValue( false ); m_scaleOpt->Enable( true ); m_fineAdjustXscaleOpt->Enable( false ); m_fineAdjustYscaleOpt->Enable( false ); @@ -475,12 +467,6 @@ void DIALOG_PLOT::SetPlotFormat( wxCommandEvent& event ) m_linesWidth->Enable( false ); m_HPGLPenSizeOpt->Enable( false ); m_excludeEdgeLayerOpt->Enable( true ); - m_subtractMaskFromSilk->Enable( false ); - m_subtractMaskFromSilk->SetValue( false ); - m_useGerberExtensions->Enable( false ); - m_useGerberExtensions->SetValue( false ); - m_useGerberAttributes->Enable( false ); - m_useGerberAttributes->SetValue( false ); m_scaleOpt->Enable( false ); m_scaleOpt->SetSelection( 1 ); m_fineAdjustXscaleOpt->Enable( false ); @@ -649,7 +635,8 @@ void DIALOG_PLOT::applyPlotSettings() tempOptions.SetFormat( getPlotFormat() ); tempOptions.SetUseGerberProtelExtensions( m_useGerberExtensions->GetValue() ); - tempOptions.SetUseGerberAttributes( m_useGerberAttributes->GetValue() ); + tempOptions.SetUseGerberAttributes( m_useGerberX2Attributes->GetValue() ); + tempOptions.SetIncludeGerberNetlistInfo( m_useGerberNetAttributes->GetValue() ); tempOptions.SetGerberPrecision( m_rbGerberFormat->GetSelection() == 0 ? 5 : 6 ); LSET selectedLayers; diff --git a/pcbnew/dialogs/dialog_plot_base.cpp b/pcbnew/dialogs/dialog_plot_base.cpp index e273fdd4ec..d0a567b0b4 100644 --- a/pcbnew/dialogs/dialog_plot_base.cpp +++ b/pcbnew/dialogs/dialog_plot_base.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Jul 24 2016) +// C++ code generated with wxFormBuilder (version Sep 8 2016) // http://www.wxformbuilder.org/ // // PLEASE DO "NOT" EDIT THIS FILE! @@ -99,6 +99,7 @@ DIALOG_PLOT_BASE::DIALOG_PLOT_BASE( wxWindow* parent, wxWindowID id, const wxStr bSizerPlotItems->Add( m_plotModuleValueOpt, 0, wxTOP|wxRIGHT|wxLEFT, 2 ); m_plotModuleRefOpt = new wxCheckBox( sbOptionsSizer->GetStaticBox(), ID_PRINT_REF, _("Plot footprint references"), wxDefaultPosition, wxDefaultSize, 0 ); + m_plotModuleRefOpt->SetValue(true); bSizerPlotItems->Add( m_plotModuleRefOpt, 0, wxTOP|wxRIGHT|wxLEFT, 2 ); m_plotInvisibleText = new wxCheckBox( sbOptionsSizer->GetStaticBox(), wxID_ANY, _("Force plotting of invisible values/references"), wxDefaultPosition, wxDefaultSize, 0 ); @@ -223,14 +224,19 @@ DIALOG_PLOT_BASE::DIALOG_PLOT_BASE( wxWindow* parent, wxWindowID id, const wxStr bSizerGbrOpt = new wxBoxSizer( wxVERTICAL ); m_useGerberExtensions = new wxCheckBox( m_GerberOptionsSizer->GetStaticBox(), wxID_ANY, _("Use Protel filename extensions"), wxDefaultPosition, wxDefaultSize, 0 ); - m_useGerberExtensions->SetToolTip( _("Use conventional Protel Gerber extensions - .GBL, .GTL, etc...") ); + m_useGerberExtensions->SetToolTip( _("Use Protel Gerber extensions - .GBL, .GTL, etc...\nNo more recommended. The official extension is .gbr") ); bSizerGbrOpt->Add( m_useGerberExtensions, 0, wxALL, 2 ); - m_useGerberAttributes = new wxCheckBox( m_GerberOptionsSizer->GetStaticBox(), wxID_ANY, _("Include extended attributes"), wxDefaultPosition, wxDefaultSize, 0 ); - m_useGerberAttributes->SetToolTip( _("Include extended attributes (X2 Gerber files format) in the Gerber file") ); + m_useGerberX2Attributes = new wxCheckBox( m_GerberOptionsSizer->GetStaticBox(), wxID_ANY, _("Include extended (X2) attributes"), wxDefaultPosition, wxDefaultSize, 0 ); + m_useGerberX2Attributes->SetToolTip( _("Include extended attributes (X2 Gerber files format) in the Gerber file.\nMainly File Format attributes.") ); - bSizerGbrOpt->Add( m_useGerberAttributes, 0, wxALL, 2 ); + bSizerGbrOpt->Add( m_useGerberX2Attributes, 0, wxALL, 2 ); + + m_useGerberNetAttributes = new wxCheckBox( m_GerberOptionsSizer->GetStaticBox(), wxID_ANY, _("Include advanced X2 features"), wxDefaultPosition, wxDefaultSize, 0 ); + m_useGerberNetAttributes->SetToolTip( _("Only available in X2 Gerber files format.\nInclude netlist metadata and aperture attributes.") ); + + bSizerGbrOpt->Add( m_useGerberNetAttributes, 0, wxALL, 2 ); m_subtractMaskFromSilk = new wxCheckBox( m_GerberOptionsSizer->GetStaticBox(), wxID_ANY, _("Subtract soldermask from silkscreen"), wxDefaultPosition, wxDefaultSize, 0 ); m_subtractMaskFromSilk->SetToolTip( _("Remove silkscreen from areas without soldermask") ); diff --git a/pcbnew/dialogs/dialog_plot_base.fbp b/pcbnew/dialogs/dialog_plot_base.fbp index 04d243e1a5..2f765a13a0 100644 --- a/pcbnew/dialogs/dialog_plot_base.fbp +++ b/pcbnew/dialogs/dialog_plot_base.fbp @@ -44,7 +44,7 @@ -1,-1 DIALOG_PLOT_BASE - 566,618 + 733,673 wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER DIALOG_SHIM; dialog_shim.h Plot @@ -93,20 +93,20 @@ m_MainSizer wxVERTICAL protected - + 5 wxEXPAND 0 - + bupperSizer wxHORIZONTAL none - + 5 wxEXPAND|wxRIGHT|wxLEFT 0 - + bSizerPlotFmt wxVERTICAL @@ -570,11 +570,11 @@ - + 5 wxEXPAND 0 - + bmiddleSizer wxHORIZONTAL @@ -683,20 +683,20 @@ - + 5 0 - + m_PlotOptionsSizer wxVERTICAL protected - + 3 wxALL|wxEXPAND 0 - + wxID_ANY Options @@ -705,11 +705,11 @@ 1 none - + 5 wxEXPAND 0 - + bSizer192 wxHORIZONTAL @@ -1005,7 +1005,7 @@ 1 0 - 0 + 1 1 1 @@ -1605,7 +1605,7 @@ - + 3 wxRIGHT|wxLEFT 1 @@ -2748,7 +2748,7 @@ 0 - Use conventional Protel Gerber extensions - .GBL, .GTL, etc... + Use Protel Gerber extensions - .GBL, .GTL, etc... No more recommended. The official extension is .gbr wxFILTER_NONE wxDefaultValidator @@ -2815,7 +2815,7 @@ 0 0 wxID_ANY - Include extended attributes + Include extended (X2) attributes 0 @@ -2823,7 +2823,7 @@ 0 1 - m_useGerberAttributes + m_useGerberX2Attributes 1 @@ -2836,7 +2836,95 @@ 0 - Include extended attributes (X2 Gerber files format) in the Gerber file + Include extended attributes (X2 Gerber files format) in the Gerber file. Mainly File Format attributes. + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 2 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Include advanced X2 features + + 0 + + + 0 + + 1 + m_useGerberNetAttributes + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + Only available in X2 Gerber files format. Include netlist metadata and aperture attributes. wxFILTER_NONE wxDefaultValidator @@ -3052,11 +3140,11 @@ - + 3 wxALL|wxEXPAND 0 - + wxID_ANY HPGL Options @@ -3065,11 +3153,11 @@ 1 protected - + 5 wxEXPAND 1 - + bSizer22 wxVERTICAL @@ -3929,7 +4017,7 @@ 5 wxEXPAND 1 - + sbSizerMsg wxVERTICAL @@ -4020,7 +4108,7 @@ 5 wxALIGN_RIGHT|wxRIGHT|wxLEFT 0 - + bSizerButtons wxHORIZONTAL @@ -4201,21 +4289,21 @@ - + 5 wxEXPAND 1 - + 0 protected 10 - + 5 wxALL 0 - + 1 1 1 @@ -4390,7 +4478,7 @@ - + MyMenu m_popMenu protected diff --git a/pcbnew/dialogs/dialog_plot_base.h b/pcbnew/dialogs/dialog_plot_base.h index 358a74ff71..dde1e2c8ff 100644 --- a/pcbnew/dialogs/dialog_plot_base.h +++ b/pcbnew/dialogs/dialog_plot_base.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Jul 24 2016) +// C++ code generated with wxFormBuilder (version Sep 8 2016) // http://www.wxformbuilder.org/ // // PLEASE DO "NOT" EDIT THIS FILE! @@ -92,7 +92,8 @@ class DIALOG_PLOT_BASE : public DIALOG_SHIM wxStaticText* m_SolderMaskMinWidthCurrValue; wxStaticBoxSizer* m_GerberOptionsSizer; wxCheckBox* m_useGerberExtensions; - wxCheckBox* m_useGerberAttributes; + wxCheckBox* m_useGerberX2Attributes; + wxCheckBox* m_useGerberNetAttributes; wxCheckBox* m_subtractMaskFromSilk; wxRadioBox* m_rbGerberFormat; wxStaticBoxSizer* m_HPGLOptionsSizer; @@ -129,7 +130,7 @@ class DIALOG_PLOT_BASE : public DIALOG_SHIM public: - DIALOG_PLOT_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Plot"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 566,618 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); + DIALOG_PLOT_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("Plot"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 733,673 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER ); ~DIALOG_PLOT_BASE(); void DIALOG_PLOT_BASEOnContextMenu( wxMouseEvent &event ) diff --git a/pcbnew/exporters/gen_drill_report_files.cpp b/pcbnew/exporters/gen_drill_report_files.cpp index 79882a4d86..15131eb259 100644 --- a/pcbnew/exporters/gen_drill_report_files.cpp +++ b/pcbnew/exporters/gen_drill_report_files.cpp @@ -403,7 +403,7 @@ bool EXCELLON_WRITER::PlotDrillMarks( PLOTTER* aPlotter ) if( hole.m_Hole_Shape != 0 ) { wxSize oblong_size = hole.m_Hole_Size; - aPlotter->FlashPadOval( pos, oblong_size, hole.m_Hole_Orient, SKETCH ); + aPlotter->FlashPadOval( pos, oblong_size, hole.m_Hole_Orient, SKETCH, NULL ); } } diff --git a/pcbnew/pcb_plot_params.cpp b/pcbnew/pcb_plot_params.cpp index ffcf96e15b..980d51fa87 100644 --- a/pcbnew/pcb_plot_params.cpp +++ b/pcbnew/pcb_plot_params.cpp @@ -81,6 +81,7 @@ PCB_PLOT_PARAMS::PCB_PLOT_PARAMS() { m_useGerberProtelExtensions = false; m_useGerberAttributes = false; + m_includeGerberNetlistInfo = false; m_gerberPrecision = gbrDefaultPrecision; m_excludeEdgeLayer = true; m_lineWidth = g_DrawDefaultLineThickness; @@ -148,8 +149,13 @@ void PCB_PLOT_PARAMS::Format( OUTPUTFORMATTER* aFormatter, if( m_useGerberAttributes ) // save this option only if active, // to avoid incompatibility with older Pcbnew version + { aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_usegerberattributes ), trueStr ); + if( GetIncludeGerberNetlistInfo() ) + aFormatter->Print( aNestLevel+1, "(%s %s)\n", getTokenName( T_usegerberadvancedattributes ), trueStr ); + } + if( m_gerberPrecision != gbrDefaultPrecision ) // save this option only if it is not the default value, // to avoid incompatibility with older Pcbnew version aFormatter->Print( aNestLevel+1, "(%s %d)\n", @@ -222,6 +228,8 @@ bool PCB_PLOT_PARAMS::operator==( const PCB_PLOT_PARAMS &aPcbPlotParams ) const return false; if( m_useGerberAttributes != aPcbPlotParams.m_useGerberAttributes ) return false; + if( m_useGerberAttributes && m_includeGerberNetlistInfo != aPcbPlotParams.m_includeGerberNetlistInfo ) + return false; if( m_gerberPrecision != aPcbPlotParams.m_gerberPrecision ) return false; if( m_excludeEdgeLayer != aPcbPlotParams.m_excludeEdgeLayer ) @@ -384,6 +392,10 @@ void PCB_PLOT_PARAMS_PARSER::Parse( PCB_PLOT_PARAMS* aPcbPlotParams ) aPcbPlotParams->m_useGerberAttributes = parseBool(); break; + case T_usegerberadvancedattributes: + aPcbPlotParams->m_includeGerberNetlistInfo = parseBool(); + break; + case T_gerberprecision: aPcbPlotParams->m_gerberPrecision = parseInt( gbrDefaultPrecision-1, gbrDefaultPrecision); diff --git a/pcbnew/pcb_plot_params.h b/pcbnew/pcb_plot_params.h index 59f921a360..8559ef7d86 100644 --- a/pcbnew/pcb_plot_params.h +++ b/pcbnew/pcb_plot_params.h @@ -97,6 +97,9 @@ private: /// Include attributes from the Gerber X2 format (chapter 5 in revision J2) bool m_useGerberAttributes; + /// Include netlist info (only in Gerber X2 format) (chapter ? in revision ?) + bool m_includeGerberNetlistInfo; + /// precision of coordinates in Gerber files: accepted 5 or 6 /// when units are in mm (6 or 7 in inches, but Pcbnew uses mm). /// 6 is the internal resolution of Pcbnew, but not alwys accepted by board maker @@ -231,6 +234,9 @@ public: void SetUseGerberAttributes( bool aUse ) { m_useGerberAttributes = aUse; } bool GetUseGerberAttributes() const { return m_useGerberAttributes; } + void SetIncludeGerberNetlistInfo( bool aUse ) { m_includeGerberNetlistInfo = aUse; } + bool GetIncludeGerberNetlistInfo() const { return m_includeGerberNetlistInfo; } + void SetUseGerberProtelExtensions( bool aUse ) { m_useGerberProtelExtensions = aUse; } bool GetUseGerberProtelExtensions() const { return m_useGerberProtelExtensions; } diff --git a/pcbnew/pcbplot.cpp b/pcbnew/pcbplot.cpp index 6d1b1c3137..96b781cd5a 100644 --- a/pcbnew/pcbplot.cpp +++ b/pcbnew/pcbplot.cpp @@ -85,8 +85,7 @@ const wxString GetGerberProtelExtension( LAYER_NUM aLayer ) } } - -wxString GetGerberFileFunctionAttribute( const BOARD *aBoard, +const wxString GetGerberFileFunctionAttribute( const BOARD *aBoard, LAYER_NUM aLayer, bool aUseX1CompatibilityMode ) { wxString attrib; @@ -94,81 +93,81 @@ wxString GetGerberFileFunctionAttribute( const BOARD *aBoard, switch( aLayer ) { case F_Adhes: - attrib = wxString( wxT( "Glue,Top" ) ); + attrib = "Glue,Top"; break; case B_Adhes: - attrib = wxString( wxT( "Glue,Bot" ) ); + attrib = "Glue,Bot"; break; case F_SilkS: - attrib = wxString( wxT( "Legend,Top" ) ); + attrib = "Legend,Top"; break; case B_SilkS: - attrib = wxString( wxT( "Legend,Bot" ) ); + attrib = "Legend,Bot"; break; case F_Mask: - attrib = wxString( wxT( "Soldermask,Top" ) ); + attrib = "Soldermask,Top"; break; case B_Mask: - attrib = wxString( wxT( "Soldermask,Bot" ) ); + attrib = "Soldermask,Bot"; break; case F_Paste: - attrib = wxString( wxT( "Paste,Top" ) ); + attrib = "Paste,Top"; break; case B_Paste: - attrib = wxString( wxT( "Paste,Bot" ) ); + attrib = "Paste,Bot"; break; case Edge_Cuts: // Board outline. // Can be "Profile,NP" (Not Plated: usual) or "Profile,P" // This last is the exception (Plated) - attrib = wxString( wxT( "Profile,NP" ) ); + attrib = "Profile,NP"; break; case Dwgs_User: - attrib = wxString( wxT( "Drawing" ) ); + attrib = "Drawing"; break; case Cmts_User: - attrib = wxString( wxT( "Other,Comment" ) ); + attrib = "Other,Comment"; break; case Eco1_User: - attrib = wxString( wxT( "Other,ECO1" ) ); + attrib = "Other,ECO1"; break; case Eco2_User: - attrib = wxString( wxT( "Other,ECO2" ) ); + attrib = "Other,ECO2"; break; case B_Fab: - attrib = wxString( wxT( "Other,Fab,Bot" ) ); + attrib = "Other,Fab,Bot"; break; case F_Fab: - attrib = wxString( wxT( "Other,Fab,Top" ) ); + attrib = "Other,Fab,Top"; break; case B_Cu: - attrib = wxString::Format( wxT( "Copper,L%d,Bot" ), aBoard->GetCopperLayerCount() ); + attrib.Printf( wxT( "Copper,L%d,Bot" ), aBoard->GetCopperLayerCount() ); break; case F_Cu: - attrib = wxString::Format( wxT( "Copper,L1,Top" ) ); + attrib = "Copper,L1,Top"; break; default: if( IsCopperLayer( aLayer ) ) - attrib = wxString::Format( wxT( "Copper,L%d,Inr" ), aLayer+1 ); + attrib.Printf( wxT( "Copper,L%d,Inr" ), aLayer+1 ); else - attrib = wxString::Format( wxT( "Other,User" ), aLayer+1 ); + attrib.Printf( wxT( "Other,User" ), aLayer+1 ); break; } @@ -180,13 +179,13 @@ wxString GetGerberFileFunctionAttribute( const BOARD *aBoard, switch( type ) { case LT_SIGNAL: - attrib += wxString( wxT( ",Signal" ) ); + attrib += ",Signal"; break; case LT_POWER: - attrib += wxString( wxT( ",Plane" ) ); + attrib += ",Plane"; break; case LT_MIXED: - attrib += wxString( wxT( ",Mixed" ) ); + attrib += ",Mixed"; break; default: break; // do nothing (but avoid a warning for unhandled LAYER_T values from GCC) @@ -203,16 +202,69 @@ wxString GetGerberFileFunctionAttribute( const BOARD *aBoard, return fileFct; } + +static const wxString GetGerberFilePolarityAttribute( LAYER_NUM aLayer ) +{ + /* build the string %TF.FilePolarity,Positive*% + * or %TF.FilePolarity,Negative*% + * an emply string for layers which do not use a polarity + * + * The value of the .FilePolarity specifies whether the image represents the + * presence or absence of material. + * This attribute can only be used when the file represents a pattern in a material layer, + * e.g. copper, solder mask, legend. + * Together with.FileFunction it defines the role of that image in + * the layer structure of the PCB. + * Note that the .FilePolarity attribute does not change the image - + * no attribute does. + * It changes the interpretation of the image. + * For example, in a copper layer in positive polarity a round flash generates a copper pad. + * In a copper layer in negative polarity it generates a clearance. + * Solder mask images usually represent solder mask openings and are then negative. + * This may be counter-intuitive. + */ + int polarity = 0; + + switch( aLayer ) + { + case F_Adhes: + case B_Adhes: + case F_SilkS: + case B_SilkS: + case F_Paste: + case B_Paste: + polarity = 1; + break; + + case F_Mask: + case B_Mask: + polarity = -1; + break; + + default: + if( IsCopperLayer( aLayer ) ) + polarity = 1; + break; + } + + wxString filePolarity; + + if( polarity == 1 ) + filePolarity = "%TF.FilePolarity,Positive*%"; + if( polarity == -1 ) + filePolarity = "%TF.FilePolarity,Negative*%"; + + return filePolarity; +} + /* Add some X2 attributes to the file header, as defined in the * Gerber file format specification J4 and "Revision 2015.06" */ -#define USE_REVISION_2015_06_ATTR void AddGerberX2Attribute( PLOTTER * aPlotter, const BOARD *aBoard, LAYER_NUM aLayer ) { wxString text; -#ifdef USE_REVISION_2015_06_ATTR // Creates the TF,.GenerationSoftware. Format is: // %TF,.GenerationSoftware,,[,]*% text.Printf( wxT( "%%TF.GenerationSoftware,KiCad,Pcbnew,%s*%%" ), GetBuildVersion() ); @@ -278,11 +330,16 @@ void AddGerberX2Attribute( PLOTTER * aPlotter, text.Printf( wxT( "%%TF.ProjectId,%s,%s,%s*%%" ), msg.ToAscii(), GetChars( guid ), rev.ToAscii() ); aPlotter->AddLineToHeader( text ); -#endif // Add the TF.FileFunction text = GetGerberFileFunctionAttribute( aBoard, aLayer, false ); aPlotter->AddLineToHeader( text ); + + // Add the TF.FilePolarity (for layers which support that) + text = GetGerberFilePolarityAttribute( aLayer ); + + if( !text.IsEmpty() ) + aPlotter->AddLineToHeader( text ); } diff --git a/pcbnew/pcbplot.h b/pcbnew/pcbplot.h index 665b063716..4ef67b6d05 100644 --- a/pcbnew/pcbplot.h +++ b/pcbnew/pcbplot.h @@ -268,7 +268,7 @@ const wxString GetGerberProtelExtension( LAYER_NUM aLayer ); * , compatible with X1 (rx274) notation (G04#@!TF.FileFunction) * @return The attribute, as a text string */ -extern wxString GetGerberFileFunctionAttribute( const BOARD *aBoard, +const wxString GetGerberFileFunctionAttribute( const BOARD *aBoard, LAYER_NUM aLayer, bool aUseX1CompatibilityMode ); /** diff --git a/pcbnew/plot_board_layers.cpp b/pcbnew/plot_board_layers.cpp index 68a027e735..8cfd691c4a 100644 --- a/pcbnew/plot_board_layers.cpp +++ b/pcbnew/plot_board_layers.cpp @@ -50,6 +50,7 @@ #include #include +#include // Local /* Plot a solder mask layer. @@ -88,6 +89,8 @@ void PlotSilkScreen( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask, { for( MODULE* Module = aBoard->m_Modules; Module; Module = Module->Next() ) { + aPlotter->StartBlock( NULL ); + for( D_PAD * pad = Module->Pads(); pad; pad = pad->Next() ) { // See if the pad is on this layer @@ -105,6 +108,8 @@ void PlotSilkScreen( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask, itemplotter.PlotPad( pad, color, SKETCH ); } + + aPlotter->EndBlock( NULL ); } } @@ -119,6 +124,8 @@ void PlotSilkScreen( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask, } // Plot filled areas + aPlotter->StartBlock( NULL ); + for( int ii = 0; ii < aBoard->GetAreaCount(); ii++ ) { ZONE_CONTAINER* edge_zone = aBoard->GetArea( ii ); @@ -129,6 +136,8 @@ void PlotSilkScreen( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask, itemplotter.PlotFilledAreas( edge_zone ); } + aPlotter->EndBlock( NULL ); + // Plot segments used to fill zone areas (outdated, but here for old boards // compatibility): for( SEGZONE* seg = aBoard->m_Zone; seg; seg = seg->Next() ) @@ -137,7 +146,7 @@ void PlotSilkScreen( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask, continue; aPlotter->ThickSegment( seg->GetStart(), seg->GetEnd(), seg->GetWidth(), - itemplotter.GetPlotMode() ); + itemplotter.GetPlotMode(), NULL ); } } @@ -325,6 +334,8 @@ void PlotStandardLayer( BOARD *aBoard, PLOTTER* aPlotter, // Plot footprint pads for( MODULE* module = aBoard->m_Modules; module; module = module->Next() ) { + aPlotter->StartBlock( NULL ); + for( D_PAD* pad = module->Pads(); pad; pad = pad->Next() ) { if( (pad->GetLayerSet() & aLayerMask) == 0 ) @@ -388,10 +399,25 @@ void PlotStandardLayer( BOARD *aBoard, PLOTTER* aPlotter, pad->SetSize( tmppadsize ); // Restore the pad size } + + aPlotter->EndBlock( NULL ); } // Plot vias on copper layers, and if aPlotOpt.GetPlotViaOnMaskLayer() is true, // plot them on solder mask + + GBR_METADATA gbr_metadata; + + bool isOnCopperLayer = ( aLayerMask & LSET::AllCuMask() ).any(); + + if( isOnCopperLayer ) + { + gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_VIAPAD ); + gbr_metadata.SetNetAttribType( GBR_NETLIST_METADATA::GBR_NETINFO_NET ); + } + + aPlotter->StartBlock( NULL ); + for( TRACK* track = aBoard->m_Track; track; track = track->Next() ) { const VIA* Via = dyn_cast( track ); @@ -433,13 +459,19 @@ void PlotStandardLayer( BOARD *aBoard, PLOTTER* aPlotter, if( diameter <= 0 ) continue; + gbr_metadata.SetNetName( Via->GetNetname() ); + EDA_COLOR_T color = aBoard->GetVisibleElementColor(VIAS_VISIBLE + Via->GetViaType()); // Set plot color (change WHITE to LIGHTGRAY because // the white items are not seen on a white paper or screen aPlotter->SetColor( color != WHITE ? color : LIGHTGRAY); - aPlotter->FlashPadCircle( Via->GetStart(), diameter, plotMode ); + aPlotter->FlashPadCircle( Via->GetStart(), diameter, plotMode, &gbr_metadata ); } + aPlotter->EndBlock( NULL ); + aPlotter->StartBlock( NULL ); + gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_CONDUCTOR ); + // Plot tracks (not vias) : for( TRACK* track = aBoard->m_Track; track; track = track->Next() ) { @@ -449,11 +481,14 @@ void PlotStandardLayer( BOARD *aBoard, PLOTTER* aPlotter, if( !aLayerMask[track->GetLayer()] ) continue; + gbr_metadata.SetNetName( track->GetNetname() ); int width = track->GetWidth() + itemplotter.getFineWidthAdj(); aPlotter->SetColor( itemplotter.getColor( track->GetLayer() ) ); - aPlotter->ThickSegment( track->GetStart(), track->GetEnd(), width, plotMode ); + aPlotter->ThickSegment( track->GetStart(), track->GetEnd(), width, plotMode, &gbr_metadata ); } + aPlotter->EndBlock( NULL ); + // Plot zones (outdated, for old boards compatibility): for( TRACK* track = aBoard->m_Zone; track; track = track->Next() ) { @@ -462,10 +497,11 @@ void PlotStandardLayer( BOARD *aBoard, PLOTTER* aPlotter, int width = track->GetWidth() + itemplotter.getFineWidthAdj(); aPlotter->SetColor( itemplotter.getColor( track->GetLayer() ) ); - aPlotter->ThickSegment( track->GetStart(), track->GetEnd(), width, plotMode ); + aPlotter->ThickSegment( track->GetStart(), track->GetEnd(), width, plotMode, NULL ); } // Plot filled ares + aPlotter->StartBlock( NULL ); for( int ii = 0; ii < aBoard->GetAreaCount(); ii++ ) { ZONE_CONTAINER* zone = aBoard->GetArea( ii ); @@ -475,6 +511,7 @@ void PlotStandardLayer( BOARD *aBoard, PLOTTER* aPlotter, itemplotter.PlotFilledAreas( zone ); } + aPlotter->EndBlock( NULL ); // Adding drill marks, if required and if the plotter is able to plot them: if( aPlotOpt.GetDrillMarksType() != PCB_PLOT_PARAMS::NO_DRILL_SHAPE ) @@ -604,7 +641,7 @@ void PlotLayerOutlines( BOARD* aBoard, PLOTTER* aPlotter, int width; pad->GetOblongDrillGeometry( drl_start, drl_end, width ); aPlotter->ThickSegment( pad->GetPosition() + drl_start, - pad->GetPosition() + drl_end, width, SKETCH ); + pad->GetPosition() + drl_end, width, SKETCH, NULL ); } } } @@ -985,7 +1022,12 @@ PLOTTER* StartPlotBoard( BOARD *aBoard, PCB_PLOT_PARAMS *aPlotOpts, bool useX2mode = plotOpts.GetUseGerberAttributes(); if( useX2mode ) + { AddGerberX2Attribute( plotter, aBoard, aLayer ); + GERBER_PLOTTER* gbrplotter = static_cast ( plotter ); + gbrplotter->UseX2Attributes( true ); + gbrplotter->UseX2NetAttributes( plotOpts.GetIncludeGerberNetlistInfo() ); + } else plotter->AddLineToHeader( GetGerberFileFunctionAttribute( aBoard, aLayer, true ) ); diff --git a/pcbnew/plot_brditems_plotter.cpp b/pcbnew/plot_brditems_plotter.cpp index 4634c3915f..3998f095a1 100644 --- a/pcbnew/plot_brditems_plotter.cpp +++ b/pcbnew/plot_brditems_plotter.cpp @@ -7,7 +7,7 @@ /* * This program source code file is part of KiCad, a free EDA CAD application. * - * Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -48,12 +48,12 @@ #include #include +#include /* class BRDITEMS_PLOTTER is a helper class to plot board items * and a group of board items */ - EDA_COLOR_T BRDITEMS_PLOTTER::getColor( LAYER_NUM aLayer ) { EDA_COLOR_T color = m_board->GetLayerColor( ToLAYER_ID( aLayer ) ); @@ -66,6 +66,91 @@ EDA_COLOR_T BRDITEMS_PLOTTER::getColor( LAYER_NUM aLayer ) void BRDITEMS_PLOTTER::PlotPad( D_PAD* aPad, EDA_COLOR_T aColor, EDA_DRAW_MODE_T aPlotMode ) { wxPoint shape_pos = aPad->ShapePos(); + GBR_METADATA gbr_metadata; + + bool isOnCopperLayer = ( m_layerMask & LSET::AllCuMask() ).any(); + bool isOnExternalCopperLayer = ( m_layerMask & LSET::ExternalCuMask() ).any(); + bool isPadOnBoardTechLayers = ( aPad->GetLayerSet() & LSET::AllBoardTechMask() ).any(); + + gbr_metadata.SetCmpReference( aPad->GetParent()->GetReference() ); + + if( isOnCopperLayer ) + { + gbr_metadata.SetNetAttribType( GBR_NETINFO_ALL ); + + if( isOnExternalCopperLayer ) + gbr_metadata.SetPadName( aPad->GetPadName() ); + + gbr_metadata.SetNetName( aPad->GetNetname() ); + + // Some pads are mechanical pads ( through hole or smd ) + // when this is the case, they have no pad name and/or are not plated. + // In this case gerber files have slightly different attributes. + if( aPad->GetAttribute() == PAD_ATTRIB_HOLE_NOT_PLATED || + aPad->GetPadName().IsEmpty() ) + gbr_metadata.m_NetlistMetadata.m_NotInNet = true; + + if( !isOnExternalCopperLayer || !isPadOnBoardTechLayers ) + { + // On internal layers one cannot use the GBR_NETLIST_METADATA::GBR_INFO_FLASHED_PAD + // attribute when the component is on an external layer (most of the case) + // Also, if a SMD pad is not on a tech layer (masks) use also net+cmp attribute, because + // it is not really a pad (can be a "pad", actually a node in a virtual component) + gbr_metadata.SetNetAttribType( GBR_NETLIST_METADATA::GBR_NETINFO_NET | + GBR_NETLIST_METADATA::GBR_NETINFO_CMP ); + + if( !isPadOnBoardTechLayers ) + // such a pad is not soldered and is not a connecting point. + // Just set aperture attribute as conductor + // If it is a through hole pad, it will be adjusted later + gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_CONDUCTOR ); + + switch( aPad->GetAttribute() ) + { + case PAD_ATTRIB_HOLE_NOT_PLATED: // Mechanical pad through hole + gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_WASHERPAD ); + break; + + case PAD_ATTRIB_STANDARD : // Pad through hole, a hole is also expected + gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_VIAPAD ); + break; + + default: + break; + } + } + else // Some attributes are reserved to the external copper layers + { + switch( aPad->GetAttribute() ) + { + case PAD_ATTRIB_HOLE_NOT_PLATED: // Mechanical pad through hole + gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_WASHERPAD ); + break; + + case PAD_ATTRIB_STANDARD : // Pad through hole, a hole is also expected + gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_COMPONENTPAD ); + break; + + case PAD_ATTRIB_CONN: // Connector pads have no solder paste. + gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_CONNECTORPAD ); + break; + + case PAD_ATTRIB_SMD: // SMD pads (One external copper layer only) with solder paste + if( aPad->GetShape() == PAD_SHAPE_CIRCLE ) // perhaps a BGA pad + gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_BGAPAD_CUDEF ); + else + gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_SMDPAD_CUDEF ); + break; + } + } + + if( aPad->GetAttribute() == PAD_ATTRIB_HOLE_NOT_PLATED ) + gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_WASHERPAD ); + } + else + { + gbr_metadata.SetNetAttribType( GBR_NETLIST_METADATA::GBR_NETINFO_CMP ); + } // Set plot color (change WHITE to LIGHTGRAY because // the white items are not seen on a white paper or screen @@ -74,12 +159,12 @@ void BRDITEMS_PLOTTER::PlotPad( D_PAD* aPad, EDA_COLOR_T aColor, EDA_DRAW_MODE_T switch( aPad->GetShape() ) { case PAD_SHAPE_CIRCLE: - m_plotter->FlashPadCircle( shape_pos, aPad->GetSize().x, aPlotMode ); + m_plotter->FlashPadCircle( shape_pos, aPad->GetSize().x, aPlotMode, &gbr_metadata ); break; case PAD_SHAPE_OVAL: m_plotter->FlashPadOval( shape_pos, aPad->GetSize(), - aPad->GetOrientation(), aPlotMode ); + aPad->GetOrientation(), aPlotMode, &gbr_metadata ); break; case PAD_SHAPE_TRAPEZOID: @@ -87,19 +172,19 @@ void BRDITEMS_PLOTTER::PlotPad( D_PAD* aPad, EDA_COLOR_T aColor, EDA_DRAW_MODE_T wxPoint coord[4]; aPad->BuildPadPolygon( coord, wxSize(0,0), 0 ); m_plotter->FlashPadTrapez( shape_pos, coord, - aPad->GetOrientation(), aPlotMode ); + aPad->GetOrientation(), aPlotMode, &gbr_metadata ); } break; case PAD_SHAPE_ROUNDRECT: m_plotter->FlashPadRoundRect( shape_pos, aPad->GetSize(), aPad->GetRoundRectCornerRadius(), - aPad->GetOrientation(), aPlotMode ); + aPad->GetOrientation(), aPlotMode, &gbr_metadata ); break; case PAD_SHAPE_RECT: default: m_plotter->FlashPadRect( shape_pos, aPad->GetSize(), - aPad->GetOrientation(), aPlotMode ); + aPad->GetOrientation(), aPlotMode, &gbr_metadata ); break; } } @@ -236,11 +321,16 @@ void BRDITEMS_PLOTTER::PlotTextModule( TEXTE_MODULE* pt_texte, EDA_COLOR_T aColo // So we set bold flag to true bool allow_bold = pt_texte->IsBold() || thickness; + GBR_METADATA gbr_metadata; + gbr_metadata.SetNetAttribType( GBR_NETLIST_METADATA::GBR_NETINFO_CMP ); + MODULE* parent = static_cast ( pt_texte->GetParent() ); + gbr_metadata.SetCmpReference( parent->GetReference() ); + m_plotter->Text( pos, aColor, pt_texte->GetShownText(), orient, size, pt_texte->GetHorizJustify(), pt_texte->GetVertJustify(), - thickness, pt_texte->IsItalic(), allow_bold ); + thickness, pt_texte->IsItalic(), allow_bold, false, &gbr_metadata ); } @@ -379,15 +469,31 @@ void BRDITEMS_PLOTTER::Plot_1_EdgeModule( EDGE_MODULE* aEdge ) wxPoint pos( aEdge->GetStart() ); wxPoint end( aEdge->GetEnd() ); + GBR_METADATA gbr_metadata; + gbr_metadata.SetNetAttribType( GBR_NETLIST_METADATA::GBR_NETINFO_CMP ); + MODULE* parent = static_cast ( aEdge->GetParent() ); + gbr_metadata.SetCmpReference( parent->GetReference() ); + + bool isOnCopperLayer = ( m_layerMask & LSET::AllCuMask() ).any(); + + if( isOnCopperLayer ) + { + gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_ETCHEDCMP ); + } + else if( aEdge->GetLayer() == Edge_Cuts ) // happens also when plotting copper layers + { + gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_NONCONDUCTOR ); + } + switch( type_trace ) { case S_SEGMENT: - m_plotter->ThickSegment( pos, end, thickness, GetPlotMode() ); + m_plotter->ThickSegment( pos, end, thickness, GetPlotMode(), &gbr_metadata ); break; case S_CIRCLE: radius = KiROUND( GetLineLength( end, pos ) ); - m_plotter->ThickCircle( pos, radius * 2, thickness, GetPlotMode() ); + m_plotter->ThickCircle( pos, radius * 2, thickness, GetPlotMode(), &gbr_metadata ); break; case S_ARC: @@ -396,7 +502,7 @@ void BRDITEMS_PLOTTER::Plot_1_EdgeModule( EDGE_MODULE* aEdge ) double startAngle = ArcTangente( end.y - pos.y, end.x - pos.x ); double endAngle = startAngle + aEdge->GetAngle(); - m_plotter->ThickArc( pos, -endAngle, -startAngle, radius, thickness, GetPlotMode() ); + m_plotter->ThickArc( pos, -endAngle, -startAngle, radius, thickness, GetPlotMode(), &gbr_metadata ); } break; @@ -428,14 +534,14 @@ void BRDITEMS_PLOTTER::Plot_1_EdgeModule( EDGE_MODULE* aEdge ) cornerList.push_back( corner ); } - m_plotter->PlotPoly( cornerList, FILLED_SHAPE, thickness ); + m_plotter->PlotPoly( cornerList, FILLED_SHAPE, thickness, &gbr_metadata ); } break; } } -// Plot a PCB Text, i;e. a text found on a copper or technical layer +// Plot a PCB Text, i.e. a text found on a copper or technical layer void BRDITEMS_PLOTTER::PlotTextePcb( TEXTE_PCB* pt_texte ) { double orient; @@ -450,6 +556,13 @@ void BRDITEMS_PLOTTER::PlotTextePcb( TEXTE_PCB* pt_texte ) if( !m_layerMask[pt_texte->GetLayer()] ) return; + GBR_METADATA gbr_metadata; + + if( IsCopperLayer( pt_texte->GetLayer() ) ) + { + gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_NONCONDUCTOR ); + } + m_plotter->SetColor( getColor( pt_texte->GetLayer() ) ); size = pt_texte->GetSize(); @@ -480,14 +593,14 @@ void BRDITEMS_PLOTTER::PlotTextePcb( TEXTE_PCB* pt_texte ) wxString& txt = strings_list.Item( ii ); m_plotter->Text( positions[ii], UNSPECIFIED_COLOR, txt, orient, size, pt_texte->GetHorizJustify(), pt_texte->GetVertJustify(), - thickness, pt_texte->IsItalic(), allow_bold ); + thickness, pt_texte->IsItalic(), allow_bold, false, &gbr_metadata ); } } else { m_plotter->Text( pos, UNSPECIFIED_COLOR, shownText, orient, size, pt_texte->GetHorizJustify(), pt_texte->GetVertJustify(), - thickness, pt_texte->IsItalic(), allow_bold ); + thickness, pt_texte->IsItalic(), allow_bold, false, &gbr_metadata ); } } @@ -501,6 +614,26 @@ void BRDITEMS_PLOTTER::PlotFilledAreas( ZONE_CONTAINER* aZone ) if( polysList.IsEmpty() ) return; + GBR_METADATA gbr_metadata; + + bool isOnCopperLayer = aZone->IsOnCopperLayer(); + + if( isOnCopperLayer ) + { + gbr_metadata.SetNetName( aZone->GetNetname() ); + + // Zones with no net name can exist. + // they are not used to connect items, so the aperture attribute cannot + // be set as conductor + if( aZone->GetNetname().IsEmpty() ) + gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_NONCONDUCTOR ); + else + { + gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_CONDUCTOR ); + gbr_metadata.SetNetAttribType( GBR_NETLIST_METADATA::GBR_NETINFO_NET ); + } + } + // We need a buffer to store corners coordinates: static std::vector< wxPoint > cornerList; cornerList.clear(); @@ -533,7 +666,7 @@ void BRDITEMS_PLOTTER::PlotFilledAreas( ZONE_CONTAINER* aZone ) // The area can be filled by segments or uses solid polygons if( aZone->GetFillMode() == 0 ) // We are using solid polygons { - m_plotter->PlotPoly( cornerList, FILLED_SHAPE, aZone->GetMinThickness() ); + m_plotter->PlotPoly( cornerList, FILLED_SHAPE, aZone->GetMinThickness(), &gbr_metadata ); } else // We are using areas filled by segments: plot segments and outline { @@ -543,7 +676,7 @@ void BRDITEMS_PLOTTER::PlotFilledAreas( ZONE_CONTAINER* aZone ) wxPoint end = aZone->FillSegments()[iseg].m_End; m_plotter->ThickSegment( start, end, aZone->GetMinThickness(), - GetPlotMode() ); + GetPlotMode(), &gbr_metadata ); } // Plot the area outline only @@ -558,7 +691,7 @@ void BRDITEMS_PLOTTER::PlotFilledAreas( ZONE_CONTAINER* aZone ) for( unsigned jj = 1; jjThickSegment( cornerList[jj -1], cornerList[jj], aZone->GetMinThickness(), - GetPlotMode() ); + GetPlotMode(), &gbr_metadata ); } m_plotter->SetCurrentLineWidth( -1 ); @@ -584,37 +717,44 @@ void BRDITEMS_PLOTTER::PlotDrawSegment( DRAWSEGMENT* aSeg ) m_plotter->SetColor( getColor( aSeg->GetLayer() ) ); wxPoint start( aSeg->GetStart() ); - wxPoint end( aSeg->GetEnd() ); + wxPoint end( aSeg->GetEnd() ); - m_plotter->SetCurrentLineWidth( thickness ); + GBR_METADATA gbr_metadata; + + bool isOnCopperLayer = ( m_layerMask & LSET::AllCuMask() ).any(); + + if( isOnCopperLayer && aSeg->GetLayer() == Edge_Cuts ) // can happens when plotting copper layers + { + gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_NONCONDUCTOR ); + } switch( aSeg->GetShape() ) { case S_CIRCLE: radius = KiROUND( GetLineLength( end, start ) ); - m_plotter->ThickCircle( start, radius * 2, thickness, GetPlotMode() ); + m_plotter->ThickCircle( start, radius * 2, thickness, GetPlotMode(), &gbr_metadata ); break; case S_ARC: radius = KiROUND( GetLineLength( end, start ) ); StAngle = ArcTangente( end.y - start.y, end.x - start.x ); EndAngle = StAngle + aSeg->GetAngle(); - m_plotter->ThickArc( start, -EndAngle, -StAngle, radius, thickness, GetPlotMode() ); + m_plotter->ThickArc( start, -EndAngle, -StAngle, radius, thickness, GetPlotMode(), &gbr_metadata ); break; case S_CURVE: { + m_plotter->SetCurrentLineWidth( thickness, &gbr_metadata ); const std::vector& bezierPoints = aSeg->GetBezierPoints(); for( unsigned i = 1; i < bezierPoints.size(); i++ ) - m_plotter->ThickSegment( bezierPoints[i - 1], - bezierPoints[i], - thickness, GetPlotMode() ); + m_plotter->ThickSegment( bezierPoints[i - 1], bezierPoints[i], + thickness, GetPlotMode(), &gbr_metadata ); } break; default: - m_plotter->ThickSegment( start, end, thickness, GetPlotMode() ); + m_plotter->ThickSegment( start, end, thickness, GetPlotMode(), &gbr_metadata ); } } @@ -639,10 +779,10 @@ void BRDITEMS_PLOTTER::plotOneDrillMark( PAD_DRILL_SHAPE_T aDrillShape, { aDrillSize.y -= getFineWidthAdj(); aDrillSize.y = Clamp( 1, aDrillSize.y, aPadSize.y - 1 ); - m_plotter->FlashPadOval( aDrillPos, aDrillSize, aOrientation, GetPlotMode() ); + m_plotter->FlashPadOval( aDrillPos, aDrillSize, aOrientation, GetPlotMode(), NULL ); } else - m_plotter->FlashPadCircle( aDrillPos, aDrillSize.x, GetPlotMode() ); + m_plotter->FlashPadCircle( aDrillPos, aDrillSize.x, GetPlotMode(), NULL ); }