servo: Merge #14153 - Add support for DirectWrite font rendering on Windows (from vvuk:win32-dwrite); r=glennw
authorVladimir Vukicevic <vladimir@pobox.com>
Thu, 10 Nov 2016 16:55:17 -0600
changeset 340130 4cacff53a6cca42c0b33182de97d9364a150d1ab
parent 340129 0a48433f7d228894a0885b83efebbfa4d1eb7e1c
child 340131 8fe146766b76952ab3c1eba6bd8bd5e272a7cae6
push id31307
push usergszorc@mozilla.com
push dateSat, 04 Feb 2017 00:59:06 +0000
treeherdermozilla-central@94079d43835f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersglennw
servo: Merge #14153 - Add support for DirectWrite font rendering on Windows (from vvuk:win32-dwrite); r=glennw <!-- Please describe your changes on the following line: --> This PR adds support for DirectWrite text rendering using a thin wrapper for dwrite, as well as similar functionality added to WebRender. In doing so it removes the FreeType dep from the Windows build. There is still work to be done here, but this is a good starting point for future cleanup and fixes. --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [ ] `./mach test-tidy` does not report any errors - [X] These changes fix #13371 (github issue number if applicable). <!-- Either: --> - [ ] There are tests for these changes OR - [X] These changes do not require tests because they are already tested by other tests <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> Source-Repo: https://github.com/servo/servo Source-Revision: 796fae4bbe966a4e6e32b01fa44f6123c7162992
servo/components/gfx/Cargo.toml
servo/components/gfx/lib.rs
servo/components/gfx/platform/mod.rs
servo/components/gfx/platform/windows/font.rs
servo/components/gfx/platform/windows/font_context.rs
servo/components/gfx/platform/windows/font_list.rs
servo/components/gfx/platform/windows/font_template.rs
servo/components/servo/Cargo.lock
servo/ports/cef/Cargo.lock
servo/resources/shaders/blur.fs.glsl
servo/resources/shaders/blur.vs.glsl
servo/resources/shaders/cs_blur.fs.glsl
servo/resources/shaders/cs_blur.glsl
servo/resources/shaders/cs_blur.vs.glsl
servo/resources/shaders/cs_text_run.fs.glsl
servo/resources/shaders/cs_text_run.glsl
servo/resources/shaders/cs_text_run.vs.glsl
servo/resources/shaders/debug_font.fs.glsl
servo/resources/shaders/prim_shared.glsl
servo/resources/shaders/ps_cache_image.fs.glsl
servo/resources/shaders/ps_cache_image.glsl
servo/resources/shaders/ps_cache_image.vs.glsl
servo/resources/shaders/ps_image.fs.glsl
servo/resources/shaders/ps_image.vs.glsl
servo/resources/shaders/ps_image_clip.fs.glsl
servo/resources/shaders/ps_image_clip.vs.glsl
servo/resources/shaders/ps_text_run.fs.glsl
servo/resources/shaders/ps_text_run.vs.glsl
servo/resources/shaders/shared.glsl
--- a/servo/components/gfx/Cargo.toml
+++ b/servo/components/gfx/Cargo.toml
@@ -48,20 +48,17 @@ default_features = false
 features = ["serde_derive"]
 
 [target.'cfg(target_os = "macos")'.dependencies]
 byteorder = "0.5"
 core-foundation = "0.2"
 core-graphics = "0.4"
 core-text = "2.0"
 
-[target.'cfg(any(target_os = "linux", target_os = "android", target_os = "windows"))'.dependencies]
+[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies]
 freetype = {git = "https://github.com/servo/rust-freetype"}
-
-[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies]
 servo-fontconfig = "0.2.1"
 
 [target.'cfg(any(target_arch = "x86_64", target_arch = "aarch64"))'.dependencies]
 simd = {git = "https://github.com/huonw/simd"}
 
 [target.'cfg(target_os = "windows")'.dependencies]
-winapi = "0.2"
-gdi32-sys = "0.2"
+dwrote = {git = "https://github.com/vvuk/dwrote-rs"}
--- a/servo/components/gfx/lib.rs
+++ b/servo/components/gfx/lib.rs
@@ -24,29 +24,26 @@ extern crate bitflags;
 
 // Mac OS-specific library dependencies
 #[cfg(target_os = "macos")] extern crate byteorder;
 #[cfg(target_os = "macos")] extern crate core_foundation;
 #[cfg(target_os = "macos")] extern crate core_graphics;
 #[cfg(target_os = "macos")] extern crate core_text;
 
 // Windows-specific library dependencies
-#[cfg(target_os = "windows")] extern crate gdi32;
-#[cfg(target_os = "windows")] extern crate winapi;
+#[cfg(target_os = "windows")] extern crate dwrote;
 
 extern crate euclid;
 extern crate fnv;
 
-// Platforms that use Freetype/Fontconfig library dependencies
 #[cfg(any(target_os = "linux", target_os = "android"))]
 extern crate fontconfig;
 extern crate fontsan;
-#[cfg(any(target_os = "linux", target_os = "android", target_os = "windows"))]
+#[cfg(any(target_os = "linux", target_os = "android"))]
 extern crate freetype;
-
 extern crate gfx_traits;
 
 // Eventually we would like the shaper to be pluggable, as many operating systems have their own
 // shapers. For now, however, this is a hard dependency.
 extern crate harfbuzz_sys as harfbuzz;
 
 extern crate heapsize;
 #[macro_use] extern crate heapsize_derive;
--- a/servo/components/gfx/platform/mod.rs
+++ b/servo/components/gfx/platform/mod.rs
@@ -1,25 +1,25 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#[cfg(any(target_os = "linux", target_os = "android", target_os = "windows"))]
+#[cfg(any(target_os = "linux", target_os = "android"))]
 pub use platform::freetype::{font, font_context};
 
 #[cfg(any(target_os = "linux", target_os = "android"))]
 pub use platform::freetype::{font_list, font_template};
 
 #[cfg(target_os = "windows")]
-pub use platform::windows::{font_list, font_template};
+pub use platform::windows::{font, font_context, font_list, font_template};
 
 #[cfg(target_os = "macos")]
 pub use platform::macos::{font, font_context, font_list, font_template};
 
