ADDED: knockout pcb and fp text.

Fixes https://gitlab.com/kicad/code/kicad/issues/7055
This commit is contained in:
Jeff Young 2022-03-08 13:16:39 +00:00
parent 96f9ea286e
commit 293021c58c
17 changed files with 307 additions and 122 deletions

View File

@ -28,7 +28,7 @@
showgrid="true"
inkscape:zoom="21.189179"
inkscape:cx="12.751369"
inkscape:cy="11.535261"
inkscape:cy="12.434844"
inkscape:window-x="0"
inkscape:window-y="23"
inkscape:window-maximized="0"
@ -81,14 +81,14 @@
id="title176">add_glabel</title>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:26.6667px;line-height:1.25;font-family:sans-serif;fill:#333333;fill-opacity:1;stroke:none"
x="-21.317667"
y="20.574646"
style="font-style:normal;font-weight:normal;font-size:26.7797px;line-height:1.25;font-family:sans-serif;fill:#333333;fill-opacity:1;stroke:none;stroke-width:1.11582"
x="-21.453262"
y="20.113962"
id="text863"
transform="scale(-1,1)"><tspan
transform="scale(-0.95860218,1.0431856)"><tspan
sodipodi:role="line"
id="tspan861"
x="-21.317667"
y="20.574646"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:26.6667px;font-family:'Gurmukhi MN';-inkscape-font-specification:'Gurmukhi MN';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#333333">R</tspan></text>
x="-21.453262"
y="20.113962"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:26.7797px;font-family:'Gurmukhi MN';-inkscape-font-specification:'Gurmukhi MN';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#333333;stroke-width:1.11582">R</tspan></text>
</svg>

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@ -21,12 +21,13 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <plotters/plotter.h>
#include <trigo.h>
#include <convert_to_biu.h>
#include <convert_basic_shapes_to_polygon.h>
#include <geometry/geometry_utils.h>
#include <callback_gal.h>
using namespace KIGFX;
@ -39,7 +40,22 @@ void CALLBACK_GAL::DrawGlyph( const KIFONT::GLYPH& aGlyph, int aNth, int aTotal
for( const std::vector<VECTOR2D>& pointList : glyph )
{
for( size_t ii = 1; ii < pointList.size(); ii++ )
m_strokeCallback( pointList[ ii - 1], pointList[ii] );
{
if( m_stroke )
{
m_strokeCallback( pointList[ ii - 1 ], pointList[ ii ] );
}
else
{
int strokeWidth = GetLineWidth();
SHAPE_POLY_SET poly;
TransformOvalToPolygon( poly, pointList[ ii - 1 ], pointList[ ii ],
strokeWidth, strokeWidth / 48, ERROR_OUTSIDE );
m_outlineCallback( poly.Outline( 0 ) );
}
}
}
}
else if( aGlyph.IsOutline() )

View File

