import { findAsset, type Project } from './Project'; import { textOf } from './Properties'; /** Mirrors `FontStore::isValidName` on the server, where the name is derived from the bytes. */ const FILE_PATTERN = /^[a-f0-9]{64}\.(ttf|otf|woff|woff2)$/; export function isFontFile(name: string): boolean { return FILE_PATTERN.test(name); } /** * The CSS family a file is registered under. Derived from the content-addressed name, so the same * bytes are always one family and two uploads of one typeface cannot fight over a name – the name * inside the font is never used for this, only for the asset's label. */ export function fontFamilyOf(file: string): string { return `gm-font-${file.slice(0, 16)}`; } /** * Whether the face a `font` property points at is drawn smoothed, the font asset's Filter row the * way it is a texture's. The editor's own typeface, and a dangling id, are smooth. */ export function fontSmoothOf(project: Project, id: string): boolean { const asset = id === '' ? undefined : findAsset(project, id); return asset?.type !== 'font' || textOf(asset.props.filter ?? 'linear') !== 'nearest'; } /** The file a `font` property points at, empty when the id is unset or no longer resolves. */ export function fontFileOf(project: Project, id: string): string { if (id === '') return ''; const asset = findAsset(project, id); return asset?.type === 'font' ? asset.file : ''; }