Skip to content

fix(layout): keep the size of a picture or shape composed in a table cell - #928

Merged
DemchaAV merged 2 commits into
2.5-devfrom
fix/docx-composed-cell-picture
Oct 20, 2026
Merged

DemchaAV merged 2 commits into
2.5-devfrom
fix/docx-composed-cell-picture

Conversation

@DemchaAV

@DemchaAV DemchaAV commented Oct 20, 2026 •

Copy link
Copy Markdown
Owner

Why

A table cell lays out the node composed in it (DocumentTableCell.node) in a placement that
NodeDefinitionSupport.emitComposedCellFragments builds. Its width was the cell's inner width
and its height was what the node measured. Every drawn node fills the width it is given, so one
of a size of its own was stretched across the cell.

In a 120pt column padded 4pt (fixed(120)), this is what the page drew:

Composed in the cell Page before Page after Word / LibreOffice
picture 200×100, fitToBounds(100, 100) 112×56, y 111 100×50, x 76–176, y 114 76–176, y 114 / 75.5–175.5, y 113.9
picture size(60, 60) 112×60, stretched 60×60 60×60 / 60×60
circle(20) ellipse 112×20 20×20, x 76–96 76–96 / 76–96.1
shape 30×10 112×10 30×10, x 76–106 74.5–107.4 in Word, 1.5pt past each side as before

The DOCX export already wrote the pictures at their own size, so they stood where the page now
draws them. It drew the circle and the shape from the page's fragments, stretched as the page
was.

Elsewhere a leaf is laid out at the width it measured: LayoutCompiler.compileAtomicLeaf,
SplittableLeafCompiler and a row slot's leaf all use it. No layout test pinned the stretch.
Two things leaned on it:

  • a comment, as the reason the cell's horizontal anchor is not read;
  • one DOCX report test, on a composed shape's corners, rewritten here.

What changed

  • emitComposedCellFragments: a leaf of a size of its own is placed at the width it
    measured, held to the cell's inner width where it measures wider. It starts at the cell's
    content edge as before, since the horizontal anchor is still not read. This covers a picture,
    a shape, a circle, a barcode, a line, a path, a polygon and a nested table.
    • Text keeps the cell's inner width: a paragraph, a list, a page number and a page
      reference (alignsInTheWidthItIsGiven). Text aligns in that width, and a page number
      measures only as wide as its digits: set right, at its own width, it would leave the cell's
      right edge.
    • A composite keeps the cell's inner box, which it lays itself out in.
  • DocxSemanticBackend.cornersDiffer: a composed shape's radii are now measured against
    its own width, held to half its shorter side, rather than against an unbounded width.
    • The rule comments say a bar is its own width, held to its cell's.
  • Docs:
    • CHANGELOG v2.5.0: a new entry, and an older v2.5.0 sentence that said a composed shape is
      laid out at the cell's width;
    • docs/recipes/tables.md (composed cells);
    • docs/recipes/docx-export.md (corners).

Verification

  • Corpus, 62 DOCX before and after: all 62 are byte-identical, and the report's 1246 notes
    are identical. No corpus document composes a drawn node directly in a cell.

  • Reach, from a temporary trace, removed before commit, of every leaf the change gives a
    narrower box, across the qa, templates and examples suites:

    • pictures, a circle and a shape in the new test;
    • a nested table (252 → 170, its rows drawn at the table's own width either way);
    • spacers, which draw nothing;
    • the timeline marker of TimelineSplitSpikeTest, an 8pt circle drawn 16×8 before.

    No template and no example composes a picture or shape in a cell.

  • ComposedCellLeafWidthTest (new, qa, 8 tests):

    • a fitted picture in its own box;
    • a circle stays a circle;
    • a shape at its width from the cell's content edge;
    • one wider than the cell held to it;
    • a centred and a left-aligned paragraph keep the cell's width;
    • a page number set right keeps it too;
    • a PDF of the cells for inspection under target/visual-tests/table/.
  • DocxCarriedWithoutReportTest: the composed-shape corners case now pins its own width.
    10 and 12 on a 40×40 shape are named, and on a 20×40 one both are held at 10, as the page
    draws them, and are not named.

  • 5 sabotages, 4 caught:

    • every child at the cell's width;
    • a leaf not held to the cell;
    • text at its measured width;
    • a composed shape's corners against an unbounded width.

    Not caught: a composite given its measured width rather than the cell's box. A composite
    lays its children out at their own widths inside the box, so in every suite this gives the
    same output.

  • ./mvnw -B -ntp clean verify: BUILD SUCCESS, including every visual and layout-snapshot
    baseline in qa.

  • Knowledge pack: the claims and proofs indexes were regenerated for the lines the recipe
    moved. The API surfaces, stability doc, claims and routes checks all pass, and core javadoc
    passes with no warnings.

Lane: shared-engine (document.layout), with the render-docx report following it. PDF output
changes only for a node of a size of its own composed directly in a table cell narrower than the
cell's inner width.

…cell

A table cell gave the node composed in it the cell's inner width and
the height it measured. In a 120pt column padded 4pt, the page drew a
picture fitted to 100pt in a box 112pt wide, 112x56 for 100x50, a 20pt
circle as an ellipse 112pt wide and a 60pt picture stretched to
112x60, while Word and LibreOffice drew the pictures at their own size.

A node of a size of its own is now laid out at the width it measured,
as the flow and a row slot lay one out, held to the cell's inner width
where it measures wider. Text, which aligns in the width it is given,
and a composite keep the cell's inner box. The DOCX export measures a
composed shape's corners against its own width.
@DemchaAV
DemchaAV marked this pull request as draft October 20, 2026 07:18
…ipe lines

The composed-cell paragraph added to docs/recipes/tables.md moved the
lines its claims point at; the claims and proofs indexes follow them.
@DemchaAV
DemchaAV marked this pull request as ready for review October 20, 2026 07:19
@DemchaAV
DemchaAV merged commit 7e5d548 into 2.5-dev Oct 20, 2026
13 checks passed
@DemchaAV
DemchaAV deleted the fix/docx-composed-cell-picture branch October 20, 2026 09:01
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.

1 participant