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).
This commit is contained in:
parent
dacf0b2b96
commit
c71cf21e2f
|
@ -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<const PCB_TEXT*>( 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
|
||||
|
|
|
@ -649,7 +649,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
|
|||
{
|
||||
PCB_TEXT* text = static_cast<PCB_TEXT*>( 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<PCB_TEXTBOX*>( 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<PCB_TEXT*>( 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<PCB_TEXTBOX*>( item );
|
||||
|
||||
textbox->TransformTextToPolySet( *layerPoly, layer, 0, maxError, ERROR_INSIDE );
|
||||
textbox->TransformTextToPolySet( *layerPoly, 0, maxError, ERROR_INSIDE );
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 ) )
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -2382,7 +2382,7 @@ void BOARD::ConvertBrdLayerToPolygonalContours( PCB_LAYER_ID aLayer,
|
|||
case PCB_TEXT_T:
|
||||
{
|
||||
const PCB_TEXT* text = static_cast<const PCB_TEXT*>( 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -167,7 +167,7 @@ void DRC_TEST_PROVIDER_SOLDER_MASK::addItemToRTrees( BOARD_ITEM* aItem )
|
|||
{
|
||||
const PCB_TEXT* text = static_cast<const PCB_TEXT*>( 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 );
|
||||
|
|
|
@ -1952,13 +1952,13 @@ double FOOTPRINT::GetCoverageArea( const BOARD_ITEM* aItem, const GENERAL_COLLEC
|
|||
{
|
||||
const PCB_TEXT* text = static_cast<const PCB_TEXT*>( 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<const PCB_TEXTBOX*>( 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 );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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<SHAPE> 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<SHAPE_POLY_SET>( finalPoly );
|
||||
return std::make_shared<SHAPE_POLY_SET>( 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 );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -447,8 +447,8 @@ std::shared_ptr<SHAPE> 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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#include <pcb_plot_params.h>
|
||||
#include <settings/color_settings.h>
|
||||
#include <settings/settings_manager.h>
|
||||
#include <board.h>
|
||||
#include <board_design_settings.h>
|
||||
#include <board_item.h>
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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<const PCB_TEXT*>( 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
|
||||
{
|
||||
|
|
|
@ -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<const PCB_TEXT*>( 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 )
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -786,7 +786,7 @@ SHAPE_POLY_SET CONVERT_TOOL::makePolysFromClosedGraphics( const std::deque<EDA_I
|
|||
case PCB_TEXT_T:
|
||||
{
|
||||
PCB_TEXT* text = static_cast<PCB_TEXT*>( 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;
|
||||
}
|
||||
|
|
|
@ -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<PCB_TEXT*>( aItem ); break;
|
||||
case PCB_TEXTBOX_T: text = static_cast<PCB_TEXTBOX*>( 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<PCB_TEXT*>( 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<PCB_TEXTBOX*>( 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;
|
||||
|
|
Loading…
Reference in New Issue