Skip to content

feat: add support for rendering silkscreen knockout text.#654

Open
nailoo wants to merge 3 commits intotscircuit:mainfrom
nailoo:knockout
Open

feat: add support for rendering silkscreen knockout text.#654
nailoo wants to merge 3 commits intotscircuit:mainfrom
nailoo:knockout

Conversation

@nailoo
Copy link
Copy Markdown
Contributor

@nailoo nailoo commented Feb 9, 2026

No description provided.

@vercel
Copy link
Copy Markdown

vercel bot commented Feb 9, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
pcb-viewer Ready Ready Preview, Comment Feb 9, 2026 6:34am

Request Review

@@ -0,0 +1,74 @@
import type { AnyCircuitElement } from "circuit-json"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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-canvas dependency 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.

Comment on lines +1 to +74
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,
},
]
}
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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.

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,66 @@
import type React from "react"
import { PCBViewer } from "../../PCBViewer"
import { AnyCircuitElement } from "circuit-json"
Copy link

Copilot AI Feb 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
import { AnyCircuitElement } from "circuit-json"
import type { AnyCircuitElement } from "circuit-json"

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants