Add support for colored emojis on Linux/BSD

Fixes #153.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d4dcc11..c769d5d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,7 @@
 
 - Terminal escape bindings with combined modifiers for Delete and Insert
 - /Applications symlink into OS X DMG for easier installation
+- Colored emojis on Linux/BSD
 
 ### Fixed
 
diff --git a/alacritty/src/cursor.rs b/alacritty/src/cursor.rs
index e671bf4..a3e6a2c 100644
--- a/alacritty/src/cursor.rs
+++ b/alacritty/src/cursor.rs
@@ -18,7 +18,7 @@
 
 use alacritty_terminal::ansi::CursorStyle;
 
-use font::{Metrics, RasterizedGlyph};
+use font::{BitmapBuffer, Metrics, RasterizedGlyph};
 
 /// Width/Height of the cursor relative to the font width
 pub const CURSOR_WIDTH_PERCENTAGE: i32 = 15;
@@ -55,7 +55,14 @@
     let buf = vec![255u8; (width * line_width * 3) as usize];
 
     // Create a custom glyph with the rectangle data attached to it
-    RasterizedGlyph { c: ' ', top: line_width, left: 0, height: line_width, width, buf }
+    RasterizedGlyph {
+        c: ' ',
+        top: line_width,
+        left: 0,
+        height: line_width,
+        width,
+        buf: BitmapBuffer::RGB(buf),
+    }
 }
 
 // Returns a custom beam cursor character
@@ -64,7 +71,14 @@
     let buf = vec![255u8; (line_width * height * 3) as usize];
 
     // Create a custom glyph with the rectangle data attached to it
-    RasterizedGlyph { c: ' ', top: height, left: 0, height, width: line_width, buf }
+    RasterizedGlyph {
+        c: ' ',
+        top: height,
+        left: 0,
+        height,
+        width: line_width,
+        buf: BitmapBuffer::RGB(buf),
+    }
 }
 
 // Returns a custom box cursor character
@@ -86,7 +100,7 @@
     }
 
     // Create a custom glyph with the rectangle data attached to it
-    RasterizedGlyph { c: ' ', top: height, left: 0, height, width, buf }
+    RasterizedGlyph { c: ' ', top: height, left: 0, height, width, buf: BitmapBuffer::RGB(buf) }
 }
 
 // Returns a custom block cursor character
@@ -95,5 +109,5 @@
     let buf = vec![255u8; (width * height * 3) as usize];
 
     // Create a custom glyph with the rectangle data attached to it
-    RasterizedGlyph { c: ' ', top: height, left: 0, height, width, buf }
+    RasterizedGlyph { c: ' ', top: height, left: 0, height, width, buf: BitmapBuffer::RGB(buf) }
 }
diff --git a/alacritty/src/renderer/mod.rs b/alacritty/src/renderer/mod.rs
index a061798..2d124cc 100644
--- a/alacritty/src/renderer/mod.rs
+++ b/alacritty/src/renderer/mod.rs
@@ -22,7 +22,9 @@
 use std::time::Duration;
 
 use fnv::FnvHasher;
-use font::{self, FontDesc, FontKey, GlyphKey, Rasterize, RasterizedGlyph, Rasterizer};
+use font::{
+    self, BitmapBuffer, FontDesc, FontKey, GlyphKey, Rasterize, RasterizedGlyph, Rasterizer,
+};
 use log::{error, info};
 use notify::{watcher, DebouncedEvent, RecursiveMode, Watcher};
 
@@ -139,6 +141,7 @@
 #[derive(Copy, Debug, Clone)]
 pub struct Glyph {
     tex_id: GLuint,
+    colored: bool,
     top: f32,
     left: f32,
     width: f32,
@@ -462,11 +465,19 @@
         Batch { tex: 0, instances: Vec::with_capacity(BATCH_MAX) }
     }
 
-    pub fn add_item(&mut self, cell: RenderableCell, glyph: &Glyph) {
+    pub fn add_item(&mut self, mut cell: RenderableCell, glyph: &Glyph) {
         if self.is_empty() {
             self.tex = glyph.tex_id;
         }
 
+        if glyph.colored {
+            // XXX Temporary workaround to prevent emojis being rendered with a wrong colors on, at
+            // least, dark backgrounds. For more info see #1864.
+            cell.fg.r = 255;
+            cell.fg.g = 255;
+            cell.fg.b = 255;
+        }
+
         self.instances.push(InstanceData {
             col: cell.column.0 as f32,
             row: cell.line.0 as f32,
@@ -1091,6 +1102,7 @@
         },
         Err(AtlasInsertError::GlyphTooLarge) => Glyph {
             tex_id: atlas[*current_atlas].id,
+            colored: false,
             top: 0.0,
             left: 0.0,
             width: 0.0,
@@ -1573,11 +1585,23 @@
         let offset_x = self.row_extent;
         let height = glyph.height as i32;
         let width = glyph.width as i32;
+        let colored;
 
         unsafe {
             gl::BindTexture(gl::TEXTURE_2D, self.id);
 
             // Load data into OpenGL
+            let (format, buf) = match &glyph.buf {
+                BitmapBuffer::RGB(buf) => {
+                    colored = false;
+                    (gl::RGB, buf)
+                },
+                BitmapBuffer::RGBA(buf) => {
+                    colored = true;
+                    (gl::RGBA, buf)
+                },
+            };
+
             gl::TexSubImage2D(
                 gl::TEXTURE_2D,
                 0,
@@ -1585,9 +1609,9 @@
                 offset_y,
                 width,
                 height,
-                gl::RGB,
+                format,
                 gl::UNSIGNED_BYTE,
-                glyph.buf.as_ptr() as *const _,
+                buf.as_ptr() as *const _,
             );
 
             gl::BindTexture(gl::TEXTURE_2D, 0);
@@ -1608,6 +1632,7 @@
 
         Glyph {
             tex_id: self.id,
+            colored,
             top: glyph.top as f32,
             width: width as f32,
             height: height as f32,
diff --git a/font/src/darwin/byte_order.rs b/font/src/darwin/byte_order.rs
index 382caa3..1574cf1 100644
--- a/font/src/darwin/byte_order.rs
+++ b/font/src/darwin/byte_order.rs
@@ -24,6 +24,27 @@
 pub const kCGBitmapByteOrder32Host: u32 = kCGBitmapByteOrder32Big;
 
 #[cfg(target_endian = "little")]
+pub fn extract_rgba(bytes: &[u8]) -> Vec<u8> {
+    let pixels = bytes.len() / 4;
+    let mut rgb = Vec::with_capacity(pixels * 4);
+
+    for i in 0..pixels {
+        let offset = i * 4;
+        rgb.push(bytes[offset + 2]);
+        rgb.push(bytes[offset + 1]);
+        rgb.push(bytes[offset]);
+        rgb.push(bytes[offset + 3]);
+    }
+
+    rgb
+}
+
+#[cfg(target_endian = "big")]
+pub fn extract_rgba(bytes: Vec<u8>) -> Vec<u8> {
+    bytes
+}
+
+#[cfg(target_endian = "little")]
 pub fn extract_rgb(bytes: &[u8]) -> Vec<u8> {
     let pixels = bytes.len() / 4;
     let mut rgb = Vec::with_capacity(pixels * 3);
diff --git a/font/src/darwin/mod.rs b/font/src/darwin/mod.rs
index dae7ee0..f95802f 100644
--- a/font/src/darwin/mod.rs
+++ b/font/src/darwin/mod.rs
@@ -33,6 +33,7 @@
 };
 use core_text::font_collection::create_for_family;
 use core_text::font_collection::get_family_names as ct_get_family_names;
+use core_text::font_descriptor::kCTFontColorGlyphsTrait;
 use core_text::font_descriptor::kCTFontDefaultOrientation;
 use core_text::font_descriptor::kCTFontHorizontalOrientation;
 use core_text::font_descriptor::kCTFontVerticalOrientation;
@@ -41,10 +42,9 @@
 
 use euclid::{Point2D, Rect, Size2D};
 
-use super::{FontDesc, FontKey, GlyphKey, Metrics, RasterizedGlyph};
+use super::{BitmapBuffer, FontDesc, FontKey, GlyphKey, Metrics, RasterizedGlyph};
 
 pub mod byte_order;
-use self::byte_order::extract_rgb;
 use self::byte_order::kCGBitmapByteOrder32Host;
 
 use super::Size;
@@ -431,6 +431,10 @@
         self.ct_font.symbolic_traits().is_italic()
     }
 
+    pub fn is_colored(&self) -> bool {
+        (self.ct_font.symbolic_traits() & kCTFontColorGlyphsTrait) != 0
+    }
+
     fn glyph_advance(&self, character: char) -> f64 {
         let index = self.glyph_index(character).unwrap();
 
@@ -471,7 +475,7 @@
                 height: 0,
                 top: 0,
                 left: 0,
-                buf: Vec::new(),
+                buf: BitmapBuffer::RGB(Vec::new()),
             });
         }
 
@@ -520,7 +524,11 @@
 
         let rasterized_pixels = cg_context.data().to_vec();
 
-        let buf = extract_rgb(&rasterized_pixels);
+        let buf = if self.is_colored() {
+            BitmapBuffer::RGBA(byte_order::extract_rgba(&rasterized_pixels))
+        } else {
+            BitmapBuffer::RGB(byte_order::extract_rgb(&rasterized_pixels))
+        };
 
         Ok(RasterizedGlyph {
             c: character,
@@ -564,6 +572,8 @@
 
 #[cfg(test)]
 mod tests {
+    use super::BitmapBuffer;
+
     #[test]
     fn get_family_names() {
         let names = super::get_family_names();
@@ -585,11 +595,16 @@
             for c in &['a', 'b', 'c', 'd'] {
                 let glyph = font.get_glyph(*c, 72., false).unwrap();
 
+                let buf = match &glyph.buf {
+                    BitmapBuffer::RGB(buf) => buf,
+                    BitmapBuffer::RGBA(buf) => buf,
+                };
+
                 // Debug the glyph.. sigh
                 for row in 0..glyph.height {
                     for col in 0..glyph.width {
                         let index = ((glyph.width * 3 * row) + (col * 3)) as usize;
-                        let value = glyph.buf[index];
+                        let value = buf[index];
                         let c = match value {
                             0..=50 => ' ',
                             51..=100 => '.',
diff --git a/font/src/directwrite/mod.rs b/font/src/directwrite/mod.rs
index 579f7fa..74f3d6e 100644
--- a/font/src/directwrite/mod.rs
+++ b/font/src/directwrite/mod.rs
@@ -18,7 +18,9 @@
     FontCollection, FontStretch, FontStyle, FontWeight, GlyphOffset, GlyphRunAnalysis,
 };
 
-use super::{FontDesc, FontKey, GlyphKey, Metrics, RasterizedGlyph, Size, Slant, Style, Weight};
+use super::{
+    BitmapBuffer, FontDesc, FontKey, GlyphKey, Metrics, RasterizedGlyph, Size, Slant, Style, Weight,
+};
 
 pub struct DirectWriteRasterizer {
     fonts: Vec<dwrote::FontFace>,
@@ -173,7 +175,7 @@
             height: (bounds.bottom - bounds.top) as i32,
             top: -bounds.top,
             left: bounds.left,
-            buf,
+            buf: BitmapBuffer::RGB(buf),
         })
     }
 
diff --git a/font/src/ft/fc/pattern.rs b/font/src/ft/fc/pattern.rs
index 149a45b..2500739 100644
--- a/font/src/ft/fc/pattern.rs
+++ b/font/src/ft/fc/pattern.rs
@@ -420,6 +420,7 @@
         size() => b"size\0",
         aspect() => b"aspect\0",
         pixelsize() => b"pixelsize\0",
+        pixelsizefixupfactor() => b"pixelsizefixupfactor\0",
         scale() => b"scale\0",
         dpi() => b"dpi\0"
     }
diff --git a/font/src/ft/mod.rs b/font/src/ft/mod.rs
index 0886f17..431a500 100644
--- a/font/src/ft/mod.rs
+++ b/font/src/ft/mod.rs
@@ -13,18 +13,22 @@
 // limitations under the License.
 //
 //! Rasterization powered by FreeType and FontConfig
-use std::cmp::min;
+use std::cmp::{min, Ordering};
 use std::collections::HashMap;
 use std::fmt;
 use std::path::PathBuf;
 
+use freetype::freetype_sys;
 use freetype::tt_os2::TrueTypeOS2Table;
 use freetype::{self, Library};
 use libc::c_uint;
 
 pub mod fc;
 
-use super::{FontDesc, FontKey, GlyphKey, Metrics, RasterizedGlyph, Size, Slant, Style, Weight};
+use super::{
+    BitmapBuffer, FontDesc, FontKey, GlyphKey, Metrics, Rasterize, RasterizedGlyph, Size, Slant,
+    Style, Weight,
+};
 
 struct FixedSize {
     pixelsize: f64,
@@ -37,6 +41,8 @@
     render_mode: freetype::RenderMode,
     lcd_filter: c_uint,
     non_scalable: Option<FixedSize>,
+    has_color: bool,
+    pixelsize_fixup_factor: Option<f64>,
 }
 
 impl fmt::Debug for Face {
@@ -64,6 +70,7 @@
     library: Library,
     keys: HashMap<PathBuf, FontKey>,
     device_pixel_ratio: f32,
+    pixel_size: f64,
 }
 
 #[inline]
@@ -71,7 +78,7 @@
     ((1i32 << 6) as f32 * f) as isize
 }
 
-impl ::Rasterize for FreeTypeRasterizer {
+impl Rasterize for FreeTypeRasterizer {
     type Err = Error;
 
     fn new(device_pixel_ratio: f32, _: bool) -> Result<FreeTypeRasterizer, Error> {
@@ -82,6 +89,7 @@
             keys: HashMap::new(),
             library,
             device_pixel_ratio,
+            pixel_size: 0.0,
         })
     }
 
@@ -181,15 +189,16 @@
     fn get_face(&mut self, desc: &FontDesc, size: Size) -> Result<FontKey, Error> {
         // Adjust for DPI
         let size = Size::new(size.as_f32_pts() * self.device_pixel_ratio * 96. / 72.);
+        self.pixel_size = f64::from(size.as_f32_pts());
 
         match desc.style {
             Style::Description { slant, weight } => {
                 // Match nearest font
-                self.get_matching_face(&desc, slant, weight, size)
+                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, size)
+                self.get_specific_face(&desc, &style)
             },
         }
     }
@@ -212,13 +221,12 @@
         desc: &FontDesc,
         slant: Slant,
         weight: Weight,
-        size: Size,
     ) -> Result<FontKey, 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());
-        pattern.add_pixelsize(f64::from(size.as_f32_pts()));
+        pattern.add_pixelsize(self.pixel_size);
 
         let font = fc::font_match(fc::Config::get_current(), &mut pattern)
             .ok_or_else(|| Error::MissingFont(desc.to_owned()))?;
@@ -228,16 +236,11 @@
         })
     }
 
