circuit-to-canvas 0.0.65 → 0.0.67

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/dist/index.d.ts CHANGED
@@ -69,7 +69,10 @@ interface PcbColorMap {
69
69
  bottom: string;
70
70
  };
71
71
  substrate: string;
72
- courtyard: string;
72
+ courtyard: {
73
+ top: string;
74
+ bottom: string;
75
+ };
73
76
  keepout: string;
74
77
  fabricationNote: string;
75
78
  }
package/dist/index.js CHANGED
@@ -674,13 +674,16 @@ function drawCircle(params) {
674
674
  }
675
675
 
676
676
  // lib/drawer/elements/pcb-courtyard-circle.ts
677
+ function layerToCourtyardColor(layer, colorMap) {
678
+ return layer === "bottom" ? colorMap.courtyard.bottom : colorMap.courtyard.top;
679
+ }
677
680
  function drawPcbCourtyardCircle(params) {
678
681
  const { ctx, circle, realToCanvasMat, colorMap } = params;
679
682
  drawCircle({
680
683
  ctx,
681
684
  center: circle.center,
682
685
  radius: circle.radius,
683
- stroke: colorMap.courtyard,
686
+ stroke: layerToCourtyardColor(circle.layer, colorMap),
684
687
  strokeWidth: 0.05,
685
688
  // Default thin line for courtyard info
686
689
  realToCanvasMat
@@ -688,6 +691,9 @@ function drawPcbCourtyardCircle(params) {
688
691
  }
689
692
 
690
693
  // lib/drawer/elements/pcb-courtyard-rect.ts
694
+ function layerToCourtyardColor2(layer, colorMap) {
695
+ return layer === "bottom" ? colorMap.courtyard.bottom : colorMap.courtyard.top;
696
+ }
691
697
  function drawPcbCourtyardRect(params) {
692
698
  const { ctx, rect, realToCanvasMat, colorMap } = params;
693
699
  drawRect({
@@ -695,7 +701,7 @@ function drawPcbCourtyardRect(params) {
695
701
  center: rect.center,
696
702
  width: rect.width,
697
703
  height: rect.height,
698
- stroke: colorMap.courtyard,
704
+ stroke: layerToCourtyardColor2(rect.layer, colorMap),
699
705
  strokeWidth: 0.05,
700
706
  // Default thin line for courtyard info
701
707
  realToCanvasMat
@@ -3038,103 +3044,6 @@ function drawNegativeMarginRingForPad(params) {
3038
3044
  }
3039
3045
  }
3040
3046
 
3041
- // lib/drawer/elements/pcb-soldermask/via.ts
3042
- import { applyToPoint as applyToPoint21 } from "transformation-matrix";
3043
- function processViaSoldermask(params) {
3044
- const { ctx, via, realToCanvasMat, colorMap } = params;
3045
- const [cx, cy] = applyToPoint21(realToCanvasMat, [via.x, via.y]);
3046
- const scaledRadius = via.outer_diameter / 2 * Math.abs(realToCanvasMat.a);
3047
- ctx.fillStyle = colorMap.substrate;
3048
- ctx.beginPath();
3049
- ctx.arc(cx, cy, scaledRadius, 0, Math.PI * 2);
3050
- ctx.closePath();
3051
- ctx.fill();
3052
- }
3053
-
3054
- // lib/drawer/elements/pcb-soldermask/index.ts
3055
- function drawPcbSoldermask(params) {
3056
- const {
3057
- ctx,
3058
- board,
3059
- elements,
3060
- realToCanvasMat,
3061
- colorMap,
3062
- layer,
3063
- drawSoldermask
3064
- } = params;
3065
- const soldermaskColor = colorMap.soldermask[layer] ?? colorMap.soldermask.top;
3066
- const soldermaskOverCopperColor = colorMap.soldermaskOverCopper[layer] ?? colorMap.soldermaskOverCopper.top;
3067
- if (drawSoldermask) {
3068
- drawBoardSoldermask({ ctx, board, realToCanvasMat, soldermaskColor });
3069
- }
3070
- for (const element of elements) {
3071
- processElementSoldermask({
3072
- ctx,
3073
- element,
3074
- realToCanvasMat,
3075
- colorMap,
3076
- soldermaskOverCopperColor,
3077
- layer,
3078
- drawSoldermask
3079
- });
3080
- }
3081
- }
3082
- function processElementSoldermask(params) {
3083
- const {
3084
- ctx,
3085
- element,
3086
- realToCanvasMat,
3087
- colorMap,
3088
- soldermaskOverCopperColor,
3089
- layer,
3090
- drawSoldermask
3091
- } = params;
3092
- if (element.type === "pcb_smtpad") {
3093
- processSmtPadSoldermask({
3094
- ctx,
3095
- pad: element,
3096
- realToCanvasMat,
3097
- colorMap,
3098
- soldermaskOverCopperColor,
3099
- layer,
3100
- drawSoldermask
3101
- });
3102
- } else if (element.type === "pcb_plated_hole") {
3103
- processPlatedHoleSoldermask({
3104
- ctx,
3105
- hole: element,
3106
- realToCanvasMat,
3107
- colorMap,
3108
- soldermaskOverCopperColor,
3109
- layer,
3110
- drawSoldermask
3111
- });
3112
- } else if (element.type === "pcb_hole") {
3113
- processHoleSoldermask({
3114
- ctx,
3115
- hole: element,
3116
- realToCanvasMat,
3117
- colorMap,
3118
- soldermaskOverCopperColor,
3119
- drawSoldermask
3120
- });
3121
- } else if (element.type === "pcb_via") {
3122
- processViaSoldermask({
3123
- ctx,
3124
- via: element,
3125
- realToCanvasMat,
3126
- colorMap
3127
- });
3128
- } else if (element.type === "pcb_cutout") {
3129
- processCutoutSoldermask({
3130
- ctx,
3131
- cutout: element,
3132
- realToCanvasMat,
3133
- colorMap
3134
- });
3135
- }
3136
- }
3137
-
3138
3047
  // lib/drawer/elements/pcb-trace/normalize-trace-direction.ts
3139
3048
  function normalizeTraceDirection(x, y) {
3140
3049
  const length = Math.hypot(x, y);
@@ -3254,6 +3163,163 @@ function hasVariableWidth(points) {
3254
3163
  );
3255
3164
  }
3256
3165
 
3166
+ // lib/drawer/elements/pcb-soldermask/trace.ts
3167
+ function processTraceSoldermask(params) {
3168
+ const {
3169
+ ctx,
3170
+ trace,
3171
+ realToCanvasMat,
3172
+ soldermaskOverCopperColor,
3173
+ layer,
3174
+ drawSoldermask
3175
+ } = params;
3176
+ if (!drawSoldermask) return;
3177
+ if (!trace.route || !Array.isArray(trace.route) || trace.route.length < 2) {
3178
+ return;
3179
+ }
3180
+ const segments = collectTraceSegments(trace.route);
3181
+ for (const segment of segments) {
3182
+ const segmentLayer = segment[0]?.layer;
3183
+ if (segmentLayer !== layer) continue;
3184
+ if (hasVariableWidth(segment)) {
3185
+ const polygonPoints = buildTracePolygon(segment);
3186
+ drawPolygon({
3187
+ ctx,
3188
+ points: polygonPoints,
3189
+ fill: soldermaskOverCopperColor,
3190
+ realToCanvasMat
3191
+ });
3192
+ continue;
3193
+ }
3194
+ for (let i = 0; i < segment.length - 1; i++) {
3195
+ const start = segment[i];
3196
+ const end = segment[i + 1];
3197
+ if (!start || !end) continue;
3198
+ drawLine({
3199
+ ctx,
3200
+ start: { x: start.x, y: start.y },
3201
+ end: { x: end.x, y: end.y },
3202
+ strokeWidth: start.width,
3203
+ stroke: soldermaskOverCopperColor,
3204
+ realToCanvasMat,
3205
+ lineCap: "round"
3206
+ });
3207
+ }
3208
+ }
3209
+ }
3210
+
3211
+ // lib/drawer/elements/pcb-soldermask/via.ts
3212
+ import { applyToPoint as applyToPoint21 } from "transformation-matrix";
3213
+ function processViaSoldermask(params) {
3214
+ const { ctx, via, realToCanvasMat, colorMap } = params;
3215
+ const [cx, cy] = applyToPoint21(realToCanvasMat, [via.x, via.y]);
3216
+ const scaledRadius = via.outer_diameter / 2 * Math.abs(realToCanvasMat.a);
3217
+ ctx.fillStyle = colorMap.substrate;
3218
+ ctx.beginPath();
3219
+ ctx.arc(cx, cy, scaledRadius, 0, Math.PI * 2);
3220
+ ctx.closePath();
3221
+ ctx.fill();
3222
+ }
3223
+
3224
+ // lib/drawer/elements/pcb-soldermask/index.ts
3225
+ function drawPcbSoldermask(params) {
3226
+ const {
3227
+ ctx,
3228
+ board,
3229
+ elements,
3230
+ realToCanvasMat,
3231
+ colorMap,
3232
+ layer,
3233
+ drawSoldermask
3234
+ } = params;
3235
+ const soldermaskColor = colorMap.soldermask[layer] ?? colorMap.soldermask.top;
3236
+ const soldermaskOverCopperColor = colorMap.soldermaskOverCopper[layer] ?? colorMap.soldermaskOverCopper.top;
3237
+ if (drawSoldermask) {
3238
+ drawBoardSoldermask({ ctx, board, realToCanvasMat, soldermaskColor });
3239
+ }
3240
+ if (drawSoldermask) {
3241
+ for (const element of elements) {
3242
+ if (element.type !== "pcb_trace") continue;
3243
+ processTraceSoldermask({
3244
+ ctx,
3245
+ trace: element,
3246
+ realToCanvasMat,
3247
+ soldermaskOverCopperColor,
3248
+ layer,
3249
+ drawSoldermask
3250
+ });
3251
+ }
3252
+ }
3253
+ for (const element of elements) {
3254
+ processElementSoldermask({
3255
+ ctx,
3256
+ element,
3257
+ realToCanvasMat,
3258
+ colorMap,
3259
+ soldermaskOverCopperColor,
3260
+ layer,
3261
+ drawSoldermask
3262
+ });
3263
+ }
3264
+ }
3265
+ function processElementSoldermask(params) {
3266
+ const {
3267
+ ctx,
3268
+ element,
3269
+ realToCanvasMat,
3270
+ colorMap,
3271
+ soldermaskOverCopperColor,
3272
+ layer,
3273
+ drawSoldermask
3274
+ } = params;
3275
+ if (element.type === "pcb_smtpad") {
3276
+ processSmtPadSoldermask({
3277
+ ctx,
3278
+ pad: element,
3279
+ realToCanvasMat,
3280
+ colorMap,
3281
+ soldermaskOverCopperColor,
3282
+ layer,
3283
+ drawSoldermask
3284
+ });
3285
+ } else if (element.type === "pcb_plated_hole") {
3286
+ processPlatedHoleSoldermask({
3287
+ ctx,
3288
+ hole: element,
3289
+ realToCanvasMat,
3290
+ colorMap,
3291
+ soldermaskOverCopperColor,
3292
+ layer,
3293
+ drawSoldermask
3294
+ });
3295
+ } else if (element.type === "pcb_hole") {
3296
+ processHoleSoldermask({
3297
+ ctx,
3298
+ hole: element,
3299
+ realToCanvasMat,
3300
+ colorMap,
3301
+ soldermaskOverCopperColor,
3302
+ drawSoldermask
3303
+ });
3304
+ } else if (element.type === "pcb_via") {
3305
+ processViaSoldermask({
3306
+ ctx,
3307
+ via: element,
3308
+ realToCanvasMat,
3309
+ colorMap
3310
+ });
3311
+ } else if (element.type === "pcb_cutout") {
3312
+ processCutoutSoldermask({
3313
+ ctx,
3314
+ cutout: element,
3315
+ realToCanvasMat,
3316
+ colorMap
3317
+ });
3318
+ } else if (element.type === "pcb_trace") {
3319
+ return;
3320
+ }
3321
+ }
3322
+
3257
3323
  // lib/drawer/elements/pcb-trace/layer-to-color.ts
3258
3324
  function layerToColor4(layer, colorMap) {
3259
3325
  return colorMap.copper[layer] ?? colorMap.copper.top;
@@ -3360,7 +3426,10 @@ var DEFAULT_PCB_COLOR_MAP = {
3360
3426
  bottom: "#5da9e9"
3361
3427
  },
3362
3428
  boardOutline: "rgba(255, 255, 255, 0.5)",
3363
- courtyard: "#FF00FF",
3429
+ courtyard: {
3430
+ top: "#FF00FF",
3431
+ bottom: "rgb(38, 233, 255)"
3432
+ },
3364
3433
  keepout: "#FF6B6B",
3365
3434
  // Red color for keepout zones
3366
3435
  fabricationNote: "rgba(255, 255, 255, 0.5)"
@@ -3550,7 +3619,7 @@ var CircuitToCanvasDrawer = class {
3550
3619
  colorMap: this.colorMap
3551
3620
  });
3552
3621
  }
3553
- if (element.type === "pcb_trace") {
3622
+ if (element.type === "pcb_trace" && (!drawSoldermask || !board)) {
3554
3623
  drawPcbTrace({
3555
3624
  ctx: this.ctx,
3556
3625
  trace: element,
@@ -332,7 +332,7 @@ export class CircuitToCanvasDrawer {
332
332
  })
333
333
  }
334
334
 
335
- if (element.type === "pcb_trace") {
335
+ if (element.type === "pcb_trace" && (!drawSoldermask || !board)) {
336
336
  drawPcbTrace({
337
337
  ctx: this.ctx,
338
338
  trace: element as PcbTrace,
@@ -10,6 +10,10 @@ export interface DrawPcbCourtyardCircleParams {
10
10
  colorMap: PcbColorMap
11
11
  }
12
12
 
13
+ function layerToCourtyardColor(layer: string, colorMap: PcbColorMap): string {
14
+ return layer === "bottom" ? colorMap.courtyard.bottom : colorMap.courtyard.top
15
+ }
16
+
13
17
  export function drawPcbCourtyardCircle(
14
18
  params: DrawPcbCourtyardCircleParams,
15
19
  ): void {
@@ -19,7 +23,7 @@ export function drawPcbCourtyardCircle(
19
23
  ctx,
20
24
  center: circle.center,
21
25
  radius: circle.radius,
22
- stroke: colorMap.courtyard,
26
+ stroke: layerToCourtyardColor(circle.layer, colorMap),
23
27
  strokeWidth: 0.05, // Default thin line for courtyard info
24
28
  realToCanvasMat,
25
29
  })
@@ -10,6 +10,10 @@ export interface DrawPcbCourtyardRectParams {
10
10
  colorMap: PcbColorMap
11
11
  }
12
12
 
13
+ function layerToCourtyardColor(layer: string, colorMap: PcbColorMap): string {
14
+ return layer === "bottom" ? colorMap.courtyard.bottom : colorMap.courtyard.top
15
+ }
16
+
13
17
  export function drawPcbCourtyardRect(params: DrawPcbCourtyardRectParams): void {
14
18
  const { ctx, rect, realToCanvasMat, colorMap } = params
15
19
 
@@ -18,7 +22,7 @@ export function drawPcbCourtyardRect(params: DrawPcbCourtyardRectParams): void {
18
22
  center: rect.center,
19
23
  width: rect.width,
20
24
  height: rect.height,
21
- stroke: colorMap.courtyard,
25
+ stroke: layerToCourtyardColor(rect.layer, colorMap),
22
26
  strokeWidth: 0.05, // Default thin line for courtyard info
23
27
  realToCanvasMat,
24
28
  })
@@ -6,6 +6,7 @@ import { processCutoutSoldermask } from "./cutout"
6
6
  import { processHoleSoldermask } from "./hole"
7
7
  import { processPlatedHoleSoldermask } from "./plated-hole"
8
8
  import { processSmtPadSoldermask } from "./smt-pad"
9
+ import { processTraceSoldermask } from "./trace"
9
10
  import { processViaSoldermask } from "./via"
10
11
 
11
12
  export interface DrawPcbSoldermaskParams {
@@ -56,7 +57,22 @@ export function drawPcbSoldermask(params: DrawPcbSoldermaskParams): void {
56
57
  drawBoardSoldermask({ ctx, board, realToCanvasMat, soldermaskColor })
57
58
  }
58
59
 
59
- // Step 2: Process each element - draw cutouts and light green areas as needed
60
+ // Step 2: Draw soldermask over traces first so pads can open over them.
61
+ if (drawSoldermask) {
62
+ for (const element of elements) {
63
+ if (element.type !== "pcb_trace") continue
64
+ processTraceSoldermask({
65
+ ctx,
66
+ trace: element,
67
+ realToCanvasMat,
68
+ soldermaskOverCopperColor,
69
+ layer,
70
+ drawSoldermask,
71
+ })
72
+ }
73
+ }
74
+
75
+ // Step 3: Process remaining elements - draw cutouts and openings as needed
60
76
  for (const element of elements) {
61
77
  processElementSoldermask({
62
78
  ctx,
@@ -136,5 +152,7 @@ function processElementSoldermask(params: {
136
152
  realToCanvasMat,
137
153
  colorMap,
138
154
  })
155
+ } else if (element.type === "pcb_trace") {
156
+ return
139
157
  }
140
158
  }
@@ -0,0 +1,65 @@
1
+ import type { PcbTrace } from "circuit-json"
2
+ import type { Matrix } from "transformation-matrix"
3
+ import type { CanvasContext } from "../../types"
4
+ import { drawLine } from "../../shapes/line"
5
+ import { drawPolygon } from "../../shapes/polygon"
6
+ import { buildTracePolygon } from "../pcb-trace/build-trace-polygon"
7
+ import { collectTraceSegments } from "../pcb-trace/collect-trace-segments"
8
+ import { hasVariableWidth } from "../pcb-trace/has-variable-width"
9
+
10
+ export function processTraceSoldermask(params: {
11
+ ctx: CanvasContext
12
+ trace: PcbTrace
13
+ realToCanvasMat: Matrix
14
+ soldermaskOverCopperColor: string
15
+ layer: "top" | "bottom"
16
+ drawSoldermask: boolean
17
+ }): void {
18
+ const {
19
+ ctx,
20
+ trace,
21
+ realToCanvasMat,
22
+ soldermaskOverCopperColor,
23
+ layer,
24
+ drawSoldermask,
25
+ } = params
26
+
27
+ if (!drawSoldermask) return
28
+ if (!trace.route || !Array.isArray(trace.route) || trace.route.length < 2) {
29
+ return
30
+ }
31
+
32
+ const segments = collectTraceSegments(trace.route)
33
+
34
+ for (const segment of segments) {
35
+ const segmentLayer = segment[0]?.layer
36
+ if (segmentLayer !== layer) continue
37
+
38
+ if (hasVariableWidth(segment)) {
39
+ const polygonPoints = buildTracePolygon(segment)
40
+ drawPolygon({
41
+ ctx,
42
+ points: polygonPoints,
43
+ fill: soldermaskOverCopperColor,
44
+ realToCanvasMat,
45
+ })
46
+ continue
47
+ }
48
+
49
+ for (let i = 0; i < segment.length - 1; i++) {
50
+ const start = segment[i]
51
+ const end = segment[i + 1]
52
+ if (!start || !end) continue
53
+
54
+ drawLine({
55
+ ctx,
56
+ start: { x: start.x, y: start.y },
57
+ end: { x: end.x, y: end.y },
58
+ strokeWidth: start.width,
59
+ stroke: soldermaskOverCopperColor,
60
+ realToCanvasMat,
61
+ lineCap: "round",
62
+ })
63
+ }
64
+ }
65
+ }
@@ -91,7 +91,10 @@ export interface PcbColorMap {
91
91
  bottom: string
92
92
  }
93
93
  substrate: string
94
- courtyard: string
94
+ courtyard: {
95
+ top: string
96
+ bottom: string
97
+ }
95
98
  keepout: string
96
99
  fabricationNote: string
97
100
  }
@@ -126,7 +129,10 @@ export const DEFAULT_PCB_COLOR_MAP: PcbColorMap = {
126
129
  bottom: "#5da9e9",
127
130
  },
128
131
  boardOutline: "rgba(255, 255, 255, 0.5)",
129
- courtyard: "#FF00FF",
132
+ courtyard: {
133
+ top: "#FF00FF",
134
+ bottom: "rgb(38, 233, 255)",
135
+ },
130
136
  keepout: "#FF6B6B", // Red color for keepout zones
131
137
  fabricationNote: "rgba(255, 255, 255, 0.5)",
132
138
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "circuit-to-canvas",
3
3
  "main": "dist/index.js",
4
- "version": "0.0.65",
4
+ "version": "0.0.67",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "build": "tsup-node ./lib/index.ts --format esm --dts",
@@ -17,9 +17,9 @@
17
17
  "@tscircuit/math-utils": "^0.0.29",
18
18
  "@types/bun": "latest",
19
19
  "bun-match-svg": "^0.0.14",
20
- "circuit-json": "^0.0.374",
20
+ "circuit-json": "^0.0.375",
21
21
  "circuit-json-to-connectivity-map": "^0.0.23",
22
- "circuit-to-svg": "^0.0.323",
22
+ "circuit-to-svg": "^0.0.324",
23
23
  "looks-same": "^10.0.1",
24
24
  "schematic-symbols": "^0.0.202",
25
25
  "tsup": "^8.5.1"