Skip to content

Task #347: exam_eng.hwp 표/그림 절대 좌표·Z-order·셀 padding/vpos 통합 수정#351

Merged
edwardkim merged 10 commits into
edwardkim:develfrom
planet6897:local/task347
Apr 26, 2026
Merged

Task #347: exam_eng.hwp 표/그림 절대 좌표·Z-order·셀 padding/vpos 통합 수정#351
edwardkim merged 10 commits into
edwardkim:develfrom
planet6897:local/task347

Conversation

@planet6897

Copy link
Copy Markdown
Contributor

개요

samples/exam_eng.hwp 의 SVG 출력이 PDF 참조본과 어긋나는 문제를 통합 수정. p2 우측 박스, p4 Q27/Q28 박스, p8 "확인 사항" 마스터 페이지 박스 등 표/그림의 절대 좌표 계산, Z-order, 셀 내부 padding/vpos 관련 결함 6단계를 한 이슈(#347)로 묶어 처리한다.

Closes #347

변경 사항

1. 표/그림 절대 좌표 계산 (commit 34e432f)

  • compute_table_x_position: HorzRelTo::Page 가 단(col_area)이 아닌 body_area 기준으로 계산되도록 수정
  • compute_table_x_position: HorzAlign::Right 부호 보정
  • compute_table_y_position: VertRelTo::Pagebody_area 기준으로 통일
  • InFrontOfText 표는 본문 흐름을 밀어내지 않도록 push-down 분기 한정
  • layout_body_picture: BehindText / InFrontOfText 그림이 y_offset 을 진행시키지 않도록 분리
  • layout_shape_item: 본문 텍스트 없는 문단의 TAC 그림이 누락되지 않도록 인라인 렌더 분기 추가

2. TAC 그림/InFrontOfText 표 Z-order 보존 (commit 336cfa4)

  • 같은 문단 인덱스에서 [Table, Picture] 순으로 컨트롤이 등장하는 케이스(p4 Q28)에서 Picture가 Table 뒤에 그려지지 않도록 트리 삽입 위치 보정

3. 인라인 TAC 그림 x 좌표 (commit 039eb1e)

  • TAC 그림이 단 좌측에 붙어 그려지던 문제 — paragraph margin_left / indent 를 x 계산에 반영

4. 확장 바탕쪽 is_extension 판별 보강 (commit 5237d7d)

  • ext_flags & 0x02 비트 OR apply_to 중복 휴리스틱으로 보강하여 첫 등록+확장 표시(0x03) 케이스 누락 해소
  • p8 "확인 사항" 마스터 페이지가 정상 노출되도록 함

5. 셀 첫 줄 y 위치 (commit f3ba9eb)

  • layout_table_cells: 셀 내부 첫 줄 y를 vertical_align 으로만 결정하던 로직을 LineSeg.vertical_pos 가 있을 경우 우선 사용하도록 통합 (Q27 Center valign 케이스 포함)

6. 셀 padding 우선순위·축소 보정 (commit 72d8245)

검증

  • cargo build --release / cargo test — 전체 1047+ 테스트 통과
  • 시각 회귀: exam_eng.hwp 8 페이지 전체에 대해 PDF 참조본 대비 비교 (p2/p4/p8 우측 박스 정상화)
  • 첨부 스크린샷: mydocs/working/task_347_exam_eng_p{2,4,8}*_after.png

문서

  • mydocs/plans/task_347.md — 수행 계획서
  • mydocs/plans/task_347_impl.md — 구현 계획서
  • mydocs/working/task_347_stage{1,2,3}.md — 단계별 보고서
  • mydocs/report/task_347_report.md — 최종 결과 보고서
  • mydocs/orders/20260426.md — 오늘 할일 갱신

영향 범위

  • 파서: src/parser/body_text.rs — 마스터 페이지 확장 판별
  • 렌더러: src/renderer/layout.rs, src/renderer/layout/table_layout.rs, src/renderer/layout/picture_footnote.rs
  • 외부 API 변경 없음, 골든 SVG 갱신 없음

planet6897 and others added 10 commits April 26, 2026 18:37
samples/exam_eng.hwp p2/p4 우측 박스 렌더링이 PDF와 상이한 문제 해결.
picture_footnote 경로의 시맨틱을 정답으로 표/그림 코드 경로 통일.

수정 내용:
1. layout.rs: current_body_area Cell 추가 (페이지 1회 set)
2. table_layout.rs: HorzRelTo::Page / VertRelTo::Page → body_area 기준
   (기존 col_area로 처리되어 다단 문서에서 컬럼 1로 잘못 배치)
3. table_layout.rs: HorzAlign::Right 부호 정정 (+h_offset → -h_offset)
4. picture_footnote.rs: 글뒤로/글앞으로 그림 y_offset 진행 차단
   (본문 흐름 미점유 객체가 후속 인라인 콘텐츠를 푸시다운하던 문제)
5. layout.rs: layout_shape_item에 TAC 그림 직접 렌더 분기 추가
   (텍스트 없는 빈 문단의 인라인 TAC 그림이 영영 미렌더되던 문제)
6. table_layout.rs: InFrontOfText/BehindText 표 push-down 미적용
   (절대 위치 오버레이 표가 본문 흐름 따라 밀리던 문제)

검증:
- cargo test --release: 1047+ passed, 0 failed
- exam_eng.hwp p2 좌측 하단 안내 박스 위치 정상화
- exam_eng.hwp p2 우측 Marathon 박스 내부 텍스트 정상화
- exam_eng.hwp p4 우측 Q27/Q28 City Pass / Snow Festival 박스 프레임 + 내용 정상
- 다단단 문서·TAC 표·중첩 표·Paper 기준 객체 회귀 없음
pi=189(p4 Q28 Lockwood Snow Festival)는 컨트롤 순서가
[표(InFrontOfText), 그림(TAC)]이라 PageItem 처리 순서대로 렌더하면
그림이 표 위를 덮어 박스 본문 텍스트가 보이지 않음.

수정: layout_shape_item에서 인라인 TAC 그림을 col_node에 push할 때,
같은 문단에 이미 렌더된 Table 노드가 있으면 그 앞에 insert하여
z-order(그림 → 표) 보존.

검증:
- cargo test --release: 1047+ passed, 0 failed
- exam_eng.hwp p4 Q28 박스 프레임 + 내용 (제목, When & Where,
  Special Activities, Transportation 등) 모두 정상 렌더
- p1, 2, 3, 5, 6, 7, 8 시각 회귀 없음
증상:
- exam_eng.hwp p4 우측 Q27/Q28 박스가 컬럼 좌측 끝에 붙어 있어
  PDF의 박스 들여쓰기(margin_left ≈ 4mm)와 불일치

원인:
- layout_shape_item의 TAC 그림 x 계산이 col_area.x 만 사용,
  paragraph margin_left/indent 무시

수정:
- ParaShape의 margin_left + (indent>0이면 +indent, 아니면 hanging이라 0)
  = effective_margin_left 를 col_area.x 에 더해 그림 x 결정
- Alignment 별 분기 (Left/Right/Center)도 동일 기준으로 보정

검증:
- PDF/SVG 동일 스케일 픽셀 측정: 박스 좌측 가장자리 x 차 1px 이내
  (148.5mm 폭 1100px crop에서 PDF=69, SVG=70)
- ① 글머리표 위치도 1px 이내 일치
- cargo test --release: 1047+ passed, 0 failed
증상:
- exam_eng.hwp 마지막 쪽(p8) 우하단 '* 확인 사항' 박스 미표시

원인:
- master_pages [2]가 ext_flags=0x0003(bit0=overlap, bit1=is_extension)
  인데, 파서가 is_extension을 휴리스틱(같은 apply_to 중복) 단독으로
  결정해 비트 정보를 놓침
- ext_flags=0x03 케이스(첫 등록 + 확장 표시)는 휴리스틱이 false 반환
- 결과: 확장 바탕쪽이 마지막 쪽 적용 대상에서 제외됨

수정 (src/parser/body_text.rs):
- is_extension = (ext_flags bit 1) || (휴리스틱 OR)

검증:
- exam_eng.hwp p8 우하단 '확인 사항' 박스 정상 출력
- cargo test --release: 1047+ passed, 0 failed
…_align 통합)

증상:
- exam_eng.hwp p4 Q27/Q28 박스의 셀 내부 텍스트(헤더 'Adenville City
  Pass Card', 본문)가 PDF 대비 ~1mm 위로 올라가 보이는 미세 오프셋

원인:
- HWP는 LineSeg.vertical_pos에 첫 줄의 절대 위치(셀 컨텐츠 상단부터)를
  기록하며 이는 vertical_align(Top/Center/Bottom) 결과를 이미 반영한 값
- 우리 layout_table_cells는 cell.vertical_align과 mechanical_offset
  ((inner_height - total_content_height)/2)으로 자체 계산해 적용
- 두 방식의 결과가 달라 PDF와 어긋남

수정 (src/renderer/layout/table_layout.rs::layout_table_cells):
- 첫 문단 line_segs[0].vertical_pos가 양수이면
  text_y_start = cell_y + pad_top + vpos 로 사용
- vpos가 0이거나 line_segs 없으면 기존 mechanical_offset 폴백 유지

검증:
- exam_eng.hwp p4 Q27/Q28 박스 내부 텍스트가 PDF와 거의 픽셀 단위로 정렬
  (오버레이 비교 시 헤더/본문 텍스트 중첩 → task_347_exam_eng_p4_overlay_after.png)
- cargo test --release: 1047+ passed, 0 failed
- p1~p8 시각 회귀 없음
…ing 우선순위 보정

증상:
- exam_eng.hwp p2 Q18 박스, p4 Q28 박스의 셀 내부 텍스트가 박스 좌측 가장자리에
  거의 붙음 (PDF는 ~3mm 좌측 여백 표시)

원인 (2건):
1. resolve_cell_padding이 "cell.padding 명시값(0 아님) 무조건 우선" 휴리스틱
   (Task edwardkim#279 호환)으로 작동. 일반 박스 셀의 default-ish 작은 cell.padding
   (예: pi=104 cell pad=141 HU=0.5mm)이 표 padding(850 HU=3mm)을 무시
2. shrink_cell_padding_for_overflow가 estimate_text_width의 자연 폭 추정
   (영어 본문 +5~15% 과대 추정)에 padding을 1px까지 축소

수정 (src/renderer/layout/table_layout.rs):
1. resolve_cell_padding: aim(apply_inner_margin) 플래그 기반 분기 복원.
   - aim=true: cell.padding 우선 (HWP 스펙)
   - aim=false: cell이 table보다 명백히 큰 비대칭 케이스만 cell 우선
     (KTX 목차 R=1417 같은 작성자 의도 보존, Task edwardkim#279 호환)
   - 그 외 aim=false는 table.padding 사용
2. shrink_cell_padding_for_overflow: 15% 초과만 축소 트리거
   (자연 폭 추정 오차 흡수)

검증:
- p2 Q18 'Dear Rosydale...' 박스 좌측 여백 ~3mm 정상 표시
- p4 Q28 'Luckwood Snow Festival' 박스 좌측 여백 정상 표시
- cargo test --release: 1047+ passed, 0 failed
- p1, 3, 5, 6, 7, 8 시각 회귀 없음
resolve_cell_padding 의 cell.padding/table.padding 우선순위 보정
(commit 72d8245) 부수효과로 셀 좌측 padding 이 ~0.88px(=1 HU) 만큼
변경되어 골든이 어긋남. 시각적 회귀 아님 — 의도된 padding 적용 결과.
resolve_cell_padding (그리기 경로) 의 prefer_cell_axis 규칙
(aim=false 일 때 cell > table 인 비대칭 축만 cell 우선) 을
height_measurer (행 높이 측정) 에도 동일 적용.

기존 height_measurer 는 'cell.padding != 0 이면 무조건 cell' 규칙
이라 layout 과 어긋났음. exam_eng.hwp p1 의 '1번부터 17번까지...' 박스
(table.padding=852, cell.padding=141, aim=false) 에서 측정은 141 로
작은 행을 만들고 그리기는 852 로 큰 padding 을 적용해 마지막 줄이
박스 밖으로 잘려 보이는 회귀가 발생.

검증: 1055+ 테스트 통과, p1 박스 텍스트 박스 안에 정상 표시.
@edwardkim

Copy link
Copy Markdown
Owner

@planet6897 님 — Task #347 통합 수정 작업 감사합니다.

메인테이너 검증

  • cargo build --release v0.7.6: 26.70s ✅
  • cargo test --lib: 1008 passed (1000 → +8 신규) ✅
  • cargo test --test svg_snapshot: 6/6 (form-002 포함) ✅
  • cargo test --test issue_301: z-table 가드 ✅
  • cargo clippy --lib -D warnings: clean ✅
  • cargo check --target wasm32: clean ✅
  • 7 핵심 샘플 + form-002 페이지 수 무변화 ✅
  • WASM Docker 빌드 + 작업지시자 시각 검증 통과 ✅

안내 사항

1. 골든 form-002/page-0.svg 변경

PR description 에 "골든 SVG 갱신 없음" 으로 적혀 있으나 실제로는 ±572 변경 발생. Stage 6 (셀 padding 정책) 의 자연스러운 부수효과로 form-002 좌표가 미세 시프트 (≈+0.88px) — 의도된 변경이지만 PR description 오류로 보입니다. 다음 PR 부터 description 정확성 점검 부탁드립니다.

2. 이슈 #345 (exam_eng 9 → 8 페이지 회귀) 미해결

본 PR 의 6 영역은 좌표 / Z-order / 셀 padding / vpos 영역으로 페이지 분할 알고리즘 변경 없음. exam_eng 페이지 수는 8 그대로. 따라서 이슈 #345 는 본 PR 머지 후에도 OPEN 유지하고 별도 작업으로 추적합니다.

이번 사이클에도 깊은 통합 분석 + 자체 보강 (Stage 1~6 + height_measurer 동기화 + form-002 골든 갱신) 감사합니다. admin merge 진행합니다 🙏

@edwardkim edwardkim merged commit 34e329e into edwardkim:devel Apr 26, 2026
6 checks passed
edwardkim added a commit that referenced this pull request Apr 26, 2026
@planet6897 의 6 영역 통합 수정. admin merge (commit 34e329e).

이슈 #347 close. 이슈 #345 (exam_eng 페이지 회귀) 는 본 PR 영역 밖
이라 OPEN 유지 별도 작업 필요.

Co-Authored-By: Jaeuk Ryu <planet6897@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@planet6897 planet6897 deleted the local/task347 branch April 30, 2026 00:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants