Skip to content

Task #713: 분할 표 orphan sliver(<25px) 행 단위 push (closes #713)#715

Closed
planet6897 wants to merge 5 commits into
edwardkim:develfrom
planet6897:pr-task713
Closed

Task #713: 분할 표 orphan sliver(<25px) 행 단위 push (closes #713)#715
planet6897 wants to merge 5 commits into
edwardkim:develfrom
planet6897:pr-task713

Conversation

@planet6897

Copy link
Copy Markdown
Contributor

Summary

  • samples/2022년 국립국어원 업무계획.hwp 12x5 일정 표 row 8 (한국어교육 내실화 섹션) 이 페이지 경계에서 17.6 px sliver 분할되던 결함 정정 (#713)
  • Root cause: PartialTable.split_end_content_limit = avail_content_for_r (현 페이지의 행 r top portion) 가 한 줄 정도(17.6 px) 로 너무 작은 orphan sliver 인데도 분할 적용. 한컴은 페이지 끝의 작은 sliver 를 두지 않고 행 전체를 다음 페이지로 push
  • 정정 (src/renderer/typeset.rs:1892-1905): avail_content_for_r >= MIN_TOP_KEEP_PX (25.0) 가드 추가
  • 순수 코드 변경 5 라인

임계값 25 px 결정 근거

케이스 avail_content_for_r 가드 적용 후
본 결함 (row 8 sliver) 17.6 px < 25 → 차단 ✓
synam-001 p23 (정합) 27.3 px ≥ 25 → 변경 없음 ✓
기타 정합 분할 93/437/510 px ≥ 25 → 변경 없음 ✓

Test plan

  • cargo build
  • cargo test --release — 1250 passed, 0 failed (회귀 0)
  • cargo test --test issue_713 — TDD RED→GREEN (row 8 단일 페이지, clip=0)
  • 181 샘플 페이지 수 횡단 비교 — diff 0
  • PDF 권위 (한글 2022 page 32 첫 줄 "한국어교육 내실화") 정합 확인

활성 경로 메모

src/document_core/queries/rendering.rs:1041-1042 에서 RHWP_USE_PAGINATOR=1 미설정 시 typeset.rs::typeset_section 이 활성, pagination/engine.rs::paginate_with_measured_opts 는 fallback. 본 정정은 활성 경로(typeset.rs) 에만 적용.

관련 자료

  • 수행 계획서: mydocs/plans/task_m100_713.md
  • 구현 계획서: mydocs/plans/task_m100_713_impl.md
  • Stage 1-5 보고서: mydocs/working/task_m100_713_stage{1..4}.md
  • 최종 보고서: mydocs/report/task_m100_713_report.md

🤖 Generated with Claude Code

@planet6897

Copy link
Copy Markdown
Contributor Author

연관 PR (samples/2022년 국립국어원 업무계획.hwp)

본 PR 은 samples/2022년 국립국어원 업무계획.hwp 의 페이지 분할 결함 정정 시리즈 중 세 번째 (최종).

순서 PR Issue 본질 결함 위치
1 #644 #643 페이지 분할 드리프트 5축 정합 6 페이지 마지막 줄 (40→35 페이지로 정정)
2 #714 #712 u32 음수 vert_offset 게이트 31 페이지 상단 12x5 표 침범
3 #715 (본 PR) #713 인트라-로우 분할 orphan(<25px) 가드 31 페이지 하단 row 8 sliver 분할

권장 merge 순서: #644#714#715. 각 PR 은 베이스가 stream/devel 이며 상호 conflict 0 (merge-tree 점검 완료).

통합 검증: stream/devel + 3 PR 통합 빌드에서 cargo test --release 1252 passed, 0 failed.

planet6897 and others added 5 commits May 9, 2026 08:58
Issue edwardkim#713 — RowBreak 표 인트라-로우 분할 결함 정정 계획.

본질: src/renderer/typeset.rs 의 인트라-로우 분할 분기가 page_break
모드를 점검하지 않아 RowBreak 표(쪽나눔=2, 행 경계만 분할)도
인트라-로우 분할 가능. 명세 위반.

베이스라인: stream/devel (Task edwardkim#643/edwardkim#712 미적용 상태)에서도 동일
재현 (page 36 pi=586 split_end=17.6 px). PR 도 stream/devel 기준.

가설 H1: 인트라-로우 분할 분기에 page_break != RowBreak 가드 추가
가설 H2: allows_row_break_split() 의미 분리 (rowspan 보호 vs intra-row)

6 stage TDD: 계획→RED→분석→GREEN→회귀→광범위→보고.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
tests/issue_713.rs 신규 — pi=586 ci=0 (12x5 RowBreak 표) 의 row 8
셀들이 단일 페이지에만 등장하고 clip=false 임을 단언.

RED 확인 (stream/devel 베이스, page_count=40):
  row 8 cells appear on pages={35, 36} clipped_cells=10
  → row 8 (5 cells) 이 page 35, 36 양쪽 분할, 10 셀 모두 clip=true
  → 인트라-로우 분할 명세 (RowBreak) 위반 정확 검출

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Stage 0/1 가설 검증 결과:
- H1 (RowBreak 인트라-로우 분할 가드): 광범위 회귀 3 샘플 발생
  (inner-table-01, k-water-rfp, synam-001 모두 PDF 정합 깨짐) — 폐기
- H3 (잔여 < 임계값 시 push): 효과 미발현. 활성 분기 미확인 — 폐기

신규 발견 — Rust enum 매핑이 거꾸로:
- attr 값 1: Rust=CellBreak (셀 분할) vs 정답=TABLE/행 경계만
- attr 값 2: Rust=RowBreak (행 경계만) vs 정답=CELL/셀 분할 허용

Task edwardkim#474 가 "RowBreak (Rust 값 2) 보호 블록 비적용" 처리하면서
한컴 의도 (값 2 = 셀 분할) 와 결과적 일치 — 그래서 광범위 회귀 0.

본 결함 (행 8 분할) 의 root cause 가 enum 매핑인지, 다른 본질인지
시각 검증 (PDF vs SVG) 필요. Stage 3 진입 보류, 사용자 결정 대기.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…_r >= 25px

활성 경로 식별 — typeset.rs (TypesetEngine) 가 main pagination
(rendering.rs:1042 use_paginator=false 기본). Stage 2 의 engine.rs
수정 시도가 효과 없었던 이유.

가설 H4: PartialTable 의 split_end_content_limit = avail_content_for_r
(현 페이지의 행 r top portion 높이) 가 한 줄 정도로 작으면 (orphan)
분할 대신 행 전체를 다음 페이지로 push. 한컴은 페이지 끝 sliver 를
두지 않음.

정정 (typeset.rs:1892-1905):
  const MIN_TOP_KEEP_PX: f64 = 25.0;
  if avail_content_for_r >= MIN_SPLIT_CONTENT_PX
      && avail_content_for_r >= min_first_line
      && avail_content_for_r >= MIN_TOP_KEEP_PX  // 신규 가드
      && remaining_content >= MIN_SPLIT_CONTENT_PX

임계값 25 결정 근거:
  - 본 결함 (2022 국립국어원 row 8): 17.6 px < 25 → 차단
  - synam-001 p23 (정합): 27.3 px >= 25 → 허용 (변경 없음)
  - 다른 정합 분할 (93/437/510 px): 모두 >= 25 → 변경 없음

검증:
  - tests/issue_713 RED→GREEN (row 8 단일 페이지, clip=0)
  - cargo test --release: 1250 passed, 0 failed
  - 181 샘플 페이지 수 회귀 0 (H1 회귀 3 샘플 모두 정합 유지)

PDF 권위 (한글 2022 page 32 첫 줄 "한국어교육 내실화") 정합.

순수 코드 변경 5 라인 (가드 1 + 상수 + 주석).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
samples/2022년 국립국어원 업무계획.hwp 12x5 일정 표 row 8 의 17.6 px
sliver 분할 결함 정정. typeset.rs 의 인트라-로우 분할 분기에
avail_content_for_r >= 25 px (MIN_TOP_KEEP_PX) 가드 추가로 orphan
sliver 차단, 행 전체를 다음 페이지로 push.

Stage 진행:
- 0: 수행/구현 계획서
- 1 RED: row 8 cells appear on pages={35,36} clipped=10 (FAIL)
- 2 분석: H1 (RowBreak 차단) 폐기 (3 회귀), H3 효과 0 (engine.rs fallback)
  → 활성 경로 typeset.rs 재식별, H4 (top portion 임계값) 채택
- 3 GREEN: 가드 추가, row 8 cells appear on pages={36} clipped=0 (PASS)
- 4 회귀: cargo test --release 1250 passed, 0 failed
- 5 광범위: 181 샘플 페이지 수 회귀 0 (H1 회귀 3 샘플 모두 정합)
- 6 보고: 본 문서

PDF 권위 (한글 2022 page 32 첫 줄 "한국어교육 내실화") 정합.
순수 코드 변경 5 라인.

closes edwardkim#713

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@edwardkim edwardkim added this to the v1.0.0 milestone May 9, 2026
@edwardkim edwardkim added the enhancement New feature or request label May 9, 2026
edwardkim added a commit that referenced this pull request May 9, 2026
본질: samples/2022년 국립국어원 업무계획.hwp 12x5 일정 표 (pi=586,
RowBreak) row 8 영역 의 17.6 px 인트라-로우 분할 결함. 한컴은 페이지 끝
영역 의 작은 sliver 영역 부재 영역 의 행 단위 push 가 한컴 권위.

본 환경 직접 재현:
- BEFORE: page_index=30 rows=0..9 split_end=17.6 px (orphan sliver)
- AFTER:  page_index=30 rows=0..8 (cont=false) → page_index=31 rows=8..12
          (row 8 전체 다음 페이지 push)

정정 (src/renderer/typeset.rs:1931+, 5 LOC + 주석):
const MIN_TOP_KEEP_PX: f64 = 25.0;
&& avail_content_for_r >= MIN_TOP_KEEP_PX  // [Task #713] orphan 가드

임계값 25 px 결정 근거:
- 본 결함 (row 8 sliver):     17.6 px → < 25 차단 ✓
- synam-001 p23 정합:        27.3 px → ≥ 25 변경 없음 ✓
- 기타 정합 분할:        93/437/510 px → ≥ 25 변경 없음 ✓

영향 좁힘 (feedback_hancom_compat_specific_over_general):
- avail_content_for_r >= 25 px 영역 의 분할 영역 무영향
- 비-RowBreak 표 / 비-Partial 분할 영역 무관
- 활성 경로 (typeset.rs) 만 정정 — fallback 경로 (pagination/engine.rs)
  영역 무영향 (RHWP_USE_PAGINATOR=1 미설정 영역 의 fallback 영역)

회귀 가드 (tests/issue_713.rs +108 LOC, 신규):
- 동적 페이지 sweep 영역 — 모든 페이지 영역 의 row 8 셀 영역 수집
- RowBreak 모드 영역 의 단일 페이지 영역 위치 검증
- clip=false 검증

검증:
- cargo test --release: lib 1173 + 통합 ALL GREEN, failed 0
- cargo test --release --test issue_713: 1 PASS (회귀 가드)
- cargo test --release --test issue_712: PASS (PR #714 영역 보존)
- cargo test --release --test svg_snapshot: 8/8 (form-002 PR #706 영역 보존)
- cargo clippy --release: 신규 경고 0
- 광범위 sweep 7 fixture / 170 페이지 / 회귀 0

Closes #713

Co-Authored-By: Jaeook Ryu <jaeook.ryu@gmail.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
edwardkim added a commit that referenced this pull request May 9, 2026
- mydocs/pr/archives/pr_715_review.md (검토 문서)
- mydocs/pr/archives/pr_715_report.md (처리 보고서)
- mydocs/plans/archives/task_m100_713{,_impl}.md
- mydocs/orders/20260509.md: PR #715 행 + 본 사이클 패턴 라인 추가

처리 결과:
- 옵션 A — 5 commits 단계별 보존 cherry-pick + no-ff merge (d4efc29)
- 작업지시자 시각 판정 ★ 통과 (웹 에디터)
- 본 환경 직접 재현 + 정정 입증: row 8 sliver 17.6 px → 0 px
- 광범위 sweep 7 fixture / 170 페이지 / 회귀 0
- WASM 빌드 4,607,734 bytes
- Issue #713 close 자동 정합

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@edwardkim

Copy link
Copy Markdown
Owner

@planet6897 PR 머지 완료되었습니다 (devel d4efc29a, --no-ff merge).

처리 결과

검증

본 환경 직접 재현 + 정정 입증

  • BEFORE: page_index=30 rows=0..9 split_end=17.6 px (orphan sliver)
  • AFTER: page_index=30 rows=0..8 split_end=0 px / page_index=31 rows=8..12 cont=true

→ row 8 전체 영역 다음 페이지로 push 정합 (한컴 권위).

임계값 25 px 결정 근거 정합

  • 본 결함 (17.6 px) 차단 ✓
  • synam-001 p23 정합 (27.3 px) 보존 ✓
  • 기타 정합 분할 (93/437/510 px) 보존 ✓

메모리 룰 정합

처리 보고서: mydocs/pr/archives/pr_715_report.md. 감사합니다.

@edwardkim edwardkim closed this May 9, 2026
edwardkim added a commit that referenced this pull request May 9, 2026
…YOUT_OVERFLOW_DRAW)

본질: Task #9 의 fix_overlay_active push 영역 의 빈 paragraph (text_len=0)
영역 push 로 의미 없는 drift 만 +20 px (pi=1 +8 + pi=3 +12) 누적 → page 1
마지막 줄 (pi=15 line=2) 이 컬럼 하단 +20.15 px 초과 시각 cropping.

본 환경 직접 재현:
  LAYOUT_OVERFLOW_DRAW: section=0 pi=15 line=2 y=1048.2 col_bottom=1028.0 overflow=20.1px
  LAYOUT_OVERFLOW: page=0, col=0, para=15, type=PartialParagraph, y=1059.4, bottom=1028.0, overflow=31.3px

→ 정정 후: LAYOUT_OVERFLOW_DRAW 부재 / LAYOUT_OVERFLOW 11.3 px (잔존, trailing ls 영역 별도).

Root cause 분석 흐름:
- 수행계획서 정적 분석 가설 ("음수 line_spacing 미반영") → Stage 2 instrument
  실측 결과 line advance 자체는 ls 가산 정확함 확인
- drift 진원지 = Task #9 fix_overlay_active 의 빈 paragraph push
  (pi=1 empty +8 px / pi=3 empty +12 px = +20.00 px ≈ overflow 20.15 px 99.3% 일치)

정정 (src/renderer/layout.rs:1562-1582, +13 LOC):
- is_empty_para 가드 추가 — text.is_empty() || control/FFFC 만
- !is_fixed && !is_empty_para 조건 영역 push 적용
- Task #9 의 텍스트 paragraph push 의도 (TAC 표 위 침범 차단) 그대로 유지
- fix_overlay_active 유지 (후속 비-empty paragraph push 가능)

영향 좁힘 (feedback_hancom_compat_specific_over_general):
- 텍스트 paragraph 영역 무영향 (Task #9 의도 유지)
- Fixed line spacing 영역 무영향 (is_fixed 가드)
- 비-fix_overlay_active 경로 무영향
- 빈 paragraph (text 부재 또는 control/FFFC 만) 영역만 차단

회귀 가드 (tests/issue_716.rs +91 LOC, 신규):
- page 0 body bbox 수집 + 모든 TextLine bbox 수집 (Header/Footer 제외)
- max_bottom <= body_bottom + 0.5 검증 (sub-pixel rounding 허용)

검증:
- cargo test --release: lib 1173 + 통합 ALL GREEN, failed 0
- cargo test --release --test issue_716: 1 PASS (회귀 가드)
- cargo test --release --test svg_snapshot: 8/8 (form-002 PR #706 영역 보존)
- cargo test --release --test issue_712/713: PASS (PR #714/#715 영역 보존)
- cargo clippy --release: 신규 경고 0
- 광범위 sweep 7 fixture / 170 페이지 / 회귀 0
- 본 환경 직접 측정: LAYOUT_OVERFLOW_DRAW 부재 ★

PR 본문 광범위 sweep (169 샘플):
- LAYOUT_OVERFLOW_DRAW 187 → 185 (−2 정정: hongbo + hongbo-no)
- LAYOUT_OVERFLOW 279 → 277 (−2 부수 개선: table-vpos-01 hwp/hwpx)
- 페이지 수 변동 0 샘플
- panic 0

Closes #716

Co-Authored-By: Jaeook Ryu <jaeook.ryu@gmail.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <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