Repository navigation
fix(typeset): 글 host 의 양수 오프셋 자리차지 표를 밀린 저장 줄이 아니라 문단 원점에서 잰다 (#8156) - #8159
planet6897 wants to merge 3 commits into
Conversation
…#7687) 빈 host 에 자리차지 표가 둘(오프셋 0 / 양수)인 문단은 edwardkim#7687 이후 글 있는 host 와 같은 visible float 배치(place_table_with_text)를 탄다. 그 배치는 표 원점에 바깥 위 여백을, 흐름 끝·배제 띠 끝에 바깥 아래 여백을 스스로 더한다. 그런데 통째 배치 호출부는 이 host 에 흐름용 높이(표 + host 앞 간격)와 RowBreak 흐름 꼬리(아래 여백)를 넘겨, 오프셋 0 표의 흐름 끝과 양수 오프셋 표의 배제 띠 끝이 바깥 여백만큼 더 내려갔다. 한글문서파일형식 20쪽 pi=130: 둘째 표 띠 끝 379.72px — 저장 사다리(pi=132 vpos 28197)와 배치는 375.96px. 뒤 빈 문단이 그 띠로 뛰어 pi=133 「3.2.12. 참고문헌」 host 원점이 3.76px 내려갔고, 통합 뒤 배치가 typeset 확정 원점을 쓰면서 그 host 의 둘째 표(7×2)·제목·뒤 본문이 정본보다 +4.3px 아래에 그려졌다. 첫 표(오프셋 0)는 배치 흐름이 놓아 제자리였다. 글 있는 host 처럼 표 상자 높이(effective_height)만 넘기고 흐름 꼬리를 붙이지 않는다. - 한글문서파일형식 20쪽: 둘째 표 686.0 → 682.3(정본 681.7), 「3.2.12.」 853.9 → 850.2(849.5) - 합성 K1~K4(gen_titled_host_after_band.py, 한/글 2020 Print): K1~K3 T4·뒤 글줄 +3.8px → 정본 ±0.5px, K4(앞 빈 host 없음) 불변 - 회귀: titled_host_after_empty_host_band_keeps_its_float_offsets — 수정 전 FAIL(K1 T4 496.7, 기대 492.9)
…kim#8156) 같은 문단의 앞 자리차지 표(오프셋 0)가 흐름을 소비하면 한/글은 host 첫 줄을 그 띠 아래에 저장한다. 통째 배치(entry.rs)는 저장 사다리가 인증한 그 첫 줄 원점 (source_text_origin)을 글줄 원점이자 표 앵커로 함께 넘겨, 뒤 양수 오프셋 표가 앞 표의 띠(바깥 여백 포함)만큼 아래로 내려갔다. 오프셋 0 표는 문단 원점 (placement_para_start_height)에 놓이므로 같은 문단의 두 표가 서로 다른 원점에서 쟀다. 앞에 공동 앵커 자리차지 표가 있으면 from_stored_host / from_stored_head_host 에 문단 원점을 넘긴다. 글줄은 종전대로 저장 원점(stored_host_origin)을 쓴다. 앞 표 띠와 겹치는 경우의 쌓기는 HostPlacementConstraint 가 그대로 맡는다. - 합성 K1~K4 HWP 저장본(한/글 2020 Print): T4 윗변 700.5/700.5/679.1/386.3 → 492.9/612.9/471.6/298.7 (정본 492.4/612.3/471.2/298.4). 글줄·T3 불변 - samples 1,318 · 10k 코퍼스 9,991 문서 SVG A/B: 변화 0 - 회귀: saved_titled_host_measures_offset_float_from_paragraph_origin — 수정 전 FAIL(K2 T4−T3 207.6, 기대 120.0)
…ve·fresh WASM)
19626cc to
c5d4943
Compare
기존 planet6897 PR #8111·#8141·#8152·#8157·#8159·#8163·#8170·#8176·#8185·#8193의 기능 commit 49개와 통합 보정을 반영합니다. 중복 종료된 #8130의 임시 2개 적용은 제거했으며 기능 적용 수에서 제외합니다. 메인터너 보정은 현재 셀 글줄·물리 프레임·선언 행 높이와 선택 span 정렬의 일관성, 공백·출력 경계 및 요청한 회귀 제외를 처리합니다. sample16 계열과 행정업무운영 편람 HWP/HWPX는 사용자 지시로 검토에서 제외했습니다. 검증 code head 673c1d5f7cdcb5573b793ba2d2abaaedd2602134의 전체 nextest는 11,481 PASS/0 FAIL/45 skip이며 필수 로컬 게이트 14개를 통과했습니다. Native/fresh WASM 각35조건·2,041쪽의 최저 raw 91.87422%/91.82753%,90% 미달·고정 devel 대비0.1%p 이상 하락은 없습니다. 실제 Native15/Canvas2D15/지원CanvasKit12와 초기화 JS/WASM 응답을 확인했습니다. Mac WASM은 no-opt 로컬 대체 빌드입니다. CI 보정은 편람 Gym 과제8건 제거에 따른 원장 기대 건수와 삭제된 case를 참조한 --print 대상 한 줄입니다. 제품 Rust·Studio source는 로컬 검증 head와 같습니다. 최종 PR head b1e93d8, 테스트 merge 41a30c3eeb6e50464b6806beeaa20dbaa23a77a8의 Full CI·CodeQL·Render Diff·Proptest·Adapter·Gym 검사가 모두 통과했습니다. Rust4 shard 합계11,288 PASS/0 FAIL/45 skip입니다. 원 PR별 검토 기록, 대응하는 review/overlay PNG·전쪽 TSV와 오늘할일을 포함합니다. 머지 후 사용자 지정 옵션2로 실제 CI·merge·후속 처리 기록을 보완합니다. 대표 #7445 전체 해결을 주장하지 않습니다. Refs #8099, #8105, #7687, #8156, #7874, #8169, #8167, #8172, #4599, #7445, #7765, #7881 Co-authored-by: Jaeuk Ryu <35355437+planet6897@users.noreply.github.com>
|
기여해 주셔서 감사합니다. 이 PR의 기능을 검토·체리픽 통합하여 PR #8228로 devel에 반영했습니다.
원 기여에서는 양수 오프셋 자리차지 표의 원점을 밀린 저장 줄이 아닌 문단 소유 정보로 결정합니다. 원 기여와 통합 보정#8157과 같은 4d06f563a6ba38c3d77cd8cbb81c02b9913f4c19는 중복 제외하고 고유 2개 기능 commit을 적용했습니다. 원 기여 기능과 메인터너의 통합 보정 범위는 위 개별 검토 문서의 적용 commit·소비 경로·실제 회귀 결과에 구분했습니다. 다른 PR의 문서나 제외한 sample16·편람을 이 PR의 개선 증거로 대신하지 않았습니다. 해당 원 PR의 전쪽 비교
전체 페이지 90% 미만·누락 0쪽입니다. 같은 조건의 고정 base 대비 0.1%p 이상 하락은 0쪽이며, 쪽수 개선은 본문 소유·순서 보존을 따로 확인했습니다. 실제 입력·PDF SHA-256과 증적 바이트. 이 원 PR에 대응하는 정식 회귀 1건의 실제 PASS는 개별 검토 기록에 기재했습니다. 직접 확인한 증적직접 판독: K1에서 앞 빈 host의 띠와 T4를, K4에서 앞 빈 host가 없는 T3/T4 상대 오프셋과 host/뒤 글줄을 확인했습니다. Visual Sweep 비교·병합 판정 방법과 공통 producer·해시·잔여 원장을 연결합니다. 일치율은 내용 픽셀 중심 자동 비교 보조값이며 사람 판독의 정확도나 완전한 픽셀 동일성을 뜻하지 않습니다. 이 원 PR은 별도 직접 merge가 아니라 통합 PR에 반영했으므로 종료하겠습니다. contributor의 원격 브랜치는 유지합니다. 관련 이슈 전체의 완료 여부는 개별 증거 범위로 별도 판단하며 이 PR 종료만으로 일괄 종료하지 않습니다. |




