diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt
index dae7441c0f..74fe696323 100644
--- a/common/CMakeLists.txt
+++ b/common/CMakeLists.txt
@@ -38,6 +38,7 @@ add_custom_target(
 
 set( GAL_SRCS
     # Common part
+    basic_gal.cpp
     draw_panel_gal.cpp
     painter.cpp
     newstroke_font.cpp
diff --git a/common/basic_gal.cpp b/common/basic_gal.cpp
new file mode 100644
index 0000000000..3e538125b4
--- /dev/null
+++ b/common/basic_gal.cpp
@@ -0,0 +1,131 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
+ * Copyright (C) 1992-2016 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
+ */
+
+/**
+ * @brief Implement a very basic GAL used to draw, plot and convert texts in segments
+ * for DRC funstions, using the common GAL functions.
+ * Draw functions use wxDC.
+ * Plot functions use a PLOTTER
+ * Convert texts in segments use a callback function created by the caller
+ * @file basic_gal.cpp
+ */
+
+#include <gr_basic.h>
+#include <plot_common.h>
+#include <trigo.h>
+
+#include <basic_gal.h>
+
+using namespace KIGFX;
+
+BASIC_GAL basic_gal;
+
+const VECTOR2D BASIC_GAL::transform( const VECTOR2D& aPoint ) const
+{
+    VECTOR2D point = aPoint + m_transform.m_moveOffset - m_transform.m_rotCenter;
+    point = point.Rotate( m_transform.m_rotAngle ) + m_transform.m_rotCenter;
+    return point;
+}
+
+void BASIC_GAL::DrawPolyline( const std::deque<VECTOR2D>& aPointList )
+{
+    if( aPointList.empty() )
+        return;
+
+    std::deque<VECTOR2D>::const_iterator it = aPointList.begin();
+    std::vector <wxPoint> polyline_corners;
+
+    for( ; it != aPointList.end(); ++it )
+    {
+        VECTOR2D corner = transform(*it);
+        polyline_corners.push_back( wxPoint( corner.x, corner.y ) );
+    }
+
+    if( m_DC )
+    {
+        if( isFillEnabled )
+        {
+            GRPoly( m_isClipped ? &m_clipBox : NULL, m_DC, polyline_corners.size(),
+                    &polyline_corners[0], 0, GetLineWidth(), m_Color, m_Color );
+        }
+        else
+        {
+            for( unsigned ii = 1; ii < polyline_corners.size(); ++ii )
+            {
+                GRCSegm( m_isClipped ? &m_clipBox : NULL, m_DC, polyline_corners[ii-1],
+                         polyline_corners[ii], GetLineWidth(), m_Color );
+            }
+        }
+    }
+    else if( m_plotter )
+    {
+        m_plotter->MoveTo( polyline_corners[0] );
+
+        for( unsigned ii = 1; ii < polyline_corners.size(); ii++ )
+        {
+            m_plotter->LineTo( polyline_corners[ii] );
+        }
+
+        m_plotter->PenFinish();
+    }
+    else if( m_callback )
+    {
+        for( unsigned ii = 1; ii < polyline_corners.size(); ii++ )
+        {
+            m_callback( polyline_corners[ii-1].x, polyline_corners[ii-1].y,
+                        polyline_corners[ii].x, polyline_corners[ii].y );
+        }
+    }
+}
+
+void BASIC_GAL::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
+{
+    VECTOR2D startVector = transform( aStartPoint );
+    VECTOR2D endVector = transform( aEndPoint );
+
+    if( m_DC )
+    {
+        if( isFillEnabled )
+        {
+            GRLine( m_isClipped ? &m_clipBox : NULL, m_DC, startVector.x, startVector.y,
+                    endVector.x, endVector.y, GetLineWidth(), m_Color );
+        }
+        else
+        {
+            GRCSegm( m_isClipped ? &m_clipBox : NULL, m_DC, startVector.x, startVector.y,
+                    endVector.x, endVector.y, GetLineWidth(), 0, m_Color );
+        }
+    }
+    else if( m_plotter )
+    {
+        m_plotter->MoveTo( wxPoint( startVector.x, startVector.y ) );
+        m_plotter->LineTo( wxPoint( endVector.x, endVector.y ) );
+        m_plotter->PenFinish();
+    }
+    else if( m_callback )
+    {
+            m_callback( startVector.x, startVector.y,
+                        endVector.x, endVector.y );
+    }
+}
diff --git a/common/drawtxt.cpp b/common/drawtxt.cpp
index 0114eb3724..080181cc61 100644
--- a/common/drawtxt.cpp
+++ b/common/drawtxt.cpp
@@ -39,230 +39,7 @@
 #include <class_drawpanel.h>
 #include <class_base_screen.h>
 
-#include <gal/stroke_font.h>
-
-#include <gal/graphics_abstraction_layer.h>
-#include <newstroke_font.h>
-
-#include <plot_common.h>
-
-using namespace KIGFX;
-
-/*
- * class BASIC_GAL is a minimal GAL implementation to draw, plot and convert
- * stroke texts to a set of segments for DRC tests.
- * Currently it allows to use GAL and STROKE_FONT methods in legacy draw mode
- * (using wxDC functions) in plot functions only for texts.
- *
- * The main purpose is to avoid duplicate code to do the same thing in GAL canvas
- * legacy canvas, plotter canvas and DRC.
- *
- * It will be certainly removed when a full GAL canvas using wxDC is implemented
- * (or at least restricted to plotter and DRC "canvas")
- */
-
-struct TRANSFORM_PRM    // A helper class to transfort coordinates in BASIC_GAL canvas
-{
-    VECTOR2D m_rotCenter;
-    VECTOR2D m_moveOffset;
-    double   m_rotAngle;
-};
-
-class BASIC_GAL: public GAL
-{
-public:
-    wxDC* m_DC;
-    EDA_COLOR_T m_Color;
-
-private:
-    TRANSFORM_PRM m_transform;
-    std::stack <TRANSFORM_PRM>  m_transformHistory;
-
-public:
-    BASIC_GAL()
-    {
-        m_DC = NULL;
-        m_Color = RED;
-        m_plotter = NULL;
-        m_callback = NULL;
-    }
-
-    void SetPlotter( PLOTTER* aPlotter )
-    {
-        m_plotter = aPlotter;
-    }
-
-    void SetCallback( void (* aCallback)( int x0, int y0, int xf, int yf ) )
-    {
-        m_callback = aCallback;
-    }
-
-    /// Set a clip box for drawings
-    /// If NULL, no clip will be made
-    void SetClipBox( EDA_RECT* aClipBox )
-    {
-        m_isClipped = aClipBox != NULL;
-
-        if( aClipBox )
-            m_clipBox = *aClipBox;
-    }
-
-    /// @brief Save the context.
-    virtual void Save()
-    {
-        m_transformHistory.push( m_transform );
-    }
-
-    virtual void Restore()
-    {
-        m_transform = m_transformHistory.top();
-        m_transformHistory.pop();
-    }
-
-
-    /**
-     * @brief Draw a polyline
-     * @param aPointList is a list of 2D-Vectors containing the polyline points.
-     */
-    virtual void DrawPolyline( const std::deque<VECTOR2D>& aPointList );
-
-    /** Start and end points are defined as 2D-Vectors.
-     * @param aStartPoint   is the start point of the line.
-     * @param aEndPoint     is the end point of the line.
-     */
-    virtual void DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint );
-
-    /**
-     * @brief Translate the context.
-     *
-     * @param aTranslation is the translation vector.
-     */
-    virtual void Translate( const VECTOR2D& aTranslation )
-    {
-        m_transform.m_moveOffset += aTranslation;
-    }
-
-    /**
-     * @brief Rotate the context.
-     *
-     * @param aAngle is the rotation angle in radians.
-     */
-    virtual void Rotate( double aAngle )
-    {
-        m_transform.m_rotAngle = aAngle * M_PI/1800;
-        m_transform.m_rotCenter = m_transform.m_moveOffset;
-    }
-
-private:
-    // Apply the roation/translation transform to aPoint
-    const VECTOR2D transform( const VECTOR2D& aPoint ) const;
-
-    // A clip box, to clip drawings in a wxDC (mandatory to avoid draw issues)
-    EDA_RECT  m_clipBox;        // The clip box
-    bool      m_isClipped;      // Allows/disallows clipping
-
-    // When calling the draw functions outside a wxDC, to get the basic drawings
-    // lines / polylines ..., a callback function (used in DRC) to store
-    // coordinates of each segment:
-    void (* m_callback)( int x0, int y0, int xf, int yf );
-
-    // When calling the draw functions for plot, the plotter acts as a wxDC
-    // to plot basic items
-    PLOTTER* m_plotter;
-};
-
-
-const VECTOR2D BASIC_GAL::transform( const VECTOR2D& aPoint ) const
-{
-    VECTOR2D point = aPoint + m_transform.m_moveOffset - m_transform.m_rotCenter;
-    point = point.Rotate( m_transform.m_rotAngle ) + m_transform.m_rotCenter;
-    return point;
-}
-
-void BASIC_GAL::DrawPolyline( const std::deque<VECTOR2D>& aPointList )
-{
-    if( aPointList.empty() )
-        return;
-
-    std::deque<VECTOR2D>::const_iterator it = aPointList.begin();
-    std::vector <wxPoint> polyline_corners;
-
-    for( ; it != aPointList.end(); ++it )
-    {
-        VECTOR2D corner = transform(*it);
-        polyline_corners.push_back( wxPoint( corner.x, corner.y ) );
-    }
-
-    if( m_DC )
-    {
-        if( isFillEnabled )
-        {
-            GRPoly( m_isClipped ? &m_clipBox : NULL, m_DC, polyline_corners.size(),
-                    &polyline_corners[0], 0, GetLineWidth(), m_Color, m_Color );
-        }
-        else
-        {
-            for( unsigned ii = 1; ii < polyline_corners.size(); ++ii )
-            {
-                GRCSegm( m_isClipped ? &m_clipBox : NULL, m_DC, polyline_corners[ii-1],
-                         polyline_corners[ii], GetLineWidth(), m_Color );
-            }
-        }
-    }
-    else if( m_plotter )
-    {
-        m_plotter->MoveTo( polyline_corners[0] );
-
-        for( unsigned ii = 1; ii < polyline_corners.size(); ii++ )
-        {
-            m_plotter->LineTo( polyline_corners[ii] );
-        }
-
-        m_plotter->PenFinish();
-    }
-    else if( m_callback )
-    {
-        for( unsigned ii = 1; ii < polyline_corners.size(); ii++ )
-        {
-            m_callback( polyline_corners[ii-1].x, polyline_corners[ii-1].y,
-                        polyline_corners[ii].x, polyline_corners[ii].y );
-        }
-    }
-}
-
-void BASIC_GAL::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
-{
-    VECTOR2D startVector = transform( aStartPoint );
-    VECTOR2D endVector = transform( aEndPoint );
-
-    if( m_DC )
-    {
-        if( isFillEnabled )
-        {
-            GRLine( m_isClipped ? &m_clipBox : NULL, m_DC, startVector.x, startVector.y,
-                    endVector.x, endVector.y, GetLineWidth(), m_Color );
-        }
-        else
-        {
-            GRCSegm( m_isClipped ? &m_clipBox : NULL, m_DC, startVector.x, startVector.y,
-                    endVector.x, endVector.y, GetLineWidth(), 0, m_Color );
-        }
-    }
-    else if( m_plotter )
-    {
-        m_plotter->MoveTo( wxPoint( startVector.x, startVector.y ) );
-        m_plotter->LineTo( wxPoint( endVector.x, endVector.y ) );
-        m_plotter->PenFinish();
-    }
-    else if( m_callback )
-    {
-            m_callback( startVector.x, startVector.y,
-                        endVector.x, endVector.y );
-    }
-}
-
-
-BASIC_GAL basic_gal;
+#include <basic_gal.h>
 
 /**
  * Function GetPensizeForBold
@@ -469,45 +246,10 @@ void PLOTTER::Text( const wxPoint&              aPos,
     if( aColor >= 0 )
         SetColor( aColor );
 
-    if( aMultilineAllowed )
-    {
-        // EDA_TEXT needs for calculations of the position of every
-        // line according to orientation and justifications
-        wxArrayString strings;
-        EDA_TEXT* multilineText = new EDA_TEXT( aText );
-        multilineText->SetSize( aSize );
-        multilineText->SetTextPosition( aPos );
-        multilineText->SetOrientation( aOrient );
-        multilineText->SetHorizJustify( aH_justify );
-        multilineText->SetVertJustify( aV_justify );
-        multilineText->SetThickness( aWidth );
-        multilineText->SetMultilineAllowed( aMultilineAllowed );
-
-        std::vector<wxPoint> positions;
-        wxStringSplit( aText, strings, '\n' );
-        positions.reserve( strings.Count() );
-
-        multilineText->GetPositionsOfLinesOfMultilineText(
-                positions, strings.Count() );
-
-        for( unsigned ii = 0; ii < strings.Count(); ii++ )
-        {
-            wxString& txt = strings.Item( ii );
-            DrawGraphicText( NULL, NULL, positions[ii], aColor, txt,
-                             aOrient, aSize,
-                             aH_justify, aV_justify,
-                             textPensize, aItalic, aBold, NULL, this );
-        }
-
-        delete multilineText;
-    }
-    else
-    {
-        DrawGraphicText( NULL, NULL, aPos, aColor, aText,
-                         aOrient, aSize,
-                         aH_justify, aV_justify,
-                         textPensize, aItalic, aBold, NULL, this );
-    }
+    DrawGraphicText( NULL, NULL, aPos, aColor, aText,
+                     aOrient, aSize,
+                     aH_justify, aV_justify,
+                     textPensize, aItalic, aBold, NULL, this );
 
     if( aWidth != textPensize )
         SetCurrentLineWidth( aWidth );
diff --git a/common/eda_text.cpp b/common/eda_text.cpp
index 4d1bf0ce16..f6c3c52635 100644
--- a/common/eda_text.cpp
+++ b/common/eda_text.cpp
@@ -33,6 +33,8 @@
 #include <trigo.h>               // RotatePoint
 #include <class_drawpanel.h>     // EDA_DRAW_PANEL
 
+#include <basic_gal.h>
+
 // Conversion to application internal units defined at build time.
 #if defined( PCBNEW )
     #include <class_board_item.h>       // for FMT_IU
@@ -46,8 +48,6 @@
 #error "Cannot resolve units formatting due to no definition of EESCHEMA or PCBNEW."
 #endif
 
-#include <gal/stroke_font.h>
-
 #include <convert_to_biu.h>
 
 EDA_TEXT::EDA_TEXT( const wxString& text )
@@ -90,7 +90,13 @@ EDA_TEXT::~EDA_TEXT()
 
 int EDA_TEXT::LenSize( const wxString& aLine ) const
 {
-    return GraphicTextWidth( aLine, m_Size, m_Italic, m_Bold );
+    basic_gal.SetItalic( m_Italic );
+    basic_gal.SetBold( m_Bold );
+    basic_gal.SetGlyphSize( VECTOR2D( m_Size ) );
+
+    VECTOR2D tsize = basic_gal.GetTextLineSize( aLine );
+
+    return KiROUND( tsize.x );
 }
 
 
@@ -123,7 +129,6 @@ int EDA_TEXT::GetInterline( int aTextThickness ) const
 EDA_RECT EDA_TEXT::GetTextBox( int aLine, int aThickness, bool aInvertY ) const
 {
     EDA_RECT       rect;
-    wxPoint        pos;
     wxArrayString  strings;
     wxString       text = GetShownText();
     int            thickness = ( aThickness < 0 ) ? m_Thickness : aThickness;
@@ -157,30 +162,35 @@ EDA_RECT EDA_TEXT::GetTextBox( int aLine, int aThickness, bool aInvertY ) const
     }
 
     // calculate the H and V size
-    int    dx = LenSize( text );
-    int    dy = GetInterline( thickness );
+    int dx = KiROUND( basic_gal.GetStrokeFont().ComputeStringBoundaryLimits(
+                            text, VECTOR2D( m_Size ), double( thickness ) ).x );
+    int dy = GetInterline( thickness );
 
-    // Creates bounding box (rectangle) for an horizontal text
+    // Creates bounding box (rectangle) for an horizontal
+    // and left and top justified text. the bounding box will be moved later
+    // according to the catual text options
     wxSize textsize = wxSize( dx, dy );
+    wxPoint pos = m_Pos;
 
     if( aInvertY )
-        rect.SetOrigin( m_Pos.x, -m_Pos.y );
-    else
-        rect.SetOrigin( m_Pos );
+        pos.x = -pos.y;
+
+    rect.SetOrigin( pos );
 
     // The bbox vertical size returned by GetInterline( aThickness )
     // includes letters like j and y and ] + interval between lines.
     // The interval below the last line is not usefull, and we can use its half value
     // as vertical margin above the text
     // the full interval is roughly m_Size.y * 0.4 - aThickness/2
-    rect.Move( wxPoint( 0, thickness/4 - KiROUND( m_Size.y * 0.2 ) ) );
+    rect.Move( wxPoint( 0, thickness/4 - KiROUND( m_Size.y * 0.22 ) ) );
 
     if( hasOverBar )
-    {
-        // A overbar adds an extra size to the text
-        double curr_height = m_Size.y * 1.15;   // Height from the base line text of chars like [ or {
+    {   // A overbar adds an extra size to the text
+        // Height from the base line text of chars like [ or {
+        double curr_height = m_Size.y * 1.15;
         int extra_height = KiROUND(
-            KIGFX::STROKE_FONT::ComputeOverbarVerticalPosition( m_Size.y, thickness ) - curr_height );
+            basic_gal.GetStrokeFont().ComputeOverbarVerticalPosition( m_Size.y, thickness ) - curr_height );
+        extra_height += thickness/2;
         textsize.y += extra_height;
         rect.Move( wxPoint( 0, -extra_height ) );
     }
@@ -192,7 +202,8 @@ EDA_RECT EDA_TEXT::GetTextBox( int aLine, int aThickness, bool aInvertY ) const
         for( unsigned ii = 1; ii < strings.GetCount(); ii++ )
         {
             text = strings.Item( ii );
-            dx   = LenSize( text );
+            dx   = KiROUND( basic_gal.GetStrokeFont().ComputeStringBoundaryLimits(
+                            text, VECTOR2D( m_Size ), double( thickness ) ).x );
             textsize.x  = std::max( textsize.x, dx );
             textsize.y += dy;
         }
diff --git a/common/gal/stroke_font.cpp b/common/gal/stroke_font.cpp
index d490ccb28c..6bb8360885 100644
--- a/common/gal/stroke_font.cpp
+++ b/common/gal/stroke_font.cpp
@@ -97,11 +97,20 @@ bool STROKE_FONT::LoadNewStrokeFont( const char* const aNewStrokeFont[], int aNe
             }
             else
             {
-                // Every coordinate description of the Hershey format has an offset,
+                // In stroke font, coordinates values are coded as <value> + 'R',
+                // <value> is an ASCII char.
+                // therefore every coordinate description of the Hershey format has an offset,
                 // it has to be subtracted
+                // Note:
+                //  * the stroke coordinates are stored in reduced form (-1.0 to +1.0),
+                //    and the actual size is stroke coordinate * glyph size
+                //  * a few shapes have a height slightly bigger than 1.0 ( like '{' '[' )
                 point.x = (double) ( coordinate[0] - 'R' ) * STROKE_FONT_SCALE - glyphStartX;
-				// -10 is here to keep GAL rendering consistent with the legacy gfx stuff
-                point.y = (double) ( coordinate[1] - 'R' - 10) * STROKE_FONT_SCALE;
+                #define FONT_OFFSET -10
+				// FONT_OFFSET is here for historical reasons, due to the way the stroke font
+                // was built. It allows shapes coordinates like W M ... to be >= 0
+                // Only shapes like j y have coordinates < 0
+                point.y = (double) ( coordinate[1] - 'R' + FONT_OFFSET ) * STROKE_FONT_SCALE;
                 pointList.push_back( point );
             }
 
@@ -371,7 +380,7 @@ void STROKE_FONT::drawSingleLineText( const UTF8& aText )
 }
 
 
-double STROKE_FONT::ComputeOverbarVerticalPosition( double aGlyphHeight, double aGlyphThickness )
+double STROKE_FONT::ComputeOverbarVerticalPosition( double aGlyphHeight, double aGlyphThickness ) const
 {
     // Static method.
     // Compute the Y position of the overbar. This is the distance between
@@ -389,8 +398,18 @@ double STROKE_FONT::computeOverbarVerticalPosition() const
 
 
 VECTOR2D STROKE_FONT::computeTextLineSize( const UTF8& aText ) const
+{
+    return ComputeStringBoundaryLimits( aText, m_glyphSize, m_gal->GetLineWidth() );
+}
+
+
+VECTOR2D STROKE_FONT::ComputeStringBoundaryLimits( const UTF8& aText, VECTOR2D aGlyphSize,
+                                        double aGlyphThickness,
+                                        double* aTopLimit, double* aBottomLimit ) const
 {
     VECTOR2D result = VECTOR2D( 0.0, m_glyphSize.y );
+    double ymax = 0.0;
+    double ymin = 0.0;
 
     for( UTF8::uni_iter it = aText.ubegin(), end = aText.uend(); it < end; ++it )
     {
@@ -411,12 +430,36 @@ VECTOR2D STROKE_FONT::computeTextLineSize( const UTF8& aText ) const
         if( dd >= (int) m_glyphBoundingBoxes.size() || dd < 0 )
             dd = '?' - ' ';
 
-        result.x += m_glyphSize.x * m_glyphBoundingBoxes[dd].GetEnd().x;
+        const BOX2D& box = m_glyphBoundingBoxes[dd];
+
+        result.x += box.GetEnd().x;
+
+        // Calculate Y min and Y max
+        if( aTopLimit )
+        {
+            ymax = std::max( ymax, box.GetY() );
+            ymax = std::max( ymax, box.GetEnd().y );
+        }
+
+        if( aBottomLimit )
+        {
+            ymin = std::min( ymin, box.GetY() );
+            ymin = std::min( ymin, box.GetEnd().y );
+        }
     }
 
+    result.x *= aGlyphSize.x;
+    result.x += aGlyphThickness;
+
     // For italic correction, take in account italic tilt
     if( m_italic )
         result.x += result.y * STROKE_FONT::ITALIC_TILT;
 
+    if( aTopLimit )
+        *aTopLimit = ymax * aGlyphSize.y;
+
+    if( aBottomLimit )
+        *aBottomLimit = ymin * aGlyphSize.y;
+
     return result;
 }
diff --git a/eeschema/sch_text.cpp b/eeschema/sch_text.cpp
index 4f8fd8444f..73d7840fdf 100644
--- a/eeschema/sch_text.cpp
+++ b/eeschema/sch_text.cpp
@@ -46,7 +46,8 @@
 
 extern void IncrementLabelMember( wxString& name, int aIncrement );
 
-#define DRAW_BBOX 0     // Only for tests: set to 1 to draw the bounding box of labels
+// Only for tests: set DRAW_BBOX to 1 to draw the bounding box of labels
+#define DRAW_BBOX 0
 
 /* Names of sheet label types. */
 const char* SheetLabelType[] =
diff --git a/include/basic_gal.h b/include/basic_gal.h
new file mode 100644
index 0000000000..f282cfff0b
--- /dev/null
+++ b/include/basic_gal.h
@@ -0,0 +1,162 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
+ * Copyright (C) 1992-2016 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 BASIC_GAL_H
+#define BASIC_GAL_H
+
+#include <plot_common.h>
+
+#include <gal/stroke_font.h>
+#include <gal/graphics_abstraction_layer.h>
+#include <newstroke_font.h>
+
+/*
+ * class BASIC_GAL is a minimal GAL implementation to draw, plot and convert
+ * stroke texts to a set of segments for DRC tests, and to calculate text sizes.
+ *
+ * Currently it allows to use GAL and STROKE_FONT methods in legacy draw mode
+ * (using wxDC functions) in plot functions only for texts.
+ * It is used also to calculate the text bounding boxes
+ *
+ * The main purpose is to avoid duplicate code to do the same thing in GAL canvas
+ * legacy canvas, plotter canvas and DRC.
+ *
+ * It will be certainly removed when a full GAL canvas using wxDC is implemented
+ * (or at least restricted to plotter and DRC "canvas")
+ */
+
+struct TRANSFORM_PRM    // A helper class to transform coordinates in BASIC_GAL canvas
+{
+    VECTOR2D m_rotCenter;
+    VECTOR2D m_moveOffset;
+    double   m_rotAngle;
+};
+
+class BASIC_GAL: public KIGFX::GAL
+{
+public:
+    wxDC* m_DC;
+    EDA_COLOR_T m_Color;
+
+private:
+    TRANSFORM_PRM m_transform;
+    std::stack <TRANSFORM_PRM>  m_transformHistory;
+
+public:
+    BASIC_GAL()
+    {
+        m_DC = NULL;
+        m_Color = RED;
+        m_plotter = NULL;
+        m_callback = NULL;
+    }
+
+    void SetPlotter( PLOTTER* aPlotter )
+    {
+        m_plotter = aPlotter;
+    }
+
+    void SetCallback( void (* aCallback)( int x0, int y0, int xf, int yf ) )
+    {
+        m_callback = aCallback;
+    }
+
+    /// Set a clip box for drawings
+    /// If NULL, no clip will be made
+    void SetClipBox( EDA_RECT* aClipBox )
+    {
+        m_isClipped = aClipBox != NULL;
+
+        if( aClipBox )
+            m_clipBox = *aClipBox;
+    }
+
+    /// @brief Save the context.
+    virtual void Save()
+    {
+        m_transformHistory.push( m_transform );
+    }
+
+    virtual void Restore()
+    {
+        m_transform = m_transformHistory.top();
+        m_transformHistory.pop();
+    }
+
+
+    /**
+     * @brief Draw a polyline
+     * @param aPointList is a list of 2D-Vectors containing the polyline points.
+     */
+    virtual void DrawPolyline( const std::deque<VECTOR2D>& aPointList );
+
+    /** Start and end points are defined as 2D-Vectors.
+     * @param aStartPoint   is the start point of the line.
+     * @param aEndPoint     is the end point of the line.
+     */
+    virtual void DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint );
+
+    /**
+     * @brief Translate the context.
+     *
+     * @param aTranslation is the translation vector.
+     */
+    virtual void Translate( const VECTOR2D& aTranslation )
+    {
+        m_transform.m_moveOffset += aTranslation;
+    }
+
+    /**
+     * @brief Rotate the context.
+     *
+     * @param aAngle is the rotation angle in radians.
+     */
+    virtual void Rotate( double aAngle )
+    {
+        m_transform.m_rotAngle = aAngle * M_PI/1800;
+        m_transform.m_rotCenter = m_transform.m_moveOffset;
+    }
+
+private:
+    // Apply the roation/translation transform to aPoint
+    const VECTOR2D transform( const VECTOR2D& aPoint ) const;
+
+    // A clip box, to clip drawings in a wxDC (mandatory to avoid draw issues)
+    EDA_RECT  m_clipBox;        // The clip box
+    bool      m_isClipped;      // Allows/disallows clipping
+
+    // When calling the draw functions outside a wxDC, to get the basic drawings
+    // lines / polylines ..., a callback function (used in DRC) to store
+    // coordinates of each segment:
+    void (* m_callback)( int x0, int y0, int xf, int yf );
+
+    // When calling the draw functions for plot, the plotter acts as a wxDC
+    // to plot basic items
+    PLOTTER* m_plotter;
+};
+
+
+extern BASIC_GAL basic_gal;
+
+#endif      // define BASIC_GAL_H
diff --git a/include/gal/graphics_abstraction_layer.h b/include/gal/graphics_abstraction_layer.h
index 40611f4006..0046bf4fcb 100644
--- a/include/gal/graphics_abstraction_layer.h
+++ b/include/gal/graphics_abstraction_layer.h
@@ -269,6 +269,12 @@ public:
     // ----
     // Text
     // ----
