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;