circuit-to-canvas 0.0.51 → 0.0.53
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 +5 -2
- package/dist/index.js +1748 -1743
- package/lib/drawer/CircuitToCanvasDrawer.ts +61 -60
- package/lib/drawer/elements/pcb-board.ts +26 -21
- package/lib/drawer/elements/pcb-plated-hole.ts +3 -3
- package/lib/drawer/elements/pcb-soldermask/hole.ts +4 -4
- package/lib/drawer/elements/pcb-soldermask/index.ts +9 -9
- package/lib/drawer/elements/pcb-soldermask/plated-hole.ts +4 -4
- package/lib/drawer/elements/pcb-soldermask/smt-pad.ts +4 -4
- package/lib/drawer/shapes/text/getTextStartPosition.ts +10 -4
- package/package.json +1 -1
- package/tests/board-snapshot/usb-c-flashlight-board.test.ts +1 -1
- 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__/oval-plated-hole.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-fabrication-note-dimension.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-no-soldermask.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-plated-hole.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-silkscreen-oval.snap.png +0 -0
- package/tests/elements/__snapshots__/pcb-silkscreen-text-anchor-alignment.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 +1 -1
- package/tests/elements/pcb-hole-soldermask-margin.test.ts +1 -1
- package/tests/elements/pcb-keepout-with-group-id.test.ts +1 -1
- package/tests/elements/pcb-plated-hole-soldermask-margin.test.ts +1 -1
- package/tests/elements/pcb-plated-hole.test.ts +3 -3
- package/tests/elements/pcb-silkscreen-text-anchor-alignment.test.ts +221 -0
- 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 +5 -5
|
@@ -1,83 +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"
|
|
75
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"
|
|
76
74
|
|
|
77
75
|
export interface DrawElementsOptions {
|
|
78
76
|
layers?: PcbRenderLayer[]
|
|
79
77
|
/** Whether to render the soldermask layer. Defaults to false. */
|
|
80
|
-
|
|
78
|
+
drawSoldermask?: boolean
|
|
79
|
+
/** Whether to render the board material (substrate fill). Defaults to false. */
|
|
80
|
+
drawBoardMaterial?: boolean
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
interface CanvasLike {
|
|
@@ -187,6 +187,7 @@ export class CircuitToCanvasDrawer {
|
|
|
187
187
|
board,
|
|
188
188
|
realToCanvasMat: this.realToCanvasMat,
|
|
189
189
|
colorMap: this.colorMap,
|
|
190
|
+
drawBoardMaterial: options.drawBoardMaterial ?? false,
|
|
190
191
|
})
|
|
191
192
|
}
|
|
192
193
|
|
|
@@ -214,7 +215,7 @@ export class CircuitToCanvasDrawer {
|
|
|
214
215
|
}
|
|
215
216
|
|
|
216
217
|
// Step 3: Draw soldermask layer (only if showSoldermask is true)
|
|
217
|
-
const
|
|
218
|
+
const drawSoldermask = options.drawSoldermask ?? false
|
|
218
219
|
if (board) {
|
|
219
220
|
drawPcbSoldermask({
|
|
220
221
|
ctx: this.ctx,
|
|
@@ -223,7 +224,7 @@ export class CircuitToCanvasDrawer {
|
|
|
223
224
|
realToCanvasMat: this.realToCanvasMat,
|
|
224
225
|
colorMap: this.colorMap,
|
|
225
226
|
layer: "top",
|
|
226
|
-
|
|
227
|
+
drawSoldermask,
|
|
227
228
|
})
|
|
228
229
|
}
|
|
229
230
|
|
|
@@ -328,10 +329,10 @@ export class CircuitToCanvasDrawer {
|
|
|
328
329
|
hole: element as PcbPlatedHole,
|
|
329
330
|
realToCanvasMat: this.realToCanvasMat,
|
|
330
331
|
colorMap: this.colorMap,
|
|
331
|
-
soldermaskMargin:
|
|
332
|
+
soldermaskMargin: drawSoldermask
|
|
332
333
|
? (element as PcbPlatedHole).soldermask_margin
|
|
333
334
|
: undefined,
|
|
334
|
-
|
|
335
|
+
drawSoldermask,
|
|
335
336
|
})
|
|
336
337
|
}
|
|
337
338
|
|
|
@@ -355,7 +356,7 @@ export class CircuitToCanvasDrawer {
|
|
|
355
356
|
hole: element as PcbHole,
|
|
356
357
|
realToCanvasMat: this.realToCanvasMat,
|
|
357
358
|
colorMap: this.colorMap,
|
|
358
|
-
soldermaskMargin:
|
|
359
|
+
soldermaskMargin: drawSoldermask
|
|
359
360
|
? element.soldermask_margin
|
|
360
361
|
: undefined,
|
|
361
362
|
})
|
|
@@ -1,32 +1,35 @@
|
|
|
1
1
|
import type { PcbBoard } from "circuit-json"
|
|
2
2
|
import type { Matrix } from "transformation-matrix"
|
|
3
|
-
import type { PcbColorMap, CanvasContext } from "../types"
|
|
4
3
|
import { drawPath } from "../shapes/path"
|
|
5
4
|
import { drawRect } from "../shapes/rect"
|
|
5
|
+
import type { CanvasContext, PcbColorMap } from "../types"
|
|
6
6
|
|
|
7
7
|
export interface DrawPcbBoardParams {
|
|
8
8
|
ctx: CanvasContext
|
|
9
9
|
board: PcbBoard
|
|
10
10
|
realToCanvasMat: Matrix
|
|
11
11
|
colorMap: PcbColorMap
|
|
12
|
+
drawBoardMaterial: boolean
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
export function drawPcbBoard(params: DrawPcbBoardParams): void {
|
|
15
|
-
const { ctx, board, realToCanvasMat, colorMap } = params
|
|
16
|
+
const { ctx, board, realToCanvasMat, colorMap, drawBoardMaterial } = params
|
|
16
17
|
const { width, height, center, outline } = board
|
|
17
18
|
|
|
18
19
|
// If the board has a custom outline, draw substrate and outline
|
|
19
20
|
if (outline && Array.isArray(outline) && outline.length >= 3) {
|
|
20
|
-
// Draw substrate fill
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
21
|
+
// Draw substrate fill only if drawBoardMaterial is true
|
|
22
|
+
if (drawBoardMaterial) {
|
|
23
|
+
drawPath({
|
|
24
|
+
ctx,
|
|
25
|
+
points: outline.map((p) => ({ x: p.x, y: p.y })),
|
|
26
|
+
fill: colorMap.substrate,
|
|
27
|
+
realToCanvasMat,
|
|
28
|
+
closePath: true,
|
|
29
|
+
})
|
|
30
|
+
}
|
|
28
31
|
|
|
29
|
-
//
|
|
32
|
+
// Always draw outline stroke
|
|
30
33
|
drawPath({
|
|
31
34
|
ctx,
|
|
32
35
|
points: outline.map((p) => ({ x: p.x, y: p.y })),
|
|
@@ -40,17 +43,19 @@ export function drawPcbBoard(params: DrawPcbBoardParams): void {
|
|
|
40
43
|
|
|
41
44
|
// Otherwise draw a rectangle
|
|
42
45
|
if (width !== undefined && height !== undefined && center) {
|
|
43
|
-
// Draw substrate fill
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
46
|
+
// Draw substrate fill only if drawBoardMaterial is true
|
|
47
|
+
if (drawBoardMaterial) {
|
|
48
|
+
drawRect({
|
|
49
|
+
ctx,
|
|
50
|
+
center,
|
|
51
|
+
width,
|
|
52
|
+
height,
|
|
53
|
+
fill: colorMap.substrate,
|
|
54
|
+
realToCanvasMat,
|
|
55
|
+
})
|
|
56
|
+
}
|
|
52
57
|
|
|
53
|
-
//
|
|
58
|
+
// Always draw the outline stroke separately using path
|
|
54
59
|
const halfWidth = width / 2
|
|
55
60
|
const halfHeight = height / 2
|
|
56
61
|
const corners = [
|
|
@@ -14,7 +14,7 @@ export interface DrawPcbPlatedHoleParams {
|
|
|
14
14
|
realToCanvasMat: Matrix
|
|
15
15
|
colorMap: PcbColorMap
|
|
16
16
|
soldermaskMargin?: number
|
|
17
|
-
|
|
17
|
+
drawSoldermask?: boolean
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
export function drawPcbPlatedHole(params: DrawPcbPlatedHoleParams): void {
|
|
@@ -24,13 +24,13 @@ export function drawPcbPlatedHole(params: DrawPcbPlatedHoleParams): void {
|
|
|
24
24
|
realToCanvasMat,
|
|
25
25
|
colorMap,
|
|
26
26
|
soldermaskMargin = 0,
|
|
27
|
-
|
|
27
|
+
drawSoldermask,
|
|
28
28
|
} = params
|
|
29
29
|
|
|
30
30
|
// Skip holes that are fully covered with soldermask when soldermask is enabled,
|
|
31
31
|
// as they should have been handled by soldermask processing.
|
|
32
32
|
// When soldermask is disabled, fully covered holes should be drawn as normal copper.
|
|
33
|
-
if (hole.is_covered_with_solder_mask === true &&
|
|
33
|
+
if (hole.is_covered_with_solder_mask === true && drawSoldermask) {
|
|
34
34
|
return
|
|
35
35
|
}
|
|
36
36
|
|
|
@@ -12,7 +12,7 @@ export function processHoleSoldermask(params: {
|
|
|
12
12
|
realToCanvasMat: Matrix
|
|
13
13
|
colorMap: PcbColorMap
|
|
14
14
|
soldermaskOverCopperColor: string
|
|
15
|
-
|
|
15
|
+
drawSoldermask: boolean
|
|
16
16
|
}): void {
|
|
17
17
|
const {
|
|
18
18
|
ctx,
|
|
@@ -20,13 +20,13 @@ export function processHoleSoldermask(params: {
|
|
|
20
20
|
realToCanvasMat,
|
|
21
21
|
colorMap,
|
|
22
22
|
soldermaskOverCopperColor,
|
|
23
|
-
|
|
23
|
+
drawSoldermask,
|
|
24
24
|
} = params
|
|
25
25
|
// When soldermask is disabled, treat all holes as not covered with soldermask
|
|
26
26
|
// and use zero margin (normal rendering)
|
|
27
27
|
const isCoveredWithSoldermask =
|
|
28
|
-
|
|
29
|
-
const margin =
|
|
28
|
+
drawSoldermask && hole.is_covered_with_solder_mask === true
|
|
29
|
+
const margin = drawSoldermask ? (hole.soldermask_margin ?? 0) : 0
|
|
30
30
|
|
|
31
31
|
if (isCoveredWithSoldermask) {
|
|
32
32
|
// Draw light green over the entire hole
|
|
@@ -15,7 +15,7 @@ export interface DrawPcbSoldermaskParams {
|
|
|
15
15
|
realToCanvasMat: Matrix
|
|
16
16
|
colorMap: PcbColorMap
|
|
17
17
|
layer: "top" | "bottom"
|
|
18
|
-
|
|
18
|
+
drawSoldermask: boolean
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
/**
|
|
@@ -44,7 +44,7 @@ export function drawPcbSoldermask(params: DrawPcbSoldermaskParams): void {
|
|
|
44
44
|
realToCanvasMat,
|
|
45
45
|
colorMap,
|
|
46
46
|
layer,
|
|
47
|
-
|
|
47
|
+
drawSoldermask,
|
|
48
48
|
} = params
|
|
49
49
|
|
|
50
50
|
const soldermaskColor = colorMap.soldermask[layer] ?? colorMap.soldermask.top
|
|
@@ -52,7 +52,7 @@ export function drawPcbSoldermask(params: DrawPcbSoldermaskParams): void {
|
|
|
52
52
|
colorMap.soldermaskOverCopper[layer] ?? colorMap.soldermaskOverCopper.top
|
|
53
53
|
|
|
54
54
|
// Step 1: Draw the full soldermask covering the board (only if enabled)
|
|
55
|
-
if (
|
|
55
|
+
if (drawSoldermask) {
|
|
56
56
|
drawBoardSoldermask({ ctx, board, realToCanvasMat, soldermaskColor })
|
|
57
57
|
}
|
|
58
58
|
|
|
@@ -65,7 +65,7 @@ export function drawPcbSoldermask(params: DrawPcbSoldermaskParams): void {
|
|
|
65
65
|
colorMap,
|
|
66
66
|
soldermaskOverCopperColor,
|
|
67
67
|
layer,
|
|
68
|
-
|
|
68
|
+
drawSoldermask,
|
|
69
69
|
})
|
|
70
70
|
}
|
|
71
71
|
}
|
|
@@ -81,7 +81,7 @@ function processElementSoldermask(params: {
|
|
|
81
81
|
colorMap: PcbColorMap
|
|
82
82
|
soldermaskOverCopperColor: string
|
|
83
83
|
layer: "top" | "bottom"
|
|
84
|
-
|
|
84
|
+
drawSoldermask: boolean
|
|
85
85
|
}): void {
|
|
86
86
|
const {
|
|
87
87
|
ctx,
|
|
@@ -90,7 +90,7 @@ function processElementSoldermask(params: {
|
|
|
90
90
|
colorMap,
|
|
91
91
|
soldermaskOverCopperColor,
|
|
92
92
|
layer,
|
|
93
|
-
|
|
93
|
+
drawSoldermask,
|
|
94
94
|
} = params
|
|
95
95
|
|
|
96
96
|
if (element.type === "pcb_smtpad") {
|
|
@@ -101,7 +101,7 @@ function processElementSoldermask(params: {
|
|
|
101
101
|
colorMap,
|
|
102
102
|
soldermaskOverCopperColor,
|
|
103
103
|
layer,
|
|
104
|
-
|
|
104
|
+
drawSoldermask,
|
|
105
105
|
})
|
|
106
106
|
} else if (element.type === "pcb_plated_hole") {
|
|
107
107
|
processPlatedHoleSoldermask({
|
|
@@ -111,7 +111,7 @@ function processElementSoldermask(params: {
|
|
|
111
111
|
colorMap,
|
|
112
112
|
soldermaskOverCopperColor,
|
|
113
113
|
layer,
|
|
114
|
-
|
|
114
|
+
drawSoldermask,
|
|
115
115
|
})
|
|
116
116
|
} else if (element.type === "pcb_hole") {
|
|
117
117
|
processHoleSoldermask({
|
|
@@ -120,7 +120,7 @@ function processElementSoldermask(params: {
|
|
|
120
120
|
realToCanvasMat,
|
|
121
121
|
colorMap,
|
|
122
122
|
soldermaskOverCopperColor,
|
|
123
|
-
|
|
123
|
+
drawSoldermask,
|
|
124
124
|
})
|
|
125
125
|
} else if (element.type === "pcb_via") {
|
|
126
126
|
processViaSoldermask({
|
|
@@ -16,7 +16,7 @@ export function processPlatedHoleSoldermask(params: {
|
|
|
16
16
|
colorMap: PcbColorMap
|
|
17
17
|
soldermaskOverCopperColor: string
|
|
18
18
|
layer: "top" | "bottom"
|
|
19
|
-
|
|
19
|
+
drawSoldermask: boolean
|
|
20
20
|
}): void {
|
|
21
21
|
const {
|
|
22
22
|
ctx,
|
|
@@ -25,7 +25,7 @@ export function processPlatedHoleSoldermask(params: {
|
|
|
25
25
|
colorMap,
|
|
26
26
|
soldermaskOverCopperColor,
|
|
27
27
|
layer,
|
|
28
|
-
|
|
28
|
+
drawSoldermask,
|
|
29
29
|
} = params
|
|
30
30
|
// Check if this hole is on the current layer
|
|
31
31
|
if (hole.layers && !hole.layers.includes(layer)) return
|
|
@@ -33,8 +33,8 @@ export function processPlatedHoleSoldermask(params: {
|
|
|
33
33
|
// When soldermask is disabled, treat all holes as not covered with soldermask
|
|
34
34
|
// and use zero margin (normal rendering)
|
|
35
35
|
const isCoveredWithSoldermask =
|
|
36
|
-
|
|
37
|
-
const margin =
|
|
36
|
+
drawSoldermask && hole.is_covered_with_solder_mask === true
|
|
37
|
+
const margin = drawSoldermask ? (hole.soldermask_margin ?? 0) : 0
|
|
38
38
|
const copperColor = colorMap.copper.top
|
|
39
39
|
|
|
40
40
|
if (isCoveredWithSoldermask) {
|
|
@@ -16,7 +16,7 @@ export function processSmtPadSoldermask(params: {
|
|
|
16
16
|
colorMap: PcbColorMap
|
|
17
17
|
soldermaskOverCopperColor: string
|
|
18
18
|
layer: "top" | "bottom"
|
|
19
|
-
|
|
19
|
+
drawSoldermask: boolean
|
|
20
20
|
}): void {
|
|
21
21
|
const {
|
|
22
22
|
ctx,
|
|
@@ -25,7 +25,7 @@ export function processSmtPadSoldermask(params: {
|
|
|
25
25
|
colorMap,
|
|
26
26
|
soldermaskOverCopperColor,
|
|
27
27
|
layer,
|
|
28
|
-
|
|
28
|
+
drawSoldermask,
|
|
29
29
|
} = params
|
|
30
30
|
// Only process pads on the current layer
|
|
31
31
|
if (pad.layer !== layer) return
|
|
@@ -33,8 +33,8 @@ export function processSmtPadSoldermask(params: {
|
|
|
33
33
|
// When soldermask is disabled, treat all pads as not covered with soldermask
|
|
34
34
|
// and use zero margin (normal rendering)
|
|
35
35
|
const isCoveredWithSoldermask =
|
|
36
|
-
|
|
37
|
-
const margin =
|
|
36
|
+
drawSoldermask && pad.is_covered_with_solder_mask === true
|
|
37
|
+
const margin = drawSoldermask ? (pad.soldermask_margin ?? 0) : 0
|
|
38
38
|
|
|
39
39
|
// Get asymmetric margins for rect shapes
|
|
40
40
|
let ml = margin
|
|
@@ -14,7 +14,11 @@ export function getTextStartPosition(
|
|
|
14
14
|
let y = 0
|
|
15
15
|
|
|
16
16
|
// Horizontal alignment
|
|
17
|
-
if (
|
|
17
|
+
if (
|
|
18
|
+
alignment === "center" ||
|
|
19
|
+
alignment === "top_center" ||
|
|
20
|
+
alignment === "bottom_center"
|
|
21
|
+
) {
|
|
18
22
|
x = -totalWidth / 2
|
|
19
23
|
} else if (
|
|
20
24
|
alignment === "top_left" ||
|
|
@@ -31,7 +35,11 @@ export function getTextStartPosition(
|
|
|
31
35
|
}
|
|
32
36
|
|
|
33
37
|
// Vertical alignment
|
|
34
|
-
if (
|
|
38
|
+
if (
|
|
39
|
+
alignment === "center" ||
|
|
40
|
+
alignment === "center_left" ||
|
|
41
|
+
alignment === "center_right"
|
|
42
|
+
) {
|
|
35
43
|
y = -totalHeight / 2
|
|
36
44
|
} else if (
|
|
37
45
|
alignment === "top_left" ||
|
|
@@ -45,8 +53,6 @@ export function getTextStartPosition(
|
|
|
45
53
|
alignment === "bottom_center"
|
|
46
54
|
) {
|
|
47
55
|
y = -totalHeight
|
|
48
|
-
} else {
|
|
49
|
-
y = 0
|
|
50
56
|
}
|
|
51
57
|
|
|
52
58
|
return { x, y }
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@ test("USB-C flashlight - comprehensive comparison (circuit-to-canvas vs circuit-
|
|
|
9
9
|
const stackedPng = await getStackedPngSvgComparison(circuitElements, {
|
|
10
10
|
width: 400,
|
|
11
11
|
height: 800,
|
|
12
|
-
|
|
12
|
+
drawSoldermask: true,
|
|
13
13
|
})
|
|
14
14
|
|
|
15
15
|
await expect(stackedPng).toMatchPngSnapshot(import.meta.path)
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -22,7 +22,7 @@ test("draw rectangular board", async () => {
|
|
|
22
22
|
material: "fr4",
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
drawer.drawElements([board])
|
|
25
|
+
drawer.drawElements([board], { drawBoardMaterial: true })
|
|
26
26
|
|
|
27
27
|
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
28
28
|
import.meta.path,
|
|
@@ -57,7 +57,7 @@ test("draw board with custom outline", async () => {
|
|
|
57
57
|
],
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
drawer.drawElements([board])
|
|
60
|
+
drawer.drawElements([board], { drawBoardMaterial: true })
|
|
61
61
|
|
|
62
62
|
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
63
63
|
import.meta.path,
|
|
@@ -1273,7 +1273,7 @@ test("comprehensive soldermask margin test", async () => {
|
|
|
1273
1273
|
]
|
|
1274
1274
|
|
|
1275
1275
|
drawer.setCameraBounds({ minX: -95, maxX: 90, minY: -22, maxY: 22 })
|
|
1276
|
-
drawer.drawElements(circuit, {
|
|
1276
|
+
drawer.drawElements(circuit, { drawSoldermask: true })
|
|
1277
1277
|
|
|
1278
1278
|
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
1279
1279
|
import.meta.path,
|
|
@@ -278,7 +278,7 @@ test("draw holes with positive and negative soldermask margins", async () => {
|
|
|
278
278
|
]
|
|
279
279
|
|
|
280
280
|
drawer.setCameraBounds({ minX: -7, maxX: 7, minY: -5, maxY: 5 })
|
|
281
|
-
drawer.drawElements(circuit, {
|
|
281
|
+
drawer.drawElements(circuit, { drawSoldermask: true })
|
|
282
282
|
|
|
283
283
|
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
284
284
|
import.meta.path,
|
|
@@ -37,7 +37,7 @@ test("pcb keepout with pcb_group_id and subcircuit_id", async () => {
|
|
|
37
37
|
},
|
|
38
38
|
]
|
|
39
39
|
|
|
40
|
-
drawer.drawElements(elements)
|
|
40
|
+
drawer.drawElements(elements, { drawBoardMaterial: true })
|
|
41
41
|
|
|
42
42
|
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
43
43
|
import.meta.path,
|
|
@@ -217,7 +217,7 @@ test("draw plated holes with positive and negative soldermask margins", async ()
|
|
|
217
217
|
]
|
|
218
218
|
|
|
219
219
|
drawer.setCameraBounds({ minX: -8, maxX: 8, minY: -6.5, maxY: 6.5 })
|
|
220
|
-
drawer.drawElements(circuit, {
|
|
220
|
+
drawer.drawElements(circuit, { drawSoldermask: true })
|
|
221
221
|
|
|
222
222
|
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
223
223
|
import.meta.path,
|
|
@@ -34,7 +34,7 @@ test("draw circular plated hole", async () => {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
drawer.setCameraBounds({ minX: 0, maxX: 100, minY: 0, maxY: 100 })
|
|
37
|
-
drawer.drawElements([board, hole])
|
|
37
|
+
drawer.drawElements([board, hole], { drawBoardMaterial: true })
|
|
38
38
|
|
|
39
39
|
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
40
40
|
import.meta.path,
|
|
@@ -75,7 +75,7 @@ test("draw oval plated hole", async () => {
|
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
drawer.setCameraBounds({ minX: 0, maxX: 100, minY: 0, maxY: 100 })
|
|
78
|
-
drawer.drawElements([board, hole])
|
|
78
|
+
drawer.drawElements([board, hole], { drawBoardMaterial: true })
|
|
79
79
|
|
|
80
80
|
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
81
81
|
import.meta.path,
|
|
@@ -117,7 +117,7 @@ test("draw pill plated hole", async () => {
|
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
drawer.setCameraBounds({ minX: 0, maxX: 100, minY: 0, maxY: 100 })
|
|
120
|
-
drawer.drawElements([board, hole])
|
|
120
|
+
drawer.drawElements([board, hole], { drawBoardMaterial: true })
|
|
121
121
|
|
|
122
122
|
await expect(canvas.toBuffer("image/png")).toMatchPngSnapshot(
|
|
123
123
|
import.meta.path,
|