Skip to main content

max / makeover

4.5 KB · 127 lines History Blame Raw
1 //! Candidate page-to-raised ramps for one theme, in both units the ramp
2 //! decisions are argued in.
3 //!
4 //! `cargo run --example ramp_candidates -- makenotwork`
5 //!
6 //! Two units, and mixing them is how a ramp gets misread: `raised_is_distinct
7 //! _from_page` asserts in **oklab L on 0 to 1** (0.05), while the theme files
8 //! and the rulings quote **CIE L\* on 0 to 100** (6.7). They are not a factor
9 //! of a hundred apart. Both are printed for every row.
10 //!
11 //! Two directions, because a ramp has two ends. Lifting `raised` runs it toward
12 //! white on a light theme, and `bevel-light` is derived from `raised` by
13 //! lightening -- so past a point the lit edge stops gaining while the shadowed
14 //! one keeps going, and the bevel gets less symmetric rather than more legible.
15 //! Dropping `page` buys the same separation with the headroom left alone.
16 //!
17 //! Prints; changes nothing. The edit it argues for is a hand edit to
18 //! `[surface]`, and the look call is not this program's.
19
20 #![allow(clippy::many_single_char_names)]
21
22 use makeover::{Oklab, Rgb, SemanticTokens, ThemeColors};
23
24 /// CIE L\*, the unit the theme files quote.
25 fn cie_l(c: Rgb) -> f32 {
26 let lin = |v: u8| {
27 let v = f32::from(v) / 255.0;
28 if v <= 0.04045 {
29 v / 12.92
30 } else {
31 ((v + 0.055) / 1.055).powf(2.4)
32 }
33 };
34 let (r, g, b) = c.tuple();
35 let y = 0.212_672_9 * lin(r) + 0.715_152_2 * lin(g) + 0.072_175_0 * lin(b);
36 let f = if y > 216.0 / 24389.0 {
37 y.cbrt()
38 } else {
39 ((24389.0 / 27.0) * y + 16.0) / 116.0
40 };
41 116.0 * f - 16.0
42 }
43
44 /// The same color at a new oklab L, hue and chroma untouched.
45 fn at_l(c: Rgb, l: f32) -> Rgb {
46 Rgb::from_oklab(Oklab { l, ..c.to_oklab() })
47 }
48
49 fn with_surfaces(theme: &ThemeColors, page: Rgb, raised: Rgb) -> SemanticTokens {
50 let mut colors = theme.colors.clone();
51 colors.insert("surface.page".into(), page.to_hex());
52 colors.insert("surface.raised".into(), raised.to_hex());
53 // Equal to raised in every house theme: an overlay is a raised surface that
54 // happens to float.
55 if colors.contains_key("surface.overlay") {
56 colors.insert("surface.overlay".into(), raised.to_hex());
57 }
58 makeover::resolve(&ThemeColors {
59 meta: theme.meta.clone(),
60 colors,
61 })
62 }
63
64 fn row(label: &str, page: Rgb, raised: Rgb, tokens: &SemanticTokens) {
65 let delta = raised.to_oklab().l - page.to_oklab().l;
66 // A well is cut into the page, so a page that has dropped past `sunken`
67 // leaves the theme claiming a recess that reads as a rise. The direction
68 // that drops the page runs into this before it runs out of gamut.
69 let inverted = tokens
70 .hex("surface-sunken")
71 .and_then(Rgb::from_hex)
72 .is_some_and(|sunken| sunken.to_oklab().l >= page.to_oklab().l);
73 println!(
74 "{label:<22} page {} raised {} delta {:.3} oklab / {:.1} L* bevel {} .. {}{}",
75 page.to_hex(),
76 raised.to_hex(),
77 delta,
78 cie_l(raised) - cie_l(page),
79 tokens.hex("bevel-light").unwrap_or("-"),
80 tokens.hex("bevel-dark").unwrap_or("-"),
81 if inverted {
82 " SUNKEN IS NO LONGER BELOW THE PAGE"
83 } else {
84 ""
85 },
86 );
87 }
88
89 fn main() {
90 let id = std::env::args()
91 .nth(1)
92 .unwrap_or_else(|| "makenotwork".into());
93 let dirs = vec![(
94 makeover::bundled_themes_dir().expect("run me from a checkout"),
95 false,
96 )];
97 let theme = makeover::load_theme(&dirs, &id).expect("no such theme");
98 let hex = |key: &str| Rgb::from_hex(&theme.colors[key]).expect("hex");
99 let (page, raised) = (hex("surface.page"), hex("surface.raised"));
100
101 println!("{id}, as shipped:");
102 row(
103 " current",
104 page,
105 raised,
106 &with_surfaces(&theme, page, raised),
107 );
108 println!(
109 "\nthe assertion's floor is 0.05 oklab; goingson sits at {:.3}, audiofiles at {:.3}\n",
110 0.119, 0.065
111 );
112
113 println!("lifting raised, page fixed:");
114 for delta in [0.070_f32, 0.085, 0.100, 0.119] {
115 let candidate = at_l(raised, page.to_oklab().l + delta);
116 let tokens = with_surfaces(&theme, page, candidate);
117 row(&format!(" delta {delta:.3}"), page, candidate, &tokens);
118 }
119
120 println!("\ndropping page, raised fixed:");
121 for delta in [0.070_f32, 0.085, 0.100, 0.119] {
122 let candidate = at_l(page, raised.to_oklab().l - delta);
123 let tokens = with_surfaces(&theme, candidate, raised);
124 row(&format!(" delta {delta:.3}"), candidate, raised, &tokens);
125 }
126 }
127