circuit-to-canvas 0.0.17 → 0.0.19

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.
Files changed (37) hide show
  1. package/dist/index.d.ts +32 -8
  2. package/dist/index.js +179 -13
  3. package/lib/drawer/CircuitToCanvasDrawer.ts +14 -2
  4. package/lib/drawer/elements/index.ts +5 -0
  5. package/lib/drawer/elements/pcb-copper-text.ts +2 -2
  6. package/lib/drawer/elements/pcb-note-dimension.ts +201 -0
  7. package/lib/drawer/shapes/arrow.ts +36 -0
  8. package/lib/drawer/shapes/index.ts +1 -0
  9. package/lib/drawer/shapes/text/getAlphabetLayout.ts +41 -0
  10. package/lib/drawer/shapes/text/getTextStartPosition.ts +53 -0
  11. package/lib/drawer/shapes/text/index.ts +3 -0
  12. package/lib/drawer/shapes/{text.ts → text/text.ts} +5 -104
  13. package/package.json +2 -1
  14. package/tests/board-snapshot/__snapshots__/usb-c-flashlight-board.snap.png +0 -0
  15. package/tests/board-snapshot/usb-c-flashlight-board.test.ts +15 -0
  16. package/tests/board-snapshot/usb-c-flashlight.json +2456 -0
  17. package/tests/elements/__snapshots__/fabrication-note-text-descenders.snap.png +0 -0
  18. package/tests/elements/__snapshots__/fabrication-note-text-full-charset.snap.png +0 -0
  19. package/tests/elements/__snapshots__/pcb-fabrication-note-text-rgba-color.snap.png +0 -0
  20. package/tests/elements/__snapshots__/pcb-fabrication-note-text-small.snap.png +0 -0
  21. package/tests/elements/__snapshots__/pcb-note-dimension-angled-and-vertical.snap.png +0 -0
  22. package/tests/elements/__snapshots__/pcb-note-dimension-basic.snap.png +0 -0
  23. package/tests/elements/__snapshots__/pcb-note-dimension-vertical.snap.png +0 -0
  24. package/tests/elements/__snapshots__/pcb-note-dimension-with-offset.snap.png +0 -0
  25. package/tests/elements/__snapshots__/pcb-note-text-anchor-alignment.snap.png +0 -0
  26. package/tests/elements/__snapshots__/pcb-note-text-custom-color.snap.png +0 -0
  27. package/tests/elements/__snapshots__/pcb-note-text-small.snap.png +0 -0
  28. package/tests/elements/pcb-note-dimension-angled-and-vertical.test.ts +37 -0
  29. package/tests/elements/pcb-note-dimension-basic.test.ts +36 -0
  30. package/tests/elements/pcb-note-dimension-vertical.test.ts +42 -0
  31. package/tests/elements/pcb-note-dimension-with-offset.test.ts +38 -0
  32. package/tests/fixtures/assets/label-circuit-to-canvas.png +0 -0
  33. package/tests/fixtures/assets/label-circuit-to-svg.png +0 -0
  34. package/tests/fixtures/getStackedPngSvgComparison.ts +62 -0
  35. package/tests/fixtures/stackPngsVertically.ts +82 -0
  36. package/tests/shapes/__snapshots__/oval.snap.png +0 -0
  37. package/tsconfig.json +1 -0
