From 72d15972010617a5c0b7d44af31685594a2d7c58 Mon Sep 17 00:00:00 2001
From: jean-pierre charras <jp.charras@wanadoo.fr>
Date: Sat, 7 Jul 2018 13:04:01 +0200
Subject: [PATCH] DXF import: add import of DXF splines that are converted to
 Bezier curves.

Fix also a lot of bugs related to Bezier curves (S_CURVE shape in DRAW_SEGMENT class) in Pcbnew code.
Add missing code to handle these Bezier curves
---
 CMakeLists.txt                                |   2 +-
 common/bezier_curves.cpp                      |   3 +-
 include/bezier_curves.h                       |  19 +-
 pcbnew/CMakeLists.txt                         |   2 +-
 pcbnew/block_footprint_editor.cpp             |   5 +-
 ...board_items_to_polygon_shape_transform.cpp |  15 +-
 pcbnew/class_drawsegment.cpp                  | 119 +++-
 pcbnew/class_drawsegment.h                    |  10 +
 pcbnew/class_edge_mod.cpp                     |  62 +-
 pcbnew/class_edge_mod.h                       |  12 +-
 pcbnew/edgemod.cpp                            |   6 +-
 pcbnew/editedge.cpp                           |   3 +-
 pcbnew/import_dxf/dialog_dxf_import.cpp       |  10 +-
 pcbnew/import_dxf/dxf2brd_items.cpp           | 535 +++++++++++-------
 pcbnew/import_dxf/dxf2brd_items.h             | 274 ++++++---
 pcbnew/kicad_plugin.cpp                       |   4 +-
 pcbnew/pcb_painter.cpp                        |   5 +-
 pcbnew/pcb_parser.cpp                         |   4 +-
 pcbnew/tools/drawing_tool.cpp                 |  11 +-
 utils/idftools/CMakeLists.txt                 |   7 +-
 20 files changed, 760 insertions(+), 348 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index f2ea761f95..fbc438c78c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -941,7 +941,7 @@ add_subdirectory( 3d-viewer )
 add_subdirectory( cvpcb )
 add_subdirectory( eeschema )
 add_subdirectory( gerbview )
-add_subdirectory( lib_dxf )
+add_subdirectory( dxflib_qcad )
 add_subdirectory( pcbnew )
 add_subdirectory( polygon )
 add_subdirectory( pagelayout_editor )
diff --git a/common/bezier_curves.cpp b/common/bezier_curves.cpp
index 8b66185b7f..8d7f588478 100644
--- a/common/bezier_curves.cpp
+++ b/common/bezier_curves.cpp
@@ -45,9 +45,10 @@ static inline double sqrt_len( int dx, int dy )
 }
 
 
-void BEZIER_POLY::GetPoly( std::vector<wxPoint>& aOutput )
+void BEZIER_POLY::GetPoly( std::vector<wxPoint>& aOutput, int aMinSegLen )
 {
     wxCHECK( !m_ctrlPts.empty(), /* void */ );
+    m_minSegLen = std::max( 1, aMinSegLen );
     m_output = &aOutput;
     m_output->clear();
     m_output->push_back( wxPoint( m_ctrlPts.front() ) );
diff --git a/include/bezier_curves.h b/include/bezier_curves.h
index c4dabb3fb7..7fb63a139d 100644
--- a/include/bezier_curves.h
+++ b/include/bezier_curves.h
@@ -30,18 +30,22 @@
 
 /**
  * Bezier curves to polygon converter.
+ * Only quadratic and cubic Bezier curves are handled
  */
 class BEZIER_POLY
 {
 public:
+    /** cubic Bezier curve */
     BEZIER_POLY( int x1, int y1, int x2, int y2, int x3, int y3 )
     {
         m_ctrlPts.emplace_back( x1, y1 );
         m_ctrlPts.emplace_back( x2, y2 );
         m_ctrlPts.emplace_back( x3, y3 );
         m_output = nullptr;
+        m_minSegLen = 0;
     }
 
+    /** Quadratic and cubic Bezier curve */
     BEZIER_POLY( int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4 )
     {
         m_ctrlPts.emplace_back( x1, y1 );
@@ -49,21 +53,28 @@ public:
         m_ctrlPts.emplace_back( x3, y3 );
         m_ctrlPts.emplace_back( x4, y4 );
         m_output = nullptr;
+        m_minSegLen = 0;
     }
 
     BEZIER_POLY( const std::vector<wxPoint>& aControlPoints )
         : m_ctrlPts( aControlPoints )
     {
         m_output = nullptr;
+        m_minSegLen = 0;
     }
 
     /**
      * Converts Bezier curve to a polygon.
      * @param aOutput will be used as an output vector storing polygon points.
+     * @param aMinSegLen is the min dist between 2 successve points.
+     * It can be used to reduce the number of points.
+     * (the last point is always generated)
      */
-    void GetPoly( std::vector<wxPoint>& aOutput );
+    void GetPoly( std::vector<wxPoint>& aOutput, int aMinSegLen = 0 );
 
 private:
+    int m_minSegLen;
+
     ///> Control points
     std::vector<wxPoint> m_ctrlPts;
 
@@ -72,7 +83,11 @@ private:
 
     void addSegment( const wxPoint& aSegment )
     {
-        if( m_output->back() != aSegment )
+        int seglen = std::abs( m_output->back().x - aSegment.x )
+                     + std::abs( m_output->back().y - aSegment.y );
+
+        // m_minSegLen is always > 0, so never store a 0 len segment
+        if( seglen >= m_minSegLen )
             m_output->push_back( aSegment );
     }
 
diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt
index 0c7e1e7f63..f890e6179e 100644
--- a/pcbnew/CMakeLists.txt
+++ b/pcbnew/CMakeLists.txt
@@ -42,7 +42,7 @@ include_directories(
     ../polygon
     ../common/dialogs
     ./exporters
-    ../lib_dxf
+    ../dxflib_qcad
     ./import_dxf
     ../utils/idftools
     ${GLM_INCLUDE_DIR}
diff --git a/pcbnew/block_footprint_editor.cpp b/pcbnew/block_footprint_editor.cpp
index add517487f..11ac957c1c 100644
--- a/pcbnew/block_footprint_editor.cpp
+++ b/pcbnew/block_footprint_editor.cpp
@@ -533,10 +533,11 @@ void MoveMarkedItems( MODULE* module, wxPoint offset )
         case PCB_MODULE_EDGE_T:
         {
             EDGE_MODULE* em = (EDGE_MODULE*) item;
-            em->SetStart( em->GetStart() + offset );
-            em->SetEnd( em->GetEnd() + offset );
+            em->Move( offset );
             em->SetStart0( em->GetStart0() + offset );
             em->SetEnd0( em->GetEnd0() + offset );
+            em->SetBezier0_C1( em->GetBezier0_C1() + offset );
+            em->SetBezier0_C2( em->GetBezier0_C2() + offset );
         }
         break;
 
diff --git a/pcbnew/board_items_to_polygon_shape_transform.cpp b/pcbnew/board_items_to_polygon_shape_transform.cpp
index 9b94f08c4a..ffdab7d2da 100644
--- a/pcbnew/board_items_to_polygon_shape_transform.cpp
+++ b/pcbnew/board_items_to_polygon_shape_transform.cpp
@@ -33,6 +33,7 @@
 #include <vector>
 
 #include <fctsys.h>
+#include <bezier_curves.h>
 #include <base_units.h>     // for IU_PER_MM
 #include <draw_graphic_text.h>
 #include <pcbnew.h>
@@ -602,7 +603,19 @@ void DRAWSEGMENT::TransformShapeWithClearanceToPolygon( SHAPE_POLY_SET& aCornerB
         }
         break;
 
-    case S_CURVE:       // Bezier curve (TODO: not yet in use)
+    case S_CURVE:       // Bezier curve
+        {
+            std::vector<wxPoint> ctrlPoints = { m_Start, m_BezierC1, m_BezierC2, m_End };
+            BEZIER_POLY converter( ctrlPoints );
+            std::vector< wxPoint> poly;
+            converter.GetPoly( poly, m_Width );
+
+            for( unsigned ii = 1; ii < poly.size(); ii++ )
+            {
+                TransformRoundedEndsSegmentToPolygon( aCornerBuffer,
+                        poly[ii-1], poly[ii], aCircleToSegmentsCount, linewidth );
+            }
+        }
         break;
 
     default:
diff --git a/pcbnew/class_drawsegment.cpp b/pcbnew/class_drawsegment.cpp
index 3a2989dc49..75c1292a37 100644
--- a/pcbnew/class_drawsegment.cpp
+++ b/pcbnew/class_drawsegment.cpp
@@ -91,6 +91,18 @@ void DRAWSEGMENT::Move( const wxPoint& aMoveVector )
             (*iter) += VECTOR2I( aMoveVector );
         }
         break;
+
+    case S_CURVE:
+        m_BezierC1 += aMoveVector;
+        m_BezierC2 += aMoveVector;
+
+        for( unsigned int ii = 0; ii < m_BezierPoints.size(); ii++ )
+        {
+            m_BezierPoints[ii] += aMoveVector;
+        }
+
+        break;
+
     default:
         break;
     }
@@ -119,6 +131,8 @@ void DRAWSEGMENT::Rotate( const wxPoint& aRotCentre, double aAngle )
     case S_CURVE:
         RotatePoint( &m_Start, aRotCentre, aAngle);
         RotatePoint( &m_End, aRotCentre, aAngle);
+        RotatePoint( &m_BezierC1, aRotCentre, aAngle);
+        RotatePoint( &m_BezierC2, aRotCentre, aAngle);
 
         for( unsigned int ii = 0; ii < m_BezierPoints.size(); ii++ )
         {
@@ -145,21 +159,51 @@ void DRAWSEGMENT::Flip( const wxPoint& aCentre )
     case S_ARC:
         m_Angle = -m_Angle;
         break;
+
     case S_POLYGON:
         for( auto iter = m_Poly.Iterate(); iter; iter++ )
         {
             iter->y  = aCentre.y - (iter->y - aCentre.y);
         }
         break;
+
+    case S_CURVE:
+        {
+            m_BezierC1.y  = aCentre.y - (m_BezierC1.y - aCentre.y);
+            m_BezierC2.y  = aCentre.y - (m_BezierC2.y - aCentre.y);
+
+            // Rebuild the poly points shape
+            std::vector<wxPoint> ctrlPoints = { m_Start, m_BezierC1, m_BezierC2, m_End };
+            BEZIER_POLY converter( ctrlPoints );
+            converter.GetPoly( m_BezierPoints, m_Width );
+        }
+        break;
+
     default:
         break;
     }
 
     // DRAWSEGMENT items are not allowed on copper layers, so
-    // copper layers count is not taken in accoun in Flip transform
+    // copper layers count is not taken in account in Flip transform
     SetLayer( FlipLayer( GetLayer() ) );
 }
 
+
+void DRAWSEGMENT::RebuildBezierToSegmentsPointsList( int aMinSegLen )
+{
+    // Has meaning only for S_CURVE DRAW_SEGMENT shape
+    if( m_Shape != S_CURVE )
+    {
+        m_BezierPoints.clear();
+        return;
+    }
+    // Rebuild the m_BezierPoints vertex list that approximate the Bezier curve
+    std::vector<wxPoint> ctrlPoints = { m_Start, m_BezierC1, m_BezierC2, m_End };
+    BEZIER_POLY converter( ctrlPoints );
+    converter.GetPoly( m_BezierPoints, aMinSegLen );
+}
+
+
 const wxPoint DRAWSEGMENT::GetCenter() const
 {
     wxPoint c;
@@ -340,29 +384,24 @@ void DRAWSEGMENT::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, GR_DRAWMODE draw_mode,
 
     case S_CURVE:
         {
-            std::vector<wxPoint> ctrlPoints = { m_Start, m_BezierC1, m_BezierC2, m_End };
-            BEZIER_POLY converter( ctrlPoints );
-            converter.GetPoly( m_BezierPoints );
-        }
+            RebuildBezierToSegmentsPointsList( m_Width );
 
-        for( unsigned int i=1; i < m_BezierPoints.size(); i++ )
-        {
-            if( filled )
+            wxPoint& startp = m_BezierPoints[0];
+
+            for( unsigned int i = 1; i < m_BezierPoints.size(); i++ )
             {
-                GRFillCSegm( panel->GetClipBox(), DC,
-                             m_BezierPoints[i].x, m_BezierPoints[i].y,
-                             m_BezierPoints[i-1].x, m_BezierPoints[i-1].y,
-                             m_Width, color );
-            }
-            else
-            {
-                GRCSegm( panel->GetClipBox(), DC,
-                         m_BezierPoints[i].x, m_BezierPoints[i].y,
-                         m_BezierPoints[i-1].x, m_BezierPoints[i-1].y,
-                         m_Width, color );
+                wxPoint& endp = m_BezierPoints[i];
+
+                if( filled )
+                    GRFilledSegment( panel->GetClipBox(), DC,
+                                     startp+aOffset, endp+aOffset, m_Width, color );
+                else
+                    GRCSegm( panel->GetClipBox(), DC,
+                             startp+aOffset, endp+aOffset, m_Width, color );
+
+                startp = m_BezierPoints[i];
             }
         }
-
         break;
 
     case S_POLYGON:
@@ -518,6 +557,15 @@ const EDA_RECT DRAWSEGMENT::GetBoundingBox() const
         bbox.SetEnd( p_end );
         break;
 	}
+
+    case S_CURVE:
+        // Rebuild the poly points shape
+        ((DRAWSEGMENT*)this)->RebuildBezierToSegmentsPointsList( m_Width );
+
+        for( unsigned ii = 0; ii < m_BezierPoints.size(); ++ii )
+            bbox.Merge( m_BezierPoints[ii] );
+        break;
+
     default:
         break;
     }
@@ -578,6 +626,8 @@ bool DRAWSEGMENT::HitTest( const wxPoint& aPosition ) const
         break;
 
     case S_CURVE:
+        ((DRAWSEGMENT*)this)->RebuildBezierToSegmentsPointsList( m_Width );
+
         for( unsigned int i= 1; i < m_BezierPoints.size(); i++)
         {
             if( TestSegmentHit( aPosition, m_BezierPoints[i-1], m_BezierPoints[i-1], m_Width / 2 ) )
@@ -711,6 +761,35 @@ bool DRAWSEGMENT::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy
         break;
 
     case S_CURVE:     // not yet handled
+        if( aContained )
+        {
+            return arect.Contains( bb );
+        }
+        else
+        {
+            // Fast test: if aRect is outside the polygon bounding box,
+            // rectangles cannot intersect
+            if( !arect.Intersects( bb ) )
+                return false;
+
+            // Account for the width of the line
+            arect.Inflate( GetWidth() / 2 );
+            unsigned count = m_BezierPoints.size();
+
+            for( unsigned ii = 1; ii < count; ii++ )
+            {
+                wxPoint vertex = m_BezierPoints[ii-1];
+                wxPoint vertexNext = m_BezierPoints[ii];
+
+                // Test if the point is within aRect
+                if( arect.Contains( ( wxPoint ) vertex ) )
+                    return true;
+
+                // Test if this edge intersects aRect
+                if( arect.Intersects( vertex, vertexNext ) )
+                    return true;
+            }
+        }
         break;
 
 
diff --git a/pcbnew/class_drawsegment.h b/pcbnew/class_drawsegment.h
index 0b6dff4fbc..ee740aaebc 100644
--- a/pcbnew/class_drawsegment.h
+++ b/pcbnew/class_drawsegment.h
@@ -194,6 +194,16 @@ public:
         m_BezierPoints = aPoints;
     }
 
+    /** Rebuild the m_BezierPoints vertex list that approximate the Bezier curve
+     * by a list of segments
+     * Has meaning only for S_CURVE DRAW_SEGMENT shape
+     * @param aMinSegLen is the min length of segments approximating the shape.
+     * the last segment can be shorter
+     * This param avoid having too many very short segment in list.
+     * a good value is m_Width/2 to m_Width
+     */
+    void RebuildBezierToSegmentsPointsList( int aMinSegLen );
+
     void SetPolyPoints( const std::vector<wxPoint>& aPoints );
 
     void Draw( EDA_DRAW_PANEL* panel, wxDC* DC,
diff --git a/pcbnew/class_edge_mod.cpp b/pcbnew/class_edge_mod.cpp
index feef53a7b3..d16bc64829 100644
--- a/pcbnew/class_edge_mod.cpp
+++ b/pcbnew/class_edge_mod.cpp
@@ -75,14 +75,19 @@ void EDGE_MODULE::SetLocalCoord()
     {
         m_Start0 = m_Start;
         m_End0 = m_End;
+        m_Bezier0_C1 = m_BezierC1;
+        m_Bezier0_C2 = m_BezierC2;
         return;
     }
 
     m_Start0 = m_Start - module->GetPosition();
     m_End0 = m_End - module->GetPosition();
+    m_Bezier0_C1 = m_BezierC1 - module->GetPosition();
+    m_Bezier0_C2 = m_BezierC2 - module->GetPosition();
     double angle = module->GetOrientation();
     RotatePoint( &m_Start0.x, &m_Start0.y, -angle );
     RotatePoint( &m_End0.x, &m_End0.y, -angle );
+    RotatePoint( &m_Bezier0_C1.x, &m_Bezier0_C1.y, -angle );
 }
 
 
@@ -92,15 +97,23 @@ void EDGE_MODULE::SetDrawCoord()
 
     m_Start = m_Start0;
     m_End   = m_End0;
+    m_BezierC1 = m_Bezier0_C1;
+    m_BezierC2 = m_Bezier0_C2;
 
     if( module )
     {
         RotatePoint( &m_Start.x, &m_Start.y, module->GetOrientation() );
-        RotatePoint( &m_End.x,   &m_End.y,   module->GetOrientation() );
+        RotatePoint( &m_End.x, &m_End.y, module->GetOrientation() );
+        RotatePoint( &m_BezierC1.x, &m_BezierC1.y, module->GetOrientation() );
+        RotatePoint( &m_BezierC2.x, &m_BezierC2.y, module->GetOrientation() );
 
         m_Start += module->GetPosition();
         m_End   += module->GetPosition();
+        m_BezierC1   += module->GetPosition();
+        m_BezierC2   += module->GetPosition();
     }
+
+    RebuildBezierToSegmentsPointsList( m_Width );
 }
 
 
@@ -225,6 +238,28 @@ void EDGE_MODULE::Draw( EDA_DRAW_PANEL* panel, wxDC* DC, GR_DRAWMODE draw_mode,
         }
         break;
 
+    case S_CURVE:
+        {
+            RebuildBezierToSegmentsPointsList( m_Width );
+
+            wxPoint& startp = m_BezierPoints[0];
+
+            for( unsigned int i = 1; i < m_BezierPoints.size(); i++ )
+            {
+                wxPoint& endp = m_BezierPoints[i];
+
+                if( filled )
+                    GRFilledSegment( panel->GetClipBox(), DC,
+                                     startp-offset, endp-offset, m_Width, color );
+                else
+                    GRCSegm( panel->GetClipBox(), DC,
+                             startp-offset, endp-offset, m_Width, color );
+
+                startp = m_BezierPoints[i];
+            }
+        }
+        break;
+
     default:
         break;
     }
@@ -290,6 +325,7 @@ void EDGE_MODULE::Flip( const wxPoint& aCentre )
         //Fall through
     default:
     case S_SEGMENT:
+    case S_CURVE:
         pt = GetStart();
         MIRROR( pt.y, aCentre.y );
         SetStart( pt );
