altium-toolkit 0.1.1 → 0.1.17

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.
Files changed (54) hide show
  1. package/README.md +25 -6
  2. package/docs/api.md +42 -4
  3. package/docs/model-format.md +95 -5
  4. package/docs/schemas/altium_toolkit/normalized_model_a1.schema.json +553 -0
  5. package/docs/testing.md +7 -2
  6. package/package.json +6 -2
  7. package/spec/library-scope.md +7 -1
  8. package/src/core/altium/AltiumParser.mjs +22 -325
  9. package/src/core/altium/NormalizedModelSchema.mjs +28 -0
  10. package/src/core/altium/PcbArcPrimitiveParser.mjs +87 -0
  11. package/src/core/altium/PcbBinaryPrimitiveParser.mjs +43 -370
  12. package/src/core/altium/PcbBoardRegionSemanticsParser.mjs +477 -0
  13. package/src/core/altium/PcbComponentAnnotationNormalizer.mjs +290 -0
  14. package/src/core/altium/PcbComponentBodyPlacementNormalizer.mjs +52 -0
  15. package/src/core/altium/PcbComponentPrimitiveIndexer.mjs +109 -0
  16. package/src/core/altium/PcbEmbeddedFontExtractor.mjs +484 -0
  17. package/src/core/altium/PcbFillPrimitiveParser.mjs +84 -0
  18. package/src/core/altium/PcbFontMetricsParser.mjs +308 -0
  19. package/src/core/altium/PcbGeometryFlipper.mjs +244 -0
  20. package/src/core/altium/PcbLayerIdCodec.mjs +136 -0
  21. package/src/core/altium/PcbLibModelParser.mjs +202 -0
  22. package/src/core/altium/PcbLibStreamExtractor.mjs +968 -0
  23. package/src/core/altium/PcbModelParser.mjs +618 -66
  24. package/src/core/altium/PcbOutlineRecovery.mjs +4 -112
  25. package/src/core/altium/PcbPadPrimitiveParser.mjs +347 -0
  26. package/src/core/altium/PcbPadShapeCodec.mjs +158 -0
  27. package/src/core/altium/PcbPadStackParser.mjs +903 -0
  28. package/src/core/altium/PcbPrimitiveOwnershipIndexParser.mjs +60 -0
  29. package/src/core/altium/PcbPrimitiveParameterParser.mjs +212 -0
  30. package/src/core/altium/PcbPrimitiveRecordSlicer.mjs +243 -0
  31. package/src/core/altium/PcbRawRecordRegistry.mjs +831 -0
  32. package/src/core/altium/PcbRegionPrimitiveParser.mjs +317 -0
  33. package/src/core/altium/PcbRuleParser.mjs +587 -0
  34. package/src/core/altium/PcbStreamExtractor.mjs +127 -4
  35. package/src/core/altium/PcbTextPrimitiveParser.mjs +537 -0
  36. package/src/core/altium/PcbTrackPrimitiveParser.mjs +87 -0
  37. package/src/core/altium/PcbViaPrimitiveParser.mjs +88 -0
  38. package/src/core/altium/PcbViaStackParser.mjs +548 -0
  39. package/src/core/altium/PcbWideStringTableParser.mjs +108 -0
  40. package/src/core/altium/PrjPcbModelParser.mjs +797 -0
  41. package/src/core/altium/SchematicComponentTextResolver.mjs +355 -0
  42. package/src/parser.mjs +13 -0
  43. package/src/renderers.mjs +5 -0
  44. package/src/styles/altium-renderers.css +11 -6
  45. package/src/ui/PcbCopperPrimitiveSplitter.mjs +113 -0
  46. package/src/ui/PcbEdgeFacingGlyphNormalizer.mjs +6 -5
  47. package/src/ui/PcbEmbeddedFontFaceRenderer.mjs +126 -0
  48. package/src/ui/PcbFootprintPrimitiveSelector.mjs +27 -6
  49. package/src/ui/PcbRegionPrimitiveRenderer.mjs +243 -0
  50. package/src/ui/PcbSideResolvedRenderModel.mjs +336 -0
  51. package/src/ui/PcbSvgRenderer.mjs +101 -109
  52. package/src/ui/PcbTextPrimitiveRenderer.mjs +252 -0
  53. package/src/ui/SchematicSheetChromeRenderer.mjs +2 -93
  54. package/src/ui/SchematicSheetZoneRenderer.mjs +104 -0
@@ -2,423 +2,96 @@
2
2
  //
3
3
  // SPDX-License-Identifier: GPL-3.0-or-later
4
4
 
5
+ import { PcbArcPrimitiveParser } from './PcbArcPrimitiveParser.mjs'
6
+ import { PcbFillPrimitiveParser } from './PcbFillPrimitiveParser.mjs'
7
+ import { PcbPadPrimitiveParser } from './PcbPadPrimitiveParser.mjs'
8
+ import { PcbRegionPrimitiveParser } from './PcbRegionPrimitiveParser.mjs'
9
+ import { PcbTextPrimitiveParser } from './PcbTextPrimitiveParser.mjs'
10
+ import { PcbTrackPrimitiveParser } from './PcbTrackPrimitiveParser.mjs'
11
+ import { PcbViaPrimitiveParser } from './PcbViaPrimitiveParser.mjs'
12
+
5
13
  /**
6
- * Decodes fixed-size binary PCB primitive streams recovered from OLE-backed
7
- * PcbDoc files.
14
+ * Decodes binary PCB primitive streams recovered from OLE-backed PcbDoc files,
15
+ * including legacy fixed-layout records and object-id/length-prefixed records.
8
16
  */
9
17
  export class PcbBinaryPrimitiveParser {
10
- static #ARC_OBJECT_ID = 1
11
-
12
- static #ARC_RECORD_MIN_BYTE_LENGTH = 45
13
-
14
- static #TRACK_OBJECT_ID = 4
15
-
16
- static #PAD_OBJECT_ID = 2
17
-
18
- static #PAD_SUBRECORD_COUNT = 6
19
-
20
- static #PAD_MAIN_SUBRECORD_INDEX = 4
21
-
22
- static #PAD_EXTENSION_SUBRECORD_INDEX = 5
23
-
24
- static #PAD_MAIN_RECORD_MIN_BYTE_LENGTH = 61
25
-
26
- static #PAD_EXTENSION_MIN_BYTE_LENGTH = 596
27
-
28
18
  /**
29
- * Decodes one length-prefixed track stream.
19
+ * Decodes one track stream in either supported binary record format.
30
20
  * @param {Uint8Array | ArrayBuffer} headerBytes
31
21
  * @param {Uint8Array | ArrayBuffer} dataBytes
32
- * @returns {{ x1: number, y1: number, x2: number, y2: number, width: number, layerCode: number, layerId: number }[]}
22
+ * @returns {{ x1: number, y1: number, x2: number, y2: number, width: number, componentIndex: number | null, netIndex: number | null, polygonIndex: number | null, layerCode: number, layerId: number }[]}
33
23
  */
34
24
  static parseTrackStream(headerBytes, dataBytes) {
35
- const count = PcbBinaryPrimitiveParser.#readRecordCount(headerBytes)
36
- const normalizedData = PcbBinaryPrimitiveParser.#toUint8Array(dataBytes)
37
-
38
- if (!count) {
39
- return []
40
- }
41
-
42
- let offset = 0
43
- const tracks = []
44
-
45
- for (let index = 0; index < count; index += 1) {
46
- if (offset + 5 > normalizedData.byteLength) {
47
- return []
48
- }
49
-
50
- const objectId = normalizedData[offset]
51
- offset += 1
52
-
53
- if (objectId !== PcbBinaryPrimitiveParser.#TRACK_OBJECT_ID) {
54
- return []
55
- }
56
-
57
- const payloadLength = new DataView(
58
- normalizedData.buffer,
59
- normalizedData.byteOffset + offset,
60
- 4
61
- ).getUint32(0, true)
62
- offset += 4
63
-
64
- if (offset + payloadLength > normalizedData.byteLength) {
65
- return []
66
- }
67
-
68
- const payload = new DataView(
69
- normalizedData.buffer,
70
- normalizedData.byteOffset + offset,
71
- payloadLength
72
- )
73
- const layerId = payload.getUint8(0)
74
-
75
- tracks.push({
76
- x1: PcbBinaryPrimitiveParser.#readMil(payload, 13),
77
- y1: PcbBinaryPrimitiveParser.#readMil(payload, 17),
78
- x2: PcbBinaryPrimitiveParser.#readMil(payload, 21),
79
- y2: PcbBinaryPrimitiveParser.#readMil(payload, 25),
80
- width: PcbBinaryPrimitiveParser.#readMil(payload, 29),
81
- layerCode: layerId,
82
- layerId
83
- })
84
-
85
- offset += payloadLength
86
- }
87
-
88
- return tracks
25
+ return PcbTrackPrimitiveParser.parseTrackStream(headerBytes, dataBytes)
89
26
  }
90
27
 
91
28
  /**
92
- * Decodes one fixed-size via stream.
29
+ * Decodes one via stream in either supported binary record format.
93
30
  * @param {Uint8Array | ArrayBuffer} headerBytes
94
31
  * @param {Uint8Array | ArrayBuffer} dataBytes
95
- * @returns {{ x: number, y: number, diameter: number, holeDiameter: number }[]}
32
+ * @returns {{ x: number, y: number, diameter: number, holeDiameter: number, componentIndex: number | null, netIndex: number | null, polygonIndex: number | null, layerCode: number | null, layerId: number | null, layerStartId: number | null, layerEndId: number | null }[]}
96
33
  */
97
34
  static parseViaStream(headerBytes, dataBytes) {
98
- return PcbBinaryPrimitiveParser.#sliceFixedRecords(
99
- headerBytes,
100
- dataBytes,
101
- 326
102
- ).map((view) => ({
103
- x: PcbBinaryPrimitiveParser.#readMil(view, 18),
104
- y: PcbBinaryPrimitiveParser.#readMil(view, 22),
105
- diameter: PcbBinaryPrimitiveParser.#readMil(view, 26),
106
- holeDiameter: PcbBinaryPrimitiveParser.#readMil(view, 30)
107
- }))
35
+ return PcbViaPrimitiveParser.parseViaStream(headerBytes, dataBytes)
108
36
  }
109
37
 
110
38
  /**
111
- * Decodes one fixed-size fill stream.
39
+ * Decodes one fill stream in either supported binary record format.
112
40
  * @param {Uint8Array | ArrayBuffer} headerBytes
113
41
  * @param {Uint8Array | ArrayBuffer} dataBytes
114
- * @returns {{ x1: number, y1: number, x2: number, y2: number, layerCode: number, layerId: number }[]}
42
+ * @returns {{ x1: number, y1: number, x2: number, y2: number, componentIndex: number | null, netIndex: number | null, polygonIndex: number | null, layerCode: number, layerId: number }[]}
115
43
  */
116
44
  static parseFillStream(headerBytes, dataBytes) {
117
- return PcbBinaryPrimitiveParser.#sliceFixedRecords(
118
- headerBytes,
119
- dataBytes,
120
- 55
121
- ).map((view) => ({
122
- x1: PcbBinaryPrimitiveParser.#readMil(view, 18),
123
- y1: PcbBinaryPrimitiveParser.#readMil(view, 22),
124
- x2: PcbBinaryPrimitiveParser.#readMil(view, 26),
125
- y2: PcbBinaryPrimitiveParser.#readMil(view, 30),
126
- layerCode: view.getUint16(46, true),
127
- layerId: view.getUint8(5)
128
- }))
45
+ return PcbFillPrimitiveParser.parseFillStream(headerBytes, dataBytes)
129
46
  }
130
47
 
131
48
  /**
132
- * Decodes one length-prefixed arc stream.
49
+ * Decodes one arc stream in either supported binary record format.
133
50
  * @param {Uint8Array | ArrayBuffer} headerBytes
134
51
  * @param {Uint8Array | ArrayBuffer} dataBytes
135
- * @returns {{ x: number, y: number, radius: number, startAngle: number, endAngle: number, width: number, layerCode: number, layerId: number }[]}
52
+ * @returns {{ x: number, y: number, radius: number, startAngle: number, endAngle: number, width: number, componentIndex: number | null, netIndex: number | null, polygonIndex: number | null, layerCode: number, layerId: number }[]}
136
53
  */
137
54
  static parseArcStream(headerBytes, dataBytes) {
138
- const count = PcbBinaryPrimitiveParser.#readRecordCount(headerBytes)
139
- const normalizedData = PcbBinaryPrimitiveParser.#toUint8Array(dataBytes)
140
-
141
- if (!count) {
142
- return []
143
- }
144
-
145
- let offset = 0
146
- const arcs = []
147
-
148
- for (let index = 0; index < count; index += 1) {
149
- if (offset + 5 > normalizedData.byteLength) {
150
- return []
151
- }
152
-
153
- const objectId = normalizedData[offset]
154
- offset += 1
155
-
156
- if (objectId !== PcbBinaryPrimitiveParser.#ARC_OBJECT_ID) {
157
- return []
158
- }
159
-
160
- const payloadLength = new DataView(
161
- normalizedData.buffer,
162
- normalizedData.byteOffset + offset,
163
- 4
164
- ).getUint32(0, true)
165
- offset += 4
166
-
167
- if (
168
- payloadLength <
169
- PcbBinaryPrimitiveParser.#ARC_RECORD_MIN_BYTE_LENGTH ||
170
- offset + payloadLength > normalizedData.byteLength
171
- ) {
172
- return []
173
- }
174
-
175
- const payload = new DataView(
176
- normalizedData.buffer,
177
- normalizedData.byteOffset + offset,
178
- payloadLength
179
- )
180
- const layerId = payload.getUint8(0)
181
-
182
- arcs.push({
183
- x: PcbBinaryPrimitiveParser.#readMil(payload, 13),
184
- y: PcbBinaryPrimitiveParser.#readMil(payload, 17),
185
- radius: PcbBinaryPrimitiveParser.#readMil(payload, 21),
186
- startAngle: payload.getFloat64(25, true),
187
- endAngle: payload.getFloat64(33, true),
188
- width: PcbBinaryPrimitiveParser.#readMil(payload, 41),
189
- layerCode: layerId,
190
- layerId
191
- })
192
-
193
- offset += payloadLength
194
- }
195
-
196
- return arcs
55
+ return PcbArcPrimitiveParser.parseArcStream(headerBytes, dataBytes)
197
56
  }
198
57
 
199
58
  /**
200
59
  * Decodes one variable-length pad stream.
201
60
  * @param {Uint8Array | ArrayBuffer} headerBytes
202
61
  * @param {Uint8Array | ArrayBuffer} dataBytes
203
- * @returns {{ x: number, y: number, sizeTopX: number, sizeTopY: number, sizeMidX: number, sizeMidY: number, sizeBottomX: number, sizeBottomY: number, holeDiameter: number, shapeTop: number, shapeMid: number, shapeBottom: number, rotation: number, isPlated: boolean, holeShape: number | null, holeSlotLength: number | null, holeRotation: number | null, hasRoundedRect: boolean, roundedRectShapeTop: number | null, cornerRadiusTop: number | null, offsetTopX: number, offsetTopY: number }[]}
62
+ * @returns {{ x: number, y: number, sizeTopX: number, sizeTopY: number, sizeMidX: number, sizeMidY: number, sizeBottomX: number, sizeBottomY: number, holeDiameter: number, shapeTop: number, shapeMid: number, shapeBottom: number, shapeTopName: string | null, shapeMidName: string | null, shapeBottomName: string | null, rotation: number, isPlated: boolean, holeShape: number | null, holeSlotLength: number | null, holeRotation: number | null, hasRoundedRect: boolean, roundedRectShapeTop: number | null, cornerRadiusTop: number | null, offsetTopX: number, offsetTopY: number, componentIndex: number | null, netIndex: number | null, polygonIndex: number | null, layerCode: number | null, layerId: number | null, legacyLayerId: number | null, layerV7SaveId: number | null, [key: string]: unknown }[]}
204
63
  */
205
64
  static parsePadStream(headerBytes, dataBytes) {
206
- const count = PcbBinaryPrimitiveParser.#readRecordCount(headerBytes)
207
- const normalizedData = PcbBinaryPrimitiveParser.#toUint8Array(dataBytes)
208
-
209
- if (!count) {
210
- return []
211
- }
212
-
213
- let offset = 0
214
- const pads = []
215
-
216
- for (let index = 0; index < count; index += 1) {
217
- if (offset + 1 > normalizedData.byteLength) {
218
- return []
219
- }
220
-
221
- const objectId = normalizedData[offset]
222
- offset += 1
223
-
224
- if (objectId !== PcbBinaryPrimitiveParser.#PAD_OBJECT_ID) {
225
- return []
226
- }
227
-
228
- const subrecords = []
229
-
230
- for (
231
- let subrecordIndex = 0;
232
- subrecordIndex < PcbBinaryPrimitiveParser.#PAD_SUBRECORD_COUNT;
233
- subrecordIndex += 1
234
- ) {
235
- if (offset + 4 > normalizedData.byteLength) {
236
- return []
237
- }
238
-
239
- const subrecordLength = new DataView(
240
- normalizedData.buffer,
241
- normalizedData.byteOffset + offset,
242
- 4
243
- ).getUint32(0, true)
244
- offset += 4
245
-
246
- if (offset + subrecordLength > normalizedData.byteLength) {
247
- return []
248
- }
249
-
250
- subrecords.push(
251
- new DataView(
252
- normalizedData.buffer,
253
- normalizedData.byteOffset + offset,
254
- subrecordLength
255
- )
256
- )
257
- offset += subrecordLength
258
- }
259
-
260
- const pad = PcbBinaryPrimitiveParser.#parsePadSubrecords(subrecords)
261
-
262
- if (!pad) {
263
- return []
264
- }
265
-
266
- pads.push(pad)
267
- }
268
-
269
- return pads
65
+ return PcbPadPrimitiveParser.parsePadStream(headerBytes, dataBytes)
270
66
  }
