feat: add support for rendering silkscreen knockout text.#654
feat: add support for rendering silkscreen knockout text.#654nailoo wants to merge 3 commits intotscircuit:mainfrom
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
| @@ -0,0 +1,74 @@ | |||
| import type { AnyCircuitElement } from "circuit-json" | |||
There was a problem hiding this comment.
We don't use primitives to render any more, if knock out is supported in circuit to canvas it should render remove convert to primitives file
There was a problem hiding this comment.
Pull request overview
Adds support for “knockout” rendering on silkscreen text in the PCB viewer, and includes an example fixture to demonstrate the behavior.
Changes:
- Add a
pcb_silkscreen_text→ primitive converter that preserves knockout-related fields (is_knockout,knockout_padding). - Add a new example fixture showcasing silkscreen knockout text behavior.
- Bump
circuit-to-canvasdependency version.
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
src/lib/element-to-primitive/convert-pcb-silkscreen-text-to-primitive.ts |
Introduces a converter intended to map silkscreen text elements into text primitives, including knockout settings. |
src/examples/2025/silkscreen-knockout.fixture.tsx |
Adds a visual example to validate silkscreen knockout text rendering. |
package.json |
Updates circuit-to-canvas to ^0.0.71. |
bun.lock |
Locks updated circuit-to-canvas version. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| import type { AnyCircuitElement } from "circuit-json" | ||
| import { distance } from "circuit-json" | ||
| import type { PcbSilkscreenText } from "circuit-json" | ||
| import type { Primitive } from "../types" | ||
| import { getNewPcbDrawingObjectId } from "../convert-element-to-primitive" | ||
|
|
||
| type MetaData = { | ||
| _parent_pcb_component?: any | ||
| _parent_source_component?: any | ||
| _source_port?: any | ||
| } | ||
|
|
||
| export const convertPcbSilkscreenTextToPrimitive = ( | ||
| element: AnyCircuitElement, | ||
| metadata: MetaData, | ||
| ): (Primitive & MetaData)[] => { | ||
| const { _parent_pcb_component, _parent_source_component } = metadata | ||
| const silkscreenText = element as PcbSilkscreenText | ||
|
|
||
| const fontSize = | ||
| typeof silkscreenText.font_size === "string" | ||
| ? distance.parse(silkscreenText.font_size) | ||
| : (silkscreenText.font_size ?? 0.2) | ||
|
|
||
| // Parse knockout padding if provided | ||
| let knockoutPadding: | ||
| | { | ||
| left: number | ||
| top: number | ||
| bottom: number | ||
| right: number | ||
| } | ||
| | undefined | ||
| if (silkscreenText.knockout_padding) { | ||
| knockoutPadding = { | ||
| left: | ||
| typeof silkscreenText.knockout_padding.left === "string" | ||
| ? distance.parse(silkscreenText.knockout_padding.left) | ||
| : silkscreenText.knockout_padding.left, | ||
| top: | ||
| typeof silkscreenText.knockout_padding.top === "string" | ||
| ? distance.parse(silkscreenText.knockout_padding.top) | ||
| : silkscreenText.knockout_padding.top, | ||
| bottom: | ||
| typeof silkscreenText.knockout_padding.bottom === "string" | ||
| ? distance.parse(silkscreenText.knockout_padding.bottom) | ||
| : silkscreenText.knockout_padding.bottom, | ||
| right: | ||
| typeof silkscreenText.knockout_padding.right === "string" | ||
| ? distance.parse(silkscreenText.knockout_padding.right) | ||
| : silkscreenText.knockout_padding.right, | ||
| } | ||
| } | ||
|
|
||
| return [ | ||
| { | ||
| _pcb_drawing_object_id: getNewPcbDrawingObjectId("text"), | ||
| pcb_drawing_type: "text", | ||
| x: silkscreenText.anchor_position.x, | ||
| y: silkscreenText.anchor_position.y, | ||
| layer: silkscreenText.layer, // "top", "bottom" | ||
| align: silkscreenText.anchor_alignment ?? "center", | ||
| text: silkscreenText.text, | ||
| size: fontSize, | ||
| ccw_rotation: silkscreenText.ccw_rotation, | ||
| is_mirrored: silkscreenText.is_mirrored, | ||
| is_knockout: silkscreenText.is_knockout, | ||
| knockout_padding: knockoutPadding, | ||
| _element: element, | ||
| _parent_pcb_component, | ||
| _parent_source_component, | ||
| }, | ||
| ] | ||
| } |
There was a problem hiding this comment.
convertPcbSilkscreenTextToPrimitive is currently dead code: it isn’t imported anywhere and convertElementToPrimitives has no pcb_silkscreen_text case, so these primitives will never be produced. Either wire this converter into the element-to-primitive pipeline (and ensure silkscreen text isn’t also drawn via drawSilkscreenElementsForLayer to avoid double-rendering), or remove this file if circuit-to-canvas is intended to handle knockout rendering directly.
| import type { AnyCircuitElement } from "circuit-json" | |
| import { distance } from "circuit-json" | |
| import type { PcbSilkscreenText } from "circuit-json" | |
| import type { Primitive } from "../types" | |
| import { getNewPcbDrawingObjectId } from "../convert-element-to-primitive" | |
| type MetaData = { | |
| _parent_pcb_component?: any | |
| _parent_source_component?: any | |
| _source_port?: any | |
| } | |
| export const convertPcbSilkscreenTextToPrimitive = ( | |
| element: AnyCircuitElement, | |
| metadata: MetaData, | |
| ): (Primitive & MetaData)[] => { | |
| const { _parent_pcb_component, _parent_source_component } = metadata | |
| const silkscreenText = element as PcbSilkscreenText | |
| const fontSize = | |
| typeof silkscreenText.font_size === "string" | |
| ? distance.parse(silkscreenText.font_size) | |
| : (silkscreenText.font_size ?? 0.2) | |
| // Parse knockout padding if provided | |
| let knockoutPadding: | |
| | { | |
| left: number | |
| top: number | |
| bottom: number | |
| right: number | |
| } | |
| | undefined | |
| if (silkscreenText.knockout_padding) { | |
| knockoutPadding = { | |
| left: | |
| typeof silkscreenText.knockout_padding.left === "string" | |
| ? distance.parse(silkscreenText.knockout_padding.left) | |
| : silkscreenText.knockout_padding.left, | |
| top: | |
| typeof silkscreenText.knockout_padding.top === "string" | |
| ? distance.parse(silkscreenText.knockout_padding.top) | |
| : silkscreenText.knockout_padding.top, | |
| bottom: | |
| typeof silkscreenText.knockout_padding.bottom === "string" | |
| ? distance.parse(silkscreenText.knockout_padding.bottom) | |
| : silkscreenText.knockout_padding.bottom, | |
| right: | |
| typeof silkscreenText.knockout_padding.right === "string" | |
| ? distance.parse(silkscreenText.knockout_padding.right) | |
| : silkscreenText.knockout_padding.right, | |
| } | |
| } | |
| return [ | |
| { | |
| _pcb_drawing_object_id: getNewPcbDrawingObjectId("text"), | |
| pcb_drawing_type: "text", | |
| x: silkscreenText.anchor_position.x, | |
| y: silkscreenText.anchor_position.y, | |
| layer: silkscreenText.layer, // "top", "bottom" | |
| align: silkscreenText.anchor_alignment ?? "center", | |
| text: silkscreenText.text, | |
| size: fontSize, | |
| ccw_rotation: silkscreenText.ccw_rotation, | |
| is_mirrored: silkscreenText.is_mirrored, | |
| is_knockout: silkscreenText.is_knockout, | |
| knockout_padding: knockoutPadding, | |
| _element: element, | |
| _parent_pcb_component, | |
| _parent_source_component, | |
| }, | |
| ] | |
| } | |
| // This file is intentionally left empty. | |
| // PCB silkscreen text primitives are handled elsewhere in the rendering pipeline. |
| @@ -0,0 +1,66 @@ | |||
| import type React from "react" | |||
| import { PCBViewer } from "../../PCBViewer" | |||
| import { AnyCircuitElement } from "circuit-json" | |||
There was a problem hiding this comment.
AnyCircuitElement is only used as a type (in the as AnyCircuitElement[] assertion), but it’s imported as a runtime value. With the current toolchain (tsup/SWC) this can accidentally generate a runtime import for a type-only symbol and fail at runtime if circuit-json doesn’t export it as a value. Switch to a type-only import (import type { AnyCircuitElement } from "circuit-json") to match the existing fixtures and avoid potential runtime issues.
| import { AnyCircuitElement } from "circuit-json" | |
| import type { AnyCircuitElement } from "circuit-json" |
No description provided.