Bug 1604062 - Use less Au in font code. r=boris
authorEmilio Cobos Álvarez <emilio@crisal.io>
Mon, 16 Dec 2019 13:22:04 +0000
changeset 507090 b2da3109db2c956c0e6a922c529cbdf56df904e1
parent 507089 0d3256a2c780b9d2ca106d0703f51c2681b67d22
child 507091 bbf2f47ef9f534802d2fa49832eae80c5681fc1e
push id36922
push userncsoregi@mozilla.com
push dateMon, 16 Dec 2019 17:21:47 +0000
treeherdermozilla-central@27d0d6cc2131 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersboris
bugs1604062
milestone73.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1604062 - Use less Au in font code. r=boris Font code is the only thing that was using Au in the style system without interfacing with Gecko, and there was no real reason for it to do so. This slightly simplifies the code. Differential Revision: https://phabricator.services.mozilla.com/D57248
servo/components/style/font_metrics.rs
servo/components/style/gecko/media_queries.rs
servo/components/style/gecko/wrapper.rs
servo/components/style/matching.rs
servo/components/style/properties/cascade.rs
servo/components/style/properties/gecko.mako.rs
servo/components/style/servo/media_queries.rs
servo/components/style/values/computed/font.rs
servo/components/style/values/computed/length.rs
servo/components/style/values/specified/font.rs
servo/components/style/values/specified/gecko.rs
servo/components/style/values/specified/length.rs
servo/components/style/values/specified/text.rs
--- a/servo/components/style/font_metrics.rs
+++ b/servo/components/style/font_metrics.rs
@@ -3,26 +3,26 @@
  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
 
 //! Access to font metrics from the style system.
 
 #![deny(missing_docs)]
 
 use crate::context::SharedStyleContext;
 use crate::Atom;
-use app_units::Au;
+use crate::values::computed::Length;
 
 /// Represents the font metrics that style needs from a font to compute the
 /// value of certain CSS units like `ex`.
 #[derive(Clone, Debug, Default, PartialEq)]
 pub struct FontMetrics {
     /// The x-height of the font.
-    pub x_height: Option<Au>,
+    pub x_height: Option<Length>,
     /// The zero advance. This is usually writing mode dependent
-    pub zero_advance_measure: Option<Au>,
+    pub zero_advance_measure: Option<Length>,
 }
 
 /// Type of font metrics to retrieve.
 #[derive(Clone, Debug, PartialEq)]
 pub enum FontMetricsOrientation {
     /// Get metrics for horizontal or vertical according to the Context's
     /// writing mode.
     MatchContext,
@@ -42,17 +42,17 @@ pub trait FontMetricsProvider {
         Default::default()
     }
 
     /// Get default size of a given language and generic family.
     fn get_size(
         &self,
         font_name: &Atom,
         font_family: crate::values::computed::font::GenericFontFamily,
-    ) -> Au;
+    ) -> Length;
 
     /// Construct from a shared style context
     fn create_from(context: &SharedStyleContext) -> Self
     where
         Self: Sized;
 }
 
 // TODO: Servo's font metrics provider will probably not live in this crate, so this will
@@ -65,17 +65,17 @@ pub trait FontMetricsProvider {
 pub struct ServoMetricsProvider;
 
 #[cfg(feature = "servo")]
 impl FontMetricsProvider for ServoMetricsProvider {
     fn create_from(_: &SharedStyleContext) -> Self {
         ServoMetricsProvider
     }
 
-    fn get_size(&self, _: &Atom, _: crate::values::computed::font::GenericFontFamily) -> Au {
+    fn get_size(&self, _: &Atom, _: crate::values::computed::font::GenericFontFamily) -> Length {
         unreachable!("Dummy provider should never be used to compute font size")
     }
 }
 
 // Servo's font metrics provider will probably not live in this crate, so this will
 // have to be replaced with something else (perhaps a trait method on TElement)
 // when we get there
 
--- a/servo/components/style/gecko/media_queries.rs
+++ b/servo/components/style/gecko/media_queries.rs
@@ -6,20 +6,19 @@
 
 use crate::custom_properties::CssEnvironment;
 use crate::gecko::values::{convert_nscolor_to_rgba, convert_rgba_to_nscolor};
 use crate::gecko_bindings::bindings;
 use crate::gecko_bindings::structs;
 use crate::media_queries::MediaType;
 use crate::properties::ComputedValues;
 use crate::string_cache::Atom;
-use crate::values::computed::font::FontSize;
+use crate::values::specified::font::FONT_MEDIUM_PX;
 use crate::values::{CustomIdent, KeyframesName};
-use app_units::Au;
-use app_units::AU_PER_PX;
+use app_units::{Au, AU_PER_PX};
 use cssparser::RGBA;
 use euclid::default::Size2D;
 use euclid::Scale;
 use servo_arc::Arc;
 use std::fmt;
 use std::sync::atomic::{AtomicBool, AtomicIsize, AtomicUsize, Ordering};
 use style_traits::viewport::ViewportConstraints;
 use style_traits::{CSSPixel, DevicePixel};
@@ -82,17 +81,17 @@ impl Device {
     pub fn new(document: *const structs::Document) -> Self {
         assert!(!document.is_null());
         let doc = unsafe { &*document };
         let prefs = unsafe { &*bindings::Gecko_GetPrefSheetPrefs(doc) };
         Device {
             document,
             default_values: ComputedValues::default_values(doc),
             // FIXME(bz): Seems dubious?
-            root_font_size: AtomicIsize::new(FontSize::medium().size().0 as isize),
+            root_font_size: AtomicIsize::new(Au::from_px(FONT_MEDIUM_PX as i32).0 as isize),
             body_text_color: AtomicUsize::new(prefs.mDefaultColor as usize),
             used_root_font_size: AtomicBool::new(false),
             used_viewport_size: AtomicBool::new(false),
             environment: CssEnvironment,
         }
     }
 
     /// Get the relevant environment to resolve `env()` functions.
@@ -134,18 +133,17 @@ impl Device {
     /// Get the font size of the root element (for rem)
     pub fn root_font_size(&self) -> Au {
         self.used_root_font_size.store(true, Ordering::Relaxed);
         Au::new(self.root_font_size.load(Ordering::Relaxed) as i32)
     }
 
     /// Set the font size of the root element (for rem)
     pub fn set_root_font_size(&self, size: Au) {
-        self.root_font_size
-            .store(size.0 as isize, Ordering::Relaxed)
+        self.root_font_size.store(size.0 as isize, Ordering::Relaxed)
     }
 
     /// Sets the body text color for the "inherit color from body" quirk.
     ///
     /// <https://quirks.spec.whatwg.org/#the-tables-inherit-color-from-body-quirk>
     pub fn set_body_text_color(&self, color: RGBA) {
         self.body_text_color
             .store(convert_rgba_to_nscolor(&color) as usize, Ordering::Relaxed)
--- a/servo/components/style/gecko/wrapper.rs
+++ b/servo/components/style/gecko/wrapper.rs
@@ -63,16 +63,17 @@ use crate::properties::animated_properti
 use crate::properties::{ComputedValues, LonghandId};
 use crate::properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock};
 use crate::rule_tree::CascadeLevel as ServoCascadeLevel;
 use crate::selector_parser::{AttrValue, HorizontalDirection, Lang};
 use crate::shared_lock::Locked;
 use crate::string_cache::{Atom, Namespace, WeakAtom, WeakNamespace};
 use crate::stylist::CascadeData;
 use crate::values::computed::font::GenericFontFamily;
+use crate::values::computed::Length;
 use crate::values::specified::length::FontBaseSize;
 use crate::CaseSensitivityExt;
 use app_units::Au;
 use atomic_refcell::{AtomicRefCell, AtomicRefMut};
 use selectors::attr::{AttrSelectorOperation, AttrSelectorOperator};
 use selectors::attr::{CaseSensitivity, NamespaceConstraint};
 use selectors::matching::VisitedHandlingMode;
 use selectors::matching::{ElementSelectorFlags, MatchingContext};
@@ -924,17 +925,17 @@ impl GeckoFontMetricsProvider {
     }
 }
 
 impl FontMetricsProvider for GeckoFontMetricsProvider {
     fn create_from(_: &SharedStyleContext) -> GeckoFontMetricsProvider {
         GeckoFontMetricsProvider::new()
     }
 
-    fn get_size(&self, font_name: &Atom, font_family: GenericFontFamily) -> Au {
+    fn get_size(&self, font_name: &Atom, font_family: GenericFontFamily) -> Length {
         let mut cache = self.font_size_cache.borrow_mut();
         if let Some(sizes) = cache.iter().find(|el| el.0 == *font_name) {
             return sizes.1.size_for_generic(font_family);
         }
         let sizes = unsafe { bindings::Gecko_GetBaseSize(font_name.as_ptr()) };
         cache.push((font_name.clone(), sizes));
         sizes.size_for_generic(font_family)
     }
@@ -945,17 +946,17 @@ impl FontMetricsProvider for GeckoFontMe
         base_size: FontBaseSize,
         orientation: FontMetricsOrientation,
     ) -> FontMetrics {
         let pc = match context.device().pres_context() {
             Some(pc) => pc,
             None => return Default::default(),
         };
 
-        let size = base_size.resolve(context);
+        let size = Au::from(base_size.resolve(context));
         let style = context.style();
 
         let (wm, font) = match base_size {
             FontBaseSize::CurrentStyle => (style.writing_mode, style.get_font()),
             // These are only used for font-size computation, and the first is
             // really dubious...
             FontBaseSize::InheritedStyleButStripEmUnits | FontBaseSize::InheritedStyle => {
                 (*style.inherited_writing_mode(), style.get_parent_font())
@@ -972,39 +973,39 @@ impl FontMetricsProvider for GeckoFontMe
                 vertical_metrics,
                 font.gecko(),
                 size.0,
                 // we don't use the user font set in a media query
                 !context.in_media_query,
             )
         };
         FontMetrics {
-            x_height: Some(Au(gecko_metrics.mXSize)),
+            x_height: Some(Au(gecko_metrics.mXSize).into()),
             zero_advance_measure: if gecko_metrics.mChSize >= 0 {
-                Some(Au(gecko_metrics.mChSize))
+                Some(Au(gecko_metrics.mChSize).into())
             } else {
                 None
             },
         }
     }
 }
 
 impl structs::FontSizePrefs {
-    fn size_for_generic(&self, font_family: GenericFontFamily) -> Au {
+    fn size_for_generic(&self, font_family: GenericFontFamily) -> Length {
         Au(match font_family {
             GenericFontFamily::None => self.mDefaultVariableSize,
             GenericFontFamily::Serif => self.mDefaultSerifSize,
             GenericFontFamily::SansSerif => self.mDefaultSansSerifSize,
             GenericFontFamily::Monospace => self.mDefaultMonospaceSize,
             GenericFontFamily::Cursive => self.mDefaultCursiveSize,
             GenericFontFamily::Fantasy => self.mDefaultFantasySize,
             GenericFontFamily::MozEmoji => unreachable!(
                 "Should never get here, since this doesn't (yet) appear on font family"
             ),
-        })
+        }).into()
     }
 }
 
 impl<'le> TElement for GeckoElement<'le> {
     type ConcreteNode = GeckoNode<'le>;
     type FontMetricsProvider = GeckoFontMetricsProvider;
     type TraversalChildrenIterator = GeckoChildrenIterator<'le>;
 
--- a/servo/components/style/matching.rs
+++ b/servo/components/style/matching.rs
@@ -710,17 +710,17 @@ pub trait MatchMethods: TElement {
             let new_font_size = new_primary_style.get_font().clone_font_size();
 
             if old_styles
                 .primary
                 .as_ref()
                 .map_or(true, |s| s.get_font().clone_font_size() != new_font_size)
             {
                 debug_assert!(self.owner_doc_matches_for_testing(device));
-                device.set_root_font_size(new_font_size.size());
+                device.set_root_font_size(new_font_size.size().into());
                 // If the root font-size changed since last time, and something
                 // in the document did use rem units, ensure we recascade the
                 // entire tree.
                 if device.used_root_font_size() {
                     cascade_requirement = ChildCascadeRequirement::MustCascadeDescendants;
                 }
             }
         }
--- a/servo/components/style/properties/cascade.rs
+++ b/servo/components/style/properties/cascade.rs
@@ -738,33 +738,34 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
         }
     }
 
     /// Some keyword sizes depend on the font family and language.
     #[cfg(feature = "gecko")]
     fn recompute_keyword_font_size_if_needed(&mut self) {
         use crate::values::computed::ToComputedValue;
         use crate::values::specified;
+        use app_units::Au;
 
         if !self.seen.contains(LonghandId::XLang) &&
            !self.seen.contains(LonghandId::FontFamily) {
             return;
         }
 
         let new_size = {
             let font = self.context.builder.get_font();
             let new_size = match font.clone_font_size().keyword_info {
                 Some(info) => {
                     self.context.for_non_inherited_property = None;
                     specified::FontSize::Keyword(info).to_computed_value(self.context)
                 }
                 None => return,
             };
 
-            if font.gecko().mScriptUnconstrainedSize == new_size.size().0 {
+            if font.gecko().mScriptUnconstrainedSize == Au::from(new_size.size()).0 {
                 return;
             }
 
             new_size
         };
 
         self.context.builder.mutate_font().set_font_size(new_size);
     }
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -1129,17 +1129,17 @@ fn static_assert() {
 
     pub fn reset_font_size(&mut self, other: &Self) {
         self.copy_font_size_from(other)
     }
 
     pub fn set_font_size(&mut self, v: FontSize) {
         use crate::values::specified::font::KeywordSize;
 
-        let size = v.size();
+        let size = Au::from(v.size());
         self.gecko.mScriptUnconstrainedSize = size.0;
 
         // These two may be changed from Cascade::fixup_font_stuff.
         self.gecko.mSize = size.0;
         self.gecko.mFont.size = size.0;
 
         if let Some(info) = v.keyword_info {
             self.gecko.mFontSizeKeyword = match info.kw {
--- a/servo/components/style/servo/media_queries.rs
+++ b/servo/components/style/servo/media_queries.rs
@@ -5,19 +5,19 @@
 //! Servo's media-query device and expression representation.
 
 use crate::custom_properties::CssEnvironment;
 use crate::media_queries::media_feature::{AllowsRanges, ParsingRequirements};
 use crate::media_queries::media_feature::{Evaluator, MediaFeatureDescription};
 use crate::media_queries::media_feature_expression::RangeOrOperator;
 use crate::media_queries::MediaType;
 use crate::properties::ComputedValues;
-use crate::values::computed::font::FontSize;
 use crate::values::computed::CSSPixelLength;
 use crate::values::KeyframesName;
+use crate::values::specified::font::FONT_MEDIUM_PX;
 use app_units::Au;
 use cssparser::RGBA;
 use euclid::default::Size2D as UntypedSize2D;
 use euclid::{Scale, Size2D};
 use std::sync::atomic::{AtomicBool, AtomicIsize, Ordering};
 use style_traits::viewport::ViewportConstraints;
 use style_traits::{CSSPixel, DevicePixel};
 
@@ -63,17 +63,17 @@ impl Device {
         viewport_size: Size2D<f32, CSSPixel>,
         device_pixel_ratio: Scale<f32, CSSPixel, DevicePixel>,
     ) -> Device {
         Device {
             media_type,
             viewport_size,
             device_pixel_ratio,
             // FIXME(bz): Seems dubious?
-            root_font_size: AtomicIsize::new(FontSize::medium().size().0 as isize),
+            root_font_size: AtomicIsize::new(Au::from_px(FONT_MEDIUM_PX).0 as isize),
             used_root_font_size: AtomicBool::new(false),
             used_viewport_units: AtomicBool::new(false),
             environment: CssEnvironment,
         }
     }
 
     /// Get the relevant environment to resolve `env()` functions.
     #[inline]
--- a/servo/components/style/values/computed/font.rs
+++ b/servo/components/style/values/computed/font.rs
@@ -16,17 +16,16 @@ use crate::values::computed::{Number, Pe
 use crate::values::generics::font::{FeatureTagValue, FontSettings, VariationValue};
 use crate::values::generics::{font as generics, NonNegative};
 use crate::values::specified::font::{
     self as specified, KeywordInfo, MAX_FONT_WEIGHT, MIN_FONT_WEIGHT,
 };
 use crate::values::specified::length::{FontBaseSize, NoCalcLength};
 use crate::values::CSSFloat;
 use crate::Atom;
-use app_units::Au;
 use byteorder::{BigEndian, ByteOrder};
 use cssparser::{serialize_identifier, CssStringWriter, Parser};
 #[cfg(feature = "gecko")]
 use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
 use std::fmt::{self, Write};
 use std::hash::{Hash, Hasher};
 #[cfg(feature = "gecko")]
 use std::mem::{self, ManuallyDrop};
@@ -143,25 +142,26 @@ impl FontWeight {
         } else {
             FontWeight(700.)
         }
     }
 }
 
 impl FontSize {
     /// The actual computed font size.
-    pub fn size(self) -> Au {
-        self.size.into()
+    #[inline]
+    pub fn size(&self) -> Length {
+        self.size.0
     }
 
     #[inline]
     /// Get default value of font size.
     pub fn medium() -> Self {
         Self {
-            size: Au::from_px(specified::FONT_MEDIUM_PX).into(),
+            size: NonNegative(Length::new(specified::FONT_MEDIUM_PX as CSSFloat)),
             keyword_info: Some(KeywordInfo::medium()),
         }
     }
 }
 
 impl ToAnimatedValue for FontSize {
     type AnimatedValue = Length;
 
--- a/servo/components/style/values/computed/length.rs
+++ b/servo/components/style/values/computed/length.rs
@@ -24,17 +24,17 @@ use std::ops::{Add, AddAssign, Div, Mul,
 use style_traits::values::specified::AllowedNumericType;
 use style_traits::{CSSPixel, CssWriter, ToCss};
 
 pub use super::image::Image;
 pub use crate::values::specified::url::UrlOrNone;
 pub use crate::values::specified::{Angle, BorderStyle, Time};
 
 impl ToComputedValue for specified::NoCalcLength {
-    type ComputedValue = CSSPixelLength;
+    type ComputedValue = Length;
 
     #[inline]
     fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
         match *self {
             specified::NoCalcLength::Absolute(length) => length.to_computed_value(context),
             specified::NoCalcLength::FontRelative(length) => {
                 length.to_computed_value(context, FontBaseSize::CurrentStyle)
             },
--- a/servo/components/style/values/specified/font.rs
+++ b/servo/components/style/values/specified/font.rs
@@ -15,17 +15,16 @@ use crate::values::computed::{CSSPixelLe
 use crate::values::generics::font::VariationValue;
 use crate::values::generics::font::{self as generics, FeatureTagValue, FontSettings, FontTag};
 use crate::values::generics::NonNegative;
 use crate::values::specified::length::{FontBaseSize, AU_PER_PT, AU_PER_PX};
 use crate::values::specified::{AllowQuirks, Angle, Integer, LengthPercentage};
 use crate::values::specified::{NoCalcLength, NonNegativeNumber, Number, Percentage};
 use crate::values::CustomIdent;
 use crate::Atom;
-use app_units::Au;
 use byteorder::{BigEndian, ByteOrder};
 use cssparser::{Parser, Token};
 #[cfg(feature = "gecko")]
 use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
 use std::fmt::{self, Write};
 use style_traits::values::SequenceWriter;
 use style_traits::{CssWriter, KeywordsCollectFn, ParseError};
 use style_traits::{SpecifiedValueInfo, StyleParseErrorKind, ToCss};
@@ -768,43 +767,42 @@ const LARGER_FONT_SIZE_RATIO: f32 = 1.2;
 /// The default font size.
 pub const FONT_MEDIUM_PX: i32 = 16;
 
 #[cfg(feature = "servo")]
 impl ToComputedValue for KeywordSize {
     type ComputedValue = NonNegativeLength;
     #[inline]
     fn to_computed_value(&self, _: &Context) -> NonNegativeLength {
+        let medium = Length::new(FONT_MEDIUM_PX as f32);
         // https://drafts.csswg.org/css-fonts-3/#font-size-prop
-        match *self {
-            KeywordSize::XXSmall => Au::from_px(FONT_MEDIUM_PX) * 3 / 5,
-            KeywordSize::XSmall => Au::from_px(FONT_MEDIUM_PX) * 3 / 4,
-            KeywordSize::Small => Au::from_px(FONT_MEDIUM_PX) * 8 / 9,
-            KeywordSize::Medium => Au::from_px(FONT_MEDIUM_PX),
-            KeywordSize::Large => Au::from_px(FONT_MEDIUM_PX) * 6 / 5,
-            KeywordSize::XLarge => Au::from_px(FONT_MEDIUM_PX) * 3 / 2,
-            KeywordSize::XXLarge => Au::from_px(FONT_MEDIUM_PX) * 2,
-            KeywordSize::XXXLarge => Au::from_px(FONT_MEDIUM_PX) * 3,
-        }
-        .into()
+        NonNegative(match *self {
+            KeywordSize::XXSmall => medium * 3.0 / 5.0,
+            KeywordSize::XSmall => medium * 3.0 / 4.0,
+            KeywordSize::Small => medium * 8.0 / 9.0,
+            KeywordSize::Medium => medium,
+            KeywordSize::Large => medium * 6.0 / 5.0,
+            KeywordSize::XLarge => medium * 3.0 / 2.0,
+            KeywordSize::XXLarge => medium * 2.0,
+            KeywordSize::XXXLarge => medium * 3.0,
+        })
     }
 
     #[inline]
     fn from_computed_value(_: &NonNegativeLength) -> Self {
         unreachable!()
     }
 }
 
 #[cfg(feature = "gecko")]
 impl ToComputedValue for KeywordSize {
     type ComputedValue = NonNegativeLength;
     #[inline]
     fn to_computed_value(&self, cx: &Context) -> NonNegativeLength {
         use crate::context::QuirksMode;
-        use crate::values::specified::length::au_to_int_px;
 
         // The tables in this function are originally from
         // nsRuleNode::CalcFontPointSize in Gecko:
         //
         // https://searchfox.org/mozilla-central/rev/c05d9d61188d32b8/layout/style/nsRuleNode.cpp#3150
         //
         // Mapping from base size and HTML size to pixels
         // The first index is (base_size - 9), the second is the
@@ -845,32 +843,31 @@ impl ToComputedValue for KeywordSize {
 
         static FONT_SIZE_FACTORS: [i32; 8] = [60, 75, 89, 100, 120, 150, 200, 300];
 
         let ref gecko_font = cx.style().get_font().gecko();
         let base_size = unsafe {
             Atom::with(gecko_font.mLanguage.mRawPtr, |atom| {
                 cx.font_metrics_provider
                     .get_size(atom, gecko_font.mGenericID)
-                    .0
             })
         };
 
-        let base_size_px = au_to_int_px(base_size as f32);
+        let base_size_px = base_size.px().round() as i32;
         let html_size = self.html_size() as usize;
-        if base_size_px >= 9 && base_size_px <= 16 {
+        NonNegative(if base_size_px >= 9 && base_size_px <= 16 {
             let mapping = if cx.quirks_mode == QuirksMode::Quirks {
                 QUIRKS_FONT_SIZE_MAPPING
             } else {
                 FONT_SIZE_MAPPING
             };
-            Au::from_px(mapping[(base_size_px - 9) as usize][html_size]).into()
+            Length::new(mapping[(base_size_px - 9) as usize][html_size] as f32)
         } else {
-            Au(FONT_SIZE_FACTORS[html_size] * base_size / 100).into()
-        }
+            base_size * FONT_SIZE_FACTORS[html_size] as f32 / 100.0
+        })
     }
 
     #[inline]
     fn from_computed_value(_: &NonNegativeLength) -> Self {
         unreachable!()
     }
 }
 
@@ -922,17 +919,17 @@ impl FontSize {
             FontSize::Length(LengthPercentage::Length(NoCalcLength::Absolute(ref l))) => {
                 context.maybe_zoom_text(l.to_computed_value(context))
             },
             FontSize::Length(LengthPercentage::Length(ref l)) => l.to_computed_value(context),
             FontSize::Length(LengthPercentage::Percentage(pc)) => {
                 // If the parent font was keyword-derived, this is too.
                 // Tack the % onto the factor
                 info = compose_keyword(pc.0);
-                base_size.resolve(context).scale_by(pc.0).into()
+                base_size.resolve(context) * pc.0
             },
             FontSize::Length(LengthPercentage::Calc(ref calc)) => {
                 let parent = context.style().get_parent_font().clone_font_size();
                 // if we contain em/% units and the parent was keyword derived, this is too
                 // Extract the ratio/offset and compose it
                 if (calc.em.is_some() || calc.percentage.is_some()) && parent.keyword_info.is_some()
                 {
                     let ratio = calc.em.unwrap_or(0.) + calc.percentage.map_or(0., |pc| pc.0);
@@ -959,18 +956,17 @@ impl FontSize {
                     info = parent.keyword_info.map(|i| i.compose(ratio, abs));
                 }
                 let calc = calc.to_computed_value_zoomed(context, base_size);
                 // FIXME(emilio): we _could_ use clamp_to_non_negative()
                 // everywhere, without affecting behavior in theory, since the
                 // others should reject negatives during parsing. But SMIL
                 // allows parsing negatives, and relies on us _not_ doing that
                 // clamping. That's so bonkers :(
-                CSSPixelLength::from(calc.to_used_value(base_size.resolve(context)))
-                    .clamp_to_non_negative()
+                calc.percentage_relative_to(base_size.resolve(context)).clamp_to_non_negative()
             },
             FontSize::Keyword(i) => {
                 // As a specified keyword, this is keyword derived
                 info = Some(i);
                 i.to_computed_value(context).clamp_to_non_negative()
             },
             FontSize::Smaller => {
                 info = compose_keyword(1. / LARGER_FONT_SIZE_RATIO);
--- a/servo/components/style/values/specified/gecko.rs
+++ b/servo/components/style/values/specified/gecko.rs
@@ -1,17 +1,16 @@
 /* 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 https://mozilla.org/MPL/2.0/. */
 
 //! Specified types for legacy Gecko-only properties.
 
 use crate::parser::{Parse, ParserContext};
-use crate::values::computed::length::CSSPixelLength;
-use crate::values::computed::{self, LengthPercentage};
+use crate::values::computed::{self, LengthPercentage, Length};
 use crate::values::generics::rect::Rect;
 use cssparser::{Parser, Token};
 use std::fmt;
 use style_traits::values::SequenceWriter;
 use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
 
 fn parse_pixel_or_percent<'i, 't>(
     _context: &ParserContext,
@@ -19,17 +18,17 @@ fn parse_pixel_or_percent<'i, 't>(
 ) -> Result<LengthPercentage, ParseError<'i>> {
     let location = input.current_source_location();
     let token = input.next()?;
     let value = match *token {
         Token::Dimension {
             value, ref unit, ..
         } => {
             match_ignore_ascii_case! { unit,
-                "px" => Ok(LengthPercentage::new(CSSPixelLength::new(value), None)),
+                "px" => Ok(LengthPercentage::new(Length::new(value), None)),
                 _ => Err(()),
             }
         },
         Token::Percentage { unit_value, .. } => Ok(LengthPercentage::new_percent(
             computed::Percentage(unit_value),
         )),
         _ => Err(()),
     };
--- a/servo/components/style/values/specified/length.rs
+++ b/servo/components/style/values/specified/length.rs
@@ -42,24 +42,16 @@ pub const AU_PER_CM: CSSFloat = AU_PER_I
 pub const AU_PER_MM: CSSFloat = AU_PER_IN / 25.4;
 /// Number of app units per quarter
 pub const AU_PER_Q: CSSFloat = AU_PER_MM / 4.;
 /// Number of app units per point
 pub const AU_PER_PT: CSSFloat = AU_PER_IN / 72.;
 /// Number of app units per pica
 pub const AU_PER_PC: CSSFloat = AU_PER_PT * 12.;
 
-/// Same as Gecko's AppUnitsToIntCSSPixels
-///
-/// Converts app units to integer pixel values,
-/// rounding during the conversion
-pub fn au_to_int_px(au: f32) -> i32 {
-    (au / AU_PER_PX).round() as i32
-}
-
 /// A font relative length.
 #[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss, ToShmem)]
 pub enum FontRelativeLength {
     /// A "em" value: https://drafts.csswg.org/css-values/#em
     #[css(dimension)]
     Em(CSSFloat),
     /// A "ex" value: https://drafts.csswg.org/css-values/#ex
     #[css(dimension)]
@@ -82,17 +74,17 @@ pub enum FontBaseSize {
     /// Use the inherited font-size, but strip em units.
     ///
     /// FIXME(emilio): This is very complex, and should go away.
     InheritedStyleButStripEmUnits,
 }
 
 impl FontBaseSize {
     /// Calculate the actual size for a given context
-    pub fn resolve(&self, context: &Context) -> Au {
+    pub fn resolve(&self, context: &Context) -> computed::Length {
         match *self {
             FontBaseSize::CurrentStyle => context.style().get_font().clone_font_size().size(),
             FontBaseSize::InheritedStyleButStripEmUnits | FontBaseSize::InheritedStyle => {
                 context.style().get_parent_font().clone_font_size().size()
             },
         }
     }
 }
@@ -104,37 +96,33 @@ impl FontRelativeLength {
             FontRelativeLength::Em(v) |
             FontRelativeLength::Ex(v) |
             FontRelativeLength::Ch(v) |
             FontRelativeLength::Rem(v) => v == 0.0,
         }
     }
 
     /// Computes the font-relative length.
-    pub fn to_computed_value(&self, context: &Context, base_size: FontBaseSize) -> CSSPixelLength {
-        use std::f32;
+    pub fn to_computed_value(&self, context: &Context, base_size: FontBaseSize) -> computed::Length {
         let (reference_size, length) = self.reference_font_size_and_length(context, base_size);
-        let pixel = (length * reference_size.to_f32_px())
-            .min(f32::MAX)
-            .max(f32::MIN);
-        CSSPixelLength::new(pixel)
+        reference_size * length
     }
 
     /// Return reference font size.
     ///
     /// We use the base_size flag to pass a different size for computing
     /// font-size and unconstrained font-size.
     ///
     /// This returns a pair, the first one is the reference font size, and the
     /// second one is the unpacked relative length.
     fn reference_font_size_and_length(
         &self,
         context: &Context,
         base_size: FontBaseSize,
-    ) -> (Au, CSSFloat) {
+    ) -> (computed::Length, CSSFloat) {
         fn query_font_metrics(
             context: &Context,
             base_size: FontBaseSize,
             orientation: FontMetricsOrientation,
         ) -> FontMetrics {
             context
                 .font_metrics_provider
                 .query(context, base_size, orientation)
@@ -148,17 +136,17 @@ impl FontRelativeLength {
                         context
                             .rule_cache_conditions
                             .borrow_mut()
                             .set_font_size_dependency(reference_font_size.into());
                     }
                 }
 
                 if base_size == FontBaseSize::InheritedStyleButStripEmUnits {
-                    (Au(0), length)
+                    (Zero::zero(), length)
                 } else {
                     (reference_font_size, length)
                 }
             },
             FontRelativeLength::Ex(length) => {
                 if context.for_non_inherited_property.is_some() {
                     context.rule_cache_conditions.borrow_mut().set_uncacheable();
                 }
@@ -170,17 +158,17 @@ impl FontRelativeLength {
                     query_font_metrics(context, base_size, FontMetricsOrientation::Horizontal);
                 let reference_size = metrics.x_height.unwrap_or_else(|| {
                     // https://drafts.csswg.org/css-values/#ex
                     //
                     //     In the cases where it is impossible or impractical to
                     //     determine the x-height, a value of 0.5em must be
                     //     assumed.
                     //
-                    reference_font_size.scale_by(0.5)
+                    reference_font_size * 0.5
                 });
                 (reference_size, length)
             },
             FontRelativeLength::Ch(length) => {
                 if context.for_non_inherited_property.is_some() {
                     context.rule_cache_conditions.borrow_mut().set_uncacheable();
                 }
                 context
@@ -205,32 +193,32 @@ impl FontRelativeLength {
                     //     1em when it would be typeset upright (i.e.
                     //     writing-mode is vertical-rl or vertical-lr and
                     //     text-orientation is upright).
                     //
                     let wm = context.style().writing_mode;
                     if wm.is_vertical() && wm.is_upright() {
                         reference_font_size
                     } else {
-                        reference_font_size.scale_by(0.5)
+                        reference_font_size * 0.5
                     }
                 });
                 (reference_size, length)
             },
             FontRelativeLength::Rem(length) => {
                 // https://drafts.csswg.org/css-values/#rem:
                 //
                 //     When specified on the font-size property of the root
                 //     element, the rem units refer to the property's initial
                 //     value.
                 //
                 let reference_size = if context.is_root_element || context.in_media_query {
                     reference_font_size
                 } else {
-                    context.device().root_font_size()
+                    computed::Length::new(context.device().root_font_size().to_f32_px())
                 };
                 (reference_size, length)
             },
         }
     }
 }
 
 /// A viewport-relative length.
@@ -285,25 +273,24 @@ impl ViewportPercentageLength {
 }
 
 /// HTML5 "character width", as defined in HTML5 § 14.5.4.
 #[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss, ToShmem)]
 pub struct CharacterWidth(pub i32);
 
 impl CharacterWidth {
     /// Computes the given character width.
-    pub fn to_computed_value(&self, reference_font_size: Au) -> CSSPixelLength {
-        // This applies the *converting a character width to pixels* algorithm as specified
-        // in HTML5 § 14.5.4.
+    pub fn to_computed_value(&self, reference_font_size: computed::Length) -> computed::Length {
+        // This applies the *converting a character width to pixels* algorithm
+        // as specified in HTML5 § 14.5.4.
         //
         // TODO(pcwalton): Find these from the font.
-        let average_advance = reference_font_size.scale_by(0.5);
+        let average_advance = reference_font_size * 0.5;
         let max_advance = reference_font_size;
-        let au = average_advance.scale_by(self.0 as CSSFloat - 1.0) + max_advance;
-        au.into()
+        average_advance * (self.0 as CSSFloat - 1.0) + max_advance
     }
 }
 
 /// Represents an absolute length with its unit
 #[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss, ToShmem)]
 pub enum AbsoluteLength {
     /// An absolute length in pixels (px)
     #[css(dimension)]
--- a/servo/components/style/values/specified/text.rs
+++ b/servo/components/style/values/specified/text.rs
@@ -72,17 +72,16 @@ impl Parse for WordSpacing {
     }
 }
 
 impl ToComputedValue for LineHeight {
     type ComputedValue = ComputedLineHeight;
 
     #[inline]
     fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
-        use crate::values::computed::Length as ComputedLength;
         use crate::values::specified::length::FontBaseSize;
         match *self {
             GenericLineHeight::Normal => GenericLineHeight::Normal,
             #[cfg(feature = "gecko")]
             GenericLineHeight::MozBlockHeight => GenericLineHeight::MozBlockHeight,
             GenericLineHeight::Number(number) => {
                 GenericLineHeight::Number(number.to_computed_value(context))
             },
@@ -92,26 +91,18 @@ impl ToComputedValue for LineHeight {
                         context.maybe_zoom_text(abs.to_computed_value(context))
                     },
                     LengthPercentage::Length(ref length) => length.to_computed_value(context),
                     LengthPercentage::Percentage(ref p) => FontRelativeLength::Em(p.0)
                         .to_computed_value(context, FontBaseSize::CurrentStyle),
                     LengthPercentage::Calc(ref calc) => {
                         let computed_calc =
                             calc.to_computed_value_zoomed(context, FontBaseSize::CurrentStyle);
-                        let font_relative_length =
-                            FontRelativeLength::Em(computed_calc.percentage())
-                                .to_computed_value(context, FontBaseSize::CurrentStyle)
-                                .px();
-
-                        let absolute_length = computed_calc.unclamped_length().px();
-                        let pixel = computed_calc
-                            .clamping_mode
-                            .clamp(absolute_length + font_relative_length);
-                        ComputedLength::new(pixel)
+                        let base = context.style().get_font().clone_font_size().size();
+                        computed_calc.percentage_relative_to(base)
                     },
                 };
                 GenericLineHeight::Length(result.into())
             },
         }
     }
 
     #[inline]