Task #146: text-align.hwp SVG ↔ 한컴 PDF 렌더링 일치#256
Conversation
- samples/text-align.hwp 신규 편입 - text-align.pdf ↔ SVG 150dpi 비교 파이프라인 명령 고정 - 버그 후보 3건(공백 advance 누락/Justify 미반영/hanging indent) 수치 베이스라인 확보 - 코드 변경 없음 (조사·문서 단계) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
is_fullwidth_symbol 범위 리스트에 U+25A0-U+25FF (□■▲◆○ 등 Geometric Shapes 블록) 추가. HWP 섹션 머리 기호로 빈번히 쓰이며, PDF(한컴) 폰트 메트릭은 이를 전각으로 측정하나 rhwp 는 반각(em/2) 으로 측정해 후속 글자가 ≈em/2 만큼 좌측으로 붕괴하던 문제 해결. - 수정: text_measurement.rs:845 is_fullwidth_symbol 에 한 줄 추가 - 테스트: tests.rs 에 Geometric Shapes 전각 검증 + "□ 가" 회귀 방지 2건 검증 (samples/text-align.hwp): - 제목 "국" 시작 x: 94.40 → 105.40 (PDF 환산 105.39 와 0.01px 일치) - cargo test --lib: 929 passed (신규 2건 포함) - cargo clippy --lib -- -D warnings: clean Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- 수행계획서 v2: 원본 ②③(Justify/Hanging indent) 은 PDF 좌표 비교 결과 실제 버그 아님이 확인되어 범위 축소. 핵심은 ① 공백 advance 가 아닌 □ 글자 폭 측정 오류 (is_fullwidth_symbol 범위 누락). - 구현계획서 v2: 2단계 (소스 + 테스트, 통합 검증) - 단계2 보고서: 수정 내역, 좌표 비교, 영향 정량화 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- form-002 page 0 golden 업데이트: "□ 개념" / "□ 개발내용" 섹션 머리에서 □ 전각 인식으로 후속 글자 +9px 정상 advance (2 위치 × 3줄 = 6줄 변경) - 최종 결과보고서: 원인 규명(가설 ② Justify / ③ hanging indent 기각 → 실제 원인은 is_fullwidth_symbol 범위 누락), 수정 내역, 검증 결과 - orders/20260423 완료 상태로 갱신 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
pagination 이 TAC 표 문단에 PageItem::Table 만 발행하고 FullParagraph 를 발행하지 않아 paragraph_layout 의 TAC 분기가 호출되지 않는 경우 (선행 공백만 있는 TAC 표, 또는 너비 ≥ 90% seg_width 로 block 분류된 TAC 표), layout_table_item 의 inline_shape_position 이 비어있어 표가 body_left(col_area.x) 에 붙는 문제 수정. layout_table_item 의 tbl_inline_x 분기에 is_tac 케이스 추가: composed.lines[0] 의 runs 에서 target TAC 이전 텍스트 폭을 직접 합산. block 취급 TAC (tac_controls 빈 상태) 에서는 line 0 전체 합산 fallback. - 수정: layout.rs tbl_inline_x 분기 + compute_tac_leading_width 헬퍼 - 테스트: tests.rs 에 block/inline 두 케이스 검증 2건 - 검증 (samples/text-align.hwp): 표 첫 셀 x 75.59 → 109.59 (PDF 환산 112 와 ±3px 수렴) - cargo test --lib: 931 passed (신규 2건 포함) - cargo test --test svg_snapshot: 3 passed (기존 golden 영향 없음) - cargo clippy --lib -- -D warnings: clean Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- v3 수행·구현계획서: TAC 표 선행 공백 x 좌표 보정 스코프 (2단계) - 단계4 보고서: 수정 내역, 원인 재확인(composer is_tac_table_inline 90% 임계치로 block 분류된 TAC 표에서 tac_controls 비어있는 케이스), 검증 결과 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
HY헤드라인M / HY견고딕 / HY견명조 / HY그래픽 등 face 이름 자체가 굵은 display 폰트들은 HWP CharShape.bold=false 로 저장되어도 PDF(한컴) 출력에서는 heavy face 자체 weight 로 굵게 렌더된다. rhwp SVG 는 해당 face 가 설치되지 않은 환경에서 Malgun Gothic 등 regular fallback 으로 떨어지며 시각적 bold 가 소실. - style_resolver.rs: is_heavy_display_face() 헬퍼 추가 (8개 face) - mod.rs: TextStyle::is_visually_bold() 메서드 (bold || heavy_face) - svg.rs: 4곳 font-weight="bold" 분기를 is_visually_bold() 로 치환 - tests.rs: heavy face 매칭 + 체인 기준 primary face 판정 2건 추가 검증 (samples/text-align.hwp): - 제목 "□ 국어 변화..." 에 font-weight="bold" 속성 추가됨 - Chrome headless 150dpi 렌더에서 제목이 PDF 와 시각적으로 근사한 굵기 - cargo test --lib: 933 passed (신규 2건 포함) - cargo test --test svg_snapshot: 3 passed (기존 golden 영향 없음) - cargo clippy --lib -- -D warnings: clean Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- v4 수행·구현계획서: heavy display face 시각 bold 근사 스코프 (2단계) - 단계5 보고서: 수정 내역, is_heavy_display_face 헬퍼, TextStyle::is_visually_bold, svg.rs 4곳 분기, 시각 검증 결과 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- 최종 결과보고서 v4: v1~v4 전체 여정, 좌표·시각 수렴 표, 커밋 이력, 잔여 범위, 종결 승인 요청 - 단계6 보고서: 테스트 재확인(933 passed, clippy clean, svg_snapshot 3 passed), 스모크 스위프(exam_kor/biz_plan/text-align) 회귀 없음 - orders/20260423.md: v3/v4 단계 체크박스 + 머지 대기 상태 종결 항목: - 수행계획서 v1~v4, 구현계획서 v1~v4 - 단계별 보고서 stage1~stage6 (6건) - 신규 단위 테스트 6건, 신규 샘플 1건, svg_snapshot golden 1건 갱신 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…etric Shapes + TAC 표 선행 공백 + heavy face bold)
|
@planet6897 감사합니다. 머지 완료했습니다. 이번 PR 에서 특히 인상적이었던 점: 진단 방법의 엄밀성. 기각된 초기 가설을 기록해주신 것도 큰 자산이 됩니다. Justify 미반영 / Hanging indent 어긋남 가설을 0.04~0.12 pt 오차로 정상 동작임을 실측으로 확인하신 기록은 다른 기여자가 같은 가설을 다시 검증하지 않아도 되게 해줍니다. 수행계획서 v1~v4 점진 확장 + 단계별 6개 보고서 + v4 최종 보고서까지 하이퍼-워터폴 구조를 완전히 따라주셔서 리뷰가 수월했습니다. 검증 결과 (로컬 최신 devel + PR #256 머지 후):
#146 close 수동 완료 (GitHub auto-close 가 이번엔 작동 안 했습니다). 다음 기여 때 참고용 소소한 팁: 이번처럼 기여자 fork 의 다시 한 번 감사합니다. |
- README: devel 섹션 추가 (edwardkim#157/edwardkim#267/edwardkim#256 PR 반영) - plans/ → plans/archives/: task_m100_267{,_impl}.md 이동
- 최근 변경: v0.7.3 → v0.7.6 (2026-04-26) 교체 - PR edwardkim#266 (Task edwardkim#157), edwardkim#273 (Task edwardkim#267), edwardkim#282 (Task edwardkim#279) by @seanshin - PR edwardkim#256, edwardkim#327, edwardkim#341, edwardkim#343 by @planet6897 - PR edwardkim#334, edwardkim#335 by @oksure, PR edwardkim#339 by @postmelee - devel 섹션: 머지된 항목 제거, 현재 분석 중(edwardkim#362/edwardkim#345) + 계획 중(edwardkim#150/edwardkim#253) 반영 - 테스트 수: 891+ → 1000+ - README_EN.md 동일 내용 영문 반영
mydocs/feedback/: - manual_currency_audit.md (매뉴얼 현행화 감사 결정 요청 — 2026-04-23) - open_issues_priority.md (열린 이슈 37건 우선순위 — 2026-04-22) - pr165_merge_decisions.md (PR #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 #256 검토 + 구현 계획) - pr_273_review.md (PR #273 Task #267 right tab 처리 검토) 이전 사이클 작성 후 미커밋 보관 — devel 머지 + push 진행 시 함께 커밋. Co-Authored-By: Claude Opus 4.7 (1M context) <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>
요약
text-align.hwp1페이지 문서의 rhwp SVG 출력이 한컴 오피스 PDF 출력과 시각적으로 달라 이를 3가지 수정으로 일치시켰다. 원인 규명은mutool draw -F stext로 추출한 PDF 문자 좌표와 SVG 좌표를 1:1 비교해 확정.수정 1: Geometric Shapes 블록 전각 처리
is_fullwidth_symbol범위 리스트에U+25A0-U+25FF(□■▲◆○ 등, 섹션 머리 기호) 추가수정 2: TAC 표 선행 텍스트 폭 반영
layout_table_item에compute_tac_leading_width헬퍼 추가PageItem::Table만 발행(FullParagraph 미발행)하는 경우paragraph_layout의 TAC 분기가 호출되지 않아 선행 공백이 표 x 좌표에 반영되지 않던 문제 해결수정 3: Heavy display face 를 visual bold 로 렌더
is_heavy_display_face헬퍼 +TextStyle::is_visually_bold메서드 추가기각된 초기 가설 (좌표 정밀 비교로 확정)
변경 요약
src/renderer/layout/text_measurement.rssrc/renderer/layout.rssrc/renderer/style_resolver.rsis_heavy_display_facesrc/renderer/mod.rsTextStyle::is_visually_boldsrc/renderer/svg.rssrc/renderer/layout/tests.rstests/golden_svg/form-002/page-0.svgsamples/text-align.hwpmydocs/{plans,working,report,orders}/...Test plan
cargo test --lib933 passed (신규 6건 포함, 기존 실패 14건은 본 PR 무관)cargo test --test svg_snapshot3 passed (form-002 golden 갱신 반영)cargo clippy --lib -- -D warningscleansamples/text-align.hwp150dpi 렌더 PDF 와 좌표 ±3 px 일치exam_kor.hwp(25페이지),biz_plan.hwp(6페이지),text-align.hwp— 회귀 없음samples/text-align.hwp출력 이미지로 시각 확인관련 문서
mydocs/report/task_m100_146_report_v4.mdmydocs/plans/task_m100_146_v{2,3,4}{_impl,}.mdmydocs/working/task_m100_146_stage{1..6}.md