Skip to content

Task #975: Fix PageBackground fill mode and RealPic watermark tone#1019

Merged
edwardkim merged 7 commits into
edwardkim:develfrom
postmelee:task-975-page-background-fill-mode
May 28, 2026
Merged

Task #975: Fix PageBackground fill mode and RealPic watermark tone#1019
edwardkim merged 7 commits into
edwardkim:develfrom
postmelee:task-975-page-background-fill-mode

Conversation

@postmelee

@postmelee postmelee commented May 19, 2026

Copy link
Copy Markdown
Collaborator

관련 이슈

Refs #975
Related #976

요약

이 PR은 #975의 원래 문제였던 PageBackground/BorderFill 이미지가 fill mode를 무시하고 페이지 전체로 stretch 렌더링되는 문제를 수정합니다.

작업 중 추가로 확인된 effect=RealPic, brightness=-50, contrast=70 색상 워터마크 preset도 함께 정합했습니다. 이 preset은 #976 계열의 effect != RealPic JPEG grayscale/baked watermark와 다르게, 한컴 뷰어에서 색상을 보존한 밝은 워터마크 톤으로 보입니다.

따라서 변경 범위는 아래 두 축으로 분리됩니다.

  1. PageBackground/BorderFill 이미지의 ImageFillMode 정합
  2. RealPic 색상 워터마크 preset의 한컴 뷰어 톤 정합

왜 변경했나

#975 재현 샘플의 BorderFill image는 dump 기준으로 mode=Center를 보존하고 있었습니다.

border_fill[2] fill_type=Image image(bin_id=3, mode=Center, brightness=-50, contrast=70, effect=0)

하지만 SVG/Web Canvas의 PageBackground 경로가 ImageFillMode를 사용하지 않고 항상 bbox 전체 렌더링을 해서, 원본 512x512 워터마크가 페이지 전체로 늘어났습니다.

또한 effect=RealPic, brightness=-50, contrast=70인 색상 이미지 워터마크는 한컴 뷰어가 단순 brightness/contrast CSS filter나 #976 JPEG baked watermark와 다른 톤으로 처리합니다. 이 PR은 해당 preset을 별도 감지해 SVG와 Web Canvas가 같은 픽셀 변환 결과를 쓰도록 맞춥니다.

변경 내용

1. PageBackground 이미지 fill mode 정합

  • PageBackgroundImagebrightness, contrast, effect를 보존하도록 확장
  • style resolver / layout / render tree 경로에서 BorderFill ImageFill의 tone 속성을 누락 없이 전달
  • SVG PageBackground 렌더링을 render_page_background_image() helper로 분리
  • PageBackground 이미지도 일반 ImageNode와 같은 fill mode 의미를 사용
    • FitToSize | None: 대상 bbox 전체 렌더링
    • Center 등 위치 모드: 원본 이미지 픽셀 크기 기준 배치
    • tile 계열: 기존 tiled image helper 재사용
  • Web Canvas PageBackground 경로도 draw_image_with_fill_mode()를 재사용
  • PageBackground non-RealPic watermark opacity 조건을 ImageNode와 같은 tone 속성 기반으로 정합

2. RealPic 색상 워터마크 preset 정합

  • effect=RealPic, brightness=-50, contrast=70 조합을 색상 워터마크 tone preset으로 판정
  • 기존 brightness/contrast 필터 및 #976의 non-RealPic JPEG baked watermark 경로와 분리
  • SVG와 Web Canvas가 같은 image_resolver 기반 PNG bake helper를 사용하도록 정리
  • 브라우저별 SVG/CSS filter 정밀도 차이를 줄이기 위해 decode 가능한 이미지는 tone 변환을 PNG 픽셀에 직접 bake
  • PageBackground와 셀/도형 배경 ImageFill을 분리해 opacity/tone을 적용
    • PageBackground RealPic watermark: page용 opacity/tone
    • 셀/도형 배경 RealPic watermark: fill용 opacity/tone
  • Web Canvas 셀/도형 배경 ImageFill 경로도 fill용 RealPic helper/opacity를 직접 사용하도록 정합
  • bake 실패 시에만 기존 SVG/CSS filter fallback 사용

