circuit-to-canvas 0.0.50 → 0.0.52
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 +10 -4
- package/dist/index.js +2911 -2719
- package/lib/drawer/CircuitToCanvasDrawer.ts +317 -366
- package/lib/drawer/elements/helper-functions/draw-pill.ts +39 -0
- package/lib/drawer/elements/helper-functions/draw-polygon.ts +25 -0
- package/lib/drawer/elements/helper-functions/draw-rounded-rect.ts +34 -0
- package/lib/drawer/elements/helper-functions/index.ts +3 -0
- package/lib/drawer/elements/pcb-board.ts +28 -13
- package/lib/drawer/elements/pcb-hole.ts +56 -338
- package/lib/drawer/elements/pcb-plated-hole.ts +154 -442
- package/lib/drawer/elements/pcb-smtpad.ts +3 -292
- package/lib/drawer/elements/pcb-soldermask/board.ts +44 -0
- package/lib/drawer/elements/pcb-soldermask/cutout.ts +74 -0
- package/lib/drawer/elements/pcb-soldermask/hole.ts +288 -0
- package/lib/drawer/elements/pcb-soldermask/index.ts +140 -0
- package/lib/drawer/elements/pcb-soldermask/plated-hole.ts +365 -0
- package/lib/drawer/elements/pcb-soldermask/smt-pad.ts +354 -0
- package/lib/drawer/elements/pcb-soldermask/via.ts +27 -0
- package/package.json +1 -1
- package/tests/board-snapshot/__snapshots__/usb-c-flashlight-board.snap.png +0 -0
- package/tests/board-snapshot/usb-c-flashlight-board.test.ts +1 -0
- package/tests/elements/__snapshots__/board-with-elements.snap.png +0 -0
- package/tests/elements/__snapshots__/brep-copper-pours.snap.png +0 -0
- package/tests/elements/__snapshots__/custom-outline-board.snap.png +0 -0
- package/tests/elements/__snapshots__/oval-plated-hole.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-board.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-comprehensive-soldermask-margin.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-fabrication-note-dimension.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-hole-soldermask-margin.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-keepout-layer-filter.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-keepout-multiple-layers.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-keepout-rect-and-circle.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-keepout-with-group-id.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-no-soldermask.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-plated-hole-soldermask-margin.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-plated-hole.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-silkscreen-on-component.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-silkscreen-oval.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-smtpad-asymmetric-soldermask-margin.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-smtpad-soldermask-coverage.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-smtpad-soldermask-margin.snap.png +0 -0
- package/tests/elements/__snapshots__/pill-plated-hole.snap.png +0 -0
- package/tests/elements/pcb-board.test.ts +2 -2
- package/tests/elements/pcb-comprehensive-soldermask-margin.test.ts +2 -2
- package/tests/elements/pcb-hole-soldermask-margin.test.ts +155 -2
- package/tests/elements/pcb-keepout-with-group-id.test.ts +1 -1
- package/tests/elements/pcb-no-soldermask.test.ts +1281 -0
- package/tests/elements/pcb-plated-hole-soldermask-margin.test.ts +1 -1
- package/tests/elements/pcb-plated-hole.test.ts +40 -4
- package/tests/elements/pcb-smtpad-asymmetric-soldermask-margin.test.ts +1 -1
- package/tests/elements/pcb-smtpad-soldermask-coverage.test.ts +1 -1
- package/tests/elements/pcb-smtpad-soldermask-margin.test.ts +1 -1
- package/tests/fixtures/getStackedPngSvgComparison.ts +10 -4
|
@@ -1,80 +1,83 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
AnyCircuitElement,
|
|
3
|
-
PcbPlatedHole,
|
|
4
|
-
PcbVia,
|
|
5
|
-
PcbHole,
|
|
6
|
-
PcbSmtPad,
|
|
7
|
-
PcbTrace,
|
|
8
|
-
PcbBoard,
|
|
9
|
-
PcbSilkscreenText,
|
|
10
|
-
PcbSilkscreenRect,
|
|
11
|
-
PcbSilkscreenCircle,
|
|
12
|
-
PcbSilkscreenLine,
|
|
13
|
-
PcbSilkscreenOval,
|
|
14
|
-
PcbSilkscreenPath,
|
|
15
|
-
PcbSilkscreenPill,
|
|
16
|
-
PcbCutout,
|
|
17
3
|
PCBKeepout,
|
|
4
|
+
PcbBoard,
|
|
18
5
|
PcbCopperPour,
|
|
19
6
|
PcbCopperText,
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
PcbNoteRect,
|
|
7
|
+
PcbCutout,
|
|
8
|
+
PcbFabricationNoteDimension,
|
|
23
9
|
PcbFabricationNotePath,
|
|
24
|
-
|
|
25
|
-
|
|
10
|
+
PcbFabricationNoteRect,
|
|
11
|
+
PcbFabricationNoteText,
|
|
12
|
+
PcbHole,
|
|
26
13
|
PcbNoteDimension,
|
|
27
|
-
PcbFabricationNoteDimension,
|
|
28
14
|
PcbNoteLine,
|
|
15
|
+
PcbNotePath,
|
|
16
|
+
PcbNoteRect,
|
|
17
|
+
PcbNoteText,
|
|
18
|
+
PcbPlatedHole,
|
|
29
19
|
PcbRenderLayer,
|
|
20
|
+
PcbSilkscreenCircle,
|
|
21
|
+
PcbSilkscreenLine,
|
|
22
|
+
PcbSilkscreenOval,
|
|
23
|
+
PcbSilkscreenPath,
|
|
24
|
+
PcbSilkscreenPill,
|
|
25
|
+
PcbSilkscreenRect,
|
|
26
|
+
PcbSilkscreenText,
|
|
27
|
+
PcbSmtPad,
|
|
28
|
+
PcbTrace,
|
|
29
|
+
PcbVia,
|
|
30
30
|
} from "circuit-json"
|
|
31
|
+
import type { Matrix } from "transformation-matrix"
|
|
31
32
|
import {
|
|
32
|
-
|
|
33
|
+
applyToPoint,
|
|
33
34
|
compose,
|
|
34
|
-
|
|
35
|
+
identity,
|
|
35
36
|
scale,
|
|
36
|
-
|
|
37
|
+
translate,
|
|
37
38
|
} from "transformation-matrix"
|
|
38
|
-
import { shouldDrawElement } from "./pcb-render-layer-filter"
|
|
39
|
-
import type { Matrix } from "transformation-matrix"
|
|
40
|
-
import {
|
|
41
|
-
type CanvasContext,
|
|
42
|
-
type PcbColorMap,
|
|
43
|
-
type DrawerConfig,
|
|
44
|
-
type CameraBounds,
|
|
45
|
-
DEFAULT_PCB_COLOR_MAP,
|
|
46
|
-
} from "./types"
|
|
47
|
-
import { drawPcbPlatedHole } from "./elements/pcb-plated-hole"
|
|
48
|
-
import { drawPcbVia } from "./elements/pcb-via"
|
|
49
|
-
import { drawPcbHole } from "./elements/pcb-hole"
|
|
50
|
-
import { drawPcbSmtPad } from "./elements/pcb-smtpad"
|
|
51
|
-
import { drawPcbTrace } from "./elements/pcb-trace"
|
|
52
39
|
import { drawPcbBoard } from "./elements/pcb-board"
|
|
53
|
-
import { drawPath } from "./shapes/path"
|
|
54
|
-
import { drawRect } from "./shapes/rect"
|
|
55
|
-
import { drawPcbSilkscreenText } from "./elements/pcb-silkscreen-text"
|
|
56
|
-
import { drawPcbSilkscreenRect } from "./elements/pcb-silkscreen-rect"
|
|
57
|
-
import { drawPcbSilkscreenCircle } from "./elements/pcb-silkscreen-circle"
|
|
58
|
-
import { drawPcbSilkscreenLine } from "./elements/pcb-silkscreen-line"
|
|
59
|
-
import { drawPcbSilkscreenPath } from "./elements/pcb-silkscreen-path"
|
|
60
|
-
import { drawPcbSilkscreenOval } from "./elements/pcb-silkscreen-oval"
|
|
61
|
-
import { drawPcbSilkscreenPill } from "./elements/pcb-silkscreen-pill"
|
|
62
|
-
import { drawPcbCutout } from "./elements/pcb-cutout"
|
|
63
|
-
import { drawPcbKeepout } from "./elements/pcb-keepout"
|
|
64
40
|
import { drawPcbCopperPour } from "./elements/pcb-copper-pour"
|
|
65
41
|
import { drawPcbCopperText } from "./elements/pcb-copper-text"
|
|
66
|
-
import {
|
|
67
|
-
import {
|
|
68
|
-
import { drawPcbNoteRect } from "./elements/pcb-note-rect"
|
|
42
|
+
import { drawPcbCutout } from "./elements/pcb-cutout"
|
|
43
|
+
import { drawPcbFabricationNoteDimension } from "./elements/pcb-fabrication-note-dimension"
|
|
69
44
|
import { drawPcbFabricationNotePath } from "./elements/pcb-fabrication-note-path"
|
|
70
|
-
import {
|
|
71
|
-
import {
|
|
45
|
+
import { drawPcbFabricationNoteRect } from "./elements/pcb-fabrication-note-rect"
|
|
46
|
+
import { drawPcbFabricationNoteText } from "./elements/pcb-fabrication-note-text"
|
|
47
|
+
import { drawPcbHole } from "./elements/pcb-hole"
|
|
48
|
+
import { drawPcbKeepout } from "./elements/pcb-keepout"
|
|
72
49
|
import { drawPcbNoteDimension } from "./elements/pcb-note-dimension"
|
|
73
|
-
import { drawPcbFabricationNoteDimension } from "./elements/pcb-fabrication-note-dimension"
|
|
74
50
|
import { drawPcbNoteLine } from "./elements/pcb-note-line"
|
|
51
|
+
import { drawPcbNotePath } from "./elements/pcb-note-path"
|
|
52
|
+
import { drawPcbNoteRect } from "./elements/pcb-note-rect"
|
|
53
|
+
import { drawPcbNoteText } from "./elements/pcb-note-text"
|
|
54
|
+
import { drawPcbPlatedHole } from "./elements/pcb-plated-hole"
|
|
55
|
+
import { drawPcbSilkscreenCircle } from "./elements/pcb-silkscreen-circle"
|
|
56
|
+
import { drawPcbSilkscreenLine } from "./elements/pcb-silkscreen-line"
|
|
57
|
+
import { drawPcbSilkscreenOval } from "./elements/pcb-silkscreen-oval"
|
|
58
|
+
import { drawPcbSilkscreenPath } from "./elements/pcb-silkscreen-path"
|
|
59
|
+
import { drawPcbSilkscreenPill } from "./elements/pcb-silkscreen-pill"
|
|
60
|
+
import { drawPcbSilkscreenRect } from "./elements/pcb-silkscreen-rect"
|
|
61
|
+
import { drawPcbSilkscreenText } from "./elements/pcb-silkscreen-text"
|
|
62
|
+
import { drawPcbSmtPad } from "./elements/pcb-smtpad"
|
|
63
|
+
import { drawPcbSoldermask } from "./elements/pcb-soldermask"
|
|
64
|
+
import { drawPcbTrace } from "./elements/pcb-trace"
|
|
65
|
+
import { drawPcbVia } from "./elements/pcb-via"
|
|
66
|
+
import { shouldDrawElement } from "./pcb-render-layer-filter"
|
|
67
|
+
import {
|
|
68
|
+
type CameraBounds,
|
|
69
|
+
type CanvasContext,
|
|
70
|
+
DEFAULT_PCB_COLOR_MAP,
|
|
71
|
+
type DrawerConfig,
|
|
72
|
+
type PcbColorMap,
|
|
73
|
+
} from "./types"
|
|
75
74
|
|
|
76
75
|
export interface DrawElementsOptions {
|
|
77
76
|
layers?: PcbRenderLayer[]
|
|
77
|
+
/** Whether to render the soldermask layer. Defaults to false. */
|
|
78
|
+
drawSoldermask?: boolean
|
|
79
|
+
/** Whether to render the board material (substrate fill). Defaults to false. */
|
|
80
|
+
drawBoardMaterial?: boolean
|
|
78
81
|
}
|
|
79
82
|
|
|
80
83
|
interface CanvasLike {
|
|
@@ -162,358 +165,306 @@ export class CircuitToCanvasDrawer {
|
|
|
162
165
|
elements: AnyCircuitElement[],
|
|
163
166
|
options: DrawElementsOptions = {},
|
|
164
167
|
): void {
|
|
165
|
-
//
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
)
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
for (const element of elements) {
|
|
185
|
-
if (element.type === "pcb_board") {
|
|
186
|
-
this.drawBoardWithSoldermask(element as PcbBoard)
|
|
187
|
-
} else {
|
|
188
|
-
this.drawElement(element, options)
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
private drawBoardWithSoldermask(board: PcbBoard): void {
|
|
194
|
-
const { width, height, center, outline } = board
|
|
195
|
-
const layer = "top" // Default to top layer for soldermask color
|
|
196
|
-
|
|
197
|
-
// If the board has a custom outline, draw it as a path with soldermask fill
|
|
198
|
-
if (outline && Array.isArray(outline) && outline.length >= 3) {
|
|
199
|
-
const soldermaskColor =
|
|
200
|
-
this.colorMap.soldermask[
|
|
201
|
-
layer as keyof typeof this.colorMap.soldermask
|
|
202
|
-
] ?? this.colorMap.soldermask.top
|
|
203
|
-
|
|
204
|
-
// Draw filled path
|
|
205
|
-
const canvasPoints = outline.map((p) => {
|
|
206
|
-
const [x, y] = applyToPoint(this.realToCanvasMat, [p.x, p.y])
|
|
207
|
-
return { x, y }
|
|
208
|
-
})
|
|
209
|
-
|
|
210
|
-
this.ctx.beginPath()
|
|
211
|
-
const firstPoint = canvasPoints[0]
|
|
212
|
-
if (firstPoint) {
|
|
213
|
-
this.ctx.moveTo(firstPoint.x, firstPoint.y)
|
|
214
|
-
for (let i = 1; i < canvasPoints.length; i++) {
|
|
215
|
-
const point = canvasPoints[i]
|
|
216
|
-
if (point) {
|
|
217
|
-
this.ctx.lineTo(point.x, point.y)
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
this.ctx.closePath()
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
this.ctx.fillStyle = soldermaskColor
|
|
224
|
-
this.ctx.fill()
|
|
225
|
-
|
|
226
|
-
// Draw outline stroke
|
|
227
|
-
drawPath({
|
|
228
|
-
ctx: this.ctx,
|
|
229
|
-
points: outline.map((p) => ({ x: p.x, y: p.y })),
|
|
230
|
-
stroke: this.colorMap.boardOutline,
|
|
231
|
-
strokeWidth: 0.1,
|
|
232
|
-
realToCanvasMat: this.realToCanvasMat,
|
|
233
|
-
closePath: true,
|
|
234
|
-
})
|
|
235
|
-
return
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
// Otherwise draw a rectangle with soldermask fill
|
|
239
|
-
if (width !== undefined && height !== undefined && center) {
|
|
240
|
-
const soldermaskColor =
|
|
241
|
-
this.colorMap.soldermask[
|
|
242
|
-
layer as keyof typeof this.colorMap.soldermask
|
|
243
|
-
] ?? this.colorMap.soldermask.top
|
|
244
|
-
|
|
245
|
-
// Draw filled rectangle
|
|
246
|
-
drawRect({
|
|
247
|
-
ctx: this.ctx,
|
|
248
|
-
center,
|
|
249
|
-
width,
|
|
250
|
-
height,
|
|
251
|
-
fill: soldermaskColor,
|
|
252
|
-
realToCanvasMat: this.realToCanvasMat,
|
|
253
|
-
})
|
|
254
|
-
|
|
255
|
-
// Draw the outline stroke separately using path
|
|
256
|
-
const halfWidth = width / 2
|
|
257
|
-
const halfHeight = height / 2
|
|
258
|
-
const corners = [
|
|
259
|
-
{ x: center.x - halfWidth, y: center.y - halfHeight },
|
|
260
|
-
{ x: center.x + halfWidth, y: center.y - halfHeight },
|
|
261
|
-
{ x: center.x + halfWidth, y: center.y + halfHeight },
|
|
262
|
-
{ x: center.x - halfWidth, y: center.y + halfHeight },
|
|
263
|
-
]
|
|
264
|
-
|
|
265
|
-
drawPath({
|
|
266
|
-
ctx: this.ctx,
|
|
267
|
-
points: corners,
|
|
268
|
-
stroke: this.colorMap.boardOutline,
|
|
269
|
-
strokeWidth: 0.1,
|
|
270
|
-
realToCanvasMat: this.realToCanvasMat,
|
|
271
|
-
closePath: true,
|
|
272
|
-
})
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
private drawElement(
|
|
277
|
-
element: AnyCircuitElement,
|
|
278
|
-
options: DrawElementsOptions,
|
|
279
|
-
): void {
|
|
280
|
-
// Check if element should be drawn based on layer options
|
|
281
|
-
if (!shouldDrawElement(element, options)) {
|
|
282
|
-
return
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
if (element.type === "pcb_plated_hole") {
|
|
286
|
-
drawPcbPlatedHole({
|
|
168
|
+
// Find the board element
|
|
169
|
+
const board = elements.find((el) => el.type === "pcb_board") as
|
|
170
|
+
| PcbBoard
|
|
171
|
+
| undefined
|
|
172
|
+
|
|
173
|
+
// Drawing order:
|
|
174
|
+
// 1. Board outline (just the outline stroke, no fill)
|
|
175
|
+
// 2. Copper elements underneath soldermask (pads, copper text)
|
|
176
|
+
// 3. Soldermask (covers everything except openings)
|
|
177
|
+
// 4. Silkscreen (on soldermask, under top copper layers)
|
|
178
|
+
// 5. Copper pour and traces (drawn on top of soldermask and silkscreen)
|
|
179
|
+
// 6. Plated holes, vias (copper ring + drill hole on top of soldermask)
|
|
180
|
+
// 7. Holes and cutouts (punch through everything)
|
|
181
|
+
// 8. Other annotations
|
|
182
|
+
|
|
183
|
+
// Step 1: Draw board outline
|
|
184
|
+
if (board) {
|
|
185
|
+
drawPcbBoard({
|
|
287
186
|
ctx: this.ctx,
|
|
288
|
-
|
|
187
|
+
board,
|
|
289
188
|
realToCanvasMat: this.realToCanvasMat,
|
|
290
189
|
colorMap: this.colorMap,
|
|
190
|
+
drawBoardMaterial: options.drawBoardMaterial ?? false,
|
|
291
191
|
})
|
|
292
192
|
}
|
|
293
193
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
194
|
+
// Step 2: Draw copper elements underneath soldermask (pads, copper text)
|
|
195
|
+
for (const element of elements) {
|
|
196
|
+
if (!shouldDrawElement(element, options)) continue
|
|
197
|
+
|
|
198
|
+
if (element.type === "pcb_smtpad") {
|
|
199
|
+
drawPcbSmtPad({
|
|
200
|
+
ctx: this.ctx,
|
|
201
|
+
pad: element as PcbSmtPad,
|
|
202
|
+
realToCanvasMat: this.realToCanvasMat,
|
|
203
|
+
colorMap: this.colorMap,
|
|
204
|
+
})
|
|
205
|
+
}
|
|
302
206
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
207
|
+
if (element.type === "pcb_copper_text") {
|
|
208
|
+
drawPcbCopperText({
|
|
209
|
+
ctx: this.ctx,
|
|
210
|
+
text: element as PcbCopperText,
|
|
211
|
+
realToCanvasMat: this.realToCanvasMat,
|
|
212
|
+
colorMap: this.colorMap,
|
|
213
|
+
})
|
|
214
|
+
}
|
|
310
215
|
}
|
|
311
216
|
|
|
312
|
-
|
|
313
|
-
|
|
217
|
+
// Step 3: Draw soldermask layer (only if showSoldermask is true)
|
|
218
|
+
const drawSoldermask = options.drawSoldermask ?? false
|
|
219
|
+
if (board) {
|
|
220
|
+
drawPcbSoldermask({
|
|
314
221
|
ctx: this.ctx,
|
|
315
|
-
|
|
222
|
+
board,
|
|
223
|
+
elements,
|
|
316
224
|
realToCanvasMat: this.realToCanvasMat,
|
|
317
225
|
colorMap: this.colorMap,
|
|
226
|
+
layer: "top",
|
|
227
|
+
drawSoldermask,
|
|
318
228
|
})
|
|
319
229
|
}
|
|
320
230
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
231
|
+
// Step 4: Draw silkscreen (on soldermask, under top copper layers)
|
|
232
|
+
for (const element of elements) {
|
|
233
|
+
if (!shouldDrawElement(element, options)) continue
|
|
234
|
+
|
|
235
|
+
if (element.type === "pcb_silkscreen_text") {
|
|
236
|
+
drawPcbSilkscreenText({
|
|
237
|
+
ctx: this.ctx,
|
|
238
|
+
text: element as PcbSilkscreenText,
|
|
239
|
+
realToCanvasMat: this.realToCanvasMat,
|
|
240
|
+
colorMap: this.colorMap,
|
|
241
|
+
})
|
|
242
|
+
}
|
|
329
243
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
244
|
+
if (element.type === "pcb_silkscreen_rect") {
|
|
245
|
+
drawPcbSilkscreenRect({
|
|
246
|
+
ctx: this.ctx,
|
|
247
|
+
rect: element as PcbSilkscreenRect,
|
|
248
|
+
realToCanvasMat: this.realToCanvasMat,
|
|
249
|
+
colorMap: this.colorMap,
|
|
250
|
+
})
|
|
251
|
+
}
|
|
338
252
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
253
|
+
if (element.type === "pcb_silkscreen_circle") {
|
|
254
|
+
drawPcbSilkscreenCircle({
|
|
255
|
+
ctx: this.ctx,
|
|
256
|
+
circle: element as PcbSilkscreenCircle,
|
|
257
|
+
realToCanvasMat: this.realToCanvasMat,
|
|
258
|
+
colorMap: this.colorMap,
|
|
259
|
+
})
|
|
260
|
+
}
|
|
347
261
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
262
|
+
if (element.type === "pcb_silkscreen_line") {
|
|
263
|
+
drawPcbSilkscreenLine({
|
|
264
|
+
ctx: this.ctx,
|
|
265
|
+
line: element as PcbSilkscreenLine,
|
|
266
|
+
realToCanvasMat: this.realToCanvasMat,
|
|
267
|
+
colorMap: this.colorMap,
|
|
268
|
+
})
|
|
269
|
+
}
|
|
356
270
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
271
|
+
if (element.type === "pcb_silkscreen_path") {
|
|
272
|
+
drawPcbSilkscreenPath({
|
|
273
|
+
ctx: this.ctx,
|
|
274
|
+
path: element as PcbSilkscreenPath,
|
|
275
|
+
realToCanvasMat: this.realToCanvasMat,
|
|
276
|
+
colorMap: this.colorMap,
|
|
277
|
+
})
|
|
278
|
+
}
|
|
365
279
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
280
|
+
if (element.type === "pcb_silkscreen_pill") {
|
|
281
|
+
drawPcbSilkscreenPill({
|
|
282
|
+
ctx: this.ctx,
|
|
283
|
+
pill: element as PcbSilkscreenPill,
|
|
284
|
+
realToCanvasMat: this.realToCanvasMat,
|
|
285
|
+
colorMap: this.colorMap,
|
|
286
|
+
})
|
|
287
|
+
}
|
|
374
288
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
289
|
+
if (element.type === "pcb_silkscreen_oval") {
|
|
290
|
+
drawPcbSilkscreenOval({
|
|
291
|
+
ctx: this.ctx,
|
|
292
|
+
oval: element as PcbSilkscreenOval,
|
|
293
|
+
realToCanvasMat: this.realToCanvasMat,
|
|
294
|
+
colorMap: this.colorMap,
|
|
295
|
+
})
|
|
296
|
+
}
|
|
382
297
|
}
|
|
383
298
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
299
|
+
// Step 5: Draw copper pour and traces (on top of soldermask and silkscreen)
|
|
300
|
+
for (const element of elements) {
|
|
301
|
+
if (!shouldDrawElement(element, options)) continue
|
|
302
|
+
|
|
303
|
+
if (element.type === "pcb_copper_pour") {
|
|
304
|
+
drawPcbCopperPour({
|
|
305
|
+
ctx: this.ctx,
|
|
306
|
+
pour: element as PcbCopperPour,
|
|
307
|
+
realToCanvasMat: this.realToCanvasMat,
|
|
308
|
+
colorMap: this.colorMap,
|
|
309
|
+
})
|
|
310
|
+
}
|
|
392
311
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
312
|
+
if (element.type === "pcb_trace") {
|
|
313
|
+
drawPcbTrace({
|
|
314
|
+
ctx: this.ctx,
|
|
315
|
+
trace: element as PcbTrace,
|
|
316
|
+
realToCanvasMat: this.realToCanvasMat,
|
|
317
|
+
colorMap: this.colorMap,
|
|
318
|
+
})
|
|
319
|
+
}
|
|
400
320
|
}
|
|
401
321
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
322
|
+
// Step 6: Draw plated holes, vias (copper ring + drill hole on top of soldermask)
|
|
323
|
+
for (const element of elements) {
|
|
324
|
+
if (!shouldDrawElement(element, options)) continue
|
|
325
|
+
|
|
326
|
+
if (element.type === "pcb_plated_hole") {
|
|
327
|
+
drawPcbPlatedHole({
|
|
328
|
+
ctx: this.ctx,
|
|
329
|
+
hole: element as PcbPlatedHole,
|
|
330
|
+
realToCanvasMat: this.realToCanvasMat,
|
|
331
|
+
colorMap: this.colorMap,
|
|
332
|
+
soldermaskMargin: drawSoldermask
|
|
333
|
+
? (element as PcbPlatedHole).soldermask_margin
|
|
334
|
+
: undefined,
|
|
335
|
+
drawSoldermask,
|
|
336
|
+
})
|
|
337
|
+
}
|
|
410
338
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
339
|
+
if (element.type === "pcb_via") {
|
|
340
|
+
drawPcbVia({
|
|
341
|
+
ctx: this.ctx,
|
|
342
|
+
via: element as PcbVia,
|
|
343
|
+
realToCanvasMat: this.realToCanvasMat,
|
|
344
|
+
colorMap: this.colorMap,
|
|
345
|
+
})
|
|
346
|
+
}
|
|
418
347
|
}
|
|
419
348
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
349
|
+
// Step 7: Draw holes and cutouts (these punch through everything)
|
|
350
|
+
for (const element of elements) {
|
|
351
|
+
if (!shouldDrawElement(element, options)) continue
|
|
352
|
+
|
|
353
|
+
if (element.type === "pcb_hole") {
|
|
354
|
+
drawPcbHole({
|
|
355
|
+
ctx: this.ctx,
|
|
356
|
+
hole: element as PcbHole,
|
|
357
|
+
realToCanvasMat: this.realToCanvasMat,
|
|
358
|
+
colorMap: this.colorMap,
|
|
359
|
+
soldermaskMargin: drawSoldermask
|
|
360
|
+
? element.soldermask_margin
|
|
361
|
+
: undefined,
|
|
362
|
+
})
|
|
363
|
+
}
|
|
428
364
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
365
|
+
if (element.type === "pcb_cutout") {
|
|
366
|
+
drawPcbCutout({
|
|
367
|
+
ctx: this.ctx,
|
|
368
|
+
cutout: element as PcbCutout,
|
|
369
|
+
realToCanvasMat: this.realToCanvasMat,
|
|
370
|
+
colorMap: this.colorMap,
|
|
371
|
+
})
|
|
372
|
+
}
|
|
436
373
|
}
|
|
437
374
|
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
375
|
+
// Step 8: Draw other annotations
|
|
376
|
+
for (const element of elements) {
|
|
377
|
+
if (!shouldDrawElement(element, options)) continue
|
|
378
|
+
|
|
379
|
+
if (element.type === "pcb_keepout") {
|
|
380
|
+
drawPcbKeepout({
|
|
381
|
+
ctx: this.ctx,
|
|
382
|
+
keepout: element as PCBKeepout,
|
|
383
|
+
realToCanvasMat: this.realToCanvasMat,
|
|
384
|
+
colorMap: this.colorMap,
|
|
385
|
+
})
|
|
386
|
+
}
|
|
446
387
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
388
|
+
if (element.type === "pcb_fabrication_note_text") {
|
|
389
|
+
drawPcbFabricationNoteText({
|
|
390
|
+
ctx: this.ctx,
|
|
391
|
+
text: element as PcbFabricationNoteText,
|
|
392
|
+
realToCanvasMat: this.realToCanvasMat,
|
|
393
|
+
colorMap: this.colorMap,
|
|
394
|
+
})
|
|
395
|
+
}
|
|
455
396
|
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
397
|
+
if (element.type === "pcb_fabrication_note_rect") {
|
|
398
|
+
drawPcbFabricationNoteRect({
|
|
399
|
+
ctx: this.ctx,
|
|
400
|
+
rect: element as PcbFabricationNoteRect,
|
|
401
|
+
realToCanvasMat: this.realToCanvasMat,
|
|
402
|
+
colorMap: this.colorMap,
|
|
403
|
+
})
|
|
404
|
+
}
|
|
464
405
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
406
|
+
if (element.type === "pcb_note_rect") {
|
|
407
|
+
drawPcbNoteRect({
|
|
408
|
+
realToCanvasMat: this.realToCanvasMat,
|
|
409
|
+
colorMap: this.colorMap,
|
|
410
|
+
ctx: this.ctx,
|
|
411
|
+
rect: element as PcbNoteRect,
|
|
412
|
+
})
|
|
413
|
+
}
|
|
473
414
|
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
415
|
+
if (element.type === "pcb_fabrication_note_path") {
|
|
416
|
+
drawPcbFabricationNotePath({
|
|
417
|
+
ctx: this.ctx,
|
|
418
|
+
path: element as PcbFabricationNotePath,
|
|
419
|
+
realToCanvasMat: this.realToCanvasMat,
|
|
420
|
+
colorMap: this.colorMap,
|
|
421
|
+
})
|
|
422
|
+
}
|
|
482
423
|
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
424
|
+
if (element.type === "pcb_note_path") {
|
|
425
|
+
drawPcbNotePath({
|
|
426
|
+
ctx: this.ctx,
|
|
427
|
+
path: element as PcbNotePath,
|
|
428
|
+
realToCanvasMat: this.realToCanvasMat,
|
|
429
|
+
colorMap: this.colorMap,
|
|
430
|
+
})
|
|
431
|
+
}
|
|
491
432
|
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
433
|
+
if (element.type === "pcb_note_text") {
|
|
434
|
+
drawPcbNoteText({
|
|
435
|
+
ctx: this.ctx,
|
|
436
|
+
text: element as PcbNoteText,
|
|
437
|
+
realToCanvasMat: this.realToCanvasMat,
|
|
438
|
+
colorMap: this.colorMap,
|
|
439
|
+
})
|
|
440
|
+
}
|
|
500
441
|
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
442
|
+
if (element.type === "pcb_note_line") {
|
|
443
|
+
drawPcbNoteLine({
|
|
444
|
+
ctx: this.ctx,
|
|
445
|
+
line: element as PcbNoteLine,
|
|
446
|
+
realToCanvasMat: this.realToCanvasMat,
|
|
447
|
+
colorMap: this.colorMap,
|
|
448
|
+
})
|
|
449
|
+
}
|
|
509
450
|
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
451
|
+
if (element.type === "pcb_note_dimension") {
|
|
452
|
+
drawPcbNoteDimension({
|
|
453
|
+
ctx: this.ctx,
|
|
454
|
+
pcbNoteDimension: element as PcbNoteDimension,
|
|
455
|
+
realToCanvasMat: this.realToCanvasMat,
|
|
456
|
+
colorMap: this.colorMap,
|
|
457
|
+
})
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
if (element.type === "pcb_fabrication_note_dimension") {
|
|
461
|
+
drawPcbFabricationNoteDimension({
|
|
462
|
+
ctx: this.ctx,
|
|
463
|
+
pcbFabricationNoteDimension: element as PcbFabricationNoteDimension,
|
|
464
|
+
realToCanvasMat: this.realToCanvasMat,
|
|
465
|
+
colorMap: this.colorMap,
|
|
466
|
+
})
|
|
467
|
+
}
|
|
517
468
|
}
|
|
518
469
|
}
|
|
519
470
|
}
|