diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 93d4692a1d..a81666cb74 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -252,6 +252,7 @@ set( COMMON_SRCS filter_reader.cpp footprint_info.cpp footprint_filter.cpp + hash_eda.cpp lib_id.cpp lib_table_keywords.cpp # findkicadhelppath.cpp.notused deprecated, use searchhelpfilefullpath.cpp diff --git a/common/hash_eda.cpp b/common/hash_eda.cpp new file mode 100644 index 0000000000..8148df0737 --- /dev/null +++ b/common/hash_eda.cpp @@ -0,0 +1,188 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2017 CERN + * @author Maciej Suminski + * + * 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 + +#include +#include +#include +#include + +#include + +using namespace std; + +// Common calculation part for all BOARD_ITEMs +static inline size_t hash_board_item( const BOARD_ITEM* aItem, int aFlags ) +{ + size_t ret = 0; + + if( aFlags & LAYER ) + ret ^= hash{}( aItem->GetLayerSet().to_ullong() ); + + return ret; +} + + +size_t hash_eda( const EDA_ITEM* aItem, int aFlags ) +{ + size_t ret = 0xa82de1c0; + + switch( aItem->Type() ) + { + case PCB_MODULE_T: + { + const MODULE* module = static_cast( aItem ); + + ret ^= hash_board_item( module, aFlags ); + + if( aFlags & POSITION ) + { + ret ^= hash{}( module->GetPosition().x ); + ret ^= hash{}( module->GetPosition().y ); + } + + if( aFlags & ROTATION ) + ret ^= hash{}( module->GetOrientation() ); + + for( const BOARD_ITEM* i = module->GraphicalItemsList(); i; i = i->Next() ) + ret ^= hash_eda( i, aFlags ); + + for( const D_PAD* i = module->PadsList(); i; i = i->Next() ) + ret ^= hash_eda( i, aFlags ); + } + break; + + case PCB_PAD_T: + { + const D_PAD* pad = static_cast( aItem ); + ret ^= hash_board_item( pad, aFlags ); + ret ^= hash{}( pad->GetShape() << 16 ); + ret ^= hash{}( pad->GetDrillShape() << 18 ); + ret ^= hash{}( pad->GetSize().x << 8 ); + ret ^= hash{}( pad->GetSize().y << 9 ); + ret ^= hash{}( pad->GetOffset().x << 6 ); + ret ^= hash{}( pad->GetOffset().y << 7 ); + ret ^= hash{}( pad->GetDelta().x << 4 ); + ret ^= hash{}( pad->GetDelta().y << 5 ); + + if( aFlags & POSITION ) + { + if( aFlags & REL_COORD ) + { + ret ^= hash{}( pad->GetPos0().x ); + ret ^= hash{}( pad->GetPos0().y ); + } + else + { + ret ^= hash{}( pad->GetPosition().x ); + ret ^= hash{}( pad->GetPosition().y ); + } + } + + if( aFlags & ROTATION ) + ret ^= hash{}( pad->GetOrientation() ); + + if( aFlags & NET ) + ret ^= hash{}( pad->GetNetCode() << 6 ); + } + break; + + case PCB_MODULE_TEXT_T: + { + const TEXTE_MODULE* text = static_cast( aItem ); + + if( !( aFlags & REFERENCE ) && text->GetType() == TEXTE_MODULE::TEXT_is_REFERENCE ) + break; + + if( !( aFlags & VALUE ) && text->GetType() == TEXTE_MODULE::TEXT_is_VALUE ) + break; + + ret ^= hash_board_item( text, aFlags ); + ret ^= hash{}( text->GetText().ToStdString() ); + ret ^= hash{}( text->IsItalic() ); + ret ^= hash{}( text->IsBold() ); + ret ^= hash{}( text->IsMirrored() ); + ret ^= hash{}( text->GetTextWidth() ); + ret ^= hash{}( text->GetTextHeight() ); + ret ^= hash{}( text->GetHorizJustify() ); + ret ^= hash{}( text->GetVertJustify() ); + + if( aFlags & POSITION ) + { + if( aFlags & REL_COORD ) + { + ret ^= hash{}( text->GetPos0().x ); + ret ^= hash{}( text->GetPos0().y ); + } + else + { + ret ^= hash{}( text->GetPosition().x ); + ret ^= hash{}( text->GetPosition().y ); + } + } + + if( aFlags & ROTATION ) + ret ^= hash{}( text->GetTextAngle() ); + } + break; + + case PCB_MODULE_EDGE_T: + { + const EDGE_MODULE* segment = static_cast( aItem ); + ret ^= hash_board_item( segment, aFlags ); + ret ^= hash{}( segment->GetType() ); + ret ^= hash{}( segment->GetShape() ); + ret ^= hash{}( segment->GetWidth() ); + ret ^= hash{}( segment->GetRadius() ); + + if( aFlags & POSITION ) + { + if( aFlags & REL_COORD ) + { + ret ^= hash{}( segment->GetStart0().x ); + ret ^= hash{}( segment->GetStart0().y ); + ret ^= hash{}( segment->GetEnd0().x ); + ret ^= hash{}( segment->GetEnd0().y ); + } + else + { + ret ^= hash{}( segment->GetStart().x ); + ret ^= hash{}( segment->GetStart().y ); + ret ^= hash{}( segment->GetEnd().x ); + ret ^= hash{}( segment->GetEnd().y ); + } + } + + if( aFlags & ROTATION ) + ret ^= hash{}( segment->GetAngle() ); + } + break; + + default: + wxASSERT_MSG( false, "Unhandled type in function hashModItem() (exporter_gencad.cpp)" ); + } + + return ret; +} diff --git a/include/hash_eda.h b/include/hash_eda.h new file mode 100644 index 0000000000..2707039e74 --- /dev/null +++ b/include/hash_eda.h @@ -0,0 +1,54 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2017 CERN + * @author Maciej Suminski + * + * 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 + */ + +/** + * @brief Hashing functions for EDA_ITEMs. + */ + +#include + +class EDA_ITEM; + +///> Enables/disables properties that will be used for calculating the hash. +///> The properties might be combined using the bitwise 'or' operator. +enum HASH_FLAGS +{ + POSITION = 0x01, + + ///> use coordinates relative to the parent object + REL_COORD = 0x02, + ROTATION = 0x04, + LAYER = 0x08, + NET = 0x10, + REFERENCE = 0x20, + VALUE = 0x40, + ALL = 0xff +}; + +/* + * Calculates hash of an EDA_ITEM. + * @param aItem is the item for which the hash will be computed. + * @return Hash value. + */ +std::size_t hash_eda( const EDA_ITEM* aItem, int aFlags = HASH_FLAGS::ALL );