diff --git a/bitmaps_png/png/via_sketch_24.png b/bitmaps_png/png/via_sketch_24.png
index 421a11424d..9fe5549bc1 100644
Binary files a/bitmaps_png/png/via_sketch_24.png and b/bitmaps_png/png/via_sketch_24.png differ
diff --git a/bitmaps_png/png/via_sketch_dark_24.png b/bitmaps_png/png/via_sketch_dark_24.png
index 57d1bef8f3..872fca1d80 100644
Binary files a/bitmaps_png/png/via_sketch_dark_24.png and b/bitmaps_png/png/via_sketch_dark_24.png differ
diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt
index ace6b4a9a7..031147fe7b 100644
--- a/common/CMakeLists.txt
+++ b/common/CMakeLists.txt
@@ -385,6 +385,7 @@ set( COMMON_SRCS
     search_stack.cpp
     searchhelpfilefullpath.cpp
     status_popup.cpp
+    stroke_params.cpp
     systemdirsappend.cpp
     template_fieldnames.cpp
     textentry_tricks.cpp
@@ -613,6 +614,14 @@ generate_lemon_grammar(
     libeval_compiler/grammar.lemon
     )
 
+# auto-generate stroke_params_lexer.h and stroke_params_keywords.cpp
+make_lexer(
+    common
+    stroke_params.keywords
+    stroke_params_lexer.h
+    stroke_params_keywords.cpp
+    STROKEPARAMS_T
+    )
 
 # auto-generate netlist_lexer.h and netlist_keywords.cpp
 make_lexer(
diff --git a/common/base_units.cpp b/common/base_units.cpp
index 6e09de66f5..0d4553fd45 100644
--- a/common/base_units.cpp
+++ b/common/base_units.cpp
@@ -35,11 +35,10 @@
  */
 
 #include <base_units.h>
-#include <common.h>
 #include <string_utils.h>
 #include <math/util.h>      // for KiROUND
 #include <macros.h>
-#include <title_block.h>
+
 
 #if defined( PCBNEW ) || defined( CVPCB ) || defined( EESCHEMA ) || defined( GERBVIEW ) || defined( PL_EDITOR )
 #define IU_TO_MM( x )       ( x / IU_PER_MM )
diff --git a/common/eda_shape.cpp b/common/eda_shape.cpp
index bf9582107f..c72c783f52 100644
--- a/common/eda_shape.cpp
+++ b/common/eda_shape.cpp
@@ -40,8 +40,9 @@
 EDA_SHAPE::EDA_SHAPE( SHAPE_T aType, int aLineWidth, FILL_T aFill, bool eeWinding ) :
     m_endsSwapped( false ),
     m_shape( aType ),
-    m_width( aLineWidth ),
+    m_stroke( aLineWidth, PLOT_DASH_TYPE::DEFAULT, COLOR4D::UNSPECIFIED ),
     m_fill( aFill ),
+    m_fillColor( COLOR4D::UNSPECIFIED ),
     m_editState( 0 ),
     m_eeWinding( eeWinding )
 {
@@ -352,7 +353,7 @@ void EDA_SHAPE::flip( const wxPoint& aCentre, bool aFlipLeftRight )
         {
             std::vector<wxPoint> ctrlPoints = { m_start, m_bezierC1, m_bezierC2, m_end };
             BEZIER_POLY converter( ctrlPoints );
-            converter.GetPoly( m_bezierPoints, m_width );
+            converter.GetPoly( m_bezierPoints, m_stroke.GetWidth() );
         }
         break;
 
@@ -605,7 +606,7 @@ void EDA_SHAPE::ShapeGetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PA
         break;
     }
 
-    aList.emplace_back( _( "Line width" ), MessageTextFromValue( units, m_width ) );
+    aList.emplace_back( _( "Line width" ), MessageTextFromValue( units, GetWidth() ) );
 }
 
 
@@ -663,7 +664,7 @@ const EDA_RECT EDA_SHAPE::getBoundingBox() const
         break;
     }
 
-    bbox.Inflate( std::max( 0, m_width / 2 ) );
+    bbox.Inflate( std::max( 0, GetWidth() ) / 2 );
     bbox.Normalize();
 
     return bbox;
@@ -674,8 +675,8 @@ bool EDA_SHAPE::hitTest( const wxPoint& aPosition, int aAccuracy ) const
 {
     int maxdist = aAccuracy;
 
-    if( m_width > 0 )
-        maxdist += m_width / 2;
+    if( GetWidth() > 0 )
+        maxdist += GetWidth() / 2;
 
     switch( m_shape )
     {
@@ -727,7 +728,7 @@ bool EDA_SHAPE::hitTest( const wxPoint& aPosition, int aAccuracy ) const
     }
 
     case SHAPE_T::BEZIER:
-        const_cast<EDA_SHAPE*>( this )->RebuildBezierToSegmentsPointsList( m_width );
+        const_cast<EDA_SHAPE*>( this )->RebuildBezierToSegmentsPointsList( GetWidth() );
 
         for( unsigned int i= 1; i < m_bezierPoints.size(); i++)
         {
@@ -1070,7 +1071,7 @@ void EDA_SHAPE::SetPolyPoints( const std::vector<wxPoint>& aPoints )
 }
 
 
-std::vector<SHAPE*> EDA_SHAPE::MakeEffectiveShapes() const
+std::vector<SHAPE*> EDA_SHAPE::MakeEffectiveShapes( bool aEdgeOnly ) const
 {
     std::vector<SHAPE*> effectiveShapes;
 
@@ -1078,60 +1079,50 @@ std::vector<SHAPE*> EDA_SHAPE::MakeEffectiveShapes() const
     {
     case SHAPE_T::ARC:
         effectiveShapes.emplace_back( new SHAPE_ARC( m_arcCenter, m_start, GetArcAngle() / 10.0,
-                                                     m_width ) );
+                                                     GetWidth() ) );
         break;
 
     case SHAPE_T::SEGMENT:
-        effectiveShapes.emplace_back( new SHAPE_SEGMENT( m_start, m_end, m_width ) );
+        effectiveShapes.emplace_back( new SHAPE_SEGMENT( m_start, m_end, GetWidth() ) );
         break;
 
     case SHAPE_T::RECT:
     {
         std::vector<wxPoint> pts = GetRectCorners();
 
-        if( IsFilled() )
+        if( IsFilled() && !aEdgeOnly )
             effectiveShapes.emplace_back( new SHAPE_SIMPLE( pts ) );
 
-        if( m_width > 0 || !IsFilled() )
+        if( GetWidth() > 0 || !IsFilled() || aEdgeOnly )
         {
-            effectiveShapes.emplace_back( new SHAPE_SEGMENT( pts[0], pts[1], m_width ) );
-            effectiveShapes.emplace_back( new SHAPE_SEGMENT( pts[1], pts[2], m_width ) );
-            effectiveShapes.emplace_back( new SHAPE_SEGMENT( pts[2], pts[3], m_width ) );
-            effectiveShapes.emplace_back( new SHAPE_SEGMENT( pts[3], pts[0], m_width ) );
+            effectiveShapes.emplace_back( new SHAPE_SEGMENT( pts[0], pts[1], GetWidth() ) );
+            effectiveShapes.emplace_back( new SHAPE_SEGMENT( pts[1], pts[2], GetWidth() ) );
+            effectiveShapes.emplace_back( new SHAPE_SEGMENT( pts[2], pts[3], GetWidth() ) );
+            effectiveShapes.emplace_back( new SHAPE_SEGMENT( pts[3], pts[0], GetWidth() ) );
         }
     }
         break;
 
     case SHAPE_T::CIRCLE:
     {
-        if( IsFilled() )
+        if( IsFilled() && !aEdgeOnly )
             effectiveShapes.emplace_back( new SHAPE_CIRCLE( getCenter(), GetRadius() ) );
 
-        if( m_width > 0 || !IsFilled() )
-        {
-            // SHAPE_CIRCLE has no ConvertToPolyline() method, so use a 360.0 SHAPE_ARC
-            SHAPE_ARC        circle( getCenter(), GetEnd(), 360.0 );
-            SHAPE_LINE_CHAIN l = circle.ConvertToPolyline();
-
-            for( int i = 0; i < l.SegmentCount(); i++ )
-            {
-                effectiveShapes.emplace_back( new SHAPE_SEGMENT( l.Segment( i ).A, l.Segment( i ).B,
-                                                                 m_width ) );
-            }
-        }
+        if( GetWidth() > 0 || !IsFilled() || aEdgeOnly )
+            effectiveShapes.emplace_back( new SHAPE_ARC( getCenter(), GetEnd(), 360.0 ) );
 
         break;
     }
 
     case SHAPE_T::BEZIER:
     {
-        auto bezierPoints = buildBezierToSegmentsPointsList( GetWidth() );
+        std::vector<wxPoint> bezierPoints = buildBezierToSegmentsPointsList( GetWidth() );
         wxPoint start_pt = bezierPoints[0];
 
         for( unsigned int jj = 1; jj < bezierPoints.size(); jj++ )
         {
             wxPoint end_pt = bezierPoints[jj];
-            effectiveShapes.emplace_back( new SHAPE_SEGMENT( start_pt, end_pt, m_width ) );
+            effectiveShapes.emplace_back( new SHAPE_SEGMENT( start_pt, end_pt, GetWidth() ) );
             start_pt = end_pt;
         }
 
@@ -1145,13 +1136,13 @@ std::vector<SHAPE*> EDA_SHAPE::MakeEffectiveShapes() const
         l.Rotate( -DECIDEG2RAD( getParentOrientation() ) );
         l.Move( getParentPosition() );
 
-        if( IsFilled() )
+        if( IsFilled() && !aEdgeOnly )
             effectiveShapes.emplace_back( new SHAPE_SIMPLE( l ) );
 
-        if( m_width > 0 || !IsFilled() )
+        if( GetWidth() > 0 || !IsFilled() || aEdgeOnly )
         {
             for( int i = 0; i < l.SegmentCount(); i++ )
-                effectiveShapes.emplace_back( new SHAPE_SEGMENT( l.Segment( i ), m_width ) );
+                effectiveShapes.emplace_back( new SHAPE_SEGMENT( l.Segment( i ), GetWidth() ) );
         }
     }
         break;
@@ -1322,9 +1313,9 @@ void EDA_SHAPE::calcEdit( const wxPoint& aPosition )
 
         case 4:
         {
-            double chordA = GetLineLength( m_start, aPosition );
-            double chordB = GetLineLength( m_end, aPosition );
-            radius = int( ( chordA + chordB ) / 2.0 ) + 1;
+            double radialA = GetLineLength( m_start, aPosition );
+            double radialB = GetLineLength( m_end, aPosition );
+            radius = int( ( radialA + radialB ) / 2.0 ) + 1;
         }
             break;
 
@@ -1373,6 +1364,10 @@ void EDA_SHAPE::calcEdit( const wxPoint& aPosition )
         case 4:
             // Pick the one closer to the mouse position
             m_arcCenter = GetLineLength( c1, aPosition ) < GetLineLength( c2, aPosition ) ? c1 : c2;
+
+            if( GetArcAngle() > 1800 )
+                std::swap( m_start, m_end );
+
             break;
         }
     }
@@ -1425,7 +1420,7 @@ void EDA_SHAPE::SwapShape( EDA_SHAPE* aImage )
     EDA_SHAPE* image = dynamic_cast<EDA_SHAPE*>( aImage );
     assert( image );
 
-    std::swap( m_width, image->m_width );
+    std::swap( m_stroke, image->m_stroke );
     std::swap( m_start, image->m_start );
     std::swap( m_end, image->m_end );
     std::swap( m_arcCenter, image->m_arcCenter );
@@ -1462,12 +1457,16 @@ int EDA_SHAPE::Compare( const EDA_SHAPE* aOther ) const
     else if( m_shape == SHAPE_T::POLY )
     {
         TEST( m_poly.TotalVertices(), aOther->m_poly.TotalVertices() );
-
-        for( int ii = 0; ii < m_poly.TotalVertices(); ++ii )
-            TEST_PT( m_poly.CVertex( ii ), aOther->m_poly.CVertex( ii ) );
     }
 
-    TEST_E( m_width, aOther->m_width );
+    for( size_t ii = 0; ii < m_bezierPoints.size(); ++ii )
+        TEST_PT( m_bezierPoints[ii], aOther->m_bezierPoints[ii] );
+
+    for( int ii = 0; ii < m_poly.TotalVertices(); ++ii )
+        TEST_PT( m_poly.CVertex( ii ), aOther->m_poly.CVertex( ii ) );
+
+    TEST_E( m_stroke.GetWidth(), aOther->m_stroke.GetWidth() );
+    TEST( (int) m_stroke.GetPlotStyle(), (int) aOther->m_stroke.GetPlotStyle() );
     TEST( (int) m_fill, (int) aOther->m_fill );
 
     return 0;
@@ -1479,7 +1478,7 @@ void EDA_SHAPE::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuf
                                                       int aError, ERROR_LOC aErrorLoc,
                                                       bool ignoreLineWidth ) const
 {
-    int width = ignoreLineWidth ? 0 : m_width;
+    int width = ignoreLineWidth ? 0 : GetWidth();
 
     width += 2 * aClearanceValue;
 
@@ -1580,7 +1579,7 @@ void EDA_SHAPE::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuf
         std::vector<wxPoint> ctrlPts = { GetStart(), GetBezierC1(), GetBezierC2(), GetEnd() };
         BEZIER_POLY converter( ctrlPts );
         std::vector< wxPoint> poly;
-        converter.GetPoly( poly, m_width );
+        converter.GetPoly( poly, GetWidth() );
 
         for( unsigned ii = 1; ii < poly.size(); ii++ )
         {
diff --git a/common/layer_id.cpp b/common/layer_id.cpp
index d2d9813871..21d33edcd8 100644
--- a/common/layer_id.cpp
+++ b/common/layer_id.cpp
@@ -117,6 +117,7 @@ wxString LayerName( int aLayer )
     case LAYER_DEVICE:                  return _( "Symbol body outlines" );
     case LAYER_DEVICE_BACKGROUND:       return _( "Symbol body fills" );
     case LAYER_NOTES:                   return _( "Schematic text && graphics" );
+    case LAYER_NOTES_BACKGROUND:        return _( "Schematic text && graphics backgrounds" );
     case LAYER_PIN:                     return _( "Pins" );
     case LAYER_SHEET:                   return _( "Sheet borders" );
     case LAYER_SHEET_BACKGROUND:        return _( "Sheet backgrounds" );
diff --git a/common/plotters/plotter.cpp b/common/plotters/plotter.cpp
index 4d4b7d7331..617c062373 100644
--- a/common/plotters/plotter.cpp
+++ b/common/plotters/plotter.cpp
@@ -41,7 +41,6 @@
 #include <eda_item.h>
 #include <plotters/plotter.h>
 #include <geometry/shape_line_chain.h>
-#include <geometry/geometry_utils.h>
 #include <bezier_curves.h>
 #include <math/util.h>      // for KiROUND
 
@@ -138,19 +137,19 @@ double PLOTTER::userToDeviceSize( double size ) const
 
 double PLOTTER::GetDotMarkLenIU() const
 {
-    return userToDeviceSize( dot_mark_len( GetCurrentLineWidth() ) );
+    return userToDeviceSize( m_renderSettings->GetDotLength( GetCurrentLineWidth() ) );
 }
 
 
 double PLOTTER::GetDashMarkLenIU() const
 {
-    return userToDeviceSize( dash_mark_len( GetCurrentLineWidth() ) );
+    return userToDeviceSize( m_renderSettings->GetDashLength( GetCurrentLineWidth() ) );
 }
 
 
 double PLOTTER::GetDashGapLenIU() const
 {
-    return userToDeviceSize( dash_gap_len( GetCurrentLineWidth() ) );
+    return userToDeviceSize( m_renderSettings->GetGapLength( GetCurrentLineWidth() ) );
 }
 
 
diff --git a/common/render_settings.cpp b/common/render_settings.cpp
index a6d0a3854f..764de1302f 100644
--- a/common/render_settings.cpp
+++ b/common/render_settings.cpp
@@ -51,6 +51,27 @@ RENDER_SETTINGS::~RENDER_SETTINGS()
 }
 
 
+constexpr double visualCorrection = 0.8;
+
+
+double RENDER_SETTINGS::GetDashLength( int aLineWidth ) const
+{
+    return std::max( m_dashLengthRatio - visualCorrection, 1.0 ) * aLineWidth;
+}
+
+
+double RENDER_SETTINGS::GetDotLength( int aLineWidth ) const
+{
+    return ( 1.0 - visualCorrection ) * aLineWidth;
+}
+
+
+double RENDER_SETTINGS::GetGapLength( int aLineWidth ) const
+{
+    return std::max( m_gapLengthRatio + visualCorrection, 1.0 ) * aLineWidth;
+}
+
+
 void RENDER_SETTINGS::update()
 {
     // Calculate darkened/highlighted variants of layer colors
diff --git a/common/settings/builtin_color_themes.h b/common/settings/builtin_color_themes.h
index b71c9c51a3..cc83b3c812 100644
--- a/common/settings/builtin_color_themes.h
+++ b/common/settings/builtin_color_themes.h
@@ -48,6 +48,7 @@ static const std::map<int, COLOR4D> s_defaultTheme =
             { LAYER_LOCLABEL,             CSS_COLOR( 15,  15,  15,  1 ) },
             { LAYER_NOCONNECT,            CSS_COLOR( 0,   0,   132, 1 ) },
             { LAYER_NOTES,                CSS_COLOR( 0,   0,   194, 1 ) },
+            { LAYER_NOTES_BACKGROUND,     CSS_COLOR( 0,   0,   0,   0 ) },
             { LAYER_PIN,                  CSS_COLOR( 132, 0,   0,   1 ) },
             { LAYER_PINNAM,               CSS_COLOR( 0,   100, 100, 1 ) },
             { LAYER_PINNUM,               CSS_COLOR( 169, 0,   0,   1 ) },
@@ -193,6 +194,7 @@ static const std::map<int, COLOR4D> s_classicTheme =
             { LAYER_LOCLABEL,               COLOR4D( BLACK ) },
             { LAYER_NOCONNECT,              COLOR4D( BLUE ) },
             { LAYER_NOTES,                  COLOR4D( LIGHTBLUE ) },
+            { LAYER_NOTES_BACKGROUND,       COLOR4D( UNSPECIFIED_COLOR ) },
             { LAYER_PIN,                    COLOR4D( RED ) },
             { LAYER_PINNAM,                 COLOR4D( CYAN ) },
             { LAYER_PINNUM,                 COLOR4D( RED ) },
diff --git a/common/settings/color_settings.cpp b/common/settings/color_settings.cpp
index 50a975a111..93dbfcfb15 100644
--- a/common/settings/color_settings.cpp
+++ b/common/settings/color_settings.cpp
@@ -94,6 +94,7 @@ COLOR_SETTINGS::COLOR_SETTINGS( const wxString& aFilename, bool aAbsolutePath )
     CLR( "schematic.label_local",       LAYER_LOCLABEL               );
     CLR( "schematic.no_connect",        LAYER_NOCONNECT              );
     CLR( "schematic.note",              LAYER_NOTES                  );
+    CLR( "schematic.note_background",   LAYER_NOTES_BACKGROUND       );
     CLR( "schematic.pin",               LAYER_PIN                    );
     CLR( "schematic.pin_name",          LAYER_PINNAM                 );
     CLR( "schematic.pin_number",        LAYER_PINNUM                 );
diff --git a/common/stroke_params.cpp b/common/stroke_params.cpp
new file mode 100644
index 0000000000..c9c82c8c78
--- /dev/null
+++ b/common/stroke_params.cpp
@@ -0,0 +1,276 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <macros.h>
+#include <base_units.h>
+#include <string_utils.h>
+#include <eda_rect.h>
+#include <render_settings.h>
+#include <geometry/shape.h>
+#include <geometry/shape_segment.h>
+#include <geometry/shape_simple.h>
+#include <geometry/geometry_utils.h>
+#include <stroke_params.h>
+#include <trigo.h>
+
+using namespace STROKEPARAMS_T;
+
+
+void STROKE_PARAMS::Stroke( const SHAPE* aShape, PLOT_DASH_TYPE aLineStyle, int aWidth,
+                            const KIGFX::RENDER_SETTINGS* aRenderSettings,
+                            std::function<void( const wxPoint& a, const wxPoint& b )> aStroker )
+{
+    double strokes[6];
+    int    wrapAround;
+
+    switch( aLineStyle )
+    {
+    case PLOT_DASH_TYPE::DASH:
+        strokes[0] = aRenderSettings->GetDashLength( aWidth );
+        strokes[1] = aRenderSettings->GetGapLength( aWidth );
+        wrapAround = 2;
+        break;
+    case PLOT_DASH_TYPE::DOT:
+        strokes[0] = aRenderSettings->GetDotLength( aWidth );
+        strokes[1] = aRenderSettings->GetGapLength( aWidth );
+        wrapAround = 2;
+        break;
+    case PLOT_DASH_TYPE::DASHDOT:
+        strokes[0] = aRenderSettings->GetDashLength( aWidth );
+        strokes[1] = aRenderSettings->GetGapLength( aWidth );
+        strokes[2] = aRenderSettings->GetDotLength( aWidth );
+        strokes[3] = aRenderSettings->GetGapLength( aWidth );
+        wrapAround = 4;
+        break;
+    default:
+        UNIMPLEMENTED_FOR( lineTypeNames.at( aLineStyle ).name );
+    }
+
+    switch( aShape->Type() )
+    {
+    case SH_SIMPLE:
+    {
+        const SHAPE_SIMPLE* poly = static_cast<const SHAPE_SIMPLE*>( aShape );
+
+        for( size_t ii = 0; ii < poly->GetSegmentCount(); ++ii )
+        {
+            SEG seg = poly->GetSegment( ii );
+            SHAPE_SEGMENT line( seg.A, seg.B );
+            STROKE_PARAMS::Stroke( &line, aLineStyle, aWidth, aRenderSettings, aStroker );
+        }
+    }
+        break;
+
+    case SH_SEGMENT:
+    {
+        const SHAPE_SEGMENT* line = static_cast<const SHAPE_SEGMENT*>( aShape );
+
+        VECTOR2D start = line->GetSeg().A;
+        VECTOR2D end = line->GetSeg().B;
+
+        EDA_RECT clip( (wxPoint)start, wxSize( end.x - start.x, end.y - start.y ) );
+        clip.Normalize();
+
+        double theta = atan2( end.y - start.y, end.x - start.x );
+
+        for( size_t i = 0; i < 10000; ++i )
+        {
+            // Calculations MUST be done in doubles to keep from accumulating rounding
+            // errors as we go.
+            VECTOR2D next( start.x + strokes[ i % wrapAround ] * cos( theta ),
+                           start.y + strokes[ i % wrapAround ] * sin( theta ) );
+
+            // Drawing each segment can be done rounded to ints.
+            wxPoint a( KiROUND( start.x ), KiROUND( start.y ) );
+            wxPoint b( KiROUND( next.x ), KiROUND( next.y ) );
+
+            if( ClipLine( &clip, a.x, a.y, b.x, b.y ) )
+                break;
+            else if( i % 2 == 0 )
+                aStroker( a, b );
+
+            start = next;
+        }
+    }
+        break;
+
+    case SH_ARC:
+    {
+        const SHAPE_ARC* arc = static_cast<const SHAPE_ARC*>( aShape );
+
+        double   r = arc->GetRadius();
+        double   C = 2.0 * M_PI * r;
+        VECTOR2I center = arc->GetCenter();
+        VECTOR2D startRadial( arc->GetP0() - center );
+        double   startAngle = 180.0 / M_PI * atan2( startRadial.y, startRadial.x );
+        VECTOR2D endRadial( arc->GetP1() - center );
+        double   arcEndAngle = 180.0 / M_PI * atan2( endRadial.y, endRadial.x );
+
+        if( arcEndAngle == startAngle )
+            arcEndAngle = startAngle + 360.0;   // ring, not null
+
+        if( startAngle > arcEndAngle )
+        {
+            if( arcEndAngle < 0 )
+                arcEndAngle = NormalizeAngleDegrees( arcEndAngle, 0.0, 360.0 );
+            else
+                startAngle = NormalizeAngleDegrees( startAngle, -360.0, 0.0 );
+        }
+
+        wxASSERT( startAngle < arcEndAngle );
+
+        for( size_t i = 0; i < 10000 && startAngle < arcEndAngle; ++i )
+        {
+            double theta = 360.0 * strokes[ i % wrapAround ] / C;
+            double endAngle = std::min( startAngle + theta, arcEndAngle );
+
+            if( i % 2 == 0 )
+            {
+                wxPoint a( center.x + r * cos( startAngle * M_PI / 180.0 ),
+                           center.y + r * sin( startAngle * M_PI / 180.0 ) );
+                wxPoint b( center.x + r * cos( endAngle * M_PI / 180.0 ),
+                           center.y + r * sin( endAngle * M_PI / 180.0 ) );
+
+                aStroker( a, b );
+            }
+
+            startAngle = endAngle;
+        }
+    }
+        break;
+
+    case SH_CIRCLE:
+        // A circle is always filled; a ring is represented by a 360° arc.
+        KI_FALLTHROUGH;
+
+    default:
+        UNIMPLEMENTED_FOR( SHAPE_TYPE_asString( aShape->Type() ) );
+    }
+}
+
+
+static wxString getLineStyleToken( PLOT_DASH_TYPE aStyle )
+{
+    wxString token;
+
+    switch( aStyle )
+    {
+    case PLOT_DASH_TYPE::DASH:     token = "dash";      break;
+    case PLOT_DASH_TYPE::DOT:      token = "dot";       break;
+    case PLOT_DASH_TYPE::DASHDOT:  token = "dash_dot";  break;
+    case PLOT_DASH_TYPE::SOLID:    token = "solid";     break;
+    case PLOT_DASH_TYPE::DEFAULT:  token = "default";   break;
+    }
+
+    return token;
+}
+
+
+void STROKE_PARAMS::Format( OUTPUTFORMATTER* aFormatter, int aNestLevel ) const
+{
+    wxASSERT( aFormatter != nullptr );
+
+    aFormatter->Print( aNestLevel, "(stroke (width %s) (type %s) (color %d %d %d %s))",
+                       FormatInternalUnits(GetWidth() ).c_str(),
+                       TO_UTF8( getLineStyleToken( GetPlotStyle() ) ),
+                       KiROUND( GetColor().r * 255.0 ),
+                       KiROUND( GetColor().g * 255.0 ),
+                       KiROUND( GetColor().b * 255.0 ),
+                       Double2Str( GetColor().a ).c_str() );
+}
+
+
+void STROKE_PARAMS_PARSER::ParseStroke( STROKE_PARAMS& aStroke )
+{
+    for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
+    {
+        if( token != T_LEFT )
+            Expecting( T_LEFT );
+
+        token = NextTok();
+
+        switch( token )
+        {
+        case T_width:
+            aStroke.SetWidth( parseDouble( "stroke width" ) * m_iuPerMM );
+            NeedRIGHT();
+            break;
+
+        case T_type:
+        {
+            token = NextTok();
+
+            switch( token )
+            {
+            case T_dash:      aStroke.SetPlotStyle( PLOT_DASH_TYPE::DASH );      break;
+            case T_dot:       aStroke.SetPlotStyle( PLOT_DASH_TYPE::DOT );       break;
+            case T_dash_dot:  aStroke.SetPlotStyle( PLOT_DASH_TYPE::DASHDOT );   break;
+            case T_solid:     aStroke.SetPlotStyle( PLOT_DASH_TYPE::SOLID );     break;
+            case T_default:   aStroke.SetPlotStyle( PLOT_DASH_TYPE::DEFAULT );   break;
+            default:
+                Expecting( "solid, dash, dash_dot, dot or default" );
+            }
+
+            NeedRIGHT();
+            break;
+        }
+
+        case T_color:
+        {
+            KIGFX::COLOR4D color;
+
+            color.r = parseInt( "red" ) / 255.0;
+            color.g = parseInt( "green" ) / 255.0;
+            color.b = parseInt( "blue" ) / 255.0;
+            color.a = Clamp( parseDouble( "alpha" ), 0.0, 1.0 );
+
+            aStroke.SetColor( color );
+            NeedRIGHT();
+            break;
+        }
+
+        default:
+            Expecting( "width, type, or color" );
+        }
+    }
+}
+
+
+int STROKE_PARAMS_PARSER::parseInt( const char* aText )
+{
+    T token = NextTok();
+
+    if( token != T_NUMBER )
+        Expecting( aText );
+
+    return atoi( CurText() );
+}
+
+
+double STROKE_PARAMS_PARSER::parseDouble( const char* aText )
+{
+    T token = NextTok();
+
+    if( token != T_NUMBER )
+        Expecting( aText );
+
+    double val = strtod( CurText(), NULL );
+
+    return val;
+}
diff --git a/common/stroke_params.keywords b/common/stroke_params.keywords
new file mode 100644
index 0000000000..44975ea188
--- /dev/null
+++ b/common/stroke_params.keywords
@@ -0,0 +1,10 @@
+color
+dash
+dash_dot
+dash_dot_dot
+default
+dot
+solid
+stroke
+type
+width
\ No newline at end of file
diff --git a/eeschema/CMakeLists.txt b/eeschema/CMakeLists.txt
index 01120207cb..79b4fe6b2d 100644
--- a/eeschema/CMakeLists.txt
+++ b/eeschema/CMakeLists.txt
@@ -91,6 +91,8 @@ set( EESCHEMA_DLGS
     dialogs/dialog_rescue_each_base.cpp
     dialogs/dialog_sch_import_settings.cpp
     dialogs/dialog_sch_import_settings_base.cpp
+    dialogs/dialog_shape_properties.cpp
+    dialogs/dialog_shape_properties_base.cpp
     dialogs/dialog_sheet_pin_properties.cpp
     dialogs/dialog_sheet_pin_properties_base.cpp
     dialogs/dialog_sheet_properties.cpp
@@ -183,7 +185,6 @@ set( EESCHEMA_SRCS
     lib_pin.cpp
     lib_symbol.cpp
     lib_text.cpp
-    symbol_viewer_frame.cpp
     libarch.cpp
     menubar.cpp
     pin_numbers.cpp
@@ -210,6 +211,7 @@ set( EESCHEMA_SRCS
     sch_screen.cpp
     sch_plugins/kicad/sch_sexpr_parser.cpp
     sch_plugins/kicad/sch_sexpr_plugin.cpp
+    sch_shape.cpp
     sch_sheet.cpp
     sch_sheet_path.cpp
     sch_sheet_pin.cpp
@@ -226,6 +228,7 @@ set( EESCHEMA_SRCS
     symbol_library.cpp
     symbol_tree_model_adapter.cpp
     symbol_tree_synchronizing_adapter.cpp
+    symbol_viewer_frame.cpp
     toolbars_symbol_viewer.cpp
     toolbars_sch_editor.cpp
     transform.cpp
diff --git a/eeschema/bus-wire-junction.cpp b/eeschema/bus-wire-junction.cpp
index 79a33429fd..82401ba81a 100644
--- a/eeschema/bus-wire-junction.cpp
+++ b/eeschema/bus-wire-junction.cpp
@@ -319,7 +319,7 @@ bool SCH_EDIT_FRAME::BreakSegment( SCH_LINE* aSegment, const wxPoint& aPoint,
 
 bool SCH_EDIT_FRAME::BreakSegments( const wxPoint& aPoint, SCH_SCREEN* aScreen )
 {
-    static const KICAD_T wiresAndBuses[] = { SCH_LINE_LOCATE_WIRE_T, SCH_LINE_LOCATE_BUS_T, EOT };
+    static const KICAD_T wiresAndBuses[] = { SCH_ITEM_LOCATE_WIRE_T, SCH_ITEM_LOCATE_BUS_T, EOT };
 
     if( aScreen == nullptr )
         aScreen = GetScreen();
@@ -380,7 +380,7 @@ void SCH_EDIT_FRAME::DeleteJunction( SCH_ITEM* aJunction, bool aAppend )
     SCH_SCREEN*        screen = GetScreen();
     PICKED_ITEMS_LIST  undoList;
     EE_SELECTION_TOOL* selectionTool = m_toolManager->GetTool<EE_SELECTION_TOOL>();
-    KICAD_T            wiresAndBuses[] = { SCH_LINE_LOCATE_WIRE_T, SCH_LINE_LOCATE_BUS_T, EOT };
+    KICAD_T            wiresAndBuses[] = { SCH_ITEM_LOCATE_WIRE_T, SCH_ITEM_LOCATE_BUS_T, EOT };
 
     auto remove_item = [ & ]( SCH_ITEM* aItem ) -> void
     {
diff --git a/eeschema/dialogs/dialog_global_edit_text_and_graphics.cpp b/eeschema/dialogs/dialog_global_edit_text_and_graphics.cpp
index 78349e1a77..6c9358ac87 100644
--- a/eeschema/dialogs/dialog_global_edit_text_and_graphics.cpp
+++ b/eeschema/dialogs/dialog_global_edit_text_and_graphics.cpp
@@ -27,6 +27,7 @@
 #include <sch_symbol.h>
 #include <sch_connection.h>
 #include <sch_edit_frame.h>
+#include <sch_shape.h>
 #include <sch_line.h>
 #include <sch_junction.h>
 #include <sch_sheet.h>
@@ -117,8 +118,8 @@ DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS( SCH_
 
     m_colorSwatch->SetSwatchColor( COLOR4D::UNSPECIFIED, false );
     m_colorSwatch->SetDefaultColor( COLOR4D::UNSPECIFIED );
-    m_bgColorSwatch->SetSwatchColor( COLOR4D::UNSPECIFIED, false );
-    m_bgColorSwatch->SetDefaultColor( COLOR4D::UNSPECIFIED );
+    m_fillColorSwatch->SetSwatchColor( COLOR4D::UNSPECIFIED, false );
+    m_fillColorSwatch->SetDefaultColor( COLOR4D::UNSPECIFIED );
     m_dotColorSwatch->SetSwatchColor( COLOR4D::UNSPECIFIED, false );
     m_dotColorSwatch->SetDefaultColor( COLOR4D::UNSPECIFIED );
 
@@ -217,7 +218,7 @@ bool DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::TransferDataToWindow()
     m_lineStyle->SetStringSelection( INDETERMINATE_ACTION );
     m_junctionSize.SetValue( INDETERMINATE_ACTION );
     m_setColor->SetValue( false );
-    m_setBgColor->SetValue( false );
+    m_setFillColor->SetValue( false );
     m_setDotColor->SetValue( false );
 
     return true;
@@ -240,7 +241,6 @@ void DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::processItem( const SCH_SHEET_PATH& aS
 
     EDA_TEXT*     eda_text = dynamic_cast<EDA_TEXT*>( aItem );
     SCH_TEXT*     sch_text = dynamic_cast<SCH_TEXT*>( aItem );
-    SCH_LINE*     lineItem = dynamic_cast<SCH_LINE*>( aItem );
     SCH_JUNCTION* junction = dynamic_cast<SCH_JUNCTION*>( aItem );
 
     m_parent->SaveCopyInUndoList( aSheetPath.LastScreen(), aItem, UNDO_REDO::CHANGED, m_appendUndo );
@@ -274,21 +274,40 @@ void DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::processItem( const SCH_SHEET_PATH& aS
             sch_text->SetLabelSpinStyle( (LABEL_SPIN_STYLE::SPIN) m_orientation->GetSelection() );
     }
 
-    if( lineItem )
+    if( aItem->HasLineStroke() )
     {
+        STROKE_PARAMS stroke = aItem->GetStroke();
+
         if( !m_lineWidth.IsIndeterminate() )
-            lineItem->SetLineWidth( m_lineWidth.GetValue() );
+            stroke.SetWidth( m_lineWidth.GetValue() );
 
         if( m_lineStyle->GetStringSelection() != INDETERMINATE_ACTION )
         {
             if( m_lineStyle->GetStringSelection() == DEFAULT_STYLE )
-                lineItem->SetLineStyle( PLOT_DASH_TYPE::DEFAULT );
+                stroke.SetPlotStyle( PLOT_DASH_TYPE::DEFAULT );
             else
-                lineItem->SetLineStyle( m_lineStyle->GetSelection() );
+                stroke.SetPlotStyle( (PLOT_DASH_TYPE) m_lineStyle->GetSelection() );
         }
 
         if( m_setColor->GetValue() )
-            lineItem->SetLineColor( m_colorSwatch->GetSwatchColor() );
+            stroke.SetColor( m_colorSwatch->GetSwatchColor() );
+
+        aItem->SetStroke( stroke );
+    }
+
+    if( aItem->Type() == SCH_SHAPE_T )
+    {
+        SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( aItem );
+
+        if( m_setFillColor->GetValue() )
+        {
+            shape->SetFillColor( m_fillColorSwatch->GetSwatchColor() );
+
+            if( m_fillColorSwatch->GetSwatchColor() == COLOR4D::UNSPECIFIED )
+                shape->SetFillMode( FILL_T::NO_FILL );
+            else
+                shape->SetFillMode( FILL_T::FILLED_WITH_COLOR );
+        }
     }
 
     if( junction )
@@ -348,9 +367,9 @@ void DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::visitItem( const SCH_SHEET_PATH& aShe
         }
     }
 
-    static KICAD_T wireTypes[] = { SCH_LINE_LOCATE_WIRE_T, SCH_LABEL_LOCATE_WIRE_T, EOT };
-    static KICAD_T busTypes[] = { SCH_LINE_LOCATE_BUS_T, SCH_LABEL_LOCATE_BUS_T, EOT };
-    static KICAD_T schTextAndGraphics[] = { SCH_TEXT_T, SCH_LINE_LOCATE_GRAPHIC_LINE_T, EOT };
+    static KICAD_T wireTypes[] = { SCH_ITEM_LOCATE_WIRE_T, SCH_LABEL_LOCATE_WIRE_T, EOT };
+    static KICAD_T busTypes[] = { SCH_ITEM_LOCATE_BUS_T, SCH_LABEL_LOCATE_BUS_T, EOT };
+    static KICAD_T schTextAndGraphics[] = { SCH_TEXT_T, SCH_ITEM_LOCATE_GRAPHIC_LINE_T, EOT };
 
     if( aItem->Type() == SCH_SYMBOL_T )
     {
@@ -409,8 +428,8 @@ void DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::visitItem( const SCH_SHEET_PATH& aShe
             if( m_setColor->GetValue() )
                 sheet->SetBorderColor( m_colorSwatch->GetSwatchColor() );
 
-            if( m_setBgColor->GetValue() )
-                sheet->SetBackgroundColor( m_bgColorSwatch->GetSwatchColor() );
+            if( m_setFillColor->GetValue() )
+                sheet->SetBackgroundColor( m_fillColorSwatch->GetSwatchColor() );
         }
     }
     else if( aItem->Type() == SCH_JUNCTION_T )
diff --git a/eeschema/dialogs/dialog_global_edit_text_and_graphics_base.cpp b/eeschema/dialogs/dialog_global_edit_text_and_graphics_base.cpp
index 245a32cb81..dc2a096241 100644
--- a/eeschema/dialogs/dialog_global_edit_text_and_graphics_base.cpp
+++ b/eeschema/dialogs/dialog_global_edit_text_and_graphics_base.cpp
@@ -327,14 +327,14 @@ DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS_BASE::DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS_
 
 	fgSizer1->Add( 0, 0, 1, wxEXPAND, 5 );
 
-	m_setBgColor = new wxCheckBox( m_specifiedValues, wxID_ANY, _("Sheet background color:"), wxDefaultPosition, wxDefaultSize, 0 );
-	fgSizer1->Add( m_setBgColor, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
+	m_setFillColor = new wxCheckBox( m_specifiedValues, wxID_ANY, _("Fill color:"), wxDefaultPosition, wxDefaultSize, 0 );
+	fgSizer1->Add( m_setFillColor, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
 
-	m_bgColorSwatch = new COLOR_SWATCH( m_specifiedValues, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
-	m_bgColorSwatch->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
-	m_bgColorSwatch->SetMinSize( wxSize( 48,24 ) );
+	m_fillColorSwatch = new COLOR_SWATCH( m_specifiedValues, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
+	m_fillColorSwatch->SetForegroundColour( wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) );
+	m_fillColorSwatch->SetMinSize( wxSize( 48,24 ) );
 
-	fgSizer1->Add( m_bgColorSwatch, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
+	fgSizer1->Add( m_fillColorSwatch, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
 
 	m_dotSizeLabel = new wxStaticText( m_specifiedValues, wxID_ANY, _("Junction size:"), wxDefaultPosition, wxDefaultSize, 0 );
 	m_dotSizeLabel->Wrap( -1 );
diff --git a/eeschema/dialogs/dialog_global_edit_text_and_graphics_base.fbp b/eeschema/dialogs/dialog_global_edit_text_and_graphics_base.fbp
index 2cfe9de015..cfccbec1fc 100644
--- a/eeschema/dialogs/dialog_global_edit_text_and_graphics_base.fbp
+++ b/eeschema/dialogs/dialog_global_edit_text_and_graphics_base.fbp
@@ -3570,7 +3570,7 @@
                                                     <property name="gripper">0</property>
                                                     <property name="hidden">0</property>
                                                     <property name="id">wxID_ANY</property>
-                                                    <property name="label">Sheet background color:</property>
+                                                    <property name="label">Fill color:</property>
                                                     <property name="max_size"></property>
                                                     <property name="maximize_button">0</property>
                                                     <property name="maximum_size"></property>
@@ -3578,7 +3578,7 @@
                                                     <property name="minimize_button">0</property>
                                                     <property name="minimum_size"></property>
                                                     <property name="moveable">1</property>
-                                                    <property name="name">m_setBgColor</property>
+                                                    <property name="name">m_setFillColor</property>
                                                     <property name="pane_border">1</property>
                                                     <property name="pane_position"></property>
                                                     <property name="pane_size"></property>
@@ -3644,7 +3644,7 @@
                                                     <property name="minimize_button">0</property>
                                                     <property name="minimum_size">48,24</property>
                                                     <property name="moveable">1</property>
-                                                    <property name="name">m_bgColorSwatch</property>
+                                                    <property name="name">m_fillColorSwatch</property>
                                                     <property name="pane_border">1</property>
                                                     <property name="pane_position"></property>
                                                     <property name="pane_size"></property>
diff --git a/eeschema/dialogs/dialog_global_edit_text_and_graphics_base.h b/eeschema/dialogs/dialog_global_edit_text_and_graphics_base.h
index 066b07d0ef..cf0adacf1f 100644
--- a/eeschema/dialogs/dialog_global_edit_text_and_graphics_base.h
+++ b/eeschema/dialogs/dialog_global_edit_text_and_graphics_base.h
@@ -88,8 +88,8 @@ class DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS_BASE : public DIALOG_SHIM
 		COLOR_SWATCH* m_colorSwatch;
 		wxStaticText* lineStyleLabel;
 		wxChoice* m_lineStyle;
-		wxCheckBox* m_setBgColor;
-		COLOR_SWATCH* m_bgColorSwatch;
+		wxCheckBox* m_setFillColor;
+		COLOR_SWATCH* m_fillColorSwatch;
 		wxStaticText* m_dotSizeLabel;
 		wxTextCtrl* m_dotSizeCtrl;
 		wxStaticText* m_dotSizeUnits;
diff --git a/eeschema/dialogs/dialog_lib_shape_properties.cpp b/eeschema/dialogs/dialog_lib_shape_properties.cpp
index b7bc060aa0..4a6cc9ea9a 100644
--- a/eeschema/dialogs/dialog_lib_shape_properties.cpp
+++ b/eeschema/dialogs/dialog_lib_shape_properties.cpp
@@ -25,7 +25,7 @@
 #include <dialog_lib_shape_properties.h>
 #include <symbol_edit_frame.h>
 #include <confirm.h>
-
+#include <lib_shape.h>
 
 DIALOG_LIB_SHAPE_PROPERTIES::DIALOG_LIB_SHAPE_PROPERTIES( SYMBOL_EDIT_FRAME* aParent,
                                                           LIB_ITEM* aItem ) :
@@ -85,7 +85,7 @@ bool DIALOG_LIB_SHAPE_PROPERTIES::TransferDataToWindow()
     m_checkApplyToAllConversions->Enable( enblConvOptStyle );
 
     if( shape )
-        m_fillCtrl->SetSelection( static_cast<int>( shape->GetFillType() ) - 1 );
+        m_fillCtrl->SetSelection( static_cast<int>( shape->GetFillMode() ) - 1 );
 
     m_fillCtrl->Enable( shape != nullptr );
 
@@ -98,13 +98,16 @@ bool DIALOG_LIB_SHAPE_PROPERTIES::TransferDataFromWindow()
     if( !wxDialog::TransferDataFromWindow() )
         return false;
 
-    EDA_SHAPE*  shape = dynamic_cast<EDA_SHAPE*>( m_item );
+    LIB_SHAPE* shape = dynamic_cast<LIB_SHAPE*>( m_item );
 
     if( shape )
+    {
         shape->SetFillMode( static_cast<FILL_T>( std::max( m_fillCtrl->GetSelection() + 1, 1 ) ) );
 
-    if( shape )
-        shape->SetWidth( m_lineWidth.GetValue() );
+        STROKE_PARAMS stroke = shape->GetStroke();
+        stroke.SetWidth( m_lineWidth.GetValue() );
+        shape->SetStroke( stroke );
+    }
 
     if( GetApplyToAllConversions() )
         m_item->SetConvert( 0 );
diff --git a/eeschema/dialogs/dialog_line_wire_bus_properties.cpp b/eeschema/dialogs/dialog_line_wire_bus_properties.cpp
index f85051d7ca..4d9a4bd284 100644
--- a/eeschema/dialogs/dialog_line_wire_bus_properties.cpp
+++ b/eeschema/dialogs/dialog_line_wire_bus_properties.cpp
@@ -22,37 +22,15 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
-#include <bitmaps.h>
 #include <sch_line.h>
 #include <dialog_line_wire_bus_properties.h>
 #include <dialogs/dialog_color_picker.h>
 #include <settings/settings_manager.h>
 #include <sch_edit_frame.h>
+#include <stroke_params.h>
 #include <widgets/color_swatch.h>
 
 
-struct lineTypeStruct
-{
-    wxString      name;
-    const BITMAPS bitmap;
-};
-
-
-/*
- * Conversion map between PLOT_DASH_TYPE values and style names displayed
- */
-const std::map<PLOT_DASH_TYPE, struct lineTypeStruct> lineTypeNames = {
-    { PLOT_DASH_TYPE::SOLID, { _( "Solid" ), BITMAPS::stroke_solid } },
-    { PLOT_DASH_TYPE::DASH, { _( "Dashed" ), BITMAPS::stroke_dash } },
-    { PLOT_DASH_TYPE::DOT, { _( "Dotted" ), BITMAPS::stroke_dot } },
-    { PLOT_DASH_TYPE::DASHDOT, { _( "Dash-Dot" ), BITMAPS::stroke_dashdot } },
-};
-
-
-#define DEFAULT_STYLE _( "Default" )
-#define INDETERMINATE_STYLE _( "Leave unchanged" )
-
-
 DIALOG_LINE_WIRE_BUS_PROPERTIES::DIALOG_LINE_WIRE_BUS_PROPERTIES( SCH_EDIT_FRAME* aParent,
                                                                   std::deque<SCH_ITEM*>& aItems ) :
         DIALOG_LINE_WIRE_BUS_PROPERTIES_BASE( aParent ),
diff --git a/eeschema/dialogs/dialog_shape_properties.cpp b/eeschema/dialogs/dialog_shape_properties.cpp
new file mode 100644
index 0000000000..d7e80f762c
--- /dev/null
+++ b/eeschema/dialogs/dialog_shape_properties.cpp
@@ -0,0 +1,113 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+#include <widgets/color_swatch.h>
+#include <stroke_params.h>
+#include <sch_edit_frame.h>
+#include <sch_shape.h>
+#include <dialog_shape_properties.h>
+
+
+DIALOG_SHAPE_PROPERTIES::DIALOG_SHAPE_PROPERTIES( SCH_EDIT_FRAME* aParent, SCH_SHAPE* aShape ) :
+    DIALOG_SHAPE_PROPERTIES_BASE( aParent ),
+    m_shape( aShape ),
+    m_lineWidth( aParent, m_lineWidthLabel, m_lineWidthCtrl, m_lineWidthUnits, true )
+{
+    SetTitle( wxString::Format( GetTitle(), aShape->ShowShape() ) );
+
+    m_helpLabel1->SetFont( KIUI::GetInfoFont( this ) );
+    m_helpLabel2->SetFont( KIUI::GetInfoFont( this ) );
+
+    SetInitialFocus( m_lineWidthCtrl );
+
+    m_lineColorSwatch->SetDefaultColor( COLOR4D::UNSPECIFIED );
+
+    for( const std::pair<const PLOT_DASH_TYPE, lineTypeStruct>& typeEntry : lineTypeNames )
+        m_lineStyleCombo->Append( typeEntry.second.name, KiBitmap( typeEntry.second.bitmap ) );
+
+    m_lineStyleCombo->Append( DEFAULT_STYLE );
+
+    m_fillColorSwatch->SetDefaultColor( COLOR4D::UNSPECIFIED );
+
+    // Required under wxGTK if we want to dismiss the dialog with the ESC key
+    SetFocus();
+    m_sdbSizerOK->SetDefault();
+
+    // Now all widgets have the size fixed, call FinishDialogSettings
+    finishDialogSettings();
+}
+
+
+bool DIALOG_SHAPE_PROPERTIES::TransferDataToWindow()
+{
+    if( !wxDialog::TransferDataToWindow() )
+        return false;
+
+    m_lineWidth.SetValue( m_shape->GetWidth() );
+    m_lineColorSwatch->SetSwatchColor( m_shape->GetStroke().GetColor(), false );
+
+    int style = static_cast<int>( m_shape->GetStroke().GetPlotStyle() );
+
+    if( style == -1 )
+        m_lineStyleCombo->SetStringSelection( DEFAULT_STYLE );
+    else if( style < (int) lineTypeNames.size() )
+        m_lineStyleCombo->SetSelection( style );
+    else
+        wxFAIL_MSG( "Line type not found in the type lookup map" );
+
+    m_filledCtrl->SetValue( m_shape->IsFilled() );
+    m_fillColorSwatch->SetSwatchColor( m_shape->GetFillColor(), false );
+
+    return true;
+}
+
+
+bool DIALOG_SHAPE_PROPERTIES::TransferDataFromWindow()
+{
+    if( !wxDialog::TransferDataFromWindow() )
+        return false;
+
+    STROKE_PARAMS stroke = m_shape->GetStroke();
+
+    if( !m_lineWidth.IsIndeterminate() )
+        stroke.SetWidth( m_lineWidth.GetValue() );
+
+    auto it = lineTypeNames.begin();
+    std::advance( it, m_lineStyleCombo->GetSelection() );
+
+    if( it == lineTypeNames.end() )
+        stroke.SetPlotStyle( PLOT_DASH_TYPE::DEFAULT );
+    else
+        stroke.SetPlotStyle( it->first );
+
+    stroke.SetColor( m_lineColorSwatch->GetSwatchColor() );
+
+    m_shape->SetStroke( stroke );
+
+    m_shape->SetFillMode( m_filledCtrl->GetValue() ? FILL_T::FILLED_WITH_COLOR : FILL_T::NO_FILL );
+    m_shape->SetFillColor( m_fillColorSwatch->GetSwatchColor() );
+
+    return true;
+}
+
+
diff --git a/eeschema/dialogs/dialog_shape_properties.h b/eeschema/dialogs/dialog_shape_properties.h
new file mode 100644
index 0000000000..254db7d531
--- /dev/null
+++ b/eeschema/dialogs/dialog_shape_properties.h
@@ -0,0 +1,49 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2021 KiCad Developers, see CHANGELOG.TXT for contributors.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+#ifndef DIALOG_SHAPE_PROPERTIES_H
+#define DIALOG_SHAPE_PROPERTIES_H
+
+
+class SCH_SHAPE;
+class SCH_EDIT_FRAME;
+
+
+#include <dialog_shape_properties_base.h>
+#include <widgets/unit_binder.h>
+
+
+class DIALOG_SHAPE_PROPERTIES : public DIALOG_SHAPE_PROPERTIES_BASE
+{
+public:
+    DIALOG_SHAPE_PROPERTIES( SCH_EDIT_FRAME* aParent, SCH_SHAPE* aShape );
+
+    bool TransferDataToWindow() override;
+    bool TransferDataFromWindow() override;
+
+private:
+    SCH_SHAPE*      m_shape;
+    UNIT_BINDER     m_lineWidth;
+};
+
+#endif // DIALOG_SHAPE_PROPERTIES_H
diff --git a/eeschema/dialogs/dialog_shape_properties_base.cpp b/eeschema/dialogs/dialog_shape_properties_base.cpp
new file mode 100644
index 0000000000..8be5815ad4
--- /dev/null
+++ b/eeschema/dialogs/dialog_shape_properties_base.cpp
@@ -0,0 +1,146 @@
+///////////////////////////////////////////////////////////////////////////
+// C++ code generated with wxFormBuilder (version Oct 26 2018)
+// http://www.wxformbuilder.org/
+//
+// PLEASE DO *NOT* EDIT THIS FILE!
+///////////////////////////////////////////////////////////////////////////
+
+#include "widgets/color_swatch.h"
+
+#include "dialog_shape_properties_base.h"
+
+///////////////////////////////////////////////////////////////////////////
+
+BEGIN_EVENT_TABLE( DIALOG_SHAPE_PROPERTIES_BASE, DIALOG_SHIM )
+	EVT_BUTTON( wxID_APPLY, DIALOG_SHAPE_PROPERTIES_BASE::_wxFB_resetDefaults )
+END_EVENT_TABLE()
+
+DIALOG_SHAPE_PROPERTIES_BASE::DIALOG_SHAPE_PROPERTIES_BASE( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style ) : DIALOG_SHIM( parent, id, title, pos, size, style )
+{
+	this->SetSizeHints( wxDefaultSize, wxDefaultSize );
+
+	wxBoxSizer* mainSizer;
+	mainSizer = new wxBoxSizer( wxVERTICAL );
+
+	wxFlexGridSizer* fgSizerGeneral;
+	fgSizerGeneral = new wxFlexGridSizer( 0, 3, 7, 0 );
+	fgSizerGeneral->AddGrowableCol( 1 );
+	fgSizerGeneral->SetFlexibleDirection( wxBOTH );
+	fgSizerGeneral->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
+
+	m_lineWidthLabel = new wxStaticText( this, wxID_ANY, _("Line width:"), wxDefaultPosition, wxDefaultSize, 0 );
+	m_lineWidthLabel->Wrap( -1 );
+	fgSizerGeneral->Add( m_lineWidthLabel, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 3 );
+
+	m_lineWidthCtrl = new wxTextCtrl( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( -1,-1 ), 0 );
+	fgSizerGeneral->Add( m_lineWidthCtrl, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxRIGHT, 3 );
+
+	m_lineWidthUnits = new wxStaticText( this, wxID_ANY, _("unit"), wxDefaultPosition, wxDefaultSize, 0 );
+	m_lineWidthUnits->Wrap( -1 );
+	m_lineWidthUnits->SetMinSize( wxSize( 40,-1 ) );
+
+	fgSizerGeneral->Add( m_lineWidthUnits, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 3 );
+
+	m_lineColorLabel = new wxStaticText( this, wxID_ANY, _("Line color:"), wxDefaultPosition, wxDefaultSize, 0 );
+	m_lineColorLabel->Wrap( -1 );
+	fgSizerGeneral->Add( m_lineColorLabel, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
+
+	m_panel1 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_SIMPLE|wxTAB_TRAVERSAL );
+	wxBoxSizer* bSizer2;
+	bSizer2 = new wxBoxSizer( wxVERTICAL );
+
+	m_lineColorSwatch = new COLOR_SWATCH( m_panel1, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
+	bSizer2->Add( m_lineColorSwatch, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
+
+
+	m_panel1->SetSizer( bSizer2 );
+	m_panel1->Layout();
+	bSizer2->Fit( m_panel1 );
+	fgSizerGeneral->Add( m_panel1, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 2 );
+
+
+	fgSizerGeneral->Add( 0, 0, 1, wxEXPAND, 5 );
+
+	m_lineStyleLabel = new wxStaticText( this, wxID_ANY, _("Line style:"), wxDefaultPosition, wxDefaultSize, 0 );
+	m_lineStyleLabel->Wrap( -1 );
+	fgSizerGeneral->Add( m_lineStyleLabel, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
+
+	m_lineStyleCombo = new wxBitmapComboBox( this, wxID_ANY, _("Combo!"), wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_READONLY );
+	m_lineStyleCombo->SetMinSize( wxSize( 240,-1 ) );
+
+	fgSizerGeneral->Add( m_lineStyleCombo, 0, wxALIGN_CENTER_VERTICAL|wxEXPAND|wxRIGHT, 3 );
+
+
+	fgSizerGeneral->Add( 0, 0, 1, wxEXPAND, 5 );
+
+
+	fgSizerGeneral->Add( 0, 0, 1, wxEXPAND|wxTOP|wxBOTTOM, 5 );
+
+
+	fgSizerGeneral->Add( 0, 0, 1, wxEXPAND, 5 );
+
+
+	fgSizerGeneral->Add( 0, 0, 1, wxEXPAND, 5 );
+
+	m_filledCtrl = new wxCheckBox( this, wxID_ANY, _("Filled shape"), wxDefaultPosition, wxDefaultSize, 0 );
+	fgSizerGeneral->Add( m_filledCtrl, 0, wxALIGN_CENTER_VERTICAL, 5 );
+
+
+	fgSizerGeneral->Add( 0, 0, 1, wxEXPAND, 5 );
+
+
+	fgSizerGeneral->Add( 0, 0, 1, wxEXPAND, 5 );
+
+	m_fillColorLabel = new wxStaticText( this, wxID_ANY, _("Fill color:"), wxDefaultPosition, wxDefaultSize, 0 );
+	m_fillColorLabel->Wrap( -1 );
+	fgSizerGeneral->Add( m_fillColorLabel, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT, 5 );
+
+	m_panel11 = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_SIMPLE|wxTAB_TRAVERSAL );
+	wxBoxSizer* bSizer21;
+	bSizer21 = new wxBoxSizer( wxVERTICAL );
+
+	m_fillColorSwatch = new COLOR_SWATCH( m_panel11, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
+	bSizer21->Add( m_fillColorSwatch, 0, wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL, 5 );
+
+
+	m_panel11->SetSizer( bSizer21 );
+	m_panel11->Layout();
+	bSizer21->Fit( m_panel11 );
+	fgSizerGeneral->Add( m_panel11, 0, wxALIGN_CENTER_VERTICAL|wxRIGHT|wxLEFT, 5 );
+
+
+	mainSizer->Add( fgSizerGeneral, 1, wxEXPAND|wxTOP|wxBOTTOM|wxLEFT, 10 );
+
+	m_helpLabel1 = new wxStaticText( this, wxID_ANY, _("Set line width to 0 to use Schematic Editor line widths."), wxDefaultPosition, wxDefaultSize, 0 );
+	m_helpLabel1->Wrap( 333 );
+	mainSizer->Add( m_helpLabel1, 0, wxTOP|wxRIGHT|wxLEFT, 10 );
+
+	m_helpLabel2 = new wxStaticText( this, wxID_ANY, _("Set line color to transparent to use Schematic Editor colors."), wxDefaultPosition, wxDefaultSize, 0 );
+	m_helpLabel2->Wrap( -1 );
+	mainSizer->Add( m_helpLabel2, 0, wxBOTTOM|wxRIGHT|wxLEFT, 10 );
+
+	m_staticline = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
+	mainSizer->Add( m_staticline, 0, wxEXPAND|wxTOP|wxRIGHT|wxLEFT, 5 );
+
+	m_sdbSizer = new wxStdDialogButtonSizer();
+	m_sdbSizerOK = new wxButton( this, wxID_OK );
+	m_sdbSizer->AddButton( m_sdbSizerOK );
+	m_sdbSizerApply = new wxButton( this, wxID_APPLY );
+	m_sdbSizer->AddButton( m_sdbSizerApply );
+	m_sdbSizerCancel = new wxButton( this, wxID_CANCEL );
+	m_sdbSizer->AddButton( m_sdbSizerCancel );
+	m_sdbSizer->Realize();
+
+	mainSizer->Add( m_sdbSizer, 0, wxALL|wxALIGN_RIGHT, 5 );
+
+
+	this->SetSizer( mainSizer );
+	this->Layout();
+	mainSizer->Fit( this );
+
+	this->Centre( wxBOTH );
+}
+
+DIALOG_SHAPE_PROPERTIES_BASE::~DIALOG_SHAPE_PROPERTIES_BASE()
+{
+}
diff --git a/eeschema/dialogs/dialog_shape_properties_base.fbp b/eeschema/dialogs/dialog_shape_properties_base.fbp
new file mode 100644
index 0000000000..338358ec1e
--- /dev/null
+++ b/eeschema/dialogs/dialog_shape_properties_base.fbp
@@ -0,0 +1,1099 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<wxFormBuilder_Project>
+    <FileVersion major="1" minor="15" />
+    <object class="Project" expanded="1">
+        <property name="class_decoration"></property>
+        <property name="code_generation">C++</property>
+        <property name="disconnect_events">1</property>
+        <property name="disconnect_mode">source_name</property>
+        <property name="disconnect_php_events">0</property>
+        <property name="disconnect_python_events">0</property>
+        <property name="embedded_files_path">res</property>
+        <property name="encoding">UTF-8</property>
+        <property name="event_generation">table</property>
+        <property name="file">dialog_shape_properties_base</property>
+        <property name="first_id">1000</property>
+        <property name="help_provider">none</property>
+        <property name="indent_with_spaces"></property>
+        <property name="internationalize">1</property>
+        <property name="name">dialog_shape_properties</property>
+        <property name="namespace"></property>
+        <property name="path">.</property>
+        <property name="precompiled_header"></property>
+        <property name="relative_path">1</property>
+        <property name="skip_lua_events">1</property>
+        <property name="skip_php_events">1</property>
+        <property name="skip_python_events">1</property>
+        <property name="ui_table">UI</property>
+        <property name="use_enum">1</property>
+        <property name="use_microsoft_bom">0</property>
+        <object class="Dialog" expanded="1">
+            <property name="aui_managed">0</property>
+            <property name="aui_manager_style">wxAUI_MGR_DEFAULT</property>
+            <property name="bg"></property>
+            <property name="center">wxBOTH</property>
+            <property name="context_help"></property>
+            <property name="context_menu">1</property>
+            <property name="enabled">1</property>
+            <property name="event_handler">impl_virtual</property>
+            <property name="extra_style"></property>
+            <property name="fg"></property>
+            <property name="font"></property>
+            <property name="hidden">0</property>
+            <property name="id">wxID_ANY</property>
+            <property name="maximum_size"></property>
+            <property name="minimum_size"></property>
+            <property name="name">DIALOG_SHAPE_PROPERTIES_BASE</property>
+            <property name="pos"></property>
+            <property name="size">-1,-1</property>
+            <property name="style">wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER</property>
+            <property name="subclass">DIALOG_SHIM; dialog_shim.h</property>
+            <property name="title">%s Properties</property>
+            <property name="tooltip"></property>
+            <property name="window_extra_style"></property>
+            <property name="window_name"></property>
+            <property name="window_style"></property>
+            <object class="wxBoxSizer" expanded="1">
+                <property name="minimum_size"></property>
+                <property name="name">mainSizer</property>
+                <property name="orient">wxVERTICAL</property>
+                <property name="permission">none</property>
+                <object class="sizeritem" expanded="1">
+                    <property name="border">10</property>
+                    <property name="flag">wxEXPAND|wxTOP|wxBOTTOM|wxLEFT</property>
+                    <property name="proportion">1</property>
+                    <object class="wxFlexGridSizer" expanded="1">
+                        <property name="cols">3</property>
+                        <property name="flexible_direction">wxBOTH</property>
+                        <property name="growablecols">1</property>
+                        <property name="growablerows"></property>
+                        <property name="hgap">0</property>
+                        <property name="minimum_size"></property>
+                        <property name="name">fgSizerGeneral</property>
+                        <property name="non_flexible_grow_mode">wxFLEX_GROWMODE_SPECIFIED</property>
+                        <property name="permission">none</property>
+                        <property name="rows">0</property>
+                        <property name="vgap">7</property>
+                        <object class="sizeritem" expanded="0">
+                            <property name="border">3</property>
+                            <property name="flag">wxALIGN_CENTER_VERTICAL|wxRIGHT</property>
+                            <property name="proportion">0</property>
+                            <object class="wxStaticText" expanded="0">
+                                <property name="BottomDockable">1</property>
+                                <property name="LeftDockable">1</property>
+                                <property name="RightDockable">1</property>
+                                <property name="TopDockable">1</property>
+                                <property name="aui_layer"></property>
+                                <property name="aui_name"></property>
+                                <property name="aui_position"></property>
+                                <property name="aui_row"></property>
+                                <property name="best_size"></property>
+                                <property name="bg"></property>
+                                <property name="caption"></property>
+                                <property name="caption_visible">1</property>
+                                <property name="center_pane">0</property>
+                                <property name="close_button">1</property>
+                                <property name="context_help"></property>
+                                <property name="context_menu">1</property>
+                                <property name="default_pane">0</property>
+                                <property name="dock">Dock</property>
+                                <property name="dock_fixed">0</property>
+                                <property name="docking">Left</property>
+                                <property name="enabled">1</property>
+                                <property name="fg"></property>
+                                <property name="floatable">1</property>
+                                <property name="font"></property>
+                                <property name="gripper">0</property>
+                                <property name="hidden">0</property>
+                                <property name="id">wxID_ANY</property>
+                                <property name="label">Line width:</property>
+                                <property name="markup">0</property>
+                                <property name="max_size"></property>
+                                <property name="maximize_button">0</property>
+                                <property name="maximum_size"></property>
+                                <property name="min_size"></property>
+                                <property name="minimize_button">0</property>
+                                <property name="minimum_size"></property>
+                                <property name="moveable">1</property>
+                                <property name="name">m_lineWidthLabel</property>
+                                <property name="pane_border">1</property>
+                                <property name="pane_position"></property>
+                                <property name="pane_size"></property>
+                                <property name="permission">protected</property>
+                                <property name="pin_button">1</property>
+                                <property name="pos"></property>
+                                <property name="resize">Resizable</property>
+                                <property name="show">1</property>
+                                <property name="size"></property>
+                                <property name="style"></property>
+                                <property name="subclass"></property>
+                                <property name="toolbar_pane">0</property>
+                                <property name="tooltip"></property>
+                                <property name="window_extra_style"></property>
+                                <property name="window_name"></property>
+                                <property name="window_style"></property>
+                                <property name="wrap">-1</property>
+                            </object>
+                        </object>
+                        <object class="sizeritem" expanded="0">
+                            <property name="border">3</property>
+                            <property name="flag">wxALIGN_CENTER_VERTICAL|wxEXPAND|wxRIGHT</property>
+                            <property name="proportion">0</property>
+                            <object class="wxTextCtrl" expanded="0">
+                                <property name="BottomDockable">1</property>
+                                <property name="LeftDockable">1</property>
+                                <property name="RightDockable">1</property>
+                                <property name="TopDockable">1</property>
+                                <property name="aui_layer"></property>
+                                <property name="aui_name"></property>
+                                <property name="aui_position"></property>
+                                <property name="aui_row"></property>
+                                <property name="best_size"></property>
+                                <property name="bg"></property>
+                                <property name="caption"></property>
+                                <property name="caption_visible">1</property>
+                                <property name="center_pane">0</property>
+                                <property name="close_button">1</property>
+                                <property name="context_help"></property>
+                                <property name="context_menu">1</property>
+                                <property name="default_pane">0</property>
+                                <property name="dock">Dock</property>
+                                <property name="dock_fixed">0</property>
+                                <property name="docking">Left</property>
+                                <property name="enabled">1</property>
+                                <property name="fg"></property>
+                                <property name="floatable">1</property>
+                                <property name="font"></property>
+                                <property name="gripper">0</property>
+                                <property name="hidden">0</property>
+                                <property name="id">wxID_ANY</property>
+                                <property name="max_size"></property>
+                                <property name="maximize_button">0</property>
+                                <property name="maximum_size"></property>
+                                <property name="maxlength">0</property>
+                                <property name="min_size">-1,-1</property>
+                                <property name="minimize_button">0</property>
+                                <property name="minimum_size">-1,-1</property>
+                                <property name="moveable">1</property>
+                                <property name="name">m_lineWidthCtrl</property>
+                                <property name="pane_border">1</property>
+                                <property name="pane_position"></property>
+                                <property name="pane_size"></property>
+                                <property name="permission">protected</property>
+                                <property name="pin_button">1</property>
+                                <property name="pos"></property>
+                                <property name="resize">Resizable</property>
+                                <property name="show">1</property>
+                                <property name="size">-1,-1</property>
+                                <property name="style"></property>
+                                <property name="subclass"></property>
+                                <property name="toolbar_pane">0</property>
+                                <property name="tooltip"></property>
+                                <property name="validator_data_type"></property>
+                                <property name="validator_style">wxFILTER_NONE</property>
+                                <property name="validator_type">wxDefaultValidator</property>
+                                <property name="validator_variable"></property>
+                                <property name="value"></property>
+                                <property name="window_extra_style"></property>
+                                <property name="window_name"></property>
+                                <property name="window_style"></property>
+                            </object>
+                        </object>
+                        <object class="sizeritem" expanded="0">
+                            <property name="border">3</property>
+                            <property name="flag">wxALIGN_CENTER_VERTICAL|wxRIGHT</property>
+                            <property name="proportion">0</property>
+                            <object class="wxStaticText" expanded="0">
+                                <property name="BottomDockable">1</property>
+                                <property name="LeftDockable">1</property>
+                                <property name="RightDockable">1</property>
+                                <property name="TopDockable">1</property>
+                                <property name="aui_layer"></property>
+                                <property name="aui_name"></property>
+                                <property name="aui_position"></property>
+                                <property name="aui_row"></property>
+                                <property name="best_size"></property>
+                                <property name="bg"></property>
+                                <property name="caption"></property>
+                                <property name="caption_visible">1</property>
+                                <property name="center_pane">0</property>
+                                <property name="close_button">1</property>
+                                <property name="context_help"></property>
+                                <property name="context_menu">1</property>
+                                <property name="default_pane">0</property>
+                                <property name="dock">Dock</property>
+                                <property name="dock_fixed">0</property>
+                                <property name="docking">Left</property>
+                                <property name="enabled">1</property>
+                                <property name="fg"></property>
+                                <property name="floatable">1</property>
+                                <property name="font"></property>
+                                <property name="gripper">0</property>
+                                <property name="hidden">0</property>
+                                <property name="id">wxID_ANY</property>
+                                <property name="label">unit</property>
+                                <property name="markup">0</property>
+                                <property name="max_size"></property>
+                                <property name="maximize_button">0</property>
+                                <property name="maximum_size"></property>
+                                <property name="min_size"></property>
+                                <property name="minimize_button">0</property>
+                                <property name="minimum_size">40,-1</property>
+                                <property name="moveable">1</property>
+                                <property name="name">m_lineWidthUnits</property>
+                                <property name="pane_border">1</property>
+                                <property name="pane_position"></property>
+                                <property name="pane_size"></property>
+                                <property name="permission">protected</property>
+                                <property name="pin_button">1</property>
+                                <property name="pos"></property>
+                                <property name="resize">Resizable</property>
+                                <property name="show">1</property>
+                                <property name="size"></property>
+                                <property name="style"></property>
+                                <property name="subclass"></property>
+                                <property name="toolbar_pane">0</property>
+                                <property name="tooltip"></property>
+                                <property name="window_extra_style"></property>
+                                <property name="window_name"></property>
+                                <property name="window_style"></property>
+                                <property name="wrap">-1</property>
+                            </object>
+                        </object>
+                        <object class="sizeritem" expanded="0">
+                            <property name="border">5</property>
+                            <property name="flag">wxALIGN_CENTER_VERTICAL|wxRIGHT</property>
+                            <property name="proportion">0</property>
+                            <object class="wxStaticText" expanded="0">
+                                <property name="BottomDockable">1</property>
+                                <property name="LeftDockable">1</property>
+                                <property name="RightDockable">1</property>
+                                <property name="TopDockable">1</property>
+                                <property name="aui_layer"></property>
+                                <property name="aui_name"></property>
+                                <property name="aui_position"></property>
+                                <property name="aui_row"></property>
+                                <property name="best_size"></property>
+                                <property name="bg"></property>
+                                <property name="caption"></property>
+                                <property name="caption_visible">1</property>
+                                <property name="center_pane">0</property>
+                                <property name="close_button">1</property>
+                                <property name="context_help"></property>
+                                <property name="context_menu">1</property>
+                                <property name="default_pane">0</property>
+                                <property name="dock">Dock</property>
+                                <property name="dock_fixed">0</property>
+                                <property name="docking">Left</property>
+                                <property name="enabled">1</property>
+                                <property name="fg"></property>
+                                <property name="floatable">1</property>
+                                <property name="font"></property>
+                                <property name="gripper">0</property>
+                                <property name="hidden">0</property>
+                                <property name="id">wxID_ANY</property>
+                                <property name="label">Line color:</property>
+                                <property name="markup">0</property>
+                                <property name="max_size"></property>
+                                <property name="maximize_button">0</property>
+                                <property name="maximum_size"></property>
+                                <property name="min_size"></property>
+                                <property name="minimize_button">0</property>
+                                <property name="minimum_size"></property>
+                                <property name="moveable">1</property>
+                                <property name="name">m_lineColorLabel</property>
+                                <property name="pane_border">1</property>
+                                <property name="pane_position"></property>
+                                <property name="pane_size"></property>
+                                <property name="permission">protected</property>
+                                <property name="pin_button">1</property>
+                                <property name="pos"></property>
+                                <property name="resize">Resizable</property>
+                                <property name="show">1</property>
+                                <property name="size"></property>
+                                <property name="style"></property>
+                                <property name="subclass">; ; Not forward_declare</property>
+                                <property name="toolbar_pane">0</property>
+                                <property name="tooltip"></property>
+                                <property name="window_extra_style"></property>
+                                <property name="window_name"></property>
+                                <property name="window_style"></property>
+                                <property name="wrap">-1</property>
+                            </object>
+                        </object>
+                        <object class="sizeritem" expanded="1">
+                            <property name="border">2</property>
+                            <property name="flag">wxALIGN_CENTER_VERTICAL</property>
+                            <property name="proportion">0</property>
+                            <object class="wxPanel" expanded="1">
+                                <property name="BottomDockable">1</property>
+                                <property name="LeftDockable">1</property>
+                                <property name="RightDockable">1</property>
+                                <property name="TopDockable">1</property>
+                                <property name="aui_layer"></property>
+                                <property name="aui_name"></property>
+                                <property name="aui_position"></property>
+                                <property name="aui_row"></property>
+                                <property name="best_size"></property>
+                                <property name="bg"></property>
+                                <property name="caption"></property>
+                                <property name="caption_visible">1</property>
+                                <property name="center_pane">0</property>
+                                <property name="close_button">1</property>
+                                <property name="context_help"></property>
+                                <property name="context_menu">1</property>
+                                <property name="default_pane">0</property>
+                                <property name="dock">Dock</property>
+                                <property name="dock_fixed">0</property>
+                                <property name="docking">Left</property>
+                                <property name="enabled">1</property>
+                                <property name="fg"></property>
+                                <property name="floatable">1</property>
+                                <property name="font"></property>
+                                <property name="gripper">0</property>
+                                <property name="hidden">0</property>
+                                <property name="id">wxID_ANY</property>
+                                <property name="max_size"></property>
+                                <property name="maximize_button">0</property>
+                                <property name="maximum_size"></property>
+                                <property name="min_size"></property>
+                                <property name="minimize_button">0</property>
+                                <property name="minimum_size"></property>
+                                <property name="moveable">1</property>
+                                <property name="name">m_panel1</property>
+                                <property name="pane_border">1</property>
+                                <property name="pane_position"></property>
+                                <property name="pane_size"></property>
+                                <property name="permission">protected</property>
+                                <property name="pin_button">1</property>
+                                <property name="pos"></property>
+                                <property name="resize">Resizable</property>
+                                <property name="show">1</property>
+                                <property name="size"></property>
+                                <property name="subclass">; ; forward_declare</property>
+                                <property name="toolbar_pane">0</property>
+                                <property name="tooltip"></property>
+                                <property name="window_extra_style"></property>
+                                <property name="window_name"></property>
+                                <property name="window_style">wxBORDER_SIMPLE|wxTAB_TRAVERSAL</property>
+                                <object class="wxBoxSizer" expanded="1">
+                                    <property name="minimum_size"></property>
+                                    <property name="name">bSizer2</property>
+                                    <property name="orient">wxVERTICAL</property>
+                                    <property name="permission">none</property>
+                                    <object class="sizeritem" expanded="1">
+                                        <property name="border">5</property>
+                                        <property name="flag">wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL</property>
+                                        <property name="proportion">0</property>
+                                        <object class="CustomControl" expanded="1">
+                                            <property name="BottomDockable">1</property>
+                                            <property name="LeftDockable">1</property>
+                                            <property name="RightDockable">1</property>
+                                            <property name="TopDockable">1</property>
+                                            <property name="aui_layer"></property>
+                                            <property name="aui_name"></property>
+                                            <property name="aui_position"></property>
+                                            <property name="aui_row"></property>
+                                            <property name="best_size"></property>
+                                            <property name="bg"></property>
+                                            <property name="caption"></property>
+                                            <property name="caption_visible">1</property>
+                                            <property name="center_pane">0</property>
+                                            <property name="class">COLOR_SWATCH</property>
+                                            <property name="close_button">1</property>
+                                            <property name="construction"></property>
+                                            <property name="context_help"></property>
+                                            <property name="context_menu">1</property>
+                                            <property name="declaration"></property>
+                                            <property name="default_pane">0</property>
+                                            <property name="dock">Dock</property>
+                                            <property name="dock_fixed">0</property>
+                                            <property name="docking">Left</property>
+                                            <property name="enabled">1</property>
+                                            <property name="fg"></property>
+                                            <property name="floatable">1</property>
+                                            <property name="font"></property>
+                                            <property name="gripper">0</property>
+                                            <property name="hidden">0</property>
+                                            <property name="id">wxID_ANY</property>
+                                            <property name="include"></property>
+                                            <property name="max_size"></property>
+                                            <property name="maximize_button">0</property>
+                                            <property name="maximum_size"></property>
+                                            <property name="min_size"></property>
+                                            <property name="minimize_button">0</property>
+                                            <property name="minimum_size"></property>
+                                            <property name="moveable">1</property>
+                                            <property name="name">m_lineColorSwatch</property>
+                                            <property name="pane_border">1</property>
+                                            <property name="pane_position"></property>
+                                            <property name="pane_size"></property>
+                                            <property name="permission">protected</property>
+                                            <property name="pin_button">1</property>
+                                            <property name="pos"></property>
+                                            <property name="resize">Resizable</property>
+                                            <property name="settings"></property>
+                                            <property name="show">1</property>
+                                            <property name="size"></property>
+                                            <property name="subclass">COLOR_SWATCH; widgets/color_swatch.h; forward_declare</property>
+                                            <property name="toolbar_pane">0</property>
+                                            <property name="tooltip"></property>
+                                            <property name="window_extra_style"></property>
+                                            <property name="window_name"></property>
+                                            <property name="window_style"></property>
+                                        </object>
+                                    </object>
+                                </object>
+                            </object>
+                        </object>
+                        <object class="sizeritem" expanded="1">
+                            <property name="border">5</property>
+                            <property name="flag">wxEXPAND</property>
+                            <property name="proportion">1</property>
+                            <object class="spacer" expanded="1">
+                                <property name="height">0</property>
+                                <property name="permission">protected</property>
+                                <property name="width">0</property>
+                            </object>
+                        </object>
+                        <object class="sizeritem" expanded="1">
+                            <property name="border">5</property>
+                            <property name="flag">wxALIGN_CENTER_VERTICAL|wxRIGHT</property>
+                            <property name="proportion">0</property>
+                            <object class="wxStaticText" expanded="1">
+                                <property name="BottomDockable">1</property>
+                                <property name="LeftDockable">1</property>
+                                <property name="RightDockable">1</property>
+                                <property name="TopDockable">1</property>
+                                <property name="aui_layer"></property>
+                                <property name="aui_name"></property>
+                                <property name="aui_position"></property>
+                                <property name="aui_row"></property>
+                                <property name="best_size"></property>
+                                <property name="bg"></property>
+                                <property name="caption"></property>
+                                <property name="caption_visible">1</property>
+                                <property name="center_pane">0</property>
+                                <property name="close_button">1</property>
+                                <property name="context_help"></property>
+                                <property name="context_menu">1</property>
+                                <property name="default_pane">0</property>
+                                <property name="dock">Dock</property>
+                                <property name="dock_fixed">0</property>
+                                <property name="docking">Left</property>
+                                <property name="enabled">1</property>
+                                <property name="fg"></property>
+                                <property name="floatable">1</property>
+                                <property name="font"></property>
+                                <property name="gripper">0</property>
+                                <property name="hidden">0</property>
+                                <property name="id">wxID_ANY</property>
+                                <property name="label">Line style:</property>
+                                <property name="markup">0</property>
+                                <property name="max_size"></property>
+                                <property name="maximize_button">0</property>
+                                <property name="maximum_size"></property>
+                                <property name="min_size"></property>
+                                <property name="minimize_button">0</property>
+                                <property name="minimum_size"></property>
+                                <property name="moveable">1</property>
+                                <property name="name">m_lineStyleLabel</property>
+                                <property name="pane_border">1</property>
+                                <property name="pane_position"></property>
+                                <property name="pane_size"></property>
+                                <property name="permission">protected</property>
+                                <property name="pin_button">1</property>
+                                <property name="pos"></property>
+                                <property name="resize">Resizable</property>
+                                <property name="show">1</property>
+                                <property name="size"></property>
+                                <property name="style"></property>
+                                <property name="subclass">; ; forward_declare</property>
+                                <property name="toolbar_pane">0</property>
+                                <property name="tooltip"></property>
+                                <property name="window_extra_style"></property>
+                                <property name="window_name"></property>
+                                <property name="window_style"></property>
+                                <property name="wrap">-1</property>
+                            </object>
+                        </object>
+                        <object class="sizeritem" expanded="1">
+                            <property name="border">3</property>
+                            <property name="flag">wxALIGN_CENTER_VERTICAL|wxEXPAND|wxRIGHT</property>
+                            <property name="proportion">0</property>
+                            <object class="wxBitmapComboBox" expanded="1">
+                                <property name="BottomDockable">1</property>
+                                <property name="LeftDockable">1</property>
+                                <property name="RightDockable">1</property>
+                                <property name="TopDockable">1</property>
+                                <property name="aui_layer"></property>
+                                <property name="aui_name"></property>
+                                <property name="aui_position"></property>
+                                <property name="aui_row"></property>
+                                <property name="best_size"></property>
+                                <property name="bg"></property>
+                                <property name="caption"></property>
+                                <property name="caption_visible">1</property>
+                                <property name="center_pane">0</property>
+                                <property name="choices"></property>
+                                <property name="close_button">1</property>
+                                <property name="context_help"></property>
+                                <property name="context_menu">1</property>
+                                <property name="default_pane">0</property>
+                                <property name="dock">Dock</property>
+                                <property name="dock_fixed">0</property>
+                                <property name="docking">Left</property>
+                                <property name="enabled">1</property>
+                                <property name="fg"></property>
+                                <property name="floatable">1</property>
+                                <property name="font"></property>
+                                <property name="gripper">0</property>
+                                <property name="hidden">0</property>
+                                <property name="id">wxID_ANY</property>
+                                <property name="max_size"></property>
+                                <property name="maximize_button">0</property>
+                                <property name="maximum_size"></property>
+                                <property name="min_size"></property>
+                                <property name="minimize_button">0</property>
+                                <property name="minimum_size">240,-1</property>
+                                <property name="moveable">1</property>
+                                <property name="name">m_lineStyleCombo</property>
+                                <property name="pane_border">1</property>
+                                <property name="pane_position"></property>
+                                <property name="pane_size"></property>
+                                <property name="permission">protected</property>
+                                <property name="pin_button">1</property>
+                                <property name="pos"></property>
+                                <property name="resize">Resizable</property>
+                                <property name="selection">-1</property>
+                                <property name="show">1</property>
+                                <property name="size"></property>
+                                <property name="style">wxCB_READONLY</property>
+                                <property name="subclass">; ; forward_declare</property>
+                                <property name="toolbar_pane">0</property>
+                                <property name="tooltip"></property>
+                                <property name="validator_data_type"></property>
+                                <property name="validator_style">wxFILTER_NONE</property>
+                                <property name="validator_type">wxDefaultValidator</property>
+                                <property name="validator_variable"></property>
+                                <property name="value">Combo!</property>
+                                <property name="window_extra_style"></property>
+                                <property name="window_name"></property>
+                                <property name="window_style"></property>
+                            </object>
+                        </object>
+                        <object class="sizeritem" expanded="1">
+                            <property name="border">5</property>
+                            <property name="flag">wxEXPAND</property>
+                            <property name="proportion">1</property>
+                            <object class="spacer" expanded="1">
+                                <property name="height">0</property>
+                                <property name="permission">protected</property>
+                                <property name="width">0</property>
+                            </object>
+                        </object>
+                        <object class="sizeritem" expanded="1">
+                            <property name="border">5</property>
+                            <property name="flag">wxEXPAND|wxTOP|wxBOTTOM</property>
+                            <property name="proportion">1</property>
+                            <object class="spacer" expanded="1">
+                                <property name="height">0</property>
+                                <property name="permission">protected</property>
+                                <property name="width">0</property>
+                            </object>
+                        </object>
+                        <object class="sizeritem" expanded="1">
+                            <property name="border">5</property>
+                            <property name="flag">wxEXPAND</property>
+                            <property name="proportion">1</property>
+                            <object class="spacer" expanded="1">
+                                <property name="height">0</property>
+                                <property name="permission">protected</property>
+                                <property name="width">0</property>
+                            </object>
+                        </object>
+                        <object class="sizeritem" expanded="1">
+                            <property name="border">5</property>
+                            <property name="flag">wxEXPAND</property>
+                            <property name="proportion">1</property>
+                            <object class="spacer" expanded="1">
+                                <property name="height">0</property>
+                                <property name="permission">protected</property>
+                                <property name="width">0</property>
+                            </object>
+                        </object>
+                        <object class="sizeritem" expanded="1">
+                            <property name="border">5</property>
+                            <property name="flag">wxALIGN_CENTER_VERTICAL</property>
+                            <property name="proportion">0</property>
+                            <object class="wxCheckBox" expanded="1">
+                                <property name="BottomDockable">1</property>
+                                <property name="LeftDockable">1</property>
+                                <property name="RightDockable">1</property>
+                                <property name="TopDockable">1</property>
+                                <property name="aui_layer"></property>
+                                <property name="aui_name"></property>
+                                <property name="aui_position"></property>
+                                <property name="aui_row"></property>
+                                <property name="best_size"></property>
+                                <property name="bg"></property>
+                                <property name="caption"></property>
+                                <property name="caption_visible">1</property>
+                                <property name="center_pane">0</property>
+                                <property name="checked">0</property>
+                                <property name="close_button">1</property>
+                                <property name="context_help"></property>
+                                <property name="context_menu">1</property>
+                                <property name="default_pane">0</property>
+                                <property name="dock">Dock</property>
+                                <property name="dock_fixed">0</property>
+                                <property name="docking">Left</property>
+                                <property name="enabled">1</property>
+                                <property name="fg"></property>
+                                <property name="floatable">1</property>
+                                <property name="font"></property>
+                                <property name="gripper">0</property>
+                                <property name="hidden">0</property>
+                                <property name="id">wxID_ANY</property>
+                                <property name="label">Filled shape</property>
+                                <property name="max_size"></property>
+                                <property name="maximize_button">0</property>
+                                <property name="maximum_size"></property>
+                                <property name="min_size"></property>
+                                <property name="minimize_button">0</property>
+                                <property name="minimum_size"></property>
+                                <property name="moveable">1</property>
+                                <property name="name">m_filledCtrl</property>
+                                <property name="pane_border">1</property>
+                                <property name="pane_position"></property>
+                                <property name="pane_size"></property>
+                                <property name="permission">protected</property>
+                                <property name="pin_button">1</property>
+                                <property name="pos"></property>
+                                <property name="resize">Resizable</property>
+                                <property name="show">1</property>
+                                <property name="size"></property>
+                                <property name="style"></property>
+                                <property name="subclass">; ; forward_declare</property>
+                                <property name="toolbar_pane">0</property>
+                                <property name="tooltip"></property>
+                                <property name="validator_data_type"></property>
+                                <property name="validator_style">wxFILTER_NONE</property>
+                                <property name="validator_type">wxDefaultValidator</property>
+                                <property name="validator_variable"></property>
+                                <property name="window_extra_style"></property>
+                                <property name="window_name"></property>
+                                <property name="window_style"></property>
+                            </object>
+                        </object>
+                        <object class="sizeritem" expanded="1">
+                            <property name="border">5</property>
+                            <property name="flag">wxEXPAND</property>
+                            <property name="proportion">1</property>
+                            <object class="spacer" expanded="1">
+                                <property name="height">0</property>
+                                <property name="permission">protected</property>
+                                <property name="width">0</property>
+                            </object>
+                        </object>
+                        <object class="sizeritem" expanded="1">
+                            <property name="border">5</property>
+                            <property name="flag">wxEXPAND</property>
+                            <property name="proportion">1</property>
+                            <object class="spacer" expanded="1">
+                                <property name="height">0</property>
+                                <property name="permission">protected</property>
+                                <property name="width">0</property>
+                            </object>
+                        </object>
+                        <object class="sizeritem" expanded="1">
+                            <property name="border">5</property>
+                            <property name="flag">wxALIGN_CENTER_VERTICAL|wxRIGHT</property>
+                            <property name="proportion">0</property>
+                            <object class="wxStaticText" expanded="1">
+                                <property name="BottomDockable">1</property>
+                                <property name="LeftDockable">1</property>
+                                <property name="RightDockable">1</property>
+                                <property name="TopDockable">1</property>
+                                <property name="aui_layer"></property>
+                                <property name="aui_name"></property>
+                                <property name="aui_position"></property>
+                                <property name="aui_row"></property>
+                                <property name="best_size"></property>
+                                <property name="bg"></property>
+                                <property name="caption"></property>
+                                <property name="caption_visible">1</property>
+                                <property name="center_pane">0</property>
+                                <property name="close_button">1</property>
+                                <property name="context_help"></property>
+                                <property name="context_menu">1</property>
+                                <property name="default_pane">0</property>
+                                <property name="dock">Dock</property>
+                                <property name="dock_fixed">0</property>
+                                <property name="docking">Left</property>
+                                <property name="enabled">1</property>
+                                <property name="fg"></property>
+                                <property name="floatable">1</property>
+                                <property name="font"></property>
+                                <property name="gripper">0</property>
+                                <property name="hidden">0</property>
+                                <property name="id">wxID_ANY</property>
+                                <property name="label">Fill color:</property>
+                                <property name="markup">0</property>
+                                <property name="max_size"></property>
+                                <property name="maximize_button">0</property>
+                                <property name="maximum_size"></property>
+                                <property name="min_size"></property>
+                                <property name="minimize_button">0</property>
+                                <property name="minimum_size"></property>
+                                <property name="moveable">1</property>
+                                <property name="name">m_fillColorLabel</property>
+                                <property name="pane_border">1</property>
+                                <property name="pane_position"></property>
+                                <property name="pane_size"></property>
+                                <property name="permission">protected</property>
+                                <property name="pin_button">1</property>
+                                <property name="pos"></property>
+                                <property name="resize">Resizable</property>
+                                <property name="show">1</property>
+                                <property name="size"></property>
+                                <property name="style"></property>
+                                <property name="subclass">; ; forward_declare</property>
+                                <property name="toolbar_pane">0</property>
+                                <property name="tooltip"></property>
+                                <property name="window_extra_style"></property>
+                                <property name="window_name"></property>
+                                <property name="window_style"></property>
+                                <property name="wrap">-1</property>
+                            </object>
+                        </object>
+                        <object class="sizeritem" expanded="1">
+                            <property name="border">5</property>
+                            <property name="flag">wxALIGN_CENTER_VERTICAL</property>
+                            <property name="proportion">0</property>
+                            <object class="wxPanel" expanded="1">
+                                <property name="BottomDockable">1</property>
+                                <property name="LeftDockable">1</property>
+                                <property name="RightDockable">1</property>
+                                <property name="TopDockable">1</property>
+                                <property name="aui_layer"></property>
+                                <property name="aui_name"></property>
+                                <property name="aui_position"></property>
+                                <property name="aui_row"></property>
+                                <property name="best_size"></property>
+                                <property name="bg"></property>
+                                <property name="caption"></property>
+                                <property name="caption_visible">1</property>
+                                <property name="center_pane">0</property>
+                                <property name="close_button">1</property>
+                                <property name="context_help"></property>
+                                <property name="context_menu">1</property>
+                                <property name="default_pane">0</property>
+                                <property name="dock">Dock</property>
+                                <property name="dock_fixed">0</property>
+                                <property name="docking">Left</property>
+                                <property name="enabled">1</property>
+                                <property name="fg"></property>
+                                <property name="floatable">1</property>
+                                <property name="font"></property>
+                                <property name="gripper">0</property>
+                                <property name="hidden">0</property>
+                                <property name="id">wxID_ANY</property>
+                                <property name="max_size"></property>
+                                <property name="maximize_button">0</property>
+                                <property name="maximum_size"></property>
+                                <property name="min_size"></property>
+                                <property name="minimize_button">0</property>
+                                <property name="minimum_size"></property>
+                                <property name="moveable">1</property>
+                                <property name="name">m_panel11</property>
+                                <property name="pane_border">1</property>
+                                <property name="pane_position"></property>
+                                <property name="pane_size"></property>
+                                <property name="permission">protected</property>
+                                <property name="pin_button">1</property>
+                                <property name="pos"></property>
+                                <property name="resize">Resizable</property>
+                                <property name="show">1</property>
+                                <property name="size"></property>
+                                <property name="subclass">; ; forward_declare</property>
+                                <property name="toolbar_pane">0</property>
+                                <property name="tooltip"></property>
+                                <property name="window_extra_style"></property>
+                                <property name="window_name"></property>
+                                <property name="window_style">wxBORDER_SIMPLE|wxTAB_TRAVERSAL</property>
+                                <object class="wxBoxSizer" expanded="1">
+                                    <property name="minimum_size"></property>
+                                    <property name="name">bSizer21</property>
+                                    <property name="orient">wxVERTICAL</property>
+                                    <property name="permission">none</property>
+                                    <object class="sizeritem" expanded="1">
+                                        <property name="border">5</property>
+                                        <property name="flag">wxALIGN_CENTER_VERTICAL|wxALIGN_CENTER_HORIZONTAL</property>
+                                        <property name="proportion">0</property>
+                                        <object class="CustomControl" expanded="1">
+                                            <property name="BottomDockable">1</property>
+                                            <property name="LeftDockable">1</property>
+                                            <property name="RightDockable">1</property>
+                                            <property name="TopDockable">1</property>
+                                            <property name="aui_layer"></property>
+                                            <property name="aui_name"></property>
+                                            <property name="aui_position"></property>
+                                            <property name="aui_row"></property>
+                                            <property name="best_size"></property>
+                                            <property name="bg"></property>
+                                            <property name="caption"></property>
+                                            <property name="caption_visible">1</property>
+                                            <property name="center_pane">0</property>
+                                            <property name="class">COLOR_SWATCH</property>
+                                            <property name="close_button">1</property>
+                                            <property name="construction"></property>
+                                            <property name="context_help"></property>
+                                            <property name="context_menu">1</property>
+                                            <property name="declaration"></property>
+                                            <property name="default_pane">0</property>
+                                            <property name="dock">Dock</property>
+                                            <property name="dock_fixed">0</property>
+                                            <property name="docking">Left</property>
+                                            <property name="enabled">1</property>
+                                            <property name="fg"></property>
+                                            <property name="floatable">1</property>
+                                            <property name="font"></property>
+                                            <property name="gripper">0</property>
+                                            <property name="hidden">0</property>
+                                            <property name="id">wxID_ANY</property>
+                                            <property name="include"></property>
+                                            <property name="max_size"></property>
+                                            <property name="maximize_button">0</property>
+                                            <property name="maximum_size"></property>
+                                            <property name="min_size"></property>
+                                            <property name="minimize_button">0</property>
+                                            <property name="minimum_size"></property>
+                                            <property name="moveable">1</property>
+                                            <property name="name">m_fillColorSwatch</property>
+                                            <property name="pane_border">1</property>
+                                            <property name="pane_position"></property>
+                                            <property name="pane_size"></property>
+                                            <property name="permission">protected</property>
+                                            <property name="pin_button">1</property>
+                                            <property name="pos"></property>
+                                            <property name="resize">Resizable</property>
+                                            <property name="settings"></property>
+                                            <property name="show">1</property>
+                                            <property name="size"></property>
+                                            <property name="subclass">COLOR_SWATCH; widgets/color_swatch.h; forward_declare</property>
+                                            <property name="toolbar_pane">0</property>
+                                            <property name="tooltip"></property>
+                                            <property name="window_extra_style"></property>
+                                            <property name="window_name"></property>
+                                            <property name="window_style"></property>
+                                        </object>
+                                    </object>
+                                </object>
+                            </object>
+                        </object>
+                    </object>
+                </object>
+                <object class="sizeritem" expanded="1">
+                    <property name="border">10</property>
+                    <property name="flag">wxTOP|wxRIGHT|wxLEFT</property>
+                    <property name="proportion">0</property>
+                    <object class="wxStaticText" expanded="1">
+                        <property name="BottomDockable">1</property>
+                        <property name="LeftDockable">1</property>
+                        <property name="RightDockable">1</property>
+                        <property name="TopDockable">1</property>
+                        <property name="aui_layer"></property>
+                        <property name="aui_name"></property>
+                        <property name="aui_position"></property>
+                        <property name="aui_row"></property>
+                        <property name="best_size"></property>
+                        <property name="bg"></property>
+                        <property name="caption"></property>
+                        <property name="caption_visible">1</property>
+                        <property name="center_pane">0</property>
+                        <property name="close_button">1</property>
+                        <property name="context_help"></property>
+                        <property name="context_menu">1</property>
+                        <property name="default_pane">0</property>
+                        <property name="dock">Dock</property>
+                        <property name="dock_fixed">0</property>
+                        <property name="docking">Left</property>
+                        <property name="enabled">1</property>
+                        <property name="fg"></property>
+                        <property name="floatable">1</property>
+                        <property name="font"></property>
+                        <property name="gripper">0</property>
+                        <property name="hidden">0</property>
+                        <property name="id">wxID_ANY</property>
+                        <property name="label">Set line width to 0 to use Schematic Editor line widths.</property>
+                        <property name="markup">0</property>
+                        <property name="max_size"></property>
+                        <property name="maximize_button">0</property>
+                        <property name="maximum_size"></property>
+                        <property name="min_size"></property>
+                        <property name="minimize_button">0</property>
+                        <property name="minimum_size"></property>
+                        <property name="moveable">1</property>
+                        <property name="name">m_helpLabel1</property>
+                        <property name="pane_border">1</property>
+                        <property name="pane_position"></property>
+                        <property name="pane_size"></property>
+                        <property name="permission">protected</property>
+                        <property name="pin_button">1</property>
+                        <property name="pos"></property>
+                        <property name="resize">Resizable</property>
+                        <property name="show">1</property>
+                        <property name="size"></property>
+                        <property name="style"></property>
+                        <property name="subclass">; ; forward_declare</property>
+                        <property name="toolbar_pane">0</property>
+                        <property name="tooltip"></property>
+                        <property name="window_extra_style"></property>
+                        <property name="window_name"></property>
+                        <property name="window_style"></property>
+                        <property name="wrap">333</property>
+                    </object>
+                </object>
+                <object class="sizeritem" expanded="1">
+                    <property name="border">10</property>
+                    <property name="flag">wxBOTTOM|wxRIGHT|wxLEFT</property>
+                    <property name="proportion">0</property>
+                    <object class="wxStaticText" expanded="1">
+                        <property name="BottomDockable">1</property>
+                        <property name="LeftDockable">1</property>
+                        <property name="RightDockable">1</property>
+                        <property name="TopDockable">1</property>
+                        <property name="aui_layer"></property>
+                        <property name="aui_name"></property>
+                        <property name="aui_position"></property>
+                        <property name="aui_row"></property>
+                        <property name="best_size"></property>
+                        <property name="bg"></property>
+                        <property name="caption"></property>
+                        <property name="caption_visible">1</property>
+                        <property name="center_pane">0</property>
+                        <property name="close_button">1</property>
+                        <property name="context_help"></property>
+                        <property name="context_menu">1</property>
+                        <property name="default_pane">0</property>
+                        <property name="dock">Dock</property>
+                        <property name="dock_fixed">0</property>
+                        <property name="docking">Left</property>
+                        <property name="enabled">1</property>
+                        <property name="fg"></property>
+                        <property name="floatable">1</property>
+                        <property name="font"></property>
+                        <property name="gripper">0</property>
+                        <property name="hidden">0</property>
+                        <property name="id">wxID_ANY</property>
+                        <property name="label">Set line color to transparent to use Schematic Editor colors.</property>
+                        <property name="markup">0</property>
+                        <property name="max_size"></property>
+                        <property name="maximize_button">0</property>
+                        <property name="maximum_size"></property>
+                        <property name="min_size"></property>
+                        <property name="minimize_button">0</property>
+                        <property name="minimum_size"></property>
+                        <property name="moveable">1</property>
+                        <property name="name">m_helpLabel2</property>
+                        <property name="pane_border">1</property>
+                        <property name="pane_position"></property>
+                        <property name="pane_size"></property>
+                        <property name="permission">protected</property>
+                        <property name="pin_button">1</property>
+                        <property name="pos"></property>
+                        <property name="resize">Resizable</property>
+                        <property name="show">1</property>
+                        <property name="size"></property>
+                        <property name="style"></property>
+                        <property name="subclass">; ; forward_declare</property>
+                        <property name="toolbar_pane">0</property>
+                        <property name="tooltip"></property>
+                        <property name="window_extra_style"></property>
+                        <property name="window_name"></property>
+                        <property name="window_style"></property>
+                        <property name="wrap">-1</property>
+                    </object>
+                </object>
+                <object class="sizeritem" expanded="1">
+                    <property name="border">5</property>
+                    <property name="flag">wxEXPAND|wxTOP|wxRIGHT|wxLEFT</property>
+                    <property name="proportion">0</property>
+                    <object class="wxStaticLine" expanded="1">
+                        <property name="BottomDockable">1</property>
+                        <property name="LeftDockable">1</property>
+                        <property name="RightDockable">1</property>
+                        <property name="TopDockable">1</property>
+                        <property name="aui_layer"></property>
+                        <property name="aui_name"></property>
+                        <property name="aui_position"></property>
+                        <property name="aui_row"></property>
+                        <property name="best_size"></property>
+                        <property name="bg"></property>
+                        <property name="caption"></property>
+                        <property name="caption_visible">1</property>
+                        <property name="center_pane">0</property>
+                        <property name="close_button">1</property>
+                        <property name="context_help"></property>
+                        <property name="context_menu">1</property>
+                        <property name="default_pane">0</property>
+                        <property name="dock">Dock</property>
+                        <property name="dock_fixed">0</property>
+                        <property name="docking">Left</property>
+                        <property name="enabled">1</property>
+                        <property name="fg"></property>
+                        <property name="floatable">1</property>
+                        <property name="font"></property>
+                        <property name="gripper">0</property>
+                        <property name="hidden">0</property>
+                        <property name="id">wxID_ANY</property>
+                        <property name="max_size"></property>
+                        <property name="maximize_button">0</property>
+                        <property name="maximum_size"></property>
+                        <property name="min_size"></property>
+                        <property name="minimize_button">0</property>
+                        <property name="minimum_size"></property>
+                        <property name="moveable">1</property>
+                        <property name="name">m_staticline</property>
+                        <property name="pane_border">1</property>
+                        <property name="pane_position"></property>
+                        <property name="pane_size"></property>
+                        <property name="permission">protected</property>
+                        <property name="pin_button">1</property>
+                        <property name="pos"></property>
+                        <property name="resize">Resizable</property>
+                        <property name="show">1</property>
+                        <property name="size"></property>
+                        <property name="style">wxLI_HORIZONTAL</property>
+                        <property name="subclass"></property>
+                        <property name="toolbar_pane">0</property>
+                        <property name="tooltip"></property>
+                        <property name="window_extra_style"></property>
+                        <property name="window_name"></property>
+                        <property name="window_style"></property>
+                    </object>
+                </object>
+                <object class="sizeritem" expanded="1">
+                    <property name="border">5</property>
+                    <property name="flag">wxALL|wxALIGN_RIGHT</property>
+                    <property name="proportion">0</property>
+                    <object class="wxStdDialogButtonSizer" expanded="1">
+                        <property name="Apply">1</property>
+                        <property name="Cancel">1</property>
+                        <property name="ContextHelp">0</property>
+                        <property name="Help">0</property>
+                        <property name="No">0</property>
+                        <property name="OK">1</property>
+                        <property name="Save">0</property>
+                        <property name="Yes">0</property>
+                        <property name="minimum_size"></property>
+                        <property name="name">m_sdbSizer</property>
+                        <property name="permission">protected</property>
+                        <event name="OnApplyButtonClick">resetDefaults</event>
+                    </object>
+                </object>
+            </object>
+        </object>
+    </object>
+</wxFormBuilder_Project>
diff --git a/eeschema/dialogs/dialog_shape_properties_base.h b/eeschema/dialogs/dialog_shape_properties_base.h
new file mode 100644
index 0000000000..ae16b005e6
--- /dev/null
+++ b/eeschema/dialogs/dialog_shape_properties_base.h
@@ -0,0 +1,76 @@
+///////////////////////////////////////////////////////////////////////////
+// C++ code generated with wxFormBuilder (version Oct 26 2018)
+// http://www.wxformbuilder.org/
+//
+// PLEASE DO *NOT* EDIT THIS FILE!
+///////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+#include <wx/artprov.h>
+#include <wx/xrc/xmlres.h>
+#include <wx/intl.h>
+class COLOR_SWATCH;
+
+#include "dialog_shim.h"
+#include <wx/string.h>
+#include <wx/stattext.h>
+#include <wx/gdicmn.h>
+#include <wx/font.h>
+#include <wx/colour.h>
+#include <wx/settings.h>
+#include <wx/textctrl.h>
+#include <wx/sizer.h>
+#include <wx/panel.h>
+#include <wx/bmpcbox.h>
+#include <wx/checkbox.h>
+#include <wx/statline.h>
+#include <wx/button.h>
+#include <wx/dialog.h>
+
+///////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+/// Class DIALOG_SHAPE_PROPERTIES_BASE
+///////////////////////////////////////////////////////////////////////////////
+class DIALOG_SHAPE_PROPERTIES_BASE : public DIALOG_SHIM
+{
+	DECLARE_EVENT_TABLE()
+	private:
+
+		// Private event handlers
+		void _wxFB_resetDefaults( wxCommandEvent& event ){ resetDefaults( event ); }
+
+
+	protected:
+		wxStaticText* m_lineWidthLabel;
+		wxTextCtrl* m_lineWidthCtrl;
+		wxStaticText* m_lineWidthUnits;
+		wxStaticText* m_lineColorLabel;
+		wxPanel* m_panel1;
+		COLOR_SWATCH* m_lineColorSwatch;
+		wxStaticText* m_lineStyleLabel;
+		wxBitmapComboBox* m_lineStyleCombo;
+		wxCheckBox* m_filledCtrl;
+		wxStaticText* m_fillColorLabel;
+		wxPanel* m_panel11;
+		COLOR_SWATCH* m_fillColorSwatch;
+		wxStaticText* m_helpLabel1;
+		wxStaticText* m_helpLabel2;
+		wxStaticLine* m_staticline;
+		wxStdDialogButtonSizer* m_sdbSizer;
+		wxButton* m_sdbSizerOK;
+		wxButton* m_sdbSizerApply;
+		wxButton* m_sdbSizerCancel;
+
+		// Virtual event handlers, overide them in your derived class
+		virtual void resetDefaults( wxCommandEvent& event ) { event.Skip(); }
+
+
+	public:
+
+		DIALOG_SHAPE_PROPERTIES_BASE( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("%s Properties"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( -1,-1 ), long style = wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER );
+		~DIALOG_SHAPE_PROPERTIES_BASE();
+
+};
+
diff --git a/eeschema/dialogs/panel_eeschema_color_settings.cpp b/eeschema/dialogs/panel_eeschema_color_settings.cpp
index 00fd1bff5a..e0954d380f 100644
--- a/eeschema/dialogs/panel_eeschema_color_settings.cpp
+++ b/eeschema/dialogs/panel_eeschema_color_settings.cpp
@@ -49,6 +49,7 @@
 
 std::set<int> g_excludedLayers =
         {
+            LAYER_NOTES_BACKGROUND,
             LAYER_DANGLING
         };
 
@@ -209,7 +210,6 @@ void PANEL_EESCHEMA_COLOR_SETTINGS::createSwatches()
         layers.push_back( i );
     }
 
-
     std::sort( layers.begin(), layers.end(),
                []( SCH_LAYER_ID a, SCH_LAYER_ID b )
                {
@@ -382,7 +382,7 @@ void PANEL_EESCHEMA_COLOR_SETTINGS::createPreviewItems()
 
         comp_body->SetUnit( 0 );
         comp_body->SetConvert( 0 );
-        comp_body->SetWidth( Mils2iu( 10 ) );
+        comp_body->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) );
         comp_body->SetFillMode( FILL_T::FILLED_WITH_BG_BODYCOLOR );
         comp_body->AddPoint( MILS_POINT( p.x - 200, p.y + 200 ) );
         comp_body->AddPoint( MILS_POINT( p.x + 200, p.y ) );
diff --git a/eeschema/ee_collectors.cpp b/eeschema/ee_collectors.cpp
index 9c3f5fc331..d532aac321 100644
--- a/eeschema/ee_collectors.cpp
+++ b/eeschema/ee_collectors.cpp
@@ -43,6 +43,7 @@ const KICAD_T EE_COLLECTOR::AllItems[] = {
 
 
 const KICAD_T EE_COLLECTOR::EditableItems[] = {
+    SCH_SHAPE_T,
     SCH_TEXT_T,
     SCH_LABEL_T,
     SCH_GLOBAL_LABEL_T,
@@ -80,6 +81,7 @@ const KICAD_T EE_COLLECTOR::MovableItems[] =
     SCH_BUS_WIRE_ENTRY_T,
     SCH_LINE_T,
     SCH_BITMAP_T,
+    SCH_SHAPE_T,
     SCH_TEXT_T,
     SCH_LABEL_T,
     SCH_GLOBAL_LABEL_T,
diff --git a/eeschema/lib_shape.cpp b/eeschema/lib_shape.cpp
index 9bc42a3660..506d23ace8 100644
--- a/eeschema/lib_shape.cpp
+++ b/eeschema/lib_shape.cpp
@@ -33,10 +33,9 @@
 #include <lib_shape.h>
 
 
-LIB_SHAPE::LIB_SHAPE( LIB_SYMBOL* aParent, SHAPE_T aShape, int aDefaultLineWidth,
-                      FILL_T aFillType ) :
+LIB_SHAPE::LIB_SHAPE( LIB_SYMBOL* aParent, SHAPE_T aShape, int aLineWidth, FILL_T aFillType ) :
     LIB_ITEM( LIB_SHAPE_T, aParent ),
-    EDA_SHAPE( aShape, aDefaultLineWidth, aFillType, true )
+    EDA_SHAPE( aShape, aLineWidth, aFillType, true )
 {
     m_editState = 0;
 }
@@ -260,7 +259,7 @@ void LIB_SHAPE::print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset,
             std::swap( pt1, pt2 );
     }
 
-    if( forceNoFill || GetFillType() == FILL_T::NO_FILL )
+    if( forceNoFill || GetFillMode() == FILL_T::NO_FILL )
     {
         penWidth = std::max( penWidth, aSettings->GetDefaultPenWidth() );
 
@@ -292,7 +291,7 @@ void LIB_SHAPE::print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset,
     }
     else
     {
-        if( GetFillType() == FILL_T::FILLED_WITH_BG_BODYCOLOR )
+        if( GetFillMode() == FILL_T::FILLED_WITH_BG_BODYCOLOR )
             fillColor = aSettings->GetLayerColor( LAYER_DEVICE_BACKGROUND );
 
         switch( GetShape() )
@@ -415,46 +414,20 @@ void LIB_SHAPE::AddPoint( const wxPoint& aPosition )
     }
     else
     {
-        wxFAIL_MSG( "LIB_SHAPE::AddPoint not implemented for " + SHAPE_T_asString() );
+        UNIMPLEMENTED_FOR( SHAPE_T_asString() );
     }
 }
 
 
 void LIB_SHAPE::CalcArcAngles( int& aStartAngle, int& aEndAngle ) const
 {
-    wxPoint centerStartVector = GetStart() - GetCenter();
-    wxPoint centerEndVector   = GetEnd() - GetCenter();
+    double start;
+    double end;
 
-    // Angles in Eeschema are still integers
-    aStartAngle = KiROUND( ArcTangente( centerStartVector.y, centerStartVector.x ) );
-    aEndAngle = KiROUND( ArcTangente( centerEndVector.y, centerEndVector.x ) );
+    EDA_SHAPE::CalcArcAngles( start, end );
 
-    NORMALIZE_ANGLE_POS( aStartAngle );
-    NORMALIZE_ANGLE_POS( aEndAngle );  // angles = 0 .. 3600
-
-    // Restrict angle to less than 180 to avoid PBS display mirror Trace because it is
-    // assumed that the arc is less than 180 deg to find orientation after rotate or mirror.
-    if( ( aEndAngle - aStartAngle ) > 1800 )
-        aEndAngle -= 3600;
-    else if( ( aEndAngle - aStartAngle ) <= -1800 )
-        aEndAngle += 3600;
-
-    while( ( aEndAngle - aStartAngle ) >= 1800 )
-    {
-        aEndAngle--;
-        aStartAngle++;
-    }
-
-    while( ( aStartAngle - aEndAngle ) >= 1800 )
-    {
-        aEndAngle++;
-        aStartAngle--;
-    }
-
-    NORMALIZE_ANGLE_POS( aStartAngle );
-
-    if( !IsMoving() )
-        NORMALIZE_ANGLE_POS( aEndAngle );
+    aStartAngle = KiROUND( start * 10.0 );
+    aEndAngle = KiROUND( end * 10.0 );
 }
 
 
diff --git a/eeschema/lib_shape.h b/eeschema/lib_shape.h
index faf13940d4..7f983a9d44 100644
--- a/eeschema/lib_shape.h
+++ b/eeschema/lib_shape.h
@@ -49,6 +49,9 @@ public:
         return ShowShape();
     }
 
+    STROKE_PARAMS GetStroke() const { return m_stroke; }
+    void SetStroke( const STROKE_PARAMS& aStroke ) { m_stroke = aStroke; }
+
     bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override;
     bool HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy = 0 ) const override;
 
@@ -59,7 +62,7 @@ public:
         // For historical reasons, a stored value of 0 means "default width" and negative
         // numbers meant "don't stroke".
 
-        if( GetPenWidth() < 0 && GetFillType() != FILL_T::NO_FILL )
+        if( GetPenWidth() < 0 && GetFillMode() != FILL_T::NO_FILL )
             return 0;
         else if( GetPenWidth() == 0 )
             return aSettings->GetDefaultPenWidth();
diff --git a/eeschema/lib_symbol.cpp b/eeschema/lib_symbol.cpp
index ec4b7e5aec..27dc6f234f 100644
--- a/eeschema/lib_symbol.cpp
+++ b/eeschema/lib_symbol.cpp
@@ -531,7 +531,7 @@ void LIB_SYMBOL::Print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset
                 if( aConvert && shape.m_convert && ( shape.m_convert != aConvert ) )
                     continue;
 
-                if( shape.GetFillType() == FILL_T::FILLED_WITH_BG_BODYCOLOR )
+                if( shape.GetFillMode() == FILL_T::FILLED_WITH_BG_BODYCOLOR )
                     shape.Print( aSettings, aOffset, (void*) false, aOpts.transform );
             }
         }
@@ -568,7 +568,7 @@ void LIB_SYMBOL::Print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset
         else if( item.Type() == LIB_SHAPE_T )
         {
             LIB_SHAPE& shape = static_cast<LIB_SHAPE&>( item );
-            bool       forceNoFill = shape.GetFillType() == FILL_T::FILLED_WITH_BG_BODYCOLOR;
+            bool       forceNoFill = shape.GetFillMode() == FILL_T::FILLED_WITH_BG_BODYCOLOR;
 
             shape.Print( aSettings, aOffset, (void*) forceNoFill, aOpts.transform );
         }
@@ -603,7 +603,7 @@ void LIB_SYMBOL::Plot( PLOTTER* aPlotter, int aUnit, int aConvert, const wxPoint
         if( aConvert && shape.m_convert && ( shape.m_convert != aConvert ) )
             continue;
 
-        if( shape.GetFillType() == FILL_T::FILLED_WITH_BG_BODYCOLOR && aPlotter->GetColorMode() )
+        if( shape.GetFillMode() == FILL_T::FILLED_WITH_BG_BODYCOLOR && aPlotter->GetColorMode() )
             shape.Plot( aPlotter, aOffset, true, aTransform );
     }
 
@@ -627,7 +627,7 @@ void LIB_SYMBOL::Plot( PLOTTER* aPlotter, int aUnit, int aConvert, const wxPoint
         if( item.Type() == LIB_SHAPE_T )
         {
             const LIB_SHAPE& shape = static_cast<const LIB_SHAPE&>( item );
-            forceNoFill = shape.GetFillType() == FILL_T::FILLED_WITH_BG_BODYCOLOR;
+            forceNoFill = shape.GetFillMode() == FILL_T::FILLED_WITH_BG_BODYCOLOR;
         }
 
         item.Plot( aPlotter, aOffset, !forceNoFill, aTransform );
diff --git a/eeschema/menubar.cpp b/eeschema/menubar.cpp
index 3843f615e8..53859d3194 100644
--- a/eeschema/menubar.cpp
+++ b/eeschema/menubar.cpp
@@ -215,6 +215,9 @@ void SCH_EDIT_FRAME::ReCreateMenuBar()
     placeMenu->Add( EE_ACTIONS::importSheetPin );
 
     placeMenu->AppendSeparator();
+    placeMenu->Add( EE_ACTIONS::drawRectangle );
+    placeMenu->Add( EE_ACTIONS::drawCircle );
+    placeMenu->Add( EE_ACTIONS::drawArc );
     placeMenu->Add( EE_ACTIONS::drawLines );
     placeMenu->Add( EE_ACTIONS::placeSchematicText );
     placeMenu->Add( EE_ACTIONS::placeImage );
diff --git a/eeschema/sch_bus_entry.cpp b/eeschema/sch_bus_entry.cpp
index 31d461cfe4..87474bd956 100644
--- a/eeschema/sch_bus_entry.cpp
+++ b/eeschema/sch_bus_entry.cpp
@@ -26,6 +26,7 @@
 #include <bitmaps.h>
 #include <core/mirror.h>
 #include <schematic.h>
+#include <geometry/shape_segment.h>
 #include <sch_bus_entry.h>
 #include <sch_edit_frame.h>
 #include <sch_junction.h>
@@ -172,7 +173,7 @@ const EDA_RECT SCH_BUS_ENTRY_BASE::GetBoundingBox() const
 }
 
 
-COLOR4D SCH_BUS_ENTRY_BASE::GetStrokeColor() const
+COLOR4D SCH_BUS_ENTRY_BASE::GetBusEntryColor() const
 {
     if( m_stroke.GetColor() != COLOR4D::UNSPECIFIED )
     {
@@ -190,7 +191,7 @@ COLOR4D SCH_BUS_ENTRY_BASE::GetStrokeColor() const
 }
 
 
-PLOT_DASH_TYPE SCH_BUS_ENTRY_BASE::GetStrokeStyle() const
+PLOT_DASH_TYPE SCH_BUS_ENTRY_BASE::GetLineStyle() const
 {
     if( m_stroke.GetPlotStyle() != PLOT_DASH_TYPE::DEFAULT )
     {
@@ -267,57 +268,25 @@ void SCH_BUS_BUS_ENTRY::GetEndPoints( std::vector< DANGLING_END_ITEM >& aItemLis
 void SCH_BUS_ENTRY_BASE::Print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset )
 {
     wxDC*   DC = aSettings->GetPrintDC();
-    COLOR4D color = ( GetStrokeColor() == COLOR4D::UNSPECIFIED ) ?
-                    aSettings->GetLayerColor( m_layer ) : GetStrokeColor();
+    COLOR4D color = ( GetBusEntryColor() == COLOR4D::UNSPECIFIED ) ?
+                    aSettings->GetLayerColor( m_layer ) : GetBusEntryColor();
     wxPoint start = m_pos + aOffset;
     wxPoint end = GetEnd() + aOffset;
     int     penWidth = ( GetPenWidth() == 0 ) ? aSettings->GetDefaultPenWidth() : GetPenWidth();
 
-    if( GetStrokeStyle() <= PLOT_DASH_TYPE::FIRST_TYPE )
+    if( GetLineStyle() <= PLOT_DASH_TYPE::FIRST_TYPE )
     {
         GRLine( nullptr, DC, start.x, start.y, end.x, end.y, penWidth, color );
     }
     else
     {
-        EDA_RECT clip( (wxPoint) start, wxSize( end.x - start.x, end.y - start.y ) );
-        clip.Normalize();
+        SHAPE_SEGMENT segment( start, end );
 
-        double theta = atan2( end.y - start.y, end.x - start.x );
-        double strokes[] = { 1.0, dash_gap_len( penWidth ), 1.0, dash_gap_len( penWidth ) };
-
-        switch( GetStrokeStyle() )
-        {
-        default:
-        case PLOT_DASH_TYPE::DASH:
-            strokes[0] = strokes[2] = dash_mark_len( penWidth );
-            break;
-        case PLOT_DASH_TYPE::DOT:
-            strokes[0] = strokes[2] = dot_mark_len( penWidth );
-            break;
-        case PLOT_DASH_TYPE::DASHDOT:
-            strokes[0] = dash_mark_len( penWidth );
-            strokes[2] = dot_mark_len( penWidth );
-            break;
-        }
-
-        for( size_t i = 0; i < 10000; ++i )
-        {
-            // Calculations MUST be done in doubles to keep from accumulating rounding
-            // errors as we go.
-            wxPoint next( start.x + strokes[ i % 4 ] * cos( theta ),
-                          start.y + strokes[ i % 4 ] * sin( theta ) );
-
-            // Drawing each segment can be done rounded to ints.
-            wxPoint segStart( KiROUND( start.x ), KiROUND( start.y ) );
-            wxPoint segEnd( KiROUND( next.x ), KiROUND( next.y ) );
-
-            if( ClipLine( &clip, segStart.x, segStart.y, segEnd.x, segEnd.y ) )
-                break;
-            else if( i % 2 == 0 )
-                GRLine( nullptr, DC, segStart.x, segStart.y, segEnd.x, segEnd.y, penWidth, color );
-
-            start = next;
-        }
+        STROKE_PARAMS::Stroke( &segment, GetLineStyle(), penWidth, aSettings,
+                               [&]( const wxPoint& a, const wxPoint& b )
+                               {
+                                   GRLine( nullptr, DC, a.x, a.y, b.x, b.y, penWidth, color );
+                               } );
     }
 }
 
@@ -503,15 +472,15 @@ void SCH_BUS_ENTRY_BASE::Plot( PLOTTER* aPlotter ) const
 {
     auto* settings = static_cast<KIGFX::SCH_RENDER_SETTINGS*>( aPlotter->RenderSettings() );
 
-    COLOR4D color = ( GetStrokeColor() == COLOR4D::UNSPECIFIED ) ?
-                    settings->GetLayerColor( m_layer ) : GetStrokeColor();
+    COLOR4D color = ( GetBusEntryColor() == COLOR4D::UNSPECIFIED ) ?
+                    settings->GetLayerColor( m_layer ) : GetBusEntryColor();
     int     penWidth = ( GetPenWidth() == 0 ) ? settings->GetDefaultPenWidth() : GetPenWidth();
 
     penWidth = std::max( penWidth, settings->GetMinPenWidth() );
 
     aPlotter->SetCurrentLineWidth( penWidth );
     aPlotter->SetColor( color );
-    aPlotter->SetDash( GetStrokeStyle() );
+    aPlotter->SetDash( GetLineStyle() );
     aPlotter->MoveTo( m_pos );
     aPlotter->FinishTo( GetEnd() );
 }
diff --git a/eeschema/sch_bus_entry.h b/eeschema/sch_bus_entry.h
index 9f9fddf6f3..fb987daff1 100644
--- a/eeschema/sch_bus_entry.h
+++ b/eeschema/sch_bus_entry.h
@@ -22,11 +22,6 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
  */
 
-/**
- * @file sch_bus_entry.h
- *
- */
-
 #ifndef _SCH_BUS_ENTRY_H_
 #define _SCH_BUS_ENTRY_H_
 
@@ -81,11 +76,9 @@ public:
     virtual STROKE_PARAMS GetStroke() const override { return m_stroke; }
     virtual void SetStroke( const STROKE_PARAMS& aStroke ) override { m_stroke = aStroke; }
 
-    PLOT_DASH_TYPE GetStrokeStyle() const;
-    void SetStrokeStyle( PLOT_DASH_TYPE aStyle ) { m_stroke.SetPlotStyle( aStyle ); }
+    PLOT_DASH_TYPE GetLineStyle() const;
 
-    COLOR4D GetStrokeColor() const;
-    void SetStrokeColor( const COLOR4D& aColor ) { m_stroke.SetColor( aColor ); }
+    COLOR4D GetBusEntryColor() const;
 
     void SwapData( SCH_ITEM* aItem ) override;
 
diff --git a/eeschema/sch_file_versions.h b/eeschema/sch_file_versions.h
index e9b7e6a5ce..b6c3ca0049 100644
--- a/eeschema/sch_file_versions.h
+++ b/eeschema/sch_file_versions.h
@@ -66,4 +66,5 @@
 //#define SEXPR_SCHEMATIC_FILE_VERSION 20210606  // Change overbar syntax from `~...~` to `~{...}`.
 //#define SEXPR_SCHEMATIC_FILE_VERSION 20210615  // Update overbar syntax in net names.
 //#define SEXPR_SCHEMATIC_FILE_VERSION 20210621  // Update overbar syntax in bus aliases.
-#define SEXPR_SCHEMATIC_FILE_VERSION 20211123  // R/W uuids for junctions.
+//#define SEXPR_SCHEMATIC_FILE_VERSION 20211123  // R/W uuids for junctions.
+#define SEXPR_SCHEMATIC_FILE_VERSION 20220101  // Circles, arcs, rects, polys & beziers
diff --git a/eeschema/sch_item.h b/eeschema/sch_item.h
index e628e2d09c..22efeabe56 100644
--- a/eeschema/sch_item.h
+++ b/eeschema/sch_item.h
@@ -29,8 +29,7 @@
 #include <unordered_set>
 
 #include <eda_item.h>
-#include <plotters/plotter.h>      // for PLOT_DASH_TYPE definition
-
+#include <plotters/plotter.h>
 #include <default_values.h>
 #include <sch_sheet_path.h>
 #include <netclass.h>
@@ -134,44 +133,6 @@ private:
 typedef std::unordered_set<SCH_ITEM*> SCH_ITEM_SET;
 
 
-/**
- * Simple container to manage line stroke parameters.
- */
-class STROKE_PARAMS
-{
-public:
-    STROKE_PARAMS( int aWidth = Mils2iu( DEFAULT_LINE_WIDTH_MILS ),
-                   PLOT_DASH_TYPE aPlotStyle = PLOT_DASH_TYPE::DEFAULT,
-                   const COLOR4D& aColor = COLOR4D::UNSPECIFIED ) :
-            m_width( aWidth ),
-            m_plotstyle( aPlotStyle ),
-            m_color( aColor )
-    {
-    }
-
-    int GetWidth() const { return m_width; }
-    void SetWidth( int aWidth ) { m_width = aWidth; }
-
-    PLOT_DASH_TYPE GetPlotStyle() const { return m_plotstyle; }
-    void SetPlotStyle( PLOT_DASH_TYPE aPlotStyle ) { m_plotstyle = aPlotStyle; }
-
-    COLOR4D GetColor() const { return m_color; }
-    void SetColor( const COLOR4D& aColor ) { m_color = aColor; }
-
-    bool operator!=( const STROKE_PARAMS& aOther )
-    {
-        return m_width != aOther.m_width
-                || m_plotstyle != aOther.m_plotstyle
-                || m_color != aOther.m_color;
-    }
-
-private:
-    int            m_width;
-    PLOT_DASH_TYPE m_plotstyle;
-    COLOR4D        m_color;
-};
-
-
 /**
  * Base class for any item which can be embedded within the #SCHEMATIC container class,
  * and therefore instances of derived classes should only be found in EESCHEMA or other
@@ -195,6 +156,24 @@ public:
         return wxT( "SCH_ITEM" );
     }
 
+    bool IsType( const KICAD_T aScanTypes[] ) const override
+    {
+        if( EDA_ITEM::IsType( aScanTypes ) )
+            return true;
+
+        for( const KICAD_T* p = aScanTypes; *p != EOT; ++p )
+        {
+            if( *p == SCH_ITEM_LOCATE_WIRE_T && m_layer == LAYER_WIRE )
+                return true;
+            else if ( *p == SCH_ITEM_LOCATE_BUS_T && m_layer == LAYER_BUS )
+                return true;
+            else if ( *p == SCH_ITEM_LOCATE_GRAPHIC_LINE_T && m_layer == LAYER_NOTES )
+                return true;
+        }
+
+        return false;
+    }
+
     /**
      * Swap the internal data structures \a aItem with the schematic item.
      * Obviously, aItem must have the same type than me.
diff --git a/eeschema/sch_line.cpp b/eeschema/sch_line.cpp
index 64c77f4f4e..eff76343f6 100644
--- a/eeschema/sch_line.cpp
+++ b/eeschema/sch_line.cpp
@@ -26,6 +26,7 @@
 #include <core/mirror.h>
 #include <sch_painter.h>
 #include <plotters/plotter.h>
+#include <geometry/shape_segment.h>
 #include <sch_line.h>
 #include <sch_edit_frame.h>
 #include <settings/color_settings.h>
@@ -37,6 +38,7 @@
 #include <board_item.h>
 #include <advanced_config.h>
 
+
 SCH_LINE::SCH_LINE( const wxPoint& pos, int layer ) :
     SCH_ITEM( nullptr, SCH_LINE_T )
 {
@@ -382,45 +384,13 @@ void SCH_LINE::Print( const RENDER_SETTINGS* aSettings, const wxPoint& offset )
     }
     else
     {
-        EDA_RECT clip( (wxPoint) start, wxSize( end.x - start.x, end.y - start.y ) );
-        clip.Normalize();
+        SHAPE_SEGMENT segment( start, end );
 
-        double theta = atan2( end.y - start.y, end.x - start.x );
-        double strokes[] = { 1.0, dash_gap_len( penWidth ), 1.0, dash_gap_len( penWidth ) };
-
-        switch( lineStyle )
-        {
-        default:
-        case PLOT_DASH_TYPE::DASH:
-            strokes[0] = strokes[2] = dash_mark_len( penWidth );
-            break;
-        case PLOT_DASH_TYPE::DOT:
-            strokes[0] = strokes[2] = dot_mark_len( penWidth );
-            break;
-        case PLOT_DASH_TYPE::DASHDOT:
-            strokes[0] = dash_mark_len( penWidth );
-            strokes[2] = dot_mark_len( penWidth );
-            break;
-        }
-
-        for( size_t i = 0; i < 10000; ++i )
-        {
-            // Calculations MUST be done in doubles to keep from accumulating rounding
-            // errors as we go.
-            wxPoint next( start.x + strokes[ i % 4 ] * cos( theta ),
-                          start.y + strokes[ i % 4 ] * sin( theta ) );
-
-            // Drawing each segment can be done rounded to ints.
-            wxPoint segStart( KiROUND( start.x ), KiROUND( start.y ) );
-            wxPoint segEnd( KiROUND( next.x ), KiROUND( next.y ) );
-
-            if( ClipLine( &clip, segStart.x, segStart.y, segEnd.x, segEnd.y ) )
-                break;
-            else if( i % 2 == 0 )
-                GRLine( nullptr, DC, segStart.x, segStart.y, segEnd.x, segEnd.y, penWidth, color );
-
-            start = next;
-        }
+        STROKE_PARAMS::Stroke( &segment, lineStyle, penWidth, aSettings,
+                               [&]( const wxPoint& a, const wxPoint& b )
+                               {
+                                   GRLine( nullptr, DC, a.x, a.y, b.x, b.y, penWidth, color );
+                               } );
     }
 }
 
diff --git a/eeschema/sch_line.h b/eeschema/sch_line.h
index c3a90e0172..ad7a27075d 100644
--- a/eeschema/sch_line.h
+++ b/eeschema/sch_line.h
@@ -59,24 +59,6 @@ public:
         return wxT( "SCH_LINE" );
     }
 
-    bool IsType( const KICAD_T aScanTypes[] ) const override
-    {
-        if( SCH_ITEM::IsType( aScanTypes ) )
-            return true;
-
-        for( const KICAD_T* p = aScanTypes; *p != EOT; ++p )
-        {
-            if( *p == SCH_LINE_LOCATE_WIRE_T && m_layer == LAYER_WIRE )
-                return true;
-            else if ( *p == SCH_LINE_LOCATE_BUS_T && m_layer == LAYER_BUS )
-                return true;
-            else if ( *p == SCH_LINE_LOCATE_GRAPHIC_LINE_T && m_layer == LAYER_NOTES )
-                return true;
-        }
-
-        return false;
-    }
-
     bool IsEndPoint( const wxPoint& aPoint ) const
     {
         return aPoint == m_start || aPoint == m_end;
@@ -276,11 +258,11 @@ public:
 private:
     bool doIsConnected( const wxPoint& aPosition ) const override;
 
-    bool    m_startIsDangling;  ///< True if start point is not connected.
-    bool    m_endIsDangling;    ///< True if end point is not connected.
-    wxPoint m_start;            ///< Line start point
-    wxPoint m_end;              ///< Line end point
-    STROKE_PARAMS m_stroke;     ///< Line stroke properties.
+    bool          m_startIsDangling;  ///< True if start point is not connected.
+    bool          m_endIsDangling;    ///< True if end point is not connected.
+    wxPoint       m_start;            ///< Line start point
+    wxPoint       m_end;              ///< Line end point
+    STROKE_PARAMS m_stroke;           ///< Line stroke properties.
 
     // If real-time connectivity gets disabled (due to being too slow on a particular
     // design), we can no longer rely on getting the NetClass to find netclass-specific
diff --git a/eeschema/sch_painter.cpp b/eeschema/sch_painter.cpp
index d1e4e53e1d..29675eb7a0 100644
--- a/eeschema/sch_painter.cpp
+++ b/eeschema/sch_painter.cpp
@@ -27,12 +27,12 @@
 
 #include <sch_item.h>
 #include <trigo.h>
-#include <bezier_curves.h>
 #include <symbol_library.h>
 #include <connection_graph.h>
 #include <gal/graphics_abstraction_layer.h>
 #include <geometry/geometry_utils.h>
-#include <geometry/shape_line_chain.h>
+#include <geometry/shape_segment.h>
+#include <geometry/shape_simple.h>
 #include <gr_text.h>
 #include <lib_shape.h>
 #include <lib_field.h>
@@ -60,7 +60,10 @@
 #include <default_values.h>
 #include <advanced_config.h>
 #include <string_utils.h>
+#include <stroke_params.h>
 #include "sch_painter.h"
+#include "sch_shape.h"
+
 
 namespace KIGFX
 {
@@ -82,6 +85,8 @@ SCH_RENDER_SETTINGS::SCH_RENDER_SETTINGS() :
         m_JunctionSize( DEFAULT_JUNCTION_DIAM * IU_PER_MILS )
 {
     SetDefaultPenWidth( DEFAULT_LINE_WIDTH_MILS * IU_PER_MILS );
+    SetDashLengthRatio( 5 );
+    SetGapLengthRatio( 3 );
 
     m_minPenWidth = ADVANCED_CFG::GetCfg().m_MinPlotPenWidth * IU_PER_MM;
 }
@@ -216,6 +221,7 @@ bool SCH_PAINTER::Draw( const VIEW_ITEM *aItem, int aLayer )
     HANDLE_ITEM( SCH_SYMBOL_T, SCH_SYMBOL );
     HANDLE_ITEM( SCH_JUNCTION_T, SCH_JUNCTION );
     HANDLE_ITEM( SCH_LINE_T, SCH_LINE );
+    HANDLE_ITEM( SCH_SHAPE_T, SCH_SHAPE );
     HANDLE_ITEM( SCH_TEXT_T, SCH_TEXT );
     HANDLE_ITEM( SCH_LABEL_T, SCH_TEXT );
     HANDLE_ITEM( SCH_FIELD_T, SCH_FIELD );
@@ -280,7 +286,7 @@ COLOR4D SCH_PAINTER::getRenderColor( const EDA_ITEM* aItem, int aLayer, bool aDr
     }
     else if( aItem->Type() == SCH_BUS_WIRE_ENTRY_T )
     {
-        COLOR4D busEntryColor = static_cast<const SCH_BUS_WIRE_ENTRY*>( aItem )->GetStrokeColor();
+        COLOR4D busEntryColor = static_cast<const SCH_BUS_WIRE_ENTRY*>( aItem )->GetBusEntryColor();
 
         if( busEntryColor != COLOR4D::UNSPECIFIED )
             color = busEntryColor;
@@ -496,11 +502,11 @@ bool SCH_PAINTER::setDeviceColors( const LIB_ITEM* aItem, int aLayer )
         return false;
 
     case LAYER_DEVICE_BACKGROUND:
-        if( shape && shape->GetFillType() == FILL_T::FILLED_WITH_BG_BODYCOLOR )
+        if( shape && shape->GetFillMode() == FILL_T::FILLED_WITH_BG_BODYCOLOR )
         {
             COLOR4D fillColor = getRenderColor( aItem, LAYER_DEVICE_BACKGROUND, false );
 
-            m_gal->SetIsFill( shape->GetFillType() == FILL_T::FILLED_WITH_BG_BODYCOLOR );
+            m_gal->SetIsFill( shape->GetFillMode() == FILL_T::FILLED_WITH_BG_BODYCOLOR );
             m_gal->SetFillColor( fillColor );
             m_gal->SetIsStroke( false );
             return true;
@@ -509,7 +515,7 @@ bool SCH_PAINTER::setDeviceColors( const LIB_ITEM* aItem, int aLayer )
         return false;
 
     case LAYER_DEVICE:
-        m_gal->SetIsFill( shape && shape->GetFillType() == FILL_T::FILLED_SHAPE );
+        m_gal->SetIsFill( shape && shape->GetFillMode() == FILL_T::FILLED_SHAPE );
         m_gal->SetFillColor( getRenderColor( aItem, LAYER_DEVICE, false ) );
 
         if( aItem->GetPenWidth() >= 0 || !shape || !shape->IsFilled() )
@@ -597,7 +603,7 @@ void SCH_PAINTER::draw( const LIB_SHAPE *aShape, int aLayer )
             break;
 
         default:
-            wxFAIL_MSG( "SCH_PAINTER::draw not implemented for " + aShape->SHAPE_T_asString() );
+            UNIMPLEMENTED_FOR( aShape->SHAPE_T_asString() );
         }
     }
 }
@@ -640,21 +646,19 @@ void SCH_PAINTER::draw( const LIB_FIELD *aField, int aLayer )
             return;
     }
 
-    m_gal->SetLineWidth( getTextThickness( aField, drawingShadows ) );
-    m_gal->SetIsFill( false );
     m_gal->SetIsStroke( true );
+    m_gal->SetLineWidth( getTextThickness( aField, drawingShadows ) );
     m_gal->SetStrokeColor( color );
+    m_gal->SetIsFill( drawingShadows && eeconfig()->m_Selection.text_as_box );
+    m_gal->SetFillColor( color );
 
     EDA_RECT bbox = aField->GetBoundingBox();
     wxPoint  textpos = bbox.Centre();
 
     if( drawingShadows && eeconfig()->m_Selection.text_as_box )
     {
-        m_gal->SetIsFill( true );
-        m_gal->SetFillColor( color );
-        m_gal->SetLineWidth( m_gal->GetLineWidth() * 0.5 );
         bbox.RevertYAxis();
-
+        m_gal->SetLineWidth( m_gal->GetLineWidth() / 2 );
         m_gal->DrawRectangle( mapCoords( bbox.GetPosition() ), mapCoords( bbox.GetEnd() ) );
     }
     else
@@ -948,11 +952,11 @@ void SCH_PAINTER::draw( LIB_PIN *aPin, int aLayer )
     LIB_SYMBOL* libEntry = aPin->GetParent();
 
     // Draw the labels
-    if( drawingShadows
-            && ( libEntry->Type() == LIB_SYMBOL_T || libEntry->IsSelected() )
-            && !eeconfig()->m_Selection.draw_selected_children )
+
+    if( libEntry->Type() == LIB_SYMBOL_T )
     {
-        return;
+        if( drawingShadows && !eeconfig()->m_Selection.draw_selected_children )
+            return;
     }
 
     float penWidth = (float) m_schSettings.GetDefaultPenWidth();
@@ -1278,47 +1282,120 @@ void SCH_PAINTER::draw( const SCH_LINE *aLine, int aLayer )
     }
     else
     {
-        VECTOR2D start = aLine->GetStartPoint();
-        VECTOR2D end = aLine->GetEndPoint();
+        SHAPE_SEGMENT line( aLine->GetStartPoint(), aLine->GetEndPoint() );
 
-        EDA_RECT clip( (wxPoint)start, wxSize( end.x - start.x, end.y - start.y ) );
-        clip.Normalize();
+        STROKE_PARAMS::Stroke( &line, lineStyle, width, &m_schSettings,
+                               [&]( const wxPoint& a, const wxPoint& b )
+                               {
+                                   m_gal->DrawLine( a, b );
+                               } );
+    }
+}
 
-        double theta = atan2( end.y - start.y, end.x - start.x );
-        double strokes[] = { 1.0, dash_gap_len( width ), 1.0, dash_gap_len( width ) };
 
-        switch( lineStyle )
+void SCH_PAINTER::draw( const SCH_SHAPE* aShape, int aLayer )
+{
+    bool           drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
+    PLOT_DASH_TYPE lineStyle = aShape->GetEffectiveLineStyle();
+
+    if( drawingShadows && !aShape->IsSelected() )
+        return;
+
+    auto drawShape =
+            [&]( const SCH_SHAPE* shape )
+            {
+                switch( shape->GetShape() )
+                {
+                case SHAPE_T::ARC:
+                {
+                    int startAngle;
+                    int endAngle;
+                    aShape->CalcArcAngles( startAngle, endAngle );
+
+                    m_gal->DrawArc( aShape->GetCenter(), aShape->GetRadius(),
+                                    DECIDEG2RAD( startAngle ), DECIDEG2RAD( endAngle ) );
+                }
+                    break;
+
+                case SHAPE_T::CIRCLE:
+                    m_gal->DrawCircle( shape->GetPosition(), shape->GetRadius() );
+                    break;
+
+                case SHAPE_T::RECT:
+                    m_gal->DrawRectangle( shape->GetPosition(), shape->GetEnd() );
+                    break;
+
+                case SHAPE_T::POLY:
+                {
+                    std::deque<VECTOR2D> pts;
+
+                    for( const VECTOR2I& pt : shape->GetPolyShape().Outline( 0 ).CPoints() )
+                        pts.push_back( pt );
+
+                    m_gal->DrawPolygon( pts );
+                }
+                    break;
+
+                case SHAPE_T::BEZIER:
+                {
+                    std::deque<VECTOR2D> pts;
+
+                    for( const VECTOR2I &p : shape->GetPolyShape().Outline( 0 ).CPoints() )
+                        pts.push_back( p );
+
+                    m_gal->DrawPolygon( pts );
+                }
+                    break;
+
+                default:
+                    UNIMPLEMENTED_FOR( shape->SHAPE_T_asString() );
+                }
+            };
+
+    if( aLayer == LAYER_SELECTION_SHADOWS && eeconfig()->m_Selection.fill_shapes )
+    {
+        m_gal->SetIsFill( true );
+        m_gal->SetIsStroke( false );
+        m_gal->SetFillColor( getRenderColor( aShape, aLayer, drawingShadows ) );
+
+        drawShape( aShape );
+    }
+    else if( aLayer == LAYER_NOTES_BACKGROUND && aShape->IsFilled() )
+    {
+        m_gal->SetIsFill( true );
+        m_gal->SetIsStroke( false );
+        m_gal->SetFillColor( aShape->GetFillColor() );
+
+        drawShape( aShape );
+    }
+    else if( aLayer == LAYER_NOTES )
+    {
+        int lineWidth =  getLineWidth( aShape, drawingShadows );
+
+        m_gal->SetIsFill( false );
+        m_gal->SetIsStroke( true );
+        m_gal->SetLineWidth( lineWidth );
+        m_gal->SetStrokeColor( getRenderColor( aShape, aLayer, drawingShadows ) );
+
+        if( lineStyle <= PLOT_DASH_TYPE::FIRST_TYPE || drawingShadows )
         {
-        default:
-        case PLOT_DASH_TYPE::DASH:
-            strokes[0] = strokes[2] = dash_mark_len( width );
-            break;
-        case PLOT_DASH_TYPE::DOT:
-            strokes[0] = strokes[2] = dot_mark_len( width );
-            break;
-        case PLOT_DASH_TYPE::DASHDOT:
-            strokes[0] = dash_mark_len( width );
-            strokes[2] = dot_mark_len( width );
-            break;
+            drawShape( aShape );
         }
-
-        for( size_t i = 0; i < 10000; ++i )
+        else
         {
-            // Calculations MUST be done in doubles to keep from accumulating rounding
-            // errors as we go.
-            VECTOR2D next( start.x + strokes[ i % 4 ] * cos( theta ),
-                           start.y + strokes[ i % 4 ] * sin( theta ) );
+            std::vector<SHAPE*> shapes = aShape->MakeEffectiveShapes( true );
 
-            // Drawing each segment can be done rounded to ints.
-            wxPoint segStart( KiROUND( start.x ), KiROUND( start.y ) );
-            wxPoint segEnd( KiROUND( next.x ), KiROUND( next.y ) );
+            for( SHAPE* shape : shapes )
+            {
+                STROKE_PARAMS::Stroke( shape, lineStyle, lineWidth, &m_schSettings,
+                                       [&]( const wxPoint& a, const wxPoint& b )
+                                       {
+                                           m_gal->DrawLine( a, b );
+                                       } );
+            }
 
-            if( ClipLine( &clip, segStart.x, segStart.y, segEnd.x, segEnd.y ) )
-                break;
-            else if( i % 2 == 0 )
-                m_gal->DrawLine( segStart, segEnd );
-
-            start = next;
+            for( SHAPE* shape : shapes )
+                delete shape;
         }
     }
 }
@@ -1373,10 +1450,11 @@ void SCH_PAINTER::draw( const SCH_TEXT *aText, int aLayer )
         return;
     }
 
-    m_gal->SetIsFill( false );
     m_gal->SetIsStroke( true );
     m_gal->SetLineWidth( getTextThickness( aText, drawingShadows ) );
     m_gal->SetStrokeColor( color );
+    m_gal->SetIsFill( drawingShadows && eeconfig()->m_Selection.text_as_box );
+    m_gal->SetFillColor( color );
 
     VECTOR2D text_offset = aText->GetTextPos() + aText->GetSchematicTextOffset( &m_schSettings );
     wxString shownText( aText->GetShownText() );
@@ -1386,22 +1464,19 @@ void SCH_PAINTER::draw( const SCH_TEXT *aText, int aLayer )
         if( eeconfig()->m_Selection.text_as_box )
         {
             EDA_RECT bBox = aText->GetBoundingBox();
-
-            m_gal->SetIsFill( true );
-            m_gal->SetFillColor( color );
-            m_gal->SetLineWidth( m_gal->GetLineWidth() * 0.5 );
             bBox.RevertYAxis();
-
             m_gal->DrawRectangle( mapCoords( bBox.GetPosition() ), mapCoords( bBox.GetEnd() ) );
             return;
         }
 
+        float shadowWidth = getShadowWidth();
+
         switch( aText->GetLabelSpinStyle() )
         {
-        case LABEL_SPIN_STYLE::LEFT:   text_offset.x += getShadowWidth() / 2; break;
-        case LABEL_SPIN_STYLE::UP:     text_offset.y += getShadowWidth() / 2; break;
-        case LABEL_SPIN_STYLE::RIGHT:  text_offset.x -= getShadowWidth() / 2; break;
-        case LABEL_SPIN_STYLE::BOTTOM: text_offset.y -= getShadowWidth() / 2; break;
+        case LABEL_SPIN_STYLE::LEFT:   text_offset.x += shadowWidth / 2.0; break;
+        case LABEL_SPIN_STYLE::UP:     text_offset.y += shadowWidth / 2.0; break;
+        case LABEL_SPIN_STYLE::RIGHT:  text_offset.x -= shadowWidth / 2.0; break;
+        case LABEL_SPIN_STYLE::BOTTOM: text_offset.y -= shadowWidth / 2.0; break;
         }
     }
 
@@ -1538,11 +1613,8 @@ void SCH_PAINTER::draw( const SCH_FIELD *aField, int aLayer )
     if( aField->IsVoid() )
         return;
 
-    if( drawingShadows && aField->GetParent()->IsSelected()
-            && !eeconfig()->m_Selection.draw_selected_children )
-    {
+    if( drawingShadows && !eeconfig()->m_Selection.draw_selected_children )
         return;
-    }
 
     bool underline = false;
 
@@ -1581,16 +1653,16 @@ void SCH_PAINTER::draw( const SCH_FIELD *aField, int aLayer )
     EDA_RECT bbox = aField->GetBoundingBox();
     wxPoint  textpos = bbox.Centre();
 
-    m_gal->SetStrokeColor( color );
     m_gal->SetIsStroke( true );
+    m_gal->SetLineWidth( getTextThickness( aField, drawingShadows ) );
+    m_gal->SetStrokeColor( color );
+    m_gal->SetIsFill( drawingShadows && eeconfig()->m_Selection.text_as_box );
+    m_gal->SetFillColor( color );
 
     if( drawingShadows && eeconfig()->m_Selection.text_as_box )
     {
-        m_gal->SetIsFill( true );
-        m_gal->SetFillColor( color );
-        m_gal->SetLineWidth( m_gal->GetLineWidth() * 0.5 );
         bbox.RevertYAxis();
-
+        m_gal->SetLineWidth( m_gal->GetLineWidth() / 2 );
         m_gal->DrawRectangle( mapCoords( bbox.GetPosition() ), mapCoords( bbox.GetEnd() ) );
     }
     else
@@ -1603,7 +1675,6 @@ void SCH_PAINTER::draw( const SCH_FIELD *aField, int aLayer )
         m_gal->SetFontItalic( aField->IsItalic() );
         m_gal->SetFontUnderlined( underline );
         m_gal->SetTextMirrored( aField->IsMirrored() );
-        m_gal->SetLineWidth( getTextThickness( aField, drawingShadows ) );
 
         strokeText( aField->GetShownText(), textpos, orient == TEXT_ANGLE_VERT ? M_PI / 2 : 0 );
     }
@@ -1624,38 +1695,36 @@ void SCH_PAINTER::draw( SCH_GLOBALLABEL *aLabel, int aLayer )
 {
     bool drawingShadows = aLayer == LAYER_SELECTION_SHADOWS;
 
-    if( !drawingShadows || aLabel->IsSelected() )
-    {
-        COLOR4D color = getRenderColor( aLabel, LAYER_GLOBLABEL, drawingShadows );
-
-        std::vector<wxPoint> pts;
-        std::deque<VECTOR2D> pts2;
-
-        aLabel->CreateGraphicShape( &m_schSettings, pts, aLabel->GetTextPos() );
-
-        for( const wxPoint& p : pts )
-            pts2.emplace_back( VECTOR2D( p.x, p.y ) );
-
-        // The text is drawn inside the graphic shape.
-        // On Cairo the graphic shape is filled by the background before drawing the text.
-        // However if the text is selected, it is draw twice: first on LAYER_SELECTION_SHADOWS
-        // and second on the text layer.  The second must not erase the first drawing.
-        bool fillBg = ( ( aLayer == LAYER_SELECTION_SHADOWS ) || !aLabel->IsSelected() )
-                       && aLayer != LAYER_DANGLING;
-        m_gal->SetIsFill( fillBg );
-        m_gal->SetFillColor( m_schSettings.GetLayerColor( LAYER_SCHEMATIC_BACKGROUND ) );
-        m_gal->SetIsStroke( true );
-        m_gal->SetLineWidth( getTextThickness( aLabel, drawingShadows ) );
-        m_gal->SetStrokeColor( color );
-        m_gal->DrawPolyline( pts2 );
-
-        draw( static_cast<SCH_TEXT*>( aLabel ), aLayer );
-    }
-
-    if( !drawingShadows || eeconfig()->m_Selection.draw_selected_children || !aLabel->IsSelected() )
-    {
+    if( !drawingShadows || eeconfig()->m_Selection.draw_selected_children )
         draw( aLabel->GetIntersheetRefs(), aLayer );
-    }
+
+    if( drawingShadows && !( aLabel->IsBrightened() || aLabel->IsSelected() ) )
+        return;
+
+    COLOR4D color = getRenderColor( aLabel, LAYER_GLOBLABEL, drawingShadows );
+
+    std::vector<wxPoint> pts;
+    std::deque<VECTOR2D> pts2;
+
+    aLabel->CreateGraphicShape( &m_schSettings, pts, aLabel->GetTextPos() );
+
+    for( const wxPoint& p : pts )
+        pts2.emplace_back( VECTOR2D( p.x, p.y ) );
+
+    // The text is drawn inside the graphic shape.
+    // On Cairo the graphic shape is filled by the background before drawing the text.
+    // However if the text is selected, it is draw twice: first on LAYER_SELECTION_SHADOWS
+    // and second on the text layer.  The second must not erase the first drawing.
+    bool fillBg = ( ( aLayer == LAYER_SELECTION_SHADOWS ) || !aLabel->IsSelected() )
+                   && aLayer != LAYER_DANGLING;
+    m_gal->SetIsFill( fillBg );
+    m_gal->SetFillColor( m_schSettings.GetLayerColor( LAYER_SCHEMATIC_BACKGROUND ) );
+    m_gal->SetIsStroke( true );
+    m_gal->SetLineWidth( getTextThickness( aLabel, drawingShadows ) );
+    m_gal->SetStrokeColor( color );
+    m_gal->DrawPolyline( pts2 );
+
+    draw( static_cast<SCH_TEXT*>( aLabel ), aLayer );
 }
 
 
@@ -1833,7 +1902,7 @@ void SCH_PAINTER::draw( const SCH_BUS_ENTRY_BASE *aEntry, int aLayer )
     else
     {
         line.SetLineColor( color );
-        line.SetLineStyle( aEntry->GetStrokeStyle() );
+        line.SetLineStyle( aEntry->GetLineStyle() );
 
         draw( &line, aLayer );
     }
diff --git a/eeschema/sch_painter.h b/eeschema/sch_painter.h
index b6f850ea6d..630a2abe98 100644
--- a/eeschema/sch_painter.h
+++ b/eeschema/sch_painter.h
@@ -47,6 +47,7 @@ class SCH_HIERLABEL;
 class SCH_GLOBALLABEL;
 class SCH_SHEET;
 class SCH_SHEET_PIN;
+class SCH_SHAPE;
 class SCH_MARKER;
 class SCH_NO_CONNECT;
 class SCH_LINE;
@@ -156,6 +157,7 @@ private:
     void draw( SCH_SYMBOL* aSymbol, int aLayer );
     void draw( const SCH_JUNCTION* aJct, int aLayer );
     void draw( const SCH_FIELD* aField, int aLayer );
+    void draw( const SCH_SHAPE* shape, int aLayer );
     void draw( const SCH_TEXT* aText, int aLayer );
     void draw( SCH_HIERLABEL* aLabel, int aLayer );
     void draw( SCH_GLOBALLABEL* aLabel, int aLayer );
diff --git a/eeschema/sch_plugins/altium/sch_altium_plugin.cpp b/eeschema/sch_plugins/altium/sch_altium_plugin.cpp
index 60af738418..6b8ea6133b 100644
--- a/eeschema/sch_plugins/altium/sch_altium_plugin.cpp
+++ b/eeschema/sch_plugins/altium/sch_altium_plugin.cpp
@@ -1059,7 +1059,7 @@ void SCH_ALTIUM_PLUGIN::ParseBezier( const std::map<wxString, wxString>& aProper
                                                          symbol ) );
                 }
 
-                line->SetWidth( elem.lineWidth );
+                line->SetStroke( STROKE_PARAMS( elem.lineWidth, PLOT_DASH_TYPE::SOLID ) );
             }
             else if( i + 3 == elem.points.size() )
             {
@@ -1078,7 +1078,7 @@ void SCH_ALTIUM_PLUGIN::ParseBezier( const std::map<wxString, wxString>& aProper
                                                          symbol ) );
                 }
 
-                line->SetWidth( elem.lineWidth );
+                line->SetStroke( STROKE_PARAMS( elem.lineWidth, PLOT_DASH_TYPE::SOLID ) );
             }
             else
             {
@@ -1102,7 +1102,7 @@ void SCH_ALTIUM_PLUGIN::ParseBezier( const std::map<wxString, wxString>& aProper
                     }
                 }
 
-                bezier->SetWidth( elem.lineWidth );
+                bezier->SetStroke( STROKE_PARAMS( elem.lineWidth, PLOT_DASH_TYPE::SOLID ) );
             }
         }
     }
@@ -1163,7 +1163,7 @@ void SCH_ALTIUM_PLUGIN::ParsePolyline( const std::map<wxString, wxString>& aProp
         for( wxPoint& point : elem.points )
             line->AddPoint( GetRelativePosition( point + m_sheetOffset, symbol ) );
 
-        line->SetWidth( elem.lineWidth );
+        line->SetStroke( STROKE_PARAMS( elem.lineWidth, PLOT_DASH_TYPE::SOLID ) );
     }
 }
 
@@ -1224,7 +1224,7 @@ void SCH_ALTIUM_PLUGIN::ParsePolygon( const std::map<wxString, wxString>& aPrope
 
         line->AddPoint( GetRelativePosition( elem.points.front() + m_sheetOffset, symbol ) );
 
-        line->SetWidth( elem.lineWidth );
+        line->SetStroke( STROKE_PARAMS( elem.lineWidth, PLOT_DASH_TYPE::SOLID ) );
 
         if( !elem.isSolid )
             line->SetFillMode( FILL_T::NO_FILL );
@@ -1303,7 +1303,7 @@ void SCH_ALTIUM_PLUGIN::ParseRoundRectangle( const std::map<wxString, wxString>&
 
         rect->SetPosition( GetRelativePosition( elem.topRight + m_sheetOffset, symbol ) );
         rect->SetEnd( GetRelativePosition( elem.bottomLeft + m_sheetOffset, symbol ) );
-        rect->SetWidth( elem.lineWidth );
+        rect->SetStroke( STROKE_PARAMS( elem.lineWidth, PLOT_DASH_TYPE::SOLID ) );
 
         if( !elem.isSolid )
             rect->SetFillMode( FILL_T::NO_FILL );
@@ -1351,7 +1351,7 @@ void SCH_ALTIUM_PLUGIN::ParseArc( const std::map<wxString, wxString>& aPropertie
 
             circle->SetPosition( GetRelativePosition( elem.center + m_sheetOffset, symbol ) );
             circle->SetEnd( circle->GetPosition() + wxPoint( elem.radius, 0 ) );
-            circle->SetWidth( elem.lineWidth );
+            circle->SetStroke( STROKE_PARAMS( elem.lineWidth, PLOT_DASH_TYPE::SOLID ) );
         }
         else
         {
@@ -1371,7 +1371,7 @@ void SCH_ALTIUM_PLUGIN::ParseArc( const std::map<wxString, wxString>& aPropertie
             arcEnd += arc->GetCenter();
             arc->SetEnd( arcEnd );
 
-            arc->SetWidth( elem.lineWidth );
+            arc->SetStroke( STROKE_PARAMS( elem.lineWidth, PLOT_DASH_TYPE::SOLID ) );
         }
     }
 }
@@ -1417,7 +1417,7 @@ void SCH_ALTIUM_PLUGIN::ParseLine( const std::map<wxString, wxString>& aProperti
         line->AddPoint( GetRelativePosition( elem.point1 + m_sheetOffset, symbol ) );
         line->AddPoint( GetRelativePosition( elem.point2 + m_sheetOffset, symbol ) );
 
-        line->SetWidth( elem.lineWidth );
+        line->SetStroke( STROKE_PARAMS( elem.lineWidth, PLOT_DASH_TYPE::SOLID ) );
     }
 }
 
@@ -1487,7 +1487,7 @@ void SCH_ALTIUM_PLUGIN::ParseRectangle( const std::map<wxString, wxString>& aPro
 
         rect->SetPosition( GetRelativePosition( sheetTopRight, symbol ) );
         rect->SetEnd( GetRelativePosition( sheetBottomLeft, symbol ) );
-        rect->SetWidth( elem.lineWidth );
+        rect->SetStroke( STROKE_PARAMS( elem.lineWidth, PLOT_DASH_TYPE::SOLID ) );
 
         if( !elem.isSolid )
             rect->SetFillMode( FILL_T::NO_FILL );
@@ -1606,7 +1606,7 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S
     {
         LIB_SHAPE* line1 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
         aKsymbol->AddDrawItem( line1 );
-        line1->SetWidth( Mils2iu( 10 ) );
+        line1->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) );
         line1->AddPoint( { 0, 0 } );
         line1->AddPoint( { 0, Mils2iu( -50 ) } );
 
@@ -1614,7 +1614,7 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S
         {
             LIB_SHAPE* circle = new LIB_SHAPE( aKsymbol, SHAPE_T::CIRCLE );
             aKsymbol->AddDrawItem( circle );
-            circle->SetWidth( Mils2iu( 5 ) );
+            circle->SetStroke( STROKE_PARAMS( Mils2iu( 5 ), PLOT_DASH_TYPE::SOLID ) );
             circle->SetPosition( { Mils2iu( 0 ), Mils2iu( -75 ) } );
             circle->SetEnd( circle->GetPosition() + wxPoint( Mils2iu( 25 ), 0 ) );
         }
@@ -1622,7 +1622,7 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S
         {
             LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
             aKsymbol->AddDrawItem( line2 );
-            line2->SetWidth( Mils2iu( 10 ) );
+            line2->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) );
             line2->AddPoint( { Mils2iu( -25 ), Mils2iu( -50 ) } );
             line2->AddPoint( { Mils2iu( 25 ), Mils2iu( -50 ) } );
             line2->AddPoint( { Mils2iu( 0 ), Mils2iu( -100 ) } );
@@ -1635,13 +1635,13 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S
     {
         LIB_SHAPE* line = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
         aKsymbol->AddDrawItem( line );
-        line->SetWidth( Mils2iu( 10 ) );
+        line->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) );
         line->AddPoint( { 0, 0 } );
         line->AddPoint( { 0, Mils2iu( -72 ) } );
 
         LIB_SHAPE* bezier = new LIB_SHAPE( aKsymbol, SHAPE_T::BEZIER );
         aKsymbol->AddDrawItem( bezier );
-        bezier->SetWidth( Mils2iu( 5 ) );
+        bezier->SetStroke( STROKE_PARAMS( Mils2iu( 5 ), PLOT_DASH_TYPE::SOLID ) );
         bezier->AddPoint( { Mils2iu( 30 ), Mils2iu( -50 ) } );
         bezier->AddPoint( { Mils2iu( 30 ), Mils2iu( -87 ) } );
         bezier->AddPoint( { Mils2iu( -30 ), Mils2iu( -63 ) } );
@@ -1656,7 +1656,7 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S
     {
         LIB_SHAPE* line1 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
         aKsymbol->AddDrawItem( line1 );
-        line1->SetWidth( Mils2iu( 10 ) );
+        line1->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) );
         line1->AddPoint( { 0, 0 } );
         line1->AddPoint( { 0, Mils2iu( -100 ) } );
 
@@ -1664,25 +1664,25 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S
         {
             LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
             aKsymbol->AddDrawItem( line2 );
-            line2->SetWidth( Mils2iu( 10 ) );
+            line2->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) );
             line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -100 ) } );
             line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -100 ) } );
 
             LIB_SHAPE* line3 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
             aKsymbol->AddDrawItem( line3 );
-            line3->SetWidth( Mils2iu( 10 ) );
+            line3->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) );
             line3->AddPoint( { Mils2iu( -70 ), Mils2iu( -130 ) } );
             line3->AddPoint( { Mils2iu( 70 ), Mils2iu( -130 ) } );
 
             LIB_SHAPE* line4 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
             aKsymbol->AddDrawItem( line4 );
-            line4->SetWidth( Mils2iu( 10 ) );
+            line4->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) );
             line4->AddPoint( { Mils2iu( -40 ), Mils2iu( -160 ) } );
             line4->AddPoint( { Mils2iu( 40 ), Mils2iu( -160 ) } );
 
             LIB_SHAPE* line5 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
             aKsymbol->AddDrawItem( line5 );
-            line5->SetWidth( Mils2iu( 10 ) );
+            line5->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) );
             line5->AddPoint( { Mils2iu( -10 ), Mils2iu( -190 ) } );
             line5->AddPoint( { Mils2iu( 10 ), Mils2iu( -190 ) } );
         }
@@ -1690,7 +1690,7 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S
         {
             LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
             aKsymbol->AddDrawItem( line2 );
-            line2->SetWidth( Mils2iu( 10 ) );
+            line2->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) );
             line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -100 ) } );
             line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -100 ) } );
             line2->AddPoint( { Mils2iu( 0 ), Mils2iu( -200 ) } );
@@ -1700,7 +1700,7 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S
         {
             LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
             aKsymbol->AddDrawItem( line2 );
-            line2->SetWidth( Mils2iu( 10 ) );
+            line2->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) );
             line2->AddPoint( { Mils2iu( -150 ), Mils2iu( -200 ) } );
             line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -100 ) } );
             line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -100 ) } );
@@ -1708,7 +1708,7 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S
 
             LIB_SHAPE* line3 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
             aKsymbol->AddDrawItem( line3 );
-            line3->SetWidth( Mils2iu( 10 ) );
+            line3->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) );
             line3->AddPoint( { Mils2iu( 0 ), Mils2iu( -100 ) } );
             line3->AddPoint( { Mils2iu( -50 ), Mils2iu( -200 ) } );
         }
@@ -1716,7 +1716,7 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S
         {
             LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
             aKsymbol->AddDrawItem( line2 );
-            line2->SetWidth( Mils2iu( 10 ) );
+            line2->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) );
             line2->AddPoint( { Mils2iu( -25 ), Mils2iu( -50 ) } );
             line2->AddPoint( { Mils2iu( 0 ), Mils2iu( -100 ) } );
             line2->AddPoint( { Mils2iu( 25 ), Mils2iu( -50 ) } );
@@ -1731,25 +1731,25 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S
     {
         LIB_SHAPE* line1 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
         aKsymbol->AddDrawItem( line1 );
-        line1->SetWidth( Mils2iu( 10 ) );
+        line1->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) );
         line1->AddPoint( { 0, 0 } );
         line1->AddPoint( { 0, Mils2iu( -160 ) } );
 
         LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
         aKsymbol->AddDrawItem( line2 );
-        line2->SetWidth( Mils2iu( 10 ) );
+        line2->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) );
         line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -160 ) } );
         line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -160 ) } );
 
         LIB_SHAPE* line3 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
         aKsymbol->AddDrawItem( line3 );
-        line3->SetWidth( Mils2iu( 10 ) );
+        line3->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) );
         line3->AddPoint( { Mils2iu( -60 ), Mils2iu( -200 ) } );
         line3->AddPoint( { Mils2iu( 60 ), Mils2iu( -200 ) } );
 
         LIB_SHAPE* line4 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
         aKsymbol->AddDrawItem( line4 );
-        line4->SetWidth( Mils2iu( 10 ) );
+        line4->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) );
         line4->AddPoint( { Mils2iu( -20 ), Mils2iu( -240 ) } );
         line4->AddPoint( { Mils2iu( 20 ), Mils2iu( -240 ) } );
 
@@ -1758,7 +1758,7 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S
 
         LIB_SHAPE* circle = new LIB_SHAPE( aKsymbol, SHAPE_T::CIRCLE );
         aKsymbol->AddDrawItem( circle );
-        circle->SetWidth( Mils2iu( 10 ) );
+        circle->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) );
         circle->SetPosition( { Mils2iu( 0 ), Mils2iu( -160 ) } );
         circle->SetEnd( circle->GetPosition() + wxPoint( Mils2iu( 120 ), 0 ) );
 
@@ -1768,13 +1768,13 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S
     {
         LIB_SHAPE* line1 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
         aKsymbol->AddDrawItem( line1 );
-        line1->SetWidth( Mils2iu( 10 ) );
+        line1->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) );
         line1->AddPoint( { 0, 0 } );
         line1->AddPoint( { 0, Mils2iu( -200 ) } );
 
         LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
         aKsymbol->AddDrawItem( line2 );
-        line2->SetWidth( Mils2iu( 10 ) );
+        line2->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) );
         line2->AddPoint( { Mils2iu( -100 ), Mils2iu( -200 ) } );
         line2->AddPoint( { Mils2iu( 100 ), Mils2iu( -200 ) } );
 
@@ -1790,13 +1790,13 @@ wxPoint HelperGeneratePowerPortGraphics( LIB_SYMBOL* aKsymbol, ASCH_POWER_PORT_S
 
         LIB_SHAPE* line1 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
         aKsymbol->AddDrawItem( line1 );
-        line1->SetWidth( Mils2iu( 10 ) );
+        line1->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) );
         line1->AddPoint( { 0, 0 } );
         line1->AddPoint( { 0, Mils2iu( -100 ) } );
 
         LIB_SHAPE* line2 = new LIB_SHAPE( aKsymbol, SHAPE_T::POLY );
         aKsymbol->AddDrawItem( line2 );
-        line2->SetWidth( Mils2iu( 10 ) );
+        line2->SetStroke( STROKE_PARAMS( Mils2iu( 10 ), PLOT_DASH_TYPE::SOLID ) );
         line2->AddPoint( { Mils2iu( -50 ), Mils2iu( -100 ) } );
         line2->AddPoint( { Mils2iu( 50 ), Mils2iu( -100 ) } );
 
diff --git a/eeschema/sch_plugins/cadstar/cadstar_sch_archive_loader.cpp b/eeschema/sch_plugins/cadstar/cadstar_sch_archive_loader.cpp
index dc97f1ee1c..60b2e8601c 100644
--- a/eeschema/sch_plugins/cadstar/cadstar_sch_archive_loader.cpp
+++ b/eeschema/sch_plugins/cadstar/cadstar_sch_archive_loader.cpp
@@ -1682,7 +1682,7 @@ void CADSTAR_SCH_ARCHIVE_LOADER::loadLibrarySymbolShapeVertices( const std::vect
         }
 
         shape->SetUnit( aGateNumber );
-        shape->SetWidth( aLineThickness );
+        shape->SetStroke( STROKE_PARAMS( aLineThickness, PLOT_DASH_TYPE::SOLID ) );
         aSymbol->AddDrawItem( shape );
 
         prev = cur;
diff --git a/eeschema/sch_plugins/eagle/sch_eagle_plugin.cpp b/eeschema/sch_plugins/eagle/sch_eagle_plugin.cpp
index a964c2e22c..689ec8694e 100644
--- a/eeschema/sch_plugins/eagle/sch_eagle_plugin.cpp
+++ b/eeschema/sch_plugins/eagle/sch_eagle_plugin.cpp
@@ -33,11 +33,11 @@
 #include <wx/tokenzr.h>
 #include <wx/wfstream.h>
 #include <wx/xml/xml.h>
-#include <wx/msgdlg.h>
 
 #include <symbol_library.h>
 #include <plugins/eagle/eagle_parser.h>
 #include <string_utils.h>
+#include <gr_text.h>
 #include <lib_shape.h>
 #include <lib_id.h>
 #include <lib_item.h>
@@ -1755,7 +1755,7 @@ LIB_SHAPE* SCH_EAGLE_PLUGIN::loadSymbolCircle( std::unique_ptr<LIB_SYMBOL>& aSym
 
     circle->SetPosition( center );
     circle->SetEnd( wxPoint( center.x + c.radius.ToSchUnits(), center.y ) );
-    circle->SetWidth( c.width.ToSchUnits() );
+    circle->SetStroke( STROKE_PARAMS( c.width.ToSchUnits(), PLOT_DASH_TYPE::SOLID ) );
     circle->SetUnit( aGateNumber );
 
     return circle;
@@ -1823,12 +1823,12 @@ LIB_ITEM* SCH_EAGLE_PLUGIN::loadSymbolWire( std::unique_ptr<LIB_SYMBOL>& aSymbol
                                 + ( ( center.y - begin.y ) * ( center.y - begin.y ) ) ) )
                      * 2;
 
-            arc->SetWidth( 1 );
+            arc->SetStroke( STROKE_PARAMS( 1, PLOT_DASH_TYPE::SOLID ) );
             arc->SetFillMode( FILL_T::FILLED_SHAPE );
         }
         else
         {
-            arc->SetWidth( ewire.width.ToSchUnits() );
+            arc->SetStroke( STROKE_PARAMS( ewire.width.ToSchUnits(), PLOT_DASH_TYPE::SOLID ) );
         }
 
         arc->SetArcGeometry( begin, (wxPoint) CalcArcMid( begin, end, center ), end );
@@ -1843,7 +1843,7 @@ LIB_ITEM* SCH_EAGLE_PLUGIN::loadSymbolWire( std::unique_ptr<LIB_SYMBOL>& aSymbol
         poly->AddPoint( begin );
         poly->AddPoint( end );
         poly->SetUnit( aGateNumber );
-        poly->SetWidth( ewire.width.ToSchUnits() );
+        poly->SetStroke( STROKE_PARAMS( ewire.width.ToSchUnits(), PLOT_DASH_TYPE::SOLID ) );
 
         return poly;
     }
diff --git a/eeschema/sch_plugins/kicad/sch_sexpr_parser.cpp b/eeschema/sch_plugins/kicad/sch_sexpr_parser.cpp
index 9e15c57f74..52a139774e 100644
--- a/eeschema/sch_plugins/kicad/sch_sexpr_parser.cpp
+++ b/eeschema/sch_plugins/kicad/sch_sexpr_parser.cpp
@@ -52,7 +52,7 @@
 #include <template_fieldnames.h>
 #include <trigo.h>
 #include <progress_reporter.h>
-
+#include <sch_shape.h>
 
 using namespace TSCHEMATIC_T;
 
@@ -489,67 +489,11 @@ int SCH_SEXPR_PARSER::parseInternalUnits( const char* aExpected )
 
 void SCH_SEXPR_PARSER::parseStroke( STROKE_PARAMS& aStroke )
 {
-    wxCHECK_RET( CurTok() == T_stroke,
-                 wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a stroke." ) );
+    STROKE_PARAMS_PARSER strokeParser( reader, IU_PER_MM );
+    strokeParser.SyncLineReaderWith( *this );
 
-    aStroke.SetWidth( Mils2iu( DEFAULT_LINE_WIDTH_MILS ) );
-    aStroke.SetPlotStyle( PLOT_DASH_TYPE::DEFAULT );
-    aStroke.SetColor( COLOR4D::UNSPECIFIED );
-
-    T token;
-
-    for( token = NextTok();  token != T_RIGHT;  token = NextTok() )
-    {
-        if( token != T_LEFT )
-            Expecting( T_LEFT );
-
-        token = NextTok();
-
-        switch( token )
-        {
-        case T_width:
-            aStroke.SetWidth( parseInternalUnits( "stroke width" ) );
-            NeedRIGHT();
-            break;
-
-        case T_type:
-        {
-            token = NextTok();
-
-            switch( token )
-            {
-            case T_dash:      aStroke.SetPlotStyle( PLOT_DASH_TYPE::DASH );      break;
-            case T_dot:       aStroke.SetPlotStyle( PLOT_DASH_TYPE::DOT );       break;
-            case T_dash_dot:  aStroke.SetPlotStyle( PLOT_DASH_TYPE::DASHDOT );   break;
-            case T_solid:     aStroke.SetPlotStyle( PLOT_DASH_TYPE::SOLID );     break;
-            case T_default:   aStroke.SetPlotStyle( PLOT_DASH_TYPE::DEFAULT );   break;
-            default:
-                Expecting( "solid, dash, dash_dot, dot or default" );
-            }
-
-            NeedRIGHT();
-            break;
-        }
-
-        case T_color:
-        {
-            COLOR4D color;
-
-            color.r = parseInt( "red" ) / 255.0;
-            color.g = parseInt( "green" ) / 255.0;
-            color.b = parseInt( "blue" ) / 255.0;
-            color.a = Clamp( parseDouble( "alpha" ), 0.0, 1.0 );
-
-            aStroke.SetColor( color );
-            NeedRIGHT();
-            break;
-        }
-
-        default:
-            Expecting( "width, type, or color" );
-        }
-
-    }
+    strokeParser.ParseStroke( aStroke );
+    SyncLineReaderWith( strokeParser );
 }
 
 
@@ -580,7 +524,8 @@ void SCH_SEXPR_PARSER::parseFill( FILL_PARAMS& aFill )
             case T_none:       aFill.m_FillType = FILL_T::NO_FILL;                  break;
             case T_outline:    aFill.m_FillType = FILL_T::FILLED_SHAPE;             break;
             case T_background: aFill.m_FillType = FILL_T::FILLED_WITH_BG_BODYCOLOR; break;
-            default:           Expecting( "none, outline, or background" );
+            case T_color:      aFill.m_FillType = FILL_T::FILLED_WITH_COLOR;        break;
+            default:           Expecting( "none, outline, color or background" );
             }
 
             NeedRIGHT();
@@ -1008,7 +953,7 @@ LIB_SHAPE* SCH_SEXPR_PARSER::parseArc()
 
         case T_stroke:
             parseStroke( stroke );
-            arc->SetWidth( stroke.GetWidth() );
+            arc->SetStroke( stroke );
             break;
 
         case T_fill:
@@ -1107,7 +1052,7 @@ LIB_SHAPE* SCH_SEXPR_PARSER::parseBezier()
 
         case T_stroke:
             parseStroke( stroke );
-            bezier->SetWidth( stroke.GetWidth() );
+            bezier->SetStroke( stroke );
             break;
 
         case T_fill:
@@ -1163,7 +1108,7 @@ LIB_SHAPE* SCH_SEXPR_PARSER::parseCircle()
 
         case T_stroke:
             parseStroke( stroke );
-            circle->SetWidth( stroke.GetWidth() );
+            circle->SetStroke( stroke );
             break;
 
         case T_fill:
@@ -1435,7 +1380,7 @@ LIB_SHAPE* SCH_SEXPR_PARSER::parsePolyLine()
 
         case T_stroke:
             parseStroke( stroke );
-            poly->SetWidth( stroke.GetWidth() );
+            poly->SetStroke( stroke );
             break;
 
         case T_fill:
@@ -1486,7 +1431,7 @@ LIB_SHAPE* SCH_SEXPR_PARSER::parseRectangle()
 
         case T_stroke:
             parseStroke( stroke );
-            rectangle->SetWidth( stroke.GetWidth() );
+            rectangle->SetStroke( stroke );
             break;
 
         case T_fill:
@@ -2170,6 +2115,22 @@ void SCH_SEXPR_PARSER::ParseSchematic( SCH_SHEET* aSheet, bool aIsCopyableOnly,
             screen->Append( static_cast<SCH_ITEM*>( parseLine() ) );
             break;
 
+        case T_arc:
+            screen->Append( static_cast<SCH_ITEM*>( parseSchArc() ) );
+            break;
+
+        case T_circle:
+            screen->Append( static_cast<SCH_ITEM*>( parseSchCircle() ) );
+            break;
+
+        case T_rectangle:
+            screen->Append( static_cast<SCH_ITEM*>( parseSchRectangle() ) );
+            break;
+
+        case T_bezier:
+            screen->Append( static_cast<SCH_ITEM*>( parseSchBezier() ) );
+            break;
+
         case T_text:
         case T_label:
         case T_global_label:
@@ -2837,6 +2798,320 @@ SCH_LINE* SCH_SEXPR_PARSER::parseLine()
 }
 
 
+SCH_SHAPE* SCH_SEXPR_PARSER::parseSchArc()
+{
+    wxCHECK_MSG( CurTok() == T_arc, nullptr,
+                 wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as an arc." ) );
+
+    T token;
+    wxPoint startPoint;
+    wxPoint midPoint;
+    wxPoint endPoint;
+    wxPoint pos;
+    int startAngle;
+    int endAngle;
+    STROKE_PARAMS stroke( Mils2iu( DEFAULT_LINE_WIDTH_MILS ), PLOT_DASH_TYPE::DEFAULT );
+    FILL_PARAMS fill;
+    bool hasMidPoint = false;
+    bool hasAngles = false;
+    std::unique_ptr<SCH_SHAPE> arc = std::make_unique<SCH_SHAPE>( SHAPE_T::ARC );
+
+    for( token = NextTok();  token != T_RIGHT;  token = NextTok() )
+    {
+        if( token != T_LEFT )
+            Expecting( T_LEFT );
+
+        token = NextTok();
+
+        switch( token )
+        {
+        case T_start:
+            startPoint = parseXY();
+            NeedRIGHT();
+            break;
+
+        case T_mid:
+            midPoint = parseXY();
+            NeedRIGHT();
+            hasMidPoint = true;
+            break;
+
+        case T_end:
+            endPoint = parseXY();
+            NeedRIGHT();
+            break;
+
+        case T_radius:
+            for( token = NextTok();  token != T_RIGHT;  token = NextTok() )
+            {
+                if( token != T_LEFT )
+                    Expecting( T_LEFT );
+
+                token = NextTok();
+
+                switch( token )
+                {
+                case T_at:
+                    pos = parseXY();
+                    NeedRIGHT();
+                    break;
+
+                case T_length:
+                    parseInternalUnits( "radius length" );
+                    NeedRIGHT();
+                    break;
+
+                case T_angles:
+                {
+                    startAngle = KiROUND( parseDouble( "start radius angle" ) * 10.0 );
+                    endAngle = KiROUND( parseDouble( "end radius angle" ) * 10.0 );
+                    NORMALIZE_ANGLE_POS( startAngle );
+                    NORMALIZE_ANGLE_POS( endAngle );
+                    NeedRIGHT();
+                    hasAngles = true;
+                    break;
+                }
+
+                default:
+                    Expecting( "at, length, or angle" );
+                }
+            }
+
+            break;
+
+        case T_stroke:
+            parseStroke( stroke );
+            arc->SetStroke( stroke );
+            break;
+
+        case T_fill:
+            parseFill( fill );
+            arc->SetFillMode( fill.m_FillType );
+            arc->SetFillColor( fill.m_Color );
+            break;
+
+        case T_uuid:
+            NeedSYMBOL();
+            const_cast<KIID&>( arc->m_Uuid ) = KIID( FromUTF8() );
+            NeedRIGHT();
+            break;
+
+        default:
+            Expecting( "start, mid, end, radius, stroke, fill or uuid" );
+        }
+    }
+
+    arc->SetStart( startPoint );
+    arc->SetEnd( endPoint );
+
+    if( hasMidPoint )
+    {
+        VECTOR2I center = CalcArcCenter( arc->GetStart(), midPoint, arc->GetEnd() );
+
+        arc->SetCenter( (wxPoint) center );
+    }
+    else if( hasAngles )
+    {
+        arc->SetCenter( pos );
+        /**
+         * This accounts for an oddity in the old library format, where the symbol is overdefined.
+         * The previous draw (based on wxwidgets) used start point and end point and always drew
+         * counter-clockwise.  The new GAL draw takes center, radius and start/end angles.  All of
+         * these points were stored in the file, so we need to mimic the swapping of start/end
+         * points rather than using the stored angles in order to properly map edge cases.
+         */
+        if( !TRANSFORM().MapAngles( &startAngle, &endAngle ) )
+        {
+            wxPoint temp = arc->GetStart();
+            arc->SetStart( arc->GetEnd() );
+            arc->SetEnd( temp );
+        }
+    }
+    else
+        wxFAIL_MSG( "Setting arc without either midpoint or angles not implemented." );
+
+    return arc.release();
+}
+
+
+SCH_SHAPE* SCH_SEXPR_PARSER::parseSchCircle()
+{
+    wxCHECK_MSG( CurTok() == T_circle, nullptr,
+                 wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a circle." ) );
+
+    T token;
+    wxPoint center;
+    int radius;
+    STROKE_PARAMS stroke( Mils2iu( DEFAULT_LINE_WIDTH_MILS ), PLOT_DASH_TYPE::DEFAULT );
+    FILL_PARAMS fill;
+    std::unique_ptr<SCH_SHAPE> circle = std::make_unique<SCH_SHAPE>( SHAPE_T::CIRCLE );
+
+    for( token = NextTok();  token != T_RIGHT;  token = NextTok() )
+    {
+        if( token != T_LEFT )
+            Expecting( T_LEFT );
+
+        token = NextTok();
+
+        switch( token )
+        {
+        case T_center:
+            center = parseXY();
+            NeedRIGHT();
+            break;
+
+        case T_radius:
+            radius = parseInternalUnits( "radius length" );
+            NeedRIGHT();
+            break;
+
+        case T_stroke:
+            parseStroke( stroke );
+            circle->SetStroke( stroke );
+            break;
+
+        case T_fill:
+            parseFill( fill );
+            circle->SetFillMode( fill.m_FillType );
+            circle->SetFillColor( fill.m_Color );
+            break;
+
+        case T_uuid:
+            NeedSYMBOL();
+            const_cast<KIID&>( circle->m_Uuid ) = KIID( FromUTF8() );
+            NeedRIGHT();
+            break;
+
+        default:
+            Expecting( "center, radius, stroke, fill or uuid" );
+        }
+    }
+
+    circle->SetCenter( center );
+    circle->SetEnd( wxPoint( center.x + radius, center.y ) );
+
+    return circle.release();
+}
+
+
+SCH_SHAPE* SCH_SEXPR_PARSER::parseSchRectangle()
+{
+    wxCHECK_MSG( CurTok() == T_rectangle, nullptr,
+                 wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a rectangle." ) );
+
+    T token;
+    STROKE_PARAMS stroke( Mils2iu( DEFAULT_LINE_WIDTH_MILS ), PLOT_DASH_TYPE::DEFAULT );
+    FILL_PARAMS fill;
+    std::unique_ptr<SCH_SHAPE> rectangle = std::make_unique<SCH_SHAPE>( SHAPE_T::RECT );
+
+    for( token = NextTok();  token != T_RIGHT;  token = NextTok() )
+    {
+        if( token != T_LEFT )
+            Expecting( T_LEFT );
+
+        token = NextTok();
+
+        switch( token )
+        {
+        case T_start:
+            rectangle->SetPosition( parseXY() );
+            NeedRIGHT();
+            break;
+
+        case T_end:
+            rectangle->SetEnd( parseXY() );
+            NeedRIGHT();
+            break;
+
+        case T_stroke:
+            parseStroke( stroke );
+            rectangle->SetStroke( stroke );
+            break;
+
+        case T_fill:
+            parseFill( fill );
+            rectangle->SetFillMode( fill.m_FillType );
+            rectangle->SetFillColor( fill.m_Color );
+            break;
+
+        case T_uuid:
+            NeedSYMBOL();
+            const_cast<KIID&>( rectangle->m_Uuid ) = KIID( FromUTF8() );
+            NeedRIGHT();
+            break;
+
+        default:
+            Expecting( "start, end, stroke, fill or uuid" );
+        }
+    }
+
+    return rectangle.release();
+}
+
+
+SCH_SHAPE* SCH_SEXPR_PARSER::parseSchBezier()
+{
+    wxCHECK_MSG( CurTok() == T_bezier, nullptr,
+                 wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a bezier." ) );
+
+    T token;
+    STROKE_PARAMS stroke( Mils2iu( DEFAULT_LINE_WIDTH_MILS ), PLOT_DASH_TYPE::DEFAULT );
+    FILL_PARAMS fill;
+    std::unique_ptr<SCH_SHAPE> bezier = std::make_unique<SCH_SHAPE>( SHAPE_T::BEZIER );
+
+    for( token = NextTok();  token != T_RIGHT;  token = NextTok() )
+    {
+        if( token != T_LEFT )
+            Expecting( T_LEFT );
+
+        token = NextTok();
+
+        switch( token )
+        {
+        case T_pts:
+            for( token = NextTok();  token != T_RIGHT;  token = NextTok() )
+            {
+                if( token != T_LEFT )
+                    Expecting( T_LEFT );
+
+                token = NextTok();
+
+                if( token != T_xy )
+                    Expecting( "xy" );
+
+                bezier->AddPoint( parseXY() );
+
+                NeedRIGHT();
+            }
+
+            break;
+
+        case T_stroke:
+            parseStroke( stroke );
+            bezier->SetStroke( stroke );
+            break;
+
+        case T_fill:
+            parseFill( fill );
+            bezier->SetFillMode( fill.m_FillType );
+            bezier->SetFillColor( fill.m_Color );
+            break;
+
+        case T_uuid:
+            NeedSYMBOL();
+            const_cast<KIID&>( bezier->m_Uuid ) = KIID( FromUTF8() );
+            NeedRIGHT();
+            break;
+
+        default:
+            Expecting( "pts, stroke, fill or uuid" );
+        }
+    }
+
+    return bezier.release();
+}
+
+
 SCH_TEXT* SCH_SEXPR_PARSER::parseSchText()
 {
     T token;
diff --git a/eeschema/sch_plugins/kicad/sch_sexpr_parser.h b/eeschema/sch_plugins/kicad/sch_sexpr_parser.h
index 0cd7239430..52f521f3c2 100644
--- a/eeschema/sch_plugins/kicad/sch_sexpr_parser.h
+++ b/eeschema/sch_plugins/kicad/sch_sexpr_parser.h
@@ -49,6 +49,7 @@ class SCH_BITMAP;
 class SCH_BUS_WIRE_ENTRY;
 class SCH_SYMBOL;
 class SCH_FIELD;
+class SCH_SHAPE;
 class SCH_JUNCTION;
 class SCH_LINE;
 class SCH_NO_CONNECT;
@@ -188,6 +189,10 @@ class SCH_SEXPR_PARSER : public SCHEMATIC_LEXER
     SCH_NO_CONNECT* parseNoConnect();
     SCH_BUS_WIRE_ENTRY* parseBusEntry();
     SCH_LINE* parseLine();
+    SCH_SHAPE* parseSchArc();
+    SCH_SHAPE* parseSchCircle();
+    SCH_SHAPE* parseSchRectangle();
+    SCH_SHAPE* parseSchBezier();
     SCH_TEXT* parseSchText();
     void parseBusAlias( SCH_SCREEN* aScreen );
 
diff --git a/eeschema/sch_plugins/kicad/sch_sexpr_plugin.cpp b/eeschema/sch_plugins/kicad/sch_sexpr_plugin.cpp
index 7fecb12a93..cfa24bc9b3 100644
--- a/eeschema/sch_plugins/kicad/sch_sexpr_plugin.cpp
+++ b/eeschema/sch_plugins/kicad/sch_sexpr_plugin.cpp
@@ -37,6 +37,7 @@
 #include <sch_edit_frame.h>       // SYMBOL_ORIENTATION_T
 #include <sch_junction.h>
 #include <sch_line.h>
+#include <sch_shape.h>
 #include <sch_no_connect.h>
 #include <sch_text.h>
 #include <sch_sheet.h>
@@ -59,7 +60,6 @@
 #include <wx_filename.h>       // for ::ResolvePossibleSymlinks()
 #include <progress_reporter.h>
 
-
 using namespace TSCHEMATIC_T;
 
 
@@ -80,13 +80,26 @@ static void formatFill( OUTPUTFORMATTER* aFormatter, int aNestLevel, FILL_T aFil
 
     switch( aFillMode )
     {
-    default:
     case FILL_T::NO_FILL:                  fillType = "none";       break;
     case FILL_T::FILLED_SHAPE:             fillType = "outline";    break;
     case FILL_T::FILLED_WITH_BG_BODYCOLOR: fillType = "background"; break;
+    case FILL_T::FILLED_WITH_COLOR:        fillType = "color";      break;
     }
 
-    aFormatter->Print( aNestLevel, "(fill (type %s))", fillType );
+    if( aFillMode == FILL_T::FILLED_WITH_COLOR )
+    {
+        aFormatter->Print( aNestLevel, "(fill (type %s) (color %d %d %d %s))",
+                           fillType,
+                           KiROUND( aFillColor.r * 255.0 ),
+                           KiROUND( aFillColor.g * 255.0 ),
+                           KiROUND( aFillColor.b * 255.0 ),
+                           Double2Str( aFillColor.a ).c_str() );
+    }
+    else
+    {
+        aFormatter->Print( aNestLevel, "(fill (type %s))",
+                           fillType );
+    }
 }
 
 
@@ -222,23 +235,6 @@ static double getSheetPinAngle( SHEET_SIDE aSide )
 }
 
 
-static wxString getLineStyleToken( PLOT_DASH_TYPE aStyle )
-{
-    wxString token;
-
-    switch( aStyle )
-    {
-    case PLOT_DASH_TYPE::DASH:     token = "dash";      break;
-    case PLOT_DASH_TYPE::DOT:      token = "dot";       break;
-    case PLOT_DASH_TYPE::DASHDOT:  token = "dash_dot";  break;
-    case PLOT_DASH_TYPE::SOLID:    token = "solid";     break;
-    case PLOT_DASH_TYPE::DEFAULT:  token = "default";   break;
-    }
-
-    return token;
-}
-
-
 static const char* getTextTypeToken( KICAD_T aType )
 {
     switch( aType )
@@ -252,28 +248,6 @@ static const char* getTextTypeToken( KICAD_T aType )
 }
 
 
-/**
- * Write stroke definition to \a aFormatter.
- *
- * @param aFormatter A pointer to the #OUTPUTFORMATTER object to write to.
- * @param aNestLevel The nest level to indent the stroke definition.
- * @param aStroke The stroke width, line-style and color.
- */
-static void formatStroke( OUTPUTFORMATTER* aFormatter, int aNestLevel,
-                          const STROKE_PARAMS& aStroke )
-{
-    wxASSERT( aFormatter != nullptr );
-
-    aFormatter->Print( aNestLevel, "(stroke (width %s) (type %s) (color %d %d %d %s))",
-                       FormatInternalUnits( aStroke.GetWidth() ).c_str(),
-                       TO_UTF8( getLineStyleToken( aStroke.GetPlotStyle() ) ),
-                       KiROUND( aStroke.GetColor().r * 255.0 ),
-                       KiROUND( aStroke.GetColor().g * 255.0 ),
-                       KiROUND( aStroke.GetColor().b * 255.0 ),
-                       Double2Str( aStroke.GetColor().a ).c_str() );
-}
-
-
 static void formatArc( OUTPUTFORMATTER* aFormatter, int aNestLevel, EDA_SHAPE* aArc, int x1, int x2,
                        const STROKE_PARAMS& aStroke, FILL_T aFillMode, const COLOR4D& aFillColor,
                        KIID aUuid = niluuid )
@@ -289,7 +263,7 @@ static void formatArc( OUTPUTFORMATTER* aFormatter, int aNestLevel, EDA_SHAPE* a
                        FormatInternalUnits( aArc->GetArcMid() ).c_str(),
                        FormatInternalUnits( aArc->GetEnd() ).c_str() );
 
-    formatStroke( aFormatter, aNestLevel + 1, aStroke );
+    aStroke.Format( aFormatter, aNestLevel + 1 );
     aFormatter->Print( 0, "\n" );
     formatFill( aFormatter, aNestLevel + 1, aFillMode, aFillColor );
     aFormatter->Print( 0, "\n" );
@@ -310,7 +284,7 @@ static void formatCircle( OUTPUTFORMATTER* aFormatter, int aNestLevel, EDA_SHAPE
                        FormatInternalUnits( aCircle->GetStart().y ).c_str(),
                        FormatInternalUnits( aCircle->GetRadius() ).c_str() );
 
-    formatStroke( aFormatter, aNestLevel + 1, aStroke );
+    aStroke.Format( aFormatter, aNestLevel + 1 );
     aFormatter->Print( 0, "\n" );
     formatFill( aFormatter, aNestLevel + 1, aFillMode, aFillColor );
     aFormatter->Print( 0, "\n" );
@@ -331,7 +305,7 @@ static void formatRect( OUTPUTFORMATTER* aFormatter, int aNestLevel, EDA_SHAPE*
                        FormatInternalUnits( aRect->GetStart().y ).c_str(),
                        FormatInternalUnits( aRect->GetEnd().x ).c_str(),
                        FormatInternalUnits( aRect->GetEnd().y ).c_str() );
-    formatStroke( aFormatter, aNestLevel + 1, aStroke );
+    aStroke.Format( aFormatter, aNestLevel + 1 );
     aFormatter->Print( 0, "\n" );
     formatFill( aFormatter, aNestLevel + 1, aFillMode, aFillColor );
     aFormatter->Print( 0, "\n" );
@@ -359,7 +333,7 @@ static void formatBezier( OUTPUTFORMATTER* aFormatter, int aNestLevel, EDA_SHAPE
 
     aFormatter->Print( 0, ")\n" );  // Closes pts token on same line.
 
-    formatStroke( aFormatter, aNestLevel + 1, aStroke );
+    aStroke.Format( aFormatter, aNestLevel + 1 );
     aFormatter->Print( 0, "\n" );
     formatFill( aFormatter, aNestLevel + 1, aFillMode, aFillColor );
     aFormatter->Print( 0, "\n" );
@@ -411,7 +385,7 @@ static void formatPoly( OUTPUTFORMATTER* aFormatter, int aNestLevel, EDA_SHAPE*
         aFormatter->Print( aNestLevel + 1, ")\n" );  // Closes pts token with multiple lines.
     }
 
-    formatStroke( aFormatter, aNestLevel + 1, aStroke );
+    aStroke.Format( aFormatter, aNestLevel + 1 );
     aFormatter->Print( 0, "\n" );
     formatFill( aFormatter, aNestLevel + 1, aFillMode, aFillColor );
     aFormatter->Print( 0, "\n" );
@@ -840,6 +814,10 @@ void SCH_SEXPR_PLUGIN::Format( SCH_SHEET* aSheet )
             saveLine( static_cast<SCH_LINE*>( item ), 1 );
             break;
 
+        case SCH_SHAPE_T:
+            saveShape( static_cast<SCH_SHAPE*>( item ), 1 );
+            break;
+
         case SCH_TEXT_T:
         case SCH_LABEL_T:
         case SCH_GLOBAL_LABEL_T:
@@ -981,6 +959,10 @@ void SCH_SEXPR_PLUGIN::Format( EE_SELECTION* aSelection, SCH_SHEET_PATH* aSelect
             saveLine( static_cast< SCH_LINE* >( item ), 0 );
             break;
 
+        case SCH_SHAPE_T:
+            saveShape( static_cast<SCH_SHAPE*>( item ), 0 );
+            break;
+
         case SCH_TEXT_T:
         case SCH_LABEL_T:
         case SCH_GLOBAL_LABEL_T:
@@ -1252,7 +1234,7 @@ void SCH_SEXPR_PLUGIN::saveSheet( SCH_SHEET* aSheet, int aNestLevel )
                           aSheet->GetBorderColor() );
 
     stroke.SetWidth( aSheet->GetBorderWidth() );
-    formatStroke( m_out, aNestLevel + 1, stroke );
+    stroke.Format( m_out, aNestLevel + 1 );
 
     m_out->Print( 0, "\n" );
 
@@ -1341,7 +1323,7 @@ void SCH_SEXPR_PLUGIN::saveBusEntry( SCH_BUS_ENTRY_BASE* aBusEntry, int aNestLev
                       FormatInternalUnits( aBusEntry->GetSize().GetWidth() ).c_str(),
                       FormatInternalUnits( aBusEntry->GetSize().GetHeight() ).c_str() );
 
-        formatStroke( m_out, aNestLevel + 1, aBusEntry->GetStroke() );
+        aBusEntry->GetStroke().Format( m_out, aNestLevel + 1 );
 
         m_out->Print( 0, "\n" );
 
@@ -1352,6 +1334,50 @@ void SCH_SEXPR_PLUGIN::saveBusEntry( SCH_BUS_ENTRY_BASE* aBusEntry, int aNestLev
 }
 
 
+void SCH_SEXPR_PLUGIN::saveShape( SCH_SHAPE* aShape, int aNestLevel )
+{
+    wxCHECK_RET( aShape != nullptr && m_out != nullptr, "" );
+
+    wxString lineType;
+
+    switch( aShape->GetShape() )
+    {
+    case SHAPE_T::ARC:
+        int x1;
+        int x2;
+
+        aShape->CalcArcAngles( x1, x2 );
+
+        formatArc( m_out, aNestLevel, aShape, x1, x2, aShape->GetStroke(), aShape->GetFillMode(),
+                   aShape->GetFillColor(), aShape->m_Uuid );
+        break;
+
+    case SHAPE_T::CIRCLE:
+        formatCircle( m_out, aNestLevel, aShape, aShape->GetStroke(), aShape->GetFillMode(),
+                      aShape->GetFillColor(), aShape->m_Uuid );
+        break;
+
+    case SHAPE_T::RECT:
+        formatRect( m_out, aNestLevel, aShape, aShape->GetStroke(), aShape->GetFillMode(),
+                    aShape->GetFillColor(), aShape->m_Uuid );
+        break;
+
+    case SHAPE_T::BEZIER:
+        formatBezier( m_out, aNestLevel, aShape, aShape->GetStroke(), aShape->GetFillMode(),
+                      aShape->GetFillColor(), aShape->m_Uuid );
+        break;
+
+    case SHAPE_T::POLY:
+        formatPoly( m_out, aNestLevel, aShape, aShape->GetStroke(), aShape->GetFillMode(),
+                    aShape->GetFillColor(), aShape->m_Uuid );
+        break;
+
+    default:
+        UNIMPLEMENTED_FOR( aShape->SHAPE_T_asString() );
+    }
+}
+
+
 void SCH_SEXPR_PLUGIN::saveLine( SCH_LINE* aLine, int aNestLevel )
 {
     wxCHECK_RET( aLine != nullptr && m_out != nullptr, "" );
@@ -1364,8 +1390,9 @@ void SCH_SEXPR_PLUGIN::saveLine( SCH_LINE* aLine, int aNestLevel )
     {
     case LAYER_BUS:     lineType = "bus";       break;
     case LAYER_WIRE:    lineType = "wire";      break;
-    case LAYER_NOTES:
-    default:            lineType = "polyline";  break;
+    case LAYER_NOTES:   lineType = "polyline";  break;
+    default:
+        UNIMPLEMENTED_FOR( LayerName( aLine->GetLayer() ) );
     }
 
     m_out->Print( aNestLevel, "(%s (pts (xy %s %s) (xy %s %s))\n",
@@ -1375,7 +1402,7 @@ void SCH_SEXPR_PLUGIN::saveLine( SCH_LINE* aLine, int aNestLevel )
                   FormatInternalUnits( aLine->GetEndPoint().x ).c_str(),
                   FormatInternalUnits( aLine->GetEndPoint().y ).c_str() );
 
-    formatStroke( m_out, aNestLevel + 1, line_stroke );
+    line_stroke.Format( m_out, aNestLevel + 1 );
     m_out->Print( 0, "\n" );
 
     m_out->Print( aNestLevel + 1, "(uuid %s)\n", TO_UTF8( aLine->m_Uuid.AsString() ) );
@@ -1934,7 +1961,7 @@ void SCH_SEXPR_PLUGIN_CACHE::saveSymbolDrawItem( LIB_ITEM* aItem, OUTPUTFORMATTE
     {
         LIB_SHAPE*    shape = static_cast<LIB_SHAPE*>( aItem );
         STROKE_PARAMS stroke;
-        FILL_T        fillMode = shape->GetFillType();
+        FILL_T        fillMode = shape->GetFillMode();
 
         stroke.SetWidth( shape->GetWidth() );
 
diff --git a/eeschema/sch_plugins/kicad/sch_sexpr_plugin.h b/eeschema/sch_plugins/kicad/sch_sexpr_plugin.h
index 3506d86724..8f61336012 100644
--- a/eeschema/sch_plugins/kicad/sch_sexpr_plugin.h
+++ b/eeschema/sch_plugins/kicad/sch_sexpr_plugin.h
@@ -39,6 +39,7 @@ class SCH_BITMAP;
 class SCH_JUNCTION;
 class SCH_NO_CONNECT;
 class SCH_LINE;
+class SCH_SHAPE;
 class SCH_BUS_ENTRY_BASE;
 class SCH_TEXT;
 class SCH_SYMBOL;
@@ -148,6 +149,7 @@ private:
     void saveNoConnect( SCH_NO_CONNECT* aNoConnect, int aNestLevel );
     void saveBusEntry( SCH_BUS_ENTRY_BASE* aBusEntry, int aNestLevel );
     void saveLine( SCH_LINE* aLine, int aNestLevel );
+    void saveShape( SCH_SHAPE* aShape, int aNestLevel );
     void saveText( SCH_TEXT* aText, int aNestLevel );
     void saveBusAlias( std::shared_ptr<BUS_ALIAS> aAlias, int aNestLevel );
     void saveInstances( const std::vector<SCH_SHEET_INSTANCE>&        aSheets,
diff --git a/eeschema/sch_plugins/legacy/sch_legacy_plugin.cpp b/eeschema/sch_plugins/legacy/sch_legacy_plugin.cpp
index a7f72b6513..bd423cd306 100644
--- a/eeschema/sch_plugins/legacy/sch_legacy_plugin.cpp
+++ b/eeschema/sch_plugins/legacy/sch_legacy_plugin.cpp
@@ -41,6 +41,7 @@
 #include <trigo.h>
 #include <progress_reporter.h>
 #include <general.h>
+#include <gr_text.h>
 #include <sch_bitmap.h>
 #include <sch_bus_entry.h>
 #include <sch_symbol.h>
@@ -3286,7 +3287,8 @@ LIB_SHAPE* SCH_LEGACY_PLUGIN_CACHE::loadArc( std::unique_ptr<LIB_SYMBOL>& aSymbo
 
     arc->SetUnit( parseInt( aReader, line, &line ) );
     arc->SetConvert( parseInt( aReader, line, &line ) );
-    arc->SetWidth( Mils2Iu( parseInt( aReader, line, &line ) ) );
+    arc->SetStroke( STROKE_PARAMS( Mils2Iu( parseInt( aReader, line, &line ) ),
+                                   PLOT_DASH_TYPE::SOLID ) );
 
     // Old libraries (version <= 2.2) do not have always this FILL MODE param
     // when fill mode is no fill (default mode).
@@ -3359,7 +3361,8 @@ LIB_SHAPE* SCH_LEGACY_PLUGIN_CACHE::loadCircle( std::unique_ptr<LIB_SYMBOL>& aSy
     circle->SetEnd( wxPoint( center.x + radius, center.y ) );
     circle->SetUnit( parseInt( aReader, line, &line ) );
     circle->SetConvert( parseInt( aReader, line, &line ) );
-    circle->SetWidth( Mils2Iu( parseInt( aReader, line, &line ) ) );
+    circle->SetStroke( STROKE_PARAMS( Mils2Iu( parseInt( aReader, line, &line ) ),
+                                      PLOT_DASH_TYPE::SOLID ) );
 
     if( *line != 0 )
         circle->SetFillMode( parseFillMode( aReader, line, &line ) );
@@ -3488,7 +3491,8 @@ LIB_SHAPE* SCH_LEGACY_PLUGIN_CACHE::loadRect( std::unique_ptr<LIB_SYMBOL>& aSymb
 
     rectangle->SetUnit( parseInt( aReader, line, &line ) );
     rectangle->SetConvert( parseInt( aReader, line, &line ) );
-    rectangle->SetWidth( Mils2Iu( parseInt( aReader, line, &line ) ) );
+    rectangle->SetStroke( STROKE_PARAMS( Mils2Iu( parseInt( aReader, line, &line ) ),
+                                         PLOT_DASH_TYPE::SOLID ) );
 
     if( *line != 0 )
         rectangle->SetFillMode( parseFillMode( aReader, line, &line ) );
@@ -3708,7 +3712,8 @@ LIB_SHAPE* SCH_LEGACY_PLUGIN_CACHE::loadPolyLine( std::unique_ptr<LIB_SYMBOL>& a
     int points = parseInt( aReader, line, &line );
     polyLine->SetUnit( parseInt( aReader, line, &line ) );
     polyLine->SetConvert( parseInt( aReader, line, &line ) );
-    polyLine->SetWidth( Mils2Iu( parseInt( aReader, line, &line ) ) );
+    polyLine->SetStroke( STROKE_PARAMS( Mils2Iu( parseInt( aReader, line, &line ) ),
+                                        PLOT_DASH_TYPE::SOLID ) );
 
     wxPoint pt;
 
@@ -3741,7 +3746,8 @@ LIB_SHAPE* SCH_LEGACY_PLUGIN_CACHE::loadBezier( std::unique_ptr<LIB_SYMBOL>& aSy
 
     bezier->SetUnit( parseInt( aReader, line, &line ) );
     bezier->SetConvert( parseInt( aReader, line, &line ) );
-    bezier->SetWidth( Mils2Iu( parseInt( aReader, line, &line ) ) );
+    bezier->SetStroke( STROKE_PARAMS( Mils2Iu( parseInt( aReader, line, &line ) ),
+                                      PLOT_DASH_TYPE::SOLID ) );
 
     bezier->SetStart( wxPoint( Mils2Iu( parseInt( aReader, line, &line ) ),
                                Mils2Iu( parseInt( aReader, line, &line ) ) ) );
@@ -4002,7 +4008,7 @@ void SCH_LEGACY_PLUGIN_CACHE::saveArc( LIB_SHAPE* aArc, OUTPUTFORMATTER& aFormat
                       aArc->GetUnit(),
                       aArc->GetConvert(),
                       Iu2Mils( aArc->GetWidth() ),
-                      fill_tab[ static_cast<int>( aArc->GetFillType() ) - 1 ],
+                      fill_tab[ static_cast<int>( aArc->GetFillMode() ) - 1 ],
                       Iu2Mils( aArc->GetStart().x ),
                       Iu2Mils( aArc->GetStart().y ),
                       Iu2Mils( aArc->GetEnd().x ),
@@ -4023,7 +4029,7 @@ void SCH_LEGACY_PLUGIN_CACHE::saveBezier( LIB_SHAPE* aBezier, OUTPUTFORMATTER& a
     for( const wxPoint& pt : aBezier->GetBezierPoints() )
         aFormatter.Print( 0, " %d %d", Iu2Mils( pt.x ), Iu2Mils( pt.y ) );
 
-    aFormatter.Print( 0, " %c\n", fill_tab[ static_cast<int>( aBezier->GetFillType() ) - 1 ] );
+    aFormatter.Print( 0, " %c\n", fill_tab[ static_cast<int>( aBezier->GetFillMode() ) - 1 ] );
 }
 
 
@@ -4038,7 +4044,7 @@ void SCH_LEGACY_PLUGIN_CACHE::saveCircle( LIB_SHAPE* aCircle, OUTPUTFORMATTER& a
                       aCircle->GetUnit(),
                       aCircle->GetConvert(),
                       Iu2Mils( aCircle->GetWidth() ),
-                      fill_tab[ static_cast<int>( aCircle->GetFillType() ) - 1 ] );
+                      fill_tab[ static_cast<int>( aCircle->GetFillMode() ) - 1 ] );
 }
 
 
@@ -4168,7 +4174,7 @@ void SCH_LEGACY_PLUGIN_CACHE::savePolyLine( LIB_SHAPE* aPolyLine, OUTPUTFORMATTE
     for( const VECTOR2I& pt : aPolyLine->GetPolyShape().Outline( 0 ).CPoints() )
         aFormatter.Print( 0, " %d %d", Iu2Mils( pt.x ), Iu2Mils( pt.y ) );
 
-    aFormatter.Print( 0, " %c\n", fill_tab[ static_cast<int>( aPolyLine->GetFillType() ) - 1 ] );
+    aFormatter.Print( 0, " %c\n", fill_tab[ static_cast<int>( aPolyLine->GetFillMode() ) - 1 ] );
 }
 
 
@@ -4184,7 +4190,7 @@ void SCH_LEGACY_PLUGIN_CACHE::saveRectangle( LIB_SHAPE* aRectangle, OUTPUTFORMAT
                       aRectangle->GetUnit(),
                       aRectangle->GetConvert(),
                       Iu2Mils( aRectangle->GetWidth() ),
-                      fill_tab[ static_cast<int>( aRectangle->GetFillType() ) - 1 ] );
+                      fill_tab[ static_cast<int>( aRectangle->GetFillMode() ) - 1 ] );
 }
 
 
diff --git a/eeschema/sch_shape.cpp b/eeschema/sch_shape.cpp
new file mode 100644
index 0000000000..2a7cfd6c0d
--- /dev/null
+++ b/eeschema/sch_shape.cpp
@@ -0,0 +1,422 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
+ * Copyright (C) 2004-2021 KiCad Developers, see AUTHORS.txt for contributors.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+#include <sch_draw_panel.h>
+#include <macros.h>
+#include <plotters/plotter.h>
+#include <base_units.h>
+#include <widgets/msgpanel.h>
+#include <bitmaps.h>
+#include <eda_draw_frame.h>
+#include <general.h>
+#include <sch_shape.h>
+
+
+SCH_SHAPE::SCH_SHAPE( SHAPE_T aShape, int aLineWidth, FILL_T aFillType ) :
+    SCH_ITEM( nullptr, SCH_SHAPE_T ),
+    EDA_SHAPE( aShape, aLineWidth, aFillType, true )
+{
+    SetLayer( LAYER_NOTES );
+}
+
+
+EDA_ITEM* SCH_SHAPE::Clone() const
+{
+    return new SCH_SHAPE( *this );
+}
+
+
+void SCH_SHAPE::SetStroke( const STROKE_PARAMS& aStroke )
+{
+    m_stroke = aStroke;
+}
+
+
+void SCH_SHAPE::Move( const wxPoint& aOffset )
+{
+    move( aOffset );
+}
+
+
+void SCH_SHAPE::MirrorHorizontally( int aCenter )
+{
+    flip( wxPoint( aCenter, 0 ), true );
+}
+
+
+void SCH_SHAPE::MirrorVertically( int aCenter )
+{
+    flip( wxPoint( 0, aCenter ), false );
+}
+
+
+void SCH_SHAPE::Rotate( const wxPoint& aCenter )
+{
+    rotate( aCenter, 900 );
+}
+
+
+void SCH_SHAPE::Plot( PLOTTER* aPlotter ) const
+{
+    int     pen_size = std::max( GetPenWidth(), aPlotter->RenderSettings()->GetMinPenWidth() );
+    wxPoint center;
+    int     radius;
+    int     startAngle;
+    int     endAngle;
+
+    static std::vector<wxPoint> cornerList;
+
+    if( GetShape() == SHAPE_T::POLY )
+    {
+        cornerList.clear();
+
+        for( const VECTOR2I& pt : m_poly.Outline( 0 ).CPoints() )
+            cornerList.push_back( (wxPoint) pt );
+    }
+    else if( GetShape() == SHAPE_T::ARC )
+    {
+        center = getCenter();
+        radius = GetRadius();
+        CalcArcAngles( startAngle, endAngle );
+    }
+
+    if( GetStroke().GetColor() == COLOR4D::UNSPECIFIED )
+        aPlotter->SetColor( aPlotter->RenderSettings()->GetLayerColor( LAYER_NOTES ) );
+    else
+        aPlotter->SetColor( GetStroke().GetColor() );
+
+    aPlotter->SetCurrentLineWidth( pen_size );
+    aPlotter->SetDash( GetStroke().GetPlotStyle() );
+
+    switch( GetShape() )
+    {
+    case SHAPE_T::ARC:
+        // TODO: doesn't work for dash styles
+        aPlotter->Arc( center, -endAngle, -startAngle, radius, FILL_T::NO_FILL, pen_size );
+        break;
+
+    case SHAPE_T::CIRCLE:
+        // TODO: doesn't work for dash styles
+        aPlotter->Circle( GetStart(), GetRadius() * 2, FILL_T::NO_FILL, pen_size );
+        break;
+
+    case SHAPE_T::RECT:
+    {
+        std::vector<wxPoint> pts = GetRectCorners();
+
+        aPlotter->MoveTo( pts[0] );
+        aPlotter->LineTo( pts[1] );
+        aPlotter->LineTo( pts[2] );
+        aPlotter->LineTo( pts[3] );
+        aPlotter->FinishTo( pts[0] );
+    }
+        break;
+
+    case SHAPE_T::POLY:
+    {
+        aPlotter->MoveTo( cornerList[0] );
+
+        for( size_t ii = 1; ii < cornerList.size(); ++ii )
+            aPlotter->LineTo( cornerList[ii] );
+
+        aPlotter->FinishTo( cornerList[0] );
+    }
+        break;
+
+    case SHAPE_T::BEZIER:
+        // TODO: doesn't work for dash styles
+        aPlotter->PlotPoly( m_bezierPoints, FILL_T::NO_FILL, pen_size );
+        break;
+
+    default:
+        UNIMPLEMENTED_FOR( SHAPE_T_asString() );
+    }
+
+    aPlotter->SetDash( PLOT_DASH_TYPE::SOLID );
+
+    if( m_fill == FILL_T::FILLED_WITH_COLOR && GetFillColor() != COLOR4D::UNSPECIFIED )
+    {
+        aPlotter->SetColor( GetFillColor() );
+
+        switch( GetShape() )
+        {
+        case SHAPE_T::ARC:
+            aPlotter->Arc( center, -endAngle, -startAngle, radius, m_fill, 0 );
+            break;
+
+        case SHAPE_T::CIRCLE:
+            aPlotter->Circle( GetStart(), GetRadius() * 2, m_fill, 0 );
+            break;
+
+        case SHAPE_T::RECT:
+            aPlotter->Rect( GetStart(), GetEnd(), m_fill, 0 );
+            break;
+
+        case SHAPE_T::POLY:
+            aPlotter->PlotPoly( cornerList, m_fill, 0 );
+            break;
+
+        case SHAPE_T::BEZIER:
+            aPlotter->PlotPoly( m_bezierPoints, m_fill, 0 );
+            break;
+
+        default:
+            UNIMPLEMENTED_FOR( SHAPE_T_asString() );
+        }
+    }
+}
+
+
+int SCH_SHAPE::GetPenWidth() const
+{
+    // Historically 0 meant "default width" and negative numbers meant "don't stroke".
+    if( GetWidth() < 0 && GetFillMode() != FILL_T::NO_FILL )
+        return 0;
+    else
+        return std::max( GetWidth(), 1 );
+}
+
+
+void SCH_SHAPE::Print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset )
+{
+    int      penWidth = GetPenWidth();
+    wxDC*    DC = aSettings->GetPrintDC();
+    wxPoint  pt1 = GetStart();
+    wxPoint  pt2 = GetEnd();
+    wxPoint  c;
+    COLOR4D  color;
+
+    penWidth = std::max( penWidth, aSettings->GetDefaultPenWidth() );
+
+    unsigned ptCount = 0;
+    wxPoint* buffer = nullptr;
+
+    if( GetShape() == SHAPE_T::POLY )
+    {
+        SHAPE_LINE_CHAIN poly = m_poly.Outline( 0 );
+
+        ptCount = poly.GetPointCount();
+        buffer = new wxPoint[ ptCount ];
+
+        for( unsigned ii = 0; ii < ptCount; ++ii )
+            buffer[ii] = (wxPoint) poly.CPoint( ii );
+    }
+    else if( GetShape() == SHAPE_T::BEZIER )
+    {
+        ptCount = m_bezierPoints.size();
+        buffer = new wxPoint[ ptCount ];
+
+        for( size_t ii = 0; ii < ptCount; ++ii )
+            buffer[ii] = m_bezierPoints[ii];
+    }
+    else if( GetShape() == SHAPE_T::ARC )
+    {
+        c = getCenter();
+        int t1, t2;
+
+        CalcArcAngles( t1, t2 );
+
+        if( NormalizeAngle180( t1 - t2 ) > 0 )
+            std::swap( pt1, pt2 );
+    }
+
+    if( GetFillMode() == FILL_T::FILLED_WITH_COLOR )
+    {
+        color = GetFillColor();
+
+        switch( GetShape() )
+        {
+        case SHAPE_T::ARC:
+            GRFilledArc1( nullptr, DC, pt1, pt2, c, 0, color, color );
+            break;
+
+        case SHAPE_T::CIRCLE:
+            GRFilledCircle( nullptr, DC, pt1.x, pt1.y, GetRadius(), 0, color, color );
+            break;
+
+        case SHAPE_T::RECT:
+            GRFilledRect( nullptr, DC, pt1.x, pt1.y, pt2.x, pt2.y, 0, color, color );
+            break;
+
+        case SHAPE_T::POLY:
+            GRPoly( nullptr, DC, ptCount, buffer, true, 0, color, color );
+            break;
+
+        case SHAPE_T::BEZIER:
+            GRPoly( nullptr, DC, ptCount, buffer, true, 0, color, color );
+            break;
+
+        default:
+            UNIMPLEMENTED_FOR( SHAPE_T_asString() );
+        }
+    }
+
+    if( GetStroke().GetColor() == COLOR4D::UNSPECIFIED )
+        color = aSettings->GetLayerColor( LAYER_NOTES );
+    else
+        color = GetStroke().GetColor();
+
+    if( GetStroke().GetPlotStyle() <= PLOT_DASH_TYPE::FIRST_TYPE )
+    {
+        switch( GetShape() )
+        {
+        case SHAPE_T::ARC:
+            GRArc1( nullptr, DC, pt1, pt2, c, penWidth, color );
+            break;
+
+        case SHAPE_T::CIRCLE:
+            GRCircle( nullptr, DC, pt1.x, pt1.y, GetRadius(), penWidth, color );
+            break;
+
+        case SHAPE_T::RECT:
+            GRRect( nullptr, DC, pt1.x, pt1.y, pt2.x, pt2.y, penWidth, color );
+            break;
+
+        case SHAPE_T::POLY:
+            GRPoly( nullptr, DC, ptCount, buffer, false, penWidth, color, color );
+            break;
+
+        case SHAPE_T::BEZIER:
+            GRPoly( nullptr, DC, ptCount, buffer, false, penWidth, color, color );
+            break;
+
+        default:
+            UNIMPLEMENTED_FOR( SHAPE_T_asString() );
+        }
+    }
+    else
+    {
+        std::vector<SHAPE*> shapes = MakeEffectiveShapes( true );
+
+        for( SHAPE* shape : shapes )
+        {
+            STROKE_PARAMS::Stroke( shape, GetStroke().GetPlotStyle(), penWidth, aSettings,
+                                   [&]( const wxPoint& a, const wxPoint& b )
+                                   {
+                                       GRLine( nullptr, DC, a.x, a.y, b.x, b.y, penWidth, color );
+                                   } );
+        }
+
+        for( SHAPE* shape : shapes )
+            delete shape;
+    }
+
+    delete[] buffer;
+}
+
+
+void SCH_SHAPE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
+{
+    SCH_ITEM::GetMsgPanelInfo( aFrame, aList );
+
+    ShapeGetMsgPanelInfo( aFrame, aList );
+}
+
+
+wxString SCH_SHAPE::GetSelectMenuText( EDA_UNITS aUnits ) const
+{
+    switch( GetShape() )
+    {
+    case SHAPE_T::ARC:
+        return wxString::Format( _( "Arc, radius %s" ),
+                                 MessageTextFromValue( aUnits, GetRadius() ) );
+
+    case SHAPE_T::CIRCLE:
+        return wxString::Format( _( "Circle, radius %s" ),
+                                 MessageTextFromValue( aUnits, GetRadius() ) );
+
+    case SHAPE_T::RECT:
+        return wxString::Format( _( "Rectangle, width %s height %s" ),
+                                 MessageTextFromValue( aUnits, std::abs( m_start.x - m_end.x ) ),
+                                 MessageTextFromValue( aUnits, std::abs( m_start.y - m_end.y ) ) );
+
+    case SHAPE_T::POLY:
+        return wxString::Format( _( "Polyline, %d points" ),
+                                 int( m_poly.Outline( 0 ).GetPointCount() ) );
+
+    case SHAPE_T::BEZIER:
+        return wxString::Format( _( "Bezier Curve, %d points" ),
+                                 int( m_bezierPoints.size() ) );
+
+    default:
+        UNIMPLEMENTED_FOR( SHAPE_T_asString() );
+        return wxEmptyString;
+    }
+}
+
+
+BITMAPS SCH_SHAPE::GetMenuImage() const
+{
+    switch( GetShape() )
+    {
+    case SHAPE_T::SEGMENT: return BITMAPS::add_line;
+    case SHAPE_T::ARC:     return BITMAPS::add_arc;
+    case SHAPE_T::CIRCLE:  return BITMAPS::add_circle;
+    case SHAPE_T::RECT:    return BITMAPS::add_rectangle;
+    case SHAPE_T::POLY:    return BITMAPS::add_graphical_segments;
+
+    default:
+        UNIMPLEMENTED_FOR( SHAPE_T_asString() );
+        return BITMAPS::question_mark;
+    }
+}
+
+
+void SCH_SHAPE::ViewGetLayers( int aLayers[], int& aCount ) const
+{
+    aCount     = 3;
+    aLayers[0] = LAYER_NOTES;
+    aLayers[1] = LAYER_NOTES_BACKGROUND;
+    aLayers[2] = LAYER_SELECTION_SHADOWS;
+}
+
+
+void SCH_SHAPE::AddPoint( const wxPoint& aPosition )
+{
+    if( GetShape() == SHAPE_T::POLY )
+    {
+        if( m_poly.IsEmpty() )
+            m_poly.NewOutline();
+
+        m_poly.Outline( 0 ).Append( aPosition, true );
+    }
+    else
+    {
+        UNIMPLEMENTED_FOR( SHAPE_T_asString() );
+    }
+}
+
+
+void SCH_SHAPE::CalcArcAngles( int& aStartAngle, int& aEndAngle ) const
+{
+    double start;
+    double end;
+
+    EDA_SHAPE::CalcArcAngles( start, end );
+
+    aStartAngle = KiROUND( start * 10.0 );
+    aEndAngle = KiROUND( end * 10.0 );
+}
+
+
diff --git a/eeschema/sch_shape.h b/eeschema/sch_shape.h
new file mode 100644
index 0000000000..222ad2a61d
--- /dev/null
+++ b/eeschema/sch_shape.h
@@ -0,0 +1,119 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
+ * Copyright (C) 2004-2021 KiCad Developers, see AUTHORS.txt for contributors.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+#ifndef SCH_SHAPE_H
+#define SCH_SHAPE_H
+
+#include <sch_item.h>
+#include <eda_shape.h>
+
+
+class SCH_SHAPE : public SCH_ITEM, public EDA_SHAPE
+{
+public:
+    SCH_SHAPE( SHAPE_T aShape, int aLineWidth = 0, FILL_T aFillType = FILL_T::NO_FILL );
+
+    // Do not create a copy constructor.  The one generated by the compiler is adequate.
+
+    ~SCH_SHAPE() { }
+
+    wxString GetClass() const override
+    {
+        return wxT( "SCH_SHAPE" );
+    }
+
+    bool HitTest( const wxPoint& aPosition, int aAccuracy = 0 ) const override
+    {
+        return hitTest( aPosition, aAccuracy );
+    }
+
+    bool HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy = 0 ) const override
+    {
+        return hitTest( aRect, aContained, aAccuracy );
+    }
+
+    int GetPenWidth() const override;
+
+    bool HasLineStroke() const override               { return true; }
+    STROKE_PARAMS GetStroke() const override          { return m_stroke; }
+    void SetStroke( const STROKE_PARAMS& aStroke ) override;
+
+    PLOT_DASH_TYPE GetEffectiveLineStyle() const
+    {
+        if( IsFilled() )
+            return PLOT_DASH_TYPE::SOLID;
+        else if( m_stroke.GetPlotStyle() == PLOT_DASH_TYPE::DEFAULT )
+            return PLOT_DASH_TYPE::DASH;
+        else
+            return m_stroke.GetPlotStyle();
+    }
+
+    const EDA_RECT GetBoundingBox() const override    { return getBoundingBox(); }
+
+    wxPoint GetPosition() const override              { return getPosition(); }
+    void SetPosition( const wxPoint& aPos ) override  { setPosition( aPos ); }
+
+    wxPoint GetCenter() const                         { return getCenter(); }
+
+    void CalcArcAngles( int& aStartAngle, int& aEndAngle ) const;
+
+    void BeginEdit( const wxPoint& aStartPoint )      { beginEdit( aStartPoint ); }
+    bool ContinueEdit( const wxPoint& aPosition )     { return continueEdit( aPosition ); }
+    void CalcEdit( const wxPoint& aPosition )         { calcEdit( aPosition ); }
+    void EndEdit()                                    { endEdit(); }
+    void SetEditState( int aState )                   { setEditState( aState ); }
+
+    void Move( const wxPoint& aOffset ) override;
+
+    void MirrorHorizontally( int aCenter ) override;
+    void MirrorVertically( int aCenter ) override;
+    void Rotate( const wxPoint& aCenter ) override;
+
+    void AddPoint( const wxPoint& aPosition );
+
+    void Plot( PLOTTER* aPlotter ) const override;
+
+    void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;
+
+    wxString GetSelectMenuText( EDA_UNITS aUnits ) const override;
+
+    BITMAPS GetMenuImage() const override;
+
+    EDA_ITEM* Clone() const override;
+
+    void ViewGetLayers( int aLayers[], int& aCount ) const override;
+
+#if defined(DEBUG)
+    void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
+#endif
+
+private:
+    void Print( const RENDER_SETTINGS* aSettings, const wxPoint& aOffset ) override;
+
+    double getParentOrientation() const override { return 0.0; }
+    wxPoint getParentPosition() const override { return wxPoint(); }
+};
+
+
+#endif    // SCH_SHAPE_H
diff --git a/eeschema/sch_symbol.cpp b/eeschema/sch_symbol.cpp
index 480f1814b7..7591639ef5 100644
--- a/eeschema/sch_symbol.cpp
+++ b/eeschema/sch_symbol.cpp
@@ -95,10 +95,10 @@ static LIB_SYMBOL* dummy()
 }
 
 
-SCH_SYMBOL::SCH_SYMBOL( const wxPoint& aPos, SCH_ITEM* aParent ) :
-    SCH_ITEM( aParent, SCH_SYMBOL_T )
+SCH_SYMBOL::SCH_SYMBOL() :
+    SCH_ITEM( nullptr, SCH_SYMBOL_T )
 {
-    Init( aPos );
+    Init( wxPoint( 0, 0 ) );
 }
 
 
diff --git a/eeschema/sch_symbol.h b/eeschema/sch_symbol.h
index eb6baa8b25..4afb65aac0 100644
--- a/eeschema/sch_symbol.h
+++ b/eeschema/sch_symbol.h
@@ -78,7 +78,7 @@ extern std::string toUTFTildaText( const wxString& txt );
 class SCH_SYMBOL : public SCH_ITEM
 {
 public:
-    SCH_SYMBOL( const wxPoint& pos = wxPoint( 0, 0 ), SCH_ITEM* aParent = nullptr );
+    SCH_SYMBOL();
 
     /**
      * Create schematic symbol from library symbol object.
diff --git a/eeschema/sch_text.cpp b/eeschema/sch_text.cpp
index 32980bb436..aa2f5ff1a1 100644
--- a/eeschema/sch_text.cpp
+++ b/eeschema/sch_text.cpp
@@ -853,8 +853,8 @@ EDA_ITEM* SCH_LABEL::Clone() const
 
 bool SCH_LABEL::IsType( const KICAD_T aScanTypes[] ) const
 {
-    static KICAD_T wireTypes[] = { SCH_LINE_LOCATE_WIRE_T, SCH_PIN_T, EOT };
-    static KICAD_T busTypes[] = { SCH_LINE_LOCATE_BUS_T, EOT };
+    static KICAD_T wireTypes[] = { SCH_ITEM_LOCATE_WIRE_T, SCH_PIN_T, EOT };
+    static KICAD_T busTypes[] = { SCH_ITEM_LOCATE_BUS_T, EOT };
 
     if( SCH_ITEM::IsType( aScanTypes ) )
         return true;
diff --git a/eeschema/sch_view.h b/eeschema/sch_view.h
index e9a22f27d0..b39aea6ee7 100644
--- a/eeschema/sch_view.h
+++ b/eeschema/sch_view.h
@@ -56,6 +56,7 @@ static const LAYER_NUM SCH_LAYER_ORDER[] =
     LAYER_SELECTION_SHADOWS,
     LAYER_DEVICE_BACKGROUND,
     LAYER_SHEET_BACKGROUND,
+    LAYER_NOTES_BACKGROUND,
     LAYER_DRAWINGSHEET
 };
 
diff --git a/eeschema/schematic.keywords b/eeschema/schematic.keywords
index 1f0053df5f..fceef87873 100644
--- a/eeschema/schematic.keywords
+++ b/eeschema/schematic.keywords
@@ -21,13 +21,10 @@ color
 comment
 company
 convert
-dash
-dash_dot
 data
 date
 default
 diameter
-dot
 edge_clock_high
 effects
 end
@@ -108,7 +105,6 @@ shape
 sheet
 sheet_instances
 size
-solid
 start
 stroke
 symbol
diff --git a/eeschema/symbol_editor/menubar_symbol_editor.cpp b/eeschema/symbol_editor/menubar_symbol_editor.cpp
index d3ab6cdcf8..4228b39a32 100644
--- a/eeschema/symbol_editor/menubar_symbol_editor.cpp
+++ b/eeschema/symbol_editor/menubar_symbol_editor.cpp
@@ -139,9 +139,9 @@ void SYMBOL_EDIT_FRAME::ReCreateMenuBar()
 
     placeMenu->Add( EE_ACTIONS::placeSymbolPin );
     placeMenu->Add( EE_ACTIONS::placeSymbolText );
-    placeMenu->Add( EE_ACTIONS::drawSymbolRectangle );
-    placeMenu->Add( EE_ACTIONS::drawSymbolCircle );
-    placeMenu->Add( EE_ACTIONS::drawSymbolArc );
+    placeMenu->Add( EE_ACTIONS::drawRectangle );
+    placeMenu->Add( EE_ACTIONS::drawCircle );
+    placeMenu->Add( EE_ACTIONS::drawArc );
     placeMenu->Add( EE_ACTIONS::drawSymbolLines );
 
 
diff --git a/eeschema/symbol_editor/symbol_edit_frame.cpp b/eeschema/symbol_editor/symbol_edit_frame.cpp
index e4364d7752..7a9ec65cc1 100644
--- a/eeschema/symbol_editor/symbol_edit_frame.cpp
+++ b/eeschema/symbol_editor/symbol_edit_frame.cpp
@@ -490,9 +490,9 @@ void SYMBOL_EDIT_FRAME::setupUIConditions()
     mgr->SetConditions( ACTIONS::deleteTool,             EDIT_TOOL( ACTIONS::deleteTool ) );
     mgr->SetConditions( EE_ACTIONS::placeSymbolPin,      EDIT_TOOL( EE_ACTIONS::placeSymbolPin ) );
     mgr->SetConditions( EE_ACTIONS::placeSymbolText,     EDIT_TOOL( EE_ACTIONS::placeSymbolText ) );
-    mgr->SetConditions( EE_ACTIONS::drawSymbolRectangle, EDIT_TOOL( EE_ACTIONS::drawSymbolRectangle ) );
-    mgr->SetConditions( EE_ACTIONS::drawSymbolCircle,    EDIT_TOOL( EE_ACTIONS::drawSymbolCircle ) );
-    mgr->SetConditions( EE_ACTIONS::drawSymbolArc,       EDIT_TOOL( EE_ACTIONS::drawSymbolArc ) );
+    mgr->SetConditions( EE_ACTIONS::drawRectangle, EDIT_TOOL( EE_ACTIONS::drawRectangle ) );
+    mgr->SetConditions( EE_ACTIONS::drawCircle, EDIT_TOOL( EE_ACTIONS::drawCircle ) );
+    mgr->SetConditions( EE_ACTIONS::drawArc, EDIT_TOOL( EE_ACTIONS::drawArc ) );
     mgr->SetConditions( EE_ACTIONS::drawSymbolLines,     EDIT_TOOL( EE_ACTIONS::drawSymbolLines ) );
     mgr->SetConditions( EE_ACTIONS::placeSymbolAnchor,   EDIT_TOOL( EE_ACTIONS::placeSymbolAnchor ) );
 
diff --git a/eeschema/symbol_editor/toolbars_symbol_editor.cpp b/eeschema/symbol_editor/toolbars_symbol_editor.cpp
index f734318402..bf2c8297c0 100644
--- a/eeschema/symbol_editor/toolbars_symbol_editor.cpp
+++ b/eeschema/symbol_editor/toolbars_symbol_editor.cpp
@@ -59,9 +59,9 @@ void SYMBOL_EDIT_FRAME::ReCreateVToolbar()
     m_drawToolBar->AddScaledSeparator( this );
     m_drawToolBar->Add( EE_ACTIONS::placeSymbolPin,       ACTION_TOOLBAR::TOGGLE );
     m_drawToolBar->Add( EE_ACTIONS::placeSymbolText,      ACTION_TOOLBAR::TOGGLE );
-    m_drawToolBar->Add( EE_ACTIONS::drawSymbolRectangle,  ACTION_TOOLBAR::TOGGLE );
-    m_drawToolBar->Add( EE_ACTIONS::drawSymbolCircle,     ACTION_TOOLBAR::TOGGLE );
-    m_drawToolBar->Add( EE_ACTIONS::drawSymbolArc,        ACTION_TOOLBAR::TOGGLE );
+    m_drawToolBar->Add( EE_ACTIONS::drawRectangle,        ACTION_TOOLBAR::TOGGLE );
+    m_drawToolBar->Add( EE_ACTIONS::drawCircle,           ACTION_TOOLBAR::TOGGLE );
+    m_drawToolBar->Add( EE_ACTIONS::drawArc,              ACTION_TOOLBAR::TOGGLE );
     m_drawToolBar->Add( EE_ACTIONS::drawSymbolLines,      ACTION_TOOLBAR::TOGGLE );
     m_drawToolBar->Add( EE_ACTIONS::placeSymbolAnchor,    ACTION_TOOLBAR::TOGGLE );
     m_drawToolBar->Add( ACTIONS::deleteTool,              ACTION_TOOLBAR::TOGGLE );
diff --git a/eeschema/tools/ee_actions.cpp b/eeschema/tools/ee_actions.cpp
index 218e6b917e..33b9748d86 100644
--- a/eeschema/tools/ee_actions.cpp
+++ b/eeschema/tools/ee_actions.cpp
@@ -225,21 +225,6 @@ TOOL_ACTION EE_ACTIONS::placeSymbolText( "eeschema.SymbolDrawing.placeSymbolText
         _( "Add Text" ), _( "Add a text item" ),
         BITMAPS::text, AF_ACTIVATE, (void*) LIB_TEXT_T );
 
-TOOL_ACTION EE_ACTIONS::drawSymbolRectangle( "eeschema.SymbolDrawing.drawSymbolRectangle",
-        AS_GLOBAL, 0, "",
-        _( "Add Rectangle" ), _( "Add a rectangle" ),
-        BITMAPS::add_rectangle, AF_ACTIVATE, (void*) SHAPE_T::RECT );
-
-TOOL_ACTION EE_ACTIONS::drawSymbolCircle( "eeschema.SymbolDrawing.drawSymbolCircle",
-        AS_GLOBAL, 0, "",
-        _( "Add Circle" ), _( "Add a circle" ),
-        BITMAPS::add_circle, AF_ACTIVATE, (void*) SHAPE_T::CIRCLE );
-
-TOOL_ACTION EE_ACTIONS::drawSymbolArc( "eeschema.SymbolDrawing.drawSymbolArc",
-        AS_GLOBAL, 0, "",
-        _( "Add Arc" ), _( "Add an arc" ),
-        BITMAPS::add_arc, AF_ACTIVATE, (void*) SHAPE_T::ARC );
-
 TOOL_ACTION EE_ACTIONS::drawSymbolLines( "eeschema.SymbolDrawing.drawSymbolLines",
         AS_GLOBAL, 0, "",
         _( "Add Lines" ), _( "Add connected graphic lines" ),
@@ -345,6 +330,21 @@ TOOL_ACTION EE_ACTIONS::placeSchematicText( "eeschema.InteractiveDrawing.placeSc
         _( "Add Text" ), _( "Add text" ),
         BITMAPS::text, AF_ACTIVATE );
 
+TOOL_ACTION EE_ACTIONS::drawRectangle( "eeschema.InteractiveDrawing.drawRectangle",
+        AS_GLOBAL, 0, "",
+        _( "Add Rectangle" ), _( "Add a rectangle" ),
+        BITMAPS::add_rectangle, AF_ACTIVATE, (void*) SHAPE_T::RECT );
+
+TOOL_ACTION EE_ACTIONS::drawCircle( "eeschema.InteractiveDrawing.drawCircle",
+        AS_GLOBAL, 0, "",
+        _( "Add Circle" ), _( "Add a circle" ),
+        BITMAPS::add_circle, AF_ACTIVATE, (void*) SHAPE_T::CIRCLE );
+
+TOOL_ACTION EE_ACTIONS::drawArc( "eeschema.InteractiveDrawing.drawArc",
+        AS_GLOBAL, 0, "",
+        _( "Add Arc" ), _( "Add an arc" ),
+        BITMAPS::add_arc, AF_ACTIVATE, (void*) SHAPE_T::ARC );
+
 TOOL_ACTION EE_ACTIONS::placeImage( "eeschema.InteractiveDrawing.placeImage",
         AS_GLOBAL, 0, "",
         _( "Add Image" ), _( "Add bitmap image" ),
diff --git a/eeschema/tools/ee_actions.h b/eeschema/tools/ee_actions.h
index d75067a2ab..5cb29d12fc 100644
--- a/eeschema/tools/ee_actions.h
+++ b/eeschema/tools/ee_actions.h
@@ -88,6 +88,9 @@ public:
     static TOOL_ACTION drawSheet;
     static TOOL_ACTION importSheetPin;
     static TOOL_ACTION placeSchematicText;
+    static TOOL_ACTION drawRectangle;
+    static TOOL_ACTION drawCircle;
+    static TOOL_ACTION drawArc;
     static TOOL_ACTION drawLines;
     static TOOL_ACTION placeImage;
     static TOOL_ACTION finishLineWireOrBus;
@@ -99,9 +102,6 @@ public:
     // Symbol Tools
     static TOOL_ACTION placeSymbolPin;
     static TOOL_ACTION placeSymbolText;
-    static TOOL_ACTION drawSymbolRectangle;
-    static TOOL_ACTION drawSymbolCircle;
-    static TOOL_ACTION drawSymbolArc;
     static TOOL_ACTION drawSymbolLines;
     static TOOL_ACTION placeSymbolAnchor;
     static TOOL_ACTION finishDrawing;
diff --git a/eeschema/tools/ee_point_editor.cpp b/eeschema/tools/ee_point_editor.cpp
index f10defdd1e..46b0b1b76f 100644
--- a/eeschema/tools/ee_point_editor.cpp
+++ b/eeschema/tools/ee_point_editor.cpp
@@ -37,6 +37,7 @@ using namespace std::placeholders;
 #include <sch_line.h>
 #include <sch_bitmap.h>
 #include <sch_sheet.h>
+#include <sch_shape.h>
 #include <sch_sheet_pin.h>
 #include <symbol_edit_frame.h>
 #include <lib_shape.h>
@@ -123,8 +124,59 @@ public:
                 break;
 
             default:
-                wxFAIL_MSG( "EDIT_POINTS_FACTORY::Make not implemented for "
-                            + shape->SHAPE_T_asString() );
+                UNIMPLEMENTED_FOR( shape->SHAPE_T_asString() );
+            }
+        }
+            break;
+
+        case SCH_SHAPE_T:
+        {
+            SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( aItem );
+
+            switch( shape->GetShape() )
+            {
+            case SHAPE_T::ARC:
+                points->AddPoint( shape->GetPosition() );
+                points->AddPoint( shape->GetStart() );
+                points->AddPoint( shape->GetEnd() );
+                break;
+
+            case SHAPE_T::CIRCLE:
+                points->AddPoint( shape->GetPosition() );
+                points->AddPoint( shape->GetEnd() );
+                break;
+
+            case SHAPE_T::RECT:
+            {
+                // point editor works only with rectangles having width and height > 0
+                // Some symbols can have rectangles with width or height < 0
+                // So normalize the size:
+                BOX2I dummy;
+                dummy.SetOrigin( shape->GetPosition() );
+                dummy.SetEnd( shape->GetEnd() );
+                dummy.Normalize();
+                VECTOR2I topLeft = dummy.GetPosition();
+                VECTOR2I botRight = dummy.GetEnd();
+
+                points->AddPoint( topLeft );
+                points->AddPoint( VECTOR2I( botRight.x, topLeft.y ) );
+                points->AddPoint( VECTOR2I( topLeft.x, botRight.y ) );
+                points->AddPoint( botRight );
+            }
+                break;
+
+            case SHAPE_T::POLY:
+                for( const VECTOR2I& pt : shape->GetPolyShape().Outline( 0 ).CPoints() )
+                    points->AddPoint( pt );
+
+                break;
+
+            case SHAPE_T::BEZIER:
+                // TODO
+                break;
+
+            default:
+                UNIMPLEMENTED_FOR( shape->SHAPE_T_asString() );
             }
         }
             break;
@@ -275,8 +327,9 @@ int EE_POINT_EDITOR::Main( const TOOL_EVENT& aEvent )
 {
     static KICAD_T supportedTypes[] = {
         LIB_SHAPE_T,
+        SCH_SHAPE_T,
         SCH_SHEET_T,
-        SCH_LINE_LOCATE_GRAPHIC_LINE_T,
+        SCH_ITEM_LOCATE_GRAPHIC_LINE_T,
         SCH_BITMAP_T,
         EOT
     };
@@ -540,8 +593,71 @@ void EE_POINT_EDITOR::updateParentItem() const
             break;
 
         default:
-            wxFAIL_MSG( "EE_POINT_EDITOR::updateParentItem not implemented for "
-                        + shape->SHAPE_T_asString() );
+            UNIMPLEMENTED_FOR( shape->SHAPE_T_asString() );
+        }
+    }
+        break;
+
+    case SCH_SHAPE_T:
+    {
+        SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( item );
+
+        switch( shape->GetShape() )
+        {
+        case SHAPE_T::ARC:
+            if( getEditedPointIndex() == ARC_CENTER )
+            {
+                shape->SetEditState( 4 );
+                shape->CalcEdit( (wxPoint) m_editPoints->Point( ARC_CENTER ).GetPosition() );
+            }
+            else if( getEditedPointIndex() == ARC_START )
+            {
+                shape->SetEditState( 2 );
+                shape->CalcEdit( (wxPoint) m_editPoints->Point( ARC_START ).GetPosition() );
+            }
+            else if( getEditedPointIndex() == ARC_END )
+            {
+                shape->SetEditState( 3 );
+                shape->CalcEdit( (wxPoint) m_editPoints->Point( ARC_END ).GetPosition() );
+            }
+            break;
+
+        case SHAPE_T::CIRCLE:
+            shape->SetPosition( (wxPoint) m_editPoints->Point( CIRC_CENTER ).GetPosition() );
+            shape->SetEnd( (wxPoint) m_editPoints->Point( CIRC_END ).GetPosition() );
+            break;
+
+        case SHAPE_T::POLY:
+            shape->GetPolyShape().RemoveAllContours();
+            shape->GetPolyShape().NewOutline();
+
+            for( unsigned i = 0; i < m_editPoints->PointsSize(); ++i )
+                shape->GetPolyShape().Append( m_editPoints->Point( i ).GetPosition() );
+
+            break;
+
+        case SHAPE_T::RECT:
+        {
+            EE_GRID_HELPER gridHelper( m_toolMgr );
+            VECTOR2I       topLeft = m_editPoints->Point( RECT_TOPLEFT ).GetPosition();
+            VECTOR2I       topRight = m_editPoints->Point( RECT_TOPRIGHT ).GetPosition();
+            VECTOR2I       botLeft = m_editPoints->Point( RECT_BOTLEFT ).GetPosition();
+            VECTOR2I       botRight = m_editPoints->Point( RECT_BOTRIGHT ).GetPosition();
+
+            pinEditedCorner( getEditedPointIndex(), Mils2iu( 1 ), Mils2iu( 1 ),
+                             topLeft, topRight, botLeft, botRight, &gridHelper );
+
+            shape->SetPosition( (wxPoint) topLeft );
+            shape->SetEnd( (wxPoint) botRight );
+        }
+            break;
+
+        case SHAPE_T::BEZIER:
+            // TODO
+            break;
+
+        default:
+            UNIMPLEMENTED_FOR( shape->SHAPE_T_asString() );
         }
     }
         break;
@@ -732,8 +848,73 @@ void EE_POINT_EDITOR::updatePoints()
             break;
 
         default:
-            wxFAIL_MSG( "EE_POINT_EDITOR::updatePoints not implemented for "
-                        + shape->SHAPE_T_asString() );
+            UNIMPLEMENTED_FOR( shape->SHAPE_T_asString() );
+        }
+    }
+        break;
+
+    case SCH_SHAPE_T:
+    {
+        SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( item );
+
+        switch( shape->GetShape() )
+        {
+        case SHAPE_T::ARC:
+            m_editPoints->Point( ARC_CENTER ).SetPosition( shape->GetPosition() );
+            m_editPoints->Point( ARC_START ).SetPosition( shape->GetStart() );
+            m_editPoints->Point( ARC_END ).SetPosition( shape->GetEnd() );
+            break;
+
+        case SHAPE_T::CIRCLE:
+            m_editPoints->Point( CIRC_CENTER ).SetPosition( shape->GetPosition() );
+            m_editPoints->Point( CIRC_END ).SetPosition( shape->GetEnd() );
+            break;
+
+        case SHAPE_T::POLY:
+        {
+            if( (int) m_editPoints->PointsSize() != shape->GetPointCount() )
+            {
+                getView()->Remove( m_editPoints.get() );
+                m_editedPoint = nullptr;
+                m_editPoints = EDIT_POINTS_FACTORY::Make( item, m_frame );
+                getView()->Add( m_editPoints.get() );
+            }
+            else
+            {
+                int ii = 0;
+
+                for( const VECTOR2I& pt : shape->GetPolyShape().Outline( 0 ).CPoints() )
+                    m_editPoints->Point( ii++ ).SetPosition( pt );
+            }
+
+            break;
+        }
+
+        case SHAPE_T::RECT:
+        {
+            // point editor works only with rectangles having width and height > 0
+            // Some symbols can have rectangles with width or height < 0
+            // So normalize the size:
+            BOX2I dummy;
+            dummy.SetOrigin( shape->GetPosition() );
+            dummy.SetEnd( shape->GetEnd() );
+            dummy.Normalize();
+            VECTOR2I topLeft = dummy.GetPosition();
+            VECTOR2I botRight = dummy.GetEnd();
+
+            m_editPoints->Point( RECT_TOPLEFT ).SetPosition( topLeft );
+            m_editPoints->Point( RECT_TOPRIGHT ).SetPosition( VECTOR2I( botRight.x, topLeft.y ) );
+            m_editPoints->Point( RECT_BOTLEFT ).SetPosition( VECTOR2I( topLeft.x, botRight.y ) );
+            m_editPoints->Point( RECT_BOTRIGHT ).SetPosition( botRight );
+        }
+            break;
+
+        case SHAPE_T::BEZIER:
+            // TODO
+            break;
+
+        default:
+            UNIMPLEMENTED_FOR( shape->SHAPE_T_asString() );
         }
     }
         break;
diff --git a/eeschema/tools/ee_selection_tool.cpp b/eeschema/tools/ee_selection_tool.cpp
index 8138252c7d..8431457acd 100644
--- a/eeschema/tools/ee_selection_tool.cpp
+++ b/eeschema/tools/ee_selection_tool.cpp
@@ -150,13 +150,13 @@ bool EE_SELECTION_TOOL::Init()
         m_isSymbolViewer = symbolViewerFrame != nullptr;
     }
 
-    static KICAD_T wireOrBusTypes[] = { SCH_LINE_LOCATE_WIRE_T, SCH_LINE_LOCATE_BUS_T, EOT };
-    static KICAD_T connectedTypes[] = { SCH_LINE_LOCATE_WIRE_T, SCH_LINE_LOCATE_BUS_T,
+    static KICAD_T wireOrBusTypes[] = { SCH_ITEM_LOCATE_WIRE_T, SCH_ITEM_LOCATE_BUS_T, EOT };
+    static KICAD_T connectedTypes[] = { SCH_ITEM_LOCATE_WIRE_T, SCH_ITEM_LOCATE_BUS_T,
                                         SCH_GLOBAL_LABEL_T, SCH_HIER_LABEL_T, SCH_LABEL_T,
                                         SCH_SHEET_PIN_T, SCH_PIN_T, EOT };
 
-    auto wireSelection =      E_C::MoreThan( 0 ) && E_C::OnlyType( SCH_LINE_LOCATE_WIRE_T );
-    auto busSelection =       E_C::MoreThan( 0 ) && E_C::OnlyType( SCH_LINE_LOCATE_BUS_T );
+    auto wireSelection =      E_C::MoreThan( 0 ) && E_C::OnlyType( SCH_ITEM_LOCATE_WIRE_T );
+    auto busSelection =       E_C::MoreThan( 0 ) && E_C::OnlyType( SCH_ITEM_LOCATE_BUS_T );
     auto wireOrBusSelection = E_C::MoreThan( 0 ) && E_C::OnlyTypes( wireOrBusTypes );
     auto connectedSelection = E_C::MoreThan( 0 ) && E_C::OnlyTypes( connectedTypes );
     auto sheetSelection =     E_C::Count( 1 )    && E_C::OnlyType( SCH_SHEET_T );
@@ -293,6 +293,7 @@ const KICAD_T movableSchematicItems[] =
     SCH_BUS_WIRE_ENTRY_T,
     SCH_LINE_T,
     SCH_BITMAP_T,
+    SCH_SHAPE_T,
     SCH_TEXT_T,
     SCH_LABEL_T,
     SCH_GLOBAL_LABEL_T,
@@ -307,7 +308,7 @@ const KICAD_T movableSchematicItems[] =
 
 const KICAD_T movableSymbolItems[] =
 {
-    LIB_SHAPE_T,
+   LIB_SHAPE_T,
     LIB_TEXT_T,
     LIB_PIN_T,
     LIB_FIELD_T,
@@ -1334,18 +1335,18 @@ bool EE_SELECTION_TOOL::selectMultiple()
 
 static KICAD_T nodeTypes[] =
 {
-    SCH_SYMBOL_LOCATE_POWER_T,
-    SCH_PIN_T,
-    SCH_LINE_LOCATE_WIRE_T,
-    SCH_LINE_LOCATE_BUS_T,
-    SCH_BUS_WIRE_ENTRY_T,
-    SCH_BUS_BUS_ENTRY_T,
-    SCH_LABEL_T,
-    SCH_HIER_LABEL_T,
-    SCH_GLOBAL_LABEL_T,
-    SCH_SHEET_PIN_T,
-    SCH_JUNCTION_T,
-    EOT
+        SCH_SYMBOL_LOCATE_POWER_T,
+        SCH_PIN_T,
+        SCH_ITEM_LOCATE_WIRE_T,
+        SCH_ITEM_LOCATE_BUS_T,
+        SCH_BUS_WIRE_ENTRY_T,
+        SCH_BUS_BUS_ENTRY_T,
+        SCH_LABEL_T,
+        SCH_HIER_LABEL_T,
+        SCH_GLOBAL_LABEL_T,
+        SCH_SHEET_PIN_T,
+        SCH_JUNCTION_T,
+        EOT
 };
 
 
@@ -1383,7 +1384,7 @@ int EE_SELECTION_TOOL::SelectNode( const TOOL_EVENT& aEvent )
 
 int EE_SELECTION_TOOL::SelectConnection( const TOOL_EVENT& aEvent )
 {
-    static KICAD_T wiresAndBuses[] = { SCH_LINE_LOCATE_WIRE_T, SCH_LINE_LOCATE_BUS_T, EOT };
+    static KICAD_T wiresAndBuses[] = { SCH_ITEM_LOCATE_WIRE_T, SCH_ITEM_LOCATE_BUS_T, EOT };
 
     RequestSelection( wiresAndBuses );
 
diff --git a/eeschema/tools/sch_drawing_tools.cpp b/eeschema/tools/sch_drawing_tools.cpp
index 0b8570d287..6802129a2d 100644
--- a/eeschema/tools/sch_drawing_tools.cpp
+++ b/eeschema/tools/sch_drawing_tools.cpp
@@ -53,7 +53,7 @@
 #include <string_utils.h>
 #include <wildcards_and_files_ext.h>
 #include <wx/filedlg.h>
-
+#include <sch_shape.h>
 
 SCH_DRAWING_TOOLS::SCH_DRAWING_TOOLS() :
         EE_TOOL_BASE<SCH_EDIT_FRAME>( "eeschema.InteractiveDrawing" ),
@@ -62,7 +62,9 @@ SCH_DRAWING_TOOLS::SCH_DRAWING_TOOLS() :
         m_lastTextOrientation( LABEL_SPIN_STYLE::RIGHT ),
         m_lastTextBold( false ),
         m_lastTextItalic( false ),
+        m_lastFillStyle( FILL_T::NO_FILL ),
         m_inPlaceSymbol( false ),
+        m_inDrawShape( false ),
         m_inPlaceImage( false ),
         m_inSingleClickPlace( false ),
         m_inTwoClickPlace( false ),
@@ -1180,8 +1182,7 @@ int SCH_DRAWING_TOOLS::TwoClickPlace( const TOOL_EVENT& aEvent )
             else            // ... and second click places:
             {
                 item->ClearFlags( IS_MOVING );
-                m_frame->AddItemToScreenAndUndoList( m_frame->GetScreen(), (SCH_ITEM*) item,
-                                                     false );
+                m_frame->AddItemToScreenAndUndoList( m_frame->GetScreen(), item, false );
                 item = nullptr;
 
                 m_view->ClearPreview();
@@ -1238,6 +1239,165 @@ int SCH_DRAWING_TOOLS::TwoClickPlace( const TOOL_EVENT& aEvent )
 }
 
 
+int SCH_DRAWING_TOOLS::DrawShape( const TOOL_EVENT& aEvent )
+{
+    if( m_inDrawShape )
+        return 0;
+    else
+        m_inDrawShape = true;
+
+    SHAPE_T type = aEvent.Parameter<SHAPE_T>();
+
+    // We might be running as the same shape in another co-routine.  Make sure that one
+    // gets whacked.
+    m_toolMgr->DeactivateTool();
+
+    m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
+    getViewControls()->ShowCursor( true );
+
+    std::string tool = aEvent.GetCommandStr().get();
+    m_frame->PushTool( tool );
+    Activate();
+
+    SCH_SHAPE* item = nullptr;
+
+    auto setCursor =
+            [&]()
+            {
+                m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
+            };
+
+    auto cleanup =
+            [&] ()
+            {
+                m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
+                m_view->ClearPreview();
+                delete item;
+                item = nullptr;
+            };
+
+    // Prime the pump
+    if( aEvent.HasPosition() )
+        m_toolMgr->RunAction( ACTIONS::cursorClick );
+
+    // Set initial cursor
+    setCursor();
+
+    // Main loop: keep receiving events
+    while( TOOL_EVENT* evt = Wait() )
+    {
+        setCursor();
+
+        VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !evt->DisableGridSnapping() );
+
+        if( evt->IsCancelInteractive() )
+        {
+            if( item )
+            {
+                cleanup();
+            }
+            else
+            {
+                m_frame->PopTool( tool );
+                break;
+            }
+        }
+        else if( evt->IsActivate() )
+        {
+            if( item && evt->IsMoveTool() )
+            {
+                // we're already drawing our own item; ignore the move tool
+                evt->SetPassEvent( false );
+                continue;
+            }
+
+            if( item )
+                cleanup();
+
+            if( evt->IsPointEditor() )
+            {
+                // don't exit (the point editor runs in the background)
+            }
+            else if( evt->IsMoveTool() )
+            {
+                // leave ourselves on the stack so we come back after the move
+                break;
+            }
+            else
+            {
+                m_frame->PopTool( tool );
+                break;
+            }
+        }
+        else if( evt->IsClick( BUT_LEFT ) && !item )
+        {
+            EESCHEMA_SETTINGS* cfg = m_frame->eeconfig();
+
+            m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
+
+            int lineWidth = Mils2iu( cfg->m_Drawing.default_line_thickness );
+
+            item = new SCH_SHAPE( type, lineWidth, m_lastFillStyle );
+            item->SetFlags( IS_NEW );
+            item->BeginEdit( (wxPoint) cursorPos );
+
+            m_view->ClearPreview();
+            m_view->AddToPreview( item->Clone() );
+        }
+        else if( item && ( evt->IsClick( BUT_LEFT ) || evt->IsDblClick( BUT_LEFT )
+                        || evt->IsAction( &EE_ACTIONS::finishDrawing ) ) )
+        {
+            if( evt->IsDblClick( BUT_LEFT ) || evt->IsAction( &EE_ACTIONS::finishDrawing )
+                    || !item->ContinueEdit( (wxPoint) cursorPos ) )
+            {
+                item->EndEdit();
+                item->ClearEditFlags();
+                item->SetFlags( IS_NEW );
+
+                m_frame->AddItemToScreenAndUndoList( m_frame->GetScreen(), item, false );
+                m_selectionTool->AddItemToSel( item );
+                item = nullptr;
+
+                m_view->ClearPreview();
+                m_toolMgr->RunAction( ACTIONS::activatePointEditor );
+            }
+        }
+        else if( item && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
+        {
+            item->CalcEdit( (wxPoint) cursorPos );
+            m_view->ClearPreview();
+            m_view->AddToPreview( item->Clone() );
+        }
+        else if( evt->IsDblClick( BUT_LEFT ) && !item )
+        {
+            m_toolMgr->RunAction( EE_ACTIONS::properties, true );
+        }
+        else if( evt->IsClick( BUT_RIGHT ) )
+        {
+            // Warp after context menu only if dragging...
+            if( !item )
+                m_toolMgr->VetoContextMenuMouseWarp();
+
+            m_menu.ShowContextMenu( m_selectionTool->GetSelection() );
+        }
+        else
+        {
+            evt->SetPassEvent();
+        }
+
+        // Enable autopanning and cursor capture only when there is a shape being drawn
+        getViewControls()->SetAutoPan( item != nullptr );
+        getViewControls()->CaptureCursor( item != nullptr );
+    }
+
+    getViewControls()->SetAutoPan( false );
+    getViewControls()->CaptureCursor( false );
+    m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::ARROW );
+    m_inDrawShape = false;
+    return 0;
+}
+
+
 int SCH_DRAWING_TOOLS::DrawSheet( const TOOL_EVENT& aEvent )
 {
     SCH_SHEET* sheet = nullptr;
@@ -1333,8 +1493,7 @@ int SCH_DRAWING_TOOLS::DrawSheet( const TOOL_EVENT& aEvent )
 
             m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
 
-            sheet = new SCH_SHEET( m_frame->GetCurrentSheet().Last(),
-                                   static_cast<wxPoint>( cursorPos ) );
+            sheet = new SCH_SHEET( m_frame->GetCurrentSheet().Last(), (wxPoint) cursorPos );
             sheet->SetFlags( IS_NEW | IS_RESIZING );
             sheet->SetScreen( nullptr );
             sheet->SetBorderWidth( Mils2iu( cfg->m_Drawing.default_line_thickness ) );
@@ -1448,5 +1607,8 @@ void SCH_DRAWING_TOOLS::setTransitions()
     Go( &SCH_DRAWING_TOOLS::TwoClickPlace,       EE_ACTIONS::importSheetPin.MakeEvent() );
     Go( &SCH_DRAWING_TOOLS::SingleClickPlace,    EE_ACTIONS::importSingleSheetPin.MakeEvent() );
     Go( &SCH_DRAWING_TOOLS::TwoClickPlace,       EE_ACTIONS::placeSchematicText.MakeEvent() );
+    Go( &SCH_DRAWING_TOOLS::DrawShape,           EE_ACTIONS::drawRectangle.MakeEvent() );
+    Go( &SCH_DRAWING_TOOLS::DrawShape,           EE_ACTIONS::drawCircle.MakeEvent() );
+    Go( &SCH_DRAWING_TOOLS::DrawShape,           EE_ACTIONS::drawArc.MakeEvent() );
     Go( &SCH_DRAWING_TOOLS::PlaceImage,          EE_ACTIONS::placeImage.MakeEvent() );
 }
diff --git a/eeschema/tools/sch_drawing_tools.h b/eeschema/tools/sch_drawing_tools.h
index 92a105ef3d..4a959c6d14 100644
--- a/eeschema/tools/sch_drawing_tools.h
+++ b/eeschema/tools/sch_drawing_tools.h
@@ -53,6 +53,7 @@ public:
     int PlaceSymbol( const TOOL_EVENT& aEvent );
     int SingleClickPlace( const TOOL_EVENT& aEvent );
     int TwoClickPlace( const TOOL_EVENT& aEvent );
+    int DrawShape( const TOOL_EVENT& aEvent );
     int DrawSheet( const TOOL_EVENT& aEvent );
     int PlaceImage( const TOOL_EVENT& aEvent );
 
@@ -88,9 +89,11 @@ private:
     LABEL_SPIN_STYLE           m_lastTextOrientation;
     bool                       m_lastTextBold;
     bool                       m_lastTextItalic;
+    FILL_T                     m_lastFillStyle;
 
     ///< Re-entrancy guards
     bool                       m_inPlaceSymbol;
+    bool                       m_inDrawShape;
     bool                       m_inPlaceImage;
     bool                       m_inSingleClickPlace;
     bool                       m_inTwoClickPlace;
diff --git a/eeschema/tools/sch_edit_tool.cpp b/eeschema/tools/sch_edit_tool.cpp
index 6c65db80c8..1f3fb454ad 100644
--- a/eeschema/tools/sch_edit_tool.cpp
+++ b/eeschema/tools/sch_edit_tool.cpp
@@ -28,15 +28,16 @@
 #include <tools/ee_selection_tool.h>
 #include <tools/sch_line_wire_bus_tool.h>
 #include <tools/sch_move_tool.h>
+#include <tools/sch_drawing_tools.h>
 #include <widgets/infobar.h>
 #include <ee_actions.h>
 #include <bitmaps.h>
 #include <confirm.h>
 #include <eda_item.h>
-#include <reporter.h>
 #include <string_utils.h>
 #include <sch_item.h>
 #include <sch_symbol.h>
+#include <sch_shape.h>
 #include <sch_sheet.h>
 #include <sch_sheet_pin.h>
 #include <sch_text.h>
@@ -59,17 +60,15 @@
 #include <dialogs/dialog_sheet_pin_properties.h>
 #include <dialogs/dialog_field_properties.h>
 #include <dialogs/dialog_junction_props.h>
-#include "sch_drawing_tools.h"
+#include <dialogs/dialog_shape_properties.h>
+#include <dialogs/dialog_text_and_label_properties.h>
 #include <math/util.h>      // for KiROUND
 #include <pgm_base.h>
 #include <settings/settings_manager.h>
 #include <symbol_editor_settings.h>
-#include <dialogs/dialog_text_and_label_properties.h>
 #include <core/kicad_algo.h>
 #include <wx/textdlg.h>
 
-
-
 class SYMBOL_UNIT_MENU : public ACTION_MENU
 {
 public:
@@ -415,6 +414,7 @@ bool SCH_EDIT_TOOL::Init()
 
 
 const KICAD_T rotatableItems[] = {
+    SCH_SHAPE_T,
     SCH_TEXT_T,
     SCH_LABEL_T,
     SCH_GLOBAL_LABEL_T,
@@ -533,6 +533,13 @@ int SCH_EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
             break;
         }
 
+        case SCH_SHAPE_T:
+            for( int i = 0; clockwise ? i < 1 : i < 3; ++i )
+                head->Rotate( rotPoint );
+
+            break;
+
+
         case SCH_BITMAP_T:
             for( int i = 0; clockwise ? i < 3 : i < 1; ++i )
                 head->Rotate( rotPoint );
@@ -554,7 +561,7 @@ int SCH_EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
         }
 
         default:
-            break;
+            UNIMPLEMENTED_FOR( head->GetClass() );
         }
 
         connections = head->IsConnectable();
@@ -744,6 +751,14 @@ int SCH_EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent )
             break;
         }
 
+        case SCH_SHAPE_T:
+            if( vertical )
+                item->MirrorVertically( item->GetPosition().y );
+            else
+                item->MirrorHorizontally( item->GetPosition().x );
+
+            break;
+
         case SCH_BITMAP_T:
             if( vertical )
                 item->MirrorVertically( item->GetPosition().y );
@@ -766,7 +781,7 @@ int SCH_EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent )
             break;
 
         default:
-            break;
+            UNIMPLEMENTED_FOR( item->GetClass() );
         }
 
         connections = item->IsConnectable();
@@ -915,6 +930,7 @@ static KICAD_T deletableItems[] =
     SCH_LINE_T,
     SCH_BUS_BUS_ENTRY_T,
     SCH_BUS_WIRE_ENTRY_T,
+    SCH_SHAPE_T,
     SCH_TEXT_T,
     SCH_LABEL_T,
     SCH_GLOBAL_LABEL_T,
@@ -1458,6 +1474,18 @@ int SCH_EDIT_TOOL::Properties( const TOOL_EVENT& aEvent )
     }
         break;
 
+    case SCH_SHAPE_T:
+    {
+        DIALOG_SHAPE_PROPERTIES dlg( m_frame, static_cast<SCH_SHAPE*>( item ) );
+
+        if( dlg.ShowModal() == wxID_OK )
+        {
+            m_toolMgr->PostEvent( EVENTS::SelectedItemsModified );
+            m_frame->OnModify();
+        }
+    }
+        break;
+
     case SCH_BITMAP_T:
     {
         SCH_BITMAP*         bitmap = static_cast<SCH_BITMAP*>( item );
diff --git a/eeschema/tools/sch_editor_control.cpp b/eeschema/tools/sch_editor_control.cpp
index 014afddca6..90d103d585 100644
--- a/eeschema/tools/sch_editor_control.cpp
+++ b/eeschema/tools/sch_editor_control.cpp
@@ -734,8 +734,8 @@ void SCH_EDITOR_CONTROL::doCrossProbeSchToPcb( const TOOL_EVENT& aEvent, bool aF
 
 #ifdef KICAD_SPICE
 
-static KICAD_T wires[] = { SCH_LINE_LOCATE_WIRE_T, EOT };
-static KICAD_T wiresAndPins[] = { SCH_LINE_LOCATE_WIRE_T, SCH_PIN_T, SCH_SHEET_PIN_T, EOT };
+static KICAD_T wires[] = { SCH_ITEM_LOCATE_WIRE_T, EOT };
+static KICAD_T wiresAndPins[] = { SCH_ITEM_LOCATE_WIRE_T, SCH_PIN_T, SCH_SHEET_PIN_T, EOT };
 static KICAD_T fieldsAndSymbols[] = { SCH_SYMBOL_T, SCH_FIELD_T, EOT };
 
 #define HITTEST_THRESHOLD_PIXELS 5
diff --git a/eeschema/tools/sch_line_wire_bus_tool.cpp b/eeschema/tools/sch_line_wire_bus_tool.cpp
index 2483cd5302..ae9091d2d7 100644
--- a/eeschema/tools/sch_line_wire_bus_tool.cpp
+++ b/eeschema/tools/sch_line_wire_bus_tool.cpp
@@ -95,7 +95,7 @@ private:
     {
         SCH_EDIT_FRAME*    frame = (SCH_EDIT_FRAME*) getToolManager()->GetToolHolder();
         EE_SELECTION_TOOL* selTool = getToolManager()->GetTool<EE_SELECTION_TOOL>();
-        KICAD_T            busType[] = { SCH_LINE_LOCATE_BUS_T, EOT };
+        KICAD_T            busType[] = { SCH_ITEM_LOCATE_BUS_T, EOT };
         EE_SELECTION&      selection = selTool->RequestSelection( busType );
         SCH_LINE*          bus = (SCH_LINE*) selection.Front();
 
@@ -200,7 +200,7 @@ bool SCH_LINE_WIRE_BUS_TOOL::Init()
             };
 
     auto busSelection = EE_CONDITIONS::MoreThan( 0 )
-                            && EE_CONDITIONS::OnlyType( SCH_LINE_LOCATE_BUS_T );
+                            && EE_CONDITIONS::OnlyType( SCH_ITEM_LOCATE_BUS_T );
 
     auto& ctxMenu = m_menu.GetMenu();
 
@@ -248,21 +248,21 @@ bool SCH_LINE_WIRE_BUS_TOOL::Init()
 
 bool SCH_LINE_WIRE_BUS_TOOL::IsDrawingLine( const SELECTION& aSelection )
 {
-    static KICAD_T graphicLineType[] = { SCH_LINE_LOCATE_GRAPHIC_LINE_T, EOT };
+    static KICAD_T graphicLineType[] = { SCH_ITEM_LOCATE_GRAPHIC_LINE_T, EOT };
     return IsDrawingLineWireOrBus( aSelection ) && aSelection.Front()->IsType( graphicLineType );
 }
 
 
 bool SCH_LINE_WIRE_BUS_TOOL::IsDrawingWire( const SELECTION& aSelection )
 {
-    static KICAD_T wireType[] = { SCH_LINE_LOCATE_WIRE_T, EOT };
+    static KICAD_T wireType[] = { SCH_ITEM_LOCATE_WIRE_T, EOT };
     return IsDrawingLineWireOrBus( aSelection ) && aSelection.Front()->IsType( wireType );
 }
 
 
 bool SCH_LINE_WIRE_BUS_TOOL::IsDrawingBus( const SELECTION& aSelection )
 {
-    static KICAD_T busType[] = { SCH_LINE_LOCATE_BUS_T, EOT };
+    static KICAD_T busType[] = { SCH_ITEM_LOCATE_BUS_T, EOT };
     return IsDrawingLineWireOrBus( aSelection ) && aSelection.Front()->IsType( busType );
 }
 
diff --git a/eeschema/tools/symbol_editor_drawing_tools.cpp b/eeschema/tools/symbol_editor_drawing_tools.cpp
index ba99507805..04cc88e3a2 100644
--- a/eeschema/tools/symbol_editor_drawing_tools.cpp
+++ b/eeschema/tools/symbol_editor_drawing_tools.cpp
@@ -90,6 +90,15 @@ int SYMBOL_EDITOR_DRAWING_TOOLS::TwoClickPlace( const TOOL_EVENT& aEvent )
                     m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
             };
 
+    auto cleanup =
+            [&] ()
+            {
+                m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
+                m_view->ClearPreview();
+                delete item;
+                item = nullptr;
+            };
+
     Activate();
     // Must be done after Activate() so that it gets set into the correct context
     getViewControls()->ShowCursor( true );
@@ -100,6 +109,9 @@ int SYMBOL_EDITOR_DRAWING_TOOLS::TwoClickPlace( const TOOL_EVENT& aEvent )
     if( aEvent.HasPosition() || ( isText && !aEvent.IsReactivate() ) )
         m_toolMgr->RunAction( ACTIONS::cursorClick );
 
+    // Set initial cursor
+    setCursor();
+
     // Main loop: keep receiving events
     while( TOOL_EVENT* evt = Wait() )
     {
@@ -107,15 +119,6 @@ int SYMBOL_EDITOR_DRAWING_TOOLS::TwoClickPlace( const TOOL_EVENT& aEvent )
 
         cursorPos = getViewControls()->GetCursorPosition( !evt->DisableGridSnapping() );
 
-        auto cleanup =
-                [&] ()
-                {
-                    m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
-                    m_view->ClearPreview();
-                    delete item;
-                    item = nullptr;
-                };
-
         if( evt->IsCancelInteractive() )
         {
             if( item )
@@ -310,7 +313,9 @@ int SYMBOL_EDITOR_DRAWING_TOOLS::DrawShape( const TOOL_EVENT& aEvent )
         if( evt->IsCancelInteractive() )
         {
             if( item )
+            {
                 cleanup();
+            }
             else
             {
                 m_frame->PopTool( tool );
@@ -379,7 +384,7 @@ int SYMBOL_EDITOR_DRAWING_TOOLS::DrawShape( const TOOL_EVENT& aEvent )
         }
         else if( item && ( evt->IsAction( &ACTIONS::refreshPreview ) || evt->IsMotion() ) )
         {
-            item->CalcEdit( wxPoint( cursorPos.x, -cursorPos.y) );
+            item->CalcEdit( wxPoint( cursorPos.x, -cursorPos.y ) );
             m_view->ClearPreview();
             m_view->AddToPreview( item->Clone() );
         }
@@ -514,9 +519,9 @@ void SYMBOL_EDITOR_DRAWING_TOOLS::setTransitions()
 {
     Go( &SYMBOL_EDITOR_DRAWING_TOOLS::TwoClickPlace,  EE_ACTIONS::placeSymbolPin.MakeEvent() );
     Go( &SYMBOL_EDITOR_DRAWING_TOOLS::TwoClickPlace,  EE_ACTIONS::placeSymbolText.MakeEvent() );
-    Go( &SYMBOL_EDITOR_DRAWING_TOOLS::DrawShape,      EE_ACTIONS::drawSymbolRectangle.MakeEvent() );
-    Go( &SYMBOL_EDITOR_DRAWING_TOOLS::DrawShape,      EE_ACTIONS::drawSymbolCircle.MakeEvent() );
-    Go( &SYMBOL_EDITOR_DRAWING_TOOLS::DrawShape,      EE_ACTIONS::drawSymbolArc.MakeEvent() );
+    Go( &SYMBOL_EDITOR_DRAWING_TOOLS::DrawShape,      EE_ACTIONS::drawRectangle.MakeEvent() );
+    Go( &SYMBOL_EDITOR_DRAWING_TOOLS::DrawShape,      EE_ACTIONS::drawCircle.MakeEvent() );
+    Go( &SYMBOL_EDITOR_DRAWING_TOOLS::DrawShape,      EE_ACTIONS::drawArc.MakeEvent() );
     Go( &SYMBOL_EDITOR_DRAWING_TOOLS::DrawShape,      EE_ACTIONS::drawSymbolLines.MakeEvent() );
     Go( &SYMBOL_EDITOR_DRAWING_TOOLS::PlaceAnchor,    EE_ACTIONS::placeSymbolAnchor.MakeEvent() );
     Go( &SYMBOL_EDITOR_DRAWING_TOOLS::RepeatDrawItem, EE_ACTIONS::repeatDrawItem.MakeEvent() );
diff --git a/include/board_item.h b/include/board_item.h
index eec5547d08..707e2d0666 100644
--- a/include/board_item.h
+++ b/include/board_item.h
@@ -32,6 +32,7 @@
 #include <gr_basic.h>
 #include <layer_ids.h>
 #include <geometry/geometry_utils.h>
+#include <stroke_params.h>
 
 class BOARD;
 class BOARD_ITEM_CONTAINER;
@@ -136,6 +137,16 @@ public:
 
     BOARD_ITEM_CONTAINER* GetParentFootprint() const;
 
+    /**
+     * Check if this item has line stoke properties.
+     *
+     * @see #STROKE_PARAMS
+     */
+    virtual bool HasLineStroke() const { return false; }
+
+    virtual STROKE_PARAMS GetStroke() const;
+    virtual void SetStroke( const STROKE_PARAMS& aStroke );
+
     /**
      * Return the primary layer this item is on.
      */
diff --git a/include/core/typeinfo.h b/include/core/typeinfo.h
index 0d11b0241a..e8c572fc93 100644
--- a/include/core/typeinfo.h
+++ b/include/core/typeinfo.h
@@ -127,6 +127,7 @@ enum KICAD_T
     SCH_BUS_WIRE_ENTRY_T,
     SCH_BUS_BUS_ENTRY_T,
     SCH_LINE_T,
+    SCH_SHAPE_T,
     SCH_BITMAP_T,
     SCH_TEXT_T,
     SCH_LABEL_T,
@@ -146,10 +147,10 @@ enum KICAD_T
     SCH_FIELD_LOCATE_FOOTPRINT_T,
     SCH_FIELD_LOCATE_DATASHEET_T,
 
-    // Same for picking wires and buses from SCH_LINE_T items
-    SCH_LINE_LOCATE_WIRE_T,
-    SCH_LINE_LOCATE_BUS_T,
-    SCH_LINE_LOCATE_GRAPHIC_LINE_T,
+    // Same for picking wires, buses and graphics from SCH_ITEM_T items
+    SCH_ITEM_LOCATE_WIRE_T,
+    SCH_ITEM_LOCATE_BUS_T,
+    SCH_ITEM_LOCATE_GRAPHIC_LINE_T,
 
     // Same for picking labels attached to wires and/or buses
     SCH_LABEL_LOCATE_WIRE_T,
@@ -224,7 +225,7 @@ enum KICAD_T
  * Return the underlying type of the given type.
  *
  * This is useful for finding the element type given one of the "non-type" types such as
- * SCH_LINE_LOCATE_WIRE_T.
+ * SCH_ITEM_LOCATE_WIRE_T.
  *
  * @param aType Given type to resolve.
  * @return Base type.
@@ -239,9 +240,9 @@ constexpr KICAD_T BaseType( const KICAD_T aType )
     case SCH_FIELD_LOCATE_DATASHEET_T:
         return SCH_FIELD_T;
 
-    case SCH_LINE_LOCATE_WIRE_T:
-    case SCH_LINE_LOCATE_BUS_T:
-    case SCH_LINE_LOCATE_GRAPHIC_LINE_T:
+    case SCH_ITEM_LOCATE_WIRE_T:
+    case SCH_ITEM_LOCATE_BUS_T:
+    case SCH_ITEM_LOCATE_GRAPHIC_LINE_T:
         return SCH_LINE_T;
 
     case SCH_LABEL_LOCATE_WIRE_T:
@@ -287,9 +288,9 @@ constexpr bool IsInstantiableType( const KICAD_T aType )
     case SCH_FIELD_LOCATE_FOOTPRINT_T:
     case SCH_FIELD_LOCATE_DATASHEET_T:
 
-    case SCH_LINE_LOCATE_WIRE_T:
-    case SCH_LINE_LOCATE_BUS_T:
-    case SCH_LINE_LOCATE_GRAPHIC_LINE_T:
+    case SCH_ITEM_LOCATE_WIRE_T:
+    case SCH_ITEM_LOCATE_BUS_T:
+    case SCH_ITEM_LOCATE_GRAPHIC_LINE_T:
 
     case SCH_LABEL_LOCATE_WIRE_T:
     case SCH_LABEL_LOCATE_BUS_T:
@@ -346,9 +347,9 @@ constexpr bool IsEeschemaType( const KICAD_T aType )
     case SCH_FIELD_LOCATE_FOOTPRINT_T:
     case SCH_FIELD_LOCATE_DATASHEET_T:
 
-    case SCH_LINE_LOCATE_WIRE_T:
-    case SCH_LINE_LOCATE_BUS_T:
-    case SCH_LINE_LOCATE_GRAPHIC_LINE_T:
+    case SCH_ITEM_LOCATE_WIRE_T:
+    case SCH_ITEM_LOCATE_BUS_T:
+    case SCH_ITEM_LOCATE_GRAPHIC_LINE_T:
 
     case SCH_LABEL_LOCATE_WIRE_T:
     case SCH_LABEL_LOCATE_BUS_T:
diff --git a/include/eda_shape.h b/include/eda_shape.h
index d0ba4ef75b..24b007fff6 100644
--- a/include/eda_shape.h
+++ b/include/eda_shape.h
@@ -30,12 +30,14 @@
 #include <trigo.h>
 #include <geometry/shape_poly_set.h>
 #include <geometry/geometry_utils.h>
+#include <stroke_params.h>
 
 class LINE_READER;
 class EDA_DRAW_FRAME;
 class FOOTPRINT;
 class MSG_PANEL_ITEM;
 
+using KIGFX::COLOR4D;
 
 enum class SHAPE_T : int
 {
@@ -75,18 +77,24 @@ public:
 
     wxString SHAPE_T_asString() const;
 
-    void SetFillMode( FILL_T aFill ) { m_fill = aFill; }
-    FILL_T GetFillType() const { return m_fill; }
-
-    bool IsFilled() const { return GetFillType() != FILL_T::NO_FILL; }
+    bool IsFilled() const
+    {
+        return GetFillMode() != FILL_T::NO_FILL;
+    }
 
     void SetFilled( bool aFlag )
     {
         m_fill = aFlag ? FILL_T::FILLED_SHAPE : FILL_T::NO_FILL;
     }
 
-    void SetWidth( int aWidth )             { m_width = aWidth; }
-    int GetWidth() const                    { return m_width; }
+    void SetFillMode( FILL_T aFill )           { m_fill = aFill; }
+    FILL_T GetFillMode() const                 { return m_fill; }
+
+    COLOR4D GetFillColor() const               { return m_fillColor; }
+    void SetFillColor( const COLOR4D& aColor ) { m_fillColor = aColor; }
+
+    void SetWidth( int aWidth )                { m_stroke.SetWidth( aWidth ); }
+    int GetWidth() const                       { return m_stroke.GetWidth(); }
 
     void SetShape( SHAPE_T aShape )         { m_shape = aShape; }
     SHAPE_T GetShape() const                { return m_shape; }
@@ -232,9 +240,12 @@ public:
 
     /**
      * Make a set of SHAPE objects representing the EDA_SHAPE.  Caller owns the objects.
+     *
+     * @param aEdgeOnly indicates only edges should be generated (even if 0 width), and no fill
+     *                  shapes.
      */
     // fixme: move to shape_compound
-    std::vector<SHAPE*> MakeEffectiveShapes() const;
+    std::vector<SHAPE*> MakeEffectiveShapes( bool aEdgeOnly = false ) const;
 
     void ShapeGetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList );
 
@@ -294,8 +305,10 @@ protected:
 protected:
     bool                 m_endsSwapped;  // true if start/end were swapped e.g. SetArcAngleAndEnd
     SHAPE_T              m_shape;        // Shape: line, Circle, Arc
-    int                  m_width;        // thickness of lines ...
+    STROKE_PARAMS        m_stroke;       // Line style, width, etc.
     FILL_T               m_fill;
+    COLOR4D              m_fillColor;
+
     wxPoint              m_start;        // Line start point or Circle center
     wxPoint              m_end;          // Line end point or Circle 3 o'clock point
 
diff --git a/include/layer_ids.h b/include/layer_ids.h
index 40848f09fe..70ecf2fd71 100644
--- a/include/layer_ids.h
+++ b/include/layer_ids.h
@@ -338,6 +338,7 @@ enum SCH_LAYER_ID: int
     LAYER_FIELDS,
     LAYER_DEVICE,
     LAYER_NOTES,
+    LAYER_NOTES_BACKGROUND,
     LAYER_PIN,
     LAYER_SHEET,
     LAYER_SHEETNAME,
diff --git a/include/plotters/plotter.h b/include/plotters/plotter.h
index 0f214449e4..920353010e 100644
--- a/include/plotters/plotter.h
+++ b/include/plotters/plotter.h
@@ -38,6 +38,7 @@
 #include <page_info.h>
 #include <outline_mode.h>
 #include <gal/color4d.h>
+#include <stroke_params.h>
 #include <render_settings.h>
 
 class COLOR_SETTINGS;
@@ -98,20 +99,6 @@ enum class PLOT_TEXT_MODE
     DEFAULT
 };
 
-/**
- * Dashed line types.
- */
-enum class PLOT_DASH_TYPE
-{
-    DEFAULT    = -1,
-    SOLID      = 0,
-    FIRST_TYPE = SOLID,
-    DASH,
-    DOT,
-    DASHDOT,
-    LAST_TYPE = DASHDOT
-};
-
 /**
  * Base plotter engine class. General rule: all the interface with the caller
  * is done in IU, the IU size is specified with SetViewport. Internal and
diff --git a/include/render_settings.h b/include/render_settings.h
index ea0f821faa..1b8f6c0ff6 100644
--- a/include/render_settings.h
+++ b/include/render_settings.h
@@ -203,6 +203,15 @@ public:
     int GetMinPenWidth() const { return m_minPenWidth; }
     void SetMinPenWidth( int aWidth ) { m_minPenWidth = aWidth; }
 
+    double GetDashLengthRatio() const { return m_dashLengthRatio; }
+    void SetDashLengthRatio( double aRatio ) { m_dashLengthRatio = aRatio; }
+    double GetDashLength( int aLineWidth ) const;
+    double GetDotLength( int aLineWidth ) const;
+
+    double GetGapLengthRatio() const { return m_gapLengthRatio; }
+    void SetGapLengthRatio( double aRatio ) { m_gapLengthRatio = aRatio; }
+    double GetGapLength( int aLineWidth ) const;
+
     bool GetShowPageLimits() const { return m_showPageLimits; }
     void SetShowPageLimits( bool aDraw ) { m_showPageLimits = aDraw; }
 
@@ -309,6 +318,9 @@ protected:
     int           m_defaultPenWidth;
     int           m_minPenWidth;          // Some clients (such as PDF) don't like ultra-thin
                                           // lines.  This sets an absolute minimum.
+    double        m_dashLengthRatio;
+    double        m_gapLengthRatio;
+
     bool          m_showPageLimits;
     bool          m_isPrinting;
 
diff --git a/include/stroke_params.h b/include/stroke_params.h
new file mode 100644
index 0000000000..a7b4770d44
--- /dev/null
+++ b/include/stroke_params.h
@@ -0,0 +1,145 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2021 KiCad Developers, see AUTHORS.txt for contributors.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+#ifndef STROKE_PARAMS_H
+#define STROKE_PARAMS_H
+
+#include <map>
+#include <bitmaps.h>
+#include <gal/color4d.h>
+#include <wx/translation.h>
+#include <geometry/shape.h>
+#include <stroke_params_lexer.h>
+
+class STROKE_PARAMS_LEXER;
+
+namespace KIGFX
+{
+class RENDER_SETTINGS;
+}
+
+
+/**
+ * Dashed line types.
+ */
+enum class PLOT_DASH_TYPE
+{
+    DEFAULT    = -1,
+    SOLID      = 0,
+    FIRST_TYPE = SOLID,
+    DASH,
+    DOT,
+    DASHDOT,
+    LAST_TYPE = DASHDOT
+};
+
+
+struct lineTypeStruct
+{
+    wxString      name;
+    const BITMAPS bitmap;
+};
+
+
+/*
+ * Conversion map between PLOT_DASH_TYPE values and style names displayed
+ */
+const std::map<PLOT_DASH_TYPE, struct lineTypeStruct> lineTypeNames =
+{
+    { PLOT_DASH_TYPE::SOLID,      { _( "Solid" ),        BITMAPS::stroke_solid      } },
+    { PLOT_DASH_TYPE::DASH,       { _( "Dashed" ),       BITMAPS::stroke_dash       } },
+    { PLOT_DASH_TYPE::DOT,        { _( "Dotted" ),       BITMAPS::stroke_dot        } },
+    { PLOT_DASH_TYPE::DASHDOT,    { _( "Dash-Dot" ),     BITMAPS::stroke_dashdot    } }
+};
+
+
+#define DEFAULT_STYLE _( "Default" )
+#define INDETERMINATE_STYLE _( "Leave unchanged" )
+
+
+/**
+ * Simple container to manage line stroke parameters.
+ */
+class STROKE_PARAMS
+{
+public:
+    STROKE_PARAMS( int aWidth = 0, PLOT_DASH_TYPE aPlotStyle = PLOT_DASH_TYPE::DEFAULT,
+                   const KIGFX::COLOR4D& aColor = KIGFX::COLOR4D::UNSPECIFIED ) :
+            m_width( aWidth ),
+            m_plotstyle( aPlotStyle ),
+            m_color( aColor )
+    {
+    }
+
+    int GetWidth() const { return m_width; }
+    void SetWidth( int aWidth ) { m_width = aWidth; }
+
+    PLOT_DASH_TYPE GetPlotStyle() const { return m_plotstyle; }
+    void SetPlotStyle( PLOT_DASH_TYPE aPlotStyle ) { m_plotstyle = aPlotStyle; }
+
+    KIGFX::COLOR4D GetColor() const { return m_color; }
+    void SetColor( const KIGFX::COLOR4D& aColor ) { m_color = aColor; }
+
+    bool operator!=( const STROKE_PARAMS& aOther )
+    {
+        return m_width != aOther.m_width
+                || m_plotstyle != aOther.m_plotstyle
+                || m_color != aOther.m_color;
+    }
+
+    void Format( OUTPUTFORMATTER* out, int nestLevel ) const;
+
+    // Helper functions
+
+    static void Stroke( const SHAPE* aShape, PLOT_DASH_TYPE aLineStyle, int aWidth,
+                        const KIGFX::RENDER_SETTINGS* aRenderSettings,
+                        std::function<void( const wxPoint& a, const wxPoint& b )> aStroker );
+
+private:
+    int            m_width;
+    PLOT_DASH_TYPE m_plotstyle;
+    KIGFX::COLOR4D m_color;
+};
+
+
+class STROKE_PARAMS_PARSER : public STROKE_PARAMS_LEXER
+{
+public:
+    STROKE_PARAMS_PARSER( LINE_READER* aReader, int iuPerMM ) :
+            STROKE_PARAMS_LEXER( aReader ),
+            m_iuPerMM( iuPerMM )
+    {
+    }
+
+    void ParseStroke( STROKE_PARAMS& aStroke );
+
+private:
+    int parseInt( const char* aText );
+    double parseDouble( const char* aText );
+
+private:
+    int  m_iuPerMM;
+};
+
+
+#endif  // STROKE_PARAMS_H
diff --git a/libs/kimath/include/geometry/geometry_utils.h b/libs/kimath/include/geometry/geometry_utils.h
index b36b35c942..234bf24579 100644
--- a/libs/kimath/include/geometry/geometry_utils.h
+++ b/libs/kimath/include/geometry/geometry_utils.h
@@ -149,24 +149,5 @@ VECTOR2<T> GetVectorSnapped45( const VECTOR2<T>& aVec, bool only45 = false )
 bool ClipLine( const EDA_RECT *aClipBox, int &x1, int &y1, int &x2, int &y2 );
 
 
-/**
- * Dashed and dotted line patterns.
- */
-
-constexpr double dot_mark_len( double aLineWidth )
-{
-    return std::max( 1.0, aLineWidth );
-}
-
-constexpr double dash_gap_len( double aLineWidth )
-{
-    return 3.0 * dot_mark_len( aLineWidth ) + ( 2.0 * aLineWidth );
-}
-
-constexpr double dash_mark_len( double aLineWidth )
-{
-    return std::max( dash_gap_len( aLineWidth ), 5.0 * dot_mark_len( aLineWidth ) );
-}
-
 #endif  // #ifndef GEOMETRY_UTILS_H
 
diff --git a/pcbnew/board_item.cpp b/pcbnew/board_item.cpp
index b30a661443..4aca8d3d2c 100644
--- a/pcbnew/board_item.cpp
+++ b/pcbnew/board_item.cpp
@@ -30,6 +30,7 @@
 #include <i18n_utility.h>
 #include <macros.h>
 #include <board.h>
+#include <board_design_settings.h>
 #include <pcb_group.h>
 
 
@@ -72,6 +73,18 @@ bool BOARD_ITEM::IsLocked() const
 }
 
 
+STROKE_PARAMS BOARD_ITEM::GetStroke() const
+{
+    wxCHECK( false, STROKE_PARAMS( Millimeter2iu( DEFAULT_LINE_WIDTH ) ) );
+}
+
+
+void BOARD_ITEM::SetStroke( const STROKE_PARAMS& aStroke )
+{
+    wxCHECK( false, /* void */ );
+}
+
+
 wxString BOARD_ITEM::GetLayerName() const
 {
     const BOARD* board = GetBoard();
diff --git a/pcbnew/convert_shape_list_to_polygon.cpp b/pcbnew/convert_shape_list_to_polygon.cpp
index 4300018cfe..5e0dfce5aa 100644
--- a/pcbnew/convert_shape_list_to_polygon.cpp
+++ b/pcbnew/convert_shape_list_to_polygon.cpp
@@ -745,8 +745,7 @@ bool ConvertOutlineToPolygon( std::vector<PCB_SHAPE*>& aSegList, SHAPE_POLY_SET&
                     break;
 
                 default:
-                    wxFAIL_MSG( "ConvertOutlineToPolygon not implemented for "
-                                + graphic->SHAPE_T_asString() );
+                    UNIMPLEMENTED_FOR( graphic->SHAPE_T_asString() );
                     return false;
                 }
 
diff --git a/pcbnew/dialogs/dialog_global_edit_text_and_graphics.cpp b/pcbnew/dialogs/dialog_global_edit_text_and_graphics.cpp
index 93169a33c0..d22e69cfe0 100644
--- a/pcbnew/dialogs/dialog_global_edit_text_and_graphics.cpp
+++ b/pcbnew/dialogs/dialog_global_edit_text_and_graphics.cpp
@@ -320,7 +320,11 @@ void DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::processItem( BOARD_COMMIT& aCommit, B
         if( !m_lineWidth.IsIndeterminate() )
         {
             if( drawItem )
-                drawItem->SetWidth( m_lineWidth.GetValue() );
+            {
+                STROKE_PARAMS stroke = drawItem->GetStroke();
+                stroke.SetWidth( m_lineWidth.GetValue() );
+                drawItem->SetStroke( stroke );
+            }
 
             if( dimension )
                 dimension->SetLineThickness( m_lineWidth.GetValue() );
@@ -341,7 +345,11 @@ void DIALOG_GLOBAL_EDIT_TEXT_AND_GRAPHICS::processItem( BOARD_COMMIT& aCommit, B
             fpTextItem->SetKeepUpright( m_brdSettings->GetTextUpright( layer ) );
 
         if( drawItem )
-            drawItem->SetWidth( m_brdSettings->GetLineThickness( layer ) );
+        {
+            STROKE_PARAMS stroke = drawItem->GetStroke();
+            stroke.SetWidth( m_brdSettings->GetLineThickness( layer ) );
+            drawItem->SetStroke( stroke );
+        }
 
         if( dimension )
             dimension->SetLineThickness( m_brdSettings->GetLineThickness( layer ) );
diff --git a/pcbnew/dialogs/dialog_graphic_item_properties.cpp b/pcbnew/dialogs/dialog_graphic_item_properties.cpp
index 74c8d7a674..99cc62dac5 100644
--- a/pcbnew/dialogs/dialog_graphic_item_properties.cpp
+++ b/pcbnew/dialogs/dialog_graphic_item_properties.cpp
@@ -338,7 +338,11 @@ bool DIALOG_GRAPHIC_ITEM_PROPERTIES::TransferDataFromWindow()
 
     m_item->SetFilled( m_filledCtrl->GetValue() );
     m_item->SetLocked( m_locked->GetValue() );
-    m_item->SetWidth( m_thickness.GetValue() );
+
+    STROKE_PARAMS stroke = m_item->GetStroke();
+    stroke.SetWidth( m_thickness.GetValue() );
+    m_item->SetStroke( stroke );
+
     m_item->SetLayer( ToLAYER_ID( layer ) );
 
     m_item->RebuildBezierToSegmentsPointsList( m_item->GetWidth() );
diff --git a/pcbnew/dialogs/dialog_pad_basicshapes_properties.cpp b/pcbnew/dialogs/dialog_pad_basicshapes_properties.cpp
index 4c55fa74b0..0653e50574 100644
--- a/pcbnew/dialogs/dialog_pad_basicshapes_properties.cpp
+++ b/pcbnew/dialogs/dialog_pad_basicshapes_properties.cpp
@@ -181,7 +181,10 @@ bool DIALOG_PAD_PRIMITIVES_PROPERTIES::TransferDataFromWindow()
     }
 
     // Transfer data out of the GUI.
-    m_shape->SetWidth( m_thickness.GetValue() );
+    STROKE_PARAMS stroke = m_shape->GetStroke();
+    stroke.SetWidth( m_thickness.GetValue() );
+    m_shape->SetStroke( stroke );
+
     m_shape->SetFilled( m_filledCtrl->GetValue() );
 
     switch( m_shape->GetShape() )
@@ -311,7 +314,11 @@ bool DIALOG_PAD_PRIMITIVE_POLY_PROPS::TransferDataFromWindow()
         return false;
 
     m_shape->SetPolyPoints( m_currPoints );
-    m_shape->SetWidth( m_thickness.GetValue() );
+
+    STROKE_PARAMS stroke = m_shape->GetStroke();
+    stroke.SetWidth( m_thickness.GetValue() );
+    m_shape->SetStroke( stroke );
+
     m_shape->SetFilled( m_filledCtrl->GetValue() );
 
     return true;
@@ -616,7 +623,10 @@ void DIALOG_PAD_PRIMITIVES_TRANSFORM::Transform( std::vector<std::shared_ptr<PCB
             }
 
             // Transform parameters common to all shape types (some can be unused)
-            shape->SetWidth( KiROUND( shape->GetWidth() * scale ) );
+            STROKE_PARAMS stroke = shape->GetStroke();
+            stroke.SetWidth( KiROUND( shape->GetWidth() * scale ) );
+            shape->SetStroke( stroke );
+
             shape->Move( currMoveVect );
             shape->Scale( scale );
             shape->Rotate( wxPoint( 0, 0 ), curr_rotation );
diff --git a/pcbnew/dialogs/dialog_pad_properties.cpp b/pcbnew/dialogs/dialog_pad_properties.cpp
index d17eb091db..e24590ffd1 100644
--- a/pcbnew/dialogs/dialog_pad_properties.cpp
+++ b/pcbnew/dialogs/dialog_pad_properties.cpp
@@ -2142,7 +2142,8 @@ void DIALOG_PAD_PROPERTIES::onAddPrimitive( wxCommandEvent& event )
 
     PCB_SHAPE* primitive = new PCB_SHAPE();
     primitive->SetShape( listtype[type] );
-    primitive->SetWidth( m_board->GetDesignSettings().GetLineThickness( F_Cu ) );
+    primitive->SetStroke( STROKE_PARAMS( m_board->GetDesignSettings().GetLineThickness( F_Cu ),
+                                         PLOT_DASH_TYPE::SOLID ) );
     primitive->SetFilled( true );
 
     if( listtype[type] == SHAPE_T::POLY )
diff --git a/pcbnew/drc/drc_test_provider_edge_clearance.cpp b/pcbnew/drc/drc_test_provider_edge_clearance.cpp
index 6ef6b42e6d..7891d910ee 100644
--- a/pcbnew/drc/drc_test_provider_edge_clearance.cpp
+++ b/pcbnew/drc/drc_test_provider_edge_clearance.cpp
@@ -148,7 +148,8 @@ bool DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run()
     auto queryBoardOutlineItems =
             [&]( BOARD_ITEM *item ) -> bool
             {
-                PCB_SHAPE* shape = static_cast<PCB_SHAPE*>( item );
+                PCB_SHAPE*    shape = static_cast<PCB_SHAPE*>( item );
+                STROKE_PARAMS stroke( 0 );
 
                 if( shape->GetShape() == SHAPE_T::RECT )
                 {
@@ -157,19 +158,19 @@ bool DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run()
                     edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) );
                     edges.back()->SetShape( SHAPE_T::SEGMENT );
                     edges.back()->SetEndX( shape->GetStartX() );
-                    edges.back()->SetWidth( 0 );
+                    edges.back()->SetStroke( stroke );
                     edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) );
                     edges.back()->SetShape( SHAPE_T::SEGMENT );
                     edges.back()->SetEndY( shape->GetStartY() );
-                    edges.back()->SetWidth( 0 );
+                    edges.back()->SetStroke( stroke );
                     edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) );
                     edges.back()->SetShape( SHAPE_T::SEGMENT );
                     edges.back()->SetStartX( shape->GetEndX() );
-                    edges.back()->SetWidth( 0 );
+                    edges.back()->SetStroke( stroke );
                     edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) );
                     edges.back()->SetShape( SHAPE_T::SEGMENT );
                     edges.back()->SetStartY( shape->GetEndY() );
-                    edges.back()->SetWidth( 0 );
+                    edges.back()->SetStroke( stroke );
                     return true;
                 }
                 else if( shape->GetShape() == SHAPE_T::POLY )
@@ -185,12 +186,12 @@ bool DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run()
                         edges.back()->SetShape( SHAPE_T::SEGMENT );
                         edges.back()->SetStart((wxPoint) seg.A );
                         edges.back()->SetEnd((wxPoint) seg.B );
-                        edges.back()->SetWidth( 0 );
+                        edges.back()->SetStroke( stroke );
                     }
                 }
 
                 edges.emplace_back( static_cast<PCB_SHAPE*>( shape->Clone() ) );
-                edges.back()->SetWidth( 0 );
+                edges.back()->SetStroke( stroke );
                 return true;
             };
 
diff --git a/pcbnew/drc/drc_test_provider_library_parity.cpp b/pcbnew/drc/drc_test_provider_library_parity.cpp
index 424339c3d3..b9dff417d7 100644
--- a/pcbnew/drc/drc_test_provider_library_parity.cpp
+++ b/pcbnew/drc/drc_test_provider_library_parity.cpp
@@ -22,6 +22,7 @@
  */
 
 #include <kiway.h>
+#include <macros.h>
 #include <netlist_reader/pcb_netlist.h>
 #include <fp_lib_table.h>
 #include <board.h>
diff --git a/pcbnew/exporters/export_gencad.cpp b/pcbnew/exporters/export_gencad.cpp
index d9f588f410..e1668433a3 100644
--- a/pcbnew/exporters/export_gencad.cpp
+++ b/pcbnew/exporters/export_gencad.cpp
@@ -442,7 +442,7 @@ static void CreatePadsShapesSection( FILE* aFile, BOARD* aPcb )
         switch( pad->GetShape() )
         {
         default:
-            wxASSERT_MSG( false, "Pad type not implemented" );
+            UNIMPLEMENTED_FOR( pad->ShowPadShape() );
             KI_FALLTHROUGH;
 
         case PAD_SHAPE::CIRCLE:
diff --git a/pcbnew/fp_shape.cpp b/pcbnew/fp_shape.cpp
index 9cd1a3f7ac..ddb73b9b99 100644
--- a/pcbnew/fp_shape.cpp
+++ b/pcbnew/fp_shape.cpp
@@ -103,7 +103,7 @@ void FP_SHAPE::SetDrawCoord()
         m_bezierC2  += fp->GetPosition();
     }
 
-    RebuildBezierToSegmentsPointsList( m_width );
+    RebuildBezierToSegmentsPointsList( GetWidth() );
 }
 
 
@@ -247,7 +247,7 @@ void FP_SHAPE::Flip( const wxPoint& aCentre, bool aFlipLeftRight )
         }
 
         if( GetShape() == SHAPE_T::BEZIER )
-            RebuildBezierToSegmentsPointsList( m_width );
+            RebuildBezierToSegmentsPointsList( GetWidth() );
 
         if( GetShape() == SHAPE_T::ARC )
         {
@@ -306,7 +306,7 @@ void FP_SHAPE::Mirror( const wxPoint& aCentre, bool aMirrorAroundXAxis )
         }
 
         if( GetShape() == SHAPE_T::BEZIER )
-            RebuildBezierToSegmentsPointsList( m_width );
+            RebuildBezierToSegmentsPointsList( GetWidth() );
 
         break;
 
diff --git a/pcbnew/graphics_cleaner.cpp b/pcbnew/graphics_cleaner.cpp
index 53a63c947b..f38561a51d 100644
--- a/pcbnew/graphics_cleaner.cpp
+++ b/pcbnew/graphics_cleaner.cpp
@@ -308,7 +308,7 @@ void GRAPHICS_CLEANER::mergeRects()
                     rect->SetStart( top->start );
                     rect->SetEnd( bottom->end );
                     rect->SetLayer( top->shape->GetLayer() );
-                    rect->SetWidth( top->shape->GetWidth() );
+                    rect->SetStroke( top->shape->GetStroke() );
 
                     m_commit.Add( rect );
                     m_commit.Remove( left->shape );
diff --git a/pcbnew/import_gfx/graphics_importer_pcbnew.cpp b/pcbnew/import_gfx/graphics_importer_pcbnew.cpp
index 629420e01b..6dd7d4e3a0 100644
--- a/pcbnew/import_gfx/graphics_importer_pcbnew.cpp
+++ b/pcbnew/import_gfx/graphics_importer_pcbnew.cpp
@@ -59,12 +59,13 @@ int GRAPHICS_IMPORTER_PCBNEW::MapLineWidth( double aLineWidth )
 }
 
 
-void GRAPHICS_IMPORTER_PCBNEW::AddLine( const VECTOR2D& aOrigin, const VECTOR2D& aEnd, double aWidth )
+void GRAPHICS_IMPORTER_PCBNEW::AddLine( const VECTOR2D& aOrigin, const VECTOR2D& aEnd,
+                                        double aWidth )
 {
     std::unique_ptr<PCB_SHAPE> line( createDrawing() );
     line->SetShape( SHAPE_T::SEGMENT );
     line->SetLayer( GetLayer() );
-    line->SetWidth( MapLineWidth( aWidth ) );
+    line->SetStroke( STROKE_PARAMS( MapLineWidth( aWidth ), PLOT_DASH_TYPE::SOLID ) );
     line->SetStart( MapCoordinate( aOrigin ) );
     line->SetEnd( MapCoordinate( aEnd ) );
 
@@ -75,13 +76,14 @@ void GRAPHICS_IMPORTER_PCBNEW::AddLine( const VECTOR2D& aOrigin, const VECTOR2D&
 }
 
 
-void GRAPHICS_IMPORTER_PCBNEW::AddCircle( const VECTOR2D& aCenter, double aRadius, double aWidth, bool aFilled )
+void GRAPHICS_IMPORTER_PCBNEW::AddCircle( const VECTOR2D& aCenter, double aRadius, double aWidth,
+                                          bool aFilled )
 {
     std::unique_ptr<PCB_SHAPE> circle( createDrawing() );
     circle->SetShape( SHAPE_T::CIRCLE );
     circle->SetFilled( aFilled );
     circle->SetLayer( GetLayer() );
-    circle->SetWidth( MapLineWidth( aWidth ) );
+    circle->SetStroke( STROKE_PARAMS( MapLineWidth( aWidth ), PLOT_DASH_TYPE::SOLID ) );
     circle->SetStart( MapCoordinate( aCenter ));
     circle->SetEnd( MapCoordinate( VECTOR2D( aCenter.x + aRadius, aCenter.y ) ) );
 
@@ -111,7 +113,7 @@ void GRAPHICS_IMPORTER_PCBNEW::AddArc( const VECTOR2D& aCenter, const VECTOR2D&
 
     arc->SetArcGeometry( MapCoordinate( aStart ), MapCoordinate( mid ), MapCoordinate( end ) );
 
-    arc->SetWidth( MapLineWidth( aWidth ) );
+    arc->SetStroke( STROKE_PARAMS( MapLineWidth( aWidth ), PLOT_DASH_TYPE::SOLID ) );
 
     if( arc->Type() == PCB_FP_SHAPE_T )
         static_cast<FP_SHAPE*>( arc.get() )->SetLocalCoord();
@@ -137,14 +139,15 @@ void GRAPHICS_IMPORTER_PCBNEW::AddPolygon( const std::vector< VECTOR2D >& aVerti
     if( polygon->Type() == PCB_FP_SHAPE_T )
         static_cast<FP_SHAPE*>( polygon.get() )->SetLocalCoord();
 
-    polygon->SetWidth( MapLineWidth( aWidth ) );
+    polygon->SetStroke( STROKE_PARAMS( MapLineWidth( aWidth ), PLOT_DASH_TYPE::SOLID ) );
     addItem( std::move( polygon ) );
 }
 
 
 void GRAPHICS_IMPORTER_PCBNEW::AddText( const VECTOR2D& aOrigin, const wxString& aText,
-        double aHeight, double aWidth, double aThickness, double aOrientation,
-        EDA_TEXT_HJUSTIFY_T aHJustify, EDA_TEXT_VJUSTIFY_T aVJustify )
+                                        double aHeight, double aWidth, double aThickness,
+                                        double aOrientation, EDA_TEXT_HJUSTIFY_T aHJustify,
+                                        EDA_TEXT_VJUSTIFY_T aVJustify )
 {
     std::unique_ptr<BOARD_ITEM> boardItem;
     EDA_TEXT* textItem;
@@ -167,12 +170,13 @@ void GRAPHICS_IMPORTER_PCBNEW::AddText( const VECTOR2D& aOrigin, const wxString&
 
 
 void GRAPHICS_IMPORTER_PCBNEW::AddSpline( const VECTOR2D& aStart, const VECTOR2D& BezierControl1,
-                const VECTOR2D& BezierControl2, const VECTOR2D& aEnd, double aWidth )
+                                          const VECTOR2D& BezierControl2, const VECTOR2D& aEnd,
+                                          double aWidth )
 {
     std::unique_ptr<PCB_SHAPE> spline( createDrawing() );
     spline->SetShape( SHAPE_T::BEZIER );
     spline->SetLayer( GetLayer() );
-    spline->SetWidth( MapLineWidth( aWidth ) );
+    spline->SetStroke( STROKE_PARAMS( MapLineWidth( aWidth ), PLOT_DASH_TYPE::SOLID ) );
     spline->SetStart( MapCoordinate( aStart ) );
     spline->SetBezierC1( MapCoordinate( BezierControl1 ));
     spline->SetBezierC2( MapCoordinate( BezierControl2 ));
diff --git a/pcbnew/microwave/microwave_inductor.cpp b/pcbnew/microwave/microwave_inductor.cpp
index 6e3dcf24fa..cbbe12cbdc 100644
--- a/pcbnew/microwave/microwave_inductor.cpp
+++ b/pcbnew/microwave/microwave_inductor.cpp
@@ -427,7 +427,7 @@ FOOTPRINT* MICROWAVE_TOOL::createMicrowaveInductor( MICROWAVE_INDUCTOR_PATTERN&
         FP_SHAPE* seg = new FP_SHAPE( footprint, SHAPE_T::SEGMENT );
         seg->SetStart( buffer[jj - 1] );
         seg->SetEnd( buffer[jj] );
-        seg->SetWidth( aInductorPattern.m_Width );
+        seg->SetStroke( STROKE_PARAMS( aInductorPattern.m_Width, PLOT_DASH_TYPE::SOLID ) );
         seg->SetLayer( footprint->GetLayer() );
         seg->SetStart0( seg->GetStart() - footprint->GetPosition() );
         seg->SetEnd0( seg->GetEnd() - footprint->GetPosition() );
diff --git a/pcbnew/microwave/microwave_polygon.cpp b/pcbnew/microwave/microwave_polygon.cpp
index 14f85e8fd7..c1c832145b 100644
--- a/pcbnew/microwave/microwave_polygon.cpp
+++ b/pcbnew/microwave/microwave_polygon.cpp
@@ -389,7 +389,7 @@ FOOTPRINT* MICROWAVE_TOOL::createPolygonShape()
 
     // Set the polygon outline thickness to 0, only the polygonal shape is filled
     // without extra thickness.
-    shape->SetWidth( 0 );
+    shape->SetStroke( STROKE_PARAMS( 0, PLOT_DASH_TYPE::SOLID ) );
     g_PolyEdges.clear();
 
     editFrame.OnModify();
diff --git a/pcbnew/pad_custom_shape_functions.cpp b/pcbnew/pad_custom_shape_functions.cpp
index 62778824e5..185a369429 100644
--- a/pcbnew/pad_custom_shape_functions.cpp
+++ b/pcbnew/pad_custom_shape_functions.cpp
@@ -48,7 +48,7 @@ void PAD::AddPrimitivePoly( const SHAPE_POLY_SET& aPoly, int aThickness, bool aF
     item->SetShape( SHAPE_T::POLY );
     item->SetFilled( aFilled );
     item->SetPolyShape( poly_no_hole );
-    item->SetWidth( aThickness );
+    item->SetStroke( STROKE_PARAMS( aThickness, PLOT_DASH_TYPE::SOLID ) );
     item->SetParent( this );
     m_editPrimitives.emplace_back( item );
     SetDirty();
@@ -60,7 +60,7 @@ void PAD::AddPrimitivePoly( const std::vector<wxPoint>& aPoly, int aThickness, b
     PCB_SHAPE* item = new PCB_SHAPE( nullptr, SHAPE_T::POLY );
     item->SetFilled( aFilled );
     item->SetPolyPoints( aPoly );
-    item->SetWidth( aThickness );
+    item->SetStroke( STROKE_PARAMS( aThickness, PLOT_DASH_TYPE::SOLID ) );
     item->SetParent( this );
     m_editPrimitives.emplace_back( item );
     SetDirty();
@@ -73,7 +73,7 @@ void PAD::AddPrimitiveSegment( const wxPoint& aStart, const wxPoint& aEnd, int a
     item->SetFilled( false );
     item->SetStart( aStart );
     item->SetEnd( aEnd );
-    item->SetWidth( aThickness );
+    item->SetStroke( STROKE_PARAMS( aThickness, PLOT_DASH_TYPE::SOLID ) );
     item->SetParent( this );
     m_editPrimitives.emplace_back( item );
     SetDirty();
@@ -88,7 +88,7 @@ void PAD::AddPrimitiveArc( const wxPoint& aCenter, const wxPoint& aStart, int aA
     item->SetCenter( aCenter );
     item->SetStart( aStart );
     item->SetArcAngleAndEnd( aArcAngle );
-    item->SetWidth( aThickness );
+    item->SetStroke( STROKE_PARAMS( aThickness, PLOT_DASH_TYPE::SOLID ) );
     item->SetParent( this );
     m_editPrimitives.emplace_back( item );
     SetDirty();
@@ -104,7 +104,7 @@ void PAD::AddPrimitiveCurve( const wxPoint& aStart, const wxPoint& aEnd, const w
     item->SetEnd( aEnd );
     item->SetBezierC1( aCtrl1 );
     item->SetBezierC2( aCtrl2 );
-    item->SetWidth( aThickness );
+    item->SetStroke( STROKE_PARAMS( aThickness, PLOT_DASH_TYPE::SOLID ) );
     item->SetParent( this );
     m_editPrimitives.emplace_back( item );
     SetDirty();
@@ -117,7 +117,7 @@ void PAD::AddPrimitiveCircle( const wxPoint& aCenter, int aRadius, int aThicknes
     item->SetFilled( aFilled );
     item->SetStart( aCenter );
     item->SetEnd( wxPoint( aCenter.x + aRadius, aCenter.y ) );
-    item->SetWidth( aThickness );
+    item->SetStroke( STROKE_PARAMS( aThickness, PLOT_DASH_TYPE::SOLID ) );
     item->SetParent( this );
     m_editPrimitives.emplace_back( item );
     SetDirty();
@@ -131,7 +131,7 @@ void PAD::AddPrimitiveRect( const wxPoint& aStart, const wxPoint& aEnd, int aThi
     item->SetFilled( aFilled );
     item->SetStart( aStart );
     item->SetEnd( aEnd );
-    item->SetWidth( aThickness );
+    item->SetStroke( STROKE_PARAMS( aThickness, PLOT_DASH_TYPE::SOLID ) );
     item->SetParent( this );
     m_editPrimitives.emplace_back( item );
     SetDirty();
diff --git a/pcbnew/pcb_shape.cpp b/pcbnew/pcb_shape.cpp
index ccb5eb9ae7..bd50532ea1 100644
--- a/pcbnew/pcb_shape.cpp
+++ b/pcbnew/pcb_shape.cpp
@@ -254,8 +254,9 @@ static struct PCB_SHAPE_DESC
         propMgr.InheritsAfter( TYPE_HASH( PCB_SHAPE ), TYPE_HASH( BOARD_ITEM ) );
         propMgr.InheritsAfter( TYPE_HASH( PCB_SHAPE ), TYPE_HASH( EDA_SHAPE ) );
 
-        propMgr.AddProperty( new PROPERTY<EDA_SHAPE, int>( _HKI( "Thickness" ),
-                    &EDA_SHAPE::SetWidth, &EDA_SHAPE::GetWidth, PROPERTY_DISPLAY::DISTANCE ) );
+        // JEY TODO:
+        //propMgr.AddProperty( new PROPERTY<EDA_SHAPE, int>( _HKI( "Thickness" ),
+        //            &EDA_SHAPE::SetWidth, &EDA_SHAPE::GetWidth, PROPERTY_DISPLAY::DISTANCE ) );
         // TODO show certain properties depending on the shape
         //propMgr.AddProperty( new PROPERTY<PCB_SHAPE, double>( _HKI( "Angle" ),
         //            &PCB_SHAPE::SetArcAngle, &PCB_SHAPE::GetAngle, PROPERTY_DISPLAY::DECIDEGREE ) );
diff --git a/pcbnew/pcb_shape.h b/pcbnew/pcb_shape.h
index da89061256..fee90d02ef 100644
--- a/pcbnew/pcb_shape.h
+++ b/pcbnew/pcb_shape.h
@@ -78,6 +78,11 @@ public:
 
     wxPoint GetCenter() const override { return getCenter(); }
 
+    bool HasLineStroke() const override { return true; }
+
+    STROKE_PARAMS GetStroke() const override { return m_stroke; }
+    void SetStroke( const STROKE_PARAMS& aStroke ) override { m_stroke = aStroke; }
+
     /**
      * Allows items to return their visual center rather than their anchor. For some shapes this
      * is similar to GetCenter(), but for unfilled shapes a point on the outline is better.
diff --git a/pcbnew/pcbnew.cpp b/pcbnew/pcbnew.cpp
index 8407508560..8a0daeb964 100644
--- a/pcbnew/pcbnew.cpp
+++ b/pcbnew/pcbnew.cpp
@@ -319,7 +319,7 @@ void IFACE::SaveFileAs( const wxString& aProjectBasePath, const wxString& aSrcPr
     }
     else if( ext == FootprintAssignmentFileExtension )
     {
-        // JEY TODO
+        // TODO
     }
     else if( ext == "rpt" )
     {
diff --git a/pcbnew/plot_brditems_plotter.cpp b/pcbnew/plot_brditems_plotter.cpp
index 183f92b297..6ee0c5a23b 100644
--- a/pcbnew/plot_brditems_plotter.cpp
+++ b/pcbnew/plot_brditems_plotter.cpp
@@ -421,7 +421,7 @@ void BRDITEMS_PLOTTER::PlotDimension( const PCB_DIMENSION_BASE* aDim )
 
     PCB_SHAPE draw;
 
-    draw.SetWidth( aDim->GetLineThickness() );
+    draw.SetStroke( STROKE_PARAMS( aDim->GetLineThickness(), PLOT_DASH_TYPE::SOLID ) );
     draw.SetLayer( aDim->GetLayer() );
 
     COLOR4D color = ColorSettings()->GetColor( aDim->GetLayer() );
@@ -482,7 +482,7 @@ void BRDITEMS_PLOTTER::PlotPcbTarget( const PCB_TARGET* aMire )
 
     draw.SetShape( SHAPE_T::CIRCLE );
     draw.SetFilled( false );
-    draw.SetWidth( aMire->GetWidth() );
+    draw.SetStroke( STROKE_PARAMS( aMire->GetWidth(), PLOT_DASH_TYPE::SOLID ) );
     draw.SetLayer( aMire->GetLayer() );
     draw.SetStart( aMire->GetPosition() );
     radius = aMire->GetSize() / 3;
diff --git a/pcbnew/plugins/altium/altium_pcb.cpp b/pcbnew/plugins/altium/altium_pcb.cpp
index 5cc5886bd3..7d4ed36d4f 100644
--- a/pcbnew/plugins/altium/altium_pcb.cpp
+++ b/pcbnew/plugins/altium/altium_pcb.cpp
@@ -848,6 +848,9 @@ void ALTIUM_PCB::HelperCreateBoardOutline( const std::vector<ALTIUM_VERTICE>& aV
     if( !aVertices.empty() )
     {
         const ALTIUM_VERTICE* last = &aVertices.at( 0 );
+        STROKE_PARAMS         stroke( m_board->GetDesignSettings().GetLineThickness( Edge_Cuts ),
+                                      PLOT_DASH_TYPE::SOLID );
+
         for( size_t i = 0; i < aVertices.size(); i++ )
         {
             const ALTIUM_VERTICE* cur = &aVertices.at( ( i + 1 ) % aVertices.size() );
@@ -855,7 +858,7 @@ void ALTIUM_PCB::HelperCreateBoardOutline( const std::vector<ALTIUM_VERTICE>& aV
             PCB_SHAPE* shape = new PCB_SHAPE( m_board );
             m_board->Add( shape, ADD_MODE::APPEND );
 
-            shape->SetWidth( m_board->GetDesignSettings().GetLineThickness( Edge_Cuts ) );
+            shape->SetStroke( stroke );
             shape->SetLayer( Edge_Cuts );
 
             if( !last->isRound && !cur->isRound )
@@ -887,7 +890,7 @@ void ALTIUM_PCB::HelperCreateBoardOutline( const std::vector<ALTIUM_VERTICE>& aV
 
                     PCB_SHAPE* shape2 = new PCB_SHAPE( m_board, SHAPE_T::SEGMENT );
                     m_board->Add( shape2, ADD_MODE::APPEND );
-                    shape2->SetWidth( m_board->GetDesignSettings().GetLineThickness( Edge_Cuts ) );
+                    shape2->SetStroke( stroke );
                     shape2->SetLayer( Edge_Cuts );
                     shape2->SetStart( last->position );
 
@@ -1245,7 +1248,7 @@ void ALTIUM_PCB::HelperParseDimensions6Leader( const ADIMENSION6& aElem )
             PCB_SHAPE* shape = new PCB_SHAPE( m_board, SHAPE_T::SEGMENT );
             m_board->Add( shape, ADD_MODE::APPEND );
             shape->SetLayer( klayer );
-            shape->SetWidth( aElem.linewidth );
+            shape->SetStroke( STROKE_PARAMS( aElem.linewidth, PLOT_DASH_TYPE::SOLID ) );
             shape->SetStart( last );
             shape->SetEnd( aElem.referencePoint.at( i ) );
             last = aElem.referencePoint.at( i );
@@ -1265,7 +1268,7 @@ void ALTIUM_PCB::HelperParseDimensions6Leader( const ADIMENSION6& aElem )
                 PCB_SHAPE* shape1 = new PCB_SHAPE( m_board, SHAPE_T::SEGMENT );
                 m_board->Add( shape1, ADD_MODE::APPEND );
                 shape1->SetLayer( klayer );
-                shape1->SetWidth( aElem.linewidth );
+                shape1->SetStroke( STROKE_PARAMS( aElem.linewidth, PLOT_DASH_TYPE::SOLID ) );
                 shape1->SetStart( referencePoint0 );
                 shape1->SetEnd( referencePoint0 + arrVec );
 
@@ -1274,7 +1277,7 @@ void ALTIUM_PCB::HelperParseDimensions6Leader( const ADIMENSION6& aElem )
                 PCB_SHAPE* shape2 = new PCB_SHAPE( m_board, SHAPE_T::SEGMENT );
                 m_board->Add( shape2, ADD_MODE::APPEND );
                 shape2->SetLayer( klayer );
-                shape2->SetWidth( aElem.linewidth );
+                shape2->SetStroke( STROKE_PARAMS( aElem.linewidth, PLOT_DASH_TYPE::SOLID ) );
                 shape2->SetStart( referencePoint0 );
                 shape2->SetEnd( referencePoint0 + arrVec );
             }
@@ -1316,7 +1319,7 @@ void ALTIUM_PCB::HelperParseDimensions6Datum( const ADIMENSION6& aElem )
         PCB_SHAPE* shape = new PCB_SHAPE( m_board, SHAPE_T::SEGMENT );
         m_board->Add( shape, ADD_MODE::APPEND );
         shape->SetLayer( klayer );
-        shape->SetWidth( aElem.linewidth );
+        shape->SetStroke( STROKE_PARAMS( aElem.linewidth, PLOT_DASH_TYPE::SOLID ) );
         shape->SetStart( aElem.referencePoint.at( i ) );
         // shape->SetEnd( /* TODO: seems to be based on TEXTY */ );
     }
@@ -1795,7 +1798,7 @@ void ALTIUM_PCB::ParseShapeBasedRegions6Data( const CFB::CompoundFileReader& aRe
                 m_board->Add( shape, ADD_MODE::APPEND );
                 shape->SetFilled( true );
                 shape->SetLayer( klayer );
-                shape->SetWidth( 0 );
+                shape->SetStroke( STROKE_PARAMS( 0 ) );
 
                 shape->SetPolyShape( linechain );
             }
@@ -1926,7 +1929,7 @@ void ALTIUM_PCB::ParseArcs6Data( const CFB::CompoundFileReader& aReader,
         if( elem.is_keepout || IsAltiumLayerAPlane( elem.layer ) )
         {
             PCB_SHAPE shape( nullptr ); // just a helper to get the graphic
-            shape.SetWidth( elem.width );
+            shape.SetStroke( STROKE_PARAMS( elem.width, PLOT_DASH_TYPE::SOLID ) );
 
             if( elem.startangle == 0. && elem.endangle == 360. )
             { // TODO: other variants to define circle?
@@ -2031,7 +2034,7 @@ void ALTIUM_PCB::ParseArcs6Data( const CFB::CompoundFileReader& aReader,
         else
         {
             PCB_SHAPE* shape = HelperCreateAndAddShape( elem.component );
-            shape->SetWidth( elem.width );
+            shape->SetStroke( STROKE_PARAMS( elem.width, PLOT_DASH_TYPE::SOLID ) );
             shape->SetLayer( klayer );
 
             if( elem.startangle == 0. && elem.endangle == 360. )
@@ -2329,7 +2332,7 @@ void ALTIUM_PCB::HelperParsePad6NonCopper( const APAD6& aElem )
         shape->SetShape( SHAPE_T::POLY );
         shape->SetFilled( true );
         shape->SetLayer( klayer );
-        shape->SetWidth( 0 );
+        shape->SetStroke( STROKE_PARAMS( 0 ) );
 
         shape->SetPolyPoints( { aElem.position + wxPoint( aElem.topsize.x / 2, aElem.topsize.y / 2 ),
                                 aElem.position + wxPoint( aElem.topsize.x / 2, -aElem.topsize.y / 2 ),
@@ -2353,7 +2356,7 @@ void ALTIUM_PCB::HelperParsePad6NonCopper( const APAD6& aElem )
 
             PCB_SHAPE* shape = HelperCreateAndAddShape( aElem.component );
             shape->SetLayer( klayer );
-            shape->SetWidth( offset * 2 );
+            shape->SetStroke( STROKE_PARAMS( offset * 2, PLOT_DASH_TYPE::SOLID ) );
 
             if( cornerradius < 100 )
             {
@@ -2376,7 +2379,7 @@ void ALTIUM_PCB::HelperParsePad6NonCopper( const APAD6& aElem )
                 shape->SetFilled( true );
                 shape->SetStart( aElem.position );
                 shape->SetEnd( aElem.position - wxPoint( 0, aElem.topsize.x / 4 ) );
-                shape->SetWidth( aElem.topsize.x / 2 );
+                shape->SetStroke( STROKE_PARAMS( aElem.topsize.x / 2, PLOT_DASH_TYPE::SOLID ) );
             }
             else if( aElem.topsize.x < aElem.topsize.y )
             {
@@ -2409,7 +2412,7 @@ void ALTIUM_PCB::HelperParsePad6NonCopper( const APAD6& aElem )
             shape->SetLayer( klayer );
             shape->SetStart( aElem.position );
             shape->SetEnd( aElem.position - wxPoint( 0, aElem.topsize.x / 4 ) );
-            shape->SetWidth( aElem.topsize.x / 2 );
+            shape->SetStroke( STROKE_PARAMS( aElem.topsize.x / 2, PLOT_DASH_TYPE::SOLID ) );
             HelperShapeSetLocalCoord( shape, aElem.component );
         }
         else
@@ -2418,7 +2421,8 @@ void ALTIUM_PCB::HelperParsePad6NonCopper( const APAD6& aElem )
             PCB_SHAPE* shape = HelperCreateAndAddShape( aElem.component );
             shape->SetShape( SHAPE_T::SEGMENT );
             shape->SetLayer( klayer );
-            shape->SetWidth( std::min( aElem.topsize.x, aElem.topsize.y ) );
+            shape->SetStroke( STROKE_PARAMS( std::min( aElem.topsize.x, aElem.topsize.y ),
+                                                       PLOT_DASH_TYPE::SOLID ) );
 
             if( aElem.topsize.x < aElem.topsize.y )
             {
@@ -2447,7 +2451,7 @@ void ALTIUM_PCB::HelperParsePad6NonCopper( const APAD6& aElem )
         shape->SetShape( SHAPE_T::POLY );
         shape->SetFilled( true );
         shape->SetLayer( klayer );
-        shape->SetWidth( 0 );
+        shape->SetStroke( STROKE_PARAMS( 0 ) );
 
         wxPoint p11 = aElem.position + wxPoint( aElem.topsize.x / 2, aElem.topsize.y / 2 );
         wxPoint p12 = aElem.position + wxPoint( aElem.topsize.x / 2, -aElem.topsize.y / 2 );
@@ -2564,7 +2568,7 @@ void ALTIUM_PCB::ParseTracks6Data( const CFB::CompoundFileReader& aReader,
             PCB_SHAPE shape( nullptr, SHAPE_T::SEGMENT );
             shape.SetStart( elem.start );
             shape.SetEnd( elem.end );
-            shape.SetWidth( elem.width );
+            shape.SetStroke( STROKE_PARAMS( elem.width, PLOT_DASH_TYPE::SOLID ) );
 
             ZONE* zone = new ZONE( m_board );
             m_board->Add( zone, ADD_MODE::APPEND );
@@ -2612,7 +2616,7 @@ void ALTIUM_PCB::ParseTracks6Data( const CFB::CompoundFileReader& aReader,
             klayer = Eco1_User;
         }
 
-        if( klayer >= F_Cu && klayer <= B_Cu )
+        if( IsCopperLayer( klayer ) )
         {
             PCB_TRACK* track = new PCB_TRACK( m_board );
             m_board->Add( track, ADD_MODE::APPEND );
@@ -2629,7 +2633,7 @@ void ALTIUM_PCB::ParseTracks6Data( const CFB::CompoundFileReader& aReader,
             shape->SetShape( SHAPE_T::SEGMENT );
             shape->SetStart( elem.start );
             shape->SetEnd( elem.end );
-            shape->SetWidth( elem.width );
+            shape->SetStroke( STROKE_PARAMS( elem.width, PLOT_DASH_TYPE::SOLID ) );
             shape->SetLayer( klayer );
             HelperShapeSetLocalCoord( shape, elem.component );
         }
@@ -2915,7 +2919,7 @@ void ALTIUM_PCB::ParseFills6Data( const CFB::CompoundFileReader& aReader,
             m_board->Add( shape, ADD_MODE::APPEND );
             shape->SetFilled( true );
             shape->SetLayer( klayer );
-            shape->SetWidth( 0 );
+            shape->SetStroke( STROKE_PARAMS( 0 ) );
 
             shape->SetPolyPoints( { p11, p12, p22, p21 } );
 
diff --git a/pcbnew/plugins/cadstar/cadstar_pcb_archive_loader.cpp b/pcbnew/plugins/cadstar/cadstar_pcb_archive_loader.cpp
index d76668239f..f43bc7b0ae 100644
--- a/pcbnew/plugins/cadstar/cadstar_pcb_archive_loader.cpp
+++ b/pcbnew/plugins/cadstar/cadstar_pcb_archive_loader.cpp
@@ -1179,7 +1179,7 @@ PAD* CADSTAR_PCB_ARCHIVE_LOADER::getKiCadPad( const COMPONENT_PAD& aCadstarPad,
             padShape->SetShape( SHAPE_T::POLY );
             padShape->SetFilled( true );
             padShape->SetPolyShape( padOutline );
-            padShape->SetWidth( 0 );
+            padShape->SetStroke( STROKE_PARAMS( 0 ) );
             padShape->Move( padOffset - drillOffset );
             padShape->Rotate( wxPoint( 0, 0 ),
                               1800.0 - getAngleTenthDegree( csPadcode.SlotOrientation ) );
@@ -2436,7 +2436,7 @@ void CADSTAR_PCB_ARCHIVE_LOADER::loadNetTracks( const NET_ID&         aCadstarNe
     {
         PCB_SHAPE* shape = getShapeFromVertex( prevEnd, v.Vertex );
         shape->SetLayer( getKiCadLayer( aCadstarRoute.LayerID ) );
-        shape->SetWidth( getKiCadLength( v.RouteWidth ) );
+        shape->SetStroke( STROKE_PARAMS( getKiCadLength( v.RouteWidth ), PLOT_DASH_TYPE::SOLID ) );
         shape->SetLocked( v.Fixed );
         shapes.push_back( shape );
         prevEnd = v.Vertex.End;
@@ -2695,14 +2695,15 @@ void CADSTAR_PCB_ARCHIVE_LOADER::drawCadstarShape( const SHAPE& aCadstarShape,
 
         shape->SetFilled( true );
 
-        SHAPE_POLY_SET shapePolys = getPolySetFromCadstarShape(
-                aCadstarShape, -1, aContainer, aMoveVector, aRotationAngle, aScalingFactor,
-                aTransformCentre, aMirrorInvert );
+        SHAPE_POLY_SET shapePolys = getPolySetFromCadstarShape( aCadstarShape, -1, aContainer,
+                                                                aMoveVector, aRotationAngle,
+                                                                aScalingFactor, aTransformCentre,
+                                                                aMirrorInvert );
 
         shapePolys.Fracture( SHAPE_POLY_SET::POLYGON_MODE::PM_STRICTLY_SIMPLE );
 
         shape->SetPolyShape( shapePolys );
-        shape->SetWidth( aLineThickness );
+        shape->SetStroke( STROKE_PARAMS( aLineThickness, PLOT_DASH_TYPE::SOLID ) );
         shape->SetLayer( aKiCadLayer );
         aContainer->Add( shape, ADD_MODE::APPEND );
 
@@ -2752,7 +2753,7 @@ void CADSTAR_PCB_ARCHIVE_LOADER::drawCadstarVerticesAsShapes( const std::vector<
 
     for( PCB_SHAPE* shape : shapes )
     {
-        shape->SetWidth( aLineThickness );
+        shape->SetStroke( STROKE_PARAMS( aLineThickness, PLOT_DASH_TYPE::SOLID ) );
         shape->SetLayer( aKiCadLayer );
         shape->SetParent( aContainer );
         aContainer->Add( shape, ADD_MODE::APPEND );
diff --git a/pcbnew/plugins/eagle/eagle_plugin.cpp b/pcbnew/plugins/eagle/eagle_plugin.cpp
index f41aa0041a..df37fc08b9 100644
--- a/pcbnew/plugins/eagle/eagle_plugin.cpp
+++ b/pcbnew/plugins/eagle/eagle_plugin.cpp
@@ -730,7 +730,7 @@ void EAGLE_PLUGIN::loadPlain( wxXmlNode* aGraphics )
                 }
 
                 shape->SetLayer( layer );
-                shape->SetWidth( width );
+                shape->SetStroke( STROKE_PARAMS( width, PLOT_DASH_TYPE::SOLID ) );
             }
 
             m_xpath->pop();
@@ -912,7 +912,7 @@ void EAGLE_PLUGIN::loadPlain( wxXmlNode* aGraphics )
                     shape->SetLayer( layer );
                     shape->SetStart( wxPoint( kicad_x( c.x ), kicad_y( c.y ) ) );
                     shape->SetEnd( wxPoint( kicad_x( c.x ) + radius, kicad_y( c.y ) ) );
-                    shape->SetWidth( width );
+                    shape->SetStroke( STROKE_PARAMS( width, PLOT_DASH_TYPE::SOLID ) );
                 }
             }
 
@@ -1804,7 +1804,7 @@ void EAGLE_PLUGIN::packageWire( FOOTPRINT* aFootprint, wxXmlNode* aTree ) const
     }
 
     dwg->SetLayer( layer );
-    dwg->SetWidth( width );
+    dwg->SetStroke( STROKE_PARAMS( width, PLOT_DASH_TYPE::SOLID ) );
     dwg->SetDrawCoord();
 
     aFootprint->Add( dwg );
@@ -2076,7 +2076,7 @@ void EAGLE_PLUGIN::packageRectangle( FOOTPRINT* aFootprint, wxXmlNode* aTree ) c
         aFootprint->Add( dwg );
 
         dwg->SetLayer( layer );
-        dwg->SetWidth( 0 );
+        dwg->SetStroke( STROKE_PARAMS( 0 ) );
         dwg->SetFilled( true );
 
         std::vector<wxPoint> pts;
@@ -2189,7 +2189,7 @@ void EAGLE_PLUGIN::packagePolygon( FOOTPRINT* aFootprint, wxXmlNode* aTree ) con
 
         aFootprint->Add( dwg );
 
-        dwg->SetWidth( 0 ); // it's filled, no need for boundary width
+        dwg->SetStroke( STROKE_PARAMS( 0 ) );
         dwg->SetFilled( true );
         dwg->SetLayer( layer );
 
@@ -2269,7 +2269,7 @@ void EAGLE_PLUGIN::packageCircle( FOOTPRINT* aFootprint, wxXmlNode* aTree ) cons
         }
 
         aFootprint->Add( gr );
-        gr->SetWidth( width );
+        gr->SetStroke( STROKE_PARAMS( width, PLOT_DASH_TYPE::SOLID ) );
 
         switch( (int) layer )
         {
diff --git a/pcbnew/plugins/fabmaster/import_fabmaster.cpp b/pcbnew/plugins/fabmaster/import_fabmaster.cpp
index ae00d7d699..b109d42058 100644
--- a/pcbnew/plugins/fabmaster/import_fabmaster.cpp
+++ b/pcbnew/plugins/fabmaster/import_fabmaster.cpp
@@ -2083,6 +2083,8 @@ bool FABMASTER::loadFootprints( BOARD* aBoard )
                     if( IsPcbLayer( getLayer( seg->layer ) ) )
                         layer = getLayer( seg->layer );
 
+                    STROKE_PARAMS defaultStroke( ds.GetLineThickness( layer ) );
+
                     switch( seg->shape )
                     {
 
@@ -2105,11 +2107,11 @@ bool FABMASTER::loadFootprints( BOARD* aBoard )
                             line->SetEnd( wxPoint( lsrc->end_x, lsrc->end_y ) );
                         }
 
-                        line->SetWidth( lsrc->width );
+                        line->SetStroke( STROKE_PARAMS( lsrc->width, PLOT_DASH_TYPE::SOLID ) );
                         line->SetLocalCoord();
 
                         if( lsrc->width == 0 )
-                            line->SetWidth( ds.GetLineThickness( line->GetLayer() ) );
+                            line->SetStroke( defaultStroke );
 
                         fp->Add( line, ADD_MODE::APPEND );
                         break;
@@ -2145,11 +2147,11 @@ bool FABMASTER::loadFootprints( BOARD* aBoard )
                         arc->SetArcGeometry( (wxPoint) lsrc->result.GetP0(),
                                              (wxPoint) lsrc->result.GetArcMid(),
                                              (wxPoint) lsrc->result.GetP1() );
-                        arc->SetWidth( lsrc->width );
+                        arc->SetStroke( STROKE_PARAMS( lsrc->width, PLOT_DASH_TYPE::SOLID ) );
                         arc->SetLocalCoord();
 
                         if( lsrc->width == 0 )
-                            arc->SetWidth( ds.GetLineThickness( arc->GetLayer() ) );
+                            arc->SetStroke( defaultStroke );
 
                         if( src->mirror )
                             arc->Flip( arc->GetCenter(), false );
@@ -2177,7 +2179,7 @@ bool FABMASTER::loadFootprints( BOARD* aBoard )
                             rect->SetEnd( wxPoint( lsrc->end_x, lsrc->end_y ) );
                         }
 
-                        rect->SetWidth( ds.GetLineThickness( rect->GetLayer() ) );
+                        rect->SetStroke( defaultStroke );
                         rect->SetLocalCoord();
 
                         fp->Add( rect, ADD_MODE::APPEND );
@@ -2626,7 +2628,8 @@ bool FABMASTER::loadPolygon( BOARD* aBoard, const std::unique_ptr<FABMASTER::TRA
     if( poly_outline.OutlineCount() < 1 || poly_outline.COutline( 0 ).PointCount() < 3 )
         return false;
 
-    PCB_SHAPE* new_poly = new PCB_SHAPE( aBoard );
+    STROKE_PARAMS defaultStroke( aBoard->GetDesignSettings().GetLineThickness( layer ) );
+    PCB_SHAPE*    new_poly = new PCB_SHAPE( aBoard );
 
     new_poly->SetShape( SHAPE_T::POLY );
     new_poly->SetLayer( layer );
@@ -2635,14 +2638,15 @@ bool FABMASTER::loadPolygon( BOARD* aBoard, const std::unique_ptr<FABMASTER::TRA
     if( layer == F_SilkS || layer == B_SilkS )
     {
         new_poly->SetFilled( true );
-        new_poly->SetWidth( 0 );
+        new_poly->SetStroke( STROKE_PARAMS( 0 ) );
     }
     else
     {
-        new_poly->SetWidth( ( *( aLine->segment.begin() ) )->width );
+        new_poly->SetStroke( STROKE_PARAMS( ( *( aLine->segment.begin() ) )->width,
+                                            PLOT_DASH_TYPE::SOLID ) );
 
         if( new_poly->GetWidth() == 0 )
-            new_poly->SetWidth( aBoard->GetDesignSettings().GetLineThickness( layer ) );
+            new_poly->SetStroke( defaultStroke );
     }
 
     new_poly->SetPolyShape( poly_outline );
@@ -2765,6 +2769,8 @@ bool FABMASTER::loadOutline( BOARD* aBoard, const std::unique_ptr<FABMASTER::TRA
     else
         layer = Cmts_User;
 
+    STROKE_PARAMS defaultStroke( aBoard->GetDesignSettings().GetLineThickness( layer ) );
+
     for( auto& seg : aLine->segment )
     {
         switch( seg->shape )
@@ -2778,10 +2784,10 @@ bool FABMASTER::loadOutline( BOARD* aBoard, const std::unique_ptr<FABMASTER::TRA
             line->SetLayer( layer );
             line->SetStart( wxPoint( src->start_x, src->start_y ) );
             line->SetEnd( wxPoint( src->end_x, src->end_y ) );
-            line->SetWidth( src->width );
+            line->SetStroke( STROKE_PARAMS( src->width, PLOT_DASH_TYPE::SOLID ) );
 
             if( line->GetWidth() == 0 )
-                line->SetWidth( aBoard->GetDesignSettings().GetLineThickness( layer ) );
+                line->SetStroke( defaultStroke );
 
             aBoard->Add( line, ADD_MODE::APPEND );
             break;
@@ -2812,10 +2818,10 @@ bool FABMASTER::loadOutline( BOARD* aBoard, const std::unique_ptr<FABMASTER::TRA
             arc->SetArcGeometry( (wxPoint) src->result.GetP0(),
                                  (wxPoint) src->result.GetArcMid(),
                                  (wxPoint) src->result.GetP1() );
-            arc->SetWidth( src->width );
+            arc->SetStroke( STROKE_PARAMS( src->width, PLOT_DASH_TYPE::SOLID ) );
 
             if( arc->GetWidth() == 0 )
-                arc->SetWidth( aBoard->GetDesignSettings().GetLineThickness( layer ) );
+                arc->SetStroke( defaultStroke );
 
             aBoard->Add( arc, ADD_MODE::APPEND );
             break;
@@ -2829,7 +2835,7 @@ bool FABMASTER::loadOutline( BOARD* aBoard, const std::unique_ptr<FABMASTER::TRA
             rect->SetLayer( layer );
             rect->SetStart( wxPoint( src->start_x, src->start_y ) );
             rect->SetEnd( wxPoint( src->end_x, src->end_y ) );
-            rect->SetWidth( aBoard->GetDesignSettings().GetLineThickness( layer ) );
+            rect->SetStroke( defaultStroke );
 
             aBoard->Add( rect, ADD_MODE::APPEND );
             break;
@@ -2891,7 +2897,7 @@ bool FABMASTER::loadGraphics( BOARD* aBoard )
                 PCB_SHAPE* new_poly = new PCB_SHAPE( aBoard, SHAPE_T::POLY );
                 new_poly->SetLayer( layer );
                 new_poly->SetPolyShape( poly_outline );
-                new_poly->SetWidth( 0 );
+                new_poly->SetStroke( STROKE_PARAMS( 0 ) );
 
                 if( layer == F_SilkS || layer == B_SilkS )
                     new_poly->SetFilled( true );
@@ -2913,7 +2919,7 @@ bool FABMASTER::loadGraphics( BOARD* aBoard )
                 line->SetLayer( layer );
                 line->SetStart( wxPoint( src->start_x, src->start_y ) );
                 line->SetEnd( wxPoint( src->end_x, src->end_y ) );
-                line->SetWidth( src->width );
+                line->SetStroke( STROKE_PARAMS( src->width, PLOT_DASH_TYPE::SOLID ) );
 
                 aBoard->Add( line, ADD_MODE::APPEND );
                 break;
@@ -2941,7 +2947,7 @@ bool FABMASTER::loadGraphics( BOARD* aBoard )
                 arc->SetArcGeometry( (wxPoint) src->result.GetP0(),
                                      (wxPoint) src->result.GetArcMid(),
                                      (wxPoint) src->result.GetP1() );
-                arc->SetWidth( src->width );
+                arc->SetStroke( STROKE_PARAMS( src->width, PLOT_DASH_TYPE::SOLID ) );
 
                 aBoard->Add( arc, ADD_MODE::APPEND );
                 break;
@@ -2955,7 +2961,7 @@ bool FABMASTER::loadGraphics( BOARD* aBoard )
                 rect->SetLayer( layer );
                 rect->SetStart( wxPoint( src->start_x, src->start_y ) );
                 rect->SetEnd( wxPoint( src->end_x, src->end_y ) );
-                rect->SetWidth( 0 );
+                rect->SetStroke( STROKE_PARAMS( 0 ) );
                 rect->SetFilled( true );
                 aBoard->Add( rect, ADD_MODE::APPEND );
                 break;
@@ -2990,9 +2996,7 @@ bool FABMASTER::loadGraphics( BOARD* aBoard )
 
 bool FABMASTER::orderZones( BOARD* aBoard )
 {
-    std::vector<ZONE*> zones = aBoard->Zones();
-
-    std::sort( zones.begin(), zones.end(),
+    std::sort( aBoard->Zones().begin(), aBoard->Zones().end(),
             [&]( const ZONE* a, const ZONE* b )
             {
                 if( a->GetLayer() == b->GetLayer() )
@@ -3004,7 +3008,7 @@ bool FABMASTER::orderZones( BOARD* aBoard )
     PCB_LAYER_ID layer = UNDEFINED_LAYER;
     unsigned int priority = 0;
 
-    for( ZONE* zone : zones )
+    for( ZONE* zone : aBoard->Zones() )
     {
         /// Rule areas do not have priorities
         if( zone->GetIsRuleArea() )
diff --git a/pcbnew/plugins/geda/gpcb_plugin.cpp b/pcbnew/plugins/geda/gpcb_plugin.cpp
index 7daf4e1bc5..6e9ab161e0 100644
--- a/pcbnew/plugins/geda/gpcb_plugin.cpp
+++ b/pcbnew/plugins/geda/gpcb_plugin.cpp
@@ -469,7 +469,8 @@ FOOTPRINT* GPCB_FPL_CACHE::parseFOOTPRINT( LINE_READER* aLineReader )
                                        parseInt( parameters[3], conv_unit ) ) );
             shape->SetEnd0( wxPoint( parseInt( parameters[4], conv_unit ),
                                      parseInt( parameters[5], conv_unit ) ) );
-            shape->SetWidth( parseInt( parameters[6], conv_unit ) );
+            shape->SetStroke( STROKE_PARAMS( parseInt( parameters[6], conv_unit ),
+                                             PLOT_DASH_TYPE::SOLID ) );
             shape->SetDrawCoord();
             footprint->Add( shape );
             continue;
@@ -517,7 +518,8 @@ FOOTPRINT* GPCB_FPL_CACHE::parseFOOTPRINT( LINE_READER* aLineReader )
             // Angle value is clockwise in gpcb and Pcbnew.
             shape->SetArcAngleAndEnd0( sweep_angle );
 
-            shape->SetWidth( parseInt( parameters[8], conv_unit ) );
+            shape->SetStroke( STROKE_PARAMS( parseInt( parameters[8], conv_unit ),
+                                             PLOT_DASH_TYPE::SOLID ) );
             shape->SetDrawCoord();
             continue;
         }
diff --git a/pcbnew/plugins/kicad/pcb_parser.cpp b/pcbnew/plugins/kicad/pcb_parser.cpp
index 32d1e9b992..a0deb5a473 100644
--- a/pcbnew/plugins/kicad/pcb_parser.cpp
+++ b/pcbnew/plugins/kicad/pcb_parser.cpp
@@ -2366,6 +2366,7 @@ PCB_SHAPE* PCB_PARSER::parsePCB_SHAPE()
 
     T token;
     wxPoint pt;
+    STROKE_PARAMS stroke( 0, PLOT_DASH_TYPE::SOLID );
     std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>( nullptr );
 
     switch( CurTok() )
@@ -2572,7 +2573,6 @@ PCB_SHAPE* PCB_PARSER::parsePCB_SHAPE()
     case T_gr_poly:
     {
         shape->SetShape( SHAPE_T::POLY );
-        shape->SetWidth( 0 ); // this is the default value. will be (perhaps) modified later
         shape->SetPolyPoints( {} );
 
         SHAPE_LINE_CHAIN& outline = shape->GetPolyShape().Outline( 0 );
@@ -2640,7 +2640,7 @@ PCB_SHAPE* PCB_PARSER::parsePCB_SHAPE()
             break;
 
         case T_width:
-            shape->SetWidth( parseBoardUnits( T_width ) );
+            stroke.SetWidth( parseBoardUnits( T_width ) );
             NeedRIGHT();
             break;
 
@@ -2699,7 +2699,7 @@ PCB_SHAPE* PCB_PARSER::parsePCB_SHAPE()
     {
         // Legacy versions didn't have a filled flag but allowed some shapes to indicate they
         // should be filled by specifying a 0 stroke-width.
-        if( shape->GetWidth() == 0
+        if( stroke.GetWidth() == 0
             && ( shape->GetShape() == SHAPE_T::RECT || shape->GetShape() == SHAPE_T::CIRCLE ) )
         {
             shape->SetFilled( true );
@@ -2713,11 +2713,13 @@ PCB_SHAPE* PCB_PARSER::parsePCB_SHAPE()
 
     // Only filled shapes may have a zero line-width.  This is not permitted in KiCad but some
     // external tools can generate invalid files.
-    if( shape->GetWidth() <= 0 && !shape->IsFilled() )
+    if( stroke.GetWidth() <= 0 && !shape->IsFilled() )
     {
-        shape->SetWidth( Millimeter2iu( DEFAULT_LINE_WIDTH ) );
+        stroke.SetWidth( Millimeter2iu( DEFAULT_LINE_WIDTH ) );
     }
 
+    shape->SetStroke( stroke );
+
     return shape.release();
 }
 
@@ -3670,6 +3672,7 @@ FP_SHAPE* PCB_PARSER::parseFP_SHAPE()
                  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as FP_SHAPE." ) );
 
     wxPoint pt;
+    STROKE_PARAMS stroke( 0, PLOT_DASH_TYPE::SOLID );
     T token;
 
     std::unique_ptr<FP_SHAPE> shape = std::make_unique<FP_SHAPE>( nullptr );
@@ -3933,7 +3936,7 @@ FP_SHAPE* PCB_PARSER::parseFP_SHAPE()
             break;
 
         case T_width:
-            shape->SetWidth( parseBoardUnits( T_width ) );
+            stroke.SetWidth( parseBoardUnits( T_width ) );
             NeedRIGHT();
             break;
 
@@ -3992,7 +3995,7 @@ FP_SHAPE* PCB_PARSER::parseFP_SHAPE()
     {
         // Legacy versions didn't have a filled flag but allowed some shapes to indicate they
         // should be filled by specifying a 0 stroke-width.
-        if( shape->GetWidth() == 0
+        if( stroke.GetWidth() == 0
             && ( shape->GetShape() == SHAPE_T::RECT || shape->GetShape() == SHAPE_T::CIRCLE ) )
         {
             shape->SetFilled( true );
@@ -4006,11 +4009,13 @@ FP_SHAPE* PCB_PARSER::parseFP_SHAPE()
 
     // Only filled shapes may have a zero line-width.  This is not permitted in KiCad but some
     // external tools can generate invalid files.
-    if( shape->GetWidth() <= 0 && !shape->IsFilled() )
+    if( stroke.GetWidth() <= 0 && !shape->IsFilled() )
     {
-        shape->SetWidth( Millimeter2iu( DEFAULT_LINE_WIDTH ) );
+        stroke.SetWidth( Millimeter2iu( DEFAULT_LINE_WIDTH ) );
     }
 
+    shape->SetStroke( stroke );
+
     return shape.release();
 }
 
diff --git a/pcbnew/plugins/legacy/legacy_plugin.cpp b/pcbnew/plugins/legacy/legacy_plugin.cpp
index b792a4c3e7..6dbb0afe3c 100644
--- a/pcbnew/plugins/legacy/legacy_plugin.cpp
+++ b/pcbnew/plugins/legacy/legacy_plugin.cpp
@@ -1667,7 +1667,7 @@ void LEGACY_PLUGIN::loadFP_SHAPE( FOOTPRINT* aFootprint )
     if( layer < FIRST_LAYER || layer > LAST_NON_COPPER_LAYER )
         layer = SILKSCREEN_N_FRONT;
 
-    dwg->SetWidth( width );
+    dwg->SetStroke( STROKE_PARAMS( width, PLOT_DASH_TYPE::SOLID ) );
     dwg->SetLayer( leg_layer2new( m_cu_count,  layer ) );
 
     FP_SHAPE* fpShape = dwg.release();
@@ -1846,18 +1846,9 @@ void LEGACY_PLUGIN::loadPCB_LINE()
 
             dseg->SetShape( static_cast<SHAPE_T>( shape ) );
             dseg->SetFilled( false );
-            dseg->SetWidth( width );
-
-            if( dseg->GetShape() == SHAPE_T::ARC )
-            {
-                dseg->SetCenter( wxPoint( start_x, start_y ) );
-                dseg->SetStart( wxPoint( end_x, end_y ) );
-            }
-            else
-            {
-                dseg->SetStart( wxPoint( start_x, start_y ) );
-                dseg->SetEnd( wxPoint( end_x, end_y ) );
-            }
+            dseg->SetStroke( STROKE_PARAMS( width, PLOT_DASH_TYPE::SOLID ) );
+            dseg->SetStart( wxPoint( start_x, start_y ) );
+            dseg->SetEnd( wxPoint( end_x, end_y ) );
         }
         else if( TESTLINE( "De" ) )
         {
diff --git a/pcbnew/plugins/pcad/pcb_arc.cpp b/pcbnew/plugins/pcad/pcb_arc.cpp
index 18208f7f41..d55ef9a173 100644
--- a/pcbnew/plugins/pcad/pcb_arc.cpp
+++ b/pcbnew/plugins/pcad/pcb_arc.cpp
@@ -178,7 +178,7 @@ void PCB_ARC::AddToFootprint( FOOTPRINT* aFootprint )
         arc->SetStart0( wxPoint( m_StartX, m_StartY ) );
         arc->SetArcAngleAndEnd0( -m_Angle );
 
-        arc->SetWidth( m_Width );
+        arc->SetStroke( STROKE_PARAMS( m_Width, PLOT_DASH_TYPE::SOLID ) );
         arc->SetLayer( m_KiCadLayer );
 
         arc->SetDrawCoord();
@@ -197,7 +197,7 @@ void PCB_ARC::AddToBoard()
     arc->SetCenter( wxPoint( m_positionX, m_positionY ) );
     arc->SetStart( wxPoint( m_StartX, m_StartY ) );
     arc->SetArcAngleAndEnd( -m_Angle );
-    arc->SetWidth( m_Width );
+    arc->SetStroke( STROKE_PARAMS( m_Width, PLOT_DASH_TYPE::SOLID ) );
 }
 
 
diff --git a/pcbnew/plugins/pcad/pcb_line.cpp b/pcbnew/plugins/pcad/pcb_line.cpp
index cf143df363..99dfc97049 100644
--- a/pcbnew/plugins/pcad/pcb_line.cpp
+++ b/pcbnew/plugins/pcad/pcb_line.cpp
@@ -125,7 +125,7 @@ void PCB_LINE::AddToFootprint( FOOTPRINT* aFootprint )
         segment->SetStart0( wxPoint( m_positionX, m_positionY ) );
         segment->SetEnd0( wxPoint( m_ToX, m_ToY ) );
 
-        segment->SetWidth( m_Width );
+        segment->SetStroke( STROKE_PARAMS( m_Width, PLOT_DASH_TYPE::SOLID ) );
         segment->SetLayer( m_KiCadLayer );
 
         segment->SetDrawCoord();
@@ -156,7 +156,7 @@ void PCB_LINE::AddToBoard()
         segment->SetLayer( m_KiCadLayer );
         segment->SetStart( wxPoint( m_positionX, m_positionY ) );
         segment->SetEnd( wxPoint( m_ToX, m_ToY ) );
-        segment->SetWidth( m_Width );
+        segment->SetStroke( STROKE_PARAMS( m_Width, PLOT_DASH_TYPE::SOLID ) );
     }
 }
 
diff --git a/pcbnew/plugins/pcad/pcb_polygon.cpp b/pcbnew/plugins/pcad/pcb_polygon.cpp
index 612f9cb085..f1e34eec88 100644
--- a/pcbnew/plugins/pcad/pcb_polygon.cpp
+++ b/pcbnew/plugins/pcad/pcb_polygon.cpp
@@ -166,7 +166,7 @@ void PCB_POLYGON::AddToFootprint( FOOTPRINT* aFootprint )
         FP_SHAPE* dwg = new FP_SHAPE( aFootprint, SHAPE_T::POLY );
         aFootprint->Add( dwg );
 
-        dwg->SetWidth( 0 );
+        dwg->SetStroke( STROKE_PARAMS( 0 ) );
         dwg->SetLayer( m_KiCadLayer );
 
         auto outline = new std::vector<wxPoint>;
diff --git a/pcbnew/tools/convert_tool.cpp b/pcbnew/tools/convert_tool.cpp
index 395dcfbd06..1581160123 100644
--- a/pcbnew/tools/convert_tool.cpp
+++ b/pcbnew/tools/convert_tool.cpp
@@ -200,7 +200,7 @@ int CONVERT_TOOL::CreatePolys( const TOOL_EVENT& aEvent )
 
             graphic->SetShape( SHAPE_T::POLY );
             graphic->SetFilled( false );
-            graphic->SetWidth( poly.Outline( 0 ).Width() );
+            graphic->SetStroke( STROKE_PARAMS( poly.Outline( 0 ).Width() ) );
             graphic->SetLayer( destLayer );
             graphic->SetPolyShape( poly );
 
@@ -329,15 +329,14 @@ SHAPE_POLY_SET CONVERT_TOOL::makePolysFromSegs( const std::deque<EDA_ITEM*>& aIt
 
                         if( aItem->Type() == PCB_ARC_T )
                         {
-                            std::shared_ptr<SHAPE> es =
-                                    static_cast<PCB_ARC*>( aItem )->GetEffectiveShape();
-                            arc = *static_cast<SHAPE_ARC*>( es.get() );
+                            PCB_ARC* pcb_arc = static_cast<PCB_ARC*>( aItem );
+                            arc = *static_cast<SHAPE_ARC*>( pcb_arc->GetEffectiveShape().get() );
                         }
                         else
                         {
-                            PCB_SHAPE* ps = static_cast<PCB_SHAPE*>( aItem );
-                            arc = SHAPE_ARC( ps->GetStart(), ps->GetArcMid(), ps->GetEnd(),
-                                             ps->GetWidth() );
+                            PCB_SHAPE* pcb_shape = static_cast<PCB_SHAPE*>( aItem );
+                            arc = SHAPE_ARC( pcb_shape->GetStart(), pcb_shape->GetArcMid(),
+                                             pcb_shape->GetEnd(), pcb_shape->GetWidth() );
                         }
 
                         if( aDirection )
@@ -715,8 +714,6 @@ int CONVERT_TOOL::CreateLines( const TOOL_EVENT& aEvent )
         }
         else
         {
-
-
             if( !IsCopperLayer( targetLayer ) )
             {
                 if( copperLayer == UNSELECTED_LAYER )
@@ -825,7 +822,7 @@ int CONVERT_TOOL::SegmentToArc( const TOOL_EVENT& aEvent )
 
         arc->SetFilled( false );
         arc->SetLayer( layer );
-        arc->SetWidth( line->GetWidth() );
+        arc->SetStroke( line->GetStroke() );
 
         arc->SetCenter( wxPoint( center ) );
         arc->SetStart( wxPoint( start ) );
diff --git a/pcbnew/tools/drawing_tool.cpp b/pcbnew/tools/drawing_tool.cpp
index dd7f183007..9e965fd4f7 100644
--- a/pcbnew/tools/drawing_tool.cpp
+++ b/pcbnew/tools/drawing_tool.cpp
@@ -164,7 +164,7 @@ DRAWING_TOOL::DRAWING_TOOL() :
     m_frame( nullptr ),
     m_mode( MODE::NONE ),
     m_inDrawingTool( false ),
-    m_lineWidth( 1 )
+    m_stroke( 1, PLOT_DASH_TYPE::DEFAULT, COLOR4D::UNSPECIFIED )
 {
 }
 
@@ -836,17 +836,17 @@ int DRAWING_TOOL::DrawDimension( const TOOL_EVENT& aEvent )
         }
         else if( evt->IsAction( &PCB_ACTIONS::incWidth ) && step != SET_ORIGIN )
         {
-            m_lineWidth += WIDTH_STEP;
-            dimension->SetLineThickness( m_lineWidth );
+            m_stroke.SetWidth( m_stroke.GetWidth() + WIDTH_STEP );
+            dimension->SetLineThickness( m_stroke.GetWidth() );
             m_view->Update( &preview );
             frame()->SetMsgPanel( dimension );
         }
         else if( evt->IsAction( &PCB_ACTIONS::decWidth ) && step != SET_ORIGIN )
         {
-            if( m_lineWidth > WIDTH_STEP )
+            if( (unsigned) m_stroke.GetWidth() > WIDTH_STEP )
             {
-                m_lineWidth -= WIDTH_STEP;
-                dimension->SetLineThickness( m_lineWidth );
+                m_stroke.SetWidth( m_stroke.GetWidth() - WIDTH_STEP );
+                dimension->SetLineThickness( m_stroke.GetWidth() );
                 m_view->Update( &preview );
                 frame()->SetMsgPanel( dimension );
             }
@@ -1434,7 +1434,7 @@ bool DRAWING_TOOL::drawSegment( const std::string& aTool, PCB_SHAPE** aGraphic,
     PCB_SHAPE*&      graphic = *aGraphic;
     PCB_LAYER_ID     drawingLayer = m_frame->GetActiveLayer();
 
-    m_lineWidth = getSegmentWidth( drawingLayer );
+    m_stroke.SetWidth( getSegmentWidth( drawingLayer ) );
 
     // geometric construction manager
     KIGFX::PREVIEW::TWO_POINT_GEOMETRY_MANAGER twoPointManager;
@@ -1533,7 +1533,7 @@ bool DRAWING_TOOL::drawSegment( const std::string& aTool, PCB_SHAPE** aGraphic,
         else if( evt->IsAction( &PCB_ACTIONS::layerChanged ) )
         {
             drawingLayer = m_frame->GetActiveLayer();
-            m_lineWidth = getSegmentWidth( drawingLayer );
+            m_stroke.SetWidth( getSegmentWidth( drawingLayer ) );
 
             if( graphic )
             {
@@ -1544,7 +1544,7 @@ bool DRAWING_TOOL::drawSegment( const std::string& aTool, PCB_SHAPE** aGraphic,
                 }
 
                 graphic->SetLayer( drawingLayer );
-                graphic->SetWidth( m_lineWidth );
+                graphic->SetStroke( m_stroke );
                 m_view->Update( &preview );
                 frame()->SetMsgPanel( graphic );
             }
@@ -1583,12 +1583,12 @@ bool DRAWING_TOOL::drawSegment( const std::string& aTool, PCB_SHAPE** aGraphic,
                     aStartingPoint = NULLOPT;
                 }
 
-                m_lineWidth = getSegmentWidth( drawingLayer );
+                m_stroke.SetWidth( getSegmentWidth( drawingLayer ) );
 
                 // Init the new item attributes
                 graphic->SetShape( static_cast<SHAPE_T>( shape ) );
                 graphic->SetFilled( false );
-                graphic->SetWidth( m_lineWidth );
+                graphic->SetStroke( m_stroke );
                 graphic->SetLayer( drawingLayer );
                 grid.SetSkipPoint( cursorPos );
 
@@ -1680,17 +1680,20 @@ bool DRAWING_TOOL::drawSegment( const std::string& aTool, PCB_SHAPE** aGraphic,
         }
         else if( evt->IsAction( &PCB_ACTIONS::incWidth ) )
         {
-            m_lineWidth += WIDTH_STEP;
-            graphic->SetWidth( m_lineWidth );
+            m_stroke.SetWidth( m_stroke.GetWidth() + WIDTH_STEP );
+            graphic->SetStroke( m_stroke );
             m_view->Update( &preview );
             frame()->SetMsgPanel( graphic );
         }
-        else if( evt->IsAction( &PCB_ACTIONS::decWidth ) && ( m_lineWidth > WIDTH_STEP ) )
+        else if( evt->IsAction( &PCB_ACTIONS::decWidth ) )
         {
-            m_lineWidth -= WIDTH_STEP;
-            graphic->SetWidth( m_lineWidth );
-            m_view->Update( &preview );
-            frame()->SetMsgPanel( graphic );
+            if( (unsigned) m_stroke.GetWidth() > WIDTH_STEP )
+            {
+                m_stroke.SetWidth( m_stroke.GetWidth() - WIDTH_STEP );
+                graphic->SetStroke( m_stroke );
+                m_view->Update( &preview );
+                frame()->SetMsgPanel( graphic );
+            }
         }
         else if( evt->IsAction( &ACTIONS::resetLocalCoords ) )
         {
@@ -1754,7 +1757,7 @@ bool DRAWING_TOOL::drawArc( const std::string& aTool, PCB_SHAPE** aGraphic, bool
 
     PCB_LAYER_ID drawingLayer = m_frame->GetActiveLayer();
 
-    m_lineWidth = getSegmentWidth( drawingLayer );
+    m_stroke.SetWidth( getSegmentWidth( drawingLayer ) );
 
     // Arc geometric construction manager
     KIGFX::PREVIEW::ARC_GEOM_MANAGER arcManager;
@@ -1855,12 +1858,12 @@ bool DRAWING_TOOL::drawArc( const std::string& aTool, PCB_SHAPE** aGraphic, bool
                 m_controls->CaptureCursor( true );
 
                 drawingLayer = m_frame->GetActiveLayer();
-                m_lineWidth = getSegmentWidth( drawingLayer );
+                m_stroke.SetWidth( getSegmentWidth( drawingLayer ) );
 
                 // Init the new item attributes
                 // (non-geometric, those are handled by the manager)
                 graphic->SetShape( SHAPE_T::ARC );
-                graphic->SetWidth( m_lineWidth );
+                graphic->SetStroke( m_stroke );
 
                 if( !m_view->IsLayerVisible( drawingLayer ) )
                 {
@@ -1890,7 +1893,7 @@ bool DRAWING_TOOL::drawArc( const std::string& aTool, PCB_SHAPE** aGraphic, bool
         else if( evt->IsAction( &PCB_ACTIONS::layerChanged ) )
         {
             drawingLayer = m_frame->GetActiveLayer();
-            m_lineWidth = getSegmentWidth( drawingLayer );
+            m_stroke.SetWidth( getSegmentWidth( drawingLayer ) );
 
             if( graphic )
             {
@@ -1901,7 +1904,7 @@ bool DRAWING_TOOL::drawArc( const std::string& aTool, PCB_SHAPE** aGraphic, bool
                 }
 
                 graphic->SetLayer( drawingLayer );
-                graphic->SetWidth( m_lineWidth );
+                graphic->SetStroke( m_stroke );
                 m_view->Update( &preview );
                 frame()->SetMsgPanel( graphic );
             }
@@ -1938,17 +1941,20 @@ bool DRAWING_TOOL::drawArc( const std::string& aTool, PCB_SHAPE** aGraphic, bool
         }
         else if( evt->IsAction( &PCB_ACTIONS::incWidth ) )
         {
-            m_lineWidth += WIDTH_STEP;
-            graphic->SetWidth( m_lineWidth );
+            m_stroke.SetWidth( m_stroke.GetWidth() + WIDTH_STEP );
+            graphic->SetStroke( m_stroke );
             m_view->Update( &preview );
             frame()->SetMsgPanel( graphic );
         }
-        else if( evt->IsAction( &PCB_ACTIONS::decWidth ) && m_lineWidth > WIDTH_STEP )
+        else if( evt->IsAction( &PCB_ACTIONS::decWidth ) )
         {
-            m_lineWidth -= WIDTH_STEP;
-            graphic->SetWidth( m_lineWidth );
-            m_view->Update( &preview );
-            frame()->SetMsgPanel( graphic );
+            if( (unsigned) m_stroke.GetWidth() > WIDTH_STEP )
+            {
+                m_stroke.SetWidth( m_stroke.GetWidth() - WIDTH_STEP );
+                graphic->SetStroke( m_stroke );
+                m_view->Update( &preview );
+                frame()->SetMsgPanel( graphic );
+            }
         }
         else if( evt->IsAction( &PCB_ACTIONS::arcPosture ) )
         {
diff --git a/pcbnew/tools/drawing_tool.h b/pcbnew/tools/drawing_tool.h
index c520ee8b38..207105c259 100644
--- a/pcbnew/tools/drawing_tool.h
+++ b/pcbnew/tools/drawing_tool.h
@@ -270,7 +270,7 @@ private:
     MODE                      m_mode;
     bool                      m_inDrawingTool;     // Re-entrancy guard
 
-    unsigned int              m_lineWidth;         // Current line width for multi-segment drawing
+    STROKE_PARAMS             m_stroke;            // Current stroke for multi-segment drawing
     static const unsigned int WIDTH_STEP;          // Amount of width change for one -/+ key press
 
 
diff --git a/pcbnew/tools/pad_tool.cpp b/pcbnew/tools/pad_tool.cpp
index 3b2e56b305..0ea7fc6637 100644
--- a/pcbnew/tools/pad_tool.cpp
+++ b/pcbnew/tools/pad_tool.cpp
@@ -617,7 +617,7 @@ PCB_LAYER_ID PAD_TOOL::explodePad( PAD* aPad )
 
             shape->SetShape( primitive->GetShape() );
             shape->SetFilled( primitive->IsFilled() );
-            shape->SetWidth( primitive->GetWidth() );
+            shape->SetStroke( primitive->GetStroke() );
 
             switch( shape->GetShape() )
             {
@@ -738,7 +738,7 @@ void PAD_TOOL::recombinePad( PAD* aPad )
 
             PCB_SHAPE* shape = new PCB_SHAPE( nullptr, SHAPE_T::POLY );
             shape->SetFilled( true );
-            shape->SetWidth( 0 );
+            shape->SetStroke( STROKE_PARAMS( 0, PLOT_DASH_TYPE::SOLID ) );
             shape->SetPolyShape( existingOutline );
             shape->Move( - aPad->GetPosition() );
             shape->Rotate( wxPoint( 0, 0 ), - aPad->GetOrientation() );
@@ -754,7 +754,7 @@ void PAD_TOOL::recombinePad( PAD* aPad )
 
         pcbShape->SetShape( fpShape->GetShape() );
         pcbShape->SetFilled( fpShape->IsFilled() );
-        pcbShape->SetWidth( fpShape->GetWidth() );
+        pcbShape->SetStroke( fpShape->GetStroke() );
 
 
         switch( pcbShape->GetShape() )
diff --git a/pcbnew/tools/zone_create_helper.cpp b/pcbnew/tools/zone_create_helper.cpp
index 36c89f9cb5..e22f9b3a73 100644
--- a/pcbnew/tools/zone_create_helper.cpp
+++ b/pcbnew/tools/zone_create_helper.cpp
@@ -236,7 +236,8 @@ void ZONE_CREATE_HELPER::commitZone( std::unique_ptr<ZONE> aZone )
             else
                 poly->SetFilled( true );
 
-            poly->SetWidth( board->GetDesignSettings().GetLineThickness( m_params.m_layer ) );
+            poly->SetStroke( STROKE_PARAMS( board->GetDesignSettings().GetLineThickness( layer ),
+                                            PLOT_DASH_TYPE::SOLID ) );
             poly->SetLayer( layer );
             poly->SetPolyShape( *aZone->Outline() );
 
diff --git a/qa/pcbnew_utils/board_construction_utils.cpp b/qa/pcbnew_utils/board_construction_utils.cpp
index 98d1bf5298..a601740800 100644
--- a/qa/pcbnew_utils/board_construction_utils.cpp
+++ b/qa/pcbnew_utils/board_construction_utils.cpp
@@ -34,12 +34,12 @@ namespace KI_TEST
 
 void DrawSegment( FOOTPRINT& aFootprint, const SEG& aSeg, int aWidth, PCB_LAYER_ID aLayer )
 {
-    auto seg = std::make_unique<FP_SHAPE>( &aFootprint, SHAPE_T::SEGMENT );
+    std::unique_ptr<FP_SHAPE> seg = std::make_unique<FP_SHAPE>( &aFootprint, SHAPE_T::SEGMENT );
 
     seg->SetStart0( (wxPoint) aSeg.A );
     seg->SetEnd0( (wxPoint) aSeg.B );
 
-    seg->SetWidth( aWidth );
+    seg->SetStroke( STROKE_PARAMS( aWidth, PLOT_DASH_TYPE::SOLID ) );
     seg->SetLayer( aLayer );
 
     aFootprint.Add( seg.release() );
@@ -59,16 +59,16 @@ void DrawPolyline( FOOTPRINT& aFootprint, const std::vector<VECTOR2I>& aPts, int
 void DrawArc( FOOTPRINT& aFootprint, const VECTOR2I& aCentre, const VECTOR2I& aStart,
               double aAngle, int aWidth, PCB_LAYER_ID aLayer )
 {
-    auto seg = std::make_unique<FP_SHAPE>( &aFootprint, SHAPE_T::ARC );
+    std::unique_ptr<FP_SHAPE>  arc = std::make_unique<FP_SHAPE>( &aFootprint, SHAPE_T::ARC );
 
-    seg->SetCenter0( (wxPoint) aCentre );
-    seg->SetStart0( (wxPoint) aStart );
-    seg->SetArcAngleAndEnd0( aAngle * 10 );
+    arc->SetCenter0( (wxPoint) aCentre );
+    arc->SetStart0( (wxPoint) aStart );
+    arc->SetArcAngleAndEnd0( aAngle * 10 );
 
-    seg->SetWidth( aWidth );
-    seg->SetLayer( aLayer );
+    arc->SetStroke( STROKE_PARAMS( aWidth, PLOT_DASH_TYPE::SOLID ) );
+    arc->SetLayer( aLayer );
 
-    aFootprint.Add( seg.release() );
+    aFootprint.Add( arc.release() );
 }