/* * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2004-2015 Jean-Pierre Charras, jp.charras at wanadoo.fr * Copyright (C) 2008 Wayne Stambaugh * Copyright (C) 2022 CERN * Copyright The 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 */ #ifndef LIB_SYMBOL_H #define LIB_SYMBOL_H #include #include #include #include #include #include #include class LINE_READER; class OUTPUTFORMATTER; class REPORTER; class SYMBOL_LIB; class LIB_SYMBOL; class OUTLINE_FONT; class TEST_LIB_SYMBOL_FIXTURE; namespace KIFONT { class OUTLINE_FONT; } typedef std::shared_ptr LIB_SYMBOL_SPTR; ///< shared pointer to LIB_SYMBOL typedef std::weak_ptr LIB_SYMBOL_REF; ///< weak pointer to LIB_SYMBOL typedef MULTIVECTOR LIB_ITEMS_CONTAINER; typedef LIB_ITEMS_CONTAINER::ITEM_PTR_VECTOR LIB_ITEMS; /* values for member .m_options */ enum LIBRENTRYOPTIONS { ENTRY_NORMAL, // Libentry is a standard symbol (real or alias) ENTRY_GLOBAL_POWER, // Libentry is a power symbol ENTRY_LOCAL_POWER // Libentry is a local power symbol }; extern bool operator<( const LIB_SYMBOL& aItem1, const LIB_SYMBOL& aItem2 ); struct LIB_SYMBOL_UNIT { int m_unit; ///< The unit number. int m_bodyStyle; ///< The alternate body style of the unit. std::vector m_items; ///< The items unique to this unit and alternate body style. }; /** * Define a library symbol object. * * A library symbol object is typically saved and loaded in a symbol library file (.lib). * Library symbols are different from schematic symbols. */ class LIB_SYMBOL : public SYMBOL, public LIB_TREE_ITEM, public EMBEDDED_FILES { public: LIB_SYMBOL( const wxString& aName, LIB_SYMBOL* aParent = nullptr, SYMBOL_LIB* aLibrary = nullptr ); LIB_SYMBOL( const LIB_SYMBOL& aSymbol, SYMBOL_LIB* aLibrary = nullptr ); virtual ~LIB_SYMBOL() = default; /// http://www.boost.org/doc/libs/1_55_0/libs/smart_ptr/sp_techniques.html#weak_without_shared. LIB_SYMBOL_SPTR SharedPtr() const { return m_me; } /** * Create a copy of a LIB_SYMBOL and assigns unique KIIDs to the copy and its children. */ virtual LIB_SYMBOL* Duplicate() const { LIB_SYMBOL* dupe = new LIB_SYMBOL( *this, m_library ); const_cast( dupe->m_Uuid ) = KIID(); for( SCH_ITEM& item : dupe->m_drawings ) const_cast( item.m_Uuid ) = KIID(); return dupe; } /** * Returns a dummy LIB_SYMBOL, used when one is missing in the schematic */ static LIB_SYMBOL* GetDummy(); void SetParent( LIB_SYMBOL* aParent = nullptr ); LIB_SYMBOL_REF& GetParent() { return m_parent; } const LIB_SYMBOL_REF& GetParent() const { return m_parent; } /** * Get the number of parents for this symbol. * * @return the inheritance depth for this symbol. */ unsigned GetInheritanceDepth() const; /** * Get the parent symbol that does not have another parent. * * Now that derived symbols can be derived from other derived symbols, this method provides * way to get to the base symbol in the derivation change. * * @return the weak_ptr to the root symbol of this symbol. */ LIB_SYMBOL_SPTR GetRootSymbol() const; virtual wxString GetClass() const override { return wxT( "LIB_SYMBOL" ); } static inline bool ClassOf( const EDA_ITEM* aItem ) { return aItem && aItem->Type() == LIB_SYMBOL_T; } virtual void SetName( const wxString& aName ); wxString GetName() const override { return m_name; } LIB_ID GetLIB_ID() const override { return m_libId; } wxString GetDesc() override { return GetDescription(); } int GetSubUnitCount() const override { return GetUnitCount(); } const LIB_ID& GetLibId() const override { return m_libId; } void SetLibId( const LIB_ID& aLibId ) { m_libId = aLibId; } LIB_ID GetSourceLibId() const { return m_sourceLibId; } void SetSourceLibId( const LIB_ID& aLibId ) { m_sourceLibId = aLibId; } wxString GetLibNickname() const override { return GetLibraryName(); } ///< Sets the Description field text value void SetDescription( const wxString& aDescription ) { GetDescriptionField().SetText( aDescription ); } ///< Gets the Description field text value */ wxString GetDescription() const override { if( GetDescriptionField().GetText().IsEmpty() && IsDerived() ) { if( LIB_SYMBOL_SPTR parent = m_parent.lock() ) return parent->GetDescription(); } return GetDescriptionField().GetText(); } void SetKeyWords( const wxString& aKeyWords ) { m_keyWords = aKeyWords; } wxString GetKeyWords() const override { if( m_keyWords.IsEmpty() && IsDerived() ) { if( LIB_SYMBOL_SPTR parent = m_parent.lock() ) return parent->GetKeyWords(); } return m_keyWords; } std::vector GetSearchTerms() override; wxString GetFootprint() override { return GetFootprintField().GetText(); } void GetChooserFields( std::map& aColumnMap ) override; /** * For symbols derived from other symbols, IsRoot() indicates no derivation. */ bool IsRoot() const override { return m_parent.use_count() == 0; } bool IsDerived() const { return !m_parent.expired() && m_parent.use_count() > 0; } const wxString GetLibraryName() const; SYMBOL_LIB* GetLib() const { return m_library; } void SetLib( SYMBOL_LIB* aLibrary ) { m_library = aLibrary; } timestamp_t GetLastModDate() const { return m_lastModDate; } void SetFPFilters( const wxArrayString& aFilters ) { m_fpFilters = aFilters; } wxArrayString GetFPFilters() const { if( m_fpFilters.IsEmpty() && IsDerived() ) { if( LIB_SYMBOL_SPTR parent = m_parent.lock() ) return parent->GetFPFilters(); } return m_fpFilters; } /** * Get the bounding box for the symbol. * * @return the symbol bounding box ( in user coordinates ) * @param aUnit = unit selection = 0, or 1..n * @param aBodyStyle = body style selection = 0, or 1..n * If aUnit == 0, unit is not used * if aBodyStyle == 0, body style is not used * @param aIgnoreHiddenFields default true, ignores any hidden fields * @param aIgnoreLabelsOnInvisiblePins default true, ignores pin number and pin name * of invisible pins **/ const BOX2I GetUnitBoundingBox( int aUnit, int aBodyStyle, bool aIgnoreHiddenFields = true, bool aIgnoreLabelsOnInvisiblePins = true ) const; const BOX2I GetBoundingBox() const override { return GetUnitBoundingBox( 0, 0 ); } /** * Get the symbol bounding box excluding fields. * * @return the symbol bounding box ( in user coordinates ) without fields * @param aUnit = unit selection = 0, or 1..n * @param aBodyStyle = body style selection = 0, or 1..n * If aUnit == 0, unit is not used * if aBodyStyle == 0, body style is not used * Fields are not taken in account */ const BOX2I GetBodyBoundingBox( int aUnit, int aBodyStyle, bool aIncludePins, bool aIncludePrivateItems ) const; BOX2I GetBodyBoundingBox() const override { return GetBodyBoundingBox( m_previewUnit, m_previewBodyStyle, false, false ); } BOX2I GetBodyAndPinsBoundingBox() const override { return GetBodyBoundingBox( m_previewUnit, m_previewBodyStyle, true, false ); } bool IsGlobalPower() const override; bool IsLocalPower() const override; bool IsPower() const override; bool IsNormal() const override; void SetGlobalPower(); void SetLocalPower(); void SetNormal(); /** * Set interchangeable the property for symbol units. * @param aLockUnits when true then units are set as not interchangeable. */ void LockUnits( bool aLockUnits ) { m_unitsLocked = aLockUnits; } /** * Check whether symbol units are interchangeable. * @return False when interchangeable, true otherwise. */ bool UnitsLocked() const { return m_unitsLocked; } /** * Overwrite all the existing fields in this symbol with fields supplied in \a aFieldsList. * * @param aFieldsList is a set of fields to import, removing all previous fields. */ void SetFields( const std::vector& aFieldsList ); /** * Populate a std::vector with SCH_FIELDs, sorted in ordinal order. * * @param aList is the vector to populate. */ void GetFields( std::vector& aList, bool aVisibleOnly = false ) const override; /** * Create a copy of the SCH_FIELDs, sorted in ordinal order. */ void CopyFields( std::vector& aList ); /** * Add a field. Takes ownership of the pointer. */ void AddField( SCH_FIELD* aField ); void AddField( SCH_FIELD& aField ) { AddField( new SCH_FIELD( aField ) ); } /** * Return the next ordinal for a user field for this symbol */ int GetNextFieldOrdinal() const; /** * Find a field within this symbol matching \a aFieldName; return nullptr if not found. */ SCH_FIELD* GetField( const wxString& aFieldName ); const SCH_FIELD* GetField( const wxString& aFieldName ) const; SCH_FIELD* FindFieldCaseInsensitive( const wxString& aFieldName ); const SCH_FIELD* GetField( FIELD_T aFieldType ) const; SCH_FIELD* GetField( FIELD_T aFieldType ); /** Return reference to the value field. */ SCH_FIELD& GetValueField() { return *GetField( FIELD_T::VALUE ); } const SCH_FIELD& GetValueField() const; /** Return reference to the reference designator field. */ SCH_FIELD& GetReferenceField() { return *GetField( FIELD_T::REFERENCE ); } const SCH_FIELD& GetReferenceField() const; /** Return reference to the footprint field */ SCH_FIELD& GetFootprintField() { return *GetField( FIELD_T::FOOTPRINT ); } const SCH_FIELD& GetFootprintField() const; /** Return reference to the datasheet field. */ SCH_FIELD& GetDatasheetField() { return *GetField( FIELD_T::DATASHEET ); } const SCH_FIELD& GetDatasheetField() const; /** Return reference to the description field. */ SCH_FIELD& GetDescriptionField() {return *GetField( FIELD_T::DESCRIPTION ); } const SCH_FIELD& GetDescriptionField() const; wxString GetPrefix(); const wxString GetRef( const SCH_SHEET_PATH* aSheet, bool aIncludeUnit = false ) const override { return GetReferenceField().GetText(); } const wxString GetValue( bool aResolve, const SCH_SHEET_PATH* aPath, bool aAllowExtraText ) const override { return GetValueField().GetText(); } std::set GetFonts() const override; EMBEDDED_FILES* GetEmbeddedFiles() override; const EMBEDDED_FILES* GetEmbeddedFiles() const; void EmbedFonts() override; /** * Automatically orient all the fields in the symbol. * * @param aScreen is the SCH_SCREEN associated with the current instance of the symbol. * Required when \a aAlgo is AUTOPLACE_MANUAL; optional otherwise. */ void AutoplaceFields( SCH_SCREEN* aScreen, AUTOPLACE_ALGO aAlgo ) override; void RunOnChildren( const std::function& aFunction, RECURSE_MODE aMode ) override; /** * Resolve any references to system tokens supported by the symbol. * * @param aDepth a counter to limit recursion and circular references. */ bool ResolveTextVar( wxString* token, int aDepth = 0 ) const; void Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts, int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed ) override; /** * Plot symbol fields. */ void PlotFields( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts, int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed ); /** * Add a new draw \a aItem to the draw object list and sort according to \a aSort. * * @param aItem is the new draw object to add to the symbol. * @param aSort is the flag to determine if the newly added item should be sorted. */ void AddDrawItem( SCH_ITEM* aItem, bool aSort = true ); /** * Remove draw \a aItem from list. * * @param aItem - Draw item to remove from list. */ void RemoveDrawItem( SCH_ITEM* aItem ); void RemoveField( SCH_FIELD* aField ) { RemoveDrawItem( aField ); } /** * Graphical pins: Return schematic pin objects as drawn (unexpanded), filtered by unit/body. * * Note: pin objects are owned by the symbol's draw list; do not delete them. * * @param aUnit Unit number to collect; 0 = all units * @param aBodyStyle Alternate body style to collect; 0 = all body styles */ std::vector GetGraphicalPins( int aUnit = 0, int aBodyStyle = 0 ) const; /** * Logical pins: Return expanded logical pins based on stacked-pin notation. * Each returned item pairs a base graphical pin with a single expanded logical number. */ struct LOGICAL_PIN { SCH_PIN* pin; ///< pointer to the base graphical pin wxString number; ///< expanded logical pin number }; /** * Return all logical pins (expanded) filtered by unit/body. * For non-stacked pins, the single logical pin's number equals the base pin number. */ std::vector GetLogicalPins( int aUnit, int aBodyStyle ) const; // Deprecated: use GetGraphicalPins(). This override remains to satisfy SYMBOL's pure virtual. std::vector GetPins() const override; /** * @return a count of pins for all units / converts. */ int GetPinCount() override; /** * Return pin object with the requested pin \a aNumber. * * @param aNumber - Number of the pin to find. * @param aUnit - Unit filter. Set to 0 if a specific unit number is not required. * @param aBodyStyle - Body style filter. Set to 0 if no specific body style is not required. * @return The pin object if found. Otherwise NULL. */ SCH_PIN* GetPin( const wxString& aNumber, int aUnit = 0, int aBodyStyle = 0 ) const; /** * Return true if this symbol's pins do not match another symbol's pins. This is used to * detect whether the project cache is out of sync with the system libs. * * @param aOtherSymbol - The other library symbol to test * @param aTestNums - Whether two pins at the same point must have the same number. * @param aTestNames - Whether two pins at the same point must have the same name. * @param aTestType - Whether two pins at the same point must have the same electrical type. * @param aTestOrientation - Whether two pins at the same point must have the same orientation. * @param aTestLength - Whether two pins at the same point must have the same length. */ bool PinsConflictWith( const LIB_SYMBOL& aOtherSymbol, bool aTestNums, bool aTestNames, bool aTestType, bool aTestOrientation, bool aTestLength ) const; /** * Move the symbol \a aOffset. * * @param aOffset - Offset displacement. */ void Move( const VECTOR2I& aOffset ) override; /** * Before V10 we didn't store the number of body styles in a symbol -- we just looked through all * its drawings each time we wanted to know. This is now only used to set the count when a legacy * symbol is first read. (Legacy symbols also didn't support arbitrary body styles, so the count * is always 1 or 2, and when 2 it is always a De Morgan pair.) */ bool HasLegacyAlternateBodyStyle() const; /** * @return the highest pin number of the symbol's pins. * If none of the pins has pin number assigned it returns 0. */ int GetMaxPinNumber() const; /** * Clears the status flag all draw objects in this symbol. */ void ClearTempFlags() override; void ClearEditFlags() override; /** * Locate a draw object. * * @param aUnit - Unit number of draw item. * @param aBodyStyle - Body style of draw item. * @param aType - Draw object type, set to 0 to search for any type. * @param aPoint - Coordinate for hit testing. * @return The draw object if found. Otherwise NULL. */ SCH_ITEM* LocateDrawItem( int aUnit, int aBodyStyle, KICAD_T aType, const VECTOR2I& aPoint ); /** * Locate a draw object (overlaid) * * @param aUnit - Unit number of draw item. * @param aBodyStyle - Body style of draw item. * @param aType - Draw object type, set to 0 to search for any type. * @param aPoint - Coordinate for hit testing. * @param aTransform = the transform matrix * @return The draw object if found. Otherwise NULL. */ SCH_ITEM* LocateDrawItem( int aUnit, int aBodyStyle, KICAD_T aType, const VECTOR2I& aPoint, const TRANSFORM& aTransform ); /** * Return a reference to the draw item list. * * @return LIB_ITEMS_CONTAINER& - Reference to the draw item object container. */ LIB_ITEMS_CONTAINER& GetDrawItems() { return m_drawings; } const LIB_ITEMS_CONTAINER& GetDrawItems() const { return m_drawings; } /** * This function finds the filled draw items that are covering up smaller draw items * and replaces their body fill color with the background fill color. */ void FixupDrawItems(); INSPECT_RESULT Visit( INSPECTOR inspector, void* testData, const std::vector& aScanTypes ) override; /** * Set the units per symbol count. * * If the count is greater than the current count, then the all of the * current draw items are duplicated for each additional symbol. If the * count is less than the current count, all draw objects for units * greater that count are removed from the symbol. * * @param aCount - Number of units per package. * @param aDuplicateDrawItems Create duplicate draw items of unit 1 for each additional unit. */ void SetUnitCount( int aCount, bool aDuplicateDrawItems ); int GetUnitCount() const override; wxString GetUnitName( int aUnit ) const override { return GetUnitDisplayName( aUnit, true ); } /** * Return the user-defined display name for \a aUnit for symbols with units. */ wxString GetUnitDisplayName( int aUnit, bool aLabel ) const override; wxString GetBodyStyleDescription( int aBodyStyle, bool aLabel ) const override; std::map& GetUnitDisplayNames() { return m_unitDisplayNames; } const std::map& GetUnitDisplayNames() const { return m_unitDisplayNames; } bool GetDuplicatePinNumbersAreJumpers() const { return m_duplicatePinNumbersAreJumpers; } void SetDuplicatePinNumbersAreJumpers( bool aEnabled ) { m_duplicatePinNumbersAreJumpers = aEnabled; } /** * Each jumper pin group is a set of pin numbers that should be treated as internally connected. * @return The list of jumper pin groups in this symbols */ std::vector>& JumperPinGroups() { return m_jumperPinGroups; } const std::vector>& JumperPinGroups() const { return m_jumperPinGroups; } /// Retrieves the jumper group containing the specified pin number, if one exists std::optional> GetJumperPinGroup( const wxString& aPinNumber ) const; /** * @return true if the symbol has multiple units per symbol. * When true, the reference has a sub reference to identify symbol. */ bool IsMultiUnit() const override { return m_unitCount > 1; } static wxString LetterSubReference( int aUnit, wxChar aInitialLetter ); bool IsMultiBodyStyle() const override { return GetBodyStyleCount() > 1; } int GetBodyStyleCount() const override { if( m_demorgan ) return 2; else return std::max( 1, (int) m_bodyStyleNames.size() ); } bool HasDeMorganBodyStyles() const override { return m_demorgan; } void SetHasDeMorganBodyStyles( bool aFlag ) { m_demorgan = aFlag; } const std::vector& GetBodyStyleNames() const { return m_bodyStyleNames; } void SetBodyStyleNames( const std::vector& aBodyStyleNames ) { m_bodyStyleNames = aBodyStyleNames; } /** * Set or clear the alternate body style (DeMorgan) for the symbol. * * If the symbol already has an alternate body style set and aHasAlternate is false, all * of the existing draw items for the alternate body style are remove. If the alternate * body style is not set and aHasAlternate is true, than the base draw items are duplicated * and added to the symbol. * * @param aHasAlternate - Set or clear the symbol alternate body style. * @param aDuplicatePins - Duplicate all pins from original body style if true. */ void SetBodyStyleCount( int aCount, bool aDuplicateDrawItems, bool aDuplicatePins ); /** * Comparison test that can be used for operators. * * @param aRhs is the right hand side symbol used for comparison. * * @return -1 if this symbol is less than \a aRhs * 1 if this symbol is greater than \a aRhs * 0 if this symbol is the same as \a aRhs */ int Compare( const LIB_SYMBOL& aRhs, int aCompareFlags = 0, REPORTER* aReporter = nullptr ) const; const LIB_SYMBOL& operator=( const LIB_SYMBOL& aSymbol ); /** * Return a flattened symbol inheritance to the caller. * * If the symbol does not inherit from another symbol, a copy of the symbol is returned. * * @return a flattened symbol on the heap */ std::unique_ptr< LIB_SYMBOL > Flatten() const; /** * Return a list of SCH_ITEM objects separated by unit and convert number. * * @note This does not include SCH_FIELD objects since they are not associated with * unit and/or convert numbers. */ std::vector GetUnitDrawItems(); /** * Return a list of item pointers for \a aUnit and \a aBodyStyle for this symbol. * * @note #SCH_FIELD objects are not included. * * @param aUnit is the unit number of the item, -1 includes all units. * @param aBodyStyle is the alternate body style of the item, -1 includes all body styles. * * @return a list of unit items. */ std::vector GetUnitDrawItems( int aUnit, int aBodyStyle ); /** * Return a measure of similarity between this symbol and \a aSymbol. * @param aSymbol is the symbol to compare to. * * @return a measure of similarity from 1.0 (identical) to 0.0 (no similarity). */ double Similarity( const SCH_ITEM& aSymbol ) const override; #if defined(DEBUG) void Show( int nestLevel, std::ostream& os ) const override { ShowDummy( os ); } #endif private: // We create a different set parent function for this class, so we hide the inherited one. using EDA_ITEM::SetParent; /** * The library symbol specific sort order is as follows: * * - The result of #SCH_ITEM::compare() */ int compare( const SCH_ITEM& aOther, int aCompareFlags = SCH_ITEM::COMPARE_FLAGS::EQUALITY ) const override; void deleteAllFields(); private: LIB_SYMBOL_SPTR m_me; LIB_SYMBOL_REF m_parent; ///< Use for inherited symbols. LIB_ID m_libId; LIB_ID m_sourceLibId; ///< For database library symbols; the original symbol timestamp_t m_lastModDate; int m_unitCount; ///< Number of units (parts) per package. bool m_unitsLocked; ///< True if symbol has multiple units and changing one unit ///< does not automatically change another unit. bool m_demorgan; ///< True if there are two body styles: normal and De Morgan ///< If false, the body style count is taken from m_bodyStyleNames ///< size LIBRENTRYOPTIONS m_options; ///< Special symbol features such as POWER or NORMAL. LIB_ITEMS_CONTAINER m_drawings; SYMBOL_LIB* m_library; wxString m_name; wxString m_keyWords; ///< Search keywords wxArrayString m_fpFilters; ///< List of suitable footprint names for the symbol (wild card ///< names accepted). /// A list of jumper pin groups, each of which is a set of pin numbers that should be jumpered /// together (treated as internally connected for the purposes of connectivity) std::vector > m_jumperPinGroups; /// Flag that this symbol should automatically treat sets of two or more pins with the same /// number as jumpered pin groups bool m_duplicatePinNumbersAreJumpers; std::map m_unitDisplayNames; std::vector m_bodyStyleNames; }; #endif // CLASS_LIBENTRY_H