@ -853,39 +853,49 @@ std::shared_ptr<SHAPE_COMPOUND> EDA_TEXT::GetEffectiveTextShape( bool aTriangula
KIGFX::GAL_DISPLAY_OPTIONS empty_opts;
KIFONT::FONT* font = GetDrawFont();
int penWidth = GetEffectiveTextPenWidth();
TEXT_ATTRIBUTES attrs = GetAttributes();
attrs.m_Angle = GetDrawRotation();
CALLBACK_GAL callback_gal(
empty_opts,
// Stroke callback
[&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 )
{
shape->AddShape( new SHAPE_SEGMENT( aPt1, aPt2, penWidth ) );
},
// Triangulation callback
[&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2, const VECTOR2I& aPt3 )
{
SHAPE_SIMPLE* triShape = new SHAPE_SIMPLE;
for( const VECTOR2I& point : { aPt1, aPt2, aPt3 } )
triShape->Append( point.x, point.y );
shape->AddShape( triShape );
} );
if( !aTriangulate )
if( aTriangulate )
{
callback_gal.SetOutlineCallback(
CALLBACK_GAL callback_gal(
empty_opts,
// Stroke callback
[&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 )
{
shape->AddShape( new SHAPE_SEGMENT( aPt1, aPt2, penWidth ) );
},
// Triangulation callback
[&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2, const VECTOR2I& aPt3 )
{
SHAPE_SIMPLE* triShape = new SHAPE_SIMPLE;
for( const VECTOR2I& point : { aPt1, aPt2, aPt3 } )
triShape->Append( point.x, point.y );
shape->AddShape( triShape );
} );
font->Draw( &callback_gal, GetShownText(), GetDrawPos(), attrs );
}
else
{
CALLBACK_GAL callback_gal(
empty_opts,
// Stroke callback
[&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 )
{
shape->AddShape( new SHAPE_SEGMENT( aPt1, aPt2, penWidth ) );
},
// Outline callback
[&]( const SHAPE_LINE_CHAIN& aPoly )
{
shape->AddShape( aPoly.Clone() );
} );
font->Draw( &callback_gal, GetShownText(), GetDrawPos(), attrs );
}
TEXT_ATTRIBUTES attrs = GetAttributes();
attrs.m_Angle = GetDrawRotation();
font->Draw( &callback_gal, GetShownText(), GetDrawPos(), attrs );
return shape;
}

View File

@ -158,6 +158,7 @@ keep_end_layers
keep_text_aligned
keep_upright
kicad_pcb
knockout
last_trace_width
layer
layers

View File

@ -54,6 +54,8 @@ public:
BOARD_ITEM( BOARD_ITEM* aParent, KICAD_T idtype, PCB_LAYER_ID aLayer = F_Cu ) :
EDA_ITEM( aParent, idtype ),
m_layer( aLayer ),
m_isKnockout( false ),
m_isLocked( false ),
m_group( nullptr )
{
}
@ -215,28 +217,11 @@ public:
return m_layer == aLayer;
}
/**
* Test to see if this object is a track or via (or microvia).
*
* @return true if a track or via, else false.
*/
bool IsTrack() const
{
return ( Type() == PCB_TRACE_T ) || ( Type() == PCB_VIA_T );
}
virtual bool IsKnockout() const { return m_isKnockout; }
virtual void SetIsKnockout( bool aKnockout ) { m_isKnockout = aKnockout; }
/**
* @return true if the object is locked, else false.
*/
virtual bool IsLocked() const;
/**
* Modify the 'lock' status for of the item.
*/
virtual void SetLocked( bool aLocked )
{
SetState( LOCKED, aLocked );
}
virtual void SetLocked( bool aLocked ) { m_isLocked = aLocked; }
/**
* Delete this object after removing from its parent if it has one.
@ -307,12 +292,16 @@ public:
protected:
/**
* Return a string (to be shown to the user) describing a layer mask. The BOARD is needed
* because layer names are customizable.
* Return a string (to be shown to the user) describing a layer mask.
*/
virtual wxString layerMaskDescribe() const;
protected:
PCB_LAYER_ID m_layer;
bool m_isKnockout;
bool m_isLocked;
PCB_GROUP* m_group;
};

View File

@ -33,13 +33,14 @@ public:
std::function<void( const VECTOR2I& aPt1,
const VECTOR2I& aPt2 )> aStrokeCallback,
std::function<void( const VECTOR2I& aPt1,
const VECTOR2I& aPt2,
const VECTOR2I& aPt3 )> aTriangleCallback ) :
const VECTOR2I& aPt2,
const VECTOR2I& aPt3 )> aTriangleCallback ) :
GAL( aDisplayOptions )
{
m_strokeCallback = aStrokeCallback;
m_triangleCallback = aTriangleCallback;
m_outlineCallback = []( const SHAPE_LINE_CHAIN& ) {};
m_stroke = true;
m_triangulate = true;
}
@ -52,12 +53,18 @@ public:
m_strokeCallback = aStrokeCallback;
m_triangleCallback = []( const VECTOR2I&, const VECTOR2I&, const VECTOR2I& ) {};
m_outlineCallback = aOutlineCallback;
m_stroke = true;
m_triangulate = false;
}
void SetOutlineCallback( std::function<void( const SHAPE_LINE_CHAIN& aPoly )> aOutlineCallback )
CALLBACK_GAL( KIGFX::GAL_DISPLAY_OPTIONS& aDisplayOptions,
std::function<void( const SHAPE_LINE_CHAIN& aPoly )> aOutlineCallback ) :
GAL( aDisplayOptions )
{
m_strokeCallback = []( const VECTOR2I& aPt1, const VECTOR2I& aPt2 ) {};
m_triangleCallback = []( const VECTOR2I&, const VECTOR2I&, const VECTOR2I& ) {};
m_outlineCallback = aOutlineCallback;
m_stroke = false;
m_triangulate = false;
}
@ -76,6 +83,7 @@ private:
std::function<void( const SHAPE_LINE_CHAIN& aPoly )> m_outlineCallback;
bool m_stroke;
bool m_triangulate;
};

