Repository navigation
fix(조판): RowBreak 표 분할·이어받기를 저장 쪽 경계 기록대로 — 1342000 쪽 수 415 일치·21761835·1480000·1613000 (부분 개선) - #7965
Open
planet6897 wants to merge 59 commits into
Open
fix(조판): RowBreak 표 분할·이어받기를 저장 쪽 경계 기록대로 — 1342000 쪽 수 415 일치·21761835·1480000·1613000 (부분 개선)#7965planet6897 wants to merge 59 commits into
planet6897 wants to merge 59 commits into
Conversation
planet6897
force-pushed
the
fix/devel-table-scan-regression
branch
from
October 17, 2026 12:00
0a88147 to
dd54037
Compare
jangster77
self-requested a review
October 17, 2026 15:04
planet6897
force-pushed
the
fix/devel-table-scan-regression
branch
2 times, most recently
from
October 17, 2026 21:23
4c83c61 to
06ae02f
Compare
This was referenced Oct 17, 2026
Contributor
Author
This was referenced Oct 17, 2026
PR edwardkim#7882(5601665·e5812d9fa)는 원본 셀 문단의 인접한 두 저장 줄이 모두 `vertical_pos == 0` 인 재시작을 저장 물리 경계로 인증해, 그 행을 전체 행 수용 경로에서 뺐다(`SourceFrameQuery` 의 `declared_source_frame`). 인증은 둘이다. - 행이 선언 첫 개체 프레임(`common.height`)을 가로지른다(또는 같은 행 동료가 확인) — 선언 기하의 근거라 저장 쪽 나눔과 무관하다. - 첫 프레임 뒤 행이고 원본 행 상자 합이 첫 프레임을 넘는다 — 저장 당시 그 행 안에 쪽 나눔이 있었다는 기록일 뿐이다. 둘째 근거를 첫째와 같이 취급해, 지금 흐름에서 쪽 위·중간에 놓인 행도 그 재시작에서 끊었다. 1342000_edu_curriculum_map.hwp 구역 12 표 행 132(「삶의 목적은 무엇인가? (삶의 목적)」 저장 2줄 vpos 0/0)를 쪽 위 120px 에서 끊어 213px 만 쓴 쪽이 생기는 등 문서가 418 → 422쪽이 됐다(한/글 2022 PDF 415쪽, 그 행을 끊지 않는다). 인증 종류를 `SavedZeroOriginWitness::{OpeningFrame, LaterPage}` 로 가르고, `LaterPage` 는 행 전체가 남은 예산에 들어가지 않을 때만 원본 물리 경계로 쓴다. 쪽 끝에 걸린 행은 종전대로 재시작에서 자른다 — 의도한 원 사례 table_scattered_header_rowbreak(hwp·hwpx) 47쪽 row99 「6가 크로 / 뮴)」은 수정 뒤에도 p47 rows 59..100 endCut [1], 52쪽이다. 측정(devel 463c48c 기준, compat 2022): 1342000 422 → 419쪽(edwardkim#7882 이전 2231761 418). 남은 +1(375쪽)은 구역 26 표가 edwardkim#7882 의 이어받기 바깥 위·아래 여백 예약(1.9px×2)과 상류 낡은 저장 셀 줄로 쪽마다 1행씩 덜 담는 별개 축이다. 시험: stored_zero_origin_later_page_row_fits (합성 입력 계약, HWPX 저장 후 재로드) - later_page_zero_origin_restart_does_not_cut_a_row_that_fits: 수정 전 FAIL(두 줄이 1·2쪽으로 갈림), 수정 후 PASS. - later_page_zero_origin_restart_still_cuts_a_row_at_the_page_end(대조군): 수정 전후 PASS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`stored_first_frame_row_remainder`(108edfb, edwardkim#7882)는 원본 첫 개체 프레임에서 끊긴 행의 남은 물리 높이를 `측정 행 높이 − 첫 프레임 몫` 으로 내서 다음 조각 시작 행에 넘긴다. 측정 행 높이가 선언 상자보다 큰 행에서는 그 초과분이 내용(마지막 줄의 줄간격 포함)이 만든 높이라 빈 물리 띠가 아니다. 그 초과분까지 넘겨 이어받기 상자가 남은 내용보다 길어졌다. 80168_regulatory_analysis.hwp 5쪽: 2행 표 행 1(선언 869px·측정 929.6px)의 이어받기가 33.6px (남은 내용 22.4px)로 잡혀, 한/글 2024 PDF 가 마지막 글줄 바로 아래에서 닫는 상자를 11px 더 내렸다. 물리 잔여의 기준을 `min(선언 행 상자, 측정 행 높이)` 로 둔다. 선언 상자가 내용보다 큰 행의 빈 띠를 넘기는 edwardkim#6803 의 의도는 그대로다(선언 상자가 없으면 종전 측정값). 측정(svg rasterizer, compat 2024): 80168 hwp 5쪽 83.55 → 100.00, 4·6쪽 99.60·99.91 무변화. 시험: first_frame_remainder_capped_by_row_box — 이어받기 칸 바닥과 마지막 글줄 바닥 사이 빈 띠가 아래 안 여백 + 줄간격 절반 이하인지(관계). 수정 전 FAIL(13.05px), 수정 후 PASS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… WASM overlay) - 80168 hwp 5쪽(2024 PDF): Native 99.61 / WASM 100.00 - issue1853 hwpx 16쪽(2020 PDF): Native 99.60 / WASM 99.57 - 1342000 PDF 233 = rhwp 236(2022 PDF, 쪽 내용으로 정렬): Native 69.77 / WASM 70.78 — 행 132 가 이제 끊기지 않지만, 이 base(devel)는 상류 쪽에서 4행가량 앞서 시작해 90% 미만이다. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
atomic TAC top-fit(edwardkim#409)은 분할할 수 없는 인라인 그림이 본문 하단을 60px 안에서 넘쳐도 현재 쪽에 남긴다. 그 그림 문단의 저장 줄이 되감기고 통째로 안 들어가면 (edwardkim#5755 의 stored_vpos_rewind_overflow_break) 한/글은 그 문단을 다음 쪽 첫머리에 둔 것이므로 스필 예외를 걸지 않는다. 분할 진입(split_entry::should_advance)은 이미 같은 값을 보고 있었고, 넘침 허용 경로만 그 값을 받지 않았다. 1480000-201900698 pi=88(그림 6, 370px): 19쪽 984.7px 로 본문 948.7px 를 넘기던 배치가 한/글 2020 PDF 처럼 20쪽 첫머리로 간다. 이후 21쪽의 그림 7 수용도 사라지고 전체 쪽수가 205(PDF 205)가 된다. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
edwardkim#1145 는 작은 rowspan 묶음을 행 중간에서 자르지 않는다. 쪽 끝에 묶음의 무엇도 온전히 놓이지 않을 때는 맞지만(edwardkim#1145 표본: 잔여 15.2px < 0행 17.3px), 0행이 잔여에 들고 0행에서 시작하는 rowspan 칸의 내용도 0행 안에 다 들면 0행 뒤의 컷은 어떤 칸의 글자도 자르지 않는다. 한/글 2020 PDF 는 1480000-201900698 표 9·17 의 0행만 앞 쪽 끝에 둔다(표의 저장 높이 3526 HU 도 0행과 같다). rhwp 는 표를 통째로 넘겨 36~40· 50~52쪽이 두 행씩 밀렸다. 판정은 이월 게이트(prepare)가 한 번 하고 BlockTableContinuationPreparedState 로 행 스캔에 넘긴다. 스캔은 첫 조각의 0행 묶음에만 그 결과를 소비한다. 다음은 기존대로 묶음을 통째로 둔다: 묶음 전체가 잔여에 드는 경우(task1725 pi=631), rowspan 칸 내용이 0행을 넘는 경우(task1753 pi=51), 0행이 제목 행인 경우(1613000 pi=1143). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
저장 첫 조각 프레임이 행 안에서 끝나고 그 행 내용이 프레임에 다 들면, 종전에는 행을 프레임 안에서 닫아(complete_last_row) 선언 높이의 남은 빈 띠를 버렸다. 되감긴 후속 문단의 저장 원점이 «남은 띠 + 뒤 행들 + 표 바깥 위·아래 여백»과 같으면 한/글은 그 띠를 다음 쪽 첫머리로 넘긴 것이다. 그때는 행을 닫지 않고, 행 스캔이 그 행에서 추정 문턱(MIN_TOP_KEEP_PX) 대신 저장 컷을 따른다 — 내용은 이 조각, 띠는 다음 조각. 띠로 시작하는 끝 조각은 아래 바깥여백 예약 경로가 start_cut 비어 있음을 요구해 빠졌고, 조판 흐름만 여백을 더해 그리기가 후속 문단을 그만큼 위에 두었다. 시작 행의 남은 높이를 넘겨받은 띠로 세어 같은 저장 줄 인증으로 여백을 예약한다. 1480000-201900698 표 14(pi=275): 46쪽 첫머리 띠 23.04px, 후속 문단 저장 위치 일치. 46쪽 61.2 → 100.0, 47쪽 61.8 → 98.2 (Native). A/B 변화 2문서(1490000-200800034 는 표 안 띠만, 뒤 흐름 불변·기준 PDF 없음). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 문단 안 글줄 컷의 25px 최소 상단 면제를 위 행에서 내려온 걸침 칸이 행 윗변을 가로지르는 경우로 좁힌다(1342000 120·127행은 유지, 1480000 표 15·18 75·117행은 통째 이월). - 저장 셀 되감김(쪽 컷 기록)이 없는 표에서는 1줄 행의 빈 꼬리만 다음 쪽으로 넘기지 않는다 (1480000 표 15 110행·표 18 76행). - edwardkim#2236 걸침 칸 띠 컷에서 저장 내용이 남은 띠에 다 들고 행을 지나 이어지는 걸침 칸이 없으면 행을 이 쪽 끝에서 닫는다(21761835 56행, 5쪽은 57행부터). - 회귀: tests/cases/rowbreak_short_row_whole_carry.rs (수정 전 3건 FAIL → 후 4건 PASS) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
한/글 2020 PDF 실측(선언 − 남은 띠): 21761835 56행 4.8px·1342000 115행 1.1px·56행 9.9px 는 쪽 끝에서 닫히고, 1342000 43행 15.5px 는 다음 쪽 첫머리에 빈 띠를 남긴다. 기존 TERMINAL_ROW_BOTTOM_SQUEEZE_TOLERANCE_PX(13px, 1741000 실측)를 같은 경계로 쓴다. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
행 전체가 들어가도 그 행 뒤에 최소 상단 높이가 남지 않고, 셀 저장 줄이 한 셀의 뒷줄을 vpos 0 에서 다시 시작하면 한컴이 기록한 쪽 컷으로 보고 그 줄에서 자른다. 행이 쪽 중간에 오면 따르지 않는다. 1480000 43쪽 118행·1613000 126·127쪽 17·28행이 한/글 2020 PDF 와 같아진다. 회귀: rowbreak_short_row_whole_carry::stored_restart_cuts_the_last_row_of_a_page Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- edwardkim#1686 안내 줄 흡수는 되감긴 다음 앵커의 저장 위치가 현재 흐름 위치에서 빈 줄들의 저장 전진을 모두 담을 만큼 아래면 흡수하지 않는다(1480000 44쪽 pi=264: 677.8 + 26.4 = 704.2px, pr-1674 는 앵커가 흐름보다 위라 계속 흡수). - 앞 빈 문단의 저장 vpos 가 단 높이 밖(앞 쪽 좌표계)이면 되감긴 현재 문단의 기준을 그 값에서 역산하지 않고 순차 흐름을 따른다(pi=265 에 trailing 11.7px 를 한 번 더 주지 않는다). 1480000 44쪽 50.9 → 98.5%(Native). 회귀: rowbreak_short_row_whole_carry::page_44_keeps_the_empty_line_after_the_stored_row_cut Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- solve_rowspan_row_heights: 미지 행 하나인 제약을 풀 때 그 행을 걸친 더 일찍 끝나는 제약이 아직 풀리지 않았으면 기다린다(진전이 없을 때만 종전처럼 하나를 푼다). 21761835 행 11~17 칸이 미지 행 11 을 136px 로 채워 행 10~11 블록(105.9px)을 139.7px 로 깨던 문제. - stored_fragment_row_plan: 1행 칸이 없는 행도 그 행에서 끝나는 걸침 칸의 남은 요구로 정하고, 루프가 방금 다시 푼 앞 행도 변경으로 본다. 1쪽에서 449.1px 를 쓴 칸 (6,0)의 남은 13.6px 를 2쪽 행 10 이, 행 11~17 칸의 남는 높이를 행 17 이 받는다(한/글 2020 PDF 와 1px 이내). 21761835 2쪽 50.1 → 94.4%, 1342000 33쪽 59.5 → 100%(31쪽은 분할 행 세로 정렬 차이로 96.6 → 88.8). 회귀: rowbreak_short_row_whole_carry::rowspan_extra_goes_to_the_last_row_across_the_page Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…0 85쪽 1613000 84쪽 각주 한 줄(31.4px)은 꼬리말 밴드(37.8px)에 다 들어가 각주 차감은 0 인데, 보수 여백 3000HU(40px)가 따로 붙어 본문 끝이 931.4px 였다. 빈 문단 `pi=817` 의 저장 줄(936px)은 paint 가 여는 각주 구분선(본문 위 950.4px, 한/글 2020 PDF 와 같음)보다 위인데도 85쪽으로 밀려 쪽 전체가 37px 내려갔다. 이 경우 가용 높이의 하한을 '본문 − 각주 높이'로 둔다(그 밖의 각주 예약은 그대로). 샘플 1,252 SVG + 1342000 A/B: 바뀐 쪽은 1613000 85쪽뿐(22.9→98.5). (같은 증상을 '새 쪽 첫 줄 vpos ≤ 위 간격'으로 고치는 변형은 aaaaaa·hwp3-sample16·issue2004 등 20쪽 넘게 −1~−24 로 떨어져 버렸다.) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
표 개체 높이가 행 상자 합보다 작게 저장된 원본(`native_stored_table_has_fragment_frames`)은 한/글이 그 표를 쪽에서 갈랐다는 저장 사실이다. 셀 사다리 되감김이 있는 표와 같이 edwardkim#1672 가로 허용치 (경계 행을 본문 아래로 흘려 받음)를 끈다. - 1613000 부록 105×3 표: 197쪽이 빈 구분 행 96(20.9px)을 본문 아래(659.1/642.6px)로 받아 198쪽이 한 행 늦었다. 198쪽 58.8→99.9, 197쪽 98.9→99.8. - 156505020(issue5828 픽스처 원본, 한/글 2020 MCP 변환본 43쪽): rhwp 41→43쪽 = 변환본, 전쪽 평균 98.2(43쪽 69.5 — 마지막 표 한 행 차이 남음). 픽스처 14→15쪽, 기존 edwardkim#5828 검사 통과. - 샘플 1,252 SVG + 1342000 A/B: 그 밖 변화 없음. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
문단 유지 계약(`row_cut_plain_paragraph_contract`)은 저장 글줄이 없는 문단을 통째로 제외해, 위 행에서 내려온 걸침 칸이 가로지르는 행에서도 25px 최소 상단 문턱이 첫 문단 컷을 버렸다. 문단 끝 컷은 글줄 분할 없이 문단 경계를 그대로 쓰므로 저장 글줄이 없어도 유효하다. 문단 안 컷만 종전대로 저장 글줄을 요구한다. 80168 hwp 표 `pi=516` 행 12: 60쪽이 첫 문단에서 닫히고 61쪽이 「하는 규제」로 열린다(한/글 2024 PDF). 61쪽 36.3→96.0, 60쪽 90.6→92.3. 샘플 1,252 SVG + 1342000 A/B: 그 밖 PDF 있는 쪽 변화 없음 (80168 hwpx 판 60쪽 +0.97, 61쪽 ±0.01 — 기존 저점). (같은 표 89·90쪽 이어받는 행 상자를 '선언 − 앞 조각' 으로 넓히는 변형은 18095317·nested_table_text_caption· 21761835 등 −50~−100 으로 깨져 버렸다.) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
devel 위로 리베이스하며 드러난 두 어긋남. - 스캔은 내용 컷 행을 컷 경로에 따라 내용 전진량(`split_end_limit`)·패딩 포함 컷 상자·물리 띠 가운데 하나로 예약한다. emit 의 걸침 띠는 방을 `split_end_limit` 에서 재서, 패딩 포함 상자를 예약한 경로에서 닫는 선보다 패딩만큼 짧았다(21761835 2쪽 행 20: 전진량 47.25 · 예약 50.99px, 조각 아래 1040.5 ↔ 한/글 2020 PDF 1044). 스캔이 행마다 실제로 예약한 증분을 `BlockTableRowScan::split_end_reserved` 로 넘기고 emit 이 그 값에서 잰다. - devel 26877ee 이후 재조판 프레임 하단(`rowbreak_fragment_frame_bottom`)은 걸침 칸이 있는 표에도 비끝 조각 inset(100HU)을 뺀다. 원장 띠가 그 프레임에서 재면 inset 을 한 번 더 빼서 그리는 띠가 1.33px 짧았다(1613000 154쪽 행 51: 730.57 ↔ 닫는 선 731.91). 예산이 프레임이 실제로 뺀 inset 을 함께 넘기고, 원장 띠는 그 inset 앞의 물리 띠로 잰다. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
리베이스(50dcb00) 뒤 남은 어긋남 셋. - devel 26877ee 가 `rowbreak_fragment_frame_bottom` 에서 걸침 칸 예외를 없애 HWP5 저장 표의 원본 프레임 예산에도 비끝 조각 inset(100HU)이 들어갔다. 한/글 2020·2022·2024 PDF 1342000 149쪽은 행 36·37 의 병합 칸이 걸친 행 40 첫 줄(19.76px)을 그 쪽에 두고 아래 괘선을 716.0px (본문 − 바깥 아래 여백)에 긋는다. inset 을 빼면 방이 19.25px 라 뒤 쪽이 모두 밀렸다. 병합 칸이 있는 HWP5 저장 표의 예산만 inset 없이 잰다. 재조판 일반 행 프레임(edwardkim#7642 edwardkim#7028)과 paint 상한, 통째로 받은 끝 행의 닫는 선은 그대로 둔다. 149쪽 괘선 715.43 ↔ PDF 716.0, 149–151쪽 행 경계 PDF 일치. - 50dcb00 이 원장 띠를 inset 앞 물리 띠로 늘려, 다음 조각이 그린 상자보다 1.33px 많이 소비한 것으로 셌다(issue_7692 partial_plain_row 112.4/113.75, issue_6981 FAIL). 원장 띠는 devel 처럼 프레임에서 잰 값 그대로 두고, 그리는 띠에서 프레임이 이미 뺀 inset 을 다시 빼지 않는다(1613000 154쪽 유지). - `stored_span_fragment_minimum` 의 끝 행 확장은 저장 행 높이 합(`physical`) 기준으로 상자를 키우면서 예약은 `minimum` 까지만 올렸다. 스캔이 수용한 행 합이 저장 합보다 크면 그린 조각이 예약보다 커져 본문을 넘었다(issue_6981 합성 예산 변형 42..62행: 4.64px, 아래 695.56 > 본문 694.13). 상자는 예약이 실제로 늘어난 만큼만 키운다. 남은 실패: rows_inside_a_crossing_rowspan_still_split_after_one_line(1342000 165·166쪽 고정). 저장 LineSeg 가 두 줄로 나눈 셀 문단을 한/글 2020 인쇄는 한 줄로 맞춘다(151쪽 행 56, 160쪽 행 67). devel 은 저장 줄을 따르므로 행이 커져 그 뒤 쪽 경계가 어긋난다. 이번 변경 범위 밖. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
한/글 2014 로 저장한 1342000 의 칸 문단은 공백 최소값(condense) 흡수 없이 낱말 끝 글자만 다음 줄로 보낸 저장 줄을 가진다. 한/글 2020 인쇄는 그 꼬리를 앞 줄에 붙인다(151쪽 `…시연하|기`, 154쪽 `…찬반 토|론`). - 저장 제품이 한/글 2020(11.x) 이전이고, 양쪽 정렬+condense 문단의 마지막 저장 줄이 앞 줄 낱말의 나머지뿐이면 같은 프레임으로 새로 끊어 보고 줄 수가 줄 때만 저장 줄을 버린다. 판정과 실제 줄이 같은 프레임 결과다. - 저장 제품은 컨테이너가 기록한 마지막 저장에서 읽는다(HWPX 가 원본 HWP5 요약을 실어도 version.xml 을 따른다). - 측정기의 edwardkim#6135 저장 extent 증인이 재조판된 문단에도 원래 저장 사다리를 써 행이 옛 줄 수 높이로 남던 것을 고친다. 1342000 416→415쪽(=한/글 2020 PDF), 성취기준 코드 쪽 일치 21.2%→97.8%. samples 1252건 SVG 변화 0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… TSV (code head 065125a) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
9 tasks done
대표 27쪽 Native/fresh WASM review·overlay 와 9개 문서 전쪽 TSV(브랜치 Native·WASM, devel efc52af Native)를 새 head 에서 다시 찍었다. 파일 이름은 CONTRIBUTING 의 <입력>-p<쪽>-<native|wasm>-<review|overlay>.png. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
planet6897
force-pushed
the
fix/devel-table-scan-regression
branch
from
October 19, 2026 20:31
21ab962 to
8e18113
Compare
끝 행이 물리 상자(end_row_height_override)로 닫히는 조각에서 걸침 칸의 끝 유닛을 끝 행의 내용 컷(그 행 칸의 저장 재시작)까지로만 재던 것을, 그린 상자 높이까지 넓힌다. 다음 조각은 carry 의 끝 유닛에서 잇는다. 1342000 199쪽 r=62 c8(행 62–63) 셋째 줄이 한/글 2020 PDF 처럼 199쪽에 남는다. 200쪽 첫 행이 2.9px 높던 것이 사라져 행 75 가 쪽 끝에서 줄지 않고, 행 57–92 걸침 원장이 부족분을 행 92 에 더하지 않아 202쪽 행 92 가 선언 97.1px(PDF 97.25)로 돌아온다. Native: 1342000 200쪽 92.8→100.0, 202쪽 92.3→97.3, 203쪽 91.8→99.9, 84쪽 30.4→50.8. 샘플 1,252건 SVG 변화는 1613000 139·140쪽(99.2→99.3, 99.6→99.9)뿐. 회귀: rowbreak_span_cell_page_end_lines (수정 전 2건 FAIL) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…쪽 추가) Native/fresh WASM(bbdf0abc…) 대표 쪽 review·overlay, 9문서 전쪽 TSV. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…wardkim#7702) 1342000 189쪽 칸 문단 `…실천한` / `다.` 를 rhwp 재조판이 한 줄로 붙이던 결함. 한/글 2024 에 같은 문단을 폭만 1 HU 씩 바꿔 조판시킨 합성 입력에서 한/글은 26712 HU 부터 붙이고, 수정 전 rhwp 는 약 26668 HU 부터 붙였다. - 휴먼명조 LATIN_0 를 HMKMM.TTF hmtx × 2 로 교체. 한/글 2024 `가c` 사다리 94자 × 3 조건이 94/94 일치(종전 edwardkim#2430 래더 표는 37·58·70자 불일치, `,` `.` `(` `)` 가 10pt 에서 한 장치 단위 좁음). - 문단 끝 edwardkim#2470 예외(끝 글자 자간 유지)는 자연폭으로 들어가는 줄에만 쓴다. 공백 condense 로만 들어가는 줄은 양쪽 정렬 끝 글자를 자간 없는 폭으로 잰다(edwardkim#5678). 검증: 새 회귀 2건 수정 전 FAIL / 후 PASS, nextest 11064/0, lint·tiers OK. Visual Sweep(Native/fresh WASM): 1342000 189쪽 66.6→98.0, issue5169 4쪽 97.2→100, 합성 입력 최저 99.3, 그 밖 9문서 1074쪽 변화 없음. 36382669 5·6·7쪽 줄바꿈이 한/글 2024 PDF 와 같아짐. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…169 4쪽·휴먼명조 합성 입력 추가) Native/fresh WASM(1dbb1aab…) 대표 쪽 review·overlay, 9문서 + 36382669·issue5169·합성 5종 전쪽 TSV. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
한/글 2020 Print 1342000 의 쪽 끝 표 아래 괘선(쪽 척도를 걷은 값)은 noAdjust(표 속성 bit 3) 표가 본문 아래 − 바깥 아래 여백에 −0.03~−0.15px(121·170·99·49쪽), noAdjust 아닌 표가 그 선 − 100HU(edwardkim#7095 inset)에 ±0.12px(157·213·108쪽)로 맞는다. rhwp 는 모든 RowBreak 비끝 조각을 100HU 위에서 닫아, noAdjust 표에서는 조각마다 걸침 칸 몫을 덜 소비했다. 구역 5 표의 걸침 칸 «생활안전»(1–60행) 남는 몫 490HU 가 끝 행 60 에 몰려 126쪽 행이 4.9pt 커졌고, 쪽 끝 줄이 밀려 127–129쪽이 한 줄씩 어긋났다. inset 을 표마다 정하는 `rowbreak_fragment_bottom_inset_hu` 로 모으고, 예산·그리기 띠·원장· 걸침 칸 닫는 선(row_step)이 같은 값을 쓴다. 검증: 새 회귀 3건(수정 전 2건 FAIL — 121쪽 714.92 ↔ 716.24, 126쪽 행 60 46.29 ↔ 선언 39.76 / 반례 157쪽 inset 유지 PASS), nextest 11067/0, lint·tiers OK, fresh WASM 055828a5…. 1342000 126·127·128·129쪽 86.4/76.9/76.9/77.4 → 99.4/99.4/94.8/96.8, 90% 미만 136 → 132, 하락은 기존 저점 5쪽 ≤0.8. 샘플 SVG 변화 17문서 63쪽, PDF 대조 하락 최대 −0.5(sample1-repro 39쪽), 쪽 수 변화 0. PR 9문서·합성 입력 Native/WASM 변화는 1342000 뿐. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Native/fresh WASM(055828a5…) 대표 쪽 review·overlay, 1342000 전쪽 TSV(다른 문서 TSV 는 바이트 동일). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 이어지는 조각의 바깥 위 여백 재개방(`native_multirow_rowbreak_reopens_outer_top`)에서 `vertical_offset == 0` 조건을 없앤다. 문단 기준 오프셋은 첫 조각에서 소진된다. 한/글 2020 1342000 구역 1 표(오프셋 5280·752HU) 이어지는 조각 윗변 26–29·31·34·55쪽 = 본문 위 + 141HU. - 다음 문단이 자기 앞 간격 원점(vpos = 앞 간격)으로 되감기는 저장 경계에서 앞 줄의 뒤 줄간격을 조각 높이에서 뺀다(`stored_page_reset_cut_trailing_trim`). 1342000 55쪽 행 21: p1 vpos 1800 → p2 vpos 500. 한/글 2020 은 p0·p1 을 55쪽에 담는다. - edwardkim#6143 «문단 오프셋 소진» 판정의 25px 최소 조각을 나눌 수 없는 0행 높이로 넓히고(함수가 표를 받는다), 소진된 첫 조각은 그 쪽에서 바깥 위 여백을 연다(그리기의 바깥 위 여백 OR 묶음). 한/글 2024 hwpx_sample2 6쪽: 앵커 1016.48 + 오프셋 4.0 뒤 26.4px < 0행 28.41px → 6쪽 윗변 = 본문 위 + 283HU, 첫 조각 1037.9px = 저장 첫 프레임 1038.01px. 종전 예산은 오프셋과 여백을 둘 다 빼 4px 일찍 닫고, 그 몫을 7쪽 조각이 받았다. 검증: 새 회귀 4건(A·C 수정 전 FAIL, B 는 B 만 뺀 코드에서 FAIL, 156555538 반례 보호 PASS), nextest 11071/0, lint·tiers OK, fresh WASM 0b588054…. 1342000 90% 미만 132 → 126(하락 0). 샘플 SVG 변화 10문서 14쪽: hwpx_sample2 hwp 6·7쪽 98.7/96.7 → 99.8/99.7, hwpx 6쪽 74.9 → 99.8, 75544 31·32쪽 86.7/53.3 → 99.9/97.3, 1480000 41쪽 71.1 → 100.0, 59043 24쪽 −0.1. issue2439(rhwp 11쪽 / 한/글 2024 10쪽, 기존 불일치) 3쪽 54.9 → 90% 이상, 4쪽 47.9 → 33.1 — 3·4쪽 경계는 한/글과 같아졌고 4쪽은 끝 조각 뒤 간격(+13px, 이 변경 밖의 기존 오차)이 드러남. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…x_sample2 6·7쪽 추가) Native/fresh WASM(0b588054…) 대표 쪽 review·overlay, 1342000·1480000 전쪽 TSV(다른 문서 TSV 바이트 동일). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
한/글 2024 합성 사다리(probes/make_declared_row_band.py)로 측정한 규칙: 내용이 이 쪽에서 끝난 분할 행은 닫는 선까지 그리고, 남은 선언이 1282HU(17.09px)를 넘으면 다음 쪽 첫머리 빈 띠로 넘기며 그 이하는 흡수한다(병합 칸은 원장으로 이어받음). 칸 여백·표 기본 여백·글자 크기·저장 줄·병합 칸 유무와 무관(17.0 흡수 / 17.2 이월). - 흡수 상한을 칸 마지막 줄 높이에서 위 상수로 바꾼다(재조판·저장 경로 공통). - 완료 행 + 걸침 칸에서도 상한을 넘는 남은 선언은 띠로 넘긴다(edwardkim#7642 의 일괄 제외 대체). - 저장 줄 행의 칸 내부 분할 예산은 본문 아래까지라 끝 행 상자가 그리기 닫는 선보다 383HU 컸다. 내용 완료 끝 행은 재조판 프레임(닫는 선)까지로 줄이고, 그 선언 상자는 끝 줄간격으로 접지 않는다. 병합 칸 원장·남은 선언이 같은 상자를 소비한다. - 그 행에서 끝나는 저장 줄 병합 칸의 남은 선언도 완료 행에서 띠가 된다 (1342000 61쪽 51.6px = 행 8–17 병합 칸 잔여). 1342000(한/글 2020): 90% 미만 126→123쪽, 59·61·62·307쪽 44–73→99.8–100. 하락 250·251·352쪽은 같은 쪽 중간의 기존 행 높이 차(69.1↔51.9, 머리 행 45.2↔18.0)의 연쇄. 픽스처 declared_row_band.hwpx 12쪽 Native/fresh WASM 최저 100. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…7쪽, edwardkim#8105 빈 띠 픽스처 추가) Native(native-skia)·fresh WASM(96095cdf…) 대표 쪽 review·overlay, 1342000·1480000·21761835 전쪽 TSV 갱신, declared_row_band 픽스처 TSV 추가. 다른 대표 PNG·TSV 는 바이트 동일. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1342000 250쪽 행 49 칸 문단 `…갈등 현상 탐색하` / `기`(한/글 2014 저장 줄)를 한/글 2020·2022·2024 Print 는 모두 한 줄로 다시 나눈다. rhwp 는 저장 줄을 따라 행이 69.1px (정본·선언 51.9px)였고 그 17.2px 가 250·251쪽 뒤 행을 밀었다. edwardkim#7702 의 «저장 줄 꼬리를 프레임의 새 줄 나눔이 앞 줄로 흡수하면 다시 나눈다» 는 condense 문단만 대상이었다. 한/글 2024 합성(probes/make_numbered_stale_tail.py)에서 문단 머리(«-»·«1.» 번호)를 그리는 문단은 폭이 맞는 저장 줄도 쓰지 않고 다시 나누고, 번호 없는 문단은 폭이 맞으면 저장 줄을 따른다(줄 flags·저장 제품 버전 무관). 1342000 정본도 번호 문단 꼬리 39건을 붙이고 번호 없는 `…제|정]`·`…일|부개정]` 은 두 줄로 둔다. → 대상을 condense 또는 문단 머리가 있는 문단으로 넓힌다. 실제로 붙는지는 종전대로 새 줄 나눔이 정한다(25쪽 `…필|요` 는 새 줄 나눔에서도 두 줄 = 정본). 1342000(Native·fresh WASM): 90% 미만 123→97, 250쪽 78.6→99.6·251쪽 69.8→98.0, 357–371· 282–288쪽 등 32쪽 상승. 하락 5쪽 — 175쪽 −1.6(한/글이 꼬리를 못 넣는 경계 근접 문단), 272–274· 359쪽 −3~−4(행 높이는 정본과 같아졌고 쪽 끝 분할 한 줄 차이의 기존 연쇄가 남음). 샘플 전수: 규칙이 발화하는 문서는 1342000·interview.hwp 뿐, interview 출력은 바이트 동일. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
대표 쪽 전체를 code head 9f2b241 의 Native(native-skia)·fresh WASM(sha256 c4ed9986…)으로 다시 찍었다. 바뀐 PNG 는 없고 1342000 250·251쪽 review·overlay 를 더했다. 전쪽 TSV 는 1342000 만 바뀜(Native·WASM 90% 미만 123→97, 바뀐 쪽 37). pr_review_gate 전부 passed, 최저 94.57. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
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.
변경 요약
devel 의 RowBreak 표 분할·이어받기 경로에서 한/글 Print PDF 와 어긋나던 쪽 경계·행 높이·셀 정렬을 고친다.
모두 저장 조판 정보(셀 LineSeg vpos 재시작, 선언 행·칸 높이)를 한/글이 남긴 쪽 경계 기록으로 읽는 방향이며,
문서 ID·좌표 예외는 없다. 리베이스 뒤 55개 커밋(코드 32 + style 2 + 증적 21).
03ed94157e0441c319a7bc0ba8fc04da55b333ebbc01ecd5bebf6d·eb9d271c214a1bb3206f1ac93235b662bb18a92d0d2205994ce798max(나뉜 행의 남는 몫, 걸침 칸의 남는 몫)까지, 그 끝 행 상자는end_row_owns_stored_frame, 다음 조각은 그 상자를 이어받는다b30e9e020200beb58fdd2e52e71pi=10줄 vpos 47394)b4452b80114a1bb320)은 남은 쪽 공간이 아니라 max(행 선언 높이, 자른 줄까지의 내용 높이) 상자에서 닫는다 — 공통 helperstored_restart_end_row_box를 scan 이 예약하고 paint 는 같은 컷·같은 상자면 끝 줄간격을 접지 않는다 ② 끝 조각의 아래 캡션은 통째 표처럼 표 아래 + 캡션 간격에 둔다(호스트 줄간격은 캡션 뒤 흐름 끝에만, 흐름·쪽 나눔 불변)65e20ecbaSINGLE_CELL_PAGE_FRAGMENT_BOTTOM_INSET_HU와 같은 값) 안에 들면 이 쪽에 두고 상자를 그 선에서 닫는다 — 다음 조각은 다음 행부터. 예산이 바깥 아래 여백을 예약하지 않은 표는 그 여백도 뺀다. 이 행에서 닫히는 칸이 없는 행·Stage 76 빈 띠 경로·첫 조각은 제외35f46f163page_end_band·끝 행 상자 기록·stored_reset_band_row_box·accepted_straddle_fragment_units)은 줄이기 전 띠를 소비한다. 내용 컷으로 끝난 행은 그대로7be2810a523db8512fpi=1133컷 [41,37]→[40,37], [51,72]→[51,70]; 표 아래 선 PDF ±0.1px)8c847d933text_host_terminal_successor_gap를 빈 호스트로 넓힌다(뒤 문단 줄 상자가 줄간격·아래 간격까지 본문 안에 들 때만). NextLine 배치 계획이면stored_successor_line_origin으로 인증해 paint 도 호스트 아래 간격을 더하지 않는다pi=8(빈 줄 감추기)2dfc0f184nested_host_gap_start, 측정·배치 공유) ② 중첩 표 개체 높이가 앞 k개 행 상자 합과 정수로 같고 병합 칸이 그 경계를 가로지르지 않으면 한/글이 저장한 첫 조각 경계로 보고 k행 유닛을 셀 내부 쪽 나눔으로 보존, 중첩 행 경계는 고아 줄 되감기 대상에서 뺀다 ③ 1×1 첫 조각 계획이 흐름 원점에 바깥 위 여백을 이미 담으면 다시 더하지 않는다 ④ 끝 조각 뒤 문단의 저장 줄이 상자 아래 이하에 있으면 그 줄이 문단을 닫는다(stored_successor_line_origin을 '상자 아래 이상'으로 일반화 — 기존 생산자는 모두 origin = 상자 아래) ⑤ 칸 안 어울림·왼쪽·오프셋 0 중첩 표는 저장 앵커를 쓴다(#3308 좁은 표 가운데 규칙에서 제외)55ddf0690pi=817저장 줄 936px < 각주 구분선 950.4px — 종전 본문 끝 931.4px)06dc305d5native_stored_table_has_fragment_frames)도 셀 사다리 되감김 표처럼 '한/글이 쪽에서 가른 표'로 보고 #1672 가로 용지 경계 행 허용치를 끈다de2315e55pi=516행 12 첫 문단에서 60쪽을 닫음)50dcb0078split_end_reserved, 패딩 포함 컷 상자)에서 잰다f8fa0f02astored_span_fragment_minimum)이 상자를minimum−Σ저장행만큼 키우면서 예약은minimum까지만 올리던 불일치를grow = minimum − consumed로 통일issue_7692·issue_6981065125a94478da8250f296dbc21HMKMM.TTF) hmtx × 2 로 바꾸고(#2430 COM 래더 표는,.()가 10pt 에서 한 장치 단위 좁았다), 공백 condense 로만 들어가는 문단 끝 줄은 양쪽 정렬 끝 글자를 자간 없는 폭으로 잰다(#5678 — #2470 의 문단 끝 예외는 자연폭으로 들어가는 줄에만)…실천한/다.(한/글 2024 폭 사다리 경계 26712 HU 와 같아짐), issue5169 4쪽, 36382669 5–7쪽(한/글 2024)1cf3b879bnoAdjust(표 속성 bit 3) 표의 비끝 조각은 #7095 inset(100HU) 없이 본문 아래 − 바깥 아래 여백에서 닫는다. 예산·그리기 띠·원장·걸침 칸 닫는 선이 표마다 정한 같은 inset(rowbreak_fragment_bottom_inset_hu)을 쓴다.noAdjust아닌 표는 그대로noAdjust121·170·99·49쪽 = 본문 아래 − 바깥 아래 여백(±0.15px), 아닌 표 157·213·108쪽 = 그 선 − 100HUe64b513edvertical_offset == 0조건 제거(오프셋은 첫 조각에서 소진) ② 다음 문단이 자기 앞 간격 원점으로 되감기는 저장 경계에서 앞 줄 뒤 줄간격을 조각에서 뺌 ③ #6143 «문단 오프셋 소진» 판정의 25px 최소 조각을 나눌 수 없는 0행 높이로 넓히고, 소진된 첫 조각은 그 쪽에서 바깥 위 여백을 연다(그리기 OR 묶음 — 다른 규칙이 이미 연 형상에 이중으로 열지 않음)51a628363samples/issue8105/declared_row_band.hwpx12쪽(한/글 2024)9f2b24150stored_last_row_is_rejoinable_word_tail). 한/글 2024 합성(probes/make_numbered_stale_tail.py): «-»·«1.» 번호를 그린 문단은 폭이 맞는 저장 줄도 한 줄로 다시 나누고, 번호 없는 문단은 폭이 맞으면 저장 줄 그대로(줄 flags·저장 제품 버전 무관). 실제로 붙는지는 종전대로 새 줄 나눔이 정한다관련 이슈
Refs #7445 · #5941 · #6764 · #2146 · #2236 · #7702 · #8101 · #8105 — 부분 개선. 아래 「남은 차이」의 쪽을 해결하지 않았으므로 어느 이슈도 닫지 않는다.
후속: #8079 (굵은 맑은 고딕 전진폭 — 80168 133쪽의 원인, 표 분할 밖). #7702 분석: #7702 (comment)
(#7445 의 1342000 쪽 수는 415 = PDF.)
대표 쪽 (Native·fresh WASM × review·overlay, 모두 90% 이상)
efc52afb7)pdf/1613000-202200037-air-traffic-controller-cbta-2020.pdfpdf/80168_regulatory_analysis-hwp-2024.pdfpdf/1613000-202200037-air-traffic-controller-cbta-2020.pdfpdf/issue5941-1480000-201900698-2020.pdfpdf/task2146/21761835_jeonjik_exemption_table-2020.pdfpdf/1613000-202200037-air-traffic-controller-cbta-2020.pdfpdf/17253153-traffic-safety-designated-routes-2020.pdfpdf/80168_regulatory_analysis-hwp-2024.pdfpdf/issue1853_caption_precedes_body_split-hwpx-2020.pdfmydocs/pr/assets/issue7445/education-curriculum-map/existing-hwp-hancom2020-print.pdfpdf/issue8105/declared_row_band-2024.pdf(한컴 2024)pdf/hwpx_sample2-hwp-2024.pdf(한컴 2024)pdf/issue7674/issue5169_viewtext_changetracking-2020.pdfpdf/issue7702/humanmyeongjo_condense_end_fine-2024.pdf(한컴 2024)pdf/issue7702/humanmyeongjo_ascii_10pt_m10-2024.pdf(한컴 2024)pdf/1613000-202200037-air-traffic-controller-cbta-2020.pdfpdf/issue1880/issue1880_takeplace_host_before-2024.pdfpdf/1613000-202200037-air-traffic-controller-cbta-2020.pdf(2px 이웃 관용 내용 실루엣 일치율, 96dpi. 80168 61쪽·issue1880 1쪽은 devel 이 이미 같은 값 — 그 사이 devel 에 같은 계열 수정이 들어갔다.)
1613000 58쪽 · 기준 PDF p58 ↔ rhwp p58 — 1×1 상자가 중첩 11×4 표의 저장 첫 조각 경계 [32] 에서 갈림 · 22×2 표 왼쪽 앵커
Native 98.66 / WASM 98.72.
1613000 59쪽 · 기준 PDF p59 ↔ rhwp p59 — 3행부터 이어받고 뒤 문단이 저장 줄
Native 96.00 / WASM 95.83.
1613000 85쪽 · 기준 PDF p85 ↔ rhwp p85 — 84쪽 각주 아래 빈 문단이 84쪽에 남고 85쪽이 저장 줄에서 시작
Native 99.65 / WASM 99.68.
80168 61쪽 · 기준 PDF p61 ↔ rhwp p61 — 행 12 첫 문단에서 60쪽을 닫고 「하는 규제」부터
Native 98.98 / WASM 98.75.
1613000 198쪽 · 기준 PDF p198 ↔ rhwp p198 — 빈 구분 행 96 부터 — 197쪽은 본문 안에서 닫힘
Native 99.85 / WASM 99.84.
1613000 124쪽 · 기준 PDF p124 ↔ rhwp p124 — 이어받은 행 1 이 저장 재시작 [51,70] 에서 닫힘
Native 99.32 / WASM 99.32.
1613000 125쪽 · 기준 PDF p125 ↔ rhwp p125 — 오른칸 32번째 문단 통째 · 캡션 아래 빈 호스트 뒤 문단이 저장 줄
Native 99.49 / WASM 99.48.
1480000 22쪽 · 기준 PDF p22 ↔ rhwp p22
Native 99.79 / WASM 99.87.
21761835 2쪽 · 기준 PDF p2 ↔ rhwp p2
Native 96.35 / WASM 96.62.
21761835 3쪽 · 기준 PDF p3 ↔ rhwp p3 — 쪽 끝 띠 · 걸침 총높이 보존
Native 96.03 / WASM 96.29.
1613000 127쪽 · 기준 PDF p127 ↔ rhwp p127 — 저장 재시작 컷 끝 행 = 컷 내용 96.6px
Native 99.87 / WASM 99.71.
1613000 128쪽 · 기준 PDF p128 ↔ rhwp p128 — 끝 조각 캡션 간격 = 통째 표
Native 98.02 / WASM 97.89.
1613000 144쪽 · 기준 PDF p144 ↔ rhwp p144 — 통째 끝 행 139 = 행 높이, 띠 없음
Native 99.93 / WASM 99.92.
1613000 154쪽 · 기준 PDF p154 ↔ rhwp p154 — 내용 컷 끝 행 51 = 닫는 선
Native 99.93 / WASM 99.93.
1613000 195쪽 · 기준 PDF p195 ↔ rhwp p195 — 행 43 상자 = 닫는 선 713.03px
Native 99.80 / WASM 99.81.
1613000 196쪽 · 기준 PDF p196 ↔ rhwp p196 — 195쪽 행 43 을 닫는 선에서 닫고 행 44 부터
Native 99.93 / WASM 99.93.
1613000 201쪽 · 기준 PDF p201 ↔ rhwp p201 — 75×3 표 행 43 부터
Native 98.47 / WASM 98.30.
17253153 3쪽 · 기준 PDF p3 ↔ rhwp p3 — 분할 행 칸 정렬
Native 100.00 / WASM 100.00.
80168 5쪽 · 기준 PDF p5 ↔ rhwp p5
Native 99.97 / WASM 99.94.
issue1853 16쪽 · 기준 PDF p16 ↔ rhwp p16
Native 99.78 / WASM 99.32.
1342000 31쪽 · 기준 PDF p31 ↔ rhwp p31 — 분할 행 칸 정렬
Native 99.82 / WASM 99.83.
1342000 202쪽 · 기준 PDF p202 ↔ rhwp p202 — 쪽 수 원인이던 행 92 — 선언 97.1px(PDF 97.25), 마지막 행 둘째 줄 202쪽
Native 97.24 / WASM 96.86.85 (
478da8250전 92.28 / 92.40).1342000 199쪽 · 기준 PDF p199 ↔ rhwp p199 — 끝 행 63 c4 는 저장 재시작
특성에서 갈리고, 같은 행에서 끝나는 걸침 칸 r62 c8 셋째 줄은 닫는 선 안에 남음Native 98.71 / WASM 98.62.
1342000 200쪽 · 기준 PDF p200 ↔ rhwp p200 — 행 63 이어지는 조각 16px(PDF 16.1) · 행 75 선언 높이로 쪽 끝
Native 99.95 / WASM 99.94.
1342000 203쪽 · 기준 PDF p203 ↔ rhwp p203 — 202쪽 마지막 행의 둘째 줄이 넘어오지 않음
Native 99.94 / WASM 99.91.
1342000 189쪽 · 기준 PDF p189 ↔ rhwp p189 — [9체01-04] 칸
…실천한/다.세 줄(#7702)Native 97.97 / WASM 98.11.
1342000 126쪽 · 기준 PDF p126 ↔ rhwp p126 —
noAdjust표 걸침 칸 끝 행 60 = 선언 2982HU, 쪽 끝 «자전거를 탈 때» 줄까지 (#8101)Native 99.44 / WASM 99.40.
1342000 127쪽 · 기준 PDF p127 ↔ rhwp p127 — «현장체험학습 시 버스 이용» 으로 시작
Native 99.40 / WASM 99.34.
1342000 51쪽 · 기준 PDF p51 ↔ rhwp p51 — 구역 1 표 이어지는 조각 윗변 = 본문 위 + 141HU (#8105)
Native 99.88 / WASM 99.91.
1342000 56쪽 · 기준 PDF p56 ↔ rhwp p56 — 55쪽이 행 21 p0·p1 을 담고 56쪽이 p2 «제10조» 로 시작 (#8105)
Native 98.55 / WASM 98.53.
1342000 59쪽 · 기준 PDF p59 ↔ rhwp p59 — 58쪽 «부산» 행 9 의 남은 선언 25.9px 가 첫머리 빈 띠 (#8105)
Native 99.80 / WASM 99.97. 수정 전 44.5(띠를 버려 쪽 전체가 19.4pt 위).
1342000 61쪽 · 기준 PDF p61 ↔ rhwp p61 — 첫 빈 띠 51.6px = 행 8–17 병합 칸의 남은 선언 (#8105)
Native 99.78 / WASM 99.97. 수정 전 50.0(행 17 꼬리 30.8px 로 시작).
1342000 62쪽 · 기준 PDF p62 ↔ rhwp p62
Native 99.84 / WASM 99.97. 수정 전 49.2.
1342000 307쪽 · 기준 PDF p307 ↔ rhwp p307 — 가로 쪽 첫머리 빈 띠 (#8105)
Native 99.95 / WASM 99.97. 수정 전 73.4.
1342000 250쪽 · 기준 PDF p250 ↔ rhwp p250 — 행 49 번호 문단
…갈등 현상 탐색하기한 줄 · 행 49 = 선언 3882HU 51.9px (#8105)Native 99.62 / WASM 99.67. 수정 전 78.6(행 49 가 저장 줄
…탐색하/기두 줄로 69.1px, 그 아래 행이 모두 17.2px 내려감). overlay 에서 행 경계가 모두 PDF 괘선과 겹친다.1342000 251쪽 · 기준 PDF p251 ↔ rhwp p251 — 250쪽 행 높이 복귀 뒤 이어지는 행
Native 97.98 / WASM 97.85. 수정 전 69.8.
#8105 픽스처 2쪽 · 한컴 2024 PDF p2 ↔ rhwp p2 — 저장 줄 + 병합 칸, D 15862: 남은 선언 51.2px 띠
Native·WASM 100.0.
#8105 픽스처 4쪽 · 한컴 2024 PDF p4 ↔ rhwp p4 — D 14738: 남은 선언 ≤ 1282HU 흡수, «다음» 행으로 시작
Native·WASM 100.0.
#8105 픽스처 10쪽 · 한컴 2024 PDF p10 ↔ rhwp p10 — 재조판 칸, D 14738: 흡수(수정 전 rhwp 는 15px 띠)
Native·WASM 100.0. 6·8·12쪽도 100.0(TSV).
hwpx_sample2 6쪽 · 한컴 2024 PDF p6 ↔ rhwp p6 — 미뤄진 첫 조각: 오프셋 소진, 윗변 = 본문 위 + 283HU, 아래 = 저장 첫 프레임 (#8105)
Native 99.81 / WASM 99.99.
hwpx_sample2 7쪽 · 한컴 2024 PDF p7 ↔ rhwp p7 — 이어지는 조각 행 경계 294.4px (#8105)
Native 99.67 / WASM 99.99.
issue5169 4쪽 · 기준 PDF p4 ↔ rhwp p4 —
…장기목표에/반영하는Native 99.97 / WASM 99.97.
휴먼명조 condense 끝 줄 사다리 1쪽 · 한컴 2024 — 폭 26705+d HU, d ≤ 6 은
다.셋째 줄 · d ≥ 7 은 붙음Native 99.94 / WASM 99.87.
휴먼명조 ASCII 사다리 10pt 자간 −10% 1쪽 · 한컴 2024 —
가c× 20Native 99.78 / WASM 99.70.
1613000 186쪽 · 기준 PDF p186 ↔ rhwp p186 — 26행 둘째 줄 이어받기 · 빈 문단 저장 줄 ·
pi=421행까지Native 99.35 / WASM 99.44.
1613000 188쪽 · 기준 PDF p188 ↔ rhwp p188 —
과목 3제목 뒤pi=7첫 조각Native 99.27 / WASM 99.29.
issue1880 1쪽 · 기준 PDF p1 ↔ rhwp p1 — 첫 조각 원점 = 문단 윗변 + 오프셋
Native 99.93 / WASM 99.95.
1613000 191쪽 · 기준 PDF p191 ↔ rhwp p191 — 새 쪽 첫 표 뒤 빈 문단 저장 줄 ·
pi=11첫 조각 행 0–4Native 99.87 / WASM 99.84.
1613000 192쪽 · 기준 PDF p192 ↔ rhwp p192 —
pi=11행 5 부터Native 99.54 / WASM 99.57.
전쪽 TSV (90% 미만 쪽 수)
mydocs/pr/assets/devel_table_scan_regression/tsv/에 문서별 devel(efc52afb7)·브랜치 Native·브랜치 fresh WASM TSV 를 넣었다(브랜치는 code head9f2b24150— 1342000 만 이 head 에서 바뀌었고, 다른 문서는 다시 찍은 TSV 가 직전 head 와 같다). 36382669·issue5169·휴먼명조 합성 입력의 devel 열은 같은 base 바이너리, 합성 coarse·ASCII 10pt·13pt 는 직전 head478da8250값이다.478da8250) 2 (최저 45.8)478da8250) 0 (최저 99.2)478da8250) 0 (최저 99.3)478da8250) 0 (최저 98.1)템플릿 기준(한 쪽이라도 90% 미만이면 재검토)에 미달한다. 남은 90% 미만 쪽은 이 PR 전부터 있던 쪽이다. devel 과 쪽 수가 같은 7개 문서에서 브랜치가 devel 보다 0.3 넘게 낮은 쪽 0, 새로 90% 아래로 내린 쪽 0(오른 쪽 1613000 45·issue1853 4·21761835 3·나머지 각 1). 1613000 의 6쪽 89.9·23쪽 30.4 와 1쪽 88.7 은 devel 과 같은 값이다(리베이스 뒤 devel 쪽에서 생긴 차이). 1480000·1342000 은 devel 쪽 수가 달라(206·420쪽) 전쪽 비교가 안 된다. 36382669 의 1쪽 80.3·8쪽 36.6 은 devel 과 같은 값이다(#7702 수정이 바꾼 5–7쪽은 0.3 이내).
테스트
9f2b24150(lint·nextest 는 커밋 직전 같은 트리), 정책 비교 base2e3b4f880(= 최신 devel)node scripts/rust-test-suite-manifest.mjs --prepare→cargo fmt --all -- --check→ native Clippy → WASM32-p rhwp --libClippy → workspace build → workspace all-targets Clippy-D warnings→ manifest--check --base-ref 2e3b4f880: LINT_OKcargo nextest run --cargo-profile release-test --tests: 11076 passed / 0 failed (45 skipped). 직전51a628363은 11074/0,e64b513ed는 11071/0 (새 테스트 파일은 실행 뒤 rustfmt 공백만 바뀜 — 그 뒤 lint 묶음 LINT_OK). 직전1cf3b879b은 11067/0,f296dbc21은 11064/0(rustfmt 전 공백만 다른 트리에서 실행),478da8250은 11062/0. 리베이스 직후(f8fa0f02a)에는 11053 passed / 1 failed(rows_inside_a_crossing_rowspan_still_split_after_one_line) —065125a94로 해소node scripts/rust-unit-test-tiers.mjs --check --base-ref 2e3b4f880: 통과CARGO_TARGET_DIR=target/pr-review scripts/wasm-pack-locked.sh --target web --out-dir pkg→pkg/rhwp_bg.wasm=rhwp-studio/public/rhwp_bg.wasmSHA-256c4ed9986…9f2b24150A/B(51a628363대비, 1342000 전쪽 Native·fresh WASM): 쪽 수 415 그대로, 바뀐 쪽 38 — 상승 33, 하락 5, 90% 미만 123→97(새로 90% 아래로 간 쪽 0). 250쪽 78.6→99.6·251쪽 69.8→98.0, 357–371·282–288·177·232·235쪽 90% 이상 복귀. 하락: 175쪽 84.4→82.8, 272쪽 70.4→67.6, 273쪽 71.3→67.7, 274쪽 75.9→71.7, 359쪽 74.4→70.0(WASM 같은 방향, 82.7·66.2·66.5·70.7·68.3). 175쪽은 새 줄 나눔이 꼬리를 붙이는 경계 근접 문단, 272–274·359쪽은 행 높이가 정본과 같아진 뒤 남은 기존 쪽 끝 분할 한 줄 차이의 연쇄다. 59·60쪽(번호 없는…제/정]반례)은 99.8 그대로. 샘플 전수(1,517개): 넓힌 조건이 실제로 줄을 바꾸는 문서는 1342000·interview.hwp뿐이고 interview 출력은 바이트 동일. 다른 증적 문서의 전쪽 TSV 는 직전 head 와 같다9f2b24150근거(한/글 2024 13.0.0.3901 MCP 직접 조판, 생성기mydocs/tech/investigations/issue-8105/probes/make_numbered_stale_tail.py, 입력·PDF 같은 폴더): 1×1 표 칸 문단의 저장 줄이 끝 음절기만 둘째 줄로 보내는 15가지 변형. HWP5(rhwp convert) 입력에서 «-»·«1.» 번호를 그린 문단은 모두 한 줄, 번호 없는 문단은 저장 줄 폭이 칸과 같으면 두 줄, 1HU 라도 다르면 한 줄. 줄 flags(0x200000·0x100000)·appVersion(2014·2020)은 결과를 바꾸지 않는다. HWPX 입력에서는 한/글이 덧붙인 «-» 번호를 그리지 않아 그 행은 근거에서 뺐다. 1342000 정본(한/글 2020 Print)도 번호 문단 꼬리 39/40 을 붙이고 번호 없는…제|정]·…일|부개정]은 두 줄이다478da8250A/B(065125a94대비, 샘플 1,252 SVG + 9개 문서 전쪽 TSV): SVG 가 바뀐 샘플은 1613000 139·140쪽뿐(99.2→99.3, 99.6→99.9). 1342000 은 바뀐 쪽 12 모두 상승 — 200쪽 92.8→99.95, 202쪽 92.3→97.3, 203쪽 91.8→99.9, 84쪽 30.4→50.8, 82쪽 42.8→51.2, 54쪽 77.4→78.8 등(WASM 도 같은 방향). 하락 쪽 051a628363A/B(e64b513ed대비): 샘플 SVG 13,408쪽 중 바뀐 문서 4개 — 1480000-201900698 45쪽 98.2→99.9, 18095317 6쪽 상승, 21761835 5·6쪽 ±0.03, vietnam_labor_report 41쪽(PDF 없음, 칸 clip 높이 +4.8px 만 — 보이는 이동 없음). 1342000 전쪽: 90% 미만 126→123, 59쪽 44.5→99.8·61쪽 50.0→99.8·62쪽 49.2→99.8·307쪽 73.4→100, 25–28·175·198·199·303·321·330·334·342쪽 소폭 상승. 하락: 250쪽 84.6→78.6·251쪽 98.0→69.8·352쪽 66.7→63.2 — 250쪽 첫머리 새 17.2px 띠는 PDF 에도 있다(맞음). 하락은 기존 불일치가 드러난 것: 250쪽 중간 한 행이 rhwp 69.1px ↔ PDF 51.9px, 351쪽 반복 머리 행 45.2 ↔ 18.0px. 중간 변형(블록 컷 조각까지 병합 칸 몫 확장)은 1341000 29쪽 92.1→87.6 이라 내용이 끝난 행으로 좁혔다(29쪽 기준선 복귀).51a628363근거(한/글 2024 13.0.0.3901 MCP 직접 조판, 생성기mydocs/tech/investigations/issue-8105/probes/make_declared_row_band.py): 시험 행 선언 D 사다리에서 다음 쪽 첫 행 = D − 그린 높이 > 1282HU 일 때만 빈 띠(17.0px 흡수·17.2px 이월). 칸 여백·표 기본 여백·글자 크기·저장 줄·병합 칸을 바꿔도 문턱 불변. 한/글 2020 1342000 의 13.33 흡수·21.33 이월과도 맞는다.e64b513edA/B(1cf3b879b대비): 샘플 1,252 SVG 중 바뀐 문서 10개·14쪽, 쪽 수 변화 0. PDF 대조 — hwpx_sample2 hwp 6·7쪽 98.7/96.7 → 99.8/99.7, hwpx 6쪽 74.9 → 99.8, 75544 hwpx 31·32쪽 86.7/53.3 → 99.9/97.3, 1480000 41쪽 71.1 → 100.0, 59043 24쪽 −0.1, 70833 13쪽 +0.1. PDF 없는 156555538(자리차지 표가 다음 쪽으로 넘어갈 때 문단 기준 세로 오프셋(146.7mm)을 그대로 더해 쪽 상단이 비고 표가 갈라짐 (156555538 9쪽) #6143 근거)·issue2439 는 한/글 2024 MCP 로 변환해 대조: 156555538 17쪽 = 변환본, 9쪽 윗변 77.44px = 변환본(수정 전과 같음). issue2439(rhwp 11 / 변환본 10쪽, 기존 불일치) 3쪽 54.9 → 90% 이상, 4쪽 47.9 → 33.1 — 3·4쪽 행 경계는 변환본과 같아졌고 4쪽은 끝 조각 뒤 다음 표까지 간격(+13px, 이 변경 조건 밖의 기존 오차)이 드러난다. 1342000(Native/WASM 같음) 90% 미만 132 → 126, 하락 0: 26–34쪽 +2~+13, 51쪽 +55, 53–57쪽 +20~+38e64b513ed근거: ① 1342000 구역 1 표(오프셋 5280·752HU) 한/글 2020 이어지는 조각 윗변 26–29·31·34·55쪽 본문 위 + 141HU(±0.1pt). ② 55쪽 행 21 칸 저장 vpos p0 0 · p1 1800 · p2 500(앞 간격 500) — 한/글은 p0·p1 을 34.66pt 조각에 담는다; rhwp 단위 p1 = 앞 간격 6.67 + 줄 13.33 + 뒤 줄간격 4.0px, 예산 39.95px. ③ hwpx_sample2 표pi=69: 앵커 1016.48 + 오프셋 4.0 뒤 26.4px < 0행(한 줄) 28.41px — 한/글 2024 6쪽 윗변 41.6px = 본문 위 + 283HU, 첫 조각 1037.88px = 저장 첫 프레임 1038.01px. 종전 예산은 오프셋 4.0 과 여백 3.8 을 둘 다 빼 1034.0px 로 닫았다. 그리기에서 유효 오프셋에 여백을 직접 더한 중간 변형은 156555538 9쪽(이미 다른 규칙이 여백을 엶)에서 여백을 두 번 열어 99.4 → 94.2 — OR 묶음으로 바꿨다1cf3b879bA/B(f296dbc21대비): 샘플 1,252 SVG 중 바뀐 문서 17개·63쪽, 쪽 수 변화 0. PDF 가 있는 15개 대조에서 0.3 넘게 내린 쪽은 sample1-repro 39·40쪽(−0.5)뿐, 편람 hwp 50·160쪽 +0.30.4. 1342000(Native/WASM 같은 방향): 126쪽 86.4→99.4, 127쪽 76.9→99.4, 128쪽 76.9→94.8, 129쪽 77.4→96.8, 101쪽 +2.8, 210쪽 +6.7, 90% 미만 136→132. 내린 쪽은 기존 저점 68·69·143·144·365쪽(−0.3−0.8). 그 밖 PR 8문서·합성 입력 TSV 바이트 동일1cf3b879b근거: 한/글 2020 Print 1342000 쪽 끝 표 아래 괘선(가로 쪽 척도 ×1.00047, 세로 ×1.00106 을 걷은 값) —noAdjust표(구역 5pi=80x0600000e, 구역 4pi=12, 구역 6pi=11, 구역 1pi=3) 121·99·170·49쪽이 본문 아래 − 바깥 아래 여백에 −0.15·−0.14·−0.14·−0.03px,noAdjust아닌 표 157·213·108·37쪽이 그 선 − 100HU 에 ±0.3px. 1613000(pi=1·pi=5, 0x04000006)의 기존 닫는 선 근거는noAdjust아닌 표라 그대로f296dbc21A/B(478da8250대비): 샘플 약 130개 문서 export-text 중 줄바꿈이 바뀐 문서는 1342000(189쪽)·36382669(5·6·7쪽)·issue5169(4쪽) 셋, 쪽 수 변화 0. 바뀐 줄은 모두 한/글 PDF 와 같아짐 — 1342000 189쪽…실천한/다.(한/글 2014 저장 줄·2020/2022/2024 PDF 공통), issue5169 4쪽…장기목표에/반영하는(한/글 2020 PDF), 36382669 5쪽 67/45·6쪽 69/1·7쪽 69/52 글자 줄(한/글 2024 MCP 변환본, 이번에pdf/issue7702/에 넣음). 9개 문서 전쪽 TSV: 0.3 넘게 바뀐 쪽은 1342000 189쪽 66.6→98.0(WASM 66.5→98.1) 하나, 그 밖 1,074쪽 하락 0(최대 ±0.3, 휴먼명조 ASCII 위치 이동). issue5169 4쪽 97.2→100.0. 합성 condense 사다리 40.7–58.2 → 99.9 이상f296dbc21근거(한/글 2024 MCP 직접 조판, 생성기·해시는mydocs/tech/investigations/issue-7702/probes/): ① 189쪽 문단을 본문 폭만 26705+d HU 로 바꾼 사다리 — 한/글은 d ≤ 6 에서다.를 셋째 줄로, d ≥ 7 에서 붙임(수정 전 rhwp 는 d ≥ −37 에서 붙임). 붙은 줄에서 공백 8개가 줄어든 합 400HU 는 rhwp condense 모형·[layout] 1790387 67쪽 pi=14 — 저장 LineSeg 5줄을 그대로 써 한/글(2020·2024 모두 4줄)과 문단 높이가 갈린다, 67~70쪽 +26.4px · PR #7366 실루엣 미달 #7418 과 같음 ② 94자가c× 20 사다리(10pt 자간 −10% / 10pt / 13pt) — 한/글 장치 전진폭이HMKMM.TTFhmtx 와 94/94 같고 [layout/table/regression] PR #2309 셀 저장-ls1 재래핑 허용이 정합 분할표 문서 11건을 과다분할 회귀 (10k r16, 최대 +3쪽) #2430 표는 37·58·70자 다름 ③ 남는 28HU 는 문단 끝.의 자간 — 한/글은 양쪽 정렬 줄 끝 글자를 자간 없는 폭으로 상자에 맞춤(line_breaking: 자간 trim 이 fit-test 호출부 넷 중 하나에만 닿고 어느 테스트도 구속하지 않는다 #5678, issue7418 PDF 의 줄 끝 원점)f8fa0f02a→065125a94샘플 1,252 SVG 바뀐 쪽 0(1342000 은 따로 대조 — 416→415쪽). 리베이스 전 head21ab9623d와 새 head 의 전수 A/B 는 devel 변경이 섞여 하지 않았고, 대표 30쪽·9개 문서 전쪽 TSV 를 새로 찍어 대신한다a92d0d220: 1342000 31쪽 88.8→99.0, 17253153 3쪽 87.9→98.2, 70833 2쪽 95.4→99.0, 샘플 하락 05994ce798: 샘플 중 21761835 만(2쪽 94.4→96.0, 3쪽 68.1→91.5), 1342000 81쪽 +4.2·82쪽 −0.85·83쪽 −0.3b30e9e020(리베이스 head 대비): 1342000 416→415쪽, 바뀐 쪽 195 상승·20 하락(하락은 이전에 PDF 와 한 쪽 어긋난 채 비교되던 226–365쪽, 최대 −5.6), 새로 90% 이상 141쪽, 새로 90% 미만 0. 샘플은 fragment_ghost_vrules 18쪽 +0.8 만200beb58f(b30e9e020대비, 샘플 1,252 SVG + 1342000): SVG 가 바뀐 문서는 1613000(185–191쪽 +37~+71), 59043 19쪽(45.5→90.8), table_scattered_header_rowbreak hwp·hwpx 51쪽(+0.96), issue1880(1쪽 +37.1, 2쪽 +0.08, 4쪽 −0.58 = 99.2→98.6), sample1-repro 20쪽(±0) 뿐. 90% 아래로 새로 내린 쪽 0. 1342000 SVG 동일. 중간 변형에서 나온 hwpspec 35쪽(표 40 을 쪽 끝에 가름 — 한/글은 통째 다음 쪽) 차이는 되감김 조건으로 없앴다23db8512f(7be2810a5대비, 샘플 1,252 SVG + 1342000): SVG 가 바뀐 쪽은 1613000 123–125쪽뿐 — 123쪽 96.95→99.43, 124쪽 81.73→99.50, 125쪽 26.99→30.17(표는 맞고 뒤 본문 16px 차이가 남음 → 다음 커밋). 1342000 SVG 동일8c847d933(23db8512f대비, 같은 범위): 0.3 넘게 바뀐 쪽은 issue1853 48쪽 34.26→95.82·49쪽 12.85→96.26, 1613000 125쪽 30.17→98.75 — 모두 상승. PDF 가 있는 그 밖 SVG 변화 쪽(편람 156, 86712, pr-1674, hwpx_sample2, 59043, 1341000, 1130000, 1480000-42, pic-in-head/table, synam, table_scattered_header, issue3236, 정책연구 등)은 Δ ±0.00. PDF 가 없는 문서는 한/글 2020 MCP 로 변환해 대조: task2070 은 72쪽부터 245쪽이 바뀌고 쪽 수 316→315 = 변환본 315쪽, 72–110쪽 평균 42.2(90% 미만 37쪽) → 99.77(0쪽), 전쪽 평균 97.00; 3112461 6쪽 99.63→99.44(아래 본문 1.87px 내려감 — PDF 글자 상자와의 거리는변전소줄 −1.6→+0.2,배터리줄 −1.1→+0.8 로 비슷), 156403546 16쪽 99.97→99.97; issue1891_external_bindata_link·1490000·1480000-201900698 은 부동소수 끝자리(827.6399…→827.64)만 다름. 중간 변형: 흐름 끝까지 상자 아래로 옮기면 issue1880 3·4쪽 −53·−65, 1613000 186–191쪽 −1−55(배제 띠가 뒤 문단을 밂), 빈 호스트 증거에 줄 상자 조건이 없으면 1613000 190–193쪽 −50−57(pi=8이 빈 줄 감추기로 숨으며 흡수한 위 간격이 사라짐) — 둘 다 막았다2dfc0f184(8c847d933대비, 샘플 1,252 SVG + 1342000): PDF 가 있는 쪽 중 바뀐 것은 1613000 58쪽 78.28→98.48·59쪽 29.72→96.27 뿐(issue1853 25·27쪽, rowbreak-problem-pages 15쪽은 SVG 만 바뀌고 Δ 0.00). PDF 없는 변화는 1977964 1쪽(표 전체 −0.69px, 한/글 2020 MCP 변환본 왼끝 84.67 에 85.50→84.83, 점수 98.54→98.48)과 합성stored-nested-content-flow/square-*(어울림 첫 표가 칸 가운데 x=128 → 왼쪽 x=48, square-top 한/글 2020 변환본 대비 72.8→77.3 — README 가 overlay 판에서 이미 '우연한 가운데 배치'로 기록한 같은 앵커). 1342000 SVG 동일. 중간 변형: 측정·컷만 고친 상태에서 1341000 29쪽 −23.8·30쪽 −31.3(고아 줄 되감기가 중첩 행을 한 행 일찍 자름 — 막음), 1613000 58쪽 위 여백 이중(+3.5px)·59쪽 뒤 문단 +9px(둘 다 이 커밋에서 고침)55ddf0690(2dfc0f184대비, 샘플 1,252 SVG + 1342000): SVG 가 바뀐 쪽은 1613000 85쪽뿐(22.93→98.52). 중간 변형: 같은 증상을 '새 쪽 첫 줄 vpos ≤ 그 문단 위 간격' 으로 쪽 경계 판정(꼬리 흡수)을 넓히면 aaaaaa 8쪽 −17·hwp3-sample16 35쪽 −24·48쪽 −23·issue2004 2쪽 −15 등 20쪽 넘게 떨어져 버렸다06dc305d5(55ddf0690대비, 샘플 1,252 SVG + 1342000): PDF 있는 쪽 변화는 1613000 197쪽 98.88→99.83·198쪽 58.82→99.90 뿐. PDF 없는issue5828/landscape_rowbreak_bleed.hwp(156505020 구역 3 절단 픽스처) 14→15쪽 — 픽스처 자체는 한/글 MCP 변환이 실패해 원본 156505020 을 한/글 2020 MCP 로 변환(43쪽)해 대조: rhwp 41→43쪽, 전쪽 평균 98.17(90% 미만은 43쪽 69.5 하나 — 마지막 표 행호원대하나가 42쪽에 남지 않고 43쪽으로 감). 기존issue_5828_landscape_rowbreak_absorbs_only_one_boundary_row통과de2315e55(06dc305d5대비, 샘플 1,252 SVG + 1342000): SVG 가 바뀐 쪽은 80168 hwp 60·61쪽(90.62→92.30, 36.28→96.00)과 80168 hwpx 판 60·61쪽(17.44→18.41, 24.53→24.54 — hwpx 판은 기존 저점)뿐. 중간 변형: 같은 표 89·90쪽 이어받는 행 상자를 '선언 − 앞 조각' 으로 넓히면 18095317 21쪽 −100·nested_table_text_caption 8–12쪽 −57−87·1382000 30·36쪽 −80−86·21761835 5·6쪽 −52·−57 등으로 깨져 버렸다7be2810a5(a5f9ea1c9대비, 샘플 1,252 SVG + 1342000): 오른 쪽 54(1613000 139–183쪽 21쪽 → 99.3100, 1341000 27·28쪽, hwpx_sample2 6쪽 +4.2, fragment_ghost 15쪽 +4.8, 1342000 다수), 내린 쪽 9 — 1342000 81쪽 −2.9(기존 86.7, 한/글이 끝 행에 한 줄 더 넣는 기존 컷 차이), fragment_ghost 18쪽 −1.1·1342000 251쪽 −0.7(둘 다 표 아래·끝 행 윗변은 PDF 에 더 가까워짐: 18쪽 윗변 −1.44→−0.10, 251쪽 아래 −2.58→+0.09), 21761835 hwpx 2쪽 −0.7(행 20 상자가 닫는 선보다 2.4px 짧던 기존 차이에 1.33px 더), 그 밖 기존 90% 미만 −0.4−0.6. 중간 변형: 줄인 몫을 행 자신의 다음 부분에도 넘기면 1342000 338–345쪽 −26~−31·21761835 3쪽 −10.5, 개체 든 행에도 적용하면 1341000 29쪽 91.5→86.4 — 막았다35f46f163(0e93b92a9대비, 샘플 1,252 SVG + 1342000): 오른 쪽 95(+0.3~+1.8 — table_scattered_header hwp·hwpx 다수, 80168 2·47·60·73·88·122쪽, 86712, 1613000 144–183쪽, 76076 hwpx 판 한/글 2024 PDF 2·18·52·67쪽 +0.6), 내린 쪽 4(1342000 32·227·232·298쪽 −0.3−0.8, 모두 기존 6775%). 중간 변형: 원장도 줄인 띠를 쓰면 21761835 3쪽 −15.8·1342000 80쪽 −24.6·224쪽 −21.7, 내용 컷 행까지 줄이면 1342000 203쪽 −10, 걸침 몫 계산에 줄인 상자를 넘기면 1342000 338–345쪽 −26~−31 — 모두 막았다. PDF 가 없는 문서(task1753, issue3637, issue1891_external_bindata_link, 80550, 156403546, hwpspec)도 같은 1.33px 띠 단축이며 대조하지 않았다. 80168 WASM TSV 는 이전 WASM 으로 찍은 것을 다시 찍었다(같은 head Native 는 6쪽만 바뀜, WASM 57쪽 91.07→89.84 는 빌드 차이)65e20ecba(1185e8a29대비, 샘플 1,252 SVG + 1342000): 1613000 195쪽 96.9→99.9, 196쪽 59.3→99.6, 197쪽 61.9→98.9, 198쪽 49.3→58.8, 200쪽 96.6→99.9, 201쪽 54.9→98.4, 202쪽 51.4→99.9, 1342000 335–345쪽 +2~+32(338–345 → 9799.5), 334쪽 −0.31. 그 밖 변화 없음. 중간 변형: 바깥 아래 여백을 빼지 않으면 80168 122·123쪽 −74(행 23 이 남음), 자기 칸 없는 행까지 받으면 1342000 33쪽 −40, 첫 조각까지 넣으면 합성 계약+31 이지만 80쪽 −24.6·224쪽 −21.7·21761835 3쪽 −15.8 이라 넣지 않았다. 1342000 WASM TSV 는 이전 WASM 으로 찍은 것을 다시 찍었다(같은 head Native 는 334–345쪽만 바뀜)opening_rowspan_block_cuts_after_the_first_row실패 — 셋 다 조건으로 막았다. 띠 끝에도 100HU 를 적용하는 변형은 1342000 44·47·225·226쪽 +20b4452b801(5cf391db0대비, 샘플 1,252 SVG + 1342000): 1613000 126쪽 93.2→99.7, 127쪽 91.0→99.6, 128쪽 91.6→99.1, 1480000 43쪽 97.4→99.99, myeonjeok 1쪽 98.64→98.58(표 아래 1081.3px ↔ 한/글 2020 MCP 변환본 ≈1080.5, 종전 1078.3 — 끝 줄간격 접기로 우연히 가깝던 값), hwpspec 42쪽 +0.24(쪽 수 181≠178 기존)·97쪽 ±0, hwp-3.0-HWPML 38쪽 40.0→40.1(MCP 변환본). 하락 쪽 없음. 중간 변형(paint 접기 예외를 컷 일치만으로 판정)은 1613000 139·141·167·180쪽을 −1−4 내려 같은 상자 값 조건으로 좁혔다(그 변형에서 함께 오르던 152–178쪽 +1+3.6 은 이번에 넣지 않음). 1480000 WASM TSV 는b30e9e020무렵 WASM 으로 찍은 것을 다시 찍었다 — 같은 head 의 Native 는 43쪽만 바뀌므로 그 밖 쪽의 차이(±0.1~4, 169쪽 90.38→89.67)는 WASM 빌드 차이다dd2e52e71(리베이스 전200beb58f대비, 샘플 1,252 SVG + 1342000): SVG 가 바뀐 쪽은 1613000 191–193쪽뿐(Native 77.8/41.3/57.1 → 99.9/99.97/99.85, WASM 77.5/40.7/56.7 → 99.9/99.96/99.9). 1342000 SVG 동일6ed1682c3) 전후: 샘플 SVG 중 바뀐 쪽은 누름틀 양식 5쪽(BlogForm_BookReview·MovieReview·Recipe 1쪽, field-01·field-01-memo 3쪽) — develcfd06cd2b(누름틀 교체·인쇄 보정) 영향이고 표 쪽은 리베이스 전과 같다8766fb47d) 전후: 샘플 SVG 13,416쪽 전부 바이트 동일(리베이스 전 빌드 ↔200beb58frelease)RHWP_FONT_PATH= hwp·windows TTF + KoPubWorld TTF/OTF + KoPub2.0 (모두 존재). 21761835 의 한/글 PDF 는 나눔명조가 Haansoft Batang 으로 대체돼 있으나 줄 간격이 저장값(1272HU)과 같아 행 높이 비교에는 영향 없음을 확인.새 회귀 테스트(
tests/cases/원본만, generated·manifest 미포함):rowbreak_span_cell_page_end_lines::span_cell_lines_inside_the_closing_line_stay_on_the_page(1342000 199쪽 r62 c8 셋째 줄 = 행 63 첫 줄과 같은 쪽, 행 63 c4특성은 다음 쪽 — PDF 와 같음) ·::span_end_row_keeps_its_declared_height(202쪽 행 92 = 선언 97.1px ±1)rowbreak_short_row_whole_carry::crossing_rowspan_owns_the_page_end_band(21761835 2쪽 행 20 띠 · 3쪽 빈 줄+패딩 · 걸침 칸 행 조각 합 = 선언 252px±1.5)rowbreak_short_row_whole_carry::crossing_rowspan_without_declared_slack_leaves_the_band_empty(반례: 70833 2쪽 표 끝이 본문 끝보다 30px 넘게 위)rowbreak_short_row_whole_carry앞 7건(1480000 표 15·18, 21761835 4쪽 블록 끝, 1480000 44쪽 저장 컷·빈 줄, 21761835 2쪽 걸침 분배, 1342000 반례)rowbreak_short_row_whole_carry::grown_boundary_row_continues_and_successor_keeps_its_stored_line(1613000 185쪽 26행 분할·187쪽pi=421행 통째 시작·188쪽pi=70행 시작)dump-pages로 확인: 185쪽pi=1이 통째(Table, 조각 없음)라 첫 단언이 실패하는 상태. 테스트 자체를 수정 전 코드로 실행하지는 않았다issue_6950_paragraph_end_topbottom_anchor::first_fragment_uses_paragraph_reference_not_text_or_outer_box에 문단 윗변 앵커 변형 추가(같은 첫 조각이어야 함)rowbreak_short_row_whole_carry::crossing_span_end_row_takes_the_larger_span_share_up_to_the_closing_line(1613000 139쪽 행 49 = 걸침 칸 5128 − 앞 행 2882HU = 29.95px, 144쪽 행 139 = 2882HU, 154쪽 행 51 = 닫는 선 731.91px)rowbreak_short_row_whole_carry::crossing_span_row_closes_at_the_fragment_bottom_line(1613000 196·197·201·202쪽 시작 행 44·71·43·65, 195쪽 행 43 내용이 저장 용지·여백으로 계산한 닫는 선 712.99px 안)rowbreak_short_row_whole_carry::crossing_span_row_beyond_the_closing_line_moves_whole(반례: 80168 123쪽이 행 23 으로 시작)rowbreak_short_row_whole_carry::stored_restart_end_row_closes_at_its_declared_or_cut_content_box(1613000 126·127쪽 행 17·28, 1480000 43쪽 행 118, myeonjeok 1쪽 행 29 의 끝 상자 = 저장 메트릭의 max(선언, 컷 내용))rowbreak_short_row_whole_carry::continued_table_bottom_caption_keeps_the_whole_table_gap(1613000 128쪽 끝 조각 캡션 간격 = 121쪽 통째 표)rowbreak_short_row_whole_carry::whole_table_on_a_fresh_page_leaves_its_successor_on_the_stored_line(1613000 191쪽pi=11첫 조각이 행 4 에서 끝나고 192쪽이 행 5 로 시작 — 한/글 PDF 의1.2 교육 계획/1.2.1)rowbreak_short_row_whole_carry::continued_row_closes_at_its_next_stored_restart(1613000 표pi=1133123쪽 끝 컷 [40,37]·124쪽 [51,70]·이어받기 연속, 123쪽 행 상자 = 저장 (66020+1200+282)HU = 900.03px, PDF 899.96)[41, 37])rowbreak_short_row_whole_carry::empty_host_terminal_successor_keeps_its_stored_line(1613000 125쪽pi=1135첫 줄 = 본문 위 + vpos 15006HU = 275.68px)rowbreak_short_row_whole_carry::nested_table_page_frame_splits_its_single_cell_box(1613000pi=58558쪽 끝 컷 [32]·59쪽 연속, 58쪽 「항공기 이륙」까지·59쪽 「상승비행」부터 합계 170 까지, 58쪽 상자 윗변 = 본문 위 + 바깥 위 여백 (5670+283)HU = 79.37px)rowbreak_short_row_whole_carry::continuation_successor_keeps_its_stored_line_below_the_box(59쪽pi=587첫 줄 = 본문 위 + vpos 20884HU = 354.05px, PDF 글자 윗변 353.84)rowbreak_short_row_whole_carry::square_nested_table_with_zero_offset_keeps_its_left_anchor(58쪽 22×2 표 왼끝 = 칸 왼끝 + 안 여백 510 + 바깥 왼 여백 140 HU = 8.67px, PDF 괘선 92→101px)rowbreak_short_row_whole_carry::footnote_margin_does_not_cut_body_beyond_the_footnote_height(1613000 84쪽이pi=817을 갖고 85쪽이pi=818로 시작, 그 첫 줄 = 본문 위 + vpos 700HU = 84.93px)rowbreak_short_row_whole_carry::stored_fragment_table_does_not_bleed_a_landscape_boundary_row(1613000 구역 3pi=1197쪽 끝 행 96 전, 198쪽 행 96 부터 통째)rowbreak_short_row_whole_carry::no_line_seg_cell_paragraph_end_is_a_row_split_boundary(80168 hwp 표pi=51660쪽 끝 컷 [1,1]·61쪽 연속)rowbreak_short_row_whole_carry::stored_restart_cuts_the_last_row_of_a_page(기존, 1613000 204쪽)split_row_stored_reset_valign::stored_paragraph_reset_fragment_keeps_cell_center_alignmentsplit_row_stored_reset_valign::single_cell_stored_reset_fragment_is_aligned_once(1×1 반례)first_frame_remainder_capped_by_row_box,stored_zero_origin_later_page_row_fits,tac_picture_stored_rewind_next_page,rowbreak_rowspan_opening_row_cut,rowbreak_carried_row_bandissue_7702_condense_word_tail::pre_2020_stored_word_tail_joins_the_condensed_line(1342000 151·154쪽 꼬리가 앞 줄에)issue_7702_condense_word_tail::joined_tail_row_keeps_its_declared_height(151쪽 r=56 칸 ≤ 선언+1px)issue_7702_condense_word_tail반례 3건(114쪽 앞 경계 유지, 25쪽 condense 없음, 21_언어 1쪽 한/글 2020 저장)issue_7702_condense_word_tail::stored_row_generation_comes_from_the_container_last_save(메타데이터 판정)issue_7692::partial_plain_row_keeps_source_minimum_and_owned_contents·issue_6981::continuation_height_respects_varying_page_budgets50dcb0078(원장에 inset 을 더한 리베이스 중간 변형)에서 실행 FAILissue_7702_humanmyeongjo_ascii_and_condense_end::condensed_paragraph_end_line_breaks_where_hancom_2024_does(합성 fine·coarse 사다리의 d 마다다.줄 = 한/글 2024 PDF 의 줄)issue_7702_humanmyeongjo_ascii_and_condense_end::humanmyeongjo_ascii_advances_match_hancom_2024_ladders(94자 × 3 조건 장치 전진폭 = 한/글 2024 PDF가c주기 −가),59/60.59/60(69/70 등)issue_8101_no_adjust_fragment_bottom::no_adjust_table_fragment_closes_at_the_outer_bottom_margin(1342000 121–125쪽noAdjust표 조각 아래 = (53859 − 141) HU = 716.24px)issue_8101_no_adjust_fragment_bottom::spanning_cell_end_row_keeps_its_declared_height_and_page_owns_the_line(126쪽 행 60 = 선언 2982HU, «자전거를 탈 때» 줄 126쪽·127쪽 «현장체험학습»)issue_8101_no_adjust_fragment_bottom::ordinary_table_fragment_keeps_the_bottom_inset(반례: 157쪽noAdjust아닌 표 = (53859 − 141 − 100) HU)issue_8105_fragment_outer_top_and_restart_trim::continued_offset_table_reopens_its_outer_top_margin(1342000 26–29쪽 윗변 = (5669 + 4252 + 141) HU)issue_8105_fragment_outer_top_and_restart_trim::own_before_restart_keeps_the_closing_line_on_the_page(55쪽 행 21 p1 / 56쪽 p2 «제10조(학생예방교육)»)issue_8105_fragment_outer_top_and_restart_trim::deferred_first_fragment_spends_its_offset_and_opens_the_outer_top(hwpx_sample2 6쪽 윗변 (2835 + 283) HU, 아래 (84188 − 2835 − 283 − 100) HU)issue_8105_fragment_outer_top_and_restart_trim::consumed_offset_does_not_reopen_an_already_opened_margin(반례: 156555538 9쪽 윗변 (5670 + 140) HU)issue_8105_declared_row_blank_tail::blank_tail_above_the_limit_opens_the_next_page(픽스처 2·6·8·12쪽 첫 칸 = 행 1 빈 띠, 높이 = 선언/75 − 앞 쪽 그린 높이 ±0.5)issue_8105_declared_row_blank_tail::blank_tail_within_the_limit_is_absorbed_at_the_page_end(4·10쪽은 «다음» 행 2 로 시작)issue_8105_declared_row_blank_tail::stored_rows_carry_declared_and_ending_span_remainders(1342000 59쪽 행 9 띠 = 9366HU − 58쪽 «부산» 칸, 61쪽 첫 칸 = 행 17 빈 띠 = 103310HU − 58–60쪽 병합 칸 조각 합)issue_8105_numbered_stored_word_tail::numbered_cell_paragraph_rejoins_its_stored_word_tail(1342000 250쪽…갈등 현상 탐색하기한 줄, 꼬리기단독 줄 없음, 행 49 칸 = 3882HU/75 ±0.5px)…탐색하/기)issue_8105_numbered_stored_word_tail::unnumbered_cell_paragraph_keeps_its_stored_word_tail(반례: 59쪽 번호 없는…2017.11.13., 제/정]두 줄 = 정본)issue_7702_condense_word_tail::recomposed_tail_that_does_not_fit_stays_on_the_next_line(종전stored_tail_without_condense_keeps_the_stored_break— 25쪽…필/요는 번호 문단이라 다시 나누는 대상이지만 새 줄 나눔에서도 두 줄. 이름·설명만 고치고 단언은 그대로)정렬 검사의 대조값은 구현 계산을 재인용하지 않고, 같은 문서에서 그 칸만
valign=Top으로 바꿔 다시 조판한 출력이다.조판 변경 근거 — 소비 경로
분할 판정:
typeset/table/scan/runner/row_step.rs(저장 재시작 컷, 짧은 끝 행 통째 이월, 블록 끝 닫기) →continuation/fragment/emit.rs(조각 확정·[layout/table] 걸침 칸 초과 높이를 행에 나누는 방식이 한/글과 다르다 — 1342000 edu 31쪽 +7.7px·32쪽 −9.4px, 쪽 끝 줄 수가 갈린다 (#7226 잔여) #7531 쪽 끝 띠·원장) →physical_rows.rs(다음 조각 행 계획, 띠 몫 상한crossing_span_page_end_band) → paintlayout/table_partial.rs(end_row_owns_stored_frame이면 끝 줄간격 접기 생략).행 높이 풀이:
height_measurer.rs::solve_rowspan_row_heights(가장 먼저 끝나는 제약 우선) — 측정·scan·paint 가 같은row_heights를 소비.셀 정렬:
table_partial.rs의plain_cut_frame_owns_alignment→frame_owns_alignment→effective_align. 새 조건은 기존row_cut_ends_at_stored_page_reset판정을 재사용.자란 경계 행:
height_measurer.rs::fit_measured_table_to_declared_height_with_outcome의 [layout] 비공백 호스트 표의 선언 높이 fit이 원본 행높이를 일괄 축소 — 시장구조조사 표 Ⅵ-5 #7147 예외 뒤declared_fragment_closes_on_a_grown_row→ 측정row_heights를 scan·paint 가 함께 소비.첫 조각 원점:
typeset/table/block/prepare.rs(호출자placement_para_start_height) →float_placement.rs::for_first_fragment→record_paragraph_float_placement를 paint 가 그대로 소비.이어받는 행의 저장 재시작 컷:
table_layout.rs::row_stored_restart_cut_after(=stored_plain_restart_cut에 시작 컷·문단 첫 줄 재시작) →row_step.rs용량 컷 직후 교체(stored_restart_capacity_keep로 고아 가드 면제, 예산 검사는 그대로) → emit·paint 는 같은end_cut소비.빈 호스트 끝 조각 뒤 문단의 NextLine 계획: emit
commit_fragment가stored_successor_line_origin기록 → paintParagraphFloatPlacement::paragraph_end(호스트 아래 간격 생략)·stored_frame_successor_shared_spacing_px(뒤 문단 위 간격 한 번) — typesetparagraph/flow.rs도 같은 함수.끝 조각 뒤 문단:
table_layout.rs::text_host_terminal_successor_gap← 공통native_text_frame_terminal_successor_gap를 emit(commit_fragment흐름 끝·가시 배제 띠 하단)과 paint(layout.rs의source_terminal_gap)가 같은 입력으로 호출.중첩 표 호스트 갭:
float_placement.rs::nested_host_gap_start를 측정height_measurer.rs::cell_nested_controls_bottom과 배치table_layout.rs::calc_nested_controls_bottom_height가 같은 입력(앞 문단 흐름 표 끝)으로 호출 → 측정 행 높이를 scan·paint 가 소비.중첩 표 저장 첫 조각 경계:
table_layout.rs::stored_object_frame_row_count→cell_units_uncached의 중첩 행 유닛hard_break_before(부모 유닛으로 전파) →advance_row_cut_inner가 그 유닛에서 멈춤(rewind_rowbreak_orphan_before_hard_break는 중첩 행끼리 되감지 않음) → emit·paint 는 같은end_cut.1×1 첫 조각 원점:
fragment/budget.rs의 단일 칸 위 여백 가산(흐름 원점이 이미 연 계획은 건너뜀) →record_paragraph_float_placement→ paint.칸 안 어울림 중첩 표 가로:
table_layout.rs중첩 표 x 의 [renderer] 칸 안 어울림 중첩 표가 저장 horzOffset 을 안 써 왼쪽으로 49.9px 치우친다 (#5702 의 가로 축 잔여, 2025571) #5787 어울림 분기(오프셋 ≥ 0) — export-pdf: '직인' 텍스트박스 위치 이탈 + 페이지 하단 용지규격 문구 소실 #3308 가운데 분기 앞.각주 쪽 가용 높이:
typeset/state/transition.rs::available_height(각주 차감 0·보수 여백 > 0 이면 하한 = 본문 − 각주 높이) → 문단 fitprepare_fit_budget·표 예산이 같은 값을 소비. paint 각주 영역은page_layout.rs::update_footnote_area(본문 바닥 − 각주 높이)로 같은 경계.가로 용지 허용치:
typeset/table/scan/landscape.rs::storage_records_page_cuts(셀 되감김 또는 저장 첫 조각 프레임) →whole_row_shape·short_row_shape가 허용치를 끔 → scan 의 일반 용량 컷.문단 끝 컷 계약:
layout/table_paragraph_cut.rs::row_cut_plain_paragraph_contract(문단 끝 컷은 저장 글줄 없이도 통과) →row_step.rs의plain_paragraph_keep_contract가 25px 최소 상단 문턱을 면제 → 같은end_cut을 emit·paint 가 소비.저장 앵커 분할 판정:
typeset/table/block/entry.rssaved_anchor_overlaps_current_flow→saved_anchor_splits_here→ 선언 이월 생략.빈 줄:
layout/paragraph.rs·flow.rs→empty.rs::hide_rowbreak_guide,height_cursor.rs::vpos_adjust; 셀 끝 vpos 0 재시작 빈 줄의 줄 상자 소유는table_layout.rs::empty_unit_owns_flow_line_box.(리베이스 후속) HWP5 저장 표 예산:
continuation/fragment/budget.rsnative_source_frame+ 병합 칸 →rowbreak_fragment_frame_bottom의 inset 생략 →physical_frame_bottom→page_avail→avail_for_rows. 재조판 프레임(같은 파일 reflow 분기)·painttable_partial.rspage_cap 은 devel 대로 inset.(리베이스 후속) 쪽 끝 띠:
fragment/emit.rs원장 띠는 devel 식(frame_rows + header_overhead − partial_height), 그리는 띠만SINGLE_CELL_PAGE_FRAGMENT_BOTTOM_INSET_HU − budget.reflow_frame_bottom_inset를 한 번 뺀다. 방 =split_end_reserved(스캔이 예약한 패딩 포함 컷 상자).(리베이스 후속) 걸침 예약:
scan/runner.rspost-loopstored_span_fragment_minimum의grow = minimum − consumed를 끝 행 override 와 consumed 가 같이 소비.([layout] 한/글 2014 저장 줄 나눔과 한/글 2020 출력이 갈리는 칸 — 공백 폭·줄 끝 넘침 허용 차로 행이 한 줄 높아진다 (1342000 +700px) #7702) 저장 줄 판정:
stored_cell_reflow.inc.rsfresh_rows_absorb_stored_tail(프레임 복제에resolve_stored_line_segs_in_frame(stale=true)) → 같은Reflowed경로 → 측정HeightMeasurer::measure_table_impl·typeset·paint 가 같은 줄 소비. 저장 세대는DocumentCore로드 시SourceProvenance::stored_rows_before_hancom_2020(HWP5 요약 / HWPXversion.xml) →StoredGeometryPolicy.([layout] 한/글 2014 저장 줄 나눔과 한/글 2020 출력이 갈리는 칸 — 공백 폭·줄 끝 넘침 허용 차로 행이 한 줄 높아진다 (1342000 +700px) #7702 189쪽) 휴먼명조 ASCII 폭:
font_metrics_overlays.rsHUMANMYEONGJO_LATIN_0→ 측정기 장치 전진폭 → 재조판 줄 나눔·paint 글자 위치가 같은 측정기를 소비. 문단 끝 condense 판정:composer/line_breaking.rs::fill_one_interval의w_hwp_fit(끝 글자 자간 트림을 자연폭으로 들어갈 때만 생략) → 같은 줄 나눔 결과를 측정·typeset·paint 가 소비.([layout] 1342000 90% 미만 136쪽 분류 — 한/글 2014 저장 줄 재조판·번호 머리 영역·쪽 끝 한 줄 연쇄 #8101) 비끝 조각 inset:
float_placement::rowbreak_fragment_bottom_inset_hu(table)→single_cell_page_fragment_bottom(예산budget.rs재조판 프레임·원본 프레임, painttable_partial.rspage_cap) ·emit.rs그리는 띠(unreserved_page_end_band)·원본 닫힘 판정 ·row_step.rs걸침 칸 닫는 선. 같은 함수 하나라 예산·그리기·원장이 같은 하단을 쓴다.([layout/table] 1342000 남은 90% 미만 132쪽 — 이어지는 조각 바깥 위 여백(세로 오프셋 표)·자기 앞 간격 되감김의 끝 줄간격 #8105) 이어지는 조각 위 여백:
float_placement::native_multirow_rowbreak_reopens_outer_top을 예산(budget.rs)·그리기(table_partial.rs)가 함께 소비. 뒤 줄간격:table_layout.rs::stored_page_reset_cut_trailing_trim←advance_row_cut_inner용량 컷 → 같은end_cut·조각 높이를 emit·paint 가 소비. 오프셋 소진:float_placement::para_offset_consumed_by_page_break(para, table, …)를 예산·whole_fit·typeset·controls/order·table_partial 여섯 곳이 같은 입력으로 호출, 소진 시 예산 host_before 와 그리기 바깥 위 여백 OR 묶음이 같은 원점.남은 차이 (해결하지 않음)
리베이스로 생긴 차이 — 1342000 202쪽 92.3→478da8250으로 해결(97.3). 원인은 행 92 의 분배가 아니라 199쪽: 끝 행 63 의 내용 컷이 같은 행에서 끝나는 걸침 칸 r62 c8 의 줄까지 잘라 셋째 줄이 200쪽으로 갔고(200쪽 첫 행 +2.9px → 행 75 쪽 끝 −2.9px), 행 57–92 걸침 원장이 그 부족분을 끝 행 92 에 더했다.[layout] 한/글 2014 저장 줄 나눔과 한/글 2020 출력이 갈리는 칸 — 공백 폭·줄 끝 넘침 허용 차로 행이 한 줄 높아진다 (1342000 +700px) #7702 남은 오답 — 1342000 189쪽→…실천한/다.f296dbc21로 해결(66.6→98.0). 원인은 condense 판정의 너그러움이 아니라 휴먼명조 ASCII 폭 표 오차(16HU) + 문단 끝 글자 자간(28HU)의 합이었다.1cf3b879b·e64b513ed·51a628363·9f2b24150로 126–129·26–34·51–62·307·250·251·357–371쪽은 풀었지만, 352쪽(351쪽 반복 머리 행 45.2 ↔ 18.0px)의 기존 행 높이 불일치와 130–145·252–262·272–274·349–356쪽 등의 쪽 끝 한 줄 연쇄는 남는다.9f2b24150으로 175쪽 −1.6·272–274·359쪽 −3~−4 가 내려갔다(위 A/B). 129쪽 행 102 칸 문단의 저장 vpos 되감김(한/글 2014 의 쪽 경계 기록)을 rhwp 는 컷으로 쓰고 한/글 2020 은 한 문단을 더 담는다. «2020 이전 저장본은 되감김 컷을 쓰지 않음» 변형은 60쪽 −53·75쪽 −39 로 순손실이라 넣지 않았다.21761835 3쪽 24행은 44.9px 로 한/글 43px 보다 1.9px 크다(걸침 칸이 덮는 행 조각 합은 선언 252.0px 와 같다 — 행별 래스터 오차 범위로 본다).
90% 미만 쪽(이 PR 이전부터): 표 분할 경로 — 70833 5–7쪽, 80168 90쪽(이어받는 행 상자 −8px)·93쪽(제목 문단 쪽 귀속), 1480000 11·41·145·155쪽, 1342000 다수. 문단·그림·캡션 경로 — 1480000 14·80–82·130·141쪽(그림 캡션이 앞 쪽에 남음), 70833 18쪽.
1613000 구역 1 끝 행 중 155·162쪽 +7.0, 166쪽 +5.6, 182쪽 −4.2px 는 남았다(162·166쪽은 rhwp 의 행 측정 높이가 한/글보다 큰 별도 차이). 21761835 2쪽 행 20 상자는 닫는 선보다 3.7px 짧다.
1613000 58쪽 상자 아래 선은 rhwp 992px·PDF 999px(한/글은 첫 조각을 선언 높이 920.5px 프레임으로 닫는다), 59쪽 이어진 조각 아래 선은 −5px(캡션도 5px 위). 두 쪽 모두 95.9% 이상.
80168 의 90% 미만은 리베이스 뒤 7쪽(37·90·93·109·111·133·139, Native)이다 — 리베이스 전 18쪽 중 20·21·76·77·143 등 2×2 조문 대비표 쪽은 그사이 devel 변경으로 90% 이상이 됐다. 남은 쪽은 모두 devel 과 같은 값이며 이 PR 에서 고치지 않는다. 아래 표는 리베이스 전 18쪽의 원인 분류를 그대로 둔다.
미검증
grown_boundary_row_continues_and_successor_keeps_its_stored_line와 issue_6950 추가 단언의 수정 전 FAIL 은 실행하지 않고 덤프·계산으로 확인했다(위 표).hwpspec 표 40 반례는 회귀 테스트로 넣지 않았다: hwpspec 은 최저 29.8% 로 [대표 이슈] 문서 전체 피델리티 개선과 회귀 검사 재구축 #7445 보류 목록에 있고 회귀 추가의 90% 선행 조건에 못 미친다. 근거는 A/B(현 head 에서 표 40 배치가
b30e9e020와 같음)와pdf/hwpspec-2024.pdf35쪽(쪽 번호 25) 대조 — 표 40 이 쪽 맨 위에 통째로 있다.issue1880 4쪽 −0.58(99.2→98.6): 4쪽 빈 문단·
pi=6호스트 줄이 저장 vpos(PDF 와 같은 140.0px)로 올라가고pi=6표 윗변이 PDF 173.5 에 대해 174.2(종전 174.2)로 같다. −0.58 을 만든 영역은 따로 판독하지 않았다.1342000 쪽 경계(행 92·쪽 수)를 직접 잡는 회귀 테스트는 넣지 않았다: 관련 200쪽이 89.7% 라 회귀 추가의 90% 선행 조건에 못 미친다. 근거는 위 전쪽 TSV(415쪽 = PDF)와 A/B.
crossing_rowspan_owns_the_page_end_band의 수정 전 FAIL 은 빈 줄 소유 변경만 들어간 중간 상태에서 확인했다.1341000 표 113 반례(중첩 행 고아 되감기)는 회귀 테스트로 넣지 않았다: 관련 28쪽 87.1%·31쪽 66.6% 로 90% 선행 조건에 못 미친다. 근거는 A/B(최종 head 의 28–31쪽 컷이
8c847d933와 같음)다.156505020 원본(저장소 밖 실문서 코퍼스)·1977964·square-top 의 기준 PDF 도 한/글 2020 MCP 변환본(scratch)이다.
task2070·3112461·156403546 의 기준 PDF 는 한/글 2020 MCP 변환본(scratch, 저장소에 넣지 않음)이다.
f296dbc21의 휴먼명조 표는 ASCII(U+0020–007E)만 바꿨다. Latin-1 등 다른 범위, 장평 ≠ 100% 조합은 한/글 사다리로 재지 않았다.위 8개 외 문서의 전쪽 TSV(샘플 1,248 SVG A/B 로 바뀐 쪽만 PDF 대조).
🤖 Generated with Claude Code