현재 적용 값은 파일명 분기가 아니라 동일 RealPic 색상 워터마크 preset 전체에 대한 공통값입니다.

REAL_PICTURE_WATERMARK_PAGE_OPACITY = 0.26
REAL_PICTURE_WATERMARK_FILL_OPACITY = 0.15

saturation = 0.91646104
contrast   = 0.93125103
brightness = 1.80

matrix = [
  [0.9897169325,  0.1297721480, -0.0666075849],
  [0.0236280401,  1.0778421442, -0.0471323620],
  [0.0002888270, -0.0075596780,  1.0728328592],
]
bias = [-0.0504989415, -0.0462952328, -0.0573305296]

chroma_gain = 3.0
white_blend = 0.0

fill_chroma_gain = 0.42
fill_white_blend = 0.16

LEGACY_IMAGE_WATERMARK_OPACITY = 0.17

3. SVG 경로 정합

메인테이너 피드백에 맞춰 SVG 경로도 같이 정리했습니다.

  • RealPic tone bake helper를 src/renderer/image_resolver.rs로 이동/통합
  • SVG PageBackground도 RealPic tone-baked PNG를 사용
  • SVG 셀/도형 배경 ImageFill도 RealPic fill tone-baked PNG를 사용
  • SVG의 non-RealPic JPEG watermark baked path와 RealPic color watermark path를 분리
  • PCX white area transparency 처리를 image resolver 쪽으로 통합해 Canvas/SVG 차이를 줄임
  • SVG PageBackground helper도 PCX → PNG 변환을 사용해 흰색 투명 처리를 일관 적용
  • SVG PageBackground non-RealPic watermark도 brightness/contrast 기반 legacy opacity를 적용
  • SVG 단위 테스트에 PageBackground fill mode, RealPic page watermark, RealPic fill watermark 케이스 추가

메인테이너 피드백 반영 상태

