From 63857626962da6504dea7100799c90cfda2b0480 Mon Sep 17 00:00:00 2001 From: LordBaryhobal Date: Mon, 28 Jul 2025 21:07:57 +0200 Subject: [PATCH] refactored notes rendering --- gallery/notes.typ | 4 +- src/core/draw/note.typ | 85 ++++++++++++++++++++++++++++---------- src/core/draw/sequence.typ | 6 ++- src/core/renderer.typ | 11 ++--- src/core/setup.typ | 1 + src/note.typ | 13 ++---- tests/note/color/test.typ | 4 +- 7 files changed, 82 insertions(+), 42 deletions(-) diff --git a/gallery/notes.typ b/gallery/notes.typ index f7fc8da..22489c7 100644 --- a/gallery/notes.typ +++ b/gallery/notes.typ @@ -21,10 +21,10 @@ _par("a", display-name: "Alice") _par("b", display-name: "Bob") - _note("left", [This is displayed\ left of Alice.], pos: "a", color: rgb("#00FFFF")) + _note("left", [This is displayed\ left of Alice.], pos: "a", fill: rgb("#00FFFF")) _note("right", [This is displayed right of Alice.], pos: "a") _note("over", [This is displayed over Alice.], pos: "a") - _note("over", [This is displayed\ over Bob and Alice.], pos: ("a", "b"), color: rgb("#FFAAAA")) + _note("over", [This is displayed\ over Bob and Alice.], pos: ("a", "b"), fill: rgb("#FFAAAA")) _note("over", [This is yet another\ example of\ a long note.], pos: ("a", "b")) }) diff --git a/src/core/draw/note.typ b/src/core/draw/note.typ index 33b33aa..1ee656a 100644 --- a/src/core/draw/note.typ +++ b/src/core/draw/note.typ @@ -1,14 +1,51 @@ -#import "/src/cetz.typ": draw +#import "/src/cetz.typ": draw, styles #import "/src/consts.typ": * -#import "/src/core/utils.typ": get-ctx, set-ctx, expand-parent-group +#import "/src/core/utils.typ": get-ctx, is-elmt, set-ctx, expand-parent-group, normalize-measure + +#let note-default-style = ( + shape: "default", + fill: rgb("#FEFFDD"), + stroke: black + .5pt +) + +#let resolve-style(ctx, note) = { + return styles.resolve( + ctx.style, + merge: note.style, + root: "note", + base: note-default-style + ) +} + +#let pre-resolve-styles() = get-ctx(ctx => { + let ctx = ctx + let notes = ctx.setup.notes + + for (i, elmt) in ctx.setup.elements.enumerate() { + if type(elmt) == function { + ctx = elmt(ctx).ctx + } else if is-elmt(elmt) { + if elmt.type == "note" { + let style = resolve-style(ctx, elmt) + notes.at(elmt.id).insert("resolved-style", style) + } + } + } + + set-ctx(c => { + c.setup.notes = notes + return c + }) +}) #let get-size(note) = { - let PAD = if note.shape == "hex" {NOTE-HEX-PAD} else {NOTE-PAD} + let style = note.resolved-style + let PAD = if style.shape == "hex" {NOTE-HEX-PAD} else {NOTE-PAD} let m = measure(box(note.content)) let w = m.width / 1pt + PAD.last() * 2 let h = m.height / 1pt + PAD.first() * 2 - if note.shape == "default" { + if style.shape == "default" { w += NOTE-CORNER-SIZE } return ( @@ -31,14 +68,15 @@ } #let get-box(note) = { - let PAD = if note.shape == "hex" {NOTE-HEX-PAD} else {NOTE-PAD} + let style = note.resolved-style + let PAD = if style.shape == "hex" {NOTE-HEX-PAD} else {NOTE-PAD} let inset = ( left: PAD.last() * 1pt, right: PAD.last() * 1pt, top: PAD.first() * 1pt, bottom: PAD.first() * 1pt, ) - if note.shape == "default" { + if style.shape == "default" { inset.right += NOTE-CORNER-SIZE * 1pt } if note.side == "left" { @@ -62,18 +100,21 @@ } get-ctx(ctx => { + let note = ctx.notes.at(note.id) let y = y if y == auto { y = ctx.y } - - let PAD = if note.shape == "hex" {NOTE-HEX-PAD} else {NOTE-PAD} - let m = measure(box(note.content)) - let w = m.width / 1pt + PAD.last() * 2 - let h = m.height / 1pt + PAD.first() * 2 + let style = note.resolved-style + let shape = style.shape + + let PAD = if shape == "hex" {NOTE-HEX-PAD} else {NOTE-PAD} + let m = normalize-measure(box(note.content)) + let w = m.width + PAD.last() * 2 + let h = m.height + PAD.first() * 2 let total-w = w - if note.shape == "default" { + if shape == "default" { total-w += NOTE-CORNER-SIZE } @@ -106,31 +147,31 @@ } let y1 = y0 - h - if note.shape == "default" { + if shape == "default" { draw.line( (x0, y0), (x1, y0), (x2, y0 - NOTE-CORNER-SIZE), (x2, y1), (x0, y1), - stroke: black + .5pt, - fill: note.color, + stroke: style.stroke, + fill: style.fill, close: true ) draw.line( (x1, y0), (x1, y0 - NOTE-CORNER-SIZE), (x2, y0 - NOTE-CORNER-SIZE), - stroke: black + .5pt + stroke: style.stroke ) - } else if note.shape == "rect" { + } else if shape == "rect" { draw.rect( (x0, y0), (x2, y1), - stroke: black + .5pt, - fill: note.color + stroke: style.stroke, + fill: style.fill ) - } else if note.shape == "hex" { + } else if shape == "hex" { let lx = x0 + PAD.last() let rx = x2 - PAD.last() let my = (y0 + y1) / 2 @@ -141,8 +182,8 @@ (rx, y1), (lx, y1), (x0, my), - stroke: black + .5pt, - fill: note.color, + stroke: style.stroke, + fill: style.fill, close: true ) } diff --git a/src/core/draw/sequence.typ b/src/core/draw/sequence.typ index 9082a90..575fbbf 100644 --- a/src/core/draw/sequence.typ +++ b/src/core/draw/sequence.typ @@ -70,7 +70,8 @@ h = calc.max( h, ..seq.linked-notes.map(n => { - note.get-size(n).height / 2 + let nt = ctx.notes.at(n.id) + note.get-size(nt).height / 2 }) ) ctx.y -= h @@ -354,7 +355,8 @@ end-info.y = calc.min( end-info.y, y0 - calc.max(..seq.linked-notes.map(n => { - let m = note.get-size(n) + let nt = ctx.notes.at(n.id) + let m = note.get-size(nt) return m.height / 2 })) ) diff --git a/src/core/renderer.typ b/src/core/renderer.typ index df5cfd5..09dcd64 100644 --- a/src/core/renderer.typ +++ b/src/core/renderer.typ @@ -87,7 +87,7 @@ return participants } -#let note-get-cell(pars-i, n) = { +#let note-get-cell(notes, pars-i, n) = { let (p1, p2) = (none, none) let cell = none if n.side == "left" { @@ -99,8 +99,9 @@ p2 = n.pos2 cell = note.get-box(n) } else if n.side == "over" and n.aligned-with != none { + let aligned-with = notes.at(n.aligned-with.id) let box1 = note.get-box(n) - let box2 = note.get-box(n.aligned-with) + let box2 = note.get-box(aligned-with) let m1 = measure(box1) let m2 = measure(box2) cell = box( @@ -144,7 +145,7 @@ ) } else if elmt.type == "note" { - let cell = note-get-cell(pars-i, notes.at(elmt.id)) + let cell = note-get-cell(notes, pars-i, notes.at(elmt.id)) if cell != none { cells.push(cell) } @@ -359,8 +360,8 @@ init-lifelines() set-participants-i() - + note.pre-resolve-styles() compute-columns-width() set-ctx(c => { @@ -401,7 +402,7 @@ #let render(participants, elements, notes) = context canvas(length: 1pt, { setup-ctx(participants, elements, notes) - + // Draw participants (start) get-ctx(ctx => { for p in ctx.participants { diff --git a/src/core/setup.typ b/src/core/setup.typ index 8dca53b..06c964a 100644 --- a/src/core/setup.typ +++ b/src/core/setup.typ @@ -150,6 +150,7 @@ let n = ctx.last-note.note n.aligned-with = note ctx.elmts.at(ctx.last-note.i) = n + ctx.notes.at(ctx.last-note.note.id) = n } if note.side in ("left", "right") { diff --git a/src/note.typ b/src/note.typ index 01e6b31..3ef5bb8 100644 --- a/src/note.typ +++ b/src/note.typ @@ -18,10 +18,9 @@ side, content, pos: none, - color: COL-NOTE, - shape: "default", aligned: false, - allow-overlap: true + allow-overlap: true, + ..style ) = { if side == "over" { if pos == none { @@ -33,19 +32,15 @@ panic("Aligned notes can only be over a participant (got side '" + side + "')") } } - if color == auto { - color = COL-NOTE - } return (( type: "note", draw: note.render, side: side, content: content, pos: pos, - color: color, - shape: shape, aligned: aligned, aligned-with: none, - allow-overlap: allow-overlap + allow-overlap: allow-overlap, + style: style.named() ),) } diff --git a/tests/note/color/test.typ b/tests/note/color/test.typ index bf051c5..019f7c0 100644 --- a/tests/note/color/test.typ +++ b/tests/note/color/test.typ @@ -5,9 +5,9 @@ _par("a", display-name: "Alice") _par("b", display-name: "Bob") - _note("left", [This is displayed\ left of Alice.], pos: "a", color: rgb("#00FFFF")) + _note("left", [This is displayed\ left of Alice.], pos: "a", fill: rgb("#00FFFF")) _note("right", [This is displayed right of Alice.], pos: "a") _note("over", [This is displayed over Alice.], pos: "a") - _note("over", [This is displayed\ over Bob and Alice.], pos: ("a", "b"), color: rgb("#FFAAAA")) + _note("over", [This is displayed\ over Bob and Alice.], pos: ("a", "b"), fill: rgb("#FFAAAA")) _note("over", [This is yet another\ example of\ a long note.], pos: ("a", "b")) }) \ No newline at end of file