KiCad PCB EDA Suite
Loading...
Searching...
No Matches
drill_symbol_profile.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
21
22#include <base_units.h>
24#include <fmt/format.h>
25
26
37
38
40{
41 if( aOn )
42 m_groupBy.insert( aKey );
43 else
44 m_groupBy.erase( aKey );
45}
46
47
48const DRILL_SYMBOL_ASSIGNMENT* DRILL_SYMBOL_PROFILE::GetAssignment( const std::string& aKey ) const
49{
50 auto it = m_assignments.find( aKey );
51
52 return it == m_assignments.end() ? nullptr : &it->second;
53}
54
55
56void DRILL_SYMBOL_PROFILE::SetAssignment( const std::string& aKey,
57 const DRILL_SYMBOL_ASSIGNMENT& aAssignment )
58{
59 m_assignments[aKey] = aAssignment;
60}
61
62
63std::string DRILL_SYMBOL_PROFILE::GroupKeyString( const DRILL_OPERATION& aOperation ) const
64{
65 std::string key = "v1";
66
68 key += fmt::format( "|d{}", aOperation.m_Diameter );
69
71 {
72 key += aOperation.m_IsSlot ? fmt::format( "|s{}x{}", aOperation.m_SizeXY.x, aOperation.m_SizeXY.y )
73 : "|s-";
74 }
75
77 key += aOperation.m_NotPlated ? "|p0" : "|p1";
78
80 {
81 // Copper ordinals, not layer names, so a stackup rename cannot invalidate the key
82 key += fmt::format( "|L{}-{}", CopperLayerToOrdinal( aOperation.m_TopLayer ),
83 CopperLayerToOrdinal( aOperation.m_BottomLayer ) );
84 }
85
87 key += fmt::format( "|k{}", static_cast<int>( aOperation.m_Kind ) );
88
90 key += fmt::format( "|a{}", static_cast<int>( aOperation.m_Attribute ) );
91
93 {
94 key += fmt::format( "|r{}{}{}{}{}{}{}{}", aOperation.m_Filled ? 1 : 0,
95 aOperation.m_Capped ? 1 : 0, aOperation.m_TopCovered ? 1 : 0,
96 aOperation.m_BottomCovered ? 1 : 0, aOperation.m_TopPlugged ? 1 : 0,
97 aOperation.m_BottomPlugged ? 1 : 0, aOperation.m_TopTented ? 1 : 0,
98 aOperation.m_BottomTented ? 1 : 0 );
99 }
100
102 {
103 const DRILL_POST_MACHINING& front = aOperation.m_FrontPostMachining;
104 const DRILL_POST_MACHINING& back = aOperation.m_BackPostMachining;
105
106 key += fmt::format( "|m{}:{}:{}:{}/{}:{}:{}:{}", static_cast<int>( front.m_Mode ),
107 front.m_Size, front.m_Depth, front.m_Angle,
108 static_cast<int>( back.m_Mode ), back.m_Size, back.m_Depth,
109 back.m_Angle );
110 }
111
112 return key;
113}
114
115
117{
118 uint64_t hash = 1469598103934665603ULL;
119
120 auto mix =
121 [&]( uint64_t aValue )
122 {
123 hash ^= aValue;
124 hash *= 1099511628211ULL;
125 };
126
127 for( DRILL_GROUP_KEY key : m_groupBy )
128 mix( static_cast<uint64_t>( key ) );
129
130 mix( static_cast<uint64_t>( m_markPolicy ) );
131 mix( static_cast<uint64_t>( m_symbolSize ) );
132 mix( static_cast<uint64_t>( m_symbolWidth ) );
133 mix( m_freezeAssignments ? 1 : 0 );
134
135 for( const auto& [key, assignment] : m_assignments )
136 {
137 for( const char ch : key )
138 mix( static_cast<unsigned char>( ch ) );
139
140 mix( static_cast<uint64_t>( assignment.m_MarkMode ) );
141 mix( static_cast<uint64_t>( assignment.m_ShapeIndex ) );
142
143 // Letter and description are drawn, so a change to either has to invalidate the
144 // caches keyed on this value
145 for( const wxUniChar ch : assignment.m_Letter )
146 mix( static_cast<uint64_t>( ch.GetValue() ) );
147
148 mix( assignment.m_Letter.length() );
149
150 for( const wxUniChar ch : assignment.m_Description )
151 mix( static_cast<uint64_t>( ch.GetValue() ) );
152
153 mix( assignment.m_Description.length() );
154 }
155
156 return hash;
157}
158
159
161{
162 if( m_name != aOther.m_name || m_groupBy != aOther.m_groupBy
163 || m_markPolicy != aOther.m_markPolicy || m_symbolSize != aOther.m_symbolSize
164 || m_symbolWidth != aOther.m_symbolWidth
166 {
167 return false;
168 }
169
170 if( m_assignments.size() != aOther.m_assignments.size() )
171 return false;
172
173 for( const auto& [key, assignment] : m_assignments )
174 {
175 const DRILL_SYMBOL_ASSIGNMENT* other = aOther.GetAssignment( key );
176
177 if( !other || other->m_MarkMode != assignment.m_MarkMode
178 || other->m_ShapeIndex != assignment.m_ShapeIndex
179 || other->m_Letter != assignment.m_Letter
180 || other->m_Description != assignment.m_Description )
181 {
182 return false;
183 }
184 }
185
186 return true;
187}
188
189
190namespace
191{
192struct TOKEN_MAP
193{
194 const char* token;
195 int value;
196};
197
198const TOKEN_MAP groupKeyTokens[] = {
199 { "size", (int) DRILL_GROUP_KEY::SIZE_GRP },
200 { "slot", (int) DRILL_GROUP_KEY::SLOT },
201 { "plating", (int) DRILL_GROUP_KEY::PLATING },
202 { "span", (int) DRILL_GROUP_KEY::SPAN },
203 { "operation", (int) DRILL_GROUP_KEY::OPERATION },
204 { "hole_function", (int) DRILL_GROUP_KEY::HOLE_FUNCTION },
205 { "protection", (int) DRILL_GROUP_KEY::PROTECTION },
206 { "post_machining", (int) DRILL_GROUP_KEY::POST_MACHINING },
207};
208
209const TOKEN_MAP markPolicyTokens[] = {
210 { "shapes", (int) DRILL_MARK_POLICY::SHAPES },
211 { "letters", (int) DRILL_MARK_POLICY::LETTERS },
212 { "shapes_then_letters", (int) DRILL_MARK_POLICY::SHAPES_THEN_LETTERS },
213 { "size_text", (int) DRILL_MARK_POLICY::SIZE_TEXT },
214};
215
216const TOKEN_MAP markModeTokens[] = {
217 { "shape", (int) DRILL_MARK_MODE::SHAPE },
218 { "letter", (int) DRILL_MARK_MODE::LETTER },
219 { "size_text", (int) DRILL_MARK_MODE::SIZE_TEXT },
220};
221
222template <size_t N>
223const char* tokenFor( const TOKEN_MAP ( &aMap )[N], int aValue )
224{
225 for( const TOKEN_MAP& entry : aMap )
226 {
227 if( entry.value == aValue )
228 return entry.token;
229 }
230
231 return aMap[0].token;
232}
233
234template <size_t N>
235bool valueFor( const TOKEN_MAP ( &aMap )[N], const wxString& aToken, int& aValue )
236{
237 for( const TOKEN_MAP& entry : aMap )
238 {
239 if( aToken.IsSameAs( wxString::FromUTF8( entry.token ) ) )
240 {
241 aValue = entry.value;
242 return true;
243 }
244 }
245
246 return false;
247}
248} // namespace
249
250
252{
253 return tokenFor( groupKeyTokens, (int) aKey );
254}
255
256
258{
259 return tokenFor( markPolicyTokens, (int) aPolicy );
260}
261
262
264{
265 return tokenFor( markModeTokens, (int) aMode );
266}
267
268
269bool DrillGroupKeyFromToken( const wxString& aToken, DRILL_GROUP_KEY& aKey )
270{
271 int value = 0;
272
273 if( !valueFor( groupKeyTokens, aToken, value ) )
274 return false;
275
276 aKey = (DRILL_GROUP_KEY) value;
277 return true;
278}
279
280
281bool DrillMarkPolicyFromToken( const wxString& aToken, DRILL_MARK_POLICY& aPolicy )
282{
283 int value = 0;
284
285 if( !valueFor( markPolicyTokens, aToken, value ) )
286 return false;
287
288 aPolicy = (DRILL_MARK_POLICY) value;
289 return true;
290}
291
292
293bool DrillMarkModeFromToken( const wxString& aToken, DRILL_MARK_MODE& aMode )
294{
295 int value = 0;
296
297 if( !valueFor( markModeTokens, aToken, value ) )
298 return false;
299
300 aMode = (DRILL_MARK_MODE) value;
301 return true;
302}
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:121
DRILL_MARK_POLICY m_markPolicy
std::string GroupKeyString(const DRILL_OPERATION &aOperation) const
Stable identity for a group under the currently enabled keys.
bool operator==(const DRILL_SYMBOL_PROFILE &aOther) const
std::set< DRILL_GROUP_KEY > m_groupBy
const DRILL_SYMBOL_ASSIGNMENT * GetAssignment(const std::string &aKey) const
bool IsGroupedBy(DRILL_GROUP_KEY aKey) const
uint64_t Fingerprint() const
Cheap value used to notice an edit.
void SetGroupedBy(DRILL_GROUP_KEY aKey, bool aOn)
void SetAssignment(const std::string &aKey, const DRILL_SYMBOL_ASSIGNMENT &aAssignment)
std::map< std::string, DRILL_SYMBOL_ASSIGNMENT > m_assignments
const char * DrillGroupKeyToken(DRILL_GROUP_KEY aKey)
Stable file tokens, deliberately independent of enum ordering so a later insertion into the enum cann...
bool DrillMarkModeFromToken(const wxString &aToken, DRILL_MARK_MODE &aMode)
const char * DrillMarkModeToken(DRILL_MARK_MODE aMode)
bool DrillMarkPolicyFromToken(const wxString &aToken, DRILL_MARK_POLICY &aPolicy)
bool DrillGroupKeyFromToken(const wxString &aToken, DRILL_GROUP_KEY &aKey)
const char * DrillMarkPolicyToken(DRILL_MARK_POLICY aPolicy)
DRILL_MARK_POLICY
DRILL_GROUP_KEY
Which properties split holes into separate chart rows and symbols.
size_t CopperLayerToOrdinal(PCB_LAYER_ID aLayer)
Converts KiCad copper layer enum to an ordinal between the front and back layers.
Definition layer_ids.h:945
One machining action, which is also one NC hit and one tool assignment.
DRILL_OP_KIND m_Kind
DRILL_POST_MACHINING m_BackPostMachining
PCB_LAYER_ID m_TopLayer
PCB_LAYER_ID m_BottomLayer
VECTOR2I m_SizeXY
Source axes, never normalized to (width, length).
DRILL_POST_MACHINING m_FrontPostMachining
HOLE_ATTRIBUTE m_Attribute
int m_Size
int m_Depth
int m_Angle
PAD_DRILL_POST_MACHINING_MODE m_Mode