← Back to team overview

kicad-developers team mailing list archive

[patch] GAL pixel alignment

 

Hi,

The 3 attached patches add pixel alignment while drawing strokes in GAL
(both Cairo and OpenGL), resulting in sharp and uniform width lines
regardless of the zoom level and antialiasing settings. Current GAL
canvas does not round geometry to integer pixel coordinates, resulting
in sometimes blurred or jagged lines. I encourage you to test them,
especially at the OpenGL version (as it relies on the Vertex Shader for
the rounding/alignment).

@Wayne do you think these can make to 5.1 (I guess it's too late) or
should we postpone them to V6?

Cheers,
Tom
>From dd29062174cfff5283ecd0861b4bcf4df5e83ec6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tomasz=20W=C5=82ostowski?= <tomasz.wlostowski@xxxxxxx>
Date: Mon, 21 Jan 2019 19:42:06 +0100
Subject: [PATCH 1/3] gal: pixel alignment for Cairo.

---
 common/gal/cairo/cairo_compositor.cpp     |   7 +-
 common/gal/cairo/cairo_gal.cpp            | 498 +++++++++++++++++++---
 common/gal/graphics_abstraction_layer.cpp | 185 --------
 eeschema/sch_draw_panel.h                 |   2 +-
 include/gal/cairo/cairo_gal.h             |  23 +
 include/gal/graphics_abstraction_layer.h  |   3 +-
 pcbnew/pcb_painter.cpp                    |   3 +-
 7 files changed, 458 insertions(+), 263 deletions(-)

diff --git a/common/gal/cairo/cairo_compositor.cpp b/common/gal/cairo/cairo_compositor.cpp
index 21714214d..cca06c368 100644
--- a/common/gal/cairo/cairo_compositor.cpp
+++ b/common/gal/cairo/cairo_compositor.cpp
@@ -35,7 +35,7 @@ using namespace KIGFX;
 
 CAIRO_COMPOSITOR::CAIRO_COMPOSITOR( cairo_t** aMainContext ) :
     m_current( 0 ), m_currentContext( aMainContext ), m_mainContext( *aMainContext ),
-    m_currentAntialiasingMode( CAIRO_ANTIALIAS_NONE )
+    m_currentAntialiasingMode( CAIRO_ANTIALIAS_DEFAULT )
 {
     // Do not have uninitialized members:
     cairo_matrix_init_identity( &m_matrix );
@@ -109,9 +109,8 @@ unsigned int CAIRO_COMPOSITOR::CreateBuffer()
 #endif /* __WXDEBUG__ */
 
     // Set default settings for the buffer
-    cairo_set_antialias( context, m_currentAntialiasingMode );
-    cairo_set_line_join( context, CAIRO_LINE_JOIN_ROUND );
-    cairo_set_line_cap( context, CAIRO_LINE_CAP_ROUND );
+    printf("setAntialias: %d\n", m_currentAntialiasingMode );
+    cairo_set_antialias( context,  m_currentAntialiasingMode );
 
     // Use the same transformation matrix as the main context
     cairo_get_matrix( m_mainContext, &m_matrix );
diff --git a/common/gal/cairo/cairo_gal.cpp b/common/gal/cairo/cairo_gal.cpp
index 1f5871c6e..3dc7d849d 100644
--- a/common/gal/cairo/cairo_gal.cpp
+++ b/common/gal/cairo/cairo_gal.cpp
@@ -88,26 +88,102 @@ void CAIRO_GAL_BASE::endDrawing()
     Flush();
 }
 
+void CAIRO_GAL_BASE::updateWorldScreenMatrix()
+{
+    cairo_matrix_multiply( &currentWorld2Screen, &currentXform, &cairoWorldScreenMatrix );
+}
+
+const VECTOR2D CAIRO_GAL_BASE::xform( double x, double y )
+{
+    VECTOR2D rv;
+    //printf("xform        %.5f %.5f %.5f  [%.5f %.5f]\n", cairoWorldScreenMatrix.xx, cairoWorldScreenMatrix.xy, cairoWorldScreenMatrix.x0, x, y );
+    //printf("             %.5f %.5f %.5f\n", cairoWorldScreenMatrix.yx, cairoWorldScreenMatrix.yy, cairoWorldScreenMatrix.y0 );
+
+    rv.x = currentWorld2Screen.xx * x + currentWorld2Screen.xy * y + currentWorld2Screen.x0;
+    rv.y = currentWorld2Screen.yx * x + currentWorld2Screen.yy * y + currentWorld2Screen.y0;
+    return rv;
+}
+
+const VECTOR2D CAIRO_GAL_BASE::xform( const VECTOR2D& aP )
+{
+    return xform(aP.x, aP.y);
+}
+
+const double CAIRO_GAL_BASE::xform( double x )
+{
+    double dx = currentWorld2Screen.xx * x;
+    double dy = currentWorld2Screen.yx * x;
+    return sqrt( dx * dx + dy * dy );
+}
+
+static double roundp( double x )
+{
+    return floor( x + 0.5 ) + 0.5;
+}
+
+const VECTOR2D CAIRO_GAL_BASE::roundp( const VECTOR2D& v )
+{
+    if ( lineWidthIsOdd )
+        return VECTOR2D( ::roundp( v.x ), ::roundp( v.y ) );
+    else
+        return VECTOR2D( floor( v.x + 0.5 ), floor( v.y + 0.5 ) );
+}
+
+
+//static const VECTOR2D floorp( const VECTOR2D& v )
+//{
+    //return VECTOR2D( floor( v.x ), floor( v.y) );
+//}
 
 void CAIRO_GAL_BASE::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
 {
-    cairo_move_to( currentContext, aStartPoint.x, aStartPoint.y );
-    cairo_line_to( currentContext, aEndPoint.x, aEndPoint.y );
+    syncLineWidth();
+
+    auto p0 = roundp( xform( aStartPoint ) );
+    auto p1 = roundp( xform( aEndPoint ) );
+
+    cairo_move_to( currentContext, p0.x, p0.y );
+    cairo_line_to( currentContext, p1.x, p1.y );
     flushPath();
     isElementAdded = true;
 }
 
 
+void CAIRO_GAL_BASE::syncLineWidth( bool aForceWidth, double aWidth )
+{
+    auto w =  floor( xform( aForceWidth ? aWidth : lineWidth ) + 0.5 );
+
+    if (w <= 1.0)
+    {
+        w = 1.0;
+        cairo_set_line_join( currentContext, CAIRO_LINE_JOIN_MITER );
+        cairo_set_line_cap( currentContext, CAIRO_LINE_CAP_BUTT );
+        cairo_set_line_width( currentContext, 1.0 );
+        lineWidthIsOdd = true;
+    }
+    else
+    {
+        cairo_set_line_join( currentContext, CAIRO_LINE_JOIN_ROUND );
+        cairo_set_line_cap( currentContext, CAIRO_LINE_CAP_ROUND );
+        cairo_set_line_width( currentContext, w );
+        lineWidthIsOdd = ((int)w % 2) == 1;
+    }
+
+    lineWidthInPixels = w;
+}
+
 void CAIRO_GAL_BASE::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint,
                              double aWidth )
 {
     if( isFillEnabled )
     {
-        // Filled tracks mode
-        SetLineWidth( aWidth );
+        syncLineWidth( true, aWidth );
+
+        auto p0 = roundp( xform( aStartPoint ) );
+        auto p1 = roundp( xform( aEndPoint ) );
 
-        cairo_move_to( currentContext, (double) aStartPoint.x, (double) aStartPoint.y );
-        cairo_line_to( currentContext, (double) aEndPoint.x, (double) aEndPoint.y );
+        cairo_move_to( currentContext, p0.x, p0.y );
+        cairo_line_to( currentContext, p1.x, p1.y );
         cairo_set_source_rgba( currentContext, fillColor.r, fillColor.g, fillColor.b, fillColor.a );
         cairo_stroke( currentContext );
     }
@@ -116,25 +192,29 @@ void CAIRO_GAL_BASE::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& a
         // Outline mode for tracks
         VECTOR2D startEndVector = aEndPoint - aStartPoint;
         double   lineAngle      = atan2( startEndVector.y, startEndVector.x );
-        double   lineLength     = startEndVector.EuclideanNorm();
 
-        cairo_save( currentContext );
+        double sa = sin( lineAngle + M_PI / 2.0 );
+        double ca = cos( lineAngle + M_PI / 2.0 );
 
-        cairo_set_source_rgba( currentContext, strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
+        auto pa0 = roundp( xform ( aStartPoint + VECTOR2D(aWidth * ca, aWidth * sa ) ) );
+        auto pa1 = roundp( xform ( aStartPoint - VECTOR2D(aWidth * ca, aWidth * sa ) ) );
+        auto pb0 = roundp( xform ( aEndPoint + VECTOR2D(aWidth * ca, aWidth * sa ) ) );
+        auto pb1 = roundp( xform ( aEndPoint - VECTOR2D(aWidth * ca, aWidth * sa ) ) );
+        auto pa = roundp( xform( aStartPoint ) );
+        auto pb = roundp( xform( aEndPoint ) );
+        auto rb = ::roundp( (pa0 - pa).EuclideanNorm() );
 
-        cairo_translate( currentContext, aStartPoint.x, aStartPoint.y );
-        cairo_rotate( currentContext, lineAngle );
+        cairo_set_source_rgba( currentContext, strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
 
-        cairo_arc( currentContext, 0.0,        0.0, aWidth / 2.0,  M_PI / 2.0, 3.0 * M_PI / 2.0 );
-        cairo_arc( currentContext, lineLength, 0.0, aWidth / 2.0, -M_PI / 2.0, M_PI / 2.0 );
+        cairo_move_to( currentContext, pa0.x, pa0.y );
+        cairo_line_to( currentContext, pb0.x, pb0.y );
 
-        cairo_move_to( currentContext, 0.0,        aWidth / 2.0 );
-        cairo_line_to( currentContext, lineLength, aWidth / 2.0 );
+        cairo_move_to( currentContext, pa1.x, pa1.y );
+        cairo_line_to( currentContext, pb1.x, pb1.y );
 
-        cairo_move_to( currentContext, 0.0,        -aWidth / 2.0 );
-        cairo_line_to( currentContext, lineLength, -aWidth / 2.0 );
+        cairo_arc( currentContext, pb.x, pb.y, rb, lineAngle - M_PI / 2.0, lineAngle + M_PI / 2.0 );
+        cairo_arc( currentContext, pa.x, pa.y, rb, lineAngle + M_PI / 2.0, lineAngle + 3.0 * M_PI / 2.0 );
 
-        cairo_restore( currentContext );
         flushPath();
     }
 
@@ -144,8 +224,15 @@ void CAIRO_GAL_BASE::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& a
 
 void CAIRO_GAL_BASE::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius )
 {
+    syncLineWidth();
+
+    auto c = roundp( xform( aCenterPoint ) );
+    auto r = ::roundp( xform( aRadius ) );
+
     cairo_new_sub_path( currentContext );
-    cairo_arc( currentContext, aCenterPoint.x, aCenterPoint.y, aRadius, 0.0, 2 * M_PI );
+    cairo_arc( currentContext, c.x, c.y, r, 0.0, 2 * M_PI- 0.1 );
+    cairo_close_path( currentContext );
+    printf("circle fill: %.1f %.1f %.1f %.10f %.10f %10f %.10f %d stroke : %d %.1f %.1f %.1f %.1f\n", c.x, c.y, r, aRadius, xform( aRadius ), currentWorld2Screen.xx, currentWorld2Screen.yy, !!isFillEnabled, !!isStrokeEnabled, fillColor.r, fillColor.g, fillColor.b, fillColor.a );
     flushPath();
     isElementAdded = true;
 }
@@ -154,33 +241,43 @@ void CAIRO_GAL_BASE::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius )
 void CAIRO_GAL_BASE::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double aStartAngle,
                          double aEndAngle )
 {
+    syncLineWidth();
+
+    auto c = roundp( xform( aCenterPoint ) );
+    auto r = ::roundp( xform( aRadius ) );
+
+    VECTOR2D startPoint( cos( aStartAngle ) * aRadius + aCenterPoint.x,
+                             sin( aStartAngle ) * aRadius + aCenterPoint.y );
+    VECTOR2D endPoint( cos( aEndAngle ) * aRadius + aCenterPoint.x,
+                           sin( aEndAngle ) * aRadius + aCenterPoint.y );
+
+    auto startPointS = roundp( xform ( startPoint ) );
+    auto endPointS = roundp( xform ( endPoint ) );
+
     SWAP( aStartAngle, >, aEndAngle );
 
     if( isFillEnabled )     // Draw the filled area of the shape, before drawing the outline itself
     {
-        auto pen_size = GetLineWidth();
+        //double pen_size = GetLineWidth();
         auto fgcolor = GetStrokeColor();
         SetStrokeColor( GetFillColor() );
 
-        SetLineWidth( 0 );
+        cairo_set_line_width( currentContext, 1.0 );
         cairo_new_sub_path( currentContext );
-        cairo_arc( currentContext, aCenterPoint.x, aCenterPoint.y, aRadius, aStartAngle, aEndAngle );
-        VECTOR2D startPoint( cos( aStartAngle ) * aRadius + aCenterPoint.x,
-                             sin( aStartAngle ) * aRadius + aCenterPoint.y );
-        VECTOR2D endPoint( cos( aEndAngle ) * aRadius + aCenterPoint.x,
-                           sin( aEndAngle ) * aRadius + aCenterPoint.y );
+        cairo_arc( currentContext, c.x, c.y, r, aStartAngle, aEndAngle );
 
-        cairo_move_to( currentContext, aCenterPoint.x, aCenterPoint.y );
-        cairo_line_to( currentContext, startPoint.x, startPoint.y );
-        cairo_line_to( currentContext, endPoint.x, endPoint.y );
+        cairo_move_to( currentContext, c.x, c.y );
+        cairo_line_to( currentContext, startPointS.x, startPointS.y );
+        cairo_line_to( currentContext, endPointS.x, endPointS.y );
         cairo_close_path( currentContext );
         flushPath();
-        SetLineWidth( pen_size );
+       // SetLineWidth( pen_size );
         SetStrokeColor( fgcolor );
     }
 
+    cairo_set_line_width(currentContext, lineWidthInPixels );
     cairo_new_sub_path( currentContext );
-    cairo_arc( currentContext, aCenterPoint.x, aCenterPoint.y, aRadius, aStartAngle, aEndAngle );
+    cairo_arc( currentContext, c.x, c.y, r, aStartAngle, aEndAngle );
     flushPath();
 
     isElementAdded = true;
@@ -192,6 +289,8 @@ void CAIRO_GAL_BASE::DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadiu
 {
     SWAP( aStartAngle, >, aEndAngle );
 
+    syncLineWidth();
+
     if( isFillEnabled )
     {
         // Filled segments mode
@@ -237,14 +336,16 @@ void CAIRO_GAL_BASE::DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadiu
 void CAIRO_GAL_BASE::DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
 {
     // Calculate the diagonal points
-    VECTOR2D diagonalPointA( aEndPoint.x,  aStartPoint.y );
-    VECTOR2D diagonalPointB( aStartPoint.x, aEndPoint.y );
+    syncLineWidth();
+
+    const auto p0 = roundp( xform( aStartPoint ) );
+    const auto p1 = roundp( xform( aEndPoint ) );
 
     // The path is composed from 4 segments
-    cairo_move_to( currentContext, aStartPoint.x, aStartPoint.y );
-    cairo_line_to( currentContext, diagonalPointA.x, diagonalPointA.y );
-    cairo_line_to( currentContext, aEndPoint.x, aEndPoint.y );
-    cairo_line_to( currentContext, diagonalPointB.x, diagonalPointB.y );
+    cairo_move_to( currentContext, p0.x, p0.y );
+    cairo_line_to( currentContext, p1.x, p0.y );
+    cairo_line_to( currentContext, p1.x, p1.y );
+    cairo_line_to( currentContext, p0.x, p1.y );
     cairo_close_path( currentContext );
     flushPath();
 
@@ -268,10 +369,16 @@ void CAIRO_GAL_BASE::DrawPolygon( const SHAPE_LINE_CHAIN& aPolygon )
 void CAIRO_GAL_BASE::DrawCurve( const VECTOR2D& aStartPoint, const VECTOR2D& aControlPointA,
                            const VECTOR2D& aControlPointB, const VECTOR2D& aEndPoint )
 {
-    cairo_move_to( currentContext, aStartPoint.x, aStartPoint.y );
-    cairo_curve_to( currentContext, aControlPointA.x, aControlPointA.y, aControlPointB.x,
-                    aControlPointB.y, aEndPoint.x, aEndPoint.y );
-    cairo_line_to( currentContext, aEndPoint.x, aEndPoint.y );
+    syncLineWidth();
+
+    const auto sp = roundp( xform( aStartPoint ) );
+    const auto cpa = roundp( xform( aControlPointA ) );
+    const auto cpb = roundp( xform( aControlPointB ) );
+    const auto ep = roundp( xform( aEndPoint ) );
+
+    cairo_move_to( currentContext, sp.x, sp.y );
+    cairo_curve_to( currentContext, cpa.x, cpa.y, cpb.x, cpb.y, ep.x, ep.y );
+    cairo_line_to( currentContext, ep.x, ep.y );
 
     flushPath();
     isElementAdded = true;
@@ -280,18 +387,31 @@ void CAIRO_GAL_BASE::DrawCurve( const VECTOR2D& aStartPoint, const VECTOR2D& aCo
 
 void CAIRO_GAL_BASE::DrawBitmap( const BITMAP_BASE& aBitmap )
 {
+    SetIsStroke( true );
+    SetLineWidth( 1.0 );
+    SetStrokeColor( COLOR4D(0.0, 0.0, 1.0, 1.0));
+    DrawCircle( VECTOR2D(0, 0), 100.0 );
     cairo_save( currentContext );
 
     // We have to calculate the pixel size in users units to draw the image.
     // worldUnitLength is a factor used for converting IU to inches
     double scale = 1.0 / ( aBitmap.GetPPI() * worldUnitLength );
-    cairo_scale( currentContext, scale, scale );
 
     // The position of the bitmap is the bitmap center.
     // move the draw origin to the top left bitmap corner:
     int w = aBitmap.GetSizePixels().x;
     int h = aBitmap.GetSizePixels().y;
-    cairo_translate( currentContext, -w/2, -h/2 );
+
+    auto matrix = currentWorld2Screen;
+
+    // hack: fix the world 2 screen matrix so that our bitmap is placed where it should
+    // (cairo_translate does not chain transforms)
+    matrix.xx *= scale;
+    matrix.yy *= scale;
+    matrix.x0 -= matrix.xx * (double)w / 2;
+    matrix.y0 -= matrix.yy * (double)h / 2;
+
+    cairo_set_matrix( currentContext, &matrix );
 
     cairo_new_path( currentContext );
     cairo_surface_t* image = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, w, h );
@@ -441,11 +561,7 @@ void CAIRO_GAL_BASE::SetLineWidth( float aLineWidth )
     }
     else
     {
-        // Make lines appear at least 1 pixel wide, no matter of zoom
-        double x = 1.0, y = 1.0;
-        cairo_device_to_user_distance( currentContext, &x, &y );
-        auto minWidth = std::min( fabs( x ), fabs( y ) );
-        cairo_set_line_width( currentContext, std::fmax( aLineWidth, minWidth ) );
+        lineWidth = aLineWidth;
     }
 }
 
@@ -459,7 +575,7 @@ void CAIRO_GAL_BASE::SetLayerDepth( double aLayerDepth )
 
 void CAIRO_GAL_BASE::Transform( const MATRIX3x3D& aTransformation )
 {
-    cairo_matrix_t cairoTransformation;
+    cairo_matrix_t cairoTransformation, newXform;
 
     cairo_matrix_init( &cairoTransformation,
                        aTransformation.m_data[0][0],
@@ -469,7 +585,9 @@ void CAIRO_GAL_BASE::Transform( const MATRIX3x3D& aTransformation )
                        aTransformation.m_data[0][2],
                        aTransformation.m_data[1][2] );
 
-    cairo_transform( currentContext, &cairoTransformation );
+    cairo_matrix_multiply( &newXform, &currentXform, &cairoTransformation );
+    currentXform = newXform;
+    updateWorldScreenMatrix();
 }
 
 
@@ -486,7 +604,8 @@ void CAIRO_GAL_BASE::Rotate( double aAngle )
     }
     else
     {
-        cairo_rotate( currentContext, aAngle );
+        cairo_matrix_rotate( &currentXform, aAngle );
+        updateWorldScreenMatrix();
     }
 }
 
@@ -505,7 +624,8 @@ void CAIRO_GAL_BASE::Translate( const VECTOR2D& aTranslation )
     }
     else
     {
-        cairo_translate( currentContext, aTranslation.x, aTranslation.y );
+        cairo_matrix_translate ( &currentXform, aTranslation.x, aTranslation.y );
+        updateWorldScreenMatrix();
     }
 }
 