-    fn get_specific_face(
-        &mut self,
-        desc: &FontDesc,
-        style: &str,
-        size: Size,
-    ) -> Result<FontKey, Error> {
+    fn get_specific_face(&mut self, desc: &FontDesc, style: &str) -> Result<FontKey, Error> {
         let mut pattern = fc::Pattern::new();
         pattern.add_family(&desc.name);
         pattern.add_style(style);
-        pattern.add_pixelsize(f64::from(size.as_f32_pts()));
+        pattern.add_pixelsize(self.pixel_size);
 
         let font = fc::font_match(fc::Config::get_current(), &mut pattern)
             .ok_or_else(|| Error::MissingFont(desc.to_owned()))?;
@@ -253,7 +256,7 @@
             }
 
             trace!("Got font path={:?}", path);
-            let ft_face = self.library.new_face(&path, index)?;
+            let mut ft_face = self.library.new_face(&path, index)?;
 
             // Get available pixel sizes if font isn't scalable.
             let non_scalable = if pattern.scalable().next().unwrap_or(true) {
@@ -265,6 +268,16 @@
                 Some(FixedSize { pixelsize: pixelsize.next().expect("has 1+ pixelsize") })
             };
 
+            let pixelsize_fixup_factor = pattern.pixelsizefixupfactor().next();
+
+            let has_color = ft_face.has_color();
+            if has_color {
+                unsafe {
+                    // Select the colored bitmap size to use from the array of available sizes
+                    freetype_sys::FT_Select_Size(ft_face.raw_mut(), 0);
+                }
+            }
+
             let face = Face {
                 ft_face,
                 key: FontKey::next(),
@@ -272,6 +285,8 @@
                 render_mode: Self::ft_render_mode(pattern),
                 lcd_filter: Self::ft_lcd_filter(pattern),
                 non_scalable,
+                has_color,
+                pixelsize_fixup_factor,
             };
 
             debug!("Loaded Face {:?}", face);
@@ -320,7 +335,9 @@
                 glyph_key.size.as_f32_pts() * self.device_pixel_ratio * 96. / 72.
             });
 
-        face.ft_face.set_char_size(to_freetype_26_6(size), 0, 0, 0)?;
+        if !face.has_color {
+            face.ft_face.set_char_size(to_freetype_26_6(size), 0, 0, 0)?;
+        }
 
         unsafe {
             let ft_lib = self.library.raw();
@@ -328,19 +345,33 @@
         }
 
         face.ft_face.load_glyph(index as u32, face.load_flags)?;
+
         let glyph = face.ft_face.glyph();
         glyph.render_glyph(face.render_mode)?;
 
         let (pixel_height, pixel_width, buf) = Self::normalize_buffer(&glyph.bitmap())?;
 
-        Ok(RasterizedGlyph {
+        let rasterized_glyph = RasterizedGlyph {
             c: glyph_key.c,
             top: glyph.bitmap_top(),
             left: glyph.bitmap_left(),
             width: pixel_width,
             height: pixel_height,
             buf,
-        })
+        };
+
+        if face.has_color {
+            let fixup_factor = if let Some(pixelsize_fixup_factor) = face.pixelsize_fixup_factor {
+                pixelsize_fixup_factor
+            } else {
+                // Fallback if user has bitmap scaling disabled
+                let metrics = face.ft_face.size_metrics().ok_or(Error::MissingSizeMetrics)?;
+                self.pixel_size as f64 / metrics.y_ppem as f64
+            };
+            Ok(downsample_bitmap(rasterized_glyph, fixup_factor))
+        } else {
+            Ok(rasterized_glyph)
+        }
     }
 
     fn ft_load_flags(pat: &fc::Pattern) -> freetype::face::LoadFlag {
@@ -348,6 +379,7 @@
         let hinting = pat.hintstyle().next().unwrap_or(fc::HintStyle::Slight);
         let rgba = pat.rgba().next().unwrap_or(fc::Rgba::Unknown);
         let embedded_bitmaps = pat.embeddedbitmap().next().unwrap_or(true);
+        let color = pat.color().next().unwrap_or(false);
 
         use freetype::face::LoadFlag;
         let mut flags = match (antialias, hinting, rgba) {
@@ -385,6 +417,10 @@
             flags |= LoadFlag::NO_BITMAP;
         }
 
+        if color {
+            flags |= LoadFlag::COLOR;
+        }
+
         flags
     }
 
