Skip to main content

packed_font_derive/
lib.rs

1use 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}