packed_font_derive/
lib.rs1use derive_syn_parse::Parse;
2use proc_macro::{self, TokenStream};
3use proc_macro_error::{abort_call_site, proc_macro_error};
4use quote::quote;
5use std::{fs::read, path::PathBuf};
6use syn::{LitInt, LitStr, Token, parse_macro_input};
7
8use packed_font_structs::{FontMetrics, all_chars};
9
10mod pack_font;
11mod render;
12use pack_font::CompressedFont;
13
14#[derive(Parse)]
15struct Input {
16 file: LitStr,
17 _comma: Token![,],
18 size: LitInt,
19}
20
21#[proc_macro]
22#[proc_macro_error]
23pub fn packed_font(tokens: TokenStream) -> TokenStream {
24 let Input { file, size, .. } = parse_macro_input!(tokens);
25 let src_file = file.span().file();
26 let file = file.value();
27 let size: u8 = size.base10_parse().expect("Size must be `u8`");
28
29 let src_file = PathBuf::from(src_file);
30 let file = PathBuf::from(file);
31 let file = if file.is_relative() {
32 if let Some(path) = src_file.parent() {
33 let mut path = path.to_owned();
34 path.push(file);
35 path
36 } else {
37 file
38 }
39 } else {
40 file
41 };
42 let bytes = match read(&file) {
43 Ok(file) => file,
44 Err(e) => abort_call_site!("Can't read file '{}': {}", &file.to_string_lossy(), e),
45 };
46
47 let CompressedFont {
48 metrics,
49 dict,
50 font_data,
51 } = match CompressedFont::compress(bytes, all_chars(), size as u32, &[][..]) {
52 Ok(packed) => packed,
53 Err(e) => abort_call_site!("Can't compress file '{}': {}", &file.to_string_lossy(), e),
54 };
55
56 let FontMetrics {
57 ascent,
58 descent,
59 leading,
60 } = metrics;
61
62 quote! {
63 ::packed_font::PackedFont {
64 metrics: ::packed_font::FontMetrics {
65 ascent: #ascent,
66 descent: #descent,
67 leading: #leading,
68 },
69 dict: &[
70 #(#dict),*
71 ],
72 data: &[
73 #(#font_data),*
74 ],
75 }
76 }
77 .into()
78}