@@ -414,7 +450,7 @@
     /// The i32 value in the return type is the number of pixels per row.
     fn normalize_buffer(
         bitmap: &freetype::bitmap::Bitmap,
-    ) -> freetype::FtResult<(i32, i32, Vec<u8>)> {
+    ) -> freetype::FtResult<(i32, i32, BitmapBuffer)> {
         use freetype::bitmap::PixelMode;
 
         let buf = bitmap.buffer();
@@ -427,7 +463,7 @@
                     let stop = start + bitmap.width() as usize;
                     packed.extend_from_slice(&buf[start..stop]);
                 }
-                Ok((bitmap.rows(), bitmap.width() / 3, packed))
+                Ok((bitmap.rows(), bitmap.width() / 3, BitmapBuffer::RGB(packed)))
             },
             PixelMode::LcdV => {
                 for i in 0..bitmap.rows() / 3 {
@@ -438,7 +474,7 @@
                         }
                     }
                 }
-                Ok((bitmap.rows() / 3, bitmap.width(), packed))
+                Ok((bitmap.rows() / 3, bitmap.width(), BitmapBuffer::RGB(packed)))
             },
             // Mono data is stored in a packed format using 1 bit per pixel.
             PixelMode::Mono => {
@@ -469,7 +505,7 @@
                         byte += 1;
                     }
                 }
-                Ok((bitmap.rows(), bitmap.width(), packed))
+                Ok((bitmap.rows(), bitmap.width(), BitmapBuffer::RGB(packed)))
             },
             // Gray data is stored as a value between 0 and 255 using 1 byte per pixel.
             PixelMode::Gray => {
@@ -482,7 +518,19 @@
                         packed.push(*byte);
                     }
                 }
-                Ok((bitmap.rows(), bitmap.width(), packed))
+                Ok((bitmap.rows(), bitmap.width(), BitmapBuffer::RGB(packed)))
+            },
+            PixelMode::Bgra => {
+                let buf_size = (bitmap.rows() * bitmap.width() * 4) as usize;
+                let mut i = 0;
+                while i < buf_size {
+                    packed.push(buf[i + 2]);
+                    packed.push(buf[i + 1]);
+                    packed.push(buf[i]);
+                    packed.push(buf[i + 3]);
+                    i += 4;
+                }
+                Ok((bitmap.rows(), bitmap.width(), BitmapBuffer::RGBA(packed)))
             },
             mode => panic!("unhandled pixel mode: {:?}", mode),
         }
@@ -493,6 +541,7 @@
         charset.add(glyph);
         let mut pattern = fc::Pattern::new();
         pattern.add_charset(&charset);
+        pattern.add_pixelsize(self.pixel_size as f64);
 
         let config = fc::Config::get_current();
         match fc::font_match(config, &mut pattern) {
@@ -503,6 +552,9 @@
                         // load it again.
                         Some(&key) => {
                             debug!("Hit for font {:?}; no need to load", path);
+                            // Update fixup factor
+                            self.faces.get_mut(&key).unwrap().pixelsize_fixup_factor =
+                                pattern.pixelsizefixupfactor().next();
                             Ok(key)
                         },
 
@@ -529,6 +581,76 @@
     }
 }
 
+/// Downscale a bitmap by a fixed factor.
+///
+/// This will take the `bitmap_glyph` as input and return the glyph's content downscaled by
+/// `fixup_factor`.
+fn downsample_bitmap(mut bitmap_glyph: RasterizedGlyph, fixup_factor: f64) -> RasterizedGlyph {
+    // Only scale colored buffers which are bigger than required
+    let bitmap_buffer = match (&bitmap_glyph.buf, fixup_factor.partial_cmp(&1.0)) {
+        (BitmapBuffer::RGBA(buffer), Some(Ordering::Less)) => buffer,
+        _ => return bitmap_glyph,
+    };
+
+    let bitmap_width = bitmap_glyph.width as usize;
+    let bitmap_height = bitmap_glyph.height as usize;
+
+    let target_width = (bitmap_width as f64 * fixup_factor) as usize;
+    let target_height = (bitmap_height as f64 * fixup_factor) as usize;
+
+    // Number of pixels in the input buffer, per pixel in the output buffer
+    let downsampling_step = 1.0 / fixup_factor;
+
+    let mut downsampled_buffer = Vec::<u8>::with_capacity(target_width * target_height * 4);
+
+    for line_index in 0..target_height {
+        // Get the first and last line which will be consolidated in the current output pixel
+        let line_index = line_index as f64;
+        let source_line_start = (line_index * downsampling_step).round() as usize;
+        let source_line_end = ((line_index + 1.) * downsampling_step).round() as usize;
+
+        for column_index in 0..target_width {
+            // Get the first and last column which will be consolidated in the current output pixel
+            let column_index = column_index as f64;
+            let source_column_start = (column_index * downsampling_step).round() as usize;
+            let source_column_end = ((column_index + 1.) * downsampling_step).round() as usize;
+
+            let (mut r, mut g, mut b, mut a) = (0u32, 0u32, 0u32, 0u32);
+            let mut pixels_picked: u32 = 0;
+
+            // Consolidate all pixels within the source rectangle into a single averaged pixel
+            for source_line in source_line_start..source_line_end {
+                let source_pixel_index = source_line * bitmap_width;
+
+                for source_column in source_column_start..source_column_end {
+                    let offset = (source_pixel_index + source_column) * 4;
+                    r += bitmap_buffer[offset] as u32;
+                    g += bitmap_buffer[offset + 1] as u32;
+                    b += bitmap_buffer[offset + 2] as u32;
+                    a += bitmap_buffer[offset + 3] as u32;
+                    pixels_picked += 1;
+                }
+            }
+
+            // Add a single pixel to the output buffer for the downscaled source rectangle
+            downsampled_buffer.push((r / pixels_picked) as u8);
+            downsampled_buffer.push((g / pixels_picked) as u8);
+            downsampled_buffer.push((b / pixels_picked) as u8);
+            downsampled_buffer.push((a / pixels_picked) as u8);
+        }
+    }
+
+    bitmap_glyph.buf = BitmapBuffer::RGBA(downsampled_buffer);
+
+    // Downscale the metrics
+    bitmap_glyph.top = (bitmap_glyph.top as f64 * fixup_factor) as i32;
+    bitmap_glyph.left = (bitmap_glyph.left as f64 * fixup_factor) as i32;
+    bitmap_glyph.width = target_width as i32;
+    bitmap_glyph.height = target_height as i32;
+
+    bitmap_glyph
+}
+
 /// Errors occurring when using the freetype rasterizer
 #[derive(Debug)]
 pub enum Error {
@@ -545,7 +667,7 @@
     FontNotLoaded,
 }
 
-impl ::std::error::Error for Error {
+impl std::error::Error for Error {
     fn cause(&self) -> Option<&dyn std::error::Error> {
         match *self {
             Error::FreeType(ref err) => Some(err),
@@ -563,7 +685,7 @@
     }
 }
 
-impl ::std::fmt::Display for Error {
+impl std::fmt::Display for Error {
     fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
         match *self {
             Error::FreeType(ref err) => err.fmt(f),
diff --git a/font/src/lib.rs b/font/src/lib.rs
index 262cf91..8fd0f62 100644
--- a/font/src/lib.rs
+++ b/font/src/lib.rs
@@ -220,20 +220,25 @@
     pub height: i32,
     pub top: i32,
     pub left: i32,
-    pub buf: Vec<u8>,
+    pub buf: BitmapBuffer,
+}
+
+#[derive(Clone, Debug)]
+pub enum BitmapBuffer {
+    RGB(Vec<u8>),
+    RGBA(Vec<u8>),
 }
 
 impl Default for RasterizedGlyph {
     fn default() -> RasterizedGlyph {
-        RasterizedGlyph { c: ' ', width: 0, height: 0, top: 0, left: 0, buf: Vec::new() }
-    }
-}
-
-struct BufDebugger<'a>(&'a [u8]);
-
-impl<'a> fmt::Debug for BufDebugger<'a> {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.debug_struct("GlyphBuffer").field("len", &self.0.len()).field("bytes", &self.0).finish()
+        RasterizedGlyph {
+            c: ' ',
+            width: 0,
+            height: 0,
+            top: 0,
+            left: 0,
+            buf: BitmapBuffer::RGB(Vec::new()),
+        }
     }
 }
 
@@ -245,7 +250,7 @@
             .field("height", &self.height)
             .field("top", &self.top)
             .field("left", &self.left)
-            .field("buf", &BufDebugger(&self.buf[..]))
+            .field("buf", &self.buf)
             .finish()
     }
 }