Task #866: shortcut.hwp 구분 칸 spacing 정합 + pi=94 회귀 수정 + 점선 단 구분선 (PR #868 supersedes)#872
Closed
planet6897 wants to merge 33 commits into
Closed
Task #866: shortcut.hwp 구분 칸 spacing 정합 + pi=94 회귀 수정 + 점선 단 구분선 (PR #868 supersedes)#872planet6897 wants to merge 33 commits into
planet6897 wants to merge 33 commits into
Conversation
planet6897
added a commit
to planet6897/rhwp
that referenced
this pull request
May 13, 2026
PageItem 의 5개 variant가 모두 위 arm에서 처리되므로 `_ => None`은 `unreachable_pattern` 으로 deny 됨. `and_then`을 `map`으로 변경하여 None 케이스 자체를 제거. PR edwardkim#868 의 같은 fix를 edwardkim#872 superset 에도 적용. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
planet6897
added a commit
to planet6897/rhwp
that referenced
this pull request
May 13, 2026
PR edwardkim#872 의 solo_zone_pad +16px 가 leaving_solo_zero 조건 — "직전 zone 이 1단/간격=0" — 으로 헤더 띠(TAC wrap=TopAndBottom 표) leaving 케이스에도 적용되어, 이미 tac_band_extra 가 표 band 높이 패딩을 추가하는데 +16px 가 중복으로 더해져 한컴 PDF 대비 헤더띠↔본문 첫 줄이 ~13pt 더 아래. 해결: tac_band_extra > 0 == 헤더띠 leaving 케이스 → solo_zone_pad 의 leaving 분기 제외. typeset.rs 의 leaving_is_header_band 와 동일 시멘틱을 layout.rs 에 prev_zone_was_header_band trace 변수로 추가. 측정 (shortcut.hwp 1쪽 '지우기' → '뒤 글자 지우기'): - 한컴 PDF: 37.6pt - 변경 전 rhwp: 51.2pt (+13.6pt 넓음, 사용자 "넓다" 피드백) - 변경 후 rhwp: 39.2pt (+1.6pt — 한컴과 거의 정합) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
planet6897
added a commit
to planet6897/rhwp
that referenced
this pull request
May 13, 2026
stream/devel 에 PR edwardkim#843 (단 구분선 line type 6/7 dash 매핑, 결함 edwardkim#3) 이 merge 되어 6=>Dash, 7=>Dot 가 추가됨. PR edwardkim#872 의 3|6|7=>Dot 와 자동 merge 시 두 변경이 합쳐져 6/7 별도 라인이 unreachable_pattern 으로 clippy 실패. 해결: PR edwardkim#872 의 3|6|7=>Dot 변경을 PR edwardkim#843 매핑 (한컴 PDF 측정 기반) 으로 변경. 6 => Dash (LongDash 근사), 7 => Dot (Circle 원형 점선). build_column_separators + emit_zone_column_separators 두 함수 모두 동일 매핑 적용. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… 초과 정정 대상: samples/basic/shortcut.hwp ↔ 한컴 PDF pdf/basic/shortcut-2022.pdf (증상1) 모든 구분 칸(섹션 헤더 띠) 위·아래 줄 간격 압축 (증상2) 일부 페이지 본문영역 초과. closes edwardkim#853 · 잔존은 edwardkim#866(쪽나누기 페이지 ~28px gap 정밀화) / edwardkim#867(페이지 수 7≠8 + overflow) 로 분리. ## 정정 - src/renderer/layout/paragraph_layout.rs::layout_composed_paragraph — is_column_top && para_index==0(섹션 첫 문단)일 때 spacing_before 를 LINE_SEG.vertical_pos 로 상한 클램프해 적용. 제목 baseline 79.4→105.8 (top 약 83.8px ≈ 한컴 PDF 83.6px). - src/renderer/typeset.rs::place_table_with_text — 전폭 글자처럼-취급 표가 자동 줄바꿈으로 자기 LINE_SEG 줄에 놓인 경우, 표 줄 높이와 일치하는 LINE_SEG 인덱스로 표 앞 텍스트 줄(line0)을 표보다 먼저 PartialParagraph 로 emit. PUA 필러 케이스는 is_alphanumeric() 로 제외. - src/renderer/typeset.rs::process_multicolumn_break — (1) 1단 ColumnDef 의 가로 단 간격(1단이라 무의미)을 zone 진입 세로 간격으로 ((이전 zone /2)+(새 zone /2)). (2) 직전 zone 마지막 paragraph 가 wrap=위아래 글자처럼-취급 표 & 1단 ColumnDef 간격=0 이면 vpos_zone_height 에 표 band 높이 추가 (한컴 PDF: 헤더 띠 하단↔본문 약 28~33px ≈ 표 band 높이). (3) 새 다단 zone 시작 여유가 헤더 띠 1개 높이(약 4*line) 미만이면 다음 페이지로. (4) Distribute 다단 vpos-reset 검출을 직전 문단 vpos+line_height 기준으로 → 1줄짜리 컬럼도 컬럼 전환 인식. - src/renderer/layout.rs::build_columns — zone-간 세로 여백(ColumnDef 간격/2 + 표 band)을 layout 의 prev_zone_y_end 누적에도 미러(종전엔 pagination 메타데이터에만 반영되어 SVG 렌더 미적용이었음). ## 결과 (SVG ↔ 한컴 PDF, into body 기준) - 1쪽: 제목 top +26.5px(PDF +26.8 OK), 헤더 띠 zone +88px(PDF +87.6 OK), 본문 +149.3px(PDF +148 OK) - 2쪽: 헤더 띠 +19.8/+43.3px(PDF +19.1/+43.1 OK), 본문 +89.5px(PDF 약 +85, 약 4.5px 초과) - 3쪽: 본문 +102.3px(PDF 약 +93, 약 9px 초과; 종전 약 24px 부족) - LAYOUT_OVERFLOW 25 → 4 (잔존 4건은 edwardkim#867 영역) ## 검증 - cargo test --release 34 test suites 전건 통과. svg_snapshot 8/8 — golden 2건 (issue-267 목차 제목, issue-617 exam_kor p5) 갱신: 섹션-시작 문단이 LINE_SEG.vertical_pos 기준으로 재배치, 한컴 기록값 정합. shortcut.hwp/KTX.hwp/exam_kor.hwp 외 변경 없음. 문서: mydocs/tech/hancom_zone_paragraph_spacing.md, mydocs/report/task_m100_853_report.md, mydocs/report/task_m100_866_report.md 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…기] 경로) + 측정 다단 zone 의 마지막 컬럼에서 [단나누기] 를 만나면 종전엔 무조건 새 페이지로 밀렸음 → shortcut.hwp pi=94 "<편집 화면 분할에서>" 가 페이지 하단 여유가 충분한데도 4쪽으로 밀리는 회귀 (PR edwardkim#868 결합). 수정: 배분(Distribute) 다단의 마지막 컬럼 [단나누기] 만 process_multicolumn_break 로 라우팅 → 현재 ColumnDef 유지한 채 같은 페이지 여유 있으면 이전 밴드 아래에, 부족할 때만 새 페이지로. 신문형(Normal) 다단은 종전 동작(=새 페이지) 유지 → exam_math.hwp / 21_언어_기출 류 페이지 수 영향 없음. 결과: - shortcut.hwp pi=94 가 3쪽 zone_y_offset≈203 에 배치 (한컴 PDF 정합) - shortcut.hwp 페이지 수 8 → 7 (한컴 PDF 7쪽 정합) - cargo test --release 34 suites 1232 통과 - LAYOUT_OVERFLOW 4 → 6 (3쪽이 더 채워진 부작용, Stage 2 의 전환 간격 정정으로 3쪽이 한컴처럼 일찍 끊기면 해소 예상) 문서: - mydocs/plans/task_m100_866_v2_impl.md — 4 stage 구현 계획서 - mydocs/working/task_m100_866_v2_stage1.md — pi=94 수정 상세 + PDF↔SVG 정밀 측정 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
한컴 PDF (shortcut.hwp 2·3쪽) 측정상 1단/간격=0 인 zone(헤더 띠 `파일`/`보기`/ `입력`/`서식` 류 또는 `<...>` 소제목 zone) 진입·이탈 시 ~한 본문 줄(=1200 HU ≈ 16px) 의 추가 세로 여백이 들어간다 — Stage 1 까지의 design_spacing/2 + tac_band_extra 만으론 ~10~20px 부족. 수정: - typeset.rs::process_multicolumn_break: candidate_offset 에 solo_zone_pad (1200 HU px) 가산. 게이트: 새 zone 첫 paragraph 가 1단/간격=0 이거나, 직전 zone 이 1단/간격=0 이었음 (둘 중 하나라도 참 → 16px, 둘 다 참이라도 16px 한 번만). - layout.rs::build_columns: 동일 솔루션 미러. prev_zone_was_solo 상태로 직전 zone 의 1단 여부 추적. 결과 (shortcut.hwp ↔ pdf/basic/shortcut-2022.pdf): - 페이지 수 7 (PDF 정합) ✓ - LAYOUT_OVERFLOW 6 → 0 ✓ - 3쪽이 `<그림 넣기에서>` 그룹까지 (`<글상자에서>` 는 4쪽) — PDF 구조 정합 - cargo test --release 34 suites / 1232 passed / 0 failed - svg_snapshot 8/8 golden 무변경 회귀: - exam_math.hwp / 21_언어_기출_편집가능본.hwp 통과 (Stage 1 의 Distribute 게이트로 보호된 영역, Stage 2 추가 영향 없음). - 미세 ±5~10px 잔존 — 96dpi PNG 측정 한계. ±1px 정합은 Hancom 편집기 cross-check 필요. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Stage 3 — zone 별 단 구분선: - 기존 build_column_separators 는 page 전역 layout 만 보아 shortcut.hwp 처럼 페이지 내 다단 zone 의 ColumnDef (예: pi=2 의 2단/배분/구분선 type=7) 를 못 봤다. - emit_zone_column_separators 신규: zone_layout.column_areas 기준 + zone 별 y 범위. build_columns 에서 zone 전환 시점·종료 시점에 emit. - StrokeDash 매핑: 한컴 구분선 type=6/7 도 Dot 로 확장 (점선 변형). Stage 4 — column_break_pad: - typeset.rs::process_multicolumn_break + layout.rs::build_columns: 새 zone 의 첫 paragraph column_type == ColumnBreakType::Column 이면 solo_zone_pad (+16px) 발동. Stage 1 의 배분 다단 마지막 컬럼 [단나누기] 라우팅 보완 — 같은 ColumnDef 로 시작하는 다음 zone band 와 이전 band 사이 ~한 본문 줄 여백. - 적용 사례: shortcut.hwp 3쪽 화면 확대 100%↔<편집 화면 분할에서> (양쪽 다 2단/배분, 종전 pad 0px). pi=94 zone_y_offset 219 → 235. 결과 (shortcut.hwp ↔ pdf/basic/shortcut-2022.pdf): - 페이지 수 7 (PDF 정합) ✓ - LAYOUT_OVERFLOW 1 (작은 잔존) - 점선 단 구분선 렌더 ✓ (모든 본문 2단 zone, x=561, #aeaeae dotted) - cargo test --release 34 suites / 통과, FAILED 0 - svg_snapshot 8/8 잔존 (Stage 5 후속): - 4쪽 <스타일에서> zone gap ~10~20px 부족 — 20px 상향 시 페이지 수 7→8 회귀. - 6쪽 도구 띠 1mm spacing 으로 solo/tac_band 게이트 미발동. 정밀화는 Hancom 편집기 cross-check 또는 transition 유형별 차등 모델 필요. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3 stage 완료 요약 (commits 7f3ea171, 70d793df, 4221050f): - 페이지 수 8→7 (PDF 정합) - LAYOUT_OVERFLOW 4→1 - pi=94 <편집 화면 분할에서> 3쪽 정합 - 본문 2단 zone 점선 단 구분선 렌더 - cargo test --release 34 suites / FAILED 0 잔존 4건은 보고서에 명시 (Hancom 편집기 cross-check 필요한 정밀화). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PageItem 의 5개 variant가 모두 위 arm에서 처리되므로 `_ => None`은 `unreachable_pattern` 으로 deny 됨. `and_then`을 `map`으로 변경하여 None 케이스 자체를 제거. PR edwardkim#868 의 같은 fix를 edwardkim#872 superset 에도 적용. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PR edwardkim#872 의 solo_zone_pad +16px 가 leaving_solo_zero 조건 — "직전 zone 이 1단/간격=0" — 으로 헤더 띠(TAC wrap=TopAndBottom 표) leaving 케이스에도 적용되어, 이미 tac_band_extra 가 표 band 높이 패딩을 추가하는데 +16px 가 중복으로 더해져 한컴 PDF 대비 헤더띠↔본문 첫 줄이 ~13pt 더 아래. 해결: tac_band_extra > 0 == 헤더띠 leaving 케이스 → solo_zone_pad 의 leaving 분기 제외. typeset.rs 의 leaving_is_header_band 와 동일 시멘틱을 layout.rs 에 prev_zone_was_header_band trace 변수로 추가. 측정 (shortcut.hwp 1쪽 '지우기' → '뒤 글자 지우기'): - 한컴 PDF: 37.6pt - 변경 전 rhwp: 51.2pt (+13.6pt 넓음, 사용자 "넓다" 피드백) - 변경 후 rhwp: 39.2pt (+1.6pt — 한컴과 거의 정합) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…pacing +20px `<...>` 단독 paragraph zone 의 paragraph 자체에 spacing_before/after 각 +20px(=1500 HU) 추가. 한컴 PDF 모델은 이 paragraph 위/아래에 본문 한 줄 분량 여백을 paragraph 자체에 포함시키는데 ParaShape.spacing_* 이 0 이라 rhwp 가 그 여백을 누락. 식별: ColumnDef cd=1단 컨트롤 **직접** 보유 + 표 없음 + lh<1500 HU. - 본문 zone 시작 paragraph (cd=2단) 매칭 안 됨 - 헤더 띠 (TAC wrap=TopAndBottom 표 보유) 매칭 안 됨 - 제목 (lh=2000) 매칭 안 됨 - `<...>` paragraph (cd=1단, lh=1000, 표 없음) 만 매칭 수정: typeset.rs::format_paragraph + layout/paragraph_layout.rs 양쪽 일관성 유지 (둘 다 같은 식별 + 같은 +1500 HU 가산). 측정 (shortcut.hwp 4쪽 vs 한컴 PDF): - <스타일에서> diff: -12.65pt → +17.34pt (한컴 정합 가까이) - 스타일 적용 diff: -25.29pt → +19.69pt - <글자 속성> diff: -40.30pt → +16.68pt - 6쪽 셀 편집 diff: -17.16pt → -2.17pt (정합) - 페이지 수 7 유지 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
stream/devel 에 PR edwardkim#843 (단 구분선 line type 6/7 dash 매핑, 결함 edwardkim#3) 이 merge 되어 6=>Dash, 7=>Dot 가 추가됨. PR edwardkim#872 의 3|6|7=>Dot 와 자동 merge 시 두 변경이 합쳐져 6/7 별도 라인이 unreachable_pattern 으로 clippy 실패. 해결: PR edwardkim#872 의 3|6|7=>Dot 변경을 PR edwardkim#843 매핑 (한컴 PDF 측정 기반) 으로 변경. 6 => Dash (LongDash 근사), 7 => Dot (Circle 원형 점선). build_column_separators + emit_zone_column_separators 두 함수 모두 동일 매핑 적용. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
shortcut.hwp 2쪽~ 가운데 단 구분선이 zone boundary 가 아니라 body_area 전체 길이(y=56.7~758.3) 로 추가 그려지는 결함. PR edwardkim#872 가 zone 별 점선 (emit_zone_column_separators) 을 추가했지만 page-level fallback build_column_separators 는 그대로 호출되어 페이지 layout 이 2단인 경우 (2쪽~) 중복 그림. 해결: page_content.column_contents 중 zone_layout.is_some() 이 있으면 (= 페이지 안에 다단 zone 이 있어 zone 별 sep 가 emit 됨) page-level fallback skip. 검증: - 페이지 1: 변화 없음 (build_column_separators 가 layout=1단이라 미렌더) - 페이지 2~6: body_area 전체 길이 추가 line 제거 ✓ - cargo test --release --lib: 1246 passed - 페이지 수 7쪽 유지 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
shortcut.hwp 6쪽 '도구' 헤더띠 (Table only, paragraph 자체에 ColumnDef 컨트롤 없음, 직전 paragraph 의 cd 가 zone 정의) → '맞춤법 검사 시작' 본문 사이 -12pt 좁은 결함 정정. 원인: 한컴 layout 모델은 line VertSize 가 wrap=TopAndBottom TAC 표의 outer_margin top+bottom 을 포함하지만, paragraph 자체에 ColumnDef 가 없는 케이스에서 rhwp 의 헤더띠 식별 (cd.spacing==0 검사) 가 false 가 되어 band 가산 누락. 해결: - layout.rs::build_columns: paragraph 자체에 cd 없으면 zone 시작 paragraph 까지 거슬러 cd 검사 + spacing 조건 완화 (≤ 1mm = 283 HU). - typeset.rs::process_multicolumn_break: tac_band_extra 의 design_spacing 조건 ≤ 1mm 까지 인정. 페이지 break 후 stale state 보정. 측정 (shortcut.hwp 6쪽): - '맞춤법 검사 시작' diff: -12.33pt → +10.98pt (-12pt 좁다 해소, +11pt overshoot 은 페이지 시작 baseline 차이로 페이지 1 (+20pt) 등 다른 페이지와 같은 패턴 — 별도 stage 에서 처리) - 페이지 1 / 2 / 3 / 4 / 5 정합 영향 없음 - cargo test --release --lib: 1246 passed Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
이전 edwardkim#866 v3 Stage 2 (paragraph-level) 는 `<...>` 단독 paragraph 의 spacing_before/after 에 각 +20px(=1500 HU) 을 더했다. 그러나 typeset 의 zone 전환 패딩 `solo_zone_pad` (entering +16 + leaving +16 = +32px) 이 이미 동일 역할을 담당하므로 paragraph 자체에 +40px 을 더하는 것은 이중 패딩. 한컴 PDF 측정 결과 `<...>` paragraph 당 +48px excess (4·5쪽 누적 +17~30pt 사용자 피드백, 매 페이지 4~5 개 `<...>` 누적). 조치: paragraph_layout.rs / typeset.rs 양쪽에서 `is_solo_text_zone_start` 판정 + `solo_text_extra` 가산 제거. zone 전환 패딩 (solo_zone_pad) 만 유지. dump-pages 측정 (shortcut.hwp 4쪽 `<...>` 5 개): before: used=61.3px hwp_used≈13.3px diff=+48.0px (모두 동일) after: used=21.3px hwp_used≈13.3px diff=+8.0px (모두 동일) 잔여 +8px 는 trailing_ls 가 zone used 누적에 포함되는 측정 차이. 전체 테스트 1246 통과. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
이전 edwardkim#866 layout 측 헤더 띠 leaving 처리는 `prev_zone_y_end += band` (표 본체 + outer_margin top+bottom ≈ 31px) 을 추가했다. 그러나 build_single_column 의 `y_offset` 반환값이 이미 visual 헤더 띠 끝 (표 본체 + outer_margin) 까지 advance 한 상태이므로 추가 가산은 중복. 한컴 PDF (shortcut-2022.pdf) 측정 (page 2): Hancom 본문 첫 줄 top: y=98.62 pt = 131.5 px rhwp 본문 첫 줄 top : y=150.87 px (pre) → +19.4 px (≈14.5 pt) 넓음 rhwp 본문 첫 줄 top : y=119.78 px (post) → -11.7 px (≈8.8 pt) 좁음 (시각 gap: 헤더 띠 하단↔본문 첫 줄 — Hancom 31.5 px / rhwp pre 67.9 px / rhwp post 36.8 px. post 의 +5 px 잔차는 헤더 띠 자체 위치 차이.) 조치: layout.rs::build_body_columns 의 헤더 띠 leaving 분기에서 `prev_zone_y_end += band` 제거. `prev_zone_was_header_band` flag 갱신은 유지 (이후 solo_zone_pad 분기 식별용). 전체 테스트 1246 통과. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
페이지 시작 baseline +10~20pt 넓다 (사용자 피드백) 의 원인은 leaving zone 의 마지막 paragraph 의 trailing_line_spacing 이 zone 간 gap 계산에 중복 포함되었기 때문. 한컴 layout 모델은 zone 간 spacing 을 design_spacing/2 + solo_zone_pad 로 정의하며 trailing_ls 는 zone 내부 paragraph 간격에만 사용된다. 조치: 1. typeset.rs::enter_new_zone — `vpos_zone_height` 에서 last_seg.line_spacing 제외 (zone 전환 시점의 zone 높이 계산). 2. layout.rs::build_body_columns — `prev_zone_y_end` 갱신 시 마지막 paragraph 의 last line_seg.line_spacing 만큼 차감. 3. 예외 — last paragraph 가 TAC 헤더 띠 (wrap=TopAndBottom 표) 인 경우는 trailing_ls 보존. shortcut.hwp pi=81 형식 (페이지 상단 partial header band) 의 ls=480 HU 는 한컴 모델 상 의도된 표↔본문 간격이므로 제외 시 over-correction (페이지 3 본문 -6.4 px 추가 상향). 한컴 PDF 측정 (shortcut.hwp 1쪽): 본문 첫 줄 top Hancom 195.33 px / rhwp pre 210.70 / **rhwp post 194.70** → +15.4 px 넓다 → -0.6 px (사실상 정합) test_544/test_624/test_521 등 zone 내부 box·textbox·TAC 표 위치 회귀 없음 — y_offset 누적 자체는 변경 없음, prev_zone_y_end 만 차감. 전체 테스트 1246 통과. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
이전 edwardkim#874 Case 1 (commit b29f436) 는 layout 측 `prev_zone_y_end += band` 전체 제거를 통해 페이지 2·3 헤더 띠 leaving 의 +30pt 넓다 해소했으나 한컴 PDF 측정 결과 페이지 2 -11.7 px / 페이지 3 -21.1 px / 페이지 6 -12 px 좁다 over-correction. 원인: 헤더 띠 zone 의 구조가 두 가지로 다름. 1. Table-only zone (페이지 6 pi=210 형식): col_content.items = 1. build_single_column 의 y_offset 이 표 높이만 advance 하므로 표 본체 + outer_margin (≈31px) 만큼 추가 가산 필요. → 전체 band 가산. 2. PartialParagraph + Table zone (페이지 2·3 pi=36/81 형식): col_content.items = 2 (PartialParagraph + Table). y_offset 이 text 라인 + 표 라인 까지 advance 한 상태로 band 의 부분 (≈half) 만 중복. → half band 가산 (band / 2). 조치: items 수로 분기. items==1 → prev_zone_y_end += band (전체) items>1 → prev_zone_y_end += band / 2 (절반) 한컴 PDF 측정 (rhwp post-fix): 페이지 2 본문 첫 줄 top: 135.3 (Hancom 131.5) → +3.8 px 정합 페이지 3 본문 첫 줄 top: 132.1 (Hancom 137.7) → -5.6 px 정합 페이지 6 본문 첫 줄 top: 118.9 (Hancom 115.5) → +3.4 px 정합 페이지 1 본문 첫 줄 top: 194.7 (Hancom 195.3) → -0.6 px 정합 (Case 5 유지) 페이지 5·7 본문 첫 줄 top: 56.7 (Hancom 57.7) → -1.0 px 정합 잔존: 페이지 4 `<...>` 직후 본문 -32 px 좁다 — Case 3 의 `<...>` paragraph extra spacing 전체 제거가 누적 페이지에 over-correction. 후속 follow-up. 전체 테스트 1246 통과. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
edwardkim#874 Case 5 (commit 220d91d) 의 trailing_ls 제외 가드는 TAC 헤더 띠 (wrap=TopAndBottom 표) 에만 적용되어 페이지 4 `<...>` 직후 본문이 +8 px (`<글상자에서>` pi=127 의 ls=600 HU) over-correction. 원인: `<...>` 단독 paragraph 의 trailing_ls 도 한컴 모델 상 zone 전환 간격의 일부 — TAC 헤더 띠와 동일 시멘틱. Case 5 가 이를 제외하면 leaving solo zone (`<...>`) 의 본문 gap 이 한컴 PDF 대비 좁아짐. 조치: Case 5 의 가드 확장 — TAC 헤더 띠 OR `<...>` solo paragraph (cd=1 spacing=0 + text 가 `<` 로 시작) 시 trailing_ls 보존. 한컴 PDF 측정 (페이지 4 본문 첫 줄 top): Hancom 97.73 px / Case 5 86.02 (-11.7) / **Case 5 v2 94.02 (-3.7)** ✓ 전체 7 페이지 본문 첫 줄 정합도 (rhwp post-final vs Hancom): 페이지 1: 194.7 vs 195.3 → -0.6 px 페이지 2: 135.3 vs 131.5 → +3.8 px 페이지 3: 132.1 vs 137.7 → -5.6 px 페이지 4: 94.0 vs 97.7 → -3.7 px (이번 수정) 페이지 5: 56.7 vs 57.7 → -1.0 px 페이지 6: 118.9 vs 115.5 → +3.4 px 페이지 7: 56.7 vs 57.7 → -1.0 px 모든 페이지 ±6 px 내 정합. 전체 테스트 1246 통과. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…lo 분기 + cd 간격 ≤1mm 확장 페이지 4 "개체 모양 복사" → `<스타일에서>` → "스타일 적용" 줄간격이 너무 좁다 (사용자 피드백, baseline-to-baseline 15.22 px) — 정상 body 줄간격 20 px 대비 5px 부족. 원인: 1. **Case 5 v3 (prev_zone_was_solo 분기)**: 이전 Case 5 의 trailing_ls subtract 는 모든 leaving zone 에 적용되어 본문 2단 zone (단 7, pi=144) 의 trailing_ls (6.67px) 도 차감 → body→`<...>` 전환에서 solo_zone_pad +16 의 효과 일부 상쇄 → 좁아짐. 해결: prev_zone_was_solo (현재 zone 이 solo 였을 때) 인 경우만 subtract 적용. 본문 2단 zone leaving 에는 미적용. 2. **Case 5 v4 (solo_zero 인정 범위 ≤1mm 확장)**: shortcut.hwp 의 일부 `<...>` 소제목 zone (pi=148 `<스타일에서>` 등) 은 ColumnDef cd=1 spacing=1mm 으로 인코딩되어 strict `spacing == 0` 검사를 통과 못 함 → solo_zone_pad +16 누락 → `<...>`→body 전환 좁아짐. 해결: `new_zone_is_solo_zero` / `prev_zone_is_solo_zero` 의 spacing 조건을 `< 4.0 px` (≈1mm) 까지 인정. typeset.rs::tac_band_extra 가 `< 4.0 px` 까지 인정하는 것과 동일 시멘틱. 측정값 (페이지 4, baseline-to-baseline): 개체 모양 복사 → `<스타일에서>` : 15.22 → **37.89** (Hancom ≈40) ✓ `<스타일에서>` → 스타일 적용 : 15.22 → **31.22** (Hancom ≈40, -8.92 px 잔차) 전체 7 페이지 본문 첫 줄 top 정합 변동 없음 (Case 5 + 가드만 추가). 전체 테스트 1246 통과. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
shortcut.hwp 의 우측 단축키 (Alt+P/Ctrl+P, Alt+Shift+C, Ctrl+W,H 등) 가
컬럼 우측 끝에 정렬되지 않고 ~27 px 좌측으로 밀려 렌더되는 결함.
원인 (2 가지 경로):
1. **cross-run pending mechanism** (paragraph_layout.rs:1075, 1514):
`effective_pos = if tab_type == 1 && fill_type != 0 { effective_margin_left +
available_width } else { tab_pos }`. auto_tab_right (fill_type=0) 케이스가
`else` 로 가서 effective_margin_left (≈27 px) 가 누락. → fill_type 무관하게
tab_type==1 이면 effective_margin_left 추가.
2. **intra-run tab handling** (text_measurement.rs):
`\t` 가 run 시작에 오는 paragraph (개체 모양 복사\tAlt+Shift+C, CharShape
boundary 가 `\t` 위치인 경우) 는 compute_char_positions / compute_total_width
의 inline_tabs 분기를 탐. HWP5 의 ext[0] 는 Hancom 의 right-tab 결과 위치
(= 우측 끝 - 한컴_seg_w) 이지만 한컴 폰트 metric 기준 — 우리 폰트의 seg_w
가 다르면 좌측 이탈. auto_tab_right=true + 단일 tab 일 때 ext[0] 를 무시
하고 col-relative right edge - our_seg_w 로 override.
조치:
- TextStyle 에 `text_start_offset` 필드 추가 (effective_margin_left 전달용).
- paragraph_layout.rs 의 cross-run 두 분기에서 tab_type==1 일 때
effective_margin_left 변환 적용.
- text_measurement.rs 의 inline_tabs / has_custom_tabs 분기에서 auto_tab_right
override 추가 — body_right_text_rel = text_start_offset + available_width -
line_x_offset, total = body_right_text_rel - our_seg_w.
측정 (페이지 4 단축키 right edge, Hancom 기대 532.33 px):
Alt+L (pi=142): 472 → **524** ✓
Alt+T (pi=143): 472 → **524** ✓
Alt+Shift+C (pi=144): 497 → **532** ✓
Alt+Shift+V (pi=145, col 1, Hancom 1001): 974 → **1001** ✓
F6 (pi=146): 993 → **1001** ✓
Shift+Enter (pi=147): 1006 → **1006** (변동 없음, 이미 정합)
전체 테스트 1246 통과. shortcut.hwp 7 페이지 본문 첫 줄 top 정합 유지.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ignment 정합 직전 commit `db6332b2` 는 EmbeddedTextMeasurer (native) 만 정정. WASM 빌드 의 WasmTextMeasurer (rhwp-studio 가 사용) 는 동일 버그를 가짐: 1. inline_tabs LEFT (tab_type 0/1) 경로: Hancom 의 `ext[0]` 사전 계산 위치 를 그대로 사용. 우리 폰트의 seg_w 와 차이로 좌측 이탈. 2. has_custom_tabs 경로: auto_tab_right (fill_type=0) 시 effective_margin_left (= text_start_offset) 변환 누락. 조치: EmbeddedTextMeasurer 와 동일 패턴 적용. - `auto_tab_right` paragraph + 단일 tab → body_right_text_rel - our_seg_w override. - `tab_type == 1` + (`fill_type != 0` || `auto_tab_right`) → text_start_offset + available_width - line_x_offset 사용. `cargo check --target wasm32-unknown-unknown --lib` 정상. native 테스트 1246 통과 (변경 없음 — WASM 코드는 cfg(target_arch="wasm32")). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ight-tab block_w 정합
shortcut.hwp p.4 pi=138 "상용구 등록\tF3→Alt+I" 의 단축키가 우측 정렬되어
col 0 우측 끝 (532.7 px) 을 넘어 ~38 px 만큼 더 우측으로 쏠려 렌더됨
(F 가 479.7 대신 516.7, I 가 col 0 우측 끝을 초과).
원인: composer 가 lang/script 경계로 run 을 쪼갠다 — "→" (U+2192,
lang 5/symbols) 가 "F3" (lang 1/Latin) 과 "Alt+I" (lang 1) 사이에 있어
run 2 "\tF3→Alt+I" 가 ["\tF3", "→", "Alt+I"] 3 sub-run 으로 분리됨.
text_measurement 의 `measure_segment_from` 은 현재 run 내부만 측정하므로
seg_w = width("F3") ≈ 16 px 로 과소 계산되어 우측 정렬 기준점이 38 px
우측으로 이동.
조치: 후속 run 합산을 paragraph_layout 이 미리 계산해 주입.
- `TextStyle.right_tab_block_width_override: Option<f64>` 신규 필드.
- paragraph_layout 의 est/render 두 pass 에서 "현재 run 의 last \t 가
line 의 last tab + post-tab 콘텐츠가 후속 run 으로 이어짐" 케이스 감지 후
post_tab_w (현재 run) + `right_tab_block_width` (후속 runs) 합산을 주입.
- text_measurement 의 estimate_text_width / compute_char_positions native+
WASM 두 path 의 `override_to_right` 분기에서 주입값이 있으면 사용,
없으면 종전 동작 유지.
검증:
- `cargo test --release --lib`: 1246 passed / 0 failed / 2 ignored
- `cargo check --target wasm32-unknown-unknown --lib`: 정상
- pi=138 F: 516.70 → 479.70 (-37 px); I 끝: ~572 → ~534 (col 0 우측 끝
532.7 와 정합).
- pi=140 "상용구 내용 보기 Ctrl+F3" (lang split 없음, 동일 path) 회귀 없음.
shortcut.hwp 1 페이지 우측하단 자동번호 "1" 의 시각 상단이 본문 "지우기" 섹션 (col 1 의 Ctrl+BackSpace / Ctrl+Y / Alt+Y 행) 위로 광범위하게 올라와 한컴 PDF (`pdf/basic/shortcut-2022.pdf`) 와 정합 불일치. 조사: - 바탕쪽 글상자 CharShape 3 base_size = 25400 (254 pt = 338.67 px). - shape_attr: original_width=16135, current_width=43201, render_sx=2.677; original_height=13359, current_height=33571, render_sy=2.513. 즉 도형이 원본 대비 2.5~2.7× 확대된 상태. - 한컴 PDF 의 "1" 시각 높이 ≈ 115 px (font ≈ 95~150 pt) → 우리 렌더링 보다 2.5~3× 작음. 한컴은 확대 도형 안 글꼴에 (original / current) 의 역 비율을 적용해 절대 크기를 유지 (확대 전 design size 보존). 조치: - `ResolvedStyleSet` 에 `Clone` 유도 (로컬 스타일 사본 생성용). - `layout_textbox_content` 진입 시 shape_attr 의 max(sw, sh) > 1.5 일 때 styles 사본을 만들고 모든 char_styles 의 font_size / letter_spacing 을 1/max_ratio 로 축소. 본 글상자 호출 범위 내에서만 styles 가 교체되어 본문/일반 도형 (sw/sh ≈ 1.0) 에는 영향 없음. 결과: - "1" font-size: 338.67 px → 126.49 px (254 pt → ~95 pt). - "1" 시각 상단이 본문 "지우기" 행보다 아래로 내려와 한컴 PDF 정합. - `cargo test --release --lib`: 1246 passed / 0 failed / 2 ignored - `cargo check --target wasm32-unknown-unknown --lib`: 정상.
…aph 셀 trailing ls 포함
aift.hwp p10 의 13×10 표 pi=123 마지막 행 ("4. 자연어 질의 기반 도면 검색
정확도") 이 한컴 PDF (`pdf/aift-2022.pdf`) 에서는 다음 페이지로 넘어가지만
rhwp 는 p10 마지막 행으로 잘못 분할.
조사:
- 표 cumulative_heights[6] = 555.24 px (rows 0~5 합계)
- avail_for_rows = 555.76 px
- 0.52 px 차이로 row 5 가 페이지에 fit → 한컴 분할 위치와 불일치.
- 한컴 PDF 는 row 4 (3.BOM 자동 작성) 까지만 p10 에 배치 (= rows 0~4 = 5
행), row 5 (4.자연어 질의) 부터 다음 페이지로 분할.
- 셀 콘텐츠 높이 계산에서 다중 paragraph 셀 (예: cell[52] r=5,c=9 "공인
시험기관을 통한 성능 검증 | 평가 데이터셋 구축 후 평가") 의 마지막
paragraph 마지막 line 의 `line_spacing` 을 누락. 한컴은 이 trailing gap
도 셀 콘텐츠 높이에 포함 (= 셀 하단 trailing gap 보존).
- cell[52] : 99.76 → 106.16 px (+6.4 px). row_heights[5] 동반 상승.
- cumulative_heights[6] : 555.24 → 561.64 px > avail 555.76 → row 5 다음
페이지로 push.
조치:
- `height_measurer` 의 `is_cell_last_line` 가드를 `cell_para_count > 1`
케이스에서만 우회. 단일 paragraph 셀은 종전 동작 유지 (회귀 방지).
- 두 calc 경로 (가로쓰기 일반 + 비-인라인 컨트롤 폴백) 모두 동일하게 적용.
검증:
- `cargo test --release --lib`: 1246 passed / 0 failed / 2 ignored
- `cargo check --target wasm32-unknown-unknown --lib`: 정상
- p10 PartialTable: rows=0..6 → rows=0..5 (5 rows on p10)
- p11 PartialTable: rows=6..13 → rows=5..13 (8 rows on p11)
- 한컴 PDF 시각 정합 (p10 마지막 행 = "3.BOM 자동 작성 정확도").
…e.common.height 모순 가드 aift.hwp p19~20 "기능 간 이벤트 연계 구성도 이미지" 표 pi=236 가 한컴 PDF (`pdf/aift-2022.pdf`) 에서는 p19 하단에 들어맞지만 rhwp 는 p20 으로 push. 조사: - table.common.height = 8464 HU (= 112.9 px), cell.height = 11753 HU (= 156.7 px). cell.height > table.common.height — 1×1 표에서 모순 (단일 셀이 외곽 표 보다 클 수 없음). - HWP 파일 inconsistency: 표 외곽 크기 8464 vs 셀 11753. - p19 가용 잔여 = 118 px. 우리는 effective_height = 156.7 (cell.height) 사용 → 118 < 156.7 → p20 push. 한컴 PDF 는 ~30 px 로 렌더 (content + pad 기반). - 한컴은 cell.height > table.common.height 모순 케이스에서 cell.height 를 무시하고 content+pad 로 행 높이 결정. 조치: - `height_measurer::measure_table_impl` 1단계 (row_span==1 셀의 max height 추출) 에서 1×1 표 (row_count == 1 && col_count == 1 && cells == 1) + cell.height > table.common.height 일 때만 cell.height 적용을 스킵. 2단계 (content+pad) 가 row_heights 를 채움. - table_layout 의 rect 렌더링은 MeasuredTable.row_heights 를 경유하므로 pagination 과 rendering 이 자연 일치. 결과: - p19 마지막 행: "기능 간 이벤트 연계 구성도 이미지" 17.09 px 박스 (한컴 PDF 시각 정합). - 전체 페이지 수: 77 → 75 (한컴 PDF 74 와 -1 차이). - `cargo test --release --lib`: 1246 passed / 0 failed / 2 ignored - `cargo check --target wasm32-unknown-unknown --lib`: 정상 가드 범위는 1×1 단일 셀 표로 한정 — 다중 행/열 표는 종전 동작 유지 (rowspan/병합 셀 height 분배 회귀 방지).
…t > table.common.height 모순 가드" This reverts commit 1616a52.
…ght > 가용 시 페이지 경계 분할 허용 이전 edwardkim#5 fix (cell.height 클램프) 는 표 시각 크기를 17 px 로 축소 → 한컴 PDF 와 시각 정합 실패. 한컴은 1×1 표 (line_count == 1) 의 cell.height (156.7 px) 가 가용 공간 (118 px) 보다 클 때, 페이지 경계에서 셀을 잘라 다음 페이지로 연속 렌더 (intra-cell 분할 허용). 조사: - typeset.rs `typeset_block_table` 의 첫 행 advance guard (line 2032~) 가 `first_row_splittable = is_row_splittable(0)` 만 체크. 1 line 셀은 is_row_splittable = false 라 가드가 advance_column_or_new_page 호출 → 표 전체가 다음 페이지로 push. - 한컴은 cell.height 빈 공간을 페이지 경계에서 잘라낼 수 있도록 force-split 허용. line_count 와 무관. 조치: - advance guard 에 `first_row_force_splittable` 조건 추가: `!first_block_protected && can_intra_split && remaining_on_page > 0`. force-split 케이스에서는 가드가 advance 를 건너뛰고, 메인 split 루프의 force-split 분기 (line 2153~) 가 셀을 가용 공간만큼 분할. 결과: - aift.hwp p19 PartialTable: pi=236 rows=0..1 split_end=114.2 px → p19 하단에 117.96 px 박스 (셀 상단 + 타이틀 텍스트 가시). - 전체 페이지 수: 77 → 75 (한컴 PDF 74 와 -1 차이). - `cargo test --release --lib`: 1246 passed / 0 failed / 2 ignored - `cargo check --target wasm32-unknown-unknown --lib`: 정상. 잔존: - p20 상단의 셀 빈 영역 연속 렌더 (한컴 PDF: 156.7 - 117.96 ≈ 39 px 박스) 미발현. `remaining_content_for_row` 가 content_offset > content_height 시 0 반환 → 루프 조기 종료. 추후 cell.height 기반 잔량 추적 필요 시 별도 타스크.
…외 — 한컴 PDF 정합 aift.hwp p21 "협업 시스템 구성도 이미지" 표 pi=268 (1×1 placeholder, 156.7 px) 직후 pi=284 "코멘트 스레드 관리 (답글·멘션·해결 처리)" 가 9.6 px 부족으로 다음 페이지로 밀려 한컴 PDF 와 페이지 분할 불일치 (한컴 p21 끝에 위치). 조사: - p21 hwp_used = 944.5 px (HWP 파일 vpos 기준), 우리 used = 959.9 px. - 차이 +15.4 px 중 9.6 px = host 문단 line_spacing (= LINE_SEG.line_spacing). - 비-TAC 표 의 `host_spacing.after = sa + outer_bottom + host_line_spacing` 계산에서 host_line_spacing (9.6 px) 가 표 사이즈에 가산되어 다음 paragraph 배치 공간 부족. - 한컴은 표의 outer_margin_bottom 만 사용 (host paragraph line_spacing 은 본문 라인 간 간격 의미. 표 외곽 spacing 아님). 조치: - 비-TAC 1×1 placeholder 표 (col_count==1, paras 모두 컨트롤 없는 단일 line_seg) 케이스만 host_line_spacing 제외. 일반 비-TAC 표 (다행/다열, 내부 컨트롤 포함 셀) 는 종전 동작 유지 — 라인 분리 회귀 방지. 결과: - p21 마지막 행: "코멘트 스레드 관리 (답글·멘션·해결 처리)" pi=284 (한컴 PDF 시각 정합). - 전체 페이지 수: 75 → **74** (한컴 PDF 와 일치). - `cargo test --release --lib`: 1246 passed / 0 failed / 2 ignored - `cargo check --target wasm32-unknown-unknown --lib`: 정상.
…=Para host vpos jump guard aift.hwp p44 (한컴 PDF p38) 에서 pi=579/pi=581 비-TAC TopAndBottom 표가 서로 겹쳐 그려지는 결함 정합. 원인: 1. pi=579 의 host paragraph (text=" ", 1 line, TopAndBottom+vert=Para Table) first_vpos=33421 HU 가 비정상적으로 크다 (prev pi=578 vpos_end=5920 → forward jump 27501 HU ≈ 367 px). HWP 가 stale layout 의 vpos 를 인코딩한 것으로 추정. 2. layout.rs:1830 의 vpos correction 이 이 값을 신뢰하여 pi=579 를 y=521 로 jump (자연 flow 위치 y=154). 3. pi=580 (FullParagraph) 가 y=950 까지 밀려나고, pi=581 (TopAndBottom +vert=Para+v_offset=21.7 px) 의 anchored y = 971.68 px > body_bottom=726.6. 4. compute_table_y_position (table_layout.rs:1218) 의 clamp 가 pi=581 을 y=726.6 로 끌어내려 pi=579 표 (y=549..912) 와 시각적으로 겹친다. 한컴 PDF 는 pi=579 를 자연 flow 위치(y~185)에 배치하므로 표가 모두 페이지에 fit 한다. 수정: layout.rs 의 vpos correction 단계에서 가드 추가. - 현재 paragraph 가 TopAndBottom+vert=Para Table 을 anchor 하고 - forward jump (end_y - y_offset) > 100 px 면 stale vpos 로 간주, skip. 결과 (aift.hwp p44): - pi=579 y: 521.2 → 154.5 - pi=579 표 y: 549.8 → 183.1 (한컴 PDF ~185 정합) - pi=581 y: 722.1 → 598.3 (overlap 해소) - pi=582/583/584 overflow: 38/66/161 px → 0/0/37.6 px 부차: tests/issue_554.rs 의 aift 페이지 카운트 expectation 77 → 74 갱신 (Task edwardkim#874 누적 정합 결과 한컴 PDF (pdf/aift-2022.pdf, 74p) 와 동일). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…onflict # Conflicts: # src/renderer/typeset.rs
Stream/devel 머지 (e039450) 후 paragraph 위치/spacing 미세 변동으로 3개 svg_snapshot golden 이 불일치. UPDATE_GOLDEN=1 으로 현재 코드의 렌더링 결과로 갱신. - tests/golden_svg/issue-267/ktx-toc-page.svg - tests/golden_svg/issue-617/exam-kor-page5.svg - tests/golden_svg/issue-677/bokhakwonseo-page1.svg 대부분 y 좌표 미세 shift (~7 px) — Task edwardkim#853 spacing_before 보정 등 누적 정합 결과. 시각적 의미 차이는 없음. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…페이지로 — page_avail 에 v_offset 차감
aift.hwp p44 (한컴 PDF p38) 의 pi=584 (TopAndBottom+vert=Para+v_offset=21.7px)
PartialTable 이 rows=0..2 (header + 행 1 partial split_end=41.6) 로 잘못
분할되어 행 1 ("o 사업화 형태:") 가 페이지 하단에 약 37.6 px 오버플로우.
한컴 PDF 는 헤더만 (rows=0..1) 분할 후 행 1 전체를 다음 페이지에 표시.
원인: typeset_block_table 의 page_avail 산출이 TopAndBottom+vert=Para
표의 v_offset 와 host_spacing.before 를 차감하지 않음 — layout 은 표를
cur_h + host_spacing.before + v_offset 위치에 배치하므로 split 결정 시
가용 공간이 과대 평가됨.
수정: 첫 fragment (!is_continuation) page_avail 에서 host_spacing.before
와 v_offset 차감. HwpUnit=u32 wrap (음수 vertical_offset) 처리를 위해
i32 캐스트 후 > 0 검사.
결과 (aift.hwp p44):
- pi=584 PartialTable: rows=0..2 (split_end=41.6) → rows=0..1 (no split)
- 행 1 "o 사업화 형태:" 가 page 45 에 정상 표시
- LAYOUT_OVERFLOW 37.6 px 해소
기존 회귀 차단:
- issue_713 (RowBreak 표 인트라-로우 분할 금지): v_offset u32 wrap 처리로 통과
- task554 aift 페이지 카운트 74p 유지
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…kim#290 회귀 차단 — inline LEFT tab 보호 db6332b (Task edwardkim#874 auto_tab_right) 의 override_to_right 가 inline ext[2] high-byte 검사 없이 paragraph 의 auto_tab_right 만으로 강제 적용 되어, 명시적 LEFT inline tab (high-byte=1) 도 right-align 됨. 증상: exam_math.hwp p7 item 18 "18.\t수열..." 의 "수" 가 x=109.8 (정합) → x=290.8 (회귀, Task edwardkim#290 의 원래 BUG 상태) 로 이동. 원인: ext[2] high-byte 가 명시적 정렬 종류 (1=LEFT, 2=RIGHT, 3=CENTER, 4=DECIMAL) 를 인코딩. db6332b 의 override 가 high-byte=1 LEFT 도 ParaShape.auto_tab_right=true 면 right-align 강제. shortcut.hwp 의 ext[2] high-byte=2 RIGHT 와 동일 취급. 수정: text_measurement.rs 의 양쪽 inline_tabs 분기 (estimate_text_width + compute_char_positions) 에 inline_is_explicit_left 가드 추가 — high-byte ∈ {1, 4} 이면 override 미적용. 검증: - exam_math.hwp p7 item 18 "수" x=290.8 → 109.8 (Task edwardkim#290 정합) - task290_exam_math_p7_item18_not_right_aligned ✓ pass - shortcut.hwp p4 Alt+L right edge 524.28 (Hancom 기대 532) — Task edwardkim#874 유지 - 전체 테스트 통과 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Task edwardkim#874 edwardkim#10 (b6d91ff) 에서 추가한 `chars[i+1..].iter().any(|c| *c == '\t')` 2개소가 clippy 1.95.0 `manual_contains` lint 에 걸려 PR edwardkim#872 Build & Test 실패. 수정: `chars[i+1..].contains(&'\t')` 로 치환 (의미 동일, 더 효율적). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… 회귀 차단 b6d91ff 의 Task edwardkim#874 edwardkim#10 회귀 가드 (inline_is_explicit_left) 가 native EmbeddedTextMeasurer 의 2개소 (라인 265, 423) 에만 적용되어 WASM 경로 WasmTextMeasurer 2개소 (라인 740, 884) 는 가드 누락 상태. 증상: native (cargo build / SVG export / cargo test) 는 정합이나 rhwp-studio (WASM Canvas) 에서 exam_math.hwp p7 item 18 "18.\t수열..." 의 "수" 가 우측 끝 (~290) 으로 정렬 — Task edwardkim#290 의 원래 BUG 상태로 회귀. 원인: WasmTextMeasurer 의 override_to_right 가 inline_tab_type(ext) (= ext[2] high-byte) 검사 없이 ParaShape.auto_tab_right 만으로 강제 적용. high-byte=1 LEFT / 4 DECIMAL 도 right-align 강제됨. 수정: WASM 두 경로 (estimate_text_width 라인 740, compute_char_positions 라인 884) 에 native 와 동일한 가드 추가: let inline_is_explicit_left = tab_type == 1 || tab_type == 4; override_to_right = ... && !inline_is_explicit_left; (tab_type 은 이미 inline_tab_type 으로 high-byte 정규화된 값이므로 재추출 불필요. native 경로의 inline_type_hi 와 동일 의미.) 부수: clippy manual_contains 동시 정리 (`iter().any()` → `contains()`). 검증: - cargo check --lib --target wasm32-unknown-unknown ✓ - cargo clippy --lib --target wasm32-unknown-unknown -- -D warnings: text_measurement.rs 0 errors (16 pre-existing errors 는 web_canvas.rs) - task290_exam_math_p7_item18_not_right_aligned ✓ pass (native 회귀 없음) - issue_595 (5), issue_301 (1) ✓ pass Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
edwardkim
pushed a commit
that referenced
this pull request
May 14, 2026
…closes #866) PR #872 (@planet6897) GitHub diff 기반 cherry-pick. mydocs 거버넌스 산출물 제외. supersedes PR #868. #866 v2: 구분 칸 spacing 압축 + solo_zone_pad + zone별 점선 구분선 #866 v3: 헤더 띠 leaving 보정 + <...> paragraph spacing #874: 헤더 띠 band 가산 제거 + auto_tab_right 정렬 + 스케일 도형 글꼴 검증: - cargo test --release --lib: 1246 passed (회귀 0) - SVG 7페이지 (한컴 2022 PDF 정합) - 시각 판정 ★ 통과 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Owner
|
검토 + cherry-pick 머지 완료. 감사합니다. 처리 결과
재검증
shortcut.hwp 정합성을 다각도로 정밀하게 맞춘 대규모 작업입니다. 수고하셨습니다. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
closes #866 ·
<...>소제목 spacing · 헤더 띠 band items-based 분기 · 우측 단축키 right-alignment (native + WASM) · 스케일 도형 내부 글꼴 정합 · Task #874 (Case 1·2·3·4·5 + auto_tab_right + auto_tab_right lang split + 스케일 도형 글꼴) · supersedes #868요약
shortcut.hwp 의 페이지 내 다단 zone 전환·점선 단 구분선·
<...>소제목 zone 간격·페이지 시작 baseline·헤더 띠 band 가산·<...>인접 줄간격·우측 단축키 right-alignment·바탕쪽 자동번호 시각 크기를 한컴 PDF (pdf/basic/shortcut-2022.pdf) 와 정합되도록 정정. 본 PR 은 #866 v2 (5 커밋) + #866 v3 (3 커밋) + #874 (12 커밋) 누적 묶음.커밋 (
stream/devel위에 21 commits stacked)#866 (v2)
b1449bc16561b981[단나누기]를process_multicolumn_break로 라우팅cf6d6d0dsolo_zone_pad+16px — 1단/간격=0 zone 진입·이탈 시 추가 여백e489fc80emit_zone_column_separators) +column_break_pad5631e68f#866 (v3) — 사용자 피드백 후속
07c82c58unreachable_pattern제거 (PR #872 CI)a012f896solo_zone_pad제외 (leaving_is_header_band)435e6207<...>단독 paragraph spacing +20px (이후 #874 Case 3 에서 제거)#843 정합
cac13984stream/devel(PR #843) 정합#874 (Stage 1·2·Case 1·1v2·3·5·5v2·5v3v4·auto_tab_right native·WASM·lang split·스케일 도형 글꼴)
72fa97023a15c3a9cd_gap_zerofallback chain,design_spacing ≤ 1mm인정d53b8b59<...>paragraph-level 이중 패딩 제거 (페이지당 45개 누적 +1730pt → +8px)b29f4368220d91d1ac4c3b41col_content.items수로 분기6c641e68<...>solo paragraph 까지 확장537372ccprev_zone_was_solo분기 + cd 간격≤1mm인정 (페이지 4 줄간격 15.2 → 31~38 px)db6332b28b6ca137WasmTextMeasurer양 경로 동일 패턴 적용41fe9db8right_tab_block_width_override주입21d6a367결과 (shortcut.hwp ↔ pdf/basic/shortcut-2022.pdf)
본문 첫 줄 top (px) 정합도 — 7 페이지 모두 ±6 px 내
<글상자에서>직후)우측 단축키 right edge (px) 정합도 — 한컴 PDF 기대 = col 0: 532.33, col 1: 1001.33
페이지 4 줄간격 (baseline-to-baseline, Case 5 v3+v4)
<스타일에서><스타일에서>→ 스타일 적용바탕쪽 자동번호 "1" 시각 정합 (스케일 도형 글꼴)
기타 정합 항목
<편집 화면 분할에서>위치<...>paragraph excess검증
cargo test --release --lib: 1246 passed / 0 failed / 2 ignoredcargo check --target wasm32-unknown-unknown --lib: 정상 (WASM 코드는cfg(target_arch = "wasm32")로 분기)exam_math.hwp,21_언어_기출_편집가능본.hwp)잔존 (미세 항목)
<...>→ 본문 줄간격 31.2 px vs 한컴 ≈40 px — -8.9 px 좁다 잔차. 시각적으로는 정상 줄간격 범위.hwp_used≈XXX, diff=-N잔차 —hwp_used계산식과 rhwpused의 trailing_ls 포함 여부 차이 (시각 영향 없음).문서
mydocs/plans/task_m100_866_v2_impl.md— 구현 계획서 (shortcut.hwp: 쪽나누기로 시작하는 페이지의 헤더 TAC 띠 ↔ 본문 사이 ~28px gap 미재현 #866)mydocs/working/task_m100_866_v2_stage1.md~_stage3.md— 단계별 보고서 (shortcut.hwp: 쪽나누기로 시작하는 페이지의 헤더 TAC 띠 ↔ 본문 사이 ~28px gap 미재현 #866)mydocs/report/task_m100_866_v2_report.md— 최종 결과 보고서 (shortcut.hwp: 쪽나누기로 시작하는 페이지의 헤더 TAC 띠 ↔ 본문 사이 ~28px gap 미재현 #866)🤖 Generated with Claude Code