Skip to content

fix(xlsx): seat category labels using native font metrics - #1576

Merged
developer0hye merged 2 commits into
mainfrom
fix/issue-1568-category-baseline
Sep 5, 2026
Merged

fix(xlsx): seat category labels using native font metrics#1576
developer0hye merged 2 commits into
mainfrom
fix/issue-1568-category-baseline

Conversation

@developer0hye

@developer0hye developer0hye commented Sep 5, 2026

Copy link
Copy Markdown
Owner

Summary

Place explicitly sized worksheet line/area category labels using the measured font ascent, descent, and leading, the actual plot bottom, and the available chart height. The old automatic label band placed the budget workbook's month labels too high and did not follow shorter manual plots. Native one-factor font-size, font-family, plot-height, and fractional-frame-height probes distinguish the natural baseline from its bottom cap and the order of rounding.

The calibrated Calibri/Avenir metrics retain their source line gap when a runner uses a substitute font.

Related: #1568. The shared chart-origin offset remains tracked in #1542.

Testing

  • Failing native-observation regressions captured before each correction: plot/size seating, fractional remaining-space rounding, and Arial leading quantization. Portable Calibri and numeric Arial cases cover line/area charts and short/default plots; host, flowed-chart, and implicit-size controls preserve their existing behavior.
  • Initial candidate workspace tests: 3,473 passed. Linux CI then exposed a source/substitute metric mismatch for Calibri 24pt on a short plot. The follow-up keeps the calibrated source ascent, descent, and zero line gap together; both existing worksheet-baseline regressions and current workspace clippy pass without changing their expectations. Exact-head CI validates the follow-up across platforms.
  • Native probe matrix on the initial candidate: 61 conversions passed; maximum origin-corrected baseline residual 0.000189 pt (0.01 pt gate). Five font families and multiple sizes, plot heights, and fractional frame heights; every native suite has a layout-identical no-patch control.
  • The follow-up locked rebuild has a complete two-page MuPDF trace identical to the reviewed initial candidate (excluding the PDF filename).
  • Same source fixture, Cargo.lock, and Excel DFonts before/after. The 13 month/year labels move from y=347.31837pt to 347.67213pt (native 347.88pt). The remaining -0.20787pt agrees with the independent chart text-origin offset in XLSX charts: fitted drawing foreground keeps the physical page origin #1542. January's x=185.98150pt is unchanged.
  • Page 1 is pixel-identical at 150 DPI. At 300 DPI, page 2 changes 7,544 pixels, all within the category labels. All 831 canonical page-2 drawing primitives retain geometry and paint.
  • All 55 page-1 and 480 page-2 material clusters have reviewed explicit dispositions. Normalized native/before/after text matches on both pages (486 and 2,120 non-whitespace characters).

Baseline: f0071d9ea88b71d33f4e5ba8fc2fc30ad206c099, including the separate axis-font and boundary-space fixes. Fixture SHA-256: 2b4a2d8dceda58758593c88409875efbda05780559154c02bd13fef4f7a1c65b; Cargo.lock SHA-256: 750f50c507b281f84b945b09573333ffa02dc45cddd566481af8535ae101e612.

Reproduce conversion with cargo run --locked -p office2pdf-cli -- tests/fixtures/xlsx/issue_1181_fit_to_height.xlsx -o output.pdf --font-path '/Applications/Microsoft Excel.app/Contents/Resources/DFonts'. Compare both pages using scripts/compare_layout.py GT.pdf output.pdf --audit --fine-shift 0.5 --json, and scripts/compare_render.py GT.pdf output.pdf --page P --dpi DPI --fine-shift 0.5 --cluster-report PATH --cluster-dispositions PATH --strict-clusters (150 DPI page 1, 300 DPI page 2).

Visual impact

  • Rendered PDF change or visual evidence added

Visual audit

Visual comparison

Native Excel 16.112.3 exports, verified Excel/Quartz PDF provenance. Page 2 at 300 DPI:

GT Before After
GT Before After

The unchanged page-1 native comparison is attached to #1550, #1551, and #1552.

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, rectangle geometry deviation, 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: two printable sheets retain their native order.
Element presence Remaining: #1185 marker rendering and #1566 omitted worksheet separator lines. Existing axes and chart grid paths are retained.
Position/size Remaining: #1272 chart frame, #1542 fitted drawings, #1545 fixed-row text, #1550 title-row height, #1552 footer position. Fixed: the category baseline follows the native face metrics and available chart height.
Rotation/flip No deviation observed: no transform changes.
Fill Matches GT: intended series, header, and table fills are unchanged.
Stroke/border Remaining: #1566 omitted worksheet separator lines; #1564 fitted worksheet rule thickness/placement. Declared chart-line opacity remains 25% and 50%, matching native. Gray table hairlines, teal total rules, and brown category rules retain their paths; no dashed or dotted source rules are lost.
Shape outline geometry Remaining: #1185 marker, #1272 chart frame, and #1550 title-band height. All 831 canonical primitives retain geometry and paint.
Text content Matches GT after whitespace normalization of pdftotext -layout; all label/value characters are preserved; the source month categories also retain their significant trailing space.
Font family/weight/style Matches GT: the existing Cambria major-theme category font is preserved. Bold Cambria section headings, bold Trebuchet expense headings, Arial bold instruction title, and Aptos footer retain their emphasis. No italic or underlined runs are changed.
Text color Matches GT: chart labels and worksheet text retain their colors.
Alignment Remaining: #1542 drawing labels, #1545 row text, #1550 first-page content, #1552 footer baselines. Fixed: month/year labels now use the native baseline seat relative to the chart origin.
Line/paragraph spacing Remaining: #1545 fixed-row seating and #1551 wrapped note line pitch.
Clipping/overflow No deviation observed: no new clipping or overflow; native and output both display ##### in the narrow annual-total cells.

Signed-off-by: Yonghye Kwon <developer.0hye@gmail.com>
Signed-off-by: Yonghye Kwon <developer.0hye@gmail.com>
@developer0hye
developer0hye merged commit bf81270 into main Sep 5, 2026
35 checks passed
@developer0hye
developer0hye deleted the fix/issue-1568-category-baseline branch September 5, 2026 10:26
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