@@ -298,8 +334,14 @@ void EDGE_MODULE::Flip( const wxPoint& aCentre )
         MIRROR( pt.y, aCentre.y );
         SetEnd( pt );
 
+        MIRROR( m_BezierC1.y, aCentre.y );
+        MIRROR( m_BezierC2.y, aCentre.y );
+
         MIRROR( m_Start0.y, 0 );
         MIRROR( m_End0.y, 0 );
+        MIRROR( m_Bezier0_C1.y, 0 );
+        MIRROR( m_Bezier0_C2.y, 0 );
+        RebuildBezierToSegmentsPointsList( m_Width );
         break;
 
     case S_POLYGON:
@@ -336,18 +378,32 @@ void EDGE_MODULE::Mirror( wxPoint aCentre, bool aMirrorAroundXAxis )
         SetAngle( -GetAngle() );
         //Fall through
     default:
+    case S_CURVE:
     case S_SEGMENT:
         if( aMirrorAroundXAxis )
         {
             MIRROR( m_Start0.y, aCentre.y );
             MIRROR( m_End0.y, aCentre.y );
+            MIRROR( m_Bezier0_C1.y, aCentre.y );
+            MIRROR( m_Bezier0_C2.y, aCentre.y );
         }
         else
         {
             MIRROR( m_Start0.x, aCentre.x );
             MIRROR( m_End0.x, aCentre.x );
+            MIRROR( m_Bezier0_C1.x, aCentre.x );
+            MIRROR( m_Bezier0_C2.x, aCentre.x );
         }
-            break;
+
+        for( unsigned ii = 0; ii < m_BezierPoints.size(); ii++ )
+        {
+            if( aMirrorAroundXAxis )
+                MIRROR( m_BezierPoints[ii].y, aCentre.y );
+            else
+                MIRROR( m_BezierPoints[ii].x, aCentre.x );
+        }
+
+        break;
 
     case S_POLYGON:
         // polygon corners coordinates are always relative to the
@@ -383,6 +439,8 @@ void EDGE_MODULE::Move( const wxPoint& aMoveVector )
     // This is a footprint shape modification.
     m_Start0 += aMoveVector;
     m_End0   += aMoveVector;
+    m_Bezier0_C1   += aMoveVector;
+    m_Bezier0_C2   += aMoveVector;
 
     switch( GetShape() )
     {
diff --git a/pcbnew/class_edge_mod.h b/pcbnew/class_edge_mod.h
index 07b766543f..7cfd0520e4 100644
--- a/pcbnew/class_edge_mod.h
+++ b/pcbnew/class_edge_mod.h
@@ -96,6 +96,12 @@ public:
     void SetEnd0( const wxPoint& aPoint )       { m_End0 = aPoint; }
     const wxPoint& GetEnd0() const              { return m_End0; }
 
+    void SetBezier0_C1( const wxPoint& aPoint ) { m_Bezier0_C1 = aPoint; }
+    const wxPoint& GetBezier0_C1() const        { return m_Bezier0_C1; }
+
+    void SetBezier0_C2( const wxPoint& aPoint ) { m_Bezier0_C2 = aPoint; }
+    const wxPoint& GetBezier0_C2() const        { return m_Bezier0_C2; }
+
     /**
      * Set relative coordinates from draw coordinates.
      * Call in only when the geometry ov the footprint is modified
@@ -134,8 +140,10 @@ public:
     void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); }
 #endif
 
-    wxPoint m_Start0;       // Start point or center, relative to module origin, orient 0.
-    wxPoint m_End0;         // End point, relative to module origin, orient 0.
+    wxPoint m_Start0;       ///< Start point or center, relative to module origin, orient 0.
+    wxPoint m_End0;         ///< End point, relative to module origin, orient 0.
+    wxPoint m_Bezier0_C1;   ///< Bezier Control Point 1, relative to module origin, orient 0.
+    wxPoint m_Bezier0_C2;   ///< Bezier Control Point 2, relative to module origin, orient 0.
 };
 
 #endif    // CLASS_EDGE_MOD_H_
diff --git a/pcbnew/edgemod.cpp b/pcbnew/edgemod.cpp
index 5efc65d7f9..25d22e6455 100644
--- a/pcbnew/edgemod.cpp
+++ b/pcbnew/edgemod.cpp
@@ -79,11 +79,7 @@ void FOOTPRINT_EDIT_FRAME::Place_EdgeMod( EDGE_MODULE* aEdge )
     if( aEdge == NULL )
         return;
 
-    aEdge->SetStart( aEdge->GetStart() - MoveVector );
-    aEdge->SetEnd(   aEdge->GetEnd()   - MoveVector );
-
-    aEdge->SetStart0( aEdge->GetStart0() - MoveVector );
-    aEdge->SetEnd0(   aEdge->GetEnd0()   - MoveVector );
+    aEdge->Move( -MoveVector );
 
     aEdge->ClearFlags();
     m_canvas->SetMouseCapture( NULL, NULL );
diff --git a/pcbnew/editedge.cpp b/pcbnew/editedge.cpp
index 763513788f..fa5454b96e 100644
--- a/pcbnew/editedge.cpp
+++ b/pcbnew/editedge.cpp
@@ -101,8 +101,7 @@ static void Move_Segment( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPos
     wxPoint delta;
     delta = aPanel->GetParent()->GetCrossHairPosition() - s_LastPosition;
 
-    segment->SetStart( segment->GetStart() + delta );
-    segment->SetEnd(   segment->GetEnd()   + delta );
+    segment->Move( delta );
 
     s_LastPosition = aPanel->GetParent()->GetCrossHairPosition();
 
diff --git a/pcbnew/import_dxf/dialog_dxf_import.cpp b/pcbnew/import_dxf/dialog_dxf_import.cpp
index 3fb210c2cb..c46458aa39 100644
--- a/pcbnew/import_dxf/dialog_dxf_import.cpp
+++ b/pcbnew/import_dxf/dialog_dxf_import.cpp
@@ -300,7 +300,15 @@ bool DIALOG_DXF_IMPORT::TransferDataFromWindow()
     // Read dxf file:
     m_dxfImporter.ImportDxfFile( m_dxfFilename );
 
-   return true;
+    // Get messages:
+    std::string& messages = m_dxfImporter.GetMessages();
+
+    if( messages.empty() )
+        return true;
+
+    // Show messages (list of net handled dxf items
+    wxMessageBox( messages.c_str(), _( "Not Handled DXF Items" ) );
+    return true;
 }
 
 
diff --git a/pcbnew/import_dxf/dxf2brd_items.cpp b/pcbnew/import_dxf/dxf2brd_items.cpp
index b02438630c..960b98b985 100644
--- a/pcbnew/import_dxf/dxf2brd_items.cpp
+++ b/pcbnew/import_dxf/dxf2brd_items.cpp
@@ -1,8 +1,8 @@
 /*
  * This program source code file is part of KiCad, a free EDA CAD application.
  *
- * Copyright (C) 2013 Jean-Pierre Charras, jp.charras at wanadoo.fr
- * Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors.
+ * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
+ * Copyright (C) 1992-2018 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
@@ -35,7 +35,6 @@
 // this function just add the BOARD entity from dxf parameters (start and end point ...)
 
 
-#include "libdxfrw.h"
 #include "dxf2brd_items.h"
 #include <wx/arrstr.h>
 #include <wx/regex.h>
@@ -48,13 +47,12 @@
 #include <class_pcb_text.h>
 #include <class_text_mod.h>
 #include "common.h"
-#include <drw_base.h>
 
 // minimum bulge value before resorting to a line segment;
 // the value 0.0218 is equivalent to about 5 degrees arc,
 #define MIN_BULGE 0.0218
 
-DXF2BRD_CONVERTER::DXF2BRD_CONVERTER() : DRW_Interface()
+DXF2BRD_CONVERTER::DXF2BRD_CONVERTER() : DL_CreationAdapter()
 {
     m_xOffset   = 0.0;          // X coord offset for conversion (in mm)
     m_yOffset   = 0.0;          // Y coord offset for conversion (in mm)
@@ -92,26 +90,78 @@ int DXF2BRD_CONVERTER::mapDim( double aDxfValue )
 
 int DXF2BRD_CONVERTER::mapWidth( double aDxfWidth )
 {
+    // Always return the default line width
+#if 0
     // mapWidth returns the aDxfValue if aDxfWidth > 0 m_defaultThickness
     if( aDxfWidth > 0.0 )
         return Millimeter2iu( aDxfWidth * m_DXF2mm );
-
+#endif
     return  Millimeter2iu( m_defaultThickness );
 }
 
 bool DXF2BRD_CONVERTER::ImportDxfFile( const wxString& aFile )
 {
     LOCALE_IO locale;
-    dxfRW* dxf = new dxfRW( aFile.ToUTF8() );
-    bool success = dxf->read( this, true );
 
-    delete dxf;
+    DL_Dxf dxf_reader;
+    std::string filename = TO_UTF8( aFile );
+    bool success = true;
+
+    if( !dxf_reader.in( filename, this ) )  // if file open failed
+        success = false;
 
     return success;
 }
 
 
-void DXF2BRD_CONVERTER::addLayer( const DRW_Layer& aData )
+void DXF2BRD_CONVERTER::reportMsg( const char* aMessage )
+{
+    // Add message to keep trace of not handled dxf entities
+    m_messages += aMessage;
+    m_messages += '\n';
+}
+
+
+void DXF2BRD_CONVERTER::addSpline( const DL_SplineData& aData )
+{
+    // Called when starting reading a spline
+    m_curr_entity.Clear();
+    m_curr_entity.m_EntityParseStatus = 1;
+    m_curr_entity.m_EntityFlag = aData.flags;
+    m_curr_entity.m_EntityType = DL_ENTITY_SPLINE;
+    m_curr_entity.m_SplineDegree = aData.degree;
+    m_curr_entity.m_SplineTangentStartX = aData.tangentStartX;
+    m_curr_entity.m_SplineTangentStartY = aData.tangentStartY;
+    m_curr_entity.m_SplineTangentEndX = aData.tangentEndX;
+    m_curr_entity.m_SplineTangentEndY = aData.tangentEndY;
+    m_curr_entity.m_SplineKnotsCount = aData.nKnots;
+    m_curr_entity.m_SplineControlCount = aData.nControl;
+    m_curr_entity.m_SplineFitCount = aData.nFit;
+}
+
+
+void DXF2BRD_CONVERTER::addControlPoint( const DL_ControlPointData& aData )
+{
+    // Called for every spline control point, when reading a spline entity
+    m_curr_entity.m_SplineControlPointList.push_back( SPLINE_CTRL_POINT( aData.x , aData.y, aData.w ) );
+}
+
+void DXF2BRD_CONVERTER::addFitPoint( const DL_FitPointData& aData )
+{
+    // Called for every spline fit point, when reading a spline entity
+    // we store only the X,Y coord values in a wxRealPoint
+    m_curr_entity.m_SplineFitPointList.push_back( wxRealPoint( aData.x, aData.y ) );
+}
+
+
+void DXF2BRD_CONVERTER::addKnot( const DL_KnotData& aData)
+{
+    // Called for every spline knot value, when reading a spline entity
+    m_curr_entity.m_SplineKnotsList.push_back( aData.k );
+}
+
+
+void DXF2BRD_CONVERTER::addLayer( const DL_LayerData& aData )
 {
     // Not yet useful in Pcbnew.
 #if 0
@@ -121,129 +171,110 @@ void DXF2BRD_CONVERTER::addLayer( const DRW_Layer& aData )
 }
 
 
-void DXF2BRD_CONVERTER::addLine( const DRW_Line& aData )
+void DXF2BRD_CONVERTER::addLine( const DL_LineData& aData )
 {
     DRAWSEGMENT* segm = ( m_importAsfootprintGraphicItems ) ?
                         static_cast< DRAWSEGMENT* >( new EDGE_MODULE( NULL ) ) : new DRAWSEGMENT;
 
     segm->SetLayer( ToLAYER_ID( m_brdLayer ) );
-    wxPoint start( mapX( aData.basePoint.x ), mapY( aData.basePoint.y ) );
+    wxPoint start( mapX( aData.x1 ), mapY( aData.y1 ) );
     segm->SetStart( start );
-    wxPoint end( mapX( aData.secPoint.x ), mapY( aData.secPoint.y ) );
+    wxPoint end( mapX( aData.x2 ), mapY( aData.y2 ) );
     segm->SetEnd( end );
-    segm->SetWidth( mapWidth( aData.thickness ) );
+    segm->SetWidth( mapWidth( attributes.getWidth() ) );
     m_newItemsList.push_back( segm );
 }
 
-void DXF2BRD_CONVERTER::addPolyline(const DRW_Polyline& aData )
+
+void DXF2BRD_CONVERTER::addPolyline(const DL_PolylineData& aData )
 {
     // Convert DXF Polylines into a series of KiCad Lines and Arcs.
     // A Polyline (as opposed to a LWPolyline) may be a 3D line or
     // even a 3D Mesh. The only type of Polyline which is guaranteed
     // to import correctly is a 2D Polyline in X and Y, which is what
-    // we assume of all Polylines. The width used is the width of the
-    // Polyline; per-vertex line widths, if present, are ignored.
+    // we assume of all Polylines. The width used is the width of the Polyline.
+    // per-vertex line widths, if present, are ignored.
 
-    wxRealPoint seg_start;
-    wxRealPoint poly_start;
-    double bulge = 0.0;
-    int lineWidth = mapWidth( aData.thickness );
-
-    for( unsigned ii = 0; ii < aData.vertlist.size(); ii++ )
-    {
-        DRW_Vertex* vertex = aData.vertlist[ii];
-
-        if( ii == 0 )
-        {
-            seg_start.x = m_xOffset + vertex->basePoint.x * m_DXF2mm;
-            seg_start.y = m_yOffset - vertex->basePoint.y * m_DXF2mm;
-            bulge = vertex->bulge;
-            poly_start = seg_start;
-            continue;
-        }
-
-        wxRealPoint seg_end( m_xOffset + vertex->basePoint.x * m_DXF2mm,
-                             m_yOffset - vertex->basePoint.y * m_DXF2mm );
-
-        if( std::abs( bulge ) < MIN_BULGE )
-            insertLine( seg_start, seg_end, lineWidth );
-        else
-            insertArc( seg_start, seg_end, bulge, lineWidth );
-
-        bulge = vertex->bulge;
-        seg_start = seg_end;
-    }
-
-    // LWPolyline flags bit 0 indicates closed (1) or open (0) polyline
-    if( aData.flags & 1 )
-    {
-        if( std::abs( bulge ) < MIN_BULGE )
-            insertLine( seg_start, poly_start, lineWidth );
-        else
-            insertArc( seg_start, poly_start, bulge, lineWidth );
-    }
+    m_curr_entity.Clear();
+    m_curr_entity.m_EntityParseStatus = 1;
+    m_curr_entity.m_EntityFlag = aData.flags;
+    m_curr_entity.m_EntityType = DL_ENTITY_POLYLINE;
 }
 
 
-void DXF2BRD_CONVERTER::addLWPolyline(const DRW_LWPolyline& aData )
+void DXF2BRD_CONVERTER::addVertex( const DL_VertexData& aData )
 {
-    // Currently, Pcbnew does not know polylines, for boards.
-    // So we have to convert a polyline to a set of segments.
-    // The import is a simplified import: the width of segment is
-    // (obviously constant and is the width of the DRW_LWPolyline.
-    // the variable width of each vertex (when exists) is not used.
-    wxRealPoint seg_start;
-    wxRealPoint poly_start;
-    double bulge = 0.0;
-    int lineWidth = mapWidth( aData.thickness );
+    if( m_curr_entity.m_EntityParseStatus == 0 )
+        return;     // Error
 
-    for( unsigned ii = 0; ii < aData.vertlist.size(); ii++ )
+    int lineWidth = mapWidth( attributes.getWidth() );
+
+    const DL_VertexData* vertex = &aData;
+
+    if( m_curr_entity.m_EntityParseStatus == 1 )    // This is the first vertex of an entity
     {
-        DRW_Vertex2D* vertex = aData.vertlist[ii];
-
-        if( ii == 0 )
-        {
-            seg_start.x = m_xOffset + vertex->x * m_DXF2mm;
-            seg_start.y = m_yOffset - vertex->y * m_DXF2mm;
-            bulge = vertex->bulge;
-            poly_start = seg_start;
-            continue;
-        }
-
-        wxRealPoint seg_end( m_xOffset + vertex->x * m_DXF2mm, m_yOffset - vertex->y * m_DXF2mm );
-
-        if( std::abs( bulge ) < MIN_BULGE )
-            insertLine( seg_start, seg_end, lineWidth );
-        else
-            insertArc( seg_start, seg_end, bulge, lineWidth );
-
-        bulge = vertex->bulge;
-        seg_start = seg_end;
+        m_curr_entity.m_LastCoordinate.x = m_xOffset + vertex->x * m_DXF2mm;
+        m_curr_entity.m_LastCoordinate.y = m_yOffset - vertex->y * m_DXF2mm;
+        m_curr_entity.m_PolylineStart = m_curr_entity.m_LastCoordinate;
+        m_curr_entity.m_BulgeVertex = vertex->bulge;
+        m_curr_entity.m_EntityParseStatus = 2;
+        return;
     }
 
-    // LWPolyline flags bit 0 indicates closed (1) or open (0) polyline
-    if( aData.flags & 1 )
-    {
-        if( std::abs( bulge ) < MIN_BULGE )
-            insertLine( seg_start, poly_start, lineWidth );
-        else
-            insertArc( seg_start, poly_start, bulge, lineWidth );
-    }
+
+    wxRealPoint seg_end( m_xOffset + vertex->x * m_DXF2mm,
+                         m_yOffset - vertex->y * m_DXF2mm );
+
+    if( std::abs( m_curr_entity.m_BulgeVertex ) < MIN_BULGE )
+        insertLine( m_curr_entity.m_LastCoordinate, seg_end, lineWidth );
+    else
+        insertArc( m_curr_entity.m_LastCoordinate, seg_end, m_curr_entity.m_BulgeVertex, lineWidth );
+
+    m_curr_entity.m_LastCoordinate = seg_end;
+    m_curr_entity.m_BulgeVertex = vertex->bulge;
 }
 
 
-void DXF2BRD_CONVERTER::addCircle( const DRW_Circle& aData )
+void DXF2BRD_CONVERTER::endEntity()
+{
+    if( m_curr_entity.m_EntityType == DL_ENTITY_POLYLINE ||
+        m_curr_entity.m_EntityType == DL_ENTITY_LWPOLYLINE )
+    {
+        // Polyline flags bit 0 indicates closed (1) or open (0) polyline
+        if( m_curr_entity.m_EntityFlag & 1 )
+        {
+            int lineWidth = mapWidth( attributes.getWidth() );
+
+            if( std::abs( m_curr_entity.m_BulgeVertex ) < MIN_BULGE )
+                insertLine( m_curr_entity.m_LastCoordinate, m_curr_entity.m_PolylineStart, lineWidth );
+            else
+                insertArc( m_curr_entity.m_LastCoordinate, m_curr_entity.m_PolylineStart,
+                           m_curr_entity.m_BulgeVertex, lineWidth );
+        }
+    }
+
+    if( m_curr_entity.m_EntityType == DL_ENTITY_SPLINE )
+    {
+        int lineWidth = mapWidth( attributes.getWidth() );
+        insertSpline( lineWidth );
+    }
+
+    m_curr_entity.Clear();
+}
+
+
+void DXF2BRD_CONVERTER::addCircle( const DL_CircleData& aData )
 {
     DRAWSEGMENT* segm = ( m_importAsfootprintGraphicItems ) ?
                         static_cast< DRAWSEGMENT* >( new EDGE_MODULE( NULL ) ) : new DRAWSEGMENT;
 
     segm->SetLayer( ToLAYER_ID( m_brdLayer ) );
     segm->SetShape( S_CIRCLE );
-    wxPoint center( mapX( aData.basePoint.x ), mapY( aData.basePoint.y ) );
+    wxPoint center( mapX( aData.cx ), mapY( aData.cy ) );
     segm->SetCenter( center );
-    wxPoint circle_start( mapX( aData.basePoint.x + aData.radious ), mapY( aData.basePoint.y ) );
+    wxPoint circle_start( mapX( aData.cx + aData.radius ), mapY( aData.cy ) );
     segm->SetArcStart( circle_start );
-    segm->SetWidth( mapWidth( aData.thickness ) );
+    segm->SetWidth( mapWidth( attributes.getWidth() ) );
     m_newItemsList.push_back( segm );
 }
 
@@ -251,7 +282,7 @@ void DXF2BRD_CONVERTER::addCircle( const DRW_Circle& aData )
 /*
  * Import Arc entities.
  */
-void DXF2BRD_CONVERTER::addArc( const DRW_Arc& data )
+void DXF2BRD_CONVERTER::addArc( const DL_ArcData& data )
 {
     DRAWSEGMENT* segm = ( m_importAsfootprintGraphicItems ) ?
                         static_cast< DRAWSEGMENT* >( new EDGE_MODULE( NULL ) ) : new DRAWSEGMENT;
@@ -260,18 +291,18 @@ void DXF2BRD_CONVERTER::addArc( const DRW_Arc& data )
     segm->SetShape( S_ARC );
 
     // Init arc centre:
-    wxPoint center( mapX( data.basePoint.x ), mapY( data.basePoint.y ) );
+    wxPoint center( mapX( data.cx ), mapY( data.cy ) );
     segm->SetCenter( center );
 
     // Init arc start point
-    double  arcStartx   = data.radious;
+    double  arcStartx   = data.radius;
     double  arcStarty   = 0;
-    double  startangle = data.staangle;
-    double  endangle = data.endangle;
+    double  startangle = data.angle1;
+    double  endangle = data.angle2;
 
     RotatePoint( &arcStartx, &arcStarty, -RAD2DECIDEG( startangle ) );
-    wxPoint arcStart( mapX( arcStartx + data.basePoint.x ),
-                      mapY( arcStarty + data.basePoint.y ) );
+    wxPoint arcStart( mapX( arcStartx + data.cx ),
+                      mapY( arcStarty + data.cy ) );
     segm->SetArcStart( arcStart );
 
     // calculate arc angle (arcs are CCW, and should be < 0 in Pcbnew)
@@ -282,12 +313,12 @@ void DXF2BRD_CONVERTER::addArc( const DRW_Arc& data )
 
     segm->SetAngle( angle );
 
-    segm->SetWidth( mapWidth( data.thickness ) );
+    segm->SetWidth( mapWidth( attributes.getWidth() ) );
     m_newItemsList.push_back( segm );
 }
 
 
-void DXF2BRD_CONVERTER::addText( const DRW_Text& aData )
+void DXF2BRD_CONVERTER::addText( const DL_TextData& aData )
 {
     BOARD_ITEM* brdItem;
     EDA_TEXT* textItem;
@@ -307,12 +338,12 @@ void DXF2BRD_CONVERTER::addText( const DRW_Text& aData )
 
     brdItem->SetLayer( ToLAYER_ID( m_brdLayer ) );
 
-    wxPoint refPoint( mapX( aData.basePoint.x ), mapY( aData.basePoint.y ) );
-    wxPoint secPoint( mapX( aData.secPoint.x ), mapY( aData.secPoint.y ) );
+    wxPoint refPoint( mapX( aData.ipx ), mapY( aData.ipy ) );
+    wxPoint secPoint( mapX( aData.apx ), mapY( aData.apy ) );
 
-    if( aData.alignV != 0 || aData.alignH != 0 || aData.alignH == DRW_Text::HMiddle )
+    if( aData.vJustification != 0 || aData.hJustification != 0 || aData.hJustification == 4 )
     {
-        if( aData.alignH != DRW_Text::HAligned && aData.alignH != DRW_Text::HFit )
+        if( aData.hJustification != 3 && aData.hJustification != 5 )
         {
             wxPoint tmp = secPoint;
             secPoint = refPoint;
@@ -320,50 +351,50 @@ void DXF2BRD_CONVERTER::addText( const DRW_Text& aData )
         }
     }
 
-    switch( aData.alignV )
+    switch( aData.vJustification )
     {
-    case DRW_Text::VBaseLine:
+    case 0: //DRW_Text::VBaseLine:
         textItem->SetVertJustify( GR_TEXT_VJUSTIFY_BOTTOM );
         break;
 
-    case DRW_Text::VBottom:
+    case 1: //DRW_Text::VBottom:
         textItem->SetVertJustify( GR_TEXT_VJUSTIFY_BOTTOM );
         break;
 
-    case DRW_Text::VMiddle:
+    case 2: //DRW_Text::VMiddle:
         textItem->SetVertJustify( GR_TEXT_VJUSTIFY_CENTER );
         break;
 
-    case DRW_Text::VTop:
+    case 3: //DRW_Text::VTop:
         textItem->SetVertJustify( GR_TEXT_VJUSTIFY_TOP );
         break;
     }
 
-    switch( aData.alignH )
+    switch( aData.hJustification )
     {
-    case DRW_Text::HLeft:
+    case 0: //DRW_Text::HLeft:
         textItem->SetHorizJustify( GR_TEXT_HJUSTIFY_LEFT );
         break;
 
-    case DRW_Text::HCenter:
+    case 1: //DRW_Text::HCenter:
         textItem->SetHorizJustify( GR_TEXT_HJUSTIFY_CENTER );
         break;
 
-    case DRW_Text::HRight:
+    case 2: //DRW_Text::HRight:
         textItem->SetHorizJustify( GR_TEXT_HJUSTIFY_RIGHT );
         break;
 
-    case DRW_Text::HAligned:
+    case 3: //DRW_Text::HAligned:
         // no equivalent options in text pcb.
         textItem->SetHorizJustify( GR_TEXT_HJUSTIFY_LEFT );
         break;
 
-    case DRW_Text::HMiddle:
+    case 4: //DRW_Text::HMiddle:
         // no equivalent options in text pcb.
         textItem->SetHorizJustify( GR_TEXT_HJUSTIFY_CENTER );
         break;
 
-    case DRW_Text::HFit:
+    case 5: //DRW_Text::HFit:
         // no equivalent options in text pcb.
         textItem->SetHorizJustify( GR_TEXT_HJUSTIFY_LEFT );
         break;
@@ -392,14 +423,14 @@ void DXF2BRD_CONVERTER::addText( const DRW_Text& aData )
     // The 0.8 factor gives a better height/width ratio with our font
     textItem->SetTextWidth( mapDim( aData.height * 0.8 ) );
     textItem->SetTextHeight( mapDim( aData.height ) );
-    textItem->SetThickness( mapWidth( aData.thickness ) );
+    textItem->SetThickness( mapWidth( aData.height * 0.15 ) );  // Gives a reasonable text thickness
     textItem->SetText( text );
 
     m_newItemsList.push_back( static_cast< BOARD_ITEM* >( brdItem ) );
 }
 
 
-void DXF2BRD_CONVERTER::addMText( const DRW_MText& aData )
+void DXF2BRD_CONVERTER::addMText( const DL_MTextData& aData )
 {
     wxString    text = toNativeString( wxString::FromUTF8( aData.text.c_str() ) );
     wxString    attrib, tmp;
@@ -446,7 +477,7 @@ void DXF2BRD_CONVERTER::addMText( const DRW_MText& aData )
     }
 
     brdItem->SetLayer( ToLAYER_ID( m_brdLayer ) );
-    wxPoint     textpos( mapX( aData.basePoint.x ), mapY( aData.basePoint.y ) );
+    wxPoint textpos( mapX( aData.ipx ), mapY( aData.ipy ) );
 
     textItem->SetTextPos( textpos );
     textItem->SetTextAngle( aData.angle * 10 );
@@ -454,15 +485,15 @@ void DXF2BRD_CONVERTER::addMText( const DRW_MText& aData )
     // The 0.8 factor gives a better height/width ratio with our font
     textItem->SetTextWidth( mapDim( aData.height * 0.8 ) );
     textItem->SetTextHeight( mapDim( aData.height ) );
-    textItem->SetThickness( mapWidth( aData.thickness ) );
+    textItem->SetThickness( mapWidth( aData.height * 0.15 ) );  // Gives a reasonable text thickness
     textItem->SetText( text );
 
     // Initialize text justifications:
-    if( aData.textgen <= 3 )
+    if( aData.attachmentPoint <= 3 )
     {
         textItem->SetVertJustify( GR_TEXT_VJUSTIFY_TOP );
     }
-    else if( aData.textgen <= 6 )
+    else if( aData.attachmentPoint <= 6 )
     {
         textItem->SetVertJustify( GR_TEXT_VJUSTIFY_CENTER );
     }
@@ -471,11 +502,11 @@ void DXF2BRD_CONVERTER::addMText( const DRW_MText& aData )
         textItem->SetVertJustify( GR_TEXT_VJUSTIFY_BOTTOM );
     }
 
-    if( aData.textgen % 3 == 1 )
+    if( aData.attachmentPoint % 3 == 1 )
     {
         textItem->SetHorizJustify( GR_TEXT_HJUSTIFY_LEFT );
     }
-    else if( aData.textgen % 3 == 2 )
+    else if( aData.attachmentPoint % 3 == 2 )
     {
         textItem->SetHorizJustify( GR_TEXT_HJUSTIFY_CENTER );
     }
@@ -484,7 +515,7 @@ void DXF2BRD_CONVERTER::addMText( const DRW_MText& aData )
         textItem->SetHorizJustify( GR_TEXT_HJUSTIFY_RIGHT );
     }
 