+
+    const STROKE_FONT& GetStrokeFont() const
+    {
+        return strokeFont;
+    }
+
     /**
      * @brief Draws a vector type text using preloaded Newstroke font.
      *
diff --git a/include/gal/stroke_font.h b/include/gal/stroke_font.h
index c4fbf96aa9..67319fcc1c 100644
--- a/include/gal/stroke_font.h
+++ b/include/gal/stroke_font.h
@@ -152,12 +152,32 @@ public:
         m_gal = aGal;
     }
 
+    /**
+     * Compute the boundary limits of aText (the bbox of all shapes).
+     * The overbar is not taken in account, by ~ are skipped.
+     * @return a VECTOR2D giving the h size of line, and the V glyph size
+     * and ( if aTopLimit or aBottomLimit not NULL ) the top and bottom
+     * limits of the text.
+     */
+    VECTOR2D ComputeStringBoundaryLimits( const UTF8& aText, VECTOR2D aGlyphSize,
+                                          double aGlyphThickness,
+                                          double* aTopLimit = NULL, double* aBottomLimit = NULL ) const;
+
+    /**
+     * @brief Compute the X and Y size of a given text. The text is expected to be
+     * a only one line text.
+     *
+     * @param aText is the text string (one line).
+     * @return the text size.
+     */
+    VECTOR2D ComputeTextLineSize( const UTF8& aText ) const;
+
     /**
      * Compute the vertical position of an overbar, sometimes used in texts.
      * This is the distance between the text base line and the overbar.
      * @return the relative position of the overbar axis.
      */
