feat(odf): draw the shape elements the parser used to drop - #797
Merged
Conversation
andiwand
force-pushed
the
odf-drawings/shapes
branch
2 times, most recently
from
August 31, 2026 06:10
3620672 to
7b7778d
Compare
andiwand
force-pushed
the
odf-drawings/transform
branch
3 times, most recently
from
August 31, 2026 18:33
1f02184 to
eb177f2
Compare
`parse_any_element_tree` knew nine drawing tags; everything else fell through
its final `return {null_element_id, …}` and vanished with its subtree. This maps
the rest onto the types that already exist rather than inventing new ones, the
way `draw:g` already collapses onto `frame`:
- `draw:path`, `draw:polygon`, `draw:polyline`, `draw:regular-polygon` and
`draw:connector` are custom shapes, which is what ODF's own term means for a
shape whose geometry is given rather than named
- `draw:ellipse` is a circle, and so is a `draw:circle`; one that `draw:kind`
cuts to an arc, section or chord becomes a custom shape carrying that arc
- `draw:measure` is a line, `draw:caption` a rect
- `dr3d:scene` stays unhandled: a 3-D scene is not a 2-D path
`CustomShape::path()` hands the renderer a `DrawingPath` — an svg `d` plus the
user-space box it is written in — and the renderer draws it into an
`<svg viewBox>` sized to the shape. `odf_geometry.cpp` builds one from
`svg:d`, `draw:points`, `draw:corners` or the arc `draw:kind` asks for. An
`svg:d` is parsed and re-serialised rather than forwarded, so nothing the file
wrote reaches the output as markup.
A `draw:connector` states no box at all — its `svg:d` is in the page's own
coordinates at 1/100 mm — so its path is what places it. A straight one boxes to
nothing in one axis, which svg refuses, hence the one-unit floor.
Two fixes made along the way: `translate_circle` wrote `r="50%"`, which is a
circle inscribed in the box rather than the ellipse ODF means, and
`text:measure` had no parser, so a measure's label came out empty.
Five of the nine tags occur nowhere in the test corpus, so they are covered by
unit tests over string literals instead: `odf_geometry_test.cpp`.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017XABfEapaADjFQCt1vjmDF
17 files over 8 documents. Every changed line is an insertion of a newly drawn shape or its label, bar 26 `<circle>` that become `<ellipse>`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UJ6NPShQBp1nX7WuMvty8V
andiwand
force-pushed
the
odf-drawings/shapes
branch
from
August 31, 2026 19:17
7b7778d to
c5ecb74
Compare
This was referenced Aug 31, 2026
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>
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🤖 Generated with Claude Code
Stage 2 of #771, on main now that #796 has landed.
parse_any_element_treeknew nine drawing tags; everything else fell throughits final
return {null_element_id, …}and vanished with its subtree. Thismaps the rest onto the types that already exist rather than inventing new ones,
the way
draw:galready collapses ontoframe:draw:path,draw:polygon,draw:polyline,draw:regular-polygon,draw:connectorcustom_shapedraw:ellipse, and adraw:circle/draw:ellipsedraw:kindcutscircle/custom_shapedraw:measurelinesvg:x1/y1/x2/y2, same asdraw:linedraw:captionrectdr3d:sceneCustomShape::path()hands the renderer aDrawingPath— an svgdplus theuser-space box it is written in — and the renderer draws it into an
<svg viewBox>sized to the shape.odf_geometry.cppbuilds one fromsvg:d,draw:points,draw:cornersor the arcdraw:kindasks for. Ansvg:disparsed and re-serialised rather than forwarded, so nothing the file wrote
reaches the output as markup.
Notes
draw:connectorcarriessvg:x1/y1/x2/y2but no box, and a curve'scontrol points can reach outside its endpoints, so its path is what places
it; the
svg:dis in the page's own coordinates at 1/100 mm. A straight one boxesto nothing in one axis, which svg refuses, hence the one-unit floor.
fill="none": svg would else fill it asif it did, and libreoffice draws an open
draw:pathas a line. 3 of thecorpus's 6
draw:pathare open; all 349 enhanced paths close.vector-effect="non-scaling-stroke"on the path: the view box scales, andwith
preserveAspectRatio="none"unevenly, which the stroke must not follow.translate_circlewroter="50%", a circleinscribed in the box rather than the ellipse ODF means, and
text:measurehad no parser, so a measure's label came out empty.
DrawingPathandCustomShape::path(), mirrored in the JNI,Apple and Python bindings.
Verification
Five of the nine tags occur nowhere in the test corpus, so they are covered by
unit tests over string literals instead:
odf_geometry_test.cpp.SpotfaceCoord40270-L.odgwas compared against libreoffice's own png export.The reference-output pin is advanced: 17 files over 8 documents, every changed
line an insertion of a newly drawn shape or its label, bar the 26
<circle>that become
<ellipse>.