1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
use crate::{FontRef, FontVec, VariableFont, VariationAxis};
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
use owned_ttf_parser::{self as ttfp, AsFaceRef, FaceMut};

impl VariableFont for FontRef<'_> {
    fn set_variation(&mut self, axis: &[u8; 4], value: f32) -> bool {
        let tag = ttfp::Tag::from_bytes(axis);
        // TODO remove existence check in next breaking version
        let exists = self
            .0
            .as_face_ref()
            .variation_axes()
            .into_iter()
            .any(|axis| axis.tag == tag);
        if exists {
            self.0.set_variation(tag, value);
        }
        exists
    }

    fn variations(&self) -> Vec<VariationAxis> {
        variations(self.0.as_face_ref())
    }
}

impl VariableFont for FontVec {
    fn set_variation(&mut self, axis: &[u8; 4], value: f32) -> bool {
        self.0
            .set_variation(ttfp::Tag::from_bytes(axis), value)
            .is_some()
    }

    fn variations(&self) -> Vec<VariationAxis> {
        variations(self.0.as_face_ref())
    }
}

fn variations(face: &ttfp::Face<'_>) -> Vec<VariationAxis> {
    face.variation_axes()
        .into_iter()
        .map(|axis| {
            #[cfg(feature = "std")]
            let name = face.names().into_iter().find_map(|n| {
                if n.name_id == axis.name_id {
                    n.to_string()
                } else {
                    None
                }
            });
            #[cfg(not(feature = "std"))]
            let name = None;
            VariationAxis {
                tag: axis.tag.to_bytes(),
                name,
                min_value: axis.min_value,
                default_value: axis.def_value,
                max_value: axis.max_value,
                hidden: axis.hidden,
            }
        })
        .collect()
}