circuit-to-canvas 0.0.1 → 0.0.2
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/.github/workflows/bun-formatcheck.yml +26 -0
- package/.github/workflows/bun-pver-release.yml +77 -0
- package/.github/workflows/bun-test.yml +31 -0
- package/.github/workflows/bun-typecheck.yml +26 -0
- package/LICENSE +21 -0
- package/README.md +2 -0
- package/dist/index.d.ts +146 -2
- package/dist/index.js +620 -0
- package/lib/drawer/CircuitToCanvasDrawer.ts +138 -1
- package/lib/drawer/elements/index.ts +30 -0
- package/lib/drawer/elements/pcb-board.ts +62 -0
- package/lib/drawer/elements/pcb-copper-pour.ts +84 -0
- package/lib/drawer/elements/pcb-cutout.ts +53 -0
- package/lib/drawer/elements/pcb-hole.ts +90 -0
- package/lib/drawer/elements/pcb-silkscreen.ts +171 -0
- package/lib/drawer/elements/pcb-smtpad.ts +108 -0
- package/lib/drawer/elements/pcb-trace.ts +59 -0
- package/lib/drawer/elements/pcb-via.ts +33 -0
- package/lib/drawer/shapes/index.ts +3 -0
- package/lib/drawer/shapes/line.ts +37 -0
- package/lib/drawer/shapes/path.ts +61 -0
- package/lib/drawer/shapes/polygon.ts +38 -0
- package/lib/drawer/types.ts +16 -0
- package/package.json +2 -2
- package/tests/elements/__snapshots__/board-with-elements.snap.png +0 -0
- package/tests/elements/__snapshots__/bottom-layer-pad.snap.png +0 -0
- package/tests/elements/__snapshots__/bottom-layer-trace.snap.png +0 -0
- package/tests/elements/__snapshots__/circular-cutout.snap.png +0 -0
- package/tests/elements/__snapshots__/circular-pad.snap.png +0 -0
- package/tests/elements/__snapshots__/copper-pour-with-trace.snap.png +0 -0
- package/tests/elements/__snapshots__/custom-outline-board.snap.png +0 -0
- package/tests/elements/__snapshots__/multi-segment-trace.snap.png +0 -0
- package/tests/elements/__snapshots__/multiple-traces.snap.png +0 -0
- package/tests/elements/__snapshots__/multiple-vias.snap.png +0 -0
- package/tests/elements/__snapshots__/oval-hole.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-board.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-copper-pour.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-cutout.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-hole.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-silkscreen.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-smtpad.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-trace.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-via.snap.png +0 -0
- package/tests/elements/__snapshots__/pill-hole.snap.png +0 -0
- package/tests/elements/__snapshots__/pill-pad.snap.png +0 -0
- package/tests/elements/__snapshots__/polygon-copper-pour.snap.png +0 -0
- package/tests/elements/__snapshots__/polygon-cutout.snap.png +0 -0
- package/tests/elements/__snapshots__/polygon-pad.snap.png +0 -0
- package/tests/elements/__snapshots__/rect-pad-with-border-radius.snap.png +0 -0
- package/tests/elements/__snapshots__/rotated-rect-pad.snap.png +0 -0
- package/tests/elements/__snapshots__/silkscreen-circle.snap.png +0 -0
- package/tests/elements/__snapshots__/silkscreen-line.snap.png +0 -0
- package/tests/elements/__snapshots__/silkscreen-on-component.snap.png +0 -0
- package/tests/elements/__snapshots__/silkscreen-path.snap.png +0 -0
- package/tests/elements/__snapshots__/silkscreen-rect.snap.png +0 -0
- package/tests/elements/__snapshots__/silkscreen-text-bottom.snap.png +0 -0
- package/tests/elements/__snapshots__/square-hole.snap.png +0 -0
- package/tests/elements/pcb-board.test.ts +155 -0
- package/tests/elements/pcb-copper-pour.test.ts +120 -0
- package/tests/elements/pcb-cutout.test.ts +82 -0
- package/tests/elements/pcb-hole.test.ts +105 -0
- package/tests/elements/pcb-silkscreen.test.ts +245 -0
- package/tests/elements/pcb-smtpad.test.ts +198 -0
- package/tests/elements/pcb-trace.test.ts +116 -0
- package/tests/elements/pcb-via.test.ts +75 -0
- package/.claude/settings.local.json +0 -7
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import { createCanvas } from "canvas"
|
|
3
|
+
import type { PcbCopperPour } from "circuit-json"
|
|
4
|
+
import { CircuitToCanvasDrawer } from "../../lib/drawer"
|
|
5
|
+
|
|
6
|
+
test("draw rectangular copper pour", async () => {
|
|
7
|
+
const canvas = createCanvas(100, 100)
|
|
8
|
+
const ctx = canvas.getContext("2d")
|
|
9
|
+
const drawer = new CircuitToCanvasDrawer(ctx)
|
|
10
|
+
|
|
11
|
+
ctx.fillStyle = "#1a1a1a"
|
|
12
|
+
ctx.fillRect(0, 0, 100, 100)
|
|
13
|
+
|
|
14
|
+
const pour: PcbCopperPour = {
|
|
15
|
+
type: "pcb_copper_pour",
|
|
16
|
+
pcb_copper_pour_id: "pour1",
|
|
17
|
+
shape: "rect",
|
|
18
|
+
layer: "top",
|
|
19
|
+
center: { x: 50, y: 50 },
|
|
20
|
+
width: 60,
|
|
21
|
+
height: 40,
|
|
22
|
+
covered_with_solder_mask: false,
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
drawer.drawElements([pour])
|
|
26
|
+
|
|
27
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
28
|
+
import.meta.path,
|
|
29
|
+
)
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
test("draw polygon copper pour", async () => {
|
|
33
|
+
const canvas = createCanvas(100, 100)
|
|
34
|
+
const ctx = canvas.getContext("2d")
|
|
35
|
+
const drawer = new CircuitToCanvasDrawer(ctx)
|
|
36
|
+
|
|
37
|
+
ctx.fillStyle = "#1a1a1a"
|
|
38
|
+
ctx.fillRect(0, 0, 100, 100)
|
|
39
|
+
|
|
40
|
+
const pour: PcbCopperPour = {
|
|
41
|
+
type: "pcb_copper_pour",
|
|
42
|
+
pcb_copper_pour_id: "pour1",
|
|
43
|
+
shape: "polygon",
|
|
44
|
+
layer: "bottom",
|
|
45
|
+
points: [
|
|
46
|
+
{ x: 10, y: 10 },
|
|
47
|
+
{ x: 90, y: 10 },
|
|
48
|
+
{ x: 90, y: 90 },
|
|
49
|
+
{ x: 10, y: 90 },
|
|
50
|
+
],
|
|
51
|
+
covered_with_solder_mask: false,
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
drawer.drawElements([pour])
|
|
55
|
+
|
|
56
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
57
|
+
import.meta.path,
|
|
58
|
+
"polygon-copper-pour",
|
|
59
|
+
)
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
test("draw copper pour with trace", async () => {
|
|
63
|
+
const canvas = createCanvas(100, 100)
|
|
64
|
+
const ctx = canvas.getContext("2d")
|
|
65
|
+
const drawer = new CircuitToCanvasDrawer(ctx)
|
|
66
|
+
|
|
67
|
+
ctx.fillStyle = "#1a1a1a"
|
|
68
|
+
ctx.fillRect(0, 0, 100, 100)
|
|
69
|
+
|
|
70
|
+
const elements = [
|
|
71
|
+
{
|
|
72
|
+
type: "pcb_copper_pour" as const,
|
|
73
|
+
pcb_copper_pour_id: "pour1",
|
|
74
|
+
shape: "polygon" as const,
|
|
75
|
+
layer: "top" as const,
|
|
76
|
+
points: [
|
|
77
|
+
{ x: 10, y: 10 },
|
|
78
|
+
{ x: 90, y: 10 },
|
|
79
|
+
{ x: 90, y: 90 },
|
|
80
|
+
{ x: 10, y: 90 },
|
|
81
|
+
],
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
type: "pcb_trace" as const,
|
|
85
|
+
pcb_trace_id: "trace1",
|
|
86
|
+
route: [
|
|
87
|
+
{
|
|
88
|
+
route_type: "wire" as const,
|
|
89
|
+
x: 20,
|
|
90
|
+
y: 50,
|
|
91
|
+
width: 5,
|
|
92
|
+
layer: "top" as const,
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
route_type: "wire" as const,
|
|
96
|
+
x: 80,
|
|
97
|
+
y: 50,
|
|
98
|
+
width: 5,
|
|
99
|
+
layer: "top" as const,
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
type: "pcb_via" as const,
|
|
105
|
+
pcb_via_id: "via1",
|
|
106
|
+
x: 50,
|
|
107
|
+
y: 50,
|
|
108
|
+
outer_diameter: 15,
|
|
109
|
+
hole_diameter: 8,
|
|
110
|
+
layers: ["top", "bottom"],
|
|
111
|
+
},
|
|
112
|
+
]
|
|
113
|
+
|
|
114
|
+
drawer.drawElements(elements)
|
|
115
|
+
|
|
116
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
117
|
+
import.meta.path,
|
|
118
|
+
"copper-pour-with-trace",
|
|
119
|
+
)
|
|
120
|
+
})
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import { createCanvas } from "canvas"
|
|
3
|
+
import type { PcbCutout } from "circuit-json"
|
|
4
|
+
import { CircuitToCanvasDrawer } from "../../lib/drawer"
|
|
5
|
+
|
|
6
|
+
test("draw rectangular cutout", async () => {
|
|
7
|
+
const canvas = createCanvas(100, 100)
|
|
8
|
+
const ctx = canvas.getContext("2d")
|
|
9
|
+
const drawer = new CircuitToCanvasDrawer(ctx)
|
|
10
|
+
|
|
11
|
+
ctx.fillStyle = "#1a1a1a"
|
|
12
|
+
ctx.fillRect(0, 0, 100, 100)
|
|
13
|
+
|
|
14
|
+
const cutout: PcbCutout = {
|
|
15
|
+
type: "pcb_cutout",
|
|
16
|
+
pcb_cutout_id: "cutout1",
|
|
17
|
+
shape: "rect",
|
|
18
|
+
center: { x: 50, y: 50 },
|
|
19
|
+
width: 30,
|
|
20
|
+
height: 20,
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
drawer.drawElements([cutout])
|
|
24
|
+
|
|
25
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
26
|
+
import.meta.path,
|
|
27
|
+
)
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
test("draw circular cutout", async () => {
|
|
31
|
+
const canvas = createCanvas(100, 100)
|
|
32
|
+
const ctx = canvas.getContext("2d")
|
|
33
|
+
const drawer = new CircuitToCanvasDrawer(ctx)
|
|
34
|
+
|
|
35
|
+
ctx.fillStyle = "#1a1a1a"
|
|
36
|
+
ctx.fillRect(0, 0, 100, 100)
|
|
37
|
+
|
|
38
|
+
const cutout: PcbCutout = {
|
|
39
|
+
type: "pcb_cutout",
|
|
40
|
+
pcb_cutout_id: "cutout1",
|
|
41
|
+
shape: "circle",
|
|
42
|
+
center: { x: 50, y: 50 },
|
|
43
|
+
radius: 20,
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
drawer.drawElements([cutout])
|
|
47
|
+
|
|
48
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
49
|
+
import.meta.path,
|
|
50
|
+
"circular-cutout",
|
|
51
|
+
)
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
test("draw polygon cutout", async () => {
|
|
55
|
+
const canvas = createCanvas(100, 100)
|
|
56
|
+
const ctx = canvas.getContext("2d")
|
|
57
|
+
const drawer = new CircuitToCanvasDrawer(ctx)
|
|
58
|
+
|
|
59
|
+
ctx.fillStyle = "#1a1a1a"
|
|
60
|
+
ctx.fillRect(0, 0, 100, 100)
|
|
61
|
+
|
|
62
|
+
const cutout: PcbCutout = {
|
|
63
|
+
type: "pcb_cutout",
|
|
64
|
+
pcb_cutout_id: "cutout1",
|
|
65
|
+
shape: "polygon",
|
|
66
|
+
points: [
|
|
67
|
+
{ x: 30, y: 30 },
|
|
68
|
+
{ x: 70, y: 30 },
|
|
69
|
+
{ x: 80, y: 50 },
|
|
70
|
+
{ x: 70, y: 70 },
|
|
71
|
+
{ x: 30, y: 70 },
|
|
72
|
+
{ x: 20, y: 50 },
|
|
73
|
+
],
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
drawer.drawElements([cutout])
|
|
77
|
+
|
|
78
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
79
|
+
import.meta.path,
|
|
80
|
+
"polygon-cutout",
|
|
81
|
+
)
|
|
82
|
+
})
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import { createCanvas } from "canvas"
|
|
3
|
+
import type { PCBHole } from "circuit-json"
|
|
4
|
+
import { CircuitToCanvasDrawer } from "../../lib/drawer"
|
|
5
|
+
|
|
6
|
+
test("draw circular hole", async () => {
|
|
7
|
+
const canvas = createCanvas(100, 100)
|
|
8
|
+
const ctx = canvas.getContext("2d")
|
|
9
|
+
const drawer = new CircuitToCanvasDrawer(ctx)
|
|
10
|
+
|
|
11
|
+
ctx.fillStyle = "#1a1a1a"
|
|
12
|
+
ctx.fillRect(0, 0, 100, 100)
|
|
13
|
+
|
|
14
|
+
const hole: PCBHole = {
|
|
15
|
+
type: "pcb_hole",
|
|
16
|
+
pcb_hole_id: "hole1",
|
|
17
|
+
hole_shape: "circle",
|
|
18
|
+
hole_diameter: 30,
|
|
19
|
+
x: 50,
|
|
20
|
+
y: 50,
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
drawer.drawElements([hole])
|
|
24
|
+
|
|
25
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
26
|
+
import.meta.path,
|
|
27
|
+
)
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
test("draw square hole", async () => {
|
|
31
|
+
const canvas = createCanvas(100, 100)
|
|
32
|
+
const ctx = canvas.getContext("2d")
|
|
33
|
+
const drawer = new CircuitToCanvasDrawer(ctx)
|
|
34
|
+
|
|
35
|
+
ctx.fillStyle = "#1a1a1a"
|
|
36
|
+
ctx.fillRect(0, 0, 100, 100)
|
|
37
|
+
|
|
38
|
+
const hole: PCBHole = {
|
|
39
|
+
type: "pcb_hole",
|
|
40
|
+
pcb_hole_id: "hole1",
|
|
41
|
+
hole_shape: "square",
|
|
42
|
+
hole_diameter: 30,
|
|
43
|
+
x: 50,
|
|
44
|
+
y: 50,
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
drawer.drawElements([hole])
|
|
48
|
+
|
|
49
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
50
|
+
import.meta.path,
|
|
51
|
+
"square-hole",
|
|
52
|
+
)
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
test("draw oval hole", async () => {
|
|
56
|
+
const canvas = createCanvas(100, 100)
|
|
57
|
+
const ctx = canvas.getContext("2d")
|
|
58
|
+
const drawer = new CircuitToCanvasDrawer(ctx)
|
|
59
|
+
|
|
60
|
+
ctx.fillStyle = "#1a1a1a"
|
|
61
|
+
ctx.fillRect(0, 0, 100, 100)
|
|
62
|
+
|
|
63
|
+
const hole: PCBHole = {
|
|
64
|
+
type: "pcb_hole",
|
|
65
|
+
pcb_hole_id: "hole1",
|
|
66
|
+
hole_shape: "oval",
|
|
67
|
+
hole_width: 50,
|
|
68
|
+
hole_height: 30,
|
|
69
|
+
x: 50,
|
|
70
|
+
y: 50,
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
drawer.drawElements([hole])
|
|
74
|
+
|
|
75
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
76
|
+
import.meta.path,
|
|
77
|
+
"oval-hole",
|
|
78
|
+
)
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
test("draw pill hole", async () => {
|
|
82
|
+
const canvas = createCanvas(100, 100)
|
|
83
|
+
const ctx = canvas.getContext("2d")
|
|
84
|
+
const drawer = new CircuitToCanvasDrawer(ctx)
|
|
85
|
+
|
|
86
|
+
ctx.fillStyle = "#1a1a1a"
|
|
87
|
+
ctx.fillRect(0, 0, 100, 100)
|
|
88
|
+
|
|
89
|
+
const hole: PCBHole = {
|
|
90
|
+
type: "pcb_hole",
|
|
91
|
+
pcb_hole_id: "hole1",
|
|
92
|
+
hole_shape: "pill",
|
|
93
|
+
hole_width: 60,
|
|
94
|
+
hole_height: 30,
|
|
95
|
+
x: 50,
|
|
96
|
+
y: 50,
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
drawer.drawElements([hole])
|
|
100
|
+
|
|
101
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
102
|
+
import.meta.path,
|
|
103
|
+
"pill-hole",
|
|
104
|
+
)
|
|
105
|
+
})
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import { createCanvas } from "canvas"
|
|
3
|
+
import type {
|
|
4
|
+
PcbSilkscreenText,
|
|
5
|
+
PcbSilkscreenRect,
|
|
6
|
+
PcbSilkscreenCircle,
|
|
7
|
+
PcbSilkscreenLine,
|
|
8
|
+
PcbSilkscreenPath,
|
|
9
|
+
} from "circuit-json"
|
|
10
|
+
import { CircuitToCanvasDrawer } from "../../lib/drawer"
|
|
11
|
+
|
|
12
|
+
test("draw silkscreen text", async () => {
|
|
13
|
+
const canvas = createCanvas(100, 100)
|
|
14
|
+
const ctx = canvas.getContext("2d")
|
|
15
|
+
const drawer = new CircuitToCanvasDrawer(ctx)
|
|
16
|
+
|
|
17
|
+
ctx.fillStyle = "#1a1a1a"
|
|
18
|
+
ctx.fillRect(0, 0, 100, 100)
|
|
19
|
+
|
|
20
|
+
const text: PcbSilkscreenText = {
|
|
21
|
+
type: "pcb_silkscreen_text",
|
|
22
|
+
pcb_silkscreen_text_id: "text1",
|
|
23
|
+
pcb_component_id: "component1",
|
|
24
|
+
layer: "top",
|
|
25
|
+
text: "U1",
|
|
26
|
+
anchor_position: { x: 50, y: 50 },
|
|
27
|
+
anchor_alignment: "center",
|
|
28
|
+
font: "tscircuit2024",
|
|
29
|
+
font_size: 8,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
drawer.drawElements([text])
|
|
33
|
+
|
|
34
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
35
|
+
import.meta.path,
|
|
36
|
+
)
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
test("draw silkscreen text bottom layer", async () => {
|
|
40
|
+
const canvas = createCanvas(100, 100)
|
|
41
|
+
const ctx = canvas.getContext("2d")
|
|
42
|
+
const drawer = new CircuitToCanvasDrawer(ctx)
|
|
43
|
+
|
|
44
|
+
ctx.fillStyle = "#1a1a1a"
|
|
45
|
+
ctx.fillRect(0, 0, 100, 100)
|
|
46
|
+
|
|
47
|
+
const text: PcbSilkscreenText = {
|
|
48
|
+
type: "pcb_silkscreen_text",
|
|
49
|
+
pcb_silkscreen_text_id: "text1",
|
|
50
|
+
pcb_component_id: "component1",
|
|
51
|
+
layer: "bottom",
|
|
52
|
+
text: "BOTTOM",
|
|
53
|
+
anchor_position: { x: 50, y: 50 },
|
|
54
|
+
anchor_alignment: "center",
|
|
55
|
+
font: "tscircuit2024",
|
|
56
|
+
font_size: 8,
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
drawer.drawElements([text])
|
|
60
|
+
|
|
61
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
62
|
+
import.meta.path,
|
|
63
|
+
"silkscreen-text-bottom",
|
|
64
|
+
)
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
test("draw silkscreen rect", async () => {
|
|
68
|
+
const canvas = createCanvas(100, 100)
|
|
69
|
+
const ctx = canvas.getContext("2d")
|
|
70
|
+
const drawer = new CircuitToCanvasDrawer(ctx)
|
|
71
|
+
|
|
72
|
+
ctx.fillStyle = "#1a1a1a"
|
|
73
|
+
ctx.fillRect(0, 0, 100, 100)
|
|
74
|
+
|
|
75
|
+
const rect: PcbSilkscreenRect = {
|
|
76
|
+
type: "pcb_silkscreen_rect",
|
|
77
|
+
pcb_silkscreen_rect_id: "rect1",
|
|
78
|
+
pcb_component_id: "component1",
|
|
79
|
+
layer: "top",
|
|
80
|
+
center: { x: 50, y: 50 },
|
|
81
|
+
width: 40,
|
|
82
|
+
height: 20,
|
|
83
|
+
stroke_width: 0.2,
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
drawer.drawElements([rect])
|
|
87
|
+
|
|
88
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
89
|
+
import.meta.path,
|
|
90
|
+
"silkscreen-rect",
|
|
91
|
+
)
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
test("draw silkscreen circle", async () => {
|
|
95
|
+
const canvas = createCanvas(100, 100)
|
|
96
|
+
const ctx = canvas.getContext("2d")
|
|
97
|
+
const drawer = new CircuitToCanvasDrawer(ctx)
|
|
98
|
+
|
|
99
|
+
ctx.fillStyle = "#1a1a1a"
|
|
100
|
+
ctx.fillRect(0, 0, 100, 100)
|
|
101
|
+
|
|
102
|
+
const circle: PcbSilkscreenCircle = {
|
|
103
|
+
type: "pcb_silkscreen_circle",
|
|
104
|
+
pcb_silkscreen_circle_id: "circle1",
|
|
105
|
+
pcb_component_id: "component1",
|
|
106
|
+
layer: "top",
|
|
107
|
+
center: { x: 50, y: 50 },
|
|
108
|
+
radius: 20,
|
|
109
|
+
stroke_width: 0.2,
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
drawer.drawElements([circle])
|
|
113
|
+
|
|
114
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
115
|
+
import.meta.path,
|
|
116
|
+
"silkscreen-circle",
|
|
117
|
+
)
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
test("draw silkscreen line", async () => {
|
|
121
|
+
const canvas = createCanvas(100, 100)
|
|
122
|
+
const ctx = canvas.getContext("2d")
|
|
123
|
+
const drawer = new CircuitToCanvasDrawer(ctx)
|
|
124
|
+
|
|
125
|
+
ctx.fillStyle = "#1a1a1a"
|
|
126
|
+
ctx.fillRect(0, 0, 100, 100)
|
|
127
|
+
|
|
128
|
+
const line: PcbSilkscreenLine = {
|
|
129
|
+
type: "pcb_silkscreen_line",
|
|
130
|
+
pcb_silkscreen_line_id: "line1",
|
|
131
|
+
pcb_component_id: "component1",
|
|
132
|
+
layer: "top",
|
|
133
|
+
x1: 20,
|
|
134
|
+
y1: 20,
|
|
135
|
+
x2: 80,
|
|
136
|
+
y2: 80,
|
|
137
|
+
stroke_width: 2,
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
drawer.drawElements([line])
|
|
141
|
+
|
|
142
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
143
|
+
import.meta.path,
|
|
144
|
+
"silkscreen-line",
|
|
145
|
+
)
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
test("draw silkscreen path", async () => {
|
|
149
|
+
const canvas = createCanvas(100, 100)
|
|
150
|
+
const ctx = canvas.getContext("2d")
|
|
151
|
+
const drawer = new CircuitToCanvasDrawer(ctx)
|
|
152
|
+
|
|
153
|
+
ctx.fillStyle = "#1a1a1a"
|
|
154
|
+
ctx.fillRect(0, 0, 100, 100)
|
|
155
|
+
|
|
156
|
+
const path: PcbSilkscreenPath = {
|
|
157
|
+
type: "pcb_silkscreen_path",
|
|
158
|
+
pcb_silkscreen_path_id: "path1",
|
|
159
|
+
pcb_component_id: "component1",
|
|
160
|
+
layer: "top",
|
|
161
|
+
route: [
|
|
162
|
+
{ x: 10, y: 50 },
|
|
163
|
+
{ x: 30, y: 20 },
|
|
164
|
+
{ x: 70, y: 20 },
|
|
165
|
+
{ x: 90, y: 50 },
|
|
166
|
+
{ x: 70, y: 80 },
|
|
167
|
+
{ x: 30, y: 80 },
|
|
168
|
+
{ x: 10, y: 50 },
|
|
169
|
+
],
|
|
170
|
+
stroke_width: 2,
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
drawer.drawElements([path])
|
|
174
|
+
|
|
175
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
176
|
+
import.meta.path,
|
|
177
|
+
"silkscreen-path",
|
|
178
|
+
)
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
test("draw silkscreen on component", async () => {
|
|
182
|
+
const canvas = createCanvas(150, 100)
|
|
183
|
+
const ctx = canvas.getContext("2d")
|
|
184
|
+
const drawer = new CircuitToCanvasDrawer(ctx)
|
|
185
|
+
|
|
186
|
+
ctx.fillStyle = "#1a1a1a"
|
|
187
|
+
ctx.fillRect(0, 0, 150, 100)
|
|
188
|
+
|
|
189
|
+
const elements = [
|
|
190
|
+
// Component outline
|
|
191
|
+
{
|
|
192
|
+
type: "pcb_silkscreen_rect" as const,
|
|
193
|
+
pcb_silkscreen_rect_id: "outline1",
|
|
194
|
+
layer: "top" as const,
|
|
195
|
+
center: { x: 75, y: 50 },
|
|
196
|
+
width: 60,
|
|
197
|
+
height: 30,
|
|
198
|
+
},
|
|
199
|
+
// Pin 1 indicator
|
|
200
|
+
{
|
|
201
|
+
type: "pcb_silkscreen_circle" as const,
|
|
202
|
+
pcb_silkscreen_circle_id: "pin1marker",
|
|
203
|
+
layer: "top" as const,
|
|
204
|
+
center: { x: 55, y: 40 },
|
|
205
|
+
radius: 3,
|
|
206
|
+
},
|
|
207
|
+
// Component label
|
|
208
|
+
{
|
|
209
|
+
type: "pcb_silkscreen_text" as const,
|
|
210
|
+
pcb_silkscreen_text_id: "label1",
|
|
211
|
+
layer: "top" as const,
|
|
212
|
+
text: "IC1",
|
|
213
|
+
anchor_position: { x: 75, y: 50 },
|
|
214
|
+
font_size: 8,
|
|
215
|
+
},
|
|
216
|
+
// SMT pads
|
|
217
|
+
{
|
|
218
|
+
type: "pcb_smtpad" as const,
|
|
219
|
+
pcb_smtpad_id: "pad1",
|
|
220
|
+
shape: "rect" as const,
|
|
221
|
+
x: 55,
|
|
222
|
+
y: 50,
|
|
223
|
+
width: 10,
|
|
224
|
+
height: 5,
|
|
225
|
+
layer: "top" as const,
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
type: "pcb_smtpad" as const,
|
|
229
|
+
pcb_smtpad_id: "pad2",
|
|
230
|
+
shape: "rect" as const,
|
|
231
|
+
x: 95,
|
|
232
|
+
y: 50,
|
|
233
|
+
width: 10,
|
|
234
|
+
height: 5,
|
|
235
|
+
layer: "top" as const,
|
|
236
|
+
},
|
|
237
|
+
]
|
|
238
|
+
|
|
239
|
+
drawer.drawElements(elements)
|
|
240
|
+
|
|
241
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
242
|
+
import.meta.path,
|
|
243
|
+
"silkscreen-on-component",
|
|
244
|
+
)
|
|
245
|
+
})
|