Skip to content

fix(docx): keep a card's paint off the paragraphs in its table's cells - #731

Merged
DemchaAV merged 2 commits into
2.5-devfrom
fix/docx-table-in-filled-card
Sep 23, 2026
Merged

DemchaAV merged 2 commits into
2.5-devfrom
fix/docx-table-in-filled-card

Conversation

@DemchaAV

@DemchaAV DemchaAV commented Sep 23, 2026 •

Copy link
Copy Markdown
Owner

Why

A filled or bordered card is written by painting every paragraph inside it (w:shd, w:pBdr), since Word has no element that wraps a run of paragraphs.

A table inside the card writes its plain-text cells directly. A cell built from a node (DocumentTableCell.node(...)) goes through newBodyParagraph, the same path as body paragraphs, and that path painted it with the card too. In a zebra table inside a filled card, the composed cell came out in the card's colour laid over its stripe. With a bordered card, the paragraph inside the cell got boxed.

What changed

  • newBodyParagraph takes container paint only from containers opened inside the cell being written.
    • writeCellNode records how many containers were open when the cell began (cellPaintDepth, saved and restored around nested cells).
    • The card's own paragraphs keep their paint, and the cell's own fill (w:shd on the cell) shows as the page draws it.
    • A container opened inside the cell (a filled section as a composed cell) still paints its own paragraphs.
  • writeRow asks the same question through paintHere(), which both paths share. Before, a row built into a zebra cell of a filled card shaded its own cells in the card's colour, covering the stripe. A row placed directly in a card still shades its cells with the card's fill. It no longer draws a bordered card's outline around the text of each cell, which matches the PDF: the PDF draws only the card's outline.
  • A cell with no fill of its own is left alone. The engine's default cell style is white (TableCellLayoutStyle.DEFAULT), so the PDF draws such a cell white inside a card too. In Word the card's shading sits on its paragraphs and never under the table, so that cell is already white. Shading it with the card's colour would have moved Word away from the PDF.
  • Recipe ("What a panel keeps and loses") and CHANGELOG under v2.5.0.

Verification

In an editor. A card with a zebra table whose last row holds a composed cell, converted with LibreOffice. The composed cell is grey like the rest of its stripe, as in the engine's PNG. Before the change its paragraph shading was the card's E6F0FF.

Gate. Full reactor gate (clean verify over core, render-pdf/docx/pptx, templates, testing, qa, coverage) → BUILD SUCCESS. Examples after install: 93 green. No committed preview moved.

New tests in DocxContainerPaintTest (12 total, +5):

  • a composed cell in a filled, bordered card keeps its zebra fill, with no paragraph shading and no paragraph border;
  • a row built into a zebra cell leaves its own cells unshaded;
  • a row directly in a bordered card keeps shaded cells, with no border around the text in each cell;
  • the card paints its paragraphs again after the table;
  • a filled section inside a cell still paints its paragraph.

Reverting either path to "always paint" fails the matching test.

Found alongside, not fixed here. Two tables with nothing between them are merged into one table by LibreOffice. Their different column grids then squeeze the result, and text breaks letter by letter. I proved this by swapping tables in the XML. It affects any two consecutive tables, not only inside a card, and is the next PR.

Lane: shared-engine (render-docx). No public API change.

A composed table cell writes its paragraphs through the body path, so
they took the enclosing card's fill and border as paragraph shading:
in a zebra table inside a filled card the composed cell showed the
card's colour over its stripe, and a bordered card boxed the
paragraphs inside cells. A paragraph in a cell now takes paint only
from a container opened inside that cell.
writeRow shaded its cells with the innermost panel's fill without the
cell check, so a row built into a zebra cell of a filled card came out
in the card's colour over the stripe. Row cells and cell paragraphs now
ask the same question (paintHere). Tests pin a row in a composed cell,
a row directly in a bordered card, and the panel painting again after
a table.
@DemchaAV
DemchaAV merged commit ae93ff3 into 2.5-dev Sep 23, 2026
12 checks passed
@DemchaAV
DemchaAV deleted the fix/docx-table-in-filled-card branch September 23, 2026 16:44
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