extern crate font_kit;
use font_kit::error::SelectionError;
use font_kit::family_name::FamilyName;
use font_kit::handle::Handle;
use font_kit::properties::Properties;
use std::ffi::OsStr;
#[cfg(feature = "source")]
use font_kit::source::SystemSource;
#[cfg(all(feature = "source", any(target_os = "windows", target_os = "macos")))]
macro_rules! match_handle {
($handle:expr, $path:expr, $index:expr) => {
match $handle {
Handle::Path {
ref path,
font_index,
} => {
assert_eq!(path, path);
assert_eq!(
font_index, $index,
"expecting font index {} not {}",
font_index, $index
);
}
Handle::Memory {
bytes: _,
font_index,
} => {
assert_eq!(
font_index, $index,
"expecting font index {} not {}",
font_index, $index
);
}
}
};
}
#[inline(always)]
fn check_filename(handle: &Handle, filename: &str) {
match *handle {
Handle::Path {
ref path,
font_index,
} => {
assert_eq!(path.file_name(), Some(OsStr::new(filename)));
assert_eq!(font_index, 0);
}
_ => panic!("Expected path handle!"),
}
}
#[cfg(all(feature = "source", target_os = "windows"))]
mod test {
use super::*;
#[test]
fn select_best_match_serif() {
let handle = SystemSource::new()
.select_best_match(&[FamilyName::Serif], &Properties::default())
.unwrap();
match_handle!(handle, "C:\\WINDOWS\\FONTS\\TIMES.TTF", 0);
}
#[test]
fn select_best_match_sans_serif() {
let handle = SystemSource::new()
.select_best_match(&[FamilyName::SansSerif], &Properties::default())
.unwrap();
match_handle!(handle, ":\\WINDOWS\\FONTS\\ARIAL.TTF", 0);
}
#[test]
fn select_best_match_monospace() {
let handle = SystemSource::new()
.select_best_match(&[FamilyName::Monospace], &Properties::default())
.unwrap();
match_handle!(handle, "C:\\WINDOWS\\FONTS\\COUR.TTF", 0);
}
#[test]
fn select_best_match_cursive() {
let handle = SystemSource::new()
.select_best_match(&[FamilyName::Cursive], &Properties::default())
.unwrap();
match_handle!(handle, "C:\\WINDOWS\\FONTS\\COMIC.TTF", 0);
}
#[test]
fn select_best_match_bold_sans_serif() {
let handle = SystemSource::new()
.select_best_match(
&[FamilyName::SansSerif],
&Properties {
style: font_kit::properties::Style::Normal,
weight: font_kit::properties::Weight::BOLD,
stretch: font_kit::properties::Stretch::NORMAL,
},
)
.unwrap();
match_handle!(handle, "C:\\WINDOWS\\FONTS\\ARIALBD.TTF", 0);
}
#[test]
fn select_best_match_by_name_after_invalid() {
let handle = SystemSource::new()
.select_best_match(
&[
FamilyName::Title("Invalid".to_string()),
FamilyName::Title("Times New Roman".to_string()),
],
&Properties::default(),
)
.unwrap();
match_handle!(handle, "C:\\WINDOWS\\FONTS\\TIMES.TTF", 0);
}
#[test]
fn select_family_by_name_arial() {
let family = SystemSource::new().select_family_by_name("Arial").unwrap();
assert_eq!(family.fonts().len(), 8);
match_handle!(family.fonts()[0], "C:\\WINDOWS\\FONTS\\ARIAL.TTF", 0);
match_handle!(family.fonts()[1], "C:\\WINDOWS\\FONTS\\ARIALI.TTF", 0);
match_handle!(family.fonts()[2], "C:\\WINDOWS\\FONTS\\ARIALBD.TTF", 0);
match_handle!(family.fonts()[3], "C:\\WINDOWS\\FONTS\\ARIALBI.TTF", 0);
match_handle!(family.fonts()[4], "C:\\WINDOWS\\FONTS\\ARIBLK.TTF", 0);
match_handle!(family.fonts()[5], "C:\\WINDOWS\\FONTS\\ARIAL.TTF", 0);
match_handle!(family.fonts()[6], "C:\\WINDOWS\\FONTS\\ARIALBD.TTF", 0);
match_handle!(family.fonts()[7], "C:\\WINDOWS\\FONTS\\ARIBLK.TTF", 0);
}
#[allow(non_snake_case)]
#[test]
fn select_by_postscript_name_ArialMT() {
let font = SystemSource::new()
.select_by_postscript_name("ArialMT")
.unwrap()
.load()
.unwrap();
assert_eq!(font.postscript_name().unwrap(), "ArialMT");
}
#[test]
fn select_by_postscript_name_invalid() {
match SystemSource::new().select_by_postscript_name("zxhjfgkadsfhg") {
Err(SelectionError::NotFound) => {}
other => panic!("unexpected error: {:?}", other),
}
}
#[test]
#[ignore]
fn select_localized_family_name() {
let handle = SystemSource::new()
.select_best_match(
&[FamilyName::Title("MS ゴシック".to_string())],
&Properties::default(),
)
.unwrap();
match_handle!(handle, "C:\\WINDOWS\\FONTS\\msgothic.ttc", 0);
}
}
#[cfg(all(feature = "source", target_os = "linux"))]
mod test {
use super::*;
#[test]
fn select_best_match_serif() {
let handle = SystemSource::new()
.select_best_match(&[FamilyName::Serif], &Properties::default())
.unwrap();
check_filename(&handle, "DejaVuSerif.ttf");
}
#[test]
fn select_best_match_sans_serif() {
let handle = SystemSource::new()
.select_best_match(&[FamilyName::SansSerif], &Properties::default())
.unwrap();
check_filename(&handle, "DejaVuSans.ttf");
}
#[test]
fn select_best_match_monospace() {
let handle = SystemSource::new()
.select_best_match(&[FamilyName::Monospace], &Properties::default())
.unwrap();
check_filename(&handle, "DejaVuSansMono.ttf");
}
#[test]
fn select_best_match_bold_sans_serif() {
let handle = SystemSource::new()
.select_best_match(
&[FamilyName::SansSerif],
&Properties {
style: font_kit::properties::Style::Normal,
weight: font_kit::properties::Weight::BOLD,
stretch: font_kit::properties::Stretch::NORMAL,
},
)
.unwrap();
check_filename(&handle, "DejaVuSans-Bold.ttf");
}
#[test]
fn select_best_match_by_name_after_invalid() {
let handle = SystemSource::new()
.select_best_match(
&[
FamilyName::Title("Invalid".to_string()),
FamilyName::Title("DejaVu Sans".to_string()),
],
&Properties::default(),
)
.unwrap();
check_filename(&handle, "DejaVuSans.ttf");
}
#[test]
fn select_family_by_name_dejavu() {
let family = SystemSource::new()
.select_family_by_name("DejaVu Sans")
.unwrap();
let filenames: Vec<String> = family
.fonts()
.iter()
.map(|handle| match *handle {
Handle::Path {
ref path,
font_index,
} => {
assert_eq!(font_index, 0);
path.file_name()
.expect("Where's the filename?")
.to_string_lossy()
.into_owned()
}
_ => panic!("Expected path handle!"),
})
.collect();
assert!(filenames.iter().any(|name| name == "DejaVuSans-Bold.ttf"));
assert!(filenames.iter().any(|name| name == "DejaVuSans.ttf"));
}
#[allow(non_snake_case)]
#[test]
fn select_by_postscript_name_ArialMT() {
let font = SystemSource::new()
.select_by_postscript_name("DejaVuSans")
.unwrap()
.load()
.unwrap();
assert_eq!(font.postscript_name().unwrap(), "DejaVuSans");
}
#[test]
fn select_by_postscript_name_invalid() {
match SystemSource::new().select_by_postscript_name("zxhjfgkadsfhg") {
Err(SelectionError::NotFound) => {}
other => panic!("unexpected error: {:?}", other),
}
}
#[test]
fn select_localized_family_name() {
if let Ok(handle) = SystemSource::new().select_best_match(
&[FamilyName::Title("さざなみゴシック".to_string())],
&Properties::default(),
) {
check_filename(&handle, "sazanami-gothic.ttf");
}
}
}
#[cfg(all(feature = "source", target_os = "macos"))]
mod test {
use super::*;
#[test]
fn select_best_match_serif() {
let handle = SystemSource::new()
.select_best_match(&[FamilyName::Serif], &Properties::default())
.unwrap();
match_handle!(handle, "/Library/Fonts/Times New Roman.ttf", 0);
}
#[test]
fn select_best_match_sans_serif() {
let handle = SystemSource::new()
.select_best_match(&[FamilyName::SansSerif], &Properties::default())
.unwrap();
match_handle!(handle, "/Library/Fonts/Arial.ttf", 0);
}
#[test]
fn select_best_match_monospace() {
let handle = SystemSource::new()
.select_best_match(&[FamilyName::Monospace], &Properties::default())
.unwrap();
match_handle!(handle, "/Library/Fonts/Courier New.ttf", 0);
}
#[test]
fn select_best_match_cursive() {
let handle = SystemSource::new()
.select_best_match(&[FamilyName::Cursive], &Properties::default())
.unwrap();
match_handle!(handle, "/Library/Fonts/Comic Sans MS.ttf", 0);
}
#[test]
fn select_best_match_fantasy() {
let handle = SystemSource::new()
.select_best_match(&[FamilyName::Fantasy], &Properties::default())
.unwrap();
match_handle!(handle, "/Library/Fonts/Papyrus.ttc", 1);
}
#[test]
fn select_best_match_bold_sans_serif() {
let handle = SystemSource::new()
.select_best_match(
&[FamilyName::SansSerif],
&Properties {
style: font_kit::properties::Style::Normal,
weight: font_kit::properties::Weight::BOLD,
stretch: font_kit::properties::Stretch::NORMAL,
},
)
.unwrap();
match_handle!(handle, "/Library/Fonts/Arial Bold.ttf", 0);
}
#[test]
fn select_best_match_by_name_after_invalid() {
let handle = SystemSource::new()
.select_best_match(
&[
FamilyName::Title("Invalid".to_string()),
FamilyName::Title("Times New Roman".to_string()),
],
&Properties::default(),
)
.unwrap();
match_handle!(handle, "/Library/Fonts/Times New Roman.ttf", 0);
}
#[test]
fn select_family_by_name_arial() {
let family = SystemSource::new().select_family_by_name("Arial").unwrap();
assert_eq!(family.fonts().len(), 4);
match_handle!(family.fonts()[0], "/Library/Fonts/Arial.ttf", 0);
match_handle!(family.fonts()[1], "/Library/Fonts/Arial Bold.ttf", 0);
match_handle!(family.fonts()[2], "/Library/Fonts/Arial Bold Italic.ttf", 0);
match_handle!(family.fonts()[3], "/Library/Fonts/Arial Italic.ttf", 0);
}
#[allow(non_snake_case)]
#[test]
fn select_by_postscript_name_ArialMT() {
let font = SystemSource::new()
.select_by_postscript_name("ArialMT")
.unwrap()
.load()
.unwrap();
assert_eq!(font.postscript_name().unwrap(), "ArialMT");
}
#[test]
fn select_by_postscript_name_invalid() {
match SystemSource::new().select_by_postscript_name("zxhjfgkadsfhg") {
Err(SelectionError::NotFound) => {}
other => panic!("unexpected error: {:?}", other),
}
}
#[test]
fn select_localized_family_name() {
let handle = SystemSource::new()
.select_best_match(
&[FamilyName::Title("רעננה".to_string())],
&Properties::default(),
)
.unwrap();
match_handle!(handle, "/Library/Fonts/Raanana.ttc", 0);
}
}