void PCB_TABLE::TransformShapeToPolySet() fix transform shape.

PCB_TABLE is not a simple shape: it is built with a lot of sub-items.
So convert it to a poly set need to convert each shape (line, text)
to a polygon set.
It especially fixes PDF plot silkscreen layer when Subtract soldermask is enabled.
This commit is contained in:
jean-pierre charras
2025-12-08 12:55:11 +01:00
parent b54750156d
commit 984d1e5883
6 changed files with 69 additions and 18 deletions
+10 -5
View File
@@ -44,6 +44,10 @@ class PCB_BASE_FRAME;
class SHAPE;
class PCB_GROUP;
class FOOTPRINT;
namespace KIGFX
{
class RENDER_SETTINGS;
};
namespace KIFONT
{
@@ -401,7 +405,7 @@ public:
* Convert the item shape to a closed polygon. Circles and arcs are approximated by segments.
*
* @param aBuffer a buffer to store the polygon.
* @param aClearance the clearance around the pad.
* @param aClearance the clearance around the polygonal shape (inflated polygon).
* @param aError the maximum deviation from true circle.
* @param aErrorLoc should the approximation error be placed outside or inside the polygon?
* @param ignoreLineWidth used for edge cut items where the line width is only
@@ -413,17 +417,18 @@ public:
/**
* Convert the item shape to a polyset. Circles and arcs are approximated by segments; hatched
* fills will be included.
* fills and details (if any) will be included.
*
* @param aBuffer a buffer to store the polygon.
* @param aClearance the clearance around the pad.
* @param aError the maximum deviation from true circle.
* @param aErrorLoc should the approximation error be placed outside or inside the polygon?
* @param ignoreLineWidth used for edge cut items where the line width is only
* for visualization.
* @param aRenderSettings used to plot outlines with not solid segments like dashed lines.
* So it is not used by all BOARD_ITEMS. If null lines like dashed will be converted as SOLID
*/
virtual void TransformShapeToPolySet( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer,
int aClearance, int aError, ERROR_LOC aErrorLoc ) const
int aClearance, int aError, ERROR_LOC aErrorLoc,
KIGFX::RENDER_SETTINGS* aRenderSettings = nullptr ) const
{
TransformShapeToPolygon( aBuffer, aLayer, aClearance, aError, aErrorLoc );
}
+2 -1
View File
@@ -836,7 +836,8 @@ void PCB_SHAPE::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID a
void PCB_SHAPE::TransformShapeToPolySet( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer,
int aClearance, int aError, ERROR_LOC aErrorLoc ) const
int aClearance, int aError, ERROR_LOC aErrorLoc,
KIGFX::RENDER_SETTINGS* aRenderSettings ) const
{
EDA_SHAPE::TransformShapeToPolygon( aBuffer, aClearance, aError, aErrorLoc, false, true );
}
+14 -2
View File
@@ -170,8 +170,20 @@ public:
int aError, ERROR_LOC aErrorLoc,
bool ignoreLineWidth = false ) const override;
void TransformShapeToPolySet( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, int aClearance,
int aError, ERROR_LOC aErrorLoc ) const override;
/**
* Convert the item shape to a polyset. Circles and arcs are approximated by segments; hatched
* fills and details (if any) will be included.
*
* @param aBuffer a buffer to store the polygon.
* @param aClearance the clearance around the pad.
* @param aError the maximum deviation from true circle.
* @param aErrorLoc should the approximation error be placed outside or inside the polygon?
* @param aRenderSettings used to plot outlines with not solid segments like dashed lines.
* So it is not used by all BOARD_ITEMS. If null lines like dashed will be converted as SOLID
*/
void TransformShapeToPolySet( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer,
int aClearance, int aError, ERROR_LOC aErrorLoc,
KIGFX::RENDER_SETTINGS* aRenderSettings = nullptr ) const override;
wxString GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const override;
+19 -1
View File
@@ -451,6 +451,8 @@ void PCB_TABLE::TransformGraphicItemsToPolySet( SHAPE_POLY_SET& aBuffer, int aMa
KIGFX::RENDER_SETTINGS* aRenderSettings ) const
{
// Convert graphic items (segments and texts) to a set of polygonal shapes
// aRenderSettings is used to draw lines when line style != LINE_STYLE::SOLID, so
// if nullptr line style will be ignored
DrawBorders(
[&aBuffer, aMaxError, aErrorLoc, aRenderSettings]( const VECTOR2I& ptA, const VECTOR2I& ptB,
const STROKE_PARAMS& stroke )
@@ -458,7 +460,7 @@ void PCB_TABLE::TransformGraphicItemsToPolySet( SHAPE_POLY_SET& aBuffer, int aMa
int lineWidth = stroke.GetWidth();
LINE_STYLE lineStyle = stroke.GetLineStyle();
if( lineStyle <= LINE_STYLE::FIRST_TYPE )
if( lineStyle <= LINE_STYLE::FIRST_TYPE || aRenderSettings == nullptr )
TransformOvalToPolygon( aBuffer, ptA, ptB, lineWidth, aMaxError, aErrorLoc );
else
{
@@ -488,6 +490,22 @@ void PCB_TABLE::TransformGraphicItemsToPolySet( SHAPE_POLY_SET& aBuffer, int aMa
}
void PCB_TABLE::TransformShapeToPolySet( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer,
int aClearance, int aMaxError, ERROR_LOC aErrorLoc,
KIGFX::RENDER_SETTINGS* aRenderSettings ) const
{
if( aClearance <= 0 )
TransformGraphicItemsToPolySet( aBuffer, aMaxError, aErrorLoc, aRenderSettings );
else
{
SHAPE_POLY_SET tmp;
TransformGraphicItemsToPolySet( tmp, aMaxError, aErrorLoc, aRenderSettings );
tmp.Inflate( aClearance, CORNER_STRATEGY::CHAMFER_ALL_CORNERS, aMaxError );
aBuffer.Append( tmp );
}
}
INSPECT_RESULT PCB_TABLE::Visit( INSPECTOR aInspector, void* aTestData, const std::vector<KICAD_T>& aScanTypes )
{
for( KICAD_T scanType : aScanTypes )
+15 -1
View File
@@ -231,11 +231,25 @@ public:
int aMaxError, ERROR_LOC aErrorLoc,
bool aIgnoreLineWidth = false ) const override;
/**
* Convert the TABLE shape to a polyset. details will be included.
*
* @param aBuffer a buffer to store the polygon.
* @param aClearance the clearance around the pad.
* @param aError the maximum deviation from true circle.
* @param aErrorLoc should the approximation error be placed outside or inside the polygon?
* @param aRenderSettings used to plot outlines with not solid segments like dashed lines.
* If null, lines like dashed will be converted as SOLID
*/
void TransformShapeToPolySet( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer,
int aClearance, int aError, ERROR_LOC aErrorLoc,
KIGFX::RENDER_SETTINGS* aRenderSettings = nullptr ) const override;
/**
* Convert graphic items (segments and texts) to a set of polygonal shapes
*/
void TransformGraphicItemsToPolySet( SHAPE_POLY_SET& aBuffer, int aMaxError, ERROR_LOC aErrorLoc,
KIGFX::RENDER_SETTINGS* aRenderSettings ) const;
KIGFX::RENDER_SETTINGS* aRenderSettings ) const;
INSPECT_RESULT Visit( INSPECTOR inspector, void* testData,
const std::vector<KICAD_T>& aScanTypes ) override;
+9 -8
View File
@@ -46,8 +46,7 @@
#include <gbr_metadata.h>
#include <advanced_config.h>
void GenerateLayerPoly( SHAPE_POLY_SET* aResult, BOARD *aBoard, PCB_LAYER_ID aLayer,
void GenerateLayerPoly( SHAPE_POLY_SET* aResult, BOARD *aBoard, PLOTTER* aPlotter, PCB_LAYER_ID aLayer,
bool aPlotFPText, bool aPlotReferences, bool aPlotValues );
@@ -102,7 +101,7 @@ void PlotSolderMaskLayer( BOARD* aBoard, PLOTTER* aPlotter, const LSET& aLayerMa
SHAPE_POLY_SET solderMask;
PCB_LAYER_ID layer = aLayerMask[B_Mask] ? B_Mask : F_Mask;
GenerateLayerPoly( &solderMask, aBoard, layer, aPlotOpt.GetPlotFPText(),
GenerateLayerPoly( &solderMask, aBoard, aPlotter, layer, aPlotOpt.GetPlotFPText(),
aPlotOpt.GetPlotReference(), aPlotOpt.GetPlotValue() );
PlotPolySet( aBoard, aPlotter, aPlotOpt, &solderMask, layer );
@@ -116,9 +115,9 @@ void PlotClippedSilkLayer( BOARD* aBoard, PLOTTER* aPlotter, const LSET& aLayerM
PCB_LAYER_ID silkLayer = aLayerMask[F_SilkS] ? F_SilkS : B_SilkS;
PCB_LAYER_ID maskLayer = aLayerMask[F_SilkS] ? F_Mask : B_Mask;
GenerateLayerPoly( &silkscreen, aBoard, silkLayer, aPlotOpt.GetPlotFPText(),
GenerateLayerPoly( &silkscreen, aBoard, aPlotter, silkLayer, aPlotOpt.GetPlotFPText(),
aPlotOpt.GetPlotReference(), aPlotOpt.GetPlotValue() );
GenerateLayerPoly( &solderMask, aBoard, maskLayer, aPlotOpt.GetPlotFPText(),
GenerateLayerPoly( &solderMask, aBoard, aPlotter, maskLayer, aPlotOpt.GetPlotFPText(),
aPlotOpt.GetPlotReference(), aPlotOpt.GetPlotValue() );
silkscreen.BooleanSubtract( solderMask );
@@ -936,7 +935,7 @@ void PlotLayerOutlines( BOARD* aBoard, PLOTTER* aPlotter, const LSET& aLayerMask
/**
* Generates a SHAPE_POLY_SET representing the plotted items on a layer.
*/
void GenerateLayerPoly( SHAPE_POLY_SET* aResult, BOARD *aBoard, PCB_LAYER_ID aLayer,
void GenerateLayerPoly( SHAPE_POLY_SET* aResult, BOARD *aBoard, PLOTTER* aPlotter, PCB_LAYER_ID aLayer,
bool aPlotFPText, bool aPlotReferences, bool aPlotValues )
{
int maxError = aBoard->GetDesignSettings().m_MaxError;
@@ -1052,9 +1051,11 @@ void GenerateLayerPoly( SHAPE_POLY_SET* aResult, BOARD *aBoard, PCB_LAYER_ID aLa
else
{
if( inflate != 0 )
item->TransformShapeToPolygon( exactPolys, aLayer, 0, maxError, ERROR_OUTSIDE );
item->TransformShapeToPolySet( exactPolys, aLayer, 0, maxError, ERROR_OUTSIDE,
aPlotter->RenderSettings() );
item->TransformShapeToPolygon( *aResult, aLayer, inflate, maxError, ERROR_OUTSIDE );
item->TransformShapeToPolySet( *aResult, aLayer, inflate, maxError,
ERROR_OUTSIDE, aPlotter->RenderSettings() );
}
}
}