Skip to content

render: add glyph payload resource proof diagnostics#1159

Merged
edwardkim merged 2 commits into
edwardkim:develfrom
seo-rii:render-p20
May 31, 2026
Merged

render: add glyph payload resource proof diagnostics#1159
edwardkim merged 2 commits into
edwardkim:develfrom
seo-rii:render-p20

Conversation

@seo-rii

@seo-rii seo-rii commented May 28, 2026

Copy link
Copy Markdown
Contributor

What

  • advanced GlyphOutline payload에 payloadResourceKey를 추가해서 color layer / bitmap glyph / SVG glyph sidecar의 replay/cache identity를 분리합니다.
  • bitmap imageRef와 SVG svgRef처럼 같은 숫자 ref를 쓰는 payload가 서로 같은 cache entry로 보이지 않도록 Rust JSON과 Studio helper 양쪽에 같은 key contract를 둡니다.
  • ResourceArena에서 versioned FontBlob ref로 실제 blob bytes를 확인하는 proof helper를 추가합니다.
  • native Skia glyph-run replay proof를 추가해서 portable contract와 exact typeface construction blocker를 분리해 보고합니다.
  • layer schema를 1.15, resource table schema를 1.4로 올리고, 관련 문서와 테스트를 갱신합니다.

Why

P19에서 color layer / bitmap glyph / sanitized SVG glyph payload vocabulary와 COLRv1 일부 CanvasKit replay gate를 열었습니다. P20은 그 다음 단계로 실제 replay를 더 열기 전에 resource identity와 native font construction 실패 이유를 명시하는 작업입니다.

특히 payload family가 다른데 numeric ref만 같아서 cache key가 충돌하는 상황, font blob ref는 있지만 bytes가 없는 상황, TTC/OTC face index나 variation axis 때문에 native Skia exact typeface construction이 막히는 상황을 조용히 통과시키지 않도록 합니다.

Review follow-up

  • review 반영으로 payloadResourceKey는 strict payload contract를 만족할 때만 내보냅니다. incomplete payload는 key를 만들지 않아 - placeholder 기반 충돌을 피합니다.
  • font blob ref lookup은 intern 시점에 key map을 만들고 lookup 때 재해시하지 않도록 바꿨습니다.
  • native Skia proof reason은 replayEligibilityNotPortablefontBlobNotPortable을 분리하고, reason list는 전역 정렬로 안정화했습니다.
  • #536의 z-order 후속 메모는 P20 코드 범위는 아니지만 README에 후속 renderer sweep 기준으로 반영했습니다. 이후 PDF/export/API 확장 시 normalized PageLayerTree replay iterator를 검토하는 쪽입니다.

Compatibility

  • 기본 renderer 경로는 바꾸지 않습니다.
  • unsupported glyph payload는 계속 TextRun fallback을 유지합니다.
  • native Skia glyph-id replay는 아직 enable하지 않습니다. 이번 PR은 blocker를 분리해서 보여주는 proof 단계입니다.
  • schema 변경은 additive minor bump입니다.

Non-goals

  • 임의 GlyphRun / GlyphOutline direct replay를 켜지 않습니다.
  • 문서에서 실제 image/SVG glyph payload bytes를 resource table로 뽑아내지는 않습니다.
  • native Skia exact blob typeface construction을 구현하지 않습니다.
  • CanvasKit bitmap/SVG glyph replay를 열지 않습니다.
  • normalized replay iterator는 후속 renderer sweep/PDF export 범위로 남깁니다.

Validation

  • cargo fmt --check
  • cargo test --lib
  • cargo test --features native-skia skia --lib
  • cargo test --features native-skia --lib native_skia_glyph_run_proof --no-default-features
  • npm --prefix rhwp-studio test -- render-backend
  • npm --prefix rhwp-studio run build
  • git diff --check

Refs #536

@edwardkim edwardkim added this to the v1.0.0 milestone May 28, 2026
@edwardkim edwardkim added the enhancement New feature or request label May 28, 2026
@edwardkim edwardkim self-requested a review May 28, 2026 22:01
@seo-rii seo-rii marked this pull request as ready for review May 31, 2026 08:08
Copilot AI review requested due to automatic review settings May 31, 2026 08:08

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds “P20” diagnostics and identity tooling for advanced glyph payloads and native Skia glyph-run replay, including version bumps to reflect the expanded IR/resource semantics.

