Skip to content

Task #1029: HWP3 외곽선 paper-edge 정합 회귀 정정 (closes #1029)#1031

Closed
jangster77 wants to merge 4 commits into
edwardkim:develfrom
jangster77:local/task1029
Closed

Task #1029: HWP3 외곽선 paper-edge 정합 회귀 정정 (closes #1029)#1031
jangster77 wants to merge 4 commits into
edwardkim:develfrom
jangster77:local/task1029

Conversation

@jangster77

Copy link
Copy Markdown
Collaborator

Summary

PR #1003 (closes #990) 의 cherry-pick --theirs 자동 충돌 해소가 PR #1011 (closes #1006) 의 PageBorderBasis 통합 contract 를 PR #987 시절 attr & 0x01 비트 로직으로 무심코 revert 했던 시각 회귀 정정. HWP3 native (samples/hwp3-sample16.hwp) cover 페이지 외곽선이 body-edge 로 좁아져 logo 와 인접한 시각 회귀를 paper-edge 정합으로 복원.

src/renderer/layout.rs 단일 파일 4 hunk 복원, parser/model 무수정.

Bisect 단언

Merge PR border_top y 상태
850cfb5 PR #1011 17.88 ✓ paper-edge (기준선)
71aedda PR #1015 17.88 ✓ 무관
84246b2 PR #1018 17.88 ✓ 무관
27c05d5 PR #1020 17.88 ✓ 무관
b5d3834 PR #1021 17.88 ✓ 무관
c2024ec PR #1003 (Task #990) 55.64 ❌ 회귀 도입
77a2547 PR #1004 55.64 (회귀 유지)
65c8e69 devel HEAD 55.64 (회귀 유지)

Root cause

PR #1003 merge commit (c2024ec) 본문에 명시:

"옵션 A: 3 본질 커밋 cherry-pick (d7663dd Stage 2 layout.rs PR #1005 영역 --theirs 충돌 해소 ...)"

d7663dd4 cherry-pick 시 PR #1011 영역과 충돌 → --theirs 자동 해소로 PR #1011basis 필드 기반 로직이 PR #987 시절 attr & 0x01 비트 로직으로 revert. merge 본문에 "sample16-hwp5/hwp3 외곽선만 (텍스트 무변동)" 으로 sweep diff 가 기록되었으나 비공개 샘플 시각 판정 생략 수용으로 시각 회귀가 인지되지 못함.

포맷별 attr 단언

포맷 attr basis paper_based (회귀 로직) 외곽선
HWP3 native 0x00000000 PaperBased false (revert) body-edge (회귀)
HWP5 변환본 0x00000001 PaperBased true paper-edge (OK)
HWPX 변환본 0x00000041 PaperBased true paper-edge (OK)

Parser 측 PR #1011basis=PaperBased 주입은 PR #1003 cherry-pick 시 보존됨 — fix 는 renderer (layout.rs) 한정.

핵심 변경 (4 hunk in src/renderer/layout.rs)

Hunk 위치 변경
A page_number_baseline_y() (line ~947) (pbf.attr & 0x01) != 0matches!(pbf.basis, PageBorderBasis::PaperBased)
B build_page_borders() (line ~976) A 와 동일 + 주석 history 정정 + 디버그 로그 포맷 (bit1/bit2/footer_inside 추가)
C line ~1015 footer_inside clip 블록 복원 — 페이지 번호 외곽선 바깥 위치 정합 (PR #1011)
D line ~1001 (bx, by, bw, bh)(bx, mut by, bw, mut bh) — footer clip 의 by/bh 수정

변경량: 1 file changed, 31 insertions(+), 12 deletions(-)

검증

재발 방지 (별도 troubleshooting 권고)

  • cherry-pick --theirs/--ours 자동 해소 후 영향 hunk line-by-line 검토
  • 시각 회귀 sweep 을 비공개 샘플 외 공개 fixture (예: hwp3-sample16) 로 사전 단언 의무화
  • PR merge 직전에 RHWP_DEBUG_PAGE_BORDER=1 같은 진단 hook 으로 외곽선 좌표 baseline diff 자동 단언

Test plan

Closes #1029

🤖 Generated with Claude Code

jangster77 and others added 4 commits May 20, 2026 16:30
…kim#1011 layout.rs 4 hunk 복원

PR edwardkim#1003 (closes edwardkim#990) 의 cherry-pick `--theirs` 충돌 해소가 PR edwardkim#1011
(closes edwardkim#1006) 의 PageBorderBasis 통합 contract 를 PR edwardkim#987 시절 attr 비트
해석으로 무심코 revert. HWP3 native (attr=0) 만 paper_based=false 로 판정되어
외곽선이 body-edge 로 좁아진 시각 회귀 발생.

Bisect 단언 (border_top y):
- 850cfb5 (PR edwardkim#1011): 17.88 (paper-edge, 기준선)
- 71aedda (PR edwardkim#1015): 17.88
- 84246b2 (PR edwardkim#1018): 17.88
- 27c05d5 (PR edwardkim#1020): 17.88
- b5d3834 (PR edwardkim#1021): 17.88
- c2024ec (PR edwardkim#1003): 55.64 ← 회귀 도입
- 65c8e69 (devel HEAD): 55.64

Fix: src/renderer/layout.rs 4 hunk 복원
- 변경 A: page_number_baseline_y() — (attr & 0x01) → matches!(basis, PaperBased)
- 변경 B: build_page_borders() — 동일 + 주석 + 디버그 로그 (bit1/bit2/footer_inside)
- 변경 C: footer_inside clip 복원 — 페이지 번호 외곽선 바깥 위치 (PR edwardkim#1011)
- 변경 D: `(bx, mut by, bw, mut bh)` — footer clip 의 by/bh 수정 위함

Parser 측 PR edwardkim#1011 변경 (basis=PaperBased 주입) 은 PR edwardkim#1003 cherry-pick 시
보존됨. fix 는 renderer (layout.rs) 한정 단일 파일.

검증 (Stage 2 별도 보고):
- 3 포맷 paper_based=true 단언 (RHWP_DEBUG_PAGE_BORDER)
- HWP3 sample16 border_top y=17.88 복원
- HWP5/HWPX 변환본 무변동 (17.88 유지)
- cargo test --release --lib 1307 passed
- cargo clippy --release --lib -- -D warnings clean
- cargo fmt --check clean

Refs edwardkim#1029

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…시각 검증 OK

작업지시자 시각 검증 통과 (HWP3 외곽선 paper-edge 복원 한컴 viewer 정합).

전체 sweep:
- cargo build --release: warning 0
- cargo clippy --release --lib -- -D warnings: clean
- cargo fmt --check: clean
- cargo test --release --lib: 1307 passed; 0 failed
- cargo test --release --tests: 68 passed (전체 integration); 0 failed
- issue_table_vpos_01_page5_cell_hit_test: 13 passed (Task edwardkim#990 보존)

3 포맷 외곽선 단언:
- HWP3 native:  attr=0x00 basis=PaperBased paper_based=true border_top=17.88
- HWP5 변환본:  attr=0x01 basis=PaperBased paper_based=true border_top=17.88
- HWPX 변환본:  attr=0x41 basis=PaperBased paper_based=true border_top=17.88

페이지 수 sweep 12 fixture: 모두 정상 (hwp3-sample10 763, 11 151, 13 3, 14 11,
16 64, 16-hwp5 64/71, exam_kor 20, exam_eng 8, exam_math 20, aift 74, biz_plan 6).

성공 기준 C1~C6 자동 단언 완료. C7 (시각 검증) 작업지시자 통과.

Refs edwardkim#1029

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Stage 1 (944ddff) + Stage 2 (9bd851f) 종결:
- Bisect 단언 + Root cause 정리 (PR edwardkim#1003 cherry-pick --theirs 사고)
- Fix 4 hunk 복원 결과 + 검증 sweep 통과
- 성공 기준 C1~C7 전체 충족 (작업지시자 시각 판정 포함)

재발 방지 권고:
- --theirs/--ours 자동 해소 후 영향 hunk line-by-line 검토
- 공개 fixture 시각 회귀 sweep 의무화
- 외곽선 좌표 baseline diff 자동 단언 진단 hook

orders/20260520.md 에 본 task entry 추가.

closes edwardkim#1029 (PR merge 시점에 자동 close 예정)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@edwardkim edwardkim self-requested a review May 20, 2026 08:34
@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

Copy link
Copy Markdown
Owner

검토 완료 — merge 수용. devel 에 반영합니다.

검증 결과

  • CI 전체 pass (Build & Test / Analyze rust·js·py / Canvas visual diff / CodeQL)
  • 본 환경 cargo test --release --lib: 1308 passed, 0 failed
  • cargo fmt --check 통과
  • WASM Docker 빌드 성공 (release + wasm-opt, 4.6M, 1m 31s)
  • 본 환경 git 검증: 본 PR 적용 결과의 build_page_borders 영역이 PR Task #1006: 쪽 테두리 포맷별 분리 + cover logo overlap 해소 #1011 baseline (850cfb54) 와 byte-identical 복원 — bisect 단언 사실 확인
  • HWP3 sample16 cover paper-edge 시각 정합 작업지시자 직접 확인

처리

평가

attr & 0x01 측정 의존 분기 → matches!(basis, PaperBased) 구조 가드로 복원. parser 가 포맷별 비일관성을 basis 필드로 normalize → renderer 는 구조 분기로 단순화. 포맷 3축 (HWP3/HWP5/HWPX) 통합 contract 의 권위 사례입니다.

bisect 단언 (850cfb54 ~ c2024ec9 사이 border_top y 가 17.88 → 55.64 로 튄 시점 정확 특정) + HWP5/HWPX 가 attr bit0=1 로 우연히 회귀가 가려진 점을 분리해서 짚어주신 분석이 매우 명료했습니다. PR 본문 §재발 방지 권고 3건 (cherry-pick --theirs 자동 해소 주의 / 공개 fixture 사전 단언 / RHWP_DEBUG_PAGE_BORDER 진단 hook) 도 합리적이라 별도 troubleshooting / 메모리 룰 정리 task 후보로 보존합니다.

기여 감사합니다.

@edwardkim

Copy link
Copy Markdown
Owner

devel 반영 완료 (cherry-pick). PR close 합니다.

@edwardkim edwardkim closed this May 20, 2026
edwardkim pushed a commit that referenced this pull request May 20, 2026
HWP3 외곽선 paper-edge 정합 회귀 정정 (PR #1003 cherry-pick --theirs
사고 복원). CI 전부 pass + 본 환경 git 검증으로 PR #1011 baseline
(850cfb5) build_page_borders 영역과 byte-identical 복원 확인 +
작업지시자 시각 판정 사실 확인 → merge 수용.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
edwardkim pushed a commit that referenced this pull request May 20, 2026
PR #1003 cherry-pick `--theirs` 자동 충돌 해소가 PR #1011 의
PageBorderBasis 통합 contract 를 PR #987 시절 attr & 0x01 비트
로직으로 revert 한 사고 — HWP3 native (attr=0) 만 회귀 노출.
layout.rs 4 hunk 복원으로 PR #1011 baseline (850cfb5) 정합.

본 환경 git 검증: build_page_borders 영역 byte-identical 복원.
작업지시자 시각 판정 통과 (HWP3 sample16 cover paper-edge 정합).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
edwardkim added a commit that referenced this pull request May 20, 2026
orders/20260520.md 충돌 해소 — PR #1031 entry (origin/devel 의 PR 시리즈
와 연속) + Task #852 entry (메인테이너 task) 두 항목 모두 보존.

origin/devel 의 변경 (PR #1031 + Task #1029): src/renderer/layout.rs +
mydocs/{plans,pr/archives,report,working}/task_m100_1029_*.md +
mydocs/pr/archives/pr_1031_*.md.

본 local/devel 의 변경 (Task #852): src/parser/hwpx/* + src/serializer/* +
tests/issue_852_*.rs + mydocs/{plans,report,working}/task_m100_852_*.md.

두 작업 영역 무충돌 (renderer/layout vs parser/serializer), orders 만
공유 → 양립 통합. 회귀 가드 issue_852 5/5 통과 + fmt clean 사후 검증.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
edwardkim added a commit that referenced this pull request May 20, 2026
@planet6897 22번째 PR (분할 표·측정 시리즈 마무리) — `HeightCursor`
공유 측정 엔진으로 페이지네이터(`typeset.rs`)와 렌더러(`layout.rs
build_single_column`)의 inter-item VPOS_CORR 측정 공간 일치.

본질:
- 신규 `src/renderer/height_cursor.rs` (+333) — VPOS_CORR 상태머신
  캡슐화 (page/lazy base + prev + partial_table + overlay bypass +
  ≤8px backward clamp + stale TopAndBottom guard) + parity 단위
  테스트 7개.
- `src/renderer/layout.rs` (+96/-233) — 230줄 inline 로직 →
  `HeightCursor::vpos_adjust` 위임 + `vpos_corrected_end_y()` /
  `para_has_overlay_shape()` 순수 함수 추출 (Stage A/B/C 무동작).
- `src/renderer/typeset.rs` (+119/-2):
  - Stage D: fit 직전 `vpos_snap_current_height` 호출 → 누적 drift
    제거 (단단 한정, col_count!=1 가드).
  - Stage E1: treat_as_char 인라인 표 advance 정합 (host LINE_SEG
    fmt.total_height, +16.9px).
  - Stage E2: atomic top-fit 60px 스필에서 TopAndBottom Shape 제외
    (한컴이 본문 항목처럼 다음 페이지로 넘김).

검증 (본 환경):
- cargo test --release --lib **1317 passed** (+8 parity)
- cargo test --release --tests 모든 통합 passed (issue_852 5/5 포함)
- cargo fmt --all --check clean
- cargo clippy 본 PR 변경 0 warnings
- sweep 7 fixtures: hwp3-sample16-hwp5 40 diff (의도된 측정 정합,
  Stage E1 효과, 페이지 수 64→64 불변) / 다른 6 fixtures diff=0
- WASM Docker 빌드 4.86MB + rhwp-studio 동기화
- 작업지시자 시각 판정 통과

자연 cherry-pick 영역:
- PR base = 7ec2e25 (PR #1031 이전), origin/devel = d359c30
- cherry-pick 자연 통합 — PR #1031 (build_page_borders 4 hunk)
  영역 보존 + 본 PR (build_single_column 추출) 영역 양립
- HWP3 외곽선 paper-edge 정합 (PR #1031) 회귀 부재 확인

검증 권위 PR 본문 명시 (AI 184p 비공개 fixture, 본 환경 미접근):
- 노트 "추진일정은" 9쪽→8쪽 한컴 2022 PDF 정합
- 글상자 pi=142 10쪽 정합
- LAYOUT_OVERFLOW 27→18

다단 (col_count>1) Stage E3 비범위 — #412 per-column base 선행 필요
(컨트리뷰터 명시 후속).

closes #1027

Co-Authored-By: Jaeook Ryu <planet6897@users.noreply.github.com>
edwardkim added a commit that referenced this pull request May 20, 2026
@planet6897 23번째 PR (분할 표·측정 시리즈 5번째 마지막 마디:
#1003#1004#1024#1032#1033). page-larger 단일 표 셀 (PMR-007
세부내용 셀 25문단 ≈ 1024px) 이 rowspan 라벨 셀 (rs=2) 이 걸친 행에
있어 `advance_row_cut` 의 row_span==1 셀만 다루는 #993 컷 모델에서
원자 처리되어 본문 143px 초과·용지 밖 잘림. row-block 컷으로 일반화.

본질:
- src/renderer/layout/table_layout.rs (+170): `advance_row_block_cut`
  신규 — rowspan 블록 [b_start, b_end) 셀을 (row,col) 순서로 순회,
  거대 row_span==1 셀 줄 단위 분할, rs>1 라벨 셀 첫 조각 전량 소비
  + 연속 조각 공란. + `row_block_cells` / `row_block_content_height`
  헬퍼 (페이지네이터·렌더러 단일 권위). + parity 단위 테스트 2건
  (단일 비-rowspan 행 = advance_row_cut 동등 + rowspan 거대 셀 분할).
- src/renderer/pagination.rs (+6): PageItem::PartialTable.is_block_split
  플래그 추가 — page-larger 분할만 새 모드, 기존 분할 (form-002 등)
  은 false 유지 (backward-compatible).
- src/renderer/layout/table_partial.rs (+170/-29): is_block_split=true
  렌더 — rowspan 행 포함, rowspan_block_range/block_cut_index 로
  블록-셀 인덱싱, rs>1 라벨 셀 연속 공란.
- src/renderer/typeset.rs (+83/-6): mid-page 분할 게이트 (block_h >
  base_available 일 때만 진짜 page-larger 활성, 아니면 deferred).
  연속분 행-스킵 가드 블록 컷에서 스킵 (컷 보존).
- src/renderer/{layout.rs, page_number.rs, pagination/engine.rs,
  document_core/queries/rendering.rs} 최소 변경.

검증 (본 환경):
- cargo test --release --lib **1319 passed** (+2 block_cut tests)
- cargo test --release --tests 모든 통합 passed (issue_852 5/5 +
  svg_snapshot 8/8 + table-vpos-01 13/13 + issue_938 3/3 등)
- cargo fmt --all --check clean
- cargo clippy 통과
- sweep 7 fixtures: **diff=0 전체** — page-larger 케이스가 공개
  fixture 에 없음. PR #1031/#1032 회귀 부재 + 일반 분할 form/일반
  fixture 무변경 입증
- WASM Docker 빌드 4.89MB (+30KB) + rhwp-studio 동기화
- 작업지시자 시각 판정 통과

cherry-pick 자연 통합:
- PR base = a52859d (PR #1032 이전), origin/devel = 5263f53
- cherry-pick auto-merge 로 PR #1031 (build_page_borders) + PR #1032
  (HeightCursor / vpos_snap_current_height 13건) 영역 자동 보존
- PR #1033 변경 (advance_row_block_cut + is_block_split) 통합

검증 권위 PR 본문 명시 (AI 184p 비공개 RFP, 본 환경 미접근):
- LAYOUT_OVERFLOW 27→25
- pi=272 세부 셀 (854.9px) 해소
- pi=324 PMR-007 (143.9px) 2-프래그먼트 분할 한컴 2022 PDF 정합

@planet6897 분할 표·측정 시리즈 마무리 (#1003+#1004+#1024+#1032+#1033).

closes #1025

Co-Authored-By: Jaeook Ryu <planet6897@users.noreply.github.com>
edwardkim added a commit that referenced this pull request May 20, 2026
…격차 종합 정정

@jangster77 25+번째 PR (paper_based outline 시리즈 #1011/#1015/#1031
마무리 후 HWP3 sample16 정합 시리즈 진입). samples/hwp3-sample16.hwp
한컴 한글 정답지 비교 4 격차 종합 정정. src/parser/hwp3/ 격리 엄격
(HWP5/HWPX/renderer 무수정).

본문 가설 정반대 발견: 원본 이슈 가설(HWP5 변환본 gradient strip) 이
한컴 한글 정답지 시각 검증 결과 정반대로 판명 (gradient 가 정답, HWP3
회귀). issue body + 수행/구현계획서 v2 재작성 — feedback_visual_judgment_authority
모범 사례.

본질 (2 코드 + 1 test + 9 문서):
- 격차 A — HWP3 Shape gradient IR 매핑 (drawing.rs:792~830):
  HWP3 raw Hwp3DrawingObjectGradientAttr 가 이미 파싱되었으나 Fill IR
  구축에서 fill_type=Solid 하드코딩으로 데이터 무시. HWP5 doc_info.rs:404
  와 동일 contract 로 GradientFill 주입.
- 격차 B — Shape border LineType 2~7 → Solid normalize (drawing.rs:758~785):
  HWP3 raw style=0x0002 (LineType=2 Dash) 가 점선 렌더되나 한컴은 실선.
  sample16 한정 분포 — narrow fix 회귀 risk 0.
- 격차 C — HWP3 heading decoration 휴리스틱 strip (mod.rs:2870~2960):
  "═════■ 1.추진목적 ■═════" 형태 decoration 을 fixup_hwp3_heading_decoration
  + strip_heading_decoration 패턴 detection 으로 strip. 한컴 변환기 mimic.
- 격차 D-1 — CharShape dedupe (mod.rs:1869~1900):
  같은 start_pos 에 rep + inline shape change 양쪽 push 시 마지막
  (inline override) 유지.
- 격차 D-2 — 폰트명 매핑 (mod.rs:2570~2585, 2908~2924):
  "신명조"→"HY신명조" 등 5 legacy 매핑 + font.alt_name 원본 보존.
  HWP3 SVG 좌표가 HWP5 변환본과 byte-for-byte 일치.

검증 (본 환경):
- cargo test --release --lib 1319 passed
- cargo test --release --tests 모든 통합 passed
- cargo test --release --test issue_1008_gradient **4/4 passed**:
  hwp3_sample16_business_box_has_gradient, _border_solid,
  _heading_decoration_stripped, _font_name_mapped_to_hwp5_convention
- cargo fmt --all --check clean
- sweep 9 fixtures: hwp3-sample16 **44 diff** (의도된 본 PR 본질, 페이지
  수 64→64 불변) / 다른 8 fixtures (HWP5/HWPX 변환본 + sample10/11/sample
  + exam_kor/aift/biz_plan) **diff=0** — HWP3 격리 검증, PR #1031/#1032/
  #1033 회귀 부재
- SVG 본질 검증: cover <radialGradient id="grad1" #c8ccf8→#ffffff> 추가
  + 폰트 "신명조"→"HY신명조" 매핑
- WASM Docker 빌드 4.89MB + rhwp-studio 동기화
- 작업지시자 시각 판정 통과

squash 적용:
- PR base = 5263f53 (PR #1032 후 docs commit) — PR #1033 (01a8c75)
  미흡수
- cherry-pick 직접 머지 대신 본질 파일만 origin/devel 위에 squash
  적용 (src/parser/hwp3/{drawing.rs, mod.rs} + tests/issue_1008_gradient.rs
  + 문서 8 파일, 총 11 파일)
- 결과: PR #1033 영역 (src/renderer/*, advance_row_block_cut, is_block_split)
  자동 보존 + 본 PR 본질 적용

한계 (PR 본문 명시):
- 휴리스틱 (격차 C): HWP3 spec 미참조 패턴 detection — 의도된
  "═══...■...■═══" typography 회귀 risk. sweep diff=0 으로 1차 입증
- 폰트 매핑 5 legacy 한정: 다른 명칭 발견 시 확장 필요
- 공백 cosmetic 비범위: rhwp "1.추진목적" vs 한컴 "1. 추진목적" period
  뒤 공백 — HWP3 raw 부재, 한컴 자동 삽입

closes #1008

Co-Authored-By: Taesup Jang <tsjang@gmail.com>
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