-#if 0   // These setting have no mening in Pcbnew
+#if 0   // These setting have no meaning in Pcbnew
     if( data.alignH == 1 )
     {
         // Text is left to right;
@@ -512,86 +543,92 @@ void DXF2BRD_CONVERTER::addMText( const DRW_MText& aData )
 }
 
 
-void DXF2BRD_CONVERTER::addHeader( const DRW_Header* data )
+void DXF2BRD_CONVERTER::setVariableInt( const std::string& key, int value, int code )
 {
-    std::map<std::string, DRW_Variant*>::const_iterator it;
-    m_DXF2mm = 1.0; // assume no scale factor
+    // Called for every int variable in the DXF file (e.g. "$INSUNITS").
 
-    for( it = data->vars.begin(); it != data->vars.end(); ++it )
+    if( key == "$DWGCODEPAGE" )
     {
-        std::string key = ( (*it).first ).c_str();
-
-        if( key == "$DWGCODEPAGE" )
-        {
-            DRW_Variant* var = (*it).second;
-            m_codePage = ( *var->content.s );
-        }
-        else if( key == "$INSUNITS" )
-        {
-            DRW_Variant* var = (*it).second;
-
-            switch( var->content.i )
-            {
-            case 1:     // inches
-                m_DXF2mm = 25.4;
-                break;
-
-            case 2:     // feet
-                m_DXF2mm = 304.8;
-                break;
-
-            case 5:     // centimeters
-                m_DXF2mm = 10.0;
-                break;
-
-            case 6:     // meters
-                m_DXF2mm = 1000.0;
-                break;
-
-            case 8:     // microinches
-                m_DXF2mm = 2.54e-5;
-                break;
-
-            case 9:     // mils
-                m_DXF2mm = 0.0254;
-                break;
-
-            case 10:    // yards
-                m_DXF2mm = 914.4;
-                break;
-
-            case 11:    // Angstroms
-                m_DXF2mm = 1.0e-7;
-                break;
-
-            case 12:    // nanometers
-                m_DXF2mm = 1.0e-6;
-                break;
-
-            case 13:    // micrometers
-                m_DXF2mm = 1.0e-3;
-                break;
-
-            case 14:    // decimeters
-                m_DXF2mm = 100.0;
-                break;
-
-            default:
-                // use the default of 1.0 for:
-                // 0: Unspecified Units
-                // 4: mm
-                // 3: miles
-                // 7: kilometers
-                // 15: decameters
-                // 16: hectometers
-                // 17: gigameters
-                // 18: AU
-                // 19: lightyears
-                // 20: parsecs
-                break;
-            }
-        }
+        m_codePage = value;
+        return;
     }
+
+    if( key == "$INSUNITS" )    // Drawing units
+    {
+        switch( value )
+        {
+        case 1:     // inches
+            m_DXF2mm = 25.4;
+            break;
+
+        case 2:     // feet
+            m_DXF2mm = 304.8;
+            break;
+
+        case 4:     // mm
+            m_DXF2mm = 1.0;
+            break;
+
+        case 5:     // centimeters
+            m_DXF2mm = 10.0;
+            break;
+
+        case 6:     // meters
+            m_DXF2mm = 1000.0;
+            break;
+
+        case 8:     // microinches
+            m_DXF2mm = 2.54e-5;
+            break;
+
+        case 9:     // mils
+            m_DXF2mm = 0.0254;
+            break;
+
+        case 10:    // yards
+            m_DXF2mm = 914.4;
+            break;
+
+        case 11:    // Angstroms
+            m_DXF2mm = 1.0e-7;
+            break;
+
+        case 12:    // nanometers
+            m_DXF2mm = 1.0e-6;
+            break;
+
+        case 13:    // micrometers
+            m_DXF2mm = 1.0e-3;
+            break;
+
+        case 14:    // decimeters
+            m_DXF2mm = 100.0;
+            break;
+
+        default:
+            // use the default of 1.0 for:
+            // 0: Unspecified Units
+            // 3: miles
+            // 7: kilometers
+            // 15: decameters
+            // 16: hectometers
+            // 17: gigameters
+            // 18: AU
+            // 19: lightyears
+            // 20: parsecs
+            m_DXF2mm = 1.0;
+            break;
+        }
+
+    return;
+    }
+}
+
+
+void DXF2BRD_CONVERTER::setVariableString( const std::string& key, const std::string& value,
+        int code )
+{
+    // Called for every string variable in the DXF file (e.g. "$ACADVER").
 }
 
 
