From 359c16320e33b5abac5212d3dd7ce59acff1dccc Mon Sep 17 00:00:00 2001 From: Andreas Stefl Date: Mon, 31 Aug 2026 23:07:17 +0200 Subject: [PATCH] docs(odf): retire the drawings plan, its stages having landed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `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) Claude-Session: https://claude.ai/code/session_01UJ6NPShQBp1nX7WuMvty8V --- AGENTS.md | 2 +- src/odr/internal/odf/AGENTS.md | 10 +- src/odr/internal/odf/PLAN.md | 179 --------------------------------- 3 files changed, 9 insertions(+), 182 deletions(-) delete mode 100644 src/odr/internal/odf/PLAN.md diff --git a/AGENTS.md b/AGENTS.md index ca7dab287..874b3c743 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -62,7 +62,7 @@ bytes ─▶ magic/open_strategy ─▶ DecodedFile ─▶ Document ─▶ Eleme | `src/odr/internal/file_type_table.*` | **The** per-`FileType` table: extensions, MIME types, category, document type, `FileTypeCapabilities`. Every public lookup in `odr.hpp` is a thin forward into it — extend the table, not the lookups. | | `src/odr/internal/html/` | Generic HTML renderer. | | `src/odr/internal/cfb/`, `zip/` | Container formats (CFB, ZIP). | -| `src/odr/internal/odf/` | OpenDocument (odt/ods/odp/odg); see [`odf/AGENTS.md`](src/odr/internal/odf/AGENTS.md) + [`odf/PLAN.md`](src/odr/internal/odf/PLAN.md). | +| `src/odr/internal/odf/` | OpenDocument (odt/ods/odp/odg); see [`odf/AGENTS.md`](src/odr/internal/odf/AGENTS.md). | | `src/odr/internal/ooxml/` | OOXML (docx/pptx/xlsx); see [`ooxml/AGENTS.md`](src/odr/internal/ooxml/AGENTS.md) + per-format docs. | | `src/odr/internal/oldms/` | **Legacy MS binary** (.doc/.ppt/.xls). | | `src/odr/internal/iwork/` | Apple iWork (`.pages`, `.key`, `.numbers`); see [`iwork/AGENTS.md`](src/odr/internal/iwork/AGENTS.md) + [`iwork/PLAN.md`](src/odr/internal/iwork/PLAN.md). | diff --git a/src/odr/internal/odf/AGENTS.md b/src/odr/internal/odf/AGENTS.md index b612bb884..59371d94b 100644 --- a/src/odr/internal/odf/AGENTS.md +++ b/src/odr/internal/odf/AGENTS.md @@ -145,8 +145,14 @@ are **tolerated** to keep rendering best-effort. ## Status & open work Feature coverage (element/style checkboxes) is tracked in [`README.md`](README.md). -The drawing gap — transforms, the unparsed shape elements, enhanced geometry and -the embedded chart — has its own staged plan in [`PLAN.md`](PLAN.md) (#771). +The drawing gap #771 named — transforms, the unparsed shape elements, enhanced +geometry and the embedded chart — is closed; what is left of drawings is the +unticked boxes in [`README.md`](README.md). Two of them are deliberate rather +than pending: a `draw:type` naming a preset shape with no `draw:enhanced-path` +would need libreoffice's own preset table, and all 350 in the corpus write the +path; and a `draw:connector` is drawn from the `svg:d` its producer wrote, +since re-routing one between the shapes it names is layout rather than +decoding. The structural/foundational gaps, roughly by value: 1. **Editing is text-content only.** No structural edits (insert/delete/move diff --git a/src/odr/internal/odf/PLAN.md b/src/odr/internal/odf/PLAN.md deleted file mode 100644 index 44256683e..000000000 --- a/src/odr/internal/odf/PLAN.md +++ /dev/null @@ -1,179 +0,0 @@ -# ODF drawings plan - -Closing #771: everything an ODF shape carries beyond its bounding box — -`draw:transform`, the shape elements with no parser, `draw:enhanced-geometry`, -and the `draw:object` chart. The module as it stands is in -[`AGENTS.md`](AGENTS.md); the feature checklist is [`README.md`](README.md). -Keep this file honest as stages land, and delete it when nothing is left -under *Today*. - -## Today - -All five stages have landed. What is left is listed under each of them and in -[`README.md`](README.md): `draw:text-areas` and `draw:handle` on an enhanced -geometry, the arrowheads `draw:marker` names, `dr3d:scene`, and the chart -features below stage 5. - -## The corpus - -Every number below is `` fallback stays for a shape with no geometry. - -Emitting a path is not "passing the file's markup through": `svg:d` is parsed -into commands and re-serialised by us, so nothing the file wrote reaches the -output as live markup. - -**A transform is not a style.** `get_intermediate_style` walks the *element* -parent chain and overrides down it, so a `GraphicStyle` field would leak a -group's transform onto every child — and CSS already composes a transform -through the nesting. `draw:transform` is therefore an accessor on the shape -handles, next to `x()`/`y()`, not a style property. - -**A transform is composed, not passed through.** ODF angles are radians and CSS -wants degrees, so the list has to be read anyway. It composes to -`internal::util::math::Transform2D`'s shape — four unitless numbers and a -translation that carries a length — which is also what `matrix(a b c d e f)` -means in 19.228. - -**The SVM replacement image stays.** For `draw:object` it is the fallback when -the chart cannot be read, and it is what a producer that wrote no chart part -leaves behind. - -## Stages - -Each stage is one pull request, stacked on the one before. - -### 1 — `draw:transform` — landed - -`DrawingTransform` in the public header; `transform()` on `Frame`, `Rect`, -`Line`, `Circle` and `CustomShape`; `odf_geometry.cpp` reads and composes the -attribute; the renderer writes `transform` + `transform-origin:0 0`. - -Two things the spec text does not settle, both fixed against libreoffice's own -svg export of `style-drawing-1.odp`: the list applies to the shape **left to -right**, so a `translate` after a `rotate` is not itself rotated, and `rotate` -is **counter-clockwise** for a positive angle — libreoffice writes svg's -`rotate(-19.4°)` for the file's `rotate (0.34 rad)`. Composing both readings -and comparing against the bounding box libreoffice reports (`x=23084`, exact) -is what decided it. - -### 2 — the missing shape elements — landed - -The tag → type table above, the geometry conversions, `DrawingPath` and -`CustomShape::path()`, and the renderer branch that draws it into an -``. `translate_circle` became an ``; it wrote `r="50%"`, -wrong for every non-square box. `text:measure` is parsed too, or a measure's -label comes out empty. - -`vector-effect="non-scaling-stroke"` on the path: the view box scales, and with -`preserveAspectRatio="none"` unevenly, which the stroke must not follow. - -### 3 — `draw:enhanced-path` and `draw:equation`, parser only — landed - -`odf_enhanced_geometry.cpp`: the formula language of 20.36 (`$N` modifiers, -`?name` references, the named view-box values, `abs sqrt sin cos tan atan min -max atan2 if`) and every command of 19.145, converted to an svg `d`. Pure -functions over strings, unit-tested from string literals. - -Decisions worth knowing: `sin`/`cos` take radians, which the corpus confirms by -writing `sin(105*(pi/180))`; an arc is emitted in segments of at most a half -turn, so the large-arc flag is never needed and a full `U … 0 360` — which one -svg `A` cannot express — still draws; `F` and `S` are read and dropped, since -painting one subpath differently is more than one `d` can say. - -### 4 — enhanced geometry, rendered — landed - -Stage 3 wired into `CustomShape::path()`: `svg:viewBox`, `draw:modifiers`, the -`draw:equation` children resolved on demand and memoised, and -`draw:mirror-horizontal` / `-vertical` folded into the coordinates as they are -written. Closes #159. - -Still open, and deliberately: `draw:text-areas`, so a shape's text is laid out -in the whole box rather than the region the geometry reserves for it; -`draw:handle`, which only matters to an editor; and `F`/`S`, which want one -subpath painted differently from the rest. - -`hasstroke` and `hasfill` are always true — the geometry reader has no style -in hand — and no corpus formula reads them. - -### 5 — `draw:object` charts — landed - -`odf_chart.cpp` renders the embedded part's `` to svg, and the -object reaches the renderer as an image carrying it, so the existing image path -writes it out. The `draw:image` beside an object is the replacement the producer -wrote, and is skipped where the object itself draws; an object with no chart we -can read — a formula, an ole blob — still leaves it. Closes #179. - -Decisions: the plotted values come from the chart's own `local-table` rather -than the cells it names in the host document, which is the snapshot the part -carries and the only one an embedded chart is guaranteed; the layout comes from -`chart:plot-area` and `chartooo:coordinate-region`, so it matches what the -producer laid out rather than something we invent. - -Open: 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. - -## Not scoped - -- **`dr3d:scene`** — a 3-D scene, occurring nowhere in the corpus. -- **`draw:object-ole`** (2 occurrences) — an OLE blob, not ODF markup; what is - readable there is the replacement image we already draw. -- **Glue points and connector routing.** `draw:connector` carries `svg:d` - written by the producer, and drawing that is the whole win. Re-routing a - connector between the shapes it names is layout, not decoding. -- **Editing any of this.** The editor is text-content only (`AGENTS.md`). -- **`draw:type`'s preset shapes.** A named type with no `draw:enhanced-path` - would need libreoffice's preset table; all 350 in the corpus write the path. -- **`draw:marker`** (28 in the corpus): the arrowheads a stroke ends with, an - svg `marker` and a separate piece of style work.