@@ -524,7 +644,8 @@ void CAIRO_GAL_BASE::Scale( const VECTOR2D& aScale )
     }
     else
     {
-        cairo_scale( currentContext, aScale.x, aScale.y );
+        cairo_matrix_scale( &currentXform, aScale.x, aScale.y );
+        updateWorldScreenMatrix();
     }
 }
 
@@ -541,7 +662,8 @@ void CAIRO_GAL_BASE::Save()
     }
     else
     {
-        cairo_save( currentContext );
+        xformStack.push_back( currentXform );
+        updateWorldScreenMatrix();
     }
 }
 
@@ -558,7 +680,12 @@ void CAIRO_GAL_BASE::Restore()
     }
     else
     {
-        cairo_restore( currentContext );
+        if( !xformStack.empty() )
+        {
+            currentXform = xformStack.back();
+            xformStack.pop_back();
+            updateWorldScreenMatrix();
+        }
     }
 }
 
@@ -747,9 +874,6 @@ void CAIRO_GAL_BASE::EnableDepthTest( bool aEnabled )
 
 void CAIRO_GAL_BASE::resetContext()
 {
-
-    cairo_set_antialias( context, CAIRO_ANTIALIAS_NONE );
-
     ClearScreen();
 
     // Compute the world <-> screen transformations
@@ -760,14 +884,21 @@ void CAIRO_GAL_BASE::resetContext()
                        worldScreenMatrix.m_data[1][1], worldScreenMatrix.m_data[0][2],
                        worldScreenMatrix.m_data[1][2] );
 
-    cairo_set_matrix( context, &cairoWorldScreenMatrix );
+    //printf("resetContext %.5f %.5f %.5f\n", cairoWorldScreenMatrix.xx, cairoWorldScreenMatrix.xy, cairoWorldScreenMatrix.x0 );
+    //printf("             %.5f %.5f %.5f\n", cairoWorldScreenMatrix.yx, cairoWorldScreenMatrix.yy, cairoWorldScreenMatrix.y0 );
+
+    //cairo_set_matrix( context, &cairoWorldScreenMatrix );
+
+    // we work in screen-space coordinates and do the transforms outside.
+    cairo_identity_matrix( context );
+
+    cairo_matrix_init_identity( &currentXform );
 
     // Start drawing with a new path
     cairo_new_path( context );
     isElementAdded = true;
 
-    cairo_set_line_join( context, CAIRO_LINE_JOIN_ROUND );
-    cairo_set_line_cap( context, CAIRO_LINE_CAP_ROUND );
+    updateWorldScreenMatrix();
 
     lineWidth = 0;
 }
@@ -775,12 +906,39 @@ void CAIRO_GAL_BASE::resetContext()
 
 void CAIRO_GAL_BASE::drawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
 {
-    cairo_move_to( currentContext, aStartPoint.x, aStartPoint.y );
-    cairo_line_to( currentContext, aEndPoint.x, aEndPoint.y );
+    auto p0 = roundp( xform( aStartPoint ) );
+    auto p1 = roundp( xform( aEndPoint ) );
+
+    syncLineWidth();
+
+    cairo_move_to( currentContext, p0.x, p0.y );
+    cairo_line_to( currentContext, p1.x, p1.y );
     cairo_set_source_rgba( currentContext, strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
     cairo_stroke( currentContext );
 }
 
+void CAIRO_GAL_BASE::drawGridPoint( const VECTOR2D& aPoint, double aSize )
+{
+    auto p = roundp( xform( aPoint ) );
+    auto s = aSize / 2.0;
+
+    if( (((int)aSize) % 2) == 0 ) // s even
+    {
+        p += VECTOR2D( 0.5, 0.5 );
+    }
+
+    cairo_set_line_join( currentContext, CAIRO_LINE_JOIN_MITER );
+    cairo_set_line_cap( currentContext, CAIRO_LINE_CAP_BUTT );
+    cairo_set_line_width( currentContext, 1.0 ); //floor( aSize + 0.5 ) - 0.5 );
+
+    cairo_move_to( currentContext, p.x - s, p.y - s);
+    cairo_line_to( currentContext, p.x + s, p.y - s);
+    cairo_line_to( currentContext, p.x + s, p.y + s);
+    cairo_line_to( currentContext, p.x - s, p.y + s);
+    cairo_close_path( currentContext );
+
+    cairo_fill( currentContext );
+}
 
 void CAIRO_GAL_BASE::flushPath()
 {
@@ -875,11 +1033,17 @@ void CAIRO_GAL_BASE::drawPoly( const std::deque<VECTOR2D>& aPointList )
     // Iterate over the point list and draw the segments
     std::deque<VECTOR2D>::const_iterator it = aPointList.begin();
 
-    cairo_move_to( currentContext, it->x, it->y );
+    syncLineWidth();
+
+    const auto p = roundp( xform( it->x, it->y ) );
+
+    cairo_move_to( currentContext, p.x, p.y );
 
     for( ++it; it != aPointList.end(); ++it )
     {
-        cairo_line_to( currentContext, it->x, it->y );
+        const auto p2 = roundp( xform( it->x, it->y ) );
+
+        cairo_line_to( currentContext, p2.x, p2.y );
     }
 
     flushPath();
@@ -892,12 +1056,16 @@ void CAIRO_GAL_BASE::drawPoly( const VECTOR2D aPointList[], int aListSize )
     // Iterate over the point list and draw the segments
     const VECTOR2D* ptr = aPointList;
 
-    cairo_move_to( currentContext, ptr->x, ptr->y );
+    syncLineWidth();
+
+    const auto p = roundp( xform( ptr->x, ptr->y ) );
+    cairo_move_to( currentContext, p.x, p.y );
 
     for( int i = 0; i < aListSize; ++i )
     {
         ++ptr;
-        cairo_line_to( currentContext, ptr->x, ptr->y );
+        const auto p2 = roundp( xform( ptr->x, ptr->y ) );
+        cairo_line_to( currentContext, p2.x, p2.y );
     }
 
     flushPath();
@@ -910,18 +1078,22 @@ void CAIRO_GAL_BASE::drawPoly( const SHAPE_LINE_CHAIN& aLineChain )
     if( aLineChain.PointCount() < 2 )
         return;
 
+    syncLineWidth();
+
     auto numPoints = aLineChain.PointCount();
 
     if( aLineChain.IsClosed() )
         numPoints += 1;
 
     const VECTOR2I start = aLineChain.CPoint( 0 );
-    cairo_move_to( currentContext, start.x, start.y );
+    const auto p = roundp( xform( start.x, start.y ) );
+    cairo_move_to( currentContext, p.x, p.y );
 
     for( int i = 1; i < numPoints; ++i )
     {
-        const VECTOR2I& p = aLineChain.CPoint( i );
-        cairo_line_to( currentContext, p.x, p.y );
+        const VECTOR2I& pw = aLineChain.CPoint( i );
+        const auto ps = roundp( xform( pw.x, pw.y ) );
+        cairo_line_to( currentContext, ps.x, ps.y );
     }
 
     flushPath();
@@ -1236,7 +1408,6 @@ void CAIRO_GAL::setCompositor()
     // Recreate the compositor with the new Cairo context
     compositor.reset( new CAIRO_COMPOSITOR( &currentContext ) );
     compositor->Resize( screenSize.x, screenSize.y );
-    compositor->SetAntialiasingMode( options.cairo_antialiasing_mode );
 
     // Prepare buffers
     mainBuffer = compositor->CreateBuffer();
@@ -1282,3 +1453,188 @@ bool CAIRO_GAL::updatedGalDisplayOptions( const GAL_DISPLAY_OPTIONS& aOptions )
 
     return refresh;
 }
+
+void CAIRO_GAL_BASE::DrawGrid()
+{
+    SetTarget( TARGET_NONCACHED );
+
+    // Draw the grid
+    // For the drawing the start points, end points and increments have
+    // to be calculated in world coordinates
+    VECTOR2D worldStartPoint = screenWorldMatrix * VECTOR2D( 0.0, 0.0 );
+    VECTOR2D worldEndPoint   = screenWorldMatrix * VECTOR2D( screenSize );
+
+    const double gridThreshold = computeMinGridSpacing();
+
+    int gridScreenSizeDense  = KiROUND( gridSize.x * worldScale );
+    int gridScreenSizeCoarse = KiROUND( gridSize.x * static_cast<double>( gridTick ) * worldScale );
+
+    // Compute the line marker or point radius of the grid
+    // Note: generic grids can't handle sub-pixel lines without
+    // either losing fine/course distinction or having some dots
+    // fail to render
+    float marker = std::fmax( 1.0f, gridLineWidth ) / worldScale;
+    float doubleMarker = 2.0f * marker;
+
+    // Draw axes if desired
+    if( axesEnabled )
+    {
+        SetIsFill( false );
+        SetIsStroke( true );
+        SetStrokeColor( axesColor );
+        SetLineWidth( marker );
+
+        drawGridLine( VECTOR2D( worldStartPoint.x, 0 ),
+                      VECTOR2D( worldEndPoint.x, 0 ) );
+
+        drawGridLine( VECTOR2D( 0, worldStartPoint.y ),
+                      VECTOR2D( 0, worldEndPoint.y ) );
+    }
+
+    if( !gridVisibility )
+        return;
+
+    // Check if the grid would not be too dense
+    if( std::max( gridScreenSizeDense, gridScreenSizeCoarse ) <= gridThreshold )
+        return;
+
+    // Compute grid staring and ending indexes to draw grid points on the
+    // visible screen area
+    // Note: later any point coordinate will be offsetted by gridOrigin
+    int gridStartX = KiROUND( ( worldStartPoint.x - gridOrigin.x ) / gridSize.x );
+    int gridEndX = KiROUND( ( worldEndPoint.x - gridOrigin.x ) / gridSize.x );
+    int gridStartY = KiROUND( ( worldStartPoint.y - gridOrigin.y ) / gridSize.y );
+    int gridEndY = KiROUND( ( worldEndPoint.y - gridOrigin.y ) / gridSize.y );
+
+    // Ensure start coordinate > end coordinate
+    if( gridStartX > gridEndX )
+        std::swap( gridStartX, gridEndX );
+
+    if( gridStartY > gridEndY )
+        std::swap( gridStartY, gridEndY );
+
+    // Ensure the grid fills the screen
+    --gridStartX; ++gridEndX;
+    --gridStartY; ++gridEndY;
+
+    // Draw the grid behind all other layers
+    SetLayerDepth( depthRange.y * 0.75 );
+
+    if( gridStyle == GRID_STYLE::LINES )
+    {
+        SetIsFill( false );
+        SetIsStroke( true );
+        SetStrokeColor( gridColor );
+
+        // Now draw the grid, every coarse grid line gets the double width
+
+        // Vertical lines
+        for( int j = gridStartY; j <= gridEndY; j++ )
+        {
+            const double y = j * gridSize.y + gridOrigin.y;
+
+            if( axesEnabled && y == 0 )
+                continue;
+
+            if( j % gridTick == 0 && gridScreenSizeDense > gridThreshold )
+                SetLineWidth( doubleMarker );
+            else
+                SetLineWidth( marker );
+
+            if( ( j % gridTick == 0 && gridScreenSizeCoarse > gridThreshold )
+                || gridScreenSizeDense > gridThreshold )
+            {
+                drawGridLine( VECTOR2D( gridStartX * gridSize.x + gridOrigin.x, y ),
+                              VECTOR2D( gridEndX * gridSize.x + gridOrigin.x, y ) );
+            }
+        }
+
+        // Horizontal lines
+        for( int i = gridStartX; i <= gridEndX; i++ )
+        {
+            const double x = i * gridSize.x + gridOrigin.x;
+
+            if( axesEnabled && x == 0 )
+                continue;
+
+            if( i % gridTick == 0 && gridScreenSizeDense > gridThreshold )
+                SetLineWidth( doubleMarker );
+            else
+                SetLineWidth( marker );
+
+            if( ( i % gridTick == 0 && gridScreenSizeCoarse > gridThreshold )
+                || gridScreenSizeDense > gridThreshold )
+            {
+                drawGridLine( VECTOR2D( x, gridStartY * gridSize.y + gridOrigin.y ),
+                              VECTOR2D( x, gridEndY * gridSize.y + gridOrigin.y ) );
+            }
+        }
+    }
+    else if( gridStyle == GRID_STYLE::SMALL_CROSS )
+    {
+        SetIsFill( false );
+        SetIsStroke( true );
+        SetStrokeColor( gridColor );
+
+        SetLineWidth( marker );
+        double lineLen = GetLineWidth() * 2;
+
+        // Vertical positions:
+        for( int j = gridStartY; j <= gridEndY; j++ )
+        {
+            if( ( j % gridTick == 0 && gridScreenSizeCoarse > gridThreshold )
+                || gridScreenSizeDense > gridThreshold )
+            {
+                int posY =  j * gridSize.y + gridOrigin.y;
+
+                // Horizontal positions:
+                for( int i = gridStartX; i <= gridEndX; i++ )
+                {
+                    if( ( i % gridTick == 0 && gridScreenSizeCoarse > gridThreshold )
+                        || gridScreenSizeDense > gridThreshold )
+                    {
+                        int posX = i * gridSize.x + gridOrigin.x;
+
+                        drawGridLine( VECTOR2D( posX - lineLen, posY ),
+                                        VECTOR2D( posX + lineLen,   posY ) );
+
+                        drawGridLine( VECTOR2D( posX, posY - lineLen ),
+                                        VECTOR2D( posX, posY + lineLen ) );
+                    }
+                }
+            }
+        }
+    }
+    else    // Dotted grid
+    {
+        bool tickX, tickY;
+        SetIsFill( true );
+        SetIsStroke( false );
+        SetFillColor( gridColor );
+
+        for( int j = gridStartY; j <= gridEndY; j++ )
+        {
+            if( j % gridTick == 0 && gridScreenSizeDense > gridThreshold )
+                tickY = true;
+            else
+                tickY = false;
+
+            for( int i = gridStartX; i <= gridEndX; i++ )
+            {
+                if( i % gridTick == 0 && gridScreenSizeDense > gridThreshold )
+                    tickX = true;
+                else
+                    tickX = false;
+
+                if( tickX || tickY || gridScreenSizeDense > gridThreshold )
+                {
+                    double radius = ( ( tickX && tickY ) ? 2.0 : 1.0 );
+                    drawGridPoint( VECTOR2D( i * gridSize.x + gridOrigin.x,
+                                             j * gridSize.y + gridOrigin.y ), radius );
+
+                }
+            }
+        }
+    }
+}
+
diff --git a/common/gal/graphics_abstraction_layer.cpp b/common/gal/graphics_abstraction_layer.cpp
index 74074dcd3..1c0064148 100644
--- a/common/gal/graphics_abstraction_layer.cpp
+++ b/common/gal/graphics_abstraction_layer.cpp
@@ -213,191 +213,6 @@ double GAL::computeMinGridSpacing() const
 }
 
 
-void GAL::DrawGrid()
-{
-    SetTarget( TARGET_NONCACHED );
-
-    // Draw the grid
-    // For the drawing the start points, end points and increments have
-    // to be calculated in world coordinates
-    VECTOR2D worldStartPoint = screenWorldMatrix * VECTOR2D( 0.0, 0.0 );
-    VECTOR2D worldEndPoint   = screenWorldMatrix * VECTOR2D( screenSize );
-
-    const double gridThreshold = computeMinGridSpacing();
-
-    int gridScreenSizeDense  = KiROUND( gridSize.x * worldScale );
-    int gridScreenSizeCoarse = KiROUND( gridSize.x * static_cast<double>( gridTick ) * worldScale );
-
-    // Compute the line marker or point radius of the grid
-    // Note: generic grids can't handle sub-pixel lines without
-    // either losing fine/course distinction or having some dots
-    // fail to render
-    float marker = std::fmax( 1.0f, gridLineWidth ) / worldScale;
-    float doubleMarker = 2.0f * marker;
-
-    // Draw axes if desired
-    if( axesEnabled )
-    {
-        SetIsFill( false );
-        SetIsStroke( true );
-        SetStrokeColor( axesColor );
-        SetLineWidth( marker );
-
-        drawGridLine( VECTOR2D( worldStartPoint.x, 0 ),
-                      VECTOR2D( worldEndPoint.x, 0 ) );
-
-        drawGridLine( VECTOR2D( 0, worldStartPoint.y ),
-                      VECTOR2D( 0, worldEndPoint.y ) );
-    }
-
-    if( !gridVisibility )
-        return;
-
-    // Check if the grid would not be too dense
-    if( std::max( gridScreenSizeDense, gridScreenSizeCoarse ) <= gridThreshold )
-        return;
-
-    // Compute grid staring and ending indexes to draw grid points on the
-    // visible screen area
-    // Note: later any point coordinate will be offsetted by gridOrigin
-    int gridStartX = KiROUND( ( worldStartPoint.x - gridOrigin.x ) / gridSize.x );
-    int gridEndX = KiROUND( ( worldEndPoint.x - gridOrigin.x ) / gridSize.x );
-    int gridStartY = KiROUND( ( worldStartPoint.y - gridOrigin.y ) / gridSize.y );
-    int gridEndY = KiROUND( ( worldEndPoint.y - gridOrigin.y ) / gridSize.y );
-
-    // Ensure start coordinate > end coordinate
-    if( gridStartX > gridEndX )
-        std::swap( gridStartX, gridEndX );
-
-    if( gridStartY > gridEndY )
-        std::swap( gridStartY, gridEndY );
-
-    // Ensure the grid fills the screen
-    --gridStartX; ++gridEndX;
-    --gridStartY; ++gridEndY;
-
-    // Draw the grid behind all other layers
-    SetLayerDepth( depthRange.y * 0.75 );
-
-    if( gridStyle == GRID_STYLE::LINES )
-    {
-        SetIsFill( false );
-        SetIsStroke( true );
-        SetStrokeColor( gridColor );
-
-        // Now draw the grid, every coarse grid line gets the double width
-
-        // Vertical lines
-        for( int j = gridStartY; j <= gridEndY; j++ )
-        {
-            const double y = j * gridSize.y + gridOrigin.y;
-
-            if( axesEnabled && y == 0 )
-                continue;
-
-            if( j % gridTick == 0 && gridScreenSizeDense > gridThreshold )
-                SetLineWidth( doubleMarker );
-            else
-                SetLineWidth( marker );
-
-            if( ( j % gridTick == 0 && gridScreenSizeCoarse > gridThreshold )
-                || gridScreenSizeDense > gridThreshold )
-            {
-                drawGridLine( VECTOR2D( gridStartX * gridSize.x + gridOrigin.x, y ),
-                              VECTOR2D( gridEndX * gridSize.x + gridOrigin.x, y ) );
-            }
-        }
-
-        // Horizontal lines
-        for( int i = gridStartX; i <= gridEndX; i++ )
-        {
-            const double x = i * gridSize.x + gridOrigin.x;
-
-            if( axesEnabled && x == 0 )
-                continue;
-
-            if( i % gridTick == 0 && gridScreenSizeDense > gridThreshold )
-                SetLineWidth( doubleMarker );
-            else
-                SetLineWidth( marker );
-
-            if( ( i % gridTick == 0 && gridScreenSizeCoarse > gridThreshold )
-                || gridScreenSizeDense > gridThreshold )
-            {
-                drawGridLine( VECTOR2D( x, gridStartY * gridSize.y + gridOrigin.y ),
-                              VECTOR2D( x, gridEndY * gridSize.y + gridOrigin.y ) );
-            }
-        }
-    }
-    else if( gridStyle == GRID_STYLE::SMALL_CROSS )
-    {
-        SetIsFill( false );
-        SetIsStroke( true );
-        SetStrokeColor( gridColor );
-
-        SetLineWidth( marker );
-        double lineLen = GetLineWidth() * 2;
-
-        // Vertical positions:
-        for( int j = gridStartY; j <= gridEndY; j++ )
-        {
-            if( ( j % gridTick == 0 && gridScreenSizeCoarse > gridThreshold )
-                || gridScreenSizeDense > gridThreshold )
-            {
-                int posY =  j * gridSize.y + gridOrigin.y;
-
-                // Horizontal positions:
-                for( int i = gridStartX; i <= gridEndX; i++ )
-                {
-                    if( ( i % gridTick == 0 && gridScreenSizeCoarse > gridThreshold )
-                        || gridScreenSizeDense > gridThreshold )
-                    {
-                        int posX = i * gridSize.x + gridOrigin.x;
-
-                        drawGridLine( VECTOR2D( posX - lineLen, posY ),
-                                        VECTOR2D( posX + lineLen,   posY ) );
-
-                        drawGridLine( VECTOR2D( posX, posY - lineLen ),
-                                        VECTOR2D( posX, posY + lineLen ) );
-                    }
-                }
-            }
-        }
-    }
-    else    // Dotted grid
-    {
-        bool tickX, tickY;
-        SetIsFill( true );
-        SetIsStroke( false );
-        SetFillColor( gridColor );
-
-        for( int j = gridStartY; j <= gridEndY; j++ )
-        {
-            if( j % gridTick == 0 && gridScreenSizeDense > gridThreshold )
-                tickY = true;
-            else
-                tickY = false;
-
-            for( int i = gridStartX; i <= gridEndX; i++ )
-            {
-                if( i % gridTick == 0 && gridScreenSizeDense > gridThreshold )
-                    tickX = true;
-                else
-                    tickX = false;
-
-                if( tickX || tickY || gridScreenSizeDense > gridThreshold )
-                {
-                    double radius = ( ( tickX && tickY ) ? doubleMarker : marker ) / 2.0;
-                    DrawRectangle( VECTOR2D( i * gridSize.x - radius + gridOrigin.x,
-                                                j * gridSize.y - radius + gridOrigin.y ),
-                                    VECTOR2D( i * gridSize.x + radius + gridOrigin.x,
-                                                j * gridSize.y + radius + gridOrigin.y ) );
-                }
-            }
-        }
-    }
-}
-
 
 VECTOR2D GAL::GetGridPoint( const VECTOR2D& aPoint ) const
 {
diff --git a/eeschema/sch_draw_panel.h b/eeschema/sch_draw_panel.h
index e5dc309f7..c52b133f9 100644
--- a/eeschema/sch_draw_panel.h
+++ b/eeschema/sch_draw_panel.h
@@ -6,7 +6,7 @@
 #include <gr_basic.h>
 #include <eda_rect.h>
 
-#include <class_drawpanel.h>
+#include <legacy_gal/class_drawpanel.h>
 
 
 namespace KIGFX
diff --git a/include/gal/cairo/cairo_gal.h b/include/gal/cairo/cairo_gal.h
index e9c059829..c845dfa67 100644
--- a/include/gal/cairo/cairo_gal.h
+++ b/include/gal/cairo/cairo_gal.h
@@ -214,7 +214,15 @@ public:
 
     virtual void EnableDepthTest( bool aEnabled = false ) override;
 
+    ///> @copydoc GAL::DrawGrid()
+    virtual void DrawGrid() override;
+
+
 protected:
+    const double xform( double x );
+    const VECTOR2D xform( double x, double y );
+    const VECTOR2D xform( const VECTOR2D& aP );
+
     /// @copydoc GAL::BeginDrawing()
     virtual void beginDrawing() override;
 
@@ -224,6 +232,7 @@ protected:
     void resetContext();
 
     virtual void drawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) override;
