use write_fonts::types::Tag;
#[derive(Clone, Debug, Default)]
pub(crate) struct UnicodeRange([u32; 4]);
#[derive(Clone, Debug, Default)]
pub(crate) struct CodePageRange([u32; 2]);
#[derive(Clone, Debug, Default)]
pub(crate) struct Os2Builder {
pub us_weight_class: u16,
pub us_width_class: u16,
pub fs_type: u16,
pub s_family_class: i16,
pub panose_10: [u8; 10],
pub unicode_range: UnicodeRange,
pub ach_vend_id: Tag,
pub us_win_ascent: u16,
pub us_win_descent: u16,
pub code_page_range: CodePageRange,
pub sx_height: i16,
pub s_cap_height: i16,
pub s_typo_ascender: i16,
pub s_typo_descender: i16,
pub s_typo_line_gap: i16,
pub us_lower_optical_point_size: Option<u16>,
pub us_upper_optical_point_size: Option<u16>,
}
impl UnicodeRange {
pub(crate) fn set_bit(&mut self, bit: u8) {
set_bit_impl(&mut self.0, bit)
}
}
impl CodePageRange {
pub(crate) fn bit_for_code_page(val: u16) -> Option<u8> {
CODEPAGE_TO_BIT
.iter()
.find_map(|(page, bit)| if *page == val { Some(*bit) } else { None })
}
pub(crate) fn add_code_page(&mut self, page: u16) {
let bit = Self::bit_for_code_page(page).unwrap();
set_bit_impl(&mut self.0, bit)
}
}
fn set_bit_impl<const N: usize>(array: &mut [u32; N], bit: u8) {
assert!(bit < (32 * N) as u8);
let idx = (bit / 32) as usize;
let bit = bit % 32;
array[idx] |= 1 << bit;
}
impl Os2Builder {
pub fn build(&self) -> write_fonts::tables::os2::Os2 {
let [ul_code_page_range_1, ul_code_page_range_2] = self.code_page_range.0;
let [ul_unicode_range_1, ul_unicode_range_2, ul_unicode_range_3, ul_unicode_range_4] =
self.unicode_range.0;
write_fonts::tables::os2::Os2 {
us_weight_class: self.us_weight_class,
us_width_class: self.us_width_class,
fs_type: self.fs_type,
s_family_class: self.s_family_class,
ul_unicode_range_1,
ul_unicode_range_2,
ul_unicode_range_3,
ul_unicode_range_4,
panose_10: self.panose_10,
ach_vend_id: self.ach_vend_id,
s_typo_ascender: self.s_typo_ascender,
s_typo_descender: self.s_typo_descender,
s_typo_line_gap: self.s_typo_line_gap,
us_win_ascent: self.us_win_ascent,
us_win_descent: self.us_win_descent,
ul_code_page_range_1: Some(ul_code_page_range_1),
ul_code_page_range_2: Some(ul_code_page_range_2),
sx_height: Some(self.sx_height),
s_cap_height: Some(self.s_cap_height),
us_default_char: Some(0),
us_max_context: Some(0),
us_break_char: Some(0),
us_lower_optical_point_size: self.us_lower_optical_point_size,
us_upper_optical_point_size: self.us_upper_optical_point_size,
..Default::default()
}
}
}
static CODEPAGE_TO_BIT: &[(u16, u8)] = &[
(437, 63),
(708, 61),
(737, 60),
(775, 59),
(850, 62),
(852, 58),
(855, 57),
(857, 56),
(860, 55),
(861, 54),
(862, 53),
(863, 52),
(864, 51),
(865, 50),
(866, 49),
(869, 48),
(874, 16),
(932, 17),
(936, 18),
(949, 19),
(950, 20),
(1250, 1),
(1251, 2),
(1252, 0),
(1253, 3),
(1254, 4),
(1255, 5),
(1256, 6),
(1257, 7),
(1258, 8),
(1361, 21),
];