Repository navigation
fix(docx): hold a ruled table's first and last rows less the rule and a half they carry - #829
Merged
Merged
Conversation
… a half they carry
…old a row its rules fill at a twip, and re-render the Word preview
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
holdRowHeightholds a table's row at the height the page gives it. It writestrHeight(at least) as that height less the most any cell takes around its content: its top and bottom margins and one horizontal rule (verticalMargins).Word, like LibreOffice, reads
trHeightas the cells' content. It splits a rule between two rows half to each row: the lower row's rule, where the two differ. The rule above the table and the rule below it go whole to their row.clearOfTheRulesalready takes the rules out of the padding that way. So the first row and the last carry a rule and a half, and written less one rule they were held half a rule taller than their content needs.Measured in Word, on a hand-made table of four rows ruled at 0.75pt (7pt padding, exact 10.8pt lines, margins as
clearOfTheRuleswrites them):In
EditorialProposal, takingtrHeightoff the timeline table's last row moved its bottom rule up 0.24pt.EditorialProposal. Its timeline and investment tables each stood that much taller in Word. Its second page ran 2.5pt low by the acceptance block, with 11 lines more than 2pt off.What changed
outerRulesBeyondOne. It counts what a table's first or last row holds of its rules beyond the one ruleverticalMarginscounts:The first row is held after the rest of the table is written, since its share of the rule under it is the next row's.
holdRowAtLeast(row, points, beyond).holdRowHeightpasses that in, and it comes off the written height too.fitBlankLinesToTheRow).The half rules are rounded as a sum. A 0.75pt rule is 15 twips; rounded one half at a time, a one-row table lost a twip.
Javadoc.
holdRowHeightandfitBlankLinesToTheRowsaid Word reads a row's written height as the row's whole. It reads it as the content, as LibreOffice does.Baselines.
word-windows,libreoffice-windowsand their-linesfiles are rewritten; every document with a ruled table moves.libreoffice-linuxand its-linesfile are taken from this PR's first CI run (docx-fidelity-37125838538). On Linux, LibreOffice moves only three documents:MerchantInvoiceagain, so the next CI run re-measures it.Preview.
assets/readme/examples/word-export-companion.docxis re-rendered. Its table's first and last rows are written 8 twips shorter, and nothing else in it changes.Docs.
CHANGELOG.md, and the Tables row ofdocs/recipes/docx-export.md.Verification
Template corpus, re-measured in full in both editors on Windows.
No line is lost, and page counts are unchanged.
Per document, median in Word:
Lines that move further from the page. In each case a table that now stands where the page sets it stops cancelling an offset of its own next to it.
MeteredInvoice.ObsidianInvoice: median 0.26 → 0.32pt.ModernProposal: median 0.35 → 0.48pt. The page above its timeline table already stands 0.4 to 0.8pt high. The lines from the table down now stand 0.4 to 0.5pt high, where they ranged from 0.3pt high to 0.7pt low.EditorialProposal: 34, on its second page, which a page break of LibreOffice's own already puts 44pt off. It moves 0.5pt on average, 1.2pt at most.MeteredInvoice: 8.ModernProposal: 3.ObsidianInvoice: 2.WorkspaceInvoice: 1.New test class,
DocxRuledRowHeightTest, four tests.Each test fails when its mechanism is taken out:
beyond, the first and last rows are written at 274 and a one-row table at 289;DocxRuleRowTest.aLineWithLettersKeepsItsHeightnow expects a rule and a half between a last row's written height and its line, where it expected one. The line itself is unchanged.Examples module:
./mvnw -B -ntp test -f examples/pom.xmlruns 93 tests,CommittedAssetDriftTestamong them: BUILD SUCCESS.Full reactor gate:
./mvnw -B -ntp clean verify -pl :graph-compose-core,:graph-compose-render-pdf,:graph-compose-render-docx,:graph-compose-render-pptx,:graph-compose-templates,:graph-compose-testing,:graph-compose-qa,:graph-compose-coverage -amgives BUILD SUCCESS. render-docx runs 845 tests, qa 1814.Known limits
ObsidianInvoice's header row,MeteredInvoice's payment details and closing note, andModernProposal's blocks above its timeline.Lane: shared-engine (render-docx). No public API change.