Skip to content

fix(xlsx): resolve drawing-only sheet anchors with the Normal-font metric - #716

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

fix(xlsx): resolve drawing-only sheet anchors with the Normal-font metric#716
developer0hye merged 1 commit into
mainfrom
fix/xlsx-empty-sheet-normal-font

Conversation

@developer0hye

@developer0hye developer0hye commented Jul 30, 2026

Copy link
Copy Markdown
Owner

Summary

Sheets with an empty <sheetData/> but drawings/text boxes/charts resolved their anchors through empty_sheet_context(), which hardcoded max_digit_width_px: 7.0 and dropped the workbook Normal font — laying every drawing-only sheet out on 44.2575pt columns where the converter's own Calibri-11 metric says 50.58pt. Pictures were 12.5% narrow and 8% aspect-distorted.

The digit-width derivation is now a single shared helper resolve_max_digit_width_px (Normal-font metric, falling back to the dominant-cell-font path that degrades to the legacy 7px on an empty sheet with unreadable styles). prepare_sheet_context uses the same helper — a behavior-identical extraction — so the metric cannot drift between populated and drawing-only sheets. Both empty_sheet_context call sites (parse and streaming parse) pass the Normal font through.

Related issue

Fixes #620

Testing

  • cargo test --workspace — green (new red-first tests: an in-memory drawing-only workbook whose spliced twoCellAnchor picture must resolve x/width at the 50.58pt metric with the 44.2575pt legacy negative-asserted; a triangulation test pinning Calibri-11→8px, Calibri-8→6px, None→7px so a hardcoded 8.0 cannot pass)
  • cargo +1.97 clippy --workspace --all-targets — clean; cargo fmt --check — clean
  • Release-build measurement vs a fresh local Excel-for-Mac GT export: column width solves to exactly 50.58pt from three independent anchors across WithDrawing/WithTextBox (was 44.2575); tomcat.png x error −69.5pt → −19.0pt; clock.jpg width error −16.5% → −4.6%
  • Populated-sheet regression: 05_project_schedule_en trace byte-identical to main

Visual impact

  • No rendered PDF change
  • Rendered PDF change or visual evidence added
  • Reason:

Visual audit

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

Deviation audit

Check Result
Page count/order Remaining: #713 — GT prints sheet 1 on 2 pages (tomcat right edge 580.95pt > printable 544.88pt); drawing extents never map to horizontal breaks
Element presence Matches GT — all 6 elements present (GT carries tomcat/santa continuations on page 2, tracked under #713)
Position/size Remaining: #715 — GT lays default rows out at 17pt vs our 15pt (clock height 132 vs 148pt); Remaining: #621 — Calibri default column 50.58 vs GT's measured 52.95pt/col; Remaining: #714 — declared cols widths still ignored on drawing-only sheets (one-factor probe run in this audit). The column-metric shrink this PR fixes is gone: tomcat x error −69.5pt → −19.0pt, clock width −16.5% → −4.6%
Rotation/flip No deviation observed
Fill Matches GT — text-box fill matches; ink delta fully accounted by the unclipped picture halves (#713)
Stroke/border Matches GT — text-box border weight and all picture outline hairlines match at 150 DPI
Text content Matches GT — both text lines identical
Font family/weight/style Matches GT — Calibri regular both sides
Text color Matches GT — black both sides
Alignment Matches GT — both lines centred in the text box
Line/paragraph spacing Remaining: #656 — text-box line advance 26.49pt vs GT 13.86pt (the xdr:txBody double-pitch defect), pushing line 2 below the frame
Clipping/overflow Remaining: #713 — GT clips pictures at the printable edge and continues them on page 2; ours overflows the margin by 36.07pt

Checklist

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

🤖 Generated with Claude Code

…tric

empty_sheet_context() hardcoded max_digit_width_px 7.0 and dropped the
workbook Normal font, so every sheet with an empty <sheetData/> laid its
drawing anchors out on column_width_to_pt(8.43, 7.0) = 44.2575pt
columns. The same workbooks declare Calibri 11, for which the
converter's own metric says 8.0px and 50.58pt — drawing-only sheets
were 12.5% narrow by the converter's own model, pictures 8%
aspect-distorted, and WithDrawing's content stopped reaching the second
page-column.

The digit-width derivation is now one shared helper,
resolve_max_digit_width_px: the Normal-font metric when styles.xml is
readable, else the dominant-cell-font fallback that on an empty sheet
degrades to the legacy 7px. prepare_sheet_context uses the same helper
(behavior-identical extraction), and both empty_sheet_context call
sites (parse and streaming parse) pass the Normal font through.

Measured on WithDrawing.xlsx against a fresh local Excel-for-Mac GT
export: column width solves to exactly 50.58pt from two independent
anchors (was 44.2575), tomcat.png's x error shrinks from -69.5pt to
-19.0pt, clock.jpg's width error from -16.5% to -4.6%. Populated-sheet
golden mocks are byte-identical.

The audit decomposed every residual: our 50.58pt vs GT's measured
52.95pt/col default is the #621 metric-table gap; drawing extents still
never split into page-columns (#713); declared <cols> widths are still
ignored on drawing-only sheets (#714); GT lays default rows out at 17pt
where the file declares 15 (#715); the text-box line pitch doubling is
#656.

Related: #620

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Yonghye Kwon <developer.0hye@gmail.com>
@developer0hye
developer0hye merged commit b72e5c1 into main Jul 30, 2026
32 of 33 checks passed
@developer0hye
developer0hye deleted the fix/xlsx-empty-sheet-normal-font branch July 30, 2026 06:47
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: drawing-only sheets lay out columns with a hardcoded 7px digit width, so pictures are 8% distorted and a 2-page sheet collapses to 1

1 participant