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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
use crate::{Expression, Value};

macro_rules! define_property {
    (
        $(
            $(#[$attr:meta])*
            $variant:ident($value_ty:ident, $name:expr),
        )+
    ) => {
        #[derive(Clone, Debug, PartialEq)]
        #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
        pub enum Property {
            $(
                $(#[$attr])*
                $variant(Expression),
            )+
            Dynamic(String, Expression),
        }

        impl Property {
            pub fn kind(&self) -> PropertyKind {
                match self {
                    $(
                        Property::$variant(_) => PropertyKind::$variant,
                    )+
                    Property::Dynamic(s, _) => PropertyKind::Dynamic(s.clone()),
                }
            }
        }

        #[derive(Clone, Debug, PartialEq, Eq)]
        #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
        pub enum PropertyKind {
            $(
                $(#[$attr])*
                $variant,
            )+
            Dynamic(String),
        }

        parse_enum! {
            PropertyKind,
            $(
                ($variant, $name),
            )+
            |s| Ok(PropertyKind::Dynamic(s.into())),
        }

        impl PropertyKind {
            pub fn make_property(self, expr: Expression) -> Property {
                match self {
                    $(
                        PropertyKind::$variant => Property::$variant(expr),
                    )+
                    PropertyKind::Dynamic(name) => Property::Dynamic(name.clone(), expr),
                }
            }
        }
    };
}

define_property! {
    /// Font family names
    Family(String, "family"),
    /// Languages corresponding to each family
    FamilyLang(String, "familylang"),
    /// Font style. Overrides weight and slant
    Style(String, "style"),
    /// Languages corresponding to each style
    StyleLang(String, "stylelang"),
    /// Font full names (often includes style)
    FullName(String, "fullname"),
    /// Languages corresponding to each fullname
    FullNameLang(String, "fullnamelang"),

    /// Italic, oblique or roman
    Slant(Int, "slant"),
    /// Light, medium, demibold, bold or black
    Weight(Int, "weight"),
    /// Point size
    Size(Double, "size"),
    /// Condensed, normal or expanded
    Width(Int, "width"),
    /// Stretches glyphs horizontally before hinting
    Aspect(Double, "aspect"),
    /// Pixel size
    PixelSize(Double, "pixelsize"),
    /// Proportional, dual-width, monospace or charcell
    Spacing(Int, "spacing"),
    /// Font foundry name
    Foundry(String, "foundry"),
    /// Whether glyphs can be antialiased
    Antialias(Bool, "antialias"),
    /// Whether the rasterizer should use hinting
    Hinting(Bool, "hinting"),
    /// Automatic hinting style
    HintStyle(Int, "hintstyle"),
    /// Automatic hinting style
    VerticalLayout(Bool, "verticallayout"),
    /// Use autohinter instead of normal hinter
    AutoHint(Bool, "autohint"),
    /// Use font global advance data (deprecated)
    GlobalAdvance(Bool, "globaladvance"),

    /// The filename holding the font
    File(String, "file"),
    /// The index of the font within the file
    Index(Int, "index"),
    // TODO:
    // /// Use the specified FreeType face object
    // Ftface(FT_Face),
    /// Which rasterizer is in use (deprecated)
    Rasterizer(String, "rasterizer"),
    /// Whether the glyphs are outlines
    Outline(Bool, "outline"),
    /// Whether glyphs can be scaled
    Scalable(Bool, "scalable"),
    /// Whether any glyphs have color
    Color(Bool, "color"),
    /// Scale factor for point->pixel conversions (deprecated)
    Scale(Double, "scale"),
    /// Target dots per inch
    Dpi(Double, "dpi"),
    /// unknown, rgb, bgr, vrgb, vbgr, none - subpixel geometry
    Rgba(Int, "rgba"),
    /// Type of LCD filter
    Lcdfilter(Int, "lcdfilter"),
    /// Eliminate leading from line spacing
    Minspace(Bool, "minspace"),
    /// Unicode chars encoded by the font
    Charset(CharSet, "charset"),
    /// List of RFC-3066-style languages this font supports
    Lang(String, "lang"),
    /// Version number of the font
    Fontversion(Int, "fontversion"),
    /// List of layout capabilities in the font
    Capability(String, "capability"),
    /// String name of the font format
    Fontformat(String, "fontformat"),
    /// Rasterizer should synthetically embolden the font
    Embolden(Bool, "embolden"),
    /// Use the embedded bitmap instead of the outline
    Embeddedbitmap(Bool, "embeddedbitmap"),
    /// Whether the style is a decorative variant
    Decorative(Bool, "decorative"),
    /// List of the feature tags in OpenType to be enabled
    Fontfeatures(String, "fontfeatures"),
    /// Language name to be used for the default value of familylang, stylelang, and fullnamelang
    Namelang(String, "namelang"),
    /// String  Name of the running program
    Prgname(String, "prgname"),
    /// Font family name in PostScript
    Postscriptname(String, "postscriptname"),
    /// Whether the font has hinting
    Fonthashint(Bool, "fonthashint"),
    /// Order number of the font
    Order(Int, "order"),

    // custom

    Matrix(Matrix, "matrix"),
    PixelSizeFixupFactor(Double, "pixelsizefixupfactor"),
    ScalingNotNeeded(Bool, "scalingnotneeded"),
}

impl Default for Property {
    fn default() -> Self {
        Property::Family(Expression::Simple(Value::String(String::default())))
    }
}

impl Default for PropertyKind {
    fn default() -> Self {
        PropertyKind::Family
    }
}