fix: INFINITH 덱 폰트 pt 표준화 — 20in 캔버스를 2/3 균등 축소한 v2_표준캔버스 버전 추가

원인: INFINITH 덱 캔버스가 20x11.25in(표준 1.5배)이라 폰트 pt가 1.5배 부풀려짐
(본문 18pt = 화면상 12pt). ADO2 정본(12.5in)과 달리 14pt 지정 시 9.3pt처럼 렌더.
scripts/rescale_deck.py로 좌표·폰트·선·여백 전부 2/3 축소 → 13.33x7.5in 표준,
화면 모습 동일, pt 숫자 표준화(본문 12pt·타이틀 42pt). haewon 수정 원본은 보존.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0155BJMHJyhqqAPGYjGKYhPS
This commit is contained in:
Haewon Kam 2026-09-01 11:44:41 +09:00
parent 69b580c135
commit bf4e1a5548
5 changed files with 75 additions and 0 deletions

75
scripts/rescale_deck.py Normal file
View File

@ -0,0 +1,75 @@
#!/usr/bin/env python3
"""PPTX 덱을 균등 배율로 축소/확대한다 (좌표·폰트·선굵기·여백 전부).
INFINITH (20x11.25in) 표준 캔버스(13.33x7.5in) 1.5배라 폰트 pt 숫자가
1.5 부풀려져 있다. 2/3 균등 축소하면 화면 모습은 동일하고 pt는 표준이 된다.
원본은 덮어쓰지 않는다. 반드시 파일로 저장한다.
python3 scripts/rescale_deck.py <in.pptx> <out.pptx> [배율=0.6667]
"""
import sys
from fractions import Fraction
from pptx import Presentation
NS = "{http://schemas.openxmlformats.org/drawingml/2006/main}"
# EMU 좌표 속성 (요소 태그 → 속성들)
GEOM = {
f"{NS}off": ("x", "y"),
f"{NS}ext": ("cx", "cy"),
f"{NS}chOff": ("x", "y"),
f"{NS}chExt": ("cx", "cy"),
}
# 폰트 크기(1/100pt) 속성을 갖는 요소
SZ_TAGS = {f"{NS}rPr", f"{NS}defRPr", f"{NS}endParaRPr"}
# 텍스트 프레임 안쪽 여백(EMU)
BODYPR_ATTRS = ("lIns", "tIns", "rIns", "bIns")
def scale_int(v, f):
return str(int(round(int(v) * f)))
def scale_tree(root, f):
for el in root.iter():
tag = el.tag
if tag in GEOM:
for a in GEOM[tag]:
if el.get(a) is not None:
el.set(a, scale_int(el.get(a), f))
elif tag in SZ_TAGS:
if el.get("sz") is not None:
el.set("sz", scale_int(el.get("sz"), f))
elif tag == f"{NS}ln":
if el.get("w") is not None:
el.set("w", scale_int(el.get("w"), f))
elif tag == f"{NS}bodyPr":
for a in BODYPR_ATTRS:
if el.get(a) is not None:
el.set(a, scale_int(el.get(a), f))
elif tag == f"{NS}spcPts":
if el.get("val") is not None:
el.set("val", scale_int(el.get("val"), f))
def main():
src, dst = sys.argv[1], sys.argv[2]
f = float(sys.argv[3]) if len(sys.argv) > 3 else float(Fraction(2, 3))
if src == dst:
sys.exit("원본 덮어쓰기 금지. 출력 파일명을 다르게 지정하세요.")
prs = Presentation(src)
prs.slide_width = int(round(prs.slide_width * f))
prs.slide_height = int(round(prs.slide_height * f))
for slide in prs.slides:
scale_tree(slide._element, f)
for layout in prs.slide_layouts:
scale_tree(layout._element, f)
for master in prs.slide_masters:
scale_tree(master._element, f)
prs.save(dst)
print(f"저장: {dst} ({prs.slide_width/914400:.3f} x {prs.slide_height/914400:.3f} in, 배율 {f:.4f})")
if __name__ == "__main__":
main()