Skip to content

feat(odf): draw a custom shape as the shape, not as its box - #799

Merged
andiwand merged 2 commits into
mainfrom
odf-drawings/enhanced-geometry-render
Aug 31, 2026
Merged

feat(odf): draw a custom shape as the shape, not as its box#799
andiwand merged 2 commits into
mainfrom
odf-drawings/enhanced-geometry-render

Conversation

@andiwand

@andiwand andiwand commented Aug 31, 2026

Copy link
Copy Markdown
Member

🤖 Generated with Claude Code

Stage 4 of #771, on main now that #798 has landed. Closes #159.

html::translate_custom_shape carried a // TODO draw shape in svg and emitted
a positioned <div> with fill and stroke — the bounding box, never the shape.
Every one of the corpus's 350 custom shapes came out a rectangle, arrows,
callouts, rings and stars alike.

read_path now resolves a draw:custom-shape's draw:enhanced-geometry
through the languages #798 added: svg:viewBox gives the box the formulas
measure against, draw:modifiers fills $0, $1, …, the draw:equation
children resolve on demand and are memoised, with a reference that cycles
resolving to nothing rather than recursing, and draw:enhanced-path becomes
the svg d.

Notes

  • draw:mirror-horizontal and draw:mirror-vertical are folded into the
    coordinates as they are written, rather than into a transform: the pen keeps
    tracking the unmirrored geometry, so the angles and radii an arc needs are
    computed once, and only the emitted numbers and the sweep flags are
    reflected.
  • The path is drawn with fill-rule="evenodd", which is what leaves a ring its
    hole; the corpus has one.
  • hasstroke and hasfill evaluate as true because the geometry reader has no
    style in hand — no corpus formula reads them.

Not done, and recorded in PLAN.md

draw:text-areas, so a shape's text is still laid out in the whole box;
draw:handle, which only an editor needs; and F/S, which want one subpath
painted differently from the rest.

Verification

Checked against libreoffice's own png export of sample.odg and
SpotfaceCoord40270-L.odg.

The reference-output pin is advanced: 36 files, every changed line an insertion
— 740 <svg><path> pairs where a custom shape used to be a plain box, and
nothing removed.

@andiwand
andiwand force-pushed the odf-drawings/enhanced-geometry branch from 19a4a54 to 004227b Compare August 31, 2026 06:07
@andiwand
andiwand force-pushed the odf-drawings/enhanced-geometry-render branch from d67ffd5 to a291432 Compare August 31, 2026 06:07
@andiwand
andiwand force-pushed the odf-drawings/enhanced-geometry branch from 004227b to a75a25e Compare August 31, 2026 06:10
@andiwand
andiwand force-pushed the odf-drawings/enhanced-geometry-render branch from a291432 to caf9df2 Compare August 31, 2026 06:10
@andiwand
andiwand force-pushed the odf-drawings/enhanced-geometry branch 2 times, most recently from 16404bc to e4f645c Compare August 31, 2026 19:41
Base automatically changed from odf-drawings/enhanced-geometry to main August 31, 2026 19:43
andiwand and others added 2 commits August 31, 2026 21:49
`html::translate_custom_shape` carried a `// TODO draw shape in svg` and emitted
a positioned `<div>` with fill and stroke — the bounding box, never the shape.
Every one of the corpus's 350 custom shapes came out a rectangle, arrows,
callouts, rings and stars alike. Closes #159.

`read_path` now resolves a `draw:custom-shape`'s `draw:enhanced-geometry`
through the languages the previous change added: `svg:viewBox` gives the box the
formulas measure against, `draw:modifiers` fills `$0`, `$1`, …, the
`draw:equation` children resolve on demand and are memoised, with a reference
that cycles resolving to nothing rather than recursing, and
`draw:enhanced-path` becomes the svg `d`.

`draw:mirror-horizontal` and `draw:mirror-vertical` are folded into the
coordinates as they are written, rather than into a transform: the pen keeps
tracking the unmirrored geometry, so the angles and radii an arc needs are
computed once, and only the emitted numbers and the sweep flags are reflected.

The path is drawn with `fill-rule="evenodd"`, which is what leaves a ring its
hole; the corpus has one.

Not done, and recorded in `PLAN.md`: `draw:text-areas`, so a shape's text is
still laid out in the whole box; `draw:handle`, which only an editor needs; and
`F`/`S`, which want one subpath painted differently from the rest. `hasstroke`
and `hasfill` evaluate as true because the geometry reader has no style in
hand — no corpus formula reads them.

Checked against libreoffice's own png export of `sample.odg` and
`SpotfaceCoord40270-L.odg`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017XABfEapaADjFQCt1vjmDF
36 files. Every changed line is an insertion — 740 `<svg><path>` pairs where a
custom shape used to be a plain box; nothing is removed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UJ6NPShQBp1nX7WuMvty8V
@andiwand
andiwand force-pushed the odf-drawings/enhanced-geometry-render branch from caf9df2 to 3b8c0a0 Compare August 31, 2026 19:51
@andiwand
andiwand merged commit 37165cd into main Aug 31, 2026
36 checks passed
@andiwand
andiwand deleted the odf-drawings/enhanced-geometry-render branch August 31, 2026 20:37
andiwand added a commit that referenced this pull request Aug 31, 2026
`PLAN.md` said to delete it once nothing was left under *Today*, and #771's
four goals are on main: `draw:transform` (#796), the shape elements with no
parser (#797), `draw:enhanced-geometry` (#798, #799) and the `draw:object`
chart (#800). What remains of drawings is the unticked boxes in `README.md`;
the two decisions the plan held that the checklist cannot express — preset
`draw:type` shapes and connector routing — move to `AGENTS.md`.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
@andiwand andiwand mentioned this pull request Aug 31, 2026
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.

support odf custom-shape

1 participant