mirror of
https://gitlab.com/kicad/code/kicad.git
synced 2025-09-14 18:23:15 +02:00
Support custom padstacks in plotter
This commit is contained in:
parent
6e0f6da2fa
commit
752371833b
@ -101,7 +101,8 @@ public:
|
|||||||
* Unlike other items, a pad had not a specific color and be drawn as a non filled item
|
* Unlike other items, a pad had not a specific color and be drawn as a non filled item
|
||||||
* although the plot mode is filled color and plot mode are needed by this function.
|
* although the plot mode is filled color and plot mode are needed by this function.
|
||||||
*/
|
*/
|
||||||
void PlotPad( const PAD* aPad, const COLOR4D& aColor, OUTLINE_MODE aPlotMode );
|
void PlotPad( const PAD* aPad, PCB_LAYER_ID aLayer, const COLOR4D& aColor,
|
||||||
|
OUTLINE_MODE aPlotMode );
|
||||||
|
|
||||||
void PlotPadNumber( const PAD* aPad, const COLOR4D& aColor );
|
void PlotPadNumber( const PAD* aPad, const COLOR4D& aColor );
|
||||||
|
|
||||||
|
@ -367,210 +367,218 @@ void PlotStandardLayer( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
|
|||||||
itemplotter.PlotPadNumber( pad, color );
|
itemplotter.PlotPadNumber( pad, color );
|
||||||
}
|
}
|
||||||
|
|
||||||
VECTOR2I margin;
|
auto plotPadLayer =
|
||||||
int width_adj = 0;
|
[&]( PCB_LAYER_ID aLayer )
|
||||||
|
|
||||||
if( onCopperLayer )
|
|
||||||
width_adj = itemplotter.getFineWidthAdj();
|
|
||||||
|
|
||||||
if( onSolderMaskLayer )
|
|
||||||
margin.x = margin.y = pad->GetSolderMaskExpansion( PADSTACK::ALL_LAYERS );
|
|
||||||
|
|
||||||
if( onSolderPasteLayer )
|
|
||||||
margin = pad->GetSolderPasteMargin( PADSTACK::ALL_LAYERS );
|
|
||||||
|
|
||||||
// not all shapes can have a different margin for x and y axis
|
|
||||||
// in fact only oval and rect shapes can have different values.
|
|
||||||
// Round shape have always the same x,y margin
|
|
||||||
// so define a unique value for other shapes that do not support different values
|
|
||||||
int mask_clearance = margin.x;
|
|
||||||
|
|
||||||
// Now offset the pad size by margin + width_adj
|
|
||||||
VECTOR2I padPlotsSize = pad->GetSize( PADSTACK::ALL_LAYERS ) + margin * 2 + VECTOR2I( width_adj, width_adj );
|
|
||||||
|
|
||||||
// Store these parameters that can be modified to plot inflated/deflated pads shape
|
|
||||||
PAD_SHAPE padShape = pad->GetShape( PADSTACK::ALL_LAYERS );
|
|
||||||
VECTOR2I padSize = pad->GetSize( PADSTACK::ALL_LAYERS );
|
|
||||||
VECTOR2I padDelta = pad->GetDelta( PADSTACK::ALL_LAYERS ); // has meaning only for trapezoidal pads
|
|
||||||
// CornerRadius and CornerRadiusRatio can be modified
|
|
||||||
// the radius is built from the ratio, so saving/restoring the ratio is enough
|
|
||||||
double padCornerRadiusRatio = pad->GetRoundRectRadiusRatio( PADSTACK::ALL_LAYERS );
|
|
||||||
|
|
||||||
// Don't draw a 0 sized pad.
|
|
||||||
// Note: a custom pad can have its pad anchor with size = 0
|
|
||||||
if( pad->GetShape( PADSTACK::ALL_LAYERS ) != PAD_SHAPE::CUSTOM
|
|
||||||
&& ( padPlotsSize.x <= 0 || padPlotsSize.y <= 0 ) )
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch( pad->GetShape( PADSTACK::ALL_LAYERS ) )
|
|
||||||
{
|
|
||||||
case PAD_SHAPE::CIRCLE:
|
|
||||||
case PAD_SHAPE::OVAL:
|
|
||||||
pad->SetSize( PADSTACK::ALL_LAYERS, padPlotsSize );
|
|
||||||
|
|
||||||
if( aPlotOpt.GetSkipPlotNPTH_Pads() &&
|
|
||||||
( aPlotOpt.GetDrillMarksType() == DRILL_MARKS::NO_DRILL_SHAPE ) &&
|
|
||||||
( pad->GetSize( PADSTACK::ALL_LAYERS ) == pad->GetDrillSize() ) &&
|
|
||||||
( pad->GetAttribute() == PAD_ATTRIB::NPTH ) )
|
|
||||||
{
|
{
|
||||||
break;
|
VECTOR2I margin;
|
||||||
}
|
int width_adj = 0;
|
||||||
|
|
||||||
itemplotter.PlotPad( pad, color, padPlotMode );
|
if( onCopperLayer )
|
||||||
break;
|
width_adj = itemplotter.getFineWidthAdj();
|
||||||
|
|
||||||
case PAD_SHAPE::RECTANGLE:
|
if( onSolderMaskLayer )
|
||||||
pad->SetSize( PADSTACK::ALL_LAYERS, padPlotsSize );
|
margin.x = margin.y = pad->GetSolderMaskExpansion( aLayer );
|
||||||
|
|
||||||
if( mask_clearance > 0 )
|
if( onSolderPasteLayer )
|
||||||
{
|
margin = pad->GetSolderPasteMargin( aLayer );
|
||||||
pad->SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::ROUNDRECT );
|
|
||||||
pad->SetRoundRectCornerRadius( PADSTACK::ALL_LAYERS, mask_clearance );
|
|
||||||
}
|
|
||||||
|
|
||||||
itemplotter.PlotPad( pad, color, padPlotMode );
|
// not all shapes can have a different margin for x and y axis
|
||||||
break;
|
// in fact only oval and rect shapes can have different values.
|
||||||
|
// Round shape have always the same x,y margin
|
||||||
|
// so define a unique value for other shapes that do not support different values
|
||||||
|
int mask_clearance = margin.x;
|
||||||
|
|
||||||
case PAD_SHAPE::TRAPEZOID:
|
// Now offset the pad size by margin + width_adj
|
||||||
// inflate/deflate a trapezoid is a bit complex.
|
VECTOR2I padPlotsSize =
|
||||||
// so if the margin is not null, build a similar polygonal pad shape,
|
pad->GetSize( aLayer ) + margin * 2 + VECTOR2I( width_adj, width_adj );
|
||||||
// and inflate/deflate the polygonal shape
|
|
||||||
// because inflating/deflating using different values for y and y
|
|
||||||
// we are using only margin.x as inflate/deflate value
|
|
||||||
if( mask_clearance == 0 )
|
|
||||||
{
|
|
||||||
itemplotter.PlotPad( pad, color, padPlotMode );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PAD dummy( *pad );
|
|
||||||
dummy.SetAnchorPadShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::CIRCLE );
|
|
||||||
dummy.SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::CUSTOM );
|
|
||||||
SHAPE_POLY_SET outline;
|
|
||||||
outline.NewOutline();
|
|
||||||
int dx = padSize.x / 2;
|
|
||||||
int dy = padSize.y / 2;
|
|
||||||
int ddx = padDelta.x / 2;
|
|
||||||
int ddy = padDelta.y / 2;
|
|
||||||
|
|
||||||
outline.Append( -dx - ddy, dy + ddx );
|
// Store these parameters that can be modified to plot inflated/deflated pads shape
|
||||||
outline.Append( dx + ddy, dy - ddx );
|
PAD_SHAPE padShape = pad->GetShape( aLayer );
|
||||||
outline.Append( dx - ddy, -dy + ddx );
|
VECTOR2I padSize = pad->GetSize( aLayer );
|
||||||
outline.Append( -dx + ddy, -dy - ddx );
|
VECTOR2I padDelta = pad->GetDelta( aLayer ); // has meaning only for trapezoidal pads
|
||||||
|
// CornerRadius and CornerRadiusRatio can be modified
|
||||||
|
// the radius is built from the ratio, so saving/restoring the ratio is enough
|
||||||
|
double padCornerRadiusRatio = pad->GetRoundRectRadiusRatio( aLayer );
|
||||||
|
|
||||||
// Shape polygon can have holes so use InflateWithLinkedHoles(), not Inflate()
|
// Don't draw a 0 sized pad.
|
||||||
// which can create bad shapes if margin.x is < 0
|
// Note: a custom pad can have its pad anchor with size = 0
|
||||||
outline.InflateWithLinkedHoles( mask_clearance,
|
if( padShape != PAD_SHAPE::CUSTOM
|
||||||
CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError,
|
&& ( padPlotsSize.x <= 0 || padPlotsSize.y <= 0 ) )
|
||||||
SHAPE_POLY_SET::PM_FAST );
|
{
|
||||||
dummy.DeletePrimitivesList();
|
return;
|
||||||
dummy.AddPrimitivePoly( PADSTACK::ALL_LAYERS, outline, 0, true );
|
}
|
||||||
|
|
||||||
// Be sure the anchor pad is not bigger than the deflated shape because this
|
switch( padShape )
|
||||||
// anchor will be added to the pad shape when plotting the pad. So now the
|
{
|
||||||
// polygonal shape is built, we can clamp the anchor size
|
case PAD_SHAPE::CIRCLE:
|
||||||
dummy.SetSize( PADSTACK::ALL_LAYERS, VECTOR2I( 0, 0 ) );
|
case PAD_SHAPE::OVAL:
|
||||||
|
pad->SetSize( aLayer, padPlotsSize );
|
||||||
|
|
||||||
itemplotter.PlotPad( &dummy, color, padPlotMode );
|
if( aPlotOpt.GetSkipPlotNPTH_Pads() &&
|
||||||
}
|
( aPlotOpt.GetDrillMarksType() == DRILL_MARKS::NO_DRILL_SHAPE ) &&
|
||||||
|
( pad->GetSize(aLayer ) == pad->GetDrillSize() ) &&
|
||||||
|
( pad->GetAttribute() == PAD_ATTRIB::NPTH ) )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
itemplotter.PlotPad( pad, aLayer, color, padPlotMode );
|
||||||
|
break;
|
||||||
|
|
||||||
case PAD_SHAPE::ROUNDRECT:
|
case PAD_SHAPE::RECTANGLE:
|
||||||
{
|
pad->SetSize( aLayer, padPlotsSize );
|
||||||
// rounding is stored as a percent, but we have to update this ratio
|
|
||||||
// to force recalculation of other values after size changing (we do not
|
|
||||||
// really change the rounding percent value)
|
|
||||||
double radius_ratio = pad->GetRoundRectRadiusRatio( PADSTACK::ALL_LAYERS );
|
|
||||||
pad->SetSize( PADSTACK::ALL_LAYERS, padPlotsSize );
|
|
||||||
pad->SetRoundRectRadiusRatio( PADSTACK::ALL_LAYERS, radius_ratio );
|
|
||||||
|
|
||||||
itemplotter.PlotPad( pad, color, padPlotMode );
|
if( mask_clearance > 0 )
|
||||||
break;
|
{
|
||||||
}
|
pad->SetShape( aLayer, PAD_SHAPE::ROUNDRECT );
|
||||||
|
pad->SetRoundRectCornerRadius( aLayer, mask_clearance );
|
||||||
|
}
|
||||||
|
|
||||||
case PAD_SHAPE::CHAMFERED_RECT:
|
itemplotter.PlotPad( pad, aLayer, color, padPlotMode );
|
||||||
if( mask_clearance == 0 )
|
break;
|
||||||
{
|
|
||||||
// the size can be slightly inflated by width_adj (PS/PDF only)
|
|
||||||
pad->SetSize( PADSTACK::ALL_LAYERS, padPlotsSize );
|
|
||||||
itemplotter.PlotPad( pad, color, padPlotMode );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Due to the polygonal shape of a CHAMFERED_RECT pad, the best way is to
|
|
||||||
// convert the pad shape to a full polygon, inflate/deflate the polygon
|
|
||||||
// and use a dummy CUSTOM pad to plot the final shape.
|
|
||||||
PAD dummy( *pad );
|
|
||||||
// Build the dummy pad outline with coordinates relative to the pad position
|
|
||||||
// pad offset and orientation 0. The actual pos, offset and rotation will be
|
|
||||||
// taken in account later by the plot function
|
|
||||||
dummy.SetPosition( VECTOR2I( 0, 0 ) );
|
|
||||||
dummy.SetOffset( PADSTACK::ALL_LAYERS, VECTOR2I( 0, 0 ) );
|
|
||||||
dummy.SetOrientation( ANGLE_0 );
|
|
||||||
SHAPE_POLY_SET outline;
|
|
||||||
dummy.TransformShapeToPolygon( outline, UNDEFINED_LAYER, 0, maxError,
|
|
||||||
ERROR_INSIDE );
|
|
||||||
outline.InflateWithLinkedHoles( mask_clearance,
|
|
||||||
CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError,
|
|
||||||
SHAPE_POLY_SET::PM_FAST );
|
|
||||||
|
|
||||||
// Initialize the dummy pad shape:
|
case PAD_SHAPE::TRAPEZOID:
|
||||||
dummy.SetAnchorPadShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::CIRCLE );
|
// inflate/deflate a trapezoid is a bit complex.
|
||||||
dummy.SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::CUSTOM );
|
// so if the margin is not null, build a similar polygonal pad shape,
|
||||||
dummy.DeletePrimitivesList();
|
// and inflate/deflate the polygonal shape
|
||||||
dummy.AddPrimitivePoly( PADSTACK::ALL_LAYERS, outline, 0, true );
|
// because inflating/deflating using different values for y and y
|
||||||
|
// we are using only margin.x as inflate/deflate value
|
||||||
|
if( mask_clearance == 0 )
|
||||||
|
{
|
||||||
|
itemplotter.PlotPad( pad, aLayer, color, padPlotMode );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PAD dummy( *pad );
|
||||||
|
dummy.SetAnchorPadShape( aLayer, PAD_SHAPE::CIRCLE );
|
||||||
|
dummy.SetShape( aLayer, PAD_SHAPE::CUSTOM );
|
||||||
|
SHAPE_POLY_SET outline;
|
||||||
|
outline.NewOutline();
|
||||||
|
int dx = padSize.x / 2;
|
||||||
|
int dy = padSize.y / 2;
|
||||||
|
int ddx = padDelta.x / 2;
|
||||||
|
int ddy = padDelta.y / 2;
|
||||||
|
|
||||||
// Be sure the anchor pad is not bigger than the deflated shape because this
|
outline.Append( -dx - ddy, dy + ddx );
|
||||||
// anchor will be added to the pad shape when plotting the pad.
|
outline.Append( dx + ddy, dy - ddx );
|
||||||
// So we set the anchor size to 0
|
outline.Append( dx - ddy, -dy + ddx );
|
||||||
dummy.SetSize( PADSTACK::ALL_LAYERS, VECTOR2I( 0, 0 ) );
|
outline.Append( -dx + ddy, -dy - ddx );
|
||||||
// Restore pad position and offset
|
|
||||||
dummy.SetPosition( pad->GetPosition() );
|
|
||||||
dummy.SetOffset( PADSTACK::ALL_LAYERS, pad->GetOffset( PADSTACK::ALL_LAYERS ) );
|
|
||||||
dummy.SetOrientation( pad->GetOrientation() );
|
|
||||||
|
|
||||||
itemplotter.PlotPad( &dummy, color, padPlotMode );
|
// Shape polygon can have holes so use InflateWithLinkedHoles(), not Inflate()
|
||||||
}
|
// which can create bad shapes if margin.x is < 0
|
||||||
|
outline.InflateWithLinkedHoles( mask_clearance,
|
||||||
|
CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError,
|
||||||
|
SHAPE_POLY_SET::PM_FAST );
|
||||||
|
dummy.DeletePrimitivesList();
|
||||||
|
dummy.AddPrimitivePoly( aLayer, outline, 0, true );
|
||||||
|
|
||||||
break;
|
// Be sure the anchor pad is not bigger than the deflated shape because this
|
||||||
|
// anchor will be added to the pad shape when plotting the pad. So now the
|
||||||
|
// polygonal shape is built, we can clamp the anchor size
|
||||||
|
dummy.SetSize( aLayer, VECTOR2I( 0, 0 ) );
|
||||||
|
|
||||||
case PAD_SHAPE::CUSTOM:
|
itemplotter.PlotPad( &dummy, aLayer, color, padPlotMode );
|
||||||
{
|
}
|
||||||
// inflate/deflate a custom shape is a bit complex.
|
|
||||||
// so build a similar pad shape, and inflate/deflate the polygonal shape
|
|
||||||
PAD dummy( *pad );
|
|
||||||
dummy.SetParentGroup( nullptr );
|
|
||||||
|
|
||||||
SHAPE_POLY_SET shape;
|
break;
|
||||||
pad->MergePrimitivesAsPolygon( PADSTACK::ALL_LAYERS, &shape );
|
|
||||||
|
|
||||||
// Shape polygon can have holes so use InflateWithLinkedHoles(), not Inflate()
|
case PAD_SHAPE::ROUNDRECT:
|
||||||
// which can create bad shapes if margin.x is < 0
|
{
|
||||||
shape.InflateWithLinkedHoles( mask_clearance,
|
// rounding is stored as a percent, but we have to update this ratio
|
||||||
CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError,
|
// to force recalculation of other values after size changing (we do not
|
||||||
SHAPE_POLY_SET::PM_FAST );
|
// really change the rounding percent value)
|
||||||
dummy.DeletePrimitivesList();
|
double radius_ratio = pad->GetRoundRectRadiusRatio( aLayer );
|
||||||
dummy.AddPrimitivePoly( PADSTACK::ALL_LAYERS, shape, 0, true );
|
pad->SetSize( aLayer, padPlotsSize );
|
||||||
|
pad->SetRoundRectRadiusRatio( aLayer, radius_ratio );
|
||||||
|
|
||||||
// Be sure the anchor pad is not bigger than the deflated shape because this
|
itemplotter.PlotPad( pad, aLayer, color, padPlotMode );
|
||||||
// anchor will be added to the pad shape when plotting the pad. So now the
|
break;
|
||||||
// polygonal shape is built, we can clamp the anchor size
|
}
|
||||||
if( mask_clearance < 0 ) // we expect margin.x = margin.y for custom pads
|
|
||||||
dummy.SetSize( PADSTACK::ALL_LAYERS, padPlotsSize );
|
|
||||||
|
|
||||||
itemplotter.PlotPad( &dummy, color, padPlotMode );
|
case PAD_SHAPE::CHAMFERED_RECT:
|
||||||
break;
|
if( mask_clearance == 0 )
|
||||||
}
|
{
|
||||||
}
|
// the size can be slightly inflated by width_adj (PS/PDF only)
|
||||||
|
pad->SetSize( aLayer, padPlotsSize );
|
||||||
|
itemplotter.PlotPad( pad, aLayer, color, padPlotMode );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Due to the polygonal shape of a CHAMFERED_RECT pad, the best way is to
|
||||||
|
// convert the pad shape to a full polygon, inflate/deflate the polygon
|
||||||
|
// and use a dummy CUSTOM pad to plot the final shape.
|
||||||
|
PAD dummy( *pad );
|
||||||
|
// Build the dummy pad outline with coordinates relative to the pad position
|
||||||
|
// pad offset and orientation 0. The actual pos, offset and rotation will be
|
||||||
|
// taken in account later by the plot function
|
||||||
|
dummy.SetPosition( VECTOR2I( 0, 0 ) );
|
||||||
|
dummy.SetOffset( aLayer, VECTOR2I( 0, 0 ) );
|
||||||
|
dummy.SetOrientation( ANGLE_0 );
|
||||||
|
SHAPE_POLY_SET outline;
|
||||||
|
dummy.TransformShapeToPolygon( outline, UNDEFINED_LAYER, 0, maxError,
|
||||||
|
ERROR_INSIDE );
|
||||||
|
outline.InflateWithLinkedHoles( mask_clearance,
|
||||||
|
CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError,
|
||||||
|
SHAPE_POLY_SET::PM_FAST );
|
||||||
|
|
||||||
// Restore the pad parameters modified by the plot code
|
// Initialize the dummy pad shape:
|
||||||
pad->SetSize( PADSTACK::ALL_LAYERS, padSize );
|
dummy.SetAnchorPadShape( aLayer, PAD_SHAPE::CIRCLE );
|
||||||
pad->SetDelta( PADSTACK::ALL_LAYERS, padDelta );
|
dummy.SetShape( aLayer, PAD_SHAPE::CUSTOM );
|
||||||
pad->SetShape( PADSTACK::ALL_LAYERS, padShape );
|
dummy.DeletePrimitivesList();
|
||||||
pad->SetRoundRectRadiusRatio( PADSTACK::ALL_LAYERS, padCornerRadiusRatio );
|
dummy.AddPrimitivePoly( aLayer, outline, 0, true );
|
||||||
|
|
||||||
|
// Be sure the anchor pad is not bigger than the deflated shape because this
|
||||||
|
// anchor will be added to the pad shape when plotting the pad.
|
||||||
|
// So we set the anchor size to 0
|
||||||
|
dummy.SetSize( aLayer, VECTOR2I( 0, 0 ) );
|
||||||
|
// Restore pad position and offset
|
||||||
|
dummy.SetPosition( pad->GetPosition() );
|
||||||
|
dummy.SetOffset( aLayer, pad->GetOffset( aLayer ) );
|
||||||
|
dummy.SetOrientation( pad->GetOrientation() );
|
||||||
|
|
||||||
|
itemplotter.PlotPad( &dummy, aLayer, color, padPlotMode );
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PAD_SHAPE::CUSTOM:
|
||||||
|
{
|
||||||
|
// inflate/deflate a custom shape is a bit complex.
|
||||||
|
// so build a similar pad shape, and inflate/deflate the polygonal shape
|
||||||
|
PAD dummy( *pad );
|
||||||
|
dummy.SetParentGroup( nullptr );
|
||||||
|
|
||||||
|
SHAPE_POLY_SET shape;
|
||||||
|
pad->MergePrimitivesAsPolygon( aLayer, &shape );
|
||||||
|
|
||||||
|
// Shape polygon can have holes so use InflateWithLinkedHoles(), not Inflate()
|
||||||
|
// which can create bad shapes if margin.x is < 0
|
||||||
|
shape.InflateWithLinkedHoles( mask_clearance,
|
||||||
|
CORNER_STRATEGY::ROUND_ALL_CORNERS, maxError,
|
||||||
|
SHAPE_POLY_SET::PM_FAST );
|
||||||
|
dummy.DeletePrimitivesList();
|
||||||
|
dummy.AddPrimitivePoly( aLayer, shape, 0, true );
|
||||||
|
|
||||||
|
// Be sure the anchor pad is not bigger than the deflated shape because this
|
||||||
|
// anchor will be added to the pad shape when plotting the pad. So now the
|
||||||
|
// polygonal shape is built, we can clamp the anchor size
|
||||||
|
if( mask_clearance < 0 ) // we expect margin.x = margin.y for custom pads
|
||||||
|
dummy.SetSize( aLayer, padPlotsSize );
|
||||||
|
|
||||||
|
itemplotter.PlotPad( &dummy, aLayer, color, padPlotMode );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore the pad parameters modified by the plot code
|
||||||
|
pad->SetSize( aLayer, padSize );
|
||||||
|
pad->SetDelta( aLayer, padDelta );
|
||||||
|
pad->SetShape( aLayer, padShape );
|
||||||
|
pad->SetRoundRectRadiusRatio( aLayer, padCornerRadiusRatio );
|
||||||
|
};
|
||||||
|
|
||||||
|
for( PCB_LAYER_ID layer : aLayerMask.SeqStackupForPlotting() )
|
||||||
|
plotPadLayer( layer );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( footprint->IsDNP()
|
if( footprint->IsDNP()
|
||||||
|
@ -142,9 +142,10 @@ void BRDITEMS_PLOTTER::PlotPadNumber( const PAD* aPad, const COLOR4D& aColor )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void BRDITEMS_PLOTTER::PlotPad( const PAD* aPad, const COLOR4D& aColor, OUTLINE_MODE aPlotMode )
|
void BRDITEMS_PLOTTER::PlotPad( const PAD* aPad, PCB_LAYER_ID aLayer, const COLOR4D& aColor,
|
||||||
|
OUTLINE_MODE aPlotMode )
|
||||||
{
|
{
|
||||||
VECTOR2I shape_pos = aPad->ShapePos( PADSTACK::ALL_LAYERS );
|
VECTOR2I shape_pos = aPad->ShapePos( aLayer );
|
||||||
GBR_METADATA metadata;
|
GBR_METADATA metadata;
|
||||||
|
|
||||||
bool plotOnCopperLayer = ( m_layerMask & LSET::AllCuMask() ).any();
|
bool plotOnCopperLayer = ( m_layerMask & LSET::AllCuMask() ).any();
|
||||||
@ -269,31 +270,31 @@ void BRDITEMS_PLOTTER::PlotPad( const PAD* aPad, const COLOR4D& aColor, OUTLINE_
|
|||||||
|
|
||||||
// Set plot color (change WHITE to LIGHTGRAY because
|
// Set plot color (change WHITE to LIGHTGRAY because
|
||||||
// the white items are not seen on a white paper or screen
|
// the white items are not seen on a white paper or screen
|
||||||
m_plotter->SetColor( aColor != WHITE ? aColor : LIGHTGRAY);
|
m_plotter->SetColor( aColor != WHITE ? aColor : LIGHTGRAY );
|
||||||
|
|
||||||
if( aPlotMode == SKETCH )
|
if( aPlotMode == SKETCH )
|
||||||
m_plotter->SetCurrentLineWidth( GetSketchPadLineWidth(), &metadata );
|
m_plotter->SetCurrentLineWidth( GetSketchPadLineWidth(), &metadata );
|
||||||
|
|
||||||
switch( aPad->GetShape( PADSTACK::ALL_LAYERS ) )
|
switch( aPad->GetShape( aLayer ) )
|
||||||
{
|
{
|
||||||
case PAD_SHAPE::CIRCLE:
|
case PAD_SHAPE::CIRCLE:
|
||||||
m_plotter->FlashPadCircle( shape_pos, aPad->GetSize( PADSTACK::ALL_LAYERS ).x,
|
m_plotter->FlashPadCircle( shape_pos, aPad->GetSize( aLayer ).x,
|
||||||
aPlotMode, &metadata );
|
aPlotMode, &metadata );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PAD_SHAPE::OVAL:
|
case PAD_SHAPE::OVAL:
|
||||||
m_plotter->FlashPadOval( shape_pos, aPad->GetSize( PADSTACK::ALL_LAYERS ),
|
m_plotter->FlashPadOval( shape_pos, aPad->GetSize( aLayer ),
|
||||||
aPad->GetOrientation(), aPlotMode, &metadata );
|
aPad->GetOrientation(), aPlotMode, &metadata );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PAD_SHAPE::RECTANGLE:
|
case PAD_SHAPE::RECTANGLE:
|
||||||
m_plotter->FlashPadRect( shape_pos, aPad->GetSize( PADSTACK::ALL_LAYERS ),
|
m_plotter->FlashPadRect( shape_pos, aPad->GetSize( aLayer ),
|
||||||
aPad->GetOrientation(), aPlotMode, &metadata );
|
aPad->GetOrientation(), aPlotMode, &metadata );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PAD_SHAPE::ROUNDRECT:
|
case PAD_SHAPE::ROUNDRECT:
|
||||||
m_plotter->FlashPadRoundRect( shape_pos, aPad->GetSize( PADSTACK::ALL_LAYERS ),
|
m_plotter->FlashPadRoundRect( shape_pos, aPad->GetSize( aLayer ),
|
||||||
aPad->GetRoundRectCornerRadius( PADSTACK::ALL_LAYERS ),
|
aPad->GetRoundRectCornerRadius( aLayer ),
|
||||||
aPad->GetOrientation(), aPlotMode, &metadata );
|
aPad->GetOrientation(), aPlotMode, &metadata );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -305,8 +306,8 @@ void BRDITEMS_PLOTTER::PlotPad( const PAD* aPad, const COLOR4D& aColor, OUTLINE_
|
|||||||
VECTOR2I coord[4];
|
VECTOR2I coord[4];
|
||||||
|
|
||||||
// Order is lower left, lower right, upper right, upper left.
|
// Order is lower left, lower right, upper right, upper left.
|
||||||
VECTOR2I half_size = aPad->GetSize( PADSTACK::ALL_LAYERS ) / 2;
|
VECTOR2I half_size = aPad->GetSize( aLayer ) / 2;
|
||||||
VECTOR2I trap_delta = aPad->GetDelta( PADSTACK::ALL_LAYERS ) / 2;
|
VECTOR2I trap_delta = aPad->GetDelta( aLayer ) / 2;
|
||||||
|
|
||||||
coord[0] = VECTOR2I( -half_size.x - trap_delta.y, half_size.y + trap_delta.x );
|
coord[0] = VECTOR2I( -half_size.x - trap_delta.y, half_size.y + trap_delta.x );
|
||||||
coord[1] = VECTOR2I( half_size.x + trap_delta.y, half_size.y - trap_delta.x );
|
coord[1] = VECTOR2I( half_size.x + trap_delta.y, half_size.y - trap_delta.x );
|
||||||
@ -323,10 +324,10 @@ void BRDITEMS_PLOTTER::PlotPad( const PAD* aPad, const COLOR4D& aColor, OUTLINE_
|
|||||||
GERBER_PLOTTER* gerberPlotter = static_cast<GERBER_PLOTTER*>( m_plotter );
|
GERBER_PLOTTER* gerberPlotter = static_cast<GERBER_PLOTTER*>( m_plotter );
|
||||||
|
|
||||||
gerberPlotter->FlashPadChamferRoundRect( shape_pos,
|
gerberPlotter->FlashPadChamferRoundRect( shape_pos,
|
||||||
aPad->GetSize( PADSTACK::ALL_LAYERS ),
|
aPad->GetSize( aLayer ),
|
||||||
aPad->GetRoundRectCornerRadius( PADSTACK::ALL_LAYERS ),
|
aPad->GetRoundRectCornerRadius( aLayer ),
|
||||||
aPad->GetChamferRectRatio( PADSTACK::ALL_LAYERS ),
|
aPad->GetChamferRectRatio( aLayer ),
|
||||||
aPad->GetChamferPositions( PADSTACK::ALL_LAYERS ), aPad->GetOrientation(),
|
aPad->GetChamferPositions( aLayer ), aPad->GetOrientation(),
|
||||||
aPlotMode, &metadata );
|
aPlotMode, &metadata );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -337,11 +338,11 @@ void BRDITEMS_PLOTTER::PlotPad( const PAD* aPad, const COLOR4D& aColor, OUTLINE_
|
|||||||
case PAD_SHAPE::CUSTOM:
|
case PAD_SHAPE::CUSTOM:
|
||||||
{
|
{
|
||||||
const std::shared_ptr<SHAPE_POLY_SET>& polygons =
|
const std::shared_ptr<SHAPE_POLY_SET>& polygons =
|
||||||
aPad->GetEffectivePolygon( PADSTACK::ALL_LAYERS, ERROR_INSIDE );
|
aPad->GetEffectivePolygon( aLayer, ERROR_INSIDE );
|
||||||
|
|
||||||
if( polygons->OutlineCount() )
|
if( polygons->OutlineCount() )
|
||||||
{
|
{
|
||||||
m_plotter->FlashPadCustom( shape_pos, aPad->GetSize( PADSTACK::ALL_LAYERS ), aPad->GetOrientation(),
|
m_plotter->FlashPadCustom( shape_pos, aPad->GetSize( aLayer ), aPad->GetOrientation(),
|
||||||
polygons.get(), aPlotMode, &metadata );
|
polygons.get(), aPlotMode, &metadata );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user