Skip to content

Task #741: hwp3-sample10.hwp HWP3 외부 file path + ParaShape tab + 사적 char + 제목차례 장식 + 차례 page 번호 정합 (closes #741)#753

Closed
jangster77 wants to merge 37 commits into
edwardkim:develfrom
jangster77:local/task741
Closed

Conversation

@jangster77

Copy link
Copy Markdown
Collaborator

⚠️ 의존성

본 PR 은 PR #732 (Task #724) 머지 후 적용 요청합니다. 본 PR 은 PR #732 위 분기되어 있으며, PR #732 머지 시 자동으로 base 갱신되어 본 task #741 의 commit 만 남습니다.

요약

hwp3-sample10.hwp (Oracle 기술 문서, 763 페이지) HWP3 native 렌더링 결함 8개 영역 정정. 한컴 viewer 와 동일 수준 시각 정합 도달.

단계별 영역

Stage 영역 commit
1~4 HWP3 외부 file path 그림 IR (ImageAttr.external_path) + image placeholder + TAC 그림 paragraph line_spacing 정합 (ls=600) + HWP5 변환본 paragraph 26 페이지 분할 정합 (vpos-reset 후속 가드) a63114e
5 HWP3 사적 graphic char (0x0080~0x7FFF) cross-ref 매핑 — 표준 KSSM 영역 (0x8000+) 외 한컴 사적 인코딩. 상위 6값 = 98.5% coverage 86bf0bd
6 HWP3 ParaShape tabs[40] → Document IR TabDef 변환 + Hwp3TabDef 필드 순서 bug 정정 (30+ 사이클 미발견 본질 결함) ccbb0b6
7 HWP3 leader → HWP5 fill_type 매핑 (1→3 점선) + 제목차례 자동 장식 inject (한컴 사적 로직 cross-ref) + char_shape 위치 정정 d03109e + b77d071
8 HWP3 차례 inline page 번호 (ch=1) decode + display 6f09ece

핵심 본질 발견

Stage 5 — HWP3 사적 인코딩

HWP3 hchar 0x0080~0x7FFF 범위는 표준 KSSM 조합형 외 한컴 사적 인코딩. johab decoder 가 '?' 반환 → 가로선/▷/■ 등 visible char 누락. 한컴 변환본 cross-ref 로 매핑 자동 도출:

HWP3 ch → Unicode 빈도
0x301C U+F080F (한컴 PUA 가로선) 24,695
0x35E1 U+2500 ─ 892
0x303D U+F0827 (한컴 PUA) 129
0x3479 U+25B7 ▷ 11
0x347A U+25B6 ▶ 4
0x3441 U+25A0 ■ 7

Stage 6 — Hwp3TabDef 필드 순서 bug

기존 (position:u16, type:u8, leader:u8) — 실제 byte stream 어긋남. HWP3_DIAG_TABS 진단으로 default tab pattern (slot N: position=1000×(N+1) hunit) 검증 → 실제 byte 순서 (tab_type:u8, leader:u8, position:u16 LE) 로 정정.

Stage 7 — 한컴 viewer 자동 장식

HWP3 paragraph 26 (cc=8 " 제목차례 ") → 한컴 viewer 가 "════════════════════■ 제목차례 ■══════════════════════" 자동 장식 inject. HWP3 spec 외 한컴 사적 로직 (ParaShape border / char_shape attr 모두 부재 확정). 한컴 변환본 cross-ref 로 trigger 조건 도출 (새번호 + 쪽번호위치 controls + visible text ≤ 6 chars). 보수적 영역으로 광범위 sweep 회귀 위험 최소화.

Stage 8 — 차례 inline page 번호 (ch=1)

HWP3 차례 entries (paragraph 28~339) 가 페이지 번호를 inline ch=1 control 로 저장. HWP3_DIAG_CTRL1 진단으로 byte 패턴 도출 — header_val1 second u16 + ch2 = ASCII digit. 290 ch=1 occurrences 모두 정합. 3-digit 페이지는 ch=1 가 first 2 digit + literal char 로 자연 결합 (paragraph 339 page 757).

정정 영역

파일 변경
src/parser/hwp3/mod.rs Stage 5 (johab decoder) + Stage 6 (convert_para_shape + parse_paragraph_list signature 확장) + Stage 7 (제목차례 inject + char_shape 재구성) + Stage 8 (ch=1 page 번호 decode)
src/parser/hwp3/records.rs Stage 6 (Hwp3TabDef::read 필드 순서 정정)
src/parser/hwp3/drawing.rs Stage 6 (parse_drawing_object_tree / parse_shape_list / map_to_shape_object signature 확장)
src/parser/hwp3/johab.rs Stage 5 (HWP3 사적 graphic char 매핑)
src/model/image.rs Stage 1~4 (ImageAttr.external_path 추가)
src/renderer/render_tree.rs, src/renderer/layout/picture_footnote.rs, src/renderer/layout/table_cell_content.rs, src/renderer/svg.rs Stage 1~4 (image placeholder 렌더링)
src/renderer/typeset.rs Stage 1~4 (vpos-reset 후속 가드)

자료 추가

경로 용도
samples/hwp3-sample10.hwp (945 KB) HWP3 native sample
samples/hwp3-sample10-hwp5.hwp (1.1 MB) 한컴 HWP5 변환본 (cross-ref 권위)
samples/hwp3-sample10-hwpx.hwpx (847 KB) 한컴 HWPX 변환본
pdf/hwp3-sample10-hwp5-2022.pdf (90 MB) 한글 2022 편집기 PDF (PDF 권위 자료, 1-up 인쇄)

⚠️ PDF 90MB — GitHub 권장 50MB 초과. Git LFS 미사용.

검증

  • cargo test --lib --release: 1166 passed (회귀 0)
  • cargo clippy --release --lib: 신규 경고 0
  • 광범위 sweep (devel..HEAD 단계별 8회): 170/170 same diff=0
  • 메인테이너 시각 판정 ★: 한컴 viewer + PDF (한글 2022) 정합 통과
    • 페이지 1: image placeholder 표시
    • 페이지 2: "════════════════════■ 제목차례 ■══════════════════════" 자동 장식 + ▷ markers + 점선 leader + 페이지 번호 (1, 4, 5, ..., 134)

Test plan

후속

  • HWP3 leader 값 2+ (점선/파선) 등장 시 추가 매핑
  • PUA char (U+F080F, U+F0827) 폰트 fallback (별도 task)
  • 다른 HWP3 sample 의 "제목차례 type" 패턴 추가 발견 시 trigger 조건 확장

🤖 Generated with Claude Code

jangster77 and others added 30 commits May 9, 2026 12:01
…loses edwardkim#722)

페이지 8/27/48 의 wrap=Square 그림 paragraph 한컴 PDF 권위 자료 정합 회복.

본질 정정 영역:
- typeset.rs: anchor 다음 paragraph register + anchor host self register
  (image margin_right 추출, LINE_SEG 갯수 + caption_room 가드)
- pagination.rs: WrapAnchorRef.anchor_image_margin_right 필드 추가
- paragraph_layout.rs: wrap_anchor 처리 cs/sw 보정 (inter-image-text gap 3mm)

3 paragraph 정합:
- 페이지 8 paragraph 175 (LINE_SEG 2): image 우측 wrap zone + gap 3mm
- 페이지 27 paragraph 779 (LINE_SEG 1, caption_room>line_height): image 위 caption
- 페이지 48 paragraph 1394 (LINE_SEG 1, caption_room≤line_height): image 우측 wrap zone

검증: 1165 lib + clippy clean + 광범위 sweep 209 fixture DIFF 0 + rsvg-convert PNG
시각 판정 PDF 권위 정합 ★ 통과.

HWP5 변환본 결함 (hwp3-sample5-hwp5.hwp paragraph 441) 은 별도 issue 분리.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…+ HWP3 파서 IR 정합 (closes edwardkim#724)

PR edwardkim#723 (Task edwardkim#722) 후속. HWP5 변환본 paragraph 441 wrap zone 매칭 실패 +
HWP3 파서 sw=0 인코딩 결함 (한컴 HWP5 변환본 IR 정합 sw=51024 위반).

본질 정정:
- typeset.rs: anchor host cs=0 caption-style 매칭 가드 (anchor_image_match)
  + Task edwardkim#321 vpos-reset 가드의 wrap_around 강제 종료 (anchor cs=0 한정)
- parser/hwp3/mod.rs: 빈 paragraph + page break flag 가드 (column_type=Normal +
  force_vpos_reset) + wrap_zone 영역 끝 sw=col_area_width 정합화 +
  wrap_zone 비활성 cs=0/sw=0 정합화

작업지시자 핵심 지적: "HWP3 파서가 잘못해석해서 IR 로 잘못 전달, composer.rs
에서 처리하면 너무 예외" — HWP3 파서 ↔ Document IR 표준 정합 영역 본질 식별.
CLAUDE.md HWP3 파서 규칙 정합 (composer/layout 미수정).

3 paragraph 정합 회복 (HWP3 native):
- 페이지 4 paragraph 75: image 우측 wrap zone 21 lines
- 페이지 9 paragraph 191/192: "루트 파일시스템" 등 표시 회복
- 페이지 16 paragraph 435/441/443: 본문 + image wrap zone

HWP5 변환본:
- 페이지 16 paragraph 441/442/443: image 우측 wrap zone (anchor_image_match)
- 페이지 22 paragraph 599: 페이지 분할 정합

검증: 1166 lib + clippy clean + 광범위 sweep 209 fixture DIFF 0
시각 판정 PDF 권위 정합 ★ 통과.

PR edwardkim#723 (Task edwardkim#722) 머지 후 적용 요청.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
… + vpos-reset 후속 가드

진행 단계:
- Stage 1: 본질 진단 (Document IR Picture + HWP3 파서 그림 + 폰트)
- Stage 2: image placeholder Document IR 확장
- Stage 3: TAC 그림 paragraph line_spacing=600 정합
- Stage 4: 매칭 실패 후 vpos-reset 후속 가드 (HWP5 변환본 paragraph 26)

본질 정정:
- model/image.rs: ImageAttr.external_path 필드 추가
- parser/hwp3/mod.rs: pic_name → external_path 전달, TAC ls=600
- renderer/render_tree.rs: ImageNode.external_path 필드
- renderer/layout/{picture_footnote,table_cell_content}.rs: external_path 전달
- renderer/svg.rs: 빈 binary + external_path placeholder
- renderer/typeset.rs: 매칭 실패 후 vpos-reset 후속 가드
- main.rs: dump 출력 external_path
- paint/json.rs, serializer/hwpx/picture.rs, document_core/commands/object_ops.rs: ImageAttr 구성 정합

검증:
- cargo test --lib --release: 1166 passed
- cargo clippy --release: 신규 경고 0
- 광범위 sweep: DIFF 0 (kps-ai 등 회귀 0)

시각 판정 (한컴 viewer ★):
- HWP3 native + HWP5 변환본 페이지 1 image placeholder 정합
- HWP5 변환본 페이지 2 paragraph 26 (제목차례) 시작 정합

PR edwardkim#732 (Task edwardkim#724) 머지 후 적용 요청.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…s-ref 매핑

본질
- HWP3 hchar 0x0080~0x7FFF 영역은 표준 KSSM 조합형 (0x8000+) 외 한컴 사적
  인코딩. johab decoder 가 '?' 반환 → mod.rs 가 skip → 가로선/▷/■ 등
  visible char 누락.

매핑 도출
- hwp3-sample10.hwp ↔ hwp3-sample10-hwp5.hwp (한컴 변환본) paragraph 별
  cross-ref. 각 ch 값을 5+ paragraphs 에서 동일 Unicode 매핑 검증.
- 매핑 target: PUA 보존 (HWP5 변환본 IR 정합)

상위 6값 매핑 (98.5% coverage)
- 0x301C → U+F080F (한컴 PUA 굵은 가로선, 24695회)
- 0x35E1 → U+2500 ─ (892회)
- 0x303D → U+F0827 (한컴 PUA, 129회)
- 0x3479 → U+25B7 ▷
- 0x347A → U+25B6 ▶
- 0x3441 → U+25A0 ■

검증
- cargo test --lib --release: 1166 passed
- cargo clippy --release --lib: 신규 경고 0
- 광범위 sweep (a63114e..HEAD): TOTAL pages=170 same=170 diff=0

자료 추가
- samples/hwp3-sample10*.hwp/.hwpx (HWP3 native + 한컴 변환본)
- pdf/hwp3-sample10-hwp5-2022.pdf (한글 2022 편집기 PDF 권위)

후속
- Stage 6: ParaShape tab_def 처리 (페이지 번호 우측 정렬 + 가로선 채움)
…Def 변환

본질
- Hwp3TabDef::read 의 필드 순서 bug. 기존 (position:u16, type:u8, leader:u8)
  은 실제 byte stream 과 어긋남. 1076 paragraphs HWP3_DIAG_TABS 진단 결과
  default tab pattern (slot N: position=1000*(N+1) hunit) 검증.
- 실제 byte 순서: tab_type(u8) → leader(u8) → position(u16 LE) = 4 bytes.
- convert_para_shape 가 tabs[40] 무시 → ParaShape.tab_def_id 항상 0.

정정
- records.rs: Hwp3TabDef::read 필드 순서 정정.
- mod.rs: convert_para_shape 가 tabs[40] → TabItem 변환. default tab pattern
  + empty slot 제외, explicit user tab 만 등록.
- mod.rs / drawing.rs: parse_paragraph_list / parse_drawing_object_tree /
  parse_shape_list / map_to_shape_object 시그니처에 doc_tab_defs 추가.
- mod.rs: 최상위 entry 에서 doc_tab_defs Vec 생성 + doc.doc_info.tab_defs 할당.

검증
- paragraph 29 (TOC entry "EXPORT/IMPORT Q & A"): tab_def_id 0→3,
  tabs=[pos=42516 (150.0mm) type=1 (right) fill=1] — A4 content right edge
  (210mm - 30mm×2) 정합.
- cargo test --lib --release: 1166 passed
- cargo clippy --release --lib: 신규 경고 0
- 광범위 sweep (86bf0bd..HEAD): TOTAL pages=170 same=170 diff=0 (회귀 0)

시각 정합 (PDF hwp3-sample10-hwp5-2022.pdf 페이지 2)
- ✓ TOC entries 가로선 leader (──────) 표시
- ✓ 페이지 번호 우측 정렬

잔여 (Stage 6 외)
- HWP3 leader 값 ↔ HWP5 fill_type 정밀 매핑 (HWP3 leader=1 vs HWP5 fill=3)
- 한컴 사적 폰트 fallback (PUA glyph 영역)
…ewer 정합)

본질
- convert_para_shape 가 HWP3 leader 값을 그대로 fill_type 으로 전달.
  HWP3 leader=1 → fill_type=1 (실선) 으로 매핑되어 한컴 변환본 fill_type=3 (점선) 과 불일치.
- HWP3 paragraph 26 (cc=8 " 제목차례 ") 한컴 viewer 가 자동 ═══ ■ 장식 inject.
  HWP3 spec 외 한컴 사적 로직 영역 (ParaShape border/char_shape attr 모두 부재 확정).

진단 영역 도출
- HWP3 leader 값 분포: 5개 sample 합계 39,000+ tabs 중 leader=1 은 19개 (sample10 TOC 만).
  나머지는 leader=0. → HWP3 leader 사실상 0/1 boolean.
- HWP5 fill_type 12종 (svg.rs 정의): 0=없음, 1=실선, 2=파선, 3=점선, 4=일점쇄선, ...
- 매핑: HWP3 leader=1 → HWP5 fill_type=3 (점선) — sample10 paragraph 29 cross-ref.
- 새번호+쪽번호위치 controls 조합 paragraphs (제목 type 후보):
  sample10: paragraph 26 (cc=8 짧은 제목 → HWP5 변환본 ═══ 장식 추가),
            paragraph 340 (cc=30 긴 chapter 제목 → HWP5 변환본 장식 없음)
  나머지 sample: 0개. 차이는 visible text 길이.

정정
- convert_para_shape: leader=1 → fill_type=3 매핑 추가.
- parse_paragraph_list: 제목차례 type paragraph 자동 장식 inject.
  Trigger 조건 (보수적):
    - 새번호 + 쪽번호위치 controls 양쪽 보유
    - whitespace +  제외 visible text ≤ 6 chars (짧은 제목)
  Inject 패턴: ═ × 20 + ■ + " 제목 " + ■ + ═ × 22 (HWP5 변환본 paragraph 26 정합).

검증
- paragraph 26: text " 제목차례 " (cc=8) → "════...■ 제목차례 ■════" (cc=50) — 한컴 정합
- paragraph 29: tab fill=1 → fill=3 — HWP5 변환본 정합
- paragraph 340 (cc=30, 긴 제목): trigger 조건 미충족 → 장식 inject 안 됨 (보수성 정합)
- cargo test --lib --release: 1166 passed
- cargo clippy --release --lib: 신규 경고 0
- 광범위 sweep (ccbb0b6..HEAD): TOTAL pages=170 same=170 diff=0 (회귀 0)

시각 정합 (PDF hwp3-sample10-hwp5-2022.pdf 페이지 2)
- ✓ "════════════════════■ 제목차례 ■══════════════════════" 장식 표시
- ✓ TOC entries 점선 leader (────) fill
- ✓ ▷ markers + 페이지 번호 우측 정렬

후속
- HWP3 leader 값 2~ (점선/파선) 등장 시 추가 매핑
- PUA char (U+F080F, U+F0827) 폰트 fallback — 별도 task
본질
- Stage 7 (d03109e) 제목차례 inject 로 text 50 chars 로 확장됐으나
  hwp3_inline_shapes 가 원본 char index (0,3,8) 그대로 유지 →
  새 텍스트의 ═ 영역에 bold 잘못 적용 (제목차례 자체는 regular).

정정
- Inject 직전 hwp3_inline_shapes 에서 visible 영역 (idx>0 && idx<cc-1)
  shape id 추출 (sample10 p.26 의 경우 id=78 bold).
- Inject 후 hwp3_inline_shapes 재구성:
  - pos 22 (제목 시작): bold shape (추출한 id)
  - pos after_title (■ 시작): rep_char_shape_id (regular)
- hwp3_char_to_utf16_pos 도 새 길이 만큼 1:1 재구성.

검증
- paragraph 26 dump: pos 0 regular, pos 22 bold, pos 27 regular 정합
- 시각: "═══...■ 제목차례 ■═══" 의 "제목차례" 만 bold (한컴 viewer 정합)
- cargo test --lib --release: 1166 passed
- 광범위 sweep (d03109e..HEAD): TOTAL pages=170 same=170 diff=0
- mydocs/report/task_m100_741_report.md: Stage 1~7 통합 최종 보고서
- mydocs/orders/20260509.md: 메인테이너 본인 영역에 Task edwardkim#741 추가
본질
- HWP3 차례 entries (paragraph 28~339) 가 페이지 번호를 inline ch=1 control 로 저장.
  본 환경 catch-all `_` 분기에서 ch=1 처리 시 header_val1 + ch2 값 unused +
  '\u{FFFC}' placeholder push → 차례 page 번호 누락.

Byte 영역 진단 (HWP3_DIAG_CTRL1 임시)
- hwp3-sample10.hwp ch=1 occurrences = 290 (paragraph 29~339).
- 패턴: header_val1 first u16 = 0x0009 (page reference marker),
        header_val1 second u16 = digit1 ASCII (0x0030~0x0039),
        ch2 = digit2 ASCII OR 0x000D (1-digit terminator).
- 3-digit 페이지: ch=1 가 first 2 digit 만 저장, 세 번째 digit 은 literal char
  로 paragraph text 안에 별도 저장 → 자연 정합.

정정
- mod.rs match arm 에 ch=1 별도 분기 추가. header_val1 second u16 + ch2
  decode 후 page_str (1~2 digit ASCII) 을 text_string 에 직접 push.
- '\u{FFFC}' placeholder + Unknown control push 회피.

검증
- paragraph 29 (page 1): "...\t" → "...\t1"
- paragraph 50 (page 45): "...\t" → "...\t45"
- paragraph 339 (page 757): "...\t7" → "...\t757" (3-digit literal 자연 결합)
- cargo test --lib --release: 1166 passed
- cargo clippy --release --lib: 신규 경고 0
- 광범위 sweep (b793ad5..HEAD): TOTAL pages=170 same=170 diff=0

시각 정합 (PDF hwp3-sample10-hwp5-2022.pdf 페이지 2)
- ✓ TOC entries 페이지 번호 모두 표시 (1, 4, 5, ..., 134)
- ✓ 한컴 viewer + HWP5 변환본 정합

후속
- 4-digit 페이지 번호 (1000+) 등장 시 추가 verification
- ch=1 외 다른 inline reference control 등장 시 동일 패턴 처리
- Stage 8 (6f09ece) HWP3 차례 inline page 번호 (ch=1) 정합 영역 반영
- mydocs/report/task_m100_741_report.md: Stage 8 본질 결함 + 정정 영역 추가
- mydocs/orders/20260509.md: Task edwardkim#741 Stage 8 본문 갱신
…ttr external_path 누락 정정

