Files
vnidrop/packaging/apple/studio/screens.typ

79 lines
3.1 KiB
Typst

// App Store screenshot composition.
// Rendered per (locale, screen) via:
// typst compile screens.typ out.png --input locale=fr --input screen=share-securely --ppi 72
// Canvas is 1284x2778pt -> at 72ppi that's exactly 1284x2778px.
#let strings = json("strings.json")
// ---- inputs (with dev-friendly defaults) --------------------------------
#let locale = sys.inputs.at("locale", default: "en")
#let screen-id = sys.inputs.at("screen", default: "share-securely")
// A pre-framed device PNG (mockup + screenshot, produced by frame.sh), or "none"
// to show the empty mockup. Screen curvature comes from the mockup mask, not Typst.
#let device-image = sys.inputs.at("device", default: "none")
#let cap = strings.locales.at(locale).at(screen-id)
// ---- canvas -------------------------------------------------------------
#let CW = 1284pt
#let CH = 2778pt
// ---- per-screen layout data --------------------------------------------
#let screens = (
"choose-receivers": (
bg: gradient.linear(angle: 160deg, rgb("#f1eafc"), rgb("#e6d8fb"), rgb("#d9c4f7")),
text: (place: "top", theme: "dark"),
device: (mockup: "straight", w: 860pt, dx: 212pt, dy: 560pt, rot: 4deg),
),
"share-securely": (
bg: gradient.linear(angle: 165deg, rgb("#efe7fb"), rgb("#e3d3f8"), rgb("#d5bff4")),
text: (place: "top", theme: "dark"),
device: (mockup: "straight", w: 820pt, dx: 232pt, dy: 470pt, rot: 0deg),
),
"send-anywhere": (
bg: gradient.linear(dir: ttb, rgb("#e9ddf9"), rgb("#ddc9f4")),
text: (place: "bottom", theme: "dark"),
globe: (w: 1180pt, dx: 52pt, dy: -160pt),
device: (mockup: "rotated", w: 900pt, dx: 90pt, dy: 980pt, rot: 0deg),
),
"stay-private": (
bg: gradient.linear(dir: ttb, rgb("#2a0f4d"), rgb("#6b3fa0"), rgb("#e9dcf8"), rgb("#ddc7f4")),
text: (place: "top", theme: "light"),
),
)
#let cfg = screens.at(screen-id)
#set page(width: CW, height: CH, margin: 0pt, fill: cfg.bg)
#set text(font: ("SF NS", "Helvetica Neue")) // "SF NS" is macOS San Francisco (= SF Pro)
// ---- compose ------------------------------------------------------------
// globe (transparent PNG)
#if "globe" in cfg [
#place(top + left, dx: cfg.globe.dx, dy: cfg.globe.dy,
image("assets/globe.png", width: cfg.globe.w))
]
// device: a pre-framed PNG (frame.sh) when available, else the empty mockup.
#if "device" in cfg [
#let d = cfg.device
#let img = if device-image != "none" { device-image } else { "assets/mockup-" + d.mockup + ".png" }
#place(top + left, dx: d.dx, dy: d.dy,
rotate(d.rot, origin: center, image(img, width: d.w)))
]
// caption
#let theme-color = if cfg.text.theme == "light" { white } else { rgb("#1b1226") }
#let sub-color = if cfg.text.theme == "light" { rgb("#f3ecfb") } else { rgb("#2c2138") }
#let caption = align(center)[
#text(size: 104pt, weight: 800, fill: theme-color)[#cap.title]
#v(10pt, weak: true)
#text(size: 60pt, weight: 600, fill: sub-color)[#cap.subtitle]
]
#if cfg.text.place == "top" [
#place(top + center, dy: 96pt, box(width: CW - 160pt, caption))
] else [
#place(bottom + center, dy: -220pt, box(width: CW - 160pt, caption))
]