1#[cfg(feature = "encoding")]
51mod encoder;
52mod models;
53#[cfg(feature = "parsing")]
54mod parser;
55mod utils;
56
57#[cfg(feature = "encoding")]
58pub use crate::encoder::to_yaff_string;
59pub use crate::models::*;
60#[cfg(feature = "parsing")]
61pub use crate::parser::{classify_line, parse_key_as_label};
62pub use crate::utils::{
63 calculate_ascent, convert_codepoint_to_unicode_labels, minimize_all_bounding_boxes,
64 minimize_glyph_bounding_box, set_ascent,
65};
66#[cfg(feature = "parsing")]
67use std::fs::File;
68#[cfg(feature = "parsing")]
69use std::io::BufReader;
70#[cfg(feature = "parsing")]
71use std::path::Path;
72
73impl YaffFont {
74 pub fn new() -> Self {
75 Self::default()
76 }
77}
78
79#[cfg(feature = "parsing")]
80use std::str::FromStr;
81
82#[cfg(feature = "parsing")]
83impl FromStr for YaffFont {
84 type Err = ParseError;
85
86 fn from_str(s: &str) -> Result<Self, Self::Err> {
87 parser::from_str(s)
88 }
89}
90
91#[cfg(feature = "parsing")]
92impl YaffFont {
93
94 pub fn from_reader<R: std::io::Read>(mut reader: R) -> Result<YaffFont, ParseError> {
95 let mut buffer = String::new();
96 reader.read_to_string(&mut buffer)?;
97 Self::from_str(&buffer)
98 }
99
100 pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Self, ParseError> {
101 let file = File::open(path).map_err(ParseError::Io)?;
102 let reader = BufReader::new(file);
103 Self::from_reader(reader)
104 }
105}
106
107#[cfg(test)]
108mod tests {
109 use super::*;
110
111 #[test]
112 fn test_font_creation_and_defaults() {
113 let font = YaffFont::new();
114 assert!(font.name.is_none());
115 assert!(font.glyphs.is_empty());
116 assert_eq!(font.yaff_version, None);
117 }
118
119 #[test]
120 fn test_font_property_setting() {
121 let mut font = YaffFont::new();
122 font.name = Some("Test Font".to_string());
123 font.ascent = Some(10);
124 font.descent = Some(-2);
125
126 assert_eq!(font.name, Some("Test Font".to_string()));
127 assert_eq!(font.ascent, Some(10));
128 assert_eq!(font.descent, Some(-2));
129 }
130
131 #[test]
132 fn test_glyph_creation() {
133 let glyph = GlyphDefinition {
134 labels: vec![Label::Unicode(vec![65])], bitmap: Bitmap::default(),
136 left_bearing: Some(-1),
137 right_bearing: Some(2),
138 ..Default::default()
139 };
140
141 assert_eq!(glyph.labels.len(), 1);
142 assert_eq!(glyph.left_bearing, Some(-1));
143 assert_eq!(glyph.right_bearing, Some(2));
144 assert!(glyph.bitmap.pixels.is_empty());
145 }
146
147 #[test]
148 fn test_label_variants() {
149 let unicode_label = Label::Unicode(vec![65, 66]); let codepoint_label = Label::Codepoint(vec![65, 66]);
151 let tag_label = Label::Tag("my-tag".to_string());
152 let anonymous_label = Label::Anonymous;
153
154 assert!(matches!(unicode_label, Label::Unicode(_)));
155 assert!(matches!(codepoint_label, Label::Codepoint(_)));
156 assert!(matches!(tag_label, Label::Tag(_)));
157 assert!(matches!(anonymous_label, Label::Anonymous));
158 }
159
160 #[test]
161 fn test_bitmap_creation() {
162 let bitmap = Bitmap {
163 pixels: vec![vec![true, false, true], vec![false, true, false]],
164 width: 3,
165 height: 2,
166 };
167
168 assert_eq!(bitmap.width, 3);
169 assert_eq!(bitmap.height, 2);
170 assert_eq!(bitmap.pixels.len(), 2);
171 assert_eq!(bitmap.pixels[0].len(), 3);
172 }
173}