diff --git a/gerbview/class_aperture_macro.cpp b/gerbview/class_aperture_macro.cpp index 866e00b20d..9896ff1b51 100644 --- a/gerbview/class_aperture_macro.cpp +++ b/gerbview/class_aperture_macro.cpp @@ -100,7 +100,8 @@ void AM_PRIMITIVE::DrawBasicShape( GERBER_DRAW_ITEM* aParent, { #define TO_POLY_SHAPE { aShapeBuffer.NewOutline(); \ for( unsigned jj = 0; jj < polybuffer.size(); jj++ )\ - aShapeBuffer.Append( polybuffer[jj].x, polybuffer[jj].y );} + aShapeBuffer.Append( polybuffer[jj].x, polybuffer[jj].y );\ + aShapeBuffer.Append( polybuffer[0].x, polybuffer[0].y );} // Draw the primitive shape for flashed items. static std::vector polybuffer; // create a static buffer to avoid a lot of memory reallocation @@ -746,6 +747,50 @@ int AM_PRIMITIVE::GetShapeDim( GERBER_DRAW_ITEM* aParent ) } +SHAPE_POLY_SET* APERTURE_MACRO::GetApertureMacroShape( GERBER_DRAW_ITEM* aParent, + wxPoint aShapePos ) +{ + SHAPE_POLY_SET holeBuffer; + bool hasHole = false; + + m_shape.RemoveAllContours(); + + for( AM_PRIMITIVES::iterator prim_macro = primitives.begin(); + prim_macro != primitives.end(); ++prim_macro ) + { + if( prim_macro->primitive_id == AMP_COMMENT ) + continue; + + if( prim_macro->IsAMPrimitiveExposureOn( aParent ) ) + prim_macro->DrawBasicShape( aParent, m_shape, aShapePos ); + else + { + prim_macro->DrawBasicShape( aParent, holeBuffer, aShapePos ); + + if( holeBuffer.OutlineCount() ) // we have a new hole in shape: remove the hole + { + m_shape.BooleanSubtract( holeBuffer, SHAPE_POLY_SET::PM_FAST ); + holeBuffer.RemoveAllContours(); + hasHole = true; + } + } + } + + // If a hole is defined inside a polygon, we must fracture the polygon + // to be able to drawn it (i.e link holes by overlapping edges) + if( hasHole ) + m_shape.Fracture( SHAPE_POLY_SET::PM_FAST ); + + m_boundingBox = EDA_RECT( wxPoint( 0, 0 ), wxSize( 1, 1 ) ); + auto bb = m_shape.BBox(); + wxPoint center( bb.Centre().x, bb.Centre().y ); + m_boundingBox.Move( aParent->GetABPosition( center ) ); + m_boundingBox.Inflate( bb.GetWidth() / 2, bb.GetHeight() / 2 ); + + return &m_shape; +} + + /* * Function DrawApertureMacroShape * Draw the primitive shape for flashed items. @@ -756,39 +801,14 @@ void APERTURE_MACRO::DrawApertureMacroShape( GERBER_DRAW_ITEM* aParent, COLOR4D aColor, wxPoint aShapePos, bool aFilledShape ) { - SHAPE_POLY_SET shapeBuffer; - SHAPE_POLY_SET holeBuffer; - bool hasHole = false; + SHAPE_POLY_SET* shapeBuffer = GetApertureMacroShape( aParent, aShapePos ); - for( AM_PRIMITIVES::iterator prim_macro = primitives.begin(); - prim_macro != primitives.end(); ++prim_macro ) - { - if( prim_macro->IsAMPrimitiveExposureOn( aParent ) ) - prim_macro->DrawBasicShape( aParent, shapeBuffer, aShapePos ); - else - { - prim_macro->DrawBasicShape( aParent, holeBuffer, aShapePos ); - - if( holeBuffer.OutlineCount() ) // we have a new hole in shape: remove the hole - { - shapeBuffer.BooleanSubtract( holeBuffer, SHAPE_POLY_SET::PM_FAST ); - holeBuffer.RemoveAllContours(); - hasHole = true; - } - } - } - - if( shapeBuffer.OutlineCount() == 0 ) + if( shapeBuffer->OutlineCount() == 0 ) return; - // If a hole is defined inside a polygon, we must fracture the polygon - // to be able to drawn it (i.e link holes by overlapping edges) - if( hasHole ) - shapeBuffer.Fracture( SHAPE_POLY_SET::PM_FAST ); - - for( int ii = 0; ii < shapeBuffer.OutlineCount(); ii++ ) + for( int ii = 0; ii < shapeBuffer->OutlineCount(); ii++ ) { - SHAPE_LINE_CHAIN& poly = shapeBuffer.Outline( ii ); + SHAPE_LINE_CHAIN& poly = shapeBuffer->Outline( ii ); GRClosedPoly( aClipBox, aDC, poly.PointCount(), (wxPoint*)&poly.Point( 0 ), aFilledShape, aColor, aColor ); diff --git a/gerbview/class_aperture_macro.h b/gerbview/class_aperture_macro.h index dc94ef259a..c6579828e6 100644 --- a/gerbview/class_aperture_macro.h +++ b/gerbview/class_aperture_macro.h @@ -35,6 +35,7 @@ #include #include +#include class SHAPE_POLY_SET; @@ -170,6 +171,9 @@ struct APERTURE_MACRO */ AM_PARAMS m_localparamStack; + SHAPE_POLY_SET m_shape; ///< The shape of the item, calculated by GetApertureMacroShape + EDA_RECT m_boundingBox; ///< The bounding box of the item, calculated by GetApertureMacroShape + /** * function GetLocalParam * Usually, parameters are defined inside the aperture primitive @@ -183,6 +187,16 @@ struct APERTURE_MACRO */ double GetLocalParam( const D_CODE* aDcode, unsigned aParamId ) const; + + /** + * Function GetApertureMacroShape + * Calculate the primitive shape for flashed items. + * When an item is flashed, this is the shape of the item + * @param aParent = the parent GERBER_DRAW_ITEM which is actually drawn + * @return The shape of the item + */ + SHAPE_POLY_SET* GetApertureMacroShape( GERBER_DRAW_ITEM* aParent, wxPoint aShapePos ); + /** * Function DrawApertureMacroShape * Draw the primitive shape for flashed items. @@ -210,6 +224,12 @@ struct APERTURE_MACRO * @return a dimension, or -1 if no dim to calculate */ int GetShapeDim( GERBER_DRAW_ITEM* aParent ); + + /// Returns the bounding box of the shape + EDA_RECT GetBoundingBox() const + { + return m_boundingBox; + } }; diff --git a/gerbview/class_gbr_display_options.h b/gerbview/class_gbr_display_options.h index e4b17d44b5..43834594ab 100644 --- a/gerbview/class_gbr_display_options.h +++ b/gerbview/class_gbr_display_options.h @@ -47,6 +47,8 @@ public: bool m_DisplayNegativeObjects; ///< Option to draw negative objects in a specific color bool m_IsPrinting; ///< true when printing a page, false when drawing on screen bool m_ForceBlackAndWhite; ///< Option print in blackand white (ont used id draw mode + bool m_DiffMode; ///< Display layers in diff mode + bool m_HighContrastMode; ///< High contrast mode (dim un-highlighted objects) COLOR4D m_NegativeDrawColor; ///< The color used to draw negative objects, usually the ///< background color, but not always, when negative objects ///< must be visible @@ -65,6 +67,8 @@ public: m_ForceBlackAndWhite = false; m_NegativeDrawColor = COLOR4D( DARKGRAY ); m_BgDrawColor = COLOR4D::BLACK; + m_DiffMode = true; + m_HighContrastMode = false; } }; diff --git a/gerbview/class_gbr_layer_box_selector.cpp b/gerbview/class_gbr_layer_box_selector.cpp index 7ae5b7aaae..b7dfd2227e 100644 --- a/gerbview/class_gbr_layer_box_selector.cpp +++ b/gerbview/class_gbr_layer_box_selector.cpp @@ -73,7 +73,7 @@ COLOR4D GBR_LAYER_BOX_SELECTOR::GetLayerColor( int aLayer ) const { GERBVIEW_FRAME* frame = (GERBVIEW_FRAME*) GetParent()->GetParent(); - return frame->GetLayerColor( aLayer ); + return frame->GetLayerColor( GERBER_DRAW_LAYER( aLayer ) ); } diff --git a/gerbview/class_gbr_layout.cpp b/gerbview/class_gbr_layout.cpp index ebba33f4c0..dc1f20355d 100644 --- a/gerbview/class_gbr_layout.cpp +++ b/gerbview/class_gbr_layout.cpp @@ -36,7 +36,8 @@ #include #include -GBR_LAYOUT::GBR_LAYOUT() +GBR_LAYOUT::GBR_LAYOUT() : + EDA_ITEM( (EDA_ITEM*)NULL, GERBER_LAYOUT_T ) { } @@ -46,7 +47,7 @@ GBR_LAYOUT::~GBR_LAYOUT() } // Accessor to the list of gerber files (and drill files) images -GERBER_FILE_IMAGE_LIST* GBR_LAYOUT::GetImagesList() +GERBER_FILE_IMAGE_LIST* GBR_LAYOUT::GetImagesList() const { return &GERBER_FILE_IMAGE_LIST::GetImagesList(); } @@ -64,7 +65,7 @@ bool GBR_LAYOUT::IsLayerPrintable( int aLayer ) const } -EDA_RECT GBR_LAYOUT::ComputeBoundingBox() +EDA_RECT GBR_LAYOUT::ComputeBoundingBox() const { EDA_RECT bbox; bool first_item = true; @@ -88,7 +89,10 @@ EDA_RECT GBR_LAYOUT::ComputeBoundingBox() } } - SetBoundingBox( bbox ); + bbox.Inflate( ( bbox.GetWidth() / 10 ) + 100 ); + bbox.Normalize(); + + m_BoundingBox = bbox; return bbox; } @@ -185,7 +189,7 @@ void GBR_LAYOUT::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, GR_DRAWMODE aDrawMode, // In non transparent modes, the last layer drawn masks others layers for( int layer = GERBER_DRAWLAYERS_COUNT-1; !end; --layer ) { - int active_layer = gerbFrame->getActiveLayer(); + int active_layer = gerbFrame->GetActiveLayer(); if( layer == active_layer ) // active layer will be drawn after other layers continue; @@ -204,12 +208,12 @@ void GBR_LAYOUT::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, GR_DRAWMODE aDrawMode, if( aDisplayOptions->m_IsPrinting ) gerber->m_IsVisible = IsLayerPrintable( layer ); else - gerber->m_IsVisible = gerbFrame->IsLayerVisible( layer ); + gerber->m_IsVisible = gerbFrame->IsLayerVisible( GERBER_DRAW_LAYER( layer ) ); if( !gerber->m_IsVisible ) continue; - gerber->m_PositiveDrawColor = gerbFrame->GetLayerColor( layer ); + gerber->m_PositiveDrawColor = gerbFrame->GetLayerColor( GERBER_DRAW_LAYER( layer ) ); // Force black and white draw mode on request: if( aDisplayOptions->m_ForceBlackAndWhite ) @@ -277,7 +281,7 @@ void GBR_LAYOUT::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, GR_DRAWMODE aDrawMode, int dcode_highlight = 0; - if( layer == gerbFrame->getActiveLayer() ) + if( layer == gerbFrame->GetActiveLayer() ) dcode_highlight = gerber->m_Selected_Tool; GR_DRAWMODE layerdrawMode = GR_COPY; @@ -433,3 +437,50 @@ void GBR_LAYOUT::DrawItemsDCodeID( EDA_DRAW_PANEL* aPanel, wxDC* aDC, } } } + + +SEARCH_RESULT GBR_LAYOUT::Visit( INSPECTOR inspector, void* testData, const KICAD_T scanTypes[] ) +{ + KICAD_T stype; + SEARCH_RESULT result = SEARCH_CONTINUE; + const KICAD_T* p = scanTypes; + bool done = false; + +#if 0 && defined(DEBUG) + std::cout << GetClass().mb_str() << ' '; +#endif + + while( !done ) + { + stype = *p; + + switch( stype ) + { + case GERBER_IMAGE_LIST_T: + for( unsigned layer = 0; layer < GetImagesList()->ImagesMaxCount(); ++layer ) + { + GERBER_FILE_IMAGE* gerber = GetImagesList()->GetGbrImage( layer ); + + if( gerber == NULL ) // Graphic layer not yet used + continue; + + result = gerber->Visit( inspector, testData, p ); + + if( result == SEARCH_QUIT ) + break; + } + + ++p; + break; + + default: // catch EOT or ANY OTHER type here and return. + done = true; + break; + } + + if( result == SEARCH_QUIT ) + break; + } + + return result; +} diff --git a/gerbview/class_gbr_layout.h b/gerbview/class_gbr_layout.h index 8f0ae598f0..c68bc2e7f4 100644 --- a/gerbview/class_gbr_layout.h +++ b/gerbview/class_gbr_layout.h @@ -50,10 +50,10 @@ class GERBER_FILE_IMAGE_LIST; * Class GBR_LAYOUT * holds list of GERBER_DRAW_ITEM currently loaded. */ -class GBR_LAYOUT +class GBR_LAYOUT : public EDA_ITEM { private: - EDA_RECT m_BoundingBox; + mutable EDA_RECT m_BoundingBox; TITLE_BLOCK m_titles; wxPoint m_originAxisPosition; std::vector m_printLayersList; // When printing: the list of graphic layers Id to print @@ -63,9 +63,14 @@ public: GBR_LAYOUT(); ~GBR_LAYOUT(); + wxString GetClass() const override + { + return wxT( "GBR_LAYOUT" ); + } + // Accessor to the GERBER_FILE_IMAGE_LIST, // which handles the list of gerber files (and drill files) images loaded - GERBER_FILE_IMAGE_LIST* GetImagesList(); + GERBER_FILE_IMAGE_LIST* GetImagesList() const; const wxPoint& GetAuxOrigin() const { @@ -92,14 +97,15 @@ public: * calculates the bounding box containing all Gerber items. * @return EDA_RECT - the full item list bounding box */ - EDA_RECT ComputeBoundingBox(); + EDA_RECT ComputeBoundingBox() const; /** * Function GetBoundingBox - * may be called soon after ComputeBoundingBox() to return the same EDA_RECT, - * as long as the CLASS_GBR_LAYOUT has not changed. */ - EDA_RECT GetBoundingBox() const { return m_BoundingBox; } + const EDA_RECT GetBoundingBox() const override + { + return ComputeBoundingBox(); + } void SetBoundingBox( const EDA_RECT& aBox ) { m_BoundingBox = aBox; } @@ -176,8 +182,13 @@ public: */ bool IsLayerPrintable( int aLayer ) const; + ///> @copydoc EDA_ITEM::Visit() + SEARCH_RESULT Visit( INSPECTOR inspector, void* testData, const KICAD_T scanTypes[] ) override; + + #if defined(DEBUG) - void Show( int nestLevel, std::ostream& os ) const; + + void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); } #endif }; diff --git a/gerbview/class_gerber_draw_item.cpp b/gerbview/class_gerber_draw_item.cpp index 6cea3a714d..0a9ab84d39 100644 --- a/gerbview/class_gerber_draw_item.cpp +++ b/gerbview/class_gerber_draw_item.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -40,7 +41,7 @@ GERBER_DRAW_ITEM::GERBER_DRAW_ITEM( GERBER_FILE_IMAGE* aGerberImageFile ) : - EDA_ITEM( (EDA_ITEM*)NULL, TYPE_GERBER_DRAW_ITEM ) + EDA_ITEM( (EDA_ITEM*)NULL, GERBER_DRAW_ITEM_T ) { m_GerberImageFile = aGerberImageFile; m_Shape = GBR_SEGMENT; @@ -158,7 +159,7 @@ void GERBER_DRAW_ITEM::SetLayerParameters() } -wxString GERBER_DRAW_ITEM::ShowGBRShape() +wxString GERBER_DRAW_ITEM::ShowGBRShape() const { switch( m_Shape ) { @@ -203,7 +204,7 @@ wxString GERBER_DRAW_ITEM::ShowGBRShape() } -D_CODE* GERBER_DRAW_ITEM::GetDcodeDescr() +D_CODE* GERBER_DRAW_ITEM::GetDcodeDescr() const { if( (m_DCode < FIRST_DCODE) || (m_DCode > LAST_DCODE) ) return NULL; @@ -211,7 +212,7 @@ D_CODE* GERBER_DRAW_ITEM::GetDcodeDescr() if( m_GerberImageFile == NULL ) return NULL; - return m_GerberImageFile->GetDCODE( m_DCode, false ); + return m_GerberImageFile->GetDCODE( m_DCode ); } @@ -219,8 +220,100 @@ const EDA_RECT GERBER_DRAW_ITEM::GetBoundingBox() const { // return a rectangle which is (pos,dim) in nature. therefore the +1 EDA_RECT bbox( m_Start, wxSize( 1, 1 ) ); + D_CODE* code = GetDcodeDescr(); - bbox.Inflate( m_Size.x / 2, m_Size.y / 2 ); + // TODO(JE) GERBER_DRAW_ITEM maybe should actually be a number of subclasses. + // Until/unless that is changed, we need to do different things depending on + // what is actually being represented by this GERBER_DRAW_ITEM. + + switch( m_Shape ) + { + case GBR_POLYGON: + { + auto bb = m_Polygon.BBox(); + bbox.Inflate( bb.GetWidth() / 2, bb.GetHeight() / 2 ); + bbox.SetOrigin( bb.GetOrigin().x, bb.GetOrigin().y ); + break; + } + + case GBR_CIRCLE: + { + double radius = GetLineLength( m_Start, m_End ); + bbox.Inflate( radius, radius ); + break; + } + + case GBR_ARC: + { + // Note: using a larger-than-necessary BB to simplify computation + double radius = GetLineLength( m_Start, m_ArcCentre ); + bbox.Inflate( radius, radius ); + break; + } + + case GBR_SPOT_CIRCLE: + { + int radius = code->m_Size.x >> 1; + bbox.Inflate( radius, radius ); + break; + } + + case GBR_SPOT_RECT: + { + bbox.Inflate( code->m_Size.x / 2, code->m_Size.y / 2 ); + break; + } + + case GBR_SPOT_OVAL: + { + bbox.Inflate( code->m_Size.x, code->m_Size.y ); + break; + } + + case GBR_SPOT_POLY: + { + if( code->m_Polygon.OutlineCount() == 0 ) + code->ConvertShapeToPolygon(); + + bbox.Inflate( code->m_Polygon.BBox().GetWidth() / 2, code->m_Polygon.BBox().GetHeight() / 2 ); + break; + } + case GBR_SPOT_MACRO: + { + bbox = code->GetMacro()->GetBoundingBox(); + break; + } + + case GBR_SEGMENT: + { + if( code && code->m_Shape == APT_RECT ) + { + if( m_Polygon.OutlineCount() > 0 ) + { + auto bb = m_Polygon.BBox(); + bbox.Inflate( bb.GetWidth() / 2, bb.GetHeight() / 2 ); + bbox.SetOrigin( bb.GetOrigin().x, bb.GetOrigin().y ); + } + } + else + { + int radius = ( m_Size.x + 1 ) / 2; + + int ymax = std::max( m_Start.y, m_End.y ) + radius; + int xmax = std::max( m_Start.x, m_End.x ) + radius; + + int ymin = std::min( m_Start.y, m_End.y ) - radius; + int xmin = std::min( m_Start.x, m_End.x ) - radius; + + bbox = EDA_RECT( wxPoint( xmin, ymin ), wxSize( xmax - xmin + 1, ymax - ymin + 1 ) ); + } + + break; + } + default: + wxASSERT_MSG( false, wxT( "GERBER_DRAW_ITEM shape is unknown!" ) ); + break; + } // calculate the corners coordinates in current gerber axis orientations wxPoint org = GetABPosition( bbox.GetOrigin() ); @@ -243,8 +336,11 @@ void GERBER_DRAW_ITEM::MoveAB( const wxPoint& aMoveVector ) m_End += xymove; m_ArcCentre += xymove; - for( unsigned ii = 0; ii < m_PolyCorners.size(); ii++ ) - m_PolyCorners[ii] += xymove; + if( m_Polygon.OutlineCount() > 0 ) + { + for( auto it = m_Polygon.Iterate( 0 ); it; ++it ) + *it += xymove; + } } @@ -254,8 +350,11 @@ void GERBER_DRAW_ITEM::MoveXY( const wxPoint& aMoveVector ) m_End += aMoveVector; m_ArcCentre += aMoveVector; - for( unsigned ii = 0; ii < m_PolyCorners.size(); ii++ ) - m_PolyCorners[ii] += aMoveVector; + if( m_Polygon.OutlineCount() > 0 ) + { + for( auto it = m_Polygon.Iterate( 0 ); it; ++it ) + *it += aMoveVector; + } } @@ -378,8 +477,8 @@ void GERBER_DRAW_ITEM::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, GR_DRAWMODE aDra */ if( d_codeDescr->m_Shape == APT_RECT ) { - if( m_PolyCorners.size() == 0 ) - ConvertSegmentToPolygon( ); + if( m_Polygon.OutlineCount() == 0 ) + ConvertSegmentToPolygon(); DrawGbrPoly( aPanel->GetClipBox(), aDC, color, aOffset, isFilled ); } @@ -411,10 +510,10 @@ void GERBER_DRAW_ITEM::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDC, GR_DRAWMODE aDra } -void GERBER_DRAW_ITEM::ConvertSegmentToPolygon( ) +void GERBER_DRAW_ITEM::ConvertSegmentToPolygon() { - m_PolyCorners.clear(); - m_PolyCorners.reserve(6); + m_Polygon.RemoveAllContours(); + m_Polygon.NewOutline(); wxPoint start = m_Start; wxPoint end = m_End; @@ -443,34 +542,37 @@ void GERBER_DRAW_ITEM::ConvertSegmentToPolygon( ) wxPoint corner; corner.x -= m_Size.x/2; corner.y -= m_Size.y/2; - m_PolyCorners.push_back( corner ); // Lower left corner, start point (1) + wxPoint close = corner; + m_Polygon.Append( VECTOR2I( corner ) ); // Lower left corner, start point (1) corner.y += m_Size.y; - m_PolyCorners.push_back( corner ); // upper left corner, start point (2) + m_Polygon.Append( VECTOR2I( corner ) ); // upper left corner, start point (2) if( delta.x || delta.y) { corner += delta; - m_PolyCorners.push_back( corner ); // upper left corner, end point (3) + m_Polygon.Append( VECTOR2I( corner ) ); // upper left corner, end point (3) } corner.x += m_Size.x; - m_PolyCorners.push_back( corner ); // upper right corner, end point (4) + m_Polygon.Append( VECTOR2I( corner ) ); // upper right corner, end point (4) corner.y -= m_Size.y; - m_PolyCorners.push_back( corner ); // lower right corner, end point (5) + m_Polygon.Append( VECTOR2I( corner ) ); // lower right corner, end point (5) if( delta.x || delta.y ) { corner -= delta; - m_PolyCorners.push_back( corner ); // lower left corner, start point (6) + m_Polygon.Append( VECTOR2I( corner ) ); // lower left corner, start point (6) } + m_Polygon.Append( VECTOR2I( close ) ); // close the shape + // Create final polygon: - for( unsigned ii = 0; ii < m_PolyCorners.size(); ii++ ) + for( auto it = m_Polygon.Iterate( 0 ); it; ++it ) { if( change ) - m_PolyCorners[ii].y = -m_PolyCorners[ii].y; + ( *it ).y = -( *it ).y; - m_PolyCorners[ii] += start; + *it += start; } } @@ -482,15 +584,19 @@ void GERBER_DRAW_ITEM::DrawGbrPoly( EDA_RECT* aClipBox, bool aFilledShape ) { std::vector points; + SHAPE_LINE_CHAIN& poly = m_Polygon.Outline( 0 ); + int pointCount = poly.PointCount() - 1; - points = m_PolyCorners; - for( unsigned ii = 0; ii < points.size(); ii++ ) + points.reserve( pointCount ); + + for( int ii = 0; ii < pointCount; ii++ ) { - points[ii] += aOffset; - points[ii] = GetABPosition( points[ii] ); + wxPoint p( poly.Point( ii ).x, poly.Point( ii ).y ); + points[ii] = p + aOffset; + points[ii] = GetABPosition( points[ii] ); } - GRClosedPoly( aClipBox, aDC, points.size(), &points[0], aFilledShape, aColor, aColor ); + GRClosedPoly( aClipBox, aDC, pointCount, &points[0], aFilledShape, aColor, aColor ); } @@ -506,7 +612,7 @@ void GERBER_DRAW_ITEM::GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ) msg.Printf( _( "D Code %d" ), m_DCode ); D_CODE* apertDescr = GetDcodeDescr(); - if( apertDescr->m_AperFunction.IsEmpty() ) + if( !apertDescr || apertDescr->m_AperFunction.IsEmpty() ) text = _( "No attribute" ); else text = apertDescr->m_AperFunction; @@ -582,6 +688,37 @@ bool GERBER_DRAW_ITEM::HitTest( const wxPoint& aRefPos ) const // TODO: a better analyze of the shape (perhaps create a D_CODE::HitTest for flashed items) int radius = std::min( m_Size.x, m_Size.y ) >> 1; + SHAPE_POLY_SET poly; + + switch( m_Shape ) + { + case GBR_POLYGON: + poly = m_Polygon; + return poly.Contains( VECTOR2I( ref_pos ), 0 ); + break; + + case GBR_SPOT_POLY: + poly = GetDcodeDescr()->m_Polygon; + poly.Move( m_Start ); + return poly.Contains( VECTOR2I( ref_pos ), 0 ); + break; + + case GBR_SPOT_RECT: + return GetBoundingBox().Contains( aRefPos ); + break; + + case GBR_SPOT_MACRO: + // Aperture macro polygons are already in absolute coordinates + poly = GetDcodeDescr()->GetMacro()->m_shape; + for( int i = 0; i < poly.OutlineCount(); ++i ) + { + if( poly.Contains( VECTOR2I( aRefPos ), i ) ) + return true; + } + return false; + break; + } + if( m_Flashed ) return HitTestPoints( m_Start, ref_pos, radius ); else @@ -624,3 +761,60 @@ void GERBER_DRAW_ITEM::Show( int nestLevel, std::ostream& os ) const } #endif + + +void GERBER_DRAW_ITEM::ViewGetLayers( int aLayers[], int& aCount ) const +{ + aCount = 2; + aLayers[0] = GERBER_DRAW_LAYER( GetLayer() ); + aLayers[1] = GERBER_DCODE_LAYER( aLayers[0] ); +} + + +const BOX2I GERBER_DRAW_ITEM::ViewBBox() const +{ + EDA_RECT bbox = GetBoundingBox(); + return BOX2I( VECTOR2I( bbox.GetOrigin() ), + VECTOR2I( bbox.GetSize() ) ); +} + + +unsigned int GERBER_DRAW_ITEM::ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const +{ + // DCodes will be shown only if zoom is appropriate + if( IsDCodeLayer( aLayer ) ) + { + return ( 400000 / ( m_Size.x + 1 ) ); + } + + // Other layers are shown without any conditions + return 0; +} + + +SEARCH_RESULT GERBER_DRAW_ITEM::Visit( INSPECTOR inspector, void* testData, const KICAD_T scanTypes[] ) +{ + KICAD_T stype = *scanTypes; + + // If caller wants to inspect my type + if( stype == Type() ) + { + if( SEARCH_QUIT == inspector( this, testData ) ) + return SEARCH_QUIT; + } + + return SEARCH_CONTINUE; +} + + +wxString GERBER_DRAW_ITEM::GetSelectMenuText() const +{ + wxString text, layerName; + + layerName = GERBER_FILE_IMAGE_LIST::GetImagesList().GetDisplayName( GetLayer(), true ); + + text.Printf( _( "%s (D%d) on layer %d: %s" ), ShowGBRShape(), m_DCode, + GetLayer() + 1, layerName ); + + return text; +} diff --git a/gerbview/class_gerber_draw_item.h b/gerbview/class_gerber_draw_item.h index 832528fb79..a272392e34 100644 --- a/gerbview/class_gerber_draw_item.h +++ b/gerbview/class_gerber_draw_item.h @@ -35,6 +35,7 @@ #include #include #include +#include class GERBER_FILE_IMAGE; class GBR_LAYOUT; @@ -42,6 +43,11 @@ class D_CODE; class MSG_PANEL_ITEM; class GBR_DISPLAY_OPTIONS; +namespace KIGFX +{ + class VIEW; +}; + /* Shapes id for basic shapes ( .m_Shape member ) */ enum Gbr_Basic_Shapes { @@ -76,7 +82,7 @@ public: // for flashed items wxPoint m_End; // Line or arc end point wxPoint m_ArcCentre; // for arcs only: Centre of arc - std::vector m_PolyCorners; // list of corners for polygons (G36 to G37 coordinates) + SHAPE_POLY_SET m_Polygon; // Polygon shape data (G36 to G37 coordinates) // or for complex shapes which are converted to polygon wxSize m_Size; // Flashed shapes: size of the shape // Lines : m_Size.x = m_Size.y = line width @@ -116,7 +122,7 @@ public: GERBER_DRAW_ITEM* Back() const { return static_cast( Pback ); } void SetNetAttributes( const GBR_NETLIST_METADATA& aNetAttributes ); - const GBR_NETLIST_METADATA& GetNetAttributes() { return m_netAttributes; } + const GBR_NETLIST_METADATA& GetNetAttributes() const { return m_netAttributes; } /** * Function GetLayer @@ -124,7 +130,7 @@ public: */ int GetLayer() const; - bool GetLayerPolarity() + bool GetLayerPolarity() const { return m_LayerNegative; } @@ -186,6 +192,11 @@ public: */ wxPoint GetABPosition( const wxPoint& aXYPosition ) const; + VECTOR2I GetABPosition( const VECTOR2I& aXYPosition ) const + { + return VECTOR2I( GetABPosition( wxPoint( aXYPosition.x, aXYPosition.y ) ) ); + } + /** * Function GetXYPosition * returns the image position of aPosition for this object. @@ -201,7 +212,7 @@ public: * returns the GetDcodeDescr of this object, or NULL. * @return D_CODE* - a pointer to the DCode description (for flashed items). */ - D_CODE* GetDcodeDescr(); + D_CODE* GetDcodeDescr() const; const EDA_RECT GetBoundingBox() const override; @@ -229,7 +240,7 @@ public: void GetMsgPanelInfo( std::vector< MSG_PANEL_ITEM >& aList ) override; - wxString ShowGBRShape(); + wxString ShowGBRShape() const; /** * Function HitTest @@ -284,6 +295,26 @@ public: void Show( int nestLevel, std::ostream& os ) const override; #endif + /// @copydoc VIEW_ITEM::ViewGetLayers() + virtual void ViewGetLayers( int aLayers[], int& aCount ) const override; + + /// @copydoc VIEW_ITEM::ViewBBox() + virtual const BOX2I ViewBBox() const override; + + /// @copydoc VIEW_ITEM::ViewGetLOD() + virtual unsigned int ViewGetLOD( int aLayer, KIGFX::VIEW* aView ) const override; + + ///> @copydoc EDA_ITEM::Visit() + SEARCH_RESULT Visit( INSPECTOR inspector, void* testData, const KICAD_T scanTypes[] ) override; + + virtual wxString GetSelectMenuText() const override; + +}; + + +class GERBER_NEGATIVE_IMAGE_BACKDROP : public EDA_ITEM +{ + }; #endif /* CLASS_GERBER_DRAW_ITEM_H */ diff --git a/gerbview/class_gerber_file_image.cpp b/gerbview/class_gerber_file_image.cpp index 9e30fc2220..0e35991ae7 100644 --- a/gerbview/class_gerber_file_image.cpp +++ b/gerbview/class_gerber_file_image.cpp @@ -89,7 +89,8 @@ void GERBER_LAYER::ResetDefaultValues() } -GERBER_FILE_IMAGE::GERBER_FILE_IMAGE( int aLayer ) +GERBER_FILE_IMAGE::GERBER_FILE_IMAGE( int aLayer ) : + EDA_ITEM( (EDA_ITEM*)NULL, GERBER_IMAGE_T ) { m_GraphicLayer = aLayer; // Graphic layer Number m_IsVisible = true; // must be drawn @@ -126,7 +127,8 @@ GERBER_DRAW_ITEM * GERBER_FILE_IMAGE::GetItemsList() return m_Drawings; } -D_CODE* GERBER_FILE_IMAGE::GetDCODE( int aDCODE, bool aCreateIfNoExist ) + +D_CODE* GERBER_FILE_IMAGE::GetDCODEOrCreate( int aDCODE, bool aCreateIfNoExist ) { unsigned ndx = aDCODE - FIRST_DCODE; @@ -146,6 +148,19 @@ D_CODE* GERBER_FILE_IMAGE::GetDCODE( int aDCODE, bool aCreateIfNoExist ) } +D_CODE* GERBER_FILE_IMAGE::GetDCODE( int aDCODE ) const +{ + unsigned ndx = aDCODE - FIRST_DCODE; + + if( ndx < (unsigned) DIM( m_Aperture_List ) ) + { + return m_Aperture_List[ndx]; + } + + return NULL; +} + + APERTURE_MACRO* GERBER_FILE_IMAGE::FindApertureMacro( const APERTURE_MACRO& aLookup ) { APERTURE_MACRO_SET::iterator iter = m_aperture_macros.find( aLookup ); @@ -370,3 +385,43 @@ void GERBER_FILE_IMAGE::RemoveAttribute( X2_ATTRIBUTE& aAttribute ) if( aAttribute.GetPrm( 1 ).IsEmpty() || aAttribute.GetPrm( 1 ) == ".AperFunction" ) m_AperFunction.Clear(); } + + +SEARCH_RESULT GERBER_FILE_IMAGE::Visit( INSPECTOR inspector, void* testData, const KICAD_T scanTypes[] ) +{ + KICAD_T stype; + SEARCH_RESULT result = SEARCH_CONTINUE; + const KICAD_T* p = scanTypes; + bool done = false; + +#if 0 && defined(DEBUG) + std::cout << GetClass().mb_str() << ' '; +#endif + + while( !done ) + { + stype = *p; + + switch( stype ) + { + case GERBER_IMAGE_T: + case GERBER_IMAGE_LIST_T: + ++p; + break; + + case GERBER_DRAW_ITEM_T: + result = IterateForward( &m_Drawings[0], inspector, testData, p ); + ++p; + break; + + default: // catch EOT or ANY OTHER type here and return. + done = true; + break; + } + + if( result == SEARCH_QUIT ) + break; + } + + return result; +} diff --git a/gerbview/class_gerber_file_image.h b/gerbview/class_gerber_file_image.h index 6875e60e43..6d83ae91c5 100644 --- a/gerbview/class_gerber_file_image.h +++ b/gerbview/class_gerber_file_image.h @@ -95,7 +95,7 @@ private: * holds the Image data and parameters for one gerber file * and layer parameters (TODO: move them in GERBER_LAYER class */ -class GERBER_FILE_IMAGE +class GERBER_FILE_IMAGE : public EDA_ITEM { D_CODE* m_Aperture_List[TOOLS_MAX_COUNT]; ///< Dcode (Aperture) List for this layer (max 999) bool m_Exposure; ///< whether an aperture macro tool is flashed on or off @@ -180,6 +180,11 @@ public: GERBER_FILE_IMAGE( int layer ); virtual ~GERBER_FILE_IMAGE(); + wxString GetClass() const override + { + return wxT( "GERBER_FILE_IMAGE" ); + } + void Clear_GERBER_FILE_IMAGE(); /** @@ -300,7 +305,7 @@ public: /** - * Function GetDCODE + * Function GetDCODEOrCreate * returns a pointer to the D_CODE within this GERBER for the given * \a aDCODE. * @param aDCODE The numeric value of the D_CODE to look up. @@ -309,7 +314,17 @@ public: * @return D_CODE* - the one implied by the given \a aDCODE, or NULL * if the requested \a aDCODE is out of range. */ - D_CODE* GetDCODE( int aDCODE, bool aCreateIfNoExist = true ); + D_CODE* GetDCODEOrCreate( int aDCODE, bool aCreateIfNoExist = true ); + + /** + * Function GetDCODE + * returns a pointer to the D_CODE within this GERBER for the given + * \a aDCODE. + * @param aDCODE The numeric value of the D_CODE to look up. + * @return D_CODE* - the one implied by the given \a aDCODE, or NULL + * if the requested \a aDCODE is out of range. + */ + D_CODE* GetDCODE( int aDCODE ) const; /** * Function FindApertureMacro @@ -350,6 +365,15 @@ public: * only this attribute is cleared */ void RemoveAttribute( X2_ATTRIBUTE& aAttribute ); + + ///> @copydoc EDA_ITEM::Visit() + SEARCH_RESULT Visit( INSPECTOR inspector, void* testData, const KICAD_T scanTypes[] ) override; + +#if defined(DEBUG) + + void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); } + +#endif }; #endif // ifndef CLASS_GERBER_FILE_IMAGE_H diff --git a/gerbview/class_gerber_file_image_list.cpp b/gerbview/class_gerber_file_image_list.cpp index 8c89ac0647..0f034a53d9 100644 --- a/gerbview/class_gerber_file_image_list.cpp +++ b/gerbview/class_gerber_file_image_list.cpp @@ -43,7 +43,8 @@ GERBER_FILE_IMAGE_LIST s_GERBER_List; // GERBER_FILE_IMAGE_LIST is a helper class to handle a list of GERBER_FILE_IMAGE files -GERBER_FILE_IMAGE_LIST::GERBER_FILE_IMAGE_LIST() +GERBER_FILE_IMAGE_LIST::GERBER_FILE_IMAGE_LIST() : + EDA_ITEM( (EDA_ITEM*)NULL, GERBER_IMAGE_LIST_T ) { m_GERBER_List.reserve( GERBER_DRAWLAYERS_COUNT ); @@ -244,4 +245,3 @@ void GERBER_FILE_IMAGE_LIST::SortImagesByZOrder() gerber->m_GraphicLayer = layer ; } } - diff --git a/gerbview/class_gerber_file_image_list.h b/gerbview/class_gerber_file_image_list.h index dd4c2baf16..ddd765ffd0 100644 --- a/gerbview/class_gerber_file_image_list.h +++ b/gerbview/class_gerber_file_image_list.h @@ -59,7 +59,7 @@ class GERBER_FILE_IMAGE; * which are loaded and can be displayed * there are 32 images max which can be loaded */ -class GERBER_FILE_IMAGE_LIST +class GERBER_FILE_IMAGE_LIST : public EDA_ITEM { // the list of loaded images (1 image = 1 gerber file) std::vector m_GERBER_List; @@ -68,6 +68,11 @@ public: GERBER_FILE_IMAGE_LIST(); ~GERBER_FILE_IMAGE_LIST(); + wxString GetClass() const override + { + return wxT( "GERBER_FILE_IMAGE_LIST" ); + } + //Accessor static GERBER_FILE_IMAGE_LIST& GetImagesList(); GERBER_FILE_IMAGE* GetGbrImage( int aIdx ); @@ -115,6 +120,12 @@ public: * (SortImagesByZOrder updates the graphic layer of these items) */ void SortImagesByZOrder(); + + #if defined(DEBUG) + + void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); } + + #endif }; #endif // ifndef CLASS_GERBER_FILE_IMAGE_LIST_H diff --git a/gerbview/class_gerbview_layer_widget.cpp b/gerbview/class_gerbview_layer_widget.cpp index e67a8a5fd9..f5ef8b9b10 100644 --- a/gerbview/class_gerbview_layer_widget.cpp +++ b/gerbview/class_gerbview_layer_widget.cpp @@ -41,6 +41,10 @@ #include #include +#include +#include +#include + /* * Class GERBER_LAYER_WIDGET @@ -80,6 +84,12 @@ GERBER_FILE_IMAGE_LIST* GERBER_LAYER_WIDGET::GetImagesList() } +bool GERBER_LAYER_WIDGET::AreArbitraryColorsAllowed() +{ + return myframe->IsGalCanvasActive(); +} + + void GERBER_LAYER_WIDGET::SetLayersManagerTabsText( ) { m_notebook->SetPageText(0, _("Layer") ); @@ -180,8 +190,11 @@ void GERBER_LAYER_WIDGET::onPopupSelection( wxCommandEvent& event ) int layer = getDecodedId( cb->GetId() ); bool loc_visible = visible; - if( force_active_layer_visible && (layer == myframe->getActiveLayer() ) ) + if( force_active_layer_visible && + (layer == GERBER_DRAW_LAYER( myframe->GetActiveLayer() ) ) ) + { loc_visible = true; + } cb->SetValue( loc_visible ); @@ -228,8 +241,19 @@ void GERBER_LAYER_WIDGET::ReFill() { wxString msg = GetImagesList()->GetDisplayName( layer ); - AppendLayerRow( LAYER_WIDGET::ROW( msg, layer, - myframe->GetLayerColor( layer ), wxEmptyString, true ) ); + bool visible = true; + if( auto canvas = myframe->GetGalCanvas() ) + { + visible = canvas->GetView()->IsLayerVisible( GERBER_DRAW_LAYER( layer ) ); + } + else + { + visible = myframe->IsLayerVisible( layer ); + } + + AppendLayerRow( LAYER_WIDGET::ROW( msg, GERBER_DRAW_LAYER( layer ), + myframe->GetLayerColor( GERBER_DRAW_LAYER( layer ) ), + wxEmptyString, visible, true ) ); } Thaw(); @@ -246,6 +270,14 @@ void GERBER_LAYER_WIDGET::OnLayerColorChange( int aLayer, COLOR4D aColor ) { myframe->SetLayerColor( aLayer, aColor ); myframe->m_SelLayerBox->ResyncBitmapOnly(); + + if( myframe->IsGalCanvasActive() ) + { + KIGFX::VIEW* view = myframe->GetGalCanvas()->GetView(); + view->GetPainter()->GetSettings()->ImportLegacyColors( myframe->m_colorsSettings ); + view->UpdateLayerColor( aLayer ); + } + myframe->GetCanvas()->Refresh(); } @@ -253,11 +285,13 @@ bool GERBER_LAYER_WIDGET::OnLayerSelect( int aLayer ) { // the layer change from the GERBER_LAYER_WIDGET can be denied by returning // false from this function. - int layer = myframe->getActiveLayer( ); - myframe->setActiveLayer( aLayer, false ); + int layer = myframe->GetActiveLayer( ); + // TODO(JE) ActiveLayer is stored as an index from 0 rather than as a layer + // id matching GERBER_DRAW_LAYER( idx ), is this what we want long-term? + myframe->SetActiveLayer( GERBER_DRAW_LAYER_INDEX( aLayer ), false ); myframe->syncLayerBox(); - if( layer != myframe->getActiveLayer( ) ) + if( layer != myframe->GetActiveLayer( ) ) { if( ! OnLayerSelected() ) myframe->GetCanvas()->Refresh(); @@ -284,13 +318,48 @@ void GERBER_LAYER_WIDGET::OnLayerVisible( int aLayer, bool isVisible, bool isFin void GERBER_LAYER_WIDGET::OnRenderColorChange( int aId, COLOR4D aColor ) { myframe->SetVisibleElementColor( (GERBVIEW_LAYER_ID) aId, aColor ); - myframe->GetCanvas()->Refresh(); + + auto galCanvas = myframe->GetGalCanvas(); + + if( galCanvas && myframe->IsGalCanvasActive() ) + { + auto view = galCanvas->GetView(); + view->GetPainter()->GetSettings()->ImportLegacyColors( myframe->m_colorsSettings ); + view->UpdateLayerColor( aId ); + // TODO(JE) Why are the below two lines needed? Not needed in pcbnew + view->MarkTargetDirty( KIGFX::TARGET_NONCACHED ); + view->RecacheAllItems(); + } + + if( galCanvas && myframe->IsGalCanvasActive() ) + galCanvas->Refresh(); + else + myframe->GetCanvas()->Refresh(); } void GERBER_LAYER_WIDGET::OnRenderEnable( int aId, bool isEnabled ) { myframe->SetElementVisibility( (GERBVIEW_LAYER_ID) aId, isEnabled ); - myframe->GetCanvas()->Refresh(); + + auto galCanvas = myframe->GetGalCanvas(); + + if( galCanvas ) + { + if( aId == LAYER_GERBVIEW_GRID ) + { + galCanvas->GetGAL()->SetGridVisibility( myframe->IsGridVisible() ); + galCanvas->GetView()->MarkTargetDirty( KIGFX::TARGET_NONCACHED ); + // TODO(JE) Why is the below line needed? Not needed in pcbnew + galCanvas->GetView()->RecacheAllItems(); + } + else + galCanvas->GetView()->SetLayerVisible( aId, isEnabled ); + } + + if( galCanvas && myframe->IsGalCanvasActive() ) + galCanvas->Refresh(); + else + myframe->GetCanvas()->Refresh(); } //----------------------------------------------- diff --git a/gerbview/class_gerbview_layer_widget.h b/gerbview/class_gerbview_layer_widget.h index 3ef8870bf9..8f8e031333 100644 --- a/gerbview/class_gerbview_layer_widget.h +++ b/gerbview/class_gerbview_layer_widget.h @@ -65,6 +65,8 @@ class GERBER_LAYER_WIDGET : public LAYER_WIDGET */ virtual bool useAlternateBitmap(int aRow) override; + virtual bool AreArbitraryColorsAllowed() override; + GERBER_FILE_IMAGE_LIST* GetImagesList(); public: diff --git a/gerbview/clear_gbr_drawlayers.cpp b/gerbview/clear_gbr_drawlayers.cpp index 112afc223a..bba59750ec 100644 --- a/gerbview/clear_gbr_drawlayers.cpp +++ b/gerbview/clear_gbr_drawlayers.cpp @@ -35,6 +35,7 @@ #include #include #include +#include bool GERBVIEW_FRAME::Clear_DrawLayers( bool query ) { @@ -47,11 +48,16 @@ bool GERBVIEW_FRAME::Clear_DrawLayers( bool query ) return false; } + if( auto canvas = GetGalCanvas() ) + { + canvas->GetView()->Clear(); + } + GetImagesList()->DeleteAllImages(); GetGerberLayout()->SetBoundingBox( EDA_RECT() ); - setActiveLayer( 0 ); + SetActiveLayer( 0 ); ReFillLayerWidget(); syncLayerBox(); return true; @@ -60,7 +66,7 @@ bool GERBVIEW_FRAME::Clear_DrawLayers( bool query ) void GERBVIEW_FRAME::Erase_Current_DrawLayer( bool query ) { - int layer = getActiveLayer(); + int layer = GetActiveLayer(); wxString msg; msg.Printf( _( "Clear layer %d?" ), layer + 1 ); diff --git a/gerbview/dcode.cpp b/gerbview/dcode.cpp index b7cd055cb7..847a6835c3 100644 --- a/gerbview/dcode.cpp +++ b/gerbview/dcode.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #define DCODE_DEFAULT_SIZE Millimeter2iu( 0.1 ) @@ -87,7 +88,7 @@ void D_CODE::Clear_D_CODE_Data() m_Macro = NULL; m_Rotation = 0.0; m_EdgesCount = 0; - m_PolyCorners.clear(); + m_Polygon.RemoveAllContours(); } @@ -173,7 +174,7 @@ void D_CODE::DrawFlashedShape( GERBER_DRAW_ITEM* aParent, GRFilledCircle( aClipBox, aDC, aParent->GetABPosition(aShapePos), radius, aColor ); } - else if( APT_DEF_ROUND_HOLE == 1 ) // round hole in shape + else if( m_DrillShape == APT_DEF_ROUND_HOLE ) // round hole in shape { int width = (m_Size.x - m_Drill.x ) / 2; GRCircle( aClipBox, aDC, aParent->GetABPosition(aShapePos), @@ -181,7 +182,7 @@ void D_CODE::DrawFlashedShape( GERBER_DRAW_ITEM* aParent, } else // rectangular hole { - if( m_PolyCorners.size() == 0 ) + if( m_Polygon.OutlineCount() == 0 ) ConvertShapeToPolygon(); DrawFlashedPolygon( aParent, aClipBox, aDC, aColor, aFilledShape, aShapePos ); @@ -207,7 +208,7 @@ void D_CODE::DrawFlashedShape( GERBER_DRAW_ITEM* aParent, } else { - if( m_PolyCorners.size() == 0 ) + if( m_Polygon.OutlineCount() == 0 ) ConvertShapeToPolygon(); DrawFlashedPolygon( aParent, aClipBox, aDC, aColor, aFilledShape, aShapePos ); @@ -248,7 +249,7 @@ void D_CODE::DrawFlashedShape( GERBER_DRAW_ITEM* aParent, } else { - if( m_PolyCorners.size() == 0 ) + if( m_Polygon.OutlineCount() == 0 ) ConvertShapeToPolygon(); DrawFlashedPolygon( aParent, aClipBox, aDC, aColor, aFilledShape, aShapePos ); @@ -257,7 +258,7 @@ void D_CODE::DrawFlashedShape( GERBER_DRAW_ITEM* aParent, break; case APT_POLYGON: - if( m_PolyCorners.size() == 0 ) + if( m_Polygon.OutlineCount() == 0 ) ConvertShapeToPolygon(); DrawFlashedPolygon( aParent, aClipBox, aDC, aColor, aFilledShape, aShapePos ); @@ -271,27 +272,29 @@ void D_CODE::DrawFlashedPolygon( GERBER_DRAW_ITEM* aParent, COLOR4D aColor, bool aFilled, const wxPoint& aPosition ) { - if( m_PolyCorners.size() == 0 ) + if( m_Polygon.OutlineCount() == 0 ) return; + int pointCount = m_Polygon.VertexCount(); std::vector points; - points = m_PolyCorners; + points.reserve( pointCount ); - for( unsigned ii = 0; ii < points.size(); ii++ ) + for( int ii = 0; ii < pointCount; ii++ ) { - points[ii] += aPosition; + wxPoint p( m_Polygon.Vertex( ii ).x, m_Polygon.Vertex( ii ).y ); + points[ii] = p + aPosition; points[ii] = aParent->GetABPosition( points[ii] ); } - GRClosedPoly( aClipBox, aDC, points.size(), &points[0], aFilled, aColor, aColor ); + GRClosedPoly( aClipBox, aDC, pointCount, &points[0], aFilled, aColor, aColor ); } -#define SEGS_CNT 32 // number of segments to approximate a circle +#define SEGS_CNT 64 // number of segments to approximate a circle // A helper function for D_CODE::ConvertShapeToPolygon(). Add a hole to a polygon -static void addHoleToPolygon( std::vector& aBuffer, +static void addHoleToPolygon( SHAPE_POLY_SET* aPolygon, APERTURE_DEF_HOLETYPE aHoleShape, wxSize aSize, wxPoint aAnchorPos ); @@ -302,43 +305,37 @@ void D_CODE::ConvertShapeToPolygon() wxPoint initialpos; wxPoint currpos; - m_PolyCorners.clear(); + m_Polygon.RemoveAllContours(); switch( m_Shape ) { case APT_CIRCLE: // creates only a circle with rectangular hole - currpos.x = m_Size.x >> 1; - initialpos = currpos; - - for( unsigned ii = 0; ii <= SEGS_CNT; ii++ ) - { - currpos = initialpos; - RotatePoint( &currpos, ii * 3600.0 / SEGS_CNT ); - m_PolyCorners.push_back( currpos ); - } - - addHoleToPolygon( m_PolyCorners, m_DrillShape, m_Drill, initialpos ); + TransformCircleToPolygon( m_Polygon, initialpos, m_Size.x >> 1, SEGS_CNT ); + addHoleToPolygon( &m_Polygon, m_DrillShape, m_Drill, initialpos ); break; case APT_RECT: + m_Polygon.NewOutline(); currpos.x = m_Size.x / 2; currpos.y = m_Size.y / 2; initialpos = currpos; - m_PolyCorners.push_back( currpos ); + m_Polygon.Append( VECTOR2I( currpos ) ); currpos.x -= m_Size.x; - m_PolyCorners.push_back( currpos ); + m_Polygon.Append( VECTOR2I( currpos ) ); currpos.y -= m_Size.y; - m_PolyCorners.push_back( currpos ); + m_Polygon.Append( VECTOR2I( currpos ) ); currpos.x += m_Size.x; - m_PolyCorners.push_back( currpos ); + m_Polygon.Append( VECTOR2I( currpos ) ); currpos.y += m_Size.y; - m_PolyCorners.push_back( currpos ); // close polygon + m_Polygon.Append( VECTOR2I( currpos ) ); // close polygon + m_Polygon.Append( VECTOR2I( initialpos ) ); - addHoleToPolygon( m_PolyCorners, m_DrillShape, m_Drill, initialpos ); + addHoleToPolygon( &m_Polygon, m_DrillShape, m_Drill, initialpos ); break; case APT_OVAL: { + m_Polygon.NewOutline(); int delta, radius; // we create an horizontal oval shape. then rotate if needed @@ -355,7 +352,7 @@ void D_CODE::ConvertShapeToPolygon() currpos.y = radius; initialpos = currpos; - m_PolyCorners.push_back( currpos ); + m_Polygon.Append( VECTOR2I( currpos ) ); // build the right arc of the shape unsigned ii = 0; @@ -365,7 +362,7 @@ void D_CODE::ConvertShapeToPolygon() currpos = initialpos; RotatePoint( &currpos, ii * 3600.0 / SEGS_CNT ); currpos.x += delta; - m_PolyCorners.push_back( currpos ); + m_Polygon.Append( VECTOR2I( currpos ) ); } // build the left arc of the shape @@ -374,22 +371,23 @@ void D_CODE::ConvertShapeToPolygon() currpos = initialpos; RotatePoint( &currpos, ii * 3600.0 / SEGS_CNT ); currpos.x -= delta; - m_PolyCorners.push_back( currpos ); + m_Polygon.Append( VECTOR2I( currpos ) ); } - m_PolyCorners.push_back( initialpos ); // close outline + m_Polygon.Append( VECTOR2I( initialpos ) ); // close outline if( m_Size.y > m_Size.x ) // vertical oval, rotate polygon. { - for( unsigned jj = 0; jj < m_PolyCorners.size(); jj++ ) - RotatePoint( &m_PolyCorners[jj], 900 ); + for( auto it = m_Polygon.Iterate( 0 ); it; ++it ) + it->Rotate( -M_PI / 2 ); } - addHoleToPolygon( m_PolyCorners, m_DrillShape, m_Drill, initialpos ); + addHoleToPolygon( &m_Polygon, m_DrillShape, m_Drill, initialpos ); } break; case APT_POLYGON: + m_Polygon.NewOutline(); currpos.x = m_Size.x >> 1; // first point is on X axis initialpos = currpos; @@ -400,23 +398,21 @@ void D_CODE::ConvertShapeToPolygon() if( m_EdgesCount > 12 ) m_EdgesCount = 12; - for( int ii = 0; ii <= m_EdgesCount; ii++ ) + for( int ii = 0; ii < m_EdgesCount; ii++ ) { currpos = initialpos; RotatePoint( &currpos, ii * 3600.0 / m_EdgesCount ); - m_PolyCorners.push_back( currpos ); + m_Polygon.Append( VECTOR2I( currpos ) ); } - addHoleToPolygon( m_PolyCorners, m_DrillShape, m_Drill, initialpos ); + addHoleToPolygon( &m_Polygon, m_DrillShape, m_Drill, initialpos ); if( m_Rotation ) // vertical oval, rotate polygon. { int angle = KiROUND( m_Rotation * 10 ); - for( unsigned jj = 0; jj < m_PolyCorners.size(); jj++ ) - { - RotatePoint( &m_PolyCorners[jj], -angle ); - } + for( auto it = m_Polygon.Iterate( 0 ); it; ++it ) + it->Rotate( -angle ); } break; @@ -431,39 +427,36 @@ void D_CODE::ConvertShapeToPolygon() // The helper function for D_CODE::ConvertShapeToPolygon(). // Add a hole to a polygon -static void addHoleToPolygon( std::vector& aBuffer, +static void addHoleToPolygon( SHAPE_POLY_SET* aPolygon, APERTURE_DEF_HOLETYPE aHoleShape, wxSize aSize, wxPoint aAnchorPos ) { wxPoint currpos; + SHAPE_POLY_SET holeBuffer; - if( aHoleShape == APT_DEF_ROUND_HOLE ) // build a round hole + if( aHoleShape == APT_DEF_ROUND_HOLE ) { - for( int ii = 0; ii <= SEGS_CNT; ii++ ) - { - currpos.x = 0; - currpos.y = aSize.x / 2; // aSize.x / 2 is the radius of the hole - RotatePoint( &currpos, ii * 3600.0 / SEGS_CNT ); - aBuffer.push_back( currpos ); - } - - aBuffer.push_back( aAnchorPos ); // link to outline + TransformCircleToPolygon( holeBuffer, wxPoint( 0, 0 ), aSize.x / 2, SEGS_CNT ); } - - if( aHoleShape == APT_DEF_RECT_HOLE ) // Create rectangular hole + else if( aHoleShape == APT_DEF_RECT_HOLE ) { + holeBuffer.NewOutline(); currpos.x = aSize.x / 2; currpos.y = aSize.y / 2; - aBuffer.push_back( currpos ); // link to hole and begin hole + holeBuffer.Append( VECTOR2I( currpos ) ); // link to hole and begin hole currpos.x -= aSize.x; - aBuffer.push_back( currpos ); + holeBuffer.Append( VECTOR2I( currpos ) ); currpos.y -= aSize.y; - aBuffer.push_back( currpos ); + holeBuffer.Append( VECTOR2I( currpos ) ); currpos.x += aSize.x; - aBuffer.push_back( currpos ); + holeBuffer.Append( VECTOR2I( currpos ) ); currpos.y += aSize.y; - aBuffer.push_back( currpos ); // close hole - aBuffer.push_back( aAnchorPos ); // link to outline + holeBuffer.Append( VECTOR2I( currpos ) ); // close hole } + + aPolygon->BooleanSubtract( holeBuffer, SHAPE_POLY_SET::PM_FAST ); + + // Needed for legacy canvas only + aPolygon->Fracture( SHAPE_POLY_SET::PM_FAST ); } diff --git a/gerbview/dcode.h b/gerbview/dcode.h index 31c98268b5..7b40e205b5 100644 --- a/gerbview/dcode.h +++ b/gerbview/dcode.h @@ -34,6 +34,7 @@ #include #include +#include using KIGFX::COLOR4D; @@ -89,11 +90,6 @@ private: */ std::vector m_am_params; - std::vector m_PolyCorners; /* Polygon used to draw APT_POLYGON shape and some other - * complex shapes which are converted to polygon - * (shapes with hole ) - */ - public: wxSize m_Size; ///< Horizontal and vertical dimensions. APERTURE_T m_Shape; ///< shape ( Line, rectangle, circle , oval .. ) @@ -108,7 +104,10 @@ public: bool m_Defined; ///< false if the aperture is not defined in the header wxString m_AperFunction; ///< the aperture attribute (created by a %TA.AperFunction command) ///< attached to the D_CODE - + SHAPE_POLY_SET m_Polygon; /* Polygon used to draw APT_POLYGON shape and some other + * complex shapes which are converted to polygon + * (shapes with hole ) + */ public: D_CODE( int num_dcode ); diff --git a/gerbview/dialogs/gerbview_dialog_display_options_frame.cpp b/gerbview/dialogs/gerbview_dialog_display_options_frame.cpp index 504d742fdd..132347752d 100644 --- a/gerbview/dialogs/gerbview_dialog_display_options_frame.cpp +++ b/gerbview/dialogs/gerbview_dialog_display_options_frame.cpp @@ -32,11 +32,18 @@ #include #include #include +#include #include #include #include +#include +#include +#include +#include +#include + /*******************************************/ /* Dialog frame to select display options */ @@ -45,6 +52,7 @@ class DIALOG_DISPLAY_OPTIONS : public DIALOG_DISPLAY_OPTIONS_BASE { private: GERBVIEW_FRAME* m_Parent; + GAL_OPTIONS_PANEL* m_galOptsPanel; public: @@ -79,6 +87,8 @@ DIALOG_DISPLAY_OPTIONS::DIALOG_DISPLAY_OPTIONS( GERBVIEW_FRAME *parent) : GetSizer()->SetSizeHints( this ); Center(); m_sdbSizer1OK->SetDefault(); + + FinishDialogSettings(); } @@ -90,23 +100,14 @@ void DIALOG_DISPLAY_OPTIONS::OnCancelButtonClick( wxCommandEvent& event ) void DIALOG_DISPLAY_OPTIONS::initOptDialog( ) { + KIGFX::GAL_DISPLAY_OPTIONS& galOptions = m_Parent->GetGalDisplayOptions(); + m_galOptsPanel = new GAL_OPTIONS_PANEL( this, galOptions ); + m_UpperSizer->Add( m_galOptsPanel, 0, wxEXPAND, 0 ); + m_galOptsPanel->TransferDataToWindow(); + m_PolarDisplay->SetSelection( m_Parent->m_DisplayOptions.m_DisplayPolarCood ? 1 : 0 ); m_BoxUnits->SetSelection( g_UserUnit ? 1 : 0 ); - // @todo: LEGACY: Cursor shape can be set using the GAL options - // widget, when that is added to gerbview. For now, access the - // setting via the frame's GAL options object directly - - // Cursor shape cannot be implemented on OS X -#ifdef __APPLE__ - m_CursorShape->Hide(); -#else - { - auto& galOpts = m_Parent->GetGalDisplayOptions(); - m_CursorShape->SetSelection( galOpts.m_fullscreenCursor ? 1 : 0 ); - } -#endif // __APPLE__ - // Show Option Draw Lines. We use DisplayPcbTrackFill as Lines draw option m_OptDisplayLines->SetSelection( m_Parent->m_DisplayOptions.m_DisplayLinesFill ? 1 : 0 ); m_OptDisplayFlashedItems->SetSelection( m_Parent->m_DisplayOptions.m_DisplayFlashedItemsFill ? 1 : 0); @@ -131,8 +132,6 @@ void DIALOG_DISPLAY_OPTIONS::initOptDialog( ) } m_OptDisplayDCodes->SetValue( m_Parent->IsElementVisible( LAYER_DCODES ) ); - - m_OptZoomNoCenter->SetValue( m_Parent->GetCanvas()->GetEnableZoomNoCenter() ); m_OptMousewheelPan->SetValue( m_Parent->GetCanvas()->GetEnableMousewheelPan() ); } @@ -140,18 +139,12 @@ void DIALOG_DISPLAY_OPTIONS::initOptDialog( ) void DIALOG_DISPLAY_OPTIONS::OnOKBUttonClick( wxCommandEvent& event ) { + auto displayOptions = (GBR_DISPLAY_OPTIONS*) m_Parent->GetDisplayOptions(); + m_Parent->m_DisplayOptions.m_DisplayPolarCood = (m_PolarDisplay->GetSelection() == 0) ? false : true; g_UserUnit = (m_BoxUnits->GetSelection() == 0) ? INCHES : MILLIMETRES; - // @todo LEGACY: as above, this should be via the GAL display widget -#ifndef __APPLE__ - { - auto& galOpts = m_Parent->GetGalDisplayOptions(); - galOpts.m_fullscreenCursor = m_CursorShape->GetSelection(); - } -#endif // !__APPLE__ - if( m_OptDisplayLines->GetSelection() == 1 ) m_Parent->m_DisplayOptions.m_DisplayLinesFill = true; else @@ -166,7 +159,6 @@ void DIALOG_DISPLAY_OPTIONS::OnOKBUttonClick( wxCommandEvent& event ) m_Parent->m_DisplayOptions.m_DisplayFlashedItemsFill = false; } - if( m_OptDisplayPolygons->GetSelection() == 0 ) m_Parent->m_DisplayOptions.m_DisplayPolygonsFill = false; else @@ -185,6 +177,16 @@ void DIALOG_DISPLAY_OPTIONS::OnOKBUttonClick( wxCommandEvent& event ) m_Parent->GetCanvas()->SetEnableZoomNoCenter( m_OptZoomNoCenter->GetValue() ); m_Parent->GetCanvas()->SetEnableMousewheelPan( m_OptMousewheelPan->GetValue() ); + m_galOptsPanel->TransferDataFromWindow(); + + // Apply changes to the GAL + auto view = m_Parent->GetGalCanvas()->GetView(); + auto painter = static_cast( view->GetPainter() ); + auto settings = static_cast( painter->GetSettings() ); + settings->LoadDisplayOptions( displayOptions ); + view->RecacheAllItems(); + view->MarkTargetDirty( KIGFX::TARGET_NONCACHED ); + m_Parent->GetCanvas()->Refresh(); EndModal( 1 ); diff --git a/gerbview/dialogs/gerbview_dialog_display_options_frame_base.cpp b/gerbview/dialogs/gerbview_dialog_display_options_frame_base.cpp index f977d04ce8..9c09480280 100644 --- a/gerbview/dialogs/gerbview_dialog_display_options_frame_base.cpp +++ b/gerbview/dialogs/gerbview_dialog_display_options_frame_base.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version May 6 2016) +// C++ code generated with wxFormBuilder (version Nov 30 2016) // http://www.wxformbuilder.org/ // // PLEASE DO "NOT" EDIT THIS FILE! @@ -16,8 +16,7 @@ DIALOG_DISPLAY_OPTIONS_BASE::DIALOG_DISPLAY_OPTIONS_BASE( wxWindow* parent, wxWi wxBoxSizer* bDialogSizer; bDialogSizer = new wxBoxSizer( wxVERTICAL ); - wxBoxSizer* bUpperSizer; - bUpperSizer = new wxBoxSizer( wxHORIZONTAL ); + m_UpperSizer = new wxBoxSizer( wxHORIZONTAL ); wxBoxSizer* bLeftSizer; bLeftSizer = new wxBoxSizer( wxVERTICAL ); @@ -34,42 +33,30 @@ DIALOG_DISPLAY_OPTIONS_BASE::DIALOG_DISPLAY_OPTIONS_BASE( wxWindow* parent, wxWi m_BoxUnits->SetSelection( 0 ); bLeftSizer->Add( m_BoxUnits, 0, wxALL|wxEXPAND, 5 ); - wxString m_CursorShapeChoices[] = { _("Small cross"), _("Full screen cursor") }; - int m_CursorShapeNChoices = sizeof( m_CursorShapeChoices ) / sizeof( wxString ); - m_CursorShape = new wxRadioBox( this, wxID_ANY, _("Cursor"), wxDefaultPosition, wxDefaultSize, m_CursorShapeNChoices, m_CursorShapeChoices, 1, wxRA_SPECIFY_COLS ); - m_CursorShape->SetSelection( 1 ); - bLeftSizer->Add( m_CursorShape, 0, wxALL|wxEXPAND, 5 ); + wxString m_OptDisplayFlashedItemsChoices[] = { _("Sketch"), _("Filled") }; + int m_OptDisplayFlashedItemsNChoices = sizeof( m_OptDisplayFlashedItemsChoices ) / sizeof( wxString ); + m_OptDisplayFlashedItems = new wxRadioBox( this, wxID_ANY, _("Flashed items"), wxDefaultPosition, wxDefaultSize, m_OptDisplayFlashedItemsNChoices, m_OptDisplayFlashedItemsChoices, 1, wxRA_SPECIFY_COLS ); + m_OptDisplayFlashedItems->SetSelection( 1 ); + bLeftSizer->Add( m_OptDisplayFlashedItems, 0, wxALL|wxEXPAND, 5 ); + + wxString m_OptDisplayLinesChoices[] = { _("Sketch"), _("Filled") }; + int m_OptDisplayLinesNChoices = sizeof( m_OptDisplayLinesChoices ) / sizeof( wxString ); + m_OptDisplayLines = new wxRadioBox( this, wxID_ANY, _("Lines"), wxDefaultPosition, wxDefaultSize, m_OptDisplayLinesNChoices, m_OptDisplayLinesChoices, 1, wxRA_SPECIFY_COLS ); + m_OptDisplayLines->SetSelection( 1 ); + bLeftSizer->Add( m_OptDisplayLines, 0, wxALL|wxEXPAND, 5 ); + + wxString m_OptDisplayPolygonsChoices[] = { _("Sketch"), _("Filled") }; + int m_OptDisplayPolygonsNChoices = sizeof( m_OptDisplayPolygonsChoices ) / sizeof( wxString ); + m_OptDisplayPolygons = new wxRadioBox( this, wxID_ANY, _("Polygons"), wxDefaultPosition, wxDefaultSize, m_OptDisplayPolygonsNChoices, m_OptDisplayPolygonsChoices, 1, wxRA_SPECIFY_COLS ); + m_OptDisplayPolygons->SetSelection( 1 ); + bLeftSizer->Add( m_OptDisplayPolygons, 0, wxALL|wxEXPAND, 5 ); m_OptDisplayDCodes = new wxCheckBox( this, wxID_ANY, _("Show D codes"), wxDefaultPosition, wxDefaultSize, 0 ); m_OptDisplayDCodes->SetValue(true); bLeftSizer->Add( m_OptDisplayDCodes, 0, wxALL, 5 ); - bUpperSizer->Add( bLeftSizer, 1, wxALL|wxEXPAND, 5 ); - - wxBoxSizer* bMiddleSizer; - bMiddleSizer = new wxBoxSizer( wxVERTICAL ); - - wxString m_OptDisplayLinesChoices[] = { _("Sketch"), _("Filled") }; - int m_OptDisplayLinesNChoices = sizeof( m_OptDisplayLinesChoices ) / sizeof( wxString ); - m_OptDisplayLines = new wxRadioBox( this, wxID_ANY, _("Lines"), wxDefaultPosition, wxDefaultSize, m_OptDisplayLinesNChoices, m_OptDisplayLinesChoices, 1, wxRA_SPECIFY_COLS ); - m_OptDisplayLines->SetSelection( 1 ); - bMiddleSizer->Add( m_OptDisplayLines, 0, wxALL|wxEXPAND, 5 ); - - wxString m_OptDisplayFlashedItemsChoices[] = { _("Sketch"), _("Filled") }; - int m_OptDisplayFlashedItemsNChoices = sizeof( m_OptDisplayFlashedItemsChoices ) / sizeof( wxString ); - m_OptDisplayFlashedItems = new wxRadioBox( this, wxID_ANY, _("Flashed items"), wxDefaultPosition, wxDefaultSize, m_OptDisplayFlashedItemsNChoices, m_OptDisplayFlashedItemsChoices, 1, wxRA_SPECIFY_COLS ); - m_OptDisplayFlashedItems->SetSelection( 1 ); - bMiddleSizer->Add( m_OptDisplayFlashedItems, 0, wxALL|wxEXPAND, 5 ); - - wxString m_OptDisplayPolygonsChoices[] = { _("Sketch"), _("Filled") }; - int m_OptDisplayPolygonsNChoices = sizeof( m_OptDisplayPolygonsChoices ) / sizeof( wxString ); - m_OptDisplayPolygons = new wxRadioBox( this, wxID_ANY, _("Polygons"), wxDefaultPosition, wxDefaultSize, m_OptDisplayPolygonsNChoices, m_OptDisplayPolygonsChoices, 1, wxRA_SPECIFY_COLS ); - m_OptDisplayPolygons->SetSelection( 1 ); - bMiddleSizer->Add( m_OptDisplayPolygons, 0, wxALL|wxEXPAND, 5 ); - - - bUpperSizer->Add( bMiddleSizer, 1, wxALL|wxEXPAND, 5 ); + m_UpperSizer->Add( bLeftSizer, 1, wxALL|wxEXPAND, 5 ); wxBoxSizer* bRightSizer; bRightSizer = new wxBoxSizer( wxVERTICAL ); @@ -97,10 +84,10 @@ DIALOG_DISPLAY_OPTIONS_BASE::DIALOG_DISPLAY_OPTIONS_BASE( wxWindow* parent, wxWi bRightSizer->Add( bLeftBottomSizer, 0, wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT, 5 ); - bUpperSizer->Add( bRightSizer, 2, wxALL|wxEXPAND, 5 ); + m_UpperSizer->Add( bRightSizer, 2, wxALL|wxEXPAND, 5 ); - bDialogSizer->Add( bUpperSizer, 1, wxEXPAND, 5 ); + bDialogSizer->Add( m_UpperSizer, 1, wxEXPAND, 5 ); m_staticline1 = new wxStaticLine( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL ); bDialogSizer->Add( m_staticline1, 0, wxEXPAND|wxLEFT|wxRIGHT, 5 ); diff --git a/gerbview/dialogs/gerbview_dialog_display_options_frame_base.fbp b/gerbview/dialogs/gerbview_dialog_display_options_frame_base.fbp index 1eafe8b81e..5581a3d0a0 100644 --- a/gerbview/dialogs/gerbview_dialog_display_options_frame_base.fbp +++ b/gerbview/dialogs/gerbview_dialog_display_options_frame_base.fbp @@ -99,9 +99,9 @@ 1 - bUpperSizer + m_UpperSizer wxHORIZONTAL - none + protected 5 wxALL|wxEXPAND @@ -309,7 +309,7 @@ 1 0 - "Small cross" "Full screen cursor" + "Sketch" "Filled" 1 1 @@ -324,7 +324,7 @@ 0 0 wxID_ANY - Cursor + Flashed items 1 0 @@ -333,7 +333,7 @@ 0 1 - m_CursorShape + m_OptDisplayFlashedItems 1 @@ -381,105 +381,6 @@ - - 5 - wxALL - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Show D codes - - 0 - - - 0 - - 1 - m_OptDisplayDCodes - 1 - - - protected - 1 - - Resizable - 1 - - - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 - wxALL|wxEXPAND - 1 - - - bMiddleSizer - wxVERTICAL - none 5 wxALL|wxEXPAND @@ -570,96 +471,6 @@ - - 5 - wxALL|wxEXPAND - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - "Sketch" "Filled" - 1 - - 1 - 0 - Dock - 0 - Left - 1 - - 1 - - 0 - 0 - wxID_ANY - Flashed items - 1 - - 0 - - - 0 - - 1 - m_OptDisplayFlashedItems - 1 - - - protected - 1 - - Resizable - 1 - 1 - - wxRA_SPECIFY_COLS - - 0 - - - wxFILTER_NONE - wxDefaultValidator - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 5 wxALL|wxEXPAND @@ -750,6 +561,94 @@ + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Show D codes + + 0 + + + 0 + + 1 + m_OptDisplayDCodes + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gerbview/dialogs/gerbview_dialog_display_options_frame_base.h b/gerbview/dialogs/gerbview_dialog_display_options_frame_base.h index d9eae92426..a240107770 100644 --- a/gerbview/dialogs/gerbview_dialog_display_options_frame_base.h +++ b/gerbview/dialogs/gerbview_dialog_display_options_frame_base.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version May 6 2016) +// C++ code generated with wxFormBuilder (version Nov 30 2016) // http://www.wxformbuilder.org/ // // PLEASE DO "NOT" EDIT THIS FILE! @@ -38,13 +38,13 @@ class DIALOG_DISPLAY_OPTIONS_BASE : public DIALOG_SHIM private: protected: + wxBoxSizer* m_UpperSizer; wxRadioBox* m_PolarDisplay; wxRadioBox* m_BoxUnits; - wxRadioBox* m_CursorShape; - wxCheckBox* m_OptDisplayDCodes; - wxRadioBox* m_OptDisplayLines; wxRadioBox* m_OptDisplayFlashedItems; + wxRadioBox* m_OptDisplayLines; wxRadioBox* m_OptDisplayPolygons; + wxCheckBox* m_OptDisplayDCodes; wxRadioBox* m_ShowPageLimits; wxCheckBox* m_OptZoomNoCenter; wxCheckBox* m_OptMousewheelPan; diff --git a/gerbview/draw_gerber_screen.cpp b/gerbview/draw_gerber_screen.cpp index 64c630c4a8..f1a7ea6bcf 100644 --- a/gerbview/draw_gerber_screen.cpp +++ b/gerbview/draw_gerber_screen.cpp @@ -135,7 +135,16 @@ void GERBVIEW_FRAME::RedrawActiveWindow( wxDC* DC, bool EraseBg ) if( IsShown() ) { m_overlay.Reset(); - wxDCOverlay overlaydc( m_overlay, (wxWindowDC*)DC ); + + // On macOS, the call to create overlaydc fails for some reason due to + // the DC having zero size initially. + wxCoord w = 0, h = 0; + ( (wxWindowDC*)DC )->GetSize( &w, &h ); + if( w == 0 || h == 0) + { + w = h = 1; + } + wxDCOverlay overlaydc( m_overlay, (wxWindowDC*)DC, 0, 0, 1, 1 ); overlaydc.Clear(); } #endif diff --git a/gerbview/events_called_functions.cpp b/gerbview/events_called_functions.cpp index 4e70219014..3108152795 100644 --- a/gerbview/events_called_functions.cpp +++ b/gerbview/events_called_functions.cpp @@ -43,6 +43,10 @@ #include #include +#include +#include +#include + // Event table: @@ -83,6 +87,12 @@ BEGIN_EVENT_TABLE( GERBVIEW_FRAME, EDA_DRAW_FRAME ) EVT_MENU( ID_MENU_GERBVIEW_SHOW_HIDE_LAYERS_MANAGER_DIALOG, GERBVIEW_FRAME::OnSelectOptionToolbar ) EVT_MENU( wxID_PREFERENCES, GERBVIEW_FRAME::InstallGerberOptionsDialog ) + EVT_UPDATE_UI( ID_MENU_CANVAS_LEGACY, GERBVIEW_FRAME::OnUpdateSwitchCanvas ) + EVT_UPDATE_UI( ID_MENU_CANVAS_CAIRO, GERBVIEW_FRAME::OnUpdateSwitchCanvas ) + EVT_UPDATE_UI( ID_MENU_CANVAS_OPENGL, GERBVIEW_FRAME::OnUpdateSwitchCanvas ) + EVT_MENU( ID_MENU_CANVAS_LEGACY, GERBVIEW_FRAME::SwitchCanvas ) + EVT_MENU( ID_MENU_CANVAS_CAIRO, GERBVIEW_FRAME::SwitchCanvas ) + EVT_MENU( ID_MENU_CANVAS_OPENGL, GERBVIEW_FRAME::SwitchCanvas ) // menu Postprocess EVT_MENU( ID_GERBVIEW_SHOW_LIST_DCODES, GERBVIEW_FRAME::Process_Special_Functions ) @@ -115,6 +125,7 @@ BEGIN_EVENT_TABLE( GERBVIEW_FRAME, EDA_DRAW_FRAME ) // Option toolbar //EVT_TOOL( ID_NO_TOOL_SELECTED, GERBVIEW_FRAME::Process_Special_Functions ) // mentioned below EVT_TOOL( ID_ZOOM_SELECTION, GERBVIEW_FRAME::Process_Special_Functions ) + EVT_TOOL( ID_TB_MEASUREMENT_TOOL, GERBVIEW_FRAME::Process_Special_Functions ) EVT_TOOL( ID_TB_OPTIONS_SHOW_POLAR_COORD, GERBVIEW_FRAME::OnSelectOptionToolbar ) EVT_TOOL( ID_TB_OPTIONS_SHOW_POLYGONS_SKETCH, GERBVIEW_FRAME::OnSelectOptionToolbar ) EVT_TOOL( ID_TB_OPTIONS_SHOW_FLASHED_ITEMS_SKETCH, GERBVIEW_FRAME::OnSelectOptionToolbar ) @@ -125,11 +136,13 @@ BEGIN_EVENT_TABLE( GERBVIEW_FRAME, EDA_DRAW_FRAME ) EVT_TOOL( ID_TB_OPTIONS_SHOW_NEGATIVE_ITEMS, GERBVIEW_FRAME::OnSelectOptionToolbar ) EVT_TOOL_RANGE( ID_TB_OPTIONS_SHOW_GBR_MODE_0, ID_TB_OPTIONS_SHOW_GBR_MODE_2, GERBVIEW_FRAME::OnSelectDisplayMode ) + EVT_TOOL( ID_TB_OPTIONS_DIFF_MODE, GERBVIEW_FRAME::OnSelectOptionToolbar ) + EVT_TOOL( ID_TB_OPTIONS_HIGH_CONTRAST_MODE, GERBVIEW_FRAME::OnSelectOptionToolbar ) // Auxiliary horizontal toolbar - EVT_CHOICE( ID_GBR_AUX_TOOLBAR_PCB_CMP_CHOICE, GERBVIEW_FRAME::Process_Special_Functions ) - EVT_CHOICE( ID_GBR_AUX_TOOLBAR_PCB_NET_CHOICE, GERBVIEW_FRAME::Process_Special_Functions ) - EVT_CHOICE( ID_GBR_AUX_TOOLBAR_PCB_APERATTRIBUTES_CHOICE, GERBVIEW_FRAME::Process_Special_Functions ) + EVT_CHOICE( ID_GBR_AUX_TOOLBAR_PCB_CMP_CHOICE, GERBVIEW_FRAME::OnSelectHighlightChoice ) + EVT_CHOICE( ID_GBR_AUX_TOOLBAR_PCB_NET_CHOICE, GERBVIEW_FRAME::OnSelectHighlightChoice ) + EVT_CHOICE( ID_GBR_AUX_TOOLBAR_PCB_APERATTRIBUTES_CHOICE, GERBVIEW_FRAME::OnSelectHighlightChoice ) // Right click context menu EVT_MENU( ID_HIGHLIGHT_CMP_ITEMS, GERBVIEW_FRAME::Process_Special_Functions ) @@ -139,6 +152,7 @@ BEGIN_EVENT_TABLE( GERBVIEW_FRAME, EDA_DRAW_FRAME ) EVT_UPDATE_UI( ID_NO_TOOL_SELECTED, GERBVIEW_FRAME::OnUpdateSelectTool ) EVT_UPDATE_UI( ID_ZOOM_SELECTION, GERBVIEW_FRAME::OnUpdateSelectTool ) + EVT_UPDATE_UI( ID_TB_MEASUREMENT_TOOL, GERBVIEW_FRAME::OnUpdateSelectTool ) EVT_UPDATE_UI( ID_TB_OPTIONS_SHOW_POLAR_COORD, GERBVIEW_FRAME::OnUpdateCoordType ) EVT_UPDATE_UI( ID_TB_OPTIONS_SHOW_FLASHED_ITEMS_SKETCH, GERBVIEW_FRAME::OnUpdateFlashedItemsDrawMode ) @@ -223,6 +237,10 @@ void GERBVIEW_FRAME::Process_Special_Functions( wxCommandEvent& event ) SetNoToolSelected(); break; + case ID_TB_MEASUREMENT_TOOL: + SetToolID( id, wxCURSOR_DEFAULT, _( "Unsupported tool in this canvas" ) ); + break; + case ID_POPUP_CLOSE_CURRENT_TOOL: SetToolID( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor(), wxEmptyString ); break; @@ -246,12 +264,6 @@ void GERBVIEW_FRAME::Process_Special_Functions( wxCommandEvent& event ) HandleBlockEnd( &dc ); break; - case ID_GBR_AUX_TOOLBAR_PCB_CMP_CHOICE: - case ID_GBR_AUX_TOOLBAR_PCB_NET_CHOICE: - case ID_GBR_AUX_TOOLBAR_PCB_APERATTRIBUTES_CHOICE: - m_canvas->Refresh(); - break; - case ID_HIGHLIGHT_CMP_ITEMS: if( m_SelComponentBox->SetStringSelection( currItem->GetNetAttributes().m_Cmpref ) ) m_canvas->Refresh(); @@ -275,8 +287,8 @@ void GERBVIEW_FRAME::Process_Special_Functions( wxCommandEvent& event ) m_SelNetnameBox->SetSelection( 0 ); m_SelAperAttributesBox->SetSelection( 0 ); - if( GetGbrImage( getActiveLayer() ) ) - GetGbrImage( getActiveLayer() )->m_Selected_Tool = 0; + if( GetGbrImage( GetActiveLayer() ) ) + GetGbrImage( GetActiveLayer() )->m_Selected_Tool = 0; m_canvas->Refresh(); break; @@ -288,9 +300,40 @@ void GERBVIEW_FRAME::Process_Special_Functions( wxCommandEvent& event ) } +// Handles the changing of the highlighted component/net/attribute +void GERBVIEW_FRAME::OnSelectHighlightChoice( wxCommandEvent& event ) +{ + if( IsGalCanvasActive() ) + { + auto settings = static_cast( GetGalCanvas()->GetView()->GetPainter() )->GetSettings(); + + switch( event.GetId() ) + { + case ID_GBR_AUX_TOOLBAR_PCB_CMP_CHOICE: + settings->m_componentHighlightString = m_SelComponentBox->GetStringSelection(); + break; + + case ID_GBR_AUX_TOOLBAR_PCB_NET_CHOICE: + settings->m_netHighlightString = m_SelNetnameBox->GetStringSelection(); + break; + + case ID_GBR_AUX_TOOLBAR_PCB_APERATTRIBUTES_CHOICE: + settings->m_attributeHighlightString = m_SelAperAttributesBox->GetStringSelection(); + break; + + } + + GetGalCanvas()->GetView()->RecacheAllItems(); + GetGalCanvas()->Refresh(); + } + else + m_canvas->Refresh(); +} + + void GERBVIEW_FRAME::OnSelectActiveDCode( wxCommandEvent& event ) { - GERBER_FILE_IMAGE* gerber_image = GetGbrImage( getActiveLayer() ); + GERBER_FILE_IMAGE* gerber_image = GetGbrImage( GetActiveLayer() ); if( gerber_image ) { @@ -307,11 +350,11 @@ void GERBVIEW_FRAME::OnSelectActiveDCode( wxCommandEvent& event ) void GERBVIEW_FRAME::OnSelectActiveLayer( wxCommandEvent& event ) { - int layer = getActiveLayer(); + int layer = GetActiveLayer(); - setActiveLayer( event.GetSelection() ); + SetActiveLayer( event.GetSelection() ); - if( layer != getActiveLayer() ) + if( layer != GetActiveLayer() ) { if( m_LayersManager->OnLayerSelected() ) m_canvas->Refresh(); @@ -321,7 +364,7 @@ void GERBVIEW_FRAME::OnSelectActiveLayer( wxCommandEvent& event ) void GERBVIEW_FRAME::OnShowGerberSourceFile( wxCommandEvent& event ) { - int layer = getActiveLayer(); + int layer = GetActiveLayer(); GERBER_FILE_IMAGE* gerber_layer = GetGbrImage( layer ); if( gerber_layer ) @@ -427,16 +470,19 @@ void GERBVIEW_FRAME::OnSelectOptionToolbar( wxCommandEvent& event ) case ID_TB_OPTIONS_SHOW_FLASHED_ITEMS_SKETCH: m_DisplayOptions.m_DisplayFlashedItemsFill = not state; + applyDisplaySettingsToGAL(); m_canvas->Refresh( true ); break; case ID_TB_OPTIONS_SHOW_LINES_SKETCH: m_DisplayOptions.m_DisplayLinesFill = not state; + applyDisplaySettingsToGAL(); m_canvas->Refresh( true ); break; case ID_TB_OPTIONS_SHOW_POLYGONS_SKETCH: m_DisplayOptions.m_DisplayPolygonsFill = not state; + applyDisplaySettingsToGAL(); m_canvas->Refresh( true ); break; @@ -450,6 +496,18 @@ void GERBVIEW_FRAME::OnSelectOptionToolbar( wxCommandEvent& event ) m_canvas->Refresh( true ); break; + case ID_TB_OPTIONS_DIFF_MODE: + m_DisplayOptions.m_DiffMode = state; + applyDisplaySettingsToGAL(); + m_canvas->Refresh( true ); + break; + + case ID_TB_OPTIONS_HIGH_CONTRAST_MODE: + m_DisplayOptions.m_HighContrastMode = state; + applyDisplaySettingsToGAL(); + m_canvas->Refresh( true ); + break; + case ID_TB_OPTIONS_SHOW_LAYERS_MANAGER_VERTICAL_TOOLBAR: // show/hide auxiliary Vertical layers and visibility manager toolbar @@ -461,6 +519,11 @@ void GERBVIEW_FRAME::OnSelectOptionToolbar( wxCommandEvent& event ) _("Hide &Layers Manager" ) : _("Show &Layers Manager" )); break; + // collect GAL-only tools here: + case ID_TB_MEASUREMENT_TOOL: + SetToolID( id, wxCURSOR_DEFAULT, _( "Unsupported tool in this canvas" ) ); + break; + default: wxMessageBox( wxT( "GERBVIEW_FRAME::OnSelectOptionToolbar error" ) ); break; @@ -472,3 +535,62 @@ void GERBVIEW_FRAME::OnUpdateSelectTool( wxUpdateUIEvent& aEvent ) { aEvent.Check( GetToolId() == aEvent.GetId() ); } + + +void GERBVIEW_FRAME::SwitchCanvas( wxCommandEvent& aEvent ) +{ + bool use_gal = false; + EDA_DRAW_PANEL_GAL::GAL_TYPE canvasType = EDA_DRAW_PANEL_GAL::GAL_TYPE_NONE; + + switch( aEvent.GetId() ) + { + case ID_MENU_CANVAS_LEGACY: + break; + + case ID_MENU_CANVAS_CAIRO: + use_gal = GetGalCanvas()->SwitchBackend( EDA_DRAW_PANEL_GAL::GAL_TYPE_CAIRO ); + + if( use_gal ) + canvasType = EDA_DRAW_PANEL_GAL::GAL_TYPE_CAIRO; + break; + + case ID_MENU_CANVAS_OPENGL: + use_gal = GetGalCanvas()->SwitchBackend( EDA_DRAW_PANEL_GAL::GAL_TYPE_OPENGL ); + + if( use_gal ) + canvasType = EDA_DRAW_PANEL_GAL::GAL_TYPE_OPENGL; + break; + } + + SaveCanvasTypeSetting( canvasType ); + UseGalCanvas( use_gal ); + wxUpdateUIEvent e; + OnUpdateSwitchCanvas( e ); +} + + +void GERBVIEW_FRAME::OnUpdateSwitchCanvas( wxUpdateUIEvent& aEvent ) +{ + wxMenuBar* menuBar = GetMenuBar(); + EDA_DRAW_PANEL_GAL* gal_canvas = GetGalCanvas(); + EDA_DRAW_PANEL_GAL::GAL_TYPE canvasType = EDA_DRAW_PANEL_GAL::GAL_TYPE_NONE; + + if( IsGalCanvasActive() && gal_canvas ) + canvasType = gal_canvas->GetBackend(); + + struct { int menuId; int galType; } menuList[] = + { + { ID_MENU_CANVAS_LEGACY, EDA_DRAW_PANEL_GAL::GAL_TYPE_NONE }, + { ID_MENU_CANVAS_OPENGL, EDA_DRAW_PANEL_GAL::GAL_TYPE_OPENGL }, + { ID_MENU_CANVAS_CAIRO, EDA_DRAW_PANEL_GAL::GAL_TYPE_CAIRO }, + }; + + for( auto ii: menuList ) + { + wxMenuItem* item = menuBar->FindItem( ii.menuId ); + if( ii.galType == canvasType ) + { + item->Check( true ); + } + } +} diff --git a/gerbview/excellon_read_drill_file.cpp b/gerbview/excellon_read_drill_file.cpp index 458e953703..b916f36776 100644 --- a/gerbview/excellon_read_drill_file.cpp +++ b/gerbview/excellon_read_drill_file.cpp @@ -73,6 +73,7 @@ #include #include #include +#include #include @@ -160,7 +161,7 @@ static EXCELLON_CMD excellon_G_CmdList[] = bool GERBVIEW_FRAME::Read_EXCELLON_File( const wxString& aFullFileName ) { wxString msg; - int layerId = getActiveLayer(); // current layer used in GerbView + int layerId = GetActiveLayer(); // current layer used in GerbView GERBER_FILE_IMAGE_LIST* images = GetGerberLayout()->GetImagesList(); EXCELLON_IMAGE* drill_Layer = (EXCELLON_IMAGE*) images->GetGbrImage( layerId ); @@ -193,6 +194,21 @@ bool GERBVIEW_FRAME::Read_EXCELLON_File( const wxString& aFullFileName ) dlg.ListSet( drill_Layer->GetMessages() ); dlg.ShowModal(); } + + // TODO(JE) Is this the best place to add items to the view? + if( success ) + { + EDA_DRAW_PANEL_GAL* canvas = GetGalCanvas(); + if( canvas ) + { + KIGFX::VIEW* view = canvas->GetView(); + for( GERBER_DRAW_ITEM* item = drill_Layer->GetItemsList(); item; item = item->Next() ) + { + view->Add( (KIGFX::VIEW_ITEM*) item ); + } + } + } + return success; } @@ -494,7 +510,7 @@ bool EXCELLON_IMAGE::readToolInformation( char*& aText ) // Initialize Dcode to handle this Tool // Remember: dcodes are >= FIRST_DCODE - D_CODE* dcode = GetDCODE( iprm + FIRST_DCODE ); + D_CODE* dcode = GetDCODEOrCreate( iprm + FIRST_DCODE ); if( dcode == NULL ) return false; @@ -532,7 +548,7 @@ bool EXCELLON_IMAGE::Execute_Drill_Command( char*& text ) Execute_EXCELLON_G_Command( text ); break; case 0: // E.O.L: execute command - tool = GetDCODE( m_Current_Tool, false ); + tool = GetDCODE( m_Current_Tool ); if( !tool ) { @@ -593,13 +609,13 @@ bool EXCELLON_IMAGE::Select_Tool( char*& text ) dcode_id = TOOLS_MAX_COUNT - 1; m_Current_Tool = dcode_id; - D_CODE* currDcode = GetDCODE( dcode_id , false ); + D_CODE* currDcode = GetDCODEOrCreate( dcode_id, true ); if( currDcode == NULL && tool_id > 0 ) // if the definition is embedded, enter it { text = startline; // text starts at the beginning of the command readToolInformation( text ); - currDcode = GetDCODE( dcode_id , false ); + currDcode = GetDCODE( dcode_id ); } if( currDcode ) diff --git a/gerbview/files.cpp b/gerbview/files.cpp index 3562a29486..3634ac705a 100644 --- a/gerbview/files.cpp +++ b/gerbview/files.cpp @@ -222,7 +222,7 @@ bool GERBVIEW_FRAME::LoadGerberFiles( const wxString& aFullFileName ) // Read gerber files: each file is loaded on a new GerbView layer bool success = true; - int layer = getActiveLayer(); + int layer = GetActiveLayer(); // Manage errors when loading files wxString msg; @@ -237,7 +237,7 @@ bool GERBVIEW_FRAME::LoadGerberFiles( const wxString& aFullFileName ) m_lastFileName = filename.GetFullPath(); - setActiveLayer( layer, false ); + SetActiveLayer( layer, false ); if( Read_GERBER_File( filename.GetFullPath() ) ) { @@ -263,7 +263,7 @@ bool GERBVIEW_FRAME::LoadGerberFiles( const wxString& aFullFileName ) break; } - setActiveLayer( layer, false ); + SetActiveLayer( layer, false ); } } @@ -278,7 +278,7 @@ bool GERBVIEW_FRAME::LoadGerberFiles( const wxString& aFullFileName ) // Synchronize layers tools with actual active layer: ReFillLayerWidget(); - setActiveLayer( getActiveLayer() ); + SetActiveLayer( GetActiveLayer() ); m_LayersManager->UpdateLayerIcons(); syncLayerBox(); return success; @@ -325,7 +325,7 @@ bool GERBVIEW_FRAME::LoadExcellonFiles( const wxString& aFullFileName ) // Read Excellon drill files: each file is loaded on a new GerbView layer bool success = true; - int layer = getActiveLayer(); + int layer = GetActiveLayer(); // Manage errors when loading files wxString msg; @@ -340,7 +340,7 @@ bool GERBVIEW_FRAME::LoadExcellonFiles( const wxString& aFullFileName ) m_lastFileName = filename.GetFullPath(); - setActiveLayer( layer, false ); + SetActiveLayer( layer, false ); if( Read_EXCELLON_File( filename.GetFullPath() ) ) { @@ -367,7 +367,7 @@ bool GERBVIEW_FRAME::LoadExcellonFiles( const wxString& aFullFileName ) break; } - setActiveLayer( layer, false ); + SetActiveLayer( layer, false ); } } @@ -382,7 +382,7 @@ bool GERBVIEW_FRAME::LoadExcellonFiles( const wxString& aFullFileName ) // Synchronize layers tools with actual active layer: ReFillLayerWidget(); - setActiveLayer( getActiveLayer() ); + SetActiveLayer( GetActiveLayer() ); m_LayersManager->UpdateLayerIcons(); syncLayerBox(); @@ -454,7 +454,7 @@ bool GERBVIEW_FRAME::unarchiveFiles( const wxString& aFullFileName, REPORTER* aR continue; } - int layer = getActiveLayer(); + int layer = GetActiveLayer(); if( layer == NO_AVAILABLE_LAYERS ) { @@ -531,7 +531,7 @@ bool GERBVIEW_FRAME::unarchiveFiles( const wxString& aFullFileName, REPORTER* aR gerber_image->m_FileName = fname; layer = getNextAvailableLayer( layer ); - setActiveLayer( layer, false ); + SetActiveLayer( layer, false ); } } @@ -584,7 +584,7 @@ bool GERBVIEW_FRAME::LoadZipArchiveFile( const wxString& aFullFileName ) // Synchronize layers tools with actual active layer: ReFillLayerWidget(); - setActiveLayer( getActiveLayer() ); + SetActiveLayer( GetActiveLayer() ); m_LayersManager->UpdateLayerIcons(); syncLayerBox(); diff --git a/gerbview/gerbview_config.cpp b/gerbview/gerbview_config.cpp index 8b52e1a19b..e233fcaab7 100644 --- a/gerbview/gerbview_config.cpp +++ b/gerbview/gerbview_config.cpp @@ -92,6 +92,11 @@ PARAM_CFG_ARRAY& GERBVIEW_FRAME::GetConfigurationSettings() &g_ColorsSettings.m_LayersColors[ LAYER_NEGATIVE_OBJECTS], DARKGRAY ) ); + m_configSettings.push_back( new PARAM_CFG_SETCOLOR( true, + wxT( "GridColorEx" ), + &g_ColorsSettings.m_LayersColors[ + LAYER_GERBVIEW_GRID], + DARKGRAY ) ); m_configSettings.push_back( new PARAM_CFG_BOOL( true, wxT( "DisplayPolarCoordinates" ), &m_DisplayOptions.m_DisplayPolarCood, @@ -129,7 +134,7 @@ PARAM_CFG_ARRAY& GERBVIEW_FRAME::GetConfigurationSettings() for( unsigned i = 0; i < DIM(keys); ++i ) { - COLOR4D* prm = &g_ColorsSettings.m_LayersColors[i]; + COLOR4D* prm = &g_ColorsSettings.m_LayersColors[ GERBER_DRAW_LAYER( i ) ]; PARAM_CFG_SETCOLOR* prm_entry = new PARAM_CFG_SETCOLOR( true, keys[i], prm, color_default[i] ); diff --git a/gerbview/gerbview_frame.cpp b/gerbview/gerbview_frame.cpp index fbb6698652..9f15392670 100644 --- a/gerbview/gerbview_frame.cpp +++ b/gerbview/gerbview_frame.cpp @@ -49,6 +49,14 @@ #include #include +#include +#include +#include +#include +#include +#include +#include + // Config keywords static const wxString cfgShowPageSizeOption( wxT( "PageSizeOpt" ) ); @@ -56,6 +64,8 @@ static const wxString cfgShowDCodes( wxT( "ShowDCodesOpt" ) ); static const wxString cfgShowNegativeObjects( wxT( "ShowNegativeObjectsOpt" ) ); static const wxString cfgShowBorderAndTitleBlock( wxT( "ShowBorderAndTitleBlock" ) ); +const wxChar GERBVIEW_FRAME::CANVAS_TYPE_KEY[] = wxT( "canvas_type" ); + // Colors for layers and items COLORS_DESIGN_SETTINGS g_ColorsSettings( FRAME_GERBER ); @@ -87,6 +97,16 @@ GERBVIEW_FRAME::GERBVIEW_FRAME( KIWAY* aKiway, wxWindow* aParent ): m_zipFileHistory.SetBaseId( ID_GERBVIEW_ZIP_FILE1 ); m_jobFileHistory.SetBaseId( ID_GERBVIEW_JOB_FILE1 ); + EDA_DRAW_PANEL_GAL* galCanvas = new GERBVIEW_DRAW_PANEL_GAL( this, -1, wxPoint( 0, 0 ), + m_FrameSize, + GetGalDisplayOptions(), + EDA_DRAW_PANEL_GAL::GAL_TYPE_NONE ); + + SetGalCanvas( galCanvas ); + + // GerbView requires draw priority for rendering negative objects + galCanvas->GetView()->UseDrawPriority( true ); + if( m_canvas ) m_canvas->SetEnableBlockCommands( true ); @@ -174,22 +194,59 @@ GERBVIEW_FRAME::GERBVIEW_FRAME( KIWAY* aKiway, wxWindow* aParent ): m_auimgr.AddPane( m_canvas, wxAuiPaneInfo().Name( wxT( "DrawFrame" ) ).CentrePane() ); + if( GetGalCanvas() ) + m_auimgr.AddPane( (wxWindow*) GetGalCanvas(), + wxAuiPaneInfo().Name( wxT( "DrawFrameGal" ) ).CentrePane().Hide() ); + if( m_messagePanel ) m_auimgr.AddPane( m_messagePanel, wxAuiPaneInfo( mesg ).Name( wxT( "MsgPanel" ) ).Bottom().Layer( 10 ) ); ReFillLayerWidget(); // this is near end because contents establish size - m_LayersManager->ReFillRender(); // Update colors in Render after the config is read m_auimgr.Update(); - setActiveLayer( 0, true ); + setupTools(); + + SetActiveLayer( 0, true ); Zoom_Automatique( false ); // Gives a default zoom value UpdateTitleAndInfo(); + + EDA_DRAW_PANEL_GAL::GAL_TYPE canvasType = LoadCanvasTypeSetting(); + + if( canvasType != EDA_DRAW_PANEL_GAL::GAL_TYPE_NONE ) + { + if( GetGalCanvas()->SwitchBackend( canvasType ) ) + UseGalCanvas( true ); + wxUpdateUIEvent e; + OnUpdateSwitchCanvas( e ); + } + else + { + forceColorsToLegacy(); + m_canvas->Refresh(); + } + + // Enable the axes to match legacy draw style + auto& galOptions = GetGalDisplayOptions(); + galOptions.m_axesEnabled = true; + galOptions.NotifyChanged(); + + m_LayersManager->ReFill(); + m_LayersManager->ReFillRender(); // Update colors in Render after the config is read } GERBVIEW_FRAME::~GERBVIEW_FRAME() { + if( m_toolManager ) + m_toolManager->DeactivateTool(); + + if( auto canvas = GetGalCanvas() ) + { + canvas->GetView()->Clear(); + } + + GetGerberLayout()->GetImagesList()->DeleteAllImages(); } @@ -228,7 +285,7 @@ bool GERBVIEW_FRAME::OpenProjectFiles( const std::vector& aFileSet, in for( unsigned i=0; iSetRenderState( aItemIdVisible, aNewState ); } +void GERBVIEW_FRAME::applyDisplaySettingsToGAL() +{ + auto view = GetGalCanvas()->GetView(); + auto painter = static_cast( view->GetPainter() ); + auto settings = static_cast( painter->GetSettings() ); + settings->LoadDisplayOptions( &m_DisplayOptions ); + + settings->ImportLegacyColors( m_colorsSettings ); + + view->RecacheAllItems(); + view->MarkTargetDirty( KIGFX::TARGET_NONCACHED ); +} + + int GERBVIEW_FRAME::getNextAvailableLayer( int aLayer ) const { int layer = aLayer; @@ -427,7 +499,7 @@ int GERBVIEW_FRAME::getNextAvailableLayer( int aLayer ) const void GERBVIEW_FRAME::syncLayerWidget() { - m_LayersManager->SelectLayer( getActiveLayer() ); + m_LayersManager->SelectLayer( GetActiveLayer() ); UpdateTitleAndInfo(); } @@ -437,10 +509,10 @@ void GERBVIEW_FRAME::syncLayerBox( bool aRebuildLayerBox ) if( aRebuildLayerBox ) m_SelLayerBox->Resync(); - m_SelLayerBox->SetSelection( getActiveLayer() ); + m_SelLayerBox->SetSelection( GetActiveLayer() ); int dcodeSelected = -1; - GERBER_FILE_IMAGE* gerber = GetGbrImage( getActiveLayer() ); + GERBER_FILE_IMAGE* gerber = GetGbrImage( GetActiveLayer() ); if( gerber ) dcodeSelected = gerber->m_Selected_Tool; @@ -462,7 +534,7 @@ void GERBVIEW_FRAME::Liste_D_Codes() wxString Line; wxArrayString list; double scale = g_UserUnit == INCHES ? IU_PER_MILS * 1000 : IU_PER_MM; - int curr_layer = getActiveLayer(); + int curr_layer = GetActiveLayer(); for( int layer = 0; layer < (int)ImagesMaxCount(); ++layer ) { @@ -485,7 +557,7 @@ void GERBVIEW_FRAME::Liste_D_Codes() for( ii = 0, jj = 1; ii < TOOLS_MAX_COUNT; ii++ ) { - D_CODE* pt_D_code = gerber->GetDCODE( ii + FIRST_DCODE, false ); + D_CODE* pt_D_code = gerber->GetDCODE( ii + FIRST_DCODE ); if( pt_D_code == NULL ) continue; @@ -522,7 +594,7 @@ void GERBVIEW_FRAME::Liste_D_Codes() void GERBVIEW_FRAME::UpdateTitleAndInfo() { - GERBER_FILE_IMAGE* gerber = GetGbrImage( getActiveLayer() ); + GERBER_FILE_IMAGE* gerber = GetGbrImage( GetActiveLayer() ); // Display the gerber filename if( gerber == NULL ) @@ -532,7 +604,7 @@ void GERBVIEW_FRAME::UpdateTitleAndInfo() SetStatusText( wxEmptyString, 0 ); wxString info; - info.Printf( _( "Drawing layer %d not in use" ), getActiveLayer() + 1 ); + info.Printf( _( "Drawing layer %d not in use" ), GetActiveLayer() + 1 ); m_TextInfo->SetValue( info ); if( EnsureTextCtrlWidth( m_TextInfo, &info ) ) // Resized @@ -611,14 +683,29 @@ long GERBVIEW_FRAME::GetVisibleLayers() const void GERBVIEW_FRAME::SetVisibleLayers( long aLayerMask ) { -// GetGerberLayout()->SetVisibleLayers( aLayerMask ); + if( auto canvas = GetGalCanvas() ) + { + // NOTE: This assumes max 32 drawlayers! + for( int i = 0; i < GERBER_DRAWLAYERS_COUNT; i++ ) + { + bool v = ( aLayerMask & ( 1 << i ) ); + int layer = GERBER_DRAW_LAYER( i ); + canvas->GetView()->SetLayerVisible( layer, v ); + canvas->GetView()->SetLayerVisible( GERBER_DCODE_LAYER( layer ), v ); + } + } } bool GERBVIEW_FRAME::IsLayerVisible( int aLayer ) const { if( ! m_DisplayOptions.m_IsPrinting ) + { + if( IsGalCanvasActive() ) + aLayer = GERBER_DRAW_LAYER( aLayer ); + return m_LayersManager->IsLayerVisible( aLayer ); + } else return GetGerberLayout()->IsLayerPrintable( aLayer ); } @@ -666,6 +753,8 @@ void GERBVIEW_FRAME::SetVisibleElementColor( GERBVIEW_LAYER_ID aItemIdVisible, break; case LAYER_GERBVIEW_GRID: + // Ensure grid always has low alpha + aColor.a = 0.8; SetGridColor( aColor ); m_colorsSettings->SetItemColor( aItemIdVisible, aColor ); break; @@ -694,21 +783,35 @@ COLOR4D GERBVIEW_FRAME::GetLayerColor( int aLayer ) const void GERBVIEW_FRAME::SetLayerColor( int aLayer, COLOR4D aColor ) { m_colorsSettings->SetLayerColor( aLayer, aColor ); + applyDisplaySettingsToGAL(); } -int GERBVIEW_FRAME::getActiveLayer() +int GERBVIEW_FRAME::GetActiveLayer() { return ( (GBR_SCREEN*) GetScreen() )->m_Active_Layer; } -void GERBVIEW_FRAME::setActiveLayer( int aLayer, bool doLayerWidgetUpdate ) +void GERBVIEW_FRAME::SetActiveLayer( int aLayer, bool doLayerWidgetUpdate ) { ( (GBR_SCREEN*) GetScreen() )->m_Active_Layer = aLayer; if( doLayerWidgetUpdate ) - m_LayersManager->SelectLayer( getActiveLayer() ); + m_LayersManager->SelectLayer( GetActiveLayer() ); + + if( IsGalCanvasActive() ) + { + m_toolManager->RunAction( GERBVIEW_ACTIONS::layerChanged ); // notify other tools + GetGalCanvas()->SetFocus(); // otherwise hotkeys are stuck somewhere + + GetGalCanvas()->SetTopLayer( GERBER_DRAW_LAYER( aLayer ) ); + + GetGalCanvas()->SetHighContrastLayer( GERBER_DRAW_LAYER( aLayer ) ); + GetGalCanvas()->Refresh(); + + GetGalCanvas()->GetView()->RecacheAllItems(); + } } @@ -784,6 +887,17 @@ void GERBVIEW_FRAME::SetCurItem( GERBER_DRAW_ITEM* aItem, bool aDisplayInfo ) } +void GERBVIEW_FRAME::SetGridColor( COLOR4D aColor ) +{ + if( IsGalCanvasActive() ) + { + GetGalCanvas()->GetGAL()->SetGridColor( aColor ); + } + + m_gridColor = aColor; +} + + EDA_RECT GERBVIEW_FRAME::GetGerberLayoutBoundingBox() { GetGerberLayout()->ComputeBoundingBox(); @@ -909,3 +1023,113 @@ void GERBVIEW_FRAME::unitsChangeRefresh() EDA_DRAW_FRAME::unitsChangeRefresh(); updateDCodeSelectBox(); } + + +void GERBVIEW_FRAME::forceColorsToLegacy() +{ + for( int i = 0; i < LAYER_ID_COUNT; i++ ) + { + COLOR4D c = m_colorsSettings->GetLayerColor( i ); + c.SetToNearestLegacyColor(); + m_colorsSettings->SetLayerColor( i, c ); + } +} + + +void GERBVIEW_FRAME::UseGalCanvas( bool aEnable ) +{ + EDA_DRAW_FRAME::UseGalCanvas( aEnable ); + + EDA_DRAW_PANEL_GAL* galCanvas = GetGalCanvas(); + + if( m_toolManager ) + m_toolManager->SetEnvironment( m_gerberLayout, GetGalCanvas()->GetView(), + GetGalCanvas()->GetViewControls(), this ); + + if( aEnable ) + { + if( m_toolManager ) + m_toolManager->ResetTools( TOOL_BASE::GAL_SWITCH ); + + galCanvas->GetGAL()->SetGridColor( GetLayerColor( LAYER_GERBVIEW_GRID ) ); + + galCanvas->GetView()->RecacheAllItems(); + galCanvas->SetEventDispatcher( m_toolDispatcher ); + galCanvas->StartDrawing(); + } + else + { + if( m_toolManager ) + m_toolManager->ResetTools( TOOL_BASE::GAL_SWITCH ); + + galCanvas->StopDrawing(); + + // Redirect all events to the legacy canvas + galCanvas->SetEventDispatcher( NULL ); + + forceColorsToLegacy(); + m_canvas->Refresh(); + } + + m_LayersManager->ReFill(); + m_LayersManager->ReFillRender(); + + ReCreateOptToolbar(); +} + + +EDA_DRAW_PANEL_GAL::GAL_TYPE GERBVIEW_FRAME::LoadCanvasTypeSetting() const +{ + EDA_DRAW_PANEL_GAL::GAL_TYPE canvasType = EDA_DRAW_PANEL_GAL::GAL_TYPE_NONE; + wxConfigBase* cfg = Kiface().KifaceSettings(); + + if( cfg ) + canvasType = (EDA_DRAW_PANEL_GAL::GAL_TYPE) cfg->ReadLong( CANVAS_TYPE_KEY, + EDA_DRAW_PANEL_GAL::GAL_TYPE_NONE ); + + if( canvasType < EDA_DRAW_PANEL_GAL::GAL_TYPE_NONE + || canvasType >= EDA_DRAW_PANEL_GAL::GAL_TYPE_LAST ) + { + assert( false ); + canvasType = EDA_DRAW_PANEL_GAL::GAL_TYPE_NONE; + } + + return canvasType; +} + + +bool GERBVIEW_FRAME::SaveCanvasTypeSetting( EDA_DRAW_PANEL_GAL::GAL_TYPE aCanvasType ) +{ + if( aCanvasType < EDA_DRAW_PANEL_GAL::GAL_TYPE_NONE + || aCanvasType >= EDA_DRAW_PANEL_GAL::GAL_TYPE_LAST ) + { + assert( false ); + return false; + } + + wxConfigBase* cfg = Kiface().KifaceSettings(); + + if( cfg ) + return cfg->Write( CANVAS_TYPE_KEY, (long) aCanvasType ); + + return false; +} + + +void GERBVIEW_FRAME::setupTools() +{ + // Create the manager and dispatcher & route draw panel events to the dispatcher + m_toolManager = new TOOL_MANAGER; + m_toolManager->SetEnvironment( m_gerberLayout, GetGalCanvas()->GetView(), + GetGalCanvas()->GetViewControls(), this ); + m_actions = new GERBVIEW_ACTIONS(); + m_toolDispatcher = new TOOL_DISPATCHER( m_toolManager, m_actions ); + + // Register tools + m_actions->RegisterAllTools( m_toolManager ); + m_toolManager->InitTools(); + + // Run the selection tool, it is supposed to be always active + m_toolManager->InvokeTool( "gerbview.InteractiveSelection" ); +} + diff --git a/gerbview/gerbview_frame.h b/gerbview/gerbview_frame.h index 39a7f1b868..a25b18f1a6 100644 --- a/gerbview/gerbview_frame.h +++ b/gerbview/gerbview_frame.h @@ -36,10 +36,12 @@ #include #include +#include #include #include #include #include +#include #include extern COLORS_DESIGN_SETTINGS g_ColorsSettings; @@ -154,6 +156,9 @@ public: */ int SelectPCBLayer( int aDefaultLayer, int aOpperLayerCount, bool aNullLayer = false ); + ///> @copydoc EDA_DRAW_FRAME::SetGridColor() + virtual void SetGridColor( COLOR4D aColor ) override; + protected: GERBER_LAYER_WIDGET* m_LayersManager; @@ -169,6 +174,9 @@ protected: /// The last filename chosen to be proposed to the user wxString m_lastFileName; + ///> @copydoc EDA_DRAW_FRAME::forceColorsToLegacy() + virtual void forceColorsToLegacy() override; + public: wxChoice* m_SelComponentBox; // a choice box to display and highlight component graphic items wxChoice* m_SelNetnameBox; // a choice box to display and highlight netlist graphic items @@ -179,6 +187,8 @@ public: wxTextCtrl* m_TextInfo; // a wxTextCtrl used to display some info about // gerber data (format..) + COLORS_DESIGN_SETTINGS* m_colorsSettings; + private: /// Auxiliary tool bar typically shown below the main tool bar at the top of the /// main window. @@ -186,7 +196,6 @@ private: // list of PARAM_CFG_xxx to read/write parameters saved in config PARAM_CFG_ARRAY m_configSettings; - COLORS_DESIGN_SETTINGS* m_colorsSettings; int m_displayMode; // Gerber images ("layers" in Gerbview) can be drawn: // - in fast mode (write mode) but if there are negative @@ -206,9 +215,15 @@ private: void updateDCodeSelectBox(); virtual void unitsChangeRefresh() override; // See class EDA_DRAW_FRAME + // The Tool Framework initalization + void setupTools(); + // An array string to store warning messages when reading a gerber file. wxArrayString m_Messages; + /// Updates the GAL with display settings changes + void applyDisplaySettingsToGAL(); + public: GERBVIEW_FRAME( KIWAY* aKiway, wxWindow* aParent ); ~GERBVIEW_FRAME(); @@ -243,6 +258,8 @@ public: double BestZoom() override; void UpdateStatusBar() override; + wxAuiToolBar* GetMainToolBar() { return m_optionsToolBar; } + /** * Function GetZoomLevelIndicator * returns a human readable value which can be displayed as zoom @@ -332,7 +349,7 @@ public: /** * Function IsLayerVisible * tests whether a given layer is visible - * @param aLayer = The layer to be tested + * @param aLayer = The layer to be tested (still 0-31!) * @return bool - true if the layer is visible. */ bool IsLayerVisible( int aLayer ) const; @@ -403,17 +420,17 @@ public: void ReFillLayerWidget(); /** - * Function setActiveLayer + * Function SetActiveLayer * will change the currently active layer to \a aLayer and also * update the GERBER_LAYER_WIDGET. */ - void setActiveLayer( int aLayer, bool doLayerWidgetUpdate = true ); + void SetActiveLayer( int aLayer, bool doLayerWidgetUpdate = true ); /** - * Function getActiveLayer + * Function SetActiveLayer * returns the active layer */ - int getActiveLayer(); + int GetActiveLayer(); /** * Function getNextAvailableLayer @@ -432,7 +449,7 @@ public: /** * Function syncLayerWidget * updates the currently "selected" layer within the GERBER_LAYER_WIDGET. - * The currently active layer is defined by the return value of getActiveLayer(). + * The currently active layer is defined by the return value of GetActiveLayer(). *

* This function cannot be inline without including layer_widget.h in * here and we do not want to do that. @@ -443,7 +460,7 @@ public: * Function syncLayerBox * updates the currently "selected" layer within m_SelLayerBox * The currently active layer, as defined by the return value of - * getActiveLayer(). + * GetActiveLayer(). * @param aRebuildLayerBox = true to rebuild the layer box * false to just updates the selection. */ @@ -479,6 +496,7 @@ public: void Process_Special_Functions( wxCommandEvent& event ); void OnSelectOptionToolbar( wxCommandEvent& event ); + void OnSelectHighlightChoice( wxCommandEvent& event ); /** * Function OnSelectActiveDCode @@ -714,6 +732,34 @@ public: virtual void PrintPage( wxDC* aDC, LSET aPrintMasklayer, bool aPrintMirrorMode, void* aData = NULL ) override; + ///> @copydoc EDA_DRAW_FRAME::UseGalCanvas + virtual void UseGalCanvas( bool aEnable ) override; + + /** + * switches currently used canvas (default / Cairo / OpenGL). + */ + void SwitchCanvas( wxCommandEvent& aEvent ); + + /** + * Update UI called when switches currently used canvas (default / Cairo / OpenGL). + */ + void OnUpdateSwitchCanvas( wxUpdateUIEvent& aEvent ); + + /** + * Function LoadCanvasTypeSetting() + * Returns the canvas type stored in the application settings. + */ + EDA_DRAW_PANEL_GAL::GAL_TYPE LoadCanvasTypeSetting() const; + + /** + * Function SaveCanvasTypeSetting() + * Stores the canvas type in the application settings. + */ + bool SaveCanvasTypeSetting( EDA_DRAW_PANEL_GAL::GAL_TYPE aCanvasType ); + + ///> Key in KifaceSettings to store the canvas type. + static const wxChar CANVAS_TYPE_KEY[]; + DECLARE_EVENT_TABLE() }; diff --git a/gerbview/gerbview_id.h b/gerbview/gerbview_id.h index e54a6bb07e..2e4494b814 100644 --- a/gerbview/gerbview_id.h +++ b/gerbview/gerbview_id.h @@ -50,6 +50,9 @@ enum gerbview_ids ID_MENU_GERBVIEW_SHOW_HIDE_LAYERS_MANAGER_DIALOG, ID_MENU_GERBVIEW_SELECT_PREFERED_EDITOR, + ID_MENU_CANVAS_LEGACY, + ID_MENU_CANVAS_OPENGL, + ID_MENU_CANVAS_CAIRO, ID_GBR_AUX_TOOLBAR_PCB_CMP_CHOICE, ID_GBR_AUX_TOOLBAR_PCB_NET_CHOICE, @@ -104,6 +107,9 @@ enum gerbview_ids ID_TB_OPTIONS_SHOW_GBR_MODE_0, ID_TB_OPTIONS_SHOW_GBR_MODE_1, ID_TB_OPTIONS_SHOW_GBR_MODE_2, + ID_TB_OPTIONS_DIFF_MODE, + ID_TB_OPTIONS_HIGH_CONTRAST_MODE, + ID_TB_MEASUREMENT_TOOL, // Right click context menu ID_HIGHLIGHT_REMOVE_ALL, diff --git a/gerbview/hotkeys.cpp b/gerbview/hotkeys.cpp index 2a830358c1..19ed1315a9 100644 --- a/gerbview/hotkeys.cpp +++ b/gerbview/hotkeys.cpp @@ -28,7 +28,7 @@ #include #include -#include +#include #include #include @@ -86,6 +86,25 @@ static EDA_HOTKEY HkSwitch2NextCopperLayer( _HKI( "Switch to Next Layer" ), static EDA_HOTKEY HkSwitch2PreviousCopperLayer( _HKI( "Switch to Previous Layer" ), HK_SWITCH_LAYER_TO_PREVIOUS, '-' ); +static EDA_HOTKEY HkCanvasDefault( _HKI( "Switch to Legacy Canvas" ), + HK_CANVAS_LEGACY, +#ifdef __WXMAC__ + GR_KB_ALT + +#endif + WXK_F9 ); +static EDA_HOTKEY HkCanvasOpenGL( _HKI( "Switch to OpenGL Canvas" ), + HK_CANVAS_OPENGL, +#ifdef __WXMAC__ + GR_KB_ALT + +#endif + WXK_F11 ); +static EDA_HOTKEY HkCanvasCairo( _HKI( "Switch to Cairo Canvas" ), + HK_CANVAS_CAIRO, +#ifdef __WXMAC__ + GR_KB_ALT + +#endif + WXK_F12 ); + // List of common hotkey descriptors EDA_HOTKEY* gerbviewHotkeyList[] = { &HkHelp, @@ -95,6 +114,9 @@ EDA_HOTKEY* gerbviewHotkeyList[] = { &HkDCodesDisplayMode, &HkNegativeObjDisplayMode, &HkSwitch2NextCopperLayer, &HkSwitch2PreviousCopperLayer, + &HkCanvasDefault, + &HkCanvasOpenGL, + &HkCanvasCairo, NULL }; @@ -205,22 +227,37 @@ bool GERBVIEW_FRAME::OnHotKey( wxDC* aDC, int aHotkeyCode, const wxPoint& aPosit break; case HK_SWITCH_LAYER_TO_PREVIOUS: - if( getActiveLayer() > 0 ) + if( GetActiveLayer() > 0 ) { - setActiveLayer( getActiveLayer() - 1 ); + SetActiveLayer( GetActiveLayer() - 1 ); m_LayersManager->OnLayerSelected(); m_canvas->Refresh(); } break; case HK_SWITCH_LAYER_TO_NEXT: - if( getActiveLayer() < 31 ) + if( GetActiveLayer() < GERBER_DRAWLAYERS_COUNT - 1 ) { - setActiveLayer( getActiveLayer() + 1 ); + SetActiveLayer( GetActiveLayer() + 1 ); m_LayersManager->OnLayerSelected(); m_canvas->Refresh(); } break; + + case HK_CANVAS_CAIRO: + cmd.SetId( ID_MENU_CANVAS_CAIRO ); + GetEventHandler()->ProcessEvent( cmd ); + break; + + case HK_CANVAS_OPENGL: + cmd.SetId( ID_MENU_CANVAS_OPENGL ); + GetEventHandler()->ProcessEvent( cmd ); + break; + + case HK_CANVAS_LEGACY: + cmd.SetId( ID_MENU_CANVAS_LEGACY ); + GetEventHandler()->ProcessEvent( cmd ); + break; } return true; diff --git a/gerbview/hotkeys.h b/gerbview/hotkeys.h index 206d537755..21e2c30b6d 100644 --- a/gerbview/hotkeys.h +++ b/gerbview/hotkeys.h @@ -42,7 +42,10 @@ enum hotkey_id_commnand { HK_GBR_NEGATIVE_DISPLAY_ONOFF, HK_GBR_DCODE_DISPLAY_ONOFF, HK_SWITCH_LAYER_TO_NEXT, - HK_SWITCH_LAYER_TO_PREVIOUS + HK_SWITCH_LAYER_TO_PREVIOUS, + HK_CANVAS_LEGACY, + HK_CANVAS_OPENGL, + HK_CANVAS_CAIRO }; // List of hotkey descriptors for GerbView. diff --git a/gerbview/job_file_reader.cpp b/gerbview/job_file_reader.cpp index 48798dbba8..faf731d192 100644 --- a/gerbview/job_file_reader.cpp +++ b/gerbview/job_file_reader.cpp @@ -193,7 +193,7 @@ bool GERBVIEW_FRAME::LoadGerberJobFile( const wxString& aFullFileName ) wxFileName gbr_fn = filename; bool read_ok; int layer = 0; - setActiveLayer( layer, false ); + SetActiveLayer( layer, false ); for( unsigned ii = 0; ii < gbrfiles.GetCount(); ii++ ) { @@ -207,7 +207,7 @@ bool GERBVIEW_FRAME::LoadGerberJobFile( const wxString& aFullFileName ) if( read_ok ) { layer = getNextAvailableLayer( layer ); - setActiveLayer( layer, false ); + SetActiveLayer( layer, false ); } } else diff --git a/gerbview/locate.cpp b/gerbview/locate.cpp index 5ee8869f66..d3ff27ca5e 100644 --- a/gerbview/locate.cpp +++ b/gerbview/locate.cpp @@ -49,7 +49,7 @@ GERBER_DRAW_ITEM* GERBVIEW_FRAME::Locate( const wxPoint& aPosition, int aTypeloc if( aTypeloc == CURSEUR_ON_GRILLE ) ref = GetNearestGridPosition( ref ); - int layer = getActiveLayer(); + int layer = GetActiveLayer(); GERBER_FILE_IMAGE* gerber = GetGbrImage( layer ); GERBER_DRAW_ITEM* gerb_item = NULL; diff --git a/gerbview/menubar.cpp b/gerbview/menubar.cpp index 40bb93fb93..fa3f372b70 100644 --- a/gerbview/menubar.cpp +++ b/gerbview/menubar.cpp @@ -42,6 +42,7 @@ void GERBVIEW_FRAME::ReCreateMenuBar() { // Create and try to get the current menubar wxMenuBar* menuBar = GetMenuBar(); + wxString text; if( !menuBar ) menuBar = new wxMenuBar(); @@ -207,6 +208,33 @@ void GERBVIEW_FRAME::ReCreateMenuBar() // Hotkey submenu AddHotkeyConfigMenu( configMenu ); + // Canvas selection + configMenu->AppendSeparator(); + + text = AddHotkeyName( _( "Legacy Canva&s" ), GerbviewHokeysDescr, + HK_CANVAS_LEGACY ); + + configMenu->Append( + new wxMenuItem( configMenu, ID_MENU_CANVAS_LEGACY, + text, _( "Switch the canvas implementation to Legacy" ), + wxITEM_RADIO ) ); + + text = AddHotkeyName( _( "Open&GL Canvas" ), GerbviewHokeysDescr, + HK_CANVAS_OPENGL ); + + configMenu->Append( + new wxMenuItem( configMenu, ID_MENU_CANVAS_OPENGL, + text, _( "Switch the canvas implementation to OpenGL" ), + wxITEM_RADIO ) ); + + text = AddHotkeyName( _( "&Cairo Canvas" ), GerbviewHokeysDescr, + HK_CANVAS_CAIRO ); + + configMenu->Append( + new wxMenuItem( configMenu, ID_MENU_CANVAS_CAIRO, + text, _( "Switch the canvas implementation to Cairo" ), + wxITEM_RADIO ) ); + // Menu miscellaneous wxMenu* miscellaneousMenu = new wxMenu; diff --git a/gerbview/onleftclick.cpp b/gerbview/onleftclick.cpp index c07bb96210..9855d71730 100644 --- a/gerbview/onleftclick.cpp +++ b/gerbview/onleftclick.cpp @@ -36,13 +36,15 @@ */ void GERBVIEW_FRAME::OnLeftClick( wxDC* aDC, const wxPoint& aPosition ) { + SetToolID( ID_NO_TOOL_SELECTED, m_canvas->GetDefaultCursor(), wxEmptyString ); + GERBER_DRAW_ITEM* DrawStruct = Locate( aPosition, CURSEUR_OFF_GRILLE ); GetScreen()->SetCurItem( DrawStruct ); if( DrawStruct == NULL ) { - GERBER_FILE_IMAGE* gerber = GetGbrImage( getActiveLayer() ); + GERBER_FILE_IMAGE* gerber = GetGbrImage( GetActiveLayer() ); if( gerber ) gerber->DisplayImageInfo( this ); diff --git a/gerbview/onrightclick.cpp b/gerbview/onrightclick.cpp index 1c3849e6d6..1d676bd56a 100644 --- a/gerbview/onrightclick.cpp +++ b/gerbview/onrightclick.cpp @@ -120,7 +120,7 @@ bool GERBVIEW_FRAME::OnRightClick( const wxPoint& aPosition, wxMenu* aPopMenu ) D_CODE* apertDescr = currItem->GetDcodeDescr(); - if( !apertDescr->m_AperFunction.IsEmpty() ) + if( apertDescr && !apertDescr->m_AperFunction.IsEmpty() ) { AddMenuItem( aPopMenu, ID_HIGHLIGHT_APER_ATTRIBUTE_ITEMS, wxString::Format( _( "Highlight aperture type '%s'" ), diff --git a/gerbview/readgerb.cpp b/gerbview/readgerb.cpp index 59f2ec61f1..f55c10f743 100644 --- a/gerbview/readgerb.cpp +++ b/gerbview/readgerb.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -40,7 +41,7 @@ bool GERBVIEW_FRAME::Read_GERBER_File( const wxString& GERBER_FullFileName ) { wxString msg; - int layer = getActiveLayer(); + int layer = GetActiveLayer(); GERBER_FILE_IMAGE_LIST* images = GetImagesList(); GERBER_FILE_IMAGE* gerber = GetGbrImage( layer ); @@ -79,6 +80,23 @@ bool GERBVIEW_FRAME::Read_GERBER_File( const wxString& GERBER_FullFileName ) wxMessageBox( msg ); } + auto canvas = GetGalCanvas(); + if( canvas ) + { + auto view = canvas->GetView(); + + if( gerber->m_ImageNegative ) + { + // TODO: find a way to handle negative images + // (maybe convert geometry into positives?) + } + + for( auto item = gerber->GetItemsList(); item; item = item->Next() ) + { + view->Add( (KIGFX::VIEW_ITEM*) item ); + } + } + return true; } diff --git a/gerbview/rs274d.cpp b/gerbview/rs274d.cpp index 45831d7ee6..3d66bf8fea 100644 --- a/gerbview/rs274d.cpp +++ b/gerbview/rs274d.cpp @@ -140,6 +140,9 @@ void fillFlashedGBRITEM( GERBER_DRAW_ITEM* aGbrItem, case APT_MACRO: aGbrItem->m_Shape = GBR_SPOT_MACRO; + + // Cache the bounding box for aperture macros + aGbrItem->GetDcodeDescr()->GetMacro()->GetApertureMacroShape( aGbrItem, aPos ); break; } } @@ -379,6 +382,9 @@ static void fillArcPOLY( GERBER_DRAW_ITEM* aGbrItem, const int increment_angle = 3600 / 36; int count = std::abs( arc_angle / increment_angle ); + if( aGbrItem->m_Polygon.OutlineCount() == 0 ) + aGbrItem->m_Polygon.NewOutline(); + // calculate polygon corners // when arc is counter-clockwise, dummyGbrItem arc goes from end to start // and we must always create a polygon from start to end. @@ -397,7 +403,7 @@ static void fillArcPOLY( GERBER_DRAW_ITEM* aGbrItem, else // last point end_arc = aClockwise ? end : start; - aGbrItem->m_PolyCorners.push_back( end_arc + center ); + aGbrItem->m_Polygon.Append( VECTOR2I( end_arc + center ) ); start_arc = end_arc; } @@ -510,7 +516,7 @@ bool GERBER_FILE_IMAGE::Execute_G_Command( char*& text, int G_command ) if( D_commande > (TOOLS_MAX_COUNT - 1) ) D_commande = TOOLS_MAX_COUNT - 1; m_Current_Tool = D_commande; - D_CODE* pt_Dcode = GetDCODE( D_commande, false ); + D_CODE* pt_Dcode = GetDCODE( D_commande ); if( pt_Dcode ) pt_Dcode->m_InUse = true; break; @@ -552,6 +558,7 @@ bool GERBER_FILE_IMAGE::Execute_G_Command( char*& text, int G_command ) if( m_Exposure && GetItemsList() ) // End of polygon { GERBER_DRAW_ITEM * gbritem = m_Drawings.GetLast(); + gbritem->m_Polygon.Append( gbritem->m_Polygon.Vertex( 0 ) ); StepAndRepeatItem( *gbritem ); } m_Exposure = false; @@ -594,7 +601,7 @@ bool GERBER_FILE_IMAGE::Execute_DCODE_Command( char*& text, int D_commande ) // call m_Current_Tool = D_commande; - D_CODE* pt_Dcode = GetDCODE( D_commande, false ); + D_CODE* pt_Dcode = GetDCODE( D_commande ); if( pt_Dcode ) pt_Dcode->m_InUse = true; @@ -635,11 +642,14 @@ bool GERBER_FILE_IMAGE::Execute_DCODE_Command( char*& text, int D_commande ) gbritem = m_Drawings.GetLast(); gbritem->m_Start = m_PreviousPos; // m_Start is used as temporary storage - if( gbritem->m_PolyCorners.size() == 0 ) - gbritem->m_PolyCorners.push_back( gbritem->m_Start ); + if( gbritem->m_Polygon.OutlineCount() == 0 ) + { + gbritem->m_Polygon.NewOutline(); + gbritem->m_Polygon.Append( VECTOR2I( gbritem->m_Start ) ); + } gbritem->m_End = m_CurrentPos; // m_End is used as temporary storage - gbritem->m_PolyCorners.push_back( gbritem->m_End ); + gbritem->m_Polygon.Append( VECTOR2I( gbritem->m_End ) ); break; } @@ -651,6 +661,7 @@ bool GERBER_FILE_IMAGE::Execute_DCODE_Command( char*& text, int D_commande ) if( m_Exposure && GetItemsList() ) // End of polygon { gbritem = m_Drawings.GetLast(); + gbritem->m_Polygon.Append( gbritem->m_Polygon.Vertex( 0 ) ); StepAndRepeatItem( *gbritem ); } m_Exposure = false; @@ -669,7 +680,7 @@ bool GERBER_FILE_IMAGE::Execute_DCODE_Command( char*& text, int D_commande ) case 1: // code D01 Draw line, exposure ON m_Exposure = true; - tool = GetDCODE( m_Current_Tool, false ); + tool = GetDCODE( m_Current_Tool ); if( tool ) { size = tool->m_Size; @@ -722,7 +733,7 @@ bool GERBER_FILE_IMAGE::Execute_DCODE_Command( char*& text, int D_commande ) break; case 3: // code D3: flash aperture - tool = GetDCODE( m_Current_Tool, false ); + tool = GetDCODE( m_Current_Tool ); if( tool ) { size = tool->m_Size; diff --git a/gerbview/rs274x.cpp b/gerbview/rs274x.cpp index 73d3c6381a..fca35208b9 100644 --- a/gerbview/rs274x.cpp +++ b/gerbview/rs274x.cpp @@ -710,7 +710,7 @@ bool GERBER_FILE_IMAGE::ExecuteRS274XCommand( int command, char* buff, char*& te code = ReadInt( text ); D_CODE* dcode; - dcode = GetDCODE( code ); + dcode = GetDCODEOrCreate( code ); if( dcode == NULL ) break; diff --git a/gerbview/toolbars_gerber.cpp b/gerbview/toolbars_gerber.cpp index 367870265d..43384e7e0c 100644 --- a/gerbview/toolbars_gerber.cpp +++ b/gerbview/toolbars_gerber.cpp @@ -206,11 +206,10 @@ void GERBVIEW_FRAME::ReCreateVToolbar( void ) void GERBVIEW_FRAME::ReCreateOptToolbar( void ) { if( m_optionsToolBar ) - return; - - // creation of tool bar options - m_optionsToolBar = new wxAuiToolBar( this, ID_OPT_TOOLBAR, wxDefaultPosition, wxDefaultSize, - wxAUI_TB_DEFAULT_STYLE | wxAUI_TB_VERTICAL ); + m_optionsToolBar->Clear(); + else + m_optionsToolBar = new wxAuiToolBar( this, ID_OPT_TOOLBAR, wxDefaultPosition, wxDefaultSize, + wxAUI_TB_DEFAULT_STYLE | wxAUI_TB_VERTICAL ); // TODO: these can be moved to the 'proper' vertical toolbar if and when there are // actual tools to put there. That, or I'll get around to implementing configurable @@ -218,6 +217,17 @@ void GERBVIEW_FRAME::ReCreateOptToolbar( void ) m_optionsToolBar->AddTool( ID_NO_TOOL_SELECTED, wxEmptyString, KiBitmap( cursor_xpm ), wxEmptyString, wxITEM_CHECK ); + m_optionsToolBar->AddTool( ID_ZOOM_SELECTION, wxEmptyString, KiBitmap( zoom_area_xpm ), + _( "Zoom to selection" ), wxITEM_CHECK ); + + if( IsGalCanvasActive() ) + { + m_optionsToolBar->AddTool( ID_TB_MEASUREMENT_TOOL, wxEmptyString, + KiBitmap( measurement_xpm ), + _( "Measure distance between two points" ), + wxITEM_CHECK ); + } + m_optionsToolBar->AddSeparator(); m_optionsToolBar->AddTool( ID_TB_OPTIONS_SHOW_GRID, wxEmptyString, KiBitmap( grid_xpm ), @@ -264,23 +274,39 @@ void GERBVIEW_FRAME::ReCreateOptToolbar( void ) KiBitmap( show_dcodenumber_xpm ), _( "Show dcode number" ), wxITEM_CHECK ); - // tools to select draw mode in GerbView - m_optionsToolBar->AddSeparator(); - m_optionsToolBar->AddTool( ID_TB_OPTIONS_SHOW_GBR_MODE_0, wxEmptyString, - KiBitmap( gbr_select_mode0_xpm ), - _( "Show layers in raw mode \ -(could have problems with negative items when more than one gerber file is shown)" ), - wxITEM_CHECK ); - m_optionsToolBar->AddTool( ID_TB_OPTIONS_SHOW_GBR_MODE_1, wxEmptyString, - KiBitmap( gbr_select_mode1_xpm ), - _( "Show layers in stacked mode \ -(show negative items without artifacts, sometimes slow)" ), - wxITEM_CHECK ); - m_optionsToolBar->AddTool( ID_TB_OPTIONS_SHOW_GBR_MODE_2, wxEmptyString, - KiBitmap( gbr_select_mode2_xpm ), - _( "Show layers in transparency mode \ -(show negative items without artifacts, sometimes slow)" ), - wxITEM_CHECK ); + // tools to select draw mode in GerbView, unused in GAL + if( !IsGalCanvasActive() ) + { + m_optionsToolBar->AddSeparator(); + m_optionsToolBar->AddTool( ID_TB_OPTIONS_SHOW_GBR_MODE_0, wxEmptyString, + KiBitmap( gbr_select_mode0_xpm ), + _( "Show layers in raw mode \ + (could have problems with negative items when more than one gerber file is shown)" ), + wxITEM_CHECK ); + m_optionsToolBar->AddTool( ID_TB_OPTIONS_SHOW_GBR_MODE_1, wxEmptyString, + KiBitmap( gbr_select_mode1_xpm ), + _( "Show layers in stacked mode \ + (show negative items without artifacts, sometimes slow)" ), + wxITEM_CHECK ); + m_optionsToolBar->AddTool( ID_TB_OPTIONS_SHOW_GBR_MODE_2, wxEmptyString, + KiBitmap( gbr_select_mode2_xpm ), + _( "Show layers in transparency mode \ + (show negative items without artifacts, sometimes slow)" ), + wxITEM_CHECK ); + } + else + { + m_optionsToolBar->AddTool( ID_TB_OPTIONS_DIFF_MODE, wxEmptyString, + KiBitmap( gbr_select_mode2_xpm ), + _( "Show layers in diff (compare) mode" ), + wxITEM_CHECK ); + + m_optionsToolBar->AddTool( ID_TB_OPTIONS_HIGH_CONTRAST_MODE, wxEmptyString, + KiBitmap( contrast_mode_xpm ), + _( "Enable high contrast display mode" ), + wxITEM_CHECK ); + + } // Tools to show/hide toolbars: m_optionsToolBar->AddSeparator(); @@ -304,7 +330,7 @@ void GERBVIEW_FRAME::updateDCodeSelectBox() // Add an empty string to deselect net highlight m_DCodeSelector->Append( NO_SELECTION_STRING ); - int layer = getActiveLayer(); + int layer = GetActiveLayer(); GERBER_FILE_IMAGE* gerber = GetGbrImage( layer ); if( !gerber || gerber->GetDcodesCount() == 0 ) @@ -323,7 +349,7 @@ void GERBVIEW_FRAME::updateDCodeSelectBox() for( int ii = 0; ii < TOOLS_MAX_COUNT; ii++ ) { - D_CODE* dcode = gerber->GetDCODE( ii + FIRST_DCODE, false ); + D_CODE* dcode = gerber->GetDCODE( ii + FIRST_DCODE ); if( dcode == NULL ) continue; @@ -433,7 +459,7 @@ void GERBVIEW_FRAME::updateAperAttributesSelectBox() for( int ii = 0; ii < TOOLS_MAX_COUNT; ii++ ) { - D_CODE* aperture = gerber->GetDCODE( ii + FIRST_DCODE, false ); + D_CODE* aperture = gerber->GetDCODE( ii + FIRST_DCODE ); if( aperture == NULL ) continue; @@ -534,7 +560,7 @@ void GERBVIEW_FRAME::OnUpdateSelectDCode( wxUpdateUIEvent& aEvent ) if( !m_DCodeSelector ) return; - int layer = getActiveLayer(); + int layer = GetActiveLayer(); GERBER_FILE_IMAGE* gerber = GetGbrImage( layer ); int selected = ( gerber ) ? gerber->m_Selected_Tool : 0; @@ -553,8 +579,8 @@ void GERBVIEW_FRAME::OnUpdateSelectDCode( wxUpdateUIEvent& aEvent ) void GERBVIEW_FRAME::OnUpdateLayerSelectBox( wxUpdateUIEvent& aEvent ) { - if( m_SelLayerBox->GetSelection() != getActiveLayer() ) + if( m_SelLayerBox->GetSelection() != GetActiveLayer() ) { - m_SelLayerBox->SetSelection( getActiveLayer() ); + m_SelLayerBox->SetSelection( GetActiveLayer() ); } } diff --git a/include/core/typeinfo.h b/include/core/typeinfo.h index 1c4c4e597f..34c3324e63 100644 --- a/include/core/typeinfo.h +++ b/include/core/typeinfo.h @@ -171,7 +171,10 @@ enum KICAD_T /* * For GerbView: items type: */ - TYPE_GERBER_DRAW_ITEM, + GERBER_LAYOUT_T, + GERBER_DRAW_ITEM_T, + GERBER_IMAGE_LIST_T, + GERBER_IMAGE_T, /* * for Pl_Editor, in undo/redo commands diff --git a/include/layers_id_colors_and_visibility.h b/include/layers_id_colors_and_visibility.h index 26404fec1d..db861838e6 100644 --- a/include/layers_id_colors_and_visibility.h +++ b/include/layers_id_colors_and_visibility.h @@ -276,8 +276,8 @@ enum GERBVIEW_LAYER_ID: int { GERBVIEW_LAYER_ID_START = SCH_LAYER_ID_END, - /// GerbView draw layers - GERBVIEW_LAYER_ID_RESERVED = GERBVIEW_LAYER_ID_START + GERBER_DRAWLAYERS_COUNT, + /// GerbView draw layers and d-code layers + GERBVIEW_LAYER_ID_RESERVED = GERBVIEW_LAYER_ID_START + ( 2 * GERBER_DRAWLAYERS_COUNT ), LAYER_DCODES, LAYER_NEGATIVE_OBJECTS, @@ -288,6 +288,12 @@ enum GERBVIEW_LAYER_ID: int GERBVIEW_LAYER_ID_END }; +#define GERBER_DRAW_LAYER( x ) ( GERBVIEW_LAYER_ID_START + x ) + +#define GERBER_DCODE_LAYER( x ) ( GERBER_DRAWLAYERS_COUNT + x ) + +#define GERBER_DRAW_LAYER_INDEX( x ) ( x - GERBVIEW_LAYER_ID_START ) + /// Must update this if you add any enums after GerbView! #define LAYER_ID_COUNT GERBVIEW_LAYER_ID_END @@ -605,6 +611,7 @@ private: } }; + /** * Function IsValidLayer * tests whether a given integer is a valid layer index, i.e. can @@ -774,6 +781,13 @@ inline bool IsNetnameLayer( LAYER_NUM aLayer ) } +inline bool IsDCodeLayer( int aLayer ) +{ + return aLayer >= (GERBVIEW_LAYER_ID_START + GERBER_DRAWLAYERS_COUNT) && + aLayer < (GERBVIEW_LAYER_ID_START + (2 * GERBER_DRAWLAYERS_COUNT)); +} + + PCB_LAYER_ID ToLAYER_ID( int aLayer ); #endif // LAYERS_ID_AND_VISIBILITY_H_