Skip to content

fix(layout): 같은 문단의 위아래 개체는 문단 흐름 시작을 차지할 때만 글자처럼 그림을 아래로 보낸다 (#8168) - #8206

Closed
planet6897 wants to merge 4 commits into
edwardkim:develfrom
planet6897:fix/8168-topandbottom-sibling-tac-picture
Closed

planet6897 wants to merge 4 commits into
edwardkim:develfrom
planet6897:fix/8168-topandbottom-sibling-tac-picture

Conversation

@planet6897

@planet6897 planet6897 commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Closes #8168

요약

문단에 글자처럼 취급 그림과 떠 있는 위아래(TopAndBottom) 개체가 함께 있으면, rhwp 는 그림 y 에 그 개체의 높이와 바깥 여백을 무조건 더했다(#1151 보정, calc_sibling_topandbottom_reserved_hu). 그래서 종이 기준으로 줄 아래에 놓인 글상자가 있으면, 줄의 글자는 제자리인데 그림만 글상자 자리로 약 83px 내려가 글상자와 겹쳤다.

#1151 보정의 전제는 그 표본(samples/tac-verify/scenario-a-after.hwp)처럼 개체가 문단 기준·세로 오프셋 0 으로 이 문단의 흐름 시작을 차지하는 것이다. 이 PR 은 그 전제를 조건으로 쓴다.

변경

src/renderer/layout/paragraph_layout.rs

  • calc_sibling_topandbottom_reserved_hu(controls, line_top_hu) 는 문단 기준(VertRelTo::Para) 개체 중 띠 위끝(세로 오프셋)이 그림 줄 위끝 이하인 것만 더한다. 종이·쪽 기준 개체와 줄보다 아래에서 시작하는 개체는 그림을 밀지 않는다.
  • 그림 줄 위끝은 para_line_top_hu 가 문단 첫 줄 기준 저장 vpos 차로 구한다.
  • 세 소비 지점이 같은 판정을 쓴다: 본문 줄 그림(emit_line_runs), 빈 runs 줄 그림(layout_empty_runs_line), 문단 시작 그림 항목(tac_picture_item.inc.rs, 줄 위끝 0).

독립 근거

  • 한/글 2024(13.0.0.564) Print: 이슈 재현과 같은 편집(「앞 글 뒤 글」 둘째 글자 자리에 글자처럼 그림, 같은 문단에 종이 기준 세로 15000HU 위아래 글상자)을 저장한 samples/issue8168/tac_picture_with_topandbottom_textbox.hwpx 를 Print 하면 「앞 [그림] 글 뒤 글」이 한 줄이고 글상자는 그 줄 아래 지정 위치에 있다.
  • 반례: rhwp-studio: 표 셀 안 이미지 삽입이 표 밖 본문 문단에 들어가는 결함 (insert_picture_native cellPath 미지원) #1151 의 한/글 산출물 samples/tac-verify/scenario-a-after.hwp(문단 기준·오프셋 0 의 위아래 표 + 글자처럼 그림)는 한/글 2024 Print 에서도 그림이 표 아래에 있다 — 종전 동작을 유지한다.

회귀 테스트

tests/cases/issue_8168_topandbottom_sibling_tac_picture.rs — 관계로 검사한다(절대 px 고정 없음).

검사 수정 전 수정 후
paper_relative_topandbottom_float_keeps_tac_picture_in_its_line — 그림이 host 줄 안에 있고 글상자 위끝보다 위 FAIL (그림 215.4–274.7 · 줄 132.3–191.6) PASS
para_relative_topandbottom_table_at_para_start_still_puts_picture_below — #1151 반례, 그림이 표 아래 PASS PASS

단위 검사 topandbottom_table_reserved_single 에 종이 기준 개체와 줄 아래에서 시작하는 문단 기준 개체의 반례 assertion 을 더했다(모듈 검사 수는 그대로).

Visual Sweep (base = devel 9418ed0c7, head = 이 PR)

판정값 = 2px 실루엣 raw(TSV 4열), 한/글 2024 Print, --compat 2024, 전 쪽.

입력 · 기준 PDF 쪽수 base Native / WASM head Native / WASM
samples/issue8168/tac_picture_with_topandbottom_textbox.hwpx · pdf/issue8168/tac_picture_with_topandbottom_textbox-2024.pdf 1 = 1 18.70 / 18.97 94.96 / 94.31
samples/tac-verify/scenario-a-after.hwp · pdf/issue8168/scenario-a-after-2024.pdf (반례) 1 = 1 99.93 / 99.93 99.93 / 99.93
  • samples 1,317건 SVG A/B(base vs head): 바뀐 문서 0.
  • 직접 판독: head 는 그림이 「앞」과 「글 뒤 글」 사이 한 줄에 있고 글상자와 겹치지 않는다. 남은 약 5% 는 글상자 왼쪽 변이 PDF 보다 약 2px 어긋난 것으로 base 에도 같은 차이다.

수정 전 / 수정 후 — Native

native base review
native head review
native head overlay

수정 후 — fresh WASM

wasm head review
wasm head overlay

수정 전 WASM 과 overlay 는 mydocs/report/issue8168_topandbottom_tac_picture/ 에 있다.

게이트 (head c6468b0d3, base 9418ed0c7)

  • rustfmt 차이 0 · Clippy native / wasm32 / workspace all-targets / native-skia all-targets 경고 0(매 단계 소스 touch 후 실제 재컴파일) · manifest --check · unit tier --check 통과.
  • nextest(--features native-skia, release-test) 11,761건 중 11,757 통과 — 실패 4건은 devel 에서도 같은 이 host 환경 문제다(issue_7966_pdf_close_stroke 3건은 Windows 체크아웃 CRLF, fix(checkout): Windows CRLF·심볼릭 링크 체크아웃에서만 실패하던 로컬 검사를 고친다 #8193 · custom_font_paths_select_style_within_the_first_family_owner 는 글꼴 설치). 이 전체 실행은 단위 검사 통합(c6468b0d3) 직전 head 28ae3d4b0 에서 했고, 통합 뒤에는 관련 검사 45건·Clippy all-targets·unit tier 를 다시 통과했다.

최신 devel rebase (2026-10-26, 4e690c930)

  • base 9418ed0c7 → 4e690c930(feat: 기여 PR 10건 통합과 조판·Studio 회귀 보정 #8228 통합 포함)으로 충돌 없이 rebase했다. 코드 head 6e59ef78f(이전 c6468b0d3), 증적·입력 커밋 dd3ad0b29.
  • 새로 들어온 devel 변경 중 이 PR 파일(paragraph_layout.rs)과 겹치는 것은 줄 범위 소유 정리(ParagraphLineRange)와 줄 앞 소비 오프셋이다. 위아래 개체 예약 판정(calc_sibling_topandbottom_reserved_hu)·세 소비 지점과 겹치지 않는다.
  • 빌드: base·head 모두 --profile release-test --features native-skia Native, fresh WASM. head rhwp_bg.wasm sha256 5b251e31677f….
입력 · 기준 PDF 쪽수 base Native / WASM head Native / WASM
samples/issue8168/tac_picture_with_topandbottom_textbox.hwpx 1 = 1 20.58 / 20.48 95.16 / 94.46
samples/tac-verify/scenario-a-after.hwp (반례) 1 = 1 99.93 / 99.93 99.93 / 99.93
  • 전쪽 TSV 원본: tac_picture_with_topandbottom_textbox: base/native · base/wasm · head/native · head/wasm · scenario-a-after: base/native · base/wasm · head/native · head/wasm
  • samples 1,334건 SVG A/B(devel 4e690c930 vs head): 바뀐 문서는 samples/issue8168/ 의 입력뿐이고, 그 밖의 문서 변화 0, 쪽수 변화 0. 이 실행에서 합성 입력 3건은 HWPX 판이었다. 커밋한 HWP 판은 따로 비교했다 — 쪽 기준 입력만 바뀌고 문단 기준 두 입력은 SVG 바이트가 같다. 암호 문서 3건은 양쪽 모두 열지 않는다(exit 2).
  • 직접 판독(위 대표 이미지, rebase 뒤 다시 만든 PNG): 그림이 「앞」과 「글 뒤 글」 사이 한 줄에 있고, 글상자는 그 줄 아래, 「다음 문단」은 글상자 아래에 있다. 남은 차이는 글상자 좌우 변 약 2px 로 base 에도 같다.
  • 게이트(head 6e59ef78f, base 4e690c930): --prepare · rustfmt --check · Clippy native · wasm32 lib · workspace build · workspace all-targets · native-skia all-targets · manifest --check · unit tier --check 통과.
  • cargo test --profile release-test --features native-skia: 11,691건 통과, 실패 2건. 두 건은 devel 4e690c930 에서도 같은 메시지로 실패하는 이 host 의 native-skia 화소 검사다(issue_7445_biotoxin_source_ownership::gray_grid_keeps_its_print_coverage_cell_owners_and_pdf_origin, native_skia_public_paint_contract::renders_complete_svg_image_larger_than_a_raw_fragment).

미검증 — 합성 입력 추가, 한/글 출력 대기

두 경우의 합성 입력을 추가했다. 한/글 2024 Print PDF 를 받아 대조할 때까지 미검증으로 둔다.

입력 (samples/issue8168/) 경우 devel 4e690c930 head
tac_picture_with_page_relative_topandbottom_textbox.hwp 쪽 기준(VertRelTo::Page) 세로 15000HU 위아래 글상자 그림을 줄 밖으로 내려 「다음 문단」 아래(y215)에 그리고, 줄 안에는 그림 폭만큼 빈 칸이 남는다 그림이 줄 안(y132)에 있고 줄이 그림 높이로 커진다
multiline_tac_picture_para_topandbottom_offset_above.hwp 세 줄 문단 둘째 줄 그림 + 문단 기준 세로 300HU 위아래 글상자 그림 y154, 글상자 y140–216 이 그림과 첫 줄 글자를 덮는다 devel 과 같다
multiline_tac_picture_para_topandbottom_offset_below.hwp 위와 같고 글상자 세로 9000HU(비교용) 그림 둘째 줄 안, 글상자가 「다음 문단」을 덮는다 devel 과 같다

🤖 Generated with Claude Code

@edwardkim edwardkim added bug Something isn't working layout 문서 레이아웃/페이지네이션: 표·그림 배치, float/anchor, 줄·행 높이, 겹침·클리핑 rendering SVG/Canvas/PDF 등 렌더 출력과 시각 표시: 그리기, 표시 누락, bbox, paint 정합성 rust Pull requests that update rust code test regression test labels Oct 25, 2026 — with ChatGPT Codex Connector
@edwardkim edwardkim added this to the v1.0.0 milestone Oct 25, 2026 — with ChatGPT Codex Connector
@planet6897
planet6897 force-pushed the fix/8168-topandbottom-sibling-tac-picture branch from c6468b0 to dd3ad0b Compare October 26, 2026 08:18
@planet6897

Copy link
Copy Markdown
Contributor Author

후속 PR #8283(#8271)이 이 PR 의 코드 커밋 두 개를 선행으로 포함합니다. 이 PR 이 통합되면 #8283 을 rebase 해 그 커밋을 뺍니다.

@jangster77
jangster77 self-requested a review October 26, 2026 14:19
planet6897 and others added 4 commits October 27, 2026 20:54
…kim#8168)

문단에 글자처럼 취급 그림과 떠 있는 위아래(TopAndBottom) 개체가 함께 있으면 그림 y 에 그
개체의 높이(+바깥 여백)를 무조건 더했다(edwardkim#1151 보정, `calc_sibling_topandbottom_reserved_hu`).
그 보정의 전제는 edwardkim#1151 표본 `samples/tac-verify/scenario-a-after.hwp` 처럼 개체가 문단 기준·
세로 오프셋 0 으로 이 문단의 흐름 시작을 차지하는 것이다. 종이 기준으로 줄 아래에 놓인 글상자에도
적용돼 줄의 글자는 제자리인데 그림만 글상자 자리(+83px)로 내려가 겹쳤다.

- 예약은 문단 기준(`VertRelTo::Para`) 개체 중 띠 위끝(세로 오프셋)이 그림 줄 위끝(문단 첫 줄
  기준 저장 vpos 차) 이하인 것만 더한다. 세 소비 지점(본문 줄 그림·빈 runs 줄 그림·문단 시작
  그림 항목)이 같은 판정을 쓴다.
- 한/글 2024(13.0.0.564) Print: 「앞 [그림] 글 뒤 글」이 한 줄이고 글상자는 그 줄 아래 지정
  위치에 있다. edwardkim#1151 표본은 그림이 표 아래(종전과 같음).
- 회귀: `issue_8168_topandbottom_sibling_tac_picture` — 종이 기준 위아래 글상자는 그림을 host 줄
  안에 두고 겹치지 않는다(수정 전 실패: 그림 215.4–274.7 · 줄 132.3–191.6), edwardkim#1151 반례는
  그림이 표 아래(전후 통과). 단위 검사에 종이 기준·줄 아래 개체 반례 추가.
- Visual Sweep raw: 표본(`samples/issue8168/`, 한/글 2024 Print) 18.70 → 94.96(Native),
  18.97 → 94.31(WASM). edwardkim#1151 표본 99.93 전후 동일. samples 1,317건 A/B 바뀐 문서 0.
단위 검사 수 기준선(issue_1151_v3_helper_tests 7개)을 늘리지 않도록, 종이 기준
개체와 줄 아래에서 시작하는 문단 기준 개체의 반례를 같은 표를 쓰는
topandbottom_table_reserved_single 의 assertion 으로 옮긴다.
- 대표 PNG(글자처럼 그림 + 종이 기준 위아래 글상자)를 rebase head 와 devel 4e690c9 에서 다시 만들었다.
- 전쪽 TSV: tac_picture_with_topandbottom_textbox·scenario-a-after 의 base/head × native/wasm.
- 미검증 두 경우의 합성 입력(HWP)과 생성기를 더한다. 쪽 기준 위아래 글상자, 세 줄 문단 둘째 줄
  그림 + 문단 기준 위아래 글상자(세로 300HU / 비교용 9000HU). 한/글 2024 Print PDF 는 아직 없다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@planet6897
planet6897 force-pushed the fix/8168-topandbottom-sibling-tac-picture branch from dd3ad0b to da54116 Compare October 27, 2026 13:05
@planet6897

Copy link
Copy Markdown
Contributor Author

최신 devel 로 rebase

  • 새 head da54116c8 (이전 dd3ad0b29), 기준 devel af6bb05b2
  • 충돌 해소: 충돌 없음.
  • 확인: --prepare → cargo fmt --all -- --check → native clippy → wasm32 clippy → workspace build → workspace all-targets clippy → manifest --check → unit-test-tiers --check 통과
  • 미실행(사용자 지시): 전체 integration nextest, 대표 쪽 Visual Sweep 재측정. 본문의 시험·시각 증적은 이전 head 기준이다.

@planet6897

Copy link
Copy Markdown
Contributor Author

#8348(통합 c76d87cfda)로 devel 에 반영되어 닫습니다.

devel f291d772a1 에서 확인:

  • 이 PR 이 추가·변경한 코드 줄이 devel 에 모두 있습니다(통합 때 보정된 곳은 같은 동작의 다른 형태로 반영).
  • 이 PR 의 회귀 검사를 포함한 통합 PR 회귀 검사 90건이 devel 에서 모두 통과했습니다.

관련 이슈 #8168 는 devel 재측정 뒤 따로 정리합니다.

@jangster77

Copy link
Copy Markdown
Collaborator

기여해 주셔서 감사합니다. 제안해 주신 변경을 체리픽하고 필요한 통합 보정을 거쳐 통합 PR #8348에서 devel에 반영했습니다. 통합 merge는 c76d87cfda742a4624e0a588aa09eb9d89b87d49입니다.

  • 개별 리뷰와 근거에 원 기여, 보정 및 남은 차이를 구분해 기록했습니다.
  • 통합 head의 CI와 CodeQL 등 필수 검사를 확인했습니다. 관련 로컬 회귀 110개와 후속 24개도 통과했으며, 최종 head의 전체 Rust 회귀를 로컬에서 재실행했다고 주장하지 않습니다.
  • scenario-a-after 1쪽은 Native·fresh WASM 각 99.92661%였으며 그림과 표의 경계를 독립 Print 좌표와 비교했습니다.

문서 비교는 Visual Sweep 가이드를 따릅니다. 위 수치는 기준 PDF와 출력의 내용 픽셀 일치율 보조값으로, 사람의 판정을 대신하지 않습니다. 후보 수와 별도 pixel match가 기록되지 않은 경우 추정하지 않았습니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working layout 문서 레이아웃/페이지네이션: 표·그림 배치, float/anchor, 줄·행 높이, 겹침·클리핑 rendering SVG/Canvas/PDF 등 렌더 출력과 시각 표시: 그리기, 표시 누락, bbox, paint 정합성 rust Pull requests that update rust code test regression test

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants