Skip to content

Task #672: TAC 표 비례 축소 임계값 강화 — 작은 차이 (≤2%) 면제 (closes #672)#675

Closed
jangster77 wants to merge 6 commits into
edwardkim:develfrom
jangster77:local/task672
Closed

Task #672: TAC 표 비례 축소 임계값 강화 — 작은 차이 (≤2%) 면제 (closes #672)#675
jangster77 wants to merge 6 commits into
edwardkim:develfrom
jangster77:local/task672

Conversation

@jangster77

Copy link
Copy Markdown
Collaborator

요약

TAC 표 (treat_as_char=true) 에서 측정된 row_heights 합산이 common.height (HWP 인코딩 권위값) 을 초과하면 모든 row_heights 가 비례 축소되어 셀 콘텐츠 일부가 클립되던 결함 정정.

closes #672

⚠️ 의존성 — PR #673 (Task #671) 선행 머지 권장

본 PR 은 Task #671 정정 (recompose_for_cell_width 신규 함수 + 호출 위치 6 곳) 위에서 분기. PR #673 머지 후 본 PR 의 diff 가 Task #672 단일 분기 정정으로 자동 축약.

본질 진단

samples/계획서.hwp 셀 [21] 의 시각 결함:

  • raw_table_height = 982.29 (측정값 합)
  • common.height = 969.53 (HWP 인코딩)
  • 차이 = 12.76 px (1.32%)
  • 기존 동작: raw > common + 1.0 → 비례 축소 발동 → row_heights 축소 → 셀 콘텐츠 클립

한컴 권위 영역: 작은 차이는 비례 축소 안 함 (계획서.hwp 3줄 정상 표시).

187 fixture sweep 결과

차이 비율 발생 케이스 분류
0~1% 3 건 측정 오차
1~2% 4 건 (계획서.hwp 1.32% 포함) 작은 불일치 (정정 후보)
2~5% 4 건 중간
5~10% 1 건
10~20% 6 건 의도적 큰 압축
20%+ 4 건 의도적 큰 압축

본질 정정

src/renderer/height_measurer.rs:805-822 — 단일 분기 정정.

const TAC_SHRINK_THRESHOLD_RATIO: f64 = 0.02;
let shrink_threshold = (common_h * TAC_SHRINK_THRESHOLD_RATIO).max(1.0);
let table_height = if table.common.treat_as_char && common_h > 0.0
    && raw_table_height > common_h + shrink_threshold {
    let scale = common_h / raw_table_height;
    for h in &mut row_heights {
        *h *= scale;
    }
    common_h
} else {
    raw_table_height
};

임계값: (common_h * 0.02).max(1.0) — 2% + 절대값 1px 보장.

동작 영역:

  • ≤2% 차이 (7 건): 비례 축소 면제 → row_heights 측정값 보존
  • ≥2% 차이 (15 건): 비례 축소 발동 (사용자 의도 영역 그대로)

회귀 위험 영역 좁힘

  • 단일 분기 가드 추가 — 다른 영역 무영향
  • 광범위 페이지네이션 sweep: 187 fixture / 2013 pages / 차이 0
  • 의도적 큰 압축 영역 (≥5%, 11 건) 기존 동작 유지

feedback_rule_not_heuristic + feedback_hancom_compat_specific_over_general 정합.

검증

검증 영역 결과
cargo build --release
cargo test --lib --release 1155 passed (회귀 0)
cargo test --release --test svg_snapshot 6/6
cargo test --release --test issue_546 1/1
cargo test --release --test issue_554 12/12
cargo clippy --release ✅ 0 warnings

광범위 페이지네이션 회귀 sweep

영역 결과
BEFORE 187 fixtures / 2013 pages
AFTER 187 fixtures / 2013 pages
차이 0

본 PR 본질 영역 정정 결과

samples/계획서.hwp 1페이지 표:

영역 BEFORE AFTER
셀 [21] row_heights[5] 66.88 (비례 축소) 67.76 (측정값 보존)
layout cell_h 66.88 67.76
SVG 3줄 baseline 그려짐 그려짐 (단 마지막 줄 시각 클립) 3줄 정상 그려짐
다른 셀 회귀 0 ✅

