From 53989e3bdc88d096ba43d21acfea357f57322bb6 Mon Sep 17 00:00:00 2001 From: Seth Hillbrand Date: Tue, 20 Aug 2019 06:45:57 -0700 Subject: [PATCH] SVG: Correct plot fills for arcs/polylines When plotting in Eeschema, various elements may be filled with either the foreground or background colors. The fill mode is rather unique, requiring un-stroked pie wedges for arcs and both closed and open filled polylines. Fixes: lp:1840769 * https://bugs.launchpad.net/kicad/+bug/1840769 (cherry picked from commit 213547f545f8d3914f811454c2158720b0671ebc) --- common/plotters/SVG_plotter.cpp | 33 ++++++++++++++++++++++++++------- common/plotters/plotter.cpp | 27 +++++++++++++++++++++++++-- 2 files changed, 51 insertions(+), 9 deletions(-) diff --git a/common/plotters/SVG_plotter.cpp b/common/plotters/SVG_plotter.cpp index 9c3f595c2e..83d1fd7f89 100644 --- a/common/plotters/SVG_plotter.cpp +++ b/common/plotters/SVG_plotter.cpp @@ -424,9 +424,6 @@ void SVG_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, i if( StAngle > EndAngle ) std::swap( StAngle, EndAngle ); - setFillMode( fill ); - SetCurrentLineWidth( width ); - // Calculate start point. DPOINT centre_dev = userToDeviceCoordinates( centre ); double radius_dev = userToDeviceSize( radius ); @@ -487,6 +484,21 @@ void SVG_PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, i // flag arc size (0 = small arc > 180 deg, 1 = large arc > 180 deg), // sweep arc ( 0 = CCW, 1 = CW), // end point + if( fill != NO_FILL ) + { + // Filled arcs (in eeschema) consist of the pie wedge and a stroke only on the arc + // This needs to be drawn in two steps. + setFillMode( fill ); + SetCurrentLineWidth( 0 ); + + fprintf( outputFile, "\n", + start.x, start.y, radius_dev, radius_dev, + flg_arc, flg_sweep, + end.x, end.y, centre_dev.x, centre_dev.y ); + } + + setFillMode( NO_FILL ); + SetCurrentLineWidth( width ); fprintf( outputFile, "\n", start.x, start.y, radius_dev, radius_dev, flg_arc, flg_sweep, @@ -517,15 +529,22 @@ void SVG_PLOTTER::PlotPoly( const std::vector& aCornerList, } DPOINT pos = userToDeviceCoordinates( aCornerList[0] ); - fprintf( outputFile, "d=\"M %d,%d\n", (int) pos.x, (int) pos.y ); + fprintf( outputFile, "d=\"M %g,%g\n", pos.x, pos.y ); - for( unsigned ii = 1; ii < aCornerList.size(); ii++ ) + for( unsigned ii = 1; ii < aCornerList.size() - 1; ii++ ) { pos = userToDeviceCoordinates( aCornerList[ii] ); - fprintf( outputFile, "%d,%d\n", (int) pos.x, (int) pos.y ); + fprintf( outputFile, "%g,%g\n", pos.x, pos.y ); } - fprintf( outputFile, "Z\" /> \n" ); + // If the cornerlist ends where it begins, then close the poly + if( aCornerList.front() == aCornerList.back() ) + fprintf( outputFile, "Z\" /> \n" ); + else + { + pos = userToDeviceCoordinates( aCornerList.back() ); + fprintf( outputFile, "%g,%g\n\" /> \n", pos.x, pos.y ); + } } diff --git a/common/plotters/plotter.cpp b/common/plotters/plotter.cpp index b7a21db48b..3dbf5abffc 100644 --- a/common/plotters/plotter.cpp +++ b/common/plotters/plotter.cpp @@ -38,6 +38,7 @@ */ #include +#include #include #include @@ -164,7 +165,17 @@ void PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, int r /* Please NOTE the different sign due to Y-axis flip */ start.x = centre.x + KiROUND( cosdecideg( radius, -StAngle ) ); start.y = centre.y + KiROUND( sindecideg( radius, -StAngle ) ); - MoveTo( start ); + + if( fill != NO_FILL ) + { + MoveTo( centre ); + LineTo( start ); + } + else + { + MoveTo( start ); + } + for( int ii = StAngle + delta; ii < EndAngle; ii += delta ) { end.x = centre.x + KiROUND( cosdecideg( radius, -ii ) ); @@ -174,7 +185,16 @@ void PLOTTER::Arc( const wxPoint& centre, double StAngle, double EndAngle, int r end.x = centre.x + KiROUND( cosdecideg( radius, -EndAngle ) ); end.y = centre.y + KiROUND( sindecideg( radius, -EndAngle ) ); - FinishTo( end ); + + if( fill != NO_FILL ) + { + LineTo( end ); + FinishTo( centre ); + } + else + { + FinishTo( end ); + } } @@ -530,6 +550,9 @@ void PLOTTER::PlotPoly( const SHAPE_LINE_CHAIN& aCornerList, FILL_T aFill, for( int ii = 0; ii < aCornerList.PointCount(); ii++ ) cornerList.push_back( wxPoint( aCornerList.CPoint( ii ) ) ); + if( aCornerList.IsClosed() && cornerList.front() != cornerList.back() ) + cornerList.push_back( wxPoint( aCornerList.CPoint( 0 ) ) ); + PlotPoly( cornerList , aFill, aWidth, aData ); }