geckolib: Return @font-face rules to Gecko in the expected cascade order. r?xidorn draft
authorCameron McCormack <cam@mcc.id.au>
Mon, 14 Aug 2017 10:26:21 +0800
changeset 645717 32fa99eee1af582e10d2054766503d3960f91488
parent 645716 d13528c03bdaa6d653a858a29d176863ed0be2f3
child 725986 b4e6ce78152f8d6fda299ef8b94092cdaf37008c
push id73847
push userbmo:cam@mcc.id.au
push dateMon, 14 Aug 2017 03:25:52 +0000
reviewersxidorn
milestone57.0a1
geckolib: Return @font-face rules to Gecko in the expected cascade order. r?xidorn MozReview-Commit-ID: 18gfwcHhuf7
servo/components/style/stylesheets/origin.rs
servo/ports/geckolib/glue.rs
--- a/servo/components/style/stylesheets/origin.rs
+++ b/servo/components/style/stylesheets/origin.rs
@@ -59,16 +59,27 @@ impl<T> PerOrigin<T> {
     }
 
     /// Iterates over references to per-origin extra style data, from highest
     /// level (author) to lowest (user agent).
     pub fn iter_origins(&self) -> PerOriginIter<T> {
         PerOriginIter {
             data: &self,
             cur: 0,
+            rev: false,
+        }
+    }
+
+    /// Iterates over references to per-origin extra style data, from lowest
+    /// level (user agent) to highest (author).
+    pub fn iter_origins_rev(&self) -> PerOriginIter<T> {
+        PerOriginIter {
+            data: &self,
+            cur: 2,
+            rev: true,
         }
     }
 
     /// Iterates over mutable references to per-origin extra style data, from
     /// highest level (author) to lowest (user agent).
     pub fn iter_mut_origins(&mut self) -> PerOriginIterMut<T> {
         PerOriginIterMut {
             data: self,
@@ -94,30 +105,31 @@ impl<T> PerOriginClear for PerOrigin<T> 
 
 /// Iterator over `PerOrigin<T>`, from highest level (author) to lowest
 /// (user agent).
 ///
 /// We rely on this specific order for correctly looking up @font-face,
 /// @counter-style and @keyframes rules.
 pub struct PerOriginIter<'a, T: 'a> {
     data: &'a PerOrigin<T>,
-    cur: usize,
+    cur: isize,
+    rev: bool,
 }
 
 impl<'a, T> Iterator for PerOriginIter<'a, T> where T: 'a {
     type Item = (&'a T, Origin);
 
     fn next(&mut self) -> Option<Self::Item> {
         let result = match self.cur {
             0 => (&self.data.author, Origin::Author),
             1 => (&self.data.user, Origin::User),
             2 => (&self.data.user_agent, Origin::UserAgent),
             _ => return None,
         };
-        self.cur += 1;
+        self.cur += if self.rev { -1 } else { 1 };
         Some(result)
     }
 }
 
 /// Like `PerOriginIter<T>`, but iterates over mutable references to the
 /// per-origin data.
 ///
 /// We must use unsafe code here since it's not possible for the borrow
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -3408,18 +3408,20 @@ pub extern "C" fn Servo_StyleSet_GetFont
     let global_style_data = &*GLOBAL_STYLE_DATA;
     let guard = global_style_data.shared_lock.read();
 
     let len: u32 = data.extra_style_data
         .iter_origins()
         .map(|(d, _)| d.font_faces.len() as u32)
         .sum();
 
+    // Reversed iterator because Gecko expects rules to appear sorted
+    // UserAgent first, Author last.
     let font_face_iter = data.extra_style_data
-        .iter_origins()
+        .iter_origins_rev()
         .flat_map(|(d, o)| d.font_faces.iter().zip(iter::repeat(o)));
 
     unsafe { rules.set_len(len) };
     for (src, dest) in font_face_iter.zip(rules.iter_mut()) {
         dest.mRule = src.0.read_with(&guard).clone().forget();
         dest.mSheetType = src.1.into();
     }
 }