잔존 결함 영역 (별도 Issue)

본 PR 정정 후 잔존: PNG 변환 시 셀 [21] / [52] 마지막 줄 미표시.

잔존 결함의 본질 (별개 영역)

  • paragraph_layout 줄 layout 위치 (col_area.y + line_idx * line_height) 가 row_heights 와 무관
  • cell BoundingBox 확장만으로 시각 클립 해결 안 됨
  • descent 여유 추가 시도 (max_fs * 0.5): 마지막 줄 일부 보임 (행 침범 시각 회귀)

→ paragraph_layout 줄 위치 결정 로직 자체의 본질 영역.

별도 Issue: #674 — paragraph_layout 줄 위치 vs row_heights 정합 — line_segs 부재 paragraph 마지막 줄 시각 클립

본 PR 본질 영역 (TAC 표 비례 축소) 과 다른 본질 영역 (paragraph_layout 줄 위치) 으로 분리 — feedback_hancom_compat_specific_over_general + 회귀 위험 좁힘 정합.

진단 도구

examples/inspect_task672.rs — TAC 표 비례 축소 발동 영역 sweep + 차이 비율 분포 분석 (187 fixture).

산출물

영역 파일
코드 정정 src/renderer/height_measurer.rs (단일 분기)
진단 도구 examples/inspect_task672.rs
거버넌스 산출물 mydocs/plans/task_m100_672{,_impl}.md, mydocs/working/task_m100_672_stage{1,2,3}.md, mydocs/report/task_m100_672_report.md

커밋 시퀀스 (3 단계)

  • Stage 1: 본질 진단 + 임계값 평가 (sweep 도구 + 분포 분석)
  • Stage 2: 본질 정정 — TAC 표 비례 축소 임계값 강화 (2% 가드)
  • Stage 3: 광범위 회귀 sweep + 최종 보고서 + orders 갱신

jangster77 added 6 commits May 8, 2026 17:37
- 수행계획서 / 구현계획서 작성
- 진단 도구 (examples/inspect_task671.rs / _v2.rs) — 셀 paragraph
  line_segs 검사 + recompose 정밀 진단
- 권위 자료 samples/계획서.hwp git tracked 등록 (HWP5 한컴
  PARA_LINE_SEG 인코딩 부재 케이스 권위 영역)
- Stage 1 보고서: composer::compose_lines fallback 의 단일 ComposedLine
  압축이 본질 결함 위치로 식별. line_segs 비어 있는 셀 paragraph
  fallback 경로에서 텍스트 폭 측정 + 자동 줄바꿈 미수행 → 셀 너비
  초과 텍스트 한 줄 그려져 줄겹침 시각 결함

refs edwardkim#671
본질: HWP5 일부 파일은 셀 paragraph 의 PARA_LINE_SEG 를 인코딩하지
않는다 (한컴이 layout 시 자동 계산). 본 환경 fallback (compose_lines
단일 ComposedLine 압축) 은 셀 너비 초과 텍스트가 한 줄에 그려져
줄겹침 시각 결함 발생.

신규 함수 (composer.rs):
- recompose_for_cell_width(composed, para, cell_inner_width_px, styles)
  — 진입점 (3 중 가드: line_segs.is_empty() + lines.len()==1 + 폭 초과)
- split_composed_line_by_width(line, max_width_px, styles)
  — 단어 경계 우선 + CJK 글자 단위 break 본질 룰

호출 위치 (6 곳):
- table_layout.rs:1226 — 셀 layout 렌더링 경로 (핵심)
- table_layout.rs:614/678/700 — resolve_row_heights 측정 fallback
  (caller + callee 시그니처 변경)
- table_partial.rs:94/358 — 분할 표 측정 + layout
- height_measurer.rs:527/712 — MeasuredTable 핵심 측정
  (row_heights 정합 보장)

회귀 위험 영역 좁힘:
- 본문 paragraph 무영향 (compose_paragraph 변경 없음)
- HWPX 영역 무영향
- 정상 line_segs 인코딩된 셀 무영향 (1차 가드)
- 단일 줄 텍스트 무영향 (3차 가드)

