Skip to content

fix(docx): float an anchored drawing, and draw a table's own borders - #812

Merged
andiwand merged 1 commit into
mainfrom
fix/docx-float-drawing-and-table-borders
Sep 3, 2026
Merged

fix(docx): float an anchored drawing, and draw a table's own borders#812
andiwand merged 1 commit into
mainfrom
fix/docx-float-drawing-and-table-borders

Conversation

@andiwand

@andiwand andiwand commented Sep 3, 2026

Copy link
Copy Markdown
Member

🤖 Generated with Claude Code

Closes #803.

What was wrong

Two defects a user reported from a German letterhead + invoice, both docx-only. The html renderer already implements the whole anchor/wrap matrix and odf feeds it properly; it is the docx adapter that starved it.

A wp:anchor drawing rendered inline. frame_anchor_type returned AnchorType::as_char unconditionally, frame_x/frame_y returned nullopt, and frame_style returned {} — so a floating logo was laid out at its anchor's character position, landing between two lines instead of below them.

A table's own borders were dropped. resolve_table_cell_style_ read w:tcPr/w:tcBorders only. Nothing read w:tblPr/w:tblBorders, so a table stating its rules once — directly or through a w:tblStyle — rendered borderless. And w:sz was read as half-points where [ECMA-376] 17.3.4 says eighths, so every border that did draw was four times too thick.

The change

  • wp:anchor reports its real anchor type, its wp:positionH/wp:positionV offset (read_emus_text), and a GraphicStyle carrying its wrap and its side. A page-relative offset is dropped rather than measured against the wrong box.
  • table_cell_border resolves each cell's edges: its own w:tcBorders over the neighbour's over the table's, and only the edges the cell leads, so a rule between two cells is one line. New TableStyle::border, ::border_inside_horizontal, ::border_inside_vertical, mirrored in the JNI, Apple and Python bindings.
  • read_border_node reads w:sz in eighths of a point, and w:val="none"/"nil" now says no border rather than saying nothing.
  • td{vertical-align:top} in document.css — word and odf start a cell's content at the top where the browser default centres it; a sheet still says its own.
  • A right-floated frame with no offset no longer gets margin-right:calc(100% - 0 - width), which pinned it to the left.

Verified

New fixture docx/float-drawing+table-borders.docx — a wp:anchor wrapped top-and-bottom at an offset, a table whose borders live on a w:tblStyle, and a cell whose w:tcBorders override them. 272 lines of unit tests over the border resolution.

Full suite 1417 passed / 6 pre-existing skips. Reference output regenerated: 14 public and 7 private files, every one a table gaining the borders it states, plus image-anchor.docx, where two stacked images now sit side by side at their own offsets — which is where LibreOffice puts them too. The three odt files lose the redundant margin-right; nothing there moves by more than a pixel. Changed TUs re-checked under -Werror.

A `wp:anchor` was reported as `as_char` with no position and no graphic style,
so it landed at its anchor's character position: the reporter's letterhead logo
sat between two lines instead of below them. It now floats at its
`wp:positionH`/`wp:positionV` offset, with the wrap and the side it states.

Table borders were read from `w:tcPr/w:tcBorders` alone, so a table stating its
rules once — on `w:tblPr/w:tblBorders`, a `w:tblStyle`'s included — rendered
borderless. The table's borders now reach its cells, each edge drawn by the cell
that leads it. New `TableStyle::border`, `::border_inside_horizontal` and
`::border_inside_vertical`, mirrored in the JNI, Apple and Python bindings.

`w:sz` is in eighths of a point, not half-points, so every border was four times
too thick, and `w:val="none"` now says "no border" rather than saying nothing.

A cell in a text document starts its content at the top, as word and odf do.

Closes #803.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UDi21mwuKRGvGiFcGwETtS
@andiwand
andiwand force-pushed the fix/docx-float-drawing-and-table-borders branch from 8b167ab to ee6b054 Compare September 3, 2026 18:25
@andiwand
andiwand merged commit bdf3e3b into main Sep 3, 2026
36 checks passed
@andiwand
andiwand deleted the fix/docx-float-drawing-and-table-borders branch September 3, 2026 19:07
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.

docx: a floating drawing renders inline, and a table's borders are dropped unless they sit on the cell

1 participant