@@ -723,7 +760,7 @@ wxString DXF2BRD_CONVERTER::toNativeString( const wxString& aData )
 }
 
 
-void DXF2BRD_CONVERTER::addTextStyle( const DRW_Textstyle& aData )
+void DXF2BRD_CONVERTER::addTextStyle( const DL_StyleData& aData )
 {
     // TODO
 }
@@ -743,7 +780,6 @@ void DXF2BRD_CONVERTER::insertLine( const wxRealPoint& aSegStart,
     segm->SetWidth( aWidth );
 
     m_newItemsList.push_back( segm );
-    return;
 }
 
 
@@ -825,3 +861,82 @@ void DXF2BRD_CONVERTER::insertArc( const wxRealPoint& aSegStart, const wxRealPoi
     m_newItemsList.push_back( segm );
     return;
 }
+
+
+#include "tinyspline_lib/tinysplinecpp.h"
+
+void DXF2BRD_CONVERTER::insertSpline( int aWidth )
+{
+    #if 0   // Debug only
+    wxLogMessage("spl deg %d kn %d ctr %d fit %d",
+         m_curr_entity.m_SplineDegree,
+         m_curr_entity.m_SplineKnotsList.size(),
+         m_curr_entity.m_SplineControlPointList.size(),
+         m_curr_entity.m_SplineFitPointList.size() );
+    #endif
+
+    // Very basic conversion to segments
+    unsigned imax = m_curr_entity.m_SplineControlPointList.size();
+
+    if( imax < 2 )  // malformed spline
+        return;
+
+#if 0   // set to 1 to approximate the spline by segments between 2 control points
+    wxPoint startpoint( mapX( m_curr_entity.m_SplineControlPointList[0].m_x ),
+                        mapY( m_curr_entity.m_SplineControlPointList[0].m_y ) );
+
+    for( unsigned int ii = 1; ii < imax; ++ii )
+    {
+        wxPoint endpoint( mapX( m_curr_entity.m_SplineControlPointList[ii].m_x ),
+                          mapY( m_curr_entity.m_SplineControlPointList[ii].m_y ) );
+
+        if( startpoint != endpoint )
+        {
+            DRAWSEGMENT* segm = ( m_importAsfootprintGraphicItems ) ?
+                                    static_cast< DRAWSEGMENT* >( new EDGE_MODULE( NULL ) ) :
+                                    new DRAWSEGMENT;
+            segm->SetLayer( ToLAYER_ID( m_brdLayer ) );
+            segm->SetStart( startpoint );
+            segm->SetEnd( endpoint );
+            segm->SetWidth( aWidth );
+            m_newItemsList.push_back( segm );
+            startpoint = endpoint;
+        }
+    }
+#else   // Use bezier curves, supported by pcbnew, to approximate the spline
+	tinyspline::BSpline dxfspline( m_curr_entity.m_SplineControlPointList.size(),
+                                   /* coord dim */ 2, m_curr_entity.m_SplineDegree );
+    std::vector<double> ctrlp;
+
+    for( unsigned ii = 0; ii < imax; ++ii )
+    {
+        ctrlp.push_back( m_curr_entity.m_SplineControlPointList[ii].m_x );
+        ctrlp.push_back( m_curr_entity.m_SplineControlPointList[ii].m_y );
+    }
+
+	dxfspline.setCtrlp( ctrlp );
+	dxfspline.setKnots( m_curr_entity.m_SplineKnotsList );
+	tinyspline::BSpline beziers( dxfspline.toBeziers() );
+
+    std::vector<double> coords = beziers.ctrlp();
+
+    // Each Bezier curve uses 4 vertices (a start point, 2 control points and a end point).
+    // So we can have more than one Bezier curve ( there are one curve each four vertices)
+    for( unsigned ii = 0; ii < coords.size(); ii += 8 )
+    {
+        DRAWSEGMENT* segm = ( m_importAsfootprintGraphicItems ) ?
+                                static_cast< DRAWSEGMENT* >( new EDGE_MODULE( NULL ) ) :
+                                new DRAWSEGMENT;
+        segm->SetLayer( ToLAYER_ID( m_brdLayer ) );
+        segm->SetShape( S_CURVE );
+        segm->SetStart( wxPoint( mapX( coords[ii] ), mapY( coords[ii+1] ) ) );
+        segm->SetBezControl1( wxPoint( mapX( coords[ii+2] ), mapY( coords[ii+3] ) ) );
+        segm->SetBezControl2( wxPoint( mapX( coords[ii+4] ), mapY( coords[ii+5] ) ) );
+        segm->SetEnd( wxPoint( mapX( coords[ii+6] ), mapY( coords[ii+7] ) ) );
+        segm->SetWidth( aWidth );
+        segm->RebuildBezierToSegmentsPointsList( aWidth );
+        m_newItemsList.push_back( segm );
+    }
+#endif
+}
+
diff --git a/pcbnew/import_dxf/dxf2brd_items.h b/pcbnew/import_dxf/dxf2brd_items.h
index bee2cf5677..1874bb26ec 100644
--- a/pcbnew/import_dxf/dxf2brd_items.h
+++ b/pcbnew/import_dxf/dxf2brd_items.h
@@ -1,32 +1,33 @@
 /****************************************************************************
-**
-** This file comes from the LibreCAD project, a 2D CAD program
-**
-** Copyright (C) 2011 Rallaz, rallazz@gmail.com
-** Copyright (C) 2010 R. van Twisk (librecad@rvt.dds.nl)
-**
-**
-** This file may be distributed and/or modified 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, write to the Free Software
-** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-**
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
+ * Copyright (C) 1992-2018 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 FILTERDXFRW_H
-#define FILTERDXFRW_H
+#ifndef DXF2BRD_ITEMS_H
+#define DXF2BRD_ITEMS_H
 
-#include "drw_interface.h"
+#include "dl_dxf.h"
+#include "dl_creationadapter.h"
 #include "wx/wx.h"
 #include <list>
 
@@ -34,12 +35,81 @@ class BOARD;
 class BOARD_ITEM;
 
 /**
- * This format filter class can import and export DXF files.
- * It depends on the dxflib library.
- *
- * @author Rallaz
+ * A helper class to store a spline control point (in X,Y plane only)
  */
