KiCad PCB EDA Suite
Loading...
Searching...
No Matches
easypc_classes_root.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
24
25#include <algorithm>
26#include <climits>
27
28#include <ki_exception.h>
29#include <wx/translation.h>
30
31
32namespace EASYPC
33{
34
35namespace
36{
37
39 constexpr FIELD_ROW LEGACY_COLOURS[] = { { 0, INT_MAX, "i2 b i6" },
40 { 9000, INT_MAX, "i" },
41 { 0, INT_MAX, "b i b i b i5 b i b8" },
42 { 0, 0x837, "b" },
43 { 0x838, INT_MAX, "b2" },
44 { 2001, INT_MAX, "i b" },
45 { 3000, INT_MAX, "i b" },
46 { 6000, INT_MAX, "b2 i3" },
47 { 7000, INT_MAX, "o a b i b17" },
48 { 7001, INT_MAX, "b" },
49 { 8000, INT_MAX, "b4" },
50 { 8000, 0x1f42, "b2" },
51 { 8000, INT_MAX, "b s" },
52 { 0x1f43, INT_MAX, "b8 i4" },
53 { 9000, INT_MAX, "b i" },
54 { 9001, INT_MAX, "b i" },
55 { 0x2712, INT_MAX, "b6 f" },
56 { 0x2716, INT_MAX, "b" },
57 { 0x2717, INT_MAX, "i2 b i2 b i2 b i b i b i b" },
58 { 12001, INT_MAX, "i b" },
59 { 0x2ee6, INT_MAX, "i b" },
60 { 0x3e81, INT_MAX, "i b" },
61 { 13000, INT_MAX, "b2 i b3 i i b2 i b2" },
62 { 0x32c9, INT_MAX, "i b" },
63 { 14000, INT_MAX, "i b i b b21" },
64 { 14001, INT_MAX, "b" },
65 { 0x36b3, INT_MAX, "b2" },
66 { 15000, INT_MAX, "i b2 i b4" },
67 { 16001, INT_MAX, "b2" },
68 { 17000, INT_MAX, "b i b i" } };
69
70
72 constexpr FIELD_ROW DEFAULTS_TAIL[] = { { 7000, INT_MAX, "o4 s i3 b i2" }, { 8001, INT_MAX, "b s o b s o3" },
73 { 0x1f43, INT_MAX, "s" }, { 9000, INT_MAX, "o" },
74 { 0x2716, INT_MAX, "s" }, { 0x2717, INT_MAX, "o2 s i3 o2 s 1 i3" },
75 { 12001, INT_MAX, "o2 s" }, { 0x2ee4, INT_MAX, "s 12" },
76 { 0x2ee6, INT_MAX, "o4 s" }, { 14000, INT_MAX, "o6 s3 i3 1 i2 13" },
77 { 0x36b2, INT_MAX, "s" }, { 0x36b3, INT_MAX, "1 s i2" },
78 { 16001, INT_MAX, "i s" }, { 18000, INT_MAX, "1 i2 1 s i2 13" } };
79
80
82 constexpr FIELD_ROW DESIGN_TAIL[] = { { 12000, INT_MAX, "o" }, { 16000, INT_MAX, "o2" }, { 17000, INT_MAX, "o" },
83 { 22000, INT_MAX, "o" }, { 0x6d62, INT_MAX, "s" }, { 29001, INT_MAX, "o" },
84 { 30000, INT_MAX, "o" }, { 0x7531, INT_MAX, "o" }, { 0x36b1, INT_MAX, "o" } };
85
86
87 // Classes whose fields no importer reads
88 constexpr FIELD_ROW UNITS[] = { { 0, INT_MAX, "i2" } };
89 constexpr FIELD_ROW DESIGN_VIEW[] = { { 0, INT_MAX, "i3" } };
90 constexpr FIELD_ROW ONE_LIST[] = { { 0, INT_MAX, "o" } };
91 constexpr FIELD_ROW GRID[] = { { 0, INT_MAX, "s b i2 b i2 b i b2 i5 b" },
92 { 17000, INT_MAX, "b" },
93 { 20000, INT_MAX, "b" } };
94 constexpr FIELD_ROW SCREEN_GRID[] = { { 0, INT_MAX, "i" }, { 9000, INT_MAX, "i b3" }, { 13000, INT_MAX, "b" } };
95
96
98 void setGrow( std::vector<int32_t>& aArray, size_t aIndex, int32_t aValue )
99 {
100 if( ( aIndex < aArray.size() ? aArray[aIndex] : 0 ) == aValue )
101 return;
102
103 if( aArray.size() <= aIndex )
104 aArray.resize( aIndex + 1, 0 );
105
106 aArray[aIndex] = aValue;
107 }
108
109
110 void clearIfSet( std::vector<int32_t>& aArray, size_t aIndex )
111 {
112 if( aIndex < aArray.size() )
113 aArray[aIndex] = 0;
114 }
115
116
117 LOAD_TASK loadMember( ARCHIVE& aAr, OBJECT& aMember, const char* aClass, bool aDesignOwned )
118 {
119 if( DESIGN_MEMBER* member = dynamic_cast<DESIGN_MEMBER*>( &aMember ) )
120 member->DesignOwned = aDesignOwned;
121
122 co_await aAr.Embedded( aMember, aClass );
123 }
124
125
127 struct SOURCE_OLD_WORKING_GRID : DESIGN_MEMBER
128 {
129 LOAD_TASK Load( ARCHIVE& aAr ) override
130 {
131 // Only a constructed owner is tested; without one the owner tag is always read
132 if( !DesignOwned || ItemFormat( aAr ) >= 0x835 )
133 co_await DESIGN_MEMBER::Load( aAr );
134
135 aAr.Skip( ItemFormat( aAr ) >= 9000 ? 12 : 8 );
136 }
137 };
138
139
140 struct SOURCE_ROUTING_PARAMETERS : DESIGN_MEMBER
141 {
142 LOAD_TASK Load( ARCHIVE& aAr ) override
143 {
144 // The gate is taken from the constructed owner, before the owner tag
145 const int v = ItemFormat( aAr );
146
147 co_await DESIGN_MEMBER::Load( aAr );
148
149 // From 3000 a tool parameter map; every 2105 and 2106 file stores the six flags as 4-byte BOOLs
150 if( v >= 3000 )
151 aAr.Skip( 8 * size_t( aAr.Count() ) );
152 else
153 co_await SkipFields( aAr, v >= 0x839 ? "i6 b6 i4" : "i6" );
154 }
155 };
156
157
158 struct SOURCE_PLACEMENT_PARAMETERS : DESIGN_MEMBER
159 {
160 LOAD_TASK Load( ARCHIVE& aAr ) override
161 {
162 co_await DESIGN_MEMBER::Load( aAr );
163
164 if( ItemFormat( aAr ) > 0x1f41 )
165 aAr.Skip( 4 * size_t( std::max( 0, aAr.I32() ) ) );
166 else
167 co_await SkipFields( aAr, "b4 i4" );
168 }
169 };
170
171
172 struct SOURCE_MANUFACTURE_DATA : DESIGN_MEMBER
173 {
174 LOAD_TASK Load( ARCHIVE& aAr ) override
175 {
176 co_await DESIGN_MEMBER::Load( aAr );
177
178 if( ItemFormat( aAr ) < 10000 )
179 co_return;
180
181 for( uint32_t i = aAr.Count(); i > 0; --i )
182 aAr.SkipString();
183
184 aAr.Skip( 4 * size_t( aAr.Count() ) );
185 }
186 };
187
188
189 struct SOURCE_DESIGN_COLOURS : DESIGN_MEMBER
190 {
191 LOAD_TASK Load( ARCHIVE& aAr ) override
192 {
193 co_await DESIGN_MEMBER::Load( aAr );
194
195 const int v = ItemFormat( aAr );
196
197 if( v <= 17999 )
198 {
199 co_await SkipRows( aAr, v, LEGACY_COLOURS );
200 co_return;
201 }
202
203 // Plain int32 counts: id to colour, then three id to flag tables
204 aAr.Skip( 8 * size_t( std::max( 0, aAr.I32() ) ) );
205
206 for( int i = 0; i < 3; ++i )
207 aAr.Skip( 5 * size_t( std::max( 0, aAr.I32() ) ) );
208
209 co_await SkipFields( aAr, "o a s f" );
210 }
211 };
212
213
215 void assignDefaultNetClass( OBJECT* aNets, OBJECT* aNetClasses )
216 {
217 const std::vector<OBJECT*>& classes = ListItems( aNetClasses );
218
219 for( SOURCE_NET* net : TypedItems<SOURCE_NET>( aNets ) )
220 {
221 if( !net->NetClass && !classes.empty() )
222 net->NetClass = classes.front();
223 }
224 }
225
226} // namespace
227
228
230{
231 POINT32 p;
232 p.X = aAr.I32();
233 p.Y = aAr.I32();
234 return p;
235}
236
237
238LOAD_TASK SkipMember( ARCHIVE& aAr, const char* aClass, bool aDesignOwned )
239{
240 std::unique_ptr<OBJECT> member = ARCHIVE::Create( aClass );
241 co_await loadMember( aAr, *member, aClass, aDesignOwned );
242}
243
244
246{
247 co_await SOURCE_DESIGN_DATA::Load( aAr );
248 OwnerRead = true;
249}
250
251
252int DESIGN_MEMBER::ItemFormat( const ARCHIVE& aAr ) const
253{
254 // Before the owner tag is read the owner is whatever the constructor set
255 if( !OwnerRead )
256 return DesignOwned ? aAr.DocumentVersion() : aAr.CurrentReadFormat();
257
258 return SOURCE_DESIGN_DATA::ItemFormat( aAr );
259}
260
261
263{
264 // The gate is taken from the constructed owner; older designs store no checks
265 if( ItemFormat( aAr ) <= 12999 )
266 co_return;
267
268 co_await DESIGN_MEMBER::Load( aAr );
269
270 for( uint32_t i = aAr.Count(); i > 0; --i )
271 {
272 int32_t key = aAr.I32();
273 Values[key] = aAr.I32();
274 }
275}
276
277
279{
280 static constexpr FIELD_ROW ROWS[] = {
281 { 13000, INT_MAX, "1" }, { 14000, INT_MAX, "s" }, { 0x36b2, INT_MAX, "s" }, { 17000, INT_MAX, "s" }
282 };
283
284 co_await DESIGN_MEMBER::Load( aAr );
285
286 const int v = ItemFormat( aAr );
287
288 aAr.Skip( 4 * size_t( std::max( 0, aAr.I32() ) ) ); // wire lengths
289
290 if( v > 8999 )
291 {
292 aAr.SkipString();
293
294 for( uint32_t i = aAr.Count(); i > 0; --i )
295 Params.push_back( aAr.I32() );
296 }
297
298 co_await SkipRows( aAr, v, ROWS );
299
300 if( v > 17999 )
301 co_await SkipFields( aAr, THERMAL_RULE_SET );
302
303 if( v >= 22000 )
304 aAr.Skip( 4 );
305
306 // Parameters newer than the file take their defaults
307 if( v < 22000 )
308 {
309 setGrow( Params, 24, 0x6338 );
310 setGrow( Params, 25, 0xf80c );
311 clearIfSet( Params, 27 );
312 clearIfSet( Params, 31 );
313 setGrow( Params, 28, Param( 4 ) );
314 }
315
316 if( v < 26000 )
317 {
318 setGrow( Params, 37, 0xfe );
319 clearIfSet( Params, 38 );
320 }
321}
322
323
325{
326 co_await SOURCE_DESIGN_ITEM::Load( aAr );
327
328 const int v = ItemFormat( aAr );
329
330 // Line style, hatch style from 12001, track and pad styles
331 co_await SkipFields( aAr, v > 12000 ? "o4" : "o3" );
332 TextStyle = co_await aAr.Object();
333 co_await SkipFields( aAr, "o s5 o b4" );
334
335 if( v > 0x7d4 )
336 aAr.SkipString();
337
338 if( v > 0x7d6 )
339 NetClass = aAr.ReadString();
340
341 co_await SkipRows( aAr, v, DEFAULTS_TAIL );
342}
343
344
346{
347 // OLE items
348 for( uint32_t i = aAr.U32(); i > 0; --i )
349 co_await aAr.Object();
350
351 size_t versionPos = aAr.Pos();
352 Version = aAr.I32();
353
354 if( Version > NEWEST_ITEM_FORMAT && !( Version >= 30000 && Version < 31000 ) )
355 {
357 wxString::Format( _( "Easy-PC design format %d at offset %zu is too new." ), Version, versionPos ) );
358 }
359
360 const int v = Version;
361
362 aAr.SetDocumentVersion( v );
363 aAr.SetBooleanIsByte( v > 7999 );
364 Product = v >= 0x1f44 ? aAr.I32() : PRODUCT_EASYPC;
365 aAr.SetProduct( Product );
366 co_await SkipFields( aAr, v < 0x834 ? "i4 b i" : "i4" ); // design area, old units
367
368 Areas = co_await aAr.Object();
369 Boards = co_await aAr.Object();
370 Coppers = co_await aAr.Object();
371
372 if( v > 2999 )
373 co_await aAr.Object(); // layer types
374
375 Layers = co_await aAr.Object();
376
377 if( v > 0x2713 )
378 co_await aAr.Object(); // layer spans
379
380 NetClasses = co_await aAr.Object();
381 Symbols = co_await aAr.Object();
382 Nets = co_await aAr.Object();
383 Pads = co_await aAr.Object();
384 co_await aAr.Object(); // pad styles
385 Texts = co_await aAr.Object();
386 co_await aAr.Object(); // text styles
387 Spacings = co_await aAr.Object();
388 Attributes = co_await aAr.Object();
389 co_await SkipFields( aAr, "o2" ); // attribute names, components
390 ComponentInstances = co_await aAr.Object();
391 co_await aAr.Object(); // errors
392 Defaults = co_await aAr.ObjectAs<SOURCE_DEFAULTS>();
393 co_await aAr.Object(); // track styles
394 co_await SkipFields( aAr, "o2" ); // line styles, schematic components
395 Buses = co_await aAr.Object();
396 SymbolInstances = co_await aAr.Object();
397
398 // Old routing values, bus terminal offset, origins and overlays
399 co_await SkipFields( aAr, v < 0x835 ? "i3 o2" : "i o2" );
400 IsolationGap = aAr.I32();
401
402 if( v > 3999 )
403 aAr.Skip( 8 ); // minimum copper area
404
405 ThermalRelief = aAr.I32();
406
407 if( v > 15000 )
408 aAr.Skip( 4 );
409
410 if( v > 0x3e81 )
411 ThermalAngled = aAr.Bool();
412
413 aAr.Skip( 4 );
414
415 if( v > 0x7d5 )
416 {
417 aAr.InBool();
418 Origin = ReadPoint( aAr );
419 }
420
421 if( v > 0x835 )
422 Groups = co_await aAr.Object();
423
424 if( v > 2999 )
425 {
426 co_await SkipFields( aAr, "s b o" );
428 }
429
430 if( v >= 0x2713 )
431 ValuePositions = co_await aAr.Object();
432
433 co_await SkipRows( aAr, v, DESIGN_TAIL );
434
435 if( v < 0x36b1 )
436 {
437 co_await SkipMember( aAr, "CScreenGrid", true );
438 co_await SkipMember( aAr, "COldWorkingGrid", true );
439 }
440
441 co_await SkipMember( aAr, "CDesignColours", true );
442 co_await SkipMember( aAr, "CDesignView", true );
443
444 if( v > 0x833 )
445 co_await SkipMember( aAr, "CUnits", true );
446
447 if( v > 0x834 )
448 co_await SkipMember( aAr, "CRoutingParameters", true );
449
450 if( v > 2999 )
451 co_await SkipMember( aAr, "CPlacementParameters", true );
452
453 if( v > 7999 )
454 co_await SkipFields( aAr, "o2" ); // pictures
455
456 if( v > 8000 )
457 co_await loadMember( aAr, DesignParameters, "CDesignParameters", true );
458
459 if( v >= 9000 )
460 {
461 aAr.Skip( 8 );
462 co_await SkipMember( aAr, "CUnits", true );
463 }
464
465 if( v > 9999 )
466 co_await SkipMember( aAr, "CManufactureData", true );
467
468 if( v >= 13000 )
469 {
470 co_await loadMember( aAr, DrcParameters, "CCheckParameters", true );
471 co_await SkipMember( aAr, "CCheckParameters", true );
472 co_await SkipFields( aAr, "o2" ); // ruler stops, sheets
473 }
474
475 if( v > 22999 )
476 co_await SkipMember( aAr, "CComponentRules" );
477
478 if( v > 23999 )
479 co_await SkipMember( aAr, "CComponentColours" );
480
481 assignDefaultNetClass( Nets, NetClasses );
482}
483
484
486{
487 Register<SOURCE_DESIGN>( aReg, { "CPcbDesign", "CScmDesign" } );
488 Register<SOURCE_DESIGN_LIST>( aReg, { "CGrids" } );
489 RegisterSkipped<DESIGN_MEMBER>( aReg, "CUnits", UNITS );
490 Register<SOURCE_DESIGN_COLOURS>( aReg, { "CDesignColours" } );
491 Register<SOURCE_ROUTING_PARAMETERS>( aReg, { "CRoutingParameters" } );
492 Register<SOURCE_CHECK_PARAMETERS>( aReg, { "CCheckParameters" } );
493 Register<SOURCE_PLACEMENT_PARAMETERS>( aReg, { "CPlacementParameters" } );
494 Register<SOURCE_MANUFACTURE_DATA>( aReg, { "CManufactureData" } );
495 Register<SOURCE_DESIGN_PARAMETERS>( aReg, { "CDesignParameters" } );
496 Register<SOURCE_OLD_WORKING_GRID>( aReg, { "COldWorkingGrid" } );
497 RegisterSkipped<SOURCE_DESIGN_ITEM>( aReg, "CDesignView", DESIGN_VIEW );
499 RegisterSkipped<SOURCE_DESIGN_ITEM>( aReg, "CScreenGrid", SCREEN_GRID );
500 Register<SOURCE_DEFAULTS>( aReg, { "CDefaults" } );
501 RegisterSkipped<SOURCE_DESIGN_ITEM>( aReg, "CComponentRules", ONE_LIST );
502 RegisterSkipped<SOURCE_DESIGN_ITEM>( aReg, "CComponentColours", ONE_LIST );
503 Register<SOURCE_PROJECT>( aReg, { "CProject" } );
504 Register<SOURCE_PROJECT_ITEM>( aReg, { "CProjectItem" } );
505}
506
507} // namespace EASYPC
KICAD_PLUGIN_EXPORT SCENEGRAPH * Load(char const *aFileName)
Read a model file and creates a generic display structure.
One archive load stream; it owns every object it creates.
void Skip(size_t aLen)
int CurrentReadFormat() const
static std::unique_ptr< OBJECT > Create(const char *aClass)
An object of a registered class, not yet loaded.
wxString ReadString()
ANSI (windows-1252) or the 0xFF 0xFFFE UTF-16 form.
void SetProduct(int32_t aProduct)
TYPED_AWAITER< T > ObjectAs()
size_t Pos() const
bool InBool()
one or four bytes, depending on the active format
int DocumentVersion() const
void SetDocumentVersion(int aVersion)
void SetBooleanIsByte(bool aByte)
uint32_t Count()
a 16-bit count, 0xFFFF escaping to 32 bits
OBJECT_AWAITER Object()
A loader coroutine. Awaiting one queues it on its archive's frame stack instead of nesting the call.
Placed instances and connectivity: component, symbol and pad instances, nets, nodes,...
Symbols, components and gates, embedded in designs or the single object of a library item stream.
The project file (.prj), a bare archive stream.
The design document and the design parameter tables the importers use.
#define _(s)
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
std::map< std::string, std::function< std::unique_ptr< OBJECT >()>, std::less<> > REGISTRY
LOAD_TASK SkipRows(ARCHIVE &aAr, int aVersion, std::span< const FIELD_ROW > aRows)
SkipFields for every row aVersion falls in, in order.
LOAD_TASK SkipMember(ARCHIVE &aAr, const char *aClass, bool aDesignOwned)
Load and drop an embedded member of a registered class; aDesignOwned marks its design as owner.
constexpr int NEWEST_ITEM_FORMAT
The newest item format a file can carry (30001)
LOAD_TASK SkipFields(ARCHIVE &aAr, std::string_view aOps)
Read and drop a run of fields described by aOps, each letter optionally followed by a repeat count: b...
constexpr char THERMAL_RULE_SET[]
A thermal rule set as SkipFields ops: owner, four thermal rules (owner and an int array),...
std::vector< T * > TypedItems(const OBJECT *aList)
The items of ListItems that are a T, in order.
void RegisterRootClasses(REGISTRY &aReg)
void RegisterSkipped(REGISTRY &aReg, const char *aName, std::span< const FIELD_ROW > aRows)
const std::vector< OBJECT * > & ListItems(const OBJECT *aList)
The items of a design list or array, empty for anything else.
void Register(REGISTRY &aReg, std::initializer_list< const char * > aNames)
Register the class names whose objects load as a T.
POINT32 ReadPoint(ARCHIVE &aAr)
A member stored inside the design.
LOAD_TASK Load(ARCHIVE &aAr) override
Read this object's fields.
int ItemFormat(const ARCHIVE &aAr) const override
The version this object gates on; the base is the archive's current read format.
A run of fields present from version since to until inclusive.
Root of every deserialized object.
A point read as two int32 values.
LOAD_TASK Load(ARCHIVE &aAr) override
Read this object's fields.
std::map< int32_t, int32_t > Values
LOAD_TASK Load(ARCHIVE &aAr) override
Read this object's fields.
LOAD_TASK Load(ARCHIVE &aAr) override
Read this object's fields.
int ItemFormat(const ARCHIVE &aAr) const override
The version this object gates on; the base is the archive's current read format.
LOAD_TASK Load(ARCHIVE &aAr) override
Read this object's fields.
int ItemFormat(const ARCHIVE &aAr) const override
The version this object gates on; the base is the archive's current read format.
int32_t Param(int aIndex, int32_t aDefault=0) const
The value at aIndex, or aDefault where the stored array is shorter, as the accessors do.
LOAD_TASK Load(ARCHIVE &aAr) override
Read this object's fields.
LOAD_TASK Load(ARCHIVE &aAr) override
Read this object's fields.
OBJECT * Spacings
legacy or current design spacings, depending on format
SOURCE_CHECK_PARAMETERS DrcParameters
from 13000
SOURCE_DESIGN_PARAMETERS DesignParameters
after 8000
Common grid settings, available to every frame.