Lazy context handling for SVG plotting.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/15325
This commit is contained in:
Jeff Young 2023-08-07 13:06:46 +01:00
parent 256c7fa788
commit f43b90b15f
7 changed files with 35 additions and 50 deletions

View File

@ -178,20 +178,13 @@ void PSLIKE_PLOTTER::FlashPadRoundRect( const VECTOR2I& aPadPos, const VECTOR2I&
int aCornerRadius, const EDA_ANGLE& aOrient,
OUTLINE_MODE aTraceMode, void* aData )
{
VECTOR2I size( aSize );
if( aTraceMode == FILLED )
{
SetCurrentLineWidth( 0 );
}
else
{
SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH );
}
SHAPE_POLY_SET outline;
TransformRoundChamferedRectToPolygon( outline, aPadPos, size, aOrient, aCornerRadius, 0.0, 0,
TransformRoundChamferedRectToPolygon( outline, aPadPos, aSize, aOrient, aCornerRadius, 0.0, 0,
0, GetPlotterArcHighDef(), ERROR_INSIDE );
std::vector<VECTOR2I> cornerList;
@ -215,17 +208,10 @@ void PSLIKE_PLOTTER::FlashPadCustom( const VECTOR2I& aPadPos, const VECTOR2I& aS
const EDA_ANGLE& aOrient, SHAPE_POLY_SET* aPolygons,
OUTLINE_MODE aTraceMode, void* aData )
{
VECTOR2I size( aSize );
if( aTraceMode == FILLED )
{
SetCurrentLineWidth( 0 );
}
else
{
SetCurrentLineWidth( USE_DEFAULT_LINE_WIDTH );
}
std::vector<VECTOR2I> cornerList;

View File

@ -152,7 +152,9 @@ static wxString XmlEsc( const wxString& aStr, bool isAttribute = false )
}
}
else
{
escaped.append(c);
}
}
}
@ -203,15 +205,6 @@ void SVG_PLOTTER::SetSvgCoordinatesFormat( unsigned aPrecision )
}
void SVG_PLOTTER::SetColor( const COLOR4D& color )
{
PSLIKE_PLOTTER::SetColor( color );
if( m_graphics_changed )
setSVGPlotStyle( GetCurrentLineWidth() );
}
void SVG_PLOTTER::setFillMode( FILL_T fill )
{
if( m_fillMode != fill )
@ -322,30 +315,19 @@ void SVG_PLOTTER::SetCurrentLineWidth( int aWidth, void* aData )
m_graphics_changed = true;
m_currentPenWidth = aWidth;
}
if( m_graphics_changed )
setSVGPlotStyle( aWidth );
}
void SVG_PLOTTER::StartBlock( void* aData )
{
std::string* idstr = reinterpret_cast<std::string*>( aData );
fputs( "<g ", m_outputFile );
if( idstr )
fprintf( m_outputFile, "id=\"%s\"", idstr->c_str() );
fprintf( m_outputFile, ">\n" );
// We can't use <g></g> for blocks because we're already using it for graphics context, and
// our graphics context handling is lazy (ie: it leaves the last group open until the context
// changes).
}
void SVG_PLOTTER::EndBlock( void* aData )
{
fprintf( m_outputFile, "</g>\n" );
m_graphics_changed = true;
}
@ -399,6 +381,9 @@ void SVG_PLOTTER::Rect( const VECTOR2I& p1, const VECTOR2I& p2, FILL_T fill, int
setFillMode( fill );
SetCurrentLineWidth( width );
if( m_graphics_changed )
setSVGPlotStyle( GetCurrentLineWidth() );
// Rectangles having a 0 size value for height or width are just not drawn on Inkscape,
// so use a line when happens.
if( rect_dev.GetSize().x == 0.0 || rect_dev.GetSize().y == 0.0 ) // Draw a line
@ -427,6 +412,9 @@ void SVG_PLOTTER::Circle( const VECTOR2I& pos, int diametre, FILL_T fill, int wi
setFillMode( fill );
SetCurrentLineWidth( width );
if( m_graphics_changed )
setSVGPlotStyle( GetCurrentLineWidth() );
// If diameter is less than width, switch to filled mode
if( fill == FILL_T::NO_FILL && diametre < width )
{
@ -524,6 +512,9 @@ void SVG_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
setFillMode( aFill );
SetCurrentLineWidth( 0 );
if( m_graphics_changed )
setSVGPlotStyle( GetCurrentLineWidth() );
fprintf( m_outputFile, "<path d=\"M%.*f %.*f A%.*f %.*f 0.0 %d %d %.*f %.*f L %.*f %.*f Z\" />\n",
m_precision, start.x, m_precision, start.y,
m_precision, radius_device, m_precision, radius_device,
@ -534,6 +525,10 @@ void SVG_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
setFillMode( FILL_T::NO_FILL );
SetCurrentLineWidth( aWidth );
if( m_graphics_changed )
setSVGPlotStyle( GetCurrentLineWidth() );
fprintf( m_outputFile, "<path d=\"M%.*f %.*f A%.*f %.*f 0.0 %d %d %.*f %.*f\" />\n",
m_precision, start.x, m_precision, start.y,
m_precision, radius_device, m_precision, radius_device,
@ -550,6 +545,9 @@ void SVG_PLOTTER::BezierCurve( const VECTOR2I& aStart, const VECTOR2I& aControl1
setFillMode( FILL_T::NO_FILL );
SetCurrentLineWidth( aLineThickness );
if( m_graphics_changed )
setSVGPlotStyle( GetCurrentLineWidth() );
VECTOR2D start = userToDeviceCoordinates( aStart );
VECTOR2D ctrl1 = userToDeviceCoordinates( aControl1 );
VECTOR2D ctrl2 = userToDeviceCoordinates( aControl2 );
@ -633,7 +631,9 @@ void SVG_PLOTTER::PlotImage( const wxImage& aImage, const VECTOR2I& aPos, double
wxMemoryOutputStream img_stream;
if( m_colorMode )
{
aImage.SaveFile( img_stream, wxBITMAP_TYPE_PNG );
}
else // Plot in B&W
{
wxImage image = aImage.ConvertToGreyscale();
@ -686,10 +686,10 @@ void SVG_PLOTTER::PenTo( const VECTOR2I& pos, char plume )
// Ensure we do not use a fill mode when moving the pen,
// in SVG mode (i;e. we are plotting only basic lines, not a filled area
if( m_fillMode != FILL_T::NO_FILL )
{
setFillMode( FILL_T::NO_FILL );
if( m_graphics_changed )
setSVGPlotStyle( GetCurrentLineWidth() );
}
fprintf( m_outputFile, "<path d=\"M%.*f %.*f\n",
m_precision, pos_dev.x,
@ -697,6 +697,9 @@ void SVG_PLOTTER::PenTo( const VECTOR2I& pos, char plume )
}
else if( m_penState != plume || pos != m_penLastpos )
{
if( m_graphics_changed )
setSVGPlotStyle( GetCurrentLineWidth() );
VECTOR2D pos_dev = userToDeviceCoordinates( pos );
fprintf( m_outputFile, "L%.*f %.*f\n",

View File

@ -530,8 +530,6 @@ public:
return PLOT_FORMAT::SVG;
}
virtual void SetColor( const COLOR4D& color ) override;
/**
* Create SVG file header.
*/

View File

@ -87,7 +87,7 @@ public:
void PlotDimension( const PCB_DIMENSION_BASE* aDim );
void PlotPcbTarget( const PCB_TARGET* aMire );
void PlotZones( const ZONE* aZone, PCB_LAYER_ID aLayer, const SHAPE_POLY_SET& aPolysList );
void PlotZone( const ZONE* aZone, PCB_LAYER_ID aLayer, const SHAPE_POLY_SET& aPolysList );
void PlotText( const EDA_TEXT* aText, PCB_LAYER_ID aLayer, bool aIsKnockout,
const KIFONT::METRICS& aFontMetrics );
void PlotShape( const PCB_SHAPE* aShape );

View File

@ -691,13 +691,13 @@ void PlotStandardLayer( BOARD* aBoard, PLOTTER* aPlotter, LSET aLayerMask,
}
}
itemplotter.PlotZones( zone, layer, mainArea );
itemplotter.PlotZone( zone, layer, mainArea );
if( !islands.IsEmpty() )
{
ZONE dummy( *zone );
dummy.SetNet( &nonet );
itemplotter.PlotZones( &dummy, layer, islands );
itemplotter.PlotZone( &dummy, layer, islands );
}
}
}
@ -994,7 +994,7 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask,
areas.BooleanAdd( initialPolys, SHAPE_POLY_SET::PM_FAST );
areas.Fracture( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE );
itemplotter.PlotZones( &zone, layer, areas );
itemplotter.PlotZone( &zone, layer, areas );
}

View File

@ -621,8 +621,8 @@ void BRDITEMS_PLOTTER::PlotText( const EDA_TEXT* aText, PCB_LAYER_ID aLayer, boo
}
void BRDITEMS_PLOTTER::PlotZones( const ZONE* aZone, PCB_LAYER_ID aLayer,
const SHAPE_POLY_SET& aPolysList )
void BRDITEMS_PLOTTER::PlotZone( const ZONE* aZone, PCB_LAYER_ID aLayer,
const SHAPE_POLY_SET& aPolysList )
{
if( aPolysList.IsEmpty() )
return;

View File

@ -98,8 +98,6 @@ bool ZONE_FILLER::Fill( std::vector<ZONE*>& aZones, bool aCheck, wxWindow* aPare
connectivity->ClearRatsnest();
connectivity->Build( m_board, m_progressReporter );
BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
m_worstClearance = m_board->GetMaxClearanceValue();
if( m_progressReporter )