polygon-art/src/font.rs

141 lines
7.8 KiB
Rust

// props to https://trmm.net/Asteroids_font
// https://github.com/osresearch/vst/blob/master/teensyv/asteroids_font.c
use geo::algorithm::translate::Translate;
use geo::{Coordinate, LineString, MultiLineString};
use std::collections::HashMap;
pub struct AsteroidFont {
letters: HashMap<char, Vec<Vec<(i32, i32)>>>,
}
impl AsteroidFont {
#[rustfmt::skip]
pub fn new() -> Self {
let mut letters = HashMap::new();
letters.insert('0', vec![vec![(0, 0), (8, 0), (8, 12), (0, 12), (0, 0), (8, 12)]]);
letters.insert('1', vec![vec![(4, 0), (4, 12), (3, 10)]]);
letters.insert('2', vec![vec![(0, 12), (8, 12), (8, 7), (0, 5), (0, 0), (8, 0)]]);
letters.insert('3', vec![vec![(0, 12), (8, 12), (8, 0), (0, 0), ], vec![(0, 6), (8, 6)]]);
letters.insert('4', vec![vec![(0, 12), (0, 6), (8, 6), ], vec![(8, 12), (8, 0)]]);
letters.insert('5', vec![vec![(0, 0), (8, 0), (8, 6), (0, 7), (0, 12), (8, 12)]]);
letters.insert('6', vec![vec![(0, 12), (0, 0), (8, 0), (8, 5), (0, 7)]]);
letters.insert('7', vec![vec![(0, 12), (8, 12), (8, 6), (4, 0)]]);
letters.insert('8', vec![vec![(0, 0), (8, 0), (8, 12), (0, 12), (0, 0), ], vec![(0, 6), (8, 6)]]);
letters.insert('9', vec![vec![(8, 0), (8, 12), (0, 12), (0, 7), (8, 5)]]);
letters.insert(' ', vec![]);
letters.insert('.', vec![vec![(3, 0), (4, 0)]]);
letters.insert(',', vec![vec![(2, 0), (4, 2)]]);
letters.insert('-', vec![vec![(2, 6), (6, 6)]]);
letters.insert('+', vec![vec![(1, 6), (7, 6), ], vec![(4, 9), (4, 3)]]);
letters.insert('!', vec![vec![(4, 0), (3, 2), (5, 2), (4, 0), ], vec![(4, 4), (4, 12)]]);
letters.insert('#', vec![vec![(0, 4), (8, 4), (6, 2), (6, 10), (8, 8), (0, 8), (2, 10), (2, 2)]]);
letters.insert('^', vec![vec![(2, 6), (4, 12), (6, 6)]]);
letters.insert('=', vec![vec![(1, 4), (7, 4), ], vec![(1, 8), (7, 8)]]);
letters.insert('*', vec![vec![(0, 0), (4, 12), (8, 0), (0, 8), (8, 8), (0, 0)]]);
letters.insert('_', vec![vec![(0, 0), (8, 0)]]);
letters.insert('/', vec![vec![(0, 0), (8, 12)]]);
letters.insert('\\', vec![vec![(0, 12), (8, 0)]]);
letters.insert('@', vec![vec![(8, 4), (4, 0), (0, 4), (0, 8), (4, 12), (8, 8), (4, 4), (3, 6)]]);
letters.insert('$', vec![vec![(6, 2), (2, 6), (6, 10), ], vec![(4, 12), (4, 0)]]);
letters.insert('&', vec![vec![(8, 0), (4, 12), (8, 8), (0, 4), (4, 0), (8, 4)]]);
letters.insert('[', vec![vec![(6, 0), (2, 0), (2, 12), (6, 12)]]);
letters.insert(']', vec![vec![(2, 0), (6, 0), (6, 12), (2, 12)]]);
letters.insert('(', vec![vec![(6, 0), (2, 4), (2, 8), (6, 12)]]);
letters.insert(')', vec![vec![(2, 0), (6, 4), (6, 8), (2, 12)]]);
letters.insert('{', vec![vec![(6, 0), (4, 2), (4, 10), (6, 12), ], vec![(2, 6), (4, 6)]]);
letters.insert('}', vec![vec![(4, 0), (6, 2), (6, 10), (4, 12), ], vec![(6, 6), (8, 6)]]);
letters.insert('%', vec![vec![(0, 0), (8, 12), ], vec![(2, 10), (2, 8), ], vec![(6, 4), (6, 2)]]);
letters.insert('<', vec![vec![(6, 0), (2, 6), (6, 12)]]);
letters.insert('>', vec![vec![(2, 0), (6, 6), (2, 12)]]);
letters.insert('|', vec![vec![(4, 0), (4, 5), ], vec![(4, 6), (4, 12)]]);
letters.insert(':', vec![vec![(4, 9), (4, 7), ], vec![(4, 5), (4, 3)]]);
letters.insert(';', vec![vec![(4, 9), (4, 7), ], vec![(4, 5), (1, 2)]]);
letters.insert('"', vec![vec![(2, 10), (2, 6), ], vec![(6, 10), (6, 6)]]);
letters.insert('\'', vec![vec![(2, 6), (6, 10)]]);
letters.insert('`', vec![vec![(2, 10), (6, 6)]]);
letters.insert('~', vec![vec![(0, 4), (2, 8), (6, 4), (8, 8)]]);
letters.insert('?', vec![vec![(0, 8), (4, 12), (8, 8), (4, 4), ], vec![(4, 1), (4, 0)]]);
letters.insert('a', vec![vec![(0, 0), (0, 8), (4, 12), (8, 8), (8, 0), ], vec![(0, 4), (8, 4)]]);
letters.insert('b', vec![vec![(0, 0), (0, 12), (4, 12), (8, 10), (4, 6), (8, 2), (4, 0), (0, 0)]]);
letters.insert('c', vec![vec![(8, 0), (0, 0), (0, 12), (8, 12)]]);
letters.insert('d', vec![vec![(0, 0), (0, 12), (4, 12), (8, 8), (8, 4), (4, 0), (0, 0)]]);
letters.insert('e', vec![vec![(8, 0), (0, 0), (0, 12), (8, 12), ], vec![(0, 6), (6, 6)]]);
letters.insert('f', vec![vec![(0, 0), (0, 12), (8, 12), ], vec![(0, 6), (6, 6)]]);
letters.insert('g', vec![vec![(6, 6), (8, 4), (8, 0), (0, 0), (0, 12), (8, 12)]]);
letters.insert('h', vec![vec![(0, 0), (0, 12), ], vec![(0, 6), (8, 6), ], vec![(8, 12), (8, 0)]]);
letters.insert('i', vec![vec![(0, 0), (8, 0), ], vec![(4, 0), (4, 12), ], vec![(0, 12), (8, 12)]]);
letters.insert('j', vec![vec![(0, 4), (4, 0), (8, 0), (8, 12)]]);
letters.insert('k', vec![vec![(0, 0), (0, 12), ], vec![(8, 12), (0, 6), (6, 0)]]);
letters.insert('l', vec![vec![(8, 0), (0, 0), (0, 12)]]);
letters.insert('m', vec![vec![(0, 0), (0, 12), (4, 8), (8, 12), (8, 0)]]);
letters.insert('n', vec![vec![(0, 0), (0, 12), (8, 0), (8, 12)]]);
letters.insert('o', vec![vec![(0, 0), (0, 12), (8, 12), (8, 0), (0, 0)]]);
letters.insert('p', vec![vec![(0, 0), (0, 12), (8, 12), (8, 6), (0, 5)]]);
letters.insert('q', vec![vec![(0, 0), (0, 12), (8, 12), (8, 4), (0, 0), ], vec![(4, 4), (8, 0)]]);
letters.insert('r', vec![vec![(0, 0), (0, 12), (8, 12), (8, 6), (0, 5), ], vec![(4, 5), (8, 0)]]);
letters.insert('s', vec![vec![(0, 2), (2, 0), (8, 0), (8, 5), (0, 7), (0, 12), (6, 12), (8, 10)]]);
letters.insert('t', vec![vec![(0, 12), (8, 12), ], vec![(4, 12), (4, 0)]]);
letters.insert('u', vec![vec![(0, 12), (0, 2), (4, 0), (8, 2), (8, 12)]]);
letters.insert('v', vec![vec![(0, 12), (4, 0), (8, 12)]]);
letters.insert('w', vec![vec![(0, 12), (2, 0), (4, 4), (6, 0), (8, 12)]]);
letters.insert('x', vec![vec![(0, 0), (8, 12), ], vec![(0, 12), (8, 0)]]);
letters.insert('y', vec![vec![(0, 12), (4, 6), (8, 12), ], vec![(4, 6), (4, 0)]]);
letters.insert('z', vec![vec![(0, 12), (8, 12), (0, 0), (8, 0), ], vec![(2, 6), (6, 6)]]);
AsteroidFont {letters }
}
pub fn get_letter(&self, letter: &char, size: f64) -> Vec<LineString<f64>> {
let letter_coordinates = self.letters.get(&letter.to_ascii_lowercase()).unwrap();
let mut polygons: Vec<LineString<f64>> = Vec::new();
for letter_part in letter_coordinates.iter() {
let coordinates: Vec<Coordinate<f64>> = letter_part
.iter()
.map(|&(x, y)| Coordinate {
x: x as f64 * size / 12.,
y: (12. - y as f64) * size / 12.,
})
.collect();
polygons.push(LineString(coordinates));
}
polygons
}
/// size of space (per letter)
pub fn get_text_scale_factor(&self, size: f64) -> (f64, f64) {
let scale_factor = size / 12.;
(10.2 * scale_factor, 14.2 * scale_factor)
}
pub fn get_text(
&self,
text: String,
size: f64,
direction: FontDirection,
) -> MultiLineString<f64> {
let mut letters: Vec<LineString<f64>> = Vec::new();
let mut count = 0.;
for char in text.chars() {
let letter = self.get_letter(&char, size);
let (x_translate_factor, y_translate_factor) = self.get_text_scale_factor(size);
for character in letter.iter() {
match direction {
FontDirection::LeftRight => {
letters.push(character.translate(count * x_translate_factor, 0.))
}
FontDirection::TopDown => {
letters.push(character.translate(0., count * y_translate_factor))
}
}
}
count = count + 1.;
}
MultiLineString(letters)
}
}
pub enum FontDirection {
LeftRight,
TopDown,
}