nitai/projects
noxstrap / src / crates / nox-text / examples / specimen.rs
138 lines · 5.4 KB Raw
1use nox_gfx::canvas::{Canvas, Paint};
2use nox_gfx::color::{hex, rgba, Color};
3use nox_gfx::geom::{pt, Rect};
4use nox_text::{draw_text, measure, Font, GlyphCache, TextStyle};
5
6const BG: Color = hex(0x0e0e16);
7const FG: Color = hex(0xe8e8f2);
8const DIM: Color = hex(0x8a8aa5);
9const ACCENT: Color = hex(0x7c5cff);
10const CYAN: Color = hex(0x35d0ff);
11
12const SANS: &str = "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf";
13const SANS_BOLD: &str = "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf";
14const SERIF: &str = "/usr/share/fonts/truetype/dejavu/DejaVuSerif.ttf";
15const MONO: &str = "/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf";
16const LIB: &str = "/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf";
17
18fn main() {
19 let (w, h) = (1180usize, 1000usize);
20 let mut c = Canvas::new(w, h);
21 c.fill(
22 &{
23 let mut p = nox_gfx::path::Path::new();
24 p.rect(c.full());
25 p
26 },
27 &nox_gfx::geom::IDENTITY,
28 &Paint::vgrad(c.full(), hex(0x14141f), BG),
29 );
30
31 let sans_b = std::fs::read(SANS).unwrap();
32 let bold_b = std::fs::read(SANS_BOLD).unwrap();
33 let serif_b = std::fs::read(SERIF).unwrap();
34 let mono_b = std::fs::read(MONO).unwrap();
35 let lib_b = std::fs::read(LIB).unwrap();
36 let sans = Font::parse(&sans_b).unwrap();
37 let bold = Font::parse(&bold_b).unwrap();
38 let serif = Font::parse(&serif_b).unwrap();
39 let mono = Font::parse(&mono_b).unwrap();
40 let lib = Font::parse(&lib_b).unwrap();
41 let mut cache = GlyphCache::new();
42 cache.set_gamma(0.85);
43
44 let mut y = 62.0;
45 draw_text(&mut c, &mut cache, &bold, "Noxstrap", 60.0, y, TextStyle::new(46.0), FG);
46 let wdt = measure(&bold, "Noxstrap", TextStyle::new(46.0));
47 draw_text(
48 &mut c,
49 &mut cache,
50 &sans,
51 "every glyph here was parsed and rasterised by this repo",
52 60.0 + wdt + 16.0,
53 y,
54 TextStyle::new(14.0),
55 DIM,
56 );
57
58 y += 40.0;
59 c.fill_rect(Rect::new(60.0, y, 1120.0, y + 1.0), rgba(255, 255, 255, 26));
60
61 y += 40.0;
62 draw_text(&mut c, &mut cache, &bold, "SIZE LADDER", 60.0, y, TextStyle { px: 11.0, letter_spacing: 1.6, kerning: true }, CYAN);
63 y += 26.0;
64 for px in [8.0f32, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 16.0, 18.0, 21.0, 24.0, 30.0] {
65 draw_text(&mut c, &mut cache, &sans, &format!("{px:.0}"), 60.0, y, TextStyle::new(10.0), DIM);
66 draw_text(
67 &mut c,
68 &mut cache,
69 &sans,
70 "Handgloves Roblox 0123 — the quick brown fox",
71 92.0,
72 y,
73 TextStyle::new(px),
74 FG,
75 );
76 y += px * 1.42 + 5.0;
77 }
78
79 y += 18.0;
80 draw_text(&mut c, &mut cache, &bold, "KERNING", 60.0, y, TextStyle { px: 11.0, letter_spacing: 1.6, kerning: true }, CYAN);
81 y += 28.0;
82 for (label, kern) in [("off", false), ("on", true)] {
83 draw_text(&mut c, &mut cache, &sans, label, 60.0, y, TextStyle::new(11.0), DIM);
84 draw_text(
85 &mut c,
86 &mut cache,
87 &sans,
88 "AV Wa To LT V. Yo P, ff fi Type",
89 92.0,
90 y,
91 TextStyle { px: 26.0, letter_spacing: 0.0, kerning: kern },
92 if kern { FG } else { DIM },
93 );
94 y += 36.0;
95 }
96
97 y += 20.0;
98 draw_text(&mut c, &mut cache, &bold, "FACES", 60.0, y, TextStyle { px: 11.0, letter_spacing: 1.6, kerning: true }, CYAN);
99 y += 28.0;
100 for (name, f) in [
101 ("DejaVu Sans", &sans),
102 ("DejaVu Sans Bold", &bold),
103 ("DejaVu Serif", &serif),
104 ("DejaVu Sans Mono", &mono),
105 ("Liberation Sans", &lib),
106 ] {
107 draw_text(&mut c, &mut cache, &sans, name, 60.0, y, TextStyle::new(11.0), DIM);
108 draw_text(&mut c, &mut cache, f, "Bootstrapper — Ærøskøbing, naïve café 42%", 240.0, y, TextStyle::new(17.0), FG);
109 y += 30.0;
110 }
111
112 y += 16.0;
113 draw_text(&mut c, &mut cache, &bold, "COMPOSITES & COVERAGE", 60.0, y, TextStyle { px: 11.0, letter_spacing: 1.6, kerning: true }, CYAN);
114 y += 30.0;
115 draw_text(&mut c, &mut cache, &sans, "ÀÁÂÃÄÅ Çéèêë ñÑ öÖ üÜ ýÿ Ω→ ‹›«» ①②③ ★☆♠♥ ¼½¾ ≈≠≤≥", 60.0, y, TextStyle::new(22.0), FG);
116
117 y += 46.0;
118 let panel = Rect::new(60.0, y, 1120.0, y + 92.0);
119 let mut p = nox_gfx::path::Path::new();
120 p.rrect(panel, 12.0);
121 c.shadow(&p, &nox_gfx::geom::IDENTITY, 14.0, rgba(0, 0, 0, 150), pt(0.0, 6.0));
122 c.fill(&p, &nox_gfx::geom::IDENTITY, &Paint::vgrad(panel, hex(0x1b1b28), hex(0x15151f)));
123 c.stroke(&p, &nox_gfx::geom::IDENTITY, &Paint::Solid(rgba(255, 255, 255, 20)), &nox_gfx::canvas::Stroke::new(1.0));
124 draw_text(&mut c, &mut cache, &bold, "Installing Roblox", 84.0, y + 34.0, TextStyle::new(17.0), FG);
125 draw_text(&mut c, &mut cache, &mono, "version-a1b2c3d4e5f6 · 184.2 MB / 271.9 MB", 84.0, y + 58.0, TextStyle::new(12.5), DIM);
126 let track = Rect::new(84.0, y + 70.0, 1096.0, y + 76.0);
127 c.fill_rrect(track, 3.0, &Paint::Solid(rgba(255, 255, 255, 22)));
128 let fill = Rect::new(track.x0, track.y0, track.x0 + (track.x1 - track.x0) * 0.677, track.y1);
129 c.fill_rrect(fill, 3.0, &Paint::hgrad(fill, ACCENT, CYAN));
130
131 let out = std::env::args().nth(1).unwrap_or_else(|| "specimen.png".into());
132 std::fs::write(&out, c.to_png()).unwrap();
133 println!(
134 "wrote {out} ({} glyphs cached, {} KB)",
135 cache.len(),
136 cache.bytes() / 1024
137 );
138}