Fix solder mask generation issues in STEP export

Fixed two problems with soldermask generation.  First, via holes weren't
cut in soldermask when copper export was disabled.  Second, we ignored
zones on F.Mask/B.Mask when zone export was disabled even though
soldermask export was enabled.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/20452

(cherry picked from commit 497fe12f2d)
This commit is contained in:
Seth Hillbrand
2026-01-08 08:40:34 -08:00
parent 2c55930bcf
commit 366d083da2
2 changed files with 32 additions and 5 deletions
+28 -1
View File
@@ -512,6 +512,17 @@ bool EXPORTER_STEP::buildTrack3DShape( PCB_TRACK* aTrack, VECTOR2D aOrigin )
// m_poly_holes[B_SilkS].Append( holePoly );
//}
// Cut via holes in soldermask when the via is not tented.
// This ensures the mask has a proper hole through the via drill, not just the annular ring opening.
if( m_params.m_ExportSoldermask )
{
if( via->IsOnLayer( F_Mask ) )
m_poly_holes[F_Mask].Append( holePoly );
if( via->IsOnLayer( B_Mask ) )
m_poly_holes[B_Mask].Append( holePoly );
}
m_pcbModel->AddHole( *holeShape, m_platingThickness, top_layer, bot_layer, true, aOrigin,
!m_params.m_FillAllVias, m_params.m_CutViasInBody );
@@ -533,12 +544,13 @@ bool EXPORTER_STEP::buildTrack3DShape( PCB_TRACK* aTrack, VECTOR2D aOrigin )
}
void EXPORTER_STEP::buildZones3DShape( VECTOR2D aOrigin )
void EXPORTER_STEP::buildZones3DShape( VECTOR2D aOrigin, bool aSolderMaskOnly )
{
for( ZONE* zone : m_board->Zones() )
{
LSET layers = zone->GetLayerSet();
// Filter by net if a net filter is specified and zone is on copper layer(s)
if( ( layers & LSET::AllCuMask() ).count() && !m_params.m_NetFilter.IsEmpty()
&& !zone->GetNetname().Matches( m_params.m_NetFilter ) )
{
@@ -547,6 +559,16 @@ void EXPORTER_STEP::buildZones3DShape( VECTOR2D aOrigin )
for( PCB_LAYER_ID layer : layers.Seq() )
{
bool isMaskLayer = ( layer == F_Mask || layer == B_Mask );
// If we're only processing soldermask zones, skip non-mask layers
if( aSolderMaskOnly && !isMaskLayer )
continue;
// If we're doing full zone export, skip mask layers if they'll be handled separately
if( !aSolderMaskOnly && isMaskLayer && !m_params.m_ExportZones )
continue;
SHAPE_POLY_SET fill_shape;
zone->TransformSolidAreasShapesToPolygon( layer, fill_shape );
fill_shape.Unfracture();
@@ -779,6 +801,11 @@ bool EXPORTER_STEP::buildBoard3DShapes()
buildZones3DShape( origin );
}
// Process zones on soldermask layers even when copper zone export is disabled.
// This ensures mask openings defined by zones are properly exported.
if( m_params.m_ExportSoldermask && !m_params.m_ExportZones )
buildZones3DShape( origin, true );
for( PCB_LAYER_ID pcblayer : m_layersToExport.Seq() )
{
SHAPE_POLY_SET holes = m_poly_holes[pcblayer];
+4 -4
View File
@@ -55,10 +55,10 @@ public:
private:
bool buildBoard3DShapes();
bool buildFootprint3DShapes( FOOTPRINT* aFootprint, VECTOR2D aOrigin, SHAPE_POLY_SET* aClipPolygon );
bool buildTrack3DShape( PCB_TRACK* aTrack, VECTOR2D aOrigin );
void buildZones3DShape( VECTOR2D aOrigin );
bool buildGraphic3DShape( BOARD_ITEM* aItem, VECTOR2D aOrigin );
bool buildFootprint3DShapes( FOOTPRINT* aFootprint, const VECTOR2D& aOrigin, SHAPE_POLY_SET* aClipPolygon );
bool buildTrack3DShape( PCB_TRACK* aTrack, const VECTOR2D& aOrigin );
void buildZones3DShape( VECTOR2D aOrigin, bool aSolderMaskOnly = false );
bool buildGraphic3DShape( BOARD_ITEM* aItem, const VECTOR2D& aOrigin );
void initOutputVariant();
EXPORTER_STEP_PARAMS m_params;