glifparser/
pedantry.rs

1//! When reading .glif files, how strict ought we to be? Can we make fixes to
2//! bad input, or ought we to error out and make the user do it?
3use integer_or_float::IntegerOrFloat;
4
5#[derive(Constructor, Debug, Default, Copy, Clone, PartialEq, Eq)]
6pub struct Pedantry {
7    pub level: Level,
8    pub mend: Mend,
9}
10
11impl Pedantry {
12    pub fn should_mend(&self) -> bool {
13        !(self.level.is_sfnt() && self.mend.is_never())
14    }
15}
16
17#[derive(Derivative, Debug, Copy, Clone, PartialEq, Eq, IsVariant, Unwrap)]
18#[derivative(Default)]
19pub enum Mend {
20    #[derivative(Default(new="true"))]
21    Always,
22    Never,
23    UfoSpecErrorsOnly,
24    UfoSpecOutdatedOnly,
25}
26
27#[derive(Derivative, Debug, Copy, Clone, PartialEq, Eq, IsVariant, Unwrap)]
28#[derivative(Default)]
29pub enum Level {
30    #[derivative(Default(new="true"))]
31    /// Glifparser's permissive attitude to the spec
32    GlifParser,
33    /// Strict to the UFO spec
34    Ufo,
35    /// Strict to a UFO that will be used to make an OpenType font. For example,
36    /// this places limits on anchor values: a UfoPedantic `<anchor>` can have
37    /// float placement, while an OpenTypePedantic anchor cannot.
38    OpenType,
39    /// Strict to a UFO that will be used to make a TrueType font. This will
40    /// refuse floats everywhere but matrices, with the more important
41    /// consequence being every point location gets rounded to integer.
42    TrueType,
43}
44
45#[derive(Debug, Copy, Clone, PartialEq, Eq, IsVariant, Unwrap)]
46pub enum FloatClass {
47    Anchor,
48    AdvanceWidth
49}
50
51impl FloatClass {
52    fn should_round(&self) -> bool {
53        *self == FloatClass::Anchor
54    }
55}
56
57impl Level {
58    pub fn maybe_round(&self, f: IntegerOrFloat, fc: FloatClass) -> f32 {
59        if self.is_sfnt() && fc.should_round() {
60            f32::from(f).round()
61        } else {
62            f.into()
63        }
64    }
65
66    pub fn is_sfnt(&self) -> bool {
67        self.is_open_type() || self.is_true_type()
68    }
69}