+    virtual void drawGridPoint( const VECTOR2D& aPoint, double aSize ) override;
 
     /// Super class definition
     typedef GAL super;
@@ -270,11 +279,20 @@ protected:
     unsigned int                groupCounter;       ///< Counter used for generating keys for groups
     GROUP*                      currentGroup;       ///< Currently used group
 
+    double lineWidth;
+    double linePixelWidth;
+    double lineWidthInPixels;
+    bool lineWidthIsOdd;
+
     cairo_matrix_t      cairoWorldScreenMatrix; ///< Cairo world to screen transformation matrix
+    cairo_matrix_t      currentXform;
+    cairo_matrix_t      currentWorld2Screen;
     cairo_t*            currentContext;         ///< Currently used Cairo context for drawing
     cairo_t*            context;                ///< Cairo image
     cairo_surface_t*    surface;                ///< Cairo surface
 
+    std::vector<cairo_matrix_t> xformStack;
+
     void flushPath();
     void storePath();                           ///< Store the actual path
 
@@ -295,6 +313,11 @@ protected:
      */
     unsigned int getNewGroupNumber();
 
+    void syncLineWidth( bool aForceWidth = false, double aWidth = 0.0);
+    void updateWorldScreenMatrix();
+    const VECTOR2D roundp( const VECTOR2D& v );
+
+
     /// Format used to store pixels
     static constexpr cairo_format_t GAL_FORMAT = CAIRO_FORMAT_RGB24;
 };
diff --git a/include/gal/graphics_abstraction_layer.h b/include/gal/graphics_abstraction_layer.h
index da61dcb72..c266c628d 100644
--- a/include/gal/graphics_abstraction_layer.h
+++ b/include/gal/graphics_abstraction_layer.h
@@ -944,7 +944,7 @@ public:
     }
 
     ///> @brief Draw the grid
-    virtual void DrawGrid();
+    virtual void DrawGrid() {};
 
     /**
      * Function GetGridPoint()
@@ -1138,6 +1138,7 @@ protected:
      * @param aEndPoint is the end point of the line.
      */
     virtual void drawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) {};
+    virtual void drawGridPoint( const VECTOR2D& aPoint, double aSize ) {};
 
     /// Possible depth range
     static const int MIN_DEPTH;
diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp
index 8814249e7..018e50810 100644
--- a/pcbnew/pcb_painter.cpp
+++ b/pcbnew/pcb_painter.cpp
@@ -1148,12 +1148,13 @@ void PCB_PAINTER::draw( const ZONE_CONTAINER* aZone, int aLayer )
 
         // Set up drawing options
         m_gal->SetFillColor( color );
