[WIP] Add antialias option

Still a WIP because of unimplemented Linux portion.

Support has been added for font rasterization options. At this time, the
only supported option is antialias. It's a tri-state flag which can be
either ~ for "use default", true to force antialias, and false to force
disable antialias.

The options may be specified both globally and per font section. The per
font sections override global options. An example of a complex config
follows. In the example, the global value requests using default
antialias settings, and the normal face disables antialias.

    font:
      options:
        antialias: ~
      normal:
        family: monospace
        options:
          antialias: false

Finally, note that the top level font.options is used for fallback
fonts.
diff --git a/Cargo.lock b/Cargo.lock
index 61404ae..faab4cb 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -373,6 +373,8 @@
  "freetype-rs 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "servo-fontconfig 0.4.0 (git+https://github.com/jwilm/rust-fontconfig?branch=updated-2017-10-8)",
 ]
 
diff --git a/Cargo.toml b/Cargo.toml
index e983e3a..97a8448 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -16,7 +16,7 @@
 cgmath = "0.15"
 notify = "4"
 bitflags = "0.9.1"
-font = { path = "./font" }
+font = { path = "./font", features = ["with-serde"] }
 errno = "0.2.3"
 parking_lot = "0.4.5"
 serde = "1"
diff --git a/alacritty.yml b/alacritty.yml
index d260705..d1607fc 100644
--- a/alacritty.yml
+++ b/alacritty.yml
@@ -53,21 +53,31 @@
 # * https://wiki.archlinux.org/index.php/font_configuration#Fontconfig_configuration
 # * file:///usr/share/doc/fontconfig/fontconfig-user.html
 font:
+  # Default rasterization options
+  #
+  # These settings are used for fallback fonts *and* for normal/bold/italic
+  # fonts when they don't specify their own `options`.
+  #
+  # If you prefer to respect fontconfig settings, set the value of these
+  # properties to ~.
+  options:
+    antialias: true
+
   # The normal (roman) font face to use.
   normal:
-    family: monospace # should be "Menlo" or something on macOS.
+    family: monospace
     # Style can be specified to pick a specific face.
     # style: Regular
 
   # The bold font face
   bold:
-    family: monospace # should be "Menlo" or something on macOS.
+    family: monospace
     # Style can be specified to pick a specific face.
     # style: Bold
 
   # The italic font face
   italic:
-    family: monospace # should be "Menlo" or something on macOS.
+    family: monospace
     # Style can be specified to pick a specific face.
     # style: Italic
 
diff --git a/alacritty_macos.yml b/alacritty_macos.yml
index 761542a..0b7c513 100644
--- a/alacritty_macos.yml
+++ b/alacritty_macos.yml
@@ -34,6 +34,13 @@
 
 # Font configuration (changes require restart)
 font:
+  # Default rasterization options
+  #
+  # These settings are used for fallback fonts *and* for normal/bold/italic
+  # fonts when they don't specify their own `options`.
+  options:
+    antialias: true
+
   # The normal (roman) font face to use.
   normal:
     family: Menlo
diff --git a/font/Cargo.toml b/font/Cargo.toml
index 2a97f0b..e67cdaf 100644
--- a/font/Cargo.toml
+++ b/font/Cargo.toml
@@ -5,11 +5,16 @@
 description = "Font rendering using the best available solution per platform"
 license = "Apache-2.0"
 
+[features]
+with-serde = ["serde", "serde_derive"]
+
 [dependencies]
 euclid = "0.12.0"
 libc = "0.2"
 foreign-types = "0.2.0"
 log = "0.3"
+serde = { version = "1", optional = true }
+serde_derive = { version = "1", optional = true }
 
 [target.'cfg(not(target_os = "macos"))'.dependencies]
 servo-fontconfig = { git = "https://github.com/jwilm/rust-fontconfig", branch = "updated-2017-10-8" }
@@ -20,3 +25,4 @@
 core-text = "6.1.0"
 core-graphics = "0.8.1"
 core-foundation-sys = "0.3.1"
+
diff --git a/font/src/darwin/mod.rs b/font/src/darwin/mod.rs
index 70b9e1f..73a9156 100644
--- a/font/src/darwin/mod.rs
+++ b/font/src/darwin/mod.rs
@@ -43,6 +43,7 @@
 use euclid::size::Size2D;
 
 use super::{FontDesc, RasterizedGlyph, Metrics, FontKey, GlyphKey};
+use ::Options;
 
 pub mod byte_order;
 use self::byte_order::kCGBitmapByteOrder32Host;