271
67
 
272
68
  /**
273
- * Splits one fixed-length record stream into DataView slices.
69
+ * Decodes one variable-length PCB text stream.
274
70
  * @param {Uint8Array | ArrayBuffer} headerBytes
275
71
  * @param {Uint8Array | ArrayBuffer} dataBytes
276
- * @param {number} recordByteLength
277
- * @returns {DataView[]}
72
+ * @param {{ wideStrings?: Map<number | string, string> | Record<string, string> | { byIndex?: Record<string, string> } }} [options]
73
+ * @returns {{ text: string, x: number, y: number, height: number, layerId: number, ownerIndex: number | null, kind: number, visibilityFlags: number, rotation: number, role?: string, isDesignator?: boolean, isComment?: boolean, isPlaceholder?: boolean, componentIndex?: number }[]}
278
74
  */
279
- static #sliceFixedRecords(headerBytes, dataBytes, recordByteLength) {
280
- const normalizedData = PcbBinaryPrimitiveParser.#toUint8Array(dataBytes)
281
- const count = PcbBinaryPrimitiveParser.#readRecordCount(headerBytes)
282
-
283
- if (!count) {
284
- return []
285
- }
286
-
287
- if (normalizedData.byteLength < count * recordByteLength) {
288
- return []
289
- }
290
-
291
- const views = []
292
-
293
- for (let index = 0; index < count; index += 1) {
294
- views.push(
295
- new DataView(
296
- normalizedData.buffer,
297
- normalizedData.byteOffset + index * recordByteLength,
298
- recordByteLength
299
- )
300
- )
301
- }
302
-
303
- return views
304
- }
305
-
306
- /**
307
- * Decodes one pad payload from its subrecords.
308
- * @param {DataView[]} subrecords
309
- * @returns {{ x: number, y: number, sizeTopX: number, sizeTopY: number, sizeMidX: number, sizeMidY: number, sizeBottomX: number, sizeBottomY: number, holeDiameter: number, shapeTop: number, shapeMid: number, shapeBottom: number, rotation: number, isPlated: boolean, holeShape: number | null, holeSlotLength: number | null, holeRotation: number | null, hasRoundedRect: boolean, roundedRectShapeTop: number | null, cornerRadiusTop: number | null, offsetTopX: number, offsetTopY: number } | null}
310
- */
311
- static #parsePadSubrecords(subrecords) {
312
- const mainRecord =
313
- subrecords[PcbBinaryPrimitiveParser.#PAD_MAIN_SUBRECORD_INDEX]
314
- const extensionRecord =
315
- subrecords[PcbBinaryPrimitiveParser.#PAD_EXTENSION_SUBRECORD_INDEX]
316
-
317
- if (
318
- !mainRecord ||
319
- mainRecord.byteLength <
320
- PcbBinaryPrimitiveParser.#PAD_MAIN_RECORD_MIN_BYTE_LENGTH
321
- ) {
322
- return null
323
- }
324
-
325
- return {
326
- x: PcbBinaryPrimitiveParser.#readMil(mainRecord, 13),
327
- y: PcbBinaryPrimitiveParser.#readMil(mainRecord, 17),
328
- sizeTopX: PcbBinaryPrimitiveParser.#readMil(mainRecord, 21),
329
- sizeTopY: PcbBinaryPrimitiveParser.#readMil(mainRecord, 25),
330
- sizeMidX: PcbBinaryPrimitiveParser.#readMil(mainRecord, 29),
331
- sizeMidY: PcbBinaryPrimitiveParser.#readMil(mainRecord, 33),
332
- sizeBottomX: PcbBinaryPrimitiveParser.#readMil(mainRecord, 37),
333
- sizeBottomY: PcbBinaryPrimitiveParser.#readMil(mainRecord, 41),
334
- holeDiameter: PcbBinaryPrimitiveParser.#readMil(mainRecord, 45),
335
- shapeTop: mainRecord.getUint8(49),
336
- shapeMid: mainRecord.getUint8(50),
337
- shapeBottom: mainRecord.getUint8(51),
338
- rotation: mainRecord.getFloat64(52, true),
339
- isPlated: mainRecord.getUint8(60) !== 0,
340
- ...PcbBinaryPrimitiveParser.#parsePadExtensionBlock(extensionRecord)
341
- }
342
- }
343
-
344
- /**
345
- * Decodes one optional pad extension block.
346
- * @param {DataView | undefined} extensionRecord
347
- * @returns {{ holeShape: number | null, holeSlotLength: number | null, holeRotation: number | null, hasRoundedRect: boolean, roundedRectShapeTop: number | null, cornerRadiusTop: number | null, offsetTopX: number, offsetTopY: number }}
348
- */
349
- static #parsePadExtensionBlock(extensionRecord) {
350
- if (
351
- !extensionRecord ||
352
- extensionRecord.byteLength <
353
- PcbBinaryPrimitiveParser.#PAD_EXTENSION_MIN_BYTE_LENGTH
354
- ) {
355
- return {
356
- holeShape: null,
357
- holeSlotLength: null,
358
- holeRotation: null,
359
- hasRoundedRect: false,
360
- roundedRectShapeTop: null,
361
- cornerRadiusTop: null,
362
- offsetTopX: 0,
363
- offsetTopY: 0
364
- }
365
- }
366
-
367
- return {
368
- holeShape: extensionRecord.getUint8(262),
369
- holeSlotLength: PcbBinaryPrimitiveParser.#readMil(
370
- extensionRecord,
371
- 263
372
- ),
373
- holeRotation: extensionRecord.getFloat64(267, true),
374
- hasRoundedRect: extensionRecord.getUint8(531) !== 0,
375
- roundedRectShapeTop: extensionRecord.getUint8(532),
376
- cornerRadiusTop: extensionRecord.getUint8(564),
377
- offsetTopX: PcbBinaryPrimitiveParser.#readMil(extensionRecord, 275),
378
- offsetTopY: PcbBinaryPrimitiveParser.#readMil(extensionRecord, 403)
379
- }
380
- }
381
-
382
- /**
383
- * Normalizes one byte-like input into a Uint8Array view.
384
- * @param {Uint8Array | ArrayBuffer} bytes
385
- * @returns {Uint8Array}
386
- */
387
- static #toUint8Array(bytes) {
388
- if (bytes instanceof Uint8Array) {
389
- return bytes
390
- }
391
-
392
- return new Uint8Array(bytes)
75
+ static parseTextStream(headerBytes, dataBytes, options = {}) {
76
+ return PcbTextPrimitiveParser.parseTextStream(
77
+ headerBytes,
78
+ dataBytes,
79
+ options
80
+ )
393
81
  }
394
82
 
395
83
  /**
396
- * Reads one little-endian record count from a binary stream header.
84
+ * Decodes one variable-length PCB region stream.
397
85
  * @param {Uint8Array | ArrayBuffer} headerBytes
398
- * @returns {number}
399
- */
400
- static #readRecordCount(headerBytes) {
401
- const normalizedHeader =
402
- PcbBinaryPrimitiveParser.#toUint8Array(headerBytes)
403
-
404
- if (normalizedHeader.byteLength < 4) {
405
- return 0
406
- }
407
-
408
- return new DataView(
409
- normalizedHeader.buffer,
410
- normalizedHeader.byteOffset,
411
- normalizedHeader.byteLength
412
- ).getUint32(0, true)
413
- }
414
-
415
- /**
416
- * Reads one signed fixed-point mil coordinate.
417
- * @param {DataView} view
418
- * @param {number} offset
419
- * @returns {number}
86
+ * @param {Uint8Array | ArrayBuffer} dataBytes
87
+ * @param {{ shapeBased?: boolean }} [options]
88
+ * @returns {{ layerId: number, layerCode: number, netIndex: number | null, polygonIndex: number | null, componentIndex: number | null, kind: number, isKeepout: boolean, isBoardCutout: boolean, isShapeBased: boolean, points: object[], holes: object[][], properties: Record<string, string> }[]}
420
89
  */
421
- static #readMil(view, offset) {
422
- return view.getInt32(offset, true) / 10000
90
+ static parseRegionStream(headerBytes, dataBytes, options = {}) {
91
+ return PcbRegionPrimitiveParser.parseRegionStream(
92
+ headerBytes,
93
+ dataBytes,
94
+ options
95
+ )
423
96
  }
424
97
  }