altium-toolkit 1.1.2 → 1.1.22

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 (57) hide show
  1. package/docs/api.md +37 -0
  2. package/docs/model-format.md +18 -0
  3. package/docs/schemas/altium_toolkit/normalized_model_a1.schema.json +2 -2
  4. package/docs/testing.md +5 -0
  5. package/package.json +1 -1
  6. package/spec/library-scope.md +5 -0
  7. package/src/core/altium/AltiumLayoutParser.mjs +275 -13
  8. package/src/core/altium/AltiumLibraryBatchExporter.mjs +206 -0
  9. package/src/core/altium/AltiumLibraryRecordBuilder.mjs +293 -0
  10. package/src/core/altium/AltiumParser.mjs +245 -10
  11. package/src/core/altium/AltiumPcbLibExporter.mjs +101 -0
  12. package/src/core/altium/AltiumSchLibExporter.mjs +57 -0
  13. package/src/core/altium/AsciiRecordParser.mjs +43 -11
  14. package/src/core/altium/PcbComponentKindPolicy.mjs +9 -9
  15. package/src/core/altium/PcbEmbeddedFontExtractor.mjs +186 -43
  16. package/src/core/altium/PcbEmbeddedModelExtractor.mjs +22 -3
  17. package/src/core/altium/PcbOutlineRecovery.mjs +94 -0
  18. package/src/core/altium/PrintableTextDecoder.mjs +133 -13
  19. package/src/core/altium/SchematicComponentOwnerTextResolver.mjs +13 -0
  20. package/src/core/altium/SchematicComponentTextResolver.mjs +40 -1
  21. package/src/core/altium/SchematicDirectiveParser.mjs +5 -17
  22. package/src/core/altium/SchematicImageParser.mjs +291 -6
  23. package/src/core/altium/SchematicMultipartDesignatorNormalizer.mjs +164 -0
  24. package/src/core/altium/SchematicMultipartOwnerMatcher.mjs +2 -0
  25. package/src/core/altium/SchematicNoErcSymbolResolver.mjs +36 -0
  26. package/src/core/altium/SchematicPinParser.mjs +262 -24
  27. package/src/core/altium/SchematicPrimitiveParser.mjs +116 -8
  28. package/src/core/altium/SchematicSheetStyleResolver.mjs +38 -0
  29. package/src/core/altium/SchematicStreamExtractor.mjs +62 -15
  30. package/src/core/altium/SchematicTextParser.mjs +125 -11
  31. package/src/core/altium/SchematicTextPostProcessor.mjs +146 -102
  32. package/src/core/altium/SourceBundleExporter.mjs +156 -0
  33. package/src/core/altium/SourceComponentBundleNormalizer.mjs +295 -0
  34. package/src/core/altium/SourceComponentClient.mjs +239 -0
  35. package/src/core/ole/OleCompoundDocumentWriter.mjs +449 -0
  36. package/src/parser.mjs +8 -0
  37. package/src/styles/altium-renderers.css +6 -6
  38. package/src/ui/PcbArcUtils.mjs +19 -2
  39. package/src/ui/PcbScene3dBuilder.mjs +202 -20
  40. package/src/ui/PcbScene3dModelRegistry.mjs +28 -18
  41. package/src/ui/PcbScene3dPlacementSideResolver.mjs +48 -6
  42. package/src/ui/SchematicColorResolver.mjs +263 -0
  43. package/src/ui/SchematicContentLayout.mjs +58 -1
  44. package/src/ui/SchematicDirectiveRenderer.mjs +133 -22
  45. package/src/ui/SchematicImageRenderer.mjs +125 -10
  46. package/src/ui/SchematicJunctionRenderer.mjs +1 -1
  47. package/src/ui/SchematicLineColorResolver.mjs +88 -0
  48. package/src/ui/SchematicNativeFooterPartitioner.mjs +275 -0
  49. package/src/ui/SchematicNoteRenderer.mjs +87 -7
  50. package/src/ui/SchematicOwnerPinLabelLayout.mjs +560 -10
  51. package/src/ui/SchematicOwnerPinMarkerLineThemer.mjs +155 -0
  52. package/src/ui/SchematicPinSvgRenderer.mjs +397 -48
  53. package/src/ui/SchematicPowerDiagramImageProcessor.mjs +970 -0
  54. package/src/ui/SchematicPowerDiagramLineMasks.mjs +631 -0
  55. package/src/ui/SchematicPowerPortRenderer.mjs +1 -1
  56. package/src/ui/SchematicShapeRenderer.mjs +109 -24
  57. package/src/ui/SchematicSvgRenderer.mjs +1210 -71
