Skip to content

fix: prevent PDF content clipping caused by BBox in multi-page export#798

Closed
PhilipKim85 wants to merge 1 commit into
edwardkim:mainfrom
PhilipKim85:fix/pdf-bbox-clipping
Closed

fix: prevent PDF content clipping caused by BBox in multi-page export#798
PhilipKim85 wants to merge 1 commit into
edwardkim:mainfrom
PhilipKim85:fix/pdf-bbox-clipping

Conversation

@PhilipKim85

Copy link
Copy Markdown

Summary

When svgs_to_pdf() generates multi-page PDFs, svg2pdf::to_chunk() sets the Form XObject BBox to the SVG viewport size. However, some SVG elements (particularly <clipPath> <rect> elements) have coordinates that extend beyond the viewport (e.g., x + width exceeding the viewport width). This causes the BBox to clip content on the right side of the page.

Root cause

  • SVG viewport: width="793.7" (A4 at 96 DPI)
  • clipPath rect: x="75.57" width="982.8" → right edge at 1058.37
  • BBox clips at 793.7, hiding content between 793.7 and 1058.37

Fix

Before calling to_chunk(), scan each SVG for <rect> elements whose x + width exceeds the viewport width. If overflow is detected, expand the SVG's width, height, and viewBox attributes to encompass all content, then re-parse. The page MediaBox remains at the original A4 size, so the content is properly scaled.

Before / After

Before (clipped) After (fixed)
Right-side content cut off, unbalanced margins Full content visible, balanced margins

Notes

  • Only affects multi-page PDFs (svgs_to_pdf). Single-page PDFs use to_pdf() which handles DPI internally.
  • Pages without overflow are unaffected (no re-parsing needed).
  • Related: svg2pdf#25 (DPI scaling in to_chunk vs to_pdf)

When `svgs_to_pdf()` generates multi-page PDFs via `svg2pdf::to_chunk()`,
the Form XObject BBox is set to the SVG viewport dimensions. However,
some SVG content (especially clipPath rects) extends beyond the viewport,
causing right-side content to be clipped by the BBox boundary.

This fix scans each SVG page for `<rect>` elements whose `x + width`
exceeds the viewport width, then expands the SVG viewport accordingly
before calling `to_chunk()`. The page MediaBox remains at the original
size (e.g., A4), so the expanded content is properly scaled to fit.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@PhilipKim85

Copy link
Copy Markdown
Author

Closing this PR as the viewport expansion approach causes content to shrink to 75% of its original size.

A better workaround has been found: expand the Form XObject BBox without changing the Matrix, so that the original content scale is preserved. Content that extends beyond the page MediaBox is simply not rendered (acceptable since it's only the clipPath rect extending, not actual visible content).

This fix is currently implemented as a post-processing step in the consuming application (using pikepdf). If a Rust-side fix is desired, it would require modifying the PDF chunk after svg2pdf::to_chunk() returns, which is non-trivial with the current pdf-writer API.

Root cause for reference:

  • svg2pdf::to_chunk() sets BBox = SVG viewport (793.7 for A4@96dpi)
  • Some clipPath <rect> elements have x + width exceeding the viewport (e.g., 75.57 + 982.8 = 1058.37)
  • BBox clips content at 793.7, hiding edge content

edwardkim added a commit that referenced this pull request May 11, 2026
- mydocs/pr/archives/pr_813_review.md (5 정책 위반 + 회귀 위험 분석)
- mydocs/pr/archives/pr_813_report.md (옵션 C 처리 결과 + 분리 PR 가이드)
- mydocs/orders/20260511.md PR #813 행 추가

핵심 문제점:
1. base=main 정책 위반 (devel 재제출 필수)
2. 폰트 라이선스 정책 어긋남 (Noto/Pretendard 미포함)
3. typeset.rs LINE_SEG 가드 회귀 위험 (PR #621/#622/#627/#632/#636 누적 정정 우회)
4. Issue 연결 부재
5. wasm_api.rs pub(crate) core 가시성 변경

분리 PR 3 가이드 (재제출 대기):
- 분리 PR 1: pdf.rs SVG BBox (안전, PR #798 close 후속, 우선)
- 분리 PR 2: 폰트 fallback (Noto/Pretendard 우선)
- 분리 PR 3: typeset.rs LINE_SEG + HWPX adapter (광범위 sweep 필수)
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