+        m_gal->SetStrokeColor( color );
         m_gal->SetLineWidth( aZone->GetMinThickness() );
 
         if( displayMode == PCB_RENDER_SETTINGS::DZ_SHOW_FILLED )
         {
             m_gal->SetIsFill( true );
-            m_gal->SetIsStroke( true );
+            m_gal->SetIsStroke( false );
         }
         else if( displayMode == PCB_RENDER_SETTINGS::DZ_SHOW_OUTLINED )
         {
-- 
2.17.1

>From 7cf8f291807eee537d49770736b545526061b35e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tomasz=20W=C5=82ostowski?= <tomasz.wlostowski@xxxxxxx>
Date: Sun, 3 Feb 2019 16:14:03 +0100
Subject: [PATCH 2/3] gal: pixel alignment for OpenGL

---
 common/draw_panel_gal.cpp                |  2 +
 common/gal/opengl/gl_builtin_shaders.cpp | 72 +++++++++++++-----
 common/gal/opengl/opengl_compositor.cpp  | 15 ++++
 common/gal/opengl/opengl_gal.cpp         | 95 +++++++++++++++++++++---
 common/gal/opengl/shader.cpp             | 19 ++++-
 common/view/view.cpp                     |  2 +
 include/gal/graphics_abstraction_layer.h |  2 +
 include/gal/opengl/opengl_compositor.h   |  2 +
 include/gal/opengl/opengl_gal.h          | 10 +++
 include/gal/opengl/shader.h              |  4 +
 qa/qa_utils/pcb_test_frame.cpp           |  2 +
 11 files changed, 193 insertions(+), 32 deletions(-)

diff --git a/common/draw_panel_gal.cpp b/common/draw_panel_gal.cpp
index ee555228a..7f622c3cf 100644
--- a/common/draw_panel_gal.cpp
+++ b/common/draw_panel_gal.cpp
@@ -220,6 +220,8 @@ void EDA_DRAW_PANEL_GAL::onPaint( wxPaintEvent& WXUNUSED( aEvent ) )
     {
         constexpr auto GAL_FALLBACK = GAL_TYPE_CAIRO;
 
+        printf("Exception occured: %s\n", err.what());
+
         if( m_edaFrame )
         {
             bool use_gal = m_edaFrame->SwitchCanvas( GAL_FALLBACK );
diff --git a/common/gal/opengl/gl_builtin_shaders.cpp b/common/gal/opengl/gl_builtin_shaders.cpp
index 409c71ede..39ae3b294 100644
--- a/common/gal/opengl/gl_builtin_shaders.cpp
+++ b/common/gal/opengl/gl_builtin_shaders.cpp
@@ -80,24 +80,56 @@ attribute vec4 attrShaderParams;
 varying vec4 shaderParams;
 varying vec2 circleCoords;
 uniform float worldPixelSize;
+uniform vec2 screenPixelSize;
+uniform float pixelSizeMultiplier;
 
-void computeLineCoords( bool posture, vec2 offset, vec2 texcoord, vec2 dir )
+float roundr( float f, float r )
 {
-    float w = length( offset );
+    return floor(f / r + 0.5) * r;
+}
+
+vec4 roundv( vec4 x, vec2 t)
+{
+    return vec4( roundr(x.x, t.x), roundr(x.y, t.y), x.z, x.w );
+}
+
+#define M_INV_SQRT2 0.707106781186547524400844362104849039
 
-    if( w > worldPixelSize )
+void computeLineCoords( bool posture, vec2 vs, vec2 vp, vec2 texcoord, vec2 dir, float lineWidth )
+{
+    float lineLength = length(vs);
+    float pixelWidth = roundr( lineWidth / worldPixelSize, 1.0 );
+    vec4 screenPos = gl_ModelViewProjectionMatrix * gl_Vertex + vec4(1, 1, 0, 0);
+    float aspect = lineWidth != 0.0 ? ( lineLength + lineWidth ) / lineWidth : 0.0;
+
+    if( pixelWidth < 1.0 )
+        pixelWidth = 1.0;
+
+    if ( pixelWidth > 1.0 || pixelSizeMultiplier > 1.0 )
     {
-        gl_Position = gl_ModelViewProjectionMatrix * vec4( gl_Vertex.x + offset.x, gl_Vertex.y + offset.y, gl_Vertex.z, gl_Vertex.w );
+        vec2 offsetNorm = (vs + vp) * pixelWidth / lineLength * 0.5;
+        vec4 screenOffset = vec4( offsetNorm.x  * screenPixelSize.x, -offsetNorm.y  * screenPixelSize.y , 0, 0);
+        vec4 adjust = vec4(-1, -1, 0, 0);
+
+        if( mod(pixelWidth, 2.0) > 0.9 )
+        {
+            adjust += vec4( screenPixelSize.x, screenPixelSize.y, 0, 0) * 0.5;
+        }
+
+        gl_Position = roundv(screenPos, screenPixelSize) + adjust + screenOffset;
+
         shaderParams[0] = SHADER_LINE_A;
-        gl_TexCoord[0].st = texcoord;
     }
-    else
-    {
-        vec4 pos = gl_Vertex;
-        pos.xy += ( posture ? dir : dir.yx ) * worldPixelSize / 2.0;
-        gl_Position = gl_ModelViewProjectionMatrix * pos;
+    else {
+        screenPos.xy += ( posture ? dir.xy : dir.yx ) * screenPixelSize / 2.0;
+        gl_Position = screenPos - vec4(1, 1, 0, 0);
         shaderParams[0] = SHADER_LINE_B;
     }
+
+    shaderParams[1] = aspect;
+
+    gl_TexCoord[0].st = vec2(aspect * texcoord.x, texcoord.y);
+    gl_FrontColor = gl_Color;
 }
 
 
@@ -108,23 +140,23 @@ void main()
     // Pass attributes to the fragment shader
     shaderParams = attrShaderParams;
 
-    float aspect = shaderParams.y;
+    float lineWidth = shaderParams.y;
     vec2 vs = shaderParams.zw;
     vec2 vp = vec2(-vs.y, vs.x);
     bool posture = abs( vs.x ) < abs(vs.y);
 
-    if(      mode == SHADER_LINE_A )
-        computeLineCoords( posture,  vp - vs, vec2( -aspect, -1 ), vec2( -1, 0 ) );
+    if( mode == SHADER_LINE_A )
+        computeLineCoords( posture,  -vs, vp, vec2( -1, -1 ), vec2( -1, 0 ), lineWidth );
     else if( mode == SHADER_LINE_B )
-        computeLineCoords( posture, -vp - vs, vec2( -aspect,  1 ), vec2(  1, 0 ) );
+        computeLineCoords( posture,  -vs, -vp, vec2( -1,  1 ), vec2(  1, 0 ), lineWidth );
     else if( mode == SHADER_LINE_C )
-        computeLineCoords( posture, -vp + vs, vec2(  aspect,  1 ), vec2(  1, 0 ) );
+        computeLineCoords( posture, vs, -vp, vec2(  1,  1 ), vec2(  1, 0 ), lineWidth );
     else if( mode == SHADER_LINE_D )
-        computeLineCoords( posture, -vp + vs, vec2( -aspect, -1 ), vec2(  1, 0 ) );
+        computeLineCoords( posture, vs, -vp, vec2( -1, -1 ), vec2(  1, 0 ), lineWidth );
     else if( mode == SHADER_LINE_E )
-        computeLineCoords( posture,  vp + vs, vec2( -aspect,  1 ), vec2( -1, 0 ) );
+        computeLineCoords( posture,  vs, vp, vec2( -1,  1 ), vec2( -1, 0 ), lineWidth );
     else if( mode == SHADER_LINE_F )
-        computeLineCoords( posture,  vp - vs, vec2(  aspect,  1 ), vec2( -1, 0 ) );
+        computeLineCoords( posture,  -vs, vp, vec2(  1,  1 ), vec2( -1, 0 ), lineWidth );
     else if( mode == SHADER_STROKED_CIRCLE ||
              mode == SHADER_FILLED_CIRCLE )
     {
@@ -153,14 +185,16 @@ void main()
             shaderParams[3] = shaderParams[3] / ( worldScale * lineWidth );
 
         gl_Position = ftransform();
+        gl_FrontColor = gl_Color;
     }
     else
     {
         // Pass through the coordinates like in the fixed pipeline
         gl_Position = ftransform();
+        gl_FrontColor = gl_Color;
+
     }
 
-    gl_FrontColor = gl_Color;
 }
 
 )SHADER_SOURCE";
diff --git a/common/gal/opengl/opengl_compositor.cpp b/common/gal/opengl/opengl_compositor.cpp
index 8b7e3d1a7..6fcd4b2e4 100644
--- a/common/gal/opengl/opengl_compositor.cpp
+++ b/common/gal/opengl/opengl_compositor.cpp
@@ -155,6 +155,8 @@ unsigned int OPENGL_COMPOSITOR::CreateBuffer( VECTOR2U aDimensions )
 
     int maxBuffers, maxTextureSize;
 
+    printf("createBuffer [%dx%d]\n", aDimensions.x, aDimensions.y );
+
     // Get the maximum number of buffers
     glGetIntegerv( GL_MAX_COLOR_ATTACHMENTS, (GLint*) &maxBuffers );
 
@@ -404,3 +406,16 @@ void OPENGL_COMPOSITOR::clean()
 
     m_initialized = false;
 }
+
+int OPENGL_COMPOSITOR::GetAntialiasSupersamplingFactor() const
+{
+    switch( m_currentAntialiasingMode )
+    {
+        case OPENGL_ANTIALIASING_MODE::SUPERSAMPLING_X2:
+            return 2;
+        case OPENGL_ANTIALIASING_MODE::SUPERSAMPLING_X4:
+            return 4;
+        default:
+            return 1;
+    }
+}
\ No newline at end of file
diff --git a/common/gal/opengl/opengl_gal.cpp b/common/gal/opengl/opengl_gal.cpp
index e3703bd6d..aaea54f9a 100644
--- a/common/gal/opengl/opengl_gal.cpp
+++ b/common/gal/opengl/opengl_gal.cpp
@@ -349,9 +349,18 @@ bool OPENGL_GAL::updatedGalDisplayOptions( const GAL_DISPLAY_OPTIONS& aOptions )
 double OPENGL_GAL::getWorldPixelSize() const
 {
     auto matrix = GetScreenWorldMatrix();
-    return std::min( std::abs( matrix.GetScale().x ), std::abs( matrix.GetScale().y ) );
+    auto rv = std::min( std::abs( matrix.GetScale().x ), std::abs( matrix.GetScale().y ) );
+    printf("wps %.10f\n", rv);
+    return rv;
 }
 
+VECTOR2D OPENGL_GAL::getScreenPixelSize() const
+{
+    printf("spx %d %d\n", screenSize.x, screenSize.y );
+    return VECTOR2D( 2.0 / (double) (screenSize.x), 2.0 / (double) (screenSize.y) );
+}
+
+
 void OPENGL_GAL::beginDrawing()
 {
 #ifdef __WXDEBUG__
@@ -460,6 +469,8 @@ void OPENGL_GAL::beginDrawing()
         GLint ufm_fontTexture       = shader->AddParameter( "fontTexture" );
         GLint ufm_fontTextureWidth  = shader->AddParameter( "fontTextureWidth" );
         ufm_worldPixelSize          = shader->AddParameter( "worldPixelSize" );
+        ufm_screenPixelSize         = shader->AddParameter( "screenPixelSize" );
+        ufm_pixelSizeMultiplier     = shader->AddParameter( "pixelSizeMultiplier" );
 
         shader->Use();
         shader->SetParameter( ufm_fontTexture,       (int) FONT_TEXTURE_UNIT  );
@@ -472,6 +483,9 @@ void OPENGL_GAL::beginDrawing()
 
     shader->Use();
     shader->SetParameter( ufm_worldPixelSize, (float) getWorldPixelSize() );
+    shader->SetParameter( ufm_screenPixelSize, getScreenPixelSize() );
+    double pixelSizeMultiplier = compositor->GetAntialiasSupersamplingFactor();
+    shader->SetParameter( ufm_pixelSizeMultiplier, (float) pixelSizeMultiplier );
     shader->Deactivate();
 
     // Something betreen BeginDrawing and EndDrawing seems to depend on
@@ -1639,36 +1653,39 @@ void OPENGL_GAL::drawLineQuad( const VECTOR2D& aStartPoint, const VECTOR2D& aEnd
     VECTOR2D vs ( startEndVector );
     float aspect;
 
-    if ( lineWidth == 0.0 ) // pixel-width line
+    //lineWidth = 2000000.0;
+
+/*    if ( lineWidth == 0.0 ) // pixel-wide line
     {
-        vs = vs.Resize( 0.5 );
-        aspect = ( lineLength + 1.0 );
+        vs = vs.Resize( 1.0 );
+        aspect = lineLength;
     }
     else
     {
-        vs = vs.Resize( 0.5 * lineWidth );
+        vs = vs.Resize( lineWidth );
         aspect = ( lineLength + lineWidth ) / lineWidth;
     }
+*/
 
     currentManager->Reserve( 6 );
 
     // Line width is maintained by the vertex shader
-    currentManager->Shader( SHADER_LINE_A, aspect, vs.x, vs.y );
+    currentManager->Shader( SHADER_LINE_A, lineWidth, vs.x, vs.y );
     currentManager->Vertex( aStartPoint, layerDepth );
 
-    currentManager->Shader( SHADER_LINE_B, aspect, vs.x, vs.y );
+    currentManager->Shader( SHADER_LINE_B, lineWidth, vs.x, vs.y );
     currentManager->Vertex( aStartPoint, layerDepth );
 
-    currentManager->Shader( SHADER_LINE_C, aspect, vs.x, vs.y );
+    currentManager->Shader( SHADER_LINE_C, lineWidth, vs.x, vs.y );
     currentManager->Vertex( aEndPoint, layerDepth );
 
-    currentManager->Shader( SHADER_LINE_D, aspect, vs.x, vs.y );
+    currentManager->Shader( SHADER_LINE_D, lineWidth, vs.x, vs.y );
     currentManager->Vertex( aEndPoint, layerDepth );
 
-    currentManager->Shader( SHADER_LINE_E, aspect, vs.x, vs.y );
+    currentManager->Shader( SHADER_LINE_E, lineWidth, vs.x, vs.y );
     currentManager->Vertex( aEndPoint, layerDepth );
 
-    currentManager->Shader( SHADER_LINE_F, aspect, vs.x, vs.y );
+    currentManager->Shader( SHADER_LINE_F, lineWidth, vs.x, vs.y );
     currentManager->Vertex( aStartPoint, layerDepth );
 }
 
@@ -2124,3 +2141,59 @@ void OPENGL_GAL::EnableDepthTest( bool aEnabled )
     nonCachedManager->EnableDepthTest( aEnabled );
     overlayManager->EnableDepthTest( aEnabled );
 }
+
+const VECTOR2D xform2( const MATRIX3x3D& minv, const VECTOR2D& p )
+{
+    auto t = minv * p;
+    return VECTOR2D((float)t.x, (float)t.y);
+}
+
+void OPENGL_GAL::ScreenSpaceQuad( const VECTOR2D& p0, const VECTOR2D& size, double w )
+{
+    
+    auto minv = screenWorldMatrix;
+
+    auto pa = xform2 ( minv, p0 );
+
+    auto pb = xform2 ( minv, p0 + VECTOR2D(size.x, 0 ));
+    auto pc = xform2 ( minv, p0 + VECTOR2D(size.x, size.y ));
+    auto pd = xform2 ( minv, p0 + VECTOR2D(0, size.y ));
+#if 0
+    //shader->Deactivate();
+        
+    currentManager->Reserve( 6 );
+    currentManager->Shader( SHADER_NONE );
+    currentManager->Color( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
+
+    currentManager->Shader( SHADER_NONE ); currentManager->Vertex( pa.x, pa.y, layerDepth );
+    currentManager->Shader( SHADER_NONE ); currentManager->Vertex( pb.x, pb.y, layerDepth );
+    currentManager->Shader( SHADER_NONE ); currentManager->Vertex( pc.x, pc.y, layerDepth );
+    currentManager->Shader( SHADER_NONE ); currentManager->Vertex( pa.x, pa.y, layerDepth );
+    currentManager->Shader( SHADER_NONE ); currentManager->Vertex( pc.x, pc.y, layerDepth );
+    currentManager->Shader( SHADER_NONE ); currentManager->Vertex( pd.x, pd.y, layerDepth );
+    shader->Use();
+#endif
+    SetLineWidth( w * getWorldPixelSize() );
+    drawLineQuad( pa, pc );
+
+    
+}
+
+double roundr( double f, double r )
+{
+    return floor(f / r + 0.5) * r;
+}
+
+void OPENGL_GAL::ComputeWorldScreenMatrix()
+{
+    auto pixelSize = worldScale;
+
+    printf("OVER worldPixelSize: %.10f\n", pixelSize );
+
+    lookAtPoint.x = roundr( lookAtPoint.x, pixelSize );
+    lookAtPoint.y = roundr( lookAtPoint.y, pixelSize );
+
+    GAL::ComputeWorldScreenMatrix();
+
+
+}
diff --git a/common/gal/opengl/shader.cpp b/common/gal/opengl/shader.cpp
index 57fcd7e12..9b611b10e 100644
--- a/common/gal/opengl/shader.cpp
+++ b/common/gal/opengl/shader.cpp
@@ -129,7 +129,8 @@ int SHADER::AddParameter( const std::string& aParameterName )
     if( location >= 0 )
         parameterLocation.push_back( location );
     else
-        throw std::runtime_error( "Could not find shader uniform: " + aParameterName );
+        return -1;
+        //throw std::runtime_error( "Could not find shader uniform: " + aParameterName );
 
     return parameterLocation.size() - 1;
 }
@@ -137,6 +138,8 @@ int SHADER::AddParameter( const std::string& aParameterName )
 
 void SHADER::SetParameter( int parameterNumber, float value ) const
 {
+    if (parameterNumber< 0)
+        return;
     assert( (unsigned) parameterNumber < parameterLocation.size() );
 
     glUniform1f( parameterLocation[parameterNumber], value );
@@ -145,6 +148,8 @@ void SHADER::SetParameter( int parameterNumber, float value ) const
 
 void SHADER::SetParameter( int parameterNumber, int value ) const
 {
+    if (parameterNumber< 0)
+        return;
     assert( (unsigned) parameterNumber < parameterLocation.size() );
 
     glUniform1i( parameterLocation[parameterNumber], value );
@@ -152,11 +157,21 @@ void SHADER::SetParameter( int parameterNumber, int value ) const
 
 void SHADER::SetParameter( int parameterNumber, float f0, float f1, float f2, float f3 ) const
 {
-    assert( (unsigned)parameterNumber < parameterLocation.size() );
+        if (parameterNumber< 0)
+        return;
+assert( (unsigned)parameterNumber < parameterLocation.size() );
     float arr[4] = { f0, f1, f2, f3 };
     glUniform4fv( parameterLocation[parameterNumber], 1, arr );
 }
 
+void SHADER::SetParameter( int aParameterNumber, const VECTOR2D& aValue ) const
+{
+      if (aParameterNumber< 0)
+        return;
+  assert( (unsigned)aParameterNumber < parameterLocation.size() );
+    glUniform2f( parameterLocation[aParameterNumber], aValue.x, aValue.y );
+}
+
 
 int SHADER::GetAttribute( const std::string& aAttributeName ) const
 {
diff --git a/common/view/view.cpp b/common/view/view.cpp
index fe581b3a9..ab95e3cbb 100644
--- a/common/view/view.cpp
+++ b/common/view/view.cpp
@@ -586,6 +586,8 @@ void VIEW::SetScale( double aScale, const VECTOR2D& aAnchor )
     else
         m_scale = aScale;
 
+    printf("setscale %.10f %.10f %.10f\n", aScale, aAnchor.x, aAnchor.y );
+
     m_gal->SetZoomFactor( m_scale );
     m_gal->ComputeWorldScreenMatrix();
 
diff --git a/include/gal/graphics_abstraction_layer.h b/include/gal/graphics_abstraction_layer.h
index c266c628d..afe94a7e6 100644
--- a/include/gal/graphics_abstraction_layer.h
+++ b/include/gal/graphics_abstraction_layer.h
@@ -955,6 +955,8 @@ public:
      */
     VECTOR2D GetGridPoint( const VECTOR2D& aPoint ) const;
 
+    virtual void ScreenSpaceQuad( const VECTOR2D& p0, const VECTOR2D& size, double w ) {};
+
     /**
      * @brief Compute the point position in world coordinates from given screen coordinates.
      *
diff --git a/include/gal/opengl/opengl_compositor.h b/include/gal/opengl/opengl_compositor.h
index c549209e1..936f487a1 100644
--- a/include/gal/opengl/opengl_compositor.h
+++ b/include/gal/opengl/opengl_compositor.h
@@ -91,6 +91,8 @@ public:
     void SetAntialiasingMode( OPENGL_ANTIALIASING_MODE aMode ); // clears all buffers
     OPENGL_ANTIALIASING_MODE GetAntialiasingMode() const;
 
+    int GetAntialiasSupersamplingFactor() const;
+
 protected:
     // Buffers are simply textures storing a result of certain target rendering.
     typedef struct
diff --git a/include/gal/opengl/opengl_gal.h b/include/gal/opengl/opengl_gal.h
index 250e84ee7..085bacf02 100644
--- a/include/gal/opengl/opengl_gal.h
+++ b/include/gal/opengl/opengl_gal.h
@@ -236,6 +236,11 @@ public:
     /// @copydoc GAL::SetNegativeDrawMode()
     virtual void SetNegativeDrawMode( bool aSetting ) override {}
 
+    virtual void ScreenSpaceQuad( const VECTOR2D& p0, const VECTOR2D& size, double w ) override;
+
+    virtual void ComputeWorldScreenMatrix() override;
+
+
     // -------
     // Cursor
     // -------
@@ -322,6 +327,8 @@ private:
     bool                    isContextLocked;            ///< Used for assertion checking
     int                     lockClientCookie;
     GLint                   ufm_worldPixelSize;
+    GLint                   ufm_screenPixelSize;
+    GLint                   ufm_pixelSizeMultiplier;
 
     std::unique_ptr<GL_BITMAP_CACHE>         bitmapCache;
 
@@ -477,6 +484,9 @@ private:
 
     double getWorldPixelSize() const;
 
+    VECTOR2D getScreenPixelSize() const;
+
+
     /**
      * @brief Basic OpenGL initialization.
      */
diff --git a/include/gal/opengl/shader.h b/include/gal/opengl/shader.h
index c794ac894..ff530fb0f 100644
--- a/include/gal/opengl/shader.h
+++ b/include/gal/opengl/shader.h
@@ -31,6 +31,8 @@
 
 #include <GL/glew.h>
 
+#include <math/vector2d.h>
+
 #include <string>
 #include <deque>
 
@@ -182,6 +184,8 @@ public:
      */
     void SetParameter( int aParameterNumber, float aValue ) const;
     void SetParameter( int aParameterNumber, int aValue ) const;
+    void SetParameter( int aParameterNumber, const VECTOR2D& aValue ) const;
+    //void SetParameter( int aParameterNumber, const MATRIX3x3D& aValue ) const;
     void SetParameter( int aParameterNumber, float f0, float f1, float f2, float f3 ) const;
 
     /**
diff --git a/qa/qa_utils/pcb_test_frame.cpp b/qa/qa_utils/pcb_test_frame.cpp
index 6235d67ab..3edc843ae 100644
--- a/qa/qa_utils/pcb_test_frame.cpp
+++ b/qa/qa_utils/pcb_test_frame.cpp
@@ -180,6 +180,8 @@ PCB_TEST_FRAME::PCB_TEST_FRAME( wxFrame* frame, const wxString& title, const wxP
 
     KIGFX::GAL_DISPLAY_OPTIONS options;
 
+    options.gl_antialiasing_mode = KIGFX::OPENGL_ANTIALIASING_MODE::NONE;
+
     m_galPanel.reset( new PCB_DRAW_PANEL_GAL( this, -1, wxPoint( 0,
                             0 ), wxDefaultSize, options, EDA_DRAW_PANEL_GAL::GAL_TYPE_CAIRO ) );
 
-- 
2.17.1

>From ac41f86f092a7784f41316e864a9e72e6429a0de Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tomasz=20W=C5=82ostowski?= <tomasz.wlostowski@xxxxxxx>
Date: Sun, 10 Feb 2019 03:29:25 +0100
Subject: [PATCH 3/3] Cleanup of pixel alignment patches

---
 common/draw_panel_gal.cpp                |  2 -
 common/gal/cairo/cairo_compositor.cpp    |  1 -
 common/gal/cairo/cairo_gal.cpp           | 13 -----
 common/gal/opengl/opengl_compositor.cpp  |  4 +-
 common/gal/opengl/opengl_gal.cpp         | 60 ++----------------------
 common/gal/opengl/shader.cpp             | 15 ++----
 common/view/view.cpp                     |  2 -
 include/gal/cairo/cairo_gal.h            |  2 +-
 include/gal/graphics_abstraction_layer.h |  3 --
 include/gal/opengl/opengl_gal.h          |  3 --
 include/gal/opengl/shader.h              |  1 -
 pcbnew/pcb_painter.cpp                   |  3 +-
 12 files changed, 9 insertions(+), 100 deletions(-)

diff --git a/common/draw_panel_gal.cpp b/common/draw_panel_gal.cpp
index 7f622c3cf..ee555228a 100644
--- a/common/draw_panel_gal.cpp
+++ b/common/draw_panel_gal.cpp
@@ -220,8 +220,6 @@ void EDA_DRAW_PANEL_GAL::onPaint( wxPaintEvent& WXUNUSED( aEvent ) )
     {
         constexpr auto GAL_FALLBACK = GAL_TYPE_CAIRO;
 
-        printf("Exception occured: %s\n", err.what());
-
         if( m_edaFrame )
         {
             bool use_gal = m_edaFrame->SwitchCanvas( GAL_FALLBACK );
diff --git a/common/gal/cairo/cairo_compositor.cpp b/common/gal/cairo/cairo_compositor.cpp
index cca06c368..b48655397 100644
--- a/common/gal/cairo/cairo_compositor.cpp
+++ b/common/gal/cairo/cairo_compositor.cpp
@@ -109,7 +109,6 @@ unsigned int CAIRO_COMPOSITOR::CreateBuffer()
 #endif /* __WXDEBUG__ */
 
     // Set default settings for the buffer
-    printf("setAntialias: %d\n", m_currentAntialiasingMode );
     cairo_set_antialias( context,  m_currentAntialiasingMode );
 
     // Use the same transformation matrix as the main context
diff --git a/common/gal/cairo/cairo_gal.cpp b/common/gal/cairo/cairo_gal.cpp
index 3dc7d849d..ec1245616 100644
--- a/common/gal/cairo/cairo_gal.cpp
+++ b/common/gal/cairo/cairo_gal.cpp
@@ -130,11 +130,6 @@ const VECTOR2D CAIRO_GAL_BASE::roundp( const VECTOR2D& v )
 }
 
 
-//static const VECTOR2D floorp( const VECTOR2D& v )
-//{
-    //return VECTOR2D( floor( v.x ), floor( v.y) );
-//}
-
 void CAIRO_GAL_BASE::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
 {
     syncLineWidth();
@@ -232,7 +227,6 @@ void CAIRO_GAL_BASE::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius )
     cairo_new_sub_path( currentContext );
     cairo_arc( currentContext, c.x, c.y, r, 0.0, 2 * M_PI- 0.1 );
     cairo_close_path( currentContext );
-    printf("circle fill: %.1f %.1f %.1f %.10f %.10f %10f %.10f %d stroke : %d %.1f %.1f %.1f %.1f\n", c.x, c.y, r, aRadius, xform( aRadius ), currentWorld2Screen.xx, currentWorld2Screen.yy, !!isFillEnabled, !!isStrokeEnabled, fillColor.r, fillColor.g, fillColor.b, fillColor.a );
     flushPath();
     isElementAdded = true;
 }
@@ -258,7 +252,6 @@ void CAIRO_GAL_BASE::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, doub
 
     if( isFillEnabled )     // Draw the filled area of the shape, before drawing the outline itself
     {
-        //double pen_size = GetLineWidth();
         auto fgcolor = GetStrokeColor();
         SetStrokeColor( GetFillColor() );
 
@@ -271,7 +264,6 @@ void CAIRO_GAL_BASE::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, doub
         cairo_line_to( currentContext, endPointS.x, endPointS.y );
         cairo_close_path( currentContext );
         flushPath();
-       // SetLineWidth( pen_size );
         SetStrokeColor( fgcolor );
     }
 
@@ -884,11 +876,6 @@ void CAIRO_GAL_BASE::resetContext()
                        worldScreenMatrix.m_data[1][1], worldScreenMatrix.m_data[0][2],
                        worldScreenMatrix.m_data[1][2] );
 
-    //printf("resetContext %.5f %.5f %.5f\n", cairoWorldScreenMatrix.xx, cairoWorldScreenMatrix.xy, cairoWorldScreenMatrix.x0 );
-    //printf("             %.5f %.5f %.5f\n", cairoWorldScreenMatrix.yx, cairoWorldScreenMatrix.yy, cairoWorldScreenMatrix.y0 );
-
-    //cairo_set_matrix( context, &cairoWorldScreenMatrix );
-
     // we work in screen-space coordinates and do the transforms outside.
     cairo_identity_matrix( context );
 
diff --git a/common/gal/opengl/opengl_compositor.cpp b/common/gal/opengl/opengl_compositor.cpp
index 6fcd4b2e4..44aaeda1c 100644
--- a/common/gal/opengl/opengl_compositor.cpp
+++ b/common/gal/opengl/opengl_compositor.cpp
@@ -155,8 +155,6 @@ unsigned int OPENGL_COMPOSITOR::CreateBuffer( VECTOR2U aDimensions )
 
     int maxBuffers, maxTextureSize;
 
-    printf("createBuffer [%dx%d]\n", aDimensions.x, aDimensions.y );
-
     // Get the maximum number of buffers
     glGetIntegerv( GL_MAX_COLOR_ATTACHMENTS, (GLint*) &maxBuffers );
 
@@ -418,4 +416,4 @@ int OPENGL_COMPOSITOR::GetAntialiasSupersamplingFactor() const
         default:
             return 1;
     }
-}
\ No newline at end of file
+}
diff --git a/common/gal/opengl/opengl_gal.cpp b/common/gal/opengl/opengl_gal.cpp
index aaea54f9a..e10906f8f 100644
--- a/common/gal/opengl/opengl_gal.cpp
+++ b/common/gal/opengl/opengl_gal.cpp
@@ -350,13 +350,11 @@ double OPENGL_GAL::getWorldPixelSize() const
 {
     auto matrix = GetScreenWorldMatrix();
     auto rv = std::min( std::abs( matrix.GetScale().x ), std::abs( matrix.GetScale().y ) );
-    printf("wps %.10f\n", rv);
     return rv;
 }
 
 VECTOR2D OPENGL_GAL::getScreenPixelSize() const
 {
-    printf("spx %d %d\n", screenSize.x, screenSize.y );
     return VECTOR2D( 2.0 / (double) (screenSize.x), 2.0 / (double) (screenSize.y) );
 }
 
@@ -1653,20 +1651,6 @@ void OPENGL_GAL::drawLineQuad( const VECTOR2D& aStartPoint, const VECTOR2D& aEnd
     VECTOR2D vs ( startEndVector );
     float aspect;
 
-    //lineWidth = 2000000.0;
-
-/*    if ( lineWidth == 0.0 ) // pixel-wide line
-    {
-        vs = vs.Resize( 1.0 );
-        aspect = lineLength;
-    }
-    else
-    {
-        vs = vs.Resize( lineWidth );
-        aspect = ( lineLength + lineWidth ) / lineWidth;
-    }
-*/
-
     currentManager->Reserve( 6 );
 
     // Line width is maintained by the vertex shader
@@ -2142,58 +2126,20 @@ void OPENGL_GAL::EnableDepthTest( bool aEnabled )
     overlayManager->EnableDepthTest( aEnabled );
 }
 
