From c5a3c1082a5d8518cda8a1d02331414f60aa90be Mon Sep 17 00:00:00 2001
From: Maciej Suminski <maciej.suminski@cern.ch>
Date: Tue, 25 Feb 2014 14:28:09 +0100
Subject: [PATCH] Removed a few RecacheAllItems() calls, some of them changed
 to specific type recaching (using TYPE_COLLECTOR & VIEW_ITEM::ViewUpdate() ).
 Removed OPENGL_GAL::SetStrokeColor().

---
 common/drawpanel_gal.cpp                  |  3 --
 common/gal/cairo/cairo_gal.cpp            |  5 ++-
 common/gal/opengl/opengl_gal.cpp          | 42 +++++++++++++++--------
 include/gal/opengl/opengl_gal.h           |  9 +----
 pcbnew/basepcbframe.cpp                   |  9 ++++-
 pcbnew/dialogs/dialog_display_options.cpp |  5 +--
 pcbnew/dialogs/dialog_general_options.cpp | 24 ++++++++-----
 pcbnew/pcbframe.cpp                       | 10 +-----
 8 files changed, 58 insertions(+), 49 deletions(-)

diff --git a/common/drawpanel_gal.cpp b/common/drawpanel_gal.cpp
index 6a7e4f9d6a..947e854fa6 100644
--- a/common/drawpanel_gal.cpp
+++ b/common/drawpanel_gal.cpp
@@ -226,10 +226,7 @@ void EDA_DRAW_PANEL_GAL::SwitchBackend( GalType aGalType )
         m_painter->SetGAL( m_gal );
 
     if( m_view )
-    {
         m_view->SetGAL( m_gal );
-        m_view->RecacheAllItems( true );
-    }
 
     m_currentGal = aGalType;
     m_pendingRefresh = false;
diff --git a/common/gal/cairo/cairo_gal.cpp b/common/gal/cairo/cairo_gal.cpp
index 5d1d4f6cd7..790fb06049 100644
--- a/common/gal/cairo/cairo_gal.cpp
+++ b/common/gal/cairo/cairo_gal.cpp
@@ -77,6 +77,8 @@ CAIRO_GAL::CAIRO_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener,
 
     // Allocate memory for pixel storage
     allocateBitmaps();
+
+    initSurface();
 }
 
 
@@ -954,7 +956,8 @@ void CAIRO_GAL::deleteBitmaps()
 
 void CAIRO_GAL::initSurface()
 {
-    wxASSERT( !isInitialized );
+    if( isInitialized )
+        return;
 
     // Create the Cairo surface
     surface = cairo_image_surface_create_for_data( (unsigned char*) bitmapBuffer, GAL_FORMAT,
diff --git a/common/gal/opengl/opengl_gal.cpp b/common/gal/opengl/opengl_gal.cpp
index 84b8225ac3..5eb63c31c4 100644
--- a/common/gal/opengl/opengl_gal.cpp
+++ b/common/gal/opengl/opengl_gal.cpp
@@ -101,6 +101,8 @@ OPENGL_GAL::OPENGL_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener,
     }
 
     gluTessProperty( tesselator, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE );
+
+    currentManager = &nonCachedManager;
 }
 
 
@@ -248,6 +250,8 @@ void OPENGL_GAL::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoin
     const VECTOR2D  startEndVector = aEndPoint - aStartPoint;
     double          lineAngle = startEndVector.Angle();
 