본질
- Stage 1~4 (a63114e) 에서 ImageAttr 에 external_path 필드 추가했으나
  tests/issue_516.rs 의 4개 ImageAttr 구성 중 3곳 (struct literal) 누락.
- 본 환경 검증 시 cargo test --lib --release 만 실행 → /tests/ integration
  test 가 skip 되어 결함 미발견. CI 의 cargo test --verbose 에서 발견.

정정
- tests/issue_516.rs 3곳 ImageAttr literal 에 external_path: None 추가.
- 4번째 (gray_only) 는 ..ImageAttr::default() spread 사용 → 자동 정합.

검증
- cargo test --release: 총 1274 passed (lib 1166 + integration 108)
- 광범위 sweep 회귀 영역 무관 (test 파일만 변경)

후속
- 본 환경 검증 절차에 cargo test --release (lib + integration) 통합 영역
  반복 발견 패턴 — fixture cargo test --lib 만 사용 시 integration tests
  수정사항 미발견 위험.
…am_science 5번/8번/12번 클립핑 정정

본질
- PR edwardkim#723 (Task edwardkim#722) 머지 후 메인테이너 광범위 sweep 에서 발견 (PR edwardkim#723 보고서):
  exam_science.hwp 1, 2, 8 페이지 — 5번/8번/12번 문항 지문과 그림 배치 영역
  에서 지문 왼쪽 끝 경계 글자 클립핑 회귀 (HWP3 native sweep diff 2건).
- 진단 영역 — Task edwardkim#722 typeset.rs Block 2 (host_self register, 786~) 가
  exam_science p.21 (5번)/p.37 (8번)/p.60 (12번) 의 Square wrap picture
  (image_voff=0, image_mr=0) 에서 fire → wrap_anchor 등록 후 paragraph_layout
  의 wrap_anchor 분기에서 line cs/sw 본 sample line_seg 인코딩 (sw=19592 등)
  으로 layout → text justification 영향 → 글자 위치 ±2~13px 시프트 + 좌측
  경계 클립핑.

가드 영역
- Task edwardkim#722 의 본질 (sample5 page 8/27/48) 영역 image_mr > 0 (image margin
  부재 아님) → 가드 통과, host_self register 정합 보존.
- exam_science 의 회귀 영역 image_mr = 0 (image margin 없음, line_seg 가
  이미 wrap zone 정합) → 가드 차단, OLD 의 col_area-full-width layout 정합
  복원.

검증
- exam_science 1, 2 페이지: feb11e7 baseline 정합 회복 (diff 0)
- sample5 page 8/27/48: ab910d6 (Task edwardkim#722 본질) 정합 보존 (diff 0)
- exam_eng/aift/synam-001 등 다른 sample: 본 가드 영향 없음 (HEAD 의 다른
  PR merge 영역 기존 diff 와 동일)
- cargo test --lib --release: 1173 passed
- cargo clippy --release --lib: 신규 경고 0

후속
- 메인테이너 광범위 sweep 에서 exam_eng/aift/synam-001 영역의 다른 diff
  (HEAD 의 multiple devel merge 영역 기존) 확인 필요 시 별도 task.
…alog 정정

본질
- Stage 1~4 (a63114e) 영역 ImageAttr.external_path 영역 IR 추가 + svg.rs renderer
  영역 placeholder 구현. 그러나:
  (a) src/renderer/web_canvas.rs 영역 image rendering 영역 if let Some(data) 분기 만,
      external_path 영역 fallback 영역 부재 → rhwp-studio 영역 외부 file path 그림 표시 부재.
  (b) rhwp-studio/src/ui/picture-props-dialog.ts 영역 fileNameInput 영역 hardcoded
      "(문서에 포함된 그림)" + embedCheck.checked=true → IR 영역 의 external_path 영역
      반영 부재.

정정
- src/renderer/web_canvas.rs: image data 부재 + external_path 보유 시 placeholder
  영역 (회색 점선 사각형 + "[외부: <path>]" 텍스트) 영역 렌더링. svg.rs:1075~ 영역 정합.
- src/document_core/commands/object_ops.rs: get_picture_properties_native JSON
  출력 영역 externalPath 필드 추가 (Some 시만, json_escape).
- rhwp-studio/src/core/types.ts: PictureProperties 영역 externalPath?: string 추가.
- rhwp-studio/src/ui/picture-props-dialog.ts: picFileNameInput / picEmbedCheck 영역
  class property 영역 변경 + populateFromProps 영역 props.externalPath 영역 보유 시
  file path + embed=false 갱신 (hardcoded 제거).

검증
- cargo test --release: 1337 passed
- tsc --noEmit: clean
- npm run build: 성공

후속 (별도)
- setPictureProperties 영역 영역 externalPath 영역 영역 변경 영역 (현재 readOnly 영역 영역 보존)
- web_canvas placeholder 영역 의 file path 영역 영역 텍스트 줄바꿈 영역 (긴 path 영역 영역
  다중 line 영역)
…f / s1.jpg) 추가

본질
- hwp3-sample10.hwp 영역 외부 file path 영역 영역 image 파일. Stage 1~4 (a63114e)
  영역 ImageAttr.external_path 영역 영역 file path 영역 IR 보존 영역. 다른 환경 영역 의
  본 fixture 영역 영역 영역 영역 placeholder 영역 영역 영역 의 file path 표시 영역
  검증 영역 + 향후 web_canvas 영역 영역 실제 image load 영역 검증 영역 영역.

추가
- samples/oracle.gif (1.8 KB) — Oracle 로고
- samples/rdb02.gif (6.1 KB) — 데이타베이스 다이어그램
- samples/s1.jpg (16 KB) — 창원대학교 데이타베이스 연구실
…PI + Vite middleware + 한컴 viewer 정합 dialog

본질
- HWP3 file binary 영역 image 영역 영역 영역 영역 절대 경로 (예:
  "D:\\Work\\Gwjang\\temp\\images\\rdb02.gif") 영역 저장 영역. Stage 1~4 (a63114e)
  영역 IR 영역 external_path 보존 영역, 실제 image binary 영역 영역 자동 load 부재.
  rhwp-studio 영역 영역 dialog 영역 영역 hardcoded "(문서에 포함된 그림)" + image 표시 부재.
- 사용자 시각: HWP file 영역 영역 같은 dir 영역 image (samples/oracle.gif 등) 영역
  영역 한컴 viewer (Windows) 영역 영역 영역 영역 영역 자동 load 영역 표시.
- 한컴 viewer 정합: 원본 절대 경로 영역 영역 access 부재 시 HWP file 영역 영역 같은 dir
  영역 image 영역 발견 영역 영역 dialog 영역 영역 영역 의 path 영역 resolved local path
  영역 영역 갱신.

정정 영역

(1) Native CLI 영역 (src/model/document.rs + src/document_core/commands/document.rs + src/main.rs)
- Document::populate_external_images_from_dir(base_dir) helper. external_path
  영역 영역 basename 추출 (Windows / Unix 모두 대응) → base_dir 영역 영역 file 영역
  fs::read → bin_data_content 영역 영역 (id-1) index 영역 update + external_path 영역
  resolved local path 영역 영역 갱신 (한컴 viewer 정합).
- DocumentCore::populate_external_images_from_dir + document_mut() 영역 노출.
- main.rs: export-svg 영역 영역 doc 로드 후 자동 호출 (HWP file 영역 parent dir).

(2) WASM API 영역 (src/wasm_api.rs)
- getExternalImageBasenames(): 외부 file path 그림 영역 영역 영역 영역 basename 목록
  (JSON 배열) 반환 — JS 영역 영역 영역 영역 fetch 영역 영역 영역 영역.
- injectExternalImage(basename, data, display_path): JS 영역 영역 fetch 한 binary 영역
  IR 영역 inject + external_path 영역 display_path 영역 영역 갱신 (한컴 viewer 정합).
  display_path 빈 문자열 영역 fallback `/samples/<basename>` 영역.

(3) rhwp-studio 영역
- vite.config.ts: /samples/* 경로 영역 영역 parent samples/ dir 영역 영역 정적 serve
  middleware 영역. response header `X-File-Path` 영역 영역 OS 절대 경로 노출.
- core/wasm-bridge.ts: loadDocument 후 populateExternalImagesFromDevServer() 자동
  호출 — getExternalImageBasenames → fetch → X-File-Path header 영역 영역 → injectExternalImage.
- ui/picture-props-dialog.ts: props.externalPath 영역 영역 그대로 표시 (resolved
  path — 한컴 viewer 정합). hardcoded "(문서에 포함된 그림)" 제거.

(4) 한컴 PDF 갱신
- pdf/hwp3-sample10-hwp5-2022.pdf: 외부 image 영역 영역 한글 2022 영역 영역 영역 영역
  영역 영역 표시 영역 영역 PDF 갱신.

검증 (결정적 + 시각 ★)
- 본 환경 export-svg → 페이지 1 영역 ORACLE 로고 + 데이타베이스 다이어그램 +
  학생 그림 모두 표시 영역 (PDF 권위 정합).
- rhwp-studio: 작업지시자 시각 판정 통과 — 외부 image 영역 표시 영역 + dialog 영역
  resolved local path 표시 (예: /Users/.../samples/rdb02.gif).
- cargo test --release: 1339 passed
- cargo clippy --release --lib: 신규 경고 0
- tsc --noEmit: clean
- npm run build: 성공
- 광범위 sweep (origin..HEAD): 170/170 same / diff=0 (회귀 0)

후속 (별도 task 영역)
- main.rs 영역 다른 명령 (export-pdf, dump 등) 영역 영역 동일 호출 추가 영역.
- WASM 영역 영역 file picker 영역 영역 다중 파일 영역 영역 (HWP + images) 영역 영역
  upload 영역 — production 환경 영역 영역.
…ac/Windows race condition 정합)

WasmBridge.populateExternalImagesFromDevServer 영역 fire-and-forget async 영역
영역 영역, Windows 환경 영역 영역 inject 완료 시점 영역 initial canvas render
완료 시점 영역 race 영역 영역 그림 영역 영역 영역 영역 영역. Mac 영역 영역
빠른 영역 영역 inject 영역 render 영역 영역 영역 영역 정상 영역.

수정 영역:
- WasmBridge.setEventBus(bus) 영역 추가 — main.ts 영역 영역 영역.
- populateExternalImagesFromDevServer 영역 inject 완료 후 injectedAny>0 영역 영역
  eventBus.emit('document-changed') 호출 → canvas-view.refreshPages() trigger.

EventBus 영역 'document-changed' 영역 영역 영역 dialog/command 영역 영역 사용 영역
패턴 영역 영역.
edwardkim added a commit that referenced this pull request May 10, 2026
GitHub 권장 50 MB 초과 PDF 영역 영역 일반 git history 영역 영역 누적 부담 차단.

본 환경 영역 영역:
- 기존 pdf/ (한글 2022) / pdf-2020/ / pdf-2010/ 영역 영역 일반 git 영역 영역 보존 (< 50 MB)
- 신규 pdf-large/ 영역 영역 50 MB 초과 PDF 만 배치 (LFS 자동 추적)

.gitattributes 영역 영역 패턴: pdf-large/**/*.pdf filter=lfs diff=lfs merge=lfs -text

장기 정합:
- 저장소 일반 history 영역 영역 큰 파일 미진입
- LFS 한도 (1 GB 무료) 영역 영역 효율적 활용
- 컨트리뷰터 fork clone 영역 영역 LFS 인프라 부재 영역 영역 placeholder 영역 영역 처리 가능

PR #753 (Task #741) 의 hwp3-sample10-hwp5-2022.pdf (96 MB) 영역 영역 본 폴더 영역 영역 배치 적용 예정.
edwardkim pushed a commit that referenced this pull request May 10, 2026
…누락 정정

본질
- Stage 1~4 (a63114e) 에서 ImageAttr 에 external_path 필드 추가했으나
  tests/issue_516.rs 의 4개 ImageAttr 구성 중 3곳 (struct literal) 누락.
- 본 환경 검증 시 cargo test --lib --release 만 실행 → /tests/ integration
  test 가 skip 되어 결함 미발견. CI 의 cargo test --verbose 에서 발견.

정정
- tests/issue_516.rs 3곳 ImageAttr literal 에 external_path: None 추가.
- 4번째 (gray_only) 는 ..ImageAttr::default() spread 사용 → 자동 정합.

검증
- cargo test --release: 총 1274 passed (lib 1166 + integration 108)
- 광범위 sweep 회귀 영역 무관 (test 파일만 변경)

후속
- 본 환경 검증 절차에 cargo test --release (lib + integration) 통합 영역
  반복 발견 패턴 — fixture cargo test --lib 만 사용 시 integration tests
  수정사항 미발견 위험.
edwardkim added a commit that referenced this pull request May 10, 2026
PR #753 영역 영역 hwp3-sample10-hwp5-2022.pdf (96 MB) 영역 영역 GitHub 권장 50 MB 초과
영역 영역 pdf-large/ 폴더 한정 LFS 추적 정책 영역 영역 도입.

CLAUDE.md 의 '예제 폴더' + 'PDF 권위 자료 명명 규약' 갱신:
- pdf/ / pdf-2020/ / pdf-2010/ — 일반 git (< 50 MB)
- pdf-large/ — Git LFS (≥ 50 MB)

Clone / Fork 시 LFS 미설치 환경 영역 영역:
- pdf-large/ 영역 영역 placeholder 만 진입 (135 byte)
- 실제 PDF 영역 영역 'git lfs install && git lfs pull' 영역 영역 다운로드
edwardkim added a commit that referenced this pull request May 10, 2026
…렌더링 8 단계 정정 + Git LFS 구축

PR #753@jangster77 (HWP3 핵심 컨트리뷰터) 영역 영역 Oracle 기술 문서 (763 페이지) HWP3 native 렌더링 결함 8개 영역 정정.

본 PR 영역 영역 부수 영역 — Git LFS 영역 영역 pdf-large/ 폴더 한정 격리 영역 영역 신규 구축:

8 단계 본질 정정:
- Stage 1~4: HWP3 외부 file path 그림 IR + image placeholder + TAC line_spacing + vpos-reset 후속 가드
- Stage 5: HWP3 사적 graphic char (0x0080~0x7FFF) cross-ref 매핑 (한컴 변환본 cross-ref, 상위 6값 = 98.5% coverage)
- Stage 6: HWP3 ParaShape tabs[40] → TabDef + Hwp3TabDef 필드 순서 bug 정정 (30+ 사이클 미발견 본질 결함)
- Stage 7: HWP3 leader 매핑 + 제목차례 자동 장식 inject (한컴 사적 로직)
- Stage 8: HWP3 차례 inline page 번호 (ch=1) decode

후속 commits:
- 외부 그림 영역 native CLI 자동 load + WASM API + Vite middleware + rhwp-studio web canvas + dialog 정정
- 외부 그림 fixture 3개 (oracle.gif / rdb02.gif / s1.jpg)
- CI fix (tests/issue_516.rs)

Git LFS 신규 구축:
- pdf-large/ 폴더 한정 추적 (pdf-large/**/*.pdf filter=lfs ...)
- pdf/hwp3-sample10-hwp5-2022.pdf (96 MB) 영역 영역 pdf-large/ 영역 영역 LFS pointer 영역 영역 직접 배치
- 기존 pdf/ (한글 2022) / pdf-2020/ / pdf-2010/ 영역 영역 일반 git 영역 영역 보존 (< 50 MB)

검증:
- cargo build --release ✅
- cargo test --release ALL GREEN
- tsc --noEmit ✅ (WASM 빌드 후)
- 광범위 sweep 170/170 same diff=0
- WASM 4.68 MB
- hwp3-sample10 native svg export 페이지 1/2 정합
- 작업지시자 웹 에디터 시각 판정 ✅ 통과 (한컴 viewer + PDF 한글 2022 정합)

