Skip to content
Merged
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
5 changes: 5 additions & 0 deletions mydocs/orders/20260626.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# 오늘 할일 - 2026년 6월 26일

## M100 — v1.0.0 조판 엔진 체계화

| Issue | 타스크 | 상태 | 비고 |
|------|--------|------|------|
| #1270 | HWPX 캡션 내 인라인 이미지 렌더링 누락 정정 | 완료 | 인라인 depth 1 구현·검증 완료, 플로팅은 후속. 완료: 10:58 |
## 공통 — 운영 작업

| Issue | 타스크 | 상태 | 비고 |
Expand Down
188 changes: 188 additions & 0 deletions mydocs/plans/task_m100_1270.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
# Task #1270 수행 계획서 — HWPX 캡션 내 인라인 이미지 렌더링 누락 정정

## 이슈 정합

- **Issue**: [#1270](https://github.com/edwardkim/rhwp/issues/1270) — HWPX: 온라인 데모에서 HWPX 1페이지 상단 이미지가 표시되지 않음
- **마일스톤**: M100 — v1.0.0 조판 엔진 체계화
- **작업 브랜치**: `local/task1270`
- **작업 worktree**: `/private/tmp/rhwp-task1270`
- **기준 커밋**: `upstream/devel` `48e96704`
- **대표 첨부**: issue #1270 첨부 HWPX (`서울 문화예술단체 지원사업.hwpx`)
- **메인테이너 확정 방향**: 이번 범위는 캡션 내 `treat_as_char` 인라인 이미지 스레딩만 처리하고, 플로팅 캡션 이미지는 후속 이슈로 분리한다.

## 현상

첨부 HWPX를 rhwp로 SVG 렌더링하면 1페이지 제목 영역의 작은 이미지가 누락된다.

원본 HWPX 구조상 누락 이미지는 다음 위치에 있다.

- 외부 표 첫 번째 페이지 영역 내부의 내부표 캡션
- `<hp:caption side="TOP">` 내부 문단의 `<hp:pic>`
- `binaryItemIDRef="image2"`
- `BinData/image2.png`는 정상 PNG

현재 로컬 재현 결과, 1페이지 SVG에는 `<image>` 요소가 1개만 생성된다. 이는 첫 셀의 `image1`에 해당하며, 캡션 내부 `image2`는 `ImageNode`로 방출되지 않는다.

## 사전 분석

### 원인 후보 확정

`src/renderer/layout/picture_footnote.rs::layout_caption()`은 캡션 문단을 `compose_paragraph()` 한 뒤 `layout_composed_paragraph()`로 넘긴다.

그러나 현재 호출은 마지막 인자들인 원본 문단 `para`와 이미지 데이터 `bin_data_content`를 `None`으로 고정 전달한다.

`src/renderer/layout/paragraph_layout.rs::layout_composed_paragraph()`의 주석과 구현에 따르면:

- `para`: treat_as_char 이미지 인라인 렌더링에 필요한 원본 문단
- `bin_data_content`: 해당 이미지 payload 조회에 필요한 바이너리 데이터

따라서 캡션 문단 안의 컨트롤은 파싱되어도 paragraph layout의 인라인 이미지 렌더링 분기가 활성화되지 않는다.

### 메인테이너 결정 범위

메인테이너 코멘트 기준으로 이번 PR은 다음만 수행한다.

- `layout_caption()`에 원본 캡션 문단 `para`와 `bin_data_content`를 스레딩한다.
- 캡션 내 `treat_as_char` 인라인 이미지를 depth 1로 렌더링한다.
- 인라인 경로는 `layout_caption()`을 재호출하지 않으므로 별도 재귀 가드 없이 depth 1로 제한된다.
- 캡션 속 그림의 캡션은 이번 범위에서 렌더링하지 않는 것이 의도된 동작이다.
- 플로팅 캡션 이미지, 셀 플로팅 배치 로직의 캡션 영역 일반화는 후속 이슈 범위다.

## 작업 목표

캡션 문단 안에 있는 `treat_as_char=true` 이미지가 SVG/렌더 트리에서 누락되지 않도록 한다.

정정 후 기대 상태:

- 캡션 문단의 인라인 그림이 `ImageNode`로 방출된다.
- 기존 본문/셀/글상자 문단의 인라인 그림 렌더링 경로는 유지된다.
- 캡션 안 플로팅 그림은 이번 정정으로 해결하려 하지 않는다.
- 이슈 #1270은 플로팅 후속 범위가 남으므로 이번 작업 완료 후에도 close하지 않는다.

## 범위

### 포함

- `layout_caption()`의 인자 스레딩 구조 진단 확정
- 캡션 문단의 `para` / `bin_data_content` 전달 경로 설계
- `layout_caption()` 호출부 전체 정합화
- 캡션 내 인라인 이미지 회귀 테스트 또는 렌더 산출 비교 추가
- SVG/렌더 트리 기반 집중 검증
- 기존 그림/표/캡션 회귀 테스트 확인

### 제외

- 캡션 내 플로팅 이미지 배치 일반화
- 셀 플로팅 배치 로직의 캡션 영역 적용
- 캡션 속 그림의 캡션 재귀 렌더링
- 첨부 샘플 `image2`의 완전 시각 해소를 이번 PR의 성공 조건으로 삼는 것
- HWPX 파서 구조 변경
- 공통 문서 모델 또는 HWP3 전용 로직 변경

## 의심 코드 영역

| 파일 | 역할 | 확인 포인트 |
|------|------|-------------|
| `src/renderer/layout/picture_footnote.rs` | `layout_caption()` 정의 | `layout_composed_paragraph()`에 `para` / `bin_data_content`를 `None`으로 전달 |
| `src/renderer/layout/paragraph_layout.rs` | 인라인 TAC 이미지 렌더링 | `para` / `bin_data_content`가 Some일 때 `ImageNode` 생성 |
| `src/renderer/layout/table_layout.rs` | 표 캡션 호출 | 표 캡션 경로에서 바이너리 데이터 전달 필요 |
| `src/renderer/layout/table_partial.rs` | 분할 표 캡션 호출 | partial table 캡션 경로 호출부 정합 필요 |
| `src/renderer/layout.rs` | 본문 그림/표 캡션 호출 | 기존 layout entry 경로 호출부 정합 필요 |
| `src/renderer/layout/shape_layout.rs` | 도형 캡션 호출 | 도형/그림형 shape 캡션 호출부 정합 필요 |

## 단계 분리

### Stage 1 — 진단 확정

- 첨부 HWPX의 `image2` XML 위치와 `BinData/image2.png` 정상 여부 기록
- 현재 SVG 1페이지 `<image>` 개수와 누락 상태 기록
- `layout_caption()`의 `None` 전달 지점과 `layout_composed_paragraph()` 인라인 이미지 의존성 확인
- 테스트 fixture 후보와 성공 조건 확정

**산출물**: `mydocs/working/task_m100_1270_stage1.md`

### Stage 2 — 구현 계획서 작성

- `layout_caption()` 시그니처 확장 방식 결정
- 모든 호출부별 `bin_data_content` 전달 가능성 정리
- depth 1 제한이 자연스럽게 유지되는지 확인
- 회귀 테스트 방식 확정
- 검증 명령과 위험 회피책 확정

**산출물**: `mydocs/plans/task_m100_1270_impl.md`

### Stage 3 — 구현 + 집중 테스트

- 승인된 구현 계획에 따라 `layout_caption()` 및 호출부 수정
- 캡션 내 인라인 이미지 회귀 테스트 추가
- 신규 테스트와 대상 경로 집중 테스트 실행
- 첨부 샘플은 “이번 범위로 완전 해소되지 않을 수 있음”을 명시하고 결과를 분리 기록

**산출물**: `mydocs/working/task_m100_1270_stage3.md`

### Stage 4 — 회귀 검증

- 신규 #1270 테스트 실행
- `cargo test --lib` 또는 영향 범위에 맞는 lib/layout 테스트 실행
- 관련 이슈 테스트 선별 실행
- 인라인 그림 중복 방지
- 표 셀 TAC 그림
- 캡션/표 렌더링 경로
- 필요 시 `cargo clippy --lib -- -D warnings`
- SVG 출력에서 기존 1페이지 이미지 방출 상태와 변경 범위 확인

**산출물**: `mydocs/working/task_m100_1270_stage4.md`

### Stage 5 — 최종 보고

- 최종 결과 보고서 작성
- 오늘 할일 문서 완료 상태 갱신
- PR 설명용 요약 작성
- depth 1 인라인 한정
- 플로팅 캡션 이미지는 후속
- #1270은 이번 PR merge 후에도 close하지 않음
- 작업지시자 승인 후 merge/PR 절차 진행

**산출물**: `mydocs/report/task_m100_1270_report.md` + `mydocs/orders/20260626.md` 갱신

## 검증 게이트

| 검증 | 기준 |
|------|------|
| 첨부 HWPX XML 확인 | `image2`가 캡션 문단 안의 그림으로 존재함 |
| 현재 SVG 재현 | 1페이지 기존 출력에서 `image2` 누락 상태 확인 |
| 신규 회귀 테스트 | 캡션 내 `treat_as_char` 이미지가 `ImageNode`로 방출됨 |
| 기존 인라인 이미지 테스트 | 중복 렌더링 또는 위치 등록 회귀 없음 |
| 기존 표/캡션 테스트 | 표 캡션 y/height 회귀 없음 |
| clippy | warning 0 |

## 위험 영역

| 위험 | 가능성 | 회피책 |
|------|--------|--------|
| 캡션 내 TAC 이미지가 기존 shape pass와 중복 렌더링 | 중간 | `inline_shape_position` 등록 여부와 기존 중복 방지 테스트 확인 |
| `cell_ctx` 센티널 변경으로 hit-test/cursor metadata 회귀 | 중간 | 기존 cell context 전달 방식 유지, 인자만 추가 |
| 빈 캡션/텍스트 캡션의 y advance 변화 | 낮음~중간 | `layout_composed_paragraph()`의 기존 y 반환을 유지하고 입력 데이터만 추가 |
| 플로팅 이미지까지 의도치 않게 방출 | 중간 | 테스트와 코드 리뷰에서 `treat_as_char` 경로만 성공 조건으로 제한 |
| 첨부 샘플 완전 해소 여부 혼동 | 높음 | 보고서와 PR 설명에 “플로팅 후속”을 반복 명시 |

## 처리 정합

- 코드 수정은 수행계획서와 구현 계획서 승인 후 진행한다.
- 단계별 완료보고서는 해당 단계 소스 변경과 함께 task 브랜치에서 커밋한다.
- 최종 결과보고서와 오늘 할일 갱신도 task 브랜치에서 커밋한다.
- 이슈 #1270 close는 이번 범위에서 수행하지 않는다.
- PR base는 `devel`로 한다.

## 승인 게이트

1. 본 수행계획서 승인 → Stage 1 진단 확정 진행
2. Stage 1 완료보고서 승인 → Stage 2 구현 계획서 작성
3. 구현 계획서 승인 → Stage 3 구현 시작
4. Stage 3 완료보고서 승인 → Stage 4 회귀 검증
5. Stage 4 완료보고서 승인 → Stage 5 최종 보고
6. 최종 보고서 승인 → PR/merge 후속 절차 진행

## 다음 단계

작업지시자 승인 후 Stage 1 진단 확정을 진행한다.
Loading