#!/usr/bin/env python3 # fig_플레이어비교.py — 보통 플레이어(시간 축) vs 우리 플레이어(측점 축) 비교 그림 (PNG/PDF) # 원본: docs/쉬운설명_프레임기반에서_측점기반_플레이어.md 1절 인라인 SVG (720×250) # weasyprint SVG 텍스트 디센더 잘림 이슈 회피를 위해 PIL 직접 드로잉 (3배 해상도). # 실행: python3 scripts/fig_플레이어비교.py → docs/그림_플레이어비교.png / .pdf import os from PIL import Image, ImageDraw, ImageFont OUT_DIR = os.path.join(os.path.dirname(__file__), '..', 'docs') FB = os.path.expanduser('~/.local/share/fonts/malgunbd.ttf') FR = os.path.expanduser('~/.local/share/fonts/malgun.ttf') W, H = 2160, 760 im = Image.new('RGB', (W, H), 'white') d = ImageDraw.Draw(im) SLATE = (71, 85, 105) # #475569 제목1 GRAY_TXT = (55, 65, 81) # #374151 시간 라벨 GRAY_SUB = (107, 114, 128) # #6b7280 캡션 GREEN = (22, 101, 52) # #166534 제목2·역명 BLUE_LINE = (2, 132, 199) # #0284c7 구조물 마커 BLUE_TXT = (3, 105, 161) # #0369a1 구조물 라벨 # 카드 배경 (문서 figure 스타일: #fffdf8 / #e7e0d2) d.rounded_rectangle((6, 6, W - 7, H - 7), radius=30, fill=(255, 253, 248), outline=(231, 224, 210), width=3) # ① 보통 플레이어 (시간 축) d.text((1080, 72), '① 보통 플레이어 (시간 축)', font=ImageFont.truetype(FB, 42), fill=SLATE, anchor='mm') d.rounded_rectangle((120, 114, 2040, 192), radius=18, fill=(229, 231, 235), outline=(156, 163, 175), width=3) d.rounded_rectangle((120, 114, 870, 192), radius=18, fill=(156, 163, 175)) d.ellipse((840, 123, 900, 183), fill=(55, 65, 81)) lbl = ImageFont.truetype(FR, 34) d.text((135, 240), '0:00', font=lbl, fill=GRAY_TXT, anchor='lm') d.text((870, 240), '03:12', font=lbl, fill=GRAY_TXT, anchor='mm') d.text((2025, 240), '09:28', font=lbl, fill=GRAY_TXT, anchor='rm') d.text((1080, 314), '"3분 12초 지점" — 여기가 어느 선로인지 모름', font=lbl, fill=GRAY_SUB, anchor='mm') # ② 우리 플레이어 (측점 축) d.text((1080, 450), '② 우리 플레이어 (측점 축)', font=ImageFont.truetype(FB, 42), fill=GREEN, anchor='mm') d.rounded_rectangle((120, 492, 2040, 570), radius=18, fill=(253, 233, 200), outline=(224, 169, 79), width=3) d.rounded_rectangle((120, 492, 1050, 570), radius=18, fill=(245, 158, 11)) # 구조물 마커 (회덕터널 / 회덕천교) mk = ImageFont.truetype(FR, 30) for x, name in ((615, '회덕터널'), (1440, '회덕천교')): d.line((x, 478, x, 584), fill=BLUE_LINE, width=6) d.text((x, 632), name, font=mk, fill=BLUE_TXT, anchor='mm') # 현재 위치 배지 (160k) d.ellipse((1014, 495, 1086, 567), fill=(234, 88, 12)) d.text((1050, 531), '160k', font=ImageFont.truetype(FB, 28), fill='white', anchor='mm') # 시점/종점 역명 st = ImageFont.truetype(FR, 34) d.text((135, 690), '대전조차장', font=st, fill=GREEN, anchor='lm') d.text((2025, 690), '신탄진', font=st, fill=GREEN, anchor='rm') png = os.path.join(OUT_DIR, '그림_플레이어비교.png') im.save(png) print('PNG 저장:', png, im.size) # PDF (이미지 삽입 + 압축) import fitz doc = fitz.open() rect = fitz.Rect(0, 0, W / 2, H / 2) page = doc.new_page(width=rect.width, height=rect.height) page.insert_image(rect, filename=png) pdf = os.path.join(OUT_DIR, '그림_플레이어비교.pdf') doc.save(pdf, deflate=True, garbage=4) print('PDF 저장:', pdf)