Skip to content

feat: 표 셀(중첩 포함) picture 복사(Ctrl+C) 지원 + 떠있는 개체 paste cascade (#1161)#1228

Merged
edwardkim merged 7 commits into
edwardkim:develfrom
johndoekim:feat/issue-1161-cell-picture-copy
Jun 1, 2026
Merged

feat: 표 셀(중첩 포함) picture 복사(Ctrl+C) 지원 + 떠있는 개체 paste cascade (#1161)#1228
edwardkim merged 7 commits into
edwardkim:develfrom
johndoekim:feat/issue-1161-cell-picture-copy

Conversation

@johndoekim

Copy link
Copy Markdown
Contributor

요약

표 셀(중첩 표 포함) 안 inline picture 를 객체 선택 후 Ctrl+C 로 복사해도 시스템/내부 클립보드에
저장되지 않던 결함(#1161)을 해소합니다. 추가로 떠 있는 개체 반복 붙여넣기 시 한컴처럼 위치를
계단식으로 어긋내는 cascade offset 을 구현했습니다.

근본 원인

복사 경로의 native 4종(copy_control_native / export_control_html_native /
get_control_image_data_native / get_control_image_mime_native)이 본문 컨트롤만 접근하고
셀 경로(cell_path)를 받지 못했습니다. 더 근본적으로는 렌더 트리 ImageNode 가 TextRun 과 달리
다단계 cellPath 를 보유하지 못해
(단일 레벨 스칼라만) 프런트가 중첩 셀 picture 의 경로를 복원할 수 없었습니다.

변경 내용

영역 내용
document_core/commands/clipboard.rs 복사 native 4종에 cell_path 인자 + 공통 헬퍼 resolve_control_para
document_core/queries/cursor_nav.rs resolve_control_para(빈 경로=본문, 아니면 resolve_paragraph_by_path 위임, 표 셀·글상자 공통)
wasm_api.rs 클립보드 4 래퍼에 cell_path_json 인자(parse_cell_path)
renderer/render_tree.rs + renderer/layout/* ImageNode cell_context 필드 + 셀 picture 생성 chokepoint(layout_picture_full 등 3 site) 채움
document_core/queries/rendering.rs ImageNode 컨트롤 레이아웃에 cellPath:[...] 방출(TextRun 과 동일 포맷)
rhwp-studio/* 선택 ref 가 cellPath 보유 → 복사/오려두기/컨텍스트 메뉴 전 지점 배선 + 타입 보정
clipboard.rs (cascade) 떠있는 개체(treat_as_char=false) 붙여넣기마다 위치 오프셋 누적. inline(글자처럼 취급)은 제외

설계

  • cellPath 단일 진실원: ImageNode cell_context(TextRun 정합)를 권위값으로, 기존 단일 레벨 스칼라는
    innermost 투영으로 유지(하위호환, 회귀 0).
  • inline vs floating(한글 5.0 스펙 표 70 bit 0 "글자처럼 취급"): inline 은 텍스트 흐름이 위치를
    정하므로 cascade 미적용, floating 만 cascade.

#1171 공유 기반

이슈 #1171(사각형→글상자→picture 이중 nested)과 동일 뿌리(ImageNode 다단계 cellPath 부재)입니다.
본 PR 의 ImageNode cell_context + resolve_paragraph_by_path(표 셀·글상자 공통 탐색)가 #1171
기반이 됩니다. 변경이 additive(새 필드+새 방출, 스칼라 불변, chokepoint 1곳)라 #1171 회귀 위험은 낮습니다.

검증

PR 전 체크리스트 (CONTRIBUTING.md):

  • cargo fmt --all -- --check
  • cargo test (0 failed)
  • cargo clippy -- -D warnings (경고 0)

신규 회귀 테스트:

  • tests/issue_1161_copy_picture_in_cell.rs (4) — 셀 복사 / 본문 회귀
  • tests/issue_1161_image_cellpath.rs (1) — pic-in-table-01.hwp p16 의 2단계 중첩 picture 가 2-엔트리 cellPath 방출
  • cascade 단위 테스트 (2) — floating 누적(1000→1567→2134) / inline 불변

TS: WASM 재빌드 후 tsc --noEmit 0 errors.

시각 검증(환경: macOS, rhwp-studio dev): 셀 picture 복사→붙여넣기 정상 + cascade 계단식 동작 확인.

범위 밖 / 후속

  • 표 복사 분기(getSelectedTableRef): 본 PR 은 picture 한정.
  • cut 의 삭제(deletePictureControl cellPath 미지원): 중첩 셀 picture 삭제는 후속. cut 의 복사는 정상화됨.
  • cascade step(567 HU ≈ 2mm): 한컴 정밀 정합은 추후 미세조정 가능.
  • 🔴 별도 이슈 직렬화기 mini_cfb: 출력 >7.14MB 시 DIFAT 미작성으로 CFB 손상 (대용량 저장 데이터 손실) #1227 — 직렬화기 mini_cfb 가 출력 >7.14MB 시 DIFAT 미작성으로 CFB 손상(대용량 저장
    데이터 손실). 본 PR 검증 중 발견했으나 진단 결과 본 변경과 무관한 기존 직렬화 버그로 확인
    (parse_document→bin 추가→serialize_document 만으로 재현). 분리 처리합니다.

관련 이슈

Closes #1161
관련 #1171 (공유 기반 제공)
후속 #1227 (무관한 기존 직렬화 버그)

🤖 Generated with Claude Code

johndoekim and others added 6 commits May 31, 2026 18:37
셀 안 inline picture 복사 결함(본문 컨트롤만 접근)의 native 계층 해소.

- cursor_nav: resolve_control_para(sec,para,cell_path) 헬퍼 신설
  (빈 경로=본문, 아니면 resolve_paragraph_by_path 위임, 다단계 중첩 지원)
- clipboard.rs: copy_control_native / export_control_html_native /
  get_control_image_data_native / get_control_image_mime_native 에
  cell_path 인자 추가, 컨트롤 접근을 헬퍼 경유로 일원화
- wasm_api/main/기존 테스트 호출처는 &[] 전달(컴파일 유지, Stage 2에서 JSON 연결)
- tests/issue_1161_copy_picture_in_cell.rs 신설(재귀 탐색, 중첩 표 대응 4 케이스)

검증: 새 테스트 4 passed, lib clipboard 5 passed, fmt/clippy clean.
수행계획서/구현계획서/Stage1 보고서 동반 커밋.

발견: 샘플 셀 picture 는 2단계 중첩 표 — 프런트 단일레벨 스칼라 ref 로는
도달 불가. Stage 3 착수 시 getPageControlLayout 다단계 cellPath 제공 여부 조사 필요.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- parse_cell_path_arg 헬퍼 신설(빈/"[]"=본문, 그 외 parse_cell_path)
- copyControl / exportControlHtml / getControlImageData / getControlImageMime
  에 cell_path_json: &str 인자 추가(native 정합 순서)
- wasm_api 단위테스트: 빈/"[]" 본문 복사 OK 경로 검증

검증: lib clipboard 6 passed, Stage 1 통합 4 passed, fmt/clippy clean.
구현계획서 v2 + Stage2 보고서 동반 커밋.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
 공유)

중첩 표/글상자 안 picture 가 전체 경로를 못 들고 다니던 결함(ImageNode 가
단일 레벨 스칼라만 보유) 해소.

- render_tree: ImageNode 에 cell_context: Option<CellContext> 추가
  (TextRunNode 정합). 스칼라는 innermost 투영으로 유지(하위호환).
- 셀 picture 생성 3 site 에 cell_context 채움(계약 B):
  layout_picture_full(활성 경로) / make_picture_image_node / table_cell_content
- rendering.rs: ImageNode 방출에 parentParaIdx + cellPath:[...] 추가
  (TextRun 방출과 동일 포맷). 스칼라도 계속 방출.
- tests/issue_1161_image_cellpath.rs: p16 중첩 picture 2-엔트리 cellPath 검증

검증: lib 1471 passed, 통합 0 failed, 1161 테스트(4+1) pass, fmt/clippy clean.
렌더 픽셀 무변경(메타데이터만 추가). Stage3 보고서 동반.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
중첩 셀/글상자 picture 복사가 끝까지 동작하도록 TS 전 경로에 cellPath 전달.

- findPictureAtClick/cursor/mouse: 선택 ref 가 cellPath 보유
  (이미지 선택 site 510/831; shape/line 분기는 edwardkim#1171 영역 미변경)
- pictureCellPathJson(ref) 헬퍼 + writeImageToClipboard cellPathJson 인자
- onKeyDown Ctrl+C/X, onCopy(=onCut 위임), performCopy(=performCut 위임)
  의 copyControl/exportControlHtml/writeImageToClipboard 에 cellPathJson 전달
- wasm-bridge 4 래퍼: 하위호환 trailing cellPathJson='' 인자
- 타입 보정: getSelectedPictureRef 재선언에 outerTableControlIdx + cellPath

검증: WASM 재빌드 후 tsc --noEmit clean(0, canvaskit 기존 오류 제외).
범위 밖: 표 복사 분기, cut 의 delete(중첩 picture 삭제는 별도 후속).
Stage4 보고서 동반.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
반복 붙여넣기 시 떠 있는 개체(treat_as_char=false)가 같은 위치에 겹치던 문제를
한컴처럼 위치 오프셋 누적으로 해소. inline(글자처럼 취급)은 텍스트 흐름이 위치를
정하므로 제외(회귀 위험 0).

- DocumentCore.paste_cascade_count 상태 추가(복사 시 0 리셋)
- paste_control_native: tac=false 개체에 count*PASTE_CASCADE_STEP_HU(~2mm) 가산
- 테스트: floating 누적(1000→1567→2134) / inline 불변(1000×3)

검증: lib clipboard 6 + cascade 2 passed, issue_1161(4+1) 회귀 통과, fmt/clippy clean.
step 값(567 HU ≈ 2mm)은 작업지시자 시각 대조로 미세조정 예정.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
셀(중첩 포함) picture 복사 지원 완료 + cascade 보강. 작업지시자 시각 판정 통과.
저장 시 발견된 대용량 CFB 손상은 edwardkim#1161 무관 기존 직렬화 버그(mini_cfb DIFAT)로
확인되어 신규 이슈 edwardkim#1227 분리 등록.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@edwardkim edwardkim self-requested a review June 1, 2026 12:13
@edwardkim edwardkim added bug Something isn't working enhancement New feature or request labels Jun 1, 2026
@edwardkim edwardkim added this to the v1.0.0 milestone Jun 1, 2026
# Conflicts:
#	mydocs/orders/20260531.md
#	rhwp-studio/src/engine/cursor.ts
#	rhwp-studio/src/engine/input-handler-mouse.ts
#	rhwp-studio/src/engine/input-handler-picture.ts
#	rhwp-studio/src/engine/input-handler.ts
@edwardkim edwardkim merged commit b934187 into edwardkim:devel Jun 1, 2026
7 checks passed
edwardkim added a commit that referenced this pull request Jun 1, 2026
)

@johndoekim. ImageNode cell_context additive, 1933 passed, WASM 재빌드 후 tsc 0 errors.
동작 판정 통과(표 셀 picture 복사). 글상자 그림 선택은 별도 이슈 등록 예정.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@edwardkim

Copy link
Copy Markdown
Owner

머지했습니다(devel b9341872). 감사합니다.

근본 원인(복사 native 4종 cell_path 미수신 + ImageNode 의 다단계 cellPath 부재)을 정확히 짚으셨고, ImageNode cell_context 를 TextRunNode 와 동일 메커니즘으로 추가하면서 기존 단일 레벨 스칼라를 innermost 투영으로 유지한 additive·하위호환 설계가 견고했습니다. #1171 의 공유 기반까지 함께 마련된 점도 좋았습니다.

검증:

  • cargo test --tests 1933 passed — golden SVG 스냅샷 포함 ImageNode 변경 회귀 0
  • issue_1161 회귀 5건(셀 복사 4 + pic-in-table-01 p16 2단계 중첩 cellPath 방출 1)
  • WASM 재빌드 후 rhwp-studio tsc 0 errors(4인자 API 정합 확인)
  • 작업지시자 동작 판정: 표 안 인라인 그림 선택→Ctrl+C→붙여넣기 정상

한 가지 후속: 동작 검증 중 글상자(textbox) 안 그림이 클릭 선택되지 않는 현상을 확인했습니다. 본 PR 범위 밖(글상자 click hit-test = #1171 계열)이라, 별도 이슈 #1229 로 등록했습니다. 본 PR 이 제공한 cellPath 계약 위에서 #1171/#1229 가 이어질 수 있습니다.

신규 클립보드 API 노출을 위해 WASM 을 재빌드했습니다. 감사합니다.

@johndoekim johndoekim deleted the feat/issue-1161-cell-picture-copy branch June 7, 2026 08:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants