use crate::binary::read::{ReadBinary, ReadCtxt};
use crate::error::ParseError;
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub struct GaspBehavior {
pub flags: u16,
}
impl GaspBehavior {
pub const GRIDFIT: u16 = 0x0001;
pub const DOGRAY: u16 = 0x0002;
pub const SYMMETRIC_GRIDFIT: u16 = 0x0004;
pub const SYMMETRIC_SMOOTHING: u16 = 0x0008;
pub fn should_gridfit(self) -> bool {
self.flags & Self::GRIDFIT != 0
}
pub fn should_antialias(self) -> bool {
self.flags & Self::DOGRAY != 0
}
pub fn should_symmetric_gridfit(self) -> bool {
self.flags & Self::SYMMETRIC_GRIDFIT != 0
}
pub fn should_symmetric_smoothing(self) -> bool {
self.flags & Self::SYMMETRIC_SMOOTHING != 0
}
}
#[derive(Copy, Clone, Debug)]
pub struct GaspRange {
pub range_max_ppem: u16,
pub behavior: GaspBehavior,
}
#[derive(Clone, Debug)]
pub struct GaspTable {
pub version: u16,
pub ranges: Vec<GaspRange>,
}
impl GaspTable {
pub fn rendering_flags(&self, ppem: u16) -> GaspBehavior {
for range in &self.ranges {
if ppem <= range.range_max_ppem {
return range.behavior;
}
}
GaspBehavior {
flags: GaspBehavior::GRIDFIT | GaspBehavior::DOGRAY,
}
}
}
impl ReadBinary for GaspTable {
type HostType<'a> = GaspTable;
fn read<'a>(ctxt: &mut ReadCtxt<'a>) -> Result<Self::HostType<'a>, ParseError> {
let version = ctxt.read_u16be()?;
ctxt.check(version <= 1)?;
let num_ranges = ctxt.read_u16be()? as usize;
let mut ranges = Vec::with_capacity(num_ranges);
for _ in 0..num_ranges {
let range_max_ppem = ctxt.read_u16be()?;
let flags = ctxt.read_u16be()?;
ranges.push(GaspRange {
range_max_ppem,
behavior: GaspBehavior { flags },
});
}
Ok(GaspTable { version, ranges })
}
}