Task #460: HWP 3.0 파서 + Square wrap 그림 어울림 렌더링#506
Task #460: HWP 3.0 파서 + Square wrap 그림 어울림 렌더링#506edwardkim merged 51 commits intoedwardkim:develfrom
Conversation
- src/parser/hwp3/ 신규: 9개 파일 (mod, records, paragraph, encoding, johab, johab_map, special_char, drawing, ole) · parse_hwp3() → Document IR 변환 파이프라인 구현 · Johab 조합형 → UTF-8 디코딩 · 표/그림/그리기 객체/머리말꼬리말/각주미주 기본 파싱 · debug println! 4건 제거 + clippy 오류 3건 수정 - src/parser/mod.rs: FileFormat::Hwp3 → parse_hwp3() 라우팅 - src/bin/dump_pictures.rs: 그림 덤프 유틸 신규 - samples/hwp3-sample.hwp: 테스트용 HWP3 샘플 파일 (87KB) - mydocs/: 수행/구현계획서, Stage1 완료보고서, 오늘할일 신규 hwp3-sample.hwp export-svg: 20페이지 SVG 생성 성공 cargo test --lib: 1016 passed / cargo clippy: clean Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- picture_footnote.rs: Para-relative 그림 반환 y를 base_y 기준으로 수정 (이전: y_offset+total_height → 후속 단락이 그림 위로 겹침) - paragraph_layout.rs: 캡션 AutoNumber 위치에 U+FFFC 처리 추가 (HWP3는 AutoNumber 위치를 U+FFFC로 저장, HWP5 " " 패턴과 별도 처리) - hwp3/mod.rs: caption.width=0 → pic.common.width로 보정 (캡션 렌더링 복원) - hwp3/mod.rs + parser/mod.rs: HWP3 그림 카운터 방식 수정 (HWP3는 Control::Picture 개체 자체가 카운터를 올림 — 캡션 유무 무관) 꼬리말 로고(tac=true)가 카운터 1을 선점하여 본문 그림은 2부터 시작 → 그림 번호 한컴과 일치: 그림2/3/4/5 (이전: 그림1/2/3/4) - pagination/engine.rs: Para-relative vert_offset 처리 주석 추가 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
추가정보블록 #1 TagID 3 (하이퍼텍스트 정보) 파싱 추가 — 스펙 §8.3. 각 항목 617바이트: data[0..256]=파일명(URL, kchar, null종료). 추가정보블록 순서가 본문 하이퍼링크 등장 순서와 일치하므로 순서 매핑으로 Control::Hyperlink.url에 설정. (hwp3-sample.hwp에는 하이퍼링크 없어 직접 검증 불가) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…기 제거)
- src/parser/hwp3/mod.rs: ch=18(AutoNumber) 시 U+FFFC 대신 ' ' push
→ 캡션 "그림 " + ' ' = "그림 " — HWP5/HWPX " " 패턴과 일치
- src/renderer/layout/paragraph_layout.rs: '\u{fffc}' 전용 탐색 분기 제거
→ HWP5/HWPX/HWP3 공통 " " 패턴 단일 경로로 통합
- cargo test --lib: 1068 passed, 0 failed
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- fixup_hwp3_mixed_para_line_segs() 추가 (src/parser/hwp3/mod.rs 하단) Para-relative TopAndBottom non-TAC 그림 구역을 탐색하여 마지막 그림-위쪽 LINE_SEG의 line_height를 그림 하단까지 확장 (예: seg[5] 36700 HU = 489.3px → 렌더러 y+= 점프 → 겹침 해소) - text_height=0 설정으로 document.rs advance=lh+ls 공식 보장 - cargo test --lib: 1068 passed, 0 failed Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- cargo test --lib: 1068 passed, 0 failed - cargo clippy: clean - export-svg hwp3-sample.hwp: 22페이지, 그림 겹침 없음 - HWP5/HWPX 5종 회귀 없음 - 수행계획서/구현계획서/최종보고서/오늘할일 갱신 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…p 하단 제한) - HWP3 표 셀 border_fill_id: push 후 len()-1(0-기반) → len()(1-기반)으로 수정 (렌더러가 border_fill_id-1로 인덱스 접근하므로 1-기반이 정상) - layout body clip: expand_clip 후 body_bottom+10px 초과 하방 확장 제한 (대형 부동 그림이 꼬리말 영역까지 body clip을 확장하던 문제 해소) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… 해소) - percent 줄간격 시 line_spacing = lh - th (600 HU) → 0 으로 수정 - HWP5 IR 모델에서 percent 줄간격은 line_height에 이미 반영되어 있으므로 line_spacing = 0 이어야 함 (렌더러: y += lh + ls) - 결과: 줄 이동 2200 HU → 1600 HU, 17×2 bibliography 표 텍스트 겹침 해소 - 전체 페이지 22 → 16으로 감소 (과도한 셀 높이 해소) - 1068 tests passed Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
비-TAC TopAndBottom VertRelTo::Para 그림을 가진 anchor 문단이 페이지 하단에서 텍스트+그림 합산 높이로 페이지를 초과할 때 선제적 쪽 나눔을 적용. anchor 문단과 그림이 동일 페이지에 배치되어 그림 분할 현상 해소. hwp3-sample.hwp: 16페이지→17페이지 (pi=41 그림이 페이지2에서 페이지3으로 이동). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
HWP3 binary의 LINE_SEG break_flag bit 0이 word processor의 레이아웃 결정 (새 페이지 배치)을 인코딩한다. 비-TAC TopAndBottom 그림 문단에서 이 플래그를 column_type = Page로 변환 → TypesetEngine이 기존 force_page_break 경로로 처리. 렌더러 수정(TypesetEngine 선제적 쪽 나눔 +27줄)은 롤백하고, pagination/engine.rs의 동일 dead-code도 제거(-45줄). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- border_fill_id 버그 수정: len() → (len()-1) (0-기반 인덱스) - Stage 2 fixup_hwp3_mixed_para_line_segs 제거 (OVERFLOW 원인) - Stage 6 break_flag 기반 column_type 교체 → Fix 2로 대체 - Fix 1: th=0 자리차지 LINE_SEG 방어 코드 - Fix 2: 단일 LINE_SEG 비-TAC TopAndBottom 그림 문단 → column_type=Page - 렌더러 변경 없음 (hwp3/ 디렉토리만) 결과: 17페이지, LAYOUT_OVERFLOW 0건 (꼬리말 36px 기존 경고 제외) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Stage 7에서 border_fill_id를 (len()-1)(0-based)로 변경하였으나, 렌더러(table_partial.rs)는 1-based 규칙(id>0 → border_fills[id-1])을 사용. 0-based로 변경하면 id=0이 되어 렌더러가 테두리 없음으로 처리하거나 이전 셀 border_fill을 엉뚱하게 참조 → 참조 표에 불필요한 선 표시 발생. - border_fill_id = doc_border_fills.len() (1-based) 복원 - TAC 셀 border_fill 직접 조회: get(id as usize) → get(id.saturating_sub(1) as usize) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
HWP3 파일을 열고 저장할 때 올바른 HWP5 CFB 파일이 생성되도록 처리. 변경 사항: - src/parser/hwp3/mod.rs: header.raw_data에 HWP5 헤더(256바이트) 설정 - 직렬화기가 raw_data 우선 사용 → version=5 CFB 파일 출력 - 메모리의 version.major=3은 유지(assign_auto_numbers HWP3 감지용) - HWP3→HWP5 라운드트립 테스트 추가 - src/document_core/converters/hwpx_to_hwp.rs: Hwp3 출처도 어댑터 적용 - convert_if_hwpx_source: Hwpx | Hwp3 → SectionDef 삽입 + 표 raw_ctrl_data 합성 - tests/hwpx_to_hwp_adapter.rs: no-op 메시지 문자열 갱신 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…비트필드) HWP3 그림/표 파싱 시 CommonObjAttr 개별 필드(vert_rel_to, text_wrap 등)는 올바르게 설정되었으나 직렬화에 사용되는 attr 비트필드가 0으로 남아 있어 HWP5 저장→재열기 후 vert_rel_to=Paper, text_wrap=Square로 복원되고 pushdown_h가 발동되지 않아 그림이 표를 겹치는 문제를 수정. build_common_obj_attr() 헬퍼로 attr 비트필드를 계산하여 그림/표 파싱 직후 갱신. 렌더러(layout.rs, typeset.rs) 변경 없음. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
serialize_table()에서 raw_ctrl_data가 없을 때 &[]를 사용하여 빈 CTRL_HEADER가 기록되고 재열기 시 treat_as_char=false로 복원되던 문제 수정. raw_ctrl_data가 없으면 serialize_common_obj_attr(&table.common)으로 폴백하여 Stage 9에서 설정된 table.common.attr(treat_as_char=true 등)이 실제로 직렬화에 반영됨. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
문제: typeset.rs가 table.attr(=common.attr)로 is_tac를 판정하는데 HWP3 파서는 table.common.attr만 설정하고 table.attr를 설정하지 않아 모든 HWP3 표가 is_tac=false(비TAC, 부동 블록)로 렌더링되던 버그. 수정 1 (hwp3/mod.rs): build_common_obj_attr 후 table.attr=table.common.attr로 동기화. 수정 2 (hwpx_to_hwp.rs): adapt_table에서 common.attr≠0인 경우(HWP3)는 attr=0 강제 덮어쓰기를 건너뜀. HWPX(common.attr=0)는 기존 동작 유지. 결과: HWP3 직접 렌더링에서 TAC 표가 올바르게 글자처럼 처리되고, 저장→재열기 후에도 동일하게 TAC 속성이 보존됨. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tr 비트) 문제: serialize_bin_data()가 bin_data.attr를 그대로 기록하는데 HWP3 파서는 BinData.attr를 0(기본값)으로 남겨둠. attr 비트 0-3이 data_type을 인코딩하므로 attr=0 → data_type=Link로 저장됨. 재열기 시 Embedding이 아닌 Link로 파싱 → BinData/BIN* 스트림 누락 → 이미지 사라짐. 수정 (serializer/doc_info.rs): serialize_bin_data()에서 항상 bits 0-3 = data_type, bits 4-5 = compression으로 attr을 재구성. 기존 HWP5 라운드트립은 raw_data를 사용하므로 영향 없음. test: test_hwp3_save_as_hwp5_roundtrip에 BIN* 스트림 존재 검증 추가. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Stage 9 보완1-3에서 분산된 수정을 mod.rs 한 곳으로 통합한다. - mod.rs: build_raw_ctrl_data() 추가 → 표 파싱 시 raw_ctrl_data 사전 구성 - mod.rs: BinData.attr=1 명시 (Embedding 타입 bits) - control.rs, hwpx_to_hwp.rs, doc_info.rs: 보완 패치 복원 (원래 코드로) HWP3 파서가 raw_ctrl_data를 미리 채워두면 serializer/adapter가 변경 없이도 올바른 attr를 HWP5 파일에 기록한다. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
다중 hchar 컨트롤(ch=10/18~21 등)의 extra hchar 슬롯에 hwp3_char_to_utf16_pos 값을 전파하지 않아 후속 텍스트가 잘못된 CharShape를 상속받는 버그 수정. 예: "Creating Linux Virtual Servers" 에서 "Creating"이 pg_num/footer의 extra hchar 슬롯(pos=0)에 가려져 10pt가 아닌 footer 첫 hchar(10pt)를 상속하던 현상 해소. 수정 후 전체 제목이 18pt bold로 통일됨. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… 반영) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…Canvas→LayerTree 반영 (Task edwardkim#460 기반) - upstream/devel 46 commits 병합 (PR edwardkim#446 set_field fix ~ PR edwardkim#456 Canvas→LayerTree) - 소스 파일 자동 병합 성공 (layout.rs, paragraph_layout.rs, engine.rs) - orders/20260430.md add/add 충돌만 수동 해소 (Task edwardkim#460 섹션 + PR edwardkim#450 섹션 통합) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- TAC 표 문단 LINE_SEG lh=th 수정 (160% 줄간격 배율 미적용) → 표 높이 847.9px로 정정 (기존 1357.7px는 160% 배율 오류) - break_flag(0x8001) 마지막 경계 문단에만 ColumnBreakType::Page 적용 → "참조"(pi=193) 새 페이지 시작 강제 - 결과: 17페이지, "참조"(25.6px)+표(844.8px)=874.1px ≤ 876.9px → 동일 페이지 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- assign_hwp3_picture_numbers() 추가 (hwp3/mod.rs): parse_hwp3() 완료 후 Picture 순회, pic_counter 증가, 캡션 AutoNumber(Picture).assigned_number 사전 설정 - assign_auto_numbers_in_controls (parser/mod.rs): assigned_number != 0인 AutoNumber는 skip (사전 할당 존재) Control::Picture is_hwp3 분기 제거 → 포맷 중립 단일 경로 is_hwp3 파라미터 전체 제거 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- assign_auto_numbers_in_controls: upstream 원본대로 복구 (assigned_number guard 제거, 그림 캡션 처리 주석 복원) - fixup_hwp3_picture_numbers: parse_hwp3() 내부 제거 → parse_document()에서 assign_auto_numbers 후 호출로 이동 - 이유: assign_auto_numbers 먼저 실행 후 HWP3 그림 번호 덮어쓰기가 올바른 순서. 공유 함수에 HWP3 분기 불필요. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
mydocs/feedback/: - manual_currency_audit.md (매뉴얼 현행화 감사 결정 요청 — 2026-04-23) - open_issues_priority.md (열린 이슈 37건 우선순위 — 2026-04-22) - pr165_merge_decisions.md (PR edwardkim#165 Skia + Layered Renderer 머지 충돌 결정 — 2026-04-21) - self_censor_audit.md (외부 공개 문서 자기검열 감사 — 2026-04-22) mydocs/pr/: - archives/pr_256_review.md + review_impl.md (PR edwardkim#256 검토 + 구현 계획) - pr_273_review.md (PR edwardkim#273 Task edwardkim#267 right tab 처리 검토) 이전 사이클 작성 후 미커밋 보관 — devel 머지 + push 진행 시 함께 커밋. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- src/parser/hwp3/: HWP 3.0 바이너리 포맷 파서 신규 구현 - mod.rs: 메인 파서 (문단·표·그림·하이퍼링크·페이지 경계 처리) - paragraph.rs: LINE_SEG 기반 줄 정보(pgy) 파싱 - drawing.rs: 그림 개체 파싱 - encoding.rs / johab.rs / johab_map.rs: 조합형 인코딩 변환 - ole.rs: OLE 컨테이너 파싱 - records.rs: 레코드 타입 정의 - special_char.rs: 특수 문자 처리 - src/parser/mod.rs: HWP 3.0 포맷 자동 감지 + parse_hwp3 라우팅 - samples/hwp3-sample*.hwp: HWP 3.0 테스트 파일 3종 HWP5 IR(Document)로 변환하여 기존 렌더러에서 바로 표시 가능. Square wrap(어울림) 그림: pgy 기반 줄별 column_start/segment_width 계산. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
layout.rs: - VertRelTo::Para + TextWrap::Square 그림의 result_y 오류 수정 layout_body_picture가 반환하는 y가 para_start_y로 되돌아가는 문제 → y_offset(누적 컬럼 y)으로 덮어써서 다음 문단이 밀리지 않도록 함 document.rs: - HWPX 전용 TextRunReflow 자동 보정 추가 (reflow_textrun_paragraphs) lineseg 1개 + 긴 텍스트 패턴을 문서 로드 시 자동 보정하여 "HWPX 비표준 감지" 경고 대화상자 미표시 - reflow 결과가 여전히 1 lineseg면 원본 보존 (부동소수점 누적 방지) - validate_linesegs 호출을 reflow 이후로 이동 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…n-relative 수정 parse_paragraph_list에 body_left_hu, column_width_hu 파라미터 추가. 그림의 horz_rel_to(Paper/Para/Page)에 따라 column_start/segment_width를 컬럼 기준 좌표로 올바르게 변환: - 그림이 왼쪽 절반에 있으면 텍스트가 오른쪽으로 흐름 (cs=pic_right, sw=나머지) - 그림이 오른쪽 절반에 있으면 텍스트가 왼쪽으로 흐름 (cs=0, sw=pic_left) vert_rel_to에 따라 pgy_start 계산도 분기 처리 (Para-relative vs 절대 좌표). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
[layout.rs] - layout_shape_item: non-paper-based Control::Picture Square wrap에서 wrap_around_paras(ColumnItemCtx)를 사용해 layout_wrap_around_paras 호출 추가 - layout_wrap_around_paras: end_line 1줄 제한 제거 → 전체 줄 렌더링 (표 어울림은 WrapAroundPara 1개=1줄, 그림 어울림은 1개에 여러 줄 포함 가능) - layout_column_shapes_pass: Control::Picture와 Control::Shape(Picture) 통합 처리. typeset.rs 경로에서 PaginationResult.wrap_around_paras가 항상 비어있으므로 col_content.wrap_around_paras를 직접 참조하여 어울림 텍스트 렌더링. page-relative 그림도 어울림 텍스트는 body 기준 좌표로 렌더링. [typeset.rs / engine.rs] - wrap_around_any_seg 필드 추가: Control::Picture/Shape Square wrap 앵커에서 후속 문단의 첫 LINE_SEG(cs=0)도 어울림 문단으로 흡수 가능하도록 허용 - has_non_tac_pic_square 감지 블록 추가: 비-TAC Square wrap 그림/도형 앵커에서 wrap_around_cs/sw/table_para/any_seg 설정 (표 어울림과 동일 시멘틱) [CLAUDE.md] - 파일 포맷별 파서 구조 표 추가 - HWP3 파서 규칙 명시 (공통 모듈에 HWP3 전용 분기 금지) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
layout.rs: wrap_pic_bottom_y 계산 후 앵커 Shape 처리 완료 시점부터 y_offset을 그림 하단으로 전진시켜 텍스트가 그림에 겹치지 않도록 수정. typeset.rs: wrap zone 종료 시 current_height를 그림 하단까지 보정. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
.gitignore: mydocs/privacy/* 항목 (upstream) 유지 integration_tests.rs: Task edwardkim#490, edwardkim#489 테스트 (upstream) 유지 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ick @jangster77 51 commits, Task #417 + Task #460) — relates #460
본 사이클 17번째 PR. HWP 3.0 (한컴 1990년대~2000년대 초반 레거시 포맷) 첫 오픈소스 파서 구현 + Square wrap 어울림 렌더링 정정. 본 PR 머지로 rhwp = HWP 5.0 + HWPX + HWP 3.0 3 포맷 모두 지원. 본질: - Task #417: HWP 3.0 파서 본질 (Stage 1~4) - Task #460: Square wrap + 렌더러 정정 (Stage 1~9 + 보완 1~3 + 리팩토링) - 작성자 분기에서 본 사이클 devel (Task #501 + PR #478 + PR #498 + v0.7.9) 이미 흡수 → 충돌 해결 보존 옵션 B (단일 머지) 선택. 51 commits 의 작성자 단계 보고서 보존 + 본 사이클 회귀 영역 (issue_501 PASS) 통과. 검증: cargo test --lib 1105 passed (1102 + HWP 3.0 신규 3), svg_snapshot 6/6, issue_418 1/1, issue_501 PASS, clippy 0건, WASM 4,378,441 bytes (+176 KB Johab 매핑 + 파서). 작업지시자 통찰: "이제 우리도 HWP 3.0 포맷까지 성공했습니다. 컨트리뷰터가 대단합니다." 머지 commit: c7330cf Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
처리 결과 — 단일 머지 (51 commits)본 PR 의 51 commits 모두 작성자 author 보존 + 단계 보고서 보존하여 머지 완료. 본질HWP 3.0 (1990년대~2000년대 초반 한컴 레거시 포맷) 첫 오픈소스 파서 구현 + Square wrap 어울림 렌더링 정정. 본 머지로 rhwp = HWP 5.0 + HWPX + HWP 3.0 3 포맷 모두 지원. 흡수 영역
검증
본 사이클 정합
머지
작업지시자 통찰
51 commits / 13,018 lines / Task #417 + Task #460 통합 작업 깊이 감사드립니다. rhwp 가 30년에 걸친 한국 한글 문서 포맷의 오픈소스 변환·렌더링 플랫폼으로 한 단계 도약했습니다. 상세는 `mydocs/pr/pr_506_report.md` 참고. 본 PR 은 close 합니다. 시각 판정은 본 사이클 안정화 후 회귀 발견 시 별도 task 분리 처리 정합. |
|
회귀 테스트 하는데만도 상당한 시간이 걸렸습니다. 대규모 작업을 하시느라 고생 많으셨습니다. |
|
아직도 상당히 수정할 부분이 많습니다.
수정되는데로 추가로 PR 하겠습니다.
감사합니다.
2026년 5월 1일 (금) 오후 3:29, edward kim ***@***.***>님이 작성:
… *edwardkim* left a comment (edwardkim/rhwp#506)
<#506 (comment)>
회귀 테스트 하는데만도 상당한 시간이 걸렸습니다. 대규모 작업을 하시느라 고생 많으셨습니다.
—
Reply to this email directly, view it on GitHub
<#506 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/ASIDG6SEZOQOTP64ITI3MB34YQ725AVCNFSM6AAAAACYNBB266VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHM2DGNJYGE2TENZVGA>
.
Triage notifications on the go with GitHub Mobile for iOS
<https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675>
or Android
<https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
…괄 정리 - README v0.7.9 사이클: PR #506 (jangster77, HWP 3.0 파서 + Square wrap) + PR #510 (postmelee, PageLayerTree image brightness/contrast) 추가. Task #509 (PUA 글머리표 회귀) 도 회귀 정정 섹션에 추가. - 누적 외부 기여자 목록에 jangster77 추가. - mydocs/pr/ → archives/ 일괄 이동 (PR #235~#510 closed/merged 44 PR, 84 파일). pr_507 만 OPEN 상태로 보존. pr_235_review/_impl 은 archives 사본과 byte-identical 이라 중복 제거. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
직전 commit 9b3c039 에서 의도된 변경 두 건이 누락되어 후속 정정. - README v0.7.9 사이클: PR #506 (jangster77, HWP 3.0 파서 + Square wrap) + PR #510 (postmelee, PageLayerTree image brightness/contrast) + Task #509 (PUA 글머리표) 추가. 누적 외부 기여자에 jangster77 추가. - mydocs/pr/pr_235_review.md / pr_235_review_impl.md 가 archives/ 와 pr/ 양쪽에 중복 존재했던 문제 정리 (archives 사본 보존, pr/ 사본 제거). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
cherry-pick (본질 12 commits 만 — fork devel 누적 170 commits 제외): - e7f1adb~1bca866: Task #534 v1 (4 commits, layout_shape_item TAC Picture inner_pad) - 576aa29~57ccde6: Task #534 v2 (2 commits, LINE_SEG.column_start 정합) - d70599d~58af6c9: Task #537 (3 commits, lazy_base trailing-ls 보정) - f60f580~fc32bd3: Task #539 (3 commits, prev_has_overlay_shape 가드 완화) 검증: - cargo test --lib 1113 passed - cargo test --test issue_530/505/418/501 회귀 0 - cargo test --test svg_snapshot 6/6 passed - cargo clippy --lib 0 건 - cargo build --release 정상 - WASM 빌드 4,461,870 bytes + studio 동기화 시각 판정 (작업지시자 한컴 2010/2020 직접 판정): - 1차 (SVG export-svg) 통과 - 2차 (rhwp-studio web Canvas) 통과 부수 발견 (별도 이슈): - 이슈 #545 — aift.hwp p41 표 위치 (PR #538 와 무관, 이전부터) - 이슈 #546 — exam_science.hwp p2 페이지네이션 회귀 (PR #506 origin, bisect 확정) 컨트리뷰터 안내: 다음 PR 전 fork devel 동기화 부탁. 산출물: - mydocs/pr/pr_538_review.md (검토) - mydocs/pr/pr_538_review_impl.md (cherry-pick 절차) - mydocs/pr/pr_538_report.md (처리 결과) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…— cherry-pick @planet6897 12 commits) — closes #534/#537/#539 본 PR 은 외부 컨트리뷰터 @planet6897 (Jaeuk Ryu) 의 PR. 21_언어_기출_편집가능본.hwp 의 줄간격 716 HU drift + exam_kor 18p 그림 위치 결함의 본질 정정. cherry-pick (본질 12 commits 만 — fork devel 누적 170 commits 제외): - Task #534 v1+v2: layout_shape_item TAC Picture inner_pad + LINE_SEG.column_start · src/renderer/layout.rs (+37 / -3 LOC) - Task #537: lazy_base trailing-ls 보정 (TAC 표 직후 첫 답안 줄간격 716 HU drift, P2/3/5/6/8/9/12/13/14 11곳) · src/renderer/layout.rs (+14 / -2 LOC) - Task #539: prev_has_overlay_shape 가드 완화 (treat_as_char 제외, 글박스 호스트 직후 paragraph 줄간격 P7/P9 2곳) · src/renderer/layout.rs (+9 / -0 LOC) - src/renderer/layout/integration_tests.rs (TDD 통합 테스트 3건) 검증: - cargo test --lib 1113 passed - cargo test --test issue_530/505/418/501 회귀 0 - cargo test --test svg_snapshot 6/6 통과 - cargo clippy --lib 0 건 - cargo build --release 정상 - WASM 4,461,870 bytes + rhwp-studio 동기화 시각 판정 (작업지시자 한컴 2010/2020 직접): - 1차 SVG export-svg 통과 - 2차 rhwp-studio web Canvas 통과 부수 발견 (별도 이슈, PR #538 와 무관): - 이슈 #545: aift.hwp p41 표 위치 (이전부터 발생) - 이슈 #546: exam_science.hwp p2 페이지네이션 회귀 (PR #506 origin, bisect 확정) 컨트리뷰터 안내: 다음 PR 전 fork devel 동기화 부탁.
본질: PR edwardkim#506 의 layout_wrap_around_paras 호출이 비-TAC Picture wrap=Square host 의 호스트 자기 텍스트를 두 곳에서 중복 emit → (1) 시각 결함 [edwardkim#525 표면 증상] + (2) 페이지네이션 inflation [본 edwardkim#546 표면 증상] 두 표면이 동일 root cause. Task edwardkim#525 정정 (Picture Square wrap 의 wrap-around 호출 두 곳 모두 제거) 이 본 회귀 자동 해소. 검증: - 2dbbd07 (edwardkim#525 push 직전 origin/devel) = 6 페이지 / p2 = 2 items 회귀 잔존 직접 확인 - 현재 devel HEAD f5ad122 = 4 페이지 / p2 = 37 items / 1133.6 px = v0.7.9 baseline 65e275d 정합 edwardkim#524 + edwardkim#525 역할 분담: - edwardkim#524: 그림 anchor 위치 본질 정정 (typeset.rs) - edwardkim#525: wrap-around 호출 중복 본질 정정 (layout.rs) 본 task 코드 변경 0 — 분석 보고서 + orders 갱신만. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
작업지시자 시각 판정 통과 ("시각 회귀 통과입니다").
WASM 빌드: 4,442,504 bytes (PR #538 시점 4,461,870 -19,366, 94 LOC 제거 반영) +
rhwp-studio 동기화 완료.
산출물:
- mydocs/report/task_m100_546_report.md (최종 보고서)
회귀 origin 분석:
- 82e41ba (Task #460 보완5: Square wrap 그림 아래 텍스트 y위치 보정)
- 본 의도: HWP3 Square wrap 그림 아래 텍스트 y위치 정합
- exam_science 의 부작용: 2단 + 그림이 단 0 끝 + 풍부한 wrap-around 조합에서
current_height = max(current_height, bottom_px) 가 wrap-around paragraph 의
누적 height 와 결합한 double advance 발생 → 페이지/단 강제 분리
광범위 영향 작은 이유: specific 조합에서만 결함 trigger.
PR #506 의 다른 fixture 검증에서도 미검출 (exam_science 가 정밀 fixture).
Task #460 보완5 의 본 의도 손실 — HWP3 fixture 시각 결함 재발견 시 별도 task 로
페이지네이션 안전한 방식 (wrap-around paragraph 누적 height 추적) 재시도 권장.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
@jangster77 님, 본 PR 후속 정정 사항 공유드립니다. 발견된 회귀 — 이슈 #546본 PR 의 `82e41ba` (Task #460 보완5: Square wrap 그림 아래 텍스트 y위치 보정) 이 `samples/exam_science.hwp` 페이지 2 의 페이지네이션 회귀 origin 으로 식별됨 (4 페이지 → 6 페이지, p2 본문 37 → 2 items). bisect 결과 정확히 단일 commit 로 좁힘:
결함 본질`82e41ba` 의 wrap zone 종료 시 `current_height = max(current_height, wrap_around_pic_bottom_px)` 보정이 specific 조합에서 double advance 발생:
옵션 C (col 경계 검사 `bottom_px <= col_h`) 시도 — 모든 보정값이 col 영역 이내라 가드 trigger 안 됨, 0 효과. 결함의 본질이 col 경계가 아니라 wrap-around paragraph 의 누적 height 와의 결합 영역. 정정 (Task #546, devel `7ea6e8c`)작업지시자 결정으로 옵션 A (전체 revert) 진행:
본 의도 손실 영향`82e41ba` 의 본 의도 (HWP3 Square wrap 그림 아래 텍스트가 그림과 겹치는 결함 정정) 는 본 revert 로 손실. 작업지시자 시각 판정 단계에서 HWP3 fixture 의 시각 결함 재발은 미검출 (HWP3 fixture 가 본 환경에 부재이거나, 다른 commit 인 `ab2f4d0` HWP3 paper-relative → column-relative 가 본질을 이미 흡수했을 가능성). 향후 재시도 시 권장 방향HWP3 fixture 시각 결함 재발견 시 별도 task 로 다음 옵션 중 하나로 재시도 권장 — 페이지네이션 안전한 방식:
트러블슈팅 문서본 결함의 본질 + 진단 방법 + 정정 방향을 `mydocs/troubleshootings/square_wrap_pic_bottom_double_advance.md` 에 기록. 향후 Square wrap 영역 작업 시 사전 점검 자료. 회귀 검증 보강 권장회귀 검증 게이트에 `samples/exam_science.hwp` 의 페이지 수 (4) + p2 본문 items (37) 검사 추가. 본 결함이 PR #506 의 광범위 회귀 검증에서 미검출된 이유는 specific 조합 (2단 + 그림이 단 0 끝 + 풍부한 wrap-around) 의 fixture 가 검증에 포함 안 되었기 때문. `tests/issue_546.rs` 가 본 검증 추가. 이 결함 발견은 작업지시자가 PR #538 시각 판정 중 부수적으로 식별한 사례이며, 본 PR 의 본 의도 (HWP 3.0 파서 + Square wrap 어울림 렌더링) 자체는 여전히 정합한 가치 있는 정정이라는 점 강조드립니다. 이번 정정은 specific 조합의 부작용 정정일 뿐, PR 의 다른 영역 (HWP 3.0 파서 등) 은 전혀 영향 없이 보존되었습니다. 처리 보고서: `mydocs/report/task_m100_546_report.md` |
- mydocs/troubleshootings/square_wrap_pic_bottom_double_advance.md (신규) · 결함 본질 (double advance 패턴) + 진단 방법 + 정정 방향 옵션 · 옵션 C 가 효과 없는 이유 + specific 조합의 광범위 검증 함정 · 향후 재시도 시 권장 방향 (3 옵션) - mydocs/orders/20260503.md 갱신 (Task #546 완료 반영 + PR #506 코멘트 추가) PR #506 컨트리뷰터 (@jangster77) 에게 코멘트 추가 — 회귀 발생 본질 + 정정 방안 + 향후 재시도 권장 방향 안내. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
src/parser/hwp3/)layout.rs:wrap_pic_bottom_y계산 + 앵커 Shape 처리 후 y_offset 전진 → 텍스트가 그림에 겹치지 않도록typeset.rs: wrap zone 종료 시current_height를 그림 하단까지 보정Document) 경유, 렌더러 분기 없음Test plan
cargo test— 전체 테스트 통과 확인cargo clippy -- -D warnings— 경고 없음rhwp export-svg samples/hwp3-sample5.hwp -p 3— page 4 그림+텍스트 레이아웃 정상 (그림 좌상단, wrap 텍스트 그림 우측, 전체폭 텍스트 그림 아래)🤖 Generated with Claude Code