Bug 1396045 - stylo: Round down when computing viewport units; r?emilio draft
authorManish Goregaokar <manishearth@gmail.com>
Thu, 07 Sep 2017 14:06:01 -0700
changeset 660916 994322a7ae46a21a813ea2b5e765caba3cafb7f1
parent 660913 6b232382bd62a3f2cec7e6d33c54bb890c24e21f
child 661898 21d0dd6beee4eb510413e096d9c9f6713993a716
push id78615
push userbmo:manishearth@gmail.com
push dateThu, 07 Sep 2017 21:13:00 +0000
reviewersemilio
bugs1396045
milestone57.0a1
Bug 1396045 - stylo: Round down when computing viewport units; r?emilio MozReview-Commit-ID: I90ovyBw1do
layout/reftests/pixel-rounding/reftest.list
servo/components/style/values/specified/length.rs
--- a/layout/reftests/pixel-rounding/reftest.list
+++ b/layout/reftests/pixel-rounding/reftest.list
@@ -174,10 +174,10 @@ fuzzy-if(skiaContent,1,145) == rounded-b
 == background-image-tiling.html background-image-tiling-ref.html
 
 != border-image-width-0.html border-image-width-10.html
 == border-image-width-4.html border-image-width-0.html
 == border-image-width-9.html border-image-width-0.html
 
 fails-if(webrender) == iframe-1.html iframe-1-ref.html  # bug 1374378 for webrender
 
-fails-if(styloVsGecko||stylo) == viewport-units-rounding-1.html viewport-units-rounding-1-ref.html
+fuzzy-if(stylo||styloVsGecko,128,220) == viewport-units-rounding-1.html viewport-units-rounding-1-ref.html
 == viewport-units-rounding-2.html about:blank
--- a/servo/components/style/values/specified/length.rs
+++ b/servo/components/style/values/specified/length.rs
@@ -193,33 +193,31 @@ impl ToCss for ViewportPercentageLength 
             ViewportPercentageLength::Vmax(length) => serialize_dimension(length, "vmax", dest)
         }
     }
 }
 
 impl ViewportPercentageLength {
     /// Computes the given viewport-relative length for the given viewport size.
     pub fn to_computed_value(&self, viewport_size: Size2D<Au>) -> Au {
-        macro_rules! to_unit {
-            ($viewport_dimension:expr) => {
-                $viewport_dimension.to_f32_px() / 100.0
-            }
-        }
-
-        let value = match *self {
+        let (factor, length) = match *self {
             ViewportPercentageLength::Vw(length) =>
-                length * to_unit!(viewport_size.width),
+                (length, viewport_size.width),
             ViewportPercentageLength::Vh(length) =>
-                length * to_unit!(viewport_size.height),
+                (length, viewport_size.height),
             ViewportPercentageLength::Vmin(length) =>
-                length * to_unit!(cmp::min(viewport_size.width, viewport_size.height)),
+                (length, cmp::min(viewport_size.width, viewport_size.height)),
             ViewportPercentageLength::Vmax(length) =>
-                length * to_unit!(cmp::max(viewport_size.width, viewport_size.height)),
+                (length, cmp::max(viewport_size.width, viewport_size.height)),
         };
-        Au::from_f32_px(value)
+
+        // See bug 989802. We truncate so that adding multiple viewport units
+        // that add up to 100 does not overflow due to rounding differences
+        let trunc_scaled = ((length.0 as f64) * factor as f64 / 100.).trunc();
+        Au::from_f64_au(trunc_scaled)
     }
 }
 
 /// HTML5 "character width", as defined in HTML5 ยง 14.5.4.
 #[derive(Clone, Copy, Debug, PartialEq)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 pub struct CharacterWidth(pub i32);