← Back to team overview

kicad-developers team mailing list archive

[PATCH] Add drawing priority support to VIEW

 

Hi all,

Thanks to Tom's suggestion on how to approach this, I've got it working and
now GerbView can properly render negative objects in GAL.  This patch
should have no impact on pcbnew.

By the way, I'm getting close to feeling like I can share the work I'm
doing on GerbView in a private branch, but there are still a few things
that are broken enough that it doesn't make sense to subject other people
to them :-)

Best,
Jon
From ad6a5f7a5213cec224f1dd70a620e29af321f5fd Mon Sep 17 00:00:00 2001
From: Jon Evans <jon@xxxxxxxxxxxxx>
Date: Mon, 27 Feb 2017 18:40:27 -0500
Subject: [PATCH] Add drawing priority support to VIEW

Call UseDrawPriority( true ) after creating GAL to enable.

VIEW::Add() gets a new optional argument to specify the draw order
when adding an item.  If the new argument is left default, the draw
order will increment with each call of VIEW::Add().
---
 common/view/view.cpp | 40 ++++++++++++++++++++++++++++++++++------
 include/view/view.h  | 28 +++++++++++++++++++++++++++-
 2 files changed, 61 insertions(+), 7 deletions(-)

diff --git a/common/view/view.cpp b/common/view/view.cpp
index b661115..6018e7b 100644
--- a/common/view/view.cpp
+++ b/common/view/view.cpp
@@ -89,6 +89,7 @@ private:
     VIEW*   m_view;             ///< Current dynamic view the item is assigned to.
     int     m_flags;            ///< Visibility flags
     int     m_requiredUpdate;   ///< Flag required for updating
+    int     m_drawPriority;     ///< Order to draw this item in a layer, lowest first

     ///> Helper for storing cached items group ids
     typedef std::pair<int, int> GroupPair;
@@ -260,7 +261,9 @@ VIEW::VIEW( bool aIsDynamic ) :
     m_mirrorX( false ), m_mirrorY( false ),
     m_painter( NULL ),
     m_gal( NULL ),
-    m_dynamic( aIsDynamic )
+    m_dynamic( aIsDynamic ),
+    m_useDrawPriority( false ),
+    m_nextDrawPriority( 0 )
 {
     m_boundary.SetMaximum();
     m_allItems.reserve( 32768 );
@@ -301,12 +304,16 @@ void VIEW::AddLayer( int aLayer, bool aDisplayOnly )
 }


-void VIEW::Add( VIEW_ITEM* aItem )
+void VIEW::Add( VIEW_ITEM* aItem, int aDrawPriority )
 {
     int layers[VIEW_MAX_LAYERS], layers_count;

+    if( aDrawPriority < 0 )
+        aDrawPriority = m_nextDrawPriority++;
+
     aItem->m_viewPrivData = new VIEW_ITEM_DATA;
     aItem->m_viewPrivData->m_view = this;
+    aItem->m_viewPrivData->m_drawPriority = aDrawPriority;

     aItem->ViewGetLayers( layers, layers_count );
     aItem->viewPrivData()->saveLayers( layers, layers_count );
@@ -812,8 +819,8 @@ void VIEW::UpdateAllLayersOrder()

 struct VIEW::drawItem
 {
-    drawItem( VIEW* aView, int aLayer ) :
-        view( aView ), layer( aLayer )
+    drawItem( VIEW* aView, int aLayer, bool aUseDrawPriority ) :
+        view( aView ), layer( aLayer ), useDrawPriority( aUseDrawPriority )
     {
     }

@@ -827,13 +834,29 @@ struct VIEW::drawItem
         if( !drawCondition )
             return true;

-        view->draw( aItem, layer );
+        if( useDrawPriority )
+            drawItems.push_back( aItem );
+        else
+            view->draw( aItem, layer );

         return true;
     }

+    void deferredDraw()
+    {
+        std::sort( drawItems.begin(), drawItems.end(),
+                   []( VIEW_ITEM* a, VIEW_ITEM* b ) -> bool {
+                       return b->viewPrivData()->m_drawPriority < a->viewPrivData()->m_drawPriority;
+                   });
+
+        for( auto item : drawItems )
+            view->draw( item, layer );
+    }
+
     VIEW* view;
     int layer, layers[VIEW_MAX_LAYERS];
+    bool useDrawPriority;
+    std::vector<VIEW_ITEM*> drawItems;
 };


@@ -843,11 +866,14 @@ void VIEW::redrawRect( const BOX2I& aRect )
     {
         if( l->visible && IsTargetDirty( l->target ) && areRequiredLayersEnabled( l->id ) )
         {
-            drawItem drawFunc( this, l->id );
+            drawItem drawFunc( this, l->id, m_useDrawPriority );

             m_gal->SetTarget( l->target );
             m_gal->SetLayerDepth( l->renderingOrder );
             l->items->Query( aRect, drawFunc );
+
+            if( m_useDrawPriority )
+                drawFunc.deferredDraw();
         }
     }
 }
@@ -955,6 +981,8 @@ void VIEW::Clear()
     for( LAYER_MAP_ITER i = m_layers.begin(); i != m_layers.end(); ++i )
         i->second.items->RemoveAll();

+    m_nextDrawPriority = 0;
+
     m_gal->ClearCache();
 }

diff --git a/include/view/view.h b/include/view/view.h
index 6de865a..108b2df 100644
--- a/include/view/view.h
+++ b/include/view/view.h
@@ -79,9 +79,11 @@ public:
     /**
      * Function Add()
      * Adds a VIEW_ITEM to the view.
+     * Set aDrawPriority to -1 to assign sequential priorities.
      * @param aItem: item to be added. No ownership is given
+     * @param aDrawPriority: priority to draw this item on its layer, lowest first.
      */
-    void Add( VIEW_ITEM* aItem );
+    void Add( VIEW_ITEM* aItem, int aDrawPriority = -1 );

     /**
      * Function Remove()
@@ -617,6 +619,24 @@ public:

     const BOX2I CalculateExtents() ;

+    /**
+     * Function IsUsingDrawPriority()
+     * @return true if draw priority is being respected while redrawing.
+     */
+    bool IsUsingDrawPriority() const
+    {
+        return m_useDrawPriority;
+    }
+
+    /**
+     * Function UseDrawPriority()
+     * @param aFlag is true if draw priority should be respected while redrawing.
+     */
+    void UseDrawPriority( bool aFlag )
+    {
+        m_useDrawPriority = aFlag;
+    }
+
     static const int VIEW_MAX_LAYERS = 256;      ///< maximum number of layers that may be shown

 private:
@@ -776,6 +796,12 @@ private:

     /// Flat list of all items
     std::vector<VIEW_ITEM*> m_allItems;
+
+    /// Flag to respect draw priority when drawing items
+    bool m_useDrawPriority;
+
+    /// The next sequential drawing priority
+    int m_nextDrawPriority;
 };
 } // namespace KIGFX

--
2.7.4


Follow ups