Skip to content

fix(xlsx): carry the workbook Normal font onto unstyled cells#469

Merged
developer0hye merged 1 commit into
mainfrom
fix/xlsx-normal-font
Jul 26, 2026
Merged

fix(xlsx): carry the workbook Normal font onto unstyled cells#469
developer0hye merged 1 commit into
mainfrom
fix/xlsx-normal-font

Conversation

@developer0hye

@developer0hye developer0hye commented Jul 25, 2026

Copy link
Copy Markdown
Owner

Summary

  • carry the workbook Normal font (styles.xml font 0) onto cells whose own style names no font or size
  • stop discarding a cell font because it is Calibri, or a size because it is 11.0
  • return NormalFont from extract_normal_font and derive the column print metric next to it

Related issue

Fixes #462

Details

A cell with no s attribute uses cellXfs[0], whose font is the workbook Normal font. umya reports no font at all for such a cell, so the style path returned TextStyle::default() and the renderer picked its own family and size.

Two special cases compounded it: the family was discarded when it was "Calibri" and the size when it was 11.0, on the grounds that they were "the Excel default". Both left the most common workbooks to the renderer's serif default rather than to Calibri, which font substitution resolves perfectly well. A rich-text run naming Calibri was ignored for the same reason.

pdffonts on the regression fixture, whose Normal font is Malgun Gothic 12:

before after
embedded faces LibertinusSerif-Regular, Calibri MalgunGothic, Calibri

The Libertinus fallback is gone: nothing on the page falls back to the renderer default any more.

Testing

  • cargo fmt --all -- --check
  • cargo test --workspace
  • cargo clippy --workspace --all-targets --all-features
  • pdffonts before/after comparison on tests/fixtures/xlsx/theme_color_drawing.xlsx
  • pdftoppm -r 150 rendering, matched full-resolution title crops, and magick compare -metric AE -fuzz 5%

Visual impact

  • No rendered PDF change
  • Rendered PDF change or visual evidence added
  • Reason: unstyled cells now render in the workbook Normal font and size.

Visual audit

  • Issue: XLSX: unstyled cells lose the workbook Normal font #462
  • Fixture: tests/fixtures/xlsx/theme_color_drawing.xlsx
  • Page(s): page 1 of the Excel GT and of the office2pdf output
  • Renderer and DPI: pdftoppm, 150 DPI
  • Evidence mode: fix
  • New follow-up issues found in this audit: None
  • GT: assets/bugfixes/issue-462/gt.jpg
  • Before: assets/bugfixes/issue-462/before.jpg
  • After: assets/bugfixes/issue-462/after.jpg

The GT is the native Microsoft Excel export already captured for this fixture in #434, reused unchanged: same workbook, same page, same renderer, same 150 DPI.

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
  • Inspected matched region crops at full resolution
  • Ran the 5% fuzz pixel-difference sweep
  • Inventoried hairlines and border dash styles
  • Inventoried font weight, italic, and underline emphasis

The 5% fuzz sweep against the size-normalized GT moves from 290,500 to 290,889 differing pixels: the drawing geometry defects tracked in #459 and #460 displace all three shapes and dominate the count, and the now-wider sans-serif title covers slightly more pixels than the narrow serif it replaced. The matched title crops at full resolution show the change directly — the GT and the after image both set the A1 title in the workbook's 12pt sans-serif Normal font, the before image in an 11pt serif. The fixture contains no hairlines, borders, or dashed strokes, and every run is regular weight with no italic or underline.

Deviation audit

Check Result
Page count/order Remaining: #459 - Excel emits one page; office2pdf adds a blank second page
Element presence Matches GT - the title and all three drawing labels are present
Position/size Remaining: #459 tracks same-row vertical stacking; #460 tracks undersized anchor bounds and cumulative horizontal drift
Rotation/flip No deviation observed - the fixture contains no rotated or flipped elements
Fill Matches GT - all three RGB values match Excel exactly after #430
Stroke/border No deviation observed - the shapes intentionally have no outline or hairline
Text content Matches GT - all four strings are preserved
Font family/weight/style Fixed - the A1 title now renders the workbook's 12pt Malgun Gothic Normal font, as in Excel; the drawing labels keep the Calibri resolved in #461
Text color Matches GT - all text remains black
Alignment Matches GT - the title is left-aligned and the drawing labels stay centered
Line/paragraph spacing No deviation observed - every text region is one regular single-line paragraph
Clipping/overflow Remaining: #459 - flow-height reservation spills onto a blank second page; no page-1 glyph clipping was found

Checklist

  • Commits include a Signed-off-by line
  • PR scope contains one root cause
  • Remaining visual deviations each reference an open issue

A cell with no `s` attribute uses `cellXfs[0]`, whose font is the workbook
Normal font. umya reports no font at all for such a cell, so the style path
returned `TextStyle::default()` and the renderer picked its own family and
size: an Excel-saved workbook whose Normal font is Malgun Gothic 12 rendered
its title in Typst's serif default at 11pt.

Read the Normal font from `styles.xml` - `extract_normal_font` already did,
for column print metrics - carry it on `SheetContext`, and fall back to it
whenever a cell's own style names no font or no size.

Two special cases went with it. The family was discarded when it was
"Calibri" and the size when it was 11.0, on the grounds that they were "the
Excel default"; both left the most common workbooks to the renderer's serif
default rather than to Calibri, which font substitution resolves perfectly
well. A rich-text run naming Calibri was ignored for the same reason and now
counts like any other family.

`extract_normal_font` returns a `NormalFont` struct rather than a bare
`(String, f64)`, and `prepare_sheet_context` takes it directly instead of a
precomputed max-digit-width, so the print-metric derivation lives next to the
font it derives from.

Fixes #462

Signed-off-by: Yonghye Kwon <developer.0hye@gmail.com>
@developer0hye
developer0hye merged commit f37b122 into main Jul 26, 2026
40 of 49 checks passed
@developer0hye
developer0hye deleted the fix/xlsx-normal-font branch July 26, 2026 01:37
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: unstyled cells lose the workbook Normal font

1 participant