-class DXF2BRD_CONVERTER : public DRW_Interface
+struct SPLINE_CTRL_POINT
+{
+    double m_x;
+    double m_y;
+    double m_weight;
+
+    SPLINE_CTRL_POINT( double a_x, double a_y, double a_weight )
+                    : m_x( a_x ), m_y( a_y ), m_weight( a_weight )
+    {}
+};
+
+/**
+ * A helper class to parse a DXF entity (polyline and spline)
+ */
+class DXF2BRD_ENTITY_DATA
+{
+public:
+    int m_EntityType;           // the DXF type of entity
+    int m_EntityParseStatus;    // Inside a entity: status od parsing:
+                                // 0 = no entity
+                                // 1 = first item of entity
+                                // 2 = entity in progress
+    int m_EntityFlag;           // a info flag to parse entities
+
+    wxRealPoint m_LastCoordinate;   // the last vertex coordinate read (unit = mm)
+    wxRealPoint m_PolylineStart;    // The first point of the polyline entity, when reading a polyline (unit = mm)
+    double m_BulgeVertex;       // the last vertex bulge value read
+
+    // for spline parsing: parameters
+    unsigned int m_SplineDegree;
+    unsigned int m_SplineKnotsCount;
+    unsigned int m_SplineControlCount;
+    unsigned int m_SplineFitCount;
+    double m_SplineTangentStartX;   // tangeant dir X for the start point
+    double m_SplineTangentStartY;   // tangeant dir Y for the start point
+    double m_SplineTangentEndX;     // tangeant dir X for the end point
+    double m_SplineTangentEndY;     // tangeant dir Y for the end point
+
+    // for spline parsing: buffers to store control points, fit points and knot
+    std::vector<double> m_SplineKnotsList;          // knots list, code 40
+    // control points list coordinates, code 10, 20 & 30 (only X and Y cood and Weight)
+    std::vector<SPLINE_CTRL_POINT> m_SplineControlPointList;
+    // fit points list, code 11, 21 & 31 (only X and Y cood)
+    std::vector<wxRealPoint> m_SplineFitPointList;
+
+    DXF2BRD_ENTITY_DATA() { Clear(); };
+
+    // Reset the entity parameters
+    void Clear()
+    {
+        m_EntityType = DL_UNKNOWN;
+        m_EntityParseStatus = 0;
+        m_EntityFlag = 0;
+        m_SplineDegree = 1;
+        m_SplineKnotsCount = 0;
+        m_SplineControlCount = 0;
+        m_SplineFitCount = 0;
+        m_SplineTangentStartX = 0.0;
+        m_SplineTangentStartY = 0.0;
+        m_SplineTangentEndX = 0.0;
+        m_SplineTangentEndY = 0.0;
+        m_SplineKnotsList.clear();
+        m_SplineControlPointList.clear();
+        m_SplineFitPointList.clear();
+    }
+};
+
+
+/**
+ * This class import DXF ASCII files and convert basic entities to board entities.
+ * It depends on the dxflib library.
+ */
+class DXF2BRD_CONVERTER : public DL_CreationAdapter
 {
 private:
     std::list<BOARD_ITEM*> m_newItemsList;  // The list of new items added to the board
@@ -52,6 +122,10 @@ private:
     std::string m_codePage;     // The code page, not used here
     bool m_importAsfootprintGraphicItems;  // Use module items instead of board items when true.
                                 // true when the items are imported in the footprint editor
+    std::string m_messages;     // messages generated during dxf file parsing.
+                                // Each message ends by '\n'
+    DXF2BRD_ENTITY_DATA m_curr_entity;  // the current entity parameters when parsing a DXF entity
+
 
 public:
     DXF2BRD_CONVERTER();
@@ -115,7 +189,15 @@ public:
         return m_newItemsList;
     }
 
+    /**
+     * @return the list of messages in one string. Each message ends by '\n'
+     */
+    std::string& GetMessages() { return m_messages; }
+
 private:
+    // report message to keep trace of not supported dxf entities:
+    void reportMsg( const char* aMessage );
+
     // coordinate conversions from dxf to internal units
     int mapX( double aDxfCoordX );
     int mapY( double aDxfCoordY );
@@ -124,59 +206,88 @@ private:
     // or m_defaultThickness
     int mapWidth( double aDxfWidth );
 
-    // Functions to aid in the creation of a LWPolyline
+    // Functions to aid in the creation of a Polyline
     void insertLine( const wxRealPoint& aSegStart, const wxRealPoint& aSegEnd, int aWidth );
     void insertArc( const wxRealPoint& aSegStart, const wxRealPoint& aSegEnd,
                     double aBulge, int aWidth );
+    // Add a dxf spline (stored in m_curr_entity) to the board, after conversion to segments
+    void insertSpline( int aWidth );
 
-    // Methods from DRW_CreationInterface:
-    // They are "call back" fonctions, called when the corresponding object
-    // is read in dxf file
-    // Depending of the application, they can do something or not
-    virtual void addHeader( const DRW_Header* aData ) override;
-    virtual void addLType( const DRW_LType& aData ) override {}
-    virtual void addLayer( const DRW_Layer& aData ) override;
-    virtual void addDimStyle( const DRW_Dimstyle& aData ) override {}
-    virtual void addBlock( const DRW_Block& aData ) override {}
-    virtual void endBlock() override {}
-    virtual void addPoint( const DRW_Point& aData ) override {}
-    virtual void addLine( const DRW_Line& aData) override;
-    virtual void addRay( const DRW_Ray& aData ) override {}
-    virtual void addXline( const DRW_Xline& aData ) override {}
-    virtual void addCircle( const DRW_Circle& aData ) override;
-    virtual void addArc( const DRW_Arc& aData ) override;
-    virtual void addEllipse( const DRW_Ellipse& aData ) override {}
-    virtual void addLWPolyline( const DRW_LWPolyline& aData ) override;
-    virtual void addText( const DRW_Text& aData ) override;
-    virtual void addPolyline( const DRW_Polyline& aData ) override;
-    virtual void addSpline( const DRW_Spline* aData ) override {}
-    virtual void addKnot( const DRW_Entity&) override {}
-    virtual void addInsert( const DRW_Insert& aData ) override {}
-    virtual void addTrace( const DRW_Trace& aData ) override {}
-    virtual void addSolid( const DRW_Solid& aData ) override {}
-    virtual void addMText( const DRW_MText& aData) override;
-    virtual void addDimAlign( const DRW_DimAligned* aData ) override {}
-    virtual void addDimLinear( const DRW_DimLinear* aData ) override {}
-    virtual void addDimRadial( const DRW_DimRadial* aData ) override {}
-    virtual void addDimDiametric( const DRW_DimDiametric* aData ) override {}
-    virtual void addDimAngular( const DRW_DimAngular* aData ) override {}
-    virtual void addDimAngular3P( const DRW_DimAngular3p* aData ) override {}
-    virtual void addDimOrdinate( const DRW_DimOrdinate* aData ) override {}
-    virtual void addLeader( const DRW_Leader* aData ) override {}
-    virtual void addHatch( const DRW_Hatch* aData ) override {}
-    virtual void addImage( const DRW_Image* aData ) override {}
-    virtual void linkImage( const DRW_ImageDef* aData ) override {}
+    // Methods from DL_CreationAdapter:
+    // They are something like"call back" fonctions,
+    // called when the corresponding object is read in dxf file
 
-    virtual void add3dFace( const DRW_3Dface& aData ) override {}
-    virtual void addComment( const char*) override {}
+    /**
+     * Called for every string variable in the DXF file (e.g. "$ACADVER").
+     */
+    virtual void setVariableString( const std::string& key, const std::string& value,
+            int code ) override;
 
-    virtual void addVport( const DRW_Vport& aData ) override {}
+    /**
+     * Called for every int variable in the DXF file (e.g. "$ACADMAINTVER").
+     */
+    virtual void setVariableInt( const std::string& key, int value, int code ) override;
 
-    virtual void addTextStyle( const DRW_Textstyle& aData ) override;
+    /**
+     * Called for every double variable in the DXF file (e.g. "$DIMEXO").
+     */
+    virtual void setVariableDouble( const std::string& key, double value, int code ) override {}
 
-    virtual void addViewport( const DRW_Viewport& aData ) override {}
+    virtual void addLayer( const DL_LayerData& aData ) override;
+    virtual void addLine( const DL_LineData& aData) override;
+    virtual void addCircle( const DL_CircleData& aData ) override;
+    virtual void addArc( const DL_ArcData& aData ) override;
+    //virtual void addLWPolyline( const DRW_LWPolyline& aData ) override;
+    virtual void addText( const DL_TextData& aData ) override;
+    virtual void addPolyline( const DL_PolylineData& aData ) override;
 
