Lilita One lacks most of Latin Extended-A (Turkish s-cedilla, g-breve, dotted I ...), so Turkish titles were drawn with a silent browser fallback while shots check passed. shots fonts now reads the cmap of every face (pure TS, TTF/OTF/WOFF/WOFF2), adds a Noto fallback per missing character or fails with language + characters; render measures which face drew each character (CDP probes) and records it in report.json; check errors on fallbacks the config did not choose (shots.fonts.fallback) and on system-font glyphs. Default game title font: Paytone One.
42 lines
2.2 KiB
HTML
42 lines
2.2 KiB
HTML
<!doctype html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<link rel="stylesheet" href="/fonts/fonts.css">
|
|
<!-- Caption overlay for app preview videos (transparent PNG, rendered by `storebound shots video`, overlaid by ffmpeg).
|
|
caption.html?w=<px>&h=<px>&lang=<id>&i=<caption index>. Same title font, stroke and colours as the screenshots. -->
|
|
<style>
|
|
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
html, body { background: transparent; overflow: hidden; }
|
|
#c { position: relative; width: var(--W); height: var(--H); }
|
|
.cap { position: absolute; left: 50%; top: calc(var(--u) * 7); transform: translateX(-50%) rotate(-1.5deg); max-width: calc(var(--u) * 90);
|
|
padding: calc(var(--u) * 2.6) calc(var(--u) * 5) calc(var(--u) * 3); border-radius: calc(var(--u) * 5); text-align: center;
|
|
background: linear-gradient(180deg, rgba(0,0,0,.42), rgba(0,0,0,.28)); box-shadow: inset 0 0 0 calc(var(--u) * .35) rgba(255,255,255,.3);
|
|
font-family: var(--tf); font-weight: var(--tw); font-size: calc(var(--u) * var(--fs)); line-height: 1.04; color: #fff;
|
|
-webkit-text-stroke: calc(var(--u) * var(--fs) * .07) var(--ink); paint-order: stroke fill; text-wrap: balance;
|
|
filter: drop-shadow(0 calc(var(--u) * .7) 0 var(--ink)); }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="c"></div>
|
|
<script type="module">
|
|
const q = new URLSearchParams(location.search);
|
|
const W = +q.get('w'), H = +q.get('h'), LANG = q.get('lang'), I = +q.get('i');
|
|
const job = await (await fetch(`/caption.json?lang=${encodeURIComponent(LANG)}&i=${I}`)).json();
|
|
const u = Math.min(W, H) / 100, R = document.documentElement.style;
|
|
document.documentElement.lang = LANG;
|
|
R.setProperty('--W', W + 'px'); R.setProperty('--H', H + 'px'); R.setProperty('--u', u + 'px');
|
|
R.setProperty('--ink', job.ink); R.setProperty('--fs', W > H ? 6.4 : 8.2);
|
|
const X = job.fonts.script;
|
|
R.setProperty('--tf', (job.fonts.titleStack ?? (X ? [X, job.fonts.title] : [job.fonts.title])).map(f => `'${f}'`).join(', ') + ', sans-serif');
|
|
R.setProperty('--tw', X ? 900 : 400);
|
|
const el = document.createElement('div');
|
|
el.className = 'cap';
|
|
if (job.rtl) el.dir = 'rtl';
|
|
el.textContent = job.text;
|
|
document.getElementById('c').append(el);
|
|
await document.fonts.ready;
|
|
document.body.dataset.ready = '1';
|
|
</script>
|
|
</body>
|
|
</html>
|