Skip to content

Task #1037: HWP5 변환본 ParaShape unit normalize + Dialog 한컴 정합 fix (closes #1037)#1040

Closed
jangster77 wants to merge 9 commits into
edwardkim:develfrom
jangster77:local/task1037
Closed

Task #1037: HWP5 변환본 ParaShape unit normalize + Dialog 한컴 정합 fix (closes #1037)#1040
jangster77 wants to merge 9 commits into
edwardkim:develfrom
jangster77:local/task1037

Conversation

@jangster77

Copy link
Copy Markdown
Collaborator

Summary

HWP3 → HWP5 변환본 의 raw ParaShape 값이 한컴 변환기에 의해 2× scaled 저장되는 quirk 를 parser 단계 normalize + 문단모양 dialog margin/indent 표시 산식을 raw_ps 직접 사용 + HWP3/HWP5 변환본 unit semantic 차이 분기로 한컴 정답 정합 달성.

Stages

Stage 작업 결과
1 진단 — PARA_LINE_SEG 누락 paragraph 식별 진단 only
2 parser ParaShape halve (is_hwp3_variant) + style_resolver variant_div uniform 2 spacing 정합 + rendering 무변동
3 build_para_properties_json margin/indent 공식 raw 직접 사용 + variant 분기 dialog 한컴 정합
4 D 옵션 정량 평가 (page break vpos==0 휴리스틱 + line_seg 합성 옵션 B') negative result, 코드 변경 없음

효과 (sample16 p452 / p97 동일 paragraph 비교)

필드 한컴 정답 Task #1037 이전 Task #1037 완료
dialog 왼쪽 40.0 pt HWP3 30 / HWP5 20 40 / 40 ✓
dialog 오른쪽 10.0 pt 5 / 5 10 / 10 ✓
dialog 내어쓰기 20.0 pt 10 / 10 20 / 20 ✓
dialog 문단 위 8.5 pt HWP3 8.6 / HWP5 17.0 (2×) 8.6 / 8.6 ✓
페이지 수 64 HWP3 64 / HWP5 64 64 / 64 ✓
alignment (PR #1036) 60/64 60/64 유지 ✓

작업지시자 시각 검증 — "(3) 원격지 재해복구센터(DR: Disaster Recovery) 구축" paragraph 에서 한컴/rhwp HWP3/rhwp HWP5 변환본 dialog 완전 정합 (왼쪽 30 / 오른쪽 0 / 첫줄 보통 / 줄간격 160% / 문단위 14.2 / 문단아래 0).

변경 파일

파일 변경 (stage)
src/parser/mod.rs is_hwp3_variant 시 ParaShape raw halve (Stage 2)
src/renderer/style_resolver.rs variant_div uniform 2.0 (Stage 2)
src/document_core/commands/formatting.rs build_para_properties_json margin/indent 공식 raw 직접 (Stage 3)

Stacked on PR #1036 (Task #1035)

본 PR 은 PR #1036 (Task #1035, base) 위에 적층. PR #1036 merge 후 rebase 또는 통합 검토 권고.

자동 검증

  • cargo build --release ✓ warning 0
  • cargo clippy --release --lib -- -D warnings ✓ clean
  • cargo fmt --all -- --check ✓ clean
  • cargo test --release --lib ✓ 1308 passed
  • cargo test --release --tests ✓ FAILED 0
  • 회귀 sweep 변환본 9종 + HWP3 + 일반 fixture: 페이지 수 무변동

잔존 (별도 신규 이슈 등록 예정)

  • HWP5 변환본 page_break_before 정보 100% 손실 (한컴 변환기 quirk, 휴리스틱 false negative 위험)
  • HWP5 변환본 p23 외곽선 overflow (root cause line_seg missing 아님, 다른 영역 조사)

Test plan

  • sample16-hwp5.hwp 의 paragraph 모양 dialog 확인 (왼쪽/오른쪽/내어쓰기/문단 위/줄 간격) 한컴 정답 정합
  • sample16.hwp HWP3 동일 paragraph dialog 동일 정합
  • sample16-hwp5.hwp 페이지 수 64 유지 + alignment 60/64 유지
  • HWP3 native + 일반 HWP5/HWPX fixture 무회귀 (페이지 수 무변동)

Closes #1037

🤖 Generated with Claude Code

jangster77 and others added 8 commits May 20, 2026 20:10
devel baseline 측정:
- HWP3 sample16: 64 페이지
- HWP5 변환본 sample16: 64 페이지
- alignment 정합률: 24/64 (37.5%) — 40 페이지 미정합

PR edwardkim#1009 hunks 임시 적용 결과:
- sample16-hwp5: 64 → 65 (+1 over-split 회귀 재현)
- alignment: 24 → 23 (오히려 악화)
- main_trigger 자체는 정확 (pi=472 prev_end=68312 > 0.85×72848=61920 +
  pi=473 vpos=284 < 1500)
- HWP3 native 동일 paragraph 도 vpos=0 reset 패턴 — 휴리스틱 의도는 정확

Over-split 메커니즘:
- p18~p23: PR edwardkim#1009 휴리스틱 정확히 작동
- p24 부근 PartialParagraph 처리 (pi=460 paragraph 내부 vpos-reset@line3)
- PR edwardkim#1009 force-break + PartialParagraph split 효과 누적 → +1 추가 페이지

Narrow 가드 후보 4 식별:
- A: PartialParagraph 가능성 paragraph 에서 trigger skip
- B: high_threshold 0.85 → 0.90/0.95
- C: 다음 paragraph height 검증
- D (권고): naturally-breaks 단언 — paginator 가 자연 break 할 위치인지
  미리 계산, 자연 break 시 force-break skip

CHARS_PER_LINE 45 (PR edwardkim#1009 commit message claim 45→50 부정확, actual diff
없음). 본 task 에서 composer.rs 무수정.

Stage 2 진행: PR edwardkim#1009 base + narrow 가드 D 우선 시도.

Refs edwardkim#1035

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…% → 93.75%)

PR edwardkim#1009 (Task edwardkim#1007, closed) 의 cross-paragraph vpos reset 감지 휴리스틱 base 적용
+ Task edwardkim#1035 narrow 가드 2 항목:
  1. high_threshold 0.85 → 0.95 (자연 paginator break 영역 외 제외)
  2. aux_trigger 제거 (empty bridge 휴리스틱은 false positive 다수)

Stage 1 진단 + Stage 2 narrow 가드 실험 결과:

| 시도 | sample16-hwp5 | alignment |
|------|---------------|-----------|
| devel baseline | 64 | 24/64 (37.5%) |
| PR edwardkim#1009 그대로 (0.85+aux) | 65 (+1) | 23/64 (악화) |
| 0.95 + aux 유지 | 65 | 23/64 |
| all triggers disabled | 64 | 24/64 |
| 0.95 + aux 제거 (채택) | 64 ✓ | 60/64 (93.75%) ✓ |

→ aux_trigger 자체가 over-split 의 직접 원인 (empty bridge 휴리스틱
false positive). main_trigger 만 + threshold 0.95 narrow 로 정합률 대폭 향상.

변경 파일 (PR edwardkim#1009 base):
- src/renderer/pagination/engine.rs (+84, variant_vpos_reset_break)
- src/renderer/typeset.rs (+136, 동일 로직 두 경로 정합)
- src/renderer/pagination.rs (PaginationOpts::is_hwp3_variant 필드)
- src/document_core/queries/rendering.rs (is_hwp3_variant 전달)

variant 식별 인프라 (cfb_reader/parser/model) 는 이미 edwardkim#1005 머지 — 재활용.

회귀 sweep:
- 변환본 9종 페이지 수: 모두 무변동 (over-split 회귀 0)
- HWP3 native + 일반 HWP5 (exam_*, aift, biz_plan): 무변동
- cargo test --lib: 1308 passed (1 추가 — variant 인프라 테스트)
- cargo test --tests: FAILED 0 (전체 integration)
- clippy / fmt --all: clean (feedback_cargo_fmt_all_required 정합)

회귀 가드 추가: tests/issue_1035_alignment.rs
  hwp3_sample16_hwp5_page_count_64 — sample16-hwp5 64 유지 단언
  (PR edwardkim#1009 over-split 65 회귀 재발 방지).

성공 기준 C1~C6 자동 단언 완료. C7 (시각 검증) Stage 4 시점.

Refs edwardkim#1035 / PR edwardkim#1009 follow-up

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ension 진단

p21 미정합 (HWP5 변환본 p21 시작 pi=442 vs HWP3 pi=440) case-specific fix 시도:
- aux_trigger narrow (empty_between≥3 + prev_end > body × 0.75): 65p +1 over-split 회귀
- aux_trigger 그대로 + main만 narrow: 동일 회귀
- 모든 narrow 가드 실패 — aux_trigger 발동 자체가 over-split 직접 원인

Root cause — paginator cumulative height vs encoder vpos signal:
- HWP5 변환본 encoder: pi=440 vpos=852 (page-reset signal, hwp_used=32.7px 작음)
- rhwp paginator: cumulative paragraph height 측정 971.0px (body 거의 full)
- HWP5 변환본 paragraph height 가 HWP3 보다 약 2배 (font/spacing metric 차이)
- aux_trigger force-break 후 paginator cumulative 누적이 자연 break 보다 큼 → +1 페이지

한컴 정답지 비교 단언:
- 한컴 한글 viewer p21 (footer "-21-") = rhwp HWP3 p23 (idx=22) 내용 정합
  (11 items pi=450~460 + "나." Table subheader)
- HWP5 변환본 p23 (rhwp): 같은 11 items 이나 paragraph height 2배 → pi=460
  PartialParagraph split + 시각적 overflow
- 38 페이지 추정 = 한컴 viewer 로딩 시 근사값 (별도 issue 등록 대상 아님)

잔존 미정합의 본질:
- p21 alignment + p23 overflow 모두 HWP5 변환본 paragraph height 과대 측정 원인
- Task edwardkim#1008 격차 D (폰트 매핑) 영역 연장
- 별도 issue 등록 권고: "HWP5 변환본 paragraph height 과대 측정 — HWP3 대비 약 2배"

본 task Stage 2 fix (60/64 alignment, 64 페이지 유지) 가 최선 — PR 진행 권고.

Refs edwardkim#1035

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Stage 1~3 종결:
- Stage 1: 진단 — PR edwardkim#1009 휴리스틱 over-split + alignment 악화 재현
- Stage 2: PR edwardkim#1009 base + Task edwardkim#1035 narrow 가드 (0.85→0.95, aux 제거)
  → alignment 37.5% → 93.75% (60/64) + sample16-hwp5 64 유지
- Stage 3: case-specific p21 fix 시도 — fundamental tension 단언

성공 기준 C1~C7 모두 충족 (작업지시자 한컴 정답지 시각 검증 포함).

잔존 미정합 (p21 alignment + p23 overflow) 의 본질 = HWP5 변환본 paragraph
height 가 HWP3 의 약 2배 (font/spacing metric 차이). 별도 issue 등록 권고.

closes edwardkim#1035 (alignment 부분 해결, paragraph height 본질 후속 issue)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
진단 test 로 sample16 pi=450 비교 단언:
- HWP5 변환본 LineSegs.len() = 0 (모든 paragraph, encoder typeset 안 함)
- CharShape base_size: HWP3 1000 → HWP5 1300 (+30%)
- ParaShape spacing_before: HWP3 1132 → HWP5 2264 (×2)

Height 산출 경로:
- composer.rs:441 fallback: LineSegs 빈 경우 synth line_height=400 하드코딩,
  CHARS_PER_LINE=45 로 word wrap
- layout/paragraph_layout.rs:1166 corrected_line_height: raw_lh(400) < max_fs(1300)
  → Percent: max_fs × ls_val/100 = 1300 × 1.6 = 2080
- HWP3 actual: raw_lh(1300) ≥ max_fs(1000) → no correction → 1300

Root cause = 2 요소:
1. per-line height: HWP5 corrected 2080 vs HWP3 actual 1300, 비율 ×1.6
2. 라인 수: HWP5 synth 4 (140/45) vs HWP3 actual 3, 비율 ×1.33
합산: ×1.6 × ×1.33 ≈ ×2.13 (관찰값 정합)

Stage 2 권고 (A + B 결합):
- A: composer fallback line_height = max_fs (per-line 정합)
- B: CHARS_PER_LINE 45 → 50 (라인 수 정합)
결과 (HWP5 pi=450): 3 lines × 1300 HU = 3900 HU = HWP3 actual 정합

Refs edwardkim#1037

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
PR edwardkim#1036 (Task edwardkim#1035) 위에 paragraph height 과대 측정 정정 — composer fallback
경로의 2 요소 fix:

Fix A: src/renderer/mod.rs corrected_line_height Percent 케이스 변경
  - 종전: max_fs * ls_val / 100 (= 1.6× for ls_val=160)
  - 변경: max_fs (1.0×, HWP3 actual 동등)
  - 영향: raw_lh < max_fs (fallback case 한정). HWP3 actual 은 raw_lh ≥ max_fs
    로 본 분기 미진입 — 무영향.

Fix B: src/renderer/composer.rs CHARS_PER_LINE 45 → 50
  - sample16 pi=450 (140 chars) HWP3 actual 3 lines 정합 (140/50 = 3 lines)
  - 종전 45 로는 140/45 = 4 lines 과다 (×1.33 라인 수 과대)

효과 단언 (Task edwardkim#1035 + Task edwardkim#1037 combined):
- sample16 pi=450 paragraph height: 118.5 → 59.5 (HWP3 actual 동등) ✓
- p23 pi=460 처리: PartialParagraph (overflow) → FullParagraph h=111.5 ✓
- sample16-hwp5 페이지 수 64 유지 ✓
- alignment 정합률 60/64 → 58/64 (trade-off -2, 시각 정합 우선)

회귀 sweep (모든 fixture 무변동):
- 변환본 9 종: sample/4/5/10/11/13/14/16/19-hwp5 + .hwpx (16/36/64/763/151/3/11/64/2/71)
- HWP3 native + 일반 HWP5 (exam_*, aift, biz_plan): 무변동
- cargo test --lib: 1308 passed
- cargo test --tests: FAILED 0 (전체 integration)
- clippy / fmt --all: clean

Refs edwardkim#1037

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
build_para_properties_json: margin/indent JSON 산식 raw_ps 직접 사용.
is_hwp3_variant 분기로 HWP3 (effective first-line = margin_left + min(0,
indent)) vs HWP5 변환본 (raw 직접 사용) 차별화. spacing 은 기존 그대로.

효과: sample16 p452 기준 HWP3/HWP5 변환본 dialog 모두 한컴 정합 (왼쪽 40,
오른쪽 10, 내어쓰기 20, 문단위 8.5). 페이지 수 64 한컴 정합 유지 (rendering
무변동). 회귀 0.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Stage 4 진단: 작업지시자 D 옵션 선택 (page break vpos==0 휴리스틱 + p23
overflow line_seg 합성 옵션 B') 정량 평가.
- page break: Recall 31.6%, FP 4개 (부적합)
- line_seg 합성: Task edwardkim#1010 Stage 2 회귀 (88 페이지 +24) + cross-correlation
  root cause 무관 입증 (시도 가치 낮음)

코드 변경 없음 (negative result). 잔존 2 이슈 별도 task 분리 결정.

최종 보고서 + orders 갱신 + Stage 4 보고서 추가.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@edwardkim edwardkim self-requested a review May 20, 2026 22:48
@edwardkim edwardkim added the enhancement New feature or request label May 20, 2026
@edwardkim edwardkim added this to the v1.0.0 milestone May 20, 2026
edwardkim added a commit that referenced this pull request May 21, 2026
…malize + Dialog 한컴 정합 fix

@jangster77 (Taesup Jang) PR #1040closes #1037 (M100, v1.0.0). PR #1036 (Task #1035, 방금 머지) 잔존 본질 해결.

핵심:
- HWP3 → HWP5 변환본 ParaShape margin/indent/spacing 2× quirk parser 단계 normalize
- Dialog 4 필드 한컴 정합 (왼쪽 40 / 오른쪽 10 / 내어쓰기 20 / 문단위 8.5 — HWP3 + HWP5 변환본 모두 정합)
- style_resolver variant_div 종전 4 (case-specific Task #1001) → uniform 2 단순화
- build_para_properties_json raw_ps 직접 사용 + is_hwp3_variant 분기

검증:
- cargo test --release --lib: 1319 passed (PR #1036 회귀 가드 양립)
- cargo test --release --tests: FAILED 0 (전체 통합)
- cargo clippy --release --lib -D warnings: clean
- cargo fmt --check: clean
- 10 fixture BEFORE/AFTER diff = 0 (rendering 무변동 정량 입증)
- 작업지시자 시각 판정 통과 (dialog 4 필드 한컴 정합)

PR base bbd38e8 (PR #1033 머지 후) → origin/devel 402e0ce (PR #1036 머지 후 + docs) cherry-pick squash. 본질 3 코드 파일 + Task #1037 plans/working/report 7 문서 적용.

잔존 후속 (PR 본문 명시): p23 overflow + page_break_before 손실 별도 task 분리 권고.
@edwardkim

Copy link
Copy Markdown
Owner

PR #1040 cherry-pick squash merge 완료 (devel c6fb7f2). Task #1037 HWP5 변환본 ParaShape unit normalize + Dialog 한컴 정합 fix. 작업지시자 시각 판정 통과 + 10 fixture BEFORE/AFTER diff = 0 (rendering 무변동 PR 본문 명시 정확 입증) + 1319 lib + 통합 + clippy + fmt clean.

본 PR base (bbd38e8) 가 origin/devel (402e0ce = PR #1036 머지 후) 보다 multi-merge 상태였으나 본질 3 코드 파일 (parser/mod.rs + style_resolver.rs + formatting.rs) + Task #1037 plans/working/report 7 문서만 cherry-pick squash 적용. PR #1036 (Task #1035) 회귀 가드 (tests/issue_1035_alignment.rs) 양립.

Dialog 4 필드 한컴 정합 (왼쪽 40 / 오른쪽 10 / 내어쓰기 20 / 문단위 8.5) — HWP3 + HWP5 변환본 모두 정합. PR #1036 alignment 60/64 + 페이지 수 64 완전 보존.

잔존 후속 (PR 본문 명시): p23 외곽선 overflow + HWP5 변환본 page_break_before 100% 손실 — 별도 task 분리 권고.

감사합니다, @jangster77. PR #1031/#1034/#1036/#1040 의 HWP3 sample16 정합 시리즈 모두 마무리.

@edwardkim edwardkim closed this May 21, 2026
edwardkim added a commit that referenced this pull request May 21, 2026
- mydocs/pr/archives/pr_1040_review.md (이동)
- mydocs/pr/archives/pr_1040_report.md (최종 보고서 신규)
- mydocs/plans/archives/task_m100_1037.md + task_m100_1037_impl.md (이동)
- mydocs/orders/20260521.md PR #1040 항목 추가

PR #1040 (closes #1037, @jangster77 30번째 기여): HWP5 변환본 ParaShape
unit normalize + Dialog 한컴 정합 fix. parser 단계 ParaShape /= 2
normalize + style_resolver variant_div 4 → uniform 2 + build_para_properties_json
raw_ps 직접 사용 + is_hwp3_variant 분기.

squash merge (devel c6fb7f2) + 10 fixture BEFORE/AFTER diff = 0
(rendering 무변동 정량 입증) + Dialog 4 필드 한컴 정합 시각 판정 통과 +
WASM 4.90MB 동기화. PR #1036 alignment 60/64 + 페이지 수 64 완전 보존.

HWP3 sample16 정합 시리즈 (PR #1031/#1034/#1036/#1040) 마무리.
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