@@ -157,7 +157,7 @@ export class SchematicShapeRenderer {
157
157
  pie.startAngle,
158
158
  pie.endAngle
159
159
  )
160
- const sweep = delta >= 0 ? 0 : 1
160
+ const sweep = SchematicShapeRenderer.#resolvePieSweep(delta)
161
161
  const center = {
162
162
  x: Number(pie.x) || 0,
163
163
  y: projectSchematicY(sheetHeight, Number(pie.y) || 0)
@@ -226,11 +226,18 @@ export class SchematicShapeRenderer {
226
226
 
227
227
  /**
228
228
  * Builds one schematic rectangle primitive.
229
- * @param {{ x: number, y: number, width: number, height: number, color: string, fill: string, isSolid: boolean, transparent: boolean, lineWidth: number, lineStyle?: number }} rectangle
229
+ * @param {{ x: number, y: number, width: number, height: number, color: string, fill: string, isSolid: boolean, transparent: boolean, lineWidth: number, lineStyle?: number, ownerIndex?: string }} rectangle
230
230
  * @param {number} sheetHeight
231
231
  * @returns {string}
232
232
  */
233
233
  static buildRectangleMarkup(rectangle, sheetHeight) {
234
+ const preserveSourceColors =
235
+ SchematicShapeRenderer.#isOwnerColorStrip(rectangle)
236
+ const fill = SchematicShapeRenderer.#resolveSchematicRectangleFill(
237
+ rectangle,
238
+ preserveSourceColors
239
+ )
240
+
234
241
  return (
235
242
  '<rect class="schematic-rectangle" x="' +
236
243
  formatNumber(rectangle.x) +
@@ -244,19 +251,27 @@ export class SchematicShapeRenderer {
244
251
  formatNumber(rectangle.height) +
245
252
  '" fill="' +
246
253
  escapeHtml(
247
- SchematicColorResolver.resolveFill(
248
- SchematicShapeRenderer.#resolveSchematicRectangleFill(
249
- rectangle
250
- ),
251
- '--schematic-fill-color'
252
- )
254
+ preserveSourceColors
255
+ ? SchematicColorResolver.resolveMutedSourceFill(
256
+ fill,
257
+ '--schematic-fill-color'
258
+ )
259
+ : SchematicColorResolver.resolveFill(
260
+ fill,
261
+ '--schematic-fill-color'
262
+ )
253
263
  ) +
254
264
  '" stroke="' +
255
265
  escapeHtml(
256
- SchematicColorResolver.resolveColor(
257
- rectangle.color,
258
- '--schematic-default-ink-color'
259
- )
266
+ preserveSourceColors
267
+ ? SchematicColorResolver.resolveMutedSourceColor(
268
+ rectangle.color,
269
+ '--schematic-default-ink-color'
270
+ )
271
+ : SchematicColorResolver.resolveColor(
272
+ rectangle.color,
273
+ '--schematic-default-ink-color'
274
+ )
260
275
  ) +
261
276
  '" stroke-width="' +
262
277
  formatNumber(Math.max(rectangle.lineWidth || 1, 0.8)) +
@@ -271,12 +286,18 @@ export class SchematicShapeRenderer {
271
286
 
272
287
  /**
273
288
  * Builds one schematic rounded-rectangle primitive.
274
- * @param {{ x: number, y: number, width: number, height: number, radius?: number, color: string, fill: string, isSolid: boolean, transparent: boolean, lineWidth: number, lineStyle?: number }} rectangle
289
+ * @param {{ x: number, y: number, width: number, height: number, radius?: number, color: string, fill: string, isSolid: boolean, transparent: boolean, lineWidth: number, lineStyle?: number, ownerIndex?: string }} rectangle
275
290
  * @param {number} sheetHeight
276
291
  * @returns {string}
277
292
  */
278
293
  static buildRoundedRectangleMarkup(rectangle, sheetHeight) {
279
294
  const radius = Math.max(Number(rectangle.radius || 0), 0)
295
+ const preserveSourceColors =
296
+ SchematicShapeRenderer.#isOwnerColorStrip(rectangle)
297
+ const fill = SchematicShapeRenderer.#resolveSchematicRectangleFill(
298
+ rectangle,
299
+ preserveSourceColors
300
+ )
280
301
 
281
302
  return (
282
303
  '<rect class="schematic-rounded-rectangle" x="' +
@@ -295,19 +316,27 @@ export class SchematicShapeRenderer {
295
316
  formatNumber(radius) +
296
317
  '" fill="' +
297
318
  escapeHtml(
298
- SchematicColorResolver.resolveFill(
299
- SchematicShapeRenderer.#resolveSchematicRectangleFill(
300
- rectangle
301
- ),
302
- '--schematic-fill-color'
303
- )
319
+ preserveSourceColors
320
+ ? SchematicColorResolver.resolveMutedSourceFill(
321
+ fill,
322
+ '--schematic-fill-color'
323
+ )
324
+ : SchematicColorResolver.resolveFill(
325
+ fill,
326
+ '--schematic-fill-color'
327
+ )
304
328
  ) +
305
329
  '" stroke="' +
306
330
  escapeHtml(
307
- SchematicColorResolver.resolveColor(
308
- rectangle.color,
309
- '--schematic-default-ink-color'
310
- )
331
+ preserveSourceColors
332
+ ? SchematicColorResolver.resolveMutedSourceColor(
333
+ rectangle.color,
334
+ '--schematic-default-ink-color'
335
+ )
336
+ : SchematicColorResolver.resolveColor(
337
+ rectangle.color,
338
+ '--schematic-default-ink-color'
339
+ )
311
340
  ) +
312
341
  '" stroke-width="' +
313
342
  formatNumber(Math.max(rectangle.lineWidth || 1, 0.8)) +
@@ -445,16 +474,57 @@ export class SchematicShapeRenderer {
445
474
  /**
446
475
  * Resolves the visible fill for one schematic rectangle primitive.
447
476
  * @param {{ fill: string, isSolid: boolean, transparent: boolean }} rectangle
477
+ * @param {boolean} preserveSourceFill
448
478
  * @returns {string}
449
479
  */
450
- static #resolveSchematicRectangleFill(rectangle) {
480
+ static #resolveSchematicRectangleFill(rectangle, preserveSourceFill) {
451
481
  if (rectangle.transparent || !rectangle.isSolid) {
482
+ if (
483
+ preserveSourceFill &&
484
+ SchematicShapeRenderer.#hasVisibleSourceFill(rectangle)
485
+ ) {
486
+ return rectangle.fill
487
+ }
488
+
452
489
  return 'none'
453
490
  }
454
491
 
455
492
  return rectangle.fill || 'none'
456
493
  }
457
494
 
495
+ /**
496
+ * Returns true when a transparent owner color strip still carries an
497
+ * authored fill color that encodes symbol-side rail intent.
498
+ * @param {{ fill?: string }} rectangle
499
+ * @returns {boolean}
500
+ */
501
+ static #hasVisibleSourceFill(rectangle) {
502
+ const fill = String(rectangle?.fill || '')
503
+ .trim()
504
+ .toLowerCase()
505
+
506
+ return Boolean(fill) && fill !== 'none' && fill !== 'transparent'
507
+ }
508
+
509
+ /**
510
+ * Returns true for narrow symbol-owned color swatches such as per-section
511
+ * strips that carry source palette meaning.
512
+ * @param {{ width: number, height: number, ownerIndex?: string }} rectangle
513
+ * @returns {boolean}
514
+ */
515
+ static #isOwnerColorStrip(rectangle) {
516
+ if (!rectangle?.ownerIndex) {
517
+ return false
518
+ }
519
+
520
+ const width = Math.abs(Number(rectangle.width || 0))
521
+ const height = Math.abs(Number(rectangle.height || 0))
522
+ const shortSide = Math.min(width, height)
523
+ const longSide = Math.max(width, height)
524
+
525
+ return shortSide > 0 && shortSide <= 8 && longSide >= 20
526
+ }
527
+
458
528
  /**
459
529
  * Resolves the visible fill for one schematic ellipse primitive.
460
530
  * @param {{ fill: string, isSolid: boolean, transparent: boolean }} ellipse
@@ -766,4 +836,19 @@ export class SchematicShapeRenderer {
766
836
 
767
837
  return delta
768
838
  }
839
+
840
+ /**
841
+ * Resolves SVG sweep direction for filled Altium pie primitives.
842
+ * @param {number} delta Normalized source angle delta.
843
+ * @returns {number}
844
+ */
845
+ static #resolvePieSweep(delta) {
846
+ const magnitude = Math.abs(Number(delta) || 0)
847
+
848
+ if (Math.abs(magnitude - 180) <= 0.001) {
849
+ return 0
850
+ }
851
+
852
+ return delta >= 0 ? 0 : 1
853
+ }
769
854
  }