검증:
- cargo test --lib --release: 1155 passed (회귀 0)
- svg_snapshot: 6/6
- issue_546: 1/1
- issue_554: 12/12
- cargo clippy: 0 warnings

refs edwardkim#671
광범위 페이지네이션 회귀 sweep:
- 187 fixtures / 2013 pages BEFORE/AFTER
- 차이 0 (회귀 위험 영역 완전 좁힘 입증)

핵심 fixture 개별 검증 (모두 차이 0):
  aift / exam_kor / exam_math / exam_science / synam-001 /
  footnote-01 / hwp3-sample / hwp3-sample4 / hwp3-sample5 / 계획서

시각 판정 (작업지시자 게이트웨이):
- 셀 [13] r=3,c=1: 1줄 압축(겹침) → 2줄 정상 분리 ✅
- 셀 [21] r=5,c=1: 1줄 압축(겹침) → 3줄 분리 ✅
- 본 task 본질 영역 (줄겹침) 정정 완료

잔존 결함 영역 별도 분리:
- TAC 표 (treat_as_char=true) 비례 축소 메커니즘
  (height_measurer.rs:822-830) → Issue edwardkim#672 별도 등록
- feedback_hancom_compat_specific_over_general 정합

산출물:
- mydocs/report/task_m100_671_report.md — 최종 결과 보고서
- mydocs/working/task_m100_671_stage3.md — Stage 3 단계별 보고서
- mydocs/orders/20260507.md — Task edwardkim#671 상태 갱신 + Issue edwardkim#672 등록 정보

closes edwardkim#671
- 수행계획서 / 구현계획서 작성
- 진단 도구 (examples/inspect_task672.rs) — 187 fixture 의 TAC 표
  비례 축소 발동 영역 sweep + 차이 비율 분포 분석
- Stage 1 보고서: 발동 영역 22 건 분포 — ≤2% 7건 (계획서.hwp 1.32%
  본 case), 2~5% 4건, ≥5% 11건 (의도적 큰 압축). 한컴 권위 영역:
  작은 차이는 비례 축소 안 함 추정. 임계값 후보 평가 → 옵션 1 (2%
  임계값) 권고 — 회귀 위험 가장 좁힘.

refs edwardkim#672
본질: 셀 콘텐츠 측정값과 common.height 의 미세한 불일치 (측정 오차
또는 line_height 보정 부산물) 시 비례 축소가 셀 콘텐츠 클립을 발생.
한컴 뷰어는 작은 차이를 비례 축소 안 함 (계획서.hwp 1.32% 차이 — 3 줄
정상 표시).

정정: height_measurer.rs:805-822 단일 분기에 임계값 가드 추가.

  const TAC_SHRINK_THRESHOLD_RATIO: f64 = 0.02;
  let shrink_threshold = (common_h * TAC_SHRINK_THRESHOLD_RATIO).max(1.0);

- 작은 차이 (≤2%): 측정값 우선 (raw_table_height) → row_heights 보존
- 큰 차이 (≥2%): 비례 축소 발동 (사용자 의도 영역 그대로)

면제 영역 (Stage 1 sweep 진단):
  계획서.hwp 1.32% (본 case) / 2010-01-06.hwp 1.97% / hwp-img-001
  1.22% / kps-ai 1.88% / hwp-3.0-HWPML 0.16% / synam-001 0.38%/0.94%

회귀 위험 영역 좁힘:
- 단일 분기 정정 — 다른 영역 무영향
- 5%+ 영역 (의도적 큰 압축, 11건) 그대로 동작

검증:
- cargo test --lib --release: 1155 passed (회귀 0)
- svg_snapshot 6/6 / issue_546 1/1 / issue_554 12/12 / clippy 0

본 task 본질 영역 정정 결과:
- 셀 [21] row_heights[5]: 66.88 (비례 축소) → 67.76 (측정값 보존)
- layout cell_h: 67.76 / recompose 3줄 분할 / SVG 3줄 baseline 그려짐

