From 82163e3dc0a16015836a869dad6e97420244d07d Mon Sep 17 00:00:00 2001 From: Joey Riches Date: Tue, 13 Aug 2024 18:16:02 +0100 Subject: [PATCH] moss/boulder: Add support for font providers Reads FAMILY_NAME from OpenType fonts in order to provide a font provider. e.g. `moss it 'font(Noto Sans Tamil Condensed Thin)'` --- Cargo.lock | 40 +++++++++++++++++++++++++ Cargo.toml | 1 + boulder/Cargo.toml | 1 + boulder/src/package/analysis.rs | 1 + boulder/src/package/analysis/handler.rs | 28 +++++++++++++++++ crates/stone/src/payload/meta.rs | 4 +++ moss/src/dependency.rs | 5 ++++ 7 files changed, 80 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 0140223a..fb3327ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -235,6 +235,7 @@ dependencies = [ "itertools 0.13.0", "moss", "nix 0.27.1", + "read-fonts", "regex", "serde", "serde_json", @@ -278,6 +279,26 @@ version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +[[package]] +name = "bytemuck" +version = "1.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "102087e286b4677862ea56cf8fc58bb2cdfa8725c40ffb80fe3a008eb7f2fc83" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ee891b04274a59bd38b412188e24b849617b2e45a0fd8d057deb63e7403761b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "bytes" version = "1.6.0" @@ -831,6 +852,15 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "font-types" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f0189ccb084f77c5523e08288d418cbaa09c451a08515678a0aa265df9a8b60" +dependencies = [ + "bytemuck", +] + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -1758,6 +1788,16 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "read-fonts" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c141b9980e1150201b2a3a32879001c8f975fe313ec3df5471a9b5c79a880cd" +dependencies = [ + "bytemuck", + "font-types", +] + [[package]] name = "redox_syscall" version = "0.5.2" diff --git a/Cargo.toml b/Cargo.toml index 6982447f..00c375da 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,6 +53,7 @@ tokio-util = { version = "0.7.11", features = ["io"] } url = { version = "2.5.2", features = ["serde"] } xxhash-rust = { version = "0.8.11", features = ["xxh3"] } zstd = { version = "0.13.2", features = ["zstdmt"] } +read-fonts = "0.20.0" [profile.release] lto = "thin" diff --git a/boulder/Cargo.toml b/boulder/Cargo.toml index 3ae914e5..129a8069 100644 --- a/boulder/Cargo.toml +++ b/boulder/Cargo.toml @@ -43,3 +43,4 @@ strum.workspace = true thiserror.workspace = true tokio.workspace = true url.workspace = true +read-fonts.workspace = true diff --git a/boulder/src/package/analysis.rs b/boulder/src/package/analysis.rs index 145e1692..59e454e5 100644 --- a/boulder/src/package/analysis.rs +++ b/boulder/src/package/analysis.rs @@ -38,6 +38,7 @@ impl<'a> Chain<'a> { Box::new(handler::elf), Box::new(handler::pkg_config), Box::new(handler::cmake), + Box::new(handler::font), // Catch-all if not excluded Box::new(handler::include_any), ], diff --git a/boulder/src/package/analysis/handler.rs b/boulder/src/package/analysis/handler.rs index c28fff26..2002bb50 100644 --- a/boulder/src/package/analysis/handler.rs +++ b/boulder/src/package/analysis/handler.rs @@ -1,6 +1,7 @@ use std::{path::PathBuf, process::Command}; use moss::{dependency, Dependency, Provider}; +use read_fonts::{types::NameId, FontRef, TableProvider}; use crate::package::collect::PathInfo; @@ -136,3 +137,30 @@ pub fn cmake(bucket: &mut BucketMut, info: &mut PathInfo) -> Result Result { + if !info.target_path.starts_with("/usr/share/font") + && !(info.file_name().ends_with(".ttf") || info.file_name().ends_with(".otf")) + { + return Ok(Decision::NextHandler.into()); + } + + let bytes = std::fs::read(&info.path)?; + let font = FontRef::new(&bytes)?; + let font_name_table = font.name()?; + if let Some(record) = font_name_table + .name_record() + .iter() + .find(|record| record.name_id() == NameId::FAMILY_NAME) + { + let data = record.string(font_name_table.string_data())?; + let family_name = data.chars().collect::(); + + bucket.providers.insert(Provider { + kind: dependency::Kind::Font, + name: family_name, + }); + } + + Ok(Decision::NextHandler.into()) +} diff --git a/crates/stone/src/payload/meta.rs b/crates/stone/src/payload/meta.rs index b1295f81..ce468e43 100644 --- a/crates/stone/src/payload/meta.rs +++ b/crates/stone/src/payload/meta.rs @@ -50,6 +50,9 @@ pub enum Dependency { /// An emul32-compatible pkgconfig .pc dependency (lib32/*.pc) PkgConfig32, + + /// OpenType Font FAMILY_NAME + Font, } #[repr(u8)] @@ -146,6 +149,7 @@ fn decode_dependency(i: u8) -> Result { 6 => Dependency::Binary, 7 => Dependency::SystemBinary, 8 => Dependency::PkgConfig32, + 9 => Dependency::Font, _ => return Err(DecodeError::UnknownDependency(i)), }; Ok(result) diff --git a/moss/src/dependency.rs b/moss/src/dependency.rs index 4ff7219c..80c49aa4 100644 --- a/moss/src/dependency.rs +++ b/moss/src/dependency.rs @@ -59,6 +59,9 @@ pub enum Kind { /// Exported 32-bit pkgconfig provider PkgConfig32, + + /// OpenType Font FAMILY_NAME + Font, } /// Convert payload dependency types to our internal representation @@ -74,6 +77,7 @@ impl From for Kind { payload::meta::Dependency::Binary => Kind::Binary, payload::meta::Dependency::SystemBinary => Kind::SystemBinary, payload::meta::Dependency::PkgConfig32 => Kind::PkgConfig32, + payload::meta::Dependency::Font => Kind::Font, } } } @@ -91,6 +95,7 @@ impl From for payload::meta::Dependency { Kind::Binary => Self::Binary, Kind::SystemBinary => Self::SystemBinary, Kind::PkgConfig32 => Self::PkgConfig32, + Kind::Font => Self::Font, } } }