fix: HWP5 line_segs 누락 paragraph 겹침 해소 — composer word wrap 합성 (closes #994)#997
Closed
jangster77 wants to merge 7 commits into
Closed
fix: HWP5 line_segs 누락 paragraph 겹침 해소 — composer word wrap 합성 (closes #994)#997jangster77 wants to merge 7 commits into
jangster77 wants to merge 7 commits into
Conversation
… wrap 합성 Root cause: HWP3 → HWP5 변환 시 일부 long-text paragraph (sample16 의 PUA bullet 59개) 의 PARA_LINE_SEG 레코드 누락. composer 의 compose_lines fallback 이 단일 ComposedLine 생성 → layout 이 wrap 없이 한 y 좌표에 모든 chars 그림 → 시각 겹침 (page 19~24 영향). Fix (G4-final, 3차 반복): src/renderer/composer.rs 의 compose_lines fallback (line_segs.is_empty()) 에서 paragraph 를 다수 ComposedLine 으로 분할. 1. Word boundary 분할 (~35 chars/line 한도, 공백 후 break) — mid-word 분할 회피 2. has_line_break=true 로 non-last synth line marking → Justify 정렬 비활성화 (chars 사이 spacing 부풀림 회피) 이전 시도 vs 본 fix: - 1차 (G1, paragraph_layout fallback line_height 보정): 효과 없음 — 실제 paragraph 가 layout_inline_table_paragraph 미사용 - 2차 (G4-wide, 35 chars char-count 분할): 겹침 해소했으나 Justify 가 chars spacing 부풀림 - 3차 (본 PR): word boundary + has_line_break — 자연스러운 정렬 검증: - cargo test --release --lib: 1297 passed, 0 failed ✓ - cargo fmt --check: 통과 - 240 sample 페이지 수: 타깃 1건 (62→67), 회귀 0 - HWP5 sample16 page 19~24 시각: 작업지시자 판정 통과 - Editor 기능 (parser 미변경): 영향 없음 영향 범위: - composer 의 line_segs 누락 case 만 적용 — HWP3 / HWPX (line_segs 있음) 미영향 - HWP5 변환본의 long-text paragraph 자연 렌더링 후속 (별도 issue 예정): - Page count 차이 (HWP3 64 vs HWP5 67 vs HWPX 자동보정 69) — paragraph height 누적 차이 별도 root cause closes edwardkim#994 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Collaborator
Author
|
관련 후속 issue 등록: #998 — HWP3/HWP5/HWPX sample16 페이지 수 차이 (64 vs 67 vs 69) — paragraph height 누적 차이 별도 root cause. |
This was referenced May 18, 2026
edwardkim
added a commit
that referenced
this pull request
May 19, 2026
edwardkim
added a commit
that referenced
this pull request
May 19, 2026
@jangster77 — HWP3→HWP5 변환 시 일부 long-text paragraph (sample16 PUA bullet 59개) PARA_LINE_SEG 누락 → compose_lines fallback 단일 ComposedLine → 시각 겹침 (page 19~24). word-boundary 분할 + has_line_break=true 로 해소. 옵션 A: 본질 커밋 de21afa cherry-pick (작성자 Taesup Jang 보존, 충돌 없음). 검증: cargo test 1307 + clippy -D + fmt 0. sweep (BEFORE devel ↔ AFTER): 검토 쟁점 B(hy-001 HWPX/HWP5 표 셀 경로 — Task #671 가드 충돌 우려) diff=0, 쟁점 A(sample16-hwp3 line_segs 보유) diff=0 — 회귀 0 입증. 작업지시자 시각 판정 통과 (sample16-hwp5 page 19~24 겹침 해소, 62→67). 페이지 수 잔존 (HWP5 67 vs HWP3 64)은 후속 #999 시리즈로 분리.
Owner
|
옵션 A로 devel에 반영했습니다 (본질 커밋 de21afa cherry-pick, 작성자 메타데이터 보존, 충돌 없음). 검증:
페이지 수 차이 (HWP5 67 vs HWP3 64 vs HWPX 69)는 PR 본문대로 별도 root cause로 후속 #999 시리즈에서 다룹니다. 잘 분리된 단계적 수정 감사합니다. |
jangster77
added a commit
to jangster77/rhwp
that referenced
this pull request
May 19, 2026
Root cause + Fix (2-layer): A. composer CHARS_PER_LINE 조정 (35 → 45): PR edwardkim#997 의 G4 휴리스틱 (35 chars/line) 이 HWP3 reference 평균 (43~46 chars/line) 보다 작음 → 매 paragraph +1 wrap line → ~2 페이지 inflate. HWP3 reference (sample16 pi=443 의 ts=[0,44,87,133]) 측정 결과 기반 조정. B. typeset spacing_before 보정: HWP5 변환본의 line_segs 누락 paragraph 가 ParaShape spacing_before=2264 HU (HWP3 reference 1132 HU 의 2x) — Hancom 변환기의 데이터 자체 차이. 59 paragraph × 1132 HU = ~890 px = ~1 페이지 inflate. format_paragraph 에서 line_segs.is_empty() && !text.is_empty() case 에 spacing_before=0 적용 → HWP3 reference 와 정합. 효과: - HWP5 sample16-hwp5.hwp: 67 (PR edwardkim#997) → 64 (본 PR) ✓ HWP3 reference 정합 - HWP3 / 다른 HWP5/HWPX sample: 변동 없음 - cargo test --release --lib: 1297 passed, 0 failed - 240 sample 페이지 수: 타깃 1건 만 (62→64), 회귀 0 - 작업지시자 시각 판정: 통과 영향 범위: - composer / typeset 내부만 변경 — parser 미변경 - Editor 기능 영향 없음 - HWP5 의 line_segs 누락 case 만 적용 — HWP3 / HWPX (line_segs 있음) 미영향 잔존 (별도 task 예정): - 자동 보정 (reflow_line_segs) path 의 페이지 수 69 — line_segs 채워서 본 fix path 우회 → 별도 정합 필요 - HWPX 변종 (72 페이지) — edwardkim#942/edwardkim#988 close 영역 (fundamental 한계) closes edwardkim#998 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
edwardkim
pushed a commit
that referenced
this pull request
May 19, 2026
Root cause + Fix (2-layer): A. composer CHARS_PER_LINE 조정 (35 → 45): PR #997 의 G4 휴리스틱 (35 chars/line) 이 HWP3 reference 평균 (43~46 chars/line) 보다 작음 → 매 paragraph +1 wrap line → ~2 페이지 inflate. HWP3 reference (sample16 pi=443 의 ts=[0,44,87,133]) 측정 결과 기반 조정. B. typeset spacing_before 보정: HWP5 변환본의 line_segs 누락 paragraph 가 ParaShape spacing_before=2264 HU (HWP3 reference 1132 HU 의 2x) — Hancom 변환기의 데이터 자체 차이. 59 paragraph × 1132 HU = ~890 px = ~1 페이지 inflate. format_paragraph 에서 line_segs.is_empty() && !text.is_empty() case 에 spacing_before=0 적용 → HWP3 reference 와 정합. 효과: - HWP5 sample16-hwp5.hwp: 67 (PR #997) → 64 (본 PR) ✓ HWP3 reference 정합 - HWP3 / 다른 HWP5/HWPX sample: 변동 없음 - cargo test --release --lib: 1297 passed, 0 failed - 240 sample 페이지 수: 타깃 1건 만 (62→64), 회귀 0 - 작업지시자 시각 판정: 통과 영향 범위: - composer / typeset 내부만 변경 — parser 미변경 - Editor 기능 영향 없음 - HWP5 의 line_segs 누락 case 만 적용 — HWP3 / HWPX (line_segs 있음) 미영향 잔존 (별도 task 예정): - 자동 보정 (reflow_line_segs) path 의 페이지 수 69 — line_segs 채워서 본 fix path 우회 → 별도 정합 필요 - HWPX 변종 (72 페이지) — #942/#988 close 영역 (fundamental 한계) closes #998 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
edwardkim
added a commit
that referenced
this pull request
May 19, 2026
@jangster77 — PR #997 (Task #994 G4) 직접 후속. HWP5 변환본 페이지 수 HWP3 reference 64 vs HWP5 67 해소. 2-layer: composer CHARS_PER_LINE 35→45 (HWP3 line_segs 실측 평균) + typeset spacing_before=0 (line_segs-missing, HWP3→HWP5 ParaShape 2x 보정). 옵션 A: 본질 커밋 c850148 cherry-pick (작성자 Taesup Jang 보존, 충돌 없음, #997 머지 위 적층). 검증: cargo test 1307 + clippy -D + fmt 0. sweep 8 fixture (BEFORE devel #997만 ↔ AFTER): 검토 쟁점 A(spacing_before=0 공통 typeset 경로 무차별 — exam/aift/hy-001 일반 샘플 포함) diff=0, 쟁점 B(sample16-hwp3 line_segs 보유) diff=0 — 회귀 0 입증. 작업지시자 시각 판정 통과 (sample16-hwp5 67→64 HWP3 reference 정합, page 19/22/23). 자동보정 path(69) / HWPX 변종(71) / HWP5·HWPX 한컴 권위 페이지 수는 후속 task 분리 (PR 본문 정합).
edwardkim
added a commit
that referenced
this pull request
May 19, 2026
@jangster77 — #997→#999 연장. HWP3 변환본 전반 한컴 정합. 격차 A(page border spec 표136 bit1/2 body_area clip) + B(PUA F03C5→□) + C(변환본 4중 AND 가드 식별 + ParaShape /4) 실효. 격차 D(y_offset double count) 는 후속 커밋 4e3ad58 에서 revert (non-variant table-vpos-01 회귀 발견 후 컨트리뷰터 자정) — 최종 no-op. 옵션 A: 본질 2커밋 cherry-pick (8b7fba3 + 4e3ad58, 작성자 Taesup Jang 보존, orders 충돌 --ours 메인테이너 일지 보존, 소스 .rs 충돌 없음). 검증: cargo test 1307 + clippy -D + fmt 0 + WASM 4.83MB. sweep 8 fixture: 일반 HWP5 6종(exam/aift/biz_plan/복학원서) diff=0 variant=false 유지 (오판 0), HWP3 원본 sample16.hwp 외곽선만 이동·텍스트 무변동. 작업지시자 시각 판정 통과 (sample16-hwp5 page 1/3 + HWP3 원본 외곽선 spec 정합 + 일반 HWP5 무회귀). 잔존 5건 (머릿말 inline image / 페이지 강제나눔 / gradient simplify / WASM path / 격차 D breathing room) 후속 issue 분리.
This was referenced May 19, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Root cause
HWP3 → HWP5 변환 시 일부 long-text paragraph 의 `PARA_LINE_SEG` 레코드 누락:
기존 `compose_lines` fallback (composer.rs:301-326) 이 단일 ComposedLine 생성 →
layout 이 wrap 없이 한 y 좌표에 모든 chars 그림 → 시각 겹침.
영향 paragraph: HWP5 sample16 에서 59 개.
Fix (G4-final, 3차 반복)
src/renderer/composer.rs 의 `compose_lines` fallback:
```rust
fn compose_lines(para: &Paragraph) -> Vec {
if para.line_segs.is_empty() {
if para.text.is_empty() { return Vec::new(); }
let default_style_id = ...;
}
```
3차 반복 시도 정리
Verification
Residual / 후속
Test plan
🤖 Generated with Claude Code