fix: MEMO 컨트롤이 바탕쪽으로 오분류되는 버그 수정 (Issue #147)#277
Merged
Conversation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…#157) layout.rs: Para-relative float 표(vert=Para, TopAndBottom, non-TAC)를 vpos 기준점 리셋 예외 처리하여 앵커 문단 y 좌표 drift 수정. 초기화 시 lazy_base가 잘못된 값으로 교정되어 표 y가 body_bottom에 clamp → 텍스트와 중첩되는 버그 해결. engine.rs: Para-float 표가 body 범위 내에 완전히 들어오는 경우 effective_table_height = 0.0 방어 코드 추가. - 수정: layout.rs(is_para_float_table 예외, +18줄) pagination/engine.rs(effective_table_height 보정, +4줄) - 테스트: svg_snapshot.rs issue_157_page_1 신규 등록 - golden: tests/golden_svg/issue-157/page-1.svg - 검증: cargo test 941+4 passed, Table pi=25 LAYOUT_OVERFLOW 해소 Table y 894.7px(clamp) → 819.2px(정상) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
수정 대상 5개 위치 확정:
- text_measurement.rs: EmbeddedTextMeasurer L324/L345, WasmTextMeasurer L656
- paragraph_layout.rs: pending_right_tab_est L809, pending_right_tab_render L1177
- 추가: eprintln!("[DEBUG_TAB_POS]") L347-348 제거 대상 확인
Stage 2-4 상세 수정 방안: - text_measurement.rs: seg_start 헬퍼 패턴 (3곳) + eprintln 제거 - paragraph_layout.rs: match arm 분리 + trim_start (2곳) - 검증: cargo test / clippy / KTX visual diff
3경로 모두 right tab 직후 선행 공백을 무시하고 실질 텍스트 폭으로 tab_pos 정렬: 경로 1 (compute_char_positions): seg_start 인덱스에서 공백 skip 후 measure_segment_from 호출 - EmbeddedTextMeasurer inline_tabs L324 - EmbeddedTextMeasurer tab_stops L345 (+ eprintln![DEBUG_TAB_POS] 제거) - WasmTextMeasurer tab_stops L656 경로 2 (pending_right_tab_est): right tab match arm에서 run.text.trim_start() 전달 경로 3 (pending_right_tab_render): right tab match arm에서 run.text.trim_start() 전달 center tab은 현행 동작 유지.
KTX.hwp 2페이지(목차) golden 추가: - samples/KTX.hwp 추가 - tests/svg_snapshot.rs: issue_267_ktx_toc_page 테스트 추가 - tests/golden_svg/issue-267/ktx-toc-page.svg: golden 생성
- README: devel 섹션 추가 (edwardkim#157/edwardkim#267/edwardkim#256 PR 반영) - plans/ → plans/archives/: task_m100_267{,_impl}.md 이동
원인: SectionDef extra_child_records에 포함된 MEMO 텍스트박스 LIST_HEADER를 parse_master_pages_from_raw가 바탕쪽으로 잘못 분류 → 페이지 상단에 MEMO 텍스트 출력. 수정 (이중 방어): - parser/body_text.rs: text_width=0 && text_height=0인 LIST_HEADER는 바탕쪽 skip (실제 바탕쪽은 항상 비-제로 영역을 가짐) - renderer/layout.rs: build_master_page에 0×0 바탕쪽 렌더링 가드 추가 검증: aift.hwp 4페이지 "기업 소개…" 텍스트 미출력 확인 golden: tests/golden_svg/issue-147/aift-page3.svg Closes edwardkim#147
edwardkim
approved these changes
Apr 24, 2026
edwardkim
left a comment
Owner
There was a problem hiding this comment.
Approved. 🎉
검토 결과
@seanshin 님, 오래된 이슈 #147 해결 감사합니다. 이슈 내용(0×0 바탕쪽은 MEMO 오분류 의심)을 그대로 이중 방어로 구현하신 점이 인상적입니다.
특히 인상 깊은 부분
- 루트 원인 정확 —
parse_master_pages_from_raw가HWPTAG_LIST_HEADER를 무조건 바탕쪽으로 분류. MEMO 컨트롤 텍스트박스도 LIST_HEADER를 쓰므로 오분류. 명확한 식별. - 이중 방어 적절성 — 파서 1차 방어 (근본 해결, 6줄) + 렌더러 2차 방어 (호환성, 4줄). 과도하지 않음.
- 0×0 조건의 타당성 — HWP 스펙상 바탕쪽은 반드시 비-제로 영역. 정당한 케이스 차단 없음.
- Golden SVG 등록 — 669줄 aift.hwp 4페이지 전체 스냅샷. 회귀 감지 가능.
메인테이너 검증
| 항목 | 결과 |
|---|---|
cargo test --lib |
✅ 964 / 0 / 1 ignored (merge 시뮬레이션) |
cargo test --test svg_snapshot |
✅ 6 / 0 (issue_147 포함) |
cargo clippy --lib -- -D warnings |
✅ clean |
cargo check --target wasm32 |
✅ clean |
| devel 자동 merge 시뮬레이션 | ✅ 충돌 0건 |
| WASM Docker 빌드 | ✅ 성공 |
| rhwp-studio 브라우저 시각 검증 | ✅ aift.hwp 4페이지 "기업 소개…" 텍스트 미출력 확인 |
후속 요청 (merge 후 별도 커밋)
CLAUDE.md 절차 기준으로 아래 문서가 누락되어 있습니다:
mydocs/plans/task_m100_147_impl.md— 구현계획서mydocs/working/task_m100_147_stage*.md— 단계별 보고서mydocs/report/task_m100_147_report.md— 최종 보고서mydocs/orders/20260424.md— Task #147 섹션
수행계획서(task_m100_147.md)만 포함되어 있습니다. 코드 수정은 우수하여 merge 진행하되, 후속 커밋으로 문서 보완 부탁드립니다.
BEHIND 상태이지만 충돌 없이 자동 merge 가능 — admin merge 진행합니다.
edwardkim
added a commit
that referenced
this pull request
Apr 24, 2026
edwardkim
added a commit
that referenced
this pull request
Apr 24, 2026
- 작성자: @seanshin (Task #147, PR #277) - Merge commit: 24109c9 (admin merge, BEHIND 상태지만 충돌 없음) - 이슈 #147 closed 변경: - src/parser/body_text.rs: parse_master_pages_from_raw 0×0 LIST_HEADER skip (6줄) - src/renderer/layout.rs: build_master_page 0×0 바탕쪽 렌더링 가드 (4줄) - tests/golden_svg/issue-147/aift-page3.svg 신규 (669줄) 검증: - cargo test --lib: 964 passed / 0 failed (merge 시뮬레이션) - cargo test --test svg_snapshot: 6 passed (issue_147 포함) - cargo clippy + wasm32 check: clean - WASM Docker 빌드 + rhwp-studio 브라우저 시각 검증 성공 후속 요청: 구현계획서/단계별 보고서/최종 보고서/orders 섹션 작성자 제출 대기 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
edwardkim
added a commit
that referenced
this pull request
Apr 24, 2026
…r 복구 (closes #275) - 작성자: @planet6897 (Task #275, PR #278) - Merge commit: 2a27b36 (admin merge, orders 문서 충돌 직접 해결) - 이슈 #275 closed - 커뮤니티 리뷰: @seanshin APPROVED 처리 절차: - PR 브랜치에 origin/devel 머지 → orders 문서 충돌 해결 (Task #275 섹션 "## 5" 재배치) - planet6897/local/task275에 push (maintainerCanModify 허용) - 재승인 + admin merge 검증: - cargo test --lib svg_fragment: 19 passed / 0 failed - cargo test --lib: 983 passed / 0 failed / 1 ignored (+19 신규 svg_fragment) - cargo clippy + wasm32 check: clean - svg_snapshot: 6 passed 파급 효과: WASM canvas 에서 OLE 네이티브 이미지/EMF/OOXML 차트/Placeholder 모두 복구 ===== 오늘 처리 5개 PR 완료 ===== #284 (#280) @planet6897 - 수식 폰트 스택 #285 (#283) @planet6897 - 수식 파렌 글리프 #266 (#157/#103) @seanshin - 비-TAC 표 out-of-flow #273 (#267) @seanshin - right tab 공백 처리 #277 (#147) @seanshin - MEMO 바탕쪽 오분류 #278 (#275) @planet6897 - WASM OLE RawSvg/Placeholder 별도 추적: 이슈 #291 (KTX.hwp 2단 TAC 표 회귀, 핀셋 처리 예정) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
edwardkim
added a commit
that referenced
this pull request
Apr 24, 2026
#297) - 작성자: @planet6897 (Task #297, PR #300, 오늘 6번째 기여) - Merge commit: 0e3fb02 (admin merge, orders 3구간 충돌 직접 해결) - 이슈 #297 CLOSED 처리 절차: - PR 브랜치에 origin/devel 머지 → orders 섹션 3구간 해결 (#295 "## 7", #296 "## 8", #297 "## 9") - planet6897/task297 에 push - 재승인 + admin merge 변경 (1파일): - src/renderer/layout/table_layout.rs +5 -2: - VertRelTo::Page => (col_area.y, col_area.height) [쪽 본문 영역] - VertRelTo::Paper => (0, page_h_approx) [용지 전체, 유지] - HWP 스펙 Page=쪽 본문, Paper=용지 전체 반영 성과: - pi=22 "* 확인 사항" 박스 y: 1371.5 → 1224.07 (PDF 1226.5 ±2 일치) - 145 샘플 중 본문 Page 표 13건 + 바탕쪽 5건 회귀 스캔 완료 (의도 범위 외 무회귀) 검증: - cargo test --lib: 992 passed - svg_snapshot: 6 passed (golden 유지) - 실제 SVG y 좌표 확인: 1224.07px (PDF 일치) #295 → #297 연결 모범 사례: PR #298 리뷰 중 사전 존재 버그로 분리 → 1시간 만에 PR #300 해결. 초기 가설(바탕쪽 Paper) 폐기 → pdftotext 실측으로 근본 원인(enum 미구분) 발견 → 1줄 수정. ===== 오늘 9번째 PR 머지 ===== #284 #285 #266 #273 #277 #278 #289 #292 #298 #300 + 메인테이너 핀셋 #296 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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
parse_master_pages_from_raw가SectionDef.extra_child_records에서HWPTAG_LIST_HEADER를 발견하면 무조건 바탕쪽으로 분류. MEMO 컨트롤의 텍스트박스도 LIST_HEADER를 사용하므로 오분류 발생.오분류된 "바탕쪽"의 특징:
text_width=0, text_height=0(실제 바탕쪽은 반드시 비-제로 영역)Fix (이중 방어)
src/parser/body_text.rssrc/renderer/layout.rsTest Results
cargo test: 963 passed, 0 failedcargo clippy --lib -- -D warnings: 0 warningsissue-147/aift-page3.svg등록Closes #147