circuit-to-canvas 0.0.22 → 0.0.24
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 +8 -4
- package/dist/index.js +26 -6
- package/lib/drawer/CircuitToCanvasDrawer.ts +5 -7
- package/lib/drawer/elements/index.ts +17 -5
- package/lib/drawer/elements/pcb-silkscreen-circle.ts +33 -0
- package/lib/drawer/elements/pcb-silkscreen-line.ts +34 -0
- package/lib/drawer/elements/pcb-silkscreen-path.ts +44 -0
- package/lib/drawer/elements/pcb-silkscreen-rect.ts +34 -0
- package/lib/drawer/elements/pcb-silkscreen-text.ts +71 -0
- package/package.json +1 -1
- package/tests/elements/__snapshots__/fabrication-note-text-full-charset.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-board.snap.png +0 -0
- package/tests/elements/pcb-silkscreen-circle.test.ts +29 -0
- package/tests/elements/pcb-silkscreen-line.test.ts +31 -0
- package/tests/elements/pcb-silkscreen-on-component.test.ts +75 -0
- package/tests/elements/pcb-silkscreen-path.test.ts +36 -0
- package/tests/elements/pcb-silkscreen-rect.test.ts +30 -0
- package/tests/elements/pcb-silkscreen-text-bottom-rotated.test.ts +84 -0
- package/tests/elements/pcb-silkscreen-text-bottom.test.ts +31 -0
- package/tests/elements/pcb-silkscreen-text-rotated.test.ts +32 -0
- package/tests/elements/pcb-silkscreen-text.test.ts +31 -0
- package/tests/elements/pcb-smtpad-bottom-layer.test.ts +30 -0
- package/tests/elements/pcb-smtpad-circle.test.ts +29 -0
- package/tests/elements/pcb-smtpad-pill.test.ts +31 -0
- package/tests/elements/pcb-smtpad-polygon.test.ts +34 -0
- package/tests/elements/pcb-smtpad-rect-border-radius.test.ts +31 -0
- package/tests/elements/pcb-smtpad-rect.test.ts +30 -0
- package/tests/elements/pcb-smtpad-rotated-rect.test.ts +31 -0
- package/lib/drawer/elements/pcb-silkscreen.ts +0 -186
- package/tests/elements/pcb-silkscreen.test.ts +0 -362
- package/tests/elements/pcb-smtpad.test.ts +0 -198
- /package/tests/elements/__snapshots__/{silkscreen-circle.snap.png → pcb-silkscreen-circle.snap.png} +0 -0
- /package/tests/elements/__snapshots__/{silkscreen-line.snap.png → pcb-silkscreen-line.snap.png} +0 -0
- /package/tests/elements/__snapshots__/{silkscreen-on-component.snap.png → pcb-silkscreen-on-component.snap.png} +0 -0
- /package/tests/elements/__snapshots__/{silkscreen-path.snap.png → pcb-silkscreen-path.snap.png} +0 -0
- /package/tests/elements/__snapshots__/{silkscreen-rect.snap.png → pcb-silkscreen-rect.snap.png} +0 -0
- /package/tests/elements/__snapshots__/{silkscreen-text-bottom-rotated.snap.png → pcb-silkscreen-text-bottom-rotated.snap.png} +0 -0
- /package/tests/elements/__snapshots__/{silkscreen-text-bottom.snap.png → pcb-silkscreen-text-bottom.snap.png} +0 -0
- /package/tests/elements/__snapshots__/{silkscreen-text-rotated.snap.png → pcb-silkscreen-text-rotated.snap.png} +0 -0
- /package/tests/elements/__snapshots__/{pcb-silkscreen.snap.png → pcb-silkscreen-text.snap.png} +0 -0
- /package/tests/elements/__snapshots__/{bottom-layer-pad.snap.png → pcb-smtpad-bottom-layer.snap.png} +0 -0
- /package/tests/elements/__snapshots__/{circular-pad.snap.png → pcb-smtpad-circle.snap.png} +0 -0
- /package/tests/elements/__snapshots__/{pill-pad.snap.png → pcb-smtpad-pill.snap.png} +0 -0
- /package/tests/elements/__snapshots__/{polygon-pad.snap.png → pcb-smtpad-polygon.snap.png} +0 -0
- /package/tests/elements/__snapshots__/{rect-pad-with-border-radius.snap.png → pcb-smtpad-rect-border-radius.snap.png} +0 -0
- /package/tests/elements/__snapshots__/{pcb-smtpad.snap.png → pcb-smtpad-rect.snap.png} +0 -0
- /package/tests/elements/__snapshots__/{rotated-rect-pad.snap.png → pcb-smtpad-rotated-rect.snap.png} +0 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import { createCanvas } from "@napi-rs/canvas"
|
|
3
|
+
import type { PcbSilkscreenText } from "circuit-json"
|
|
4
|
+
import { CircuitToCanvasDrawer } from "../../lib/drawer"
|
|
5
|
+
|
|
6
|
+
test("draw silkscreen text bottom layer with rotation - tests transform order", async () => {
|
|
7
|
+
const canvas = createCanvas(150, 150)
|
|
8
|
+
const ctx = canvas.getContext("2d")
|
|
9
|
+
const drawer = new CircuitToCanvasDrawer(ctx)
|
|
10
|
+
|
|
11
|
+
ctx.fillStyle = "#1a1a1a"
|
|
12
|
+
ctx.fillRect(0, 0, 150, 150)
|
|
13
|
+
|
|
14
|
+
// This test verifies the transform order (translate -> rotate -> scale) is correct
|
|
15
|
+
// by testing bottom layer text with various rotations
|
|
16
|
+
const texts: PcbSilkscreenText[] = [
|
|
17
|
+
{
|
|
18
|
+
type: "pcb_silkscreen_text",
|
|
19
|
+
pcb_silkscreen_text_id: "text1",
|
|
20
|
+
pcb_component_id: "component1",
|
|
21
|
+
layer: "bottom",
|
|
22
|
+
text: "0",
|
|
23
|
+
anchor_position: { x: 75, y: 30 },
|
|
24
|
+
anchor_alignment: "center",
|
|
25
|
+
font: "tscircuit2024",
|
|
26
|
+
font_size: 6,
|
|
27
|
+
ccw_rotation: 0,
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
type: "pcb_silkscreen_text",
|
|
31
|
+
pcb_silkscreen_text_id: "text2",
|
|
32
|
+
pcb_component_id: "component1",
|
|
33
|
+
layer: "bottom",
|
|
34
|
+
text: "90",
|
|
35
|
+
anchor_position: { x: 120, y: 75 },
|
|
36
|
+
anchor_alignment: "center",
|
|
37
|
+
font: "tscircuit2024",
|
|
38
|
+
font_size: 6,
|
|
39
|
+
ccw_rotation: 90,
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
type: "pcb_silkscreen_text",
|
|
43
|
+
pcb_silkscreen_text_id: "text3",
|
|
44
|
+
pcb_component_id: "component1",
|
|
45
|
+
layer: "bottom",
|
|
46
|
+
text: "180",
|
|
47
|
+
anchor_position: { x: 75, y: 120 },
|
|
48
|
+
anchor_alignment: "center",
|
|
49
|
+
font: "tscircuit2024",
|
|
50
|
+
font_size: 6,
|
|
51
|
+
ccw_rotation: 180,
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
type: "pcb_silkscreen_text",
|
|
55
|
+
pcb_silkscreen_text_id: "text4",
|
|
56
|
+
pcb_component_id: "component1",
|
|
57
|
+
layer: "bottom",
|
|
58
|
+
text: "270",
|
|
59
|
+
anchor_position: { x: 30, y: 75 },
|
|
60
|
+
anchor_alignment: "center",
|
|
61
|
+
font: "tscircuit2024",
|
|
62
|
+
font_size: 6,
|
|
63
|
+
ccw_rotation: 270,
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
type: "pcb_silkscreen_text",
|
|
67
|
+
pcb_silkscreen_text_id: "text5",
|
|
68
|
+
pcb_component_id: "component1",
|
|
69
|
+
layer: "bottom",
|
|
70
|
+
text: "BTM",
|
|
71
|
+
anchor_position: { x: 75, y: 75 },
|
|
72
|
+
anchor_alignment: "center",
|
|
73
|
+
font: "tscircuit2024",
|
|
74
|
+
font_size: 8,
|
|
75
|
+
ccw_rotation: 45,
|
|
76
|
+
},
|
|
77
|
+
]
|
|
78
|
+
|
|
79
|
+
drawer.drawElements(texts)
|
|
80
|
+
|
|
81
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
82
|
+
import.meta.path,
|
|
83
|
+
)
|
|
84
|
+
})
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import { createCanvas } from "@napi-rs/canvas"
|
|
3
|
+
import type { PcbSilkscreenText } from "circuit-json"
|
|
4
|
+
import { CircuitToCanvasDrawer } from "../../lib/drawer"
|
|
5
|
+
|
|
6
|
+
test("draw silkscreen text bottom layer", 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 text: PcbSilkscreenText = {
|
|
15
|
+
type: "pcb_silkscreen_text",
|
|
16
|
+
pcb_silkscreen_text_id: "text1",
|
|
17
|
+
pcb_component_id: "component1",
|
|
18
|
+
layer: "bottom",
|
|
19
|
+
text: "BOTTOM",
|
|
20
|
+
anchor_position: { x: 50, y: 50 },
|
|
21
|
+
anchor_alignment: "center",
|
|
22
|
+
font: "tscircuit2024",
|
|
23
|
+
font_size: 8,
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
drawer.drawElements([text])
|
|
27
|
+
|
|
28
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
29
|
+
import.meta.path,
|
|
30
|
+
)
|
|
31
|
+
})
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import { createCanvas } from "@napi-rs/canvas"
|
|
3
|
+
import type { PcbSilkscreenText } from "circuit-json"
|
|
4
|
+
import { CircuitToCanvasDrawer } from "../../lib/drawer"
|
|
5
|
+
|
|
6
|
+
test("draw silkscreen text with rotation", 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 text: PcbSilkscreenText = {
|
|
15
|
+
type: "pcb_silkscreen_text",
|
|
16
|
+
pcb_silkscreen_text_id: "text1",
|
|
17
|
+
pcb_component_id: "component1",
|
|
18
|
+
layer: "top",
|
|
19
|
+
text: "ROT45",
|
|
20
|
+
anchor_position: { x: 50, y: 50 },
|
|
21
|
+
anchor_alignment: "center",
|
|
22
|
+
font: "tscircuit2024",
|
|
23
|
+
font_size: 8,
|
|
24
|
+
ccw_rotation: 45,
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
drawer.drawElements([text])
|
|
28
|
+
|
|
29
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
30
|
+
import.meta.path,
|
|
31
|
+
)
|
|
32
|
+
})
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import { createCanvas } from "@napi-rs/canvas"
|
|
3
|
+
import type { PcbSilkscreenText } from "circuit-json"
|
|
4
|
+
import { CircuitToCanvasDrawer } from "../../lib/drawer"
|
|
5
|
+
|
|
6
|
+
test("draw silkscreen text", 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 text: PcbSilkscreenText = {
|
|
15
|
+
type: "pcb_silkscreen_text",
|
|
16
|
+
pcb_silkscreen_text_id: "text1",
|
|
17
|
+
pcb_component_id: "component1",
|
|
18
|
+
layer: "top",
|
|
19
|
+
text: "U1",
|
|
20
|
+
anchor_position: { x: 50, y: 50 },
|
|
21
|
+
anchor_alignment: "center",
|
|
22
|
+
font: "tscircuit2024",
|
|
23
|
+
font_size: 8,
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
drawer.drawElements([text])
|
|
27
|
+
|
|
28
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
29
|
+
import.meta.path,
|
|
30
|
+
)
|
|
31
|
+
})
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import { createCanvas } from "@napi-rs/canvas"
|
|
3
|
+
import type { PcbSmtPad } from "circuit-json"
|
|
4
|
+
import { CircuitToCanvasDrawer } from "../../lib/drawer"
|
|
5
|
+
|
|
6
|
+
test("draw bottom layer smt pad", 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 pad: PcbSmtPad = {
|
|
15
|
+
type: "pcb_smtpad",
|
|
16
|
+
pcb_smtpad_id: "pad1",
|
|
17
|
+
shape: "rect",
|
|
18
|
+
x: 50,
|
|
19
|
+
y: 50,
|
|
20
|
+
width: 40,
|
|
21
|
+
height: 20,
|
|
22
|
+
layer: "bottom",
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
drawer.drawElements([pad])
|
|
26
|
+
|
|
27
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
28
|
+
import.meta.path,
|
|
29
|
+
)
|
|
30
|
+
})
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import { createCanvas } from "@napi-rs/canvas"
|
|
3
|
+
import type { PcbSmtPad } from "circuit-json"
|
|
4
|
+
import { CircuitToCanvasDrawer } from "../../lib/drawer"
|
|
5
|
+
|
|
6
|
+
test("draw circular smt pad", 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 pad: PcbSmtPad = {
|
|
15
|
+
type: "pcb_smtpad",
|
|
16
|
+
pcb_smtpad_id: "pad1",
|
|
17
|
+
shape: "circle",
|
|
18
|
+
x: 50,
|
|
19
|
+
y: 50,
|
|
20
|
+
radius: 20,
|
|
21
|
+
layer: "top",
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
drawer.drawElements([pad])
|
|
25
|
+
|
|
26
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
27
|
+
import.meta.path,
|
|
28
|
+
)
|
|
29
|
+
})
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import { createCanvas } from "@napi-rs/canvas"
|
|
3
|
+
import type { PcbSmtPad } from "circuit-json"
|
|
4
|
+
import { CircuitToCanvasDrawer } from "../../lib/drawer"
|
|
5
|
+
|
|
6
|
+
test("draw pill smt pad", 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 pad: PcbSmtPad = {
|
|
15
|
+
type: "pcb_smtpad",
|
|
16
|
+
pcb_smtpad_id: "pad1",
|
|
17
|
+
shape: "pill",
|
|
18
|
+
x: 50,
|
|
19
|
+
y: 50,
|
|
20
|
+
width: 50,
|
|
21
|
+
height: 25,
|
|
22
|
+
radius: 12.5,
|
|
23
|
+
layer: "top",
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
drawer.drawElements([pad])
|
|
27
|
+
|
|
28
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
29
|
+
import.meta.path,
|
|
30
|
+
)
|
|
31
|
+
})
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import { createCanvas } from "@napi-rs/canvas"
|
|
3
|
+
import type { PcbSmtPad } from "circuit-json"
|
|
4
|
+
import { CircuitToCanvasDrawer } from "../../lib/drawer"
|
|
5
|
+
|
|
6
|
+
test("draw polygon smt pad", 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 pad: PcbSmtPad = {
|
|
15
|
+
type: "pcb_smtpad",
|
|
16
|
+
pcb_smtpad_id: "pad1",
|
|
17
|
+
shape: "polygon",
|
|
18
|
+
layer: "top",
|
|
19
|
+
points: [
|
|
20
|
+
{ x: 30, y: 30 },
|
|
21
|
+
{ x: 70, y: 30 },
|
|
22
|
+
{ x: 80, y: 50 },
|
|
23
|
+
{ x: 70, y: 70 },
|
|
24
|
+
{ x: 30, y: 70 },
|
|
25
|
+
{ x: 20, y: 50 },
|
|
26
|
+
],
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
drawer.drawElements([pad])
|
|
30
|
+
|
|
31
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
32
|
+
import.meta.path,
|
|
33
|
+
)
|
|
34
|
+
})
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import { createCanvas } from "@napi-rs/canvas"
|
|
3
|
+
import type { PcbSmtPad } from "circuit-json"
|
|
4
|
+
import { CircuitToCanvasDrawer } from "../../lib/drawer"
|
|
5
|
+
|
|
6
|
+
test("draw rectangular smt pad with border radius", 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 pad: PcbSmtPad = {
|
|
15
|
+
type: "pcb_smtpad",
|
|
16
|
+
pcb_smtpad_id: "pad1",
|
|
17
|
+
shape: "rect",
|
|
18
|
+
x: 50,
|
|
19
|
+
y: 50,
|
|
20
|
+
width: 40,
|
|
21
|
+
height: 20,
|
|
22
|
+
layer: "top",
|
|
23
|
+
rect_border_radius: 5,
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
drawer.drawElements([pad])
|
|
27
|
+
|
|
28
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
29
|
+
import.meta.path,
|
|
30
|
+
)
|
|
31
|
+
})
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import { createCanvas } from "@napi-rs/canvas"
|
|
3
|
+
import type { PcbSmtPad } from "circuit-json"
|
|
4
|
+
import { CircuitToCanvasDrawer } from "../../lib/drawer"
|
|
5
|
+
|
|
6
|
+
test("draw rectangular smt pad", 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 pad: PcbSmtPad = {
|
|
15
|
+
type: "pcb_smtpad",
|
|
16
|
+
pcb_smtpad_id: "pad1",
|
|
17
|
+
shape: "rect",
|
|
18
|
+
x: 50,
|
|
19
|
+
y: 50,
|
|
20
|
+
width: 40,
|
|
21
|
+
height: 20,
|
|
22
|
+
layer: "top",
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
drawer.drawElements([pad])
|
|
26
|
+
|
|
27
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
28
|
+
import.meta.path,
|
|
29
|
+
)
|
|
30
|
+
})
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { expect, test } from "bun:test"
|
|
2
|
+
import { createCanvas } from "@napi-rs/canvas"
|
|
3
|
+
import type { PcbSmtPad } from "circuit-json"
|
|
4
|
+
import { CircuitToCanvasDrawer } from "../../lib/drawer"
|
|
5
|
+
|
|
6
|
+
test("draw rotated rectangular smt pad", 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 pad: PcbSmtPad = {
|
|
15
|
+
type: "pcb_smtpad",
|
|
16
|
+
pcb_smtpad_id: "pad1",
|
|
17
|
+
shape: "rotated_rect",
|
|
18
|
+
x: 50,
|
|
19
|
+
y: 50,
|
|
20
|
+
width: 40,
|
|
21
|
+
height: 20,
|
|
22
|
+
layer: "top",
|
|
23
|
+
ccw_rotation: 45,
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
drawer.drawElements([pad])
|
|
27
|
+
|
|
28
|
+
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
29
|
+
import.meta.path,
|
|
30
|
+
)
|
|
31
|
+
})
|
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
PcbSilkscreenText,
|
|
3
|
-
PcbSilkscreenRect,
|
|
4
|
-
PcbSilkscreenCircle,
|
|
5
|
-
PcbSilkscreenLine,
|
|
6
|
-
PcbSilkscreenPath,
|
|
7
|
-
} from "circuit-json"
|
|
8
|
-
import type { Matrix } from "transformation-matrix"
|
|
9
|
-
import { applyToPoint } from "transformation-matrix"
|
|
10
|
-
import type { PcbColorMap, CanvasContext } from "../types"
|
|
11
|
-
import { drawRect } from "../shapes/rect"
|
|
12
|
-
import { drawCircle } from "../shapes/circle"
|
|
13
|
-
import { drawLine } from "../shapes/line"
|
|
14
|
-
import { drawPath } from "../shapes/path"
|
|
15
|
-
import {
|
|
16
|
-
getAlphabetLayout,
|
|
17
|
-
strokeAlphabetText,
|
|
18
|
-
getTextStartPosition,
|
|
19
|
-
type AnchorAlignment,
|
|
20
|
-
} from "../shapes/text"
|
|
21
|
-
|
|
22
|
-
export interface DrawPcbSilkscreenTextParams {
|
|
23
|
-
ctx: CanvasContext
|
|
24
|
-
text: PcbSilkscreenText
|
|
25
|
-
realToCanvasMat: Matrix
|
|
26
|
-
colorMap: PcbColorMap
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export interface DrawPcbSilkscreenRectParams {
|
|
30
|
-
ctx: CanvasContext
|
|
31
|
-
rect: PcbSilkscreenRect
|
|
32
|
-
realToCanvasMat: Matrix
|
|
33
|
-
colorMap: PcbColorMap
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export interface DrawPcbSilkscreenCircleParams {
|
|
37
|
-
ctx: CanvasContext
|
|
38
|
-
circle: PcbSilkscreenCircle
|
|
39
|
-
realToCanvasMat: Matrix
|
|
40
|
-
colorMap: PcbColorMap
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export interface DrawPcbSilkscreenLineParams {
|
|
44
|
-
ctx: CanvasContext
|
|
45
|
-
line: PcbSilkscreenLine
|
|
46
|
-
realToCanvasMat: Matrix
|
|
47
|
-
colorMap: PcbColorMap
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export interface DrawPcbSilkscreenPathParams {
|
|
51
|
-
ctx: CanvasContext
|
|
52
|
-
path: PcbSilkscreenPath
|
|
53
|
-
realToCanvasMat: Matrix
|
|
54
|
-
colorMap: PcbColorMap
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function layerToSilkscreenColor(layer: string, colorMap: PcbColorMap): string {
|
|
58
|
-
return layer === "bottom"
|
|
59
|
-
? colorMap.silkscreen.bottom
|
|
60
|
-
: colorMap.silkscreen.top
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function mapAnchorAlignment(alignment?: string): AnchorAlignment {
|
|
64
|
-
if (!alignment) return "center"
|
|
65
|
-
return alignment as AnchorAlignment
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export function drawPcbSilkscreenText(
|
|
69
|
-
params: DrawPcbSilkscreenTextParams,
|
|
70
|
-
): void {
|
|
71
|
-
const { ctx, text, realToCanvasMat, colorMap } = params
|
|
72
|
-
|
|
73
|
-
const content = text.text ?? ""
|
|
74
|
-
if (!content) return
|
|
75
|
-
|
|
76
|
-
const color = layerToSilkscreenColor(text.layer, colorMap)
|
|
77
|
-
const [x, y] = applyToPoint(realToCanvasMat, [
|
|
78
|
-
text.anchor_position.x,
|
|
79
|
-
text.anchor_position.y,
|
|
80
|
-
])
|
|
81
|
-
const scale = Math.abs(realToCanvasMat.a)
|
|
82
|
-
const fontSize = (text.font_size ?? 1) * scale
|
|
83
|
-
const rotation = text.ccw_rotation ?? 0
|
|
84
|
-
|
|
85
|
-
const layout = getAlphabetLayout(content, fontSize)
|
|
86
|
-
const alignment = mapAnchorAlignment(text.anchor_alignment)
|
|
87
|
-
const startPos = getTextStartPosition(alignment, layout)
|
|
88
|
-
|
|
89
|
-
ctx.save()
|
|
90
|
-
ctx.translate(x, y)
|
|
91
|
-
|
|
92
|
-
// Apply rotation (CCW rotation in degrees)
|
|
93
|
-
if (rotation !== 0) {
|
|
94
|
-
ctx.rotate(-rotation * (Math.PI / 180))
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
if (text.layer === "bottom") {
|
|
98
|
-
ctx.scale(-1, 1)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
ctx.lineWidth = layout.strokeWidth
|
|
102
|
-
ctx.lineCap = "round"
|
|
103
|
-
ctx.lineJoin = "round"
|
|
104
|
-
ctx.strokeStyle = color
|
|
105
|
-
|
|
106
|
-
strokeAlphabetText(ctx, content, layout, startPos.x, startPos.y)
|
|
107
|
-
|
|
108
|
-
ctx.restore()
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
export function drawPcbSilkscreenRect(
|
|
112
|
-
params: DrawPcbSilkscreenRectParams,
|
|
113
|
-
): void {
|
|
114
|
-
const { ctx, rect, realToCanvasMat, colorMap } = params
|
|
115
|
-
|
|
116
|
-
const color = layerToSilkscreenColor(rect.layer, colorMap)
|
|
117
|
-
|
|
118
|
-
drawRect({
|
|
119
|
-
ctx,
|
|
120
|
-
center: rect.center,
|
|
121
|
-
width: rect.width,
|
|
122
|
-
height: rect.height,
|
|
123
|
-
fill: color,
|
|
124
|
-
realToCanvasMat,
|
|
125
|
-
})
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
export function drawPcbSilkscreenCircle(
|
|
129
|
-
params: DrawPcbSilkscreenCircleParams,
|
|
130
|
-
): void {
|
|
131
|
-
const { ctx, circle, realToCanvasMat, colorMap } = params
|
|
132
|
-
|
|
133
|
-
const color = layerToSilkscreenColor(circle.layer, colorMap)
|
|
134
|
-
|
|
135
|
-
drawCircle({
|
|
136
|
-
ctx,
|
|
137
|
-
center: circle.center,
|
|
138
|
-
radius: circle.radius,
|
|
139
|
-
fill: color,
|
|
140
|
-
realToCanvasMat,
|
|
141
|
-
})
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
export function drawPcbSilkscreenLine(
|
|
145
|
-
params: DrawPcbSilkscreenLineParams,
|
|
146
|
-
): void {
|
|
147
|
-
const { ctx, line, realToCanvasMat, colorMap } = params
|
|
148
|
-
|
|
149
|
-
const color = layerToSilkscreenColor(line.layer, colorMap)
|
|
150
|
-
|
|
151
|
-
drawLine({
|
|
152
|
-
ctx,
|
|
153
|
-
start: { x: line.x1, y: line.y1 },
|
|
154
|
-
end: { x: line.x2, y: line.y2 },
|
|
155
|
-
strokeWidth: line.stroke_width ?? 0.1,
|
|
156
|
-
stroke: color,
|
|
157
|
-
realToCanvasMat,
|
|
158
|
-
})
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
export function drawPcbSilkscreenPath(
|
|
162
|
-
params: DrawPcbSilkscreenPathParams,
|
|
163
|
-
): void {
|
|
164
|
-
const { ctx, path, realToCanvasMat, colorMap } = params
|
|
165
|
-
|
|
166
|
-
const color = layerToSilkscreenColor(path.layer, colorMap)
|
|
167
|
-
|
|
168
|
-
if (!path.route || path.route.length < 2) return
|
|
169
|
-
|
|
170
|
-
// Draw each segment of the path
|
|
171
|
-
for (let i = 0; i < path.route.length - 1; i++) {
|
|
172
|
-
const start = path.route[i]
|
|
173
|
-
const end = path.route[i + 1]
|
|
174
|
-
|
|
175
|
-
if (!start || !end) continue
|
|
176
|
-
|
|
177
|
-
drawLine({
|
|
178
|
-
ctx,
|
|
179
|
-
start: { x: start.x, y: start.y },
|
|
180
|
-
end: { x: end.x, y: end.y },
|
|
181
|
-
strokeWidth: path.stroke_width ?? 0.1,
|
|
182
|
-
stroke: color,
|
|
183
|
-
realToCanvasMat,
|
|
184
|
-
})
|
|
185
|
-
}
|
|
186
|
-
}
|