Compare commits

..
Author SHA1 Message Date
David Stadelmann f4ebf30a08 chore: update minimum compiler version to 0.15.0 2026-07-01 11:10:01 +02:00
David Stadelmann 5a0893c7c3 deps: update tidy to 0.4.3 2026-07-01 11:09:49 +02:00
David Stadelmann d0b906ae07 deps: update CeTZ 0.3.4 to 0.5.2 with coordinate fixes
CeTZ 0.5.2 requires 3D coordinate vectors (x, y, z) for raw
coordinate tuples passed to coordinate.resolve(). Update internal
wire computations (dodge, guided) to use 3-element tuples, fix
.last() to .at(1) for y-component access on resolved coordinates,
and add a normalize-coord utility that automatically pads user-
provided 2D points (x, y) to (x, y, 0) so users do not need to
specify the z dimension.
2026-07-01 11:09:39 +02:00
9 changed files with 7021 additions and 7654 deletions

No files matched your search

+1 -1
View File
@@ -3,7 +3,7 @@
Circuiteria is a [Typst](https://typst.app) package for drawing block circuit diagrams using the [CeTZ](https://typst.app/universe/package/cetz) package. Circuiteria is a [Typst](https://typst.app) package for drawing block circuit diagrams using the [CeTZ](https://typst.app/universe/package/cetz) package.
<p align="center"> <p align="center">
<img src="./gallery/platypus.png" alt="A platypus / Perry the Platypus meme made with colored rounded rectangles"> <img src="./gallery/platypus.png" alt="Perry the platypus" alt="A platypus / Perry the Platypus meme made with colored rounded rectangles">
</p> </p>
## Examples ## Examples
-30
View File
@@ -1,30 +0,0 @@
// Demonstrates the `(from: <anchor>, to: <port-id>)` port-alignment shorthand
// for the `x` parameter (analogous to the existing shorthand for `y`).
#import "/src/lib.typ": circuit, element, util, wire
#set page(width: auto, height: auto, margin: .5cm)
#circuit({
// Anchor block: absolute placement, with a single "addr" port on its
// north side (auto-centred horizontally by circuiteria).
element.block(
x: 0, y: 0, w: 2, h: 1.5,
id: "vcemem",
fill: util.colors.orange,
ports: (north: ((id: "addr"),), east: ((id: "out"),))
)
// This block's "addr" port (south side) is x-aligned with vcemem's "addr"
// port (north side), even though B is wider than vcemem and not
// horizontally aligned by default.
element.block(
x: (from: "vcemem-port-addr", to: "addr"),
y: (rel: 2, to: "vcemem.north"),
w: 4.5, h: 1,
id: "fsm",
fill: util.colors.yellow,
ports: (south: ((id: "addr"),), east: ((id: "out"),))
)
wire.wire("wAddr", ("vcemem-port-addr", "fsm-port-addr"), style: "zigzag")
})
Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

-46
View File
@@ -1,46 +0,0 @@
// Demonstrates the `(rel: <number>, to: <anchor>)` shorthand for the `y`
// parameter (analogous to the existing shorthand for `x`).
#import "/src/lib.typ": circuit, element, util, wire
#set page(width: auto, height: auto, margin: .5cm)
#circuit({
// Anchor block: absolute placement.
element.block(
x: 0, y: 0, w: 2, h: 1.5,
id: "A",
fill: util.colors.orange,
ports: (east: ((id: "out"),))
)
// X relative, Y absolute (existing feature).
element.block(
x: (rel: 1, to: "A.east"), y: 0, w: 2, h: 1.5,
id: "B",
fill: util.colors.yellow,
ports: (west: ((id: "in"),), east: ((id: "out"),))
)
// Both X and Y relative to another element's anchor (new feature).
element.block(
x: (rel: 1, to: "B.east"),
y: (rel: 2, to: "B.south-west"),
w: 2, h: 1.5,
id: "C",
fill: util.colors.green,
ports: (west: ((id: "in"),))
)
// Y relative only, X absolute.
element.block(
x: 0,
y: (rel: -2.5, to: "A.south-west"),
w: 2, h: 1.5,
id: "D",
fill: util.colors.blue,
ports: (east: ((id: "out"),))
)
wire.wire("wAB", ("A-port-out", "B-port-in"))
wire.wire("wBC", ("B-port-out", "C-port-in"), style: "zigzag")
})
+7003 -7503
View File
File diff suppressed because it is too large. Load diff
+7 -44
View File
@@ -21,14 +21,10 @@
/// - draw-shape (function): Draw function /// - draw-shape (function): Draw function
/// - x (number, dictionary): The x position (bottom-left corner). /// - x (number, dictionary): The x position (bottom-left corner).
/// ///
/// If it is a dictionary, it can take one of two forms: /// If it is a dictionary, it should be in the format `(rel: number, to: str)`, where `rel` is the offset and `to` the base anchor
/// - `(rel: number, to: str)`: `rel` is the x offset and `to` the base anchor
/// - `(from: str, to: str)`: `from` is the base anchor and `to` is the id of the port to align with the anchor (analogous to `y`)
/// - y (number, dictionary): The y position (bottom-left corner). /// - y (number, dictionary): The y position (bottom-left corner).
/// ///
/// If it is a dictionary, it can take one of two forms: /// If it is a dictionary, it should be in the format `(from: str, to: str)`, where `from` is the base anchor and `to` is the id of the port to align with the anchor
/// - `(rel: number, to: str)`: `rel` is the y offset and `to` the base anchor (analogous to `x`)
/// - `(from: str, to: str)`: `from` is the base anchor and `to` is the id of the port to align with the anchor
/// - w (number): Width of the element /// - w (number): Width of the element
/// - h (number): Height of the element /// - h (number): Height of the element
/// - name (none, str): Optional name of the block /// - name (none, str): Optional name of the block
@@ -43,7 +39,6 @@
/// - stroke (stroke): Border stroke /// - stroke (stroke): Border stroke
/// - id (str): The block id (for future reference) /// - id (str): The block id (for future reference)
/// - auto-ports (bool): Whether to use auto port placements or not. If false, `draw-shape` is responsible for adding the appropiate ports /// - auto-ports (bool): Whether to use auto port placements or not. If false, `draw-shape` is responsible for adding the appropiate ports
/// - ports-x (dictionary): Dictionary of the ports x offsets (used with `auto-ports: false`)
/// - ports-y (dictionary): Dictionary of the ports y offsets (used with `auto-ports: false`) /// - ports-y (dictionary): Dictionary of the ports y offsets (used with `auto-ports: false`)
/// - debug (dictionary): Dictionary of debug options. /// - debug (dictionary): Dictionary of debug options.
/// ///
@@ -63,7 +58,6 @@
stroke: black + 1pt, stroke: black + 1pt,
id: "", id: "",
auto-ports: true, auto-ports: true,
ports-x: (:),
ports-y: (:), ports-y: (:),
debug: ( debug: (
ports: false ports: false
@@ -79,45 +73,14 @@
if w == none { panic("Parameter w must be set") } if w == none { panic("Parameter w must be set") }
if h == none { panic("Parameter h must be set") } if h == none { panic("Parameter h must be set") }
if (type(x) == dictionary and "rel" in x) { if (type(x) == dictionary) {
x = util.resolve-rel-coord(ctx, x, 0) let offset = x.rel
} else if (type(x) == dictionary) {
let from = x.from
let to = x.to let to = x.to
let (to-side, i) = find-port(ports, to) let (ctx, to-pos) = coordinate.resolve(ctx, (rel: (offset, 0), to: to))
let margins = (0%, 0%) x = to-pos.at(0)
if to-side in ports-margins {
margins = ports-margins.at(to-side)
}
let dx
let left-margin
if to-side in ("north", "south") {
let used-pct = 100% - margins.at(0) - margins.at(1)
let used-width = width * used-pct / 100%
left-margin = width * margins.at(0) / 100%
dx = used-width * (i + 1) / (ports.at(to-side).len() + 1)
if not auto-ports {
left-margin = 0
dx = ports-x.at(to)(width)
}
} else if to-side == "west" {
dx = 0
left-margin = 0
} else if to-side == "east" {
dx = width
left-margin = 0
}
let (ctx, from-pos) = coordinate.resolve(ctx, from)
x = from-pos.at(0) + dx - width + left-margin
} }
if (type(y) == dictionary and "rel" in y) { if (type(y) == dictionary) {
y = util.resolve-rel-coord(ctx, y, 1)
} else if (type(y) == dictionary) {
let from = y.from let from = y.from
let to = y.to let to = y.to
let (to-side, i) = find-port(ports, to) let (to-side, i) = find-port(ports, to)
+5 -5
View File
@@ -1,5 +1,4 @@
#import "/src/cetz.typ": draw, coordinate #import "/src/cetz.typ": draw, coordinate
#import "/src/util.typ"
#import "../ports.typ": add-ports, add-port #import "../ports.typ": add-ports, add-port
#import "../element.typ" #import "../element.typ"
@@ -50,12 +49,13 @@
if h == none { panic("Parameter h must be set") } if h == none { panic("Parameter h must be set") }
if (type(x) == dictionary) { if (type(x) == dictionary) {
x = util.resolve-rel-coord(ctx, x, 0) let offset = x.rel
let to = x.to
let (ctx, to-pos) = coordinate.resolve(ctx, (rel: (offset, 0), to: to))
x = to-pos.at(0)
} }
if (type(y) == dictionary and "rel" in y) { if (type(y) == dictionary) {
y = util.resolve-rel-coord(ctx, y, 1)
} else if (type(y) == dictionary) {
let from = y.from let from = y.from
let to = y.to let to = y.to
+5 -5
View File
@@ -1,5 +1,4 @@
#import "/src/cetz.typ": draw, coordinate #import "/src/cetz.typ": draw, coordinate
#import "/src/util.typ"
#import "../ports.typ": add-ports, add-port #import "../ports.typ": add-ports, add-port
#import "../element.typ" #import "../element.typ"
@@ -61,12 +60,13 @@
if h == none { panic("Parameter h must be set") } if h == none { panic("Parameter h must be set") }
if (type(x) == dictionary) { if (type(x) == dictionary) {
x = util.resolve-rel-coord(ctx, x, 0) let offset = x.rel
let to = x.to
let (ctx, to-pos) = coordinate.resolve(ctx, (rel: (offset, 0), to: to))
x = to-pos.at(0)
} }
if (type(y) == dictionary and "rel" in y) { if (type(y) == dictionary) {
y = util.resolve-rel-coord(ctx, y, 1)
} else if (type(y) == dictionary) {
let from = y.from let from = y.from
let to = y.to let to = y.to
-20
View File
@@ -1,23 +1,3 @@
#import "cetz.typ": coordinate
/// Resolves a relative coordinate shorthand of the form `(rel: <number>, to: <anchor>)`
/// to a single scalar along the requested axis.
///
/// Used to implement the shared `(rel:, to:)` shorthand accepted by the `x` and
/// `y` parameters of `elmt`, `gate` and `iec-gate`.
///
/// - ctx (dictionary): The current CeTZ context
/// - val (dictionary): A dictionary with fields `rel` (number) and `to` (anchor)
/// - axis (int): `0` for x, `1` for y
/// -> number
#let resolve-rel-coord(ctx, val, axis) = {
let offset = val.rel
let to = val.to
let delta = if axis == 0 { (offset, 0) } else { (0, offset) }
let (_, to-pos) = coordinate.resolve(ctx, (rel: delta, to: to))
return to-pos.at(axis)
}
/// Predefined color palette /// Predefined color palette
/// #let w = 4 /// #let w = 4
/// #box(width: 100%, align(center)[ /// #box(width: 100%, align(center)[