#1019 (comment) 기준으로 아래 항목을 반영했습니다.

  • 최신 devel 기준 rebase (upstream/devel@5a1c645a)
  • RealPic watermark helper를 svg.rs가 아니라 image_resolver.rs로 이동/통합
  • SVG PageBackground 경로에 watermark effect/opacity/tone bake 적용
  • SVG 배경 ImageFill 경로에 fill watermark effect/opacity/tone bake 적용
  • SVG white area transparency 처리 경로 정리 (ImageNode + PageBackground PCX)
  • 새 fixture를 samples/에 추가해 복학원서(Task #938: 복학원서 JPEG 워터마크 배경 사각형 제거 및 톤 보정 #976) + RealPic preset 발동 fixture 회귀 가드 보강

추가 fixture는 아래 파일로 samples/에 포함했습니다.

범위 제외

  • 파일명 기반 분기는 넣지 않았습니다.
  • 한컴 내부의 공식 워터마크 색 변환 알고리즘을 확정한 것은 아닙니다. 현재 값은 RealPic 색상 워터마크 샘플과 macOS 한컴 뷰어 watermark-only 캡처 기준의 근사값입니다.
  • effect != RealPic 워터마크 및 #976의 JPEG baked watermark 경로는 유지하되, 이번 RealPic 색상 워터마크 경로와 분리했습니다.
  • 253E164F57A1BC6934.hwp export 중 보이는 table overflow 경고는 기존 레이아웃 overflow이며, 워터마크 색상/배치 보정 범위가 아닙니다.

테스트

최신 devel rebase 후 재확인:

  • cargo fmt --all -- --check
  • cargo test --lib renderer::svg::tests
  • cargo test --test issue_1019 --test issue_514 --test issue_938 --test issue_1156_rowbreak_fragment_fit
  • cargo check --target wasm32-unknown-unknown --lib
  • git diff --check

최신 rebase 직전 같은 PR 브랜치에서 확인:

  • cargo test --lib realpic_watermark --offline
  • cargo test --test svg_snapshot --offline
  • cargo test --lib --offline
  • cargo check --target wasm32-unknown-unknown --lib --offline
  • docker-compose --env-file .env.docker run --rm wasm

통과한 주요 결과:

  • cargo test --lib renderer::svg::tests: 31 passed
  • cargo test --test issue_1019 --test issue_514 --test issue_938 --test issue_1156_rowbreak_fragment_fit: 11 passed
  • cargo check --target wasm32-unknown-unknown --lib: passed
  • cargo test --lib realpic_watermark --offline: 2 passed
  • cargo test --test svg_snapshot --offline: 8 passed
  • cargo test --lib --offline: 1312 passed; 0 failed; 2 ignored
  • WASM build: pkg/rhwp_bg.wasm 갱신 완료

시각 검증

143E433F503322BD33.hwp

Before (upstream/devel) After (this PR) 한컴 뷰어 Mac
image image hancom_answer pdf

253E164F57A1BC6934-empty.hwp

Page Before (upstream/devel) After (this PR) 한컴 뷰어 Mac
1 image image image
2 image image image

문서

  • mydocs/plans/task_m100_975.md
  • mydocs/plans/task_m100_975_impl.md
  • mydocs/working/task_m100_975_stage1.md
  • mydocs/working/task_m100_975_stage3.md
  • mydocs/working/task_m100_975_stage4.md
  • mydocs/report/task_m100_975_report.md

@postmelee postmelee changed the title fix(#975): align background watermark rendering Task #975: Align PageBackground fill mode and RealPic watermark tone May 19, 2026
@postmelee postmelee changed the title Task #975: Align PageBackground fill mode and RealPic watermark tone Task #975: Fix PageBackground fill mode and RealPic watermark tone May 19, 2026
@edwardkim edwardkim self-requested a review May 19, 2026 23:21
@edwardkim edwardkim added the enhancement New feature or request label May 19, 2026
@edwardkim edwardkim added this to the v1.0.0 milestone May 19, 2026
edwardkim added a commit that referenced this pull request May 19, 2026
…PaintOp::Image

@postmelee — 이미지 변환(BMP/PCX→PNG) + 워터마크 JPEG→baked PNG 판정이
5+ renderer 별 사본(svg/canvas/web_canvas/skia/paint/json)에 분산되어
있던 것을 LayerBuilder 단계 단일 image_resolver::resolve_image_payload()
진입점으로 통합. 결과를 ResolvedImagePayload 로 패키지하여
PaintOp::Image.resolved: Option<Box<...>> 옵션 필드에 부착 (schema minor
12→13, 하위호환). 모든 renderer 는 resolved payload 소비만 — 재판정 없음.

옵션 A: 본질 커밋 3aeaa5b cherry-pick (작성자 postmelee 보존,
orders/20260520.md --ours 1건 충돌 해소). 검증: cargo test 1307 +
cargo test --test issue_938 3건(overlay/svg/PageLayerTree resolved
watermark contract) + clippy -D + fmt 0 + WASM 4.83MB.

광범위 sweep 10 fixture (BEFORE devel ↔ AFTER): 복학원서(워터마크),
sample16-hwp5/hwp3, hy-001 HWPX/HWP5, exam_kor/math, aift, biz_plan,
test-image — **전부 diff=0** (SVG 출력 100% 동일). 광범위 표면(24파일,
7개 renderer 경로)에도 시각 결과 완전 보존 — feedback_image_renderer_
paths_separate 본질적 해소 + 시각 호환성 100% 모범 사례. 작업지시자
시각 판정 생략 통과 (sweep diff=0 정량 입증).

PR scope 좁힘: z-order replay 일반화는 #1017로 분리 (PR 본문 명시).
@postmelee 후속 #1019 (Task #975 PageBackground fill + RealPic
watermark tone) OPEN 시리즈 연속.
@edwardkim

Copy link
Copy Markdown
Owner

검토 결과 수정 요청드립니다 (보류, PR/이슈 OPEN 유지).

검증 결과 — PR 자체는 견고, SVG 경로 정합 미완

자기 검증 + sweep 모두 통과:

다만 작업지시자 시각 판정에서 devel 기존 SVG 경로 결함 확인 (BEFORE/AFTER 동일):

  1. SVG 출력 워터마크 효과 미적용 (canvas/web_canvas는 정상)
  2. SVG 출력 흰색 영역 투명 미처리 (canvas와 동작 차이)

본 PR이 "renderer들이 같은 resolved image payload 공유 + tone 정합"을 본질로 하시므로 SVG 정합도 함께 포함되어야 한다는 판단입니다.

요청 사항

  1. 최신 devel(84246b2a) 기준 rebaseTask #1016: Resolve image payloads in PaintOp::Image #1018 image_resolver 통합 반영. 현재 head는 Task #1016: Resolve image payloads in PaintOp::Image #1018 이전 base라 svg.rs helper 4개(bmp_bytes_to_png_bytes, pcx_bytes_to_png_bytes, watermark_jpeg_bytes_to_hancom_baked_png_bytes, detect_image_mime_type) 재정의 충돌 발생

  2. 신규 helper를 image_resolver.rs로 이동apply_real_picture_watermark_tone_rgb + real_picture_watermark_bytes_to_hancom_tone_png_bytes을 svg.rs가 아닌 src/renderer/image_resolver.rs로 이동 (#1018과 일관성, feedback_image_renderer_paths_separate 정합)

  3. SVG 경로 정합 추가 (PR scope 확장):

    • SVG <image> 요소에 워터마크 effect 필터/투명도 적용 (현재 누락)
    • SVG 흰색 영역 투명 처리 (canvas의 pcx_bytes_to_png_bytes 한컴 호환 동작과 일치)
    • render_page_background_image() helper가 워터마크 효과 + 흰색 투명 처리도 일관 적용
  4. fixture 명시 — 가능하면 복학원서(Task #938: 복학원서 JPEG 워터마크 배경 사각형 제거 및 톤 보정 #976 경로) + RealPic preset 발동 fixture를 samples/에 추가하여 회귀 가드 영구화

설계(2 fix 분리 + RealPic preset 4-param + 3x3 affine + PNG bake) 자체는 견고합니다. #1018 직후 적층에서 발견된 SVG 일관성을 함께 정합해주시면 좋겠습니다. 광범위한 작업 감사합니다.

edwardkim added a commit that referenced this pull request May 20, 2026
PR #1019 는 머지하지 않음. PR 자체(2 fix + 3 cherry-pick) 견고 + sweep
회귀 0 + rhwp-studio 시각 정상이나, 작업지시자 시각 판정으로 SVG 경로의
두 결함(워터마크 효과 미적용 + 흰색 투명 미처리, BEFORE/AFTER 동일 =
devel 기존) 발견. 컨트리뷰터에게 최신 devel rebase + image_resolver 로
신규 helper 이동 + SVG 정합 추가 + fixture 명시 요청. PR/이슈 #975 OPEN
유지.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@postmelee

Copy link
Copy Markdown
Collaborator Author

@edwardkim 네 확인했습니다. 아직 RealPic 색상 워터마크 preset 정합 부분이 한컴 뷰어 색상과 차이가 있어 색상 보정부분 정확도 작업중입니다. 완료되면 PR draft -> open으로 전환하겠습니다.

@postmelee postmelee force-pushed the task-975-page-background-fill-mode branch 2 times, most recently from bff91da to 18622fb Compare May 28, 2026 01:08
@postmelee postmelee force-pushed the task-975-page-background-fill-mode branch from 18622fb to ff04eb3 Compare May 28, 2026 03:20
@postmelee

postmelee commented May 28, 2026

Copy link
Copy Markdown
Collaborator Author

@edwardkim 후속 요청사항 1~4 기준으로 반영 완료했습니다. self-review에서 확인한 profile/opacity 정합도 추가로 보강했습니다.

  1. 최신 devel 기준 rebase
  • upstream/devel@5a1c645a 기준을 포함하도록 PR 브랜치를 갱신했습니다.
  • PR head는 3257bc6a입니다.
  1. RealPic helper image_resolver.rs 이동/통합
  • RealPic tone bake helper는 src/renderer/image_resolver.rs에 유지/통합했습니다.
  • Web Canvas 호출부도 svg.rs re-export 경유가 아니라 image_resolver 경로를 직접 참조하도록 정리했습니다.
  • self-review로 일반 ImageFill RealPic 경로가 fill용 helper/opacity를 쓰도록 추가 정합했습니다.
  1. SVG 경로 정합
  1. fixture 명시

검증:

  • cargo fmt --all -- --check
  • cargo test --lib renderer::svg::tests → 31 passed
  • cargo test --test issue_1019 --test issue_514 --test issue_938 --test issue_1156_rowbreak_fragment_fit → 11 passed
  • cargo check --target wasm32-unknown-unknown --lib
  • git diff --check

PR 본문도 위 상태에 맞춰 업데이트했습니다.

@postmelee postmelee marked this pull request as ready for review May 28, 2026 03:51
edwardkim added a commit that referenced this pull request May 28, 2026
@edwardkim edwardkim merged commit e26f159 into edwardkim:devel May 28, 2026
7 checks passed
@edwardkim

Copy link
Copy Markdown
Owner

반영 완료했습니다.

  • 메인테이너 SVG/rhwp-studio 시각 판정 통과
  • devel에 반영 완료: f4d4fa34
  • 검증:
    • cargo fmt --all -- --check
    • cargo test --lib renderer::svg::tests
    • cargo test --test issue_1019 --test issue_514 --test issue_938 --test issue_1156_rowbreak_fragment_fit
    • cargo check
    • cargo check --target wasm32-unknown-unknown --lib
    • WASM build

추가로, 같은 샘플에서 차트 컨트롤이 포함된 2단 레이아웃은 아직 한컴 에디터와 배치가 다릅니다. 표 다음 차트가 현재 단에 들어가지 않을 때 오른쪽 단으로 이동해야 하는 별도 차트 컨트롤/다단 레이아웃 문제로 확인되어, #1019 범위 밖의 후속 이슈로 분리하겠습니다.

edwardkim added a commit that referenced this pull request May 29, 2026
2단(multicolumn) 문서에서 차트(OLE) 컨트롤이 한컴과 다르게 배치되는 결함 정정.

본질 (재현: samples/hwpx/143E433F503322BD33.hwpx, 정답지 pdf-large/hwpx/):
- 차트 80mm (한컴+spec SHAPE_COMPONENT+HWPX hp:sz 3중 일치)
- 한컴: 차트가 단0 끝 넘으면 단1 상단 이동 + 단0 빈 공간 텍스트 back-fill

정정:
1. 차트 단 이동 (typeset.rs typeset_table_paragraph)
   - 비-TAC TopAndBottom vert=Para 차트(Shape/OLE)가 단 잔여 부족 시 advance_column.
   - 종전 TAC 객체만 처리하여 비-TAC 차트는 높이 0 push (단 이동 누락).
2. 자리차지 텍스트 겹침 (layout.rs layout_shape_item)
   - 비-TAC TopAndBottom Shape 의 result_y 를 차트 높이만큼 진행 → 후속 텍스트
     가 차트 영역 겹치지 않음 (텍스트 첫 줄 y 154→486, 차트 bottom 415 아래).
3. 워터마크 효과 회귀 (svg.rs/web_canvas.rs/skia/renderer.rs, scope 확대)
   - PR #1019(#975 RealPic) 가 RealPic 톤 프리셋 경로 추가하며, effect=RealPic +
     톤 프리셋 아닌 배경 워터마크(brightness=contrast=0)가 opacity 누락.
   - 페이지 배경 이미지는 본질적으로 워터마크 → RealPic 톤 프리셋 아닌 PageBackground
     도 워터마크 opacity 적용 (3 렌더러 경로 정합).

검증:
- 작업지시자 한컴 시각 판정 통과 (차트 단1 상단 + 겹침 해소 + 워터마크 반투명)
- 회귀 가드 tests/issue_1156_chart_column_flow.rs (2 passed)
- cargo test --tests / svg_snapshot 8 / clippy --lib / fmt 통과

scope 밖: 차트 그림(MS Graph OLE2) 실제 그래프 렌더 (현재 placeholder 80mm).

closes #1156

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants