Add support for reversed draw order and Cairo negative draw mode

This commit is contained in:
Jon Evans 2017-09-17 18:36:18 -04:00 committed by Maciej Suminski
parent e46fdb0115
commit 0b9b8d3e93
7 changed files with 69 additions and 9 deletions

View File

@ -391,7 +391,11 @@ bool EDA_DRAW_PANEL_GAL::SwitchBackend( GAL_TYPE aGalType )
m_painter->SetGAL( m_gal ); m_painter->SetGAL( m_gal );
if( m_view ) if( m_view )
{
m_view->SetGAL( m_gal ); m_view->SetGAL( m_gal );
// Note: OpenGL requires reverse draw order when draw priority is enabled
m_view->ReverseDrawOrder( aGalType == GAL_TYPE_OPENGL );
}
m_backend = aGalType; m_backend = aGalType;

View File

@ -857,6 +857,12 @@ void CAIRO_GAL::ClearTarget( RENDER_TARGET aTarget )
} }
void CAIRO_GAL::SetNegativeDrawMode( bool aSetting )
{
cairo_set_operator( currentContext, aSetting ? CAIRO_OPERATOR_CLEAR : CAIRO_OPERATOR_OVER );
}
void CAIRO_GAL::DrawCursor( const VECTOR2D& aCursorPosition ) void CAIRO_GAL::DrawCursor( const VECTOR2D& aCursorPosition )
{ {
cursorPosition = aCursorPosition; cursorPosition = aCursorPosition;

View File

@ -267,7 +267,8 @@ VIEW::VIEW( bool aIsDynamic ) :
m_gal( NULL ), m_gal( NULL ),
m_dynamic( aIsDynamic ), m_dynamic( aIsDynamic ),
m_useDrawPriority( false ), m_useDrawPriority( false ),
m_nextDrawPriority( 0 ) m_nextDrawPriority( 0 ),
m_reverseDrawOrder( false )
{ {
m_boundary.SetMaximum(); m_boundary.SetMaximum();
m_allItems.reserve( 32768 ); m_allItems.reserve( 32768 );
@ -815,8 +816,10 @@ void VIEW::UpdateAllLayersOrder()
struct VIEW::drawItem struct VIEW::drawItem
{ {
drawItem( VIEW* aView, int aLayer, bool aUseDrawPriority ) : drawItem( VIEW* aView, int aLayer, bool aUseDrawPriority, bool aReverseDrawOrder ) :
view( aView ), layer( aLayer ), useDrawPriority( aUseDrawPriority ) view( aView ), layer( aLayer ),
useDrawPriority( aUseDrawPriority ),
reverseDrawOrder( aReverseDrawOrder )
{ {
} }
@ -840,10 +843,16 @@ struct VIEW::drawItem
void deferredDraw() void deferredDraw()
{ {
if( reverseDrawOrder )
std::sort( drawItems.begin(), drawItems.end(), std::sort( drawItems.begin(), drawItems.end(),
[]( VIEW_ITEM* a, VIEW_ITEM* b ) -> bool { []( VIEW_ITEM* a, VIEW_ITEM* b ) -> bool {
return b->viewPrivData()->m_drawPriority < a->viewPrivData()->m_drawPriority; return b->viewPrivData()->m_drawPriority < a->viewPrivData()->m_drawPriority;
}); });
else
std::sort( drawItems.begin(), drawItems.end(),
[]( VIEW_ITEM* a, VIEW_ITEM* b ) -> bool {
return a->viewPrivData()->m_drawPriority < b->viewPrivData()->m_drawPriority;
});
for( auto item : drawItems ) for( auto item : drawItems )
view->draw( item, layer ); view->draw( item, layer );
@ -851,7 +860,7 @@ struct VIEW::drawItem
VIEW* view; VIEW* view;
int layer, layers[VIEW_MAX_LAYERS]; int layer, layers[VIEW_MAX_LAYERS];
bool useDrawPriority; bool useDrawPriority, reverseDrawOrder;
std::vector<VIEW_ITEM*> drawItems; std::vector<VIEW_ITEM*> drawItems;
}; };
@ -862,7 +871,7 @@ void VIEW::redrawRect( const BOX2I& aRect )
{ {
if( l->visible && IsTargetDirty( l->target ) && areRequiredLayersEnabled( l->id ) ) if( l->visible && IsTargetDirty( l->target ) && areRequiredLayersEnabled( l->id ) )
{ {
drawItem drawFunc( this, l->id, m_useDrawPriority ); drawItem drawFunc( this, l->id, m_useDrawPriority, m_reverseDrawOrder );
m_gal->SetTarget( l->target ); m_gal->SetTarget( l->target );
m_gal->SetLayerDepth( l->renderingOrder ); m_gal->SetLayerDepth( l->renderingOrder );

View File

@ -240,6 +240,9 @@ public:
/// @copydoc GAL::ClearTarget() /// @copydoc GAL::ClearTarget()
virtual void ClearTarget( RENDER_TARGET aTarget ) override; virtual void ClearTarget( RENDER_TARGET aTarget ) override;
/// @copydoc GAL::SetNegativeDrawMode()
virtual void SetNegativeDrawMode( bool aSetting ) override;
// ------- // -------
// Cursor // Cursor
// ------- // -------

View File

@ -772,6 +772,19 @@ public:
*/ */
virtual void ClearTarget( RENDER_TARGET aTarget ) {}; virtual void ClearTarget( RENDER_TARGET aTarget ) {};
/**
* @brief Sets negative draw mode in the renderer
*
* When negative mode is enabled, drawn items will subtract from
* previously drawn items. This is mainly needed for Gerber
* negative item support in Cairo, since unlike in OpenGL, objects
* drawn with zero opacity on top of other objects would not normally
* mask objects in Cairo. This method is a no-op in OpenGL.
*
* @param aSetting is true if negative mode should be enabled
*/
virtual void SetNegativeDrawMode( bool aSetting ) {};
// ------------- // -------------
// Grid methods // Grid methods
// ------------- // -------------

View File

@ -239,6 +239,9 @@ public:
/// @copydoc GAL::ClearTarget() /// @copydoc GAL::ClearTarget()
virtual void ClearTarget( RENDER_TARGET aTarget ) override; virtual void ClearTarget( RENDER_TARGET aTarget ) override;
/// @copydoc GAL::SetNegativeDrawMode()
virtual void SetNegativeDrawMode( bool aSetting ) override {}
// ------- // -------
// Cursor // Cursor
// ------- // -------

View File

@ -630,6 +630,25 @@ public:
m_useDrawPriority = aFlag; m_useDrawPriority = aFlag;
} }
/**
* Function IsDrawOrderReversed()
* @return true if draw order is reversed
*/
bool IsDrawOrderReversed() const
{
return m_reverseDrawOrder;
}
/**
* Function ReverseDrawOrder()
* Only takes effect if UseDrawPriority is true.
* @param aFlag is true if draw order should be reversed
*/
void ReverseDrawOrder( bool aFlag )
{
m_reverseDrawOrder = aFlag;
}
static const int VIEW_MAX_LAYERS = 512; ///< maximum number of layers that may be shown static const int VIEW_MAX_LAYERS = 512; ///< maximum number of layers that may be shown
@ -796,6 +815,9 @@ private:
/// The next sequential drawing priority /// The next sequential drawing priority
int m_nextDrawPriority; int m_nextDrawPriority;
/// Flag to reverse the draw order when using draw priority
bool m_reverseDrawOrder;
}; };
} // namespace KIGFX } // namespace KIGFX