요약
글이 있는 host 문단에 문단 기준 자리차지 표가 둘(T3 오프셋 0, T4 양수 오프셋) 있는 HWP 저장본에서 T4 가 정본보다 약 88px 아래에 그려지던 문제를 고친다. T4 의 세로 오프셋을 문단 원점이 아니라 T3 아래로 밀려 저장된 host 첫 줄에서 쟀기 때문이다.
upstream/develf7abae4a895af7c48c는 fix(typeset): 빈 공동 앵커 host 자리차지 표의 띠·흐름에 바깥 여백을 거듭 더하지 않는다 (#7687) #8157 의 코드 커밋(e648df1cf)을 cherry-pick 한 것이다. K1~K3 의 남은 +4.3px 는 fix(typeset): 빈 공동 앵커 host 자리차지 표의 띠·흐름에 바깥 여백을 거듭 더하지 않는다 (#7687) #8157 몫이라 함께 있어야 수용 기준을 확인할 수 있다. fix(typeset): 빈 공동 앵커 host 자리차지 표의 띠·흐름에 바깥 여백을 거듭 더하지 않는다 (#7687) #8157 병합 뒤 rebase 한다.5b5e4291219626cce2원인 — 생산 → 소비 경로
typeset/table/block/entry.rs의 통째 배치는 저장 사다리가 인증한 그 첫 줄 원점(source_text_origin)을 글줄 원점이자 표 앵커로from_stored_host/from_stored_head_host에 넘겼다. 이 합성은 제어문자가 글 앞이라from_stored_head_host갈래를 탄다.table_top이 T3 띠(87.5px)만큼 내려가 확정 배치로 기록되고(record_paragraph_float_placement), layout 이 그 값을 그대로 그렸다.placement_para_start_height)에 놓인다. 같은 문단의 두 공동 앵커 표가 서로 다른 원점에서 재였다.수정
같은 문단에 앞선 공동 앵커 자리차지 표가 있으면(
has_preceding_coanchored_float) 두 생성자에 문단 원점을 넘긴다.stored_host_origin)을 쓴다. 글줄 위치는 바뀌지 않는다.HostPlacementConstraint가 그대로 맡는다(K1·K3).검증
입력은 #7687 합성 K1~K4(
samples/issue7687/gen_titled_host_after_band.py)를 한/글 2020 으로 HWP 저장한samples/issue8156/titled-host-hancom2020-saved.hwp(SHA-2560fe65f11…fd776)다. 정본은 같은 HWP 의 한/글 2020 Printpdf/issue8156/titled-host-hancom2020-saved-2020.pdf(4쪽,5ce45d9d…05df8)다.직접 좌표 (96dpi px)
PDF 텍스트 상자 대조: 네 쪽 모든 표 셀 글자·본문 줄이 정본과 0.5px 안에서 맞는다.
Visual Sweep — 전쪽 TSV (
tolerant_content_match_percent, raw 2px 실루엣)전체 쪽수 rhwp 4 = 정본 4.
대표 이미지 (head
19626cce2)K4(4쪽, 앞 빈 host 없음) — 수정 전 / 수정 후 review (Native)
K4 overlay (이 PR, Native / fresh WASM)
K1(1쪽, T4 가 앞 빈 host 의 T2 띠 아래에 쌓이는 경우) — 수정 전 / 수정 후 review (Native), overlay (이 PR, Native / fresh WASM)
직접 판독: K4 의 T4 는 「K4 제목」 줄 아래·「K4 글 1」 위에, K1 의 T4 는 T2 바로 아래에 놓여 정본 괘선과 겹친다. 글줄·T3 는 전후 같다. 남은 차이는 글리프 굵기뿐이다.
회귀 검사
tests/cases/issue_8156_saved_host_offset_float_anchor.rs::saved_titled_host_measures_offset_float_from_paragraph_origin를 추가했다. 기대값은 원본 속성(오프셋 9000HU, 바깥 여백 283HU)과 저장 줄에서 정한 관계이며, 정본 PDF 와 0.6px 안에서 맞는다.K2 T4 윗변 − T3 윗변: 실제 207.6, 기대 120.0영향 범위
samples 전수 1,318 문서와 별도 10k 코퍼스 9,991 문서의 전쪽 SVG 를 수정 전(#8157 만)·후로 해시 비교했다. 바뀐 문서 0, 오류 0. 이 형상(글 host + 앞 공동 앵커 표 + 양수 오프셋 표 + 저장 줄)은 새 HWP 표본에서만 나타난다. 저장 줄 없는
issue7687/titled-host.hwpx와 한글문서파일형식은 바이트 단위로 같다.게이트 (head
5b5e42912, basef7abae4a8)--check --base-ref f7abae4a8— 통과, error 0rust-unit-test-tiers --check: 통과issue_6520_svg_layer_contract::subset_font_bytes_are_deterministic_for_multiple_codepoints는 검증 환경 글꼴 때문이며 base 에서도 같다(fix(typeset): 빈 공동 앵커 host 자리차지 표의 띠·흐름에 바깥 여백을 거듭 더하지 않는다 (#7687) #8157 과 동일).scripts/wasm-pack-locked.sh --target web로 빌드한 패키지로 Sweep 했다.남은 것 / 비범위
🤖 Generated with Claude Code
최신 devel rebase (2026-10-23, #8173 절차)
upstream/develdef947c21로 충돌 없이 rebase(fix(typeset): 빈 공동 앵커 host 자리차지 표의 띠·흐름에 바깥 여백을 거듭 더하지 않는다 (#7687) #8157 의 코드 커밋을 그대로 아래에 둔 적층 유지). headc5d49433d(이전19626cce2). 위 SHA 고정 URL 은 새 head 로 갱신했다(같은 파일).c5d49433d, 빌드 전 소스 touch): fmt · Clippy 3종 · workspace build · manifest--check· unit tier 통과, nextest 11,478건 중 11,477 통과(실패 1건issue_6520_svg_layer_contract::subset_font_bytes_are_deterministic_for_multiple_codepoints는 이 host 의 시스템 한컴 글꼴 탓으로 base 에서도 같은 assertion 실패, 무관).--compat 2022, base = develdef947c21+ 무관 커밋, 바이너리·WASM sha256 확인):samples/issue8156/titled-host-hancom2020-saved.hwpsamples/issue7687/titled-host.hwpx