Skip to content

feat(odf): draw the chart an embedded object holds, not its replacement image - #800

Merged
andiwand merged 3 commits into
mainfrom
odf-drawings/charts
Aug 31, 2026
Merged

feat(odf): draw the chart an embedded object holds, not its replacement image#800
andiwand merged 3 commits into
mainfrom
odf-drawings/charts

Conversation

@andiwand

@andiwand andiwand commented Aug 31, 2026

Copy link
Copy Markdown
Member

🤖 Generated with Claude Code

Stage 5 of #771, on main now that #799 has landed. Closes #179.

Carries one unrelated commit: Scanner is renamed ValueCursor, since it is
a position in a string that advances rather than anything that tokenises.

A libreoffice chart is
<draw:frame><draw:object xlink:href="./Object 1"/><draw:image xlink:href="./ObjectReplacements/Object 1"/></draw:frame>. draw:object had
no parser, so what drew was the sibling replacement: a flattened metafile with
no selectable text, no structure, and nothing at all where the producer wrote
none. The chart's own markup — series, axes, and a table:table of the plotted
values — sat unread in the package. 1122 draw:object over 21 files in the
test corpus.

odf_chart.cpp renders <chart:chart> to svg: bar, line, area, scatter, pie
and ring, with the title, legend, axes and the series colours the chart's own
styles name. The object reaches the renderer as an image carrying that svg, so
the existing image path writes it out with no renderer change at all.

Two decisions worth recording

  • The values come from the part's own local-table rather than the cells it
    names in the host document: that is the snapshot the chart carries, and the
    only source an embedded chart is guaranteed — it is also what lets a chart in
    a text document work, where there is no sheet to read.
  • The layout is chart:plot-area's box and chartooo:coordinate-region, so
    the plot sits where the producer put it rather than somewhere we invent.

Notes

  • The draw:image beside an object is skipped, or the two would stack; an
    object holding no chart we can read — a formula, an ole blob — falls back to
    it, which is what keeps the 1027 math objects in
    Vektoranalysis Zusammenfassung.odt drawing.
  • A bar or an area is measured from zero, or it lies about its size.
  • Category labels are thinned to what fits: every nth, n chosen from the widest
    label's width against the plot's.

Open, and recorded in PLAN.md

Stacked and percentage plots, secondary axes, trend lines, data labels, and the
number format an axis names — a date axis shows its serial number today.

Verification

odf_chart_test.cpp, from string literals. style+svm-chart-1.ods and
Blood Pressure.ods were rendered and eyeballed; the latter drew nothing at all
before, having no replacement image.

The reference-output pin is advanced: 19 files, every change a line-for-line
replacement of the metafile replacement image's data uri by the chart's own
svg.

@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/charts branch from 282a21d to 9dba185 Compare August 31, 2026 06:08
@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/charts branch 2 times, most recently from 8b40503 to b5f7772 Compare August 31, 2026 06:11
@andiwand
andiwand force-pushed the odf-drawings/enhanced-geometry-render branch from caf9df2 to 3b8c0a0 Compare August 31, 2026 19:51
Base automatically changed from odf-drawings/enhanced-geometry-render to main August 31, 2026 20:37
andiwand and others added 3 commits August 31, 2026 22:47
…nt image

A libreoffice chart is
`<draw:frame><draw:object xlink:href="./Object 1"/><draw:image
xlink:href="./ObjectReplacements/Object 1"/></draw:frame>`. `draw:object` had
no parser, so what drew was the sibling replacement: a flattened metafile with
no selectable text, no structure, and nothing at all where the producer wrote
none. The chart's own markup — series, axes, and a `table:table` of the plotted
values — sat unread in the package. 1122 `draw:object` over 21 files in the test
corpus. Closes #179.

`odf_chart.cpp` renders `<chart:chart>` to svg: bar, line, area, scatter, pie
and ring, with the title, legend, axes and the series colours the chart's own
styles name. The object reaches the renderer as an image carrying that svg, so
the existing image path writes it out with no renderer change at all.

Two decisions worth recording. The values come from the part's own
`local-table` rather than the cells it names in the host document: that is the
snapshot the chart carries, and the only source an embedded chart is guaranteed
— it is also what lets a chart in a text document work, where there is no sheet
to read. And the layout is `chart:plot-area`'s box and
`chartooo:coordinate-region`, so the plot sits where the producer put it rather
than somewhere we invent.

The `draw:image` beside an object is skipped, or the two would stack; an object
holding no chart we can read — a formula, an ole blob — falls back to it, which
is what keeps the 1027 math objects in `Vektoranalysis Zusammenfassung.odt`
drawing.

Open, and recorded in `PLAN.md`: stacked and percentage plots, secondary axes,
trend lines, data labels, and the number format an axis names — a date axis
shows its serial number today.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017XABfEapaADjFQCt1vjmDF
`Scanner` promised tokenising it does not do; the class is a position in a
string that advances, which is what its own comment already called it and what
`common::TableCursor` is named for over table positions.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UJ6NPShQBp1nX7WuMvty8V
19 files. Every change is a line-for-line replacement: the metafile
replacement image's data uri swapped for the chart's own svg.

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/charts branch from b5f7772 to 811973a Compare August 31, 2026 20:49
@andiwand
andiwand merged commit 2e4f275 into main Aug 31, 2026
36 checks passed
@andiwand
andiwand deleted the odf-drawings/charts branch August 31, 2026 21:00
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>
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.

ods chart missing

1 participant