@@ -85,6 +86,7 @@
     keys: HashMap<(FontDesc, Size), FontKey>,
     device_pixel_ratio: f32,
     use_thin_strokes: bool,
+    options: ::Options,
 }
 
 /// Errors occurring when using the core text rasterizer
@@ -130,13 +132,18 @@
 impl ::Rasterize for Rasterizer {
     type Err = Error;
 
-    fn new(device_pixel_ratio: f32, use_thin_strokes: bool) -> Result<Rasterizer, Error> {
+    fn new(
+        options: Options,
+        device_pixel_ratio: f32,
+        use_thin_strokes: bool
+    ) -> Result<Rasterizer, Error> {
         info!("device_pixel_ratio: {}", device_pixel_ratio);
         Ok(Rasterizer {
             fonts: HashMap::new(),
             keys: HashMap::new(),
             device_pixel_ratio: device_pixel_ratio,
             use_thin_strokes: use_thin_strokes,
+            options: options,
         })
     }
 
@@ -149,12 +156,18 @@
         Ok(font.metrics())
     }
 
-    fn load_font(&mut self, desc: &FontDesc, size: Size) -> Result<FontKey, Error> {
+    fn load_font(
+        &mut self,
+        desc: &FontDesc,
+        size: Size,
+        font_options: &Options,
+    ) -> Result<FontKey, Error> {
         self.keys
             .get(&(desc.to_owned(), size))
             .map(|k| Ok(*k))
             .unwrap_or_else(|| {
-                let mut font = self.get_font(desc, size)?;
+                let options = self.options.clone().merge(&font_options);
+                let mut font = self.get_font(desc, size, options)?;
 
                 // TODO, we can't use apple's proposed
                 // .Apple Symbol Fallback (filtered out below),
@@ -166,7 +179,8 @@
                     let symbols = {
                         let fallback_style = Style::Description { slant:Slant::Normal, weight:Weight::Normal  } ;
                         let d = FontDesc::new("Apple Symbols".to_owned(), fallback_style);
-                        self.get_font(&d, size)?
+                        let options = self.options.clone();
+                        self.get_font(&d, size, options)?
                     };
                     font.fallbacks.push(symbols);
                 }
@@ -209,14 +223,16 @@
         &mut self,
         desc: &FontDesc,
         style: &str,
-        size: Size
+        size: Size,
+        options: Options,
     ) -> Result<Font, Error> {
         let descriptors = descriptors_for_family(&desc.name[..]);
         for descriptor in descriptors {
             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, true);
+                let mut font = descriptor.to_font(scaled_size, options);
+                font.load_fallbacks(scaled_size, &self.options);
                 return Ok(font);
             }
         }
@@ -229,7 +245,8 @@
         desc: &FontDesc,
         slant: Slant,
         weight: Weight,
-        size: Size
+        size: Size,
+        options: Options,
     ) -> Result<Font, Error> {
         let bold = match weight {
             Weight::Bold => true,
@@ -243,7 +260,8 @@
 
         let descriptors = descriptors_for_family(&desc.name[..]);
         for descriptor in descriptors {
-            let font = descriptor.to_font(scaled_size, true);
+            let mut font = descriptor.to_font(scaled_size, options.clone());
+            font.load_fallbacks(scaled_size, &self.options);
             if font.is_bold() == bold && font.is_italic() == italic {
                 // Found the font we want
                 return Ok(font);
@@ -253,11 +271,11 @@
         Err(Error::MissingFont(desc.to_owned()))
     }
 
-    fn get_font(&mut self, desc: &FontDesc, size: Size) -> Result<Font, Error> {
+    fn get_font(&mut self, desc: &FontDesc, size: Size, options: Options) -> Result<Font, Error> {
         match desc.style {
-            Style::Specific(ref style) => self.get_specific_face(desc, style, size),
+            Style::Specific(ref style) => self.get_specific_face(desc, style, size, options),
             Style::Description { slant, weight } => {
-                self.get_matching_face(desc, slant, weight, size)
+                self.get_matching_face(desc, slant, weight, size, options)
             },
         }
     }
@@ -299,6 +317,7 @@
     ct_font: CTFont,
     cg_font: CGFont,
     fallbacks: Vec<Font>,
+    antialias: bool,
 }
 
 unsafe impl Send for Font {}
@@ -370,31 +389,15 @@
 
 impl Descriptor {
     /// Create a Font from this descriptor
-    pub fn to_font(&self, size: f64, load_fallbacks:bool) -> Font {
+    pub fn to_font(&self, size: f64, options: Options) -> Font {
         let ct_font = ct_new_from_descriptor(&self.ct_descriptor, size);
         let cg_font = ct_font.copy_to_CGFont();
 
-        let fallbacks = if load_fallbacks {
-            // TODO fixme, hardcoded en for english
-            cascade_list_for_languages(&ct_font, &vec!["en".to_owned()])
-                .into_iter()
-                // the system lists contains (at least) two strange fonts:
-                // .Apple Symbol Fallback
-                // .Noto Sans Universal
-                // both have a .-prefix (to indicate they are internal?)
-                // neither work very well. the latter even breaks things because
-                // it defines code points with just [?] glyphs.
-                .filter(|desc| desc.font_path != "")
-                .map(|desc| desc.to_font(size, false))
-                .collect()
-        } else {
-            vec![]
-        };
-
         Font {
             ct_font: ct_font,
             cg_font: cg_font,
-            fallbacks: fallbacks,
+            fallbacks: Vec::new(),
+            antialias: options.antialias.unwrap_or(true),
         }
     }
 }
@@ -505,12 +508,12 @@
 
         cg_context.set_allows_font_smoothing(true);
         cg_context.set_should_smooth_fonts(true);
-        cg_context.set_allows_font_subpixel_quantization(true);
-        cg_context.set_should_subpixel_quantize_fonts(true);
-        cg_context.set_allows_font_subpixel_positioning(true);
-        cg_context.set_should_subpixel_position_fonts(true);
-        cg_context.set_allows_antialiasing(true);
-        cg_context.set_should_antialias(true);
+        cg_context.set_allows_font_subpixel_quantization(self.antialias);
+        cg_context.set_should_subpixel_quantize_fonts(self.antialias);
+        cg_context.set_allows_font_subpixel_positioning(self.antialias);
+        cg_context.set_should_subpixel_position_fonts(self.antialias);
+        cg_context.set_allows_antialiasing(self.antialias);
+        cg_context.set_should_antialias(self.antialias);
 
         // Set fill color to white for drawing the glyph
         cg_context.set_rgb_fill_color(1.0, 1.0, 1.0, 1.0);
@@ -563,6 +566,21 @@
             None
         }
     }
+
+    pub fn load_fallbacks(&mut self, size: f64, options: &Options) {
+        // TODO fixme, hardcoded en for english
+        self.fallbacks = cascade_list_for_languages(&self.ct_font, &vec!["en".to_owned()])
+            .into_iter()
+            // the system lists contains (at least) two strange fonts:
+            // .Apple Symbol Fallback
+            // .Noto Sans Universal
+            // both have a .-prefix (to indicate they are internal?)
+            // neither work very well. the latter even breaks things because
+            // it defines code points with just [?] glyphs.
+            .filter(|desc| desc.font_path != "")
+            .map(|desc| desc.to_font(size, options.clone()))
+            .collect()
+    }
 }
 
 #[cfg(test)]
@@ -582,7 +600,7 @@
 
         // Check to_font
         let fonts = list.iter()
-                        .map(|desc| desc.to_font(72., false))
+                        .map(|desc| desc.to_font(72., &Default::default()))
                         .collect::<Vec<_>>();
 
         for font in fonts {
diff --git a/font/src/lib.rs b/font/src/lib.rs
index 513dacd..18ef194 100644
--- a/font/src/lib.rs
+++ b/font/src/lib.rs
@@ -33,6 +33,12 @@
 #[cfg(target_os = "macos")]
 extern crate euclid;
 
+#[cfg(feature = "with-serde")]
+extern crate serde;
+#[cfg_attr(feature = "with-serde", macro_use)]
+#[cfg(feature = "with-serde")]
+extern crate serde_derive;
+
 extern crate libc;
 
 #[cfg(not(target_os = "macos"))]
@@ -58,6 +64,12 @@
 #[cfg(target_os = "macos")]
 pub use darwin::*;
 
+#[derive(Debug, Clone, Default)]
+#[cfg_attr(feature="with-serde", derive(Deserialize))]
+pub struct Options {
+    antialias: Option<bool>,
+}
+
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct FontDesc {
     name: String,
@@ -237,15 +249,26 @@
     type Err: ::std::error::Error + Send + Sync + 'static;
 
     /// Create a new Rasterize
-    fn new(device_pixel_ratio: f32, use_thin_strokes: bool) -> Result<Self, Self::Err>
+    fn new(_: Options, device_pixel_ratio: f32, use_thin_strokes: bool) -> Result<Self, Self::Err>
         where Self: Sized;
 
     /// Get `Metrics` for the given `FontKey`
     fn metrics(&self, FontKey) -> Result<Metrics, Self::Err>;
 
     /// Load the font described by `FontDesc` and `Size`
-    fn load_font(&mut self, &FontDesc, Size) -> Result<FontKey, Self::Err>;
+    fn load_font(&mut self, &FontDesc, Size, &Options) -> Result<FontKey, Self::Err>;
 
     /// Rasterize the glyph described by `GlyphKey`.
     fn get_glyph(&mut self, &GlyphKey) -> Result<RasterizedGlyph, Self::Err>;
 }
+
+impl Options {
+    /// Merge options from other into self. Values defined in both self and
+    /// other will prefer other.
+    pub fn merge(mut self, other: &Options) -> Self {
+        let default = self.antialias.take();
+        self.antialias = other.antialias.or(default);
+
+        self
+    }
+}
diff --git a/src/config.rs b/src/config.rs
index 3f3b694..8f4f445 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -14,7 +14,7 @@
 use std::collections::HashMap;
 
 use ::Rgb;
-use font::Size;
+use font::{self, Size};
 use serde_yaml;
 use serde::{self, de, Deserialize};
 use serde::de::Error as SerdeError;
@@ -1305,6 +1305,10 @@
 /// doesn't provide complete config is Ok.
 #[derive(Debug, Deserialize, Clone)]
 pub struct Font {
+    /// Default font rasterization options
+    #[serde(default)]
+    pub options: font::Options,
+
     /// Font family
     pub normal: FontDescription,
 
@@ -1342,6 +1346,9 @@
 pub struct FontDescription {
     pub family: String,
     pub style: Option<String>,
+    /// Rasterization options for this font.
+    #[serde(default)]
+    pub options: font::Options,
 }
 
 impl FontDescription {
@@ -1349,6 +1356,7 @@
         FontDescription {
             family: family.into(),
             style: None,
+            options: Default::default(),
         }
     }
 }
@@ -1389,6 +1397,7 @@
 impl Default for Font {
     fn default() -> Font {
         Font {
+            options: Default::default(),
             normal: FontDescription::new_with_family("Menlo"),
             bold: FontDescription::new_with_family("Menlo"),
             italic: FontDescription::new_with_family("Menlo"),
@@ -1404,6 +1413,7 @@
 impl Default for Font {
     fn default() -> Font {
         Font {
+            options: Default::default(),
             normal: FontDescription::new_with_family("monospace"),
             bold: FontDescription::new_with_family("monospace"),
             italic: FontDescription::new_with_family("monospace"),
diff --git a/src/display.rs b/src/display.rs
index fc5a5d4..52207ac 100644
--- a/src/display.rs
+++ b/src/display.rs
@@ -212,7 +212,11 @@
     {
         let font = config.font().clone().with_size_delta(font_size_delta as f32);
         let dpr = window.hidpi_factor();
-        let rasterizer = font::Rasterizer::new(dpr, config.use_thin_strokes())?;
+        let rasterizer = font::Rasterizer::new(
+                font.options.clone(),
+                dpr,
+                config.use_thin_strokes()
+            )?;
 
         // Initialize glyph cache
         let glyph_cache = {
diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs
index bb02587..7c97023 100644
--- a/src/renderer/mod.rs
+++ b/src/renderer/mod.rs
@@ -230,26 +230,26 @@
         let regular_desc = Self::make_desc(&font.normal, font::Slant::Normal, font::Weight::Normal);
 
         let regular = rasterizer
-            .load_font(&regular_desc, size)?;
+            .load_font(&regular_desc, size, &font.normal.options)?;
 
         // helper to load a description if it is not the regular_desc
-        let mut load_or_regular = |desc:FontDesc| {
+        let mut load_or_regular = |desc:FontDesc, options:&font::Options| {
             if desc == regular_desc {
                 regular
             } else {
-                rasterizer.load_font(&desc, size).unwrap_or_else(|_| regular)
+                rasterizer.load_font(&desc, size, options).unwrap_or_else(|_| regular)
             }
         };
 
         // Load bold font
         let bold_desc = Self::make_desc(&font.bold, font::Slant::Normal, font::Weight::Bold);
 
-        let bold = load_or_regular(bold_desc);
+        let bold = load_or_regular(bold_desc, &font.bold.options);
 
         // Load italic font
         let italic_desc = Self::make_desc(&font.italic, font::Slant::Italic, font::Weight::Normal);
 
-        let italic = load_or_regular(italic_desc);
+        let italic = load_or_regular(italic_desc, &font.italic.options);
 
         Ok((regular, bold, italic))
     }