-const VECTOR2D xform2( const MATRIX3x3D& minv, const VECTOR2D& p )
-{
-    auto t = minv * p;
-    return VECTOR2D((float)t.x, (float)t.y);
-}
-
-void OPENGL_GAL::ScreenSpaceQuad( const VECTOR2D& p0, const VECTOR2D& size, double w )
-{
-    
-    auto minv = screenWorldMatrix;
-
-    auto pa = xform2 ( minv, p0 );
-
-    auto pb = xform2 ( minv, p0 + VECTOR2D(size.x, 0 ));
-    auto pc = xform2 ( minv, p0 + VECTOR2D(size.x, size.y ));
-    auto pd = xform2 ( minv, p0 + VECTOR2D(0, size.y ));
-#if 0
-    //shader->Deactivate();
-        
-    currentManager->Reserve( 6 );
-    currentManager->Shader( SHADER_NONE );
-    currentManager->Color( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
 
-    currentManager->Shader( SHADER_NONE ); currentManager->Vertex( pa.x, pa.y, layerDepth );
-    currentManager->Shader( SHADER_NONE ); currentManager->Vertex( pb.x, pb.y, layerDepth );
-    currentManager->Shader( SHADER_NONE ); currentManager->Vertex( pc.x, pc.y, layerDepth );
-    currentManager->Shader( SHADER_NONE ); currentManager->Vertex( pa.x, pa.y, layerDepth );
-    currentManager->Shader( SHADER_NONE ); currentManager->Vertex( pc.x, pc.y, layerDepth );
-    currentManager->Shader( SHADER_NONE ); currentManager->Vertex( pd.x, pd.y, layerDepth );
-    shader->Use();
-#endif
-    SetLineWidth( w * getWorldPixelSize() );
-    drawLineQuad( pa, pc );
-
-    
-}
-
-double roundr( double f, double r )
+static double roundr( double f, double r )
 {
     return floor(f / r + 0.5) * r;
 }
 
+
 void OPENGL_GAL::ComputeWorldScreenMatrix()
 {
     auto pixelSize = worldScale;
 
-    printf("OVER worldPixelSize: %.10f\n", pixelSize );
-
     lookAtPoint.x = roundr( lookAtPoint.x, pixelSize );
     lookAtPoint.y = roundr( lookAtPoint.y, pixelSize );
 
     GAL::ComputeWorldScreenMatrix();
-
-
 }
+
diff --git a/common/gal/opengl/shader.cpp b/common/gal/opengl/shader.cpp
index 9b611b10e..d78379c36 100644
--- a/common/gal/opengl/shader.cpp
+++ b/common/gal/opengl/shader.cpp
@@ -129,8 +129,7 @@ int SHADER::AddParameter( const std::string& aParameterName )
     if( location >= 0 )
         parameterLocation.push_back( location );
     else
-        return -1;
-        //throw std::runtime_error( "Could not find shader uniform: " + aParameterName );
+        throw std::runtime_error( "Could not find shader uniform: " + aParameterName );
 
     return parameterLocation.size() - 1;
 }
@@ -138,8 +137,6 @@ int SHADER::AddParameter( const std::string& aParameterName )
 
 void SHADER::SetParameter( int parameterNumber, float value ) const
 {
-    if (parameterNumber< 0)
-        return;
     assert( (unsigned) parameterNumber < parameterLocation.size() );
 
     glUniform1f( parameterLocation[parameterNumber], value );
@@ -148,8 +145,6 @@ void SHADER::SetParameter( int parameterNumber, float value ) const
 
 void SHADER::SetParameter( int parameterNumber, int value ) const
 {
-    if (parameterNumber< 0)
-        return;
     assert( (unsigned) parameterNumber < parameterLocation.size() );
 
     glUniform1i( parameterLocation[parameterNumber], value );
@@ -157,18 +152,14 @@ void SHADER::SetParameter( int parameterNumber, int value ) const
 
 void SHADER::SetParameter( int parameterNumber, float f0, float f1, float f2, float f3 ) const
 {
-        if (parameterNumber< 0)
-        return;
-assert( (unsigned)parameterNumber < parameterLocation.size() );
+    assert( (unsigned)parameterNumber < parameterLocation.size() );
     float arr[4] = { f0, f1, f2, f3 };
     glUniform4fv( parameterLocation[parameterNumber], 1, arr );
 }
 
 void SHADER::SetParameter( int aParameterNumber, const VECTOR2D& aValue ) const
 {
-      if (aParameterNumber< 0)
-        return;
-  assert( (unsigned)aParameterNumber < parameterLocation.size() );
+    assert( (unsigned)aParameterNumber < parameterLocation.size() );
     glUniform2f( parameterLocation[aParameterNumber], aValue.x, aValue.y );
 }
 
diff --git a/common/view/view.cpp b/common/view/view.cpp
index ab95e3cbb..fe581b3a9 100644
--- a/common/view/view.cpp
+++ b/common/view/view.cpp
@@ -586,8 +586,6 @@ void VIEW::SetScale( double aScale, const VECTOR2D& aAnchor )
     else
         m_scale = aScale;
 
-    printf("setscale %.10f %.10f %.10f\n", aScale, aAnchor.x, aAnchor.y );
-
     m_gal->SetZoomFactor( m_scale );
     m_gal->ComputeWorldScreenMatrix();
 
diff --git a/include/gal/cairo/cairo_gal.h b/include/gal/cairo/cairo_gal.h
index c845dfa67..9eb55eadd 100644
--- a/include/gal/cairo/cairo_gal.h
+++ b/include/gal/cairo/cairo_gal.h
@@ -232,7 +232,7 @@ protected:
     void resetContext();
 
     virtual void drawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) override;
-    virtual void drawGridPoint( const VECTOR2D& aPoint, double aSize ) override;
+    virtual void drawGridPoint( const VECTOR2D& aPoint, double aSize );
 
     /// Super class definition
     typedef GAL super;
diff --git a/include/gal/graphics_abstraction_layer.h b/include/gal/graphics_abstraction_layer.h
index afe94a7e6..0cb2ae493 100644
--- a/include/gal/graphics_abstraction_layer.h
+++ b/include/gal/graphics_abstraction_layer.h
@@ -955,8 +955,6 @@ public:
      */
     VECTOR2D GetGridPoint( const VECTOR2D& aPoint ) const;
 
-    virtual void ScreenSpaceQuad( const VECTOR2D& p0, const VECTOR2D& size, double w ) {};
-
     /**
      * @brief Compute the point position in world coordinates from given screen coordinates.
      *
@@ -1140,7 +1138,6 @@ protected:
      * @param aEndPoint is the end point of the line.
      */
     virtual void drawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) {};
-    virtual void drawGridPoint( const VECTOR2D& aPoint, double aSize ) {};
 
     /// Possible depth range
     static const int MIN_DEPTH;
diff --git a/include/gal/opengl/opengl_gal.h b/include/gal/opengl/opengl_gal.h
index 085bacf02..d14fd0921 100644
--- a/include/gal/opengl/opengl_gal.h
+++ b/include/gal/opengl/opengl_gal.h
@@ -236,11 +236,8 @@ public:
     /// @copydoc GAL::SetNegativeDrawMode()
     virtual void SetNegativeDrawMode( bool aSetting ) override {}
 
-    virtual void ScreenSpaceQuad( const VECTOR2D& p0, const VECTOR2D& size, double w ) override;
-
     virtual void ComputeWorldScreenMatrix() override;
 
-
     // -------
     // Cursor
     // -------
diff --git a/include/gal/opengl/shader.h b/include/gal/opengl/shader.h
index ff530fb0f..819afd49c 100644
--- a/include/gal/opengl/shader.h
+++ b/include/gal/opengl/shader.h
@@ -185,7 +185,6 @@ public:
     void SetParameter( int aParameterNumber, float aValue ) const;
     void SetParameter( int aParameterNumber, int aValue ) const;
     void SetParameter( int aParameterNumber, const VECTOR2D& aValue ) const;
-    //void SetParameter( int aParameterNumber, const MATRIX3x3D& aValue ) const;
     void SetParameter( int aParameterNumber, float f0, float f1, float f2, float f3 ) const;
 
     /**
diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp
index 018e50810..8814249e7 100644
--- a/pcbnew/pcb_painter.cpp
+++ b/pcbnew/pcb_painter.cpp
@@ -1148,13 +1148,12 @@ void PCB_PAINTER::draw( const ZONE_CONTAINER* aZone, int aLayer )
 
         // Set up drawing options
         m_gal->SetFillColor( color );
-        m_gal->SetStrokeColor( color );
         m_gal->SetLineWidth( aZone->GetMinThickness() );
 
         if( displayMode == PCB_RENDER_SETTINGS::DZ_SHOW_FILLED )
         {
             m_gal->SetIsFill( true );
-            m_gal->SetIsStroke( false );
+            m_gal->SetIsStroke( true );
         }
         else if( displayMode == PCB_RENDER_SETTINGS::DZ_SHOW_OUTLINED )
         {
-- 
2.17.1


Follow ups