-    virtual void setBlock( const int aHandle ) override {}
+    /** Called for every polyline vertex */
+    virtual void addVertex( const DL_VertexData& aData ) override;
+    virtual void addMText( const DL_MTextData& aData) override;
+    virtual void addTextStyle( const DL_StyleData& aData ) override;
+
+    virtual void endEntity() override;
+
+    /** Called for every spline */
+    virtual void addSpline( const DL_SplineData& aData ) override;
+
+    /** Called for every spline control point */
+    virtual void addControlPoint( const DL_ControlPointData& aData ) override;
+
+    /** Called for every spline fit point */
+    virtual void addFitPoint( const DL_FitPointData& aData ) override;
+
+    /** Called for every spline knot value */
+    virtual void addKnot( const DL_KnotData& aData ) override;
+
+    // Not yet handled DXF entities:
+    virtual void addDimAlign( const DL_DimensionData&,
+            const DL_DimAlignedData& ) override { reportMsg( "DL_Dimension not managed" ); }
+    virtual void addDimLinear( const DL_DimensionData&,
+            const DL_DimLinearData& ) override { reportMsg( "DL_Dimension not managed" ); }
+    virtual void addDimRadial( const DL_DimensionData&,
+            const DL_DimRadialData& ) override { reportMsg( "DL_Dimension not managed" ); }
+    virtual void addDimDiametric( const DL_DimensionData&,
+            const DL_DimDiametricData& ) override { reportMsg( "DL_Dimension not managed" ); }
+    virtual void addDimAngular( const DL_DimensionData&,
+            const DL_DimAngularData& ) override { reportMsg( "DL_Dimension not managed" ); }
+    virtual void addDimAngular3P( const DL_DimensionData&,
+            const DL_DimAngular3PData& ) override { reportMsg( "DL_Dimension not managed" ); }
+    virtual void addDimOrdinate( const DL_DimensionData&,
+            const DL_DimOrdinateData& ) override { reportMsg( "DL_Dimension not managed" ); }
+    virtual void addLeader( const DL_LeaderData& ) override { reportMsg( "DL_Leader not managed" ); }
+    virtual void addLeaderVertex( const DL_LeaderVertexData& ) override { reportMsg( "DL_LeaderVertex not managed" ); }
+
+    virtual void addHatch( const DL_HatchData& ) override { reportMsg( "DL_Hatch not managed" ); }
+
+    virtual void addTrace( const DL_TraceData& ) override { reportMsg( "DL_Trace not managed" ); }
+    virtual void add3dFace( const DL_3dFaceData& ) override { reportMsg( "DL_3dFace not managed" ); }
+    virtual void addSolid( const DL_SolidData& ) override { reportMsg( "DL_Solid not managed" ); }
+
+    virtual void addImage( const DL_ImageData& ) override { reportMsg( "DL_ImageDa not managed" ); }
+    virtual void linkImage( const DL_ImageDefData& ) override { reportMsg( "DL_ImageDef not managed" ); }
+    virtual void addHatchLoop( const DL_HatchLoopData& ) override { reportMsg( "DL_HatchLoop not managed" ); }
+    virtual void addHatchEdge( const DL_HatchEdgeData& ) override { reportMsg( "DL_HatchEdge not managed" ); }
 
     /**
      * Converts a native unicode string into a DXF encoded string.
@@ -193,23 +304,8 @@ private:
      */
     static wxString toNativeString( const wxString& aData );
 
-    // These functions are not used in Kicad.
-    // But because they are virtual pure in DRW_Interface, they should be defined
-    virtual void writeTextstyles() override {}
-    virtual void writeVports() override {}
-    virtual void writeHeader( DRW_Header& aData ) override {}
-    virtual void writeEntities() override {}
-    virtual void writeLTypes() override {}
-    virtual void writeLayers() override {}
-    virtual void writeBlockRecords() override {}
-    virtual void writeBlocks() override {}
-    virtual void writeDimstyles() override {}
-
     void writeLine();
     void writeMtext();
-
-    virtual void addAppId( const DRW_AppId& data ) override {}
-    virtual void writeAppId() override {}
 };
 
-#endif  // FILTERDXFRW_H
+#endif  // DXF2BRD_ITEMS_H
diff --git a/pcbnew/kicad_plugin.cpp b/pcbnew/kicad_plugin.cpp
index c5855dbcca..a6bad50ac9 100644
--- a/pcbnew/kicad_plugin.cpp
+++ b/pcbnew/kicad_plugin.cpp
@@ -984,8 +984,8 @@ void PCB_IO::format( EDGE_MODULE* aModuleDrawing, int aNestLevel ) const
     case S_CURVE:   // Bezier curve
         m_out->Print( aNestLevel, "(fp_curve (pts (xy %s) (xy %s) (xy %s) (xy %s))",
                       FMT_IU( aModuleDrawing->GetStart0() ).c_str(),
-                      FMT_IU( aModuleDrawing->GetBezControl1() ).c_str(),
-                      FMT_IU( aModuleDrawing->GetBezControl2() ).c_str(),
+                      FMT_IU( aModuleDrawing->GetBezier0_C1() ).c_str(),
+                      FMT_IU( aModuleDrawing->GetBezier0_C2() ).c_str(),
                       FMT_IU( aModuleDrawing->GetEnd0() ).c_str() );
         break;
 
diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp
index 3898d2614a..a4c0f2d9d1 100644
--- a/pcbnew/pcb_painter.cpp
+++ b/pcbnew/pcb_painter.cpp
@@ -961,7 +961,7 @@ void PCB_PAINTER::draw( const DRAWSEGMENT* aSegment, int aLayer )
         std::copy( points.begin(), points.end(), std::back_inserter( pointsList ) );
         pointsList.push_back( points[0] );
 
-        m_gal->SetLineWidth( aSegment->GetWidth() );
+        m_gal->SetLineWidth( thickness );
         m_gal->SetIsFill( true );
         m_gal->SetIsStroke( true );
         m_gal->DrawPolygon( pointsList );
@@ -971,6 +971,9 @@ void PCB_PAINTER::draw( const DRAWSEGMENT* aSegment, int aLayer )
     }
 
     case S_CURVE:
+        m_gal->SetIsFill( false );
+        m_gal->SetIsStroke( true );
+        m_gal->SetLineWidth( thickness );
         m_gal->DrawCurve( VECTOR2D( aSegment->GetStart() ),
                           VECTOR2D( aSegment->GetBezControl1() ),
                           VECTOR2D( aSegment->GetBezControl2() ),
diff --git a/pcbnew/pcb_parser.cpp b/pcbnew/pcb_parser.cpp
index 6bfcf352b6..72b0a4dd14 100644
--- a/pcbnew/pcb_parser.cpp
+++ b/pcbnew/pcb_parser.cpp
@@ -2209,8 +2209,8 @@ EDGE_MODULE* PCB_PARSER::parseEDGE_MODULE()
             Expecting( T_pts );
 
         segment->SetStart0( parseXY() );
-        segment->SetBezControl1( parseXY() );
-        segment->SetBezControl2( parseXY() );
+        segment->SetBezier0_C1( parseXY() );
+        segment->SetBezier0_C2( parseXY() );
         segment->SetEnd0( parseXY() );
         NeedRIGHT();
         break;
diff --git a/pcbnew/tools/drawing_tool.cpp b/pcbnew/tools/drawing_tool.cpp
index ef13d6175e..89d67128f4 100644
--- a/pcbnew/tools/drawing_tool.cpp
+++ b/pcbnew/tools/drawing_tool.cpp
@@ -2,7 +2,7 @@
  * This program source code file is part of KiCad, a free EDA CAD application.
  *
  * Copyright (C) 2014-2017 CERN
- * Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors.
+ * Copyright (C) 2018 KiCad Developers, see AUTHORS.txt for contributors.
  * @author Maciej Suminski <maciej.suminski@cern.ch>
  *
  * This program is free software; you can redistribute it and/or
@@ -762,6 +762,15 @@ int DRAWING_TOOL::PlaceDXF( const TOOL_EVENT& aEvent )
 
     SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::DXF );
 
+    // Now move the new items to the current cursor position:
+    cursorPos = m_controls->GetCursorPosition();
+    delta = cursorPos - firstItem->GetPosition();
+
+    for( auto item : preview )
+        static_cast<BOARD_ITEM*>( item )->Move( wxPoint( delta.x, delta.y ) );
+
+    m_view->Update( &preview );
+
     Activate();
 
     // Main loop: keep receiving events
diff --git a/utils/idftools/CMakeLists.txt b/utils/idftools/CMakeLists.txt
index 8315a9be0d..8eefaca0f9 100644
--- a/utils/idftools/CMakeLists.txt
+++ b/utils/idftools/CMakeLists.txt
@@ -26,10 +26,10 @@ add_library( idf3 STATIC ${IDF3_FILES} )
 
 add_executable( idfcyl idf_cylinder.cpp )
 add_executable( idfrect idf_rect.cpp )
-add_executable( dxf2idf dxf2idfmain.cpp dxf2idf.cpp )
+#add_executable( dxf2idf dxf2idfmain.cpp dxf2idf.cpp )
 add_executable( idf2vrml idf2vrml.cpp )
 
-target_link_libraries( dxf2idf lib_dxf idf3 ${wxWidgets_LIBRARIES} )
+#target_link_libraries( dxf2idf lib_dxf idf3 ${wxWidgets_LIBRARIES} )
 
 target_link_libraries( idf2vrml idf3 common ${OPENGL_LIBRARIES} ${wxWidgets_LIBRARIES} )
 
@@ -39,7 +39,8 @@ if( APPLE )
         RUNTIME_OUTPUT_DIRECTORY ${OSX_BUNDLE_BUILD_BIN_DIR}
         )
 else()
-    install( TARGETS idfcyl idfrect dxf2idf idf2vrml
+    install( TARGETS idfcyl idfrect idf2vrml
+        #dxf2idf
         DESTINATION ${KICAD_BIN}
         COMPONENT binary )
 endif()