-    static double ComputeOverbarVerticalPosition( double aGlyphHeight, double aGlyphThickness );
+    double ComputeOverbarVerticalPosition( double aGlyphHeight, double aGlyphThickness ) const;
 
     /**
      * @brief Compute the X and Y size of a given text. The text is expected to be
@@ -168,14 +188,19 @@ public:
      */
     static double GetInterline( double aGlyphHeight, double aGlyphThickness );
 
+
+
 private:
-    GAL*                m_gal;                                    ///< Pointer to the GAL
-    GLYPH_LIST          m_glyphs;                                 ///< Glyph list
-    std::vector<BOX2D>  m_glyphBoundingBoxes;                     ///< Bounding boxes of the glyphs
-    VECTOR2D            m_glyphSize;                              ///< Size of the glyphs
-    EDA_TEXT_HJUSTIFY_T m_horizontalJustify;                      ///< Horizontal justification
-    EDA_TEXT_VJUSTIFY_T m_verticalJustify;                        ///< Vertical justification
-    bool                m_bold, m_italic, m_mirrored, m_overbar;  ///< Properties of text
+    GAL*                m_gal;                  ///< Pointer to the GAL
+    GLYPH_LIST          m_glyphs;               ///< Glyph list
+    std::vector<BOX2D>  m_glyphBoundingBoxes;   ///< Bounding boxes of the glyphs
+    VECTOR2D            m_glyphSize;            ///< Size of the glyphs
+    EDA_TEXT_HJUSTIFY_T m_horizontalJustify;    ///< Horizontal justification
+    EDA_TEXT_VJUSTIFY_T m_verticalJustify;      ///< Vertical justification
+    bool                m_bold;
+    bool                m_italic;
+    bool                m_mirrored;
+    bool                m_overbar;              ///< Properties of text
 
     /**
      * @brief Compute the X and Y size of a given text. The text is expected to be