@@ -0,0 +1,41 @@
1
+ export const GLYPH_WIDTH_RATIO = 0.62
2
+ export const LETTER_SPACING_RATIO = 0.3 // Letter spacing between characters (25% of glyph width)
3
+ export const SPACE_WIDTH_RATIO = 1
4
+ export const STROKE_WIDTH_RATIO = 0.13
5
+
6
+ export type AlphabetLayout = {
7
+ width: number
8
+ height: number
9
+ glyphWidth: number
10
+ letterSpacing: number
11
+ spaceWidth: number
12
+ strokeWidth: number
13
+ }
14
+
15
+ export function getAlphabetLayout(
16
+ text: string,
17
+ fontSize: number,
18
+ ): AlphabetLayout {
19
+ const glyphWidth = fontSize * GLYPH_WIDTH_RATIO
20
+ const letterSpacing = glyphWidth * LETTER_SPACING_RATIO
21
+ const spaceWidth = glyphWidth * SPACE_WIDTH_RATIO
22
+ const characters = Array.from(text)
23
+
24
+ let width = 0
25
+ characters.forEach((char, index) => {
26
+ const advance = char === " " ? spaceWidth : glyphWidth
27
+ width += advance
28
+ if (index < characters.length - 1) width += letterSpacing
29
+ })
30
+
31
+ const strokeWidth = Math.max(fontSize * STROKE_WIDTH_RATIO, 0.35)
32
+
33
+ return {
34
+ width,
35
+ height: fontSize,
36
+ glyphWidth,
37
+ letterSpacing,
38
+ spaceWidth,
39
+ strokeWidth,
40
+ }
41
+ }
@@ -0,0 +1,53 @@
1
+ import type { NinePointAnchor } from "circuit-json"
2
+ import type { AlphabetLayout } from "./getAlphabetLayout"
3
+
4
+ export type AnchorAlignment = NinePointAnchor
5
+
6
+ export function getTextStartPosition(
7
+ alignment: NinePointAnchor,
8
+ layout: AlphabetLayout,
9
+ ): { x: number; y: number } {
10
+ const totalWidth = layout.width + layout.strokeWidth
11
+ const totalHeight = layout.height + layout.strokeWidth
12
+
13
+ let x = 0
14
+ let y = 0
15
+
16
+ // Horizontal alignment
17
+ if (alignment === "center") {
18
+ x = -totalWidth / 2
19
+ } else if (
20
+ alignment === "top_left" ||
21
+ alignment === "bottom_left" ||
22
+ alignment === "center_left"
23
+ ) {
24
+ x = 0
25
+ } else if (
26
+ alignment === "top_right" ||
27
+ alignment === "bottom_right" ||
28
+ alignment === "center_right"
29
+ ) {
30
+ x = -totalWidth
31
+ }
32
+
33
+ // Vertical alignment
34
+ if (alignment === "center") {
35
+ y = -totalHeight / 2
36
+ } else if (
37
+ alignment === "top_left" ||
38
+ alignment === "top_right" ||
39
+ alignment === "top_center"
40
+ ) {
41
+ y = 0
42
+ } else if (
43
+ alignment === "bottom_left" ||
44
+ alignment === "bottom_right" ||
45
+ alignment === "bottom_center"
46
+ ) {
47
+ y = -totalHeight
48
+ } else {
49
+ y = 0
50
+ }
51
+
52
+ return { x, y }
53
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./text"
2
+ export * from "./getAlphabetLayout"
3
+ export * from "./getTextStartPosition"
@@ -1,113 +1,14 @@
1
1
  import { lineAlphabet } from "@tscircuit/alphabet"
2
2
  import type { Matrix } from "transformation-matrix"
3
3
  import { applyToPoint } from "transformation-matrix"
4
- import type { CanvasContext } from "../types"
5
-
6
- const GLYPH_WIDTH_RATIO = 0.62
7
- const LETTER_SPACING_RATIO = 0.3 // Letter spacing between characters (25% of glyph width)
8
- const SPACE_WIDTH_RATIO = 1
9
- const STROKE_WIDTH_RATIO = 0.13
10
-
11
- export type AlphabetLayout = {
12
- width: number
13
- height: number
14
- glyphWidth: number
15
- letterSpacing: number
16
- spaceWidth: number
17
- strokeWidth: number
18
- }
19
-
20
- export function getAlphabetLayout(
21
- text: string,
22
- fontSize: number,
23
- ): AlphabetLayout {
24
- const glyphWidth = fontSize * GLYPH_WIDTH_RATIO
25
- const letterSpacing = glyphWidth * LETTER_SPACING_RATIO
26
- const spaceWidth = glyphWidth * SPACE_WIDTH_RATIO
27
- const characters = Array.from(text)
28
-
29
- let width = 0
30
- characters.forEach((char, index) => {
31
- const advance = char === " " ? spaceWidth : glyphWidth
32
- width += advance
33
- if (index < characters.length - 1) width += letterSpacing
34
- })
35
-
36
- const strokeWidth = Math.max(fontSize * STROKE_WIDTH_RATIO, 0.35)
37
-
38
- return {
39
- width,
40
- height: fontSize,
41
- glyphWidth,
42
- letterSpacing,
43
- spaceWidth,
44
- strokeWidth,
45
- }
46
- }
4
+ import type { CanvasContext } from "../../types"
5
+ import type { NinePointAnchor } from "circuit-json"
6
+ import { getAlphabetLayout, type AlphabetLayout } from "./getAlphabetLayout"
7
+ import { getTextStartPosition } from "./getTextStartPosition"
47
8
 
48
9
  const getGlyphLines = (char: string) =>
49
10
  lineAlphabet[char] ?? lineAlphabet[char.toUpperCase()]
50
11
 
51
- export type AnchorAlignment =
52
- | "center"
53
- | "top_left"
54
- | "top_right"
55
- | "bottom_left"
56
- | "bottom_right"
57
- | "left"
58
- | "right"
59
- | "top"
60
- | "bottom"
61
-
62
- export function getTextStartPosition(
63
- alignment: AnchorAlignment,
64
- layout: AlphabetLayout,
65
- ): { x: number; y: number } {
66
- const totalWidth = layout.width + layout.strokeWidth
67
- const totalHeight = layout.height + layout.strokeWidth
68
-
69
- let x = 0
70
- let y = 0
71
-
72
- // Horizontal alignment
73
- if (alignment === "center") {
74
- x = -totalWidth / 2
75
- } else if (
76
- alignment === "top_left" ||
77
- alignment === "bottom_left" ||
78
- alignment === "left"
79
- ) {
80
- x = 0
81
- } else if (
82
- alignment === "top_right" ||
83
- alignment === "bottom_right" ||
84
- alignment === "right"
85
- ) {
86
- x = -totalWidth
87
- }
88
-
89
- // Vertical alignment
90
- if (alignment === "center") {
91
- y = -totalHeight / 2
92
- } else if (
93
- alignment === "top_left" ||
94
- alignment === "top_right" ||
95
- alignment === "top"
96
- ) {
97
- y = 0
98
- } else if (
99
- alignment === "bottom_left" ||
100
- alignment === "bottom_right" ||
101
- alignment === "bottom"
102
- ) {
103
- y = -totalHeight
104
- } else {
105
- y = 0
106
- }
107
-
108
- return { x, y }
109
- }
110
-
111
12
  export function strokeAlphabetText(
112
13
  ctx: CanvasContext,
113
14
  text: string,
@@ -154,7 +55,7 @@ export interface DrawTextParams {
154
55
  fontSize: number
155
56
  color: string
156
57
  realToCanvasMat: Matrix
157
- anchorAlignment: AnchorAlignment
58
+ anchorAlignment: NinePointAnchor
158
59
  rotation?: number
159
60
  }
160
61
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "circuit-to-canvas",
3
3
  "main": "dist/index.js",
4
- "version": "0.0.17",
4
+ "version": "0.0.19",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "build": "tsup-node ./lib/index.ts --format esm --dts",
@@ -20,6 +20,7 @@
20
20
  "circuit-json": "^0.0.335",
21
21
  "circuit-json-to-connectivity-map": "^0.0.23",
22
22
  "circuit-to-svg": "^0.0.297",
23
+ "looks-same": "^10.0.1",
23
24
  "schematic-symbols": "^0.0.202",
24
25
  "tsup": "^8.5.1"
25
26
  },
@@ -0,0 +1,15 @@
1
+ import { expect, test } from "bun:test"
2
+ import type { AnyCircuitElement } from "circuit-json"
3
+ import { getStackedPngSvgComparison } from "../fixtures/getStackedPngSvgComparison"
4
+ import usbcFlashlightCircuit from "./usb-c-flashlight.json"
5
+
6
+ const circuitElements = usbcFlashlightCircuit as AnyCircuitElement[]
7
+
8
+ test.skip("USB-C flashlight - comprehensive comparison (circuit-to-canvas vs circuit-to-svg)", async () => {
9
+ const stackedPng = await getStackedPngSvgComparison(circuitElements, {
10
+ width: 400,
11
+ height: 800,
12
+ })
13
+
14
+ await expect(stackedPng).toMatchPngSnapshot(import.meta.path)
15
+ })