pub const ADVANCE: f64 = 0.75;
struct Glyph {
ch: char,
strokes: &'static [&'static [(f32, f32)]],
}
const BOX: &[&[(f32, f32)]] = &[&[(0.0, 0.0), (6.0, 0.0), (6.0, 10.0), (0.0, 10.0), (0.0, 0.0)]];
fn glyph(ch: char) -> &'static [&'static [(f32, f32)]] {
let ch = ch.to_ascii_uppercase();
GLYPHS.iter().find(|g| g.ch == ch).map(|g| g.strokes).unwrap_or(BOX)
}
pub fn has_glyph(ch: char) -> bool {
let ch = ch.to_ascii_uppercase();
GLYPHS.iter().any(|g| g.ch == ch)
}
pub fn stroke_text(text: &str, origin: [f64; 3], right: [f64; 3], up: [f64; 3], height: f64) -> Vec<Vec<[f64; 3]>> {
let unit = height / 10.0;
let mut out = Vec::new();
let mut pen = 0.0;
for ch in text.chars() {
if ch != ' ' {
for stroke in glyph(ch) {
if stroke.len() < 2 {
continue;
}
out.push(
stroke
.iter()
.map(|&(x, y)| {
let dx = pen + x as f64 * unit;
let dy = y as f64 * unit;
[
origin[0] + right[0] * dx + up[0] * dy,
origin[1] + right[1] * dx + up[1] * dy,
origin[2] + right[2] * dx + up[2] * dy,
]
})
.collect(),
);
}
}
pen += ADVANCE * height;
}
out
}
pub fn text_width(text: &str, height: f64) -> f64 {
text.chars().count() as f64 * ADVANCE * height
}
static GLYPHS: &[Glyph] = &[
Glyph { ch: '0', strokes: &[&[(1.0, 0.0), (5.0, 0.0), (6.0, 1.0), (6.0, 9.0), (5.0, 10.0), (1.0, 10.0), (0.0, 9.0), (0.0, 1.0), (1.0, 0.0)]] },
Glyph { ch: '1', strokes: &[&[(1.0, 8.0), (3.0, 10.0), (3.0, 0.0)], &[(1.0, 0.0), (5.0, 0.0)]] },
Glyph { ch: '2', strokes: &[&[(0.0, 8.0), (1.0, 9.5), (3.0, 10.0), (5.0, 9.5), (6.0, 8.0), (6.0, 6.5), (0.0, 0.0), (6.0, 0.0)]] },
Glyph { ch: '3', strokes: &[&[(0.0, 9.0), (2.0, 10.0), (4.0, 10.0), (6.0, 8.5), (6.0, 6.5), (4.0, 5.0), (2.0, 5.0)], &[(4.0, 5.0), (6.0, 3.5), (6.0, 1.5), (4.0, 0.0), (2.0, 0.0), (0.0, 1.0)]] },
Glyph { ch: '4', strokes: &[&[(4.5, 0.0), (4.5, 10.0), (0.0, 3.0), (6.0, 3.0)]] },
Glyph { ch: '5', strokes: &[&[(6.0, 10.0), (1.0, 10.0), (0.5, 5.0), (2.0, 6.0), (4.0, 6.0), (6.0, 4.5), (6.0, 1.5), (4.0, 0.0), (2.0, 0.0), (0.0, 1.0)]] },
Glyph { ch: '6', strokes: &[&[(5.0, 10.0), (2.0, 10.0), (0.0, 8.0), (0.0, 2.0), (2.0, 0.0), (4.0, 0.0), (6.0, 2.0), (6.0, 4.0), (4.0, 6.0), (2.0, 6.0), (0.0, 4.0)]] },
Glyph { ch: '7', strokes: &[&[(0.0, 10.0), (6.0, 10.0), (2.0, 0.0)]] },
Glyph { ch: '8', strokes: &[&[(2.0, 5.0), (0.0, 6.5), (0.0, 8.5), (2.0, 10.0), (4.0, 10.0), (6.0, 8.5), (6.0, 6.5), (4.0, 5.0), (2.0, 5.0), (0.0, 3.5), (0.0, 1.5), (2.0, 0.0), (4.0, 0.0), (6.0, 1.5), (6.0, 3.5), (4.0, 5.0)]] },
Glyph { ch: '9', strokes: &[&[(6.0, 6.0), (4.0, 4.0), (2.0, 4.0), (0.0, 6.0), (0.0, 8.0), (2.0, 10.0), (4.0, 10.0), (6.0, 8.0), (6.0, 2.0), (4.0, 0.0), (1.0, 0.0)]] },
Glyph { ch: 'A', strokes: &[&[(0.0, 0.0), (3.0, 10.0), (6.0, 0.0)], &[(1.0, 3.5), (5.0, 3.5)]] },
Glyph { ch: 'B', strokes: &[&[(0.0, 0.0), (0.0, 10.0), (4.0, 10.0), (6.0, 8.5), (6.0, 6.5), (4.0, 5.0), (0.0, 5.0)], &[(4.0, 5.0), (6.0, 3.5), (6.0, 1.5), (4.0, 0.0), (0.0, 0.0)]] },
Glyph { ch: 'C', strokes: &[&[(6.0, 8.5), (4.0, 10.0), (2.0, 10.0), (0.0, 8.0), (0.0, 2.0), (2.0, 0.0), (4.0, 0.0), (6.0, 1.5)]] },
Glyph { ch: 'D', strokes: &[&[(0.0, 0.0), (0.0, 10.0), (3.0, 10.0), (6.0, 7.0), (6.0, 3.0), (3.0, 0.0), (0.0, 0.0)]] },
Glyph { ch: 'E', strokes: &[&[(6.0, 10.0), (0.0, 10.0), (0.0, 0.0), (6.0, 0.0)], &[(0.0, 5.0), (4.0, 5.0)]] },
Glyph { ch: 'F', strokes: &[&[(6.0, 10.0), (0.0, 10.0), (0.0, 0.0)], &[(0.0, 5.0), (4.0, 5.0)]] },
Glyph { ch: 'G', strokes: &[&[(6.0, 8.5), (4.0, 10.0), (2.0, 10.0), (0.0, 8.0), (0.0, 2.0), (2.0, 0.0), (4.0, 0.0), (6.0, 2.0), (6.0, 4.5), (3.5, 4.5)]] },
Glyph { ch: 'H', strokes: &[&[(0.0, 0.0), (0.0, 10.0)], &[(6.0, 0.0), (6.0, 10.0)], &[(0.0, 5.0), (6.0, 5.0)]] },
Glyph { ch: 'I', strokes: &[&[(1.0, 10.0), (5.0, 10.0)], &[(3.0, 10.0), (3.0, 0.0)], &[(1.0, 0.0), (5.0, 0.0)]] },
Glyph { ch: 'J', strokes: &[&[(6.0, 10.0), (6.0, 2.0), (4.0, 0.0), (2.0, 0.0), (0.0, 2.0)]] },
Glyph { ch: 'K', strokes: &[&[(0.0, 0.0), (0.0, 10.0)], &[(6.0, 10.0), (0.0, 4.0)], &[(2.0, 6.0), (6.0, 0.0)]] },
Glyph { ch: 'L', strokes: &[&[(0.0, 10.0), (0.0, 0.0), (6.0, 0.0)]] },
Glyph { ch: 'M', strokes: &[&[(0.0, 0.0), (0.0, 10.0), (3.0, 4.0), (6.0, 10.0), (6.0, 0.0)]] },
Glyph { ch: 'N', strokes: &[&[(0.0, 0.0), (0.0, 10.0), (6.0, 0.0), (6.0, 10.0)]] },
Glyph { ch: 'O', strokes: &[&[(2.0, 0.0), (4.0, 0.0), (6.0, 2.0), (6.0, 8.0), (4.0, 10.0), (2.0, 10.0), (0.0, 8.0), (0.0, 2.0), (2.0, 0.0)]] },
Glyph { ch: 'P', strokes: &[&[(0.0, 0.0), (0.0, 10.0), (4.0, 10.0), (6.0, 8.5), (6.0, 6.5), (4.0, 5.0), (0.0, 5.0)]] },
Glyph { ch: 'Q', strokes: &[&[(2.0, 0.0), (4.0, 0.0), (6.0, 2.0), (6.0, 8.0), (4.0, 10.0), (2.0, 10.0), (0.0, 8.0), (0.0, 2.0), (2.0, 0.0)], &[(3.5, 2.5), (6.5, -0.5)]] },
Glyph { ch: 'R', strokes: &[&[(0.0, 0.0), (0.0, 10.0), (4.0, 10.0), (6.0, 8.5), (6.0, 6.5), (4.0, 5.0), (0.0, 5.0)], &[(3.0, 5.0), (6.0, 0.0)]] },
Glyph { ch: 'S', strokes: &[&[(6.0, 8.5), (4.0, 10.0), (2.0, 10.0), (0.0, 8.5), (0.0, 6.5), (2.0, 5.0), (4.0, 5.0), (6.0, 3.5), (6.0, 1.5), (4.0, 0.0), (2.0, 0.0), (0.0, 1.5)]] },
Glyph { ch: 'T', strokes: &[&[(0.0, 10.0), (6.0, 10.0)], &[(3.0, 10.0), (3.0, 0.0)]] },
Glyph { ch: 'U', strokes: &[&[(0.0, 10.0), (0.0, 2.0), (2.0, 0.0), (4.0, 0.0), (6.0, 2.0), (6.0, 10.0)]] },
Glyph { ch: 'V', strokes: &[&[(0.0, 10.0), (3.0, 0.0), (6.0, 10.0)]] },
Glyph { ch: 'W', strokes: &[&[(0.0, 10.0), (1.5, 0.0), (3.0, 6.0), (4.5, 0.0), (6.0, 10.0)]] },
Glyph { ch: 'X', strokes: &[&[(0.0, 0.0), (6.0, 10.0)], &[(0.0, 10.0), (6.0, 0.0)]] },
Glyph { ch: 'Y', strokes: &[&[(0.0, 10.0), (3.0, 5.0), (6.0, 10.0)], &[(3.0, 5.0), (3.0, 0.0)]] },
Glyph { ch: 'Z', strokes: &[&[(0.0, 10.0), (6.0, 10.0), (0.0, 0.0), (6.0, 0.0)]] },
Glyph { ch: ' ', strokes: &[] },
Glyph { ch: '.', strokes: &[&[(2.5, 0.0), (3.5, 0.0), (3.5, 1.0), (2.5, 1.0), (2.5, 0.0)]] },
Glyph { ch: ',', strokes: &[&[(3.5, 1.0), (3.5, 0.0), (2.5, -1.5)]] },
Glyph { ch: ':', strokes: &[&[(2.5, 1.0), (3.5, 1.0), (3.5, 2.0), (2.5, 2.0), (2.5, 1.0)], &[(2.5, 6.0), (3.5, 6.0), (3.5, 7.0), (2.5, 7.0), (2.5, 6.0)]] },
Glyph { ch: ';', strokes: &[&[(2.5, 6.0), (3.5, 6.0), (3.5, 7.0), (2.5, 7.0), (2.5, 6.0)], &[(3.5, 1.0), (3.5, 0.0), (2.5, -1.5)]] },
Glyph { ch: '(', strokes: &[&[(4.5, 11.0), (2.5, 9.0), (2.0, 5.0), (2.5, 1.0), (4.5, -1.0)]] },
Glyph { ch: ')', strokes: &[&[(1.5, 11.0), (3.5, 9.0), (4.0, 5.0), (3.5, 1.0), (1.5, -1.0)]] },
Glyph { ch: '[', strokes: &[&[(4.5, 11.0), (2.0, 11.0), (2.0, -1.0), (4.5, -1.0)]] },
Glyph { ch: ']', strokes: &[&[(1.5, 11.0), (4.0, 11.0), (4.0, -1.0), (1.5, -1.0)]] },
Glyph { ch: '+', strokes: &[&[(3.0, 2.0), (3.0, 8.0)], &[(0.0, 5.0), (6.0, 5.0)]] },
Glyph { ch: '-', strokes: &[&[(0.5, 5.0), (5.5, 5.0)]] },
Glyph { ch: '−', strokes: &[&[(0.5, 5.0), (5.5, 5.0)]] },
Glyph { ch: '–', strokes: &[&[(0.5, 5.0), (5.5, 5.0)]] },
Glyph { ch: '±', strokes: &[&[(3.0, 3.5), (3.0, 9.5)], &[(0.0, 6.5), (6.0, 6.5)], &[(0.0, 1.0), (6.0, 1.0)]] },
Glyph { ch: '/', strokes: &[&[(0.5, -1.0), (5.5, 11.0)]] },
Glyph { ch: '×', strokes: &[&[(1.0, 2.0), (5.0, 8.0)], &[(1.0, 8.0), (5.0, 2.0)]] },
Glyph { ch: '°', strokes: &[&[(4.5, 8.5), (4.214, 9.382), (3.464, 9.927), (2.536, 9.927), (1.786, 9.382), (1.5, 8.5), (1.786, 7.618), (2.536, 7.073), (3.464, 7.073), (4.214, 7.618), (4.5, 8.5)]] },
Glyph { ch: '\'', strokes: &[&[(3.0, 10.0), (3.0, 7.0)]] },
Glyph { ch: '"', strokes: &[&[(2.0, 10.0), (2.0, 7.0)], &[(4.0, 10.0), (4.0, 7.0)]] },
Glyph { ch: '%', strokes: &[&[(3.0, 8.0), (2.714, 8.882), (1.964, 9.427), (1.036, 9.427), (0.286, 8.882), (0.0, 8.0), (0.286, 7.118), (1.036, 6.573), (1.964, 6.573), (2.714, 7.118), (3.0, 8.0)], &[(6.0, 2.0), (5.714, 2.882), (4.964, 3.427), (4.036, 3.427), (3.286, 2.882), (3.0, 2.0), (3.286, 1.118), (4.036, 0.573), (4.964, 0.573), (5.714, 1.118), (6.0, 2.0)], &[(0.0, 0.0), (6.0, 10.0)]] },
Glyph { ch: '=', strokes: &[&[(0.0, 3.5), (6.0, 3.5)], &[(0.0, 6.5), (6.0, 6.5)]] },
Glyph { ch: '<', strokes: &[&[(6.0, 9.0), (0.0, 5.0), (6.0, 1.0)]] },
Glyph { ch: '>', strokes: &[&[(0.0, 9.0), (6.0, 5.0), (0.0, 1.0)]] },
Glyph { ch: '!', strokes: &[&[(3.0, 10.0), (3.0, 3.0)], &[(2.5, 0.0), (3.5, 0.0), (3.5, 1.0), (2.5, 1.0), (2.5, 0.0)]] },
Glyph { ch: '?', strokes: &[&[(0.0, 8.0), (1.0, 9.5), (3.0, 10.0), (5.0, 9.5), (6.0, 8.0), (6.0, 6.5), (3.0, 4.5), (3.0, 3.0)], &[(2.5, 0.0), (3.5, 0.0), (3.5, 1.0), (2.5, 1.0), (2.5, 0.0)]] },
Glyph { ch: '&', strokes: &[&[(6.0, 0.0), (1.0, 6.0), (0.5, 8.0), (1.5, 10.0), (3.0, 10.0), (4.5, 8.5), (4.0, 7.0), (0.5, 3.5), (0.5, 1.5), (2.0, 0.0), (3.5, 0.0), (6.0, 3.0)]] },
Glyph { ch: '*', strokes: &[&[(3.0, 4.0), (3.0, 10.0)], &[(0.5, 5.5), (5.5, 8.5)], &[(0.5, 8.5), (5.5, 5.5)]] },
Glyph { ch: '_', strokes: &[&[(0.0, -1.0), (6.0, -1.0)]] },
Glyph { ch: '#', strokes: &[&[(1.5, 0.0), (2.5, 10.0)], &[(3.5, 0.0), (4.5, 10.0)], &[(0.0, 3.5), (6.0, 3.5)], &[(0.0, 6.5), (6.0, 6.5)]] },
Glyph { ch: '|', strokes: &[&[(3.0, -1.0), (3.0, 11.0)]] },
Glyph { ch: '⌀', strokes: &[&[(7.0, 5.0), (6.696, 6.531), (5.828, 7.828), (4.531, 8.696), (3.0, 9.0), (1.469, 8.696), (0.172, 7.828), (-0.696, 6.531), (-1.0, 5.0), (-0.696, 3.469), (0.172, 2.172), (1.469, 1.304), (3.0, 1.0), (4.531, 1.304), (5.828, 2.172), (6.696, 3.469), (7.0, 5.0)], &[(0.0, 0.0), (6.0, 10.0)]] },
Glyph { ch: 'Ø', strokes: &[&[(7.0, 5.0), (6.696, 6.531), (5.828, 7.828), (4.531, 8.696), (3.0, 9.0), (1.469, 8.696), (0.172, 7.828), (-0.696, 6.531), (-1.0, 5.0), (-0.696, 3.469), (0.172, 2.172), (1.469, 1.304), (3.0, 1.0), (4.531, 1.304), (5.828, 2.172), (6.696, 3.469), (7.0, 5.0)], &[(0.0, 0.0), (6.0, 10.0)]] },
Glyph { ch: '⌴', strokes: &[&[(0.0, 8.0), (0.0, 2.0), (6.0, 2.0), (6.0, 8.0)]] },
Glyph { ch: '⌵', strokes: &[&[(0.0, 8.0), (3.0, 2.0), (6.0, 8.0)]] },
Glyph { ch: '↧', strokes: &[&[(3.0, 10.0), (3.0, 2.0)], &[(1.0, 4.0), (3.0, 2.0), (5.0, 4.0)], &[(0.0, 0.0), (6.0, 0.0)]] },
Glyph { ch: '△', strokes: &[&[(0.0, 0.0), (6.0, 0.0), (3.0, 10.0), (0.0, 0.0)]] },
Glyph { ch: '⌖', strokes: &[&[(6.0, 5.0), (5.772, 6.148), (5.121, 7.121), (4.148, 7.772), (3.0, 8.0), (1.852, 7.772), (0.879, 7.121), (0.228, 6.148), (0.0, 5.0), (0.228, 3.852), (0.879, 2.879), (1.852, 2.228), (3.0, 2.0), (4.148, 2.228), (5.121, 2.879), (5.772, 3.852), (6.0, 5.0)], &[(3.0, 0.0), (3.0, 10.0)], &[(0.0, 5.0), (6.0, 5.0)]] },
Glyph { ch: 'Ⓜ', strokes: &[&[(7.0, 5.0), (6.804, 6.236), (6.236, 7.351), (5.351, 8.236), (4.236, 8.804), (3.0, 9.0), (1.764, 8.804), (0.649, 8.236), (-0.236, 7.351), (-0.804, 6.236), (-1.0, 5.0), (-0.804, 3.764), (-0.236, 2.649), (0.649, 1.764), (1.764, 1.196), (3.0, 1.0), (4.236, 1.196), (5.351, 1.764), (6.236, 2.649), (6.804, 3.764), (7.0, 5.0)], &[(1.3, 2.6), (1.3, 7.4), (3.0, 4.8), (4.7, 7.4), (4.7, 2.6)]] },
Glyph { ch: 'Ⓛ', strokes: &[&[(7.0, 5.0), (6.804, 6.236), (6.236, 7.351), (5.351, 8.236), (4.236, 8.804), (3.0, 9.0), (1.764, 8.804), (0.649, 8.236), (-0.236, 7.351), (-0.804, 6.236), (-1.0, 5.0), (-0.804, 3.764), (-0.236, 2.649), (0.649, 1.764), (1.764, 1.196), (3.0, 1.0), (4.236, 1.196), (5.351, 1.764), (6.236, 2.649), (6.804, 3.764), (7.0, 5.0)], &[(1.8, 7.2), (1.8, 2.8), (4.4, 2.8)]] },
Glyph { ch: '⏤', strokes: &[&[(0.0, 5.0), (6.0, 5.0)]] },
Glyph { ch: '⏥', strokes: &[&[(1.5, 2.0), (6.0, 2.0), (4.5, 8.0), (0.0, 8.0), (1.5, 2.0)]] },
Glyph { ch: '○', strokes: &[&[(7.0, 5.0), (6.696, 6.531), (5.828, 7.828), (4.531, 8.696), (3.0, 9.0), (1.469, 8.696), (0.172, 7.828), (-0.696, 6.531), (-1.0, 5.0), (-0.696, 3.469), (0.172, 2.172), (1.469, 1.304), (3.0, 1.0), (4.531, 1.304), (5.828, 2.172), (6.696, 3.469), (7.0, 5.0)]] },
Glyph { ch: '⌭', strokes: &[&[(0.5, 0.0), (0.5, 10.0)], &[(5.5, 0.0), (5.5, 10.0)], &[(5.5, 5.0), (5.31, 5.957), (4.768, 6.768), (3.957, 7.31), (3.0, 7.5), (2.043, 7.31), (1.232, 6.768), (0.69, 5.957), (0.5, 5.0), (0.69, 4.043), (1.232, 3.232), (2.043, 2.69), (3.0, 2.5), (3.957, 2.69), (4.768, 3.232), (5.31, 4.043), (5.5, 5.0)]] },
Glyph { ch: '⌒', strokes: &[&[(6.0, 3.0), (5.853, 3.927), (5.427, 4.763), (4.763, 5.427), (3.927, 5.853), (3.0, 6.0), (2.073, 5.853), (1.237, 5.427), (0.573, 4.763), (0.147, 3.927), (0.0, 3.0)]] },
Glyph { ch: '⌓', strokes: &[&[(6.0, 3.0), (5.853, 3.927), (5.427, 4.763), (4.763, 5.427), (3.927, 5.853), (3.0, 6.0), (2.073, 5.853), (1.237, 5.427), (0.573, 4.763), (0.147, 3.927), (0.0, 3.0)], &[(0.0, 3.0), (6.0, 3.0)]] },
Glyph { ch: '∠', strokes: &[&[(6.0, 0.0), (0.0, 0.0), (4.5, 7.0)]] },
Glyph { ch: '⟂', strokes: &[&[(0.0, 0.0), (6.0, 0.0)], &[(3.0, 0.0), (3.0, 10.0)]] },
Glyph { ch: '∥', strokes: &[&[(0.5, 0.0), (2.5, 10.0)], &[(3.5, 0.0), (5.5, 10.0)]] },
Glyph { ch: '◎', strokes: &[&[(7.0, 5.0), (6.696, 6.531), (5.828, 7.828), (4.531, 8.696), (3.0, 9.0), (1.469, 8.696), (0.172, 7.828), (-0.696, 6.531), (-1.0, 5.0), (-0.696, 3.469), (0.172, 2.172), (1.469, 1.304), (3.0, 1.0), (4.531, 1.304), (5.828, 2.172), (6.696, 3.469), (7.0, 5.0)], &[(5.0, 5.0), (4.732, 6.0), (4.0, 6.732), (3.0, 7.0), (2.0, 6.732), (1.268, 6.0), (1.0, 5.0), (1.268, 4.0), (2.0, 3.268), (3.0, 3.0), (4.0, 3.268), (4.732, 4.0), (5.0, 5.0)]] },
Glyph { ch: '⌯', strokes: &[&[(0.0, 5.0), (6.0, 5.0)], &[(1.5, 7.5), (4.5, 7.5)], &[(1.5, 2.5), (4.5, 2.5)]] },
Glyph { ch: '↗', strokes: &[&[(0.0, 0.0), (6.0, 10.0)], &[(2.5, 10.0), (6.0, 10.0), (6.0, 6.5)]] },
Glyph { ch: '⌰', strokes: &[&[(0.0, 0.0), (6.0, 0.0)], &[(0.5, 0.0), (3.5, 7.0)], &[(1.5, 7.0), (3.5, 7.0), (3.5, 5.0)], &[(2.5, 0.0), (5.5, 7.0)], &[(3.5, 7.0), (5.5, 7.0), (5.5, 5.0)]] },
Glyph { ch: '↔', strokes: &[&[(0.0, 5.0), (6.0, 5.0)], &[(2.0, 7.0), (0.0, 5.0), (2.0, 3.0)], &[(4.0, 7.0), (6.0, 5.0), (4.0, 3.0)]] },
];