Repository navigation
fix(docx): set a row and an alignment composed in a table cell where the page does - #909
Merged
Merged
Conversation
…the page does Content composed in a table cell has no place of its own in the layout. A row the page divides by what its children measure (an arrangement other than START, a growing spacer, an auto column) had its columns left to Word, which sized them to their text: an amount set at the cell's right edge stood at its middle. A block in addAligned(...) was written from the cell's left: a total aligned right and a centred picture both stood at the left. The paragraphs' lines are laid out under the table's path and matched to them, so composedRowStarts reads where each child of such a row starts (a spacer where the page spreads the room between its neighbours) and the row is written by the placed-column path; lines found in another cell are not taken. placeComposedAcross holds an aligned paragraph in to its lines and a picture to where the alignment sets one of its written width. A row holding a child the lines do not place, an aligned block of any other kind or whose lines stand in another cell, and either inside a panel or another table in the cell are written as before and named in the report; an aligned drawing is drawn by its table where the page draws it.
DemchaAV
marked this pull request as draft
October 15, 2026 22:19
…d a pulled-up line as its cell's A row of stated columns gives each child its column's slot, a spacer among them, and the room an arrangement spreads is not there to share: placed by that share, the spacer made the column before it wider than the page's slot, and Word could wrap its text elsewhere. Such a row is now written as before and named. A paragraph with no text in a composed row stands in a column of its own, as a spacer does, rather than sending the row back to Word. A line a container pulls up past its cell's top, or out at a side, is read as the cell's: its first baseline stands in the cell, and its box crosses it. An alignment of a row, which is as wide as the width it is set in, or of an empty paragraph says nothing. Tests cover a row centred and spread around in its cell, a padded row with margins, an empty paragraph, a spacer in stated columns, an aligned row and a pulled-up line; the test's row spacing uses spacing(double) rather than the deprecated gap(double).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Content composed in a table cell (
DocumentTableCell.node(...)) has no place of its own in the layout. Its paragraphs' lines are laid out under the table's path, so the writers that read a node's placement found nothing, and two things went silently wrong.START, a spacer that grows, anautocolumn. Such a row was written as a nested one-row table with no grid, so Word sized its columns to their text. In a rowSPACE_BETWEENof "Total" and "$120", the page puts "$120" at x 284.86pt, against the cell's right edge. Word put it at 170.57pt, the middle of the cell. An auto column's value wrapped onto a second line in Word, while the page keeps it on one.addAligned(...)was written from the cell's left. A right-aligned "Total due" sits at 257.63pt on the page and at 24pt in Word. A centred 40pt picture sits at 150pt on the page and at 24pt in Word.The report said nothing in either case.
What changed
composedRowStartsfinds where each child of such a row starts. A paragraph starts where its lines start (DocxLayoutMetrics.firstTextBox, the lines the table laid out for it). In a row with no stated columns, a spacer or an empty paragraph stands where the page spreads the room between its neighbours: between two children it knows, the run takes the room they leave, less its widths and the gaps, in equal shares, as an arrangement spreads it. A growing spacer takes all of that room. A run at the row's edge is set from the row's padding: its columns hold nothing either way. In a row of stated columns, a spacer has its column's slot, which no line reports. Such a row is written as before and named. Everything is measured from the row's left: the cell's box, plus the margin written for the cell, plus the containers' insets. The row is then written by the same placed-column path a placed row takes (placedColumns, the auto column's editor point,takeHang).placeComposedAcrossholds an aligned block in throughholdIn, the same call the body uses.holdInnow takes the box's x and width.resolveImageDimensionsin the width the alignment leaves it (its padding comes off inside the sizing), aswriteImagesizes it.**Total**in another cell lays out. Such lines are not taken.APPROXIMATED). These cases keep the old output and are now named in the report:addAligned(...)passage cover composed cells; the CHANGELOG has an entry under 2.5.0 Public API.Verification
Word 16, measured with PyMuPDF. Before → after, against the page:
SPACE_BETWEEN: "$120"addAligned(RIGHT): "Total due"addAligned(CENTER)pictureThe auto column's value went from two lines at 170.57 to one line at 63.14 (page 62.14). The extra point is the auto column's editor slack, as in a placed row.
DocxComposedCellGeometryTest, 25 tests:SPACE_BETWEEN,CENTER, an auto column, a growing spacer with spacing, a fixed spacer inSPACE_BETWEENand inSPACE_AROUND, a padded row with margins, and an empty paragraph. Each expected grid is read off the session's own layout fragments.Sabotage. 20 sabotages each undo one part of the change, and every one fails a test.
Template corpus (62 DOCX) against
2.5-dev. All 62 are byte-identical and the report notes stay at 1244 → 1244: no corpus template composes such a row or alignment in a cell. The aligned SVG icons in panels inside cells ininvoice-paymentsandinvoice-workspaceare drawings, drawn as before, with no note../mvnw -B -ntp clean verify→ BUILD SUCCESS (render-docx 1653, qa 1820).Lane: shared-engine (render-docx semantic DOCX backend), no public API change.