Add font import for Now, Gotham and Open Sauce One overrides; package fonts for Void

Font import:
- Migration M6 adds user_fonts; files are stored content-addressed under
  the local data dir. New Rust commands inspect, import, list, read and
  remove fonts, refusing WOFF2, collections, variable fonts and
  restricted fsType, and unpacking WOFF1 to plain sfnt.
- Imported fonts register in the render worker as user:<Face> families
  with an italic alias, and are pinned in the frozen render prefs so
  issued invoices can still re-render. Fonts referenced by issued
  invoices are hidden, never deleted.
- Size and tracking compensations tuned for the substitutes apply only
  while the face is not overridden; default output and fingerprint
  goldens are unchanged.
- Settings gets a Fonts section with a licence acknowledgement.

Void packaging:
- Install fonts to /usr/share/fonts/voiced with per-family OFL licences,
  set font_dirs, and add INSTALL/REMOVE scripts that run fc-cache.
  xbps-create carries both scripts (verified in a void-glibc container).
- Fix xbps-create dependency specs in build-xbps.sh.
This commit is contained in:
2026-10-04 13:58:06 +05:30
parent d955130cf3
commit 43afdaf4bf
37 changed files with 2436 additions and 72 deletions
File diff suppressed because it is too large Load Diff
+1
View File
@@ -2,6 +2,7 @@ pub mod archive;
pub mod assets;
pub mod clients;
pub mod files;
pub mod fonts;
pub mod invoice;
pub mod logo;
pub mod raw;
+30 -3
View File
@@ -10,7 +10,7 @@ const MAX_BACKUPS: usize = 10;
const BACKUP_PREFIX: &str = "voiced-pre-v";
/// Highest schema version, i.e. the number of entries in `migrations()`.
const LATEST_VERSION: i64 = 5;
const LATEST_VERSION: i64 = 6;
#[derive(Debug, thiserror::Error)]
pub enum DbError {
@@ -190,8 +190,35 @@ ALTER TABLE app_settings ADD COLUMN logo_meta TEXT NOT NULL DEFAULT '';
ALTER TABLE app_settings ADD COLUMN logo_includes_name TEXT NOT NULL DEFAULT 'auto';
"#;
/// Version 6: user-imported fonts for the three licensed template faces. The files live content-addressed under
/// `<local data dir>/fonts/<sha256>.<ttf|otf>`; invoices freeze the sha256 of the fonts they used in render_prefs.
/// `hidden` retires a font that an issued invoice still references (never deleted while referenced).
const M6: &str = r#"
CREATE TABLE user_fonts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
face TEXT NOT NULL CHECK (face IN ('Now', 'Gotham', 'Open Sauce One')),
family_name TEXT NOT NULL,
full_name TEXT NOT NULL,
style_name TEXT NOT NULL DEFAULT '',
weight INTEGER NOT NULL CHECK (weight BETWEEN 100 AND 900),
style TEXT NOT NULL CHECK (style IN ('normal', 'italic')),
sha256 TEXT NOT NULL,
file_name TEXT NOT NULL,
format TEXT NOT NULL CHECK (format IN ('ttf', 'otf')),
size INTEGER NOT NULL,
fs_type INTEGER NOT NULL DEFAULT 0,
has_rupee INTEGER NOT NULL DEFAULT 0,
licence_ack_at TEXT NOT NULL,
imported_at TEXT NOT NULL,
hidden INTEGER NOT NULL DEFAULT 0
);
CREATE INDEX idx_user_fonts_sha ON user_fonts(sha256);
-- One visible font per face, weight and style; a hidden one keeps its row but frees the slot.
CREATE UNIQUE INDEX idx_user_fonts_slot ON user_fonts(face, weight, style) WHERE hidden = 0;
"#;
fn migrations() -> Migrations<'static> {
Migrations::new(vec![M::up(SCHEMA), M::up(M2), M::up(M3), M::up(M4), M::up(M5)])
Migrations::new(vec![M::up(SCHEMA), M::up(M2), M::up(M3), M::up(M4), M::up(M5), M::up(M6)])
}
/// Open (creating if needed) the database at `path` and bring it to the latest schema.
@@ -620,7 +647,7 @@ CREATE INDEX IF NOT EXISTS idx_invoices_created ON invoices(created_at DESC);
assert_eq!(user_version(&old), 4);
}
let conn = open(&path, &dir.path().join("backups")).unwrap();
assert_eq!(user_version(&conn), 5);
assert_eq!(user_version(&conn), LATEST_VERSION);
let (logo, meta): (String, String) = conn
.query_row("SELECT logo_path, logo_meta FROM app_settings WHERE id = 1", [], |r| {
Ok((r.get(0)?, r.get(1)?))
+5
View File
@@ -141,6 +141,11 @@ pub fn run() {
commands::archive::archive_pdf,
commands::archive::read_archive,
commands::archive::archive_status,
commands::fonts::inspect_font,
commands::fonts::import_font,
commands::fonts::list_user_fonts,
commands::fonts::get_user_font_bytes,
commands::fonts::remove_user_font,
commands::files::write_export_file,
commands::files::get_last_export_dir,
commands::files::reveal_in_folder,