Skip to content

render: widen exact font replay proof corpus#1421

Merged
edwardkim merged 3 commits into
edwardkim:develfrom
seo-rii:render-p25
Jun 16, 2026
Merged

render: widen exact font replay proof corpus#1421
edwardkim merged 3 commits into
edwardkim:develfrom
seo-rii:render-p25

Conversation

@seo-rii

@seo-rii seo-rii commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

What

P25 단계로 exact font replay proof corpus를 넓혔습니다.

  • CanvasKit/native Skia glyph-run selection에서 variable font instance를 variationUnsupported로 명시 reject합니다.
  • CanvasKit/native Skia glyph-run selection에서 non-default TTC/OTC face index를 faceIndexUnsupported로 명시 reject합니다. face index 0은 positive control로 유지합니다.
  • native Skia proof에서 font blob bytes 누락, dataRef metadata mismatch, digest mismatch를 각각 다른 이유로 분리했습니다.
  • font portability digest와 blob-level digest가 resource bytes와 맞지 않으면 portable contract 실패로 봅니다.
  • glyph id가 Text IR에서는 u32이지만 backend direct replay 전에는 기존 range guard를 계속 검증합니다.
  • 관련 내용을 docs/text-ir-v2.md P25 섹션에 정리했습니다.

Why

P24까지는 strict glyph payload와 resource identity 쪽을 보강했습니다. 그 다음 단계에서는 glyph-run을 실제 backend replay로 열기 전에, 폰트가 “정확히 같은 face/instance/bytes”로 재구성될 수 있다는 전제를 더 좁고 명확하게 검증해야 합니다.

이번 PR은 exact font replay를 기본 경로로 여는 변경이 아닙니다. 오히려 아직 검증되지 않은 variation/TTC face/dataRef/digest 케이스를 더 분명하게 fallback시키고, 나중에 exact construction을 구현할 때 어느 조건을 풀어야 하는지 테스트로 고정하는 단계입니다.

Compatibility

  • 기본 TextRun fallback 경로는 유지됩니다.
  • CanvasKit/native Skia direct glyph-run replay는 아직 보수적인 gate 뒤에 있습니다.
  • variable font와 non-default collection face는 현재도 fallback합니다. 다만 fallback reason이 더 구체적으로 기록됩니다.
  • font blob metadata가 resource bytes와 맞지 않으면 best-effort로 통과시키지 않습니다.
  • schema/JSON 출력 형식 자체를 바꾸지는 않습니다.

Non-goals

  • CanvasKit/native Skia exact typeface construction을 구현하지 않습니다.
  • variable font axis replay를 지원하지 않습니다.
  • TTC/OTC non-zero face index replay를 지원하지 않습니다.
  • fallback-free text profile을 기본값으로 바꾸지 않습니다.

Checks

  • git diff --check upstream/devel...HEAD
  • cargo fmt --check
  • CARGO_INCREMENTAL=0 cargo test --lib renderer::layer_renderer -- --nocapture
  • CARGO_INCREMENTAL=0 cargo test --lib --features native-skia native_skia_glyph_run_proof -- --nocapture
  • CARGO_INCREMENTAL=0 cargo check --lib

Refs #536

@jangster77 jangster77 marked this pull request as ready for review June 16, 2026 14:00
@edwardkim edwardkim self-requested a review June 16, 2026 23:51
@edwardkim edwardkim added the enhancement New feature or request label Jun 16, 2026
@edwardkim edwardkim added this to the v1.0.0 milestone Jun 16, 2026
@edwardkim edwardkim merged commit 0bd3992 into edwardkim:devel Jun 16, 2026
7 checks passed
edwardkim pushed a commit that referenced this pull request Jun 17, 2026
edwardkim pushed a commit that referenced this pull request Jun 17, 2026
@edwardkim

Copy link
Copy Markdown
Owner

좋은 방향의 보수적 확장입니다. 이번 PR은 exact font replay를 여는 변경이 아니라, 아직 증명되지 않은 조건을 더 명확히 fallback시키는 proof corpus 확장이라서 현재 방향에 동의합니다.

다음 단계에서 한 가지 경계는 분명히 유지하면 좋겠습니다. 기존 font_metrics_data.rs의 폰트 메트릭 DB는 계속 활용하되, 이것은 TextRun 호환 레이아웃과 advance 진단의 기준선으로 취급하고, portable glyph replay의 증거로 보지는 않는 쪽이 안전합니다. 메트릭 DB 매칭만으로 strict GlyphRun을 선택하면 안 됩니다.

후속 작업에서는 세 계층을 분리해서 가져가면 좋겠습니다.

  1. HWP FontFace 이름 치환과 메트릭 조회: 호환 레이아웃 기준
  2. SVG/Canvas/Skia의 런타임 폰트 fallback: 실제 화면 출력 경로
  3. fontResources/ResourceArena 기반 portable font identity: strict glyph replay 증명

즉, 메트릭 DB는 shaped advance가 기존 호환 배치와 얼마나 일치하는지 비교하는 진단 기준으로 재사용하고, strict replay 여부는 별도로 실제 폰트 bytes, digest, dataRef, face index, variation axis, shaping 결과를 통해 증명하는 구조가 좋겠습니다. shaping 과정에서 fallback font가 섞이면 usedFallbackFontCount로 드러내고, 지금처럼 strict replay에서는 reject하는 정책을 유지해야 합니다.

그래서 다음 PR은 바로 direct glyph replay를 넓히기보다, 먼저 resolver/proof 경계를 정리하는 작은 단위가 좋아 보입니다. 예를 들면 --font-path나 문서 내 embedded font 후보를 ResourceArena/FontBlobResource로 연결하되, 선택 정책은 여전히 보수적으로 두고 diagnostics만 풍부하게 만드는 식입니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants