Skip to content

Task #990: 빈 문단 위 treat-as-char 글상자 advance 이중 가산 정정 (closes #990)#1003

Closed
planet6897 wants to merge 7 commits into
edwardkim:develfrom
planet6897:pr-task990
Closed

Task #990: 빈 문단 위 treat-as-char 글상자 advance 이중 가산 정정 (closes #990)#1003
planet6897 wants to merge 7 commits into
edwardkim:develfrom
planet6897:pr-task990

Conversation

@planet6897

Copy link
Copy Markdown
Contributor

개요

빈 문단(텍스트 없음) 위에 얹힌 treat_as_char 글상자(도형)가 세로로 연속
배치될 때, 박스 사이 세로 간격이 한컴 PDF 대비 정확히 2배로 벌어지는 버그를 정정한다.

Root cause — Task #974 회귀

bisect 결과 커밋 c3e32151("Fix textbox picture rendering", Task #974)가
layout_shape_item()Control::Shape 분기를 신규 추가하면서 발생.

지점 박스 advance
c3e32151~1 (Task #974 직전) 66.44px (정상)
c3e32151 이후 132.88px (2배)

빈 문단 호스트는 FullParagraph PageItem 의 layout_paragraph() 가 이미
LINE_SEG advance(lh+ls)를 마친 상태인데, Shape PageItem 분기가
result_y = shape_y + line_advance.max(shape_h) 로 또 한 번 advance → 이중 가산.

정정

layout_shape_item()!has_real_text 분기에서 해당 문단에
PageItem::FullParagraph 가 발행되었는지(has_full_para_item) 판별:

  • 있으면(빈 문단 호스트): 글상자를 호스트 문단 시작에 배치하고
    result_y 재진행을 생략 — 이중 가산 제거.
  • 없으면(선행 표 등에 이어 붙은 Shape, 예: hy-001 pi=27):
    Task [renderer] 글상자 안 그림 출력 누락 처리 #974 동작을 유지.

Task #974set_inline_shape_position 등록 의도는 보존.

검증

  • 회귀 진단: 비공개 문서(treat-as-char 글상자 3개)로 RED 재현 —
    박스 advance 132.88px → 66.44px. 해당 문서·임시 테스트는 비공개 자료라
    커밋하지 않음.
  • 전체 cargo test 1483 passed, 0 failed. clippy/fmt clean.
  • 광범위 SVG sweep(14 샘플): 회귀 0 — hy-001 Task [renderer] 글상자 안 그림 출력 누락 처리 #974 동작 보존 확인.
  • 커밋된 회귀 가드: issue_table_vpos_01_page5_cell_hit_test
    table-vpos-01.hwp 5쪽 pi=33(빈 문단 + treat-as-char 도형)이 본 정정과
    동일 코드 경로라, 이중 가산 재발 시 셀 hit-test 가 실패한다. pi=33 정정으로
    pi=34 표가 30.84px 상향 이동 — 기존 기댓값은 커밋 c2d2157d[renderer] 글상자 안 그림 출력 누락 처리 #974 버그
    레이아웃에 박제한 stale 값이므로 inner 11x3 좌표 8건을 정정 레이아웃에 맞춰 갱신.

변경 파일

🤖 Generated with Claude Code

planet6897 and others added 7 commits May 19, 2026 09:28
빈 문단 위 treat-as-char 글상자 advance 이중 가산 정정 계획.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
빈 문단 위 treat-as-char 글상자 advance 이중 가산 — Task edwardkim#974 커밋
c3e3215 회귀 확정 (bisect). 재현·RED 검증은 비공개 문서로 로컬 수행
(픽스처·테스트는 비커밋).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
layout_shape_item() 의 !has_real_text 분기에서 shape_y 를 호스트 문단
시작(para_start_y)으로 잡고, 선행 FullParagraph 가 이미 LINE_SEG advance
를 마친 경우 result_y 재진행을 생략한다. Task edwardkim#974 c3e3215 회귀 정정.
박스 advance 132.88px -> 66.44px (RED test GREEN).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
초기 fix가 hy-001 pi=27(선행 표+Shape)을 망가뜨림(표 가림). 해당
문단에 PageItem::FullParagraph 가 발행된 경우에만(빈 문단 호스트형)
shape_y=para_start + result_y 재진행 생략을 적용하고, FullParagraph
항목이 없으면(선행 표 등에 이어 붙은 Shape) Task edwardkim#974 동작을 유지한다.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
전체 cargo test 1477 통과, clippy/fmt clean, SVG sweep 회귀 0.
issue_table_vpos_01_page5_cell_hit_test 의 pi=34 inner 11x3 좌표 8건은
커밋 c2d2157edwardkim#974 이중 가산 버그 레이아웃에 박제한 stale 값 —
pi=34 가 30.84px 상향 이동한 정정 레이아웃에 맞춰 갱신. layout.rs
shape_y 식 rustfmt 정리.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
최종 결과보고서 작성. Docker WASM 재빌드(pkg/ 갱신).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
재현 픽스처(samples/issue-990-tac-box.hwpx)와 RED 테스트
(tests/issue_990.rs)는 비공개 문서 기반이라 작업지시자 지시로 git
에서 제거. 보고서의 산출물·검증 기재를 정정 — 커밋된 회귀 가드는
issue_table_vpos_01_page5_cell_hit_test (동일 코드 경로 pi=33).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@edwardkim edwardkim self-requested a review May 19, 2026 13:28
@edwardkim edwardkim added the enhancement New feature or request label May 19, 2026
@edwardkim edwardkim added this to the v1.0.0 milestone May 19, 2026
edwardkim added a commit that referenced this pull request May 20, 2026
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
edwardkim added a commit that referenced this pull request May 20, 2026
…nce 이중 가산 정정

@planet6897 — Task #974(c3e3215, PR #1013 머지) 회귀 bisect 정확
진단 + has_full_para_item case-specific 가드. layout_shape_item()의
!has_real_text 분기에서 FullParagraph 항목 유무로 분기:
- 있으면(빈 문단 호스트): result_y 재진행 생략 → 이중 가산(132.88→66.44px) 차단
- 없으면(선행 표 이어붙은 Shape, hy-001 pi=27): Task #974 동작 유지

PR #1005 격차 D revert(4e3ad58)의 scope 외("variant flag thread 후
variant-only 분기")를 variant 무관 일반 가드로 정밀 해결 — 두 케이스
양립. feedback_pr_supersede_chain + feedback_hancom_compat_specific_
over_general 권위 사례.

옵션 A: 3 본질 커밋 cherry-pick (d7663dd Stage 2 layout.rs PR #1005
영역 --theirs 충돌 해소, a4a3647 Stage 2 v2 has_full_para_item 정밀화
자동 보완, 97c4994 Stage 3 회귀 테스트 좌표 8건 정정) — 작성자
@planet6897 보존. 검증: cargo test 1307(lib) + 전체 통합 + issue_table_
vpos_01_page5_cell_hit_test 13 passed + clippy -D + fmt 0 + WASM 4.83MB
(feedback_push_full_test_required 정합). sweep 10 fixture: hy-001
HWPX/HWP5 diff=0(Task #974 보존), table-vpos-01 1 diff(의도된 pi=34
30.84px 상향), sample16-hwp5/hwp3 외곽선만(텍스트 무변동), aift 2 diff
(의도된 빈 문단 글상자 정정 효과), 일반 fixture diff=0. 작업지시자
비공개 샘플 PR로 시각 판정 생략 수용 결정.

PR #1004(Task #990 + #991 통합) 가 본 PR 완전 포함 + Task #991 추가 —
본 PR 머지 후 #1004는 #991 부분만 재제출 안내 (feedback_small_batch_
release_strategy 정합).
@edwardkim

Copy link
Copy Markdown
Owner

옵션 A로 devel에 반영했습니다 (본질 3 커밋 cherry-pick: d7663dd Stage 2 + a4a3647 Stage 2 v2 + 97c4994 Stage 3, 작성자 @planet6897 메타데이터 보존).

검증:

bisect로 Task #974 c3e3215 회귀 정확 진단 + has_full_para_item case-specific 가드로 PR #1005 격차 D scope 외 후속을 variant 무관 일반 가드로 정밀 해결 — 두 케이스(빈 문단 호스트 vs 선행 표 이어붙은 Shape) 양립, Task #974 의도 보존. PR 본문이 stale 값 정정 명시(c2d2157d 박제 좌표 8건)도 정확합니다.

layout.rs PR #1005 영역 충돌은 Stage 2 v1 --theirs 적용 후 Stage 2 v2가 자동 정밀화로 깔끔히 해소되었습니다. 좋은 PR 감사합니다.

후속 안내: PR #1004 (Task #990 + #991 통합)가 본 PR을 완전 포함하므로, #1004는 Task #991 부분만 재제출 부탁드립니다 (작은 단위 분리 원칙, feedback_small_batch_release_strategy). #1024도 함께 검토 대기 중입니다.

@edwardkim edwardkim closed this May 20, 2026
edwardkim added a commit that referenced this pull request May 20, 2026
@planet6897 — Task #990 영역은 PR #1003 (c2024ec) 머지로 이미 해소,
본 머지로 Task #991 부분 (분할 표 렌더링 정합) 적용:

- 분할 셀 줄 범위 — 끝 페이지 패스(prefix 패스) 유도로 중복·누락 해소 (table_layout.rs, 99f2695)
- 1행 글자처럼취급 표 분할 금지 — 통째 다음 페이지/단 이동 (typeset.rs, 35afc77)
- 쪽 분할 표 직후 문단 vpos 팬텀 해소 — 직전 항목 PartialTable 시 vpos 보정 skip (layout.rs, 0f18849)
- table_layout.rs rustfmt 정리 (0d9a7c1)

옵션 A: cherry-pick 4 (작성자 @planet6897 보존). task_m100_991 문서 AA
충돌 5건 — @jangster77 이슈 #991 (composer marker, CLOSED) 가 같은
task 번호 사용 → --ours 로 jangster77 머지본 보존 + planet6897 v2/v3/
v4/v5 접미사 신규 문서 추가. 검증: cargo test 1307 (lib) + 전체 통합 +
clippy -D + fmt 0 + WASM 4.83MB (feedback_push_full_test_required 정합).
sweep 10 fixture: aift p.14/45/56/69 4 diff (분할 표 보유 fixture
case-specific 동작), 나머지 9 fixture diff=0 — Task #991 변경의 좁은
영역 입증. 작업지시자 시각 판정 통과.

PR #1024 (closes #1022, 분할 표 RowCut 이산 모델, +5912/-1742) 가 본
영역 발전형 — 본 PR 의 휴리스틱 정정을 단일 권위 RowCut 모델로 일반화
+ LAYOUT_OVERFLOW 42→12. #1024 처리 시 본 PR 영역 충돌 가능 (rebase
권고). feedback_pr_supersede_chain + feedback_small_batch_release_
strategy 정합.

**task 번호 충돌 메모**: jangster77/#991 composer + planet6897/분할 표
같은 task 번호 다른 본질 — 향후 가드 권고.
edwardkim added a commit that referenced this pull request May 20, 2026
… + LAYOUT_OVERFLOW 42→12

@planet6897 분할 표 시리즈 마무리 (#1003 + #1004 머지 후 발전형, devel 최신
기준 재구성으로 MERGEABLE). RowCut 이산 모델(cell_units + advance_row_cut
단일 권위 함수)로 페이지네이터·렌더러 측정 통합 — PR #1004 휴리스틱
정정 일반화. closes #1022 — LAYOUT_OVERFLOW 42→12 (71% 감소) 정량 측정.

v2 trailing-ls 조건부 복원 (issue_598 회귀 자정) — lazy_base_corrected >= 0
조건부 가드로 vpos≠0 시작 컬럼 보정 + IR 정확 추적 케이스 비보정.
복학원서 본문 시작 band 196→214=PDF 일치 PR 본문 명시 (본 환경 미발동,
후속 관찰).

옵션 A: 본질 squash commit bc1cd4d cherry-pick (작성자 Jaeook Ryu 보존,
충돌 없음). 검증: cargo test 1308(lib) + 전체 통합 + pagination 15 +
wasm_api 160 + clippy -D 전체(--lib 미한정 CI 패턴) + fmt --all --check
(feedback_push_full_test_required + CI 패턴 정합). sweep 10 fixture:
hy-001/table-vpos-01/복학원서 diff=0, sample16-hwp5 13/64 + sample16-hwp3
2/64 + aift 27/74 + exam_kor 16/20 + biz_plan 3/6 광범위 변동 (분할 표
영역 의도된 효과). WASM 4.84MB.

작업지시자 결정 "그대로 A로" — 광범위 변동 시각 판정 생략 머지. 정량
측정(LAYOUT_OVERFLOW 71% 감소) + 회귀 가드(issue_598/svg_snapshot) +
CI 검증 항목 통과로 게이트 대체. golden 갱신: issue-617 + form-002
(PR 본문 명시 issue-677은 PR 적용 후 출력=현재 golden binary identical
로 갱신 불필요).

feedback_pr_supersede_chain 권위 사례 — 작은 단위(#1003) + 부분(#1004) +
발전형(#1024) 순차 적층 → 단일 권위 모델 일반화. feedback_image_renderer_
paths_separate 본질 정합 (PR #1018 image_resolver 패턴).
edwardkim pushed a commit that referenced this pull request May 20, 2026
… 4 hunk 복원

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

Bisect 단언 (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): 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 #1011)
- 변경 D: `(bx, mut by, bw, mut bh)` — footer clip 의 by/bh 수정 위함

Parser 측 PR #1011 변경 (basis=PaperBased 주입) 은 PR #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 #1029

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
edwardkim pushed a commit that referenced this pull request May 20, 2026
Stage 1 (944ddff) + Stage 2 (9bd851f) 종결:
- Bisect 단언 + Root cause 정리 (PR #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 #1029 (PR merge 시점에 자동 close 예정)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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
PR #1032 (closes #1027) 머지 후속 처리:
- mydocs/pr/archives/pr_1032_review.md (검토 문서 archives 이동)
- mydocs/orders/20260520.md (PR #1032 entry 추가)
- rhwp-studio/public/{rhwp.d.ts,rhwp.js,rhwp_bg.wasm} (WASM 4.86MB 동기화)

@planet6897 분할 표·측정 시리즈 마무리 (#1003+#1004+#1024+#1032).
HeightCursor 공유 측정 엔진 + parity 7개로 페이지네이터↔렌더러 정합.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.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
PR #1033 (closes #1025) 머지 후속 처리:
- mydocs/pr/archives/pr_1033_review.md (검토 문서 archives 이동)
- mydocs/orders/20260520.md (PR #1033 entry 추가)
- rhwp-studio/public/{rhwp.d.ts,rhwp.js,rhwp_bg.wasm} (WASM 4.89MB 동기화)

@planet6897 분할 표·측정 시리즈 마무리 5번째 마지막 마디
(#1003+#1004+#1024+#1032+#1033).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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