Skip to content

Task #727: PUA U+F02B1~F02C4 사각 안 숫자 매핑 entry 제거 + fallback chain 함초롬바탕 family 확장#1020

Closed
HaimLee-4869 wants to merge 1 commit into
edwardkim:develfrom
HaimLee-4869:pr/727-pua-boxed-digits
Closed

Task #727: PUA U+F02B1~F02C4 사각 안 숫자 매핑 entry 제거 + fallback chain 함초롬바탕 family 확장#1020
HaimLee-4869 wants to merge 1 commit into
edwardkim:develfrom
HaimLee-4869:pr/727-pua-boxed-digits

Conversation

@HaimLee-4869

@HaimLee-4869 HaimLee-4869 commented May 19, 2026

Copy link
Copy Markdown
Contributor

요약

본가 issue #727samples/table-vpos-01.hwpx p.5 의 사각 안 숫자 19 (PUA U+F02B1F02B9) 가 ⊠ (두부) 로 출력되는 문제 해결.

본가 reference sample 시각 검증 OK ✓ (캡쳐 ↓).

본가 sample 시각 검증

Before — 현재 본가 devel 기준 (fix 적용 전): 1~9 모두 ⊠

before

After — 본 PR fix 적용 후: 사각 안 1~9 한컴 정합 ✓ (10-12 OVERLAP 별도 issue)

after

본 PR fix 의 본질 영역 변환 — 원문자 ① → 사각 안 ① (issue #727 (가) 가능성 정합)

PR #600 (Task #509) 매핑이 PUA U+F02B1 → 표준 U+2460 변환 → 본가 devel 에서 원문자 ① 표시 (issue #727 증상). 본 PR 의 매핑 entry 제거 (raw passthrough) + generic_fallback() chain 확장 (함초롬바탕 확장B 매칭) 으로 사각 안 ① 한컴 정합 달성.

사용자 작업 영역 (정부 공문 hwpx) 의 동일 PUA 영역 변환 확인:



Before — 본가 devel: 원문자 ① 표시 (한컴 권위와 부정합)
전



After — 본 PR 적용: 사각 안 ① 한컴 정합 ✓
후

→ issue #727(가) 가능성 ("매핑 ①~⑳ 제거 + 사각형 안 숫자 영역으로 환원") 정합 본질 변환을 사용자 작업 영역 추가 hwpx 에서 확인.

  • 사각 안 1~9 한컴 정합 (본 PR 영역)
  • ⚠️ 10~12 OVERLAP path 별도 issue (본 PR 영역 밖, 본문 참고)

Root cause

PUA 0xF02B1~F02C5 는 한컴 자체 정의 codepoint (Unicode 표준 아님). 한컴은 자체 번들 폰트 (함초롬바탕 확장B 등) 의 PUA 영역에 사각 안 숫자 글리프를 정의해 사용.

rhwp 두 단계 문제:

  1. map_pua_bullet_char() 가 0xF02B1F02C4 → 표준 ①⑳ 매핑 → 1순위 폰트의 원 안 ① 글리프 즉시 사용 → 글리프 단위 fallback 차단
  2. generic_fallback() chain 에 함초롬바탕 family 부재 → 한컴 호환 환경에서도 매칭 못 함

Fix

1. src/renderer/layout/paragraph_layout.rs:3026~3049 — PUA 매핑 entry 제거

  • 0xF02B10xF02C4 → ①⑳ 매핑 entry 20개 제거 (raw passthrough)
  • 0xF02EF (·) / 0xF02FB (▸) entry 유지 (별도 글리프, 영역 외)
  • 테스트 단언 정정: supplementary_pua_a_passthrough_for_boxed_digits

2. src/renderer/mod.rs:577~619generic_fallback() chain 확장

sans-serif + serif chain 4곳에 함초롬바탕 family (확장B → 확장 → 일반) 추가. 한글/영문 family name 둘 다 포함:

HCR Batang Ext-B, 함초롬바탕 확장B,
HCR Batang Ext, 함초롬바탕 확장,
HCR Batang, 함초롬바탕
  • 위치: Pretendard 다음, generic fallback 직전
  • 한글/영문 family name 둘 다 포함 (시스템 등록 family name 가변성 대응)
  • 함초롬바탕 우선순위: 확장B → 확장 → 일반 (PUA 글리프 보유 폰트 우선)

OVERLAP path 자동 영향

composer.rs::CharOverlap 의 SVG/Canvas 렌더 path (svg.rs:1710,1813, web_canvas.rs:2649,2754) 모두 generic_fallback() 호출 → 단일 fix 로 단일 PUA + OVERLAP 양 path 동시 영향. (다만 본가 sample p.5 의 OVERLAP 산출물은 SVG 에 안 들어가는 별도 영역 — 아래 참고)

회귀 영향

  • 본문 한글 글자: 0 (chain 1순위 폰트 사용)
  • 표준 ① (U+2460): 0 (한컴도 원 안 ①)
  • PUA 0xF02B1~F02C4 영역만 함초롬바탕 확장B 매칭 → 사각 안 숫자

검증

  • cargo test --lib: 1307 passed, 0 failed (회귀 0)
  • cargo clippy --lib -- -D warnings: 0건
  • cargo test --test svg_snapshot: 8 passed (UPDATE_GOLDEN=1 일괄 갱신)
  • ✅ golden 7개 변경: chain 확장 한 가지 패턴, 좌표/글자 변경 0
    • 영향 파일: form-002, issue-147 (aift), issue-157, issue-267 (KTX), issue-617 (exam_kor), issue-677 (복학원서), table-text
  • ✅ 본가 reference sample table-vpos-01.hwpx p.5 시각 검증: 사각 안 1~9 한컴 정합

검증 환경

한컴 PDF 환경 의존성 위키 의 정답지 framework 정합:

  • 한컴 도구: 한컴오피스 2024 한글 (Windows 편집기)
  • OS: Windows 10/11
  • 폰트: 한컴 번들 폰트 (함초롬바탕 확장B 등) 시스템 설치
  • 시각 비교

OVERLAP path 10~12 별도 issue (본 PR 영역 밖)

진단 결과 공유 — 후속 issue 영역:

  • <hp:compose composeType="OVERLAP" composeText="F02BA + F02C3~C5"> (사각 안 10~12)
  • composer.rs::inject_char_overlap_text 의 산출물이 SVG 에 안 들어감 (CharOverlap <rect> border 0개, text-anchor="middle" 내부 텍스트 0개)
  • 가능 원인:
    • control_positions 매핑 누락
    • LAYOUT_OVERFLOW (page=4, table overflow=28.9px) 와 연관 가능
    • hwpx parser 의 <hp:compose> 처리 영역

→ 본 PR 의 chain 확장이 적용된 상태에서 OVERLAP path 가 SVG 에 들어가게 되면 자동으로 글리프 매칭. 후속 issue 영역, 별도 토론 부탁드립니다.

정공법 후보 (별도 토론 영역)

본 PR 은 fallback chain 영역. 폰트 의존 제거의 정공법:

  • SVG <path> 직접 그리기: PUA codepoint 만나면 사각형 + 숫자 path 직접 출력. 폰트 의존 0.
  • 한컴 PUA 글리프 web 임베딩: 함초롬바탕 확장B PUA 영역만 추출 woff2 번들. 라이선스 검토 영역 (mydocs/tech/font_fallback_strategy.md 참고).

본 PR 영역 밖, 별도 토론 부탁드립니다.

Investigation PR 가이드 정합

본 PR 은 본가 Investigation PR 가이드 일부 정합:

  • ✅ 본질 분석 (Root cause) 보고
  • ✅ 검증 도구 (회귀 검증, 시각 검증) 결과
  • ✅ 다음 단계 권고 (OVERLAP 별도 issue + 정공법 후보)
  • ✅ 코드 변경: fallback chain 영역 (1~9 부분 정합 fix)

Closes #727

…chain 함초롬바탕 family 확장

본질:
- PUA 0xF02B1~F02C5 는 한컴 자체 정의 codepoint (Unicode 표준 아님).
- 한컴은 자체 번들 폰트 (함초롬바탕 확장B 등) 의 PUA 영역에 사각 안
  숫자 글리프를 정의 사용.
- rhwp 의 fallback chain 에 함초롬바탕 family 부재 → 글리프 단위
  fallback 이 PUA 영역에서 매칭 못 함.

Fix:
1. src/renderer/layout/paragraph_layout.rs:3026-3049
   - 0xF02B1~0xF02C4 → ①~⑳ 매핑 entry 20개 제거 (raw passthrough)
   - PUA → 표준 Unicode 변환은 1순위 폰트의 원 안 ① 글리프 즉시 사용 →
     글리프 단위 fallback 차단. raw passthrough 로 fallback chain 작동
     경로 복구.
   - 테스트 단언 정정: supplementary_pua_a_passthrough_for_boxed_digits

2. src/renderer/mod.rs:577~619 generic_fallback() (sans/serif chain 4곳)
   - 함초롬바탕 family 추가 (확장B → 확장 → 일반)
   - 한글/영문 family name 둘 다 포함 (HCR Batang Ext-B/Ext + 함초롬바탕
     확장B/확장)
   - 우선순위: Pretendard 다음, generic fallback 직전
   - test_generic_fallback() 단언 갱신
   - OVERLAP path (composer.rs CharOverlap) 도 같은 chain 사용 →
     단일 fix 로 단일 PUA + OVERLAP 양 path 동시 영향

회귀 영향:
- 1순위 폰트가 한글 글리프 보유 시 chain 우선순위로 1순위 사용 →
  한글 본문 영향 0
- 표준 ① (U+2460) 영향 0 — 한컴도 원 안 ①
- PUA 영역만 chain 진행으로 함초롬바탕 확장B 매칭

검증:
- cargo test --lib: 1307 passed, 0 failed (회귀 0)
- cargo clippy --lib -- -D warnings: 0건
- cargo test --test svg_snapshot: 8 passed (UPDATE_GOLDEN=1 일괄 갱신)
- golden 7개 변경: chain 확장 한 가지 패턴, 좌표/글자 변경 0
  (form-002, issue-147, issue-157, issue-267, issue-617,
   issue-677, table-text)
- 본가 reference sample table-vpos-01.hwpx p.5 시각 검증:
  사각 안 1~9 한컴 정합 OK

검증 환경 (한컴 PDF 환경 의존성 위키 정합):
- 한컴오피스 2024 한글 (Windows 편집기)
- Windows 10/11 + 함초롬바탕 확장B 시스템 설치
- 시각 비교

OVERLAP path 10~12 (F02BA + F02C3~C5) 는 composer.rs::CharOverlap 산출물이
SVG 에 안 들어가는 별도 영역 — 본 PR 영역 밖, 후속 issue 영역.

본 PR 은 fallback chain 영역. SVG <path> 직접 그리기 / 한컴 PUA 글리프
web 임베딩은 별도 토론 영역 (참고: mydocs/tech/font_fallback_strategy.md).

Closes edwardkim#727

Co-Authored-By: Claude <noreply@anthropic.com>
@HaimLee-4869 HaimLee-4869 force-pushed the pr/727-pua-boxed-digits branch from 5cffdaf to 51461af Compare May 19, 2026 21:22
@edwardkim edwardkim requested review from edwardkim and removed request for edwardkim May 19, 2026 22:41
@edwardkim edwardkim added the bug Something isn't working label May 19, 2026
@edwardkim edwardkim added this to the v1.0.0 milestone May 19, 2026
edwardkim added a commit that referenced this pull request May 20, 2026
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
edwardkim added a commit that referenced this pull request May 20, 2026
… fallback chain 함초롬바탕 family 확장

@HaimLee-4869 (첫 기여) — table-vpos-01.hwpx p.5 사각 안 1~9 (PUA
U+F02B1~F02B9) 한컴 권위 부정합 해소. PUA 매핑 20개 entry 제거(raw
passthrough)로 글리프 단위 fallback 활성화 + generic_fallback() chain
4곳에 함초롬바탕 family 6개(확장B→확장→일반, 한글/영문 둘 다) 추가로
PUA 영역 글리프 매칭.

옵션 A: 본질 커밋 1588c1e cherry-pick (작성자 @HaimLee-4869 보존, 충돌
없음, fmt amend). 검증: cargo test 1307 + svg_snapshot 8 + clippy -D
+ fmt 0 + WASM 4.83MB. sweep 10 fixture (BEFORE devel ↔ AFTER):
mel-001(HWP/HWPX/HWP5) + table-vpos-01(HWPX/HWP) + biz_plan/복학원서/
exam_kor/aift/sample16-hwp5 — font-family 패턴만 변경, 텍스트
좌표/내용 무변동 입증 (CSS chain 우선순위 정합). 검토 쟁점 A(mel-001
Task #509 회귀)도 sweep + 작업지시자 시각 판정으로 회귀 부재. 골든
7개 일괄 갱신 정확.

첫 기여 모범 PR — Root cause + Fix + 회귀 영향 + 검증 + OVERLAP 별건
분리 + 정공법 후보 + Investigation PR 가이드 정합. 잔존 OVERLAP
10~12(두자리 글자겹치기)는 후속 이슈 #1023 등록.
@edwardkim

Copy link
Copy Markdown
Owner

@HaimLee-4869 님 첫 기여 환영합니다. 옵션 A로 devel에 반영했습니다 (본질 커밋 1588c1e cherry-pick, 작성자 메타데이터 보존, 충돌 없음, fmt amend).

검증:

  • cargo test --release --lib 1307 passed / svg_snapshot 8 / clippy -D / fmt 0 / WASM 4.83MB
  • sweep 10 fixture (BEFORE devel ↔ AFTER): mel-001(HWP/HWPX/HWP5) + table-vpos-01(HWPX/HWP) + biz_plan/복학원서/exam_kor/aift/sample16-hwp5 — 텍스트 좌표/내용 완전 무변동 + font-family 문자열만 변경 입증 (PR 본문 주장 정확)
  • 작업지시자 시각 판정 통과 (table-vpos-01.hwpx p.5 사각 안 1~9 한컴 정합 + mel-001 회귀 부재)

PR 본문이 Root cause + Fix + 회귀 영향 + 검증 + OVERLAP 별건 분리 + 정공법 후보까지 정리되어 검토 절차가 매우 매끄러웠습니다. Investigation PR 가이드 정합도 정확합니다.

작업지시자 명시한 OVERLAP 10~12 (두자리 숫자 글자겹치기)는 본 PR 본문대로 별도 이슈로 분리했습니다 — #1023. 관심 있으시면 후속 작업도 환영합니다. 정공법 후보(SVG <path> 직접 / 함초롬바탕 woff2 번들)는 별도 토론 영역입니다.

@edwardkim edwardkim closed this May 20, 2026
edwardkim added a commit that referenced this pull request May 20, 2026
PR #1020 (Task #727 / closes #727) 이 PUA U+F02B1~F02C4 매핑 entry 를
제거 (raw passthrough) 했으나, tests/issue_826.rs:52 의 회귀 가드
"기존 매핑된 PUA 정합 유지" 단언이 `'\u{F02B1}' → '\u{2460}' (①)` 기대로
남아 있어 CI 실패 (devel run #26135345296, Build & Test).

단언 기대값을 raw passthrough (`'\u{F02B1}'`) 로 정정 — PR #1020 의
의도(fallback chain 함초롬바탕 사각 안 ① 매칭) 정합. U+F0854 → 《
단언은 보존 (별도 매핑).

검증: cargo test --test issue_826 4/4 passed, cargo test --release --lib 1307 passed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
edwardkim added a commit that referenced this pull request May 20, 2026
…ht inner 정렬

@HaimLee-4869 (두 번째 기여) — KTX 목차 페이지번호(3/4/6/7/8/14/16/17/
20/21/23/24/25/27 등) 우측 끝이 cell right inner 미달 + leader 점선-숫자
gap ~10px 초과 회귀 해소. text_measurement.rs 두 measurer(Embedded
TextMeasurer + WasmTextMeasurer)에 (2, _) RIGHT+leader 단일-run + content
분기 추가 — cell_right_run_rel(=text_start_offset + available_width -
line_x_offset) 정렬 + seg_w_full(leading space 포함). Task #874 cross-run
path(pending_right_tab carry-over)와 보완 관계, scope 좁힘(has_content_after
검사, max(x) 보존).

옵션 A: 본질 커밋 cfb71fa cherry-pick (작성자 @HaimLee-4869 보존, KTX
golden 4 블록 충돌 → source patch + UPDATE_GOLDEN 일괄 갱신 전략).
처리 중 PR #1020 회귀 CI 실패 발견 → hotfix 2회 push (issue_826 단언
정정 + fmt) 동반. 사고로 PR #1021 source 가 두 번째 hotfix(3ed8297)에
흡수 → 본 PR commit(7f879ab)은 KTX golden 정합으로 축소되었으나 원
의도(source + golden) 모두 devel 반영. 본 환경 검증: cargo test 1307 +
svg_snapshot 8 + issue_826 4 + clippy -D + fmt 0 + WASM 4.83MB. sweep 9
fixture(KTX/table-vpos-01/sample16-hwp5/exam_kor/math/aift/biz_plan/복학원서/
mel-001) 전부 diff=0 입증. 작업지시자 "svg 골든을 교체해야 합니다" +
정량 입증으로 시각 판정 대체.

native + WASM 양쪽 동시 fix (PR #900 패턴, feedback_image_renderer_paths_
separate 본질 정합). 첫 PR #1020 직후 두 번째 기여 — PR 본문 매우 충실
(Symptom 표 + Before/After 캡처 + Root cause + Fix + Wiki 정합 + 회귀
검증 + 관련 영역 분리).
edwardkim pushed a commit that referenced this pull request May 20, 2026
… 4 hunk 복원

PR #1003 (closes #990) 의 cherry-pick `--theirs` 충돌 해소가 PR #1011
(closes #1006) 의 PageBorderBasis 통합 contract 를 PR #987 시절 attr 비트
해석으로 무심코 revert. HWP3 native (attr=0) 만 paper_based=false 로 판정되어
외곽선이 body-edge 로 좁아진 시각 회귀 발생.

Bisect 단언 (border_top y):
- 850cfb5 (PR #1011): 17.88 (paper-edge, 기준선)
- 71aedda (PR #1015): 17.88
- 84246b2 (PR #1018): 17.88
- 27c05d5 (PR #1020): 17.88
- b5d3834 (PR #1021): 17.88
- c2024ec (PR #1003): 55.64 ← 회귀 도입
- 65c8e69 (devel HEAD): 55.64

Fix: src/renderer/layout.rs 4 hunk 복원
- 변경 A: page_number_baseline_y() — (attr & 0x01) → matches!(basis, PaperBased)
- 변경 B: build_page_borders() — 동일 + 주석 + 디버그 로그 (bit1/bit2/footer_inside)
- 변경 C: footer_inside clip 복원 — 페이지 번호 외곽선 바깥 위치 (PR #1011)
- 변경 D: `(bx, mut by, bw, mut bh)` — footer clip 의 by/bh 수정 위함

Parser 측 PR #1011 변경 (basis=PaperBased 주입) 은 PR #1003 cherry-pick 시
보존됨. fix 는 renderer (layout.rs) 한정 단일 파일.

검증 (Stage 2 별도 보고):
- 3 포맷 paper_based=true 단언 (RHWP_DEBUG_PAGE_BORDER)
- HWP3 sample16 border_top y=17.88 복원
- HWP5/HWPX 변환본 무변동 (17.88 유지)
- cargo test --release --lib 1307 passed
- cargo clippy --release --lib -- -D warnings clean
- cargo fmt --check clean

Refs #1029

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants