From c71cf21e2ff3fa983cce05969dd827c43b76adda Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Sun, 28 May 2023 17:20:11 +0100 Subject: [PATCH] Use rendered text to generate bounding box for knockout text. Don't open-code knockout text shape generation in several different places. Make sure triangulated knockout text gets clearance added when specified. Collapse duplicated footprint text item plot routine (they're no longer any different from plotting pcb text items). --- .../3d_canvas/create_3Dgraphic_brd_items.cpp | 26 +---- 3d-viewer/3d_canvas/create_layer_items.cpp | 8 +- common/eda_text.cpp | 30 ----- include/eda_text.h | 13 --- pcbnew/board.cpp | 4 +- pcbnew/drc/drc_test_provider_solder_mask.cpp | 2 +- pcbnew/footprint.cpp | 6 +- pcbnew/pcb_painter.cpp | 22 +--- pcbnew/pcb_text.cpp | 92 +++++++++------ pcbnew/pcb_text.h | 11 +- pcbnew/pcb_textbox.cpp | 13 ++- pcbnew/pcb_textbox.h | 4 +- pcbnew/pcbplot.h | 6 +- pcbnew/plot_board_layers.cpp | 8 +- pcbnew/plot_brditems_plotter.cpp | 108 ++---------------- pcbnew/router/pns_kicad_iface.cpp | 10 +- pcbnew/tools/convert_tool.cpp | 2 +- pcbnew/zone_filler.cpp | 45 +++++--- 18 files changed, 138 insertions(+), 272 deletions(-) diff --git a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp index 3b85c33032..5bccd86e5e 100644 --- a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp +++ b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp @@ -74,29 +74,11 @@ void BOARD_ADAPTER::addText( const EDA_TEXT* aText, CONTAINER_2D_BASE* aContaine if( aOwner && aOwner->IsKnockout() ) { - SHAPE_POLY_SET knockouts; + SHAPE_POLY_SET finalPoly; + const PCB_TEXT* pcbText = static_cast( aOwner ); - CALLBACK_GAL callback_gal( empty_opts, - // Polygon callback - [&]( const SHAPE_LINE_CHAIN& aPoly ) - { - knockouts.AddOutline( aPoly ); - } ); - - attrs.m_StrokeWidth = aText->GetEffectiveTextPenWidth(); - attrs.m_Angle = aText->GetDrawRotation(); - - callback_gal.SetIsFill( font->IsOutline() ); - callback_gal.SetIsStroke( font->IsStroke() ); - callback_gal.SetLineWidth( attrs.m_StrokeWidth ); - font->Draw( &callback_gal, aText->GetShownText( true ), aText->GetDrawPos(), attrs ); - - SHAPE_POLY_SET finalPoly; - int margin = attrs.m_StrokeWidth * 1.5 + - GetKnockoutTextMargin( attrs.m_Size, attrs.m_StrokeWidth ); - - aText->TransformBoundingBoxToPolygon( &finalPoly, margin ); - finalPoly.BooleanSubtract( knockouts, SHAPE_POLY_SET::PM_FAST ); + pcbText->TransformTextToPolySet( finalPoly, 0, m_board->GetDesignSettings().m_MaxError, + ERROR_INSIDE ); // Do not call finalPoly.Fracture() here: ConvertPolygonToTriangles() call it // if needed, and Fracture() called twice can create bad results and is useless diff --git a/3d-viewer/3d_canvas/create_layer_items.cpp b/3d-viewer/3d_canvas/create_layer_items.cpp index 9dae96d744..a577c16eab 100644 --- a/3d-viewer/3d_canvas/create_layer_items.cpp +++ b/3d-viewer/3d_canvas/create_layer_items.cpp @@ -649,7 +649,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) { PCB_TEXT* text = static_cast( item ); - text->TransformTextToPolySet( *layerPoly, layer, 0, maxError, ERROR_INSIDE ); + text->TransformTextToPolySet( *layerPoly, 0, maxError, ERROR_INSIDE ); break; } @@ -657,7 +657,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) { PCB_TEXTBOX* textbox = static_cast( item ); - textbox->TransformTextToPolySet( *layerPoly, layer, 0, maxError, ERROR_INSIDE ); + textbox->TransformTextToPolySet( *layerPoly, 0, maxError, ERROR_INSIDE ); break; } @@ -958,7 +958,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) { PCB_TEXT* text = static_cast( item ); - text->TransformTextToPolySet( *layerPoly, layer, 0, maxError, ERROR_INSIDE ); + text->TransformTextToPolySet( *layerPoly, 0, maxError, ERROR_INSIDE ); break; } @@ -966,7 +966,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter ) { PCB_TEXTBOX* textbox = static_cast( item ); - textbox->TransformTextToPolySet( *layerPoly, layer, 0, maxError, ERROR_INSIDE ); + textbox->TransformTextToPolySet( *layerPoly, 0, maxError, ERROR_INSIDE ); break; } diff --git a/common/eda_text.cpp b/common/eda_text.cpp index 089b266de7..7999c5e70b 100644 --- a/common/eda_text.cpp +++ b/common/eda_text.cpp @@ -982,36 +982,6 @@ int EDA_TEXT::Compare( const EDA_TEXT* aOther ) const } -void EDA_TEXT::TransformBoundingBoxToPolygon( SHAPE_POLY_SET* aBuffer, int aClearance ) const -{ - if( GetText().Length() == 0 ) - return; - - VECTOR2I corners[4]; // Buffer of polygon corners - BOX2I rect = GetTextBox(); - - rect.Inflate( aClearance ); - - corners[0].x = rect.GetOrigin().x; - corners[0].y = rect.GetOrigin().y; - corners[1].y = corners[0].y; - corners[1].x = rect.GetRight(); - corners[2].x = corners[1].x; - corners[2].y = rect.GetBottom(); - corners[3].y = corners[2].y; - corners[3].x = corners[0].x; - - aBuffer->NewOutline(); - - for( VECTOR2I& corner : corners ) - { - RotatePoint( corner, GetDrawPos(), GetDrawRotation() ); - - aBuffer->Append( corner.x, corner.y ); - } -} - - bool EDA_TEXT::ValidateHyperlink( const wxString& aURL ) { if( aURL.IsEmpty() || IsGotoPageHref( aURL ) ) diff --git a/include/eda_text.h b/include/eda_text.h index ef78793e41..40709084cc 100644 --- a/include/eda_text.h +++ b/include/eda_text.h @@ -231,19 +231,6 @@ public: void Print( const RENDER_SETTINGS* aSettings, const VECTOR2I& aOffset, const COLOR4D& aColor, OUTLINE_MODE aDisplay_mode = FILLED ); - /** - * Convert the text bounding box to a rectangular polygon depending on the text - * orientation, the bounding box is not always horizontal or vertical - * - * Used in filling zones calculations - * Circles and arcs are approximated by segments - * - * @param aBuffer a buffer to store the polygon. - * @param aClearance the clearance around the text bounding box - * to the real clearance value (usually near from 1.0). - */ - void TransformBoundingBoxToPolygon( SHAPE_POLY_SET* aBuffer, int aClearance ) const; - /** * build a list of segments (SHAPE_SEGMENT) to describe a text shape. * @param aTriangulate: true to build also the triangulation of each shape diff --git a/pcbnew/board.cpp b/pcbnew/board.cpp index b911f87e40..a98ea661c4 100644 --- a/pcbnew/board.cpp +++ b/pcbnew/board.cpp @@ -2382,7 +2382,7 @@ void BOARD::ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer, case PCB_TEXT_T: { const PCB_TEXT* text = static_cast( item ); - text->TransformTextToPolySet( aOutlines, aLayer, 0, maxError, ERROR_INSIDE ); + text->TransformTextToPolySet( aOutlines, 0, maxError, ERROR_INSIDE ); break; } @@ -2394,7 +2394,7 @@ void BOARD::ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer, textbox->PCB_SHAPE::TransformShapeToPolygon( aOutlines, aLayer, 0, maxError, ERROR_INSIDE ); // plot text - textbox->TransformTextToPolySet( aOutlines, aLayer, 0, maxError, ERROR_INSIDE ); + textbox->TransformTextToPolySet( aOutlines, 0, maxError, ERROR_INSIDE ); break; } diff --git a/pcbnew/drc/drc_test_provider_solder_mask.cpp b/pcbnew/drc/drc_test_provider_solder_mask.cpp index 186f129c12..3b0ae7cc1f 100644 --- a/pcbnew/drc/drc_test_provider_solder_mask.cpp +++ b/pcbnew/drc/drc_test_provider_solder_mask.cpp @@ -167,7 +167,7 @@ void DRC_TEST_PROVIDER_SOLDER_MASK::addItemToRTrees( BOARD_ITEM* aItem ) { const PCB_TEXT* text = static_cast( aItem ); - text->TransformTextToPolySet( *solderMask->GetFill( layer ), layer, + text->TransformTextToPolySet( *solderMask->GetFill( layer ), m_webWidth / 2, m_maxError, ERROR_OUTSIDE ); m_itemTree->Insert( aItem, layer, m_largestClearance ); diff --git a/pcbnew/footprint.cpp b/pcbnew/footprint.cpp index c6a2a5c215..793d4bf79b 100644 --- a/pcbnew/footprint.cpp +++ b/pcbnew/footprint.cpp @@ -1952,13 +1952,13 @@ double FOOTPRINT::GetCoverageArea( const BOARD_ITEM* aItem, const GENERAL_COLLEC { const PCB_TEXT* text = static_cast( aItem ); - text->TransformTextToPolySet( poly, UNDEFINED_LAYER, textMargin, ARC_LOW_DEF, ERROR_OUTSIDE ); + text->TransformTextToPolySet( poly, textMargin, ARC_LOW_DEF, ERROR_OUTSIDE ); } else if( aItem->Type() == PCB_TEXTBOX_T ) { const PCB_TEXTBOX* tb = static_cast( aItem ); - tb->TransformTextToPolySet( poly, UNDEFINED_LAYER, textMargin, ARC_LOW_DEF, ERROR_OUTSIDE ); + tb->TransformTextToPolySet( poly, textMargin, ARC_LOW_DEF, ERROR_OUTSIDE ); } else if( aItem->Type() == PCB_SHAPE_T ) { @@ -2747,7 +2747,7 @@ void FOOTPRINT::TransformFPShapesToPolySet( SHAPE_POLY_SET& aBuffer, PCB_LAYER_I } for( const PCB_TEXT* text : texts ) - text->TransformTextToPolySet( aBuffer, aLayer, aClearance, aError, aErrorLoc ); + text->TransformTextToPolySet( aBuffer, aClearance, aError, aErrorLoc ); } diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp index 0e613bd7a3..d38270ce27 100644 --- a/pcbnew/pcb_painter.cpp +++ b/pcbnew/pcb_painter.cpp @@ -1973,28 +1973,8 @@ void PCB_PAINTER::draw( const PCB_TEXT* aText, int aLayer ) if( aText->IsKnockout() ) { - KIGFX::GAL_DISPLAY_OPTIONS empty_opts; - SHAPE_POLY_SET knockouts; - - CALLBACK_GAL callback_gal( empty_opts, - // Polygon callback - [&]( const SHAPE_LINE_CHAIN& aPoly ) - { - knockouts.AddOutline( aPoly ); - } ); - - attrs.m_StrokeWidth = getLineThickness( aText->GetEffectiveTextPenWidth() ); - - callback_gal.SetIsFill( font->IsOutline() ); - callback_gal.SetIsStroke( font->IsStroke() ); - callback_gal.SetLineWidth( attrs.m_StrokeWidth ); - font->Draw( &callback_gal, resolvedText, aText->GetDrawPos(), attrs ); - SHAPE_POLY_SET finalPoly; - int margin = GetKnockoutTextMargin( attrs.m_Size, attrs.m_StrokeWidth ); - - aText->TransformBoundingBoxToPolygon( &finalPoly, margin ); - finalPoly.BooleanSubtract( knockouts, SHAPE_POLY_SET::PM_FAST ); + aText->TransformTextToPolySet( finalPoly, 0, m_maxError, ERROR_INSIDE ); finalPoly.Fracture( SHAPE_POLY_SET::PM_FAST ); m_gal->SetIsStroke( false ); diff --git a/pcbnew/pcb_text.cpp b/pcbnew/pcb_text.cpp index 2ea663d89e..5c6eff629c 100644 --- a/pcbnew/pcb_text.cpp +++ b/pcbnew/pcb_text.cpp @@ -294,18 +294,12 @@ const BOX2I PCB_TEXT::GetBoundingBox() const bool PCB_TEXT::TextHitTest( const VECTOR2I& aPoint, int aAccuracy ) const { + int accuracy = aAccuracy; + if( IsKnockout() ) - { - SHAPE_POLY_SET poly; + accuracy += GetKnockoutTextMargin( GetTextSize(), GetTextThickness() ); - TransformBoundingBoxToPolygon( &poly, getKnockoutMargin()); - - return poly.Collide( aPoint, aAccuracy ); - } - else - { - return EDA_TEXT::TextHitTest( aPoint, aAccuracy ); - } + return EDA_TEXT::TextHitTest( aPoint, accuracy ); } @@ -432,29 +426,48 @@ std::shared_ptr PCB_TEXT::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHIN { if( IsKnockout() ) { - SHAPE_POLY_SET knockouts; + SHAPE_POLY_SET poly; - TransformTextToPolySet( knockouts, aLayer, 0, GetBoard()->GetDesignSettings().m_MaxError, - ERROR_INSIDE ); + TransformTextToPolySet( poly, 0, GetBoard()->GetDesignSettings().m_MaxError, ERROR_INSIDE ); - SHAPE_POLY_SET finalPoly; - int strokeWidth = GetEffectiveTextPenWidth(); - VECTOR2I fontSize = GetTextSize(); - int margin = GetKnockoutTextMargin( fontSize, strokeWidth ); - - TransformBoundingBoxToPolygon( &finalPoly, margin ); - finalPoly.BooleanSubtract( knockouts, SHAPE_POLY_SET::PM_FAST ); - finalPoly.Fracture( SHAPE_POLY_SET::PM_FAST ); - - return std::make_shared( finalPoly ); + return std::make_shared( poly ); } return GetEffectiveTextShape(); } -void PCB_TEXT::TransformTextToPolySet( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, - int aClearance, int aError, ERROR_LOC aErrorLoc ) const +void PCB_TEXT::buildBoundingHull( SHAPE_POLY_SET* aBuffer, const SHAPE_POLY_SET& aRenderedText, + int aClearance ) const +{ + SHAPE_POLY_SET poly( aRenderedText ); + + poly.Rotate( -GetDrawRotation(), GetDrawPos() ); + + BOX2I rect = poly.BBox( aClearance ); + VECTOR2I corners[4]; + + corners[0].x = rect.GetOrigin().x; + corners[0].y = rect.GetOrigin().y; + corners[1].y = corners[0].y; + corners[1].x = rect.GetRight(); + corners[2].x = corners[1].x; + corners[2].y = rect.GetBottom(); + corners[3].y = corners[2].y; + corners[3].x = corners[0].x; + + aBuffer->NewOutline(); + + for( VECTOR2I& corner : corners ) + { + RotatePoint( corner, GetDrawPos(), GetDrawRotation() ); + aBuffer->Append( corner.x, corner.y ); + } +} + + +void PCB_TEXT::TransformTextToPolySet( SHAPE_POLY_SET& aBuffer, int aClearance, int aError, + ERROR_LOC aErrorLoc ) const { KIGFX::GAL_DISPLAY_OPTIONS empty_opts; KIFONT::FONT* font = getDrawFont(); @@ -466,41 +479,42 @@ void PCB_TEXT::TransformTextToPolySet( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLa // The polygonal shape of a text can have many basic shapes, so combining these shapes can // be very useful to create a final shape with a lot less vertices to speedup calculations. // Simplify shapes is not usually always efficient, but in this case it is. - SHAPE_POLY_SET buffer; + SHAPE_POLY_SET textShape; CALLBACK_GAL callback_gal( empty_opts, // Stroke callback [&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 ) { - TransformOvalToPolygon( buffer, aPt1, aPt2, penWidth + ( 2 * aClearance ), - aError, ERROR_INSIDE ); + TransformOvalToPolygon( textShape, aPt1, aPt2, penWidth, aError, aErrorLoc ); }, // Triangulation callback [&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2, const VECTOR2I& aPt3 ) { - buffer.NewOutline(); + textShape.NewOutline(); for( const VECTOR2I& point : { aPt1, aPt2, aPt3 } ) - buffer.Append( point.x, point.y ); + textShape.Append( point.x, point.y ); } ); font->Draw( &callback_gal, GetShownText( true ), GetTextPos(), attrs ); - buffer.Simplify( SHAPE_POLY_SET::PM_FAST ); + textShape.Simplify( SHAPE_POLY_SET::PM_FAST ); if( IsKnockout() ) { SHAPE_POLY_SET finalPoly; - int margin = attrs.m_StrokeWidth * 1.5 - + GetKnockoutTextMargin( attrs.m_Size, attrs.m_StrokeWidth ); + int margin = GetKnockoutTextMargin( attrs.m_Size, penWidth ); - TransformBoundingBoxToPolygon( &finalPoly, margin ); - finalPoly.BooleanSubtract( buffer, SHAPE_POLY_SET::PM_FAST ); + buildBoundingHull( &finalPoly, textShape, margin + aClearance ); + finalPoly.BooleanSubtract( textShape, SHAPE_POLY_SET::PM_FAST ); aBuffer.Append( finalPoly ); } else { - aBuffer.Append( buffer ); + if( aClearance > 0 ) + textShape.Inflate( aClearance, aClearance ); + + aBuffer.Append( textShape ); } } @@ -509,7 +523,11 @@ void PCB_TEXT::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aL int aClearance, int aError, ERROR_LOC aErrorLoc, bool aIgnoreLineWidth ) const { - EDA_TEXT::TransformBoundingBoxToPolygon( &aBuffer, aClearance ); + SHAPE_POLY_SET poly; + + TransformTextToPolySet( poly, 0, GetBoard()->GetDesignSettings().m_MaxError, ERROR_INSIDE ); + + buildBoundingHull( &aBuffer, poly, aClearance ); } diff --git a/pcbnew/pcb_text.h b/pcbnew/pcb_text.h index 01066499d6..886d2f1ab8 100644 --- a/pcbnew/pcb_text.h +++ b/pcbnew/pcb_text.h @@ -139,8 +139,8 @@ public: * @param aClearance the clearance around the text * @param aError the maximum error to allow when approximating curves */ - void TransformTextToPolySet( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, int aClearance, - int aError, ERROR_LOC aErrorLoc ) const; + void TransformTextToPolySet( SHAPE_POLY_SET& aBuffer, int aClearance, int aError, + ERROR_LOC aErrorLoc ) const; void TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, @@ -178,6 +178,13 @@ public: #endif protected: + /** + * Build a nominally rectangular bounding box for the rendered text. (It's not a BOX2I + * because it will be a diamond shape for non-cardinally rotated text.) + */ + void buildBoundingHull( SHAPE_POLY_SET* aBuffer, const SHAPE_POLY_SET& aRenderedText, + int aClearance ) const; + virtual void swapData( BOARD_ITEM* aImage ) override; int getKnockoutMargin() const; diff --git a/pcbnew/pcb_textbox.cpp b/pcbnew/pcb_textbox.cpp index 3e2113cd24..8c3f1f57e8 100644 --- a/pcbnew/pcb_textbox.cpp +++ b/pcbnew/pcb_textbox.cpp @@ -447,8 +447,8 @@ std::shared_ptr PCB_TEXTBOX::GetEffectiveShape( PCB_LAYER_ID aLayer, FLAS } -void PCB_TEXTBOX::TransformTextToPolySet( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, - int aClearance, int aError, ERROR_LOC aErrorLoc ) const +void PCB_TEXTBOX::TransformTextToPolySet( SHAPE_POLY_SET& aBuffer, int aClearance, int aError, + ERROR_LOC aErrorLoc ) const { KIGFX::GAL_DISPLAY_OPTIONS empty_opts; KIFONT::FONT* font = getDrawFont(); @@ -465,8 +465,7 @@ void PCB_TEXTBOX::TransformTextToPolySet( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID // Stroke callback [&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 ) { - TransformOvalToPolygon( buffer, aPt1, aPt2, penWidth + ( 2 * aClearance ), aError, - ERROR_INSIDE ); + TransformOvalToPolygon( buffer, aPt1, aPt2, penWidth, aError, aErrorLoc ); }, // Triangulation callback [&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2, const VECTOR2I& aPt3 ) @@ -479,7 +478,11 @@ void PCB_TEXTBOX::TransformTextToPolySet( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID font->Draw( &callback_gal, GetShownText( true ), GetDrawPos(), GetAttributes() ); - buffer.Simplify( SHAPE_POLY_SET::PM_FAST ); + if( aClearance > 0 ) + buffer.Inflate( aClearance, aClearance ); + else + buffer.Simplify( SHAPE_POLY_SET::PM_FAST ); + aBuffer.Append( buffer ); } diff --git a/pcbnew/pcb_textbox.h b/pcbnew/pcb_textbox.h index 52639c17c6..7ea761a009 100644 --- a/pcbnew/pcb_textbox.h +++ b/pcbnew/pcb_textbox.h @@ -114,8 +114,8 @@ public: * @param aClearance = the clearance around the text * @param aError = the maximum error to allow when approximating curves */ - void TransformTextToPolySet( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, int aClearance, - int aError, ERROR_LOC aErrorLoc ) const; + void TransformTextToPolySet( SHAPE_POLY_SET& aBuffer, int aClearance, int aError, + ERROR_LOC aErrorLoc ) const; void TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, diff --git a/pcbnew/pcbplot.h b/pcbnew/pcbplot.h index a8927c277e..89c4cd1e3c 100644 --- a/pcbnew/pcbplot.h +++ b/pcbnew/pcbplot.h @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include class EDA_TEXT; @@ -39,8 +41,6 @@ class PCB_DIMENSION_BASE; class FOOTPRINT; class PCB_TARGET; class ZONE; -class BOARD; -class BOARD_ITEM; class REPORTER; class wxFileName; @@ -60,6 +60,7 @@ public: { m_plotter = aPlotter; m_board = aBoard; + m_maxError = aBoard->GetDesignSettings().m_MaxError; } /** @@ -137,6 +138,7 @@ private: PLOTTER* m_plotter; BOARD* m_board; + int m_maxError; // For use when approximating shapes as polygons LSET m_layerMask; }; diff --git a/pcbnew/plot_board_layers.cpp b/pcbnew/plot_board_layers.cpp index e4801fa2a1..10728ca081 100644 --- a/pcbnew/plot_board_layers.cpp +++ b/pcbnew/plot_board_layers.cpp @@ -848,10 +848,10 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask, return; // add shapes with their exact mask layer size in initialPolys - aText.TransformTextToPolySet( initialPolys, layer, 0, maxError, ERROR_OUTSIDE ); + aText.TransformTextToPolySet( initialPolys, 0, maxError, ERROR_OUTSIDE ); // add shapes inflated by aMinThickness/2 in areas - aText.TransformTextToPolySet( areas, layer, inflate, maxError, ERROR_OUTSIDE ); + aText.TransformTextToPolySet( areas, inflate, maxError, ERROR_OUTSIDE ); }; // Generate polygons with arcs inside the shape or exact shape to minimize shape changes @@ -934,10 +934,10 @@ void PlotSolderMaskLayer( BOARD *aBoard, PLOTTER* aPlotter, LSET aLayerMask, const PCB_TEXT* text = static_cast( item ); // add shapes with their exact mask layer size in initialPolys - text->TransformTextToPolySet( initialPolys, layer, 0, maxError, ERROR_OUTSIDE ); + text->TransformTextToPolySet( initialPolys, 0, maxError, ERROR_OUTSIDE ); // add shapes inflated by aMinThickness/2 in areas - text->TransformTextToPolySet( areas, layer, inflate, maxError, ERROR_OUTSIDE ); + text->TransformTextToPolySet( areas, inflate, maxError, ERROR_OUTSIDE ); } else { diff --git a/pcbnew/plot_brditems_plotter.cpp b/pcbnew/plot_brditems_plotter.cpp index d680e5b62c..69553b004d 100644 --- a/pcbnew/plot_brditems_plotter.cpp +++ b/pcbnew/plot_brditems_plotter.cpp @@ -294,13 +294,13 @@ void BRDITEMS_PLOTTER::PlotPad( const PAD* aPad, const COLOR4D& aColor, OUTLINE_ void BRDITEMS_PLOTTER::PlotFootprintTextItems( const FOOTPRINT* aFootprint ) { const PCB_TEXT* textItem = &aFootprint->Reference(); - int textLayer = textItem->GetLayer(); + PCB_LAYER_ID textLayer = textItem->GetLayer(); // Reference and value are specific items, not in graphic items list if( GetPlotReference() && m_layerMask[textLayer] && ( textItem->IsVisible() || GetPlotInvisibleText() ) ) { - PlotFootprintTextItem( textItem, getColor( textLayer ) ); + PlotPcbText( textItem, textLayer, textItem->IsKnockout() ); } textItem = &aFootprint->Value(); @@ -309,7 +309,7 @@ void BRDITEMS_PLOTTER::PlotFootprintTextItems( const FOOTPRINT* aFootprint ) if( GetPlotValue() && m_layerMask[textLayer] && ( textItem->IsVisible() || GetPlotInvisibleText() ) ) { - PlotFootprintTextItem( textItem, getColor( textLayer ) ); + PlotPcbText( textItem, textLayer, textItem->IsKnockout() ); } for( const BOARD_ITEM* item : aFootprint->GraphicalItems() ) @@ -336,7 +336,7 @@ void BRDITEMS_PLOTTER::PlotFootprintTextItems( const FOOTPRINT* aFootprint ) if( textItem->GetText() == wxT( "${VALUE}" ) && !GetPlotValue() ) continue; - PlotFootprintTextItem( textItem, getColor( textLayer ) ); + PlotPcbText( textItem, textLayer, textItem->IsKnockout() ); } } @@ -389,84 +389,6 @@ void BRDITEMS_PLOTTER::PlotBoardGraphicItems() } -void BRDITEMS_PLOTTER::PlotFootprintTextItem( const PCB_TEXT* aText, const COLOR4D& aColor ) -{ - COLOR4D color = aColor; - - if( aColor == COLOR4D::WHITE ) - color = COLOR4D( LIGHTGRAY ); - - m_plotter->SetColor( color ); - - // calculate some text parameters : - //VECTOR2I size = aText->GetTextSize(); - VECTOR2I pos = aText->GetTextPos(); - int thickness = aText->GetEffectiveTextPenWidth(); - KIFONT::FONT* font = aText->GetFont(); - - if( !font ) - { - font = KIFONT::FONT::GetFont( m_plotter->RenderSettings() - ? m_plotter->RenderSettings()->GetDefaultFont() - : wxString( wxEmptyString ), - aText->IsBold(), aText->IsItalic() ); - } - - // Non bold texts thickness is clamped at 1/6 char size by the low level draw function. - // but in Pcbnew we do not manage bold texts and thickness up to 1/4 char size - // (like bold text) and we manage the thickness. - // So we set bold flag to true - TEXT_ATTRIBUTES attrs = aText->GetAttributes(); - attrs.m_StrokeWidth = thickness; - attrs.m_Angle = aText->GetDrawRotation(); - attrs.m_Bold = true; - attrs.m_Multiline = false; - - GBR_METADATA gbr_metadata; - - if( IsCopperLayer( aText->GetLayer() ) ) - gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_NONCONDUCTOR ); - - gbr_metadata.SetNetAttribType( GBR_NETLIST_METADATA::GBR_NETINFO_CMP ); - const FOOTPRINT* parent = aText->GetParentFootprint(); - gbr_metadata.SetCmpReference( parent->GetReference() ); - - m_plotter->SetCurrentLineWidth( thickness ); - - if( aText->IsKnockout() ) - { - KIGFX::GAL_DISPLAY_OPTIONS empty_opts; - SHAPE_POLY_SET knockouts; - - CALLBACK_GAL callback_gal( empty_opts, - // Polygon callback - [&]( const SHAPE_LINE_CHAIN& aPoly ) - { - knockouts.AddOutline( aPoly ); - } ); - - callback_gal.SetIsFill( font->IsOutline() ); - callback_gal.SetIsStroke( font->IsStroke() ); - font->Draw( &callback_gal, aText->GetShownText( true ), aText->GetDrawPos(), attrs ); - - SHAPE_POLY_SET finalPoly; - int margin = attrs.m_StrokeWidth * 1.5 - + GetKnockoutTextMargin( attrs.m_Size, attrs.m_StrokeWidth ); - - aText->TransformBoundingBoxToPolygon( &finalPoly, margin ); - finalPoly.BooleanSubtract( knockouts, SHAPE_POLY_SET::PM_FAST ); - finalPoly.Fracture( SHAPE_POLY_SET::PM_FAST ); - - for( int ii = 0; ii < finalPoly.OutlineCount(); ++ii ) - m_plotter->PlotPoly( finalPoly.Outline( ii ), FILL_T::FILLED_SHAPE, 0, &gbr_metadata ); - } - else - { - m_plotter->PlotText( pos, aColor, aText->GetShownText( true ), attrs, font, &gbr_metadata ); - } -} - - void BRDITEMS_PLOTTER::PlotDimension( const PCB_DIMENSION_BASE* aDim ) { if( !m_layerMask[aDim->GetLayer()] ) @@ -623,7 +545,7 @@ void BRDITEMS_PLOTTER::PlotFootprintGraphicItems( const FOOTPRINT* aFootprint ) } case PCB_TEXT_T: - // Plotted in PlotFootprintTextItem() + // Plotted in PlotFootprintTextItems() break; default: @@ -673,26 +595,10 @@ void BRDITEMS_PLOTTER::PlotPcbText( const EDA_TEXT* aText, PCB_LAYER_ID aLayer, if( aIsKnockout ) { - KIGFX::GAL_DISPLAY_OPTIONS empty_opts; - SHAPE_POLY_SET knockouts; - - CALLBACK_GAL callback_gal( empty_opts, - // Polygon callback - [&]( const SHAPE_LINE_CHAIN& aPoly ) - { - knockouts.AddOutline( aPoly ); - } ); - - callback_gal.SetIsFill( font->IsOutline() ); - callback_gal.SetIsStroke( font->IsStroke() ); - font->Draw( &callback_gal, shownText, aText->GetDrawPos(), attrs ); - + const PCB_TEXT* text = static_cast( aText ); SHAPE_POLY_SET finalPoly; - int margin = attrs.m_StrokeWidth * 1.5 - + GetKnockoutTextMargin( attrs.m_Size, attrs.m_StrokeWidth ); - aText->TransformBoundingBoxToPolygon( &finalPoly, margin ); - finalPoly.BooleanSubtract( knockouts, SHAPE_POLY_SET::PM_FAST ); + text->TransformTextToPolySet( finalPoly, 0, m_maxError, ERROR_INSIDE ); finalPoly.Fracture( SHAPE_POLY_SET::PM_FAST ); for( int ii = 0; ii < finalPoly.OutlineCount(); ++ii ) diff --git a/pcbnew/router/pns_kicad_iface.cpp b/pcbnew/router/pns_kicad_iface.cpp index 527f93860e..8f193229a3 100644 --- a/pcbnew/router/pns_kicad_iface.cpp +++ b/pcbnew/router/pns_kicad_iface.cpp @@ -1288,14 +1288,10 @@ bool PNS_KICAD_IFACE_BASE::syncTextItem( PNS::NODE* aWorld, PCB_TEXT* aText, PCB solid->SetShape( shape ); // takes ownership solid->SetRoutable( false ); - TEXT_ATTRIBUTES attrs = aText->GetAttributes(); - int margin = 0; - SHAPE_POLY_SET cornerBuffer; + SHAPE_POLY_SET cornerBuffer; - if( aText->IsKnockout() ) - margin = GetKnockoutTextMargin( attrs.m_Size, attrs.m_StrokeWidth ); - - aText->TransformBoundingBoxToPolygon( &cornerBuffer, margin ); + aText->TransformShapeToPolygon( cornerBuffer, aText->GetLayer(), 0, + m_board->GetDesignSettings().m_MaxError, ERROR_OUTSIDE ); if( !cornerBuffer.OutlineCount() ) return false; diff --git a/pcbnew/tools/convert_tool.cpp b/pcbnew/tools/convert_tool.cpp index f55f7f0fbb..f23fa81f90 100644 --- a/pcbnew/tools/convert_tool.cpp +++ b/pcbnew/tools/convert_tool.cpp @@ -786,7 +786,7 @@ SHAPE_POLY_SET CONVERT_TOOL::makePolysFromClosedGraphics( const std::deque( item ); - text->TransformTextToPolySet( poly, UNDEFINED_LAYER, 0, bds.m_MaxError, ERROR_INSIDE ); + text->TransformTextToPolySet( poly, 0, bds.m_MaxError, ERROR_INSIDE ); text->SetFlags( SKIP_STRUCT ); break; } diff --git a/pcbnew/zone_filler.cpp b/pcbnew/zone_filler.cpp index 21ed248aa4..544fcaa687 100644 --- a/pcbnew/zone_filler.cpp +++ b/pcbnew/zone_filler.cpp @@ -813,28 +813,43 @@ void ZONE_FILLER::addHoleKnockout( PAD* aPad, int aGap, SHAPE_POLY_SET& aHoles ) void ZONE_FILLER::addKnockout( BOARD_ITEM* aItem, PCB_LAYER_ID aLayer, int aGap, bool aIgnoreLineWidth, SHAPE_POLY_SET& aHoles ) { - EDA_TEXT* text = nullptr; - switch( aItem->Type() ) { - case PCB_TEXT_T: text = static_cast( aItem ); break; - case PCB_TEXTBOX_T: text = static_cast( aItem ); break; - default: break; - } - - switch( aItem->Type() ) - { - case PCB_SHAPE_T: case PCB_TEXT_T: - case PCB_TEXTBOX_T: - case PCB_TARGET_T: - if( !text || text->IsVisible() ) + { + PCB_TEXT* text = static_cast( aItem ); + + if( text->IsVisible() ) { - aItem->TransformShapeToPolygon( aHoles, aLayer, aGap, m_maxError, ERROR_OUTSIDE, - aIgnoreLineWidth ); + if( text->IsKnockout() ) + { + int antiGap = -m_maxError * 2; // Don't leave gaps around knockout text + text->TransformShapeToPolygon( aHoles, aLayer, antiGap, m_maxError, ERROR_OUTSIDE ); + } + else + { + text->TransformShapeToPolygon( aHoles, aLayer, aGap, m_maxError, ERROR_OUTSIDE ); + } } break; + } + + case PCB_TEXTBOX_T: + { + PCB_TEXTBOX* textbox = static_cast( aItem ); + + if( textbox->IsVisible() ) + textbox->TransformShapeToPolygon( aHoles, aLayer, aGap, m_maxError, ERROR_OUTSIDE ); + + break; + } + + case PCB_SHAPE_T: + case PCB_TARGET_T: + aItem->TransformShapeToPolygon( aHoles, aLayer, aGap, m_maxError, ERROR_OUTSIDE, + aIgnoreLineWidth ); + break; default: break;