Skip to content

fix(xlsx): keep declared wrapped line pitch - #1508

Merged
developer0hye merged 1 commit into
mainfrom
fix/issue-1498-segoe-wrapped-pitch
Sep 2, 2026
Merged

fix(xlsx): keep declared wrapped line pitch#1508
developer0hye merged 1 commit into
mainfrom
fix/issue-1498-segoe-wrapped-pitch

Conversation

@developer0hye

Copy link
Copy Markdown
Owner

Summary

  • keep spreadsheet line-box metrics tied to the face office2pdf actually paints while selecting Excel's wrapped-line advance from the workbook's declared font family
  • preserve the workbook's Segoe UI 12pt 16pt native line advance when a host paints the bundled metric-compatible substitute
  • share representative-run selection between declared and painted metric-family resolution
  • add a portable substituted-face regression that failed at 13.68pt before the fix and now emits the expected 16pt advance

Related issue

Fixes #1498

Testing

  • CARGO_INCREMENTAL=0 cargo test --locked -p office2pdf substituted_sheet_face_keeps_the_declared_excel_wrapped_advance -- --nocapture
  • CARGO_INCREMENTAL=0 cargo test --locked -p office2pdf wrapped_sheet_cell_paces_its_lines_on_excels_advance -- --nocapture
  • CARGO_INCREMENTAL=0 cargo test --locked -p office2pdf sheet_cell -- --nocapture (28/28)
  • CARGO_INCREMENTAL=0 cargo test --locked -p office2pdf centered_fixed_sheet_rows_share_one_center_across_two_and_three_wrapped_lines -- --nocapture
  • CARGO_INCREMENTAL=0 cargo test --locked --workspace (2,814 library tests plus DOCX/PPTX/XLSX/public-visual/PDF/CLI/package integration suites and doctests passed; documented ignores unchanged)
  • python3 -m unittest discover -s scripts/tests -p 'test_*.py' (326 tests; 30 business mocks and stored layout baseline included)
  • cargo fmt --all -- --check
  • git diff --check
  • CARGO_INCREMENTAL=0 cargo check --locked --workspace
  • CARGO_INCREMENTAL=0 cargo clippy --locked --workspace --all-targets -- -D warnings
  • CARGO_INCREMENTAL=0 cargo check --locked --target wasm32-unknown-unknown -p office2pdf
  • CARGO_INCREMENTAL=0 cargo check --locked --target wasm32-unknown-unknown -p office2pdf --features wasm
  • CARGO_INCREMENTAL=0 cargo check --locked --target wasm32-unknown-unknown -p office2pdf --features wasm-cjk-font
  • CARGO_INCREMENTAL=0 wasm-pack build crates/office2pdf --target web --features wasm
  • CARGO_INCREMENTAL=0 wasm-pack build crates/office2pdf --target web --features wasm-cjk-font
  • Node WASM tests with CARGO_PROFILE_DEV_DEBUG=0: 10/10 general and 11/11 CJK passed
  • exact-main versus branch rendering of all 10 business XLSX fixtures (16 pages): all 10 PDFs are byte-identical; all 20 PDFs pass qpdf --check
  • qpdf --check target/issue-1498/after.pdf
  • fresh Poppler and MuPDF 300-DPI full-page, diff, and matched-crop inspection

Visual impact

  • No rendered PDF change
  • Rendered PDF change or visual evidence added
  • Reason: the first and second baselines in the three two-line page-2 table headers spread symmetrically by 0.655pt, changing their printed pitch from 11.80994pt to Excel's 13.12pt while retaining the row centre, x origins, widths, wrapping, fills, and every non-target page element.

Visual audit

  • Issue: XLSX: a two-line centered table header compresses its line pitch #1498
  • Fixture: Gift Budget and Tracker1.xlsx (25f5dc75dab19ea12042979a61842314ddc226e3e45d447e36b2a2a104112613)
  • GT PDF: native Excel/Quartz composite ed705d89307735651eb67abedb59d014666b2567aa3be73eabd7f4518dd8f659; qpdf-clean working copy 1926ebd14c061cb0c3040a96c80cdd65ae3a0b6e19f43a499fa5adf4389ea26e
  • After PDF: d8628df93bf19f7257c13081c527d357619602719590db1b6f43f2ed3093f260
  • Page(s): 1-2
  • Renderer and DPI: Poppler and MuPDF, 300 DPI
  • Evidence mode: fix
  • Layout audit report: assets/bugfixes/issue-1498/layout-audit.json
  • Render cluster reports: assets/bugfixes/issue-1498/render-clusters-page-1.json, assets/bugfixes/issue-1498/render-clusters-page-2.json
  • Fine-detail threshold: 0.5pt
  • Layout audit page count: Pass
  • Layout audit text flow: Pass
  • Layout audit visible fills: Pass
  • Layout audit large shifts: Pass
  • Layout audit fine shifts: XLSX: a header/footer run before the first font code takes the Normal font's family but not its size or colour #1210, XLSX chart: one middle value-axis tick sits 0.70pt above its peers #1499
  • New follow-up issues found in this audit: None
  • Model vision findings: The full-page, diff, and full-resolution crops show all three two-line table headers retaining their row centre while the two baselines now match Excel's 13.12pt pitch in both Poppler and MuPDF. Page 1 remains unchanged; page 2 retains all text, wrapping, table and chart geometry, fills, borders, and image placement outside those six target lines. The output retains 12/34 text lines and 45/156 rectangles before versus after. All 73 page-1 and 50 page-2 strict 5% diff clusters were inspected and dispositioned. The only remaining shifts above 0.5pt are the chart $140 tick (XLSX chart: one middle value-axis tick sits 0.70pt above its peers #1499) and sensitivity footer (XLSX: a header/footer run before the first font code takes the Normal font's family but not its size or colour #1210). The native GT text layer fragments Birthday Budget with two extra spaces, but the rendered text is visually intact and office2pdf's extracted text is correct.
  • GT: assets/bugfixes/issue-1498/gt.jpg
  • Before: assets/bugfixes/issue-1498/before.jpg
  • After: assets/bugfixes/issue-1498/after.jpg

Visual comparison

GT Before After
GT Before After

Required inspection

  • Rendered all evidence at 150 DPI or higher
  • Stored progressive JPEG quality 86 assets with metadata stripped
  • Used Codex/Claude vision to inspect the full GT/output pages, diff, and matched crops
  • Inspected matched region crops at full resolution
  • Ran compare_layout.py --audit --fine-shift PT and dispositioned every fine/large text-instance shift, painted-text visibility mismatch, and visible-fill occlusion
  • Ran compare_render.py --cluster-report PATH --strict-clusters and dispositioned every material 5% fuzz diff cluster by explicit ID
  • Inventoried hairlines and border dash styles
  • Inventoried font weight, italic, and underline emphasis

Deviation audit

Check Result
Page count/order Matches GT
Element presence Matches GT
Position/size Remaining: #1210, #1499; Fixed #1498
Rotation/flip Matches GT
Fill Matches GT
Stroke/border Matches GT
Shape outline geometry Matches GT
Text content Matches GT visually; the native text layer fragments Birthday Budget, with no rendered or office2pdf text loss
Font family/weight/style Remaining: #1210
Text color Remaining: #1210
Alignment Remaining: #1499
Line/paragraph spacing Fixed #1498
Clipping/overflow Matches GT

GT integrity

  • PDF pages: 2
  • Printable worksheets: 2
  • Hidden worksheets: 1
  • Provenance: the two source pages were exported by Microsoft Excel with macOS Quartz PDFContext, then combined into the stored native reference
  • Structural corruption: the raw composite has a recoverable object-count/xref warning; the qpdf-clean working copy used by every report passes qpdf --check and decodes pixel-identically in Poppler and MuPDF
  • GT-side font substitution: Arial only; the target table headers declare Segoe UI 12pt
  • Source inspection records Segoe UI 12pt in wrapped cells I6, J6, and M6 on the fixed 49.5pt row; this corrects the original issue body's stale font-size description

Checklist

  • Commits include a Signed-off-by line
  • Mandatory documentation freshness reviewer returned PASS: before commit
  • PR scope contains one root cause
  • Remaining visual deviations each reference an open issue

Signed-off-by: Yonghye Kwon <developer.0hye@gmail.com>
@developer0hye
developer0hye merged commit ddfd683 into main Sep 2, 2026
18 checks passed
@developer0hye
developer0hye deleted the fix/issue-1498-segoe-wrapped-pitch branch September 2, 2026 14:24
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.

XLSX: a two-line centered table header compresses its line pitch

1 participant