Skip to main content

egui_macview/tokens/
typography.rs

1//! SF Pro dynamic typography and optical tracking tokens.
2
3use serde::{Deserialize, Serialize};
4use std::collections::HashMap;
5
6/// Single entry in the SF Pro tracking table.
7#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
8pub struct TrackingTableEntry {
9    /// Font size in points.
10    pub size_pt: u32,
11    /// Subfamily / weight name (e.g. Regular, Medium, Bold).
12    pub subfamily: String,
13    /// Tracking value in 1/1000 em.
14    pub tracking_em_1000: i32,
15    /// Tracking value in points.
16    pub tracking_pt: f32,
17    /// Optional description.
18    #[serde(rename = "$description", default)]
19    pub description: Option<String>,
20}
21
22/// Coefficients for a cubic polynomial regression $a \cdot x^3 + b \cdot x^2 + c \cdot x + d$.
23#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
24pub struct CubicCoefficients {
25    /// Cubic coefficient ($x^3$).
26    pub a: f64,
27    /// Quadratic coefficient ($x^2$).
28    pub b: f64,
29    /// Linear coefficient ($x$).
30    pub c: f64,
31    /// Constant offset ($1$).
32    pub d: f64,
33}
34
35/// Cubic polynomial regression fit specification.
36#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
37pub struct CubicFit {
38    /// Formula string representation.
39    pub formula: String,
40    /// Polynomial coefficients.
41    pub coefficients: CubicCoefficients,
42}
43
44/// Coefficients for a quadratic polynomial regression $a_2 \cdot x^2 + a_1 \cdot x + a_0$.
45#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
46pub struct QuadraticCoefficients {
47    /// Quadratic coefficient ($x^2$).
48    pub a2: f64,
49    /// Linear coefficient ($x$).
50    pub a1: f64,
51    /// Constant offset ($1$).
52    pub a0: f64,
53}
54
55/// Quadratic polynomial regression fit specification.
56#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
57pub struct QuadraticFit {
58    /// Formula string representation.
59    pub formula: String,
60    /// Polynomial coefficients.
61    pub coefficients: QuadraticCoefficients,
62}
63
64/// Discrete tracking measurement point.
65#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
66pub struct TrackingPoint {
67    /// Font size in points.
68    pub pt: f64,
69    /// Measured optical tracking in points.
70    pub tracking_pt: f64,
71}
72
73/// Continuous polynomial tracking model defined in SPEC-001.
74#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
75pub struct PolynomialSpec001 {
76    /// Optional description.
77    #[serde(default)]
78    pub description: Option<String>,
79    /// Quadratic curve fit for inspector display.
80    pub quadratic_inspector_fit: QuadraticFit,
81    /// Canonical Apple HIG cubic regression curve fit.
82    pub cubic_apple_hig_fit: CubicFit,
83    /// Discrete verification data points.
84    pub points: HashMap<String, TrackingPoint>,
85}
86
87/// Typography and tracking tokens.
88#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
89pub struct MacTypographyTokens {
90    /// Discrete SF Pro tracking lookup table.
91    pub tracking_table: HashMap<String, TrackingTableEntry>,
92    /// Continuous polynomial regression models.
93    pub polynomial_spec001: PolynomialSpec001,
94}
95
96impl MacTypographyTokens {
97    /// Evaluates continuous optical tracking in pt using Apple HIG cubic regression.
98    pub fn tracking_for_size(&self, pt: f64) -> f64 {
99        let c = &self.polynomial_spec001.cubic_apple_hig_fit.coefficients;
100        c.a * pt.powi(3) + c.b * pt.powi(2) + c.c * pt + c.d
101    }
102
103    /// Evaluates quadratic inspector fit.
104    pub fn tracking_quadratic(&self, pt: f64) -> f64 {
105        let c = &self.polynomial_spec001.quadratic_inspector_fit.coefficients;
106        c.a2 * pt.powi(2) + c.a1 * pt + c.a0
107    }
108}
109
110/// Continuous SF Pro tracking polynomial using canonical Apple HIG fit:
111/// $\text{Tracking}(p) = a \cdot p^3 + b \cdot p^2 + c \cdot p + d$
112#[inline]
113pub fn sf_pro_tracking(size_pt: f32) -> f32 {
114    let p = size_pt as f64;
115    let a = 0.000864840354;
116    let b = -0.0339060217;
117    let c = 0.355814827;
118    let d = -0.891241741;
119    (a * p.powi(3) + b * p.powi(2) + c * p + d) as f32
120}