Browse Source

SCH_PIN: break out layout calculations

The bounding box calculations of SCH_PINs are pretty complicated.
There is already caching of the name and number texts, but the
SCH_PAINTER (for example) has to repeat this work and sometimes
slightly diverges. For example, dangling indicators and alt
icons are painted, but not included in the bbox.

This commit introduces a more encapsulated 'layout cache' object which will
take care of caching the current extents, but also providing layout
geometry to SCH_PAINTER (and other interested code, like hit testers
on a given field) witohut requiring recomputation or reimplementation.

The extents calculations use exclusively the public API, so it's nice
and easy to split it out.

In this commit, nothing is functionally changed - the name and number
are still cached, and everything else is computed in the exact same way.
This is the groundwork for fixing this issue:

Relates-To: https://gitlab.com/kicad/code/kicad/-/issues/18894
pcb_db
John Beard 1 year ago
parent
commit
fe48e51315
  1. 1
      eeschema/CMakeLists.txt
  2. 241
      eeschema/pin_layout_cache.cpp
  3. 103
      eeschema/pin_layout_cache.h
  4. 194
      eeschema/sch_pin.cpp
  5. 29
      eeschema/sch_pin.h

1
eeschema/CMakeLists.txt

@ -371,6 +371,7 @@ set( EESCHEMA_SRCS
menubar.cpp
net_navigator.cpp
picksymbol.cpp
pin_layout_cache.cpp
pin_numbers.cpp
pin_type.cpp
project_sch.cpp

241
eeschema/pin_layout_cache.cpp

@ -0,0 +1,241 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2024 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
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "pin_layout_cache.h"
#include <pgm_base.h>
#include <settings/settings_manager.h>
#include <sch_symbol.h>
#include <eeschema_settings.h>
// small margin in internal units between the pin text and the pin line
#define PIN_TEXT_MARGIN 4
struct EXTENTS_CACHE
{
KIFONT::FONT* m_Font = nullptr;
int m_FontSize = 0;
VECTOR2I m_Extents;
};
/// Utility for getting the size of the 'external' pin decorators (as a radius)
// i.e. the negation circle, the polarity 'slopes' and the nonlogic
// marker
static int externalPinDecoSize( const RENDER_SETTINGS* aSettings, const SCH_PIN &aPin )
{
const SCH_RENDER_SETTINGS* settings = static_cast<const SCH_RENDER_SETTINGS*>( aSettings );
if( settings && settings->m_PinSymbolSize )
return settings->m_PinSymbolSize;
return aPin.GetNumberTextSize() / 2;
}
void PIN_LAYOUT_CACHE::recomputeExtentsCache( bool aDefinitelyDirty, KIFONT::FONT* aFont, int aSize,
const wxString& aText,
const KIFONT::METRICS& aFontMetrics,
TEXT_EXTENTS_CACHE& aCache )
{
// Even if not definitely dirty, verify no font changes
if( !aDefinitelyDirty && aCache.m_Font == aFont && aCache.m_FontSize == aSize )
{
return;
}
aCache.m_Font = aFont;
aCache.m_FontSize = aSize;
VECTOR2D fontSize( aSize, aSize );
int penWidth = GetPenSizeForNormal( aSize );
aCache.m_Extents = aFont->StringBoundaryLimits( aText, fontSize, penWidth, false, false,
aFontMetrics);
}
PIN_LAYOUT_CACHE::PIN_LAYOUT_CACHE( const SCH_PIN& aPin ) :
m_pin( aPin ), m_dirtyFlags( DIRTY_FLAGS::ALL )
{
}
void PIN_LAYOUT_CACHE::MarkDirty( int aDirtyFlags )
{
m_dirtyFlags |= aDirtyFlags;
}
BOX2I PIN_LAYOUT_CACHE::GetPinBoundingBox( bool aIncludeLabelsOnInvisiblePins,
bool aIncludeNameAndNumber, bool aIncludeElectricalType )
{
if( const SCH_SYMBOL* symbol = dynamic_cast<const SCH_SYMBOL*>( m_pin.GetParentSymbol() ) )
{
SCH_PIN* const libPin = m_pin.GetLibPin();
wxCHECK( libPin, BOX2I() );
BOX2I r = libPin->GetBoundingBox( aIncludeLabelsOnInvisiblePins, aIncludeNameAndNumber,
aIncludeElectricalType );
r = symbol->GetTransform().TransformCoordinate( r );
r.Offset( symbol->GetPosition() );
r.Normalize();
return r;
}
EESCHEMA_SETTINGS* cfg = Pgm().GetSettingsManager().GetAppSettings<EESCHEMA_SETTINGS>();
KIFONT::FONT* font = KIFONT::FONT::GetFont( cfg->m_Appearance.default_font );
VECTOR2I begin;
VECTOR2I end;
int pinNameOffset = 0;
int nameTextLength = 0;
int nameTextHeight = 0;
int numberTextLength = 0;
int numberTextHeight = 0;
int typeTextLength = 0;
bool includeName = aIncludeNameAndNumber && !m_pin.GetShownName().IsEmpty();
bool includeNumber = aIncludeNameAndNumber && !m_pin.GetShownNumber().IsEmpty();
bool includeType = aIncludeElectricalType;
int minsizeV = TARGET_PIN_RADIUS;
if( !aIncludeLabelsOnInvisiblePins && !m_pin.IsVisible() )
{
includeName = false;
includeNumber = false;
includeType = false;
}
if( const SYMBOL* parentSymbol = m_pin.GetParentSymbol() )
{
if( parentSymbol->GetShowPinNames() )
pinNameOffset = parentSymbol->GetPinNameOffset();
else
includeName = false;
if( !parentSymbol->GetShowPinNumbers() )
includeNumber = false;
}
const KIFONT::METRICS& metrics = m_pin.GetFontMetrics();
if( includeNumber )
{
recomputeExtentsCache( isDirty( DIRTY_FLAGS::NUMBER ), font, m_pin.GetNumberTextSize(),
m_pin.GetShownNumber(), metrics, m_numExtentsCache );
setClean( DIRTY_FLAGS::NUMBER );
numberTextLength = m_numExtentsCache.m_Extents.x;
numberTextHeight = m_numExtentsCache.m_Extents.y;
}
if( includeName )
{
recomputeExtentsCache( isDirty( DIRTY_FLAGS::NAME ), font, m_pin.GetNameTextSize(),
m_pin.GetShownName(), metrics, m_nameExtentsCache );
setClean( DIRTY_FLAGS::NAME );
nameTextLength = m_nameExtentsCache.m_Extents.x + pinNameOffset;
nameTextHeight = m_nameExtentsCache.m_Extents.y + schIUScale.MilsToIU( PIN_TEXT_MARGIN );
}
if( includeType )
{
// TODO: cache this
double fontSize = std::max( m_pin.GetNameTextSize() * 3 / 4, schIUScale.mmToIU( 0.7 ) );
double stroke = fontSize / 8.0;
VECTOR2I typeTextSize = font->StringBoundaryLimits( m_pin.GetElectricalTypeName(),
VECTOR2D( fontSize, fontSize ),
KiROUND( stroke ), false, false,
metrics );
typeTextLength = typeTextSize.x + schIUScale.MilsToIU( PIN_TEXT_MARGIN ) + TARGET_PIN_RADIUS;
minsizeV = std::max( minsizeV, typeTextSize.y / 2 );
}
// First, calculate boundary box corners position
if( m_pin.GetShape() == GRAPHIC_PINSHAPE::INVERTED || m_pin.GetShape() == GRAPHIC_PINSHAPE::INVERTED_CLOCK )
minsizeV = std::max( TARGET_PIN_RADIUS, externalPinDecoSize( nullptr, m_pin ) );
const int pinLength = m_pin.GetLength();
// Calculate topLeft & bottomRight corner positions for the default pin orientation (PIN_RIGHT)
if( pinNameOffset || !includeName )
{
// pin name is inside the body (or invisible)
// pin number is above the line
begin.y = std::min( -minsizeV, -numberTextHeight );
begin.x = std::min( -typeTextLength, pinLength - ( numberTextLength / 2 ) );
end.x = pinLength + nameTextLength;
end.y = std::max( minsizeV, nameTextHeight / 2 );
}
else
{
// pin name is above pin line
// pin number is below line
begin.y = std::min( -minsizeV, -nameTextHeight );
begin.x = -typeTextLength;
begin.x = std::min( begin.x, ( pinLength - numberTextLength ) / 2 );
begin.x = std::min( begin.x, ( pinLength - nameTextLength ) / 2 );
end.x = pinLength;
end.x = std::max( end.x, ( pinLength + nameTextLength ) / 2 );
end.x = std::max( end.x, ( pinLength + numberTextLength ) / 2 );
end.y = std::max( minsizeV, numberTextHeight );
}
// Now, calculate boundary box corners position for the actual pin orientation
switch( m_pin.PinDrawOrient( DefaultTransform ) )
{
case PIN_ORIENTATION::PIN_UP:
// Pin is rotated and texts positions are mirrored
RotatePoint( begin, VECTOR2I( 0, 0 ), ANGLE_90 );
RotatePoint( end, VECTOR2I( 0, 0 ), ANGLE_90 );
break;
case PIN_ORIENTATION::PIN_DOWN:
RotatePoint( begin, VECTOR2I( 0, 0 ), -ANGLE_90 );
RotatePoint( end, VECTOR2I( 0, 0 ), -ANGLE_90 );
begin.x = -begin.x;
end.x = -end.x;
break;
case PIN_ORIENTATION::PIN_LEFT:
begin.x = -begin.x;
end.x = -end.x;
break;
default:
case PIN_ORIENTATION::PIN_RIGHT:
break;
}
BOX2I bbox = BOX2I::ByCorners( begin, end );
bbox.Move( m_pin.GetPosition() );
bbox.Normalize();
bbox.Inflate( ( m_pin.GetPenWidth() / 2 ) + 1 );
return bbox;
}

103
eeschema/pin_layout_cache.h

@ -0,0 +1,103 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2024 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
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#pragma once
#include <math/box2.h>
#include <sch_pin.h>
/**
* A pin layout helper is a class that manages the layout of the parts of
* a pin on a schematic symbol:
*
* including, extents of:
* - the pin itself
* - the pin number, number, type
* - decorations
* - alternate mode icons
*
* This is useful, because this information is used in multiple places,
* and regenerating it in multiple places is error-prone. It can also
* be cached if it's encapsulated in one place.
*/
class PIN_LAYOUT_CACHE
{
public:
PIN_LAYOUT_CACHE( const SCH_PIN& aPin );
enum DIRTY_FLAGS
{
NAME = 1,
NUMBER = 2,
ALL = NAME | NUMBER,
};
/**
* Recompute all the layout information.
*/
void MarkDirty( int aFlags );
/**
* Get the bounding box of the pin itself.
*/
BOX2I GetPinBoundingBox( bool aIncludeLabelsOnInvisiblePins, bool aIncludeNameAndNumber,
bool aIncludeElectricalType );
private:
bool isDirty( int aMask ) const
{
return m_dirtyFlags & aMask;
}
void setClean( int aMask )
{
m_dirtyFlags &= ~aMask;
}
/**
* Cached extent of a text item.
*/
struct TEXT_EXTENTS_CACHE
{
KIFONT::FONT* m_Font = nullptr;
int m_FontSize = 0;
VECTOR2I m_Extents;
};
static void recomputeExtentsCache( bool aDefinitelyDirty, KIFONT::FONT* aFont, int aSize,
const wxString& aText, const KIFONT::METRICS& aFontMetrics,
TEXT_EXTENTS_CACHE& aCache );
/// The pin in question
const SCH_PIN& m_pin;
int m_dirtyFlags;
// Various cache members
TEXT_EXTENTS_CACHE m_numExtentsCache;
TEXT_EXTENTS_CACHE m_nameExtentsCache;
};

194
eeschema/sch_pin.cpp

@ -25,17 +25,19 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "sch_pin.h"
#include <base_units.h>
#include <pgm_base.h>
#include <pin_layout_cache.h>
#include <plotters/plotter.h>
#include <sch_draw_panel.h>
#include <sch_edit_frame.h>
#include <symbol_edit_frame.h>
#include <sch_pin.h>
#include <settings/settings_manager.h>
#include <symbol_editor/symbol_editor_settings.h>
#include <trigo.h>
#include <string_utils.h>
#include <plotters/plotter.h>
// small margin in internal units between the pin text and the pin line
@ -103,7 +105,8 @@ SCH_PIN::SCH_PIN( LIB_SYMBOL* aParentSymbol ) :
m_shape( GRAPHIC_PINSHAPE::LINE ),
m_type( ELECTRICAL_PINTYPE::PT_UNSPECIFIED ),
m_hidden( false ),
m_isDangling( true )
m_isDangling( true ),
m_layoutCache( std::make_unique<PIN_LAYOUT_CACHE>( *this ) )
{
// Use the application settings for pin sizes if exists.
// pgm can be nullptr when running a shared lib from a script, not from a kicad appl
@ -141,7 +144,8 @@ SCH_PIN::SCH_PIN( LIB_SYMBOL* aParentSymbol, const wxString& aName, const wxStri
m_hidden( false ),
m_numTextSize( aNumTextSize ),
m_nameTextSize( aNameTextSize ),
m_isDangling( true )
m_isDangling( true ),
m_layoutCache( std::make_unique<PIN_LAYOUT_CACHE>( *this ) )
{
SetName( aName );
SetNumber( aNumber );
@ -156,7 +160,8 @@ SCH_PIN::SCH_PIN( SCH_SYMBOL* aParentSymbol, SCH_PIN* aLibPin ) :
m_orientation( PIN_ORIENTATION::INHERIT ),
m_shape( GRAPHIC_PINSHAPE::INHERIT ),
m_type( ELECTRICAL_PINTYPE::PT_INHERIT ),
m_isDangling( true )
m_isDangling( true ),
m_layoutCache( std::make_unique<PIN_LAYOUT_CACHE>( *this ) )
{
wxASSERT( aParentSymbol );
@ -181,7 +186,8 @@ SCH_PIN::SCH_PIN( SCH_SYMBOL* aParentSymbol, const wxString& aNumber, const wxSt
m_type( ELECTRICAL_PINTYPE::PT_INHERIT ),
m_number( aNumber ),
m_alt( aAlt ),
m_isDangling( true )
m_isDangling( true ),
m_layoutCache( std::make_unique<PIN_LAYOUT_CACHE>( *this ) )
{
wxASSERT( aParentSymbol );
@ -203,7 +209,8 @@ SCH_PIN::SCH_PIN( const SCH_PIN& aPin ) :
m_numTextSize( aPin.m_numTextSize ),
m_nameTextSize( aPin.m_nameTextSize ),
m_alt( aPin.m_alt ),
m_isDangling( aPin.m_isDangling )
m_isDangling( aPin.m_isDangling ),
m_layoutCache( std::make_unique<PIN_LAYOUT_CACHE>( *this ) )
{
SetName( aPin.m_name );
SetNumber( aPin.m_number );
@ -212,6 +219,11 @@ SCH_PIN::SCH_PIN( const SCH_PIN& aPin ) :
}
SCH_PIN::~SCH_PIN()
{
}
SCH_PIN& SCH_PIN::operator=( const SCH_PIN& aPin )
{
SCH_ITEM::operator=( aPin );
@ -371,11 +383,14 @@ const wxString& SCH_PIN::GetBaseName() const
void SCH_PIN::SetName( const wxString& aName )
{
m_name = aName;
if( m_name == aName )
return;
m_name = aName;
// pin name string does not support spaces
m_name.Replace( wxT( " " ), wxT( "_" ) );
m_nameExtentsCache.m_Extents = VECTOR2I();
m_layoutCache->MarkDirty( PIN_LAYOUT_CACHE::DIRTY_FLAGS::NAME );
}
@ -474,11 +489,14 @@ wxString SCH_PIN::GetShownNumber() const
void SCH_PIN::SetNumber( const wxString& aNumber )
{
m_number = aNumber;
if( m_number == aNumber )
return;
m_number = aNumber;
// pin number string does not support spaces
m_number.Replace( wxT( " " ), wxT( "_" ) );
m_numExtentsCache.m_Extents = VECTOR2I();
m_layoutCache->MarkDirty( PIN_LAYOUT_CACHE::DIRTY_FLAGS::NUMBER );
}
@ -499,8 +517,11 @@ int SCH_PIN::GetNameTextSize() const
void SCH_PIN::SetNameTextSize( int aSize )
{
if( aSize == m_nameTextSize )
return;
m_nameTextSize = aSize;
m_nameExtentsCache.m_Extents = VECTOR2I();
m_layoutCache->MarkDirty( PIN_LAYOUT_CACHE::DIRTY_FLAGS::NAME );
}
@ -521,8 +542,11 @@ int SCH_PIN::GetNumberTextSize() const
void SCH_PIN::SetNumberTextSize( int aSize )
{
if( aSize == m_numTextSize )
return;
m_numTextSize = aSize;
m_numExtentsCache.m_Extents = VECTOR2I();
m_layoutCache->MarkDirty( PIN_LAYOUT_CACHE::DIRTY_FLAGS::NUMBER );
}
@ -1700,147 +1724,9 @@ void SCH_PIN::validateExtentsCache( KIFONT::FONT* aFont, int aSize, const wxStri
BOX2I SCH_PIN::GetBoundingBox( bool aIncludeLabelsOnInvisiblePins, bool aIncludeNameAndNumber,
bool aIncludeElectricalType ) const
{
if( const SCH_SYMBOL* symbol = dynamic_cast<const SCH_SYMBOL*>( GetParentSymbol() ) )
{
wxCHECK( m_libPin, BOX2I() );
BOX2I r = m_libPin->GetBoundingBox( aIncludeLabelsOnInvisiblePins, aIncludeNameAndNumber,
aIncludeElectricalType );
r = symbol->GetTransform().TransformCoordinate( r );
r.Offset( symbol->GetPosition() );
r.Normalize();
return r;
}
EESCHEMA_SETTINGS* cfg = Pgm().GetSettingsManager().GetAppSettings<EESCHEMA_SETTINGS>();
KIFONT::FONT* font = KIFONT::FONT::GetFont( cfg->m_Appearance.default_font );
BOX2I bbox;
VECTOR2I begin;
VECTOR2I end;
int pinNameOffset = 0;
int nameTextLength = 0;
int nameTextHeight = 0;
int numberTextLength = 0;
int numberTextHeight = 0;
int typeTextLength = 0;
bool includeName = aIncludeNameAndNumber && !GetShownName().IsEmpty();
bool includeNumber = aIncludeNameAndNumber && !GetShownNumber().IsEmpty();
bool includeType = aIncludeElectricalType;
int minsizeV = TARGET_PIN_RADIUS;
if( !aIncludeLabelsOnInvisiblePins && !IsVisible() )
{
includeName = false;
includeNumber = false;
includeType = false;
}
if( const SYMBOL* parentSymbol = GetParentSymbol() )
{
if( parentSymbol->GetShowPinNames() )
pinNameOffset = parentSymbol->GetPinNameOffset();
else
includeName = false;
if( !parentSymbol->GetShowPinNumbers() )
includeNumber = false;
}
if( includeNumber )
{
validateExtentsCache( font, GetNumberTextSize(), GetShownNumber(), &m_numExtentsCache );
numberTextLength = m_numExtentsCache.m_Extents.x;
numberTextHeight = m_numExtentsCache.m_Extents.y;
}
if( includeName )
{
validateExtentsCache( font, GetNameTextSize(), GetShownName(), &m_nameExtentsCache );
nameTextLength = m_nameExtentsCache.m_Extents.x + pinNameOffset;
nameTextHeight = m_nameExtentsCache.m_Extents.y + schIUScale.MilsToIU( PIN_TEXT_MARGIN );
}
if( includeType )
{
double fontSize = std::max( GetNameTextSize() * 3 / 4, schIUScale.mmToIU( 0.7 ) );
double stroke = fontSize / 8.0;
VECTOR2I typeTextSize = font->StringBoundaryLimits( GetElectricalTypeName(),
VECTOR2D( fontSize, fontSize ),
KiROUND( stroke ), false, false,
GetFontMetrics() );
typeTextLength = typeTextSize.x + schIUScale.MilsToIU( PIN_TEXT_MARGIN ) + TARGET_PIN_RADIUS;
minsizeV = std::max( minsizeV, typeTextSize.y / 2 );
}
// First, calculate boundary box corners position
if( m_shape == GRAPHIC_PINSHAPE::INVERTED || m_shape == GRAPHIC_PINSHAPE::INVERTED_CLOCK )
minsizeV = std::max( TARGET_PIN_RADIUS, externalPinDecoSize( nullptr, *this ) );
// Calculate topLeft & bottomRight corner positions for the default pin orientation (PIN_RIGHT)
if( pinNameOffset || !includeName )
{
// pin name is inside the body (or invisible)
// pin number is above the line
begin.y = std::min( -minsizeV, -numberTextHeight );
begin.x = std::min( -typeTextLength, GetLength() - ( numberTextLength / 2 ) );
end.x = GetLength() + nameTextLength;
end.y = std::max( minsizeV, nameTextHeight / 2 );
}
else
{
// pin name is above pin line
// pin number is below line
begin.y = std::min( -minsizeV, -nameTextHeight );
begin.x = -typeTextLength;
begin.x = std::min( begin.x, ( GetLength() - numberTextLength ) / 2 );
begin.x = std::min( begin.x, ( GetLength() - nameTextLength ) / 2 );
end.x = GetLength();
end.x = std::max( end.x, ( GetLength() + nameTextLength ) / 2 );
end.x = std::max( end.x, ( GetLength() + numberTextLength ) / 2 );
end.y = std::max( minsizeV, numberTextHeight );
}
// Now, calculate boundary box corners position for the actual pin orientation
switch( PinDrawOrient( DefaultTransform ) )
{
case PIN_ORIENTATION::PIN_UP:
// Pin is rotated and texts positions are mirrored
RotatePoint( begin, VECTOR2I( 0, 0 ), ANGLE_90 );
RotatePoint( end, VECTOR2I( 0, 0 ), ANGLE_90 );
break;
case PIN_ORIENTATION::PIN_DOWN:
RotatePoint( begin, VECTOR2I( 0, 0 ), -ANGLE_90 );
RotatePoint( end, VECTOR2I( 0, 0 ), -ANGLE_90 );
begin.x = -begin.x;
end.x = -end.x;
break;
case PIN_ORIENTATION::PIN_LEFT:
begin.x = -begin.x;
end.x = -end.x;
break;
default:
case PIN_ORIENTATION::PIN_RIGHT:
break;
}
begin += m_position;
end += m_position;
bbox.SetOrigin( begin );
bbox.SetEnd( end );
bbox.Normalize();
bbox.Inflate( ( GetPenWidth() / 2 ) + 1 );
return bbox;
// Just defer to the cache
return m_layoutCache->GetPinBoundingBox( aIncludeLabelsOnInvisiblePins, aIncludeNameAndNumber,
aIncludeElectricalType );
}

29
eeschema/sch_pin.h

@ -21,8 +21,9 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SCH_PIN_H
#define SCH_PIN_H
#pragma once
#include <memory>
#include <pin_type.h>
#include <sch_item.h>
@ -30,6 +31,7 @@
class LIB_SYMBOL;
class SCH_SYMBOL;
class PIN_LAYOUT_CACHE;
// Circle diameter drawn at the active end of pins:
#define TARGET_PIN_RADIUS schIUScale.MilsToIU( 15 )
@ -58,7 +60,7 @@ public:
SCH_PIN( const SCH_PIN& aPin );
~SCH_PIN() override { }
~SCH_PIN();
SCH_PIN& operator=( const SCH_PIN& aPin );
@ -297,6 +299,15 @@ public:
bool operator>( const SCH_ITEM& aRhs ) const { return compare( aRhs, EQUALITY ) > 0; }
/**
* Get the layout cache associated with this pin.
*
* If you need more information about how elements of the pin are physically
* laid out than just the bounding box, you can use this. The SCH_PAINTER,
* for example, can use this to avoid having to duplicate text extent calcs.
*/
PIN_LAYOUT_CACHE& GetLayoutCache() const { return *m_layoutCache; }
protected:
wxString getItemDescription( ALT* aAlt ) const;
@ -376,15 +387,15 @@ protected:
wxString m_operatingPoint;
mutable EXTENTS_CACHE m_numExtentsCache;
mutable EXTENTS_CACHE m_nameExtentsCache;
bool m_isDangling;
/**
* The layout cache for this pin.
* SCH_PIN doesn't *have* to own this, it could be part a central cache.
*/
mutable std::unique_ptr<PIN_LAYOUT_CACHE> m_layoutCache;
/// The name that this pin connection will drive onto a net.
std::recursive_mutex m_netmap_mutex;
std::map<const SCH_SHEET_PATH, std::pair<wxString, bool>> m_net_name_map;
};
#endif // SCH_PIN_H
Loading…
Cancel
Save