View File

@ -52,9 +52,8 @@
#define SKIP_STRUCT (1 << 15) ///< flag indicating that the structure should be ignored
#define DO_NOT_DRAW (1 << 16) ///< Used to disable draw function
#define IS_PASTED (1 << 17) ///< Modifier on IS_NEW which indicates it came from clipboard
#define LOCKED (1 << 18) ///< Pcbnew: locked from movement and deletion
///< NB: stored in m_status flags, NOT m_flags.
#define UNUSED (1 << 19)
#define UNUSED_1 (1 << 18)
#define UNUSED_2 (1 << 19)
#define MALFORMED_F_COURTYARD (1 << 20)
#define MALFORMED_B_COURTYARD (1 << 21)
#define MALFORMED_COURTYARDS ( MALFORMED_F_COURTYARD | MALFORMED_B_COURTYARD )

View File

@ -69,7 +69,7 @@ bool BOARD_ITEM::IsLocked() const
const BOARD* board = GetBoard();
return board && board->GetBoardUse() != BOARD_USE::FPHOLDER && GetState( LOCKED );
return board && board->GetBoardUse() != BOARD_USE::FPHOLDER && m_isLocked;
}

View File

@ -259,6 +259,7 @@ bool DIALOG_TEXT_PROPERTIES::TransferDataToWindow()
m_cbLocked->SetValue( m_item->IsLocked() );
m_LayerSelectionCtrl->SetLayerSelection( m_item->GetLayer() );
m_cbKnockout->SetValue( m_item->IsKnockout() );
m_fontCtrl->SetFontSelection( m_edaText->GetFont() );
@ -395,6 +396,7 @@ bool DIALOG_TEXT_PROPERTIES::TransferDataFromWindow()
m_item->SetLocked( m_cbLocked->GetValue() );
m_item->SetLayer( ToLAYER_ID( m_LayerSelectionCtrl->GetLayerSelection() ) );
m_item->SetIsKnockout( m_cbKnockout->GetValue() );
if( m_fontCtrl->HaveFontSelection() )
{

View File

@ -82,7 +82,10 @@ DIALOG_TEXT_PROPERTIES_BASE::DIALOG_TEXT_PROPERTIES_BASE( wxWindow* parent, wxWi
gbSizer1->SetEmptyCellSize( wxSize( 20,-1 ) );
m_cbLocked = new wxCheckBox( this, wxID_ANY, _("Locked"), wxDefaultPosition, wxDefaultSize, 0 );
gbSizer1->Add( m_cbLocked, wxGBPosition( 0, 0 ), wxGBSpan( 1, 3 ), wxBOTTOM|wxRIGHT|wxLEFT, 5 );
gbSizer1->Add( m_cbLocked, wxGBPosition( 0, 0 ), wxGBSpan( 1, 3 ), wxRIGHT|wxLEFT, 5 );
m_Visible = new wxCheckBox( this, wxID_ANY, _("Visible"), wxDefaultPosition, wxDefaultSize, 0 );
gbSizer1->Add( m_Visible, wxGBPosition( 0, 4 ), wxGBSpan( 1, 1 ), wxRIGHT, 5 );
m_LayerLabel = new wxStaticText( this, wxID_ANY, _("Layer:"), wxDefaultPosition, wxDefaultSize, 0 );
m_LayerLabel->Wrap( -1 );
@ -94,8 +97,8 @@ DIALOG_TEXT_PROPERTIES_BASE::DIALOG_TEXT_PROPERTIES_BASE( wxWindow* parent, wxWi
wxBoxSizer* bSizer7;
bSizer7 = new wxBoxSizer( wxHORIZONTAL );
m_Visible = new wxCheckBox( this, wxID_ANY, _("Visible"), wxDefaultPosition, wxDefaultSize, 0 );
bSizer7->Add( m_Visible, 1, wxRIGHT|wxALIGN_CENTER_VERTICAL, 5 );
m_cbKnockout = new wxCheckBox( this, wxID_ANY, _("Knockout"), wxDefaultPosition, wxDefaultSize, 0 );
bSizer7->Add( m_cbKnockout, 1, wxTOP|wxBOTTOM|wxRIGHT, 15 );
m_KeepUpright = new wxCheckBox( this, wxID_ANY, _("Keep upright"), wxDefaultPosition, wxDefaultSize, 0 );
m_KeepUpright->SetToolTip( _("Keep text upright") );
@ -113,7 +116,7 @@ DIALOG_TEXT_PROPERTIES_BASE::DIALOG_TEXT_PROPERTIES_BASE( wxWindow* parent, wxWi
int m_fontCtrlNChoices = sizeof( m_fontCtrlChoices ) / sizeof( wxString );
m_fontCtrl = new FONT_CHOICE( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_fontCtrlNChoices, m_fontCtrlChoices, 0 );
m_fontCtrl->SetSelection( 0 );
gbSizer1->Add( m_fontCtrl, wxGBPosition( 2, 1 ), wxGBSpan( 1, 2 ), wxALIGN_CENTER_VERTICAL|wxEXPAND|wxTOP|wxBOTTOM, 10 );
gbSizer1->Add( m_fontCtrl, wxGBPosition( 2, 1 ), wxGBSpan( 1, 2 ), wxALIGN_CENTER_VERTICAL|wxEXPAND|wxTOP|wxBOTTOM, 5 );
wxBoxSizer* bSizerButtonBar;
bSizerButtonBar = new wxBoxSizer( wxHORIZONTAL );
@ -157,7 +160,7 @@ DIALOG_TEXT_PROPERTIES_BASE::DIALOG_TEXT_PROPERTIES_BASE( wxWindow* parent, wxWi
bSizerButtonBar->Add( m_separator3, 0, wxALIGN_CENTER_VERTICAL, 5 );
gbSizer1->Add( bSizerButtonBar, wxGBPosition( 2, 4 ), wxGBSpan( 1, 3 ), wxEXPAND|wxTOP|wxBOTTOM, 8 );
gbSizer1->Add( bSizerButtonBar, wxGBPosition( 2, 4 ), wxGBSpan( 1, 3 ), wxEXPAND|wxTOP|wxBOTTOM, 3 );
m_SizeXLabel = new wxStaticText( this, wxID_ANY, _("Width:"), wxDefaultPosition, wxDefaultSize, 0 );
m_SizeXLabel->Wrap( -1 );

View File

@ -355,7 +355,7 @@
<property name="border">5</property>
<property name="colspan">3</property>
<property name="column">0</property>
<property name="flag">wxBOTTOM|wxRIGHT|wxLEFT</property>
<property name="flag">wxRIGHT|wxLEFT</property>
<property name="row">0</property>
<property name="rowspan">1</property>
<object class="wxCheckBox" expanded="1">
@ -418,6 +418,73 @@
<property name="window_style"></property>
</object>
</object>
<object class="gbsizeritem" expanded="1">
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">4</property>
<property name="flag">wxRIGHT</property>
<property name="row">0</property>
<property name="rowspan">1</property>
<object class="wxCheckBox" expanded="0">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer"></property>
<property name="aui_name"></property>
<property name="aui_position"></property>
<property name="aui_row"></property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="checked">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Visible</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_Visible</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
<object class="gbsizeritem" expanded="1">
<property name="border">5</property>
<property name="colspan">1</property>
@ -562,11 +629,11 @@
<property name="name">bSizer7</property>
<property name="orient">wxHORIZONTAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="0">
<property name="border">5</property>
<property name="flag">wxRIGHT|wxALIGN_CENTER_VERTICAL</property>
<object class="sizeritem" expanded="1">
<property name="border">15</property>
<property name="flag">wxTOP|wxBOTTOM|wxRIGHT</property>
<property name="proportion">1</property>
<object class="wxCheckBox" expanded="0">
<object class="wxCheckBox" expanded="1">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@ -595,7 +662,7 @@
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Visible</property>
<property name="label">Knockout</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
@ -603,7 +670,7 @@
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_Visible</property>
<property name="name">m_cbKnockout</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
@ -614,7 +681,7 @@
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; forward_declare</property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
@ -757,7 +824,7 @@
</object>
</object>
<object class="gbsizeritem" expanded="1">
<property name="border">10</property>
<property name="border">5</property>
<property name="colspan">2</property>
<property name="column">1</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxEXPAND|wxTOP|wxBOTTOM</property>
@ -825,7 +892,7 @@
</object>
</object>
<object class="gbsizeritem" expanded="1">
<property name="border">8</property>
<property name="border">3</property>
<property name="colspan">3</property>
<property name="column">4</property>
<property name="flag">wxEXPAND|wxTOP|wxBOTTOM</property>

View File

@ -54,9 +54,10 @@ class DIALOG_TEXT_PROPERTIES_BASE : public DIALOG_SHIM
wxStaticText* m_TextLabel;
wxTextCtrl* m_SingleLineText;
wxCheckBox* m_cbLocked;
wxCheckBox* m_Visible;
wxStaticText* m_LayerLabel;
PCB_LAYER_BOX_SELECTOR* m_LayerSelectionCtrl;
wxCheckBox* m_Visible;
wxCheckBox* m_cbKnockout;
wxCheckBox* m_KeepUpright;
wxStaticText* m_fontLabel;
FONT_CHOICE* m_fontCtrl;

View File

@ -61,6 +61,7 @@
#include <gr_text.h>
#include <pgm_base.h>
#include "pcbnew_settings.h"
#include "callback_gal.h"
using namespace KIGFX;
@ -1591,38 +1592,73 @@ void PCB_PAINTER::draw( const PCB_TEXT* aText, int aLayer )
if( resolvedText.Length() == 0 )
return;
const COLOR4D& color = m_pcbSettings.GetColor( aText, aText->GetLayer() );
bool outline_mode = pcbconfig() && !pcbconfig()->m_Display.m_DisplayTextFill;
const COLOR4D& color = m_pcbSettings.GetColor( aText, aText->GetLayer() );
bool outline_mode = pcbconfig() && !pcbconfig()->m_Display.m_DisplayTextFill;
TEXT_ATTRIBUTES attrs = aText->GetAttributes();
m_gal->SetStrokeColor( color );
m_gal->SetFillColor( color );
TEXT_ATTRIBUTES attrs = aText->GetAttributes();
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 );
} );
KIFONT::FONT* font = aText->GetDrawFont();
if( outline_mode )
attrs.m_StrokeWidth = m_pcbSettings.m_outlineWidth;
else
attrs.m_StrokeWidth = getLineThickness( aText->GetEffectiveTextPenWidth() );
std::vector<std::unique_ptr<KIFONT::GLYPH>>* cache = aText->GetRenderCache( resolvedText );
callback_gal.SetIsFill( font->IsOutline() );
callback_gal.SetIsStroke( font->IsStroke() );
callback_gal.SetLineWidth( attrs.m_StrokeWidth );
font->Draw( &callback_gal, resolvedText, aText->GetDrawPos(), attrs );
if( cache )
{
for( const std::unique_ptr<KIFONT::GLYPH>& glyph : *cache )
m_gal->DrawGlyph( *glyph.get() );
SHAPE_POLY_SET finalPoly;
int margin = attrs.m_StrokeWidth * 1.5;
aText->TransformBoundingBoxWithClearanceToPolygon( &finalPoly, margin );
finalPoly.BooleanSubtract( knockouts, SHAPE_POLY_SET::PM_FAST );
finalPoly.Fracture( SHAPE_POLY_SET::PM_FAST );
m_gal->SetIsStroke( false );
m_gal->SetIsFill( true );
m_gal->DrawPolygon( finalPoly );
}
else
{
strokeText( resolvedText, aText->GetTextPos(), attrs );
if( outline_mode )
attrs.m_StrokeWidth = m_pcbSettings.m_outlineWidth;
else
attrs.m_StrokeWidth = getLineThickness( aText->GetEffectiveTextPenWidth() );
std::vector<std::unique_ptr<KIFONT::GLYPH>>* cache = aText->GetRenderCache( resolvedText );
if( cache )
{
for( const std::unique_ptr<KIFONT::GLYPH>& glyph : *cache )
m_gal->DrawGlyph( *glyph.get() );
}
else
{
strokeText( resolvedText, aText->GetTextPos(), attrs );
}
}
}
void PCB_PAINTER::draw( const PCB_TEXTBOX* aTextBox, int aLayer )
{
const COLOR4D& color = m_pcbSettings.GetColor( aTextBox, aTextBox->GetLayer() );
const COLOR4D& color = m_pcbSettings.GetColor( aTextBox, aLayer );
int thickness = getLineThickness( aTextBox->GetWidth() );
PLOT_DASH_TYPE lineStyle = aTextBox->GetStroke().GetPlotStyle();
wxString resolvedText( aTextBox->GetShownText() );
m_gal->SetFillColor( color );
m_gal->SetStrokeColor( color );
@ -1656,8 +1692,6 @@ void PCB_PAINTER::draw( const PCB_TEXTBOX* aTextBox, int aLayer )
delete shape;
}
wxString resolvedText( aTextBox->GetShownText() );
if( resolvedText.Length() == 0 )
return;
@ -1685,31 +1719,64 @@ void PCB_PAINTER::draw( const FP_TEXT* aText, int aLayer )
if( resolvedText.Length() == 0 )
return;
const COLOR4D& color = m_pcbSettings.GetColor( aText, aLayer );
bool outline_mode = pcbconfig() && !pcbconfig()->m_Display.m_DisplayTextFill;
const COLOR4D& color = m_pcbSettings.GetColor( aText, aLayer );
bool outline_mode = pcbconfig() && !pcbconfig()->m_Display.m_DisplayTextFill;
TEXT_ATTRIBUTES attrs = aText->GetAttributes();
m_gal->SetStrokeColor( color );
m_gal->SetFillColor( color );
TEXT_ATTRIBUTES attrs = aText->GetAttributes();
attrs.m_Angle = aText->GetDrawRotation();
if( outline_mode )
attrs.m_StrokeWidth = m_pcbSettings.m_outlineWidth;
else
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 );
} );
KIFONT::FONT* font = aText->GetDrawFont();
attrs.m_StrokeWidth = getLineThickness( aText->GetEffectiveTextPenWidth() );
std::vector<std::unique_ptr<KIFONT::GLYPH>>* cache = aText->GetRenderCache( resolvedText );
callback_gal.SetIsFill( font->IsOutline() );
callback_gal.SetIsStroke( font->IsStroke() );
callback_gal.SetLineWidth( attrs.m_StrokeWidth );
font->Draw( &callback_gal, resolvedText, aText->GetDrawPos(), attrs );
if( cache )
{
for( const std::unique_ptr<KIFONT::GLYPH>& glyph : *cache )
m_gal->DrawGlyph( *glyph.get() );
SHAPE_POLY_SET finalPoly;
int margin = attrs.m_StrokeWidth * 1.5;
aText->TransformBoundingBoxWithClearanceToPolygon( &finalPoly, margin );
finalPoly.BooleanSubtract( knockouts, SHAPE_POLY_SET::PM_FAST );
finalPoly.Fracture( SHAPE_POLY_SET::PM_FAST );
m_gal->SetIsStroke( false );
m_gal->SetIsFill( true );
m_gal->DrawPolygon( finalPoly );
}
else
{
strokeText( resolvedText, aText->GetTextPos(), attrs );
if( outline_mode )
attrs.m_StrokeWidth = m_pcbSettings.m_outlineWidth;
else
attrs.m_StrokeWidth = getLineThickness( aText->GetEffectiveTextPenWidth() );
std::vector<std::unique_ptr<KIFONT::GLYPH>>* cache = aText->GetRenderCache( resolvedText );
if( cache )
{
for( const std::unique_ptr<KIFONT::GLYPH>& glyph : *cache )
m_gal->DrawGlyph( *glyph.get() );
}
else
{
strokeText( resolvedText, aText->GetTextPos(), attrs );
}
}
// Draw the umbilical line

