diff --git a/components/gfx/display_list/mod.rs b/components/gfx/display_list/mod.rs index 9b9c791569f..ddd98a07d5e 100644 --- a/components/gfx/display_list/mod.rs +++ b/components/gfx/display_list/mod.rs @@ -21,15 +21,22 @@ use euclid::approxeq::ApproxEq; use euclid::num::Zero; use euclid::rect::TypedRect; use euclid::{Matrix2D, Matrix4, Point2D, Rect, SideOffsets2D, Size2D}; +use fnv::FnvHasher; use gfx_traits::{LayerId, ScrollPolicy}; use heapsize::HeapSizeOf; use msg::constellation_msg::PipelineId; use net_traits::image::base::Image; use paint_context::PaintContext; use range::Range; +use serde::de::{self, Deserialize, Deserializer, MapVisitor, Visitor}; +use serde::ser::impls::MapIteratorVisitor; +use serde::ser::{Serialize, Serializer}; use std::cmp::Ordering; use std::collections::HashMap; use std::fmt; +use std::hash::{BuildHasherDefault, Hash}; +use std::marker::PhantomData; +use std::ops::{Deref, DerefMut}; use std::sync::Arc; use style::computed_values::{border_style, cursor, filter, image_rendering, mix_blend_mode}; use style::computed_values::{pointer_events}; @@ -141,10 +148,75 @@ pub struct StackingContextOffsets { pub outlines: u32, } +/// A FNV-based hash map. This is not serializable by `serde` by default, so we provide an +/// implementation ourselves. +pub struct FnvHashMap(pub HashMap>); + +impl Deref for FnvHashMap { + type Target = HashMap>; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for FnvHashMap { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl Serialize for FnvHashMap where K: Eq + Hash + Serialize, V: Serialize { + #[inline] + fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer { + serializer.visit_map(MapIteratorVisitor::new(self.iter(), Some(self.len()))) + } +} + +impl Deserialize for FnvHashMap where K: Eq + Hash + Deserialize, V: Deserialize { + #[inline] + fn deserialize(deserializer: &mut D) -> Result where D: Deserializer { + deserializer.visit_map(FnvHashMapVisitor::new()) + } +} +/// A visitor that produces a map. +pub struct FnvHashMapVisitor { + marker: PhantomData>, +} + +impl FnvHashMapVisitor { + /// Construct a `FnvHashMapVisitor`. + pub fn new() -> Self { + FnvHashMapVisitor { + marker: PhantomData, + } + } +} + +impl Visitor for FnvHashMapVisitor where K: Eq + Hash + Deserialize, V: Deserialize { + type Value = FnvHashMap; + + #[inline] + fn visit_unit(&mut self) -> Result, E> where E: de::Error { + Ok(FnvHashMap(HashMap::with_hasher(Default::default()))) + } + + #[inline] + fn visit_map(&mut self, mut visitor: Visitor) + -> Result, Visitor::Error> + where Visitor: MapVisitor { + let mut values = FnvHashMap(HashMap::with_hasher(Default::default())); + while let Some((key, value)) = try!(visitor.visit()) { + HashMap::insert(&mut values, key, value); + } + try!(visitor.end()); + Ok(values) + } +} + #[derive(HeapSizeOf, Deserialize, Serialize)] pub struct DisplayList { pub list: Vec, - pub offsets: HashMap, + pub offsets: FnvHashMap, pub root_stacking_context: StackingContext, } @@ -157,7 +229,7 @@ impl DisplayList { None => panic!("Tried to create empty display list."), }; - let mut offsets = HashMap::new(); + let mut offsets = FnvHashMap(HashMap::with_hasher(Default::default())); DisplayList::sort_and_count_stacking_contexts(&mut root_stacking_context, &mut offsets, 0); let mut display_list = DisplayList { @@ -201,7 +273,9 @@ impl DisplayList { fn sort_and_count_stacking_contexts( stacking_context: &mut StackingContext, - offsets: &mut HashMap, + offsets: &mut HashMap>, mut current_offset: u32) -> u32 { stacking_context.children.sort();