잔존 결함 별도 분리 (Issue edwardkim#674):
- paragraph_layout 줄 위치 (col_area.y + line_idx * line_height) 가
  row_heights 와 무관 → cell BoundingBox 확장만으로 PNG 변환 시각
  클립 해결 안 됨. descent 여유 시도 (max_fs * 0.5) 도 행 침범 회귀
  발생 → 별개 본질 영역 (paragraph_layout 줄 위치 결정 로직 자체).

refs edwardkim#672
광범위 페이지네이션 회귀 sweep:
- 187 fixtures / 2013 pages BEFORE/AFTER
- 차이 0 (회귀 위험 영역 완전 좁힘 입증)

본 task 본질 영역 정정 완료:
- TAC 표 비례 축소 임계값 강화 (2% 가드)
- 작은 차이 (≤2%) 면제 → 측정값 row_heights 보존
- 큰 차이 (≥2%) 그대로 동작 (사용자 의도 영역 보존)

잔존 결함 영역 별도 분리:
- paragraph_layout 줄 위치 vs row_heights 정합 (PNG 변환 시각 클립)
- → Issue edwardkim#674 신규 등록
- feedback_hancom_compat_specific_over_general + 회귀 위험 좁힘 정합

산출물:
- mydocs/report/task_m100_672_report.md — 최종 결과 보고서
- mydocs/working/task_m100_672_stage3.md — Stage 3 단계별 보고서
- mydocs/orders/20260507.md — Task edwardkim#672 상태 갱신 + Issue edwardkim#674 등록 정보

closes edwardkim#672
edwardkim added a commit that referenced this pull request May 8, 2026
closes #672

3 commits 단계별 보존 (Task #672 영역만 — Task #671 영역 commits 영역은 PR #673 영역에서 이미 머지됨):
- 071e952 Stage 1: 본질 진단 + 임계값 평가
- b524c4f Stage 2: 본질 정정 — TAC 표 비례 축소 임계값 강화
- d071d37 Stage 3: 광범위 회귀 sweep + 최종 보고서 + orders 갱신

본질 정정:
- src/renderer/height_measurer.rs:805 영역 단일 분기
- 정정 전: raw > common + 1.0 (절대값 1px 임계값)
- 정정 후: raw > common + max(common * 2%, 1px)
- 본질: 측정 오차 / line_height 보정 부산물 영역의 미세한 불일치 영역에서 비례
  축소 발동 영역 → 셀 콘텐츠 클립 영역. 한컴 권위 영역: 작은 차이 영역
  비례 축소 안 함 (계획서.hwp 1.32% 차이 영역 3 줄 정상 표시).
- 187 fixture sweep 영역: ≤2% 7 건 면제, ≥5% 11 건 그대로 (의도적 압축 보존)

본 환경 검증:
- cherry-pick: Task #672 commits 만 (Task #671 commits 는 PR #673 영역에서 머지됨)
  - Stage 1+2 깨끗, Stage 3 orders 영역 ours
- cargo test --release ALL PASS (1165 lib + svg_snapshot 7/7 + issue_546/issue_554 13/13)
- clippy clean
- 광범위 sweep 7 샘플 170 페이지: same=167 / diff=3
  - 2010-01-06 p5 (1.97% 차이 면제)
  - synam-001 p19 / p31 (0.38~0.94% 차이 면제)

작업지시자 가설 점검:
PR #673 영역의 A1 (자동보정 셀 폭 정정) 영역만으로는 본 PR 영역의 본질 영역 미해결 영역.
두 영역의 본질 영역 다름:
- A1: LINE_SEG 채움 영역의 셀 폭 영역 정정 영역
- Task #672: HeightMeasurer 영역의 row_heights 비례 축소 영역의 임계값 영역

PR: #675
컨트리뷰터: @jangster77 (Taesup Jang) — 14번째 사이클 PR
잔존 분리: Issue #674 → PR #678 (paragraph_layout 줄 위치 vs row_heights 정합)
edwardkim added a commit that referenced this pull request May 8, 2026
PR #675 (Task #672): TAC 표 비례 축소 임계값 강화 — 작은 차이 (≤2%) 면제
- merge commit: 877e020 (3 commits 단계별 보존 no-ff merge)
- 본질: height_measurer.rs:805 영역 단일 분기 — TAC_SHRINK_THRESHOLD_RATIO = 0.02
- 187 fixture sweep: ≤2% 7 건 면제 / ≥5% 11 건 보존
- 본 환경 결정적 검증 1165 lib + svg_snapshot 7/7 + issue_546/issue_554 13/13 + clippy clean
- 광범위 sweep 7 샘플 170 페이지: same=167 / diff=3 (영향 영역만)
- WASM 빌드 4,589,098 bytes

작업지시자 가설 점검:
"#674 PR 메인테이너 자동보정으로 #675 문제 해결?" → ❌ 미정합
- 그대로 보기 영역 SVG md5 다름 (b66efd77 → cc174155, -706 bytes)
- 두 영역 본질 다름:
  - PR #673 + A1: LINE_SEG 채움 영역의 셀 폭 정정 (document.rs)
  - PR #675: HeightMeasurer row_heights 비례 축소 임계값 (height_measurer.rs)

작업지시자 시각 판정:
- 자동보정 영역 ★ 정합 (셀내 2줄 컨텐츠 한컴처럼 정렬)
- 그대로 보기 영역 클립핑 유지 (PR #678 영역 잔존)
작업지시자 결정: 머지 유지 영역 (PR #678 머지 시 자연 해소 영역)

잔존 분리: Issue #674 → PR #678 (paragraph_layout 줄 위치 vs row_heights)

closes #672

산출물:
- mydocs/pr/archives/pr_675_review.md
- mydocs/pr/archives/pr_675_report.md
- mydocs/orders/20260508.md 갱신
@edwardkim

Copy link
Copy Markdown
Owner

@jangster77 님 14번째 사이클 PR 처리 완료입니다.

본 환경 검증 결과:

결정적 검증 통과:

  • `cargo test --release` → ALL PASS (1165 lib + svg_snapshot 7/7 + issue_546/issue_554 13/13)
  • `cargo clippy --release` → clean

광범위 회귀 sweep (7 샘플 170 페이지): same=167 / diff=3 (영향 영역만 — 계획서.hwp + 2010-01-06 p5 + synam-001 p19/p31)

inspect_task672 본 환경 측정:
```
samples/계획서.hwp ci=2 | common=969.53 raw=982.29 diff=+12.76 (+1.32%)
samples/2010-01-06.hwp pi=63 | common=351.53 raw=358.47 diff=+6.93 (+1.97%)
samples/synam-001.hwp pi=153 | common=316.39 raw=319.37 diff=+2.99 (+0.94%)
samples/synam-001.hwp pi=237 | common=994.40 raw=998.16 diff=+3.76 (+0.38%)

총 7 건 영역 모두 ≤2% 영역 면제 영역

```

작업지시자 시각 판정:

작업지시자 결정: 머지 유지 영역 — PR #678 머지 시 그대로 보기 영역의 클립핑 영역 자연 해소 영역.

처리: 3 commits 단계별 보존 no-ff merge.

본질 정정 영역의 정확성: `height_measurer.rs:805` 영역 단일 분기 영역 — `TAC_SHRINK_THRESHOLD_RATIO = 0.02` (2% 임계값) 영역. 187 fixture sweep 영역의 분포 분석 영역 영역 합리화 영역.

작업지시자 가설 점검 결과: PR #673 영역의 A1 (자동보정 셀 폭 정정) 영역만으로는 본 PR 영역의 본질 영역 미해결 영역. 두 영역의 본질 영역 다름:

잔존 영역 분리 정합: Issue #674 → PR #678 영역 (paragraph_layout 줄 위치 vs row_heights 정합 — 그대로 보기 영역의 클립핑 영역의 본질 영역).

처리 보고서: `mydocs/pr/archives/pr_675_report.md`

closes #672

@edwardkim edwardkim closed this May 8, 2026
edwardkim added a commit that referenced this pull request May 8, 2026
…보정 — 마지막 줄 시각 클립 정정

closes #674

3 commits 단계별 보존 (Task #674 영역만 — Task #671/#672 영역 commits 영역은 PR #673/#675 영역에서 머지됨):
- fda8601 Stage 1: 본질 진단 — 24px 오프셋 식별
- f50297b Stage 2: 본질 정정 — calc_para_lines_height 보정
- 230099f Stage 3: 광범위 회귀 sweep + 최종 보고서 + orders 갱신

본질 정정:
- src/renderer/layout/table_layout.rs:746 영역 calc_para_lines_height 영역 시그니처 영역
  + corrected_line_height 영역 보정 적용 (height_measurer.rs 영역과 동일 로직)
- 호출자 영역 시그니처 정정: calc_cell_paragraphs_content_height + calc_composed_paras_content_height
- 본질: line_segs 부재 셀 paragraph 영역의 fallback line_height (raw 5.33px) 영역이
  폰트 보정 (corrected 21.33px) 영역 안 받아 영역 mechanical_offset 영역 잘못 계산 영역
  → text_y_start 영역 24px 위로 밀림 영역 → 마지막 줄 cell-clip 초과 영역 → 시각 클립 영역

본 환경 검증:
- cherry-pick: Task #674 commits 만 (Task #671/#672 영역은 PR #673/#675 영역에서 머지)
  - Stage 1+2 깨끗, Stage 3 orders 영역 ours
- cargo test --release ALL PASS (1165 lib + svg_snapshot 7/7 + issue_546/issue_554 13/13)
- clippy clean
- 광범위 sweep 7 샘플 170 페이지: same=170 / diff=0 ✅

Task #671 ~ #674 시리즈 완성:
- #671: 셀 paragraph line_segs 부재 영역 — composer.rs (recompose_for_cell_width)
- #672: TAC 표 비례 축소 영역 임계값 — height_measurer.rs:822 (2% 가드)
- #674: calc_para_lines_height corrected_line_height 영역 — table_layout.rs:746

PR: #678
컨트리뷰터: @jangster77 (Taesup Jang) — 15번째 사이클 PR (HWP 3.0 파서 영역의 핵심 영역)
선행 PR: #673 (Task #671) + #675 (Task #672) 영역 머지 영역 후 영역
edwardkim added a commit that referenced this pull request May 8, 2026
…즈 완성)

PR #678 (Task #674): paragraph_layout 측정 corrected_line_height 보정
- merge commit: f8b38cc (3 commits 단계별 보존 no-ff merge)
- 본질: calc_para_lines_height 영역의 corrected_line_height 보정 누락 영역
  → 24px 영역 mechanical_offset 잘못 계산 → text_y_start 24px 위로 밀림 → 클립
- 정정: table_layout.rs:746 영역 시그니처 + 보정 + 호출자 시그니처 정정
- 본 환경 결정적 검증 1165 lib + svg_snapshot 7/7 + issue_546/issue_554 13/13 + clippy clean
- 광범위 sweep 7 샘플 170 페이지: same=170 / diff=0 ✅
- WASM 빌드 4,589,700 bytes
- 작업지시자 시각 판정 ★ 통과 (그대로 보기 + 자동보정 영역 모두 정합)

🎉 Task #671~#674 시리즈 완성:
- PR #673 (#671) — 셀 paragraph line_segs 부재 영역 → composer.rs (recompose_for_cell_width)
- A1 (메인테이너) — 자동보정 col_width → cell_inner_width (document.rs)
- PR #675 (#672) — TAC 표 비례 축소 임계값 → height_measurer.rs (2% 가드)
- PR #678 (#674) — calc_para_lines_height corrected_line_height → table_layout.rs

@jangster77 (Taesup Jang) — 15번째 사이클 PR (HWP 3.0 파서 영역 핵심 컨트리뷰터)
한컴 LINE_SEG 비표준 영역의 자체 재계산 영역 정합 영역 도달 영역 (project_hancom_lineseg_behavior)

closes #674

산출물:
- mydocs/pr/archives/pr_678_review.md
- mydocs/pr/archives/pr_678_report.md
- mydocs/orders/20260508.md 갱신
@jangster77 jangster77 deleted the local/task672 branch May 8, 2026 10:43
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