-#[cfg(any(target_os = "linux", target_os = "android", target_os = "windows"))]
+#[cfg(any(target_os = "linux", target_os = "android"))]
 mod freetype {
     use libc::c_char;
     use std::ffi::CStr;
     use std::str;
 
     /// Creates a String from the given null-terminated buffer.
     /// Panics if the buffer does not contain UTF-8.
     unsafe fn c_str_to_string(s: *const c_char) -> String {
@@ -41,11 +41,13 @@ mod macos {
     pub mod font;
     pub mod font_context;
     pub mod font_list;
     pub mod font_template;
 }
 
 #[cfg(target_os = "windows")]
 mod windows {
+    pub mod font;
+    pub mod font_context;
     pub mod font_list;
     pub mod font_template;
 }
new file mode 100644
--- /dev/null
+++ b/servo/components/gfx/platform/windows/font.rs
@@ -0,0 +1,204 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// NOTE: https://www.chromium.org/directwrite-font-proxy has useful
+// information for an approach that we'll likely need to take when the
+// renderer moves to a sandboxed process.
+
+use app_units::Au;
+use dwrote::{Font, FontFace};
+use dwrote::{FontWeight, FontStretch, FontStyle};
+use font::{FontHandleMethods, FontMetrics, FontTableMethods};
+use font::{FontTableTag, FractionalPixel};
+use platform::font_template::FontTemplateData;
+use platform::windows::font_context::FontContextHandle;
+use platform::windows::font_list::font_from_atom;
+use std::sync::Arc;
+use style::computed_values::{font_stretch, font_weight};
+use text::glyph::GlyphId;
+
+// 1em = 12pt = 16px, assuming 72 points per inch and 96 px per inch
+fn pt_to_px(pt: f64) -> f64 { pt / 72. * 96. }
+fn em_to_px(em: f64) -> f64 { em * 16. }
+fn au_from_em(em: f64) -> Au { Au::from_f64_px(em_to_px(em)) }
+fn au_from_pt(pt: f64) -> Au { Au::from_f64_px(pt_to_px(pt)) }
+
+pub struct FontTable {
+    data: Vec<u8>,
+}
+
+impl FontTable {
+    pub fn wrap(data: &[u8]) -> FontTable {
+        FontTable { data: data.to_vec() }
+    }
+}
+
+impl FontTableMethods for FontTable {
+    fn buffer(&self) -> &[u8] {
+        &self.data
+    }
+}
+
+#[derive(Debug)]
+pub struct FontHandle {
+    font_data: Arc<FontTemplateData>,
+    font: Font,
+    face: FontFace,
+    em_size: f32,
+    du_per_em: f32,
+    du_to_px: f32,
+    scaled_du_to_px: f32,
+}
+
+impl FontHandle {
+}
+
+impl FontHandleMethods for FontHandle {
+    fn new_from_template(_: &FontContextHandle, template: Arc<FontTemplateData>, pt_size: Option<Au>)
+                         -> Result<Self, ()>
+    {
+        if let Some(_) = template.bytes {
+            // FIXME we should load from template.bytes
+            Err(())
+        } else {
+            let font = font_from_atom(&template.identifier);
+            let face = font.create_font_face();
+
+            let pt_size = pt_size.unwrap_or(au_from_pt(12.));
+            let du_per_em = face.metrics().designUnitsPerEm as f32;
+
+            let em_size = pt_size.to_f32_px() / 16.;
+            let design_units_per_pixel = du_per_em / 16.;
+
+            let design_units_to_pixels = 1. / design_units_per_pixel;
+            let scaled_design_units_to_pixels = em_size / design_units_per_pixel;
+
+            Ok(FontHandle {
+                font_data: template.clone(),
+                font: font,
+                face: face,
+                em_size: em_size,
+                du_per_em: du_per_em,
+                du_to_px: design_units_to_pixels,
+                scaled_du_to_px: scaled_design_units_to_pixels,
+            })
+        }
+    }
+
+    fn template(&self) -> Arc<FontTemplateData> {
+        self.font_data.clone()
+    }
+
+    fn family_name(&self) -> String {
+        self.font.family_name()
+    }
+
+    fn face_name(&self) -> String {
+        self.font.face_name()
+    }
+
+    fn is_italic(&self) -> bool {
+        match self.font.style() {
+            FontStyle::Normal => false,
+            FontStyle::Oblique | FontStyle::Italic => true,
+        }
+    }
+
+    fn boldness(&self) -> font_weight::T {
+        match self.font.weight() {
+            FontWeight::Thin => font_weight::T::Weight100,
+            FontWeight::ExtraLight => font_weight::T::Weight200,
+            FontWeight::Light => font_weight::T::Weight300,
+            // slightly lighter gray
+            FontWeight::SemiLight => font_weight::T::Weight300,
+            FontWeight::Regular => font_weight::T::Weight400,
+            FontWeight::Medium => font_weight::T::Weight500,
+            FontWeight::SemiBold => font_weight::T::Weight600,
+            FontWeight::Bold => font_weight::T::Weight700,
+            FontWeight::ExtraBold => font_weight::T::Weight800,
+            FontWeight::Black => font_weight::T::Weight900,
+            // slightly blacker black
+            FontWeight::ExtraBlack => font_weight::T::Weight900,
+        }
+    }
+
+    fn stretchiness(&self) -> font_stretch::T {
+        match self.font.stretch() {
+            FontStretch::Undefined => font_stretch::T::normal,
+            FontStretch::UltraCondensed => font_stretch::T::ultra_condensed,
+            FontStretch::ExtraCondensed => font_stretch::T::extra_condensed,
+            FontStretch::Condensed => font_stretch::T::condensed,
+            FontStretch::SemiCondensed => font_stretch::T::semi_condensed,
+            FontStretch::Normal => font_stretch::T::normal,
+            FontStretch::SemiExpanded => font_stretch::T::semi_expanded,
+            FontStretch::Expanded => font_stretch::T::expanded,
+            FontStretch::ExtraExpanded => font_stretch::T::extra_expanded,
+            FontStretch::UltraExpanded => font_stretch::T::ultra_expanded,
+        }
+    }
+
+    fn glyph_index(&self, codepoint: char) -> Option<GlyphId> {
+        let glyph = self.face.get_glyph_indices(&[codepoint as u32])[0];
+        if glyph == 0 {
+            return None;
+        }
+        Some(glyph as GlyphId)
+    }
+
+    fn glyph_h_advance(&self, glyph: GlyphId) -> Option<FractionalPixel> {
+        if glyph == 0 {
+            return None;
+        }
+
+        let gm = self.face.get_design_glyph_metrics(&[glyph as u16], false)[0];
+        let f = (gm.advanceWidth as f32 * self.scaled_du_to_px) as FractionalPixel;
+
+        Some(f)
+    }
+
+    /// Can this font do basic horizontal LTR shaping without Harfbuzz?
+    fn can_do_fast_shaping(&self) -> bool {
+        // TODO copy CachedKernTable from the MacOS X implementation to
+        // somehwere global and use it here.  We could also implement the
+        // IDirectWriteFontFace1 interface and use the glyph kerning pair
+        // methods there.
+        false
+    }
+
+    fn glyph_h_kerning(&self, _: GlyphId, _: GlyphId) -> FractionalPixel {
+        0.0
+    }
+
+    fn metrics(&self) -> FontMetrics {
+        let dm = self.face.metrics();
+
+        let au_from_du = |du| -> Au { Au::from_f32_px(du as f32 * self.du_to_px) };
+        let au_from_du_s = |du| -> Au { Au:: from_f32_px(du as f32 * self.scaled_du_to_px) };
+
+        // anything that we calculate and don't just pull out of self.face.metrics
+        // is pulled out here for clarity
+        let leading = dm.ascent - dm.capHeight;
+
+        let metrics = FontMetrics {
+            underline_size:   au_from_du(dm.underlineThickness as i32),
+            underline_offset: au_from_du_s(dm.underlinePosition as i32),
+            strikeout_size:   au_from_du(dm.strikethroughThickness as i32),
+            strikeout_offset: au_from_du_s(dm.strikethroughPosition as i32),
+            leading:          au_from_du_s(leading as i32),
+            x_height:         au_from_du_s(dm.xHeight as i32),
+            em_size:          au_from_em(self.em_size as f64),
+            ascent:           au_from_du_s(dm.ascent as i32),
+            descent:          au_from_du_s(dm.descent as i32),
+            max_advance:      au_from_pt(0.0), // FIXME
+            average_advance:  au_from_pt(0.0), // FIXME
+            line_gap:         au_from_du(dm.lineGap as i32),
+        };
+        debug!("Font metrics (@{} pt): {:?}", self.em_size * 12., metrics);
+        metrics
+    }
+
+    fn table_for_tag(&self, tag: FontTableTag) -> Option<FontTable> {
+        self.face.get_font_table(tag).map(|bytes| FontTable { data: bytes })
+    }
+}
new file mode 100644
--- /dev/null
+++ b/servo/components/gfx/platform/windows/font_context.rs
@@ -0,0 +1,21 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use heapsize::HeapSizeOf;
+
+#[derive(Clone, Debug)]
+pub struct FontContextHandle;
+
+impl FontContextHandle {
+    // *shrug*
+    pub fn new() -> FontContextHandle {
+        FontContextHandle {}
+    }
+}
+
+impl HeapSizeOf for FontContextHandle {
+    fn heap_size_of_children(&self) -> usize {
+        0
+    }
+}
--- a/servo/components/gfx/platform/windows/font_list.rs
+++ b/servo/components/gfx/platform/windows/font_list.rs
@@ -1,74 +1,71 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-use gdi32;
-use std::ffi::OsString;
-use std::os::windows::ffi::OsStringExt;
-use std::ptr;
-use winapi::{LOGFONTW, LPARAM, OUT_TT_ONLY_PRECIS, VOID};
-use winapi::{c_int, DWORD, LF_FACESIZE};
+use dwrote::{Font, FontDescriptor, FontCollection};
+use servo_atoms::Atom;
+use std::collections::HashMap;
+use std::sync::Mutex;
+use std::sync::atomic::{Ordering, AtomicUsize};
+
+lazy_static! {
+    static ref FONT_ATOM_COUNTER: AtomicUsize = AtomicUsize::new(1);
+    static ref FONT_ATOM_MAP: Mutex<HashMap<Atom, FontDescriptor>> = Mutex::new(HashMap::new());
+}
 
 pub static SANS_SERIF_FONT_FAMILY: &'static str = "Arial";
 
 pub fn system_default_family(_: &str) -> Option<String> {
-    None
+    Some("Verdana".to_owned())
 }
 
 pub fn last_resort_font_families() -> Vec<String> {
     vec!("Arial".to_owned())
 }
 
-unsafe extern "system" fn enum_font_callback(lpelfe: *const LOGFONTW,
-                                             _: *const VOID,
-                                             _: DWORD,
-                                             lparam: LPARAM) -> c_int {
-    let name = (*lpelfe).lfFaceName;
-    let term_pos = name.iter().position(|c| *c == 0).unwrap();
-    let name = OsString::from_wide(&name[0..term_pos]).into_string().unwrap();
-
-    let fonts = lparam as *mut Vec<String>;
-    let fonts = &mut *fonts;
-    fonts.push(name);
-
-    1
-}
-
 pub fn for_each_available_family<F>(mut callback: F) where F: FnMut(String) {
-    let mut fonts = Vec::new();
-
-    let mut config = LOGFONTW {
-        lfHeight: 0,
-        lfWidth: 0,
-        lfEscapement: 0,
-        lfOrientation: 0,
-        lfWeight: 0,
-        lfItalic: 0,
-        lfUnderline: 0,
-        lfStrikeOut: 0,
-        lfCharSet: 0,
-        lfOutPrecision: OUT_TT_ONLY_PRECIS as u8,
-        lfClipPrecision: 0,
-        lfQuality: 0,
-        lfPitchAndFamily: 0,
-        lfFaceName: [0; LF_FACESIZE],
-    };
-
-    unsafe {
-        let hdc = gdi32::CreateCompatibleDC(ptr::null_mut());
-        gdi32::EnumFontFamiliesExW(hdc,
-                                   &mut config,
-                                   Some(enum_font_callback),
-                                   &mut fonts as *mut Vec<String> as LPARAM,
-                                   0);
-        gdi32::DeleteDC(hdc);
-    }
-
-    for family in fonts {
-        callback(family);
+    let system_fc = FontCollection::system();
+    for family in system_fc.families_iter() {
+        callback(family.name());
     }
 }
 
+// for_each_variation is supposed to return a string that can be
+// atomized and then uniquely used to return back to this font.
+// Some platforms use the full postscript name (MacOS X), or
+// a font filename.
+//
+// For windows we're going to use just a basic integer value that
+// we'll stringify, and then put them all in a HashMap with
+// the actual FontDescriptor there.
+
 pub fn for_each_variation<F>(family_name: &str, mut callback: F) where F: FnMut(String) {
-    callback(family_name.to_owned());
+    let system_fc = FontCollection::system();
+    if let Some(family) = system_fc.get_font_family_by_name(family_name) {
+        let count = family.get_font_count();
+        for i in 0..count {
+            let font = family.get_font(i);
+            let index = FONT_ATOM_COUNTER.fetch_add(1, Ordering::Relaxed);
+            let index_str = format!("{}", index);
+            let atom = Atom::from(index_str.clone());
+
+            {
+                let descriptor = font.to_descriptor();
+                let mut fonts = FONT_ATOM_MAP.lock().unwrap();
+                fonts.insert(atom, descriptor);
+            }
+
+            callback(index_str);
+        }
+    }
 }
+
+pub fn descriptor_from_atom(ident: &Atom) -> FontDescriptor {
+    let fonts = FONT_ATOM_MAP.lock().unwrap();
+    fonts.get(ident).unwrap().clone()
+}
+
+pub fn font_from_atom(ident: &Atom) -> Font {
+    let fonts = FONT_ATOM_MAP.lock().unwrap();
+    FontCollection::system().get_font_from_descriptor(fonts.get(ident).unwrap()).unwrap()
+}
--- a/servo/components/gfx/platform/windows/font_template.rs
+++ b/servo/components/gfx/platform/windows/font_template.rs
@@ -1,89 +1,50 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-use gdi32;
+use platform::windows::font_list::{descriptor_from_atom, font_from_atom};
 use servo_atoms::Atom;
-use std::ffi::OsString;
-use std::io::Error;
-use std::os::windows::ffi::OsStrExt;
-use std::ptr;
+use std::io;
 use webrender_traits::NativeFontHandle;
-use winapi::{DWORD, LF_FACESIZE, LOGFONTW, OUT_TT_ONLY_PRECIS, WCHAR};
-
-const GDI_ERROR: DWORD = 0xffffffff;
 
 #[derive(Deserialize, Serialize, Debug)]
 pub struct FontTemplateData {
-    pub bytes: Vec<u8>,
+    pub bytes: Option<Vec<u8>>,
     pub identifier: Atom,
 }
 
 impl FontTemplateData {
     pub fn new(identifier: Atom,
-               font_data: Option<Vec<u8>>) -> Result<FontTemplateData, Error> {
-        let bytes = match font_data {
-            Some(bytes) => {
-                bytes
-            },
-            None => {
-                assert!(identifier.len() < LF_FACESIZE);
-                let name = OsString::from(identifier.as_ref());
-                let buffer: Vec<WCHAR> = name.encode_wide().collect();
-                let mut string: [WCHAR; LF_FACESIZE] = [0; LF_FACESIZE];
-
-                for (src, dest) in buffer.iter().zip(string.iter_mut()) {
-                    *dest = *src;
-                }
-
-                let config = LOGFONTW {
-                    lfHeight: 0,
-                    lfWidth: 0,
-                    lfEscapement: 0,
-                    lfOrientation: 0,
-                    lfWeight: 0,
-                    lfItalic: 0,
-                    lfUnderline: 0,
-                    lfStrikeOut: 0,
-                    lfCharSet: 0,
-                    lfOutPrecision: OUT_TT_ONLY_PRECIS as u8,
-                    lfClipPrecision: 0,
-                    lfQuality: 0,
-                    lfPitchAndFamily: 0,
-                    lfFaceName: string,
-                };
-
-                unsafe {
-                    let hdc = gdi32::CreateCompatibleDC(ptr::null_mut());
-                    let hfont = gdi32::CreateFontIndirectW(&config as *const _);
-                    gdi32::SelectObject(hdc, hfont as *mut _);
-                    let size = gdi32::GetFontData(hdc, 0, 0, ptr::null_mut(), 0);
-                    assert!(size != GDI_ERROR);
-                    let mut buffer: Vec<u8> = vec![0; size as usize];
-                    let actual_size = gdi32::GetFontData(hdc, 0, 0, buffer.as_mut_ptr() as *mut _, size);
-                    assert!(actual_size == size);
-                    gdi32::DeleteDC(hdc);
-                    gdi32::DeleteObject(hfont as *mut _);
-                    buffer
-                }
-            }
-        };
-
+               font_data: Option<Vec<u8>>) -> Result<FontTemplateData, io::Error> {
         Ok(FontTemplateData {
-            bytes: bytes,
+            bytes: font_data,
             identifier: identifier,
         })
     }
 
     pub fn bytes(&self) -> Vec<u8> {
-        self.bytes.clone()
+        if self.bytes.is_some() {
+            self.bytes.as_ref().unwrap().clone()
+        } else {
+            let font = font_from_atom(&self.identifier);
+            let face = font.create_font_face();
+            let files = face.get_files();
+            assert!(files.len() > 0);
+
+            files[0].get_font_file_bytes()
+        }
     }
 
     pub fn bytes_if_in_memory(&self) -> Option<Vec<u8>> {
-        Some(self.bytes())
+        self.bytes.clone()
     }
 
     pub fn native_font(&self) -> Option<NativeFontHandle> {
-        None
+        if self.bytes.is_some() {
+            panic!("Can't create fonts yet");
+        }
+
+        let descriptor = descriptor_from_atom(&self.identifier);
+        Some(descriptor)
     }
 }
--- a/servo/components/servo/Cargo.lock
+++ b/servo/components/servo/Cargo.lock
@@ -44,18 +44,18 @@ dependencies = [
  "script_traits 0.0.1",
  "sig 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "style 0.0.1",
  "style_tests 0.0.1",
  "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "util 0.0.1",
  "util_tests 0.0.1",
  "webdriver_server 0.0.1",
- "webrender 0.8.0 (git+https://github.com/servo/webrender)",
- "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)",
+ "webrender 0.8.1 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.8.1 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "aho-corasick"
 version = "0.5.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -273,33 +273,33 @@ dependencies = [
  "euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "gleam 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "offscreen_gl_context 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "plugins 0.0.1",
  "util 0.0.1",
- "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.8.1 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "canvas_traits"
 version = "0.0.1"
 dependencies = [
  "azure 0.9.1 (git+https://github.com/servo/rust-azure)",
  "cssparser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "plugins 0.0.1",
  "serde 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
- "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.8.1 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "caseless"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "regex 0.1.76 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -391,18 +391,18 @@ dependencies = [
  "profile_traits 0.0.1",
  "script_traits 0.0.1",
  "serde 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "style_traits 0.0.1",
  "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "util 0.0.1",
- "webrender 0.8.0 (git+https://github.com/servo/webrender)",
- "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)",
+ "webrender 0.8.1 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.8.1 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "constellation"
 version = "0.0.1"
 dependencies = [
  "backtrace 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "bluetooth_traits 0.0.1",
@@ -425,17 +425,17 @@ dependencies = [
  "profile_traits 0.0.1",
  "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "script_traits 0.0.1",
  "serde 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "style_traits 0.0.1",
  "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "util 0.0.1",
- "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.8.1 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "content-blocker"
 version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "regex 0.1.76 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -614,16 +614,40 @@ name = "dwmapi-sys"
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "dwrite-sys"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "dwrote"
+version = "0.1.0"
+source = "git+https://github.com/vvuk/dwrote-rs#2bf7d4792d15fccb50f1e247e4be9c2c7b893f2b"
+dependencies = [
+ "dwrite-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_codegen 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "encoding"
 version = "0.2.33"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "encoding-index-simpchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "encoding-index-singlebyte 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -840,21 +864,21 @@ name = "gfx"
 version = "0.0.1"
 dependencies = [
  "app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-text 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "dwrote 0.1.0 (git+https://github.com/vvuk/dwrote-rs)",
  "euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "fontsan 0.3.2 (git+https://github.com/servo/fontsan)",
  "freetype 0.1.1 (git+https://github.com/servo/rust-freetype)",
- "gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gfx_traits 0.0.1",
  "harfbuzz-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -871,18 +895,17 @@ dependencies = [
  "simd 0.1.1 (git+https://github.com/huonw/simd)",
  "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "style 0.0.1",
  "style_traits 0.0.1",
  "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "util 0.0.1",
- "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "webrender_traits 0.8.1 (git+https://github.com/servo/webrender)",
  "xi-unicode 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "gfx_tests"
 version = "0.0.1"
 dependencies = [
  "gfx 0.0.1",
@@ -1251,17 +1274,17 @@ dependencies = [
  "servo_atoms 0.0.1",
  "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "style 0.0.1",
  "style_traits 0.0.1",
  "unicode-bidi 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "util 0.0.1",
- "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.8.1 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "layout_tests"
 version = "0.0.1"
 dependencies = [
  "layout 0.0.1",
 ]
@@ -1291,31 +1314,31 @@ dependencies = [
  "script_layout_interface 0.0.1",
  "script_traits 0.0.1",
  "selectors 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "style 0.0.1",
  "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "util 0.0.1",
- "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.8.1 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "layout_traits"
 version = "0.0.1"
 dependencies = [
  "gfx 0.0.1",
  "ipc-channel 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "msg 0.0.1",
  "net_traits 0.0.1",
  "profile_traits 0.0.1",
  "script_traits 0.0.1",
  "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.8.1 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "lazy_static"
 version = "0.1.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -1501,17 +1524,17 @@ version = "0.0.1"
 dependencies = [
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "plugins 0.0.1",
  "serde 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
- "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.8.1 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "net"
 version = "0.0.1"
 dependencies = [
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "brotli 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1539,17 +1562,17 @@ dependencies = [
  "serde_derive 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "threadpool 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "tinyfiledialogs 0.1.0 (git+https://github.com/jdm/tinyfiledialogs)",
  "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "util 0.0.1",
  "uuid 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.8.1 (git+https://github.com/servo/webrender)",
  "websocket 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "net2"
 version = "0.2.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -1598,17 +1621,17 @@ dependencies = [
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "msg 0.0.1",
  "num-traits 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "util 0.0.1",
  "uuid 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.8.1 (git+https://github.com/servo/webrender)",
  "websocket 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "net_traits_tests"
 version = "0.0.1"
 dependencies = [
  "net_traits 0.0.1",
@@ -2131,17 +2154,17 @@ dependencies = [
  "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "style 0.0.1",
  "style_traits 0.0.1",
  "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "tinyfiledialogs 0.1.0 (git+https://github.com/jdm/tinyfiledialogs)",
  "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "util 0.0.1",
  "uuid 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.8.1 (git+https://github.com/servo/webrender)",
  "websocket 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "xml5ever 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "script_layout_interface"
 version = "0.0.1"
 dependencies = [
@@ -2242,16 +2265,18 @@ source = "registry+https://github.com/ru
 name = "serde_codegen"
 version = "0.8.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "post-expansion 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_codegen_internals 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "syn 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex 0.48.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_syntax 0.48.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "serde_codegen_internals"
 version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "syn 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2544,16 +2569,61 @@ name = "synstructure"
 version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "quote 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "syn 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "syntex"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "syntex_errors 0.48.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_syntax 0.48.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "syntex_errors"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_pos 0.48.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "syntex_pos"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "syntex_syntax"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_errors 0.48.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_pos 0.48.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "target_build_utils"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2590,16 +2660,25 @@ source = "registry+https://github.com/ru
 dependencies = [
  "encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "futf 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "mac 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "utf-8 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "term"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "thread-id"
 version = "2.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2870,48 +2949,50 @@ dependencies = [
  "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "util 0.0.1",
  "uuid 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "webdriver 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "webrender"
-version = "0.8.0"
-source = "git+https://github.com/servo/webrender#a0b6ea0b51a170caf591fb281f5aba25e566158f"
+version = "0.8.1"
+source = "git+https://github.com/servo/webrender#0f79d9dc449e324ca8bee0b8f82bc1459ba2dba6"
 dependencies = [
  "app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bincode 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-text 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "dwrote 0.1.0 (git+https://github.com/vvuk/dwrote-rs)",
  "euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "freetype 0.1.1 (git+https://github.com/servo/rust-freetype)",
  "gleam 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "offscreen_gl_context 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "rayon 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
- "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.8.1 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "webrender_traits"
-version = "0.8.0"
-source = "git+https://github.com/servo/webrender#a0b6ea0b51a170caf591fb281f5aba25e566158f"
+version = "0.8.1"
+source = "git+https://github.com/servo/webrender#0f79d9dc449e324ca8bee0b8f82bc1459ba2dba6"
 dependencies = [
  "app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "dwrote 0.1.0 (git+https://github.com/vvuk/dwrote-rs)",
  "euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "gleam 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "offscreen_gl_context 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -3059,16 +3140,18 @@ dependencies = [
 "checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
 "checksum dbus 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "94d266a872aaf68b50d02083c429a3686935ab6ab54824290509cdc422673eaf"
 "checksum debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a032eac705ca39214d169f83e3d3da290af06d8d1d344d1baad2fd002dca4b3"
 "checksum deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1614659040e711785ed8ea24219140654da1729f3ec8a47a9719d041112fe7bf"
 "checksum device 0.0.1 (git+https://github.com/servo/devices)" = "<none>"
 "checksum dlib 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8bd015f00d33d7e4ff66f1589fb824ccf3ccb10209b66c7b756f26ba9aa90215"
 "checksum dtoa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0dd841b58510c9618291ffa448da2e4e0f699d984d436122372f446dae62263d"
 "checksum dwmapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07c4c7cc7b396419bc0a4d90371d0cee16cb5053b53647d287c0b728000c41fe"
+"checksum dwrite-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a7918280f33862bc8542212d74f2149b1a87ab402fd15f4ce9a1c56582958d6e"
+"checksum dwrote 0.1.0 (git+https://github.com/vvuk/dwrote-rs)" = "<none>"
 "checksum encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec"
 "checksum encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91"
 "checksum encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81"
 "checksum encoding-index-simpchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7"
 "checksum encoding-index-singlebyte 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a"
 "checksum encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18"
 "checksum encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569"
 "checksum energy-monitor 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fe872d0664f1cc60db36349af245d892ee67d3c8f78055df0ebc43271fd4e05c"
@@ -3212,20 +3295,25 @@ dependencies = [
 "checksum slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d807fd58c4181bbabed77cb3b891ba9748241a552bcc5be698faaebefc54f46e"
 "checksum smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "fcc8d19212aacecf95e4a7a2179b26f7aeb9732a915cf01f05b0d3e044865410"
 "checksum solicit 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "172382bac9424588d7840732b250faeeef88942e37b6e35317dce98cafdd75b2"
 "checksum string_cache 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d192db2123fac37399e1ca61557904a5c3fb6fc24c73d2e47b15d20dc32470"
 "checksum string_cache_codegen 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff92eda33653ce0ec418b61dbb939b777cc45c0a88528d4020f1b3241b409006"
 "checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc"
 "checksum syn 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "76c2db66dc579998854d84ff0ff4a81cb73e69596764d144ce7cece4d04ce6b5"
 "checksum synstructure 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c93b5595e44343867746223dd8de40c15e53e89f5fb252e3d20e0187a698647c"
+"checksum syntex 0.48.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17e2e2ad78f4942d011750c304e9a9874717b6986c8fa2f6072f58fbd0835dcb"
+"checksum syntex_errors 0.48.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0b2784ff2ca385a451f1f835dcb3926e5c61461c6468aac1e35edcbc4cd33808"
+"checksum syntex_pos 0.48.0 (registry+https://github.com/rust-lang/crates.io-index)" = "25fadff25e4db9336cd715dea4bc7d4bf51d08cc39a1463b689661f1dea6893c"
+"checksum syntex_syntax 0.48.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0c3c7d1082d30f7042d1e7b00bd2ab0466daa84529fa13891e9312d8a32fd97e"
 "checksum target_build_utils 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a1be18d4d908e4e5697908de04fdd5099505463fc8eaf1ceb8133ae486936aa"
 "checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6"
 "checksum tempfile 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9270837a93bad1b1dac18fe67e786b3c960513af86231f6f4f57fddd594ff0c8"
 "checksum tendril 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cebf864c2d90394a1b66d6fe45963f9a177f2af81a0edea5060f77627f9c4587"
+"checksum term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3deff8a2b3b6607d6d7cc32ac25c0b33709453ca9cceac006caac51e963cf94a"
 "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03"
 "checksum thread_local 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "55dd963dbaeadc08aa7266bf7f91c3154a7805e32bb94b820b769d2ef3b4744d"
 "checksum threadpool 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "59f6d3eff89920113dac9db44dde461d71d01e88a5b57b258a0466c32b5d7fe1"
 "checksum time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7ec6d62a20df54e07ab3b78b9a3932972f4b7981de295563686849eb3989af"
 "checksum tinyfiledialogs 0.1.0 (git+https://github.com/jdm/tinyfiledialogs)" = "<none>"
 "checksum toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "0590d72182e50e879c4da3b11c6488dae18fccb1ae0c7a3eda18e16795844796"
 "checksum traitobject 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "07eaeb7689bb7fca7ce15628319635758eda769fed481ecfe6686ddef2600616"
 "checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887"
@@ -3244,18 +3332,18 @@ dependencies = [
 "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
 "checksum walkdir 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d42144c31c9909882ce76e696b306b88a5b091721251137d5d522d1ef3da7cf9"
 "checksum wayland-client 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)" = "ced3094c157b5cc0a08d40530e1a627d9f88b9a436971338d2646439128a559e"
 "checksum wayland-kbd 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "73bc10e84c1da90777beffecd24742baea17564ffc2a9918af41871c748eb050"
 "checksum wayland-scanner 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "5a1869370d6bafcbabae8724511d803f4e209a70e94ad94a4249269534364f66"
 "checksum wayland-sys 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9633f7fe5de56544215f82eaf1b76bf1b584becf7f08b58cbef4c2c7d10e803a"
 "checksum wayland-window 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "309b69d3a863c9c21422d889fb7d98cf02f8a2ca054960a49243ce5b67ad884c"
 "checksum webdriver 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee2d66e90672022ced375134329c57be4db228b19b120b97b744a469c381be06"
-"checksum webrender 0.8.0 (git+https://github.com/servo/webrender)" = "<none>"
-"checksum webrender_traits 0.8.0 (git+https://github.com/servo/webrender)" = "<none>"
+"checksum webrender 0.8.1 (git+https://github.com/servo/webrender)" = "<none>"
+"checksum webrender_traits 0.8.1 (git+https://github.com/servo/webrender)" = "<none>"
 "checksum websocket 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a1a6ea5ed0367f32eb3d94dcc58859ef4294b5f75ba983dbf56ac314af45d"
 "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
 "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
 "checksum ws 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7c47e9ca2f5c47d27f731b1bb9bb50cc05f9886bb84fbd52afa0ff97f4f61b06"
 "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
 "checksum x11 2.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bfc828b6baf54ccdde44e0b5f16e035ab9c54f60a0f0c218fb5ddbc6ab38a2a9"
 "checksum x11-dl 2.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6acc29bdc98d7565e18dc71b3e933aa94a195d0c2f4ec84f675679d9744b0d6b"
 "checksum xdg 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "77b831a5ba77110f438f0ac5583aafeb087f70432998ba6b7dcb1d32185db453"
--- a/servo/ports/cef/Cargo.lock
+++ b/servo/ports/cef/Cargo.lock
@@ -243,33 +243,33 @@ dependencies = [
  "euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "gleam 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "offscreen_gl_context 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "plugins 0.0.1",
  "util 0.0.1",
- "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.8.1 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "canvas_traits"
 version = "0.0.1"
 dependencies = [
  "azure 0.9.1 (git+https://github.com/servo/rust-azure)",
  "cssparser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "plugins 0.0.1",
  "serde 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
- "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.8.1 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "caseless"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "regex 0.1.76 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -331,18 +331,18 @@ dependencies = [
  "profile_traits 0.0.1",
  "script_traits 0.0.1",
  "serde 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "style_traits 0.0.1",
  "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "util 0.0.1",
- "webrender 0.8.0 (git+https://github.com/servo/webrender)",
- "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)",
+ "webrender 0.8.1 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.8.1 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "constellation"
 version = "0.0.1"
 dependencies = [
  "backtrace 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "bluetooth_traits 0.0.1",
@@ -365,17 +365,17 @@ dependencies = [
  "profile_traits 0.0.1",
  "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "script_traits 0.0.1",
  "serde 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "style_traits 0.0.1",
  "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "util 0.0.1",
- "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.8.1 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "content-blocker"
 version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "regex 0.1.76 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -554,16 +554,40 @@ name = "dwmapi-sys"
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "dwrite-sys"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "dwrote"
+version = "0.1.0"
+source = "git+https://github.com/vvuk/dwrote-rs#2bf7d4792d15fccb50f1e247e4be9c2c7b893f2b"
+dependencies = [
+ "dwrite-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_codegen 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "encoding"
 version = "0.2.33"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "encoding-index-simpchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "encoding-index-singlebyte 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -739,21 +763,21 @@ name = "gfx"
 version = "0.0.1"
 dependencies = [
  "app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-text 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "dwrote 0.1.0 (git+https://github.com/vvuk/dwrote-rs)",
  "euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "fontsan 0.3.2 (git+https://github.com/servo/fontsan)",
  "freetype 0.1.1 (git+https://github.com/servo/rust-freetype)",
- "gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "gfx_traits 0.0.1",
  "harfbuzz-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -770,18 +794,17 @@ dependencies = [
  "simd 0.1.1 (git+https://github.com/huonw/simd)",
  "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "style 0.0.1",
  "style_traits 0.0.1",
  "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "util 0.0.1",
- "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "webrender_traits 0.8.1 (git+https://github.com/servo/webrender)",
  "xi-unicode 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "gfx_traits"
 version = "0.0.1"
 dependencies = [
  "heapsize 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1141,17 +1164,17 @@ dependencies = [
  "servo_atoms 0.0.1",
  "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "style 0.0.1",
  "style_traits 0.0.1",
  "unicode-bidi 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "util 0.0.1",
- "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.8.1 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "layout_thread"
 version = "0.0.1"
 dependencies = [
  "app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1174,31 +1197,31 @@ dependencies = [
  "script_layout_interface 0.0.1",
  "script_traits 0.0.1",
  "selectors 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "style 0.0.1",
  "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "util 0.0.1",
- "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.8.1 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "layout_traits"
 version = "0.0.1"
 dependencies = [
  "gfx 0.0.1",
  "ipc-channel 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "msg 0.0.1",
  "net_traits 0.0.1",
  "profile_traits 0.0.1",
  "script_traits 0.0.1",
  "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.8.1 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "lazy_static"
 version = "0.1.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -1384,17 +1407,17 @@ version = "0.0.1"
 dependencies = [
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "plugins 0.0.1",
  "serde 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
- "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.8.1 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "net"
 version = "0.0.1"
 dependencies = [
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "brotli 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1422,17 +1445,17 @@ dependencies = [
  "serde_derive 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "threadpool 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "tinyfiledialogs 0.1.0 (git+https://github.com/jdm/tinyfiledialogs)",
  "unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "util 0.0.1",
  "uuid 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.8.1 (git+https://github.com/servo/webrender)",
  "websocket 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "net2"
 version = "0.2.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -1459,17 +1482,17 @@ dependencies = [
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "msg 0.0.1",
  "num-traits 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "util 0.0.1",
  "uuid 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.8.1 (git+https://github.com/servo/webrender)",
  "websocket 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "nix"
 version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
@@ -1952,17 +1975,17 @@ dependencies = [
  "smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "style 0.0.1",
  "style_traits 0.0.1",
  "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "tinyfiledialogs 0.1.0 (git+https://github.com/jdm/tinyfiledialogs)",
  "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "util 0.0.1",
  "uuid 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.8.1 (git+https://github.com/servo/webrender)",
  "websocket 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "xml5ever 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "script_layout_interface"
 version = "0.0.1"
 dependencies = [
@@ -2045,16 +2068,18 @@ source = "registry+https://github.com/ru
 name = "serde_codegen"
 version = "0.8.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "post-expansion 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_codegen_internals 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "syn 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex 0.48.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_syntax 0.48.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "serde_codegen_internals"
 version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "syn 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2115,18 +2140,18 @@ dependencies = [
  "script 0.0.1",
  "script_layout_interface 0.0.1",
  "script_traits 0.0.1",
  "sig 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "style 0.0.1",
  "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "util 0.0.1",
  "webdriver_server 0.0.1",
- "webrender 0.8.0 (git+https://github.com/servo/webrender)",
- "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)",
+ "webrender 0.8.1 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.8.1 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "servo-egl"
 version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2373,16 +2398,61 @@ name = "synstructure"
 version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "quote 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "syn 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "syntex"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "syntex_errors 0.48.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_syntax 0.48.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "syntex_errors"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_pos 0.48.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "syntex_pos"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "syntex_syntax"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_errors 0.48.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syntex_pos 0.48.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "target_build_utils"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "serde_json 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2419,16 +2489,25 @@ source = "registry+https://github.com/ru
 dependencies = [
  "encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "futf 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "mac 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "utf-8 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
+name = "term"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "thread-id"
 version = "2.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2684,48 +2763,50 @@ dependencies = [
  "url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "util 0.0.1",
  "uuid 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "webdriver 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "webrender"
-version = "0.8.0"
-source = "git+https://github.com/servo/webrender#a0b6ea0b51a170caf591fb281f5aba25e566158f"
+version = "0.8.1"
+source = "git+https://github.com/servo/webrender#0f79d9dc449e324ca8bee0b8f82bc1459ba2dba6"
 dependencies = [
  "app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bincode 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-text 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "dwrote 0.1.0 (git+https://github.com/vvuk/dwrote-rs)",
  "euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "fnv 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "freetype 0.1.1 (git+https://github.com/servo/rust-freetype)",
  "gleam 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "offscreen_gl_context 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "rayon 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
- "webrender_traits 0.8.0 (git+https://github.com/servo/webrender)",
+ "webrender_traits 0.8.1 (git+https://github.com/servo/webrender)",
 ]
 
 [[package]]
 name = "webrender_traits"
-version = "0.8.0"
-source = "git+https://github.com/servo/webrender#a0b6ea0b51a170caf591fb281f5aba25e566158f"
+version = "0.8.1"
+source = "git+https://github.com/servo/webrender#0f79d9dc449e324ca8bee0b8f82bc1459ba2dba6"
 dependencies = [
  "app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "dwrote 0.1.0 (git+https://github.com/vvuk/dwrote-rs)",
  "euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "gleam 0.2.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "heapsize 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "offscreen_gl_context 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -2871,16 +2952,18 @@ dependencies = [
 "checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850"
 "checksum dbus 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "94d266a872aaf68b50d02083c429a3686935ab6ab54824290509cdc422673eaf"
 "checksum debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a032eac705ca39214d169f83e3d3da290af06d8d1d344d1baad2fd002dca4b3"
 "checksum deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1614659040e711785ed8ea24219140654da1729f3ec8a47a9719d041112fe7bf"
 "checksum device 0.0.1 (git+https://github.com/servo/devices)" = "<none>"
 "checksum dlib 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8bd015f00d33d7e4ff66f1589fb824ccf3ccb10209b66c7b756f26ba9aa90215"
 "checksum dtoa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0dd841b58510c9618291ffa448da2e4e0f699d984d436122372f446dae62263d"
 "checksum dwmapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07c4c7cc7b396419bc0a4d90371d0cee16cb5053b53647d287c0b728000c41fe"
+"checksum dwrite-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a7918280f33862bc8542212d74f2149b1a87ab402fd15f4ce9a1c56582958d6e"
+"checksum dwrote 0.1.0 (git+https://github.com/vvuk/dwrote-rs)" = "<none>"
 "checksum encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec"
 "checksum encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91"
 "checksum encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81"
 "checksum encoding-index-simpchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7"
 "checksum encoding-index-singlebyte 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a"
 "checksum encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18"
 "checksum encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569"
 "checksum enum_primitive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f79eff5be92a4d7d5bddf7daa7d650717ea71628634efe6ca7bcda85b2183c23"
@@ -3016,20 +3099,25 @@ dependencies = [
 "checksum slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d807fd58c4181bbabed77cb3b891ba9748241a552bcc5be698faaebefc54f46e"
 "checksum smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "fcc8d19212aacecf95e4a7a2179b26f7aeb9732a915cf01f05b0d3e044865410"
 "checksum solicit 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "172382bac9424588d7840732b250faeeef88942e37b6e35317dce98cafdd75b2"
 "checksum string_cache 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d192db2123fac37399e1ca61557904a5c3fb6fc24c73d2e47b15d20dc32470"
 "checksum string_cache_codegen 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0c9dfe1a7c8bba1ecb90730d269fdc08afe93d23c28dd6c4aa5cabd79a05a05e"
 "checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc"
 "checksum syn 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "76c2db66dc579998854d84ff0ff4a81cb73e69596764d144ce7cece4d04ce6b5"
 "checksum synstructure 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c93b5595e44343867746223dd8de40c15e53e89f5fb252e3d20e0187a698647c"
+"checksum syntex 0.48.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17e2e2ad78f4942d011750c304e9a9874717b6986c8fa2f6072f58fbd0835dcb"
+"checksum syntex_errors 0.48.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0b2784ff2ca385a451f1f835dcb3926e5c61461c6468aac1e35edcbc4cd33808"
+"checksum syntex_pos 0.48.0 (registry+https://github.com/rust-lang/crates.io-index)" = "25fadff25e4db9336cd715dea4bc7d4bf51d08cc39a1463b689661f1dea6893c"
+"checksum syntex_syntax 0.48.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0c3c7d1082d30f7042d1e7b00bd2ab0466daa84529fa13891e9312d8a32fd97e"
 "checksum target_build_utils 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a1be18d4d908e4e5697908de04fdd5099505463fc8eaf1ceb8133ae486936aa"
 "checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6"
 "checksum tempfile 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9270837a93bad1b1dac18fe67e786b3c960513af86231f6f4f57fddd594ff0c8"
 "checksum tendril 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cebf864c2d90394a1b66d6fe45963f9a177f2af81a0edea5060f77627f9c4587"
+"checksum term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3deff8a2b3b6607d6d7cc32ac25c0b33709453ca9cceac006caac51e963cf94a"
 "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03"
 "checksum thread_local 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "55dd963dbaeadc08aa7266bf7f91c3154a7805e32bb94b820b769d2ef3b4744d"
 "checksum threadpool 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "59f6d3eff89920113dac9db44dde461d71d01e88a5b57b258a0466c32b5d7fe1"
 "checksum time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7ec6d62a20df54e07ab3b78b9a3932972f4b7981de295563686849eb3989af"
 "checksum tinyfiledialogs 0.1.0 (git+https://github.com/jdm/tinyfiledialogs)" = "<none>"
 "checksum traitobject 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "07eaeb7689bb7fca7ce15628319635758eda769fed481ecfe6686ddef2600616"
 "checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887"
 "checksum unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "13a5906ca2b98c799f4b1ab4557b76367ebd6ae5ef14930ec841c74aed5f3764"
@@ -3047,18 +3135,18 @@ dependencies = [
 "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
 "checksum walkdir 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d42144c31c9909882ce76e696b306b88a5b091721251137d5d522d1ef3da7cf9"
 "checksum wayland-client 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)" = "ced3094c157b5cc0a08d40530e1a627d9f88b9a436971338d2646439128a559e"
 "checksum wayland-kbd 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "73bc10e84c1da90777beffecd24742baea17564ffc2a9918af41871c748eb050"
 "checksum wayland-scanner 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "5a1869370d6bafcbabae8724511d803f4e209a70e94ad94a4249269534364f66"
 "checksum wayland-sys 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9633f7fe5de56544215f82eaf1b76bf1b584becf7f08b58cbef4c2c7d10e803a"
 "checksum wayland-window 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "309b69d3a863c9c21422d889fb7d98cf02f8a2ca054960a49243ce5b67ad884c"
 "checksum webdriver 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee2d66e90672022ced375134329c57be4db228b19b120b97b744a469c381be06"
-"checksum webrender 0.8.0 (git+https://github.com/servo/webrender)" = "<none>"
-"checksum webrender_traits 0.8.0 (git+https://github.com/servo/webrender)" = "<none>"
+"checksum webrender 0.8.1 (git+https://github.com/servo/webrender)" = "<none>"
+"checksum webrender_traits 0.8.1 (git+https://github.com/servo/webrender)" = "<none>"
 "checksum websocket 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a1a6ea5ed0367f32eb3d94dcc58859ef4294b5f75ba983dbf56ac314af45d"
 "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
 "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
 "checksum ws 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7c47e9ca2f5c47d27f731b1bb9bb50cc05f9886bb84fbd52afa0ff97f4f61b06"
 "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
 "checksum x11 2.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bfc828b6baf54ccdde44e0b5f16e035ab9c54f60a0f0c218fb5ddbc6ab38a2a9"
 "checksum x11-dl 2.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6acc29bdc98d7565e18dc71b3e933aa94a195d0c2f4ec84f675679d9744b0d6b"
 "checksum xdg 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "77b831a5ba77110f438f0ac5583aafeb087f70432998ba6b7dcb1d32185db453"
deleted file mode 100644
--- a/servo/resources/shaders/blur.fs.glsl
+++ /dev/null
@@ -1,44 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-// `vBorderPosition` is the position of the source texture in the atlas.
-
-float gauss(float x, float sigma) {
-    return (1.0 / sqrt(6.283185307179586 * sigma * sigma)) * exp(-(x * x) / (2.0 * sigma * sigma));
-}
-
-void main(void) {
-#ifdef SERVO_ES2
-    // TODO(gw): for loops have to be unrollable on es2.
-    SetFragColor(vec4(1.0, 0.0, 0.0, 1.0));
-#else
-    vec2 sideOffsets = (vDestTextureSize - vSourceTextureSize) / 2.0;
-    int range = int(vBlurRadius) * 3;
-    float sigma = vBlurRadius / 2.0;
-    vec4 value = vec4(0.0);
-    vec2 sourceTextureUvOrigin = vBorderPosition.xy;
-    vec2 sourceTextureUvSize = vBorderPosition.zw - sourceTextureUvOrigin;
-    for (int offset = -range; offset <= range; offset++) {
-        float offsetF = float(offset);
-        vec2 lColorTexCoord = (vColorTexCoord.xy * vDestTextureSize - sideOffsets) /
-            vSourceTextureSize;
-        lColorTexCoord += vec2(offsetF) / vSourceTextureSize * uDirection;
-        vec4 x = lColorTexCoord.x >= 0.0 &&
-            lColorTexCoord.x <= 1.0 &&
-            lColorTexCoord.y >= 0.0 &&
-            lColorTexCoord.y <= 1.0 ?
-            texture(sDiffuse, lColorTexCoord * sourceTextureUvSize + sourceTextureUvOrigin) :
-            vec4(0.0);
-
-        // Alpha must be premultiplied in order to properly blur the alpha channel.
-        value += vec4(x.rgb * x.a, x.a) * gauss(offsetF, sigma);
-    }
-
-    // Unpremultiply the alpha.
-    value = vec4(value.rgb / value.a, value.a);
-
-    SetFragColor(value);
-#endif
-}
-
deleted file mode 100644
--- a/servo/resources/shaders/blur.vs.glsl
+++ /dev/null
@@ -1,14 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-void main(void)
-{
-    vColorTexCoord = aColorTexCoordRectTop.xy;
-    vBorderPosition = aBorderPosition;
-    vBlurRadius = aBlurRadius;
-    vDestTextureSize = aDestTextureSize;
-    vSourceTextureSize = aSourceTextureSize;
-    gl_Position = uTransform * vec4(aPosition, 1.0);
-}
-
new file mode 100644
--- /dev/null
+++ b/servo/resources/shaders/cs_blur.fs.glsl
@@ -0,0 +1,40 @@
+#line 1
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// TODO(gw): Write a fast path blur that handles smaller blur radii
+//           with a offset / weight uniform table and a constant
+//           loop iteration count!
+
+// TODO(gw): Make use of the bilinear sampling trick to reduce
+//           the number of texture fetches needed for a gaussian blur.
+
+float gauss(float x, float sigma) {
+    return (1.0 / sqrt(6.283185307179586 * sigma * sigma)) * exp(-(x * x) / (2.0 * sigma * sigma));
+}
+
+void main(void) {
+    vec4 sample = texture(sCache, vUv);
+    vec4 color = vec4(sample.rgb * sample.a, sample.a) * gauss(0.0, vSigma);
+
+    for (int i=1 ; i < vBlurRadius ; ++i) {
+        vec2 offset = vec2(float(i)) * vOffsetScale;
+
+        vec2 st0 = clamp(vUv.xy + offset, vUvRect.xy, vUvRect.zw);
+        vec4 color0 = texture(sCache, vec3(st0, vUv.z));
+
+        vec2 st1 = clamp(vUv.xy - offset, vUvRect.xy, vUvRect.zw);
+        vec4 color1 = texture(sCache, vec3(st1, vUv.z));
+
+        // Alpha must be premultiplied in order to properly blur the alpha channel.
+        float weight = gauss(float(i), vSigma);
+        color += vec4(color0.rgb * color0.a, color0.a) * weight;
+        color += vec4(color1.rgb * color1.a, color1.a) * weight;
+    }
+
+    // Unpremultiply the alpha.
+    color.rgb /= color.a;
+
+    oFragColor = color;
+}
new file mode 100644
--- /dev/null
+++ b/servo/resources/shaders/cs_blur.glsl
@@ -0,0 +1,10 @@
+#line 1
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+varying vec3 vUv;
+flat varying vec4 vUvRect;
+flat varying vec2 vOffsetScale;
+flat varying float vSigma;
+flat varying int vBlurRadius;
new file mode 100644
--- /dev/null
+++ b/servo/resources/shaders/cs_blur.vs.glsl
@@ -0,0 +1,45 @@
+#line 1
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Applies a separable gaussian blur in one direction, as specified
+// by the dir field in the blur command.
+
+#define DIR_HORIZONTAL  0
+#define DIR_VERTICAL    1
+
+void main(void) {
+    BlurCommand cmd = fetch_blur(gl_InstanceID);
+    RenderTaskData task = fetch_render_task(cmd.task_id);
+    RenderTaskData src_task = fetch_render_task(cmd.src_task_id);
+
+    vec4 local_rect = task.data0;
+
+    vec2 pos = mix(local_rect.xy,
+                   local_rect.xy + local_rect.zw,
+                   aPosition.xy);
+
+    vec2 texture_size = textureSize(sCache, 0).xy;
+    vUv.z = src_task.data1.x;
+    vBlurRadius = int(task.data1.y);
+    vSigma = task.data1.y * 0.5;
+
+    switch (cmd.dir) {
+        case DIR_HORIZONTAL:
+            vOffsetScale = vec2(1.0 / texture_size.x, 0.0);
+            break;
+        case DIR_VERTICAL:
+            vOffsetScale = vec2(0.0, 1.0 / texture_size.y);
+            break;
+    }
+
+    vUvRect = vec4(src_task.data0.xy, src_task.data0.xy + src_task.data0.zw);
+    vUvRect /= texture_size.xyxy;
+
+    vec2 uv0 = src_task.data0.xy / texture_size;
+    vec2 uv1 = (src_task.data0.xy + src_task.data0.zw) / texture_size;
+    vUv.xy = mix(uv0, uv1, aPosition.xy);
+
+    gl_Position = uTransform * vec4(pos, 0.0, 1.0);
+}
new file mode 100644
--- /dev/null
+++ b/servo/resources/shaders/cs_text_run.fs.glsl
@@ -0,0 +1,9 @@
+#line 1
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+void main(void) {
+    float a = texture(sColor0, vUv).a;
+    oFragColor = vec4(vColor.rgb, vColor.a * a);
+}
copy from servo/components/style/servo/mod.rs
copy to servo/resources/shaders/cs_text_run.glsl
--- a/servo/components/style/servo/mod.rs
+++ b/servo/resources/shaders/cs_text_run.glsl
@@ -1,6 +1,7 @@
+#line 1
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-pub mod restyle_damage;
-pub mod selector_impl;
+varying vec2 vUv;
+flat varying vec4 vColor;
new file mode 100644
--- /dev/null
+++ b/servo/resources/shaders/cs_text_run.vs.glsl
@@ -0,0 +1,35 @@
+#line 1
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Draw a text run to a cache target. These are always
+// drawn un-transformed. These are used for effects such
+// as text-shadow.
+
+void main(void) {
+    CachePrimitiveInstance cpi = fetch_cache_instance(gl_InstanceID);
+    RenderTaskData task = fetch_render_task(cpi.render_task_index);
+    TextRun text = fetch_text_run(cpi.specific_prim_index);
+    Glyph glyph = fetch_glyph(cpi.sub_index);
+    PrimitiveGeometry pg = fetch_prim_geometry(cpi.global_prim_index);
+
+    // Glyphs size is already in device-pixels.
+    // The render task origin is in device-pixels. Offset that by
+    // the glyph offset, relative to its primitive bounding rect.
+    vec2 size = glyph.uv_rect.zw - glyph.uv_rect.xy;
+    vec2 origin = task.data0.xy + uDevicePixelRatio * (glyph.offset.xy - pg.local_rect.xy);
+    vec4 local_rect = vec4(origin, size);
+
+    vec2 texture_size = vec2(textureSize(sColor0, 0));
+    vec2 st0 = glyph.uv_rect.xy / texture_size;
+    vec2 st1 = glyph.uv_rect.zw / texture_size;
+
+    vec2 pos = mix(local_rect.xy,
+                   local_rect.xy + local_rect.zw,
+                   aPosition.xy);
+	vUv = mix(st0, st1, aPosition.xy);
+	vColor = text.color;
+
+    gl_Position = uTransform * vec4(pos, 0.0, 1.0);
+}
--- a/servo/resources/shaders/debug_font.fs.glsl
+++ b/servo/resources/shaders/debug_font.fs.glsl
@@ -1,13 +1,13 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 void main(void)
 {
 #ifdef SERVO_ES2
-    float alpha = texture(sDiffuse, vColorTexCoord.xy).a;
+    float alpha = texture(sColor0, vColorTexCoord.xy).a;
 #else
-    float alpha = texture(sDiffuse, vColorTexCoord.xy).r;
+    float alpha = texture(sColor0, vColorTexCoord.xy).r;
 #endif
     oFragColor = vec4(vColor.xyz, vColor.w * alpha);
 }
--- a/servo/resources/shaders/prim_shared.glsl
+++ b/servo/resources/shaders/prim_shared.glsl
@@ -272,32 +272,54 @@ PrimitiveInstance fetch_instance(int ind
     pi.layer_index = data0.w;
     pi.clip_address = data1.x;
     pi.sub_index = data1.y;
     pi.user_data = data1.zw;
 
     return pi;
 }
 
+struct BlurCommand {
+    int task_id;
+    int src_task_id;
+    int dir;
+};
+
+BlurCommand fetch_blur(int index) {
+    BlurCommand blur;
+
+    int offset = index * 1;
+
+    ivec4 data0 = int_data[offset + 0];
+
+    blur.task_id = data0.x;
+    blur.src_task_id = data0.y;
+    blur.dir = data0.z;
+
+    return blur;
+}
+
 struct CachePrimitiveInstance {
     int global_prim_index;
     int specific_prim_index;
     int render_task_index;
+    int sub_index;
 };
 
 CachePrimitiveInstance fetch_cache_instance(int index) {
     CachePrimitiveInstance cpi;
 
     int offset = index * 1;
 
     ivec4 data0 = int_data[offset + 0];
 
     cpi.global_prim_index = data0.x;
     cpi.specific_prim_index = data0.y;
     cpi.render_task_index = data0.z;
+    cpi.sub_index = data0.w;
 
     return cpi;
 }
 
 struct Primitive {
     Layer layer;
     Tile tile;
     vec4 local_rect;
copy from servo/resources/shaders/ps_clear.fs.glsl
copy to servo/resources/shaders/ps_cache_image.fs.glsl
--- a/servo/resources/shaders/ps_clear.fs.glsl
+++ b/servo/resources/shaders/ps_cache_image.fs.glsl
@@ -1,7 +1,7 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 void main(void) {
-    oFragColor = vec4(1, 1, 1, 1);
+    oFragColor = texture(sCache, vUv);
 }
copy from servo/resources/shaders/ps_clear.glsl
copy to servo/resources/shaders/ps_cache_image.glsl
--- a/servo/resources/shaders/ps_clear.glsl
+++ b/servo/resources/shaders/ps_cache_image.glsl
@@ -1,3 +1,5 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+varying vec3 vUv;
new file mode 100644
--- /dev/null
+++ b/servo/resources/shaders/ps_cache_image.vs.glsl
@@ -0,0 +1,27 @@
+#line 1
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Draw a cached primitive (e.g. a blurred text run) from the
+// target cache to the framebuffer, applying tile clip boundaries.
+
+void main(void) {
+    Primitive prim = load_primitive(gl_InstanceID);
+
+    VertexInfo vi = write_vertex(prim.local_rect,
+                                 prim.local_clip_rect,
+                                 prim.layer,
+                                 prim.tile);
+
+    RenderTaskData child_task = fetch_render_task(prim.user_data.x);
+    vUv.z = child_task.data1.x;
+
+    vec2 texture_size = vec2(textureSize(sCache, 0));
+    vec2 uv0 = child_task.data0.xy / texture_size;
+    vec2 uv1 = (child_task.data0.xy + child_task.data0.zw) / texture_size;
+
+    vec2 f = (vi.local_clamped_pos - prim.local_rect.xy) / prim.local_rect.zw;
+
+    vUv.xy = mix(uv0, uv1, f);
+}
--- a/servo/resources/shaders/ps_image.fs.glsl
+++ b/servo/resources/shaders/ps_image.fs.glsl
@@ -20,10 +20,10 @@ void main(void) {
 
     // We calculate the particular tile this fragment belongs to, taking into
     // account the spacing in between tiles. We only paint if our fragment does
     // not fall into that spacing.
     vec2 position_in_tile = mod(relative_pos_in_rect, vStretchSize + vTileSpacing);
     vec2 st = vTextureOffset + ((position_in_tile / vStretchSize) * vTextureSize);
     alpha = alpha * float(all(bvec2(step(position_in_tile, vStretchSize))));
 
-    oFragColor = vec4(1, 1, 1, alpha) * texture(sDiffuse, st);
+    oFragColor = vec4(1, 1, 1, alpha) * texture(sColor0, st);
 }
--- a/servo/resources/shaders/ps_image.vs.glsl
+++ b/servo/resources/shaders/ps_image.vs.glsl
@@ -18,17 +18,17 @@ void main(void) {
     VertexInfo vi = write_vertex(prim.local_rect,
                                  prim.local_clip_rect,
                                  prim.layer,
                                  prim.tile);
     vLocalPos = vi.local_clamped_pos - vi.local_rect.p0;
 #endif
 
     // vUv will contain how many times this image has wrapped around the image size.
-    vec2 texture_size = vec2(textureSize(sDiffuse, 0));
+    vec2 texture_size = vec2(textureSize(sColor0, 0));
     vec2 st0 = image.st_rect.xy / texture_size;
     vec2 st1 = image.st_rect.zw / texture_size;
 
     vTextureSize = st1 - st0;
     vTextureOffset = st0;
     vTileSpacing = image.stretch_size_and_tile_spacing.zw;
     vStretchSize = image.stretch_size_and_tile_spacing.xy;
 }
--- a/servo/resources/shaders/ps_image_clip.fs.glsl
+++ b/servo/resources/shaders/ps_image_clip.fs.glsl
@@ -23,10 +23,10 @@ void main(void) {
 
     // We calculate the particular tile this fragment belongs to, taking into
     // account the spacing in between tiles. We only paint if our fragment does
     // not fall into that spacing.
     vec2 position_in_tile = mod(relative_pos_in_rect, vStretchSize + vTileSpacing);
     vec2 st = vTextureOffset + ((position_in_tile / vStretchSize) * vTextureSize);
     alpha = alpha * float(all(bvec2(step(position_in_tile, vStretchSize))));
 
-    oFragColor = texture(sDiffuse, st) * vec4(1, 1, 1, alpha);
+    oFragColor = texture(sColor0, st) * vec4(1, 1, 1, alpha);
 }
--- a/servo/resources/shaders/ps_image_clip.vs.glsl
+++ b/servo/resources/shaders/ps_image_clip.vs.glsl
@@ -22,17 +22,17 @@ void main(void) {
     vLocalRect = prim.local_rect;
     vLocalPos = vi.local_clamped_pos;
 #endif
 
     ClipData clip = fetch_clip(prim.clip_index);
     write_clip(clip);
 
     // vUv will contain how many times this image has wrapped around the image size.
-    vec2 texture_size = vec2(textureSize(sDiffuse, 0));
+    vec2 texture_size = vec2(textureSize(sColor0, 0));
     vec2 st0 = image.st_rect.xy / texture_size;
     vec2 st1 = image.st_rect.zw / texture_size;
 
     vTextureSize = st1 - st0;
     vTextureOffset = st0;
     vTileSpacing = image.stretch_size_and_tile_spacing.zw;
     vStretchSize = image.stretch_size_and_tile_spacing.xy;
 }
--- a/servo/resources/shaders/ps_text_run.fs.glsl
+++ b/servo/resources/shaders/ps_text_run.fs.glsl
@@ -1,17 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 void main(void) {
 #ifdef WR_FEATURE_SUBPIXEL_AA
-    oFragColor = texture(sDiffuse, vUv);
+    oFragColor = texture(sColor0, vUv);
 #else
-    float a = texture(sDiffuse, vUv).a;
+    float a = texture(sColor0, vUv).a;
 #ifdef WR_FEATURE_TRANSFORM
     float alpha = 0.0;
     init_transform_fs(vLocalPos, vLocalRect, alpha);
     a *= alpha;
 #endif
     oFragColor = vec4(vColor.rgb, vColor.a * a);
 #endif
 }
--- a/servo/resources/shaders/ps_text_run.vs.glsl
+++ b/servo/resources/shaders/ps_text_run.vs.glsl
@@ -20,15 +20,15 @@ void main(void) {
 #else
     VertexInfo vi = write_vertex(local_rect,
                                  prim.local_clip_rect,
                                  prim.layer,
                                  prim.tile);
     vec2 f = (vi.local_clamped_pos - vi.local_rect.p0) / (vi.local_rect.p1 - vi.local_rect.p0);
 #endif
 
-    vec2 texture_size = vec2(textureSize(sDiffuse, 0));
+    vec2 texture_size = vec2(textureSize(sColor0, 0));
     vec2 st0 = glyph.uv_rect.xy / texture_size;
     vec2 st1 = glyph.uv_rect.zw / texture_size;
 
     vColor = text.color;
     vUv = mix(st0, st1, f);
 }
--- a/servo/resources/shaders/shared.glsl
+++ b/servo/resources/shaders/shared.glsl
@@ -28,17 +28,19 @@
 
     // Fragment shader outputs
     out vec4 oFragColor;
 #endif
 
 //======================================================================================
 // Shared shader uniforms
 //======================================================================================
-uniform sampler2D sDiffuse;
+uniform sampler2D sColor0;
+uniform sampler2D sColor1;
+uniform sampler2D sColor2;
 uniform sampler2D sMask;
 
 //======================================================================================
 // Interpolator definitions
 //======================================================================================
 
 //======================================================================================
 // VS only types and UBOs