altium-toolkit 0.1.0 → 0.1.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -6
- package/docs/api.md +42 -4
- package/docs/model-format.md +95 -5
- package/docs/schemas/altium_toolkit/normalized_model_a1.schema.json +553 -0
- package/docs/testing.md +7 -2
- package/package.json +21 -2
- package/spec/library-scope.md +7 -1
- package/src/core/altium/AltiumParser.mjs +22 -325
- package/src/core/altium/NormalizedModelSchema.mjs +28 -0
- package/src/core/altium/PcbArcPrimitiveParser.mjs +87 -0
- package/src/core/altium/PcbBinaryPrimitiveParser.mjs +43 -370
- package/src/core/altium/PcbBoardRegionSemanticsParser.mjs +477 -0
- package/src/core/altium/PcbComponentAnnotationNormalizer.mjs +290 -0
- package/src/core/altium/PcbComponentBodyPlacementNormalizer.mjs +52 -0
- package/src/core/altium/PcbComponentPrimitiveIndexer.mjs +109 -0
- package/src/core/altium/PcbEmbeddedFontExtractor.mjs +484 -0
- package/src/core/altium/PcbFillPrimitiveParser.mjs +84 -0
- package/src/core/altium/PcbFontMetricsParser.mjs +308 -0
- package/src/core/altium/PcbGeometryFlipper.mjs +244 -0
- package/src/core/altium/PcbLayerIdCodec.mjs +136 -0
- package/src/core/altium/PcbLibModelParser.mjs +202 -0
- package/src/core/altium/PcbLibStreamExtractor.mjs +968 -0
- package/src/core/altium/PcbModelParser.mjs +618 -66
- package/src/core/altium/PcbOutlineRecovery.mjs +4 -112
- package/src/core/altium/PcbPadPrimitiveParser.mjs +347 -0
- package/src/core/altium/PcbPadShapeCodec.mjs +158 -0
- package/src/core/altium/PcbPadStackParser.mjs +903 -0
- package/src/core/altium/PcbPrimitiveOwnershipIndexParser.mjs +60 -0
- package/src/core/altium/PcbPrimitiveParameterParser.mjs +212 -0
- package/src/core/altium/PcbPrimitiveRecordSlicer.mjs +243 -0
- package/src/core/altium/PcbRawRecordRegistry.mjs +831 -0
- package/src/core/altium/PcbRegionPrimitiveParser.mjs +317 -0
- package/src/core/altium/PcbRuleParser.mjs +587 -0
- package/src/core/altium/PcbStreamExtractor.mjs +127 -4
- package/src/core/altium/PcbTextPrimitiveParser.mjs +537 -0
- package/src/core/altium/PcbTrackPrimitiveParser.mjs +87 -0
- package/src/core/altium/PcbViaPrimitiveParser.mjs +88 -0
- package/src/core/altium/PcbViaStackParser.mjs +548 -0
- package/src/core/altium/PcbWideStringTableParser.mjs +108 -0
- package/src/core/altium/PrjPcbModelParser.mjs +797 -0
- package/src/core/altium/SchematicComponentTextResolver.mjs +355 -0
- package/src/parser.mjs +13 -0
- package/src/renderers.mjs +5 -0
- package/src/styles/altium-renderers.css +11 -6
- package/src/ui/PcbCopperPrimitiveSplitter.mjs +113 -0
- package/src/ui/PcbEdgeFacingGlyphNormalizer.mjs +6 -5
- package/src/ui/PcbEmbeddedFontFaceRenderer.mjs +126 -0
- package/src/ui/PcbFootprintPrimitiveSelector.mjs +27 -6
- package/src/ui/PcbRegionPrimitiveRenderer.mjs +243 -0
- package/src/ui/PcbSideResolvedRenderModel.mjs +336 -0
- package/src/ui/PcbSvgRenderer.mjs +101 -109
- package/src/ui/PcbTextPrimitiveRenderer.mjs +252 -0
- package/src/ui/SchematicSheetChromeRenderer.mjs +2 -93
- package/src/ui/SchematicSheetZoneRenderer.mjs +104 -0
|
@@ -4,7 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
import { AsciiRecordParser } from './AsciiRecordParser.mjs'
|
|
6
6
|
import { PcbBinaryPrimitiveParser } from './PcbBinaryPrimitiveParser.mjs'
|
|
7
|
+
import { PcbEmbeddedFontExtractor } from './PcbEmbeddedFontExtractor.mjs'
|
|
7
8
|
import { PcbEmbeddedModelExtractor } from './PcbEmbeddedModelExtractor.mjs'
|
|
9
|
+
import { PcbPrimitiveParameterParser } from './PcbPrimitiveParameterParser.mjs'
|
|
10
|
+
import { PcbRawRecordRegistry } from './PcbRawRecordRegistry.mjs'
|
|
11
|
+
import { PcbWideStringTableParser } from './PcbWideStringTableParser.mjs'
|
|
8
12
|
import { OleCompoundDocument } from '../ole/OleCompoundDocument.mjs'
|
|
9
13
|
import { OleConstants } from '../ole/OleConstants.mjs'
|
|
10
14
|
|
|
@@ -41,7 +45,7 @@ export class PcbStreamExtractor {
|
|
|
41
45
|
/**
|
|
42
46
|
* Extracts PCB content directly from one OLE-backed PcbDoc buffer.
|
|
43
47
|
* @param {ArrayBuffer} arrayBuffer
|
|
44
|
-
* @returns {{ records: Array<{ raw: string, fields: Record<string, string | string[]>, sourceStream: string }>, streamNames: string[], binaryPrimitives:
|
|
48
|
+
* @returns {{ records: Array<{ raw: string, fields: Record<string, string | string[]>, sourceStream: string }>, streamNames: string[], binaryPrimitives: Record<string, object[]>, primitiveParameters: object, wideStrings: object, diagnostics: { printableRecordCount: number, printableStreamCount: number, binaryPrimitiveCount: number, primitiveParameterGroupCount: number, wideStringCount: number } } | null}
|
|
45
49
|
*/
|
|
46
50
|
static extractFromArrayBuffer(arrayBuffer) {
|
|
47
51
|
if (!PcbStreamExtractor.isCompoundDocument(arrayBuffer)) {
|
|
@@ -63,7 +67,7 @@ export class PcbStreamExtractor {
|
|
|
63
67
|
* Extracts stream-scoped printable records and known binary primitives from
|
|
64
68
|
* a stream map.
|
|
65
69
|
* @param {Map<string, Uint8Array>} streams
|
|
66
|
-
* @returns {{ records: Array<{ raw: string, fields: Record<string, string | string[]>, sourceStream: string }>, streamNames: string[], binaryPrimitives:
|
|
70
|
+
* @returns {{ records: Array<{ raw: string, fields: Record<string, string | string[]>, sourceStream: string }>, streamNames: string[], binaryPrimitives: Record<string, object[]>, primitiveParameters: object, wideStrings: object, diagnostics: { printableRecordCount: number, printableStreamCount: number, binaryPrimitiveCount: number, primitiveParameterGroupCount: number, wideStringCount: number } }}
|
|
67
71
|
*/
|
|
68
72
|
static extractFromStreams(streams) {
|
|
69
73
|
const records = []
|
|
@@ -74,7 +78,11 @@ export class PcbStreamExtractor {
|
|
|
74
78
|
tracks: [],
|
|
75
79
|
arcs: [],
|
|
76
80
|
vias: [],
|
|
77
|
-
pads: []
|
|
81
|
+
pads: [],
|
|
82
|
+
texts: [],
|
|
83
|
+
regions: [],
|
|
84
|
+
shapeBasedRegions: [],
|
|
85
|
+
boardRegions: []
|
|
78
86
|
}
|
|
79
87
|
|
|
80
88
|
for (const [name, bytes] of streams.entries()) {
|
|
@@ -82,6 +90,10 @@ export class PcbStreamExtractor {
|
|
|
82
90
|
continue
|
|
83
91
|
}
|
|
84
92
|
|
|
93
|
+
if (PcbStreamExtractor.#isBinarySidecarDataStream(name)) {
|
|
94
|
+
continue
|
|
95
|
+
}
|
|
96
|
+
|
|
85
97
|
const recordBuffer = PcbStreamExtractor.#toArrayBuffer(bytes)
|
|
86
98
|
const streamRecords = AsciiRecordParser.parse(recordBuffer).map(
|
|
87
99
|
(record) => ({
|
|
@@ -109,6 +121,35 @@ export class PcbStreamExtractor {
|
|
|
109
121
|
const fillDataBytes = streams.get('Fills6/Data')
|
|
110
122
|
const padHeaderBytes = streams.get('Pads6/Header')
|
|
111
123
|
const padDataBytes = streams.get('Pads6/Data')
|
|
124
|
+
const textHeaderBytes =
|
|
125
|
+
streams.get('Texts6/Header') || streams.get('Texts/Header')
|
|
126
|
+
const textDataBytes =
|
|
127
|
+
streams.get('Texts6/Data') || streams.get('Texts/Data')
|
|
128
|
+
const textStreamName = streams.has('Texts6/Data')
|
|
129
|
+
? 'Texts6/Data'
|
|
130
|
+
: 'Texts/Data'
|
|
131
|
+
const regionHeaderBytes = streams.get('Regions6/Header')
|
|
132
|
+
const regionDataBytes = streams.get('Regions6/Data')
|
|
133
|
+
const shapeBasedRegionHeaderBytes = streams.get(
|
|
134
|
+
'ShapeBasedRegions6/Header'
|
|
135
|
+
)
|
|
136
|
+
const shapeBasedRegionDataBytes = streams.get('ShapeBasedRegions6/Data')
|
|
137
|
+
const boardRegionHeaderBytes = streams.get('BoardRegions/Header')
|
|
138
|
+
const boardRegionDataBytes = streams.get('BoardRegions/Data')
|
|
139
|
+
const primitiveParameters = PcbPrimitiveParameterParser.parse(
|
|
140
|
+
streams.get('PrimitiveParameters/Data')
|
|
141
|
+
)
|
|
142
|
+
const wideStrings = PcbWideStringTableParser.parse(
|
|
143
|
+
streams.get('WideStrings6/Data')
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
if (primitiveParameters.groups.length) {
|
|
147
|
+
usedStreamNames.add('PrimitiveParameters/Data')
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (wideStrings.entries.length) {
|
|
151
|
+
usedStreamNames.add('WideStrings6/Data')
|
|
152
|
+
}
|
|
112
153
|
|
|
113
154
|
if (arcHeaderBytes && arcDataBytes) {
|
|
114
155
|
binaryPrimitives.arcs = PcbBinaryPrimitiveParser.parseArcStream(
|
|
@@ -160,8 +201,61 @@ export class PcbStreamExtractor {
|
|
|
160
201
|
}
|
|
161
202
|
}
|
|
162
203
|
|
|
204
|
+
if (textHeaderBytes && textDataBytes) {
|
|
205
|
+
binaryPrimitives.texts = PcbBinaryPrimitiveParser.parseTextStream(
|
|
206
|
+
textHeaderBytes,
|
|
207
|
+
textDataBytes,
|
|
208
|
+
{ wideStrings }
|
|
209
|
+
)
|
|
210
|
+
if (binaryPrimitives.texts.length) {
|
|
211
|
+
usedStreamNames.add(textStreamName)
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (regionHeaderBytes && regionDataBytes) {
|
|
216
|
+
binaryPrimitives.regions =
|
|
217
|
+
PcbBinaryPrimitiveParser.parseRegionStream(
|
|
218
|
+
regionHeaderBytes,
|
|
219
|
+
regionDataBytes
|
|
220
|
+
)
|
|
221
|
+
if (binaryPrimitives.regions.length) {
|
|
222
|
+
usedStreamNames.add('Regions6/Data')
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (shapeBasedRegionHeaderBytes && shapeBasedRegionDataBytes) {
|
|
227
|
+
binaryPrimitives.shapeBasedRegions =
|
|
228
|
+
PcbBinaryPrimitiveParser.parseRegionStream(
|
|
229
|
+
shapeBasedRegionHeaderBytes,
|
|
230
|
+
shapeBasedRegionDataBytes,
|
|
231
|
+
{ shapeBased: true }
|
|
232
|
+
)
|
|
233
|
+
if (binaryPrimitives.shapeBasedRegions.length) {
|
|
234
|
+
usedStreamNames.add('ShapeBasedRegions6/Data')
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (boardRegionHeaderBytes && boardRegionDataBytes) {
|
|
239
|
+
binaryPrimitives.boardRegions =
|
|
240
|
+
PcbBinaryPrimitiveParser.parseRegionStream(
|
|
241
|
+
boardRegionHeaderBytes,
|
|
242
|
+
boardRegionDataBytes
|
|
243
|
+
)
|
|
244
|
+
if (binaryPrimitives.boardRegions.length) {
|
|
245
|
+
usedStreamNames.add('BoardRegions/Data')
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
163
249
|
const embeddedModels =
|
|
164
250
|
PcbEmbeddedModelExtractor.extractFromStreams(streams)
|
|
251
|
+
const embeddedFonts =
|
|
252
|
+
PcbEmbeddedFontExtractor.extractFromStreams(streams)
|
|
253
|
+
const rawRecords = PcbRawRecordRegistry.collectPcbDocRecords(
|
|
254
|
+
streams,
|
|
255
|
+
binaryPrimitives
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
rawRecords.forEach((record) => usedStreamNames.add(record.sourceStream))
|
|
165
259
|
|
|
166
260
|
if (
|
|
167
261
|
embeddedModels.models.length ||
|
|
@@ -176,22 +270,40 @@ export class PcbStreamExtractor {
|
|
|
176
270
|
)
|
|
177
271
|
}
|
|
178
272
|
|
|
273
|
+
if (embeddedFonts.fonts.length) {
|
|
274
|
+
embeddedFonts.fonts.forEach((font) =>
|
|
275
|
+
usedStreamNames.add(font.sourceStream)
|
|
276
|
+
)
|
|
277
|
+
}
|
|
278
|
+
|
|
179
279
|
return {
|
|
180
280
|
records,
|
|
181
281
|
streamNames: [...usedStreamNames].sort((left, right) =>
|
|
182
282
|
left.localeCompare(right)
|
|
183
283
|
),
|
|
184
284
|
binaryPrimitives,
|
|
285
|
+
primitiveParameters,
|
|
286
|
+
wideStrings,
|
|
185
287
|
embeddedModels,
|
|
288
|
+
embeddedFonts,
|
|
289
|
+
rawRecords,
|
|
186
290
|
diagnostics: {
|
|
187
291
|
printableRecordCount: records.length,
|
|
188
292
|
printableStreamCount: printableStreamNames.size,
|
|
293
|
+
embeddedFontCount: embeddedFonts.fonts.length,
|
|
294
|
+
rawRecordCount: rawRecords.length,
|
|
295
|
+
primitiveParameterGroupCount: primitiveParameters.groups.length,
|
|
296
|
+
wideStringCount: wideStrings.entries.length,
|
|
189
297
|
binaryPrimitiveCount:
|
|
190
298
|
binaryPrimitives.arcs.length +
|
|
191
299
|
binaryPrimitives.tracks.length +
|
|
192
300
|
binaryPrimitives.vias.length +
|
|
193
301
|
binaryPrimitives.fills.length +
|
|
194
|
-
binaryPrimitives.pads.length
|
|
302
|
+
binaryPrimitives.pads.length +
|
|
303
|
+
binaryPrimitives.texts.length +
|
|
304
|
+
binaryPrimitives.regions.length +
|
|
305
|
+
binaryPrimitives.shapeBasedRegions.length +
|
|
306
|
+
binaryPrimitives.boardRegions.length
|
|
195
307
|
}
|
|
196
308
|
}
|
|
197
309
|
}
|
|
@@ -207,4 +319,15 @@ export class PcbStreamExtractor {
|
|
|
207
319
|
bytes.byteOffset + bytes.byteLength
|
|
208
320
|
)
|
|
209
321
|
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Returns true for binary sidecar streams with printable-looking payloads.
|
|
325
|
+
* @param {string} name
|
|
326
|
+
* @returns {boolean}
|
|
327
|
+
*/
|
|
328
|
+
static #isBinarySidecarDataStream(name) {
|
|
329
|
+
return (
|
|
330
|
+
name === 'PrimitiveParameters/Data' || name === 'WideStrings6/Data'
|
|
331
|
+
)
|
|
332
|
+
}
|
|
210
333
|
}
|