aboutsummaryrefslogtreecommitdiff
path: root/font
diff options
context:
space:
mode:
Diffstat (limited to 'font')
-rw-r--r--font/src/darwin/mod.rs63
-rw-r--r--font/src/ft/list_fonts.rs396
-rw-r--r--font/src/ft/mod.rs102
-rw-r--r--font/src/lib.rs37
4 files changed, 436 insertions, 162 deletions
diff --git a/font/src/darwin/mod.rs b/font/src/darwin/mod.rs
index 99f080ab..35336df9 100644
--- a/font/src/darwin/mod.rs
+++ b/font/src/darwin/mod.rs
@@ -19,6 +19,8 @@
use std::collections::HashMap;
use std::ptr;
+use ::{Slant, Weight, Style};
+
use core_foundation::base::TCFType;
use core_foundation::string::{CFString, CFStringRef};
use core_foundation::array::CFIndex;
@@ -36,6 +38,7 @@ use core_text::font_descriptor::kCTFontDefaultOrientation;
use core_text::font_descriptor::kCTFontHorizontalOrientation;
use core_text::font_descriptor::kCTFontVerticalOrientation;
use core_text::font_descriptor::{CTFontDescriptor, CTFontDescriptorRef, CTFontOrientation};
+use core_text::font_descriptor::SymbolicTraitAccessors;
use libc::{size_t, c_int};
@@ -166,10 +169,15 @@ impl ::Rasterize for Rasterizer {
}
impl Rasterizer {
- fn get_font(&mut self, desc: &FontDesc, size: Size) -> Result<Font, Error> {
+ fn get_specific_face(
+ &mut self,
+ desc: &FontDesc,
+ style: &str,
+ size: Size
+ ) -> Result<Font, Error> {
let descriptors = descriptors_for_family(&desc.name[..]);
for descriptor in descriptors {
- if descriptor.style_name == desc.style {
+ if descriptor.style_name == style {
// Found the font we want
let scaled_size = size.as_f32_pts() as f64 * self.device_pixel_ratio as f64;
let font = descriptor.to_font(scaled_size);
@@ -179,6 +187,44 @@ impl Rasterizer {
Err(Error::MissingFont(desc.to_owned()))
}
+
+ fn get_matching_face(
+ &mut self,
+ desc: &FontDesc,
+ slant: Slant,
+ weight: Weight,
+ size: Size
+ ) -> Result<Font, Error> {
+ let bold = match weight {
+ Weight::Bold => true,
+ _ => false
+ };
+ let italic = match slant {
+ Slant::Normal => false,
+ _ => true,
+ };
+ let scaled_size = size.as_f32_pts() as f64 * self.device_pixel_ratio as f64;
+
+ let descriptors = descriptors_for_family(&desc.name[..]);
+ for descriptor in descriptors {
+ let font = descriptor.to_font(scaled_size);
+ if font.is_bold() == bold && font.is_italic() == italic {
+ // Found the font we want
+ return Ok(font);
+ }
+ }
+
+ Err(Error::MissingFont(desc.to_owned()))
+ }
+
+ fn get_font(&mut self, desc: &FontDesc, size: Size) -> Result<Font, Error> {
+ match desc.style {
+ Style::Specific(ref style) => self.get_specific_face(desc, style, size),
+ Style::Description { slant, weight } => {
+ self.get_matching_face(desc, slant, weight, size)
+ },
+ }
+ }
}
/// Specifies the intended rendering orientation of the font for obtaining glyph metrics
@@ -290,6 +336,14 @@ impl Font {
}
}
+ pub fn is_bold(&self) -> bool {
+ self.ct_font.symbolic_traits().is_bold()
+ }
+
+ pub fn is_italic(&self) -> bool {
+ self.ct_font.symbolic_traits().is_italic()
+ }
+
fn glyph_advance(&self, character: char) -> f64 {
let index = self.glyph_index(character).unwrap();
@@ -539,12 +593,9 @@ mod tests {
.collect::<Vec<_>>();
for font in fonts {
- // Check deref
- println!("family: {}", font.family_name());
-
// Get a glyph
for c in &['a', 'b', 'c', 'd'] {
- let glyph = font.get_glyph(*c, 72.);
+ let glyph = font.get_glyph(*c, 72.).unwrap();
// Debug the glyph.. sigh
for row in 0..glyph.height {
diff --git a/font/src/ft/list_fonts.rs b/font/src/ft/list_fonts.rs
index 0fbc7231..29912a8f 100644
--- a/font/src/ft/list_fonts.rs
+++ b/font/src/ft/list_fonts.rs
@@ -12,28 +12,31 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//
-use std::collections::HashMap;
-use std::fmt;
-use std::path::PathBuf;
-
-mod fc {
+pub mod fc {
use std::ptr;
use std::ffi::{CStr, CString};
use std::str;
use std::ops::Deref;
+ use std::path::PathBuf;
- use ffi_util::ForeignTypeRef;
+ use ffi_util::{ForeignType, ForeignTypeRef};
use libc::{c_char, c_int};
use fontconfig::fontconfig as ffi;
use self::ffi::{FcConfigGetCurrent, FcConfigGetFonts, FcSetSystem, FcSetApplication};
use self::ffi::{FcPatternGetString, FcPatternCreate, FcPatternAddString};
- use self::ffi::{FcPatternGetInteger};
+ use self::ffi::{FcPatternGetInteger, FcPatternAddInteger};
use self::ffi::{FcObjectSetCreate, FcObjectSetAdd};
- use self::ffi::{FcResultMatch, FcFontSetList};
- use self::ffi::{FcChar8, FcConfig, FcPattern, FcFontSet, FcObjectSet};
+ use self::ffi::{FcResultMatch, FcResultNoMatch, FcFontSetList};
+ use self::ffi::{FcChar8, FcConfig, FcPattern, FcFontSet, FcObjectSet, FcCharSet};
use self::ffi::{FcFontSetDestroy, FcPatternDestroy, FcObjectSetDestroy, FcConfigDestroy};
+ use self::ffi::{FcFontMatch, FcFontList, FcFontSort, FcConfigSubstitute, FcDefaultSubstitute};
+ use self::ffi::{FcMatchFont, FcMatchPattern, FcMatchScan, FC_SLANT_ITALIC, FC_SLANT_ROMAN};
+ use self::ffi::{FC_SLANT_OBLIQUE};
+ use self::ffi::{FC_WEIGHT_THIN, FC_WEIGHT_EXTRALIGHT, FC_WEIGHT_LIGHT};
+ use self::ffi::{FC_WEIGHT_BOOK, FC_WEIGHT_REGULAR, FC_WEIGHT_MEDIUM, FC_WEIGHT_SEMIBOLD};
+ use self::ffi::{FC_WEIGHT_BOLD, FC_WEIGHT_EXTRABOLD, FC_WEIGHT_BLACK, FC_WEIGHT_EXTRABLACK};
/// Iterator over a font set
pub struct FontSetIter<'a> {
@@ -48,6 +51,7 @@ mod fc {
ffi_type!(FontSet, FontSetRef, FcFontSet, FcFontSetDestroy);
impl ObjectSet {
+ #[allow(dead_code)]
pub fn new() -> ObjectSet {
ObjectSet(unsafe {
FcObjectSetCreate()
@@ -55,6 +59,89 @@ mod fc {
}
}
+ /// Find the font closest matching the provided pattern.
+ #[allow(dead_code)]
+ pub fn font_match(
+ config: &ConfigRef,
+ pattern: &mut PatternRef,
+ ) -> Option<Pattern> {
+ pattern.config_subsitute(config, MatchKind::Pattern);
+ pattern.default_substitute();
+
+ unsafe {
+ // What is this result actually used for? Seems redundant with
+ // return type.
+ let mut result = FcResultNoMatch;
+ let ptr = FcFontMatch(
+ config.as_ptr(),
+ pattern.as_ptr(),
+ &mut result,
+ );
+
+ if ptr.is_null() {
+ None
+ } else {
+ Some(Pattern::from_ptr(ptr))
+ }
+ }
+ }
+
+ /// list fonts by closeness to the pattern
+ pub fn font_sort(
+ config: &ConfigRef,
+ pattern: &mut PatternRef,
+ ) -> Option<FontSet> {
+ pattern.config_subsitute(config, MatchKind::Pattern);
+ pattern.default_substitute();
+
+ unsafe {
+ // What is this result actually used for? Seems redundant with
+ // return type.
+ let mut result = FcResultNoMatch;
+
+ let mut charsets: *mut FcCharSet = ptr::null_mut();
+
+ let ptr = FcFontSort(
+ config.as_ptr(),
+ pattern.as_ptr(),
+ 0, // false
+ &mut charsets,
+ &mut result,
+ );
+
+ if ptr.is_null() {
+ None
+ } else {
+ Some(FontSet::from_ptr(ptr))
+ }
+ }
+ }
+
+ /// List fonts matching pattern
+ #[allow(dead_code)]
+ pub fn font_list(
+ config: &ConfigRef,
+ pattern: &mut PatternRef,
+ objects: &ObjectSetRef,
+ ) -> Option<FontSet> {
+ pattern.config_subsitute(config, MatchKind::Pattern);
+ pattern.default_substitute();
+
+ unsafe {
+ let ptr = FcFontList(
+ config.as_ptr(),
+ pattern.as_ptr(),
+ objects.as_ptr(),
+ );
+
+ if ptr.is_null() {
+ None
+ } else {
+ Some(FontSet::from_ptr(ptr))
+ }
+ }
+ }
+
impl ObjectSetRef {
fn add(&mut self, property: &[u8]) {
unsafe {
@@ -79,13 +166,28 @@ mod fc {
}
macro_rules! pattern_add_string {
- ($name:ident => $object:expr) => {
- #[inline]
- pub fn $name(&mut self, value: &str) -> bool {
- unsafe {
- self.add_string($object, value)
+ ($($name:ident => $object:expr),*) => {
+ $(
+ #[inline]
+ pub fn $name(&mut self, value: &str) -> bool {
+ unsafe {
+ self.add_string($object, value)
+ }
}
- }
+ )*
+ }
+ }
+
+ macro_rules! pattern_add_int {
+ ($($name:ident => $object:expr),*) => {
+ $(
+ #[inline]
+ pub fn $name(&mut self, value: &str) -> bool {
+ unsafe {
+ self.add_string($object, value)
+ }
+ }
+ )*
}
}
@@ -102,6 +204,14 @@ mod fc {
Application = FcSetApplication as isize,
}
+ /// When matching, how to match
+ #[derive(Debug, Copy, Clone)]
+ pub enum MatchKind {
+ Font = FcMatchFont as isize,
+ Pattern = FcMatchPattern as isize,
+ Scan = FcMatchScan as isize,
+ }
+
pub unsafe fn char8_to_string(fc_str: *mut FcChar8) -> String {
str::from_utf8(CStr::from_ptr(fc_str as *const c_char).to_bytes()).unwrap().to_owned()
}
@@ -111,20 +221,24 @@ mod fc {
$(
pub fn $method(&self, id: isize) -> Option<String> {
unsafe {
- let mut format: *mut FcChar8 = ptr::null_mut();
+ self.get_string($property, id)
+ }
+ }
+ )+
+ };
+ }
- let result = FcPatternGetString(
+ macro_rules! pattern_add_integer {
+ ($($method:ident() => $property:expr),+) => {
+ $(
+ pub fn $method(&self, int: isize) -> bool {
+ unsafe {
+ FcPatternAddInteger(
self.as_ptr(),
$property.as_ptr() as *mut c_char,
- id as c_int,
- &mut format
- );
-
- if result == FcResultMatch {
- Some(char8_to_string(format))
- } else {
- None
- }
+ int as c_int,
+ &mut index
+ ) == 1
}
}
)+
@@ -155,6 +269,28 @@ mod fc {
};
}
+ #[derive(Debug, Copy, Clone)]
+ pub enum Slant {
+ Italic = FC_SLANT_ITALIC as isize,
+ Oblique = FC_SLANT_OBLIQUE as isize,
+ Roman = FC_SLANT_ROMAN as isize,
+ }
+
+ #[derive(Debug, Copy, Clone)]
+ pub enum Weight {
+ Thin = FC_WEIGHT_THIN as isize,
+ Extralight = FC_WEIGHT_EXTRALIGHT as isize,
+ Light = FC_WEIGHT_LIGHT as isize,
+ Book = FC_WEIGHT_BOOK as isize,
+ Regular = FC_WEIGHT_REGULAR as isize,
+ Medium = FC_WEIGHT_MEDIUM as isize,
+ Semibold = FC_WEIGHT_SEMIBOLD as isize,
+ Bold = FC_WEIGHT_BOLD as isize,
+ Extrabold = FC_WEIGHT_EXTRABOLD as isize,
+ Black = FC_WEIGHT_BLACK as isize,
+ Extrablack = FC_WEIGHT_EXTRABLACK as isize,
+ }
+
impl PatternRef {
/// Add a string value to the pattern
///
@@ -175,20 +311,75 @@ mod fc {
) == 1
}
+ unsafe fn add_integer(&self, object: &[u8], int: isize) -> bool {
+ FcPatternAddInteger(
+ self.as_ptr(),
+ object.as_ptr() as *mut c_char,
+ int as c_int
+ ) == 1
+ }
+
+ unsafe fn get_string(&self, object: &[u8], index: isize) -> Option<String> {
+ let mut format: *mut FcChar8 = ptr::null_mut();
+
+ let result = FcPatternGetString(
+ self.as_ptr(),
+ object.as_ptr() as *mut c_char,
+ index as c_int,
+ &mut format
+ );
+
+ if result == FcResultMatch {
+ Some(char8_to_string(format))
+ } else {
+ None
+ }
+ }
+
pattern_add_string! {
- add_family => b"family\0"
+ add_family => b"family\0",
+ add_style => b"style\0"
+ }
+
+ pub fn set_slant(&mut self, slant: Slant) -> bool {
+ unsafe {
+ self.add_integer(b"slant\0", slant as isize)
+ }
+ }
+
+ pub fn set_weight(&mut self, weight: Weight) -> bool {
+ unsafe {
+ self.add_integer(b"weight\0", weight as isize)
+ }
+ }
+
+ pub fn file(&self, index: isize) -> Option<PathBuf> {
+ unsafe {
+ self.get_string(b"file\0", index)
+ }.map(From::from)
}
pattern_get_string! {
fontformat() => b"fontformat\0",
family() => b"family\0",
- file() => b"file\0",
style() => b"style\0"
}
pattern_get_integer! {
index() => b"index\0"
}
+
+ pub fn config_subsitute(&mut self, config: &ConfigRef, kind: MatchKind) {
+ unsafe {
+ FcConfigSubstitute(config.as_ptr(), self.as_ptr(), kind as u32);
+ }
+ }
+
+ pub fn default_substitute(&mut self) {
+ unsafe {
+ FcDefaultSubstitute(self.as_ptr());
+ }
+ }
}
impl<'a> IntoIterator for &'a FontSet {
@@ -199,6 +390,8 @@ mod fc {
(*self.as_ptr()).nfont as isize
};
+ println!("num fonts = {}", num_fonts);
+
FontSetIter {
font_set: self.deref(),
num_fonts: num_fonts as _,
@@ -215,6 +408,8 @@ mod fc {
(*self.as_ptr()).nfont as isize
};
+ println!("num fonts = {}", num_fonts);
+
FontSetIter {
font_set: self,
num_fonts: num_fonts as _,
@@ -282,119 +477,50 @@ mod fc {
}
}
-fn list_families() -> Vec<String> {
- let mut families = Vec::new();
-
- let config = fc::Config::get_current();
- let font_set = config.get_fonts(fc::SetName::System);
- for font in font_set {
- if let Some(format) = font.fontformat(0) {
- if format == "TrueType" || format == "CFF" {
- for id in 0.. {
- match font.family(id) {
- Some(family) => families.push(family),
- None => break,
- }
- }
- }
- }
- }
-
- families.sort();
- families.dedup();
- families
-}
-
-#[derive(Debug)]
-pub struct Variant {
- style: String,
- file: PathBuf,
- index: isize,
-}
-
-impl Variant {
- #[inline]
- pub fn path(&self) -> &::std::path::Path {
- self.file.as_path()
- }
-
- #[inline]
- pub fn index(&self) -> isize {
- self.index
- }
-}
-
-#[derive(Debug)]
-pub struct Family {
- name: String,
- variants: HashMap<String, Variant>,
-}
+#[cfg(test)]
+mod tests {
+ use super::fc;
-impl fmt::Display for Family {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "{}: ", self.name)?;
- for (k, _v) in &self.variants {
- write!(f, "{}, ", k)?;
+ #[test]
+ fn font_match() {
+ let mut pattern = fc::Pattern::new();
+ pattern.add_family("monospace");
+ pattern.add_style("regular");
+
+ let config = fc::Config::get_current();
+ let font = fc::font_match(config, &mut pattern).expect("match font monospace");
+
+ print!("family={:?}", font.family(0));
+ for i in 0.. {
+ if let Some(style) = font.style(i) {
+ print!(", style={:?}, ", style);
+ } else {
+ break;
+ }
}
-
- Ok(())
+ println!("");
}
-}
-
-impl Family {
- #[inline]
- pub fn variants(&self) -> &HashMap<String, Variant> {
- &self.variants
- }
-}
-#[allow(mutable_transmutes)]
-pub fn get_family_info(family: String) -> Family {
- let mut members = Vec::new();
- let config = fc::Config::get_current();
- let font_set = config.get_fonts(fc::SetName::System);
-
- let mut pattern = fc::Pattern::new();
- pattern.add_family(&family);
-
- let mut objects = fc::ObjectSet::new();
- objects.add_file();
- objects.add_index();
- objects.add_style();
-
- let variants = fc::FontSet::list(&config, unsafe { ::std::mem::transmute(font_set) }, &pattern, &objects);
- for variant in &variants {
- if let Some(file) = variant.file(0) {
- if let Some(style) = variant.style(0) {
- if let Some(index) = variant.index(0) {
- members.push(Variant {
- style: style,
- file: PathBuf::from(file),
- index: index as isize,
- });
+ #[test]
+ fn font_sort() {
+ let mut pattern = fc::Pattern::new();
+ pattern.add_family("monospace");
+ pattern.set_slant(fc::Slant::Italic);
+
+ let config = fc::Config::get_current();
+ let fonts = fc::font_sort(config, &mut pattern)
+ .expect("sort font monospace");
+
+ for font in fonts.into_iter().take(10) {
+ print!("family={:?}", font.family(0));
+ for i in 0.. {
+ if let Some(style) = font.style(i) {
+ print!(", style={:?}", style);
+ } else {
+ break;
}
}
+ println!("");
}
}
-
- Family {
- name: family,
- variants: members.into_iter().map(|v| (v.style.clone(), v)).collect()
- }
-}
-
-pub fn get_font_families() -> HashMap<String, Family> {
- list_families()
- .into_iter()
- .map(|family| (family.clone(), get_family_info(family)))
- .collect()
-}
-
-#[cfg(test)]
-mod tests {
- #[test]
- fn get_font_families() {
- let families = super::get_font_families();
- assert!(!families.is_empty());
- }
}
diff --git a/font/src/ft/mod.rs b/font/src/ft/mod.rs
index 8e653816..0ffecf03 100644
--- a/font/src/ft/mod.rs
+++ b/font/src/ft/mod.rs
@@ -17,16 +17,16 @@ use std::collections::HashMap;
use freetype::{self, Library, Face};
+
mod list_fonts;
-use self::list_fonts::{Family, get_font_families};
-use super::{FontDesc, RasterizedGlyph, Metrics, Size, FontKey, GlyphKey};
+use self::list_fonts::fc;
+use super::{FontDesc, RasterizedGlyph, Metrics, Size, FontKey, GlyphKey, Weight, Slant, Style};
/// Rasterizes glyphs for a single font face.
pub struct FreeTypeRasterizer {
faces: HashMap<FontKey, Face<'static>>,
library: Library,
- system_fonts: HashMap<String, Family>,
keys: HashMap<FontDesc, FontKey>,
dpi_x: u32,
dpi_y: u32,
@@ -45,7 +45,6 @@ impl ::Rasterize for FreeTypeRasterizer {
let library = Library::init()?;
Ok(FreeTypeRasterizer {
- system_fonts: get_font_families(),
faces: HashMap::new(),
keys: HashMap::new(),
library: library,
@@ -130,13 +129,89 @@ impl ::Rasterize for FreeTypeRasterizer {
}
}
+pub trait IntoFontconfigType {
+ type FcType;
+ fn into_fontconfig_type(&self) -> Self::FcType;
+}
+
+impl IntoFontconfigType for Slant {
+ type FcType = fc::Slant;
+ fn into_fontconfig_type(&self) -> Self::FcType {
+ match *self {
+ Slant::Normal => fc::Slant::Roman,
+ Slant::Italic => fc::Slant::Italic,
+ Slant::Oblique => fc::Slant::Oblique,
+ }
+ }
+}
+
+impl IntoFontconfigType for Weight {
+ type FcType = fc::Weight;
+
+ fn into_fontconfig_type(&self) -> Self::FcType {
+ match *self {
+ Weight::Normal => fc::Weight::Regular,
+ Weight::Bold => fc::Weight::Bold,
+ }
+ }
+}
+
impl FreeTypeRasterizer {
+ /// Load a font face accoring to `FontDesc`
fn get_face(&mut self, desc: &FontDesc) -> Result<Face<'static>, Error> {
- self.system_fonts
- .get(&desc.name[..])
- .and_then(|font| font.variants().get(&desc.style[..]))
- .ok_or_else(|| Error::MissingFont(desc.to_owned()))
- .and_then(|variant| Ok(self.library.new_face(variant.path(), variant.index())?))
+ match desc.style {
+ Style::Description { slant, weight } => {
+ // Match nearest font
+ self.get_matching_face(&desc, slant, weight)
+ }
+ Style::Specific(ref style) => {
+ // If a name was specified, try and load specifically that font.
+ self.get_specific_face(&desc, &style)
+ }
+ }
+ }
+
+ fn get_matching_face(
+ &mut self,
+ desc: &FontDesc,
+ slant: Slant,
+ weight: Weight
+ ) -> Result<Face<'static>, Error> {
+ let mut pattern = fc::Pattern::new();
+ pattern.add_family(&desc.name);
+ pattern.set_weight(weight.into_fontconfig_type());
+ pattern.set_slant(slant.into_fontconfig_type());
+
+ let fonts = fc::font_sort(fc::Config::get_current(), &mut pattern)
+ .ok_or_else(|| Error::MissingFont(desc.to_owned()))?;
+
+ // Take first font that has a path
+ for font in &fonts {
+ if let (Some(path), Some(index)) = (font.file(0), font.index(0)) {
+ return Ok(self.library.new_face(path, index)?);
+ }
+ }
+
+ Err(Error::MissingFont(desc.to_owned()))
+ }
+
+ fn get_specific_face(
+ &mut self,
+ desc: &FontDesc,
+ style: &str
+ ) -> Result<Face<'static>, Error> {
+ let mut pattern = fc::Pattern::new();
+ pattern.add_family(&desc.name);
+ pattern.add_style(style);
+
+ let font = fc::font_match(fc::Config::get_current(), &mut pattern)
+ .ok_or_else(|| Error::MissingFont(desc.to_owned()))?;
+ if let (Some(path), Some(index)) = (font.file(0), font.index(0)) {
+ println!("got font path={:?}", path);
+ return Ok(self.library.new_face(path, index)?);
+ } else {
+ Err(Error::MissingFont(desc.to_owned()))
+ }
}
}
@@ -193,12 +268,3 @@ impl From<freetype::Error> for Error {
}
unsafe impl Send for FreeTypeRasterizer {}
-
-#[cfg(test)]
-mod tests {
- use ::FontDesc;
-
- fn font_desc() -> FontDesc {
- FontDesc::new("Ubuntu Mono", "Regular")
- }
-}
diff --git a/font/src/lib.rs b/font/src/lib.rs
index afe2b94f..bc4a2006 100644
--- a/font/src/lib.rs
+++ b/font/src/lib.rs
@@ -57,16 +57,47 @@ pub use darwin::*;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct FontDesc {
name: String,
- style: String,
+ style: Style,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum Slant {
+ Normal,
+ Italic,
+ Oblique,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum Weight {
+ Normal,
+ Bold
+}
+
+/// Style of font
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub enum Style {
+ Specific(String),
+ Description { slant: Slant, weight: Weight }
+}
+
+impl fmt::Display for Style {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match *self {
+ Style::Specific(ref s) => f.write_str(&s),
+ Style::Description { slant, weight } => {
+ write!(f, "slant={:?}, weight={:?}", slant, weight)
+ },
+ }
+ }
}
impl FontDesc {
- pub fn new<S>(name: S, style: S) -> FontDesc
+ pub fn new<S>(name: S, style: Style) -> FontDesc
where S: Into<String>
{
FontDesc {
name: name.into(),
- style: style.into()
+ style: style
}
}
}