Changes:

  • Introduces native Skia glyph-run “replay proof” diagnostics with reason codes and adds targeted tests.
  • Adds stable payloadResourceKey generation/serialization for advanced GlyphOutline payloads (Rust + Studio TypeScript) to prevent cache/resource-id collisions across payload families/palettes.
  • Extends ResourceArena with BinaryResourceRef-based font-blob byte resolution and bumps schema/resource table minor versions.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/renderer/skia/renderer.rs Adds replay-proof reasoning for native Skia glyph-run replay eligibility and tests.
src/paint/schema.rs Bumps schema/resource table minor versions for the updated export surface.
src/paint/resources.rs Adds lookup of font blob bytes by BinaryResourceRef and tests.
src/paint/paint_op.rs Adds payload resource key generation for glyph outline sidecars.
src/paint/json.rs Exports payloadResourceKey and advertises the feature in metadata; updates tests.
rhwp-studio/tests/render-backend.test.ts Adds Studio test coverage for payload resource key disjointness.
rhwp-studio/src/view/glyph-outline-payload-status.ts Adds Studio-side payload resource key computation.
rhwp-studio/src/core/types.ts Extends Studio types to include payloadResourceKey and palette ref fields.
docs/text-ir-v2.md Documents P20 behavior for payload identity keys and replay-proof blockers.
README.md Adds P20 changelog entry.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/paint/resources.rs
Comment thread src/renderer/skia/renderer.rs
Comment thread src/renderer/skia/renderer.rs Outdated
Comment thread rhwp-studio/src/view/glyph-outline-payload-status.ts
Comment thread src/paint/json.rs Outdated
@edwardkim edwardkim merged commit 0f1c22b into edwardkim:devel May 31, 2026
7 checks passed
edwardkim added a commit that referenced this pull request May 31, 2026
…refs #536, by @seo-rii)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@edwardkim

Copy link
Copy Markdown
Owner

리뷰를 마치고 머지했습니다 (devel 8f3d2e91, CI 전부 통과). P19 에서 연 payload vocabulary 위에 resource identity 와 native font construction blocker 를 명시한 점이 이 PR 의 핵심이고, 설계가 본문 약속과 정확히 맞아 검토가 수월했습니다. 좋은 작업 감사합니다, @seo-rii.

리뷰 요약

핵심 변경

  • payload_resource_key: color/bitmap/SVG glyph payload 를 family prefix(glyphPayload:bitmapGlyph:imageRef: vs :svgGlyph:svgRef:)로 구분 → numeric ref 가 겹쳐도 cache/replay identity 가 분리됩니다. strict contract 미달 payload 는 key 를 만들지 않아 - placeholder 충돌도 회피합니다.
  • ResourceArena.font_blob_bytes_for_ref: versioned FontBlob ref 로 실제 blob bytes 존재를 확인합니다. intern 시점에 key map 을 구축해 lookup 시 재해시가 없습니다.
  • native Skia NativeGlyphRunReplayProof: portable variant contract 와 exact typeface construction 을 분리하고, 모든 blocker(face index, variation axis, missing blob bytes, eligibility vs portability)를 BTreeSet 으로 일괄·정렬 보고합니다.
  • layer schema 1.15 / resource table 1.4 (additive minor).

확인한 점

  • native_skia_can_replay_glyph_runtypeface_constructible 를 반환하고 contract 가 replayable 해도 TypefaceConstructionNotImplemented 가 항상 추가되므로, 실제 glyph-id replay 는 여전히 비활성입니다 — 본문의 "blocker 분리 proof 단계" 와 일치합니다.
  • 기본 renderer 경로는 불변, unsupported payload 는 TextRun fallback 유지.
  • Rust exporter 와 Studio helper 가 동일한 family prefix key contract 를 공유하며, Studio 는 exporter key 를 echo + 검증용 derive 만 하고 fabricate 하지 않습니다.

검증 (로컬 머지 시뮬레이션 + 머지 후 재검증)

  • cargo fmt --all --check / cargo clippy --lib / cargo build: 통과
  • cargo test --tests: 1879 passed, 0 failed (99 스위트)
  • cargo test --features native-skia --lib native_skia_glyph_run: proof 4건 통과
  • npm --prefix rhwp-studio test -- render-backend / run build: 통과
  • devel CI: Build & Test / Analyze ×3 전부 SUCCESS

Refs #536 의 z-order 후속(normalized PageLayerTree replay iterator)은 본문대로 별도 renderer sweep 범위로 남깁니다.

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.

3 participants