Skip to content

feat(picture): give a new picture a shadow or a glow - #448

Merged
airmang merged 1 commit into
mainfrom
feat/picture-shadow-and-glow
Oct 8, 2026
Merged

airmang merged 1 commit into
mainfrom
feat/picture-shadow-and-glow

Conversation

@airmang

@airmang airmang commented Oct 8, 2026

Copy link
Copy Markdown
Owner

바뀐 점

그림을 만들 때(doc.add_picture, HwpxOxmlParagraph.add_picture) 그림자와 빛남을 줄 수 있다. 두 클래스는 hwpx.oxml에서 가져온다.

from hwpx.oxml import PictureGlow, PictureShadow

doc.add_picture(data, "png", shadow=PictureShadow(direction=90, distance=800), glow=PictureGlow(radius=700))
클래스 필드(기본값) 쓰는 곳
PictureShadow color(#000000), alpha(0.5), blur(600), direction(45), distance(600), inside(False) hp:effects/hp:shadow
PictureGlow color(#FFC000), alpha(0.5), radius(500) hp:effects/hp:glow
  • alpha는 투명도다. 0이면 불투명하고, 1이면 그리지 않는다.
  • direction은 오른쪽에서 시계 방향으로 잰 각도다. 0은 오른쪽, 90은 아래, 180은 왼쪽, 270은 위다.
  • 길이(blur, distance, radius)는 HWPUNIT이다.
  • XML 모양은 한/글 문서가 쓰는 것과 같다. 그림자에는 skew·scale·effectsColor(RGB)가 들어가고, 순서는 그림자 다음에 빛남이다.

한/글의 동작

  • 위 범위의 값은 한/글이 그대로 저장하고 그린다. 바깥·안쪽 그림자, 방향, 거리, 흐림, 빛남의 색과 반경이 모두 반영된다.
  • 범위 밖의 값은 문단이나 이진 항목을 더하기 전에 shape-picture-effect-value로 거부한다. 한/글은 그런 값을 그대로 두지 않기 때문이다.
    • alpha가 0~1 밖이면 끝값으로 저장한다.
    • direction은 360으로 나눈 나머지로 저장한다(-90은 270, 450은 90).
    • 모르는 그림자 모양은 OUTSIDE로 저장한다.
    • 음수 반경은 0처럼 그린다.
  • 효과는 자리를 차지한다. 한/글은 그림과 바깥 그림자·빛남을 합친 크기로 배치한다.
    • 빛남은 네 변에 반경만큼 더한다.
    • 바깥 그림자는 그림(빛남 포함) 상자를 방향으로 거리만큼 옮기고 흐림만큼 넓힌 상자와 합친다.
    • 그래서 글자처럼 취급한 그림은 줄이 그만큼 높아진다. 예: 높이 10000에 빛남 500이면 줄은 10999다.
    • 안쪽 그림자는 크기를 바꾸지 않는다.

코드

  • oxml/shape_position.py: 다른 그림 검사 옆에 PictureShadow·PictureGlow·validate_picture_effects·append_picture_effects를 둔다. 새 모듈을 두면 import hwpx가 싣는 모듈 수 상한을 넘는다.
  • oxml/objects.py: _create_picture_element와 _paragraph_add_picture가 shadow·glow를 받는다.
  • _document/media.py, document.py: 문서 수준 add_picture가 같은 인자를 받고, 이진 항목을 넣기 전에 검사한다.
  • oxml/__init__.py: PictureGlow·PictureShadow를 내보낸다(hwpx.oxml.__all__ 134 → 136, tests/test_oxml_modularization.py에 사유 주석).
  • errors.py·docs/error-codes.md: shape-picture-effect-value.
  • docs/coverage-ledger.* 재생성: hp:glow·hp:effectsColor·hp:rgb·hp:scale·hp:skew를 코드가 쓴다.
  • docs/support-matrix.md(동봉본 동기화), README.md·README_EN.md(알려진 제약, 예제 원장 해시), 변경 로그.
  • tests/data/document_facade_surface.json: add_picture 서명.

쪽 수 추정이 효과가 늘린 그림 크기를 셈에 넣는 일은 이 PR에 넣지 않았다(후속).

테스트

tests/test_picture_adjustments.py:

  • 한/글 저장본 picture_shadow_and_glow.hwpx(아래 그림자 거리 800 + 빛남 700)의 hp:effects 아래 요소·속성과 같게 쓰는지 본다.
  • 기본값으로는 효과를 쓰지 않는다.
  • 범위 밖 12가지와 클래스가 아닌 값 2가지는 거부되고, 문단과 이진 항목이 늘지 않는다.

🤖 Generated with Claude Code

add_picture takes shadow=PictureShadow(...) (colour, alpha 0..1, blur,
direction 0..359 clockwise from the right, distance, inside) and
glow=PictureGlow(...) (colour, alpha, radius), written into hp:effects as
a Hancom document holds them. Hancom saves an alpha past 0..1 as the
bound, a direction modulo 360 and an unknown shadow style as OUTSIDE, and
draws a negative radius as 0, so such values are refused before anything
is added (shape-picture-effect-value). Hancom lays the picture out as
large as it and its outer shadow or glow together.

The two classes are exported from hwpx.oxml (134 -> 136 names) and live in
oxml/shape_position.py beside the picture's other checks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@airmang

airmang commented Oct 8, 2026

Copy link
Copy Markdown
Owner Author

리뷰 결과: 막을 것은 없습니다. CI가 통과하면 병합합니다.

  • 인자를 주지 않은 add_picture는 구역 XML이 고치기 전과 같습니다.
  • 그림자(hp:shadow)는 한/글에서 처음 만든 문서의 그림자와 요소·속성 구성이 같습니다. 빛남(hp:glow)은 한/글 문서에 effectsColor 아래 색 보정(hp:effect type="SAT_MOD")이 있는 것과 없는 것이 함께 있고, 이 PR은 없는 쪽과 같습니다.
  • 커버리지 원장 변경은 새로 쓰는 다섯 요소(hp:glow·effectsColor·rgb·scale·skew)의 none → api뿐입니다.
  • 후속으로 남긴 것: 효과 크기만큼 늘어나는 배치 크기(빛남 반경, 그림자 방향·거리·흐림)를 쪽 수 추정에 반영하는 일.

@airmang
airmang merged commit e9994e5 into main Oct 8, 2026
13 checks passed
@airmang
airmang deleted the feat/picture-shadow-and-glow branch October 8, 2026 15:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant