Task #445: 지문 박스/페이지 번호 박스 시각 결함 정정 (exam_kor)#450
Conversation
exam_kor.hwp 24페이지 → 20페이지 정합 작업 1단계. - 페이지별 단별 used/hwp_used/diff CSV (output/debug/task435/) - 회귀 대상 5문서 페이지 수 (exam_kor 24, exam_eng 8, k-water-rfp 28, hwpspec 177, synam-001 35) - RHWP_TYPESET_DRIFT 출력 캡처 (pi=0.30, pi=1.25 split 진단) - compute_body_wide_top_reserve_for_para 산정 경로 추적 핵심 진단: col 1 reserve 306.1px (HWP 실제 94.5px 대비 +211.6px 과대). 원인: Paper-rel 좌표를 body-rel 변환 없이 그대로 reserve 에 누적. Stage 2 에서 typeset.rs:2127-2172 의 VertRelTo::Paper 분기 정정. 수행계획서/구현계획서/Stage 1 보고서 포함.
compute_body_wide_top_reserve_for_para 의 VertRelTo::Paper 분기에서 body-rel 변환 누락 정정. body 와 일부만 겹치는 (header→body 침범) 케이스에서 Paper-rel 좌표를 그대로 reserve 에 누적하던 버그 수정. 수정 전 reserve = shape_y_offset(paper) + h + outer_bottom = 306.1 px 수정 후 reserve = max(0, shape_top_abs - body_top) ... = 94.4 px 결과: - exam_kor.hwp: 24 → 22 페이지 (page 2, 15 orphan 해소) - pi=0.30, pi=1.25 split → FullParagraph - 회귀: exam_eng 8, k-water-rfp 28, hwpspec 177, synam-001 35 유지 - cargo test: 1062 passed Stage 3 에서 일반 페이지 누적 -100~-300px 정정 (22 → 20).
원래 가설 ("표/도형 후 컬럼 잔여 공간 산정 부족") 재검토.
RHWP_TYPESET_DRIFT 분석 결과 diff 메트릭은 typeset cur_h 누적
(height_for_fit, trail_ls 제외) vs hwp_used (last line vpos+lh)
의 좌표계 차이를 측정하는 것일 뿐, "rhwp 가 채울 수 있는데 못 채운
잔여 공간" 이 아님을 확인.
실제 22→20 페이지 단축 장애물:
1. 섹션 1 페이지 14: Square wrap 표 + col 0 over-fill (1225>1211)
→ col 1 under-use (64px)
2. 섹션 1 페이지 15: 단일 컬럼 출력 (단정의는 2단인데 단 1 누락)
3. 섹션 2 페이지 18: pi=11 split + pi=13 [단나누기] orphan-like
3가지 전부 해결 시 22→19 가능 (목표 20 도달).
옵션 A/B/C 결정 필요 (현 상태 종료 / Stage 4 확장 / Stage 4 부분).
옵션 A 종료: 24→22 페이지 (Stage 2 col 1 reserve 정정). 잔여 22→20 미달성, 3가지 별도 메커니즘 (Square wrap over-fill, 단일 컬럼 출력 버그, col 0 cur_h over-advance) 별도 task 분리 권고. edwardkim#393 (옵션 A) 본 task Stage 2 로 적용 완료, close 가능.
수행계획서(task_m100_439.md) + 단계1 진단 보고서. 핵심 발견: - 이슈 가설의 engine.rs:702-711 는 fallback 경로 (RHWP_USE_PAGINATOR=1). 기본 활성 엔진은 typeset.rs::TypesetEngine. - 실제 버그 위치: typeset.rs::place_table_with_text (1400-1467). engine.rs 의 !is_wrap_around_table 가드 (engine.rs:1349, 1422) 누락. - 페이지 14 col 0 used=1225.8 (본문 1211.3 초과 +14.5) 정확히 재현. 코드 변경 없음 — 임시 디버그 코드는 모두 revert.
place_table_with_text 의 정확한 cur_h 누적 추적 (디버그 후 revert): - Square wrap 4 표가 pre_height + table_total 합산 → +244.88 px 과다 - HWP 의도: max(호스트 텍스트, 표 + v_offset) 만 누적 수정안: typeset.rs::place_table_with_text 에서 current_height += max(pre_height, v_off + table_total) (Square wrap 시) 코드 변경 없음 — 임시 디버그 println 모두 revert.
typeset.rs::place_table_with_text 에서 Square wrap (어울림) 표일 때 current_height 누적을 pre_height + table_total → max(pre_height, v_off + table_total) 로 변경. 호스트 문단 텍스트와 어울림 표는 같은 수직 영역을 공유하므로 더 큰 쪽만 한 번 누적해야 HWP layout 의도와 일치. PageItem 자체는 PartialParagraph + Table 모두 push (layout 렌더링 보존). 검증: - 페이지 14 col 0 used 1225.8 → 1036.1 px (≤ 1211.3 충족) - exam_kor.hwp 22 → 20 페이지 (목표 ≤ 21 충족) - 회귀 샘플 6 종 (exam_eng/math, 21언어, aift, 2010-01-06, biz_plan) 페이지 수 동일 - cargo test 1066 개 모두 통과 - SVG 렌더링 정상 closes edwardkim#439
Stage 4 회귀 검증 결과: - 149 개 sample HWP 전수 페이지 수 비교: exam_kor 만 22→20 변경, 148개 동일 - cargo test 1066 passed - DoD 전부 충족 본 task 완료. closes edwardkim#439.
typeset.rs::place_table_with_text 의 Square wrap 표 누적 정책을 pre_height + table_total → max(pre_height, v_off + table_total) 로 변경. 효과: - exam_kor.hwp 페이지 14 col 0 used 1225.8 → 1036.1 px (over-fill 해소) - exam_kor.hwp 22 → 20 페이지 - 149 개 sample 중 exam_kor 만 변화, 148 개 동일 (회귀 0건) - cargo test 1066 passed closes edwardkim#439
…문제 수정 - 수행/구현 계획서 + Stage 1·2 보고서 작성 - src/renderer/layout.rs: paragraph border merge 그룹을 col_area 바닥/꼭대기로 클램프 - exam_kor p2/5/8/15 의 세로 구분선이 PDF 와 일치하는 길이로 정상화 (p8: 1671 → 1425, 246px 단축, 페이지 바깥 침범 해소) - vpos-reset 미존중으로 인한 텍스트 자체의 overflow 는 별도 이슈로 분리 - snapshot 갱신: tests/golden_svg/issue-267/ktx-toc-page.svg (invisible 구조 rect 의 height 5.34px 변화, 가시 변화 없음)
페이지 번호 박스가 column divider line 과 붙어 보이는 문제 해결. 원인: 꼬리말 paragraph 의 vert=Para + wrap=TopAndBottom 표가 paragraph top 에 배치되어 본문 바닥과 같은 y 에 위치. HWP 의 실제 동작은 첫 라인의 line_height/2 만큼 아래에 anchor 되어 본문과 시각적 갭 형성. 수정: layout_header_footer_paragraphs 에서 해당 조건의 첫 paragraph 표는 y_offset 에 line_height/2 (px) 를 더하여 배치. 검증 (exam_kor.hwp 20p): - 박스 top y: 1422.93 → 1439.47 (PDF 380.6mm 와 일치) - column line - 박스 갭: 0px → 16.3-17.0px (PDF 16.0px 와 일치) - column line 길이/위치는 PDF 자연 그대로 유지 (p1 1131px, p2+ 1226px) - cargo test --release: 1117 passed, 0 failed
이슈 edwardkim#445 의 두 시각적 결함 (paragraph border 페이지 바깥 침범 + 페이지 번호 박스가 column line 에 붙음) 모두 PDF 와 일치하도록 수정 완료. 승인 후 local/devel 머지 + edwardkim#445 close 예정.
- mydocs/pr/pr_450_review.md (Task #445 cherry-pick 검토, 작성자 진단 모드 변천 분석) - mydocs/pr/pr_450_report.md (cherry-pick 머지 + 4 페이지 debug-overlay 시각 판정 통과) - mydocs/orders/20260430.md (PR #450 완료 행) 검증: 1069 passed + svg_snapshot 6/6 + issue_418 1/1 + clippy 0 + WASM 4,186,281 bytes 광범위 byte 비교: 305 중 67 차이 (머리말/꼬리말 영역 영향) 시각 판정: 4 페이지 (2/5/8/15) 모두 작업지시자 분석 일치 본질: layout.rs paragraph border 클램프 + 머리말/꼬리말 표 anchor 정정 (시각 증상) 잔여 본질 작업 (respect_vpos_reset) 별도 이슈 분리 (작성자 명시)
…hor 정정 (cherry-pick @planet6897 3 commits)
|
@planet6897 님 PR 감사드립니다. 메인테이너가 cherry-pick 으로 devel 에 적용 완료했습니다. 본 사이클 13번째 PR 입니다 — 가장 활발한 컨트리뷰터로서 exam_kor 정합 작업의 마지막 점검까지 정확히 짚어주셨습니다. 처리작성자 attribution 보존 본질 3 commits 분리 cherry-pick (Task #435/#439 흡수 + merge commits 제외):
devel 머지 commit: 검증
광범위 byte 비교10 샘플 / 305 페이지 SVG 비교: 238 동일, 67 차이. 차이 분포 (작성자 명시 외 머리말/꼬리말 영역 영향):
시각 판정 (작업지시자 직접) — 4 페이지 debug-overlay
작업지시자 통찰 — 본 PR 의 본질작업지시자께서 본 PR 검토 시 통찰을 짚으셨습니다:
PR 본문에 작성자 본인이 명시하셨듯, 본 PR 은 본질 정정이 아닌 시각 증상 클램프 — paragraph border 가 col_bottom 너머로 그려지는 시각 증상을 정리하면서 본질 ( 본 사이클 9 PR 의 본질 알고리즘 정정 흐름에서 PDF 정량 측정 정합 (200dpi ±1px) 으로 모드 전환된 정황을 메인테이너가 인지했습니다. 이는 회귀 위험 인식 + 작은 단위 회전 정책 부합 — 좋은 운영 판단입니다. 후속 PR 안내 (작성자 후속 본질 정정 계획)후속 PR 진행 시 권장:
이슈 #445 도 함께 close 됩니다. 본 사이클 13 PR 의 정성 + 활발한 진단 + 잔여 작업 분리 인식 모두 좋습니다. 감사합니다. |
- mydocs/pr/pr_461_review.md (5 Tasks 분리 cherry-pick 검토, 광범위 영향 86% 정황) 검증: 1070 passed + svg_snapshot 6/6 (golden 4건 갱신) + issue_418 1/1 + clippy 0 광범위 byte 비교: 305 중 263 차이 (86% 영향, Task #463 깊은 누적 정정) 시각 판정: PR #454 + #457 + #461 통합 검증 (작업지시자 결정) 본질 5 Tasks: - Task #459: 다단 후속 페이지 vpos-reset (PR #450 잔여 본질) - Task #462: TAC Picture 인라인 line advance - Task #463: 셀 leakage + 박스 geometry + 들여쓰기 + TAC crop + 바탕쪽 (Stage 1~8) - Task #468: cross-column 박스 partial 플래그 - Task #469: cross-column partial 박스 col_top/col_bot 침범
devel 의 PR edwardkim#461 (Task edwardkim#459+edwardkim#462+edwardkim#463+edwardkim#468+edwardkim#469) 통합본과 local/devel 의 Task edwardkim#469+edwardkim#470+edwardkim#471 작업 충돌 해결. 해결 내용: - src/renderer/layout.rs: ours (Task edwardkim#471 stroke_sig 비교 채택). devel 의 bf_id 비교는 Task edwardkim#471 에서 정정한 결함이므로 ours 가 superset. - src/renderer/layout/integration_tests.rs: ours (Task edwardkim#469/edwardkim#470/edwardkim#471 통합 테스트 3건 모두 보존). devel 은 edwardkim#469 테스트만 포함. - mydocs/orders/20260430.md: 양측 섹션 병합 (M100 박스 정합 + 잔존 이슈 + PR 처리 PR edwardkim#450). 검증: - cargo test 1072 + svg_snapshot 6 + issue_418 1 + 기타 PASS, FAIL 0.
…Canvas→LayerTree 반영 (Task edwardkim#460 기반) - upstream/devel 46 commits 병합 (PR edwardkim#446 set_field fix ~ PR edwardkim#456 Canvas→LayerTree) - 소스 파일 자동 병합 성공 (layout.rs, paragraph_layout.rs, engine.rs) - orders/20260430.md add/add 충돌만 수동 해소 (Task edwardkim#460 섹션 + PR edwardkim#450 섹션 통합) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Summary
layout.rs::build_single_column에서 paragraph border merge 그룹을 col_area 바닥/꼭대기로 클램프 —border_fill_id가 있는 PartialParagraph 의 세로 테두리가 col_bottom 을 초과해 페이지 바깥(p8y=1671 / 페이지 1587 초과)까지 그려지던 버그 해소layout.rs::layout_header_footer_paragraphs에서 머리말/꼬리말의wrap=TopAndBottom + vert=Para표 anchor 에line_height/2추가 — 페이지 번호 박스("1/20" 등) 가 column line 끝과 만나 "붙어 보이는" 문제 해소변경 내용
결함 1 — Paragraph border 페이지 바깥 침범
samples/exam_kor.hwp의 지문 박스(border_fill_id=7) 가 페이지 분할되는 경우, partial paragraph 의 border 세로 테두리가 col_bottom 너머까지 그려지고 일부 페이지에서는 페이지 자체(1587px)도 초과:원인:
respect_vpos_reset=false(CLI 기본) 로 동작 → vpos-reset 가 있는 paragraph 가 FullParagraph 로 처리되어 분할 라인이 col_bottom 너머에 layout 됨 (page 8 의 pi=297 가 91.7px 오버슈트)layout.rs::expand_clip이 자식 bbox bottom 으로 body-clip 을 확장만 (축소 없음) → clip 이 페이지 바깥까지 늘어남결함 2 — 페이지 번호 박스 위치
PDF 측정 (
samples/hancomdocs-exam_kor.pdfA3 200dpi):기존 SVG:
원인:
wrap=TopAndBottom,vert=Para/off=0,vert_align=Top) 로 그려짐compute_table_y_position은 vert=Para + vert_align=Top 일 때 표 top 을 paragraph top 에 정렬수정 (코드)
src/renderer/layout.rs::build_single_column— paragraph border merge 후 클램프:src/renderer/layout.rs::layout_header_footer_paragraphs— 표 anchor offset:검증 결과
페이지별 (exam_kor.hwp 20p)
PDF 비교:
column line 길이 (PDF 자연 차이 재현)
p1 vs p2+ 의 25mm 길이 차이는 PDF 도 동일 — 페이지 1 은 본문 내 타이틀(제 1 교시, 국어 영역) 이 있어 폴리곤 시작 y 가 더 아래임 (의도된 design).
회귀
cargo test --release: 1117 passed / 0 failed / 1 ignoredtests/golden_svg/issue-267/ktx-toc-page.svg(invisible 구조 rect height 5.34px 변경, 가시 변화 없음)본 작업 범위 외 발견
Test plan
cargo build --release성공cargo test --release1117 passed, 0 failedrhwp export-svg samples/exam_kor.hwp→ p2/5/8/15 line y_end ≤ 1423 (col_bottom 이하)samples/hancomdocs-exam_kor.pdf) 200dpi 렌더 비교 — column line / 박스 / 갭 일치단계별 커밋
c151156Stage 1+2: paragraph border 가 col_bottom 너머로 그려지는 문제 수정10d8709Stage 3: 머리말/꼬리말 wrap=TopAndBottom 표 anchor 위치 보정717ca1fStage 4: 최종 결과보고서 + 오늘할일 갱신관련
mydocs/plans/task_m100_445.mdmydocs/plans/task_m100_445_impl.mdmydocs/working/task_m100_445_stage{1,2,3}.mdmydocs/report/task_m100_445_report.md