fix(docx): seat text off its baseline as the page does and hang text below its band - #787
Merged
Merged
Conversation
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
The DOCX export wrote every paragraph on its baseline. A paragraph with
TextVerticalAlign.TOP,CENTERorBOTTOMis seated by its cap band on the page, and Word set it lower or higher.LumaStudioInvoiceshows both problems this PR fixes:DocxLayerColumns.bandclamped the space below to zero. Luma's title line is 13pt deeper than its title block, so the invoice's details and everything under them stood 13pt lower, and the notes landed on a second page.What changed
ParagraphSeating(render-pdf,@Internal) holds the PDF backend's seating correction. The correction moves the baseline so the cap top meets the line's top, the cap band sits on its middle, or the baseline sits at its foot.PdfParagraphFragmentRenderHandlerandPptxParagraphFragmentRenderHandlercall it instead of their private copies, and the DOCX backend calls the same code, so the three cannot drift apart. (PptxGeometryAssertionskeeps its own copy as an independent oracle.)seatShift/seatInTheLinecompute that correction for a seated paragraph. One shift covers the Word paragraph; the page seats each line by its own, which differs only for lines in different sizes. They use the first line holding text and a lazily builtPdfFontLibraryFactory.measurementLibraryover the export's font families, which is the library the layout measured with. The result is written asw:positionon the paragraph's own runs:getRuns()does not list them.DocxLayerColumns.bandkeeps a negativebelow.writeOverlayBandturns it intohangingBelow, aswriteLinePairalready did for a title-and-dates line, so the next block takes the overhang out of the gap under the band. The band sets the hang rather than adding to it: itsbelowis measured from its lowest text, a nested band's included, so an inner band's overhang is not taken twice.DocxLayoutMetrics.linesreturns every line a node laid out.Verification
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 -am, gave BUILD SUCCESS (1791 + 127 tests). After install, the examples are 93 green and the knowledge checks green.extract-api --checkis current:knowledge/api/excluded.jsonregenerated for the new@Internalclass, and no surface changed.DocxVerticalSeatTesthas 6 tests. Each was checked by switching its guard off and watching it fail, with the build's outcome printed.TOP, lowered forBOTTOM, halfway between the two forCENTER, and left alone forDEFAULT.Exact lines: "Élan Hold gypsy" set at 36pt
TOP,CENTERandBOTTOMwas converted by Word and showed no accent or descender clipped.Template corpus (62 documents), converted to PDF by Word. Only
LumaStudioInvoice, its long variant andNorthlineProposalchange.LumaStudioInvoiceLumaStudioInvoice(long)NorthlineProposalIn
LumaStudioInvoice, "INVOICE" stands over its rule and the lockup's "L" over its "&Co.".Known limits: a page zone's paragraph (a header or footer) is written on its baseline, having no laid-out lines to seat by; a seated picture's line keeps the room of its unseated reach. Display text set in Spectral stands about 6pt low in Word, on its baseline too (
DEFAULTmeasured the same). Word sets a line's foot by its own reading of the font's metrics. That is a per-font difference for a later change.docs/architecture/backend-capability-matrix.md(paragraph row, DOCX) anddocs/architecture/package-map.mdrecord the seating and why render-docx uses render-pdf for it.Lane: shared-engine (render-docx, render-pdf, render-pptx). No public API change.