+    currentManager->Color( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
+
     drawLineQuad( aStartPoint, aEndPoint );
 
     // Line caps
@@ -468,6 +472,8 @@ void OPENGL_GAL::DrawPolyline( std::deque<VECTOR2D>& aPointList )
     if( aPointList.empty() )
         return;
 
+    currentManager->Color( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
+
     std::deque<VECTOR2D>::const_iterator it = aPointList.begin();
 
     // Start from the second point
@@ -590,15 +596,6 @@ void OPENGL_GAL::ClearScreen()
 }
 
 
-void OPENGL_GAL::SetStrokeColor( const COLOR4D& aColor )
-{
-    strokeColor = aColor;
-
-    // This is the default drawing color
-    currentManager->Color( aColor.r, aColor.g, aColor.b, aColor.a );
-}
-
-
 void OPENGL_GAL::Transform( const MATRIX3x3D& aTransformation )
 {
     GLdouble matrixData[16] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
@@ -795,8 +792,23 @@ void OPENGL_GAL::drawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEnd
 }
 
 
-inline void OPENGL_GAL::drawLineQuad( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
+void OPENGL_GAL::drawLineQuad( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
 {
+    /* Helper drawing:                   ____--- v3       ^
+     *                           ____---- ...   \          \
+     *                   ____----      ...       \   end    \
+     *     v1    ____----           ...    ____----          \ width
+     *       ----                ...___----        \          \
+     *       \             ___...--                 \          v
+     *        \    ____----...                ____---- v2
+     *         ----     ...           ____----
+     *  start   \    ...      ____----
+     *           \... ____----
+     *            ----
+     *            v0
+     * dots mark triangles' hypotenuses
+     */
+
     VECTOR2D startEndVector = aEndPoint - aStartPoint;
     double   lineLength     = startEndVector.EuclideanNorm();
     double   scale          = 0.5 * lineWidth / lineLength;
@@ -854,8 +866,8 @@ void OPENGL_GAL::drawFilledSemiCircle( const VECTOR2D& aCenterPoint, double aRad
 
     /* Draw a triangle that contains the semicircle, then shade it to leave only
      * the semicircle. Parameters given to setShader are indices of the triangle's vertices
-     *  (if you want to understand more, check the vertex shader source [shader.vert]).
-     *  Shader uses this coordinates to determine if fragments are inside the semicircle or not.
+     * (if you want to understand more, check the vertex shader source [shader.vert]).
+     * Shader uses these coordinates to determine if fragments are inside the semicircle or not.
      *       v2
      *       /\
      *      /__\
@@ -885,9 +897,9 @@ void OPENGL_GAL::drawStrokedSemiCircle( const VECTOR2D& aCenterPoint, double aRa
 
     /* Draw a triangle that contains the semicircle, then shade it to leave only
      * the semicircle. Parameters given to setShader are indices of the triangle's vertices
-     *  (if you want to understand more, check the vertex shader source [shader.vert]), the
-     *  radius and the line width. Shader uses this coordinates to determine if fragments are
-     *  inside the semicircle or not.
+     * (if you want to understand more, check the vertex shader source [shader.vert]), the
+     * radius and the line width. Shader uses these coordinates to determine if fragments are
+     * inside the semicircle or not.
      *       v2
      *       /\
      *      /__\
diff --git a/include/gal/opengl/opengl_gal.h b/include/gal/opengl/opengl_gal.h
index 7a1879d085..d5c97aada9 100644
--- a/include/gal/opengl/opengl_gal.h
+++ b/include/gal/opengl/opengl_gal.h
@@ -145,13 +145,6 @@ public:
     /// @copydoc GAL::ClearScreen()
     virtual void ClearScreen();
 
-    // -----------------
-    // Attribute setting
-    // -----------------
-
-    /// @copydoc GAL::SetStrokeColor()
-    virtual void SetStrokeColor( const COLOR4D& aColor );
-
     // --------------
     // Transformation
     // --------------
@@ -311,7 +304,7 @@ private:
      * @param aStartPoint is the start point of the line.
      * @param aEndPoint is the end point of the line.
      */
-    inline void drawLineQuad( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint );
+    void drawLineQuad( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint );
 
     /**
      * @brief Draw a semicircle. Depending on settings (isStrokeEnabled & isFilledEnabled) it runs
diff --git a/pcbnew/basepcbframe.cpp b/pcbnew/basepcbframe.cpp
index 858aa40c0e..8b670883f9 100644
--- a/pcbnew/basepcbframe.cpp
+++ b/pcbnew/basepcbframe.cpp
@@ -443,7 +443,14 @@ void PCB_BASE_FRAME::OnTogglePadDrawMode( wxCommandEvent& aEvent )
     KIGFX::PCB_RENDER_SETTINGS* settings =
             static_cast<KIGFX::PCB_RENDER_SETTINGS*> ( painter->GetSettings() );
     settings->LoadDisplayOptions( DisplayOpt );
-    GetGalCanvas()->GetView()->RecacheAllItems( true );
+
+    // Update pads
+    BOARD* board = GetBoard();
+    for( MODULE* module = board->m_Modules; module; module = module->Next() )
+    {
+        for( D_PAD* pad = module->Pads(); pad; pad = pad->Next() )
+            pad->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
+    }
 
     m_canvas->Refresh();
 }
diff --git a/pcbnew/dialogs/dialog_display_options.cpp b/pcbnew/dialogs/dialog_display_options.cpp
index 0aa91d1302..1e140d94d9 100644
--- a/pcbnew/dialogs/dialog_display_options.cpp
+++ b/pcbnew/dialogs/dialog_display_options.cpp
@@ -177,10 +177,7 @@ void DIALOG_DISPLAY_OPTIONS::OnOkClick(wxCommandEvent& event)
     settings->LoadDisplayOptions( DisplayOpt );
     view->RecacheAllItems( true );
 
-    if( m_Parent->IsGalCanvasActive() )
-        m_Parent->GetGalCanvas()->Refresh();
-    else
-        m_Parent->GetCanvas()->Refresh();
+    m_Parent->GetCanvas()->Refresh();
 
     EndModal( 1 );
 }
diff --git a/pcbnew/dialogs/dialog_general_options.cpp b/pcbnew/dialogs/dialog_general_options.cpp
index c01e433f3e..c4ccd1ddbf 100644
--- a/pcbnew/dialogs/dialog_general_options.cpp
+++ b/pcbnew/dialogs/dialog_general_options.cpp
@@ -40,6 +40,7 @@
 #include <kicad_string.h>
 #include <pcbnew_id.h>
 #include <class_board.h>
+#include <collectors.h>
 
 #include <dialog_general_options.h>
 #include <class_drawpanel_gal.h>
@@ -157,7 +158,7 @@ void PCB_EDIT_FRAME::OnSelectOptionToolbar( wxCommandEvent& event )
             static_cast<KIGFX::PCB_PAINTER*> ( GetGalCanvas()->GetView()->GetPainter() );
     KIGFX::PCB_RENDER_SETTINGS* settings =
             static_cast<KIGFX::PCB_RENDER_SETTINGS*> ( painter->GetSettings() );
-    bool recache = false;
+    KICAD_T updateType = EOT;
 
     switch( id )
     {
@@ -192,31 +193,31 @@ void PCB_EDIT_FRAME::OnSelectOptionToolbar( wxCommandEvent& event )
 
     case ID_TB_OPTIONS_SHOW_ZONES:
         DisplayOpt.DisplayZonesMode = 0;
-        recache = true;
+        updateType = PCB_ZONE_T;
         m_canvas->Refresh();
         break;
 
     case ID_TB_OPTIONS_SHOW_ZONES_DISABLE:
         DisplayOpt.DisplayZonesMode = 1;
-        recache = true;
+        updateType = PCB_ZONE_T;
         m_canvas->Refresh();
         break;
 
     case ID_TB_OPTIONS_SHOW_ZONES_OUTLINES_ONLY:
         DisplayOpt.DisplayZonesMode = 2;
-        recache = true;
+        updateType = PCB_ZONE_T;
         m_canvas->Refresh();
         break;
 
     case ID_TB_OPTIONS_SHOW_VIAS_SKETCH:
         m_DisplayViaFill = DisplayOpt.DisplayViaFill = !state;
-        recache = true;
+        updateType = PCB_VIA_T;
         m_canvas->Refresh();
         break;
 
     case ID_TB_OPTIONS_SHOW_TRACKS_SKETCH:
         m_DisplayPcbTrackFill = DisplayOpt.DisplayPcbTrackFill = !state;
-        recache = true;
+        updateType = PCB_TRACE_T;
         m_canvas->Refresh();
         break;
 
@@ -256,11 +257,18 @@ void PCB_EDIT_FRAME::OnSelectOptionToolbar( wxCommandEvent& event )
         break;
     }
 
-    if( recache )
+    if( updateType != EOT )
     {
         // Apply new display options to the GAL canvas
         settings->LoadDisplayOptions( DisplayOpt );
-        GetGalCanvas()->GetView()->RecacheAllItems( true );
+
+        // Find items that require update
+        KICAD_T scanList[] = { updateType, EOT };
+        TYPE_COLLECTOR collector;
+        collector.Collect( GetBoard(), scanList );
+
+        for( int i = 0; i < collector.GetCount(); ++i )
+            collector[i]->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY );
     }
 
     if( IsGalCanvasActive() )
diff --git a/pcbnew/pcbframe.cpp b/pcbnew/pcbframe.cpp
index 4ec121c99e..9f1df9b5f5 100644
--- a/pcbnew/pcbframe.cpp
+++ b/pcbnew/pcbframe.cpp
@@ -544,21 +544,15 @@ void PCB_EDIT_FRAME::ViewReloadBoard( const BOARD* aBoard ) const
 
     // Load zones
     for( int i = 0; i < aBoard->GetAreaCount(); ++i )
-    {
         view->Add( (KIGFX::VIEW_ITEM*) ( aBoard->GetArea( i ) ) );
-    }
 
     // Load drawings
     for( BOARD_ITEM* drawing = aBoard->m_Drawings; drawing; drawing = drawing->Next() )
-    {
         view->Add( drawing );
-    }
 
     // Load tracks
     for( TRACK* track = aBoard->m_Track; track; track = track->Next() )
-    {
         view->Add( track );
-    }
 
     // Load modules and its additional elements
     for( MODULE* module = aBoard->m_Modules; module; module = module->Next() )
@@ -569,9 +563,7 @@ void PCB_EDIT_FRAME::ViewReloadBoard( const BOARD* aBoard ) const
 
     // Segzones (equivalent of ZONE_CONTAINER for legacy boards)
     for( SEGZONE* zone = aBoard->m_Zone; zone; zone = zone->Next() )
-    {
         view->Add( zone );
-    }
 
     // Add an entry for the worksheet layout
     KIGFX::WORKSHEET_VIEWITEM* worksheet = new KIGFX::WORKSHEET_VIEWITEM(
@@ -587,7 +579,7 @@ void PCB_EDIT_FRAME::ViewReloadBoard( const BOARD* aBoard ) const
     view->Add( new KIGFX::RATSNEST_VIEWITEM( ratsnest ) );
 
     view->SetPanBoundary( worksheet->ViewBBox() );
-    view->RecacheAllItems( true );
+    view->RecacheAllItems( false );
 
     if( IsGalCanvasActive() )
         GetGalCanvas()->Refresh();