Repository navigation
fix(조판): 한/글 2020 이전 저장 줄의 낱말 꼬리를 condense 흡수로 다시 끊는다 — 1342000 415쪽 (#7965 의존, 부분 개선) - #8092
Closed
planet6897 wants to merge 46 commits into
Closed
planet6897 wants to merge 46 commits into
planet6897 wants to merge 46 commits into
Conversation
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>
1342000 31쪽 끝 행 24 경남 칸(valign Center, 11줄)은 p[4] 첫 줄이 저장 vpos 0 으로 다시 시작한다. 한/글 2020 PDF 는 이 칸의 앞 6줄을 조각 안에서 가운데 정렬한다(첫 줄 조각 위 9.8px, 위 정렬이면 3.8px). rhwp 는 원본 조각의 정렬 소유(plain_cut_frame_owns_alignment)를 문단 안 재시작(row_plain_restart_capacity_cut)에만 주어 문단 경계 재시작 칸을 edwardkim#4042 Top 으로 떨어뜨렸다. issue1853 35쪽처럼 이미 소유 플래그가 서는 분할 행은 같은 칸 정렬로 한컴과 맞는다. - row_cut_ends_at_stored_page_reset(문단 경계 재시작까지 확인하는 행 판정)도 같은 소유로 인정한다. - 칸 하나뿐인 표는 제외한다. rowbreak-problem-pages 13쪽 1×1 Center 칸은 수정 전에도 위 정렬보다 17.9px 내려 그려져 한/글 2024 PDF 와 맞는다(첫 글줄 잉크 497 / 495). 정렬을 다시 얹으면 27.9px 로 이중 정렬된다(1382000 20쪽 −31%, rowbreak-problem-pages 13쪽 −17%). A/B(샘플 1248 + 1342000): 1342000 31쪽 88.8→99.0, 17253153 3쪽 87.9→98.2, 70833 2쪽 95.4→99.0, 샘플 하락 0, 1342000 30쪽 −0.4·229쪽 −0.2. 회귀: split_row_stored_reset_valign 2건 — 가운데 정렬 검사는 수정 전 FAIL(0.00px), 한 번만 정렬 검사는 1×1 제외를 뺀 코드에서 FAIL(27.88 > 20.72px). 대조값은 같은 문서에서 그 칸만 Top 으로 바꾼 조판. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
) - 대표 쪽(Native review · fresh WASM overlay, 모두 pr_review_gate passed): 1480000 22쪽 99.5/99.7, 21761835 2쪽 94.4/95.1, 1613000 127쪽 90.8/91.0, 17253153 3쪽 98.2/98.5, 80168 5쪽 99.7/100.0, issue1853 16쪽 99.6/99.1 - 1342000 233쪽 PNG(69.8%)는 대표 기준 미달이라 뺐다. 1342000 은 쪽 수 416 ≠ PDF 415 로 게이트가 re_review_required 라 대표 쪽으로 쓰지 않는다(1–60쪽 TSV 만 첨부). - tsv/: 문서별 devel·브랜치 Native·브랜치 fresh WASM 전쪽 실루엣 TSV. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
21761835 2·3쪽: 칸 (20,0) rs=5(252px)가 쪽 끝 행 20 을 지나 행 24 까지 간다. 한/글 2020 PDF 는 행 20 첫 조각을 본문 끝까지(59px) 그리고, 3쪽 행 20 조각에 빈 꼬리 한 줄 + 위아래 패딩(17px)을 둔 뒤 걸침 총높이를 보존한다(59+17+56+51+25+43 ≈ 251px). rhwp 는 2쪽 끝에 7.8px 빈 띠를 남기고 3쪽 행 24 를 52.5px 로 그려 3쪽이 68% 였다. 쪽 끝 띠를 걸침 칸 몫으로 주는 경로는 이미 있다(edwardkim#7531, `unreserved_page_end_band`). 이 경로는 문단 유지 계약을 만족한 컷만 받는데, 행 20 의 진행 칸은 빈 문단 뒤 저장 vpos 0 재시작(한/글이 기록한 쪽 경계)에서 끊겨 빠졌다. - emit: 컷이 저장 쪽 재시작과 정확히 맞으면(`row_cut_ends_at_stored_page_reset`) 같은 경로로 들인다. 이 경우 띠는 `max(나뉜 행의 남는 몫, 걸침 칸의 남는 몫)` 까지만 준다 — 두 몫이 모두 없으면 한/글도 띠를 비워 둔다(70833 2쪽: 표가 973px 에서 끝남). 상자는 예약이 센 끝 컷 높이에 남은 방을 더한 값과 내용+몫 중 작은 쪽이고, 예약에는 그 차이만 더한다. - 그 끝 행 상자는 원본 프레임으로 수용한 것이라 `end_row_owns_stored_frame` 을 세워 배치가 끝 줄간격 접기로 다시 줄이지 않게 한다. - 다음 조각의 행 계획은 이 상자(`stored_reset_band_row_box`)에 남은 몫(남은 내용과 행 온전한 높이 − 앞 상자 중 큰 값)을 더해 시작 행의 물리 상자로 쓴다. 걸침의 끝 행은 그만큼 뺀 몫을 받는다. - 셀 끝 빈 문단이라도 저장 줄이 새 쪽 원점(vpos 0)에서 다시 시작하면 그 줄 상자를 소유한다. A/B(PR head 0971bb2 대비, 샘플 1,248 SVG + 1342000 전쪽): 21761835 2쪽 94.4→96.0·3쪽 68.1→91.5, 1342000 81쪽 81.6→85.8, 82쪽 −0.85·83쪽 −0.32, 그 밖 변화 없음. 회귀: rowbreak_short_row_whole_carry::crossing_rowspan_owns_the_page_end_band — 2쪽 행 20 조각이 내용보다 띠만큼 크고, 3쪽 행 20 은 빈 줄+패딩, 걸침 칸이 덮는 행 조각 합이 선언 252px(±1.5). issue_6981 예산 변형(표가 본문을 넘지 않음) 통과. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
) - 대표 쪽(Native review · fresh WASM overlay, 모두 pr_review_gate passed): 1480000 22쪽, 21761835 2·3쪽(3쪽 새로 추가 — 쪽 끝 띠 규칙으로 68.1→91.5), 1613000 127쪽, 17253153 3쪽, 80168 5쪽, issue1853 16쪽 - tsv/: 문서별 devel·브랜치 Native·브랜치 fresh WASM 전쪽 실루엣 TSV(70833 추가, 1342000 은 1–60쪽). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1342000 200쪽 끝 행 75 는 예산 컷으로 나뉘고, 그 행을 지나 202쪽 행 92 까지 이어지는 걸침 칸 (셀 316 rs=36 1845.3px, 셀 370 rs=26 1440.2px)이 있다. 한/글 2020 PDF 는 200쪽 표를 쪽 끝(716px) 까지 채운다. rhwp 는 10px 띠를 비우고, 걸침 총높이를 지키려 그 몫을 202쪽 끝 행 92 에 얹었다 (선언 97.1px → 107.8px). 그 11px 때문에 202쪽 행 94 가 나뉘고, 그 뒤 쪽마다 한 줄씩 밀려 210쪽 마지막 행 216 이 211쪽을 하나 더 만들었다(416 ≠ PDF 415). 앞 커밋은 저장 쪽 재시작 컷만 edwardkim#7531 쪽 끝 띠 경로에 들였다. 문단 유지 계약 밖의 모든 내용 컷으로 넓히되, 띠는 같은 상한(나뉜 행의 남는 몫과 걸침 칸의 남는 몫 중 큰 값)까지만 준다. - 1342000: 415쪽 = PDF. 201–212쪽 97.5–99.9%(이전 한 쪽씩 어긋남). 전쪽 A/B 195쪽 상승·20쪽 하락 (하락은 이전에 PDF 와 한 쪽 어긋난 채 비교되던 226–365쪽, 최대 −5.6), 새로 90% 이상 141쪽, 새로 90% 미만 0. - 샘플 1,248 SVG: fragment_ghost_vrules 17·18쪽만 변화(18쪽 +0.8). - 반례 회귀: rowbreak_short_row_whole_carry::crossing_rowspan_without_declared_slack_leaves_the_band_empty — 70833 2쪽은 몫이 없어 띠를 비운다(표 끝이 본문 끝보다 30px 넘게 위). 상한 없이 띠를 주면 FAIL(표 끝 1024.9px), 이 커밋에서 PASS. - 1342000 쪽 경계를 직접 잡는 회귀는 넣지 않았다: 관련 200쪽이 89.7%(행 63 이어지는 조각 3px, 이 변경과 별개)라 90% 선행 조건에 못 미친다. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 대표 쪽 9쪽(Native review · fresh WASM overlay, 모두 pr_review_gate passed): 1480000 22쪽, 21761835 2·3쪽, 1613000 127쪽, 17253153 3쪽, 80168 5쪽, issue1853 16쪽, 1342000 31·202쪽(쪽 수 415 = PDF 로 게이트 통과 — 새로 추가) - tsv/: 문서별 브랜치 Native·fresh WASM 전쪽 TSV 와 devel(515bd72) Native TSV. 1342000 devel 은 419쪽 ≠ PDF 415 라 전쪽 TSV 를 낼 수 없어 뺐다. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1613000 구역 2 첫 표(29×3)의 개체 높이는 행 0–26 선언 합과 정확히 같고 그 경계를 닫는 행만 두 줄로 자랐다. 한/글 2020 PDF 는 셀 높이를 지키며 26행을 185·186쪽에 가른다. 세 단의 사슬을 함께 고친다. - 측정: `declared_fragment_closes_on_a_grown_row` — 선언 높이가 행 경계에 떨어지고 앞 행은 선언과 같으며 경계 행만 자랐으면 전 행을 선언 높이에 맞춰 줄이지 않는다(edwardkim#7147 예외의 자란-행 경우). - 첫 조각 원점: `for_first_fragment` 가 호출자의 문단 시작을 받는다. 생성 경로마다 앵커가 저장 줄 윗변이거나 이미 문단 윗변이라, 문단 윗변 앵커에서 위 간격을 두 번 빼던 것을 고친다 (정본: 표 괘선 = 문단 윗변 + 세로 오프셋 + 바깥 위 여백; issue1880 1쪽 62→99). - 끝 조각 뒤 문단: 공통 helper `native_text_frame_terminal_successor_gap` 가 글자 있는 호스트의 문단 기준 자리차지 표도 다음 문단의 저장 줄 윗변(그 쪽 vpos)을 따른다(간격 ≤ 0 만). typeset 의 `commit_fragment` 가 흐름 끝을 호스트 아래 간격으로 다시 덮고 가시 배제 띠가 문단 시작을 밀던 것을 같은 값으로 맞춘다 — paint 와 typeset 이 같은 간격을 소비한다. - 저장 앵커 분할 판정: 흐름이 호스트 위 간격 앞에 있으면 간격을 더한 흐름으로도 저장 줄과 대조한다 (1613000 188쪽 pi=7). 다음 문단 vpos 가 되감기면 쓰지 않는다(hwpspec 표 40 반례: 통째 다음 쪽). 결과(Native, head 대비): 1613000 185–190쪽 29–50 → 99.7–99.96, 191쪽 40.8 → 77.8(남은 차이는 기존 pi=11 첫 조각 행 수), 59043 19쪽 45.5 → 90.8, table_scattered_header 51쪽 +0.96, issue1880(한컴 2024 PDF) 1쪽 62.3 → 99.4·4쪽 99.2 → 98.6. 쪽 수 불변(1613000 204 = PDF). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…DF (head 27bd84b) - 대표 쪽(Native review · fresh WASM overlay, pr_review_gate passed, 쪽 수 = PDF): 1613000 186쪽 99.32 / 188쪽 99.12(WASM), issue1880 1쪽 99.35. - tsv/d1613-*.tsv 갱신(204쪽, Native·WASM): 이전 head 대비 185–191쪽만 상승, 그 밖 쪽 변화 없음. - tsv/d1880-*.tsv 추가(10쪽). 기준 PDF 는 원본 HWPX 를 한컴 2024 MCP(Hancom PDF 1.3.0.550)로 변환한 pdf/issue1880/issue1880_takeplace_host_before-2024.pdf (입력 sha256 9807766f…, PDF 662735e5…). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
분할 루프가 새 쪽 첫머리에서 표를 통째로 받는 분기(cursor_row 0, 이어받기 아님)는 흐름을 행 높이 + 호스트 간격만 전진시켰다. 문단 기준 자리차지 표의 세로 오프셋과 바깥 여백이 빠져, 뒤 문단 흐름이 한/글 저장 위치보다 위에서 시작했다(1613000 구역 2 pi=9: 오프셋 86.5px, 뒤 문단 14.5px 위). 그 결과 pi=11 표 첫 조각이 한 행 더 들어가 192–193쪽이 밀렸다. 통째로 든 첫 조각도 끝 조각이므로, 끝 조각과 같은 공통 helper `text_host_terminal_successor_gap` 으로 흐름 끝을 정한다. 표 상자 아래(오프셋·바깥 위/아래 여백 포함)보다 위가 아닌 다음 문단의 저장 줄 윗변이 있을 때만 그 줄 − 위 간격을 흐름 끝으로 쓰고, 없으면 종전 전진을 유지한다. 한/글 2020 정본: 상자 아래 631.9px = pi=10 줄 vpos 47394. - 1613000 191쪽 77.8 → 99.9, 192쪽 41.3 → 99.97, 193쪽 57.1 → 99.85 (Native). 쪽 수 204 유지. - 샘플 1,252 문서·1342000 SVG A/B: 그 밖 쪽 변화 없음. - 회귀: whole_table_on_a_fresh_page_leaves_its_successor_on_the_stored_line (수정 전 FAIL: 192쪽이 6행으로 시작, 수정 후 PASS). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 대표 쪽(Native review · fresh WASM overlay, pr_review_gate passed Native·WASM, 쪽 수 204 = PDF): 191쪽 99.88(N) / 99.89(W), 192쪽 99.97(N) / 99.96(W). - tsv/d1613-*.tsv 갱신: 이전 증적 대비 191–193쪽만 상승(N 77.8/41.3/57.1 → 99.9/99.97/99.85, W 77.5/40.7/56.7 → 99.9/99.96/99.9), 그 밖 쪽 변화 없음. 90% 미만 N 15→12, W 14→11. - fresh WASM sha256 22d52bbaa7c149da… (pkg = rhwp-studio/public). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…000 126–128쪽 1) 셀 저장 줄의 새 원점 재시작(vpos 0)에서 자른 쪽 끝 행(389f966 규칙)은 남은 쪽 공간 전부를 행 상자로 잡았다. 한/글 2020 은 max(행 선언 높이, 자른 줄까지의 내용 높이)에서 표를 닫고 아래 본문을 비운다(1613000 126·127쪽 행 17·28 = 19.76·96.56px, 1480000 43쪽 행 118 = 선언 18.89px, myeonjeok 1쪽 행 29 = 선언 31.49px). 공통 helper `stored_restart_end_row_box` 를 scan 이 예약하고, paint 는 같은 컷·같은 상자면 끝 줄간격 접기로 다시 줄이지 않는다. 2) 끝 조각의 아래 캡션만 호스트 줄간격을 캡션 위에 더 넣었다. 통째 표처럼 표 아래 + 캡션 간격에 두고, 줄간격은 캡션 뒤 흐름 끝에만 남긴다(흐름·쪽 나눔 불변). 1613000 128쪽 [표 12] 간격 20.67 → 11.33px = 121쪽 통째 표. - 1613000 126쪽 93.2→99.7, 127쪽 91.0→99.6, 128쪽 91.6→99.1, 1480000 43쪽 97.4→99.99 (Native). - myeonjeok 1쪽(한/글 2020 MCP 변환본) 98.64→98.58: 표 아래 1081.3px ↔ PDF ≈1080.5 (종전 1078.3). - 샘플 1,252 문서·1342000 A/B: 그 밖 변화는 hwpspec 42쪽(+0.24, 쪽 수 181≠178 기존)·97쪽(±0), hwp-3.0-HWPML 38쪽(40.0→40.1, MCP 변환본) — 하락 없음. - 회귀: stored_restart_end_row_closes_at_its_declared_or_cut_content_box (수정 전 FAIL: 127쪽 행 28 135.99px), continued_table_bottom_caption_keeps_the_whole_table_gap (수정 전 FAIL: 20.67 vs 11.33px). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 대표 쪽(Native review · fresh WASM overlay, pr_review_gate passed Native·WASM, 쪽 수 = PDF): 127쪽 99.64(N) / 99.86(W), 128쪽 99.07(N) / 98.66(W). 127쪽 PNG 는 같은 경로의 이전 증적을 교체. - tsv/d1613-*.tsv: 126–128쪽만 상승(N 93.2/91.0/91.6 → 99.7/99.6/99.1, W 93.2/91.0/91.3 → 99.9/99.9/98.7). - tsv/d5941-*.tsv(1480000): Native 는 43쪽만 97.4 → 99.99. WASM TSV 는 `4594ff853` 무렵 WASM 으로 찍은 이전 파일을 이번 fresh WASM 으로 다시 찍었다 — 같은 head 의 Native 가 43쪽만 바뀌므로 그 밖 쪽의 ±0.1~4 차이는 WASM 빌드 차이다(169쪽 90.38 → 89.67 로 90 아래, Native 는 이전부터 89.6). - fresh WASM sha256 adfbd6ac994bce3b… (pkg = rhwp-studio/public). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
걸침 칸 안의 행이 선언 높이로는 남은 공간을 넘쳐도, 내용이 비끝 조각 상자 아래(본문 아래 − 바깥 아래 여백 − SINGLE_CELL_PAGE_FRAGMENT_BOTTOM_INSET_HU 100HU) 안에 다 들면 한/글은 그 행을 이 쪽 끝 행으로 두고 상자를 그 선에서 닫은 뒤 다음 쪽을 다음 행부터 잇는다. rhwp 는 선언 높이로 판정해 0.5px 차로 행을 넘겨 쪽마다 한 행씩 밀렸다. - 한/글 2020 정본: 1613000 195쪽 행 43(선언 20.87 → 19.04px), 200쪽 행 42(25.08 → 20.0px), 가로 쪽 표 아래 712.91px = 본문 아래 − 3.77 − 1.43(이미 1×1 조각에서 잰 100HU 와 같은 값). - 반례: 80168 행 23(내용 20.67, 남은 22.76 — 바깥 아래 여백 1.88 을 예산이 예약하지 않았으므로 닫는 선은 22.76 − 1.88 − 1.33 = 19.55) 은 한/글 2024 처럼 다음 쪽으로 넘어간다. 76076 행 14(내용 20.7 > 21.8 − 1.33) 도 넘어간다. 새 걸침 칸만 시작하고 이 행에서 닫히는 칸이 없는 행(1342000 구역 1 행 30)은 잴 내용이 없어 제외. - 기존 Stage 76 경로(빈 띠 ≥ 25px 를 다음 조각이 잇는 경우)는 그대로 둔다. HWP5 저장 조판만. - 1613000 195쪽 96.9→99.9, 196쪽 59.3→99.6, 197쪽 61.9→98.9, 200쪽 96.6→99.9, 201쪽 54.9→98.4, 202쪽 51.4→99.9, 198쪽 49.3→58.8(197쪽 가로 허용치가 빈 행 96 을 더 받는 기존 차이로 198쪽이 한 행 늦다). 1342000 335–345쪽 +2~+32, 334쪽 −0.31. 샘플 1,252 문서 그 밖 변화 없음. - 회귀: crossing_span_row_closes_at_the_fragment_bottom_line(수정 전 FAIL: 196쪽이 43행으로 시작), 반례 crossing_span_row_beyond_the_closing_line_moves_whole(80168, 수정 전후 PASS — 바깥 여백을 빼지 않은 중간 변형에서 행 23 이 122쪽에 남는 것을 A/B 로 확인). - 남은 차이: 195쪽 행 43 상자는 쪽 끝 띠가 바깥 아래 여백 선(714.36px)까지 채워 한/글(712.91)보다 1.3px 크다. 띠 끝에도 100HU 를 적용하면 1342000·21761835 의 걸침 몫 이월이 바뀌어 여러 쪽이 내려가 이번에 넣지 않았다. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 대표 쪽(Native review · fresh WASM overlay, pr_review_gate passed Native·WASM, 쪽 수 = PDF): 196쪽 99.63(N) / 99.55(W), 201쪽 98.43(N) / 98.42(W). - tsv/d1613-*.tsv: 195–202쪽만 바뀜(N 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). 90% 미만 N 12→8, W 11→7. - tsv/d1342-*.tsv: Native 는 334–345쪽만 바뀜(338–345 → 97~99.5, 334 −0.31). WASM TSV 는 이전 WASM 으로 찍은 파일을 이번 fresh WASM 으로 다시 찍었다 — 같은 head 의 Native 변화가 334–345쪽뿐이므로 그 밖 쪽 차이는 WASM 빌드 차이다. - fresh WASM sha256 416113845c06b6d1… (pkg = rhwp-studio/public). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
쪽 끝 띠(edwardkim#7531 경로)는 남은 공간을 바깥 아래 여백 선까지 채웠다. 한/글은 이어지는 표 조각을 본문 아래 − 바깥 아래 여백 − 100HU 에서 닫는다(앞 커밋과 같은 선). 통째로 받은 끝 행(내용 컷 없음)의 그리는 띠를 그 선까지로 줄인다. 닫는 선 아래 몫을 걸침 칸이 다음 쪽으로 넘기지는 않으므로, 이월 원장(page_end_band · 끝 행 상자 기록 · stored_reset_band_row_box · accepted_straddle_fragment_units)은 줄이기 전 띠를 그대로 소비한다. 내용 컷으로 끝난 행은 다음 조각이 같은 행을 잇는 상자라 바꾸지 않는다. 중간 변형과 반례: - 모든 띠를 줄이고 원장도 줄인 값을 쓰면 21761835 3쪽 −15.8, 1342000 80쪽 −24.6·224쪽 −21.7 (줄인 몫이 다음 쪽 걸침 행으로 넘어감). - 내용 컷 행까지 줄이면 1342000 202→203쪽 시작 줄이 한 줄 당겨짐(−10). - 원래 띠가 100HU 보다 작을 때 띠 경로를 건너뛰거나, 걸침 몫 계산에 줄인 상자를 넘기면 1342000 337쪽 consumed 가 1.33px 달라져 338–345쪽이 −26~−31. - 결과(샘플 1,252 문서 + 1342000, 앞 head 대비): 오른 쪽 95(+0.3~+1.8, table_scattered_header·80168·86712· 1613000 165쪽·76076 등), 내린 쪽 4(1342000 32·227·232·298쪽 −0.3~−0.8, 모두 기존 67~75%). 76076(hwpx 판 한/글 2024 PDF) 2·18·52·67쪽 +0.6. 1613000 195쪽 행 43 상자 714.36 → 713.03px(PDF 712.91). - 회귀: crossing_span_row_closes_at_the_fragment_bottom_line 의 상자 단언을 닫는 선(712.99px ±0.5)으로 강화 (이 변경 전 head 에서 FAIL). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 대표 쪽(Native review · fresh WASM overlay, pr_review_gate passed Native·WASM): 1613000 195쪽 99.93(N) — 행 43 상자가 닫는 선(713.03px, PDF 712.91)에서 끝남. - tsv/d1613-*.tsv: 144·146·157·162·165·166·168·173·181·183쪽 +0.2~+0.9, 200쪽 +0.06. 하락 없음. - tsv/d80168-native.tsv: 2·47·60·73·88·122쪽 +0.4~+0.6. d80168-wasm.tsv 는 이전 WASM 으로 찍은 파일을 이번 fresh WASM 으로 다시 찍었다(같은 head Native 변화는 위 6쪽뿐 — 그 밖 쪽 차이, 57쪽 91.07→89.84 포함은 WASM 빌드 차이). - tsv/d1342-*.tsv: Native 상승 다수(+0.3~+0.5), 하락 32·44·72·87·160·227·232·258·274·295–298·334쪽 −0.01~−0.76(모두 기존 90% 미만 또는 경계). - fresh WASM sha256 f1baab39d84eff2e… (pkg = rhwp-studio/public). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
쪽 끝 띠(edwardkim#7531 경로)가 걸침 칸 안의 끝 행을 «걸침 칸마다 선언 − 앞 행 − 끝 행 하한 − 뒤 행 내용» 의 최솟값이나, 통째 끝 행이면 남은 띠 전부로 늘렸다. 한/글 2020 은 끝 행의 이 쪽 상자를 max(컷까지 내용, 행 선언, 걸침 칸마다 «선언 − 이 칸의 앞 행 상자») 로 정하고 비끝 조각 닫는 선을 넘지 않는다(1613000 구역 1 139–183쪽 끝 행 47쪽 중 43쪽이 PDF 와 0.2px 안). - 같은 계산을 통째 끝 행(첫 분기)에도 적용, 그 상자는 원본 프레임으로 표시해 paint 가 끝 줄간격으로 다시 접지 않는다(첫 조각 포함). 앞 행 상자를 아는 걸침 칸이 없으면 종전처럼 남은 띠 전부. - 이어받은 시작 행은 측정 행 높이를 앞 행 상자로 센다. 나뉜 행 보존 몫은 측정이 아니라 선언 높이로 잰다 (측정 2줄 행 38.43 − 17.09 − 17.09 = 4.24 는 선언 여유가 아님). - 칸 안에 표·그림 등 개체가 있는 행은 종전 계산(1341000 29쪽: 안쪽 표 컷). - 내용 컷 행도 닫는 선까지 그린다. 그 줄인 몫은 걸침 칸이 다음 조각에서 세는 앞 행 상자(수용 행 기록)로만 넘기고(fragment_ghost_vrules 14·15쪽 병합 칸 (34,1) 앞+뒤 = 선언, 한/글 15쪽 첫 행 237.3px), 같은 행의 다음 부분 높이에는 넘기지 않는다(1342000 336·337쪽: 넘기면 컷이 한 단위 당겨짐). 결과(샘플 1,252 문서 + 1342000, 앞 head 대비): 오른 쪽 54(1613000 139–183쪽 +1~+9 → 99.3~99.9, 1341000 27·28쪽, hwpx_sample2 6쪽, fragment_ghost 15쪽 +4.8 등), 내린 쪽 9(1342000 81쪽 −2.9(기존 86.7, 끝 행 컷이 한/글보다 한 줄 적은 기존 차이), fragment_ghost 18쪽 −1.1·1342000 251쪽 −0.7(둘 다 표 아래·끝 행 윗변은 PDF 에 더 가까워짐), 21761835 hwpx 2쪽 −0.7(행 20 상자가 닫는 선보다 짧은 기존 차이에 1.33px 더), 그 밖 기존 90% 미만 쪽 −0.4~−0.6). 남은 1613000 끝 행 차이: 155·162쪽 +7.0, 166쪽 +5.6, 182쪽 −4.2. 회귀: crossing_span_end_row_takes_the_larger_span_share_up_to_the_closing_line (수정 전 FAIL). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 대표 쪽(Native review · fresh WASM overlay, pr_review_gate passed Native·WASM): 1613000 144쪽 99.75(N), 154쪽 — 걸침 칸 안 끝 행 상자가 한/글 2020 과 같은 자리에서 닫힘. - tsv/d1613-*.tsv: 139–183쪽 21쪽 상승(예: 144 92.9→99.7, 147 90.7→99.8, 165 92.7→99.9), 하락 없음. - tsv/d1342-*.tsv: 이 head 의 Native·fresh WASM 재측정. - fresh WASM sha256 27c0c547fd4e5ca4… (pkg = rhwp-studio/public). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
여러 쪽에 걸친 행의 이어받는 조각은 남은 쪽 공간을 채우는 용량 컷을 썼다. 저장 재시작 컷 helper 가 행의 첫 재시작만 찾았기 때문이다. 이제 시작 컷 뒤 셀마다 첫 새 원점(문단 안 vpos 0, 또는 앞 문단이 같은 셀 좌표로 이어진 문단 첫 줄 vpos 0)을 찾아, 그 컷이 용량 컷 안에 있으면 한/글이 기록한 쪽 경계로 쓴다. 1613000 표 pi=1133: 123쪽 [41,37]→[40,37], 124쪽 [51,72]→[51,70]. 표 아래 선이 한/글 2020 PDF 와 0.1px 안으로 맞는다. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
끝 조각 뒤 문단의 저장 줄 윗변이 표·캡션 상자 아래와 같으면, 그 문단 위 간격은 상자 안에 이미 들어 있다. 이 공통 helper(`text_host_terminal_successor_gap`)가 글자 있는 호스트만 받던 것을 빈 호스트로 넓힌다. 빈 호스트에서는 뒤 문단의 줄 상자(줄간격·아래 간격 포함)가 본문 안에 들 때만 증거로 받는다. 넘치는 문단은 빈 줄 감추기나 다음 쪽 이월로 이 쪽에 놓이지 않는다(1613000 190쪽 pi=8). NextLine 배치 계획은 paint 가 문단 끝을 `상자 아래 + 호스트 아래 간격`으로 다시 정한다. 그래서 증거가 있으면 `stored_successor_line_origin` 으로 기록해, paint 도 위 간격을 한 번만 쓰게 한다. - 1613000 125쪽: 본문 첫 줄 16px 위로 → PDF 와 일치. - issue1853 48·49쪽. - task2070 72–110쪽: 평균 42.2 → 99.77, 쪽수 316 → 315(한/글 2020 변환본과 같음). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 측정: edwardkim#4533 절대배치 캡이 호스트 위 저장 줄 간격을 이 표의 예약 공간으로 오인했다. 그 띠는 앞 문단 흐름 중첩 표(22×2)가 채운 것이다. 앞 문단 중첩 표 끝을 갭 시작점에 넣는 공통 helper `nested_host_gap_start` 를 측정·배치가 함께 쓴다(상자 920.5 → 1099.4px, 분할 시작). - 컷: 쪽에서 갈린 중첩 표는 개체 높이로 첫 조각만 저장한다. 개체 높이가 앞 k개 행 상자 합과 정수로 같고 병합 칸이 그 경계를 가로지르지 않으면 k행 유닛을 셀 내부 쪽 나눔으로 보존한다 (11×4 표 6006HU = 3042+1482+1482 → 컷 [32]). 중첩 표 행 경계는 고아 줄 되감기 대상에서 뺀다 (1341000 표 113 반례: 되감으면 저장 경계보다 한 행 일찍 자른다). - 원점: 1×1 첫 조각 계획이 흐름 원점(현재 높이 + 호스트 앞 간격 = 바깥 위 여백)을 이미 담으면 위 여백을 다시 더하지 않는다(+3.77px). - 뒤 문단: 끝 조각 뒤 문단의 저장 줄(흐름 끝 + 위 간격)이 상자 아래 이하에 있으면 그 줄이 문단을 닫는다. paint 가 상자 아래 + 호스트 아래 간격으로 덮어쓰지 않는다(+9px). - 가로: 칸 안 어울림 중첩 표가 문단 기준 왼쪽·오프셋 0 을 저장하면 저장 앵커를 쓴다. edwardkim#3308 좁은 표 가운데 규칙이 가운데로 옮기던 22×2 표(+10px)가 PDF 괘선과 같아진다. 1613000 58쪽 78.3→98.5, 59쪽 29.7→96.3(한/글 2020 PDF). A/B 에서 PDF 있는 다른 쪽 변화 없음. 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>
Contributor
Author
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.
변경 요약
한/글 2014(9.1.1.3933)로 저장한
1342000_edu_curriculum_map.hwp의 칸 문단에는 공백 최소값(condense) 흡수 없이 낱말 끝 글자만 다음 줄로 보낸 저장 줄이 있다. 한/글 2020 Print 는 그 꼬리를 앞 줄에 붙인다(공백을 condense% 까지 줄여 이미 시작한 낱말을 더 담는 #7418 규칙).…순서에 맞게 시연하/기…관한 찬반 토/론rhwp 는 저장 줄을 그대로 써 행이 한 줄씩 높았고(151쪽 r=56 57.1px, 정본 44px·선언 43.5px), 편차가 쌓여 #7965 리베이스 head 에서 문서가 416쪽(정본 415쪽) 이었다.
저장 줄 판정 (
stored_cell_reflow.inc.rsfresh_rows_absorb_stored_tail,reflow_helpers.inc.rsstored_last_row_is_condensable_word_tail) — 다음을 모두 만족할 때만 저장 줄을 버린다.StoredGeometryPolicy::stored_rows_before_hancom_2020)판정과 실제 줄은 같은 프레임 결과다(폭 근사를 따로 두지 않는다).
저장 제품 세대 (
DocumentCore로드 시 1회,SourceProvenance::stored_rows_before_hancom_2020) — 컨테이너가 기록한 마지막 저장만 본다: HWP5 는 요약 정보, HWPX 는version.xml. 원본 HWP5 요약을 실은 HWPX(36388711…청년오피스.hwpx: 요약 8.0.0.466, 저장 11.0.0.8227)를 요약으로 판정하면 오판한다. 읽을 수 없으면 판정하지 않는다.측정기 (
height_measurer.rs) —#6135저장 extent 증인(ladder_exceeds_declared_text_cell)이 프레임이 다시 끊은 문단에도 원래 저장 사다리를 써 행이 옛 줄 수 높이(57.1px)로 남았다. 줄 수가 달라진 문단이 있으면 그 증인을 쓰지 않는다. 이 수정만으로는samples/1,252건 SVG 변화 0.관련 이슈
Refs #7702 · #7965 — 부분 개선. 1342000 의 이 갈래(한/글 2014 저장 줄의 낱말 꼬리)를 고치지만 아래 「남은 차이」 189쪽과 #7702 의 다른 갈래가 남아 이슈를 닫지 않는다. 원인 분석: #7702 (comment)
테스트
065125a94(code) / 정책 비교 PR base SHAefc52afb7gate(CLAUDE.md lint 묶음 순차):--prepare→cargo fmt --all -- --check→ native Clippy → WASM32-p rhwp --libClippy → workspace build → workspace all-targets Clippy → manifest--check --base-ref efc52afb7LINT_OKcargo nextest run --cargo-profile release-test --tests: 11060 run, 11060 passed, 45 skippednode scripts/rust-unit-test-tiers.mjs --check --base-ref efc52afb7: 통과CARGO_TARGET_DIR=target/pr-review scripts/wasm-pack-locked.sh --target web --out-dir pkg,rhwp_bg.wasmSHA-25674f59d5d35b3837219aea3afc3cd32eee452663d9dd6072b56449c5235c0c07c(pkg/=rhwp-studio/public/)새 회귀
tests/cases/issue_7702_condense_word_tail.rs쪽 번호를 고정하지 않고 글자로 쪽을 찾으며, 글줄은 render tree 의 같은 윗변 글자 조각을 이어 판정한다(절대 px 없음). 칸 높이는 모델의 선언 높이와 비교한다.
f8fa0f02a)pre_2020_stored_word_tail_joins_the_condensed_line(151·154쪽 꼬리가 앞 줄에)joined_tail_row_keeps_its_declared_height(151쪽 r=56 칸 ≤ 선언 43.5px+1)fresh_break_that_moves_an_earlier_boundary_keeps_the_stored_rows(반례: 114쪽…정보/가,…있/다.)stored_tail_without_condense_keeps_the_stored_break(반례: 25쪽 condense 없는…포함 논의 필/요)hancom_2020_saved_word_tail_keeps_the_stored_break(반례:21_언어_기출_편집가능본.hwp11.0.0.2129 1쪽…확인하/십시오.)stored_row_generation_comes_from_the_container_last_save(1342000 → 이전 세대, 21_언어·36388711 HWPX → 아님)joined_tail_row_keeps_its_declared_height의 높이 단언을 따로 실패시키는 증거는 실험 바이너리다: 줄 판정만 켜고 측정기 수정을 끄면 151쪽 r=56 이DIAG_TRUST text=36.0 stored=53.3→ 행 57.1px(=저장 사다리 3줄)로 남았다.기존
rowbreak_short_row_whole_carry::rows_inside_a_crossing_rowspan_still_split_after_one_line(1342000 165·166쪽 분할)은 #7965 리베이스 head 에서 실패했고 이 커밋에서 통과한다(수정 전 FAIL 확인).검사 대상 쪽의 정본 대조(Native / fresh WASM): 1342000 25쪽 95.3 / 95.1, 114쪽 100.0 / 99.9, 151쪽 99.9 / 99.9, 154쪽 99.8 / 99.7, 21_언어 1쪽(문서 최저 95.1 / 94.9).
363887111쪽 반례는 정본 대조가 86.2%(수정 전후 같음)로 90% 선행 조건에 못 미쳐 렌더 검사로 넣지 않고, 메타데이터 판정 검사로만 잠갔다.065125a94= 검증 commit (증적 커밋da062b3aa은 PNG·TSV 만 추가)mydocs/pr/assets/issue7445/education-curriculum-map/current-source-hancom2020-print.pdf(한/글 2020 Print, 415쪽),pdf/21_언어_기출_편집가능본-hwp-2020.pdftests/cases/원본만, generated·manifest 미포함#[cfg(test)]변경 없음(tiers 검사는 실행)조판 변경 근거
…찬반 토론한 줄. 같은 문서에서 이 모양(condense 有)이고 PDF 에서 줄 소속이 하나로 정해지는 문단 28개는 모두 한/글이 꼬리를 붙였다. 같은 모양으로 한/글이 저장 줄을 따른 것은 189쪽 1개(「남은 차이」), 114쪽 1개(앞 경계 제약으로 제외)recompose_stored_lines_in_frame_with_known_square_band(측정HeightMeasurer·typeset·paint 공통 프레임 소유자)와 읽기 전용probe_stored_row_disposition두 곳. 판정 =resolve_stored_line_segs_in_frame(stale=true)를 프레임 복제에 돌린 결과이며, 채택 시 같은Reflowed경로가 줄을 발행한다. 높이는HeightMeasurer::measure_table_impl가 그 줄로text_height를 잰다stored_extent(#6135)가 원래 저장 사다리를 써 행 57.1px, paint 는 새 줄 1개 — 행 안에 빈 띠. 수정 후 둘 다 새 줄(행 = 선언 43.5px, 정본 44px)Native/fresh WASM 시각 증적
검증 환경: code head
065125a94, Native--features native-skiaPNG, fresh WASM 위 SHA,scripts/visual_sweep.py --dpi 96 --compat 2022,pypdfium2==5.13.0,RHWP_FONT_PATH= 한컴·Windows·KoPub 글꼴 디렉터리(모두 존재). 판정값은 2px 이웃 관용 내용 실루엣.1342000 · 기준 PDF p151 ↔ rhwp p151 — 꼬리 흡수(
…시연하기)Native 99.94 / WASM 99.9(수정 전 Native 78.91). r=56 둘째 문단이 한 줄, 행 아래 괘선과 뒤 행 경계가 PDF 와 겹친다. 수정 전에는
기가 다음 줄에 남고 그 아래 모든 행이 한 줄씩 내려갔다.1342000 · 기준 PDF p154 ↔ rhwp p154 — 꼬리 흡수(
…찬반 토론)Native 99.8 / WASM 99.87(수정 전 77.1).
기술·가정행- 청소년기에 … 찬반 토론이 한 줄.1342000 · 기준 PDF p114 ↔ rhwp p114 — 반례(저장 줄 유지)
Native 100.0 / WASM 99.97.
[12융과04-02]칸이 PDF 처럼 저장 4줄(…정보/가 다른 … 수 있/다.) 그대로다.전쪽 TSV
f8fa0f02a1–155쪽템플릿 기준(한 쪽이라도 90% 미만이면 재검토)에 미달한다. 1342000 의 90% 미만 쪽은 이 변경 전부터 있던 쪽이다(#7743 추적). 수정 전 head 는 416쪽이라 156쪽 이후는 PDF 와 한 쪽 어긋나 쪽 단위 전후 비교가 불가하다. 비교 가능한 1–155쪽: 90% 미만 62 → 55, 새로 90% 아래로 내린 쪽 0, 새로 90% 이상 7쪽. 0.5 넘게 바뀐 쪽은 124·125(77.6→99.7·99.3), 126(+8.2), 141–145(+1.4~+6.9), 151–155(+21~+25) 상승과 128(−0.8)·142(−1.3) 하락 — 142쪽은
…이유 알기가 PDF 처럼 한 줄이 되며 위아래 행이 옮겨 간 값이고, 128쪽은 기존 76.9% 쪽. 성취기준 코드의 쪽 소속이 PDF 와 같은 비율 21.2% → 97.7%.A/B:
samples/1,252건 SVG md5 를f8fa0f02a대비로 비교해 바뀐 쪽 0(1342000 은mydocs/pr/assets에 있어 따로 대조).남은 차이
[9체01-04]…건강한 생활 습관을 실천한/다.— rhwp 는 붙이고 한/글 2020 은 두 줄. 꽉 찬 줄 경계에서 rhwp condense 판정이 한/글보다 약 2px 너그럽다(114쪽 앞 경계와 같은 계열). 이 쪽은 66.6%(기존 저점, 전후 쪽 어긋남으로 수정 전 비교 불가).samples/의 다른 한/글 2020 이전 저장 문서는 이 모양에 해당하는 문단이 없어 바뀌지 않았다.🤖 Generated with Claude Code