Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions mydocs/plans/task_m100_846.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# 수행계획서 — Task #846 (M100)

대상: shortcut.hwp 페이지 3 끝 `<편집 화면 분할에서>`(좌) | `화면 이동 ⟶ Ctrl+W,N`(우) 행이 페이지 4 로 밀리는 결함 (≈ 닫힌 #768).
GitHub Issue: edwardkim/rhwp#846 (#844 결함 B 분리) · 브랜치: `local/task846` (← upstream/devel)

## 결함 요약

`pi=94`(`<편집 화면 분할에서>`)는 `ColumnBreakType::Column`(단 나누기) 컨트롤을 가짐. "보기" 2단 zone 의 좌(pi=82~87)·우(pi=88~93) 6행씩을 채운 뒤 단 나누기를 만나면, 한컴은 **같은 페이지에 새 단-밴드(column band)를 시작**(현 6행 밴드 아래에 새 2단 밴드: 좌=`<편집...>`, 우=`화면 이동...`)한다.

rhwp 페이지네이션은 zone 당 단일 밴드만 가정 → `advance_column_or_new_page` 가 `current_column+1 < col_count` 가 false 면 무조건 `push_new_page()` → pi=94 부터 페이지 4 로 밀림. **누락 기능.**

## SVG 렌더 경로 확인 (이슈 "주의" 항 해소)

- `render_page_svg_native` (export-svg / wasm) → `src/document_core/queries/rendering.rs` → 페이지네이션은 **`src/renderer/typeset.rs` 의 `TypesetEngine`** 을 탄다 (`pagination/engine.rs` 아님). ✅ 이슈의 추정대로.
- 핵심 지점: `typeset.rs::advance_column_or_new_page` — 마지막 단에서 `push_new_page()` 호출. `column_type == ColumnBreakType::Column` 처리는 `paginate` 본문.
- 따라서 본 타스크는 `typeset.rs` (+ 필요 시 `renderer/layout.rs` 의 `ColumnContent` → 단 영역 좌표 계산) 에 "마지막 단 + 명시적 단 나누기 → 같은 페이지 새 단-밴드" 를 구현한다. `pagination/engine.rs` 에는 손대지 않는다 (SVG 경로가 안 탐).

## 진행 방침

- **선행 진단(Stage 1, 코드 수정 없음)**: `dump-pages -p 2`(페이지 3) / `-p 3`(페이지 4) + `dump -s N -p 94~96` 으로 column-break 행 배치·vpos·zone 구조 정밀 추적. `zone_y_offset` / `ColumnContent` 모델이 동일 zone 내 다중 밴드를 어떻게 표현해야 하는지(좌표 계산 연동 포함) 확정. 닫힌 #768 관련 흔적이 `mydocs/` 에 남아있는지 재확인.
- **구현(Stage 2)**: 확정 모델대로 `typeset.rs` 의 column-break 처리 + `advance_column_or_new_page` 확장. 마지막 단에서 명시적 `Column` break 시: (a) 현재 밴드 최대 단 높이만큼 `current_zone_y_offset` 진행, (b) `current_column=0` 리셋·`col_count` 유지, (c) 새 밴드가 본문 영역 하단을 넘으면 그때 새 페이지, (d) `layout.rs` 의 단 영역 y 좌표가 새 `zone_y_offset` 을 반영하는지 확인.
- **광역 회귀 검증(Stage 3)**: 모든 다단/단일 단/표분할 샘플 SVG diff (exam_* 류, k-water-rfp, 목차 류 포함). 메모리 `feedback_essential_fix_regression_risk` 정통 적용. macOS 환경 → `pdf/basic/shortcut-2022.pdf` (한글 2022) 1차 기준, 가능 시 한컴 2010/2020 정답지 보조. PDF 비교는 절대 기준 아님 (메모리 `feedback_pdf_not_authoritative`).
- **최종 보고(Stage 4)**: `cargo test` 전건, shortcut.hwp 1~8페이지 정합 최종 확인, 회귀 점검, 최종 보고서.
- 마지막 단 column-break 처리가 **단일 룰로 표현 가능한지** Stage 1 에서 판단 — 분기/허용오차/fallback 이 필요하면 "휴리스틱 vs 룰" 자문 (메모리 `feedback_rule_not_heuristic`).
- Stage 1 결과 모델 확장 규모가 예상보다 크면(`layout.rs` 대수술 등) 범위 재조정 재제안.

## 단계 구성 (예정 — 구현계획서에서 확정)

1. **진단**: column-band 모델 확장 설계 확정 (`typeset.rs` + `layout.rs` 연동점). 코드 수정 없음. → `working/task_m100_846_stage1.md`.
2. **구현**: `typeset.rs` 마지막-단 column-break → 같은 페이지 새 밴드 + 좌표 연동.
3. **광역 회귀 검증**: 다단/단일/표분할 샘플 전수 SVG diff + shortcut.hwp 8페이지 정합.
4. **종합 검증 및 최종 보고서**.

## 검증 기준

- `cargo test` 전건 통과, 신규 clippy 경고 0.
- shortcut.hwp 페이지 3 끝에 `<편집 화면 분할에서>` | `화면 이동 ⟶ Ctrl+W,N` 행이 정상 표시 (페이지 4 로 안 밀림), 이후 페이지 흐름 PDF 정합.
- 회귀: 다단/단일 단/표분할/목차/exam_* 기존 샘플 SVG diff 무변화 (의도 변경 외).
71 changes: 71 additions & 0 deletions mydocs/plans/task_m100_846_impl.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# 구현계획서 — Task #846 (M100)

대상: shortcut.hwp 페이지 3 끝 `<편집 화면 분할에서>`(좌) | `화면 이동 ⟶ Ctrl+W,N`(우) 가 페이지 4 로 밀리는 결함 (≈ 닫힌 #768, #844 결함 B 분리). Issue edwardkim/rhwp#846. 브랜치 `local/task846` (← upstream/devel).

핵심: SVG 렌더 경로는 `src/renderer/typeset.rs::TypesetEngine` 을 탄다 (`pagination/engine.rs` 아님). 마지막 단에서 명시적 `ColumnBreakType::Column` 을 만나면 — 현재는 무조건 `push_new_page()` — 한컴처럼 **같은 페이지에 새 단-밴드(column band)** 를 시작하도록 확장한다.

---

## Stage 1 — 진단 및 column-band 확장 설계 (소스 수정 없음)

목표: "마지막 단 + 명시적 단 나누기 → 같은 페이지 새 밴드" 를 `typeset.rs` 모델로 어떻게 표현할지 + `layout.rs` 좌표 연동점을 확정.

작업:
- `rhwp dump-pages -p 2`(페이지 3) / `-p 3`(페이지 4) — pi=82~96 의 zone/단 배치, vpos, used_height, column-break 컨트롤 위치 추적.
- `rhwp dump -s {sec} -p 82~96` — 해당 문단의 `ColumnBreakType`, LINE_SEG vpos, ParaShape, 단 정의(`column_count`) 확인.
- `typeset.rs` 정독: `advance_column_or_new_page`, `flush_column`, `ColumnContent`(`column_index`/`zone_y_offset`/`used_height`), `current_zone_y_offset` 진행 시점, `paginate` 본문의 `ColumnBreakType::Column` 처리 분기.
- `renderer/layout.rs` 의 `ColumnContent` → 단 영역 x/y 좌표 산출 로직: 새 밴드의 단들이 `zone_y_offset` + (이전 밴드 최대 단 높이) 를 기준으로 배치되는지, body-wide reserve / 머리말꼬리말 / 각주 영역과 충돌 없는지 확인.
- 새 밴드가 본문 영역 하단을 넘으면? → 그 시점에 새 페이지로. 이 판정을 어디서 할지 확정.
- 닫힌 #768 흔적이 `mydocs/` 에 남아있는지 재확인.
- **단일 룰 판정**: "마지막 단 + `ColumnBreakType::Column` → 새 밴드" 가 분기·허용오차 없이 표현 가능한지. 안 되면 자문 (메모리 `feedback_rule_not_heuristic`).
- 회귀 대상 샘플 목록 확정 (다단: exam_* 류, k-water-rfp, 다단+표분할, 다단+목차 등).

산출물: `mydocs/working/task_m100_846_stage1.md`. → 승인 요청.

---

## Stage 2 — 구현: 마지막 단 column-break → 같은 페이지 새 밴드

목표: pi=94 의 단 나누기에서 페이지 3 에 새 2단 밴드(좌=`<편집...>`, 우=`화면 이동...`) 가 생기고 이후 흐름이 PDF 와 정합.

작업:
- `paginate` 의 명시적 단나누기 경로: `ColumnBreakType::Column` + `!has_diff_col_def` + 마지막 단(`current_column+1 >= col_count`) + `col_count > 1` → `advance_column_or_new_page` 대신 신규 `start_new_column_band`.
- `start_new_column_band`: (a) `flush_column`, (b) 다음 밴드 콘텐츠에 떠다니는(글자처럼 취급 아닌) 표·그림·그리기 개체가 있으면 새 페이지로, (c) 현 밴드 높이 = 그 밴드 각 단의 마지막 문단 `vpos_end` 중 최댓값, (d) `available_height() - 밴드높이 >= 이_문단_첫줄_높이` 이면 새 밴드(zone_y_offset 진행, col 0 리셋, col_count 유지), 아니면 새 페이지.
- `process_multicolumn_break` 는 변경하지 않음 (`[다단나누기]` 동작 보존).
- 디버그: `export-svg --debug-overlay` 로 페이지 3 의 두 밴드 경계 확인.

검증: shortcut.hwp 페이지 3 끝에 `<편집 화면 분할에서>` | `화면 이동 ⟶ Ctrl+W,N` 정상 표시, 페이지 4 첫 줄로 안 밀림. 이후 페이지 수/흐름 PDF 정합. `cargo test` 전건. 1차 회귀: exam_* 다단 샘플.

산출물: `mydocs/working/task_m100_846_stage2.md`.

---

## Stage 3 — 광역 회귀 검증

목표: 다단/단일 단/표분할 전 영역에 회귀 없음 확정 (메모리 `feedback_essential_fix_regression_risk` 정통 적용 대상).

작업:
- 다단 샘플 전수: exam_* 류, k-water-rfp, 다단+TopAndBottom 표, 다단+목차, 다단+각주 — Stage 2 전/후 SVG diff (`rhwp export-svg`), 변화 시 의도 여부 판정.
- 단일 단(col_count==1) 샘플 일부 — 본 변경이 `col_count==1` 경로를 안 건드리는지 확인.
- shortcut.hwp 1~8페이지 SVG ↔ `pdf/basic/shortcut-2022.pdf` (한글 2022, macOS 1차 기준) 시각 비교. 가능 시 한컴 2010/2020 동작과 대조 (PDF 는 절대 기준 아님 — 메모리 `feedback_pdf_not_authoritative`).
- `cargo test` 전건 + 신규 clippy 경고 0.

산출물: `mydocs/working/task_m100_846_stage3.md`.

---

## Stage 4 — 종합 검증 및 최종 보고서

작업:
- `cargo test` 전건 최종 통과, 신규 clippy 경고 0.
- shortcut.hwp 1~8페이지 SVG ↔ PDF 최종 정합 확인, before/after 캡처.
- 회귀 대상 샘플 최종 점검.
- 최종 보고서 `mydocs/report/task_m100_846_report.md` — 닫힌 #768 과의 관계, 잔존 한계(있으면) 명기.
- merge 전 `git status` 미커밋 확인. `local/task846` → PR (`planet6897:pr-task846` → `edwardkim/rhwp:devel`, 메모리 `feedback_pr_target_devel` / `feedback_per_task_pr_branch`).

---

## 커밋 규약
- 각 Stage 소스 + `working/task_m100_846_stage{N}.md` 함께 커밋, 메시지 `Task #846: ...`.
- 본 계획서(수행 + 구현) 1커밋. 최종 보고서 커밋 후 PR.
- `mydocs/orders/` 변경 금지 (메모리 `feedback_no_orders_modification`).
36 changes: 36 additions & 0 deletions mydocs/plans/task_m100_849.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# 수행계획서 — Task #849 (M100)

대상: 다단 밴드/단의 실제 채움 높이 산출 정합 — 단 안에 큰 인라인 수식·도형·표 박스가 있을 때 밴드 높이가 과소추정되어 다단 페이지가 과압축되는 결함.
GitHub Issue: edwardkim/rhwp#849 (#846 작업 중 발견된 선행 결함) · 브랜치: `local/task849` (← `local/task846`)

## 브랜치 베이스 — `local/task846` 위

#849 의 효과(특히 `exam_math.hwp` 페이지 수)는 #846 의 `start_new_column_band` 가 적용된 상태에서만 드러난다 (`exam_math` 는 `[다단나누기]` 가 없어 `process_multicolumn_break` 경로를 안 탐). 또한 #849 의 핵심 수정은 밴드 높이 산출을 `process_multicolumn_break` 와 `start_new_column_band` 가 **공유**하도록 하는 것이라 두 코드가 같은 브랜치에 있어야 한다. 따라서 `local/task849` 는 `local/task846` 에서 분기 — 머지 시 task846 → task849 순서로 합류(또는 함께). (메모리 `feedback_branch_base_upstream_devel` 의 취지는 "미반영 누적 `local/devel` 을 base 로 쓰지 말 것"이며, 명확한 의존 관계를 가진 깨끗한 타스크 브랜치 위에 쌓는 것은 예외로 본다 — 이의 있으면 재조정.)

## 결함 요약

`src/renderer/typeset.rs` 가 다단 밴드를 한 페이지에 적층할 때 밴드 높이를 `max(밴드 각 단의 마지막 문단 LINE_SEG vpos_end)` 로 근사한다 (`process_multicolumn_break`, `start_new_column_band`). 단 안에 떠다니는 큰 박스(`Table ... wrap=TopAndBottom tac=false`, 큰 인라인 `Shape 수식` 등)가 있으면 이 추정이 실제 단 채움 길이를 크게 과소추정 → 밴드가 짧게 잡혀 한 페이지에 밴드가 과도하게 들어감.

증상: `exam_math.hwp` — #846 적용 시 18→11페이지 (한컴 PDF 2022 = 20). 페이지 3 단 0(items=38): 산출 밴드 높이 ≈ 710px vs 실제 ≈ 1100px. `21_언어_기출_편집가능본.hwp` 도 페이지 8/9 콘텐츠 시프트(`test_539`/`test_548`).

## 진행 방침

- **Stage 1 — 진단(코드 수정 없음)**: typeset 단계에서 단별 "실제 채움 높이"가 어떻게/어디서 산출·기록되는지 정리 (`current_height` 누적 vs LINE_SEG vpos vs 떠다니는 표/도형 박스 높이). `exam_math.hwp` 페이지 3 단 0 에서 산출 710px ↔ 실제 ~1100px 의 차이가 정확히 어디서 새는지(어떤 박스/문단이 vpos 에 안 잡히는지) 추적. 떠다니는 TopAndBottom 표가 차지하는 vpos 영역이 LINE_SEG 에 반영되는지 / `pending_body_wide_top_reserve` 같은 별도 경로로 처리되는지 확인. 수정 범위(공유 헬퍼 위치, `layout.rs` 연동 필요 여부)·회귀 대상 확정.
- **Stage 2 — 구현**: 밴드 높이 = "그 밴드 각 단에 배치된 모든 항목의 실제 점유 vpos 끝(인라인 수식·도형·표 박스 높이, 떠다니는 TopAndBottom 표 영역 포함)의 최댓값" 으로 산출하는 공유 헬퍼 도입. `process_multicolumn_break` 와 `start_new_column_band` 가 이 헬퍼를 쓰도록. (LINE_SEG 가 이미 박스 높이를 반영하면 헬퍼는 "단의 마지막 항목 vpos_end" 를 모든 단에 대해 정확히 집계하는 것으로 충분 — Stage 1 결과에 따라 확정.)
- **Stage 3 — 광역 회귀 검증**: exam_*, k-water-rfp, 21언어, shortcut, 다단+표분할, 다단+목차, 다단+각주 SVG diff. `exam_math` 페이지 수 PDF(20) 근접 확인. `cargo test` 전건 (#846 에서 발생한 `test_exam_math_page_count`/`test_539`/`test_548` 3건 해소 목표). 메모리 `feedback_essential_fix_regression_risk` 정통 적용.
- **Stage 4 — 종합 검증 및 최종 보고서**: `cargo test` 전건, 신규 clippy 0, exam_math/21언어/shortcut PDF 정합 최종 확인, 회귀 점검, 최종 보고서. #846 합류 가능 상태 확인.
- 밴드 높이 산출이 **단일 룰로 표현 가능한지** Stage 1 에서 판단 — 분기/허용오차/fallback 필요 시 자문 (메모리 `feedback_rule_not_heuristic`).

## 단계 구성 (예정 — 구현계획서에서 확정)

1. **진단**: 단별 실제 채움 높이 산출 경로 정리 + exam_math 과소추정 지점 규명 + 수정 범위 확정. 코드 수정 없음. → `working/task_m100_849_stage1.md`.
2. **구현**: 밴드 높이 공유 헬퍼 도입, `process_multicolumn_break` / `start_new_column_band` 적용.
3. **광역 회귀 검증**: 다단 샘플 전수 SVG diff + exam_math PDF 근접 + `cargo test` 전건.
4. **종합 검증 및 최종 보고서**.

## 검증 기준

- `cargo test` 전건 통과(특히 `test_exam_math_page_count` ≥ 18, `test_539`, `test_548` 복구), 신규 clippy 0.
- `exam_math.hwp` 페이지 수가 한컴 PDF(20) 에 근접 (≥ baseline 18).
- 다단/단일/표분할/목차 기존 샘플 SVG diff 무변화(의도 외).
- #846 의 `start_new_column_band` 가 본 헬퍼를 써서 동작, shortcut.hwp 7페이지 정합 유지.
53 changes: 53 additions & 0 deletions mydocs/plans/task_m100_849_impl.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# 구현계획서 — Task #849 (M100) — v2 (Stage 1 진단 반영, 간소화)

대상: #846 의 `start_new_column_band` 가 단 유형을 구분하지 않아 "일반"(신문형) 단에서 회귀. → `start_new_column_band` 호출을 "배분"(Distribute) 단으로 한정. Issue edwardkim/rhwp#849. 브랜치 `local/task849` (← `local/task846`).

> **v1 → v2**: v1 은 "다단 밴드 높이 산출 정합(공유 헬퍼)"을 가정했으나, Stage 1 진단(`working/task_m100_849_stage1.md`)에서 실제 원인이 단 유형 게이트 누락임이 확인됨. 밴드 높이 정합·`layout.rs` 연동은 불요. 본 v2 가 유효.

---

## Stage 1 — 진단 (완료, 소스 수정 없음)

산출물: `mydocs/working/task_m100_849_stage1.md`. 결과: 원인 = `start_new_column_band` 가 `ColumnType` 무관하게 적용 → 신문형(`Normal`) zone 회귀. 수정 = 호출을 `Distribute` 로 한정. (`exam_math` PDF 20 / shortcut 7 / 21언어 15 / `cargo test` 1232 통과 — 시범 적용 검증 완료.)

---

## Stage 2 — 구현: `start_new_column_band` 를 배분 단으로 한정

작업:
- `paginate` 의 명시적 `Column` break 경로: `start_new_column_band` 호출 조건에 `st.current_zone_column_type == ColumnType::Distribute` 추가. `Normal`(신문형) 은 기존 `advance_column_or_new_page` 유지. `Parallel`(평행) 도 현 동작 유지(범위 밖).
- (그 외 #846 의 `start_new_column_band` 본체·`upcoming_band_has_floating_object`·밴드 높이 산출은 그대로.)

검증: shortcut.hwp 7페이지 + pi=94/95 페이지 3, exam_math 20페이지, 21언어 15페이지, `cargo test` 전건(특히 `test_exam_math_page_count`/`test_539`/`test_548`).

산출물: `mydocs/working/task_m100_849_stage2.md`.

---

## Stage 3 — 광역 회귀 검증

작업:
- 다단 샘플 전수 SVG diff (Stage 2 전/후 — 즉 #846+#849 vs #846 단독, 및 vs baseline): exam_* 류, k-water-rfp, 21언어, shortcut, 다단+TopAndBottom 표, 다단+목차, 다단+각주. `Distribute` zone 의 마지막-단 `[단나누기]` 케이스 외엔 무변화 기대.
- 단일 단(col_count==1) 샘플 일부 — 무변화 확인.
- exam_math/21언어/shortcut SVG ↔ 한컴 PDF 시각 비교 (macOS → 2022 1차, 가능 시 2010/2020 대조; PDF 절대 기준 아님 — 메모리 `feedback_pdf_not_authoritative`).
- `cargo test` 전건 + 신규 clippy 0.

산출물: `mydocs/working/task_m100_849_stage3.md`.

---

## Stage 4 — 종합 검증 및 최종 보고서

작업:
- `cargo test` 전건 최종 통과, 신규 clippy 0.
- exam_math/21언어/shortcut PDF 정합 최종 확인, before/after 캡처.
- 회귀 대상 샘플 최종 점검. #846 합류 가능 상태(`local/task846` + `local/task849` 합치면 회귀 0) 확인.
- 최종 보고서 `mydocs/report/task_m100_849_report.md` — #846 과의 의존·합류 순서 명기.
- merge 전 `git status` 미커밋 확인. 머지 순서: `local/task846` → `local/task849` → `local/devel` → `devel`. PR 대상 `devel` (메모리 `feedback_pr_target_devel`).

---

## 커밋 규약
- 각 Stage 소스 + `working/task_m100_849_stage{N}.md` 함께 커밋, 메시지 `Task #849: ...`.
- 본 v2 계획서는 Stage 1 커밋에 포함. 최종 보고서 커밋 후 PR.
- `mydocs/orders/` 변경 금지 (메모리 `feedback_no_orders_modification`).
Loading
Loading