From b2dff6fa55c35d4ed1ee62f04d8a8968fd7c6c13 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Mon, 23 Aug 2021 11:25:02 +0100 Subject: [PATCH] Fix solder mask plotting issues. 1) Don't plot all footprint texts for each footprint graphic item. 2) Enforce min web thickness around board shapes and board text. 3) Enforce min web thickness around footprint shapes 4) Correctly handle multi-layer zones. (1) and (4) will get cherry-picked back to 6.0, so after rebasing won't actually appear in this changelist anymore.... --- pcbnew/drc/drc_test_provider_solder_mask.cpp | 2 - pcbnew/pcbplot.h | 2 + pcbnew/plot_board_layers.cpp | 103 ++++++++++--------- pcbnew/plot_brditems_plotter.cpp | 60 ++++++----- 4 files changed, 87 insertions(+), 80 deletions(-) diff --git a/pcbnew/drc/drc_test_provider_solder_mask.cpp b/pcbnew/drc/drc_test_provider_solder_mask.cpp index 8b17511cbd..7bdc3269fc 100644 --- a/pcbnew/drc/drc_test_provider_solder_mask.cpp +++ b/pcbnew/drc/drc_test_provider_solder_mask.cpp @@ -153,8 +153,6 @@ void DRC_TEST_PROVIDER_SOLDER_MASK::addItemToRTrees( BOARD_ITEM* item ) } else { - // JEY TODO: plotter doesn't currently expand graphics by web thickness... - for( PCB_LAYER_ID layer : { F_Mask, B_Mask } ) { if( item->IsOnLayer( layer ) ) diff --git a/pcbnew/pcbplot.h b/pcbnew/pcbplot.h index 52420c3573..20cad0301a 100644 --- a/pcbnew/pcbplot.h +++ b/pcbnew/pcbplot.h @@ -28,6 +28,7 @@ #include #include #include +#include class PLOTTER; class PCB_TEXT; @@ -105,6 +106,7 @@ public: * Plot items like text and graphics but not tracks and footprints. */ void PlotBoardGraphicItems(); + void PlotPcbGraphicItem( const BOARD_ITEM* item ); /** * Draw a drill mark for pads and vias. diff --git a/pcbnew/plot_board_layers.cpp b/pcbnew/plot_board_layers.cpp index 1c83be5c07..6ad7849e62 100644 --- a/pcbnew/plot_board_layers.cpp +++ b/pcbnew/plot_board_layers.cpp @@ -821,31 +821,16 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask, if( aBoard->GetBoardPolygonOutlines( buffer ) ) boardOutline = &buffer; - // We remove 1nm as we expand both sides of the shapes, so allowing for - // a strictly greater than or equal comparison in the shape separation (boolean add) - // means that we will end up with separate shapes that then are shrunk + // We remove 1nm as we expand both sides of the shapes, so allowing for a strictly greater + // than or equal comparison in the shape separation (boolean add) int inflate = aMinThickness/2 - 1; BRDITEMS_PLOTTER itemplotter( aPlotter, aBoard, aPlotOpt ); itemplotter.SetLayerSet( aLayerMask ); - // Plot edge layer and graphic items. - // They do not have a solder Mask margin, because they are graphic items - // on this layer (like logos), not actually areas around pads. - - itemplotter.PlotBoardGraphicItems(); - for( FOOTPRINT* footprint : aBoard->Footprints() ) - { itemplotter.PlotFootprintTextItems( footprint ); - for( BOARD_ITEM* item : footprint->GraphicalItems() ) - { - if( item->Type() == PCB_FP_SHAPE_T && item->GetLayer() == layer ) - itemplotter.PlotFootprintGraphicItem( (FP_SHAPE*) item ); - } - } - // Build polygons for each pad shape. The size of the shape on solder mask should be size // of pad + clearance around the pad, where clearance = solder mask clearance + extra margin. // Extra margin is half the min width for solder mask, which is used to merge too-close shapes @@ -860,13 +845,13 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask, SHAPE_POLY_SET initialPolys; #if NEW_ALGO - // Generate polygons with arcs inside the shape or exact shape - // to minimize shape changes created by arc to segment size correction. + // Generate polygons with arcs inside the shape or exact shape to minimize shape changes + // created by arc to segment size correction. DISABLE_ARC_RADIUS_CORRECTION disabler; #endif { - // Plot pads - for( FOOTPRINT* footprint : aBoard->Footprints() ) + // Plot footprint pads and graphics + for( const FOOTPRINT* footprint : aBoard->Footprints() ) { // add shapes with their exact mask layer size in initialPolys footprint->TransformPadsWithClearanceToPolygon( initialPolys, layer, 0, maxError, @@ -874,40 +859,41 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask, // add shapes inflated by aMinThickness/2 in areas footprint->TransformPadsWithClearanceToPolygon( areas, layer, inflate, maxError, ERROR_OUTSIDE ); + + for( const BOARD_ITEM* item : footprint->GraphicalItems() ) + { + if( item->Type() == PCB_FP_SHAPE_T && item->IsOnLayer( layer ) ) + { + // add shapes with their exact mask layer size in initialPolys + item->TransformShapeWithClearanceToPolygon( initialPolys, layer, 0, maxError, + ERROR_OUTSIDE ); + // add shapes inflated by aMinThickness/2 in areas + item->TransformShapeWithClearanceToPolygon( areas, layer, inflate, maxError, + ERROR_OUTSIDE ); + } + else if( item->Type() == PCB_FP_SHAPE_T && item->IsOnLayer( Edge_Cuts ) ) + { + itemplotter.PlotFootprintGraphicItem( static_cast( item ) ); + } + } } - // Plot vias on solder masks, if aPlotOpt.GetPlotViaOnMaskLayer() is true, - if( aPlotOpt.GetPlotViaOnMaskLayer() ) + // Plot (untented) vias + for( const PCB_TRACK* track : aBoard->Tracks() ) { - for( PCB_TRACK* track : aBoard->Tracks() ) - { - const PCB_VIA* via = dyn_cast( track ); - int via_clearance = via->GetSolderMaskExpansion(); - int via_margin = via_clearance + inflate; + const PCB_VIA* via = dyn_cast( track ); + int clearance = via->GetSolderMaskExpansion(); + // Note: IsOnLayer() checks relevant mask layers of untented vias + if( !via || !via->IsOnLayer( layer ) ) + continue; - if( !via ) - continue; - - // vias are plotted only if they are on the corresponding external copper layer - LSET via_set = via->GetLayerSet(); - - if( via_set[B_Cu] ) - via_set.set( B_Mask ); - - if( via_set[F_Cu] ) - via_set.set( F_Mask ); - - if( !( via_set & aLayerMask ).any() ) - continue; - - // add shapes with their exact mask layer size in initialPolys - via->TransformShapeWithClearanceToPolygon( initialPolys, layer, via_clearance, - maxError, ERROR_OUTSIDE ); - // add shapes inflated by aMinThickness/2 in areas - via->TransformShapeWithClearanceToPolygon( areas, layer, via_margin, maxError, - ERROR_OUTSIDE ); - } + // add shapes with their exact mask layer size in initialPolys + via->TransformShapeWithClearanceToPolygon( initialPolys, layer, clearance, maxError, + ERROR_OUTSIDE ); + // add shapes inflated by aMinThickness/2 in areas + via->TransformShapeWithClearanceToPolygon( areas, layer, clearance + inflate, maxError, + ERROR_OUTSIDE ); } // Add filled zone areas. @@ -917,6 +903,23 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask, int zone_margin = 0; #endif + for( const BOARD_ITEM* item : aBoard->Drawings() ) + { + if( item->IsOnLayer( layer ) ) + { + // add shapes with their exact mask layer size in initialPolys + item->TransformShapeWithClearanceToPolygon( initialPolys, layer, 0, maxError, + ERROR_OUTSIDE ); + // add shapes inflated by aMinThickness/2 in areas + item->TransformShapeWithClearanceToPolygon( areas, layer, inflate, maxError, + ERROR_OUTSIDE ); + } + else if( item->IsOnLayer( Edge_Cuts ) ) + { + itemplotter.PlotPcbGraphicItem( item ); + } + } + for( ZONE* zone : aBoard->Zones() ) { if( !zone->IsOnLayer( layer ) ) diff --git a/pcbnew/plot_brditems_plotter.cpp b/pcbnew/plot_brditems_plotter.cpp index ef9769f9e8..d6824e1ae8 100644 --- a/pcbnew/plot_brditems_plotter.cpp +++ b/pcbnew/plot_brditems_plotter.cpp @@ -340,36 +340,40 @@ void BRDITEMS_PLOTTER::PlotFootprintTextItems( const FOOTPRINT* aFootprint ) } +void BRDITEMS_PLOTTER::PlotPcbGraphicItem( const BOARD_ITEM* item ) +{ + switch( item->Type() ) + { + case PCB_SHAPE_T: + PlotPcbShape( static_cast( item ) ); + break; + + case PCB_TEXT_T: + PlotPcbText( static_cast( item ) ); + break; + + case PCB_DIM_ALIGNED_T: + case PCB_DIM_CENTER_T: + case PCB_DIM_RADIAL_T: + case PCB_DIM_ORTHOGONAL_T: + case PCB_DIM_LEADER_T: + PlotDimension( static_cast( item ) ); + break; + + case PCB_TARGET_T: + PlotPcbTarget( static_cast( item ) ); + break; + + default: + break; + } +} + + void BRDITEMS_PLOTTER::PlotBoardGraphicItems() { - for( BOARD_ITEM* item : m_board->Drawings() ) - { - switch( item->Type() ) - { - case PCB_SHAPE_T: - PlotPcbShape( (PCB_SHAPE*) item ); - break; - - case PCB_TEXT_T: - PlotPcbText( (PCB_TEXT*) item ); - break; - - case PCB_DIM_ALIGNED_T: - case PCB_DIM_CENTER_T: - case PCB_DIM_RADIAL_T: - case PCB_DIM_ORTHOGONAL_T: - case PCB_DIM_LEADER_T: - PlotDimension( (PCB_DIMENSION_BASE*) item ); - break; - - case PCB_TARGET_T: - PlotPcbTarget( (PCB_TARGET*) item ); - break; - - default: - break; - } - } + for( const BOARD_ITEM* item : m_board->Drawings() ) + PlotPcbGraphicItem( item ); }