From 7240b3e4d3543ac4a86cf332a47a8ff3a846cf88 Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Sun, 21 Jun 2020 19:47:26 +0200 Subject: [PATCH] PCB_PAINTER for D_PAD: for round and oval shapes, use native gal draw functions, instead of convert shapes to polygons. For small pad sizes (< 0.5mm) the polygonal shape is really ugly. Moreover, circles and oblong shapes are native in gal and give a much better look. --- pcbnew/pcb_painter.cpp | 131 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 117 insertions(+), 14 deletions(-) diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp index 83a9c930b0..daeaee01db 100644 --- a/pcbnew/pcb_painter.cpp +++ b/pcbnew/pcb_painter.cpp @@ -851,31 +851,103 @@ void PCB_PAINTER::draw( const D_PAD* aPad, int aLayer ) case F_Mask: case B_Mask: { - int clearance = aPad->GetSolderMaskMargin(); - aPad->TransformShapeWithClearanceToPolygon( polySet, clearance ); + int clearance = aPad->GetSolderMaskMargin(); + + if( aPad->GetShape() == PAD_SHAPE_CIRCLE ) + { + int radius = (aPad->GetSize().x/2) + clearance; + m_gal->DrawCircle( VECTOR2D( aPad->ShapePos() ), radius ); + } + else if( aPad->GetShape() == PAD_SHAPE_OVAL ) + { + if( aPad->GetSize().x == aPad->GetSize().y ) + { + int radius = (aPad->GetSize().x/2) + clearance; + m_gal->DrawCircle( VECTOR2D( aPad->ShapePos() ), radius ); + } + else + { + wxPoint seg_start, seg_end; + aPad->BuildSegmentFromOvalShape( seg_start, seg_end, + aPad->GetOrientation(), + wxSize( 0, 0 ) ); + int seg_width = std::min( aPad->GetSize().x, aPad->GetSize().y ) + + 2*clearance; + m_gal->DrawSegment( VECTOR2D( aPad->ShapePos()+seg_start ), + VECTOR2D( aPad->ShapePos()+seg_end ), + seg_width ); + } + } + else + { + aPad->TransformShapeWithClearanceToPolygon( polySet, clearance ); + m_gal->DrawPolygon( polySet ); + } } break; case F_Paste: case B_Paste: { - wxSize pad_size = aPad->GetSize(); - wxSize margin = aPad->GetSolderPasteMargin(); - const_cast(aPad)->SetSize( pad_size + margin + margin ); - aPad->TransformShapeWithClearanceToPolygon( polySet, 0 ); - const_cast(aPad)->SetSize( pad_size ); + wxSize pad_size = aPad->GetSize(); + wxSize margin = aPad->GetSolderPasteMargin(); + const_cast(aPad)->SetSize( pad_size + margin + margin ); + + if( aPad->GetShape() == PAD_SHAPE_CIRCLE ) + m_gal->DrawCircle( VECTOR2D( aPad->ShapePos() ), aPad->GetSize().x/2 ); + else if( aPad->GetShape() == PAD_SHAPE_OVAL ) + { + if( aPad->GetSize().x == aPad->GetSize().y ) + m_gal->DrawCircle( VECTOR2D( aPad->ShapePos() ), aPad->GetSize().x/2 ); + else + { + wxPoint seg_start, seg_end; + aPad->BuildSegmentFromOvalShape( seg_start, seg_end, + aPad->GetOrientation(), + wxSize( 0, 0 ) ); + int seg_width = std::min( aPad->GetSize().x, aPad->GetSize().y ); + m_gal->DrawSegment( VECTOR2D( aPad->ShapePos()+seg_start ), + VECTOR2D( aPad->ShapePos()+seg_end ), + seg_width ); + } + } + else + { + aPad->TransformShapeWithClearanceToPolygon( polySet, 0 ); + m_gal->DrawPolygon( polySet ); + } + const_cast(aPad)->SetSize( pad_size ); } break; default: - aPad->TransformShapeWithClearanceToPolygon( polySet, 0 ); + if( aPad->GetShape() == PAD_SHAPE_CIRCLE ) + m_gal->DrawCircle( VECTOR2D( aPad->ShapePos() ), aPad->GetSize().x/2 ); + else if( aPad->GetShape() == PAD_SHAPE_OVAL ) + { + if( aPad->GetSize().x == aPad->GetSize().y ) + m_gal->DrawCircle( VECTOR2D( aPad->ShapePos() ), aPad->GetSize().x/2 ); + else + { + wxPoint seg_start, seg_end; + aPad->BuildSegmentFromOvalShape( seg_start, seg_end, + aPad->GetOrientation(), + wxSize( 0, 0 ) ); + m_gal->DrawSegment( VECTOR2D( aPad->ShapePos()+seg_start ), + VECTOR2D( aPad->ShapePos()+seg_end ), + std::min( aPad->GetSize().x, aPad->GetSize().y ) ); + } + } + else + { + aPad->TransformShapeWithClearanceToPolygon( polySet, 0 ); + m_gal->DrawPolygon( polySet ); + } break; } - - m_gal->DrawPolygon( polySet ); } - // Clearance lines + // Clearance outlines constexpr int clearanceFlags = PCB_RENDER_SETTINGS::CL_PADS; if( ( m_pcbSettings.m_clearance & clearanceFlags ) == clearanceFlags @@ -883,13 +955,44 @@ void PCB_PAINTER::draw( const D_PAD* aPad, int aLayer ) || aLayer == LAYER_PAD_BK || aLayer == LAYER_PADS_TH ) ) { - SHAPE_POLY_SET polySet; - aPad->TransformShapeWithClearanceToPolygon( polySet, aPad->GetClearance() ); m_gal->SetLineWidth( m_pcbSettings.m_outlineWidth ); m_gal->SetIsStroke( true ); m_gal->SetIsFill( false ); m_gal->SetStrokeColor( color ); - m_gal->DrawPolygon( polySet ); + int clearance = aPad->GetClearance(); + + if( aPad->GetShape() == PAD_SHAPE_CIRCLE ) + { + int radius = (aPad->GetSize().x/2) + clearance; + m_gal->DrawCircle( VECTOR2D( aPad->ShapePos() ), radius ); + } + else if( aPad->GetShape() == PAD_SHAPE_OVAL ) + { + if( aPad->GetSize().x == aPad->GetSize().y ) + { + int radius = (aPad->GetSize().x/2) + clearance; + m_gal->DrawCircle( VECTOR2D( aPad->ShapePos() ), radius ); + } + else + { + wxPoint seg_start, seg_end; + + aPad->BuildSegmentFromOvalShape( seg_start, seg_end, + aPad->GetOrientation(), + wxSize( 0, 0 ) ); + int seg_width = std::min( aPad->GetSize().x, aPad->GetSize().y ) + + 2*clearance; + m_gal->DrawSegment( VECTOR2D( aPad->ShapePos()+seg_start ), + VECTOR2D( aPad->ShapePos()+seg_end ), + seg_width ); + } + } + else + { + SHAPE_POLY_SET polySet; + aPad->TransformShapeWithClearanceToPolygon( polySet, clearance ); + m_gal->DrawPolygon( polySet ); + } } }