Prepare Plot Gerber file to include advanced aperture and net attributes.

This option is not yet activated because the net attributes are not yet fully fixed by Ucamco, in Gerber file format specifications.
(To activate it, see dialog_plot.cpp, line 43)
This commit is contained in:
jean-pierre charras
2016-09-19 13:01:36 +02:00
parent 7f9380af26
commit 6edee2ae1d
26 changed files with 1607 additions and 306 deletions
+168 -28
View File
@@ -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 <pcbnew.h>
#include <pcbplot.h>
#include <plot_auxiliary_data.h>
/* 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<MODULE*> ( 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<MODULE*> ( 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; jj<cornerList.size(); jj++ )
m_plotter->ThickSegment( 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<wxPoint>& 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 );
}