Skip to content

fix(docx): stop reporting drawn tiles as dropped and alike corners as unequal - #902

Merged
DemchaAV merged 2 commits into
2.5-devfrom
fix/docx-report-tile-corners
Oct 14, 2026
Merged

DemchaAV merged 2 commits into
2.5-devfrom
fix/docx-report-tile-corners

Conversation

@DemchaAV

@DemchaAV DemchaAV commented Oct 14, 2026 •

Copy link
Copy Markdown
Owner

Why

Two notes in the DOCX export's report claimed losses the export did not make.

  • A tile reported dropped while drawn. A table whose composed cells hold a box framing text leaves that box to the panel it is written as, and draws its other cells' boxes. drawnByItsTable asked one table-wide flag whether the table skipped a box, so with a panel in one cell, a box node in any other cell was reported DROPPED "… so it is not in the document". Probed in a two-cell table:

    Cell beside the panel Drawn in document.xml Reported
    Tile (rectangle holding a dot) rect, ellipse DROPPED "shape container outline … not in the document"
    ShapeNode rect DROPPED "ShapeNode … its geometry has no semantic Word analogue"
    Rounded box roundRect, ellipse DROPPED
  • Corners named unequal that are drawn alike. "its corners are drawn at the largest of their radii" was said wherever the radii differ. But the page holds each radius to half the box's shorter side (PdfShapeFragmentRenderHandler.clampCornerRadius), and Word's rounded rectangle caps its one radius there too (DocxDrawings.roundness). So radii of 10 and 12 on a box 20 tall are both drawn at 10, in both, and the note named a loss that is not there.

What changed

  • CellDrawing. It keeps the fragments it skipped instead of a flag; nested tables add theirs to the outer one's. skippedBoxes() stays for the row-paint note, which is about the whole table.
  • drawnByItsTable. It asks skippedABoxInThisCell(): whether a skipped box reaches into the composed cell being written (CellBox.overlaps against composedCellBoxes, the boxes the layout placed that cell in). Overlap, not containment: a fixed box wider than its column still stands in its cell, and a box reaching into the next cell counts there too. The layout does not say which of a cell's boxes is which node. So in a cell a skipped box reaches into, a box node is still reported, as aBoxLostInACellIsStillReportedWhenItsTableDrawsSomethingElse pins. In any other cell, the table drew it. A skipped box that reaches into none of its table's rows (pushed out by a layer's offset or a negative margin) stands in no cell the report can ask, so that table keeps the old table-wide answer, as it does where no cell box is known.
  • DocxDrawings.roundsUnequally(radius, width, height). It holds each radius to half the shorter side, as the page does, and compares the results. It decides at all three places the corner note is made:
    • a drawn box fragment (roundsCornersUnequally);
    • a ShapeNode in the flow, now read off its drawn fragment like the rest, where it was decided by isUniform alone. Its corner phrase now comes before a gradient's in its note;
    • a shape container or a ShapeNode composed in a cell (cornersDiffer). A cell lays a shape out at its own width, so a ShapeNode there is held to half its height, which it is drawn at. That bound never misses a difference the page draws. A shape in a cell narrower than it is tall can still be named; the CHANGELOG and the recipe say so.
  • Docs. The recipe, the ledger entries and the Javadoc state both rules.

Verification

  • Probe. On the three tables above, no note is DROPPED after the change, and the drawings in document.xml are the same.
  • Corpus. All 62 DOCX are byte-identical to 2.5-dev's, and all 1332 notes are unchanged: no corpus document holds either case.
  • New tests.
    • DocxComposedCellTest.aBoxInACellBesideOneItsTableLeavesToAPanelIsDrawnAndNotReportedDropped has a panel, a tile and a shape in one row. It asserts no DROPPED note and the three drawings.
    • DocxCarriedWithoutReportTest.cornersWhoseRadiiDifferOnlyPastHalfTheShorterSideAreNotNamed checks a shape, a container in the flow and a container in a cell. With radii 10/12 on a 20-tall box none of them is named; with 8/12 all of them are.
  • A changed fixture. aSectionDrawnOverTheFlowWithCornersOfDifferentRadiiSaysTheyAreDrawnAtTheLargest used a section whose box the layout makes 39.69 × 2.95pt. There its radii 2 and 8 are both drawn at 1.475. The section now has 10pt of padding, so its radii differ as drawn.
  • More tests.
    • DocxComposedCellTest.aBoxReachingPastItsCellIsStillReportedWhereItsTableLeftIt: a 140pt box framing text in a 60pt column is still reported DROPPED.
    • DocxComposedCellTest.aBoxPushedOutOfEveryCellIsStillReported: a box framing text pulled above its table by a negative margin is still reported DROPPED.
    • DocxCarriedWithoutReportTest.aShapeComposedInACellNamesTheCornersItIsDrawnWithAtTheCellsWidth: a 20 × 40 shape with radii 10/12 in a 100pt cell is drawn 100 wide, so its corners are named; a 20 × 20 one beside it holds both at 10 and is not.
  • Sabotage. 16 sabotages, 15 caught. The one that survives drops the outer table's stray flag inside a nested table. A test for it would pin the fail-closed DROPPED on a nested drawing the table does draw, so the flag is carried as the skipped boxes are, untested.
  • Gate. ./mvnw -B -ntp clean verify → BUILD SUCCESS (render-docx 1581, qa 1820).

Lane: render-docx — report notes only; the Word file is unchanged

… unequal

A table whose composed cells hold a box framing text leaves that box to
the panel it is written as, and draws its other cells' boxes. Asked of
the whole table whether it skipped a box, a tile, a shape or a rounded
box in another cell was reported DROPPED, "not in the document", while it
stood drawn. CellDrawing now keeps the boxes it skipped, and a box node is
reported only in a cell one of them reaches into, past its edges
included; with no cell box known it is reported as before.

The page holds each corner's radius to half the box's shorter side and
Word's rounded rectangle its one, so radii that differ only past that are
drawn alike: 10 and 12 on a box 20 tall are both 10. DocxDrawings.
roundsUnequally compares the held radii. A drawn shape's corners are now
read off its fragment, as every drawn box's are; one composed in a cell,
drawn as wide as its cell, is held to half its height.
…shape is still named

A box framing text that reaches into none of its table's rows, pushed out
by a layer's offset or a negative margin, stands in no cell the report can
ask: that table now keeps the table-wide answer, and a box node there is
still reported rather than lost in silence.

A shape composed in a table cell is held to half its height, its width
being the cell's; the CHANGELOG and the recipe now say one in a cell
narrower than it is tall can still be named. Tests pin the shape that is
not named, and the dropped box by its own note.
@DemchaAV
DemchaAV merged commit c8e57a3 into 2.5-dev Oct 14, 2026
13 checks passed
@DemchaAV
DemchaAV deleted the fix/docx-report-tile-corners branch October 14, 2026 22:22
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