CLAUDE.md 영역 영역 pdf-large/ 폴더 정책 + 명명 규약 추가.

closes #741
@edwardkim

Copy link
Copy Markdown
Owner

@jangster77 검토 완료했습니다. 감사합니다.

처리 결과

Merge commit: a90ecd09 (devel)

본질

Oracle 기술 문서 (763 페이지) HWP3 native 렌더링 8 단계 정정 — 한컴 viewer + PDF (한글 2022) 영역 정합. Hwp3TabDef 필드 순서 bug (30+ 사이클 미발견 본질 결함) 정정 영역 영역 인상적입니다.

Git LFS 신규 구축 — pdf-large/ 폴더 한정 격리

PR 본문 영역 명시된 PDF 96 MB (GitHub 권장 50 MB 초과) 영역 영역 본 환경 영역 영역 Git LFS 영역 영역 신규 구축:

  • 메인테이너 commit fe4676c3 영역 영역 .gitattributes 패턴 (pdf-large/**/*.pdf filter=lfs) + pdf-large/README.md 영역 영역 폴더 정책 문서
  • PDF 영역 영역 pdf-large/hwp3-sample10-hwp5-2022.pdf 영역 영역 LFS pointer 영역 영역 직접 배치 (cherry-pick 시 영역 영역 메인테이너 영역 영역 처리)
  • CLAUDE.md 영역 영역 pdf-large/ 정책 + 명명 규약 추가 (commit 80eccfef)
  • 기존 pdf/ / pdf-2020/ / pdf-2010/ 영역 영역 일반 git 영역 영역 보존 (< 50 MB)

LFS 업로드 96 MB 완료. 향후 50 MB 초과 PDF 영역 영역 pdf-large/ 영역 영역 직접 배치 시 자동 LFS 처리됩니다.

Cherry-pick 결과

Task #741 본질 commits 11개 + 메인테이너 chore 2개 (.gitattributes / CLAUDE.md):

Stage 내용 author
1~4 HWP3 외부 file path + image placeholder + TAC line_spacing + vpos-reset 후속 가드 @jangster77
5 HWP3 사적 graphic char (0x0080~0x7FFF) cross-ref 매핑 @jangster77
6 ParaShape tabs[40] → TabDef + Hwp3TabDef 필드 순서 bug 정정 @jangster77
7 HWP3 leader 매핑 + 제목차례 자동 장식 inject @jangster77
8 HWP3 차례 inline page 번호 (ch=1) decode @jangster77
후속 외부 그림 native CLI + WASM API + Vite middleware + dialog @jangster77
CI fix tests/issue_516.rs @jangster77

ab2fa527 (PR #732 후속 typeset.rs host_self register) 영역 영역 devel 25299a5b 영역 영역 이미 적용 영역 영역 skip.

검증

  • cargo build/test --release ✅ ALL GREEN
  • tsc --noEmit ✅ (WASM 빌드 후)
  • 광범위 sweep 170/170 same diff=0
  • WASM 4.68 MB
  • hwp3-sample10 native svg export 페이지 1/2 정합
  • 작업지시자 웹 에디터 시각 판정 ✅ 통과

closes #741.

5/10 사이클 — HWP3 핵심 영역 영역 본질 정정 영역 영역 인상적입니다. 수고하셨습니다.

@edwardkim

Copy link
Copy Markdown
Owner

Merged. Merge commit: a90ecd0

@edwardkim edwardkim closed this May 10, 2026
edwardkim added a commit that referenced this pull request May 10, 2026
PR #753 (closes #741) 처리 보고서 + 검토 문서 archives 이동 + 5/10 orders 영역 영역 PR #753 행 추가.
hwp3-sample10.hwp HWP3 native 렌더링 8 단계 정정 + Git LFS pdf-large/ 폴더 한정 격리 신규 구축.

Merge commit: a90ecd0
Cherry-pick: 81c16cf + e184718 + 1348d93 + d574cf1 + d2ddb3b + 639088a + 0213037 + dd71507 + 4bfcee0 + 314bb12
메인테이너 chore: fe4676c (.gitattributes + pdf-large/README) + 80eccfe (CLAUDE.md)
Skipped: ab2fa52 (devel 25299a5 이미 적용)
edwardkim added a commit that referenced this pull request May 10, 2026
5/10 + 5/11 사이클 누적 — 외부 기여자 다수 PR 30+ 머지.

Cargo.toml + rhwp-vscode/package.json + npm/editor/package.json + rhwp-studio/package.json: 0.7.10 → 0.7.11
rhwp-vscode/CHANGELOG.md: [0.7.11] 항목 추가

핵심 변경:
- Skia native raster P8 (#761) + P9 (#769) — Layer IR contract hardening + text replay parity
- HWP3 native 렌더링 (#753) — hwp3-sample10 8 단계 정정 + Git LFS pdf-large/ 신규
- 페이지네이션 정정 (#778) — Task #703 다단 컬럼 분배 회귀 정정
- rhwp-studio 인터랙션 (PR #781/#786/#787/#788) — scrollbar/수식/표 셀/도구 모음 결함 정정
- rhwp-studio editor 신규 기능 (PR #728/#748/#750/#760 등) — 표 편집 Undo/Redo + 다단 설정 + 다수 단축키
@edwardkim edwardkim mentioned this pull request May 10, 2026
4 tasks
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