use error::SelectionError;
use family::Family;
use family_handle::FamilyHandle;
use family_name::FamilyName;
use font::Font;
use handle::Handle;
use matching::{self, Description};
use properties::Properties;
#[cfg(all(target_os = "macos", not(feature = "source-fontconfig-default")))]
pub use sources::core_text::CoreTextSource as SystemSource;
#[cfg(all(target_family = "windows", not(feature = "source-fontconfig-default")))]
pub use sources::directwrite::DirectWriteSource as SystemSource;
#[cfg(any(not(any(target_os = "android", target_os = "macos", target_family = "windows")),
feature = "source-fontconfig-default"))]
pub use sources::fontconfig::FontconfigSource as SystemSource;
#[cfg(all(target_os = "android", not(feature = "source-fontconfig-default")))]
pub use sources::fs::FsSource as SystemSource;
#[cfg(any(target_family = "windows", target_os = "macos"))]
const DEFAULT_FONT_FAMILY_SERIF: &'static str = "Times New Roman";
#[cfg(any(target_family = "windows", target_os = "macos"))]
const DEFAULT_FONT_FAMILY_SANS_SERIF: &'static str = "Arial";
#[cfg(any(target_family = "windows", target_os = "macos"))]
const DEFAULT_FONT_FAMILY_MONOSPACE: &'static str = "Courier New";
#[cfg(any(target_family = "windows", target_os = "macos"))]
const DEFAULT_FONT_FAMILY_CURSIVE: &'static str = "Comic Sans MS";
#[cfg(any(target_family = "windows", target_os = "macos"))]
const DEFAULT_FONT_FAMILY_FANTASY: &'static str = "Papyrus";
#[cfg(not(any(target_family = "windows", target_os = "macos")))]
const DEFAULT_FONT_FAMILY_SERIF: &'static str = "DejaVu Serif";
#[cfg(not(any(target_family = "windows", target_os = "macos")))]
const DEFAULT_FONT_FAMILY_SANS_SERIF: &'static str = "DejaVu Sans";
#[cfg(not(any(target_family = "windows", target_os = "macos")))]
const DEFAULT_FONT_FAMILY_MONOSPACE: &'static str = "DejaVu Sans Mono";
#[cfg(not(any(target_family = "windows", target_os = "macos")))]
const DEFAULT_FONT_FAMILY_CURSIVE: &'static str = "DejaVu Sans";
#[cfg(not(any(target_family = "windows", target_os = "macos")))]
const DEFAULT_FONT_FAMILY_FANTASY: &'static str = "DejaVu Sans";
pub trait Source {
fn all_families(&self) -> Result<Vec<String>, SelectionError>;
fn select_family_by_name(&self, family_name: &str) -> Result<FamilyHandle, SelectionError>;
fn select_by_postscript_name(&self, postscript_name: &str) -> Result<Handle, SelectionError> {
for family_name in try!(self.all_families()) {
if let Ok(family_handle) = self.select_family_by_name(&family_name) {
if let Ok(family) = Family::<Font>::from_handle(&family_handle) {
for (handle, font) in family_handle.fonts().iter().zip(family.fonts().iter()) {
if let Some(font_postscript_name) = font.postscript_name() {
if font_postscript_name == postscript_name {
return Ok((*handle).clone())
}
}
}
}
}
}
Err(SelectionError::NotFound)
}
#[doc(hidden)]
fn select_family_by_generic_name(&self, family_name: &FamilyName)
-> Result<FamilyHandle, SelectionError> {
match *family_name {
FamilyName::Title(ref title) => self.select_family_by_name(title),
FamilyName::Serif => self.select_family_by_name(DEFAULT_FONT_FAMILY_SERIF),
FamilyName::SansSerif => self.select_family_by_name(DEFAULT_FONT_FAMILY_SANS_SERIF),
FamilyName::Monospace => self.select_family_by_name(DEFAULT_FONT_FAMILY_MONOSPACE),
FamilyName::Cursive => self.select_family_by_name(DEFAULT_FONT_FAMILY_CURSIVE),
FamilyName::Fantasy => self.select_family_by_name(DEFAULT_FONT_FAMILY_FANTASY),
}
}
#[inline]
fn select_best_match(&self, family_names: &[FamilyName], properties: &Properties)
-> Result<Handle, SelectionError> {
for family_name in family_names {
if let Ok(family_handle) = self.select_family_by_generic_name(family_name) {
let candidates = try!(self.select_descriptions_in_family(&family_handle));
if let Ok(index) = matching::find_best_match(&candidates, properties) {
return Ok(family_handle.fonts[index].clone())
}
}
}
Err(SelectionError::NotFound)
}
#[doc(hidden)]
fn select_descriptions_in_family(&self, family: &FamilyHandle)
-> Result<Vec<Description>, SelectionError> {
let mut fields = vec![];
for font_handle in family.fonts() {
let font = Font::from_handle(font_handle).unwrap();
let (family_name, properties) = (font.family_name(), font.properties());
fields.push(Description {
family_name,
properties,
})
}
Ok(fields)
}
}