View File

@ -1117,9 +1117,6 @@ wxString PCB_TRACK::ShowState( int stateBits )
if( stateBits & IS_LINKED )
ret << wxT( " | IS_LINKED" );
if( stateBits & LOCKED )
ret << wxT( " | LOCKED" );
if( stateBits & IN_EDIT )
ret << wxT( " | IN_EDIT" );

View File

@ -2877,7 +2877,18 @@ PCB_TEXT* PCB_PARSER::parsePCB_TEXT()
{
case T_layer:
text->SetLayer( parseBoardItemLayer() );
NeedRIGHT();
token = NextTok();
if( token == T_knockout )
{
text->SetIsKnockout( true );
token = NextTok();
}
if( (int) token != DSN_RIGHT )
Expecting( DSN_RIGHT );
break;
case T_tstamp:
@ -3904,7 +3915,18 @@ FP_TEXT* PCB_PARSER::parseFP_TEXT()
{
case T_layer:
text->SetLayer( parseBoardItemLayer() );
NeedRIGHT();
token = NextTok();
if( token == T_knockout )
{
text->SetIsKnockout( true );
token = NextTok();
}
if( (int) token != DSN_RIGHT )
Expecting( DSN_RIGHT );
break;
case T_hide:

View File

@ -471,9 +471,11 @@ void PCB_PLUGIN::Format( const BOARD_ITEM* aItem, int aNestLevel ) const
}
void PCB_PLUGIN::formatLayer( PCB_LAYER_ID aLayer ) const
void PCB_PLUGIN::formatLayer( PCB_LAYER_ID aLayer, bool aIsKnockout ) const
{
m_out->Print( 0, " (layer %s)", m_out->Quotew( LSET::Name( aLayer ) ).c_str() );
m_out->Print( 0, " (layer %s%s)",
m_out->Quotew( LSET::Name( aLayer ) ).c_str(),
aIsKnockout ? " knockout" : "" );
}
@ -1729,7 +1731,7 @@ void PCB_PLUGIN::format( const PCB_TEXT* aText, int aNestLevel ) const
m_out->Print( 0, ")" );
formatLayer( aText->GetLayer() );
formatLayer( aText->GetLayer(), aText->IsKnockout() );
m_out->Print( 0, " (tstamp %s)", TO_UTF8( aText->m_Uuid.AsString() ) );
@ -1871,7 +1873,7 @@ void PCB_PLUGIN::format( const FP_TEXT* aText, int aNestLevel ) const
m_out->Print( 0, " unlocked" );
m_out->Print( 0, ")" );
formatLayer( aText->GetLayer() );
formatLayer( aText->GetLayer(), aText->IsKnockout() );
if( !aText->IsVisible() )
m_out->Print( 0, " hide" );

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2012 CERN.
* Copyright (C) 1992-2021 KiCad Developers, see AUTHORS.txt for contributors.
* Copyright (C) 1992-2022 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@ -117,7 +117,8 @@ class SHAPE_LINE_CHAIN;
//#define SEXPR_BOARD_FILE_VERSION 20211232 // Fonts
//#define SEXPR_BOARD_FILE_VERSION 20220131 // Textboxes
//#define SEXPR_BOARD_FILE_VERSION 20220211 // End support for V5 zone fill strategy
#define SEXPR_BOARD_FILE_VERSION 20220225 // Remove TEDIT
//#define SEXPR_BOARD_FILE_VERSION 20220225 // Remove TEDIT
#define SEXPR_BOARD_FILE_VERSION 20220308 // Knockout text
#define BOARD_FILE_HOST_VERSION 20200825 ///< Earlier files than this include the host tag
#define LEGACY_ARC_FORMATTING 20210925 ///< These were the last to use old arc formatting
@ -300,7 +301,7 @@ private:
void formatRenderCache( const EDA_TEXT* aText, int aNestLevel ) const;
void formatLayer( PCB_LAYER_ID aLayer ) const;
void formatLayer( PCB_LAYER_ID aLayer, bool aIsKnockout = false ) const;
void formatLayers( LSET aLayerMask, int aNestLevel = 0 ) const;