Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c14e2ceab9 | ||
|
|
13e3fee913 | ||
|
|
df4c956a0b | ||
|
|
ac087087c5 | ||
|
|
77eb4fa946 | ||
|
|
c9aa81af2e | ||
|
|
6871053810 | ||
|
|
73b7348eed
|
||
|
|
b71e822bb8
|
||
|
|
4c1025b1eb
|
||
|
|
b35c04a7d9
|
||
|
|
0612e9b6ec
|
No files matched your search
@@ -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="Perry the platypus">
|
<img src="./gallery/platypus.png" alt="A platypus / Perry the Platypus meme made with colored rounded rectangles">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
@@ -11,17 +11,17 @@ Circuiteria is a [Typst](https://typst.app) package for drawing block circuit di
|
|||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<a href="./gallery/test.typ">
|
<a href="./gallery/test.typ">
|
||||||
<img src="./gallery/test.png" width="500px">
|
<img src="./gallery/test.png" width="500px" alt="Block diagram of a multi-cycle RISC-V FPGA processor">
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">A bit of eveything</td>
|
<td colspan="2">A bit of everything</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<a href="./gallery/test5.typ">
|
<a href="./gallery/test5.typ">
|
||||||
<img src="./gallery/test5.png" width="500px">
|
<img src="./gallery/test5.png" width="500px" alt="Block diagram of a single-cycle RISC-V processor">
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -31,12 +31,12 @@ Circuiteria is a [Typst](https://typst.app) package for drawing block circuit di
|
|||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<a href="./gallery/test4.typ">
|
<a href="./gallery/test4.typ">
|
||||||
<img src="./gallery/test4.png" width="250px">
|
<img src="./gallery/test4.png" width="250px" alt="Top-level block diagram of a single-cycle RISC-V processor">
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="./gallery/test6.typ">
|
<a href="./gallery/test6.typ">
|
||||||
<img src="./gallery/test6.png" width="250px">
|
<img src="./gallery/test6.png" width="250px" alt="Block diagram of a simple single-cycle RISC-V ALU">
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -56,7 +56,7 @@ For more information, see the [manual](manual.pdf)
|
|||||||
|
|
||||||
To use this package, simply import [circuiteria](https://typst.app/universe/package/circuiteria) and call the `circuit` function:
|
To use this package, simply import [circuiteria](https://typst.app/universe/package/circuiteria) and call the `circuit` function:
|
||||||
```typ
|
```typ
|
||||||
#import "@preview/circuiteria:0.2.0"
|
#import "@preview/circuiteria:0.2.1"
|
||||||
#circuiteria.circuit({
|
#circuiteria.circuit({
|
||||||
import circuiteria: *
|
import circuiteria: *
|
||||||
...
|
...
|
||||||
|
|||||||
@@ -186,6 +186,48 @@ wire.wire("w2", ("b2-port-out", "b3-port-in2"),
|
|||||||
style: "zigzag")
|
style: "zigzag")
|
||||||
```)
|
```)
|
||||||
|
|
||||||
|
#let group-ports = example(```
|
||||||
|
// outside-port-names: true (default) — labels outside the border
|
||||||
|
element.group(
|
||||||
|
id: "g1", name: "outside (default)",
|
||||||
|
stroke: (dash: "dashed"),
|
||||||
|
fill: util.colors.blue.lighten(60%),
|
||||||
|
padding: 2em,
|
||||||
|
outside-port-names: true,
|
||||||
|
port-name-padding: 4pt,
|
||||||
|
ports: (
|
||||||
|
west: ((id: "in", name: "D"),),
|
||||||
|
east: ((id: "out", name: "Q"),),
|
||||||
|
),
|
||||||
|
{ element.block(id: "b1", w: 2, h: 1.5, x: 0, y: 0,
|
||||||
|
fill: util.colors.green,
|
||||||
|
ports: (west: ((id: "d", name: "d"),),
|
||||||
|
east: ((id: "q", name: "q"),))) }
|
||||||
|
)
|
||||||
|
wire.wire("wG1in", ("g1-port-in", "b1-port-d"), directed: true)
|
||||||
|
wire.wire("wG1out", ("b1-port-q", "g1-port-out"), directed: true)
|
||||||
|
|
||||||
|
// outside-port-names: false — labels inside the border (block style)
|
||||||
|
// with extra padding via port-name-padding
|
||||||
|
element.group(
|
||||||
|
id: "g2", name: "inside",
|
||||||
|
stroke: (dash: "dashed"),
|
||||||
|
fill: util.colors.orange.lighten(60%),
|
||||||
|
padding: 2em,
|
||||||
|
outside-port-names: false,
|
||||||
|
port-name-padding: 0.4em,
|
||||||
|
ports: (
|
||||||
|
west: ((id: "in", name: "D"),),
|
||||||
|
east: ((id: "out", name: "Q"),),
|
||||||
|
),
|
||||||
|
{ element.block(id: "b2", w: 2, h: 1.5, x: 6, y: 0,
|
||||||
|
fill: util.colors.green,
|
||||||
|
ports: (west: ((id: "d"),), east: ((id: "q"),))) }
|
||||||
|
)
|
||||||
|
wire.stub("g2-port-in", "west")
|
||||||
|
wire.stub("g2-port-out", "east")
|
||||||
|
```, vertical: true)
|
||||||
|
|
||||||
#let intersection = example(```
|
#let intersection = example(```
|
||||||
wire.wire("w1", ((0, 0), (1, 1)), style: "zigzag")
|
wire.wire("w1", ((0, 0), (1, 1)), style: "zigzag")
|
||||||
wire.wire("w2", ((0, 0), (1, -.5)),
|
wire.wire("w2", ((0, 0), (1, -.5)),
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 11 KiB |
@@ -1,4 +1,4 @@
|
|||||||
#import "../src/lib.typ": *
|
#import "@preview/circuiteria:0.2.1": *
|
||||||
|
|
||||||
#set page(width: auto, height: auto, margin: .5cm)
|
#set page(width: auto, height: auto, margin: .5cm)
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 160 KiB After Width: | Height: | Size: 53 KiB |
@@ -1,4 +1,4 @@
|
|||||||
#import "../src/lib.typ": circuit, element, util, wire
|
#import "@preview/circuiteria:0.2.1": circuit, element, util, wire
|
||||||
|
|
||||||
#set page(width: auto, height: auto, margin: .5cm)
|
#set page(width: auto, height: auto, margin: .5cm)
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 160 KiB After Width: | Height: | Size: 53 KiB |
@@ -1,4 +1,4 @@
|
|||||||
#import "../src/lib.typ": circuit, element, util, wire
|
#import "@preview/circuiteria:0.2.1": circuit, element, util, wire
|
||||||
|
|
||||||
#set page(width: auto, height: auto, margin: .5cm)
|
#set page(width: auto, height: auto, margin: .5cm)
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 23 KiB |
@@ -1,4 +1,4 @@
|
|||||||
#import "../src/lib.typ": circuit, element, util, wire
|
#import "@preview/circuiteria:0.2.1": circuit, element, util, wire
|
||||||
|
|
||||||
#set page(width: auto, height: auto, margin: .5cm)
|
#set page(width: auto, height: auto, margin: .5cm)
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 195 KiB After Width: | Height: | Size: 67 KiB |
@@ -1,5 +1,5 @@
|
|||||||
#import "/src/cetz.typ": draw
|
#import "/src/cetz.typ": draw
|
||||||
#import "../src/lib.typ": *
|
#import "@preview/circuiteria:0.2.1": *
|
||||||
|
|
||||||
#set page(width: auto, height: auto, margin: .5cm)
|
#set page(width: auto, height: auto, margin: .5cm)
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 274 KiB After Width: | Height: | Size: 93 KiB |
@@ -1,5 +1,5 @@
|
|||||||
#import "/src/cetz.typ": draw
|
#import "/src/cetz.typ": draw
|
||||||
#import "../src/lib.typ": *
|
#import "@preview/circuiteria:0.2.1": *
|
||||||
|
|
||||||
#set page(width: auto, height: auto, margin: .5cm)
|
#set page(width: auto, height: auto, margin: .5cm)
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 23 KiB |
@@ -1,5 +1,5 @@
|
|||||||
#import "/src/cetz.typ": draw
|
#import "/src/cetz.typ": draw
|
||||||
#import "../src/lib.typ": *
|
#import "@preview/circuiteria:0.2.1": *
|
||||||
|
|
||||||
#set page(width: auto, height: auto, margin: .5cm)
|
#set page(width: auto, height: auto, margin: .5cm)
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 5.8 KiB |
@@ -1,4 +1,4 @@
|
|||||||
#import "../src/lib.typ": circuit, element, util, wire
|
#import "@preview/circuiteria:0.2.1": circuit, element, util, wire
|
||||||
|
|
||||||
#set page(width: auto, height: auto, margin: .5cm)
|
#set page(width: auto, height: auto, margin: .5cm)
|
||||||
|
|
||||||
|
|||||||
|
After Width: | Height: | Size: 23 KiB |
@@ -0,0 +1,86 @@
|
|||||||
|
// Demonstrates ports on a group element.
|
||||||
|
// outside-port-names: true (default) — labels outside the group border
|
||||||
|
// outside-port-names: false — labels inside (block-style)
|
||||||
|
#import "/src/lib.typ": circuit, element, util, wire
|
||||||
|
|
||||||
|
#set page(width: auto, height: auto, margin: .5cm)
|
||||||
|
|
||||||
|
#circuit({
|
||||||
|
// --- Group with port labels INSIDE (outside-port-names: false) ---
|
||||||
|
element.group(
|
||||||
|
id: "cpu",
|
||||||
|
name: "CPU (labels outside)",
|
||||||
|
name-anchor: "north",
|
||||||
|
stroke: (dash: "dashed"),
|
||||||
|
fill: util.colors.yellow.lighten(60%),
|
||||||
|
padding: 1em,
|
||||||
|
port-name-padding: .5em,
|
||||||
|
outside-port-names: true,
|
||||||
|
ports: (
|
||||||
|
west: (
|
||||||
|
(id: "in1", name: "D1"),
|
||||||
|
(id: "in2", name: "D2"),
|
||||||
|
),
|
||||||
|
east: ((id: "out", name: "Q"),),
|
||||||
|
south: (
|
||||||
|
(id: "rst", name: "RST", vertical: true),
|
||||||
|
(id: "done", name: "DONE", vertical: true),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
{
|
||||||
|
element.block(
|
||||||
|
id: "reg2",
|
||||||
|
w: 2.5,
|
||||||
|
h: 3,
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
fill: util.colors.green,
|
||||||
|
ports: (
|
||||||
|
west: ((id: "d1"), (id: "d2")),
|
||||||
|
east: ((id: "q"),),
|
||||||
|
north: ((id: "clk", clock: true),),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
// --- Group with port labels INSIDE (outside-port-names: false) ---
|
||||||
|
element.group(
|
||||||
|
id: "cpu2",
|
||||||
|
name: "CPU (labels inside)",
|
||||||
|
name-anchor: "north",
|
||||||
|
stroke: (dash: "dashed"),
|
||||||
|
fill: util.colors.yellow.lighten(60%),
|
||||||
|
padding: 4em,
|
||||||
|
outside-port-names: false,
|
||||||
|
port-name-padding: 0.5em,
|
||||||
|
ports: (
|
||||||
|
west: (
|
||||||
|
(id: "in1", name: "D1"),
|
||||||
|
(id: "in2", name: "D2"),
|
||||||
|
),
|
||||||
|
east: ((id: "out", name: "Q"),),
|
||||||
|
south: (
|
||||||
|
(id: "rst", name: "RST", vertical: true),
|
||||||
|
(id: "done", name: "DONE", vertical: true),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
{
|
||||||
|
element.block(
|
||||||
|
id: "reg2",
|
||||||
|
w: 2.5,
|
||||||
|
h: 3,
|
||||||
|
x: 10,
|
||||||
|
y: 0,
|
||||||
|
fill: util.colors.green,
|
||||||
|
ports: (
|
||||||
|
west: ((id: "d1"), (id: "d2")),
|
||||||
|
east: ((id: "q"),),
|
||||||
|
north: ((id: "clk", clock: true),),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
wire.stub("cpu2-port-in1", "west", name: "A")
|
||||||
|
wire.stub("cpu2-port-in2", "west", name: "B")
|
||||||
|
wire.stub("cpu2-port-out", "east", name: "Q")
|
||||||
|
})
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#import "@preview/tidy:0.4.1"
|
#import "@preview/tidy:0.4.3"
|
||||||
#import "/src/cetz.typ": draw, canvas
|
#import "/src/cetz.typ": draw, canvas
|
||||||
#import "src/lib.typ"
|
#import "src/lib.typ"
|
||||||
#import "doc/examples.typ"
|
#import "doc/examples.typ"
|
||||||
@@ -105,7 +105,7 @@ This package provides a way to make beautiful block circuit diagrams using the C
|
|||||||
|
|
||||||
Simply import Circuiteria and call the `circuit` function:
|
Simply import Circuiteria and call the `circuit` function:
|
||||||
#pad(left: 1em)[```typ
|
#pad(left: 1em)[```typ
|
||||||
#import "@preview/circuiteria:0.2.0"
|
#import "@preview/circuiteria:0.2.1"
|
||||||
#circuiteria.circuit({
|
#circuiteria.circuit({
|
||||||
import circuiteria: *
|
import circuiteria: *
|
||||||
...
|
...
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
#import "@preview/cetz:0.3.4": *
|
#import "@preview/cetz:0.5.2": *
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#import "/src/cetz.typ": canvas
|
#import "/src/cetz.typ": canvas
|
||||||
#import "@preview/tidy:0.3.0"
|
#import "@preview/tidy:0.4.3"
|
||||||
|
|
||||||
/// Draws a block circuit diagram
|
/// Draws a block circuit diagram
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -27,6 +27,7 @@
|
|||||||
name-anchor: "center",
|
name-anchor: "center",
|
||||||
ports: (),
|
ports: (),
|
||||||
ports-margins: (),
|
ports-margins: (),
|
||||||
|
port-name-padding: 2pt,
|
||||||
fill: none,
|
fill: none,
|
||||||
radius: 0.5em,
|
radius: 0.5em,
|
||||||
stroke: black + 1pt,
|
stroke: black + 1pt,
|
||||||
@@ -44,6 +45,7 @@
|
|||||||
name-anchor: name-anchor,
|
name-anchor: name-anchor,
|
||||||
ports: ports,
|
ports: ports,
|
||||||
ports-margins: ports-margins,
|
ports-margins: ports-margins,
|
||||||
|
port-name-padding: port-name-padding,
|
||||||
fill: fill,
|
fill: fill,
|
||||||
stroke: stroke,
|
stroke: stroke,
|
||||||
id: id,
|
id: id,
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
/// - `clock` (`bool`): Whether it is a clock port (triangle symbol)
|
/// - `clock` (`bool`): Whether it is a clock port (triangle symbol)
|
||||||
/// - `vertical` (`bool`): Whether the name should be drawn vertically
|
/// - `vertical` (`bool`): Whether the name should be drawn vertically
|
||||||
/// - ports-margins (dictionary): Dictionary of ports margins (used with automatic port placement). They keys are cardinal directions ("north", "east", "south", "west"). The values are tuples of (`<start>`, `<end>`) margins (numbers)
|
/// - ports-margins (dictionary): Dictionary of ports margins (used with automatic port placement). They keys are cardinal directions ("north", "east", "south", "west"). The values are tuples of (`<start>`, `<end>`) margins (numbers)
|
||||||
|
/// - port-name-padding (number, length): Padding between the port name label and the port anchor point (default `2pt`)
|
||||||
/// - fill (none, color): Fill color
|
/// - fill (none, color): Fill color
|
||||||
/// - stroke (stroke): Border stroke
|
/// - stroke (stroke): Border stroke
|
||||||
/// - id (str): The block id (for future reference)
|
/// - id (str): The block id (for future reference)
|
||||||
@@ -54,6 +55,7 @@
|
|||||||
name-anchor: "center",
|
name-anchor: "center",
|
||||||
ports: (:),
|
ports: (:),
|
||||||
ports-margins: (:),
|
ports-margins: (:),
|
||||||
|
port-name-padding: 2pt,
|
||||||
fill: none,
|
fill: none,
|
||||||
stroke: black + 1pt,
|
stroke: black + 1pt,
|
||||||
id: "",
|
id: "",
|
||||||
@@ -139,7 +141,8 @@
|
|||||||
tl, tr, br, bl,
|
tl, tr, br, bl,
|
||||||
ports,
|
ports,
|
||||||
ports-margins,
|
ports-margins,
|
||||||
debug: debug.ports
|
debug: debug.ports,
|
||||||
|
name-padding: port-name-padding,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -1,9 +1,15 @@
|
|||||||
#import "/src/cetz.typ": draw, coordinate
|
#import "/src/cetz.typ": draw, coordinate
|
||||||
#import "../util.typ"
|
#import "../util.typ"
|
||||||
|
#import "ports.typ": add-ports
|
||||||
|
|
||||||
/// Draws a group of elements
|
/// Draws a group of elements
|
||||||
///
|
///
|
||||||
/// #examples.group
|
/// #examples.group
|
||||||
|
///
|
||||||
|
/// Ports can also be defined on a group, just like on a block. By default
|
||||||
|
/// port labels are drawn *outside* the group border so they do not overlap
|
||||||
|
/// child elements. Set `outside-port-names: false` to draw them inside.
|
||||||
|
/// #examples.group-ports
|
||||||
/// - body (elements, function): Elements to group
|
/// - body (elements, function): Elements to group
|
||||||
/// - id (str): see #doc-ref("element.elmt")
|
/// - id (str): see #doc-ref("element.elmt")
|
||||||
/// - name (str): The group's name
|
/// - name (str): The group's name
|
||||||
@@ -16,6 +22,11 @@
|
|||||||
/// - array: either (`<all>`,), (`<vertical>`, `<horizontal>`) or (`<top>`, `<right>`, `<bottom>`, `<left>`)
|
/// - array: either (`<all>`,), (`<vertical>`, `<horizontal>`) or (`<top>`, `<right>`, `<bottom>`, `<left>`)
|
||||||
/// - dictionary: valid keys are "top", "right", "bottom" and "left"
|
/// - dictionary: valid keys are "top", "right", "bottom" and "left"
|
||||||
/// - radius (number): The corner radius
|
/// - radius (number): The corner radius
|
||||||
|
/// - ports (dictionary): see #doc-ref("element.elmt")
|
||||||
|
/// - ports-margins (dictionary): see #doc-ref("element.elmt")
|
||||||
|
/// - outside-port-names (bool): If `true` (default), port name labels are drawn outside the group border so they do not overlap child elements. Set to `false` to draw labels inside, matching the block behaviour
|
||||||
|
/// - port-name-padding (number, length): Padding between the port name label and the group border (default `2pt`). Accepts anything CeTZ accepts as `padding` (number or length)
|
||||||
|
/// - debug (dictionary): see #doc-ref("element.elmt")
|
||||||
#let group(
|
#let group(
|
||||||
body,
|
body,
|
||||||
id: "",
|
id: "",
|
||||||
@@ -24,7 +35,14 @@
|
|||||||
fill: none,
|
fill: none,
|
||||||
stroke: black + 1pt,
|
stroke: black + 1pt,
|
||||||
padding: 0.5em,
|
padding: 0.5em,
|
||||||
radius: 0.5em
|
radius: 0.5em,
|
||||||
|
ports: (:),
|
||||||
|
ports-margins: (:),
|
||||||
|
outside-port-names: true,
|
||||||
|
port-name-padding: 2pt,
|
||||||
|
debug: (
|
||||||
|
ports: false
|
||||||
|
)
|
||||||
) = {
|
) = {
|
||||||
let min-x = none
|
let min-x = none
|
||||||
let max-x = none
|
let max-x = none
|
||||||
@@ -68,6 +86,20 @@
|
|||||||
stroke: stroke,
|
stroke: stroke,
|
||||||
fill: fill
|
fill: fill
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add-ports(
|
||||||
|
id,
|
||||||
|
id + ".north-west",
|
||||||
|
id + ".north-east",
|
||||||
|
id + ".south-east",
|
||||||
|
id + ".south-west",
|
||||||
|
ports,
|
||||||
|
ports-margins,
|
||||||
|
debug: debug.ports,
|
||||||
|
outside-name: outside-port-names,
|
||||||
|
name-padding: port-name-padding,
|
||||||
|
)
|
||||||
|
|
||||||
if name != none {
|
if name != none {
|
||||||
draw.content(
|
draw.content(
|
||||||
id + "." + name-anchor,
|
id + "." + name-anchor,
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
#import "/src/cetz.typ": draw
|
#import "/src/cetz.typ": draw
|
||||||
#import "../util.typ": rotate-anchor
|
#import "../util.typ": rotate-anchor, opposite-anchor
|
||||||
|
|
||||||
#let add-port(
|
#let add-port(
|
||||||
elmt-id, side, port, pos,
|
elmt-id, side, port, pos,
|
||||||
prev: none,
|
prev: none,
|
||||||
next: none,
|
next: none,
|
||||||
debug: false
|
debug: false,
|
||||||
|
outside-name: false,
|
||||||
|
name-padding: 2pt,
|
||||||
) = {
|
) = {
|
||||||
let name = port.at("name", default: "")
|
let name = port.at("name", default: "")
|
||||||
let name-rotate = port.at("vertical", default: false)
|
let name-rotate = port.at("vertical", default: false)
|
||||||
@@ -27,10 +29,22 @@
|
|||||||
// TODO: use context or vectors to have the height relative to the width
|
// TODO: use context or vectors to have the height relative to the width
|
||||||
draw.line(prev, pos1, next)
|
draw.line(prev, pos1, next)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When outside-name is true (e.g. for groups) the label is placed on the
|
||||||
|
// exterior of the element border so it does not overlap child elements.
|
||||||
|
// Horizontal labels: anchor = opposite of the side (e.g. east port → west-anchored text, outside).
|
||||||
|
// Vertical labels: same opposite side but rotated 90°, keeping text readable.
|
||||||
|
let name-anchor = if outside-name {
|
||||||
|
if name-rotate { rotate-anchor(opposite-anchor(side)) }
|
||||||
|
else { opposite-anchor(side) }
|
||||||
|
} else {
|
||||||
|
if name-rotate { rotate-anchor(side) } else { side }
|
||||||
|
}
|
||||||
|
|
||||||
draw.content(
|
draw.content(
|
||||||
pos,
|
pos,
|
||||||
anchor: if name-rotate {rotate-anchor(side)} else {side},
|
anchor: name-anchor,
|
||||||
padding: 2pt,
|
padding: name-padding,
|
||||||
angle: if name-rotate {90deg} else {0deg},
|
angle: if name-rotate {90deg} else {0deg},
|
||||||
name
|
name
|
||||||
)
|
)
|
||||||
@@ -60,7 +74,9 @@
|
|||||||
tl, tr, br, bl,
|
tl, tr, br, bl,
|
||||||
ports,
|
ports,
|
||||||
ports-margins,
|
ports-margins,
|
||||||
debug: false
|
debug: false,
|
||||||
|
outside-name: false,
|
||||||
|
name-padding: 2pt,
|
||||||
) = {
|
) = {
|
||||||
let sides = (
|
let sides = (
|
||||||
"north": (tl, tr),
|
"north": (tl, tr),
|
||||||
@@ -109,7 +125,9 @@
|
|||||||
pos,
|
pos,
|
||||||
prev: pos-prev,
|
prev: pos-prev,
|
||||||
next: pos-next,
|
next: pos-next,
|
||||||
debug: debug
|
debug: debug,
|
||||||
|
outside-name: outside-name,
|
||||||
|
name-padding: name-padding,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#let version = version(0, 2, 0)
|
#let version = version(0, 2, 1)
|
||||||
#let name = "circuiteria"
|
#let name = "circuiteria"
|
||||||
|
|
||||||
#import "circuit.typ": circuit
|
#import "circuit.typ": circuit
|
||||||
|
|||||||
@@ -73,4 +73,45 @@
|
|||||||
#let valid-anchors = (
|
#let valid-anchors = (
|
||||||
"center", "north", "east", "west", "south",
|
"center", "north", "east", "west", "south",
|
||||||
"north-east", "north-west", "south-east", "south-west"
|
"north-east", "north-west", "south-east", "south-west"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/// Normalizes a coordinate so that 2D points (x, y) are padded
|
||||||
|
/// to (x, y, 0) as required by CeTZ's coordinate resolver.
|
||||||
|
/// Also handles function-based and dictionary-based coordinates
|
||||||
|
/// recursively.
|
||||||
|
///
|
||||||
|
/// - coord (any): A CeTZ-compatible coordinate
|
||||||
|
/// -> any
|
||||||
|
#let normalize-coord(coord) = {
|
||||||
|
if type(coord) == array {
|
||||||
|
if coord.len() == 2 {
|
||||||
|
let (a, b) = coord
|
||||||
|
// Raw 2D point: (x, y) -> (x, y, 0)
|
||||||
|
if type(a) in (int, float) and type(b) in (int, float) {
|
||||||
|
return (a, b, 0)
|
||||||
|
}
|
||||||
|
// Function-based coordinate: (fn, point)
|
||||||
|
if type(a) == function {
|
||||||
|
let orig = a
|
||||||
|
return (v => {
|
||||||
|
let result = orig(v)
|
||||||
|
if type(result) == array and result.len() == 2 {
|
||||||
|
let (rx, ry) = result
|
||||||
|
if type(rx) in (int, float) and type(ry) in (int, float) {
|
||||||
|
return (rx, ry, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}, b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if type(coord) == dictionary {
|
||||||
|
let result = (:)
|
||||||
|
for (key, value) in coord {
|
||||||
|
result.insert(key, normalize-coord(value))
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
return coord
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#import "/src/cetz.typ": draw, coordinate
|
#import "/src/cetz.typ": draw, coordinate
|
||||||
#import "util.typ": opposite-anchor
|
#import "util.typ": opposite-anchor, normalize-coord
|
||||||
|
|
||||||
/// List of valid wire styles
|
/// List of valid wire styles
|
||||||
/// #examples.wires
|
/// #examples.wires
|
||||||
@@ -68,8 +68,8 @@
|
|||||||
|
|
||||||
let (ctx, p0) = coordinate.resolve(ctx, start)
|
let (ctx, p0) = coordinate.resolve(ctx, start)
|
||||||
let (ctx, p3) = coordinate.resolve(ctx, end)
|
let (ctx, p3) = coordinate.resolve(ctx, end)
|
||||||
p0 = (x: p0.first(), y: p0.last())
|
p0 = (x: p0.first(), y: p0.at(1))
|
||||||
p3 = (x: p3.first(), y: p3.last())
|
p3 = (x: p3.first(), y: p3.at(1))
|
||||||
|
|
||||||
let dx1 = margin-start
|
let dx1 = margin-start
|
||||||
let dx2 = margin-end
|
let dx2 = margin-end
|
||||||
@@ -86,13 +86,13 @@
|
|||||||
if side-end == "east" {
|
if side-end == "east" {
|
||||||
dx2 *= -1
|
dx2 *= -1
|
||||||
}
|
}
|
||||||
p1 = (p0.x + dx1, p0.y)
|
p1 = (p0.x + dx1, p0.y, 0)
|
||||||
p2 = (p3.x - dx2, p0.y)
|
p2 = (p3.x - dx2, p0.y, 0)
|
||||||
|
|
||||||
let points = (
|
let points = (
|
||||||
start,
|
start,
|
||||||
(horizontal: p1, vertical: ()),
|
(horizontal: p1, vertical: ()),
|
||||||
(horizontal: (), vertical: (0, dodge-y)),
|
(horizontal: (), vertical: (0, dodge-y, 0)),
|
||||||
(horizontal: p2, vertical: ()),
|
(horizontal: p2, vertical: ()),
|
||||||
(horizontal: (), vertical: end),
|
(horizontal: (), vertical: end),
|
||||||
end
|
end
|
||||||
@@ -147,18 +147,18 @@
|
|||||||
|
|
||||||
|
|
||||||
// points that are closest to the edge points
|
// points that are closest to the edge points
|
||||||
let p1 = (p0.x + dx1, p0.y + dy1)
|
let p1 = (p0.x + dx1, p0.y + dy1, 0)
|
||||||
let p5 = (p6.x + dx2, p6.y + dy2)
|
let p5 = (p6.x + dx2, p6.y + dy2, 0)
|
||||||
|
|
||||||
|
|
||||||
// middle point
|
// middle point
|
||||||
let center_x = p0.x + box_width * center_horizontal / 100%
|
let center_x = p0.x + box_width * center_horizontal / 100%
|
||||||
let center_y = p0.y + box_height * center_vertical / 100%
|
let center_y = p0.y + box_height * center_vertical / 100%
|
||||||
let p3 = (center_x, center_y)
|
let p3 = (center_x, center_y, 0)
|
||||||
|
|
||||||
// setting up the points for that touch the guides
|
// setting up the points for that touch the guides
|
||||||
let p2 = (0,0)
|
let p2 = (0, 0, 0)
|
||||||
let p4 = (0,0)
|
let p4 = (0, 0, 0)
|
||||||
if side-start in ("north", "south") {
|
if side-start in ("north", "south") {
|
||||||
p2 = (horizontal: p3, vertical: p1)
|
p2 = (horizontal: p3, vertical: p1)
|
||||||
} else {
|
} else {
|
||||||
@@ -240,6 +240,9 @@
|
|||||||
if pts.len() != 2 {
|
if pts.len() != 2 {
|
||||||
panic("Wrong number of points (got " + str(pts.len()) + " instead of 2)")
|
panic("Wrong number of points (got " + str(pts.len()) + " instead of 2)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Normalize user-provided coordinates: (x, y) -> (x, y, 0)
|
||||||
|
let pts = pts.map(normalize-coord)
|
||||||
|
|
||||||
let stroke = (
|
let stroke = (
|
||||||
paint: color,
|
paint: color,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "circuiteria"
|
name = "circuiteria"
|
||||||
version = "0.2.0"
|
version = "0.2.1"
|
||||||
compiler = "0.13.1"
|
compiler = "0.15.0"
|
||||||
repository = "https://git.kb28.ch/HEL/circuiteria"
|
repository = "https://git.kb28.ch/HEL/circuiteria"
|
||||||
entrypoint = "src/lib.typ"
|
entrypoint = "src/lib.typ"
|
||||||
authors = [
|
authors = [
|
||||||
@@ -9,6 +9,6 @@ authors = [
|
|||||||
]
|
]
|
||||||
categories = [ "visualization" ]
|
categories = [ "visualization" ]
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
description = "Drawing block circuits with Typst made easy, using CeTZ"
|
description = "Drawing block circuits made easy, using CeTZ"
|
||||||
keywords = [ "circuit", "block", "draw" ]
|
keywords = [ "circuit", "block", "draw" ]
|
||||||
exclude = [ "gallery", "justfile", "doc" ]
|
exclude = [ "gallery", "justfile", "doc" ]
|
||||||