증상
Task #518 의 본질 정정 (line_break_char_idx: Option<usize> → line_break_char_indices: Vec<usize> 다중화 — ls[2..] break 사용) 이 stream/devel 에 누락. 이슈 #496 본질 (B) 가 미해결 상태로 회귀.
회귀 케이스: samples/exam_science.hwp 페이지 2 pi=61 — 본문 1줄 column 폭 초과 시 wrap 미적용 (ls[1] break 만 사용, ls[2..] break 미사용).
회귀 메커니즘
Task #518 의 코드 정정 (b395e8e6 Stage 1) 은 local/devel 에 정상 머지되었으나, devel (= stream/devel) 으로의 승격이 일어나지 않음. 이슈 #618 (Task #519), #647 (Task #517) 와 동일한 묶음 머지 a7e43f9 (Task #517/#518/#519/#520/#521/#523/#528) 누락 패턴.
$ git merge-base --is-ancestor b395e8e6 stream/devel
NOT in stream/devel
코드 회귀 위치
src/renderer/layout/paragraph_layout.rs 내 layout_inline_table_paragraph 의 줄 나눔 결정 로직이 Task #518 이전 상태 그대로:
| 위치 |
현재 (회귀) |
정정 후 |
paragraph_layout.rs:265 |
let line_break_char_idx: Option<usize> = if para.line_segs.len() > 1 { |
let line_break_char_indices: Vec<usize> = ... |
paragraph_layout.rs:398 |
let need_wrap = if let Some(break_idx) = line_break_char_idx { |
next_break 추적 + char_offsets 직접 룩업 |
알고리즘 결함
회귀 상태의 ctrl_gap 기반 알고리즘은 paragraph 전체 controls 합으로 over-subtract 발생 → controls 가 많은 paragraph 에서 항상 saturating 0 으로 None 반환 → wrap 누락.
Task #518 정정은 char_offsets[i] >= ts 인 첫 i 를 break char index 로 직접 룩업하여 정확하고 간결.
정량 증거
$ git grep -n \"line_break_char_idx\\|line_break_char_indices\" stream/devel -- src/
stream/devel:src/renderer/layout/paragraph_layout.rs:265: let line_break_char_idx: Option<usize> = if para.line_segs.len() > 1 {
stream/devel:src/renderer/layout/paragraph_layout.rs:398: let need_wrap = if let Some(break_idx) = line_break_char_idx {
→ Task #518 이전 변수명·시그니처 그대로.
영향 범위
layout_inline_table_paragraph 가 처리하는 모든 inline-table 포함 paragraph 의 wrap 정확도 저하
ls[1] break 만 적용되어 ls[2..] 가 필요한 케이스 (3줄 이상 wrap) 에서 본문 누락/오배치
수정 방향
Task #518 의 원 commit b395e8e6 (Layout 리팩터링 Phase 2 — line_break_char_idx 다중화) 을 stream/devel 기준으로 cherry-pick 재적용.
- 코드 변경:
paragraph_layout.rs -40/+77 줄 (변수 다중화 + 알고리즘 단순화 + LAYOUT_BREAK_INDICES 디버그 로깅)
- 검증 케이스: exam_science p2 pi=61 — 본문 1줄 column 폭 초과 → 3줄 정상 wrap (
ls[1] break char 5 + ls[2] break char 28)
- 회귀 영향: 7 샘플 170 페이지 중 same=167 / diff=3 (exam_science 정확도 정정)
의존성
Task #518 디버그 로깅 (LAYOUT_BREAK_INDICES) 은 Task #517 의 layout_debug_enabled() 헬퍼에 의존 → #647 (Task #517 누락) 선행 또는 동시 적용 필요.
참고
증상
Task #518 의 본질 정정 (
line_break_char_idx: Option<usize>→line_break_char_indices: Vec<usize>다중화 —ls[2..]break 사용) 이stream/devel에 누락. 이슈 #496 본질 (B) 가 미해결 상태로 회귀.회귀 케이스:
samples/exam_science.hwp페이지 2 pi=61 — 본문 1줄 column 폭 초과 시 wrap 미적용 (ls[1]break 만 사용,ls[2..]break 미사용).회귀 메커니즘
Task #518 의 코드 정정 (
b395e8e6Stage 1) 은local/devel에 정상 머지되었으나,devel(=stream/devel) 으로의 승격이 일어나지 않음. 이슈 #618 (Task #519), #647 (Task #517) 와 동일한 묶음 머지a7e43f9 (Task #517/#518/#519/#520/#521/#523/#528)누락 패턴.코드 회귀 위치
src/renderer/layout/paragraph_layout.rs내layout_inline_table_paragraph의 줄 나눔 결정 로직이 Task #518 이전 상태 그대로:paragraph_layout.rs:265let line_break_char_idx: Option<usize> = if para.line_segs.len() > 1 {let line_break_char_indices: Vec<usize> = ...paragraph_layout.rs:398let need_wrap = if let Some(break_idx) = line_break_char_idx {next_break추적 +char_offsets직접 룩업알고리즘 결함
회귀 상태의
ctrl_gap기반 알고리즘은 paragraph 전체 controls 합으로 over-subtract 발생 → controls 가 많은 paragraph 에서 항상 saturating 0 으로None반환 → wrap 누락.Task #518 정정은
char_offsets[i] >= ts인 첫i를 break char index 로 직접 룩업하여 정확하고 간결.정량 증거
→ Task #518 이전 변수명·시그니처 그대로.
영향 범위
layout_inline_table_paragraph가 처리하는 모든 inline-table 포함 paragraph 의 wrap 정확도 저하ls[1]break 만 적용되어ls[2..]가 필요한 케이스 (3줄 이상 wrap) 에서 본문 누락/오배치수정 방향
Task #518 의 원 commit
b395e8e6(Layout 리팩터링 Phase 2 — line_break_char_idx 다중화) 을stream/devel기준으로 cherry-pick 재적용.paragraph_layout.rs-40/+77 줄 (변수 다중화 + 알고리즘 단순화 +LAYOUT_BREAK_INDICES디버그 로깅)ls[1]break char 5 +ls[2]break char 28)의존성
Task #518 디버그 로깅 (
LAYOUT_BREAK_INDICES) 은 Task #517 의layout_debug_enabled()헬퍼에 의존 → #647 (Task #517 누락) 선행 또는 동시 적용 필요.참고
b395e8e6(Task Layout 리팩터링 Phase 2: line_break_char_idx 다중화 (ls[2..] break 사용) #518: Layout 리팩터링 Phase 2 — line_break_char_idx 다중화)a7e43f9(Merge local/devel: Task Layout 리팩터링 Phase 1: 디버그 인프라 + 회귀 검증 도구 #517/Layout 리팩터링 Phase 2: line_break_char_idx 다중화 (ls[2..] break 사용) #518/그림(Picture) 회전·뒤집기(flip) 속성이 SVG 렌더링에 적용되지 않음 #519/exam_science.hwp 문제7: inline 도형(tac=true, wrap=TopAndBottom)이 다음 문단 라인에 그려져 텍스트와 겹침 #520/exam_eng p2 18번 답안지 위치가 박스 하단에 너무 가까움 — 그림(BehindText) 의 vertical extent 가 paragraph height 에 미반영 #521/exam_science 페이지 1 → 2 누적 vpos drift: 문제 6번 <보기>/답안이 다음 페이지로 밀림 #523/옛한글 PUA → KS X 1026-1:2007 자모 변환 (HncPUAConverter 정합) — exam_kor 17p 고어 미렌더 #528)