altium-toolkit 1.1.40 → 1.2.0
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 +113 -19
- package/docs/api.md +224 -18
- package/docs/capabilities.md +65 -0
- package/docs/migration/legacy-001.md +309 -0
- package/docs/migration/legacy-002.md +309 -0
- package/docs/migration/legacy-003.md +309 -0
- package/docs/migration/legacy-004.md +309 -0
- package/docs/migration/legacy-005.md +111 -0
- package/docs/migration.md +20 -0
- package/docs/model-format.md +28 -3
- package/docs/release-notes-v1.2.0.md +147 -0
- package/docs/testing.md +43 -1
- package/examples/arduino-uno/PcbThreeSceneRenderer.mjs +1 -1
- package/examples/arduino-uno/example.mjs +1 -1
- package/examples/cli-utils.mjs +1 -1
- package/examples/corpus-smoke.mjs +1 -1
- package/examples/inspect-board.mjs +1 -1
- package/examples/library-catalog.mjs +1 -1
- package/examples/validate-library.mjs +1 -1
- package/package.json +20 -5
- package/spec/api-baseline-v1.1.41.json +1 -0
- package/spec/asset-baseline-v1.1.41.json +1 -0
- package/spec/feature-preservation.json +1 -0
- package/spec/library-scope.md +14 -4
- package/spec/native-source-manifest-v1.1.41.json +1 -0
- package/src/capabilities.mjs +4 -0
- package/src/convergence/AltiumCircuitJsonProjection.mjs +230 -0
- package/src/convergence/AltiumDocumentBuilder.mjs +167 -0
- package/src/convergence/AltiumExtensionResolver.mjs +98 -0
- package/src/convergence/AltiumProjectDocumentResolver.mjs +324 -0
- package/src/convergence/AltiumSchematicCoordinateProjection.mjs +130 -0
- package/src/convergence/AltiumWorkerClient.mjs +95 -0
- package/src/convergence/Parser.mjs +285 -0
- package/src/convergence/ParserInput.mjs +282 -0
- package/src/convergence/ProjectLoader.mjs +916 -0
- package/src/convergence/SchematicSvgRenderer.mjs +126 -0
- package/src/convergence/ToolkitCapabilities.mjs +49 -0
- package/src/core/altium/AltiumLayoutParser.mjs +9 -4
- package/src/core/altium/PcbLayerStackReadModelBuilder.mjs +1 -0
- package/src/core/circuit-json/CircuitJsonSchematicDocumentGraphicBuilder.mjs +785 -0
- package/src/core/circuit-json/CircuitJsonSchematicGraphicBuilder.mjs +909 -0
- package/src/core/circuit-json/CircuitJsonSchematicImageProjection.mjs +277 -0
- package/src/core/circuit-json/CircuitJsonSchematicStrokeStyle.mjs +47 -0
- package/src/extensions.mjs +11 -0
- package/src/index.mjs +20 -4
- package/src/interaction.mjs +7 -0
- package/src/legacy-netlist-query.mjs +11 -0
- package/src/legacy-parser.mjs +141 -0
- package/src/legacy-renderers.mjs +25 -0
- package/src/legacy-scene3d.mjs +10 -0
- package/src/manufacturing.mjs +4 -0
- package/src/parser.mjs +12 -138
- package/src/project.mjs +11 -0
- package/src/query.mjs +4 -0
- package/src/renderers.mjs +4 -22
- package/src/scene3d.mjs +5 -8
- package/src/simulation.mjs +4 -0
- package/src/styles/altium-renderers.css +67 -1
- package/src/styles/renderers.css +27 -0
- package/src/testing.mjs +8 -0
- package/src/ui/PcbInteractionLayerModel.mjs +6 -2
- package/src/ui/PcbPadMaskApertureRenderer.mjs +288 -0
- package/src/ui/PcbSvgRenderer.mjs +674 -38
- package/src/workers/parser.worker.mjs +37 -0
package/src/parser.mjs
CHANGED
|
@@ -1,142 +1,16 @@
|
|
|
1
1
|
// SPDX-FileCopyrightText: 2026 André Fiedler
|
|
2
|
-
//
|
|
3
2
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
4
3
|
|
|
5
|
-
export { BinaryReader, BinaryReaderCursor } from './core/BinaryReader.mjs'
|
|
6
|
-
export { OleCompoundDocument } from './core/ole/OleCompoundDocument.mjs'
|
|
7
|
-
export { OleConstants } from './core/ole/OleConstants.mjs'
|
|
8
|
-
export { OleDirectoryEntry } from './core/ole/OleDirectoryEntry.mjs'
|
|
9
|
-
export { OleCompoundDocumentWriter } from './core/ole/OleCompoundDocumentWriter.mjs'
|
|
10
|
-
export { AltiumLibraryBatchExporter } from './core/altium/AltiumLibraryBatchExporter.mjs'
|
|
11
|
-
export { AltiumLibraryRecordBuilder } from './core/altium/AltiumLibraryRecordBuilder.mjs'
|
|
12
|
-
export { AltiumPcbLibExporter } from './core/altium/AltiumPcbLibExporter.mjs'
|
|
13
|
-
export { AltiumSchLibExporter } from './core/altium/AltiumSchLibExporter.mjs'
|
|
14
|
-
export { SelectedPartAltiumExportAdapter } from './core/altium/SelectedPartAltiumExportAdapter.mjs'
|
|
15
|
-
export { AltiumUnits } from './core/altium/AltiumUnits.mjs'
|
|
16
|
-
export { SourceBundleExporter } from './core/altium/SourceBundleExporter.mjs'
|
|
17
|
-
export { SourceComponentBundleNormalizer } from './core/altium/SourceComponentBundleNormalizer.mjs'
|
|
18
|
-
export { SourceComponentClient } from './core/altium/SourceComponentClient.mjs'
|
|
19
|
-
export { AltiumParser } from './core/altium/AltiumParser.mjs'
|
|
20
|
-
export { AltiumSchematicArcAngleNormalizer } from './core/altium/AltiumSchematicArcAngleNormalizer.mjs'
|
|
21
|
-
export { AltiumSchematicFreeGraphicStrokeNormalizer } from './core/altium/AltiumSchematicFreeGraphicStrokeNormalizer.mjs'
|
|
22
|
-
export { AltiumSchematicHiddenDesignatorResolver } from './core/altium/AltiumSchematicHiddenDesignatorResolver.mjs'
|
|
23
|
-
export { AltiumSchematicPackedImageResolver } from './core/altium/AltiumSchematicPackedImageResolver.mjs'
|
|
24
|
-
export { AltiumSchematicSheetBoundsNormalizer } from './core/altium/AltiumSchematicSheetBoundsNormalizer.mjs'
|
|
25
|
-
export { AltiumLayoutParser } from './core/altium/AltiumLayoutParser.mjs'
|
|
26
|
-
export { AsciiRecordParser } from './core/altium/AsciiRecordParser.mjs'
|
|
27
|
-
export { HostCapabilityDiagnosticsBuilder } from './core/altium/HostCapabilityDiagnosticsBuilder.mjs'
|
|
28
|
-
export { IntLibModelParser } from './core/altium/IntLibModelParser.mjs'
|
|
29
|
-
export { IntLibStreamExtractor } from './core/altium/IntLibStreamExtractor.mjs'
|
|
30
|
-
export { EmbeddedAssetReportBuilder } from './core/altium/EmbeddedAssetReportBuilder.mjs'
|
|
31
|
-
export { EmbeddedFileInventoryBuilder } from './core/altium/EmbeddedFileInventoryBuilder.mjs'
|
|
32
|
-
export { FixtureCoverageMatrixBuilder } from './core/altium/FixtureCoverageMatrixBuilder.mjs'
|
|
33
|
-
export { GeometryBoundsReportBuilder } from './core/altium/GeometryBoundsReportBuilder.mjs'
|
|
34
4
|
export {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
export {
|
|
47
|
-
export { DraftsmanDigestParser } from './core/altium/DraftsmanDigestParser.mjs'
|
|
48
|
-
export { LibraryRenderManifestBuilder } from './core/altium/LibraryRenderManifestBuilder.mjs'
|
|
49
|
-
export { LibraryCatalogArtifactBuilder } from './core/altium/LibraryCatalogArtifactBuilder.mjs'
|
|
50
|
-
export { LibraryCompatibilityReportBuilder } from './core/altium/LibraryCompatibilityReportBuilder.mjs'
|
|
51
|
-
export { LibraryDiffReportBuilder } from './core/altium/LibraryDiffReportBuilder.mjs'
|
|
52
|
-
export { LibraryInspectionReportBuilder } from './core/altium/LibraryInspectionReportBuilder.mjs'
|
|
53
|
-
export { LibraryQaReportBuilder } from './core/altium/LibraryQaReportBuilder.mjs'
|
|
54
|
-
export { LibrarySearchIndex } from './core/altium/LibrarySearchIndex.mjs'
|
|
55
|
-
export { NativeStreamInventoryBuilder } from './core/altium/NativeStreamInventoryBuilder.mjs'
|
|
56
|
-
export { ParserUtils } from './core/altium/ParserUtils.mjs'
|
|
57
|
-
export { ParameterRecordInventoryBuilder } from './core/altium/ParameterRecordInventoryBuilder.mjs'
|
|
58
|
-
export { ParserCompatibilityFuzzer } from './core/altium/ParserCompatibilityFuzzer.mjs'
|
|
59
|
-
export { ParserDiagnosticNormalizer } from './core/altium/ParserDiagnosticNormalizer.mjs'
|
|
60
|
-
export { ParserFieldCoverageReportBuilder } from './core/altium/ParserFieldCoverageReportBuilder.mjs'
|
|
61
|
-
export { ParserValueVerificationReportBuilder } from './core/altium/ParserValueVerificationReportBuilder.mjs'
|
|
62
|
-
export { NormalizedModelSchema } from './core/altium/NormalizedModelSchema.mjs'
|
|
63
|
-
export { ProjectDesignBundleBuilder } from './core/altium/ProjectDesignBundleBuilder.mjs'
|
|
64
|
-
export { ProjectDocumentGraphBuilder } from './core/altium/ProjectDocumentGraphBuilder.mjs'
|
|
65
|
-
export { ProjectHierarchyReportBuilder } from './core/altium/ProjectHierarchyReportBuilder.mjs'
|
|
66
|
-
export { ProjectAnnotationParser } from './core/altium/ProjectAnnotationParser.mjs'
|
|
67
|
-
export { ProjectNetlistExporter } from './core/altium/ProjectNetlistExporter.mjs'
|
|
68
|
-
export { ProjectVariantViewBuilder } from './core/altium/ProjectVariantViewBuilder.mjs'
|
|
69
|
-
export { CircuitJsonModelSchema } from './core/circuit-json/CircuitJsonModelSchema.mjs'
|
|
70
|
-
export { CircuitJsonModelAdapter } from './core/circuit-json/CircuitJsonModelAdapter.mjs'
|
|
71
|
-
export { PcbBinaryPrimitiveParser } from './core/altium/PcbBinaryPrimitiveParser.mjs'
|
|
72
|
-
export { PcbBomProfileBuilder } from './core/altium/PcbBomProfileBuilder.mjs'
|
|
73
|
-
export { PcbBoardRegionSemanticsParser } from './core/altium/PcbBoardRegionSemanticsParser.mjs'
|
|
74
|
-
export { PcbComponentKindPolicy } from './core/altium/PcbComponentKindPolicy.mjs'
|
|
75
|
-
export { PcbComponentPrimitiveIndexer } from './core/altium/PcbComponentPrimitiveIndexer.mjs'
|
|
76
|
-
export { PcbCustomPadShapeParser } from './core/altium/PcbCustomPadShapeParser.mjs'
|
|
77
|
-
export { PcbDimensionParser } from './core/altium/PcbDimensionParser.mjs'
|
|
78
|
-
export { PcbDimensionReportBuilder } from './core/altium/PcbDimensionReportBuilder.mjs'
|
|
79
|
-
export { PcbEmbeddedFontExtractor } from './core/altium/PcbEmbeddedFontExtractor.mjs'
|
|
80
|
-
export { PcbEmbeddedModelExtractor } from './core/altium/PcbEmbeddedModelExtractor.mjs'
|
|
81
|
-
export { PcbExtendedPrimitiveInformationParser } from './core/altium/PcbExtendedPrimitiveInformationParser.mjs'
|
|
82
|
-
export { PcbFabricationReadinessReportBuilder } from './core/altium/PcbFabricationReadinessReportBuilder.mjs'
|
|
83
|
-
export { PcbFontMetricsParser } from './core/altium/PcbFontMetricsParser.mjs'
|
|
84
|
-
export { PcbLayerIdCodec } from './core/altium/PcbLayerIdCodec.mjs'
|
|
85
|
-
export { PcbLayerGroups } from './core/altium/PcbLayerGroups.mjs'
|
|
86
|
-
export { PcbLayerStackFidelityReportBuilder } from './core/altium/PcbLayerStackFidelityReportBuilder.mjs'
|
|
87
|
-
export { PcbLayerStackInterchangeParser } from './core/altium/PcbLayerStackInterchangeParser.mjs'
|
|
88
|
-
export { PcbLayerStackQueryHelper } from './core/altium/PcbLayerStackQueryHelper.mjs'
|
|
89
|
-
export { PcbLibModelParser } from './core/altium/PcbLibModelParser.mjs'
|
|
90
|
-
export { PcbLibParityReportBuilder } from './core/altium/PcbLibParityReportBuilder.mjs'
|
|
91
|
-
export { PcbLibStreamExtractor } from './core/altium/PcbLibStreamExtractor.mjs'
|
|
92
|
-
export { PcbMechanicalLayerPairParser } from './core/altium/PcbMechanicalLayerPairParser.mjs'
|
|
93
|
-
export { PcbModelParser } from './core/altium/PcbModelParser.mjs'
|
|
94
|
-
export { PcbOutlineRasterizer } from './core/altium/PcbOutlineRasterizer.mjs'
|
|
95
|
-
export { PcbOutlineRecovery } from './core/altium/PcbOutlineRecovery.mjs'
|
|
96
|
-
export { PcbOwnershipGraphBuilder } from './core/altium/PcbOwnershipGraphBuilder.mjs'
|
|
97
|
-
export { PcbPadStackParser } from './core/altium/PcbPadStackParser.mjs'
|
|
98
|
-
export { PcbPlacedFootprintManifestBuilder } from './core/altium/PcbPlacedFootprintManifestBuilder.mjs'
|
|
99
|
-
export { PcbPickPlacePositionResolver } from './core/altium/PcbPickPlacePositionResolver.mjs'
|
|
100
|
-
export { PcbPolygonRecordParser } from './core/altium/PcbPolygonRecordParser.mjs'
|
|
101
|
-
export { PcbPrimitiveFieldOffsetReportBuilder } from './core/altium/PcbPrimitiveFieldOffsetReportBuilder.mjs'
|
|
102
|
-
export { PcbRawRecordRegistry } from './core/altium/PcbRawRecordRegistry.mjs'
|
|
103
|
-
export { PcbReviewMetadataBuilder } from './core/altium/PcbReviewMetadataBuilder.mjs'
|
|
104
|
-
export { PcbReviewPolygonRealizationBuilder } from './core/altium/PcbReviewPolygonRealizationBuilder.mjs'
|
|
105
|
-
export { PcbClassReportBuilder } from './core/altium/PcbClassReportBuilder.mjs'
|
|
106
|
-
export { PcbInspectionReportBuilder } from './core/altium/PcbInspectionReportBuilder.mjs'
|
|
107
|
-
export { PcbNetMembershipReportBuilder } from './core/altium/PcbNetMembershipReportBuilder.mjs'
|
|
108
|
-
export { PcbRouteAnalysisBuilder } from './core/altium/PcbRouteAnalysisBuilder.mjs'
|
|
109
|
-
export { PcbRuleImpactReportBuilder } from './core/altium/PcbRuleImpactReportBuilder.mjs'
|
|
110
|
-
export { PcbRuleParser } from './core/altium/PcbRuleParser.mjs'
|
|
111
|
-
export { PcbSidecarRecordParser } from './core/altium/PcbSidecarRecordParser.mjs'
|
|
112
|
-
export { PcbSpecialStringResolver } from './core/altium/PcbSpecialStringResolver.mjs'
|
|
113
|
-
export { PcbStatisticsBuilder } from './core/altium/PcbStatisticsBuilder.mjs'
|
|
114
|
-
export { PcbStreamExtractor } from './core/altium/PcbStreamExtractor.mjs'
|
|
115
|
-
export { PcbUnionParser } from './core/altium/PcbUnionParser.mjs'
|
|
116
|
-
export { PcbViaStackParser } from './core/altium/PcbViaStackParser.mjs'
|
|
117
|
-
export { PcbViaStructureParser } from './core/altium/PcbViaStructureParser.mjs'
|
|
118
|
-
export { PrintableTextDecoder } from './core/altium/PrintableTextDecoder.mjs'
|
|
119
|
-
export { PrjPcbModelParser } from './core/altium/PrjPcbModelParser.mjs'
|
|
120
|
-
export { PrjScrModelParser } from './core/altium/PrjScrModelParser.mjs'
|
|
121
|
-
export { ProjectBomPnpReconciliationBuilder } from './core/altium/ProjectBomPnpReconciliationBuilder.mjs'
|
|
122
|
-
export { RawDataPreservationReportBuilder } from './core/altium/RawDataPreservationReportBuilder.mjs'
|
|
123
|
-
export { SchLibModelParser } from './core/altium/SchLibModelParser.mjs'
|
|
124
|
-
export { SchLibStreamExtractor } from './core/altium/SchLibStreamExtractor.mjs'
|
|
125
|
-
export { SchematicMultipartOwnerMatcher } from './core/altium/SchematicMultipartOwnerMatcher.mjs'
|
|
126
|
-
export { SchematicCrossSheetConnectorParser } from './core/altium/SchematicCrossSheetConnectorParser.mjs'
|
|
127
|
-
export { SchematicCodeSymbolParser } from './core/altium/SchematicCodeSymbolParser.mjs'
|
|
128
|
-
export { SchematicConnectivityQaBuilder } from './core/altium/SchematicConnectivityQaBuilder.mjs'
|
|
129
|
-
export { SchematicHarnessParser } from './core/altium/SchematicHarnessParser.mjs'
|
|
130
|
-
export { SchematicImplementationParser } from './core/altium/SchematicImplementationParser.mjs'
|
|
131
|
-
export { SchematicImageDiagnosticsBuilder } from './core/altium/SchematicImageDiagnosticsBuilder.mjs'
|
|
132
|
-
export { SchematicOwnershipGraphParser } from './core/altium/SchematicOwnershipGraphParser.mjs'
|
|
133
|
-
export { SchematicProjectParameterResolver } from './core/altium/SchematicProjectParameterResolver.mjs'
|
|
134
|
-
export { SchematicQaReportBuilder } from './core/altium/SchematicQaReportBuilder.mjs'
|
|
135
|
-
export { SchematicRecordStreamParser } from './core/altium/SchematicRecordStreamParser.mjs'
|
|
136
|
-
export { SchematicRecordTypeRegistry } from './core/altium/SchematicRecordTypeRegistry.mjs'
|
|
137
|
-
export { SchematicRepeatedChannelParser } from './core/altium/SchematicRepeatedChannelParser.mjs'
|
|
138
|
-
export { SchematicTemplateParser } from './core/altium/SchematicTemplateParser.mjs'
|
|
139
|
-
export { UnsupportedFeatureReportBuilder } from './core/altium/UnsupportedFeatureReportBuilder.mjs'
|
|
140
|
-
export { SchematicTextRunParser } from './core/altium/SchematicTextRunParser.mjs'
|
|
141
|
-
export { SchematicStandaloneCalloutNormalizer } from './core/altium/SchematicStandaloneCalloutNormalizer.mjs'
|
|
142
|
-
export { SvgModelCrossLinkValidator } from './core/altium/SvgModelCrossLinkValidator.mjs'
|
|
5
|
+
CircuitJsonDocumentContext,
|
|
6
|
+
DocumentResult,
|
|
7
|
+
ParserWorkerClient,
|
|
8
|
+
ToolkitAsset,
|
|
9
|
+
ToolkitDiagnostic,
|
|
10
|
+
ToolkitError,
|
|
11
|
+
ToolkitProgress,
|
|
12
|
+
TOOLKIT_WORKER_PROTOCOL,
|
|
13
|
+
ToolkitWorkerProtocol
|
|
14
|
+
} from 'circuitjson-toolkit/parser'
|
|
15
|
+
|
|
16
|
+
export { Parser } from './convergence/Parser.mjs'
|
package/src/project.mjs
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 André Fiedler
|
|
2
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
3
|
+
|
|
4
|
+
export {
|
|
5
|
+
ArchiveEntryPath,
|
|
6
|
+
ArchiveLimits,
|
|
7
|
+
ProjectResult,
|
|
8
|
+
ZipArchiveInspector
|
|
9
|
+
} from 'circuitjson-toolkit/project'
|
|
10
|
+
|
|
11
|
+
export { ProjectLoader } from './convergence/ProjectLoader.mjs'
|
package/src/query.mjs
ADDED
package/src/renderers.mjs
CHANGED
|
@@ -1,26 +1,8 @@
|
|
|
1
1
|
// SPDX-FileCopyrightText: 2026 André Fiedler
|
|
2
|
-
//
|
|
3
2
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
4
3
|
|
|
5
|
-
export { BomTableRenderer } from './ui/BomTableRenderer.mjs'
|
|
6
|
-
export { AltiumPcbBottomViewMirror } from './ui/AltiumPcbBottomViewMirror.mjs'
|
|
7
|
-
export { PcbArcUtils } from './ui/PcbArcUtils.mjs'
|
|
8
|
-
export { PcbEdgeFacingGlyphNormalizer } from './ui/PcbEdgeFacingGlyphNormalizer.mjs'
|
|
9
|
-
export { PcbFootprintPrimitiveSelector } from './ui/PcbFootprintPrimitiveSelector.mjs'
|
|
10
|
-
export { PcbFootprintPadAxisNormalizer } from './ui/PcbFootprintPadAxisNormalizer.mjs'
|
|
11
|
-
export { PcbInteractionIndex } from './ui/PcbInteractionIndex.mjs'
|
|
12
|
-
export { PcbInteractionItemRegistry } from './ui/PcbInteractionItemRegistry.mjs'
|
|
13
|
-
export { PcbInteractionLayerModel } from './ui/PcbInteractionLayerModel.mjs'
|
|
14
|
-
export { PcbLayerGroups } from './core/altium/PcbLayerGroups.mjs'
|
|
15
4
|
export {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
} from '
|
|
20
|
-
export { PcbSvgRenderer } from './ui/PcbSvgRenderer.mjs'
|
|
21
|
-
export { SchematicColorResolver } from './ui/SchematicColorResolver.mjs'
|
|
22
|
-
export { SchematicContentLayout } from './ui/SchematicContentLayout.mjs'
|
|
23
|
-
export { SchematicOwnerPinLabelLayout } from './ui/SchematicOwnerPinLabelLayout.mjs'
|
|
24
|
-
export { SchematicSvgRenderer } from './ui/SchematicSvgRenderer.mjs'
|
|
25
|
-
export { SchematicSvgUtils } from './ui/SchematicSvgUtils.mjs'
|
|
26
|
-
export { SchematicTypography } from './ui/SchematicTypography.mjs'
|
|
5
|
+
BomTableRenderer,
|
|
6
|
+
PcbSvgRenderer,
|
|
7
|
+
SchematicSvgRenderer
|
|
8
|
+
} from 'circuitjson-toolkit/renderers'
|
package/src/scene3d.mjs
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
// SPDX-FileCopyrightText: 2026 André Fiedler
|
|
2
|
-
//
|
|
3
2
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
4
3
|
|
|
5
|
-
export {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
export { PcbScene3dSummaryRenderer } from './ui/PcbScene3dSummaryRenderer.mjs'
|
|
11
|
-
export { PcbScene3dTextBoxLayoutResolver } from './ui/PcbScene3dTextBoxLayoutResolver.mjs'
|
|
4
|
+
export {
|
|
5
|
+
PcbScene3dBuilder,
|
|
6
|
+
PcbScene3dPreparator,
|
|
7
|
+
SceneAssetResolver
|
|
8
|
+
} from 'circuitjson-toolkit/scene3d'
|
|
@@ -142,6 +142,16 @@
|
|
|
142
142
|
--pcb-via-hole-fill: #0f746c;
|
|
143
143
|
--pcb-footprint-fill: rgba(247, 230, 117, 0.14);
|
|
144
144
|
--pcb-footprint-track-color: rgba(237, 172, 36, 1);
|
|
145
|
+
--pcb-detail-paste-fill: rgba(146, 146, 146, 0.94);
|
|
146
|
+
--pcb-detail-paste-stroke: rgba(154, 154, 154, 0.96);
|
|
147
|
+
--pcb-detail-mask-fill: rgba(137, 34, 132, 0.4);
|
|
148
|
+
--pcb-detail-mask-stroke: rgba(137, 34, 132, 0.82);
|
|
149
|
+
--pcb-detail-mechanical-fill: rgba(148, 160, 166, 0.32);
|
|
150
|
+
--pcb-detail-mechanical-stroke: rgba(96, 110, 118, 0.86);
|
|
151
|
+
--pcb-detail-drill-fill: rgba(79, 87, 93, 0.46);
|
|
152
|
+
--pcb-detail-drill-stroke: rgba(42, 50, 56, 0.88);
|
|
153
|
+
--pcb-detail-fill: rgba(150, 160, 166, 0.38);
|
|
154
|
+
--pcb-detail-stroke: rgba(80, 92, 100, 0.82);
|
|
145
155
|
--pcb-dimension-color: rgba(39, 88, 111, 0.78);
|
|
146
156
|
--pcb-dimension-text: #22343b;
|
|
147
157
|
--pcb-text-knockout-fill: rgba(248, 246, 239, 0.96);
|
|
@@ -200,7 +210,9 @@
|
|
|
200
210
|
.pcb-track,
|
|
201
211
|
.pcb-arc,
|
|
202
212
|
.pcb-footprint-track,
|
|
203
|
-
.pcb-footprint-arc
|
|
213
|
+
.pcb-footprint-arc,
|
|
214
|
+
.pcb-detail-track,
|
|
215
|
+
.pcb-detail-arc {
|
|
204
216
|
fill: none;
|
|
205
217
|
stroke-linecap: round;
|
|
206
218
|
stroke-linejoin: round;
|
|
@@ -271,6 +283,60 @@
|
|
|
271
283
|
stroke: var(--pcb-footprint-track-color);
|
|
272
284
|
}
|
|
273
285
|
|
|
286
|
+
.pcb-detail-fill,
|
|
287
|
+
.pcb-detail-region {
|
|
288
|
+
fill: var(--pcb-detail-fill);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
.pcb-detail-track,
|
|
292
|
+
.pcb-detail-arc {
|
|
293
|
+
stroke: var(--pcb-detail-stroke);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
.pcb-detail-fill--paste,
|
|
297
|
+
.pcb-detail-region--paste {
|
|
298
|
+
fill: var(--pcb-detail-paste-fill);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
.pcb-detail-track--paste,
|
|
302
|
+
.pcb-detail-arc--paste {
|
|
303
|
+
stroke: var(--pcb-detail-paste-stroke);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
.pcb-detail-fill--mask,
|
|
307
|
+
.pcb-detail-region--mask,
|
|
308
|
+
.pcb-detail-fill--solder-mask,
|
|
309
|
+
.pcb-detail-region--solder-mask {
|
|
310
|
+
fill: var(--pcb-detail-mask-fill);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
.pcb-detail-track--mask,
|
|
314
|
+
.pcb-detail-arc--mask,
|
|
315
|
+
.pcb-detail-track--solder-mask,
|
|
316
|
+
.pcb-detail-arc--solder-mask {
|
|
317
|
+
stroke: var(--pcb-detail-mask-stroke);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
.pcb-detail-fill--mechanical,
|
|
321
|
+
.pcb-detail-region--mechanical {
|
|
322
|
+
fill: var(--pcb-detail-mechanical-fill);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
.pcb-detail-track--mechanical,
|
|
326
|
+
.pcb-detail-arc--mechanical {
|
|
327
|
+
stroke: var(--pcb-detail-mechanical-stroke);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
.pcb-detail-fill--drill,
|
|
331
|
+
.pcb-detail-region--drill {
|
|
332
|
+
fill: var(--pcb-detail-drill-fill);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
.pcb-detail-track--drill,
|
|
336
|
+
.pcb-detail-arc--drill {
|
|
337
|
+
stroke: var(--pcb-detail-drill-stroke);
|
|
338
|
+
}
|
|
339
|
+
|
|
274
340
|
.pcb-dimensions {
|
|
275
341
|
pointer-events: none;
|
|
276
342
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/* SPDX-FileCopyrightText: 2026 André Fiedler */
|
|
2
|
+
/* SPDX-License-Identifier: GPL-3.0-or-later */
|
|
3
|
+
|
|
4
|
+
.pcb-svg,
|
|
5
|
+
.schematic-svg {
|
|
6
|
+
display: block;
|
|
7
|
+
width: 100%;
|
|
8
|
+
max-width: 100%;
|
|
9
|
+
height: auto;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.pcb-svg text,
|
|
13
|
+
.schematic-svg text {
|
|
14
|
+
font-family: ui-sans-serif, system-ui, sans-serif;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.bom-table {
|
|
18
|
+
width: 100%;
|
|
19
|
+
border-collapse: collapse;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.bom-table th,
|
|
23
|
+
.bom-table td {
|
|
24
|
+
padding: 0.35rem 0.5rem;
|
|
25
|
+
border: 1px solid currentColor;
|
|
26
|
+
text-align: left;
|
|
27
|
+
}
|
package/src/testing.mjs
ADDED
|
@@ -56,13 +56,17 @@ export class PcbInteractionLayerModel {
|
|
|
56
56
|
const key = String(layer?.name || layer?.layer || '').trim()
|
|
57
57
|
if (!key || seen.has(key)) continue
|
|
58
58
|
seen.add(key)
|
|
59
|
-
|
|
59
|
+
const row = {
|
|
60
60
|
key,
|
|
61
61
|
label: key,
|
|
62
62
|
layerId: Number.isFinite(Number(layer?.layerId))
|
|
63
63
|
? Number(layer.layerId)
|
|
64
64
|
: null
|
|
65
|
-
}
|
|
65
|
+
}
|
|
66
|
+
if (Number.isFinite(Number(layer?.legacyLayerId))) {
|
|
67
|
+
row.legacyLayerId = Number(layer.legacyLayerId)
|
|
68
|
+
}
|
|
69
|
+
layers.push(row)
|
|
66
70
|
}
|
|
67
71
|
|
|
68
72
|
return layers
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 André Fiedler
|
|
2
|
+
//
|
|
3
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
4
|
+
|
|
5
|
+
import { SchematicSvgUtils } from './SchematicSvgUtils.mjs'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Renders pad-derived paste and solder-mask apertures as independent SVG layers.
|
|
9
|
+
*/
|
|
10
|
+
export class PcbPadMaskApertureRenderer {
|
|
11
|
+
static #PAD_SHAPE_RECTANGULAR = 2
|
|
12
|
+
static #SPECS = [
|
|
13
|
+
{
|
|
14
|
+
flag: 'hasTopPasteMaskOpening',
|
|
15
|
+
kind: 'paste',
|
|
16
|
+
primitiveKind: 'pad-paste',
|
|
17
|
+
side: 'top',
|
|
18
|
+
layerId: 35,
|
|
19
|
+
layerName: 'Top Paste',
|
|
20
|
+
expansionKey: 'effectivePasteMaskExpansion'
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
flag: 'hasBottomPasteMaskOpening',
|
|
24
|
+
kind: 'paste',
|
|
25
|
+
primitiveKind: 'pad-paste',
|
|
26
|
+
side: 'bottom',
|
|
27
|
+
layerId: 36,
|
|
28
|
+
layerName: 'Bottom Paste',
|
|
29
|
+
expansionKey: 'effectivePasteMaskExpansion'
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
flag: 'hasTopSolderMaskOpening',
|
|
33
|
+
kind: 'solder-mask',
|
|
34
|
+
primitiveKind: 'pad-solder-mask',
|
|
35
|
+
side: 'top',
|
|
36
|
+
layerId: 37,
|
|
37
|
+
layerName: 'Top Solder',
|
|
38
|
+
expansionKey: 'effectiveSolderMaskExpansion'
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
flag: 'hasBottomSolderMaskOpening',
|
|
42
|
+
kind: 'solder-mask',
|
|
43
|
+
primitiveKind: 'pad-solder-mask',
|
|
44
|
+
side: 'bottom',
|
|
45
|
+
layerId: 38,
|
|
46
|
+
layerName: 'Bottom Solder',
|
|
47
|
+
expansionKey: 'effectiveSolderMaskExpansion'
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Builds one SVG group containing all derived pad mask apertures.
|
|
53
|
+
* @param {object[]} pads Normalized pad records.
|
|
54
|
+
* @param {{ attributes?: (aperture: object) => string, padIndex?: (pad: object, index: number) => number }} [options]
|
|
55
|
+
* @returns {string}
|
|
56
|
+
*/
|
|
57
|
+
static render(pads, options = {}) {
|
|
58
|
+
const apertures = []
|
|
59
|
+
|
|
60
|
+
for (const [fallbackIndex, pad] of (pads || []).entries()) {
|
|
61
|
+
const padIndex = PcbPadMaskApertureRenderer.#padIndex(
|
|
62
|
+
pad,
|
|
63
|
+
fallbackIndex,
|
|
64
|
+
options
|
|
65
|
+
)
|
|
66
|
+
for (const [specIndex, spec] of this.#SPECS.entries()) {
|
|
67
|
+
if (!pad?.[spec.flag]) continue
|
|
68
|
+
const aperture = this.#apertureForPad(
|
|
69
|
+
pad,
|
|
70
|
+
padIndex,
|
|
71
|
+
specIndex,
|
|
72
|
+
spec
|
|
73
|
+
)
|
|
74
|
+
if (!aperture) continue
|
|
75
|
+
apertures.push(
|
|
76
|
+
this.#renderAperture(aperture, options.attributes)
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!apertures.length) return ''
|
|
82
|
+
|
|
83
|
+
return '<g class="pcb-pad-mask-layers">' + apertures.join('') + '</g>'
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Resolves one stable pad index.
|
|
88
|
+
* @param {object} pad Pad record.
|
|
89
|
+
* @param {number} fallbackIndex Array index.
|
|
90
|
+
* @param {{ padIndex?: (pad: object, index: number) => number }} options
|
|
91
|
+
* @returns {number}
|
|
92
|
+
*/
|
|
93
|
+
static #padIndex(pad, fallbackIndex, options) {
|
|
94
|
+
const resolved = options.padIndex?.(pad, fallbackIndex)
|
|
95
|
+
return Number.isInteger(resolved) ? resolved : fallbackIndex
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Builds one normalized aperture descriptor for a pad/spec pair.
|
|
100
|
+
* @param {object} pad Pad record.
|
|
101
|
+
* @param {number} padIndex Stable pad index.
|
|
102
|
+
* @param {number} specIndex Spec index.
|
|
103
|
+
* @param {object} spec Aperture layer spec.
|
|
104
|
+
* @returns {object | null}
|
|
105
|
+
*/
|
|
106
|
+
static #apertureForPad(pad, padIndex, specIndex, spec) {
|
|
107
|
+
const size = this.#sizeForPad(pad, spec)
|
|
108
|
+
if (size.width <= 0 || size.height <= 0) return null
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
pad,
|
|
112
|
+
padIndex,
|
|
113
|
+
index: padIndex * this.#SPECS.length + specIndex,
|
|
114
|
+
spec,
|
|
115
|
+
size,
|
|
116
|
+
primitive: {
|
|
117
|
+
...pad,
|
|
118
|
+
layerId: spec.layerId,
|
|
119
|
+
layerCode: spec.layerId,
|
|
120
|
+
legacyLayerId: spec.layerId,
|
|
121
|
+
layerName: spec.layerName
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Resolves aperture dimensions after the parsed mask expansion.
|
|
128
|
+
* @param {object} pad Pad record.
|
|
129
|
+
* @param {object} spec Aperture layer spec.
|
|
130
|
+
* @returns {{ width: number, height: number }}
|
|
131
|
+
*/
|
|
132
|
+
static #sizeForPad(pad, spec) {
|
|
133
|
+
const side = spec.side === 'bottom' ? 'Bottom' : 'Top'
|
|
134
|
+
const width = Number(pad?.['size' + side + 'X'] || pad?.sizeMidX || 0)
|
|
135
|
+
const height = Number(pad?.['size' + side + 'Y'] || pad?.sizeMidY || 0)
|
|
136
|
+
const expansion = Number(pad?.[spec.expansionKey] || 0)
|
|
137
|
+
|
|
138
|
+
return {
|
|
139
|
+
width: Math.max(width + expansion * 2, 0),
|
|
140
|
+
height: Math.max(height + expansion * 2, 0)
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Renders one aperture shape.
|
|
146
|
+
* @param {object} aperture Aperture descriptor.
|
|
147
|
+
* @param {(aperture: object) => string | undefined} attributes Attribute callback.
|
|
148
|
+
* @returns {string}
|
|
149
|
+
*/
|
|
150
|
+
static #renderAperture(aperture, attributes) {
|
|
151
|
+
const className =
|
|
152
|
+
'pcb-detail-fill pcb-detail-fill--' +
|
|
153
|
+
(aperture.spec.kind === 'solder-mask' ? 'mask' : 'paste') +
|
|
154
|
+
' pcb-pad-mask-aperture pcb-pad-mask-aperture--' +
|
|
155
|
+
aperture.spec.kind
|
|
156
|
+
const renderedAttributes = attributes?.(aperture) || ''
|
|
157
|
+
|
|
158
|
+
return PcbPadMaskApertureRenderer.#isRoundAperture(aperture)
|
|
159
|
+
? PcbPadMaskApertureRenderer.#renderCircle(
|
|
160
|
+
aperture,
|
|
161
|
+
className,
|
|
162
|
+
renderedAttributes
|
|
163
|
+
)
|
|
164
|
+
: PcbPadMaskApertureRenderer.#renderRect(
|
|
165
|
+
aperture,
|
|
166
|
+
className,
|
|
167
|
+
renderedAttributes
|
|
168
|
+
)
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Renders one circular aperture.
|
|
173
|
+
* @param {object} aperture Aperture descriptor.
|
|
174
|
+
* @param {string} className SVG class list.
|
|
175
|
+
* @param {string} attributes SVG attributes.
|
|
176
|
+
* @returns {string}
|
|
177
|
+
*/
|
|
178
|
+
static #renderCircle(aperture, className, attributes) {
|
|
179
|
+
const { pad, size } = aperture
|
|
180
|
+
const radius = Math.max(size.width, size.height) / 2
|
|
181
|
+
|
|
182
|
+
return (
|
|
183
|
+
'<circle class="' +
|
|
184
|
+
className +
|
|
185
|
+
'" cx="' +
|
|
186
|
+
SchematicSvgUtils.formatNumber(Number(pad.x || 0)) +
|
|
187
|
+
'" cy="' +
|
|
188
|
+
SchematicSvgUtils.formatNumber(Number(pad.y || 0)) +
|
|
189
|
+
'" r="' +
|
|
190
|
+
SchematicSvgUtils.formatNumber(radius) +
|
|
191
|
+
'"' +
|
|
192
|
+
attributes +
|
|
193
|
+
' />'
|
|
194
|
+
)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Renders one rectangular aperture.
|
|
199
|
+
* @param {object} aperture Aperture descriptor.
|
|
200
|
+
* @param {string} className SVG class list.
|
|
201
|
+
* @param {string} attributes SVG attributes.
|
|
202
|
+
* @returns {string}
|
|
203
|
+
*/
|
|
204
|
+
static #renderRect(aperture, className, attributes) {
|
|
205
|
+
const { pad, size } = aperture
|
|
206
|
+
const x = Number(pad.x || 0) - size.width / 2
|
|
207
|
+
const y = Number(pad.y || 0) - size.height / 2
|
|
208
|
+
|
|
209
|
+
return (
|
|
210
|
+
'<rect class="' +
|
|
211
|
+
className +
|
|
212
|
+
'" x="' +
|
|
213
|
+
SchematicSvgUtils.formatNumber(x) +
|
|
214
|
+
'" y="' +
|
|
215
|
+
SchematicSvgUtils.formatNumber(y) +
|
|
216
|
+
'" width="' +
|
|
217
|
+
SchematicSvgUtils.formatNumber(size.width) +
|
|
218
|
+
'" height="' +
|
|
219
|
+
SchematicSvgUtils.formatNumber(size.height) +
|
|
220
|
+
'" rx="' +
|
|
221
|
+
SchematicSvgUtils.formatNumber(
|
|
222
|
+
PcbPadMaskApertureRenderer.#cornerRadius(aperture)
|
|
223
|
+
) +
|
|
224
|
+
'" transform="rotate(' +
|
|
225
|
+
SchematicSvgUtils.formatNumber(Number(pad.rotation || 0)) +
|
|
226
|
+
' ' +
|
|
227
|
+
SchematicSvgUtils.formatNumber(Number(pad.x || 0)) +
|
|
228
|
+
' ' +
|
|
229
|
+
SchematicSvgUtils.formatNumber(Number(pad.y || 0)) +
|
|
230
|
+
')"' +
|
|
231
|
+
attributes +
|
|
232
|
+
' />'
|
|
233
|
+
)
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Returns true when one aperture should be rendered as a circle.
|
|
238
|
+
* @param {object} aperture Aperture descriptor.
|
|
239
|
+
* @returns {boolean}
|
|
240
|
+
*/
|
|
241
|
+
static #isRoundAperture(aperture) {
|
|
242
|
+
const shape = PcbPadMaskApertureRenderer.#shapeForAperture(aperture)
|
|
243
|
+
return (
|
|
244
|
+
shape !== PcbPadMaskApertureRenderer.#PAD_SHAPE_RECTANGULAR &&
|
|
245
|
+
Math.abs(aperture.size.width - aperture.size.height) < 0.001
|
|
246
|
+
)
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Resolves the side-specific pad shape code.
|
|
251
|
+
* @param {object} aperture Aperture descriptor.
|
|
252
|
+
* @returns {number}
|
|
253
|
+
*/
|
|
254
|
+
static #shapeForAperture(aperture) {
|
|
255
|
+
const side = aperture.spec.side === 'bottom' ? 'Bottom' : 'Top'
|
|
256
|
+
if (
|
|
257
|
+
side === 'Top' &&
|
|
258
|
+
aperture.pad?.hasRoundedRect &&
|
|
259
|
+
Number.isInteger(aperture.pad.roundedRectShapeTop)
|
|
260
|
+
) {
|
|
261
|
+
return Number(aperture.pad.roundedRectShapeTop)
|
|
262
|
+
}
|
|
263
|
+
return Number(aperture.pad?.['shape' + side] || 0)
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Resolves rectangle corner radius for rounded pad shapes.
|
|
268
|
+
* @param {object} aperture Aperture descriptor.
|
|
269
|
+
* @returns {number}
|
|
270
|
+
*/
|
|
271
|
+
static #cornerRadius(aperture) {
|
|
272
|
+
if (
|
|
273
|
+
aperture.spec.side === 'top' &&
|
|
274
|
+
aperture.pad?.hasRoundedRect &&
|
|
275
|
+
Number.isFinite(aperture.pad.cornerRadiusTop)
|
|
276
|
+
) {
|
|
277
|
+
return (
|
|
278
|
+
Math.min(aperture.size.width, aperture.size.height) *
|
|
279
|
+
(Number(aperture.pad.cornerRadiusTop) / 100)
|
|
280
|
+
)
|
|
281
|
+
}
|
|
282
|
+
if (PcbPadMaskApertureRenderer.#shapeForAperture(aperture) === 1) {
|
|
283
|
+
return Math.min(aperture.size.width, aperture.size.height) / 2
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
return 0
|
|
287
|
+
}
|
|
288
|
+
}
|