From f4b2b1b03fe52b137f0d71dfcb4ffc261f593d18 Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Tue, 14 Feb 2023 14:42:19 +0000 Subject: [PATCH] Workaround wxWidgets enforced min pen width by using transparent pen. Also fixes some bugs in our shape printing code when a border is not specified but a fill is. Fixes https://gitlab.com/kicad/code/kicad/issues/13891 (cherry picked from commit 03484aedbc540438f0b6cceb992029f3bbbf5f76) --- common/gr_basic.cpp | 5 +++ eeschema/lib_shape.cpp | 91 ++++++++++++++++++++++-------------------- eeschema/sch_shape.cpp | 88 ++++++++++++++++++++++++++++++---------- 3 files changed, 119 insertions(+), 65 deletions(-) diff --git a/common/gr_basic.cpp b/common/gr_basic.cpp index 0470c9d401..935698ed95 100644 --- a/common/gr_basic.cpp +++ b/common/gr_basic.cpp @@ -91,6 +91,11 @@ void GRSetColorPen( wxDC* DC, const COLOR4D& Color, int width, wxPenStyle style if( s_ForceBlackPen ) color = COLOR4D::BLACK; + // wxWidgets will enforce a minimum pen width when printing, so we have to make the pen + // transparent when we don't want the object stroked. + if( width == 0 ) + color = COLOR4D::UNSPECIFIED; + const wxPen& curr_pen = DC->GetPen(); if( !curr_pen.IsOk() || curr_pen.GetColour() != color.ToColour() diff --git a/eeschema/lib_shape.cpp b/eeschema/lib_shape.cpp index 5de9d491ac..4c11d4a90e 100644 --- a/eeschema/lib_shape.cpp +++ b/eeschema/lib_shape.cpp @@ -389,54 +389,59 @@ void LIB_SHAPE::print( const RENDER_SETTINGS* aSettings, const VECTOR2I& aOffset UNIMPLEMENTED_FOR( SHAPE_T_asString() ); } } - - penWidth = std::max( penWidth, aSettings->GetDefaultPenWidth() ); - - if( GetEffectiveLineStyle() == PLOT_DASH_TYPE::SOLID ) - { - switch( GetShape() ) - { - case SHAPE_T::ARC: - GRArc( DC, pt1, pt2, c, penWidth, color ); - break; - - case SHAPE_T::CIRCLE: - GRCircle( DC, pt1, GetRadius(), penWidth, color ); - break; - - case SHAPE_T::RECT: - GRRect( DC, pt1, pt2, penWidth, color ); - break; - - case SHAPE_T::POLY: - GRPoly( DC, ptCount, buffer, false, penWidth, color, color ); - break; - - case SHAPE_T::BEZIER: - GRPoly( DC, ptCount, buffer, false, penWidth, color, color ); - break; - - default: - UNIMPLEMENTED_FOR( SHAPE_T_asString() ); - } - } else { - std::vector shapes = MakeEffectiveShapes( true ); + penWidth = std::max( penWidth, aSettings->GetDefaultPenWidth() ); + } - for( SHAPE* shape : shapes ) + if( penWidth > 0 ) + { + if( GetEffectiveLineStyle() == PLOT_DASH_TYPE::SOLID ) { - STROKE_PARAMS::Stroke( shape, GetEffectiveLineStyle(), penWidth, aSettings, - [&]( const VECTOR2I& a, const VECTOR2I& b ) - { - VECTOR2I pts = aTransform.TransformCoordinate( a ) + aOffset; - VECTOR2I pte = aTransform.TransformCoordinate( b ) + aOffset; - GRLine( DC, pts.x, pts.y, pte.x, pte.y, penWidth, color ); - } ); - } + switch( GetShape() ) + { + case SHAPE_T::ARC: + GRArc( DC, pt1, pt2, c, penWidth, color ); + break; - for( SHAPE* shape : shapes ) - delete shape; + case SHAPE_T::CIRCLE: + GRCircle( DC, pt1, GetRadius(), penWidth, color ); + break; + + case SHAPE_T::RECT: + GRRect( DC, pt1, pt2, penWidth, color ); + break; + + case SHAPE_T::POLY: + GRPoly( DC, ptCount, buffer, false, penWidth, color, color ); + break; + + case SHAPE_T::BEZIER: + GRPoly( DC, ptCount, buffer, false, penWidth, color, color ); + break; + + default: + UNIMPLEMENTED_FOR( SHAPE_T_asString() ); + } + } + else + { + std::vector shapes = MakeEffectiveShapes( true ); + + for( SHAPE* shape : shapes ) + { + STROKE_PARAMS::Stroke( shape, GetEffectiveLineStyle(), penWidth, aSettings, + [&]( const VECTOR2I& a, const VECTOR2I& b ) + { + VECTOR2I pts = aTransform.TransformCoordinate( a ) + aOffset; + VECTOR2I pte = aTransform.TransformCoordinate( b ) + aOffset; + GRLine( DC, pts.x, pts.y, pte.x, pte.y, penWidth, color ); + } ); + } + + for( SHAPE* shape : shapes ) + delete shape; + } } delete[] buffer; diff --git a/eeschema/sch_shape.cpp b/eeschema/sch_shape.cpp index 135a6d62bb..e239af3571 100644 --- a/eeschema/sch_shape.cpp +++ b/eeschema/sch_shape.cpp @@ -311,9 +311,15 @@ void SCH_SHAPE::Print( const RENDER_SETTINGS* aSettings, const VECTOR2I& aOffset { int penWidth = GetPenWidth(); wxDC* DC = aSettings->GetPrintDC(); - COLOR4D color; + COLOR4D color = GetStroke().GetColor(); - penWidth = std::max( penWidth, aSettings->GetMinPenWidth() ); + if( color == COLOR4D::UNSPECIFIED ) + color = aSettings->GetLayerColor( LAYER_NOTES ); + + COLOR4D bg = aSettings->GetBackgroundColor(); + + if( bg == COLOR4D::UNSPECIFIED || GetGRForceBlackPenState() ) + bg = COLOR4D::WHITE; unsigned ptCount = 0; VECTOR2I* buffer = nullptr; @@ -337,33 +343,35 @@ void SCH_SHAPE::Print( const RENDER_SETTINGS* aSettings, const VECTOR2I& aOffset buffer[ii] = m_bezierPoints[ii]; } - if( GetStroke().GetColor() == COLOR4D::UNSPECIFIED ) - color = aSettings->GetLayerColor( LAYER_NOTES ); - else - color = GetStroke().GetColor(); + COLOR4D fillColor = COLOR4D::UNSPECIFIED; - if( GetEffectiveLineStyle() == PLOT_DASH_TYPE::SOLID ) + if( GetFillMode() == FILL_T::FILLED_SHAPE ) + fillColor = color; + else if( GetFillMode() == FILL_T::FILLED_WITH_COLOR ) + fillColor = GetFillColor(); + + if( fillColor != COLOR4D::UNSPECIFIED ) { switch( GetShape() ) { case SHAPE_T::ARC: - GRArc( DC, GetEnd(), GetStart(), getCenter(), penWidth, color ); + GRFilledArc( DC, GetEnd(), GetStart(), getCenter(), 0, fillColor, fillColor ); break; case SHAPE_T::CIRCLE: - GRCircle( DC, GetStart(), GetRadius(), penWidth, color ); + GRFilledCircle( DC, GetStart(), GetRadius(), 0, fillColor, fillColor ); break; case SHAPE_T::RECT: - GRRect( DC, GetStart(), GetEnd(), penWidth, color ); + GRFilledRect( DC, GetStart(), GetEnd(), 0, fillColor, fillColor ); break; case SHAPE_T::POLY: - GRPoly( DC, ptCount, buffer, false, penWidth, color, color ); + GRPoly( DC, ptCount, buffer, true, 0, fillColor, fillColor ); break; case SHAPE_T::BEZIER: - GRPoly( DC, ptCount, buffer, false, penWidth, color, color ); + GRPoly( DC, ptCount, buffer, true, 0, fillColor, fillColor ); break; default: @@ -372,19 +380,55 @@ void SCH_SHAPE::Print( const RENDER_SETTINGS* aSettings, const VECTOR2I& aOffset } else { - std::vector shapes = MakeEffectiveShapes( true ); + penWidth = std::max( penWidth, aSettings->GetMinPenWidth() ); + } - for( SHAPE* shape : shapes ) + if( penWidth > 0 ) + { + if( GetEffectiveLineStyle() == PLOT_DASH_TYPE::SOLID ) { - STROKE_PARAMS::Stroke( shape, GetEffectiveLineStyle(), penWidth, aSettings, - [&]( const VECTOR2I& a, const VECTOR2I& b ) - { - GRLine( DC, a.x, a.y, b.x, b.y, penWidth, color ); - } ); - } + switch( GetShape() ) + { + case SHAPE_T::ARC: + GRArc( DC, GetEnd(), GetStart(), getCenter(), penWidth, color ); + break; - for( SHAPE* shape : shapes ) - delete shape; + case SHAPE_T::CIRCLE: + GRCircle( DC, GetStart(), GetRadius(), penWidth, color ); + break; + + case SHAPE_T::RECT: + GRRect( DC, GetStart(), GetEnd(), penWidth, color ); + break; + + case SHAPE_T::POLY: + GRPoly( DC, ptCount, buffer, false, penWidth, color, color ); + break; + + case SHAPE_T::BEZIER: + GRPoly( DC, ptCount, buffer, false, penWidth, color, color ); + break; + + default: + UNIMPLEMENTED_FOR( SHAPE_T_asString() ); + } + } + else + { + std::vector shapes = MakeEffectiveShapes( true ); + + for( SHAPE* shape : shapes ) + { + STROKE_PARAMS::Stroke( shape, GetEffectiveLineStyle(), penWidth, aSettings, + [&]( const VECTOR2I& a, const VECTOR2I& b ) + { + GRLine( DC, a.x, a.y, b.x, b.y, penWidth, color ); + } ); + } + + for( SHAPE* shape : shapes ) + delete shape; + } } delete[] buffer;