servo: Merge #18381 - stylo: Bug 1392161 - Introduce CSSPixelLength as computed::Length (from BorisChiou:stylo/transform/rounding); r=<try>
authorBoris Chiou <boris.chiou@gmail.com>
Wed, 13 Sep 2017 05:20:20 -0500
changeset 430038 b9710187821b455c0ba3d5afb8e152ed4bebd782
parent 430037 05749026567be7e6a1ad187192fc782d7bfbbdc3
child 430039 26991171d8318e0ff6bef2e2d822c7d28cc48802
push id7761
push userjlund@mozilla.com
push dateFri, 15 Sep 2017 00:19:52 +0000
treeherdermozilla-beta@c38455951db4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1392161
milestone57.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
servo: Merge #18381 - stylo: Bug 1392161 - Introduce CSSPixelLength as computed::Length (from BorisChiou:stylo/transform/rounding); r=<try> These are the inter-dependent patches of bug 1392161. We want to handle extreme small lengths carefully for some properties, such as transform, so we shouldn't use |Au| as the computed value of specified::Length. Now, we introduce a new type, CSSPixelLength, which is a wrapper of CSSFloat, and it is the computed value of specified::Length, so we can keep the fractional part of computed::Length. --- - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix [Bug 1392161](https://bugzilla.mozilla.org/show_bug.cgi?id=1392161). - [X] These changes do not require tests because there is a wpt test for this, and I also add some others in Gecko. Source-Repo: https://github.com/servo/servo Source-Revision: ac1b49b1987d37b3c1ba67213b43c6d5fc373579
servo/components/gfx/font_context.rs
servo/components/layout/block.rs
servo/components/layout/construct.rs
servo/components/layout/display_list_builder.rs
servo/components/layout/flex.rs
servo/components/layout/fragment.rs
servo/components/layout/model.rs
servo/components/layout/multicol.rs
servo/components/layout/query.rs
servo/components/layout/table.rs
servo/components/layout/table_row.rs
servo/components/layout/table_rowgroup.rs
servo/components/layout/text.rs
servo/components/layout/webrender_helpers.rs
servo/components/style/gecko/conversions.rs
servo/components/style/gecko/generated/bindings.rs
servo/components/style/gecko/media_queries.rs
servo/components/style/gecko/values.rs
servo/components/style/gecko_bindings/sugar/ns_css_shadow_item.rs
servo/components/style/gecko_bindings/sugar/ns_css_value.rs
servo/components/style/matching.rs
servo/components/style/properties/gecko.mako.rs
servo/components/style/properties/helpers/animated_properties.mako.rs
servo/components/style/properties/longhand/border.mako.rs
servo/components/style/properties/longhand/box.mako.rs
servo/components/style/properties/longhand/column.mako.rs
servo/components/style/properties/longhand/font.mako.rs
servo/components/style/properties/longhand/inherited_svg.mako.rs
servo/components/style/properties/longhand/inherited_table.mako.rs
servo/components/style/properties/longhand/inherited_text.mako.rs
servo/components/style/properties/longhand/margin.mako.rs
servo/components/style/properties/longhand/outline.mako.rs
servo/components/style/properties/longhand/position.mako.rs
servo/components/style/properties/properties.mako.rs
servo/components/style/servo/media_queries.rs
servo/components/style/stylesheets/viewport_rule.rs
servo/components/style/values/animated/mod.rs
servo/components/style/values/computed/background.rs
servo/components/style/values/computed/length.rs
servo/components/style/values/computed/mod.rs
servo/components/style/values/computed/svg.rs
servo/components/style/values/computed/text.rs
servo/components/style/values/computed/transform.rs
servo/components/style/values/specified/border.rs
servo/components/style/values/specified/calc.rs
servo/components/style/values/specified/length.rs
servo/components/style/values/specified/position.rs
servo/components/style/values/specified/text.rs
servo/components/style_traits/values.rs
servo/components/style_traits/viewport.rs
servo/tests/unit/style/animated_properties.rs
servo/tests/unit/style/attr.rs
--- a/servo/components/gfx/font_context.rs
+++ b/servo/components/gfx/font_context.rs
@@ -113,17 +113,17 @@ impl FontContext {
     /// a cached font if this font instance has already been used by
     /// this context.
     pub fn layout_font_group_for_style(&mut self, style: ServoArc<style_structs::Font>)
                                        -> Rc<FontGroup> {
         self.expire_font_caches_if_necessary();
 
         let layout_font_group_cache_key = LayoutFontGroupCacheKey {
             pointer: style.clone(),
-            size: style.font_size.0,
+            size: Au::from(style.font_size),
         };
         if let Some(ref cached_font_group) = self.layout_font_group_cache.get(
                 &layout_font_group_cache_key) {
             return (*cached_font_group).clone()
         }
 
         // TODO: The font context holds a strong ref to the cached fonts
         // so they will never be released. Find out a good time to drop them.
@@ -143,17 +143,17 @@ impl FontContext {
                     match cached_font_entry.font {
                         None => {
                             cache_hit = true;
                             break;
                         }
                         Some(ref cached_font_ref) => {
                             let cached_font = (*cached_font_ref).borrow();
                             if cached_font.descriptor == desc &&
-                               cached_font.requested_pt_size == style.font_size.0 &&
+                               cached_font.requested_pt_size == Au::from(style.font_size) &&
                                cached_font.variant == style.font_variant_caps {
                                 fonts.push((*cached_font_ref).clone());
                                 cache_hit = true;
                                 break;
                             }
                         }
                     }
                 }
@@ -161,17 +161,17 @@ impl FontContext {
 
             if !cache_hit {
                 let template_info = self.font_cache_thread.find_font_template(family.clone(),
                                                                              desc.clone());
                 match template_info {
                     Some(template_info) => {
                         let layout_font = self.create_layout_font(template_info.font_template,
                                                                   desc.clone(),
-                                                                  style.font_size.0,
+                                                                  Au::from(style.font_size),
                                                                   style.font_variant_caps,
                                                                   template_info.font_key);
                         let font = match layout_font {
                             Ok(layout_font) => {
                                 let layout_font = Rc::new(RefCell::new(layout_font));
                                 fonts.push(layout_font.clone());
 
                                 Some(layout_font)
@@ -194,29 +194,29 @@ impl FontContext {
             }
         }
 
         // Add a last resort font as a fallback option.
         let mut cache_hit = false;
         for cached_font_entry in &self.fallback_font_cache {
             let cached_font = cached_font_entry.font.borrow();
             if cached_font.descriptor == desc &&
-                        cached_font.requested_pt_size == style.font_size.0 &&
+                        cached_font.requested_pt_size == Au::from(style.font_size) &&
                         cached_font.variant == style.font_variant_caps {
                 fonts.push(cached_font_entry.font.clone());
                 cache_hit = true;
                 break;
             }
         }
 
         if !cache_hit {
             let template_info = self.font_cache_thread.last_resort_font_template(desc.clone());
             let layout_font = self.create_layout_font(template_info.font_template,
                                                       desc.clone(),
-                                                      style.font_size.0,
+                                                      Au::from(style.font_size),
                                                       style.font_variant_caps,
                                                       template_info.font_key);
             match layout_font {
                 Ok(layout_font) => {
                     let layout_font = Rc::new(RefCell::new(layout_font));
                     self.fallback_font_cache.push(FallbackFontCacheEntry {
                         font: layout_font.clone(),
                     });
--- a/servo/components/layout/block.rs
+++ b/servo/components/layout/block.rs
@@ -324,38 +324,38 @@ impl CandidateBSizeIterator {
             (LengthOrPercentageOrAuto::Percentage(percent), Some(block_container_block_size)) => {
                 MaybeAuto::Specified(block_container_block_size.scale_by(percent.0))
             }
             (LengthOrPercentageOrAuto::Calc(calc), _) => {
                 MaybeAuto::from_option(calc.to_used_value(block_container_block_size))
             }
             (LengthOrPercentageOrAuto::Percentage(_), None) |
             (LengthOrPercentageOrAuto::Auto, _) => MaybeAuto::Auto,
-            (LengthOrPercentageOrAuto::Length(length), _) => MaybeAuto::Specified(length),
+            (LengthOrPercentageOrAuto::Length(length), _) => MaybeAuto::Specified(Au::from(length)),
         };
         let max_block_size = match (fragment.style.max_block_size(), block_container_block_size) {
             (LengthOrPercentageOrNone::Percentage(percent), Some(block_container_block_size)) => {
                 Some(block_container_block_size.scale_by(percent.0))
             }
             (LengthOrPercentageOrNone::Calc(calc), _) => {
                 calc.to_used_value(block_container_block_size)
             }
             (LengthOrPercentageOrNone::Percentage(_), None) |
             (LengthOrPercentageOrNone::None, _) => None,
-            (LengthOrPercentageOrNone::Length(length), _) => Some(length),
+            (LengthOrPercentageOrNone::Length(length), _) => Some(Au::from(length)),
         };
         let min_block_size = match (fragment.style.min_block_size(), block_container_block_size) {
             (LengthOrPercentage::Percentage(percent), Some(block_container_block_size)) => {
                 block_container_block_size.scale_by(percent.0)
             }
             (LengthOrPercentage::Calc(calc), _) => {
                 calc.to_used_value(block_container_block_size).unwrap_or(Au(0))
             }
             (LengthOrPercentage::Percentage(_), None) => Au(0),
-            (LengthOrPercentage::Length(length), _) => length,
+            (LengthOrPercentage::Length(length), _) => Au::from(length),
         };
 
         // If the style includes `box-sizing: border-box`, subtract the border and padding.
         let adjustment_for_box_sizing = match fragment.style.get_position().box_sizing {
             box_sizing::T::border_box => fragment.border_padding.block_start_end(),
             box_sizing::T::content_box => Au(0),
         };
 
@@ -1167,17 +1167,17 @@ impl BlockFlow {
 
     pub fn explicit_block_size(&self, containing_block_size: Option<Au>) -> Option<Au> {
         let content_block_size = self.fragment.style().content_block_size();
 
         match (content_block_size, containing_block_size) {
             (LengthOrPercentageOrAuto::Calc(calc), _) => {
                 calc.to_used_value(containing_block_size)
             }
-            (LengthOrPercentageOrAuto::Length(length), _) => Some(length),
+            (LengthOrPercentageOrAuto::Length(length), _) => Some(Au::from(length)),
             (LengthOrPercentageOrAuto::Percentage(percent), Some(container_size)) => {
                 Some(container_size.scale_by(percent.0))
             }
             (LengthOrPercentageOrAuto::Percentage(_), None) |
             (LengthOrPercentageOrAuto::Auto, None) => {
                 None
             }
             (LengthOrPercentageOrAuto::Auto, Some(container_size)) => {
--- a/servo/components/layout/construct.rs
+++ b/servo/components/layout/construct.rs
@@ -9,17 +9,16 @@
 //! proceeds to construct either a flow or a `ConstructionItem`. A construction item is a piece of
 //! intermediate data that goes with a DOM node and hasn't found its "home" yet-maybe it's a box,
 //! maybe it's an absolute or fixed position thing that hasn't found its containing block yet.
 //! Construction items bubble up the tree from children to parents until they find their homes.
 
 #![deny(unsafe_code)]
 
 use ServoArc;
-use app_units::Au;
 use block::BlockFlow;
 use context::{LayoutContext, with_thread_local_font_context};
 use data::{HAS_NEWLY_CONSTRUCTED_FLOW, LayoutData};
 use flex::FlexFlow;
 use floats::FloatKind;
 use flow::{self, AbsoluteDescendants, Flow, FlowClass, ImmutableFlowUtils};
 use flow::{CAN_BE_FRAGMENTED, IS_ABSOLUTELY_POSITIONED, MARGINS_CANNOT_COLLAPSE};
 use flow::{MutableFlowUtils, MutableOwnedFlowUtils};
@@ -1847,20 +1846,20 @@ impl ComputedValueUtils for ComputedValu
     fn has_padding_or_border(&self) -> bool {
         let padding = self.get_padding();
         let border = self.get_border();
 
         !padding.padding_top.is_definitely_zero() ||
            !padding.padding_right.is_definitely_zero() ||
            !padding.padding_bottom.is_definitely_zero() ||
            !padding.padding_left.is_definitely_zero() ||
-           border.border_top_width.0 != Au(0) ||
-           border.border_right_width.0 != Au(0) ||
-           border.border_bottom_width.0 != Au(0) ||
-           border.border_left_width.0 != Au(0)
+           border.border_top_width.px() != 0. ||
+           border.border_right_width.px() != 0. ||
+           border.border_bottom_width.px() != 0. ||
+           border.border_left_width.px() != 0.
     }
 }
 
 /// Maintains a stack of anonymous boxes needed to ensure that the flow tree is *legal*. The tree
 /// is legal if it follows the rules in CSS 2.1 § 17.2.1.
 ///
 /// As an example, the legalizer makes sure that table row flows contain only table cells. If the
 /// flow constructor attempts to place, say, a block flow directly underneath the table row, the
--- a/servo/components/layout/display_list_builder.rs
+++ b/servo/components/layout/display_list_builder.rs
@@ -1320,16 +1320,17 @@ impl FragmentDisplayListBuilding for Fra
                                shape: &EndingShape,
                                center: &Position,
                                repeating: bool)
                                -> display_list::RadialGradient {
         let center = Point2D::new(center.horizontal.to_used_value(bounds.size.width),
                                   center.vertical.to_used_value(bounds.size.height));
         let radius = match *shape {
             GenericEndingShape::Circle(Circle::Radius(length)) => {
+                let length = Au::from(length);
                 Size2D::new(length, length)
             },
             GenericEndingShape::Circle(Circle::Extent(extent)) => {
                 convert_circle_size_keyword(extent, &bounds.size, &center)
             },
             GenericEndingShape::Ellipse(Ellipse::Radii(x, y)) => {
                 Size2D::new(x.to_used_value(bounds.size.width), y.to_used_value(bounds.size.height))
             },
@@ -1404,36 +1405,37 @@ impl FragmentDisplayListBuilding for Fra
                                                        style: &ComputedValues,
                                                        display_list_section: DisplayListSection,
                                                        absolute_bounds: &Rect<Au>,
                                                        clip: &Rect<Au>) {
         // NB: According to CSS-BACKGROUNDS, box shadows render in *reverse* order (front to back).
         for box_shadow in style.get_effects().box_shadow.0.iter().rev() {
             let bounds = shadow_bounds(
                 &absolute_bounds.translate(&Vector2D::new(
-                    box_shadow.base.horizontal,
-                    box_shadow.base.vertical,
+                    Au::from(box_shadow.base.horizontal),
+                    Au::from(box_shadow.base.vertical),
                 )),
-                box_shadow.base.blur.0,
-                box_shadow.spread,
+                Au::from(box_shadow.base.blur),
+                Au::from(box_shadow.spread),
             );
 
             // TODO(pcwalton): Multiple border radii; elliptical border radii.
             let base = state.create_base_display_item(&bounds,
                                                       LocalClip::from(clip.to_rectf()),
                                                       self.node,
                                                       style.get_cursor(Cursor::Default),
                                                       display_list_section);
             state.add_display_item(DisplayItem::BoxShadow(box BoxShadowDisplayItem {
                 base: base,
                 box_bounds: *absolute_bounds,
                 color: box_shadow.base.color.unwrap_or(style.get_color().color).to_gfx_color(),
-                offset: Vector2D::new(box_shadow.base.horizontal, box_shadow.base.vertical),
-                blur_radius: box_shadow.base.blur.0,
-                spread_radius: box_shadow.spread,
+                offset: Vector2D::new(Au::from(box_shadow.base.horizontal),
+                                      Au::from(box_shadow.base.vertical)),
+                blur_radius: Au::from(box_shadow.base.blur),
+                spread_radius: Au::from(box_shadow.spread),
                 border_radius: model::specified_border_radius(style.get_border()
                                                                    .border_top_left_radius,
                                                               absolute_bounds.size).width,
                 clip_mode: if box_shadow.inset {
                     BoxShadowClipMode::Inset
                 } else {
                     BoxShadowClipMode::Outset
                 },
@@ -1591,31 +1593,31 @@ impl FragmentDisplayListBuilding for Fra
 
     fn build_display_list_for_outline_if_applicable(&self,
                                                     state: &mut DisplayListBuildState,
                                                     style: &ComputedValues,
                                                     bounds: &Rect<Au>,
                                                     clip: &Rect<Au>) {
         use style::values::Either;
 
-        let width = style.get_outline().outline_width.0;
+        let width = Au::from(style.get_outline().outline_width);
         if width == Au(0) {
             return
         }
 
         let outline_style = match style.get_outline().outline_style {
             Either::First(_auto) => border_style::T::solid,
             Either::Second(border_style::T::none) => return,
             Either::Second(border_style) => border_style
         };
 
         // Outlines are not accounted for in the dimensions of the border box, so adjust the
         // absolute bounds.
         let mut bounds = *bounds;
-        let offset = width + style.get_outline().outline_offset;
+        let offset = width + Au::from(style.get_outline().outline_offset);
         bounds.origin.x = bounds.origin.x - offset;
         bounds.origin.y = bounds.origin.y - offset;
         bounds.size.width = bounds.size.width + offset + offset;
         bounds.size.height = bounds.size.height + offset + offset;
 
         // Append the outline to the display list.
         let color = style.resolve_color(style.get_outline().outline_color).to_gfx_color();
         let base = state.create_base_display_item(&bounds,
@@ -2134,18 +2136,18 @@ impl FragmentDisplayListBuilding for Fra
 
         // NB: According to CSS-BACKGROUNDS, text shadows render in *reverse* order (front
         // to back).
 
         // Shadows
         for shadow in text_shadows.iter().rev() {
             state.add_display_item(DisplayItem::PushTextShadow(box PushTextShadowDisplayItem {
                 base: base.clone(),
-                blur_radius: shadow.blur.0,
-                offset: Vector2D::new(shadow.horizontal, shadow.vertical),
+                blur_radius: Au::from(shadow.blur),
+                offset: Vector2D::new(Au::from(shadow.horizontal), Au::from(shadow.vertical)),
                 color: shadow.color.unwrap_or(self.style().get_color().color).to_gfx_color(),
             }));
         }
 
 
         // Create display items for text decorations.
         let mut text_decorations = self.style()
                                        .get_inheritedtext()
@@ -2685,21 +2687,23 @@ impl BlockFlowDisplayListBuilding for Bl
         // CSS `clip` should only apply to position:absolute or positione:fixed elements.
         // CSS Masking Appendix A: "Applies to: Absolutely positioned elements."
         match self.positioning() {
             position::T::absolute | position::T::fixed => {}
             _ => return,
         }
 
         let clip_origin = Point2D::new(stacking_relative_border_box.origin.x +
-                                       style_clip_rect.left.unwrap_or(Au(0)),
+                                       style_clip_rect.left.map(Au::from).unwrap_or(Au(0)),
                                        stacking_relative_border_box.origin.y +
-                                       style_clip_rect.top.unwrap_or(Au(0)));
-        let right = style_clip_rect.right.unwrap_or(stacking_relative_border_box.size.width);
-        let bottom = style_clip_rect.bottom.unwrap_or(stacking_relative_border_box.size.height);
+                                       style_clip_rect.top.map(Au::from).unwrap_or(Au(0)));
+        let right = style_clip_rect.right.map(Au::from)
+            .unwrap_or(stacking_relative_border_box.size.width);
+        let bottom = style_clip_rect.bottom.map(Au::from)
+            .unwrap_or(stacking_relative_border_box.size.height);
         let clip_size = Size2D::new(right - clip_origin.x, bottom - clip_origin.y);
 
         // We use the node id to create scroll roots for overflow properties, so we
         // use the fragment address to do the same for CSS clipping.
         // TODO(mrobinson): This should be more resilient while maintaining the space
         // efficiency of ScrollRootId.
         let new_scroll_root_id = ClipId::new(self.fragment.unique_id(IdType::CSSClip),
                                              state.layout_context.id.to_webrender());
@@ -3030,17 +3034,17 @@ struct StopRun {
     start_offset: f32,
     end_offset: f32,
     start_index: usize,
     stop_count: usize,
 }
 
 fn position_to_offset(position: LengthOrPercentage, total_length: Au) -> f32 {
     match position {
-        LengthOrPercentage::Length(Au(length)) => length as f32 / total_length.0 as f32,
+        LengthOrPercentage::Length(l) => l.to_i32_au() as f32 / total_length.0 as f32,
         LengthOrPercentage::Percentage(percentage) => percentage.0 as f32,
         LengthOrPercentage::Calc(calc) => {
             calc.to_used_value(Some(total_length)).unwrap().0 as f32 / total_length.0 as f32
         },
     }
 }
 
 /// Adjusts `content_rect` as necessary for the given spread, and blur so that the resulting
--- a/servo/components/layout/flex.rs
+++ b/servo/components/layout/flex.rs
@@ -40,17 +40,17 @@ enum AxisSize {
 }
 
 impl AxisSize {
     /// Generate a new available cross or main axis size from the specified size of the container,
     /// containing block size, min constraint, and max constraint
     pub fn new(size: LengthOrPercentageOrAuto, content_size: Option<Au>, min: LengthOrPercentage,
                max: LengthOrPercentageOrNone) -> AxisSize {
         match size {
-            LengthOrPercentageOrAuto::Length(length) => AxisSize::Definite(length),
+            LengthOrPercentageOrAuto::Length(length) => AxisSize::Definite(Au::from(length)),
             LengthOrPercentageOrAuto::Percentage(percent) => {
                 match content_size {
                     Some(size) => AxisSize::Definite(size.scale_by(percent.0)),
                     None => AxisSize::Infinite
                 }
             }
             LengthOrPercentageOrAuto::Calc(calc) => {
                 match calc.to_used_value(content_size) {
@@ -71,30 +71,30 @@ impl AxisSize {
 /// is definite after flex size resolving.
 fn from_flex_basis(
     flex_basis: FlexBasis,
     main_length: LengthOrPercentageOrAuto,
     containing_length: Option<Au>
 ) -> MaybeAuto {
     match (flex_basis, containing_length) {
         (GenericFlexBasis::Length(LengthOrPercentage::Length(length)), _) =>
-            MaybeAuto::Specified(length),
+            MaybeAuto::Specified(Au::from(length)),
         (GenericFlexBasis::Length(LengthOrPercentage::Percentage(percent)), Some(size)) =>
             MaybeAuto::Specified(size.scale_by(percent.0)),
         (GenericFlexBasis::Length(LengthOrPercentage::Percentage(_)), None) =>
             MaybeAuto::Auto,
         (GenericFlexBasis::Length(LengthOrPercentage::Calc(calc)), _) =>
             MaybeAuto::from_option(calc.to_used_value(containing_length)),
         (GenericFlexBasis::Content, _) =>
             MaybeAuto::Auto,
         (GenericFlexBasis::Auto, Some(size)) =>
             MaybeAuto::from_style(main_length, size),
         (GenericFlexBasis::Auto, None) => {
             if let LengthOrPercentageOrAuto::Length(length) = main_length {
-                MaybeAuto::Specified(length)
+                MaybeAuto::Specified(Au::from(length))
             } else {
                 MaybeAuto::Auto
             }
         }
     }
 }
 
 /// Represents a child in a flex container. Most fields here are used in
--- a/servo/components/layout/fragment.rs
+++ b/servo/components/layout/fragment.rs
@@ -46,17 +46,17 @@ use style::computed_values::{transform_s
 use style::computed_values::content::ContentItem;
 use style::logical_geometry::{Direction, LogicalMargin, LogicalRect, LogicalSize, WritingMode};
 use style::properties::ComputedValues;
 use style::properties::longhands::transform::computed_value::T as TransformList;
 use style::selector_parser::RestyleDamage;
 use style::servo::restyle_damage::RECONSTRUCT_FLOW;
 use style::str::char_is_whitespace;
 use style::values::{self, Either, Auto};
-use style::values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto};
+use style::values::computed::{Length, LengthOrPercentage, LengthOrPercentageOrAuto};
 use style::values::generics::box_::VerticalAlign;
 use text;
 use text::TextRunScanner;
 use webrender_api;
 use wrapper::ThreadSafeLayoutNodeHelpers;
 
 // From gfxFontConstants.h in Firefox.
 static FONT_SUBSCRIPT_OFFSET_RATIO: f32 = 0.20;
@@ -1511,21 +1511,21 @@ impl Fragment {
                         let border = self.border_width();
                         self.border_padding.inline_start += border.inline_start;
                         self.border_padding.inline_end += border.inline_end;
                         self.border_padding.block_start += border.block_start;
                         self.border_padding.block_end += border.block_end;
                         let (result_inline, _) = self.calculate_replaced_sizes(None, None);
                         result_inline
                     }
-                    LengthOrPercentageOrAuto::Length(length) => length,
+                    LengthOrPercentageOrAuto::Length(length) => Au::from(length),
                     LengthOrPercentageOrAuto::Calc(calc) => {
                         // TODO(nox): This is probably wrong, because it accounts neither for
                         // clamping (not sure if necessary here) nor percentage.
-                        calc.unclamped_length()
+                        Au::from(calc.unclamped_length())
                     },
                 };
 
                 let size_constraint = self.size_constraint(None, Direction::Inline);
                 inline_size = size_constraint.clamp(inline_size);
 
                 result.union_block(&IntrinsicISizes {
                     minimum_inline_size: inline_size,
@@ -2256,17 +2256,17 @@ impl Fragment {
                 }
                 VerticalAlign::Bottom => {
                     if let Some(actual_line_metrics) = actual_line_metrics {
                         offset = actual_line_metrics.space_below_baseline -
                             content_inline_metrics.space_below_baseline
                     }
                 }
                 VerticalAlign::Length(LengthOrPercentage::Length(length)) => {
-                    offset -= length
+                    offset -= Au::from(length)
                 }
                 VerticalAlign::Length(LengthOrPercentage::Percentage(percentage)) => {
                     offset -= minimum_line_metrics.space_needed().scale_by(percentage.0)
                 }
                 VerticalAlign::Length(LengthOrPercentage::Calc(formula)) => {
                     offset -= formula.to_used_value(Some(minimum_line_metrics.space_needed())).unwrap()
                 }
             }
@@ -2331,42 +2331,42 @@ impl Fragment {
                 // If this node has any styles that have border/padding/margins on the following
                 // side, then we can't merge with the next fragment.
                 if let Some(ref inline_context) = self.inline_context {
                     for inline_context_node in inline_context.nodes.iter() {
                         if !inline_context_node.flags.contains(LAST_FRAGMENT_OF_ELEMENT) {
                             continue
                         }
                         if inline_context_node.style.logical_margin().inline_end !=
-                                LengthOrPercentageOrAuto::Length(Au(0)) {
+                                LengthOrPercentageOrAuto::Length(Length::new(0.)) {
                             return false
                         }
                         if inline_context_node.style.logical_padding().inline_end !=
-                                LengthOrPercentage::Length(Au(0)) {
+                                LengthOrPercentage::Length(Length::new(0.)) {
                             return false
                         }
                         if inline_context_node.style.logical_border_width().inline_end != Au(0) {
                             return false
                         }
                     }
                 }
 
                 // If the next fragment has any styles that have border/padding/margins on the
                 // preceding side, then it can't merge with us.
                 if let Some(ref inline_context) = other.inline_context {
                     for inline_context_node in inline_context.nodes.iter() {
                         if !inline_context_node.flags.contains(FIRST_FRAGMENT_OF_ELEMENT) {
                             continue
                         }
                         if inline_context_node.style.logical_margin().inline_start !=
-                                LengthOrPercentageOrAuto::Length(Au(0)) {
+                                LengthOrPercentageOrAuto::Length(Length::new(0.)) {
                             return false
                         }
                         if inline_context_node.style.logical_padding().inline_start !=
-                                LengthOrPercentage::Length(Au(0)) {
+                                LengthOrPercentage::Length(Length::new(0.)) {
                             return false
                         }
                         if inline_context_node.style.logical_border_width().inline_start != Au(0) {
                             return false
                         }
                     }
                 }
 
@@ -2569,24 +2569,26 @@ impl Fragment {
         // the time. Can't we handle relative positioning by just adjusting `border_box`?
         let relative_position = self.relative_position(relative_containing_block_size);
         border_box =
             border_box.translate_by_size(&relative_position.to_physical(self.style.writing_mode));
         let mut overflow = Overflow::from_rect(&border_box);
 
         // Box shadows cause us to draw outside our border box.
         for box_shadow in &self.style().get_effects().box_shadow.0 {
-            let offset = Vector2D::new(box_shadow.base.horizontal, box_shadow.base.vertical);
-            let inflation = box_shadow.spread + box_shadow.base.blur.0 * BLUR_INFLATION_FACTOR;
+            let offset = Vector2D::new(Au::from(box_shadow.base.horizontal),
+                                       Au::from(box_shadow.base.vertical));
+            let inflation = Au::from(box_shadow.spread) +
+                            Au::from(box_shadow.base.blur) * BLUR_INFLATION_FACTOR;
             overflow.paint = overflow.paint.union(&border_box.translate(&offset)
                                                              .inflate(inflation, inflation))
         }
 
         // Outlines cause us to draw outside our border box.
-        let outline_width = self.style.get_outline().outline_width.0;
+        let outline_width = Au::from(self.style.get_outline().outline_width);
         if outline_width != Au(0) {
             overflow.paint = overflow.paint.union(&border_box.inflate(outline_width,
                                                                       outline_width))
         }
 
         // Include the overflow of the block flow, if any.
         match self.specific {
             SpecificFragmentInfo::InlineBlock(ref info) => {
@@ -2875,17 +2877,17 @@ impl Fragment {
         let transform_origin_x =
             transform_origin.horizontal
                 .to_used_value(stacking_relative_border_box.size.width)
                 .to_f32_px();
         let transform_origin_y =
             transform_origin.vertical
                 .to_used_value(stacking_relative_border_box.size.height)
                 .to_f32_px();
-        let transform_origin_z = transform_origin.depth.to_f32_px();
+        let transform_origin_z = transform_origin.depth.px();
 
         let pre_transform = Transform3D::create_translation(transform_origin_x,
                                                             transform_origin_y,
                                                             transform_origin_z);
         let post_transform = Transform3D::create_translation(-transform_origin_x,
                                                              -transform_origin_y,
                                                              -transform_origin_z);
 
@@ -2908,17 +2910,17 @@ impl Fragment {
 
                 let pre_transform = Transform3D::create_translation(perspective_origin.x,
                                                                     perspective_origin.y,
                                                                     0.0);
                 let post_transform = Transform3D::create_translation(-perspective_origin.x,
                                                                      -perspective_origin.y,
                                                                      0.0);
 
-                let perspective_matrix = TransformList::create_perspective_matrix(length);
+                let perspective_matrix = TransformList::create_perspective_matrix(length.px());
 
                 Some(pre_transform.pre_mul(&perspective_matrix).pre_mul(&post_transform))
             }
             Either::Second(values::None_) => {
                 None
             }
         }
     }
--- a/servo/components/layout/model.rs
+++ b/servo/components/layout/model.rs
@@ -136,26 +136,26 @@ impl MarginCollapseInfo {
                                                   can_collapse_block_end_margin_with_kids: bool,
                                                   mut may_collapse_through: bool)
                                                   -> (CollapsibleMargins, Au) {
         let state = match self.state {
             MarginCollapseState::AccumulatingCollapsibleTopMargin => {
                 may_collapse_through = may_collapse_through &&
                     match fragment.style().content_block_size() {
                         LengthOrPercentageOrAuto::Auto => true,
-                        LengthOrPercentageOrAuto::Length(Au(v)) => v == 0,
+                        LengthOrPercentageOrAuto::Length(l) => l.px() == 0.,
                         LengthOrPercentageOrAuto::Percentage(v) => {
                             v.0 == 0. || containing_block_size.is_none()
                         }
                         LengthOrPercentageOrAuto::Calc(_) => false,
                     };
 
                 if may_collapse_through {
                     match fragment.style().min_block_size() {
-                        LengthOrPercentage::Length(Au(0)) => {
+                        LengthOrPercentage::Length(l) if l.px() == 0. => {
                             FinalMarginState::MarginsCollapseThrough
                         },
                         LengthOrPercentage::Percentage(v) if v.0 == 0. => {
                             FinalMarginState::MarginsCollapseThrough
                         },
                         _ => {
                             // If the fragment has non-zero min-block-size, margins may not
                             // collapse through it.
@@ -407,17 +407,17 @@ impl MaybeAuto {
         match length {
             LengthOrPercentageOrAuto::Auto => MaybeAuto::Auto,
             LengthOrPercentageOrAuto::Percentage(percent) => {
                 MaybeAuto::Specified(containing_length.scale_by(percent.0))
             }
             LengthOrPercentageOrAuto::Calc(calc) => {
                 MaybeAuto::from_option(calc.to_used_value(Some(containing_length)))
             }
-            LengthOrPercentageOrAuto::Length(length) => MaybeAuto::Specified(length)
+            LengthOrPercentageOrAuto::Length(length) => MaybeAuto::Specified(Au::from(length))
         }
     }
 
     #[inline]
     pub fn from_option(au: Option<Au>) -> MaybeAuto {
         match au {
             Some(l) => MaybeAuto::Specified(l),
             _ => MaybeAuto::Auto,
@@ -449,17 +449,17 @@ impl MaybeAuto {
 /// Receive an optional container size and return used value for width or height.
 ///
 /// `style_length`: content size as given in the CSS.
 pub fn style_length(style_length: LengthOrPercentageOrAuto,
                     container_size: Option<Au>) -> MaybeAuto {
     match container_size {
         Some(length) => MaybeAuto::from_style(style_length, length),
         None => if let LengthOrPercentageOrAuto::Length(length) = style_length {
-            MaybeAuto::Specified(length)
+            MaybeAuto::Specified(Au::from(length))
         } else {
             MaybeAuto::Auto
         }
     }
 }
 
 /// Computes a border radius size against the containing size.
 ///
@@ -521,26 +521,26 @@ impl SizeConstraint {
     /// Create a `SizeConstraint` for an axis.
     pub fn new(container_size: Option<Au>,
                min_size: LengthOrPercentage,
                max_size: LengthOrPercentageOrNone,
                border: Option<Au>) -> SizeConstraint {
         let mut min_size = match container_size {
             Some(container_size) => min_size.to_used_value(container_size),
             None => if let LengthOrPercentage::Length(length) = min_size {
-                length
+                Au::from(length)
             } else {
                 Au(0)
             }
         };
 
         let mut max_size = match container_size {
             Some(container_size) => max_size.to_used_value(container_size),
             None => if let LengthOrPercentageOrNone::Length(length) = max_size {
-                Some(length)
+                Some(Au::from(length))
             } else {
                 None
             }
         };
         // Make sure max size is not smaller than min size.
         max_size = max_size.map(|x| max(x, min_size));
 
         if let Some(border) = border {
--- a/servo/components/layout/multicol.rs
+++ b/servo/components/layout/multicol.rs
@@ -92,25 +92,26 @@ impl Flow for MulticolFlow {
         self.block_flow.assign_inline_sizes(layout_context);
         let padding_and_borders = self.block_flow.fragment.border_padding.inline_start_end();
         let content_inline_size =
             self.block_flow.fragment.border_box.size.inline - padding_and_borders;
         let column_width;
         {
             let column_style = self.block_flow.fragment.style.get_column();
 
-            let column_gap = match column_style.column_gap {
-                Either::First(len) => len.0,
-                Either::Second(_normal) => self.block_flow.fragment.style.get_font().font_size.0,
-            };
+            let column_gap = Au::from(match column_style.column_gap {
+                Either::First(len) => len,
+                Either::Second(_normal) => self.block_flow.fragment.style.get_font().font_size,
+            });
 
             let mut column_count;
             if let Either::First(column_width) = column_style.column_width {
+                let column_width = Au::from(column_width);
                 column_count =
-                    max(1, (content_inline_size + column_gap).0 / (column_width.0 + column_gap).0);
+                    max(1, (content_inline_size + column_gap).0 / (column_width + column_gap).0);
                 if let Either::First(specified_column_count) = column_style.column_count {
                     column_count = min(column_count, specified_column_count.0 as i32);
                 }
             } else {
                 column_count = match column_style.column_count {
                     Either::First(n) => n.0,
                     _ => unreachable!(),
                 }
@@ -130,19 +131,19 @@ impl Flow for MulticolFlow {
     fn assign_block_size(&mut self, ctx: &LayoutContext) {
         debug!("assign_block_size: assigning block_size for multicol");
 
         let fragmentation_context = Some(FragmentationContext {
             this_fragment_is_empty: true,
             available_block_size: {
                 let style = &self.block_flow.fragment.style;
                 if let LengthOrPercentageOrAuto::Length(length) = style.content_block_size() {
-                    length
+                    Au::from(length)
                 } else if let LengthOrPercentageOrNone::Length(length) = style.max_block_size() {
-                    length
+                    Au::from(length)
                 } else {
                     // FIXME: do column balancing instead
                     // FIXME: (until column balancing) substract margins/borders/padding
                     LogicalSize::from_physical(
                         self.block_flow.base.writing_mode,
                         ctx.shared_context().viewport_size(),
                     ).block
                 }
--- a/servo/components/layout/query.rs
+++ b/servo/components/layout/query.rs
@@ -445,20 +445,24 @@ impl FragmentBorderBoxIterator for Fragm
     fn process(&mut self, fragment: &Fragment, _: i32, border_box: &Rect<Au>) {
         let style_structs::Border {
             border_top_width: top_width,
             border_right_width: right_width,
             border_bottom_width: bottom_width,
             border_left_width: left_width,
             ..
         } = *fragment.style.get_border();
-        self.client_rect.origin.y = top_width.0.to_px();
-        self.client_rect.origin.x = left_width.0.to_px();
-        self.client_rect.size.width = (border_box.size.width - left_width.0 - right_width.0).to_px();
-        self.client_rect.size.height = (border_box.size.height - top_width.0 - bottom_width.0).to_px();
+        let (left_width, right_width) = (left_width.px(), right_width.px());
+        let (top_width, bottom_width) = (top_width.px(), bottom_width.px());
+        self.client_rect.origin.y = top_width as i32;
+        self.client_rect.origin.x = left_width as i32;
+        self.client_rect.size.width =
+            (border_box.size.width.to_f32_px() - left_width - right_width) as i32;
+        self.client_rect.size.height =
+            (border_box.size.height.to_f32_px() - top_width - bottom_width) as i32;
     }
 
     fn should_process(&mut self, fragment: &Fragment) -> bool {
         fragment.node == self.node_address
     }
 }
 
 // https://drafts.csswg.org/cssom-view/#scrolling-area
@@ -471,20 +475,22 @@ impl FragmentBorderBoxIterator for Union
         // margin rectangles as `union_rect`.
         let style_structs::Border {
             border_top_width: top_border,
             border_right_width: right_border,
             border_bottom_width: bottom_border,
             border_left_width: left_border,
             ..
         } = *fragment.style.get_border();
-        let right_padding = (border_box.size.width - right_border.0 - left_border.0).to_px();
-        let bottom_padding = (border_box.size.height - bottom_border.0 - top_border.0).to_px();
-        let top_padding = top_border.0.to_px();
-        let left_padding = left_border.0.to_px();
+        let (left_border, right_border) = (left_border.px(), right_border.px());
+        let (top_border, bottom_border) = (top_border.px(), bottom_border.px());
+        let right_padding = (border_box.size.width.to_f32_px() - right_border - left_border) as i32;
+        let bottom_padding = (border_box.size.height.to_f32_px() - bottom_border - top_border) as i32;
+        let top_padding = top_border as i32;
+        let left_padding = left_border as i32;
 
         match self.level {
             Some(start_level) if level <= start_level => { self.is_child = false; }
             Some(_) => {
                 let padding = Rect::new(Point2D::new(left_padding, top_padding),
                                         Size2D::new(right_padding, bottom_padding));
                 let top_margin = fragment.margin.top(fragment.style.writing_mode).to_px();
                 let left_margin = fragment.margin.left(fragment.style.writing_mode).to_px();
--- a/servo/components/layout/table.rs
+++ b/servo/components/layout/table.rs
@@ -23,17 +23,17 @@ use model::{IntrinsicISizes, IntrinsicIS
 use std::cmp;
 use std::fmt;
 use style::computed_values::{border_collapse, border_spacing, table_layout};
 use style::context::SharedStyleContext;
 use style::logical_geometry::LogicalSize;
 use style::properties::ComputedValues;
 use style::servo::restyle_damage::{REFLOW, REFLOW_OUT_OF_FLOW};
 use style::values::CSSFloat;
-use style::values::computed::{LengthOrPercentageOrAuto, NonNegativeAu};
+use style::values::computed::{LengthOrPercentageOrAuto, NonNegativeLength};
 use table_row::{self, CellIntrinsicInlineSize, CollapsedBorder, CollapsedBorderProvenance};
 use table_row::TableRowFlow;
 use table_wrapper::TableLayout;
 
 /// A table flow corresponded to the table's internal table fragment under a table wrapper flow.
 /// The properties `position`, `float`, and `margin-*` are used on the table wrapper fragment,
 /// not table fragment per CSS 2.1 § 10.5.
 #[derive(Serialize)]
@@ -186,29 +186,29 @@ impl TableFlow {
 
     /// Returns the effective spacing per cell, taking the value of `border-collapse` into account.
     pub fn spacing(&self) -> border_spacing::T {
         let style = self.block_flow.fragment.style();
         match style.get_inheritedtable().border_collapse {
             border_collapse::T::separate => style.get_inheritedtable().border_spacing,
             border_collapse::T::collapse => {
                 border_spacing::T {
-                    horizontal: NonNegativeAu::zero(),
-                    vertical: NonNegativeAu::zero(),
+                    horizontal: NonNegativeLength::zero(),
+                    vertical: NonNegativeLength::zero(),
                 }
             }
         }
     }
 
     pub fn total_horizontal_spacing(&self) -> Au {
         let num_columns = self.column_intrinsic_inline_sizes.len();
         if num_columns == 0 {
             return Au(0);
         }
-        self.spacing().horizontal.0 * (num_columns as i32 + 1)
+        Au::from(self.spacing().horizontal) * (num_columns as i32 + 1)
     }
 }
 
 impl Flow for TableFlow {
     fn class(&self) -> FlowClass {
         FlowClass::Table
     }
 
@@ -243,17 +243,17 @@ impl Flow for TableFlow {
         // Get column inline sizes from colgroups
         for kid in self.block_flow.base.child_iter_mut().filter(|kid| kid.is_table_colgroup()) {
             for specified_inline_size in &kid.as_mut_table_colgroup().inline_sizes {
                 self.column_intrinsic_inline_sizes.push(ColumnIntrinsicInlineSize {
                     minimum_length: match *specified_inline_size {
                         LengthOrPercentageOrAuto::Auto |
                         LengthOrPercentageOrAuto::Calc(_) |
                         LengthOrPercentageOrAuto::Percentage(_) => Au(0),
-                        LengthOrPercentageOrAuto::Length(length) => length,
+                        LengthOrPercentageOrAuto::Length(length) => Au::from(length),
                     },
                     percentage: match *specified_inline_size {
                         LengthOrPercentageOrAuto::Auto |
                         LengthOrPercentageOrAuto::Calc(_) |
                         LengthOrPercentageOrAuto::Length(_) => 0.0,
                         LengthOrPercentageOrAuto::Percentage(percentage) => percentage.0,
                     },
                     preferred: Au(0),
@@ -466,17 +466,17 @@ impl Flow for TableFlow {
                     &mut collapsed_block_direction_border_widths_for_table);
             }
         });
     }
 
     fn assign_block_size(&mut self, _: &LayoutContext) {
         debug!("assign_block_size: assigning block_size for table");
         let vertical_spacing = self.spacing().vertical.0;
-        self.block_flow.assign_block_size_for_table_like_flow(vertical_spacing)
+        self.block_flow.assign_block_size_for_table_like_flow(Au::from(vertical_spacing))
     }
 
     fn compute_stacking_relative_position(&mut self, layout_context: &LayoutContext) {
         self.block_flow.compute_stacking_relative_position(layout_context)
     }
 
     fn generated_containing_block_size(&self, flow: OpaqueFlow) -> LogicalSize<Au> {
         self.block_flow.generated_containing_block_size(flow)
--- a/servo/components/layout/table_row.rs
+++ b/servo/components/layout/table_row.rs
@@ -21,17 +21,17 @@ use model::MaybeAuto;
 use serde::{Serialize, Serializer};
 use std::cmp::max;
 use std::fmt;
 use std::iter::{Enumerate, IntoIterator, Peekable};
 use style::computed_values::{border_collapse, border_spacing, border_top_style};
 use style::logical_geometry::{LogicalSize, PhysicalSide, WritingMode};
 use style::properties::ComputedValues;
 use style::servo::restyle_damage::{REFLOW, REFLOW_OUT_OF_FLOW};
-use style::values::computed::{Color, LengthOrPercentageOrAuto, NonNegativeAu};
+use style::values::computed::{Color, LengthOrPercentageOrAuto, NonNegativeLength};
 use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize, InternalTable, VecExt};
 use table_cell::{CollapsedBordersForCell, TableCellFlow};
 
 /// A single row of a table.
 pub struct TableRowFlow {
     /// Fields common to all block flows.
     pub block_flow: BlockFlow,
 
@@ -89,18 +89,18 @@ impl TableRowFlow {
     pub fn from_fragment(fragment: Fragment) -> TableRowFlow {
         let writing_mode = fragment.style().writing_mode;
         TableRowFlow {
             block_flow: BlockFlow::from_fragment(fragment),
             cell_intrinsic_inline_sizes: Vec::new(),
             column_computed_inline_sizes: Vec::new(),
             incoming_rowspan: Vec::new(),
             spacing: border_spacing::T {
-                horizontal: NonNegativeAu::zero(),
-                vertical: NonNegativeAu::zero(),
+                horizontal: NonNegativeLength::zero(),
+                vertical: NonNegativeLength::zero(),
             },
             table_writing_mode: writing_mode,
             preliminary_collapsed_borders: CollapsedBordersForRow::new(),
             final_collapsed_borders: CollapsedBordersForRow::new(),
             collapsed_border_spacing: CollapsedBorderSpacingForRow::new(),
         }
     }
 
@@ -300,17 +300,17 @@ impl Flow for TableRowFlow {
                 let child_base = flow::mut_base(kid);
                 let child_column_inline_size = ColumnIntrinsicInlineSize {
                     minimum_length: match child_specified_inline_size {
                         LengthOrPercentageOrAuto::Auto |
                         LengthOrPercentageOrAuto::Calc(_) |
                         LengthOrPercentageOrAuto::Percentage(_) => {
                             child_base.intrinsic_inline_sizes.minimum_inline_size
                         }
-                        LengthOrPercentageOrAuto::Length(length) => length,
+                        LengthOrPercentageOrAuto::Length(length) => Au::from(length),
                     },
                     percentage: match child_specified_inline_size {
                         LengthOrPercentageOrAuto::Auto |
                         LengthOrPercentageOrAuto::Calc(_) |
                         LengthOrPercentageOrAuto::Length(_) => 0.0,
                         LengthOrPercentageOrAuto::Percentage(percentage) => percentage.0,
                     },
                     preferred: child_base.intrinsic_inline_sizes.preferred_inline_size,
@@ -391,17 +391,17 @@ impl Flow for TableRowFlow {
             // Add in computed inline sizes for any extra columns in the span.
             for _ in 1..cell_intrinsic_inline_size.column_span {
                 let extra_column_computed_inline_size =
                     match self.column_computed_inline_sizes.get(col) {
                         Some(column_computed_inline_size) => column_computed_inline_size,
                         None => break,
                     };
                 column_computed_inline_size.size = column_computed_inline_size.size +
-                    extra_column_computed_inline_size.size + self.spacing.horizontal.0;
+                    extra_column_computed_inline_size.size + Au::from(self.spacing.horizontal);
                 col += 1;
             }
 
             computed_inline_size_for_cells.push(column_computed_inline_size)
         }
 
         // Set up border collapse info.
         let border_collapse_info =
@@ -620,53 +620,53 @@ impl CollapsedBorder {
     }
 
     /// Creates a collapsed border from the block-start border described in the given CSS style
     /// object.
     fn top(css_style: &ComputedValues, provenance: CollapsedBorderProvenance)
            -> CollapsedBorder {
         CollapsedBorder {
             style: css_style.get_border().border_top_style,
-            width: css_style.get_border().border_top_width.0,
+            width: Au::from(css_style.get_border().border_top_width),
             color: css_style.get_border().border_top_color,
             provenance: provenance,
         }
     }
 
     /// Creates a collapsed border style from the right border described in the given CSS style
     /// object.
     fn right(css_style: &ComputedValues, provenance: CollapsedBorderProvenance)
              -> CollapsedBorder {
         CollapsedBorder {
             style: css_style.get_border().border_right_style,
-            width: css_style.get_border().border_right_width.0,
+            width: Au::from(css_style.get_border().border_right_width),
             color: css_style.get_border().border_right_color,
             provenance: provenance,
         }
     }
 
     /// Creates a collapsed border style from the bottom border described in the given CSS style
     /// object.
     fn bottom(css_style: &ComputedValues, provenance: CollapsedBorderProvenance)
               -> CollapsedBorder {
         CollapsedBorder {
             style: css_style.get_border().border_bottom_style,
-            width: css_style.get_border().border_bottom_width.0,
+            width: Au::from(css_style.get_border().border_bottom_width),
             color: css_style.get_border().border_bottom_color,
             provenance: provenance,
         }
     }
 
     /// Creates a collapsed border style from the left border described in the given CSS style
     /// object.
     fn left(css_style: &ComputedValues, provenance: CollapsedBorderProvenance)
             -> CollapsedBorder {
         CollapsedBorder {
             style: css_style.get_border().border_left_style,
-            width: css_style.get_border().border_left_width.0,
+            width: Au::from(css_style.get_border().border_left_width),
             color: css_style.get_border().border_left_color,
             provenance: provenance,
         }
     }
 
     /// Creates a collapsed border style from the given physical side.
     fn from_side(side: PhysicalSide,
                  css_style: &ComputedValues,
@@ -822,17 +822,17 @@ fn set_inline_position_of_child_flow(
 
     let reverse_column_order = table_writing_mode.is_bidi_ltr() != row_writing_mode.is_bidi_ltr();
 
     // Advance past any column occupied by a cell from a previous row.
     while *column_index < incoming_rowspan.len() && incoming_rowspan[*column_index] != 1 {
         let column_inline_size = column_computed_inline_sizes[*column_index].size;
         let border_inline_size = match *border_collapse_info {
             Some(_) => Au(0), // FIXME: Make collapsed borders account for colspan/rowspan.
-            None => border_spacing.horizontal.0,
+            None => Au::from(border_spacing.horizontal),
         };
         if reverse_column_order {
             *inline_end_margin_edge += column_inline_size + border_inline_size;
         } else {
             *inline_start_margin_edge += column_inline_size + border_inline_size;
         }
         *column_index += 1;
     }
@@ -877,19 +877,19 @@ fn set_inline_position_of_child_flow(
                 *inline_end_margin_edge += child_table_cell.collapsed_borders.inline_start_width;
             } else {
                 *inline_start_margin_edge += child_table_cell.collapsed_borders.inline_start_width;
             }
         }
         None => {
             // Take spacing into account.
             if reverse_column_order {
-                *inline_end_margin_edge += border_spacing.horizontal.0;
+                *inline_end_margin_edge += Au::from(border_spacing.horizontal);
             } else {
-                *inline_start_margin_edge += border_spacing.horizontal.0;
+                *inline_start_margin_edge += Au::from(border_spacing.horizontal);
             }
         }
     }
 
     let column_inline_size = column_computed_inline_sizes[*column_index].size;
     *column_index += 1;
 
     let kid_base = &mut child_table_cell.block_flow.base;
--- a/servo/components/layout/table_rowgroup.rs
+++ b/servo/components/layout/table_rowgroup.rs
@@ -17,17 +17,17 @@ use fragment::{Fragment, FragmentBorderB
 use gfx_traits::print_tree::PrintTree;
 use layout_debug;
 use serde::{Serialize, Serializer};
 use std::fmt;
 use std::iter::{IntoIterator, Iterator, Peekable};
 use style::computed_values::{border_collapse, border_spacing};
 use style::logical_geometry::LogicalSize;
 use style::properties::ComputedValues;
-use style::values::computed::NonNegativeAu;
+use style::values::computed::NonNegativeLength;
 use table::{ColumnIntrinsicInlineSize, InternalTable, TableLikeFlow};
 
 /// A table formatting context.
 pub struct TableRowGroupFlow {
     /// Fields common to all block flows.
     pub block_flow: BlockFlow,
 
     /// Information about the intrinsic inline-sizes of each column.
@@ -52,18 +52,18 @@ impl Serialize for TableRowGroupFlow {
 }
 
 impl TableRowGroupFlow {
     pub fn from_fragment(fragment: Fragment) -> TableRowGroupFlow {
         TableRowGroupFlow {
             block_flow: BlockFlow::from_fragment(fragment),
             column_intrinsic_inline_sizes: Vec::new(),
             spacing: border_spacing::T {
-                horizontal: NonNegativeAu::zero(),
-                vertical: NonNegativeAu::zero(),
+                horizontal: NonNegativeLength::zero(),
+                vertical: NonNegativeLength::zero(),
             },
             collapsed_inline_direction_border_widths_for_table: Vec::new(),
             collapsed_block_direction_border_widths_for_table: Vec::new(),
         }
     }
 
     pub fn populate_collapsed_border_spacing<'a, I>(
             &mut self,
@@ -158,17 +158,17 @@ impl Flow for TableRowGroupFlow {
                     collapsed_inline_direction_border_widths_for_table,
                     &mut collapsed_block_direction_border_widths_for_table);
             }
         });
     }
 
     fn assign_block_size(&mut self, _: &LayoutContext) {
         debug!("assign_block_size: assigning block_size for table_rowgroup");
-        self.block_flow.assign_block_size_for_table_like_flow(self.spacing.vertical.0)
+        self.block_flow.assign_block_size_for_table_like_flow(Au::from(self.spacing.vertical))
     }
 
     fn compute_stacking_relative_position(&mut self, layout_context: &LayoutContext) {
         self.block_flow.compute_stacking_relative_position(layout_context)
     }
 
     fn update_late_computed_inline_position_if_necessary(&mut self, inline_position: Au) {
         self.block_flow.update_late_computed_inline_position_if_necessary(inline_position)
--- a/servo/components/layout/text.rs
+++ b/servo/components/layout/text.rs
@@ -284,29 +284,30 @@ impl TextRunScanner {
             // Push the final run info.
             run_info.flush(&mut run_info_list, &mut insertion_point);
 
             // Per CSS 2.1 § 16.4, "when the resultant space between two characters is not the same
             // as the default space, user agents should not use ligatures." This ensures that, for
             // example, `finally` with a wide `letter-spacing` renders as `f i n a l l y` and not
             // `fi n a l l y`.
             let mut flags = ShapingFlags::empty();
-            match letter_spacing.value() {
-                Some(&Au(0)) | None => {}
-                Some(_) => flags.insert(IGNORE_LIGATURES_SHAPING_FLAG),
+            if let Some(v) = letter_spacing.value() {
+                if v.px() != 0. {
+                    flags.insert(IGNORE_LIGATURES_SHAPING_FLAG);
+                }
             }
             if text_rendering == text_rendering::T::optimizespeed {
                 flags.insert(IGNORE_LIGATURES_SHAPING_FLAG);
                 flags.insert(DISABLE_KERNING_SHAPING_FLAG)
             }
             if word_break == word_break::T::keep_all {
                 flags.insert(KEEP_ALL_FLAG);
             }
             let options = ShapingOptions {
-                letter_spacing: letter_spacing.value().cloned(),
+                letter_spacing: letter_spacing.value().cloned().map(Au::from),
                 word_spacing: word_spacing,
                 script: Script::Common,
                 flags: flags,
             };
 
             // FIXME(https://github.com/rust-lang/rust/issues/23338)
             run_info_list.into_iter().map(|run_info| {
                 let mut options = options;
@@ -441,21 +442,21 @@ pub fn font_metrics_for_style(font_conte
     let fontgroup = font_context.layout_font_group_for_style(font_style);
     // FIXME(https://github.com/rust-lang/rust/issues/23338)
     let font = fontgroup.fonts[0].borrow();
     font.metrics.clone()
 }
 
 /// Returns the line block-size needed by the given computed style and font size.
 pub fn line_height_from_style(style: &ComputedValues, metrics: &FontMetrics) -> Au {
-    let font_size = style.get_font().font_size.0;
+    let font_size = Au::from(style.get_font().font_size);
     match style.get_inheritedtext().line_height {
-        LineHeight::Normal => metrics.line_gap,
+        LineHeight::Normal => Au::from(metrics.line_gap),
         LineHeight::Number(l) => font_size.scale_by(l.0),
-        LineHeight::Length(l) => l.0
+        LineHeight::Length(l) => Au::from(l)
     }
 }
 
 fn split_first_fragment_at_newline_if_necessary(fragments: &mut LinkedList<Fragment>) {
     if fragments.is_empty() {
         return
     }
 
--- a/servo/components/layout/webrender_helpers.rs
+++ b/servo/components/layout/webrender_helpers.rs
@@ -195,17 +195,17 @@ trait ToFilterOps {
     fn to_filter_ops(&self) -> Vec<webrender_api::FilterOp>;
 }
 
 impl ToFilterOps for Vec<Filter> {
     fn to_filter_ops(&self) -> Vec<webrender_api::FilterOp> {
         let mut result = Vec::with_capacity(self.len());
         for filter in self.iter() {
             match *filter {
-                GenericFilter::Blur(radius) => result.push(webrender_api::FilterOp::Blur(radius.0.to_f32_px())),
+                GenericFilter::Blur(radius) => result.push(webrender_api::FilterOp::Blur(radius.px())),
                 GenericFilter::Brightness(amount) => result.push(webrender_api::FilterOp::Brightness(amount.0)),
                 GenericFilter::Contrast(amount) => result.push(webrender_api::FilterOp::Contrast(amount.0)),
                 GenericFilter::Grayscale(amount) => result.push(webrender_api::FilterOp::Grayscale(amount.0)),
                 GenericFilter::HueRotate(angle) => result.push(webrender_api::FilterOp::HueRotate(angle.radians())),
                 GenericFilter::Invert(amount) => result.push(webrender_api::FilterOp::Invert(amount.0)),
                 GenericFilter::Opacity(amount) => result.push(webrender_api::FilterOp::Opacity(amount.0.into())),
                 GenericFilter::Saturate(amount) => result.push(webrender_api::FilterOp::Saturate(amount.0)),
                 GenericFilter::Sepia(amount) => result.push(webrender_api::FilterOp::Sepia(amount.0)),
--- a/servo/components/style/gecko/conversions.rs
+++ b/servo/components/style/gecko/conversions.rs
@@ -24,40 +24,40 @@ use values::generics::grid::{TrackListVa
 use values::generics::image::{CompatMode, Image as GenericImage, GradientItem};
 use values::generics::rect::Rect;
 use values::specified::url::SpecifiedUrl;
 
 impl From<CalcLengthOrPercentage> for nsStyleCoord_CalcValue {
     fn from(other: CalcLengthOrPercentage) -> nsStyleCoord_CalcValue {
         let has_percentage = other.percentage.is_some();
         nsStyleCoord_CalcValue {
-            mLength: other.unclamped_length().0,
+            mLength: other.unclamped_length().to_i32_au(),
             mPercent: other.percentage.map_or(0., |p| p.0),
             mHasPercent: has_percentage,
         }
     }
 }
 
 impl From<nsStyleCoord_CalcValue> for CalcLengthOrPercentage {
     fn from(other: nsStyleCoord_CalcValue) -> CalcLengthOrPercentage {
         let percentage = if other.mHasPercent {
             Some(Percentage(other.mPercent))
         } else {
             None
         };
-        Self::new(Au(other.mLength), percentage)
+        Self::new(Au(other.mLength).into(), percentage)
     }
 }
 
 impl From<LengthOrPercentage> for nsStyleCoord_CalcValue {
     fn from(other: LengthOrPercentage) -> nsStyleCoord_CalcValue {
         match other {
-            LengthOrPercentage::Length(au) => {
+            LengthOrPercentage::Length(px) => {
                 nsStyleCoord_CalcValue {
-                    mLength: au.0,
+                    mLength: px.to_i32_au(),
                     mPercent: 0.0,
                     mHasPercent: false,
                 }
             },
             LengthOrPercentage::Percentage(pc) => {
                 nsStyleCoord_CalcValue {
                     mLength: 0,
                     mPercent: pc.0,
@@ -68,19 +68,19 @@ impl From<LengthOrPercentage> for nsStyl
         }
     }
 }
 
 impl LengthOrPercentageOrAuto {
     /// Convert this value in an appropriate `nsStyleCoord::CalcValue`.
     pub fn to_calc_value(&self) -> Option<nsStyleCoord_CalcValue> {
         match *self {
-            LengthOrPercentageOrAuto::Length(au) => {
+            LengthOrPercentageOrAuto::Length(px) => {
                 Some(nsStyleCoord_CalcValue {
-                    mLength: au.0,
+                    mLength: px.to_i32_au(),
                     mPercent: 0.0,
                     mHasPercent: false,
                 })
             },
             LengthOrPercentageOrAuto::Percentage(pc) => {
                 Some(nsStyleCoord_CalcValue {
                     mLength: 0,
                     mPercent: pc.0,
@@ -91,27 +91,27 @@ impl LengthOrPercentageOrAuto {
             LengthOrPercentageOrAuto::Auto => None,
         }
     }
 }
 
 impl From<nsStyleCoord_CalcValue> for LengthOrPercentage {
     fn from(other: nsStyleCoord_CalcValue) -> LengthOrPercentage {
         match (other.mHasPercent, other.mLength) {
-            (false, _) => LengthOrPercentage::Length(Au(other.mLength)),
+            (false, _) => LengthOrPercentage::Length(Au(other.mLength).into()),
             (true, 0) => LengthOrPercentage::Percentage(Percentage(other.mPercent)),
             _ => LengthOrPercentage::Calc(other.into()),
         }
     }
 }
 
 impl From<nsStyleCoord_CalcValue> for LengthOrPercentageOrAuto {
     fn from(other: nsStyleCoord_CalcValue) -> LengthOrPercentageOrAuto {
         match (other.mHasPercent, other.mLength) {
-            (false, _) => LengthOrPercentageOrAuto::Length(Au(other.mLength)),
+            (false, _) => LengthOrPercentageOrAuto::Length(Au(other.mLength).into()),
             (true, 0) => LengthOrPercentageOrAuto::Percentage(Percentage(other.mPercent)),
             _ => LengthOrPercentageOrAuto::Calc(other.into()),
         }
     }
 }
 
 impl From<Angle> for CoordDataValue {
     fn from(reference: Angle) -> Self {
@@ -323,18 +323,19 @@ impl nsStyleImage {
                         (*gecko_gradient).mAngle.set(angle);
                     }
                 }
 
                 // Setting radius values depending shape
                 match shape {
                     EndingShape::Circle(Circle::Radius(length)) => {
                         unsafe {
-                            (*gecko_gradient).mRadiusX.set_value(CoordDataValue::Coord(length.0));
-                            (*gecko_gradient).mRadiusY.set_value(CoordDataValue::Coord(length.0));
+                            let au = length.to_i32_au();
+                            (*gecko_gradient).mRadiusX.set_value(CoordDataValue::Coord(au));
+                            (*gecko_gradient).mRadiusY.set_value(CoordDataValue::Coord(au));
                         }
                     },
                     EndingShape::Ellipse(Ellipse::Radii(x, y)) => {
                         unsafe {
                             (*gecko_gradient).mRadiusX.set(x);
                             (*gecko_gradient).mRadiusY.set(y);
                         }
                     },
--- a/servo/components/style/gecko/generated/bindings.rs
+++ b/servo/components/style/gecko/generated/bindings.rs
@@ -1338,50 +1338,46 @@ extern "C" {
     pub fn Gecko_CSSValue_GetArrayItem(css_value: nsCSSValueBorrowedMut,
                                        index: i32) -> nsCSSValueBorrowedMut;
 }
 extern "C" {
     pub fn Gecko_CSSValue_GetArrayItemConst(css_value: nsCSSValueBorrowed,
                                             index: i32) -> nsCSSValueBorrowed;
 }
 extern "C" {
-    pub fn Gecko_CSSValue_GetAbsoluteLength(css_value: nsCSSValueBorrowed)
-     -> nscoord;
-}
-extern "C" {
     pub fn Gecko_CSSValue_GetKeyword(aCSSValue: nsCSSValueBorrowed)
      -> nsCSSKeyword;
 }
 extern "C" {
     pub fn Gecko_CSSValue_GetNumber(css_value: nsCSSValueBorrowed) -> f32;
 }
 extern "C" {
     pub fn Gecko_CSSValue_GetPercentage(css_value: nsCSSValueBorrowed) -> f32;
 }
 extern "C" {
     pub fn Gecko_CSSValue_GetCalc(aCSSValue: nsCSSValueBorrowed)
      -> nsStyleCoord_CalcValue;
 }
 extern "C" {
-    pub fn Gecko_CSSValue_SetAbsoluteLength(css_value: nsCSSValueBorrowedMut,
-                                            len: nscoord);
-}
-extern "C" {
     pub fn Gecko_CSSValue_SetNumber(css_value: nsCSSValueBorrowedMut,
                                     number: f32);
 }
 extern "C" {
     pub fn Gecko_CSSValue_SetKeyword(css_value: nsCSSValueBorrowedMut,
                                      keyword: nsCSSKeyword);
 }
 extern "C" {
     pub fn Gecko_CSSValue_SetPercentage(css_value: nsCSSValueBorrowedMut,
                                         percent: f32);
 }
 extern "C" {
+    pub fn Gecko_CSSValue_SetPixelLength(aCSSValue: nsCSSValueBorrowedMut,
+                                         aLen: f32);
+}
+extern "C" {
     pub fn Gecko_CSSValue_SetCalc(css_value: nsCSSValueBorrowedMut,
                                   calc: nsStyleCoord_CalcValue);
 }
 extern "C" {
     pub fn Gecko_CSSValue_SetFunction(css_value: nsCSSValueBorrowedMut,
                                       len: i32);
 }
 extern "C" {
--- a/servo/components/style/gecko/media_queries.rs
+++ b/servo/components/style/gecko/media_queries.rs
@@ -66,17 +66,17 @@ unsafe impl Send for Device {}
 impl Device {
     /// Trivially constructs a new `Device`.
     pub fn new(pres_context: RawGeckoPresContextOwned) -> Self {
         assert!(!pres_context.is_null());
         Device {
             pres_context: pres_context,
             default_values: ComputedValues::default_values(unsafe { &*pres_context }),
             // FIXME(bz): Seems dubious?
-            root_font_size: AtomicIsize::new(font_size::get_initial_value().value() as isize),
+            root_font_size: AtomicIsize::new(font_size::get_initial_value().0.to_i32_au() as isize),
             used_root_font_size: AtomicBool::new(false),
             used_viewport_size: AtomicBool::new(false),
         }
     }
 
     /// Tells the device that a new viewport rule has been found, and stores the
     /// relevant viewport constraints.
     pub fn account_for_viewport_rule(
@@ -708,27 +708,27 @@ impl Expression {
         let required_value = match self.value {
             Some(ref v) => v,
             None => {
                 // If there's no value, always match unless it's a zero length
                 // or a zero integer or boolean.
                 return match *actual_value {
                     BoolInteger(v) => v,
                     Integer(v) => v != 0,
-                    Length(ref l) => l.to_computed_value(&context) != Au(0),
+                    Length(ref l) => l.to_computed_value(&context).px() != 0.,
                     _ => true,
                 }
             }
         };
 
         // FIXME(emilio): Handle the possible floating point errors?
         let cmp = match (required_value, actual_value) {
             (&Length(ref one), &Length(ref other)) => {
-                one.to_computed_value(&context)
-                    .cmp(&other.to_computed_value(&context))
+                one.to_computed_value(&context).to_i32_au()
+                    .cmp(&other.to_computed_value(&context).to_i32_au())
             }
             (&Integer(one), &Integer(ref other)) => one.cmp(other),
             (&BoolInteger(one), &BoolInteger(ref other)) => one.cmp(other),
             (&Float(one), &Float(ref other)) => one.partial_cmp(other).unwrap(),
             (&IntRatio(one_num, one_den), &IntRatio(other_num, other_den)) => {
                 (one_num * other_den).partial_cmp(&(other_num * one_den)).unwrap()
             }
             (&Resolution(ref one), &Resolution(ref other)) => {
--- a/servo/components/style/gecko/values.rs
+++ b/servo/components/style/gecko/values.rs
@@ -12,20 +12,20 @@ use counter_style::{Symbol, Symbols};
 use cssparser::RGBA;
 use gecko_bindings::structs::{CounterStylePtr, nsStyleCoord};
 use gecko_bindings::structs::{StyleGridTrackBreadth, StyleShapeRadius};
 use gecko_bindings::sugar::ns_style_coord::{CoordData, CoordDataMut, CoordDataValue};
 use media_queries::Device;
 use nsstring::{nsACString, nsCString};
 use std::cmp::max;
 use values::{Auto, Either, ExtremumLength, None_, Normal};
-use values::computed::{Angle, LengthOrPercentage, LengthOrPercentageOrAuto};
+use values::computed::{Angle, Length, LengthOrPercentage, LengthOrPercentageOrAuto};
 use values::computed::{LengthOrPercentageOrNone, Number, NumberOrPercentage};
 use values::computed::{MaxLength, MozLength, Percentage};
-use values::computed::{NonNegativeAu, NonNegativeLengthOrPercentage, NonNegativeNumber};
+use values::computed::{NonNegativeLength, NonNegativeLengthOrPercentage, NonNegativeNumber};
 use values::computed::basic_shape::ShapeRadius as ComputedShapeRadius;
 use values::generics::{CounterStyleOrNone, NonNegative};
 use values::generics::basic_shape::ShapeRadius;
 use values::generics::gecko::ScrollSnapPoint;
 use values::generics::grid::{TrackBreadth, TrackKeyword};
 
 /// A trait that defines an interface to convert from and to `nsStyleCoord`s.
 pub trait GeckoStyleCoordConvertible : Sized {
@@ -101,26 +101,26 @@ impl GeckoStyleCoordConvertible for Numb
             _ => None,
         }
     }
 }
 
 impl GeckoStyleCoordConvertible for LengthOrPercentage {
     fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
         let value = match *self {
-            LengthOrPercentage::Length(au) => CoordDataValue::Coord(au.0),
+            LengthOrPercentage::Length(px) => CoordDataValue::Coord(px.to_i32_au()),
             LengthOrPercentage::Percentage(p) => CoordDataValue::Percent(p.0),
             LengthOrPercentage::Calc(calc) => CoordDataValue::Calc(calc.into()),
         };
         coord.set_value(value);
     }
 
     fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
         match coord.as_value() {
-            CoordDataValue::Coord(coord) => Some(LengthOrPercentage::Length(Au(coord))),
+            CoordDataValue::Coord(coord) => Some(LengthOrPercentage::Length(Au(coord).into())),
             CoordDataValue::Percent(p) => Some(LengthOrPercentage::Percentage(Percentage(p))),
             CoordDataValue::Calc(calc) => Some(LengthOrPercentage::Calc(calc.into())),
             _ => None,
         }
     }
 }
 
 impl GeckoStyleCoordConvertible for NonNegativeLengthOrPercentage {
@@ -128,85 +128,85 @@ impl GeckoStyleCoordConvertible for NonN
         self.0.to_gecko_style_coord(coord);
     }
 
     fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
         LengthOrPercentage::from_gecko_style_coord(coord).map(NonNegative::<LengthOrPercentage>)
     }
 }
 
-impl GeckoStyleCoordConvertible for Au {
+impl GeckoStyleCoordConvertible for Length {
     fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
-        coord.set_value(CoordDataValue::Coord(self.0));
+        coord.set_value(CoordDataValue::Coord(self.to_i32_au()));
     }
 
     fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
         match coord.as_value() {
-            CoordDataValue::Coord(coord) => Some(Au(coord)),
+            CoordDataValue::Coord(coord) => Some(Au(coord).into()),
             _ => None,
         }
     }
 }
 
-impl GeckoStyleCoordConvertible for NonNegativeAu {
+impl GeckoStyleCoordConvertible for NonNegativeLength {
     fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
         self.0.to_gecko_style_coord(coord);
     }
 
     fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
-        Au::from_gecko_style_coord(coord).map(NonNegative::<Au>)
+        Length::from_gecko_style_coord(coord).map(NonNegative::<Length>)
     }
 }
 
 impl GeckoStyleCoordConvertible for NonNegativeNumber {
     fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
         self.0.to_gecko_style_coord(coord);
     }
 
     fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
         Number::from_gecko_style_coord(coord).map(NonNegative::<Number>)
     }
 }
 
 impl GeckoStyleCoordConvertible for LengthOrPercentageOrAuto {
     fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
         let value = match *self {
-            LengthOrPercentageOrAuto::Length(au) => CoordDataValue::Coord(au.0),
+            LengthOrPercentageOrAuto::Length(px) => CoordDataValue::Coord(px.to_i32_au()),
             LengthOrPercentageOrAuto::Percentage(p) => CoordDataValue::Percent(p.0),
             LengthOrPercentageOrAuto::Auto => CoordDataValue::Auto,
             LengthOrPercentageOrAuto::Calc(calc) => CoordDataValue::Calc(calc.into()),
         };
         coord.set_value(value);
     }
 
     fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
         match coord.as_value() {
-            CoordDataValue::Coord(coord) => Some(LengthOrPercentageOrAuto::Length(Au(coord))),
+            CoordDataValue::Coord(coord) => Some(LengthOrPercentageOrAuto::Length(Au(coord).into())),
             CoordDataValue::Percent(p) => Some(LengthOrPercentageOrAuto::Percentage(Percentage(p))),
             CoordDataValue::Auto => Some(LengthOrPercentageOrAuto::Auto),
             CoordDataValue::Calc(calc) => Some(LengthOrPercentageOrAuto::Calc(calc.into())),
             _ => None,
         }
     }
 }
 
 impl GeckoStyleCoordConvertible for LengthOrPercentageOrNone {
     fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
         let value = match *self {
-            LengthOrPercentageOrNone::Length(au) => CoordDataValue::Coord(au.0),
+            LengthOrPercentageOrNone::Length(px) => CoordDataValue::Coord(px.to_i32_au()),
             LengthOrPercentageOrNone::Percentage(p) => CoordDataValue::Percent(p.0),
             LengthOrPercentageOrNone::None => CoordDataValue::None,
             LengthOrPercentageOrNone::Calc(calc) => CoordDataValue::Calc(calc.into()),
         };
         coord.set_value(value);
     }
 
     fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
         match coord.as_value() {
-            CoordDataValue::Coord(coord) => Some(LengthOrPercentageOrNone::Length(Au(coord))),
+            CoordDataValue::Coord(coord) => Some(LengthOrPercentageOrNone::Length(Au(coord).into())),
             CoordDataValue::Percent(p) => Some(LengthOrPercentageOrNone::Percentage(Percentage(p))),
             CoordDataValue::None => Some(LengthOrPercentageOrNone::None),
             CoordDataValue::Calc(calc) => Some(LengthOrPercentageOrNone::Calc(calc.into())),
             _ => None,
         }
     }
 }
 
--- a/servo/components/style/gecko_bindings/sugar/ns_css_shadow_item.rs
+++ b/servo/components/style/gecko_bindings/sugar/ns_css_shadow_item.rs
@@ -10,36 +10,36 @@ use gecko_bindings::structs::nsCSSShadow
 use values::computed::RGBAColor;
 use values::computed::effects::{BoxShadow, SimpleShadow};
 
 impl nsCSSShadowItem {
     /// Sets this item from the given box shadow.
     #[inline]
     pub fn set_from_box_shadow(&mut self, shadow: BoxShadow) {
         self.set_from_simple_shadow(shadow.base);
-        self.mSpread = shadow.spread.0;
+        self.mSpread = shadow.spread.to_i32_au();
         self.mInset = shadow.inset;
     }
 
     /// Returns this item as a box shadow.
     #[inline]
     pub fn to_box_shadow(&self) -> BoxShadow {
         BoxShadow {
             base: self.extract_simple_shadow(),
-            spread: Au(self.mSpread),
+            spread: Au(self.mSpread).into(),
             inset: self.mInset,
         }
     }
 
     /// Sets this item from the given simple shadow.
     #[inline]
     pub fn set_from_simple_shadow(&mut self, shadow: SimpleShadow) {
-        self.mXOffset = shadow.horizontal.0;
-        self.mYOffset = shadow.vertical.0;
-        self.mRadius = shadow.blur.value();
+        self.mXOffset = shadow.horizontal.to_i32_au();
+        self.mYOffset = shadow.vertical.to_i32_au();
+        self.mRadius = shadow.blur.0.to_i32_au();
         self.mSpread = 0;
         self.mInset = false;
         if let Some(color) = shadow.color {
             self.mHasColor = true;
             self.mColor = convert_rgba_to_nscolor(&color);
         } else {
             // TODO handle currentColor
             // https://bugzilla.mozilla.org/show_bug.cgi?id=760345
@@ -57,18 +57,18 @@ impl nsCSSShadowItem {
         }
     }
 
     /// Gets a simple shadow from this item.
     #[inline]
     fn extract_simple_shadow(&self) -> SimpleShadow {
         SimpleShadow {
             color: self.extract_color(),
-            horizontal: Au(self.mXOffset),
-            vertical: Au(self.mYOffset),
+            horizontal: Au(self.mXOffset).into(),
+            vertical: Au(self.mYOffset).into(),
             blur: Au(self.mRadius).into(),
         }
     }
 
     /// Returns this item as a simple shadow.
     #[inline]
     pub fn to_simple_shadow(&self) -> SimpleShadow {
         debug_assert_eq!(self.mSpread, 0);
--- a/servo/components/style/gecko_bindings/sugar/ns_css_value.rs
+++ b/servo/components/style/gecko_bindings/sugar/ns_css_value.rs
@@ -1,15 +1,14 @@
 /* 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/. */
 
 //! Little helpers for `nsCSSValue`.
 
-use app_units::Au;
 use gecko_bindings::bindings;
 use gecko_bindings::structs;
 use gecko_bindings::structs::{nsCSSValue, nsCSSUnit};
 use gecko_bindings::structs::{nsCSSValue_Array, nsCSSValueList, nscolor};
 use gecko_string_cache::Atom;
 use std::marker::PhantomData;
 use std::mem;
 use std::ops::{Index, IndexMut};
@@ -70,33 +69,34 @@ impl nsCSSValue {
         let array = *self.mValue.mArray.as_ref();
         debug_assert!(!array.is_null());
         &*array
     }
 
     /// Sets LengthOrPercentage value to this nsCSSValue.
     pub unsafe fn set_lop(&mut self, lop: LengthOrPercentage) {
         match lop {
-            LengthOrPercentage::Length(au) => {
-                bindings::Gecko_CSSValue_SetAbsoluteLength(self, au.0)
+            LengthOrPercentage::Length(px) => {
+                bindings::Gecko_CSSValue_SetPixelLength(self, px.px())
             }
             LengthOrPercentage::Percentage(pc) => {
                 bindings::Gecko_CSSValue_SetPercentage(self, pc.0)
             }
             LengthOrPercentage::Calc(calc) => {
                 bindings::Gecko_CSSValue_SetCalc(self, calc.into())
             }
         }
     }
 
     /// Returns LengthOrPercentage value.
     pub unsafe fn get_lop(&self) -> LengthOrPercentage {
+        use values::computed::Length;
         match self.mUnit {
             nsCSSUnit::eCSSUnit_Pixel => {
-                LengthOrPercentage::Length(Au(bindings::Gecko_CSSValue_GetAbsoluteLength(self)))
+                LengthOrPercentage::Length(Length::new(bindings::Gecko_CSSValue_GetNumber(self)))
             },
             nsCSSUnit::eCSSUnit_Percent => {
                 LengthOrPercentage::Percentage(Percentage(bindings::Gecko_CSSValue_GetPercentage(self)))
             },
             nsCSSUnit::eCSSUnit_Calc => {
                 LengthOrPercentage::Calc(bindings::Gecko_CSSValue_GetCalc(self).into())
             },
             x => panic!("The unit should not be {:?}", x),
--- a/servo/components/style/matching.rs
+++ b/servo/components/style/matching.rs
@@ -528,16 +528,17 @@ pub trait MatchMethods : TElement {
     /// damage.
     fn finish_restyle(
         &self,
         context: &mut StyleContext<Self>,
         data: &mut ElementData,
         mut new_styles: ElementStyles,
         important_rules_changed: bool,
     ) -> ChildCascadeRequirement {
+        use app_units::Au;
         use dom::TNode;
         use std::cmp;
         use std::mem;
 
         debug_assert!(new_styles.primary.is_some(), "How did that happen?");
 
         self.process_animations(
             context,
@@ -576,17 +577,17 @@ pub trait MatchMethods : TElement {
 
         let mut cascade_requirement = ChildCascadeRequirement::CanSkipCascade;
         if self.is_root() && !self.is_native_anonymous() {
             let device = context.shared.stylist.device();
             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.0);
+                device.set_root_font_size(Au::from(new_font_size));
                 // 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/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -56,17 +56,17 @@ use properties::computed_value_flags::Co
 use properties::{default_font_size_keyword, longhands, FontComputationData, Importance, LonghandId};
 use properties::{PropertyDeclaration, PropertyDeclarationBlock, PropertyDeclarationId};
 use rule_tree::StrongRuleNode;
 use selector_parser::PseudoElement;
 use servo_arc::{Arc, RawOffsetArc};
 use std::mem::{forget, uninitialized, transmute, zeroed};
 use std::{cmp, ops, ptr};
 use values::{self, Auto, CustomIdent, Either, KeyframesName, None_};
-use values::computed::{NonNegativeAu, ToComputedValue, Percentage};
+use values::computed::{NonNegativeLength, ToComputedValue, Percentage};
 use values::computed::effects::{BoxShadow, Filter, SimpleShadow};
 use computed_values::border_style;
 
 pub mod style_structs {
     % for style_struct in data.style_structs:
     pub use super::${style_struct.gecko_struct_name} as ${style_struct.name};
     % endfor
 }
@@ -525,23 +525,23 @@ def set_gecko_property(ffi_name, expr):
 % if need_clone:
     <%call expr="impl_simple_clone(ident, gecko_ffi_name)"></%call>
 % endif
 </%def>
 
 <%def name="impl_absolute_length(ident, gecko_ffi_name, need_clone=False)">
     #[allow(non_snake_case)]
     pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
-        ${set_gecko_property(gecko_ffi_name, "v.0")}
+        ${set_gecko_property(gecko_ffi_name, "v.to_i32_au()")}
     }
     <%call expr="impl_simple_copy(ident, gecko_ffi_name)"></%call>
     % if need_clone:
         #[allow(non_snake_case)]
         pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
-            Au(self.gecko.${gecko_ffi_name})
+            Au(self.gecko.${gecko_ffi_name}).into()
         }
     % endif
 </%def>
 
 <%def name="impl_position(ident, gecko_ffi_name, need_clone=False)">
     #[allow(non_snake_case)]
     pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
         ${set_gecko_property("%s.mXPosition" % gecko_ffi_name, "v.horizontal.into()")}
@@ -628,17 +628,17 @@ def set_gecko_property(ffi_name, expr):
         if (self.gecko.mContextFlags & CONTEXT_VALUE) != 0 {
             return SVGLength::ContextValue;
         }
         let length = match self.gecko.${gecko_ffi_name}.as_value() {
             CoordDataValue::Factor(number) =>
                 SvgLengthOrPercentageOrNumber::Number(number),
             CoordDataValue::Coord(coord) =>
                 SvgLengthOrPercentageOrNumber::LengthOrPercentage(
-                    LengthOrPercentage::Length(Au(coord))),
+                    LengthOrPercentage::Length(Au(coord).into())),
             CoordDataValue::Percent(p) =>
                 SvgLengthOrPercentageOrNumber::LengthOrPercentage(
                     LengthOrPercentage::Percentage(Percentage(p))),
             CoordDataValue::Calc(calc) =>
                 SvgLengthOrPercentageOrNumber::LengthOrPercentage(
                     LengthOrPercentage::Calc(calc.into())),
             _ => unreachable!("Unexpected coordinate {:?} in ${ident}",
                               self.gecko.${gecko_ffi_name}.as_value()),
@@ -805,26 +805,26 @@ def set_gecko_property(ffi_name, expr):
         };
         SVGPaint {
             kind: kind,
             fallback: fallback,
         }
     }
 </%def>
 
-<%def name="impl_non_negative_app_units(ident, gecko_ffi_name, need_clone, inherit_from=None,
-                                        round_to_pixels=False)">
+<%def name="impl_non_negative_length(ident, gecko_ffi_name, need_clone, inherit_from=None,
+                                     round_to_pixels=False)">
     #[allow(non_snake_case)]
     pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
         let value = {
             % if round_to_pixels:
             let au_per_device_px = Au(self.gecko.mTwipsPerPixel);
-            round_border_to_device_pixels(v.0, au_per_device_px).0
+            round_border_to_device_pixels(Au::from(v), au_per_device_px).0
             % else:
-            v.value()
+            v.0.to_i32_au()
             % endif
         };
 
         % if inherit_from:
         self.gecko.${inherit_from} = value;
         % endif
         self.gecko.${gecko_ffi_name} = value;
     }
@@ -1380,21 +1380,21 @@ fn static_assert() {
     // just copy the specified border here, we'll adjust it if it's incorrect
     // later.
     fn update_border_${side.ident}(&mut self) {
         self.gecko.mComputedBorder.${side.ident} = self.gecko.mBorder.${side.ident};
     }
 
     <% impl_color("border_%s_color" % side.ident, "(mBorderColor)[%s]" % side.index, need_clone=True) %>
 
-    <% impl_non_negative_app_units("border_%s_width" % side.ident,
-                                   "mComputedBorder.%s" % side.ident,
-                                   inherit_from="mBorder.%s" % side.ident,
-                                   need_clone=True,
-                                   round_to_pixels=True) %>
+    <% impl_non_negative_length("border_%s_width" % side.ident,
+                                "mComputedBorder.%s" % side.ident,
+                                inherit_from="mBorder.%s" % side.ident,
+                                need_clone=True,
+                                round_to_pixels=True) %>
 
     pub fn border_${side.ident}_has_nonzero_width(&self) -> bool {
         self.gecko.mComputedBorder.${side.ident} != 0
     }
 
     #[allow(non_snake_case)]
     pub fn set__moz_border_${side.ident}_colors(&mut self,
                                                 v: longhands::_moz_border_${side.ident}_colors::computed_value::T) {
@@ -2105,19 +2105,19 @@ fn static_assert() {
             % endfor
             structs::${border_style_keyword.gecko_constant('auto')} => Either::First(Auto),
             % if border_style_keyword.gecko_inexhaustive:
             x => panic!("Found unexpected value in style struct for outline_style property: {:?}", x),
             % endif
         }
     }
 
-    <% impl_non_negative_app_units("outline_width", "mActualOutlineWidth",
-                                   inherit_from="mOutlineWidth",
-                                   need_clone=True, round_to_pixels=True) %>
+    <% impl_non_negative_length("outline_width", "mActualOutlineWidth",
+                                inherit_from="mOutlineWidth",
+                                need_clone=True, round_to_pixels=True) %>
 
     % for corner in CORNERS:
     <% impl_corner_style_coord("_moz_outline_radius_%s" % corner.ident.replace("_", ""),
                                "mOutlineRadius",
                                corner.x_index,
                                corner.y_index,
                                need_clone=True) %>
     % endfor
@@ -2243,46 +2243,46 @@ fn static_assert() {
 
     pub fn unzoom_fonts(&mut self, device: &Device) {
         self.gecko.mSize = device.unzoom_text(Au(self.gecko.mSize)).0;
         self.gecko.mScriptUnconstrainedSize = device.unzoom_text(Au(self.gecko.mScriptUnconstrainedSize)).0;
         self.gecko.mFont.size = device.unzoom_text(Au(self.gecko.mFont.size)).0;
     }
 
     pub fn set_font_size(&mut self, v: longhands::font_size::computed_value::T) {
-        self.gecko.mSize = v.value();
-        self.gecko.mScriptUnconstrainedSize = v.value();
+        self.gecko.mSize = v.0.to_i32_au();
+        self.gecko.mScriptUnconstrainedSize = v.0.to_i32_au();
     }
 
     /// Set font size, taking into account scriptminsize and scriptlevel
     /// Returns Some(size) if we have to recompute the script unconstrained size
     pub fn apply_font_size(&mut self, v: longhands::font_size::computed_value::T,
                            parent: &Self,
-                           device: &Device) -> Option<NonNegativeAu> {
+                           device: &Device) -> Option<NonNegativeLength> {
         let (adjusted_size, adjusted_unconstrained_size) =
             self.calculate_script_level_size(parent, device);
         // In this case, we have been unaffected by scriptminsize, ignore it
         if parent.gecko.mSize == parent.gecko.mScriptUnconstrainedSize &&
            adjusted_size == adjusted_unconstrained_size {
             self.set_font_size(v);
             self.fixup_font_min_size(device);
             None
         } else {
-            self.gecko.mSize = v.value();
+            self.gecko.mSize = v.0.to_i32_au();
             self.fixup_font_min_size(device);
             Some(Au(parent.gecko.mScriptUnconstrainedSize).into())
         }
     }
 
     pub fn fixup_font_min_size(&mut self, device: &Device) {
         unsafe { bindings::Gecko_nsStyleFont_FixupMinFontSize(&mut self.gecko, device.pres_context()) }
     }
 
-    pub fn apply_unconstrained_font_size(&mut self, v: NonNegativeAu) {
-        self.gecko.mScriptUnconstrainedSize = v.value();
+    pub fn apply_unconstrained_font_size(&mut self, v: NonNegativeLength) {
+        self.gecko.mScriptUnconstrainedSize = v.0.to_i32_au();
     }
 
     /// Calculates the constrained and unconstrained font sizes to be inherited
     /// from the parent.
     ///
     /// See ComputeScriptLevelSize in Gecko's nsRuleNode.cpp
     ///
     /// scriptlevel is a property that affects how font-size is inherited. If scriptlevel is
@@ -2382,17 +2382,17 @@ fn static_assert() {
     }
 
     /// This function will also handle scriptminsize and scriptlevel
     /// so should not be called when you just want the font sizes to be copied.
     /// Hence the different name.
     ///
     /// Returns true if the inherited keyword size was actually used
     pub fn inherit_font_size_from(&mut self, parent: &Self,
-                                  kw_inherited_size: Option<NonNegativeAu>,
+                                  kw_inherited_size: Option<NonNegativeLength>,
                                   device: &Device) -> bool {
         let (adjusted_size, adjusted_unconstrained_size)
             = self.calculate_script_level_size(parent, device);
         if adjusted_size.0 != parent.gecko.mSize ||
            adjusted_unconstrained_size.0 != parent.gecko.mScriptUnconstrainedSize {
             // This is incorrect. When there is both a keyword size being inherited
             // and a scriptlevel change, we must handle the keyword size the same
             // way we handle em units. This complicates things because we now have
@@ -2408,19 +2408,19 @@ fn static_assert() {
             // In the case that MathML has given us an adjusted size, apply it.
             // Keep track of the unconstrained adjusted size.
             self.gecko.mSize = adjusted_size.0;
             self.gecko.mScriptUnconstrainedSize = adjusted_unconstrained_size.0;
             self.fixup_font_min_size(device);
             false
         } else if let Some(size) = kw_inherited_size {
             // Parent element was a keyword-derived size.
-            self.gecko.mSize = size.value();
+            self.gecko.mSize = size.0.to_i32_au();
             // MathML constraints didn't apply here, so we can ignore this.
-            self.gecko.mScriptUnconstrainedSize = size.value();
+            self.gecko.mScriptUnconstrainedSize = size.0.to_i32_au();
             self.fixup_font_min_size(device);
             true
         } else {
             // MathML isn't affecting us, and our parent element does not
             // have a keyword-derived size. Set things normally.
             self.gecko.mSize = parent.gecko.mSize;
             self.gecko.mScriptUnconstrainedSize = parent.gecko.mScriptUnconstrainedSize;
             self.fixup_font_min_size(device);
@@ -3015,17 +3015,17 @@ fn static_assert() {
                 pattern = " { from_list: ref list1, to_list: ref list2, count: integer_to_percentage3 }"
             else:
                 # Generate contents of pattern from items
                 pattern = "(%s)" % ", ".join([b + str(a+1) for (a,b) in enumerate(items)])
 
             # First %s substituted with the call to GetArrayItem, the second
             # %s substituted with the corresponding variable
             css_value_setters = {
-                "length" : "bindings::Gecko_CSSValue_SetAbsoluteLength(%s, %s.0)",
+                "length" : "bindings::Gecko_CSSValue_SetPixelLength(%s, %s.px())",
                 "percentage" : "bindings::Gecko_CSSValue_SetPercentage(%s, %s.0)",
                 # Note: This is an integer type, but we use it as a percentage value in Gecko, so
                 #       need to cast it to f32.
                 "integer_to_percentage" : "bindings::Gecko_CSSValue_SetPercentage(%s, %s as f32)",
                 "lop" : "%s.set_lop(%s)",
                 "angle" : "%s.set_angle(%s)",
                 "number" : "bindings::Gecko_CSSValue_SetNumber(%s, %s)",
                 # Note: We use nsCSSValueSharedList here, instead of nsCSSValueList_heap
@@ -3117,17 +3117,17 @@ fn static_assert() {
     pub fn reset_transform(&mut self, other: &Self) {
         self.copy_transform_from(other)
     }
 
     <%def name="computed_operation_arm(name, keyword, items)">
         <%
             # %s is substituted with the call to GetArrayItem.
             css_value_getters = {
-                "length" : "Au(bindings::Gecko_CSSValue_GetAbsoluteLength(%s))",
+                "length" : "Length::new(bindings::Gecko_CSSValue_GetNumber(%s))",
                 "lop" : "%s.get_lop()",
                 "angle" : "%s.get_angle()",
                 "number" : "bindings::Gecko_CSSValue_GetNumber(%s)",
                 "percentage" : "Percentage(bindings::Gecko_CSSValue_GetPercentage(%s))",
                 "percentage_to_integer" : "bindings::Gecko_CSSValue_GetPercentage(%s) as i32",
                 "list" : "TransformList(Some(convert_shared_list_to_operations(%s)))",
             }
             pre_symbols = "("
@@ -3161,17 +3161,17 @@ fn static_assert() {
             ${post_symbols}
         },
     </%def>
     fn clone_single_transform_function(gecko_value: &structs::nsCSSValue)
                                        -> longhands::transform::computed_value::ComputedOperation {
         use properties::longhands::transform::computed_value::ComputedMatrix;
         use properties::longhands::transform::computed_value::ComputedOperation;
         use properties::longhands::transform::computed_value::T as TransformList;
-        use values::computed::Percentage;
+        use values::computed::{Length, Percentage};
 
         let convert_shared_list_to_operations = |value: &structs::nsCSSValue|
                                                 -> Vec<ComputedOperation> {
             debug_assert!(value.mUnit == structs::nsCSSUnit::eCSSUnit_SharedList);
             let value_list = unsafe {
                 value.mValue.mSharedList.as_ref()
                      .as_mut().expect("List pointer should be non-null").mHead.as_ref()
             };
@@ -3455,23 +3455,23 @@ fn static_assert() {
     }
 
     pub fn reset_transform_origin(&mut self, other: &Self) {
         self.copy_transform_origin_from(other)
     }
 
     pub fn clone_transform_origin(&self) -> longhands::transform_origin::computed_value::T {
         use properties::longhands::transform_origin::computed_value::T;
-        use values::computed::LengthOrPercentage;
+        use values::computed::{Length, LengthOrPercentage};
         T {
             horizontal: LengthOrPercentage::from_gecko_style_coord(&self.gecko.mTransformOrigin[0])
                 .expect("clone for LengthOrPercentage failed"),
             vertical: LengthOrPercentage::from_gecko_style_coord(&self.gecko.mTransformOrigin[1])
                 .expect("clone for LengthOrPercentage failed"),
-            depth: Au::from_gecko_style_coord(&self.gecko.mTransformOrigin[2])
+            depth: Length::from_gecko_style_coord(&self.gecko.mTransformOrigin[2])
                 .expect("clone for Length failed"),
         }
     }
 
     pub fn set_will_change(&mut self, v: longhands::will_change::computed_value::T) {
         use gecko_bindings::bindings::{Gecko_AppendWillChange, Gecko_ClearWillChange};
         use gecko_bindings::structs::NS_STYLE_WILL_CHANGE_OPACITY;
         use gecko_bindings::structs::NS_STYLE_WILL_CHANGE_SCROLL;
@@ -4200,24 +4200,24 @@ fn static_assert() {
         match v {
             Either::Second(_auto) => {
                 self.gecko.mImageRegion.x = 0;
                 self.gecko.mImageRegion.y = 0;
                 self.gecko.mImageRegion.width = 0;
                 self.gecko.mImageRegion.height = 0;
             }
             Either::First(rect) => {
-                self.gecko.mImageRegion.x = rect.left.unwrap_or(Au(0)).0;
-                self.gecko.mImageRegion.y = rect.top.unwrap_or(Au(0)).0;
+                self.gecko.mImageRegion.x = rect.left.map(Au::from).unwrap_or(Au(0)).0;
+                self.gecko.mImageRegion.y = rect.top.map(Au::from).unwrap_or(Au(0)).0;
                 self.gecko.mImageRegion.height = match rect.bottom {
-                    Some(value) => value.0 - self.gecko.mImageRegion.y,
+                    Some(value) => (Au::from(value) - Au(self.gecko.mImageRegion.y)).0,
                     None => 0,
                 };
                 self.gecko.mImageRegion.width = match rect.right {
-                    Some(value) => value.0 - self.gecko.mImageRegion.x,
+                    Some(value) => (Au::from(value) - Au(self.gecko.mImageRegion.x)).0,
                     None => 0,
                 };
             }
         }
     }
 
     #[allow(non_snake_case)]
     pub fn clone__moz_image_region(&self) -> longhands::_moz_image_region::computed_value::T {
@@ -4229,20 +4229,20 @@ fn static_assert() {
         if self.gecko.mImageRegion.x == 0 &&
            self.gecko.mImageRegion.y == 0 &&
            self.gecko.mImageRegion.width == 0 &&
            self.gecko.mImageRegion.height == 0 {
            return Either::Second(Auto);
         }
 
         Either::First(ClipRect {
-            top: Some(Au(self.gecko.mImageRegion.y)),
-            right: Some(Au(self.gecko.mImageRegion.width) + Au(self.gecko.mImageRegion.x)),
-            bottom: Some(Au(self.gecko.mImageRegion.height) + Au(self.gecko.mImageRegion.y)),
-            left: Some(Au(self.gecko.mImageRegion.x)),
+            top: Some(Au(self.gecko.mImageRegion.y).into()),
+            right: Some(Au(self.gecko.mImageRegion.width + self.gecko.mImageRegion.x).into()),
+            bottom: Some(Au(self.gecko.mImageRegion.height + self.gecko.mImageRegion.y).into()),
+            left: Some(Au(self.gecko.mImageRegion.x).into()),
         })
     }
 
     ${impl_simple_copy('_moz_image_region', 'mImageRegion')}
 
 </%self:impl_trait>
 
 <%self:impl_trait style_struct_name="Table" skip_longhands="-x-span">
@@ -4288,38 +4288,38 @@ fn static_assert() {
         use gecko_bindings::structs::NS_STYLE_CLIP_RIGHT_AUTO;
         use gecko_bindings::structs::NS_STYLE_CLIP_BOTTOM_AUTO;
         use values::Either;
 
         match v {
             Either::First(rect) => {
                 self.gecko.mClipFlags = NS_STYLE_CLIP_RECT as u8;
                 if let Some(left) = rect.left {
-                    self.gecko.mClip.x = left.0;
+                    self.gecko.mClip.x = left.to_i32_au();
                 } else {
                     self.gecko.mClip.x = 0;
                     self.gecko.mClipFlags |= NS_STYLE_CLIP_LEFT_AUTO as u8;
                 }
 
                 if let Some(top) = rect.top {
-                    self.gecko.mClip.y = top.0;
+                    self.gecko.mClip.y = top.to_i32_au();
                 } else {
                     self.gecko.mClip.y = 0;
                     self.gecko.mClipFlags |= NS_STYLE_CLIP_TOP_AUTO as u8;
                 }
 
                 if let Some(bottom) = rect.bottom {
-                    self.gecko.mClip.height = (bottom - Au(self.gecko.mClip.y)).0;
+                    self.gecko.mClip.height = (Au::from(bottom) - Au(self.gecko.mClip.y)).0;
                 } else {
                     self.gecko.mClip.height = 1 << 30; // NS_MAXSIZE
                     self.gecko.mClipFlags |= NS_STYLE_CLIP_BOTTOM_AUTO as u8;
                 }
 
                 if let Some(right) = rect.right {
-                    self.gecko.mClip.width = (right - Au(self.gecko.mClip.x)).0;
+                    self.gecko.mClip.width = (Au::from(right) - Au(self.gecko.mClip.x)).0;
                 } else {
                     self.gecko.mClip.width = 1 << 30; // NS_MAXSIZE
                     self.gecko.mClipFlags |= NS_STYLE_CLIP_RIGHT_AUTO as u8;
                 }
             },
             Either::Second(_auto) => {
                 self.gecko.mClipFlags = NS_STYLE_CLIP_AUTO as u8;
                 self.gecko.mClip.x = 0;
@@ -4350,38 +4350,38 @@ fn static_assert() {
 
         if self.gecko.mClipFlags == NS_STYLE_CLIP_AUTO as u8 {
             ClipRectOrAuto::auto()
         } else {
             let left = if self.gecko.mClipFlags & NS_STYLE_CLIP_LEFT_AUTO as u8 != 0 {
                 debug_assert!(self.gecko.mClip.x == 0);
                 None
             } else {
-                Some(Au(self.gecko.mClip.x))
+                Some(Au(self.gecko.mClip.x).into())
             };
 
             let top = if self.gecko.mClipFlags & NS_STYLE_CLIP_TOP_AUTO as u8 != 0 {
                 debug_assert!(self.gecko.mClip.y == 0);
                 None
             } else {
-                Some(Au(self.gecko.mClip.y))
+                Some(Au(self.gecko.mClip.y).into())
             };
 
             let bottom = if self.gecko.mClipFlags & NS_STYLE_CLIP_BOTTOM_AUTO as u8 != 0 {
                 debug_assert!(self.gecko.mClip.height == 1 << 30); // NS_MAXSIZE
                 None
             } else {
-                Some(Au(self.gecko.mClip.y + self.gecko.mClip.height))
+                Some(Au(self.gecko.mClip.y + self.gecko.mClip.height).into())
             };
 
             let right = if self.gecko.mClipFlags & NS_STYLE_CLIP_RIGHT_AUTO as u8 != 0 {
                 debug_assert!(self.gecko.mClip.width == 1 << 30); // NS_MAXSIZE
                 None
             } else {
-                Some(Au(self.gecko.mClip.x + self.gecko.mClip.width))
+                Some(Au(self.gecko.mClip.x + self.gecko.mClip.width).into())
             };
 
             Either::First(ClipRect { top: top, right: right, bottom: bottom, left: left, })
         }
     }
 
     <%
     # This array is several filter function which has percentage or
@@ -4425,17 +4425,17 @@ fn static_assert() {
         for (servo, gecko_filter) in v.zip(self.gecko.mFilters.iter_mut()) {
             match servo {
                 % for func in FILTER_FUNCTIONS:
                 ${func}(factor) => fill_filter(NS_STYLE_FILTER_${func.upper()},
                                                CoordDataValue::Factor(factor.0),
                                                gecko_filter),
                 % endfor
                 Blur(length) => fill_filter(NS_STYLE_FILTER_BLUR,
-                                            CoordDataValue::Coord(length.value()),
+                                            CoordDataValue::Coord(length.0.to_i32_au()),
                                             gecko_filter),
 
                 HueRotate(angle) => fill_filter(NS_STYLE_FILTER_HUE_ROTATE,
                                                 CoordDataValue::from(angle),
                                                 gecko_filter),
 
                 DropShadow(shadow) => {
                     gecko_filter.mType = NS_STYLE_FILTER_DROP_SHADOW;
@@ -4493,17 +4493,17 @@ fn static_assert() {
                 % for func in FILTER_FUNCTIONS:
                 NS_STYLE_FILTER_${func.upper()} => {
                     filters.push(Filter::${func}(
                         GeckoStyleCoordConvertible::from_gecko_style_coord(
                             &filter.mFilterParameter).unwrap()));
                 },
                 % endfor
                 NS_STYLE_FILTER_BLUR => {
-                    filters.push(Filter::Blur(NonNegativeAu::from_gecko_style_coord(
+                    filters.push(Filter::Blur(NonNegativeLength::from_gecko_style_coord(
                         &filter.mFilterParameter).unwrap()));
                 },
                 NS_STYLE_FILTER_HUE_ROTATE => {
                     filters.push(Filter::HueRotate(
                         GeckoStyleCoordConvertible::from_gecko_style_coord(
                             &filter.mFilterParameter).unwrap()));
                 },
                 NS_STYLE_FILTER_DROP_SHADOW => {
@@ -4585,18 +4585,18 @@ fn static_assert() {
         }
     }
 </%self:impl_trait>
 
 <%self:impl_trait style_struct_name="InheritedTable"
                   skip_longhands="border-spacing">
 
     pub fn set_border_spacing(&mut self, v: longhands::border_spacing::computed_value::T) {
-        self.gecko.mBorderSpacingCol = v.horizontal.value();
-        self.gecko.mBorderSpacingRow = v.vertical.value();
+        self.gecko.mBorderSpacingCol = v.horizontal.0.to_i32_au();
+        self.gecko.mBorderSpacingRow = v.vertical.0.to_i32_au();
     }
 
     pub fn copy_border_spacing_from(&mut self, other: &Self) {
         self.gecko.mBorderSpacingCol = other.gecko.mBorderSpacingCol;
         self.gecko.mBorderSpacingRow = other.gecko.mBorderSpacingRow;
     }
 
     pub fn reset_border_spacing(&mut self, other: &Self) {
@@ -4646,17 +4646,17 @@ fn static_assert() {
         longhands::text_shadow::computed_value::T(buf)
     }
 
     pub fn set_line_height(&mut self, v: longhands::line_height::computed_value::T) {
         use values::generics::text::LineHeight;
         // FIXME: Align binary representations and ditch |match| for cast + static_asserts
         let en = match v {
             LineHeight::Normal => CoordDataValue::Normal,
-            LineHeight::Length(val) => CoordDataValue::Coord(val.value()),
+            LineHeight::Length(val) => CoordDataValue::Coord(val.0.to_i32_au()),
             LineHeight::Number(val) => CoordDataValue::Factor(val.0),
             LineHeight::MozBlockHeight =>
                     CoordDataValue::Enumerated(structs::NS_STYLE_LINE_HEIGHT_BLOCK_HEIGHT),
         };
         self.gecko.mLineHeight.set_value(en);
     }
 
     pub fn clone_line_height(&self) -> longhands::line_height::computed_value::T {
@@ -4677,23 +4677,24 @@ fn static_assert() {
         use values::generics::text::Spacing;
         match v {
             Spacing::Value(value) => self.gecko.mLetterSpacing.set(value),
             Spacing::Normal => self.gecko.mLetterSpacing.set_value(CoordDataValue::Normal)
         }
     }
 
     pub fn clone_letter_spacing(&self) -> longhands::letter_spacing::computed_value::T {
+        use values::computed::Length;
         use values::generics::text::Spacing;
         debug_assert!(
             matches!(self.gecko.mLetterSpacing.as_value(),
                      CoordDataValue::Normal |
                      CoordDataValue::Coord(_)),
             "Unexpected computed value for letter-spacing");
-        Au::from_gecko_style_coord(&self.gecko.mLetterSpacing).map_or(Spacing::Normal, Spacing::Value)
+        Length::from_gecko_style_coord(&self.gecko.mLetterSpacing).map_or(Spacing::Normal, Spacing::Value)
     }
 
     <%call expr="impl_coord_copy('letter_spacing', 'mLetterSpacing')"></%call>
 
     pub fn set_word_spacing(&mut self, v: longhands::word_spacing::computed_value::T) {
         use values::generics::text::Spacing;
         match v {
             Spacing::Value(lop) => self.gecko.mWordSpacing.set(lop),
@@ -4793,30 +4794,30 @@ fn static_assert() {
             };
 
         T::Keyword(KeywordValue {
             fill: fill,
             shape: shape
         })
     }
 
-    <%call expr="impl_non_negative_app_units('_webkit_text_stroke_width',
-                                             'mWebkitTextStrokeWidth',
-                                             need_clone=True)"></%call>
+    <%call expr="impl_non_negative_length('_webkit_text_stroke_width',
+                                          'mWebkitTextStrokeWidth',
+                                          need_clone=True)"></%call>
 
     #[allow(non_snake_case)]
     pub fn set__moz_tab_size(&mut self, v: longhands::_moz_tab_size::computed_value::T) {
         use values::Either;
 
         match v {
             Either::Second(non_negative_number) => {
                 self.gecko.mTabSize.set_value(CoordDataValue::Factor(non_negative_number.0));
             }
-            Either::First(non_negative_au) => {
-                self.gecko.mTabSize.set(non_negative_au.0);
+            Either::First(non_negative_length) => {
+                self.gecko.mTabSize.set(non_negative_length);
             }
         }
     }
 
     #[allow(non_snake_case)]
     pub fn clone__moz_tab_size(&self) -> longhands::_moz_tab_size::computed_value::T {
         use values::Either;
 
@@ -5204,17 +5205,17 @@ clip-path
         }
         let mut vec = vec![];
         for gecko in self.gecko.mStrokeDasharray.iter() {
             match gecko.as_value() {
                 CoordDataValue::Factor(number) =>
                     vec.push(SvgLengthOrPercentageOrNumber::Number(number.into())),
                 CoordDataValue::Coord(coord) =>
                     vec.push(SvgLengthOrPercentageOrNumber::LengthOrPercentage(
-                        LengthOrPercentage::Length(Au(coord)).into())),
+                        LengthOrPercentage::Length(Au(coord).into()).into())),
                 CoordDataValue::Percent(p) =>
                     vec.push(SvgLengthOrPercentageOrNumber::LengthOrPercentage(
                         LengthOrPercentage::Percentage(Percentage(p)).into())),
                 CoordDataValue::Calc(calc) =>
                     vec.push(SvgLengthOrPercentageOrNumber::LengthOrPercentage(
                         LengthOrPercentage::Calc(calc.into()).into())),
                 _ => unreachable!(),
             }
@@ -5456,18 +5457,18 @@ clip-path
             debug_assert!(self.gecko.mColumnCount >= 1 &&
                           self.gecko.mColumnCount <= nsStyleColumn_kMaxColumnCount);
             Either::First((self.gecko.mColumnCount as i32).into())
         } else {
             Either::Second(Auto)
         }
     }
 
-    <% impl_non_negative_app_units("column_rule_width", "mColumnRuleWidth", need_clone=True,
-                                   round_to_pixels=True) %>
+    <% impl_non_negative_length("column_rule_width", "mColumnRuleWidth", need_clone=True,
+                                round_to_pixels=True) %>
 </%self:impl_trait>
 
 <%self:impl_trait style_struct_name="Counters"
                   skip_longhands="content counter-increment counter-reset">
     pub fn ineffective_content_property(&self) -> bool {
         self.gecko.mContents.is_empty()
     }
 
--- a/servo/components/style/properties/helpers/animated_properties.mako.rs
+++ b/servo/components/style/properties/helpers/animated_properties.mako.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 http://mozilla.org/MPL/2.0/. */
 
 <%namespace name="helpers" file="/helpers.mako.rs" />
 
 <% from data import to_idl_name, SYSTEM_FONT_LONGHANDS %>
 
-use app_units::Au;
 use cssparser::Parser;
 #[cfg(feature = "gecko")] use gecko_bindings::bindings::RawServoAnimationValueMap;
 #[cfg(feature = "gecko")] use gecko_bindings::structs::RawGeckoGfxMatrix4x4;
 #[cfg(feature = "gecko")] use gecko_bindings::structs::nsCSSPropertyID;
 #[cfg(feature = "gecko")] use gecko_bindings::sugar::ownership::{HasFFI, HasSimpleFFI};
 #[cfg(feature = "gecko")] use gecko_string_cache::Atom;
 use itertools::{EitherOrBoth, Itertools};
 use properties::{CSSWideKeyword, PropertyDeclaration};
@@ -42,18 +41,18 @@ use values::{CSSFloat, CustomIdent, Eith
 use values::animated::{Animate, Procedure, ToAnimatedValue, ToAnimatedZero};
 use values::animated::color::{Color as AnimatedColor, RGBA as AnimatedRGBA};
 use values::animated::effects::BoxShadowList as AnimatedBoxShadowList;
 use values::animated::effects::Filter as AnimatedFilter;
 use values::animated::effects::FilterList as AnimatedFilterList;
 use values::animated::effects::TextShadowList as AnimatedTextShadowList;
 use values::computed::{Angle, BorderCornerRadius, CalcLengthOrPercentage};
 use values::computed::{ClipRect, Context, ComputedUrl};
-use values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto};
-use values::computed::{LengthOrPercentageOrNone, MaxLength, NonNegativeAu};
+use values::computed::{Length, LengthOrPercentage, LengthOrPercentageOrAuto};
+use values::computed::{LengthOrPercentageOrNone, MaxLength, NonNegativeLength};
 use values::computed::{NonNegativeNumber, Number, NumberOrPercentage, Percentage};
 use values::computed::{PositiveIntegerOrAuto, ToComputedValue};
 #[cfg(feature = "gecko")] use values::computed::MozLength;
 use values::computed::length::{NonNegativeLengthOrAuto, NonNegativeLengthOrNormal};
 use values::computed::length::NonNegativeLengthOrPercentage;
 use values::computed::transform::DirectionVector;
 use values::distance::{ComputeSquaredDistance, SquaredDistance};
 #[cfg(feature = "gecko")] use values::generics::FontSettings as GenericFontSettings;
@@ -808,31 +807,31 @@ impl Animate for CalcLengthOrPercentage 
 
 impl ToAnimatedZero for LengthOrPercentageOrAuto {
     #[inline]
     fn to_animated_zero(&self) -> Result<Self, ()> {
         match *self {
             LengthOrPercentageOrAuto::Length(_) |
             LengthOrPercentageOrAuto::Percentage(_) |
             LengthOrPercentageOrAuto::Calc(_) => {
-                Ok(LengthOrPercentageOrAuto::Length(Au(0)))
+                Ok(LengthOrPercentageOrAuto::Length(Length::new(0.)))
             },
             LengthOrPercentageOrAuto::Auto => Err(()),
         }
     }
 }
 
 impl ToAnimatedZero for LengthOrPercentageOrNone {
     #[inline]
     fn to_animated_zero(&self) -> Result<Self, ()> {
         match *self {
             LengthOrPercentageOrNone::Length(_) |
             LengthOrPercentageOrNone::Percentage(_) |
             LengthOrPercentageOrNone::Calc(_) => {
-                Ok(LengthOrPercentageOrNone::Length(Au(0)))
+                Ok(LengthOrPercentageOrNone::Length(Length::new(0.)))
             },
             LengthOrPercentageOrNone::None => Err(()),
         }
     }
 }
 
 impl ToAnimatedZero for MaxLength {
     #[inline]
@@ -1089,17 +1088,18 @@ impl<'a> Iterator for FontSettingTagIter
 
 impl<H, V> RepeatableListAnimatable for generic_position::Position<H, V>
     where H: RepeatableListAnimatable, V: RepeatableListAnimatable {}
 
 /// https://drafts.csswg.org/css-transitions/#animtype-rect
 impl Animate for ClipRect {
     #[inline]
     fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
-        let animate_component = |this: &Option<Au>, other: &Option<Au>| {
+        use values::computed::Length;
+        let animate_component = |this: &Option<Length>, other: &Option<Length>| {
             match (this.animate(other, procedure)?, procedure) {
                 (None, Procedure::Interpolate { .. }) => Ok(None),
                 (None, _) => Err(()),
                 (result, _) => Ok(result),
             }
         };
 
         Ok(ClipRect {
@@ -1239,21 +1239,21 @@ impl Animate for TransformOperation {
                 }
             },
             (
                 &TransformOperation::Perspective(ref fd),
                 &TransformOperation::Perspective(ref td),
             ) => {
                 let mut fd_matrix = ComputedMatrix::identity();
                 let mut td_matrix = ComputedMatrix::identity();
-                if fd.0 > 0 {
-                    fd_matrix.m34 = -1. / fd.to_f32_px();
+                if fd.px() > 0. {
+                    fd_matrix.m34 = -1. / fd.px();
                 }
-                if td.0 > 0 {
-                    td_matrix.m34 = -1. / td.to_f32_px();
+                if td.px() > 0. {
+                    td_matrix.m34 = -1. / td.px();
                 }
                 Ok(TransformOperation::Matrix(
                     fd_matrix.animate(&td_matrix, procedure)?,
                 ))
             },
             _ => Err(()),
         }
     }
@@ -2308,31 +2308,31 @@ impl ComputeSquaredDistance for Transfor
                 // We don't want to require doing layout in order to calculate the result, so
                 // drop the percentage part. However, dropping percentage makes us impossible to
                 // compute the distance for the percentage-percentage case, but Gecko uses the
                 // same formula, so it's fine for now.
                 // Note: We use pixel value to compute the distance for translate, so we have to
                 // convert Au into px.
                 let extract_pixel_length = |lop: &LengthOrPercentage| {
                     match *lop {
-                        LengthOrPercentage::Length(au) => au.to_f64_px(),
+                        LengthOrPercentage::Length(px) => px.px(),
                         LengthOrPercentage::Percentage(_) => 0.,
-                        LengthOrPercentage::Calc(calc) => calc.length().to_f64_px(),
+                        LengthOrPercentage::Calc(calc) => calc.length().px(),
                     }
                 };
 
                 let fx = extract_pixel_length(&fx);
                 let fy = extract_pixel_length(&fy);
                 let tx = extract_pixel_length(&tx);
                 let ty = extract_pixel_length(&ty);
 
                 Ok(
                     fx.compute_squared_distance(&tx)? +
                     fy.compute_squared_distance(&ty)? +
-                    fz.to_f64_px().compute_squared_distance(&tz.to_f64_px())?,
+                    fz.compute_squared_distance(&tz)?,
                 )
             },
             (
                 &TransformOperation::Scale(ref fx, ref fy, ref fz),
                 &TransformOperation::Scale(ref tx, ref ty, ref tz),
             ) => {
                 Ok(
                     fx.compute_squared_distance(&tx)? +
@@ -2359,35 +2359,35 @@ impl ComputeSquaredDistance for Transfor
                 }
             }
             (
                 &TransformOperation::Perspective(ref fd),
                 &TransformOperation::Perspective(ref td),
             ) => {
                 let mut fd_matrix = ComputedMatrix::identity();
                 let mut td_matrix = ComputedMatrix::identity();
-                if fd.0 > 0 {
-                    fd_matrix.m34 = -1. / fd.to_f32_px();
+                if fd.px() > 0. {
+                    fd_matrix.m34 = -1. / fd.px();
                 }
 
-                if td.0 > 0 {
-                    td_matrix.m34 = -1. / td.to_f32_px();
+                if td.px() > 0. {
+                    td_matrix.m34 = -1. / td.px();
                 }
                 fd_matrix.compute_squared_distance(&td_matrix)
             }
             (
                 &TransformOperation::Perspective(ref p),
                 &TransformOperation::Matrix(ref m),
             ) | (
                 &TransformOperation::Matrix(ref m),
                 &TransformOperation::Perspective(ref p),
             ) => {
                 let mut p_matrix = ComputedMatrix::identity();
-                if p.0 > 0 {
-                    p_matrix.m34 = -1. / p.to_f32_px();
+                if p.px() > 0. {
+                    p_matrix.m34 = -1. / p.px();
                 }
                 p_matrix.compute_squared_distance(&m)
             }
             _ => Err(()),
         }
     }
 }
 
@@ -2459,17 +2459,17 @@ impl From<NonNegativeNumber> for NumberO
     fn from(num: NonNegativeNumber) -> NumberOrPercentage {
         num.0.into()
     }
 }
 
 impl From<LengthOrPercentage> for NumberOrPercentage {
     fn from(lop: LengthOrPercentage) -> NumberOrPercentage {
         match lop {
-            LengthOrPercentage::Length(len) => NumberOrPercentage::Number(len.to_f32_px()),
+            LengthOrPercentage::Length(len) => NumberOrPercentage::Number(len.px()),
             LengthOrPercentage::Percentage(p) => NumberOrPercentage::Percentage(p),
             LengthOrPercentage::Calc(_) => {
                 panic!("We dont't expected calc interpolation for SvgLengthOrPercentageOrNumber");
             },
         }
     }
 }
 
--- a/servo/components/style/properties/longhand/border.mako.rs
+++ b/servo/components/style/properties/longhand/border.mako.rs
@@ -37,21 +37,21 @@
                               alias=maybe_moz_logical_alias(product, side, "-moz-border-%s-style"),
                               spec=maybe_logical_spec(side, "style"),
                               flags="APPLIES_TO_FIRST_LETTER",
                               animation_value_type="discrete" if not is_logical else "none",
                               logical=is_logical)}
 
     ${helpers.predefined_type("border-%s-width" % side_name,
                               "BorderSideWidth",
-                              "::values::computed::NonNegativeAu::from_px(3)",
-                              computed_type="::values::computed::NonNegativeAu",
+                              "::values::computed::NonNegativeLength::new(3.)",
+                              computed_type="::values::computed::NonNegativeLength",
                               alias=maybe_moz_logical_alias(product, side, "-moz-border-%s-width"),
                               spec=maybe_logical_spec(side, "width"),
-                              animation_value_type="NonNegativeAu",
+                              animation_value_type="NonNegativeLength",
                               logical=is_logical,
                               flags="APPLIES_TO_FIRST_LETTER",
                               allow_quirks=not is_logical)}
 % endfor
 
 ${helpers.gecko_keyword_conversion(Keyword('border-style',
                                    "none solid double dotted dashed hidden groove ridge inset outset"),
                                    type="::values::specified::BorderStyle")}
--- a/servo/components/style/properties/longhand/box.mako.rs
+++ b/servo/components/style/properties/longhand/box.mako.rs
@@ -615,28 +615,26 @@
     animation_value_type="discrete",
     allow_empty="NotInitial"
 )}
 
 <%helpers:longhand name="transform" extra_prefixes="webkit"
                    animation_value_type="ComputedValue"
                    flags="CREATES_STACKING_CONTEXT FIXPOS_CB"
                    spec="https://drafts.csswg.org/css-transforms/#propdef-transform">
-    use app_units::Au;
     use values::computed::{LengthOrPercentageOrNumber as ComputedLoPoNumber, LengthOrNumber as ComputedLoN};
     use values::computed::{LengthOrPercentage as ComputedLoP, Length as ComputedLength};
     use values::generics::transform::Matrix;
     use values::specified::{Angle, Integer, Length, LengthOrPercentage};
     use values::specified::{LengthOrNumber, LengthOrPercentageOrNumber as LoPoNumber, Number};
     use style_traits::ToCss;
 
     use std::fmt;
 
     pub mod computed_value {
-        use app_units::Au;
         use values::CSSFloat;
         use values::computed;
         use values::computed::{Length, LengthOrPercentage};
 
         #[derive(Clone, Copy, Debug, PartialEq)]
         #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
         pub struct ComputedMatrix {
             pub m11: CSSFloat, pub m12: CSSFloat, pub m13: CSSFloat, pub m14: CSSFloat,
@@ -668,17 +666,17 @@
 
         impl ComputedMatrixWithPercents {
             pub fn identity() -> ComputedMatrixWithPercents {
                 ComputedMatrixWithPercents {
                     m11: 1.0, m12: 0.0, m13: 0.0, m14: 0.0,
                     m21: 0.0, m22: 1.0, m23: 0.0, m24: 0.0,
                     m31: 0.0, m32: 0.0, m33: 1.0, m34: 0.0,
                     m41: LengthOrPercentage::zero(), m42: LengthOrPercentage::zero(),
-                    m43: Au(0), m44: 1.0
+                    m43: Length::new(0.), m44: 1.0
                 }
             }
         }
 
         #[derive(Clone, Debug, PartialEq)]
         #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
         pub enum ComputedOperation {
             Matrix(ComputedMatrix),
@@ -1247,39 +1245,39 @@
                             };
                         result.push(computed_value::ComputedOperation::MatrixWithPercents(comp));
                     }
                     SpecifiedOperation::Translate(ref tx, None) => {
                         let tx = tx.to_computed_value(context);
                         result.push(computed_value::ComputedOperation::Translate(
                             tx,
                             computed::length::LengthOrPercentage::zero(),
-                            computed::length::Length::new(0)));
+                            computed::length::Length::new(0.)));
                     }
                     SpecifiedOperation::Translate(ref tx, Some(ref ty)) => {
                         let tx = tx.to_computed_value(context);
                         let ty = ty.to_computed_value(context);
                         result.push(computed_value::ComputedOperation::Translate(
                             tx,
                             ty,
-                            computed::length::Length::new(0)));
+                            computed::length::Length::new(0.)));
                     }
                     SpecifiedOperation::TranslateX(ref tx) => {
                         let tx = tx.to_computed_value(context);
                         result.push(computed_value::ComputedOperation::Translate(
                             tx,
                             computed::length::LengthOrPercentage::zero(),
-                            computed::length::Length::new(0)));
+                            computed::length::Length::new(0.)));
                     }
                     SpecifiedOperation::TranslateY(ref ty) => {
                         let ty = ty.to_computed_value(context);
                         result.push(computed_value::ComputedOperation::Translate(
                             computed::length::LengthOrPercentage::zero(),
                             ty,
-                            computed::length::Length::new(0)));
+                            computed::length::Length::new(0.)));
                     }
                     SpecifiedOperation::TranslateZ(ref tz) => {
                         let tz = tz.to_computed_value(context);
                         result.push(computed_value::ComputedOperation::Translate(
                             computed::length::LengthOrPercentage::zero(),
                             computed::length::LengthOrPercentage::zero(),
                             tz));
                     }
@@ -1477,30 +1475,30 @@
                     };
                 }
                 result
             }).unwrap_or(Vec::new()))
         }
     }
 
     // Converts computed LengthOrPercentageOrNumber into computed
-    // LengthOrPercentage. Number maps into Length
+    // LengthOrPercentage. Number maps into Length (pixel unit)
     fn lopon_to_lop(value: &ComputedLoPoNumber) -> ComputedLoP {
         match *value {
-            Either::First(number) => ComputedLoP::Length(Au::from_f32_px(number)),
+            Either::First(number) => ComputedLoP::Length(ComputedLength::new(number)),
             Either::Second(length_or_percentage) => length_or_percentage,
         }
     }
 
     // Converts computed LengthOrNumber into computed Length.
     // Number maps into Length.
     fn lon_to_length(value: &ComputedLoN) -> ComputedLength {
         match *value {
             Either::First(length) => length,
-            Either::Second(number) => Au::from_f32_px(number),
+            Either::Second(number) => ComputedLength::new(number),
         }
     }
 </%helpers:longhand>
 
 // CSSOM View Module
 // https://www.w3.org/TR/cssom-view-1/
 ${helpers.single_keyword("scroll-behavior",
                          "auto smooth",
--- a/servo/components/style/properties/longhand/column.mako.rs
+++ b/servo/components/style/properties/longhand/column.mako.rs
@@ -34,22 +34,22 @@
                           spec="https://drafts.csswg.org/css-multicol/#propdef-column-gap")}
 
 ${helpers.single_keyword("column-fill", "balance auto", extra_prefixes="moz",
                          products="gecko", animation_value_type="discrete",
                          spec="https://drafts.csswg.org/css-multicol/#propdef-column-fill")}
 
 ${helpers.predefined_type("column-rule-width",
                           "BorderSideWidth",
-                          "::values::computed::NonNegativeAu::from_px(3)",
+                          "::values::computed::NonNegativeLength::new(3.)",
                           initial_specified_value="specified::BorderSideWidth::Medium",
-                          computed_type="::values::computed::NonNegativeAu",
+                          computed_type="::values::computed::NonNegativeLength",
                           products="gecko",
                           spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-width",
-                          animation_value_type="NonNegativeAu",
+                          animation_value_type="NonNegativeLength",
                           extra_prefixes="moz")}
 
 // https://drafts.csswg.org/css-multicol-1/#crc
 ${helpers.predefined_type(
     "column-rule-color",
     "Color",
     "computed_value::T::currentcolor()",
     initial_specified_value="specified::Color::currentcolor()",
--- a/servo/components/style/properties/longhand/font.mako.rs
+++ b/servo/components/style/properties/longhand/font.mako.rs
@@ -584,25 +584,25 @@ macro_rules! impl_gecko_keyword_conversi
 
         #[inline]
         fn from_computed_value(computed: &computed_value::T) -> Self {
             SpecifiedValue::Weight(*computed)
         }
     }
 </%helpers:longhand>
 
-<%helpers:longhand name="font-size" need_clone="True" animation_value_type="NonNegativeAu"
+<%helpers:longhand name="font-size" need_clone="True" animation_value_type="NonNegativeLength"
                    flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER"
                    allow_quirks="True" spec="https://drafts.csswg.org/css-fonts/#propdef-font-size">
     use app_units::Au;
     use properties::longhands::system_font::SystemFont;
     use std::fmt;
     use style_traits::ToCss;
     use values::FONT_MEDIUM_PX;
-    use values::computed::NonNegativeAu;
+    use values::computed::NonNegativeLength;
     use values::specified::{AllowQuirks, FontRelativeLength, LengthOrPercentage, NoCalcLength};
     use values::specified::length::FontBaseSize;
 
     impl ToCss for SpecifiedValue {
         fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
             match *self {
                 SpecifiedValue::Length(ref lop) => lop.to_css(dest),
                 SpecifiedValue::Keyword(kw, _, _) => kw.to_css(dest),
@@ -622,31 +622,31 @@ macro_rules! impl_gecko_keyword_conversi
         /// will be 1 (with offset 0), but we cascade keywordness even
         /// after font-relative (percent and em) values
         /// have been applied, which is where the ratio
         /// comes in. The offset comes in if we cascaded a calc value,
         /// where the font-relative portion (em and percentage) will
         /// go into the ratio, and the remaining units all computed together
         /// will go into the offset.
         /// See bug 1355707.
-        Keyword(KeywordSize, f32, NonNegativeAu),
+        Keyword(KeywordSize, f32, NonNegativeLength),
         Smaller,
         Larger,
         System(SystemFont)
     }
 
     impl From<specified::LengthOrPercentage> for SpecifiedValue {
         fn from(other: specified::LengthOrPercentage) -> Self {
             SpecifiedValue::Length(other)
         }
     }
 
     pub mod computed_value {
-        use values::computed::NonNegativeAu;
-        pub type T = NonNegativeAu;
+        use values::computed::NonNegativeLength;
+        pub type T = NonNegativeLength;
     }
 
     /// CSS font keywords
     #[derive(Clone, Copy, Debug, PartialEq)]
     #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
     pub enum KeywordSize {
         XXSmall = 1, // This is to enable the NonZero optimization
                      // which simplifies the representation of Option<KeywordSize>
@@ -711,17 +711,17 @@ macro_rules! impl_gecko_keyword_conversi
                                           specified values set via
                                           HTML presentation attributes"),
             })
         }
     }
 
     % if product == "servo":
         impl ToComputedValue for KeywordSize {
-            type ComputedValue = NonNegativeAu;
+            type ComputedValue = NonNegativeLength;
             #[inline]
             fn to_computed_value(&self, _: &Context) -> computed_value::T {
                 // https://drafts.csswg.org/css-fonts-3/#font-size-prop
                 use values::FONT_MEDIUM_PX;
                 match *self {
                     XXSmall => Au::from_px(FONT_MEDIUM_PX) * 3 / 5,
                     XSmall => Au::from_px(FONT_MEDIUM_PX) * 3 / 4,
                     Small => Au::from_px(FONT_MEDIUM_PX) * 8 / 9,
@@ -735,17 +735,17 @@ macro_rules! impl_gecko_keyword_conversi
 
             #[inline]
             fn from_computed_value(_: &computed_value::T) -> Self {
                 unreachable!()
             }
         }
     % else:
         impl ToComputedValue for KeywordSize {
-            type ComputedValue = NonNegativeAu;
+            type ComputedValue = NonNegativeLength;
             #[inline]
             fn to_computed_value(&self, cx: &Context) -> computed_value::T {
                 use gecko_bindings::structs::nsIAtom;
                 use values::specified::length::au_to_int_px;
                 // Data from nsRuleNode.cpp in Gecko
                 // Mapping from base size and HTML size to pixels
                 // The first index is (base_size - 9), the second is the
                 // HTML size. "0" is CSS keyword xx-small, not HTML size 0,
@@ -771,17 +771,17 @@ macro_rules! impl_gecko_keyword_conversi
                 let ref gecko_font = cx.style().get_font().gecko();
                 let base_size = unsafe { Atom::with(gecko_font.mLanguage.raw::<nsIAtom>(), |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 html_size = self.html_size() as usize;
                 if base_size_px >= 9 && base_size_px <= 16 {
-                    NonNegativeAu::from_px(FONT_SIZE_MAPPING[(base_size_px - 9) as usize][html_size])
+                    NonNegativeLength::new(FONT_SIZE_MAPPING[(base_size_px - 9) as usize][html_size] as f32)
                 } else {
                     Au(FONT_SIZE_FACTORS[html_size] * base_size / 100).into()
                 }
             }
 
             #[inline]
             fn from_computed_value(_: &computed_value::T) -> Self {
                 unreachable!()
@@ -806,86 +806,87 @@ macro_rules! impl_gecko_keyword_conversi
                 6 => XXLarge,
                 // If value is greater than 7, let it be 7.
                 _ => XXXLarge,
             }, 1., Au(0).into())
         }
 
         /// If this value is specified as a ratio of the parent font (em units
         /// or percent) return the ratio
-        pub fn as_font_ratio(&self, context: &Context) -> Option<(f32, NonNegativeAu)> {
+        pub fn as_font_ratio(&self, context: &Context) -> Option<(f32, NonNegativeLength)> {
             match *self {
                 SpecifiedValue::Length(ref lop) => {
                     match *lop {
                         LengthOrPercentage::Percentage(pc) => {
-                            Some((pc.0, Au(0).into()))
+                            Some((pc.0, NonNegativeLength::zero()))
                         }
                         LengthOrPercentage::Length(ref nocalc) => {
                             match *nocalc {
                                 NoCalcLength::FontRelative(FontRelativeLength::Em(em)) => {
-                                    Some((em, Au(0).into()))
+                                    Some((em, NonNegativeLength::zero()))
                                 }
                                 _ => None,
                             }
                         }
                         LengthOrPercentage::Calc(ref calc) => {
                             if calc.em.is_none() && calc.percentage.is_none() {
                                 return None;
                             }
                             let ratio = calc.em.unwrap_or(0.) + calc.percentage.map_or(0., |pc| pc.0);
                             // Compute it, but shave off the font-relative part (em, %)
                             // This will mean that other font-relative units like ex and ch will be computed against
                             // the old font even when the font changes. There's no particular "right answer" for what
                             // to do here -- Gecko recascades as if the font had changed, we instead track the changes
                             // and reapply, which means that we carry over old computed ex/ch values whilst Gecko
                             // recomputes new ones. This is enough of an edge case to not really matter.
-                            let abs = calc.to_computed_value_zoomed(context, FontBaseSize::Custom(Au(0).into()))
+                            let abs = calc.to_computed_value_zoomed(context, FontBaseSize::Custom(Au(0)))
                                           .length_component().into();
                             Some((ratio, abs))
                         }
                     }
                 }
                 SpecifiedValue::Larger => Some((LARGER_FONT_SIZE_RATIO, Au(0).into())),
                 SpecifiedValue::Smaller => Some((1. / LARGER_FONT_SIZE_RATIO, Au(0).into())),
                 _ => None,
             }
         }
 
         /// Compute it against a given base font size
         pub fn to_computed_value_against(
             &self,
             context: &Context,
             base_size: FontBaseSize,
-        ) -> NonNegativeAu {
+        ) -> NonNegativeLength {
             use values::specified::length::FontRelativeLength;
             match *self {
                 SpecifiedValue::Length(LengthOrPercentage::Length(
                         NoCalcLength::FontRelative(value))) => {
                     value.to_computed_value(context, base_size).into()
                 }
                 SpecifiedValue::Length(LengthOrPercentage::Length(
                         NoCalcLength::ServoCharacterWidth(value))) => {
                     value.to_computed_value(base_size.resolve(context)).into()
                 }
                 SpecifiedValue::Length(LengthOrPercentage::Length(
                         NoCalcLength::Absolute(ref l))) => {
-                    context.maybe_zoom_text(l.to_computed_value(context).into())
+                    context.maybe_zoom_text(l.to_computed_value(context)).into()
                 }
                 SpecifiedValue::Length(LengthOrPercentage::Length(ref l)) => {
                     l.to_computed_value(context).into()
                 }
                 SpecifiedValue::Length(LengthOrPercentage::Percentage(pc)) => {
                     base_size.resolve(context).scale_by(pc.0).into()
                 }
                 SpecifiedValue::Length(LengthOrPercentage::Calc(ref calc)) => {
                     let calc = calc.to_computed_value_zoomed(context, base_size);
                     calc.to_used_value(Some(base_size.resolve(context))).unwrap().into()
                 }
                 SpecifiedValue::Keyword(ref key, fraction, offset) => {
-                    context.maybe_zoom_text(key.to_computed_value(context).scale_by(fraction) + offset)
+                    let key_len = key.to_computed_value(context).scale_by(fraction) + offset;
+                    context.maybe_zoom_text(key_len.0).into()
                 }
                 SpecifiedValue::Smaller => {
                     FontRelativeLength::Em(1. / LARGER_FONT_SIZE_RATIO)
                         .to_computed_value(context, base_size).into()
                 }
                 SpecifiedValue::Larger => {
                     FontRelativeLength::Em(LARGER_FONT_SIZE_RATIO)
                         .to_computed_value(context, base_size).into()
@@ -898,17 +899,17 @@ macro_rules! impl_gecko_keyword_conversi
                 }
             }
         }
     }
 
     #[inline]
     #[allow(missing_docs)]
     pub fn get_initial_value() -> computed_value::T {
-        NonNegativeAu::from_px(FONT_MEDIUM_PX)
+        NonNegativeLength::new(FONT_MEDIUM_PX as f32)
     }
 
     #[inline]
     pub fn get_initial_specified_value() -> SpecifiedValue {
         SpecifiedValue::Keyword(Medium, 1., Au(0).into())
     }
 
 
@@ -965,29 +966,29 @@ macro_rules! impl_gecko_keyword_conversi
                 None
             }
         }
     }
 
     #[allow(unused_mut)]
     pub fn cascade_specified_font_size(context: &mut Context,
                                        specified_value: &SpecifiedValue,
-                                       mut computed: NonNegativeAu) {
+                                       mut computed: NonNegativeLength) {
         if let SpecifiedValue::Keyword(kw, fraction, offset) = *specified_value {
             context.builder.font_size_keyword = Some((kw, fraction, offset));
         } else if let Some((ratio, abs)) = specified_value.as_font_ratio(context) {
             // In case a font-size-relative value was applied to a keyword
             // value, we must preserve this fact in case the generic font family
             // changes. relative values (em and %) applied to keywords must be
             // recomputed from the base size for the keyword and the relative size.
             //
             // See bug 1355707
             if let Some((kw, fraction, old_abs)) = *context.builder.inherited_font_computation_data() {
                 context.builder.font_size_keyword =
-                    Some((kw, fraction * ratio, abs + old_abs.0.scale_by(ratio).into()));
+                    Some((kw, fraction * ratio, abs + old_abs.scale_by(ratio)));
             } else {
                 context.builder.font_size_keyword = None;
             }
         } else {
             context.builder.font_size_keyword = None;
         }
 
         // we could use clone_language and clone_font_family() here but that's
@@ -996,47 +997,49 @@ macro_rules! impl_gecko_keyword_conversi
             use gecko_bindings::structs::nsIAtom;
             // if the language or generic changed, we need to recalculate
             // the font size from the stored font-size origin information.
             if context.builder.get_font().gecko().mLanguage.raw::<nsIAtom>() !=
                context.builder.get_parent_font().gecko().mLanguage.raw::<nsIAtom>() ||
                context.builder.get_font().gecko().mGenericID !=
                context.builder.get_parent_font().gecko().mGenericID {
                 if let Some((kw, ratio, offset)) = context.builder.font_size_keyword {
-                    computed = context.maybe_zoom_text(kw.to_computed_value(context).scale_by(ratio) + offset);
+                    let len = kw.to_computed_value(context).scale_by(ratio) + offset;
+                    computed = context.maybe_zoom_text(len.0).into();
                 }
             }
         % endif
 
         let device = context.builder.device;
         let mut font = context.builder.take_font();
         let parent_unconstrained = {
             let parent_font = context.builder.get_parent_font();
             font.apply_font_size(computed, parent_font, device)
         };
         context.builder.put_font(font);
 
         if let Some(parent) = parent_unconstrained {
             let new_unconstrained =
                 specified_value
-                    .to_computed_value_against(context, FontBaseSize::Custom(parent.0));
+                    .to_computed_value_against(context, FontBaseSize::Custom(Au::from(parent)));
             context.builder
                    .mutate_font()
                    .apply_unconstrained_font_size(new_unconstrained);
         }
     }
 
     /// FIXME(emilio): This is very complex. Also, it should move to
     /// StyleBuilder.
     pub fn cascade_inherit_font_size(context: &mut Context) {
         // If inheriting, we must recompute font-size in case of language
         // changes using the font_size_keyword. We also need to do this to
         // handle mathml scriptlevel changes
         let kw_inherited_size = context.builder.font_size_keyword.map(|(kw, ratio, offset)| {
-            context.maybe_zoom_text(SpecifiedValue::Keyword(kw, ratio, offset).to_computed_value(context))
+            let len = SpecifiedValue::Keyword(kw, ratio, offset).to_computed_value(context);
+            context.maybe_zoom_text(len.0).into()
         });
         let parent_kw;
         let device = context.builder.device;
         let mut font = context.builder.take_font();
         let used_kw = {
             let parent_font = context.builder.get_parent_font();
             parent_kw = *context.builder.inherited_font_computation_data();
 
@@ -1053,18 +1056,18 @@ macro_rules! impl_gecko_keyword_conversi
     /// `StyleBuilder`, and should really move inside!
     ///
     /// Can we move the font stuff there?
     pub fn cascade_initial_font_size(context: &mut Context) {
         // font-size's default ("medium") does not always
         // compute to the same value and depends on the font
         let computed = context.maybe_zoom_text(
                             longhands::font_size::get_initial_specified_value()
-                                .to_computed_value(context)
-                        );
+                                .to_computed_value(context).0
+                        ).into();
         context.builder.mutate_font().set_font_size(computed);
         % if product == "gecko":
             let device = context.builder.device;
             context.builder.mutate_font().fixup_font_min_size(device);
         % endif
         context.builder.font_size_keyword = Some((Default::default(), 1., Au(0).into()));
     }
 </%helpers:longhand>
@@ -2346,31 +2349,31 @@ https://drafts.csswg.org/css-fonts-4/#lo
                          animation_value_type="none",
                          need_clone="True",
                          needs_conversion=True)}
 
 <%helpers:longhand name="-moz-script-min-size" products="gecko" animation_value_type="none"
                    predefined_type="Length" gecko_ffi_name="mScriptMinSize"
                    spec="Internal (not web-exposed)"
                    internal="True">
-    use app_units::Au;
     use gecko_bindings::structs::NS_MATHML_DEFAULT_SCRIPT_MIN_SIZE_PT;
-    use values::specified::length::{AU_PER_PT, FontBaseSize, NoCalcLength};
+    use values::computed::Length;
+    use values::specified::length::{AU_PER_PT, AU_PER_PX, FontBaseSize, NoCalcLength};
 
     #[derive(Clone, Debug, PartialEq, ToCss)]
     pub struct SpecifiedValue(pub NoCalcLength);
 
     pub mod computed_value {
-        pub type T = super::Au;
+        pub type T = ::values::computed::Length;
     }
 
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
-        fn to_computed_value(&self, cx: &Context) -> Au {
+        fn to_computed_value(&self, cx: &Context) -> Length {
             // this value is used in the computation of font-size, so
             // we use the parent size
             let base_size = FontBaseSize::InheritedStyle;
             match self.0 {
                 NoCalcLength::FontRelative(value) => {
                     value.to_computed_value(cx, base_size)
                 }
                 NoCalcLength::ServoCharacterWidth(value) => {
@@ -2383,17 +2386,17 @@ https://drafts.csswg.org/css-fonts-4/#lo
         }
         fn from_computed_value(other: &computed_value::T) -> Self {
             SpecifiedValue(ToComputedValue::from_computed_value(other))
         }
     }
 
     #[inline]
     pub fn get_initial_value() -> computed_value::T {
-        Au((NS_MATHML_DEFAULT_SCRIPT_MIN_SIZE_PT as f32 * AU_PER_PT) as i32)
+        Length::new(NS_MATHML_DEFAULT_SCRIPT_MIN_SIZE_PT as f32 * (AU_PER_PT / AU_PER_PX))
     }
 
     pub fn parse<'i, 't>(_context: &ParserContext, _input: &mut Parser<'i, 't>)
                          -> Result<SpecifiedValue, ParseError<'i>> {
         debug_assert!(false, "Should be set directly by presentation attributes only.");
         Err(StyleParseError::UnspecifiedError.into())
     }
 </%helpers:longhand>
--- a/servo/components/style/properties/longhand/inherited_svg.mako.rs
+++ b/servo/components/style/properties/longhand/inherited_svg.mako.rs
@@ -60,17 +60,17 @@
     "Default::default()",
     products="gecko",
     animation_value_type="IntermediateSVGPaint",
     boxed=True,
     spec="https://www.w3.org/TR/SVG2/painting.html#SpecifyingStrokePaint")}
 
 ${helpers.predefined_type(
     "stroke-width", "SVGWidth",
-    "::values::computed::NonNegativeAu::from_px(1).into()",
+    "::values::computed::NonNegativeLength::new(1.).into()",
     products="gecko",
     boxed="True",
     animation_value_type="::values::computed::SVGWidth",
     spec="https://www.w3.org/TR/SVG2/painting.html#StrokeWidth")}
 
 ${helpers.single_keyword("stroke-linecap", "butt round square",
                          products="gecko", animation_value_type="discrete",
                          spec="https://www.w3.org/TR/SVG11/painting.html#StrokeLinecapProperty")}
--- a/servo/components/style/properties/longhand/inherited_table.mako.rs
+++ b/servo/components/style/properties/longhand/inherited_table.mako.rs
@@ -22,23 +22,23 @@
 
 <%helpers:longhand name="border-spacing" animation_value_type="BorderSpacing" boxed="True"
                    spec="https://drafts.csswg.org/css-tables/#propdef-border-spacing">
     use values::specified::{AllowQuirks, Length};
     use values::specified::length::NonNegativeLength;
 
     pub mod computed_value {
         use values::animated::{ToAnimatedValue, ToAnimatedZero};
-        use values::computed::NonNegativeAu;
+        use values::computed::NonNegativeLength;
 
         #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
         #[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, PartialEq, ToCss)]
         pub struct T {
-            pub horizontal: NonNegativeAu,
-            pub vertical: NonNegativeAu,
+            pub horizontal: NonNegativeLength,
+            pub vertical: NonNegativeLength,
         }
 
         impl ToAnimatedZero for T {
             #[inline]
             fn to_animated_zero(&self) -> Result<Self, ()> { Err(()) }
         }
 
         impl ToAnimatedValue for T {
@@ -63,20 +63,20 @@
     #[derive(Clone, Debug, PartialEq, ToCss)]
     pub struct SpecifiedValue {
         pub horizontal: NonNegativeLength,
         pub vertical: Option<NonNegativeLength>,
     }
 
     #[inline]
     pub fn get_initial_value() -> computed_value::T {
-        use values::computed::NonNegativeAu;
+        use values::computed::NonNegativeLength as ComputedNonNegativeLength;
         computed_value::T {
-            horizontal: NonNegativeAu::zero(),
-            vertical: NonNegativeAu::zero(),
+            horizontal: ComputedNonNegativeLength::zero(),
+            vertical: ComputedNonNegativeLength::zero(),
         }
     }
 
     impl ToComputedValue for SpecifiedValue {
         type ComputedValue = computed_value::T;
 
         #[inline]
         fn to_computed_value(&self, context: &Context) -> computed_value::T {
--- a/servo/components/style/properties/longhand/inherited_text.mako.rs
+++ b/servo/components/style/properties/longhand/inherited_text.mako.rs
@@ -34,17 +34,17 @@
                          gecko_constant_prefix="NS_STYLE_TEXT_SIZE_ADJUST",
                          gecko_ffi_name="mTextSizeAdjust",
                          products="gecko", animation_value_type="discrete",
                          spec="https://drafts.csswg.org/css-size-adjust/#adjustment-control",
                          alias="-webkit-text-size-adjust")}
 
 ${helpers.predefined_type("text-indent",
                           "LengthOrPercentage",
-                          "computed::LengthOrPercentage::Length(Au(0))",
+                          "computed::LengthOrPercentage::Length(computed::Length::new(0.))",
                           animation_value_type="ComputedValue",
                           spec="https://drafts.csswg.org/css-text/#propdef-text-indent",
                           allow_quirks=True)}
 
 // Also known as "word-wrap" (which is more popular because of IE), but this is the preferred
 // name per CSS-TEXT 6.2.
 ${helpers.single_keyword("overflow-wrap",
                          "normal break-word",
@@ -736,19 +736,19 @@
     animation_value_type="AnimatedColor",
     need_clone=True, ignored_when_colors_disabled=True,
     flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
     spec="https://compat.spec.whatwg.org/#the-webkit-text-stroke-color",
 )}
 
 ${helpers.predefined_type("-webkit-text-stroke-width",
                           "BorderSideWidth",
-                          "::values::computed::NonNegativeAu::from_px(0)",
+                          "::values::computed::NonNegativeLength::new(0.)",
                           initial_specified_value="specified::BorderSideWidth::Length(specified::Length::zero())",
-                          computed_type="::values::computed::NonNegativeAu",
+                          computed_type="::values::computed::NonNegativeLength",
                           products="gecko",
                           flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
                           spec="https://compat.spec.whatwg.org/#the-webkit-text-stroke-width",
                           animation_value_type="discrete")}
 
 // CSS Ruby Layout Module Level 1
 // https://drafts.csswg.org/css-ruby/
 ${helpers.single_keyword("ruby-align", "space-around start center space-between",
--- a/servo/components/style/properties/longhand/margin.mako.rs
+++ b/servo/components/style/properties/longhand/margin.mako.rs
@@ -8,15 +8,15 @@
 
 % for side in ALL_SIDES:
     <%
         spec = "https://drafts.csswg.org/css-box/#propdef-margin-%s" % side[0]
         if side[1]:
             spec = "https://drafts.csswg.org/css-logical-props/#propdef-margin-%s" % side[1]
     %>
     ${helpers.predefined_type("margin-%s" % side[0], "LengthOrPercentageOrAuto",
-                              "computed::LengthOrPercentageOrAuto::Length(Au(0))",
+                              "computed::LengthOrPercentageOrAuto::Length(computed::Length::new(0.))",
                               alias=maybe_moz_logical_alias(product, side, "-moz-margin-%s"),
                               allow_quirks=not side[1],
                               animation_value_type="ComputedValue", logical = side[1], spec = spec,
                               flags="APPLIES_TO_FIRST_LETTER",
                               allowed_in_page_rule=True)}
 % endfor
--- a/servo/components/style/properties/longhand/outline.mako.rs
+++ b/servo/components/style/properties/longhand/outline.mako.rs
@@ -64,27 +64,27 @@
                     Ok(result)
                 }
             })
     }
 </%helpers:longhand>
 
 ${helpers.predefined_type("outline-width",
                           "BorderSideWidth",
-                          "::values::computed::NonNegativeAu::from_px(3)",
+                          "::values::computed::NonNegativeLength::new(3.)",
                           initial_specified_value="specified::BorderSideWidth::Medium",
-                          computed_type="::values::computed::NonNegativeAu",
-                          animation_value_type="NonNegativeAu",
+                          computed_type="::values::computed::NonNegativeLength",
+                          animation_value_type="NonNegativeLength",
                           spec="https://drafts.csswg.org/css-ui/#propdef-outline-width")}
 
 // The -moz-outline-radius-* properties are non-standard and not on a standards track.
 % for corner in ["topleft", "topright", "bottomright", "bottomleft"]:
     ${helpers.predefined_type("-moz-outline-radius-" + corner, "BorderCornerRadius",
         "computed::LengthOrPercentage::zero().into()",
         products="gecko",
         boxed=True,
         animation_value_type="BorderCornerRadius",
         spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-outline-radius)")}
 % endfor
 
-${helpers.predefined_type("outline-offset", "Length", "Au(0)", products="servo gecko",
-                          animation_value_type="ComputedValue",
+${helpers.predefined_type("outline-offset", "Length", "::values::computed::Length::new(0.)",
+                          products="servo gecko", animation_value_type="ComputedValue",
                           spec="https://drafts.csswg.org/css-ui/#propdef-outline-offset")}
--- a/servo/components/style/properties/longhand/position.mako.rs
+++ b/servo/components/style/properties/longhand/position.mako.rs
@@ -204,17 +204,17 @@ macro_rules! impl_align_conversions {
                                   "LengthOrPercentageOrAuto",
                                   "computed::LengthOrPercentageOrAuto::Auto",
                                   "parse_non_negative",
                                   spec=spec % size,
                                   allow_quirks=not logical,
                                   animation_value_type="ComputedValue", logical = logical)}
         ${helpers.predefined_type("min-%s" % size,
                                   "LengthOrPercentage",
-                                  "computed::LengthOrPercentage::Length(Au(0))",
+                                  "computed::LengthOrPercentage::Length(computed::Length::new(0.))",
                                   "parse_non_negative",
                                   spec=spec % ("min-%s" % size),
                                   animation_value_type="ComputedValue",
                                   logical=logical,
                                   allow_quirks=not logical)}
         ${helpers.predefined_type("max-%s" % size,
                                   "LengthOrPercentageOrNone",
                                   "computed::LengthOrPercentageOrNone::None",
--- a/servo/components/style/properties/properties.mako.rs
+++ b/servo/components/style/properties/properties.mako.rs
@@ -39,17 +39,17 @@ use selectors::parser::SelectorParseErro
 #[cfg(feature = "servo")] use servo_config::prefs::PREFS;
 use shared_lock::StylesheetGuards;
 use style_traits::{PARSING_MODE_DEFAULT, ToCss, ParseError};
 use style_traits::{PropertyDeclarationParseError, StyleParseError, ValueParseError};
 use stylesheets::{CssRuleType, Origin, UrlExtraData};
 #[cfg(feature = "servo")] use values::Either;
 use values::generics::text::LineHeight;
 use values::computed;
-use values::computed::NonNegativeAu;
+use values::computed::NonNegativeLength;
 use rule_tree::{CascadeLevel, StrongRuleNode};
 use self::computed_value_flags::ComputedValueFlags;
 use style_adjuster::StyleAdjuster;
 #[cfg(feature = "servo")] use values::specified::BorderStyle;
 
 pub use self::declaration_block::*;
 
 #[cfg(feature = "gecko")]
@@ -105,17 +105,17 @@ pub trait MaybeBoxed<Out> {
 /// from a keyword value or a keyword value on some ancestor with only
 /// font-size-relative keywords and regular inheritance in between. The
 /// integer stores the final ratio of the chain of font size relative values.
 /// and is 1 when there was just a keyword and no relative values.
 ///
 /// When this is Some, we compute font sizes by computing the keyword against
 /// the generic font, and then multiplying it by the ratio (as well as adding any
 /// absolute offset from calcs)
-pub type FontComputationData = Option<(longhands::font_size::KeywordSize, f32, NonNegativeAu)>;
+pub type FontComputationData = Option<(longhands::font_size::KeywordSize, f32, NonNegativeLength)>;
 
 /// Default value for FontComputationData
 pub fn default_font_size_keyword() -> FontComputationData {
     Some((Default::default(), 1., Au(0).into()))
 }
 
 impl<T> MaybeBoxed<T> for T {
     #[inline]
@@ -1685,17 +1685,17 @@ pub use gecko_properties::style_structs;
 /// The module where all the style structs are defined.
 #[cfg(feature = "servo")]
 pub mod style_structs {
     use fnv::FnvHasher;
     use super::longhands;
     use std::hash::{Hash, Hasher};
     use logical_geometry::WritingMode;
     use media_queries::Device;
-    use values::computed::NonNegativeAu;
+    use values::computed::NonNegativeLength;
 
     % for style_struct in data.active_style_structs():
         % if style_struct.name == "Font":
         #[derive(Clone, Debug)]
         % else:
         #[derive(Clone, Debug, PartialEq)]
         % endif
         #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@@ -1785,17 +1785,17 @@ pub mod style_structs {
                     }
                 % endif
             % endfor
             % if style_struct.name == "Border":
                 % for side in ["top", "right", "bottom", "left"]:
                     /// Whether the border-${side} property has nonzero width.
                     #[allow(non_snake_case)]
                     pub fn border_${side}_has_nonzero_width(&self) -> bool {
-                        self.border_${side}_width != NonNegativeAu::zero()
+                        self.border_${side}_width != NonNegativeLength::zero()
                     }
                 % endfor
             % elif style_struct.name == "Font":
                 /// Computes a font hash in order to be able to cache fonts
                 /// effectively in GFX and layout.
                 pub fn compute_font_hash(&mut self) {
                     // Corresponds to the fields in
                     // `gfx::font_template::FontTemplateDescriptor`.
@@ -1803,38 +1803,38 @@ pub mod style_structs {
                     hasher.write_u16(self.font_weight.0);
                     self.font_stretch.hash(&mut hasher);
                     self.font_family.hash(&mut hasher);
                     self.hash = hasher.finish()
                 }
 
                 /// (Servo does not handle MathML, so this just calls copy_font_size_from)
                 pub fn inherit_font_size_from(&mut self, parent: &Self,
-                                              _: Option<NonNegativeAu>,
+                                              _: Option<NonNegativeLength>,
                                               _: &Device) -> bool {
                     self.copy_font_size_from(parent);
                     false
                 }
                 /// (Servo does not handle MathML, so this just calls set_font_size)
                 pub fn apply_font_size(&mut self,
                                        v: longhands::font_size::computed_value::T,
                                        _: &Self,
-                                       _: &Device) -> Option<NonNegativeAu> {
+                                       _: &Device) -> Option<NonNegativeLength> {
                     self.set_font_size(v);
                     None
                 }
                 /// (Servo does not handle MathML, so this does nothing)
-                pub fn apply_unconstrained_font_size(&mut self, _: NonNegativeAu) {
+                pub fn apply_unconstrained_font_size(&mut self, _: NonNegativeLength) {
                 }
 
             % elif style_struct.name == "Outline":
                 /// Whether the outline-width property is non-zero.
                 #[inline]
                 pub fn outline_has_nonzero_width(&self) -> bool {
-                    self.outline_width != NonNegativeAu::zero()
+                    self.outline_width != NonNegativeLength::zero()
                 }
             % elif style_struct.name == "Text":
                 /// Whether the text decoration has an underline.
                 #[inline]
                 pub fn has_underline(&self) -> bool {
                     self.text_decoration_line.contains(longhands::text_decoration_line::UNDERLINE)
                 }
 
@@ -2236,20 +2236,20 @@ impl ComputedValuesInner {
         ))
     }
 
     /// Get the logical border width
     #[inline]
     pub fn border_width_for_writing_mode(&self, writing_mode: WritingMode) -> LogicalMargin<Au> {
         let border_style = self.get_border();
         LogicalMargin::from_physical(writing_mode, SideOffsets2D::new(
-            border_style.border_top_width.0,
-            border_style.border_right_width.0,
-            border_style.border_bottom_width.0,
-            border_style.border_left_width.0,
+            Au::from(border_style.border_top_width),
+            Au::from(border_style.border_right_width),
+            Au::from(border_style.border_bottom_width),
+            Au::from(border_style.border_left_width),
         ))
     }
 
     /// Gets the logical computed border widths for this style.
     #[inline]
     pub fn logical_border_width(&self) -> LogicalMargin<Au> {
         self.border_width_for_writing_mode(self.writing_mode)
     }
@@ -2321,17 +2321,17 @@ impl ComputedValuesInner {
                            m.m13 != 0.0 || m.m23 != 0.0 ||
                            m.m43 != 0.0 || m.m14 != 0.0 ||
                            m.m24 != 0.0 || m.m34 != 0.0 ||
                            m.m33 != 1.0 || m.m44 != 1.0 {
                             return true;
                         }
                     }
                     computed_values::transform::ComputedOperation::Translate(_, _, z) => {
-                        if z != Au(0) {
+                        if z.px() != 0. {
                             return true;
                         }
                     }
                     _ => {}
                 }
             }
         }
 
@@ -3402,17 +3402,17 @@ where
 }
 
 /// See StyleAdjuster::adjust_for_border_width.
 pub fn adjust_border_width(style: &mut StyleBuilder) {
     % for side in ["top", "right", "bottom", "left"]:
         // Like calling to_computed_value, which wouldn't type check.
         if style.get_border().clone_border_${side}_style().none_or_hidden() &&
            style.get_border().border_${side}_has_nonzero_width() {
-            style.set_border_${side}_width(NonNegativeAu::zero());
+            style.set_border_${side}_width(NonNegativeLength::zero());
         }
     % endfor
 }
 
 /// Adjusts borders as appropriate to account for a fragment's status as the
 /// first or last fragment within the range of an element.
 ///
 /// Specifically, this function sets border widths to zero on the sides for
@@ -3426,37 +3426,37 @@ pub fn modify_border_style_for_inline_si
         {
             let border = &style.border;
             let current_style = match side {
                 PhysicalSide::Left =>   (border.border_left_width,   border.border_left_style),
                 PhysicalSide::Right =>  (border.border_right_width,  border.border_right_style),
                 PhysicalSide::Top =>    (border.border_top_width,    border.border_top_style),
                 PhysicalSide::Bottom => (border.border_bottom_width, border.border_bottom_style),
             };
-            if current_style == (NonNegativeAu::zero(), BorderStyle::none) {
+            if current_style == (NonNegativeLength::zero(), BorderStyle::none) {
                 return;
             }
         }
         let style = Arc::make_mut(style);
         let border = Arc::make_mut(&mut style.border);
         match side {
             PhysicalSide::Left => {
-                border.border_left_width = NonNegativeAu::zero();
+                border.border_left_width = NonNegativeLength::zero();
                 border.border_left_style = BorderStyle::none;
             }
             PhysicalSide::Right => {
-                border.border_right_width = NonNegativeAu::zero();
+                border.border_right_width = NonNegativeLength::zero();
                 border.border_right_style = BorderStyle::none;
             }
             PhysicalSide::Bottom => {
-                border.border_bottom_width = NonNegativeAu::zero();
+                border.border_bottom_width = NonNegativeLength::zero();
                 border.border_bottom_style = BorderStyle::none;
             }
             PhysicalSide::Top => {
-                border.border_top_width = NonNegativeAu::zero();
+                border.border_top_width = NonNegativeLength::zero();
                 border.border_top_style = BorderStyle::none;
             }
         }
     }
 
     if !is_first_fragment_of_element {
         let side = style.writing_mode.inline_start_physical_side();
         modify_side(style, side)
--- a/servo/components/style/servo/media_queries.rs
+++ b/servo/components/style/servo/media_queries.rs
@@ -60,17 +60,17 @@ impl Device {
         viewport_size: TypedSize2D<f32, CSSPixel>,
         device_pixel_ratio: ScaleFactor<f32, CSSPixel, DevicePixel>
     ) -> Device {
         Device {
             media_type,
             viewport_size,
             device_pixel_ratio,
             // FIXME(bz): Seems dubious?
-            root_font_size: AtomicIsize::new(font_size::get_initial_value().value() as isize),
+            root_font_size: AtomicIsize::new(font_size::get_initial_value().0.to_i32_au() as isize),
             used_root_font_size: AtomicBool::new(false),
             used_viewport_units: AtomicBool::new(false),
         }
     }
 
     /// Return the default computed values for this device.
     pub fn default_computed_values(&self) -> &ComputedValues {
         // FIXME(bz): This isn't really right, but it's no more wrong
@@ -255,14 +255,14 @@ impl Range<specified::Length> {
             font_metrics_provider: &ServoMetricsProvider,
             in_media_query: true,
             cached_system_font: None,
             quirks_mode: quirks_mode,
             for_smil_animation: false,
         };
 
         match *self {
-            Range::Min(ref width) => Range::Min(width.to_computed_value(&context)),
-            Range::Max(ref width) => Range::Max(width.to_computed_value(&context)),
-            Range::Eq(ref width) => Range::Eq(width.to_computed_value(&context))
+            Range::Min(ref width) => Range::Min(Au::from(width.to_computed_value(&context))),
+            Range::Max(ref width) => Range::Max(Au::from(width.to_computed_value(&context))),
+            Range::Eq(ref width) => Range::Eq(Au::from(width.to_computed_value(&context)))
         }
     }
 }
--- a/servo/components/style/stylesheets/viewport_rule.rs
+++ b/servo/components/style/stylesheets/viewport_rule.rs
@@ -730,17 +730,17 @@ impl MaybeNew for ViewportConstraints {
         }
 
         macro_rules! to_pixel_length {
             ($value:ident, $dimension:ident, $extend_to:ident => $auto_extend_to:expr) => {
                 if let Some($value) = $value {
                     match *$value {
                         ViewportLength::Specified(ref length) => match *length {
                             LengthOrPercentageOrAuto::Length(ref value) =>
-                                Some(value.to_computed_value(&context)),
+                                Some(Au::from(value.to_computed_value(&context))),
                             LengthOrPercentageOrAuto::Percentage(value) =>
                                 Some(initial_viewport.$dimension.scale_by(value.0)),
                             LengthOrPercentageOrAuto::Auto => None,
                             LengthOrPercentageOrAuto::Calc(ref calc) => {
                                 calc.to_computed_value(&context).to_used_value(Some(initial_viewport.$dimension))
                             }
                         },
                         ViewportLength::ExtendToZoom => {
--- a/servo/components/style/values/animated/mod.rs
+++ b/servo/components/style/values/animated/mod.rs
@@ -14,17 +14,17 @@ use smallvec::SmallVec;
 use std::cmp::max;
 use values::computed::Angle as ComputedAngle;
 use values::computed::BorderCornerRadius as ComputedBorderCornerRadius;
 #[cfg(feature = "servo")]
 use values::computed::ComputedUrl;
 use values::computed::GreaterThanOrEqualToOneNumber as ComputedGreaterThanOrEqualToOneNumber;
 use values::computed::MaxLength as ComputedMaxLength;
 use values::computed::MozLength as ComputedMozLength;
-use values::computed::NonNegativeAu;
+use values::computed::NonNegativeLength as ComputedNonNegativeLength;
 use values::computed::NonNegativeLengthOrPercentage as ComputedNonNegativeLengthOrPercentage;
 use values::computed::NonNegativeNumber as ComputedNonNegativeNumber;
 use values::computed::PositiveInteger as ComputedPositiveInteger;
 use values::specified::url::SpecifiedUrl;
 
 pub mod color;
 pub mod effects;
 
@@ -291,27 +291,27 @@ impl ToAnimatedValue for ComputedGreater
     }
 
     #[inline]
     fn from_animated_value(animated: Self::AnimatedValue) -> Self {
         animated.0.max(1.).into()
     }
 }
 
-impl ToAnimatedValue for NonNegativeAu {
+impl ToAnimatedValue for ComputedNonNegativeLength {
     type AnimatedValue = Self;
 
     #[inline]
     fn to_animated_value(self) -> Self {
         self
     }
 
     #[inline]
     fn from_animated_value(animated: Self::AnimatedValue) -> Self {
-        max(animated.0, Au(0)).into()
+        ComputedNonNegativeLength::new(animated.px().max(0.))
     }
 }
 
 impl ToAnimatedValue for ComputedPositiveInteger {
     type AnimatedValue = Self;
 
     #[inline]
     fn to_animated_value(self) -> Self {
@@ -358,22 +358,22 @@ impl ToAnimatedValue for ComputedMaxLeng
 
     #[inline]
     fn to_animated_value(self) -> Self {
         self
     }
 
     #[inline]
     fn from_animated_value(animated: Self::AnimatedValue) -> Self {
-        use values::computed::{LengthOrPercentageOrNone, Percentage};
+        use values::computed::{Length, LengthOrPercentageOrNone, Percentage};
         match animated {
             ComputedMaxLength::LengthOrPercentageOrNone(lopn) => {
                 let result = match lopn {
-                    LengthOrPercentageOrNone::Length(au) => {
-                        LengthOrPercentageOrNone::Length(max(au, Au(0)))
+                    LengthOrPercentageOrNone::Length(px) => {
+                        LengthOrPercentageOrNone::Length(Length::new(px.px().max(0.)))
                     },
                     LengthOrPercentageOrNone::Percentage(percentage) => {
                         LengthOrPercentageOrNone::Percentage(Percentage(percentage.0.max(0.)))
                     }
                     _ => lopn
                 };
                 ComputedMaxLength::LengthOrPercentageOrNone(result)
             },
@@ -387,22 +387,22 @@ impl ToAnimatedValue for ComputedMozLeng
 
     #[inline]
     fn to_animated_value(self) -> Self {
         self
     }
 
     #[inline]
     fn from_animated_value(animated: Self::AnimatedValue) -> Self {
-        use values::computed::{LengthOrPercentageOrAuto, Percentage};
+        use values::computed::{Length, LengthOrPercentageOrAuto, Percentage};
         match animated {
             ComputedMozLength::LengthOrPercentageOrAuto(lopa) => {
                 let result = match lopa {
-                    LengthOrPercentageOrAuto::Length(au) => {
-                        LengthOrPercentageOrAuto::Length(max(au, Au(0)))
+                    LengthOrPercentageOrAuto::Length(px) => {
+                        LengthOrPercentageOrAuto::Length(Length::new(px.px().max(0.)))
                     },
                     LengthOrPercentageOrAuto::Percentage(percentage) => {
                         LengthOrPercentageOrAuto::Percentage(Percentage(percentage.0.max(0.)))
                     }
                     _ => lopa
                 };
                 ComputedMozLength::LengthOrPercentageOrAuto(result)
             },
--- a/servo/components/style/values/computed/background.rs
+++ b/servo/components/style/values/computed/background.rs
@@ -25,22 +25,21 @@ impl ToAnimatedValue for BackgroundSize 
 
     #[inline]
     fn to_animated_value(self) -> Self {
         self
     }
 
     #[inline]
     fn from_animated_value(animated: Self::AnimatedValue) -> Self {
-        use app_units::Au;
-        use values::computed::Percentage;
+        use values::computed::{Length, Percentage};
         let clamp_animated_value = |value: LengthOrPercentageOrAuto| -> LengthOrPercentageOrAuto {
             match value {
                 LengthOrPercentageOrAuto::Length(len) => {
-                    LengthOrPercentageOrAuto::Length(Au(::std::cmp::max(len.0, 0)))
+                    LengthOrPercentageOrAuto::Length(Length::new(len.px().max(0.)))
                 },
                 LengthOrPercentageOrAuto::Percentage(percent) => {
                     LengthOrPercentageOrAuto::Percentage(Percentage(percent.0.max(0.)))
                 },
                 _ => value
             }
         };
         match animated {
--- a/servo/components/style/values/computed/length.rs
+++ b/servo/components/style/values/computed/length.rs
@@ -1,178 +1,185 @@
 /* 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/. */
 
 //! `<length>` computed values, and related ones.
 
-use app_units::{Au, AU_PER_PX};
+use app_units::Au;
 use ordered_float::NotNaN;
 use std::fmt;
+use std::ops::{Add, Neg};
 use style_traits::ToCss;
-use style_traits::values::specified::AllowedLengthType;
+use style_traits::values::specified::AllowedNumericType;
 use super::{Number, ToComputedValue, Context, Percentage};
 use values::{Auto, CSSFloat, Either, ExtremumLength, None_, Normal, specified};
 use values::animated::{Animate, Procedure, ToAnimatedZero};
-use values::computed::{NonNegativeAu, NonNegativeNumber};
+use values::computed::NonNegativeNumber;
 use values::distance::{ComputeSquaredDistance, SquaredDistance};
 use values::generics::NonNegative;
 use values::specified::length::{AbsoluteLength, FontBaseSize, FontRelativeLength};
 use values::specified::length::ViewportPercentageLength;
 
 pub use super::image::Image;
 pub use values::specified::{Angle, BorderStyle, Time, UrlOrNone};
 
 impl ToComputedValue for specified::NoCalcLength {
-    type ComputedValue = Au;
+    type ComputedValue = CSSPixelLength;
 
     #[inline]
-    fn to_computed_value(&self, context: &Context) -> Au {
+    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),
             specified::NoCalcLength::ViewportPercentage(length) =>
                 length.to_computed_value(context.viewport_size_for_viewport_unit_resolution()),
             specified::NoCalcLength::ServoCharacterWidth(length) =>
-                length.to_computed_value(context.style().get_font().clone_font_size().0),
+                length.to_computed_value(Au::from(context.style().get_font().clone_font_size())),
             #[cfg(feature = "gecko")]
             specified::NoCalcLength::Physical(length) =>
                 length.to_computed_value(context),
         }
     }
 
     #[inline]
-    fn from_computed_value(computed: &Au) -> Self {
-        specified::NoCalcLength::Absolute(AbsoluteLength::Px(computed.to_f32_px()))
+    fn from_computed_value(computed: &Self::ComputedValue) -> Self {
+        specified::NoCalcLength::Absolute(AbsoluteLength::Px(computed.px()))
     }
 }
 
 impl ToComputedValue for specified::Length {
-    type ComputedValue = Au;
+    type ComputedValue = CSSPixelLength;
 
     #[inline]
-    fn to_computed_value(&self, context: &Context) -> Au {
+    fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
         match *self {
             specified::Length::NoCalc(l) => l.to_computed_value(context),
             specified::Length::Calc(ref calc) => calc.to_computed_value(context).length(),
         }
     }
 
     #[inline]
-    fn from_computed_value(computed: &Au) -> Self {
+    fn from_computed_value(computed: &Self::ComputedValue) -> Self {
         specified::Length::NoCalc(specified::NoCalcLength::from_computed_value(computed))
     }
 }
 
 #[allow(missing_docs)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 #[derive(Clone, Copy, Debug, PartialEq, ToAnimatedZero)]
 pub struct CalcLengthOrPercentage {
     #[animation(constant)]
-    pub clamping_mode: AllowedLengthType,
-    length: Au,
+    pub clamping_mode: AllowedNumericType,
+    length: Length,
     pub percentage: Option<Percentage>,
 }
 
 impl ComputeSquaredDistance for CalcLengthOrPercentage {
     #[inline]
     fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
         // FIXME(nox): This looks incorrect to me, to add a distance between lengths
         // with a distance between percentages.
         Ok(
-            self.unclamped_length().to_f64_px().compute_squared_distance(
-                &other.unclamped_length().to_f64_px())? +
+            self.unclamped_length().compute_squared_distance(&other.unclamped_length())? +
             self.percentage().compute_squared_distance(&other.percentage())?,
         )
     }
 }
 
 impl CalcLengthOrPercentage {
     /// Returns a new `CalcLengthOrPercentage`.
     #[inline]
-    pub fn new(length: Au, percentage: Option<Percentage>) -> Self {
-        Self::with_clamping_mode(length, percentage, AllowedLengthType::All)
+    pub fn new(length: Length, percentage: Option<Percentage>) -> Self {
+        Self::with_clamping_mode(length, percentage, AllowedNumericType::All)
     }
 
     /// Returns a new `CalcLengthOrPercentage` with a specific clamping mode.
     #[inline]
-    pub fn with_clamping_mode(length: Au,
+    pub fn with_clamping_mode(length: Length,
                               percentage: Option<Percentage>,
-                              clamping_mode: AllowedLengthType)
+                              clamping_mode: AllowedNumericType)
                               -> Self {
         Self {
             clamping_mode: clamping_mode,
             length: length,
             percentage: percentage,
         }
     }
 
     /// Returns this `calc()` as a `<length>`.
     ///
     /// Panics in debug mode if a percentage is present in the expression.
     #[inline]
-    pub fn length(&self) -> Au {
+    pub fn length(&self) -> CSSPixelLength {
         debug_assert!(self.percentage.is_none());
         self.length_component()
     }
 
     /// Returns the length component of this `calc()`
     #[inline]
-    pub fn length_component(&self) -> Au {
-        self.clamping_mode.clamp(self.length)
+    pub fn length_component(&self) -> CSSPixelLength {
+        CSSPixelLength::new(self.clamping_mode.clamp(self.length.px()))
     }
 
     /// Returns the `<length>` component of this `calc()`, unclamped.
     #[inline]
-    pub fn unclamped_length(&self) -> Au {
+    pub fn unclamped_length(&self) -> CSSPixelLength {
         self.length
     }
 
+    /// Return the percentage value as CSSFloat.
     #[inline]
-    #[allow(missing_docs)]
     pub fn percentage(&self) -> CSSFloat {
         self.percentage.map_or(0., |p| p.0)
     }
 
+    /// Convert the computed value into used value.
+    #[inline]
+    pub fn to_used_value(&self, container_len: Option<Au>) -> Option<Au> {
+        self.to_pixel_length(container_len).map(Au::from)
+    }
+
     /// If there are special rules for computing percentages in a value (e.g. the height property),
     /// they apply whenever a calc() expression contains percentages.
-    pub fn to_used_value(&self, container_len: Option<Au>) -> Option<Au> {
+    pub fn to_pixel_length(&self, container_len: Option<Au>) -> Option<Length> {
         match (container_len, self.percentage) {
             (Some(len), Some(percent)) => {
-                Some(self.clamping_mode.clamp(self.length + len.scale_by(percent.0)))
+                let pixel = self.length.px() + len.scale_by(percent.0).to_f32_px();
+                Some(Length::new(self.clamping_mode.clamp(pixel)))
             },
             (_, None) => Some(self.length()),
             _ => None,
         }
     }
 }
 
 impl From<LengthOrPercentage> for CalcLengthOrPercentage {
     fn from(len: LengthOrPercentage) -> CalcLengthOrPercentage {
         match len {
             LengthOrPercentage::Percentage(this) => {
-                CalcLengthOrPercentage::new(Au(0), Some(this))
+                CalcLengthOrPercentage::new(Length::new(0.), Some(this))
             }
             LengthOrPercentage::Length(this) => {
                 CalcLengthOrPercentage::new(this, None)
             }
             LengthOrPercentage::Calc(this) => {
                 this
             }
         }
     }
 }
 
 impl From<LengthOrPercentageOrAuto> for Option<CalcLengthOrPercentage> {
     fn from(len: LengthOrPercentageOrAuto) -> Option<CalcLengthOrPercentage> {
         match len {
             LengthOrPercentageOrAuto::Percentage(this) => {
-                Some(CalcLengthOrPercentage::new(Au(0), Some(this)))
+                Some(CalcLengthOrPercentage::new(Length::new(0.), Some(this)))
             }
             LengthOrPercentageOrAuto::Length(this) => {
                 Some(CalcLengthOrPercentage::new(this, None))
             }
             LengthOrPercentageOrAuto::Calc(this) => {
                 Some(this)
             }
             LengthOrPercentageOrAuto::Auto => {
@@ -181,17 +188,17 @@ impl From<LengthOrPercentageOrAuto> for 
         }
     }
 }
 
 impl From<LengthOrPercentageOrNone> for Option<CalcLengthOrPercentage> {
     fn from(len: LengthOrPercentageOrNone) -> Option<CalcLengthOrPercentage> {
         match len {
             LengthOrPercentageOrNone::Percentage(this) => {
-                Some(CalcLengthOrPercentage::new(Au(0), Some(this)))
+                Some(CalcLengthOrPercentage::new(Length::new(0.), Some(this)))
             }
             LengthOrPercentageOrNone::Length(this) => {
                 Some(CalcLengthOrPercentage::new(this, None))
             }
             LengthOrPercentageOrNone::Calc(this) => {
                 Some(this)
             }
             LengthOrPercentageOrNone::None => {
@@ -202,69 +209,71 @@ impl From<LengthOrPercentageOrNone> for 
 }
 
 impl ToCss for CalcLengthOrPercentage {
     fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
         use num_traits::Zero;
 
         let (length, percentage) = match (self.length, self.percentage) {
             (l, None) => return l.to_css(dest),
-            (l, Some(p)) if l == Au(0) => return p.to_css(dest),
+            (l, Some(p)) if l.px() == 0. => return p.to_css(dest),
             (l, Some(p)) => (l, p),
         };
 
         dest.write_str("calc(")?;
         percentage.to_css(dest)?;
 
-        dest.write_str(if length < Zero::zero() { " - " } else { " + " })?;
+        dest.write_str(if length.px() < Zero::zero() { " - " } else { " + " })?;
         length.abs().to_css(dest)?;
 
         dest.write_str(")")
     }
 }
 
 impl specified::CalcLengthOrPercentage {
     /// Compute the value, zooming any absolute units by the zoom function.
     fn to_computed_value_with_zoom<F>(&self, context: &Context, zoom_fn: F,
                                       base_size: FontBaseSize) -> CalcLengthOrPercentage
-        where F: Fn(Au) -> Au {
-        let mut length = Au(0);
+        where F: Fn(Length) -> Length {
+        use std::f32;
+        let mut length = 0.;
 
         if let Some(absolute) = self.absolute {
-            length += zoom_fn(absolute.to_computed_value(context));
+            length += zoom_fn(absolute.to_computed_value(context)).px();
         }
 
         for val in &[self.vw.map(ViewportPercentageLength::Vw),
                      self.vh.map(ViewportPercentageLength::Vh),
                      self.vmin.map(ViewportPercentageLength::Vmin),
                      self.vmax.map(ViewportPercentageLength::Vmax)] {
             if let Some(val) = *val {
-                length += val.to_computed_value(context.viewport_size_for_viewport_unit_resolution());
+                let viewport_size = context.viewport_size_for_viewport_unit_resolution();
+                length += val.to_computed_value(viewport_size).px();
             }
         }
 
         for val in &[self.ch.map(FontRelativeLength::Ch),
                      self.em.map(FontRelativeLength::Em),
                      self.ex.map(FontRelativeLength::Ex),
                      self.rem.map(FontRelativeLength::Rem)] {
             if let Some(val) = *val {
-                length += val.to_computed_value(context, base_size);
+                length += val.to_computed_value(context, base_size).px();
             }
         }
 
         CalcLengthOrPercentage {
             clamping_mode: self.clamping_mode,
-            length: length,
+            length: Length::new(length.min(f32::MAX).max(f32::MIN)),
             percentage: self.percentage,
         }
     }
 
     /// Compute font-size or line-height taking into account text-zoom if necessary.
     pub fn to_computed_value_zoomed(&self, context: &Context, base_size: FontBaseSize) -> CalcLengthOrPercentage {
-        self.to_computed_value_with_zoom(context, |abs| context.maybe_zoom_text(abs.into()).0, base_size)
+        self.to_computed_value_with_zoom(context, |abs| context.maybe_zoom_text(abs), base_size)
     }
 }
 
 impl ToComputedValue for specified::CalcLengthOrPercentage {
     type ComputedValue = CalcLengthOrPercentage;
 
     fn to_computed_value(&self, context: &Context) -> CalcLengthOrPercentage {
         // normal properties don't zoom, and compute em units against the current style's font-size
@@ -285,17 +294,17 @@ impl ToComputedValue for specified::Calc
 #[allow(missing_docs)]
 #[animate(fallback = "Self::animate_fallback")]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 #[css(derive_debug)]
 #[derive(Animate, Clone, ComputeSquaredDistance, Copy, PartialEq)]
 #[derive(ToAnimatedZero, ToCss)]
 #[distance(fallback = "Self::compute_squared_distance_fallback")]
 pub enum LengthOrPercentage {
-    Length(Au),
+    Length(Length),
     Percentage(Percentage),
     Calc(CalcLengthOrPercentage),
 }
 
 impl LengthOrPercentage {
     /// https://drafts.csswg.org/css-transitions/#animtype-lpcalc
     fn animate_fallback(
         &self,
@@ -325,73 +334,80 @@ impl LengthOrPercentage {
             &(*other).into(),
         )
     }
 }
 
 impl From<Au> for LengthOrPercentage {
     #[inline]
     fn from(length: Au) -> Self {
-        LengthOrPercentage::Length(length)
+        LengthOrPercentage::Length(length.into())
     }
 }
 
 impl LengthOrPercentage {
     #[inline]
     #[allow(missing_docs)]
     pub fn zero() -> LengthOrPercentage {
-        LengthOrPercentage::Length(Au(0))
+        LengthOrPercentage::Length(Length::new(0.))
     }
 
     #[inline]
     /// 1px length value for SVG defaults
     pub fn one() -> LengthOrPercentage {
-        LengthOrPercentage::Length(Au(AU_PER_PX))
+        LengthOrPercentage::Length(Length::new(1.))
     }
 
     /// Returns true if the computed value is absolute 0 or 0%.
     ///
     /// (Returns false for calc() values, even if ones that may resolve to zero.)
     #[inline]
     pub fn is_definitely_zero(&self) -> bool {
         use self::LengthOrPercentage::*;
         match *self {
-            Length(Au(0)) => true,
+            Length(l) => l.px() == 0.0,
             Percentage(p) => p.0 == 0.0,
-            Length(_) | Calc(_) => false
+            Calc(_) => false
         }
     }
 
+    // CSSFloat doesn't implement Hash, so does CSSPixelLength. Therefore, we still use Au as the
+    // hash key.
     #[allow(missing_docs)]
     pub fn to_hash_key(&self) -> (Au, NotNaN<f32>) {
         use self::LengthOrPercentage::*;
         match *self {
-            Length(l) => (l, NotNaN::new(0.0).unwrap()),
+            Length(l) => (Au::from(l), NotNaN::new(0.0).unwrap()),
             Percentage(p) => (Au(0), NotNaN::new(p.0).unwrap()),
-            Calc(c) => (c.unclamped_length(), NotNaN::new(c.percentage()).unwrap()),
+            Calc(c) => (Au::from(c.unclamped_length()), NotNaN::new(c.percentage()).unwrap()),
         }
     }
 
     /// Returns the used value.
     pub fn to_used_value(&self, containing_length: Au) -> Au {
+        Au::from(self.to_pixel_length(containing_length))
+    }
+
+    /// Returns the used value as CSSPixelLength.
+    pub fn to_pixel_length(&self, containing_length: Au) -> Length {
         match *self {
             LengthOrPercentage::Length(length) => length,
-            LengthOrPercentage::Percentage(p) => containing_length.scale_by(p.0),
+            LengthOrPercentage::Percentage(p) => containing_length.scale_by(p.0).into(),
             LengthOrPercentage::Calc(ref calc) => {
-                calc.to_used_value(Some(containing_length)).unwrap()
+                calc.to_pixel_length(Some(containing_length)).unwrap()
             },
         }
     }
 
     /// Returns the clamped non-negative values.
     #[inline]
     pub fn clamp_to_non_negative(self) -> Self {
         match self {
             LengthOrPercentage::Length(length) => {
-                LengthOrPercentage::Length(Au(::std::cmp::max(length.0, 0)))
+                LengthOrPercentage::Length(Length::new(length.px().max(0.)))
             },
             LengthOrPercentage::Percentage(percentage) => {
                 LengthOrPercentage::Percentage(Percentage(percentage.0.max(0.)))
             },
             _ => self
         }
     }
 }
@@ -434,17 +450,17 @@ impl ToComputedValue for specified::Leng
 
 #[allow(missing_docs)]
 #[animate(fallback = "Self::animate_fallback")]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 #[css(derive_debug)]
 #[derive(Animate, Clone, ComputeSquaredDistance, Copy, PartialEq, ToCss)]
 #[distance(fallback = "Self::compute_squared_distance_fallback")]
 pub enum LengthOrPercentageOrAuto {
-    Length(Au),
+    Length(Length),
     Percentage(Percentage),
     Auto,
     Calc(CalcLengthOrPercentage),
 }
 
 impl LengthOrPercentageOrAuto {
     /// https://drafts.csswg.org/css-transitions/#animtype-lpcalc
     fn animate_fallback(
@@ -474,19 +490,19 @@ impl LengthOrPercentageOrAuto {
 impl LengthOrPercentageOrAuto {
     /// Returns true if the computed value is absolute 0 or 0%.
     ///
     /// (Returns false for calc() values, even if ones that may resolve to zero.)
     #[inline]
     pub fn is_definitely_zero(&self) -> bool {
         use self::LengthOrPercentageOrAuto::*;
         match *self {
-            Length(Au(0)) => true,
+            Length(l) => l.px() == 0.0,
             Percentage(p) => p.0 == 0.0,
-            Length(_) | Calc(_) | Auto => false
+            Calc(_) | Auto => false
         }
     }
 }
 
 impl ToComputedValue for specified::LengthOrPercentageOrAuto {
     type ComputedValue = LengthOrPercentageOrAuto;
 
     #[inline]
@@ -530,17 +546,17 @@ impl ToComputedValue for specified::Leng
 
 #[allow(missing_docs)]
 #[animate(fallback = "Self::animate_fallback")]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 #[css(derive_debug)]
 #[derive(Animate, Clone, ComputeSquaredDistance, Copy, PartialEq, ToCss)]
 #[distance(fallback = "Self::compute_squared_distance_fallback")]
 pub enum LengthOrPercentageOrNone {
-    Length(Au),
+    Length(Length),
     Percentage(Percentage),
     Calc(CalcLengthOrPercentage),
     None,
 }
 
 impl LengthOrPercentageOrNone {
     /// https://drafts.csswg.org/css-transitions/#animtype-lpcalc
     fn animate_fallback(
@@ -566,17 +582,17 @@ impl LengthOrPercentageOrNone {
     }
 }
 
 impl LengthOrPercentageOrNone {
     /// Returns the used value.
     pub fn to_used_value(&self, containing_length: Au) -> Option<Au> {
         match *self {
             LengthOrPercentageOrNone::None => None,
-            LengthOrPercentageOrNone::Length(length) => Some(length),
+            LengthOrPercentageOrNone::Length(length) => Some(Au::from(length)),
             LengthOrPercentageOrNone::Percentage(percent) => Some(containing_length.scale_by(percent.0)),
             LengthOrPercentageOrNone::Calc(ref calc) => calc.to_used_value(Some(containing_length)),
         }
     }
 }
 
 impl ToComputedValue for specified::LengthOrPercentageOrNone {
     type ComputedValue = LengthOrPercentageOrNone;
@@ -618,19 +634,19 @@ impl ToComputedValue for specified::Leng
             }
         }
     }
 }
 
 /// A wrapper of LengthOrPercentage, whose value must be >= 0.
 pub type NonNegativeLengthOrPercentage = NonNegative<LengthOrPercentage>;
 
-impl From<NonNegativeAu> for NonNegativeLengthOrPercentage {
+impl From<NonNegativeLength> for NonNegativeLengthOrPercentage {
     #[inline]
-    fn from(length: NonNegativeAu) -> Self {
+    fn from(length: NonNegativeLength) -> Self {
         LengthOrPercentage::Length(length.0).into()
     }
 }
 
 impl From<LengthOrPercentage> for NonNegativeLengthOrPercentage {
     #[inline]
     fn from(lop: LengthOrPercentage) -> Self {
         NonNegative::<LengthOrPercentage>(lop)
@@ -659,18 +675,80 @@ impl NonNegativeLengthOrPercentage {
 
     /// Returns the used value.
     #[inline]
     pub fn to_used_value(&self, containing_length: Au) -> Au {
         self.0.to_used_value(containing_length)
     }
 }
 
-/// A computed `<length>` value.
-pub type Length = Au;
+/// The computed `<length>` value.
+#[cfg_attr(feature = "servo", derive(Deserialize, HeapSizeOf, Serialize))]
+#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, PartialEq, PartialOrd)]
+#[derive(ToAnimatedValue, ToAnimatedZero)]
+pub struct CSSPixelLength(CSSFloat);
+
+impl CSSPixelLength {
+    /// Return a new CSSPixelLength.
+    #[inline]
+    pub fn new(px: CSSFloat) -> Self {
+        CSSPixelLength(px)
+    }
+
+    /// Return the containing pixel value.
+    #[inline]
+    pub fn px(&self) -> CSSFloat {
+        self.0
+    }
+
+    /// Return the length with app_unit i32 type.
+    #[inline]
+    pub fn to_i32_au(&self) -> i32 {
+        Au::from(*self).0
+    }
+
+    /// Return the absolute value of this length.
+    pub fn abs(self) -> Self {
+        CSSPixelLength::new(self.0.abs())
+    }
+}
+
+impl ToCss for CSSPixelLength {
+    #[inline]
+    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+        self.0.to_css(dest)?;
+        dest.write_str("px")
+    }
+}
+
+impl Neg for CSSPixelLength {
+    type Output = Self;
+
+    #[inline]
+    fn neg(self) -> Self {
+        CSSPixelLength::new(-self.0)
+    }
+}
+
+impl From<CSSPixelLength> for Au {
+    #[inline]
+    fn from(len: CSSPixelLength) -> Self {
+        Au::from_f32_px(len.0)
+    }
+}
+
+impl From<Au> for CSSPixelLength {
+    #[inline]
+    fn from(len: Au) -> Self {
+        CSSPixelLength::new(len.to_f32_px())
+    }
+}
+
+/// An alias of computed `<length>` value.
+pub type Length = CSSPixelLength;
 
 /// Either a computed `<length>` or the `none` keyword.
 pub type LengthOrNone = Either<Length, None_>;
 
 /// Either a computed `<length>` or the `auto` keyword.
 pub type LengthOrAuto = Either<Length, Auto>;
 
 /// Either a computed `<length>` or a `<number>` value.
@@ -683,17 +761,73 @@ impl LengthOrNumber {
         Either::Second(0.)
     }
 }
 
 /// Either a computed `<length>` or the `normal` keyword.
 pub type LengthOrNormal = Either<Length, Normal>;
 
 /// A wrapper of Length, whose value must be >= 0.
-pub type NonNegativeLength = NonNegativeAu;
+pub type NonNegativeLength = NonNegative<Length>;
+
+impl NonNegativeLength {
+    /// Create a NonNegativeLength.
+    #[inline]
+    pub fn new(px: CSSFloat) -> Self {
+        NonNegative(Length::new(px.max(0.)))
+    }
+
+    /// Return a zero value.
+    #[inline]
+    pub fn zero() -> Self {
+        Self::new(0.)
+    }
+
+    /// Return the pixel value of |NonNegativeLength|.
+    #[inline]
+    pub fn px(&self) -> CSSFloat {
+        self.0.px()
+    }
+
+    /// Scale this NonNegativeLength.
+    /// We scale NonNegativeLength by zero if the factor is negative because it doesn't
+    /// make sense to scale a negative factor on a non-negative length.
+    #[inline]
+    pub fn scale_by(&self, factor: f32) -> Self {
+        Self::new(self.0.px() * factor.max(0.))
+    }
+}
+
+impl Add<NonNegativeLength> for NonNegativeLength {
+    type Output = Self;
+    fn add(self, other: Self) -> Self {
+        NonNegativeLength::new(self.px() + other.px())
+    }
+}
+
+impl From<Length> for NonNegativeLength {
+    #[inline]
+    fn from(len: Length) -> Self {
+        NonNegative(len)
+    }
+}
+
+impl From<Au> for NonNegativeLength {
+    #[inline]
+    fn from(au: Au) -> Self {
+        NonNegative(au.into())
+    }
+}
+
+impl From<NonNegativeLength> for Au {
+    #[inline]
+    fn from(non_negative_len: NonNegativeLength) -> Self {
+        Au::from(non_negative_len.0)
+    }
+}
 
 /// Either a computed NonNegativeLength or the `auto` keyword.
 pub type NonNegativeLengthOrAuto = Either<NonNegativeLength, Auto>;
 
 /// Either a computed NonNegativeLength or the `normal` keyword.
 pub type NonNegativeLengthOrNormal = Either<NonNegativeLength, Normal>;
 
 /// Either a computed NonNegativeLength or a NonNegativeNumber value.
--- a/servo/components/style/values/computed/mod.rs
+++ b/servo/components/style/values/computed/mod.rs
@@ -9,17 +9,17 @@ use context::QuirksMode;
 use euclid::Size2D;
 use font_metrics::FontMetricsProvider;
 use media_queries::Device;
 #[cfg(feature = "gecko")]
 use properties;
 use properties::{ComputedValues, StyleBuilder};
 #[cfg(feature = "servo")]
 use servo_url::ServoUrl;
-use std::{f32, fmt, ops};
+use std::{f32, fmt};
 #[cfg(feature = "servo")]
 use std::sync::Arc;
 use style_traits::ToCss;
 use style_traits::cursor::Cursor;
 use super::{CSSFloat, CSSInteger};
 use super::generics::{GreaterThanOrEqualToOne, NonNegative};
 use super::generics::grid::{GridLine as GenericGridLine, TrackBreadth as GenericTrackBreadth};
 use super::generics::grid::{TrackSize as GenericTrackSize, TrackList as GenericTrackList};
@@ -41,17 +41,17 @@ pub use self::flex::FlexBasis;
 pub use self::image::{Gradient, GradientItem, Image, ImageLayer, LineDirection, MozImageRect};
 #[cfg(feature = "gecko")]
 pub use self::gecko::ScrollSnapPoint;
 pub use self::rect::LengthOrNumberRect;
 pub use super::{Auto, Either, None_};
 pub use super::specified::BorderStyle;
 pub use self::length::{CalcLengthOrPercentage, Length, LengthOrNone, LengthOrNumber, LengthOrPercentage};
 pub use self::length::{LengthOrPercentageOrAuto, LengthOrPercentageOrNone, MaxLength, MozLength};
-pub use self::length::NonNegativeLengthOrPercentage;
+pub use self::length::{CSSPixelLength, NonNegativeLength, NonNegativeLengthOrPercentage};
 pub use self::percentage::Percentage;
 pub use self::position::Position;
 pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind, SVGStrokeDashArray, SVGWidth};
 pub use self::text::{InitialLetter, LetterSpacing, LineHeight, WordSpacing};
 pub use self::time::Time;
 pub use self::transform::{TimingFunction, TransformOrigin};
 
 #[cfg(feature = "gecko")]
@@ -141,30 +141,30 @@ impl<'a> Context<'a> {
 
     /// The current style.
     pub fn style(&self) -> &StyleBuilder {
         &self.builder
     }
 
     /// Apply text-zoom if enabled.
     #[cfg(feature = "gecko")]
-    pub fn maybe_zoom_text(&self, size: NonNegativeAu) -> NonNegativeAu {
+    pub fn maybe_zoom_text(&self, size: CSSPixelLength) -> CSSPixelLength {
         // We disable zoom for <svg:text> by unsetting the
         // -x-text-zoom property, which leads to a false value
         // in mAllowZoom
         if self.style().get_font().gecko.mAllowZoom {
-            self.device().zoom_text(size.0).into()
+            self.device().zoom_text(Au::from(size)).into()
         } else {
             size
         }
     }
 
     /// (Servo doesn't do text-zoom)
     #[cfg(feature = "servo")]
-    pub fn maybe_zoom_text(&self, size: NonNegativeAu) -> NonNegativeAu {
+    pub fn maybe_zoom_text(&self, size: CSSPixelLength) -> CSSPixelLength {
         size
     }
 }
 
 /// An iterator over a slice of computed values
 #[derive(Clone)]
 pub struct ComputedVecIter<'a, 'cx, 'cx_a: 'cx, S: ToComputedValue + 'a> {
     cx: &'cx Context<'cx_a>,
@@ -445,23 +445,23 @@ pub type PositiveIntegerOrAuto = Either<
 /// <length> | <percentage> | <number>
 pub type LengthOrPercentageOrNumber = Either<Number, LengthOrPercentage>;
 
 /// NonNegativeLengthOrPercentage | NonNegativeNumber
 pub type NonNegativeLengthOrPercentageOrNumber = Either<NonNegativeNumber, NonNegativeLengthOrPercentage>;
 
 #[allow(missing_docs)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-#[derive(Clone, ComputeSquaredDistance, Copy, Debug, Eq, PartialEq)]
+#[derive(Clone, ComputeSquaredDistance, Copy, Debug, PartialEq)]
 /// A computed cliprect for clip and image-region
 pub struct ClipRect {
-    pub top: Option<Au>,
-    pub right: Option<Au>,
-    pub bottom: Option<Au>,
-    pub left: Option<Au>,
+    pub top: Option<Length>,
+    pub right: Option<Length>,
+    pub bottom: Option<Length>,
+    pub left: Option<Length>,
 }
 
 impl ToCss for ClipRect {
     fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
         dest.write_str("rect(")?;
         if let Some(top) = self.top {
             top.to_css(dest)?;
             dest.write_str(", ")?;
@@ -524,60 +524,16 @@ impl ClipRectOrAuto {
             _ => false
         }
     }
 }
 
 /// <color> | auto
 pub type ColorOrAuto = Either<Color, Auto>;
 
-/// A wrapper of Au, but the value >= 0.
-pub type NonNegativeAu = NonNegative<Au>;
-
-impl NonNegativeAu {
-    /// Return a zero value.
-    #[inline]
-    pub fn zero() -> Self {
-        NonNegative::<Au>(Au(0))
-    }
-
-    /// Return a NonNegativeAu from pixel.
-    #[inline]
-    pub fn from_px(px: i32) -> Self {
-        NonNegative::<Au>(Au::from_px(::std::cmp::max(px, 0)))
-    }
-
-    /// Get the inner value of |NonNegativeAu.0|.
-    #[inline]
-    pub fn value(self) -> i32 {
-        (self.0).0
-    }
-
-    /// Scale this NonNegativeAu.
-    #[inline]
-    pub fn scale_by(self, factor: f32) -> Self {
-        // scale this by zero if factor is negative.
-        NonNegative::<Au>(self.0.scale_by(factor.max(0.)))
-    }
-}
-
-impl ops::Add<NonNegativeAu> for NonNegativeAu {
-    type Output = NonNegativeAu;
-    fn add(self, other: Self) -> Self {
-        (self.0 + other.0).into()
-    }
-}
-
-impl From<Au> for NonNegativeAu {
-    #[inline]
-    fn from(au: Au) -> NonNegativeAu {
-        NonNegative::<Au>(au)
-    }
-}
-
 /// The computed value of a CSS `url()`, resolved relative to the stylesheet URL.
 #[cfg(feature = "servo")]
 #[derive(Clone, Debug, Deserialize, HeapSizeOf, PartialEq, Serialize)]
 pub enum ComputedUrl {
     /// The `url()` was invalid or it wasn't specified by the user.
     Invalid(Arc<String>),
     /// The resolved `url()` relative to the stylesheet URL.
     Valid(ServoUrl),
--- a/servo/components/style/values/computed/svg.rs
+++ b/servo/components/style/values/computed/svg.rs
@@ -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/. */
 
 //! Computed types for SVG properties.
 
 use app_units::Au;
 use values::RGBA;
-use values::computed::{ComputedUrl, LengthOrPercentage, NonNegativeAu};
+use values::computed::{ComputedUrl, LengthOrPercentage, NonNegativeLength};
 use values::computed::{NonNegativeNumber, NonNegativeLengthOrPercentage, Number};
 use values::computed::Opacity;
 use values::generics::svg as generic;
 
 /// Computed SVG Paint value
 pub type SVGPaint = generic::SVGPaint<RGBA, ComputedUrl>;
 /// Computed SVG Paint Kind value
 pub type SVGPaintKind = generic::SVGPaintKind<RGBA, ComputedUrl>;
@@ -67,18 +67,18 @@ impl Into<NonNegativeSvgLengthOrPercenta
             },
         }
     }
 }
 
 /// An non-negative wrapper of SVGLength.
 pub type SVGWidth = generic::SVGLength<NonNegativeSvgLengthOrPercentageOrNumber>;
 
-impl From<NonNegativeAu> for SVGWidth {
-    fn from(length: NonNegativeAu) -> Self {
+impl From<NonNegativeLength> for SVGWidth {
+    fn from(length: NonNegativeLength) -> Self {
         generic::SVGLength::Length(
             generic::SvgLengthOrPercentageOrNumber::LengthOrPercentage(length.into()))
     }
 }
 
 /// [ <length> | <percentage> | <number> ]# | context-value
 pub type SVGStrokeDashArray = generic::SVGStrokeDashArray<NonNegativeSvgLengthOrPercentageOrNumber>;
 
--- a/servo/components/style/values/computed/text.rs
+++ b/servo/components/style/values/computed/text.rs
@@ -1,30 +1,30 @@
 /* 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/. */
 
 //! Computed types for text properties.
 
 use values::{CSSInteger, CSSFloat};
 use values::animated::ToAnimatedZero;
-use values::computed::{NonNegativeAu, NonNegativeNumber};
+use values::computed::{NonNegativeLength, NonNegativeNumber};
 use values::computed::length::{Length, LengthOrPercentage};
 use values::generics::text::InitialLetter as GenericInitialLetter;
 use values::generics::text::LineHeight as GenericLineHeight;
 use values::generics::text::Spacing;
 
 /// A computed value for the `initial-letter` property.
 pub type InitialLetter = GenericInitialLetter<CSSFloat, CSSInteger>;
 
 /// A computed value for the `letter-spacing` property.
 pub type LetterSpacing = Spacing<Length>;
 
 /// A computed value for the `word-spacing` property.
 pub type WordSpacing = Spacing<LengthOrPercentage>;
 
 /// A computed value for the `line-height` property.
-pub type LineHeight = GenericLineHeight<NonNegativeNumber, NonNegativeAu>;
+pub type LineHeight = GenericLineHeight<NonNegativeNumber, NonNegativeLength>;
 
 impl ToAnimatedZero for LineHeight {
     #[inline]
     fn to_animated_zero(&self) -> Result<Self, ()> { Err(()) }
 }
--- a/servo/components/style/values/computed/transform.rs
+++ b/servo/components/style/values/computed/transform.rs
@@ -25,17 +25,17 @@ pub type DirectionVector = Vector3D<CSSF
 
 impl TransformOrigin {
     /// Returns the initial computed value for `transform-origin`.
     #[inline]
     pub fn initial_value() -> Self {
         Self::new(
             LengthOrPercentage::Percentage(Percentage(0.5)),
             LengthOrPercentage::Percentage(Percentage(0.5)),
-            Length::from_px(0),
+            Length::new(0.),
         )
     }
 }
 
 impl From<ComputedMatrix> for Transform3D<CSSFloat> {
     #[inline]
     fn from(m: ComputedMatrix) -> Self {
         Transform3D::row_major(
@@ -67,50 +67,50 @@ impl TransformList {
         let mut transform = Transform3D::identity();
         let list = match self.0.as_ref() {
             Some(list) => list,
             None => return None,
         };
 
         let extract_pixel_length = |lop: &LengthOrPercentage| {
             match *lop {
-                LengthOrPercentage::Length(au) => au.to_f32_px(),
+                LengthOrPercentage::Length(px) => px.px(),
                 LengthOrPercentage::Percentage(_) => 0.,
-                LengthOrPercentage::Calc(calc) => calc.length().to_f32_px(),
+                LengthOrPercentage::Calc(calc) => calc.length().px(),
             }
         };
 
         for operation in list {
             let matrix = match *operation {
                 ComputedOperation::Rotate(ax, ay, az, theta) => {
                     let theta = Angle::from_radians(2.0f32 * f32::consts::PI - theta.radians());
                     let (ax, ay, az, theta) =
                         Self::get_normalized_vector_and_angle(ax, ay, az, theta);
                     Transform3D::create_rotation(ax, ay, az, theta.into())
                 }
                 ComputedOperation::Perspective(d) => {
-                    Self::create_perspective_matrix(d)
+                    Self::create_perspective_matrix(d.px())
                 }
                 ComputedOperation::Scale(sx, sy, sz) => {
                     Transform3D::create_scale(sx, sy, sz)
                 }
                 ComputedOperation::Translate(tx, ty, tz) => {
                     let (tx, ty) = match reference_box {
                         Some(relative_border_box) => {
-                            (tx.to_used_value(relative_border_box.size.width).to_f32_px(),
-                             ty.to_used_value(relative_border_box.size.height).to_f32_px())
+                            (tx.to_pixel_length(relative_border_box.size.width).px(),
+                             ty.to_pixel_length(relative_border_box.size.height).px())
                         },
                         None => {
                             // If we don't have reference box, we cannot resolve the used value,
                             // so only retrieve the length part. This will be used for computing
                             // distance without any layout info.
                             (extract_pixel_length(&tx), extract_pixel_length(&ty))
                         }
                     };
-                    let tz = tz.to_f32_px();
+                    let tz = tz.px();
                     Transform3D::create_translation(tx, ty, tz)
                 }
                 ComputedOperation::Matrix(m) => {
                     m.into()
                 }
                 ComputedOperation::MatrixWithPercents(_) => {
                     // `-moz-transform` is not implemented in Servo yet.
                     unreachable!()
@@ -132,25 +132,24 @@ impl TransformList {
             transform = transform.pre_mul(&matrix);
         }
 
         Some(transform)
     }
 
     /// Return the transform matrix from a perspective length.
     #[inline]
-    pub fn create_perspective_matrix(d: Au) -> Transform3D<f32> {
+    pub fn create_perspective_matrix(d: CSSFloat) -> Transform3D<f32> {
         // TODO(gw): The transforms spec says that perspective length must
         // be positive. However, there is some confusion between the spec
         // and browser implementations as to handling the case of 0 for the
         // perspective value. Until the spec bug is resolved, at least ensure
         // that a provided perspective value of <= 0.0 doesn't cause panics
         // and behaves as it does in other browsers.
         // See https://lists.w3.org/Archives/Public/www-style/2016Jan/0020.html for more details.
-        let d = d.to_f32_px();
         if d <= 0.0 {
             Transform3D::identity()
         } else {
             Transform3D::create_perspective(d)
         }
     }
 
     /// Return the normalized direction vector and its angle for Rotate3D.
--- a/servo/components/style/values/specified/border.rs
+++ b/servo/components/style/values/specified/border.rs
@@ -2,17 +2,17 @@
  * 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/. */
 
 //! Specified types for CSS values related to borders.
 
 use cssparser::Parser;
 use parser::{Parse, ParserContext};
 use style_traits::ParseError;
-use values::computed::{Context, NonNegativeAu, ToComputedValue};
+use values::computed::{Context, NonNegativeLength, ToComputedValue};
 use values::generics::border::BorderCornerRadius as GenericBorderCornerRadius;
 use values::generics::border::BorderImageSideWidth as GenericBorderImageSideWidth;
 use values::generics::border::BorderImageSlice as GenericBorderImageSlice;
 use values::generics::border::BorderRadius as GenericBorderRadius;
 use values::generics::rect::Rect;
 use values::specified::{AllowQuirks, Number, NumberOrPercentage};
 use values::specified::length::{Length, LengthOrPercentage};
 
@@ -66,28 +66,28 @@ impl BorderSideWidth {
 
 impl Parse for BorderSideWidth {
     fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
         Self::parse_quirky(context, input, AllowQuirks::No)
     }
 }
 
 impl ToComputedValue for BorderSideWidth {
-    type ComputedValue = NonNegativeAu;
+    type ComputedValue = NonNegativeLength;
 
     #[inline]
     fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
         // We choose the pixel length of the keyword values the same as both spec and gecko.
         // Spec: https://drafts.csswg.org/css-backgrounds-3/#line-width
         // Gecko: https://bugzilla.mozilla.org/show_bug.cgi?id=1312155#c0
         match *self {
             BorderSideWidth::Thin => Length::from_px(1.).to_computed_value(context),
             BorderSideWidth::Medium => Length::from_px(3.).to_computed_value(context),
             BorderSideWidth::Thick => Length::from_px(5.).to_computed_value(context),
-            BorderSideWidth::Length(ref length) => length.to_computed_value(context)
+            BorderSideWidth::Length(ref length) => length.to_computed_value(context),
         }.into()
     }
 
     #[inline]
     fn from_computed_value(computed: &Self::ComputedValue) -> Self {
         BorderSideWidth::Length(ToComputedValue::from_computed_value(&computed.0))
     }
 }
--- a/servo/components/style/values/specified/calc.rs
+++ b/servo/components/style/values/specified/calc.rs
@@ -6,17 +6,17 @@
 //!
 //! [calc]: https://drafts.csswg.org/css-values/#calc-notation
 
 use cssparser::{Parser, Token, BasicParseError};
 use parser::ParserContext;
 use std::ascii::AsciiExt;
 use std::fmt;
 use style_traits::{ToCss, ParseError, StyleParseError};
-use style_traits::values::specified::AllowedLengthType;
+use style_traits::values::specified::AllowedNumericType;
 use values::{CSSInteger, CSSFloat};
 use values::computed;
 use values::specified::{Angle, Time};
 use values::specified::length::{AbsoluteLength, FontRelativeLength, NoCalcLength};
 use values::specified::length::ViewportPercentageLength;
 
 /// A node inside a `Calc` expression's AST.
 #[derive(Clone, Debug)]
@@ -62,17 +62,17 @@ pub enum CalcUnit {
     Time,
 }
 
 /// A struct to hold a simplified `<length>` or `<percentage>` expression.
 #[derive(Clone, Copy, Debug, Default, PartialEq)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 #[allow(missing_docs)]
 pub struct CalcLengthOrPercentage {
-    pub clamping_mode: AllowedLengthType,
+    pub clamping_mode: AllowedNumericType,
     pub absolute: Option<AbsoluteLength>,
     pub vw: Option<CSSFloat>,
     pub vh: Option<CSSFloat>,
     pub vmin: Option<CSSFloat>,
     pub vmax: Option<CSSFloat>,
     pub em: Option<CSSFloat>,
     pub ex: Option<CSSFloat>,
     pub ch: Option<CSSFloat>,
@@ -286,17 +286,17 @@ impl CalcNode {
             }
         }
 
         Ok(root)
     }
 
     /// Tries to simplify this expression into a `<length>` or `<percentage`>
     /// value.
-    fn to_length_or_percentage(&self, clamping_mode: AllowedLengthType)
+    fn to_length_or_percentage(&self, clamping_mode: AllowedNumericType)
                                -> Result<CalcLengthOrPercentage, ()> {
         let mut ret = CalcLengthOrPercentage {
             clamping_mode: clamping_mode,
             .. Default::default()
         };
         self.add_length_or_percentage_to(&mut ret, 1.0)?;
         Ok(ret)
     }
@@ -560,17 +560,17 @@ impl CalcNode {
             .map(|n| n as CSSInteger)
             .map_err(|()| StyleParseError::UnspecifiedError.into())
     }
 
     /// Convenience parsing function for `<length> | <percentage>`.
     pub fn parse_length_or_percentage<'i, 't>(
         context: &ParserContext,
         input: &mut Parser<'i, 't>,
-        clamping_mode: AllowedLengthType
+        clamping_mode: AllowedNumericType
     ) -> Result<CalcLengthOrPercentage, ParseError<'i>> {
         Self::parse(context, input, CalcUnit::LengthOrPercentage)?
             .to_length_or_percentage(clamping_mode)
             .map_err(|()| StyleParseError::UnspecifiedError.into())
     }
 
     /// Convenience parsing function for percentages.
     pub fn parse_percentage<'i, 't>(
@@ -581,17 +581,17 @@ impl CalcNode {
             .to_percentage()
             .map_err(|()| StyleParseError::UnspecifiedError.into())
     }
 
     /// Convenience parsing function for `<length>`.
     pub fn parse_length<'i, 't>(
         context: &ParserContext,
         input: &mut Parser<'i, 't>,
-        clamping_mode: AllowedLengthType
+        clamping_mode: AllowedNumericType
     ) -> Result<CalcLengthOrPercentage, ParseError<'i>> {
         Self::parse(context, input, CalcUnit::Length)?
             .to_length_or_percentage(clamping_mode)
             .map_err(|()| StyleParseError::UnspecifiedError.into())
     }
 
     /// Convenience parsing function for `<number>`.
     pub fn parse_number<'i, 't>(
--- a/servo/components/style/values/specified/length.rs
+++ b/servo/components/style/values/specified/length.rs
@@ -10,22 +10,22 @@ use app_units::Au;
 use cssparser::{Parser, Token, BasicParseError};
 use euclid::Size2D;
 use font_metrics::FontMetricsQueryResult;
 use parser::{Parse, ParserContext};
 use std::{cmp, fmt, mem};
 use std::ascii::AsciiExt;
 use std::ops::{Add, Mul};
 use style_traits::{ToCss, ParseError, StyleParseError};
-use style_traits::values::specified::AllowedLengthType;
+use style_traits::values::specified::AllowedNumericType;
 use stylesheets::CssRuleType;
 use super::{AllowQuirks, Number, ToComputedValue, Percentage};
 use values::{Auto, CSSFloat, Either, FONT_MEDIUM_PX, None_, Normal};
 use values::{ExtremumLength, serialize_dimension};
-use values::computed::{self, Context};
+use values::computed::{self, CSSPixelLength, Context};
 use values::generics::NonNegative;
 use values::specified::NonNegativeNumber;
 use values::specified::calc::CalcNode;
 
 pub use values::specified::calc::CalcLengthOrPercentage;
 pub use super::image::{ColorStop, EndingShape as GradientEndingShape, Gradient};
 pub use super::image::{GradientKind, Image};
 
@@ -90,84 +90,109 @@ pub enum FontBaseSize {
     Custom(Au),
 }
 
 impl FontBaseSize {
     /// Calculate the actual size for a given context
     pub fn resolve(&self, context: &Context) -> Au {
         match *self {
             FontBaseSize::Custom(size) => size,
-            FontBaseSize::CurrentStyle => context.style().get_font().clone_font_size().0,
-            FontBaseSize::InheritedStyle => context.style().get_parent_font().clone_font_size().0,
+            FontBaseSize::CurrentStyle => Au::from(context.style().get_font().clone_font_size()),
+            FontBaseSize::InheritedStyle => Au::from(context.style().get_parent_font().clone_font_size()),
         }
     }
 }
 
 impl FontRelativeLength {
-    /// Computes the font-relative length. We use the base_size
-    /// flag to pass a different size for computing font-size and unconstrained font-size
-    pub fn to_computed_value(&self, context: &Context, base_size: FontBaseSize) -> Au {
+    /// Computes the font-relative length.
+    pub fn to_computed_value(&self, context: &Context, base_size: FontBaseSize) -> CSSPixelLength {
+        use std::f32;
+        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)
+    }
+
+    /// 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) {
         fn query_font_metrics(context: &Context, reference_font_size: Au) -> FontMetricsQueryResult {
             context.font_metrics_provider.query(context.style().get_font(),
                                                 reference_font_size,
                                                 context.style().writing_mode,
                                                 context.in_media_query,
                                                 context.device())
         }
 
         let reference_font_size = base_size.resolve(context);
 
         match *self {
-            FontRelativeLength::Em(length) => reference_font_size.scale_by(length),
+            FontRelativeLength::Em(length) => {
+                (reference_font_size, length)
+            },
             FontRelativeLength::Ex(length) => {
-                match query_font_metrics(context, reference_font_size) {
-                    FontMetricsQueryResult::Available(metrics) => metrics.x_height.scale_by(length),
+                let reference_size = match query_font_metrics(context, reference_font_size) {
+                    FontMetricsQueryResult::Available(metrics) => {
+                        metrics.x_height
+                    },
                     // 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.
                     //
-                    FontMetricsQueryResult::NotAvailable => reference_font_size.scale_by(0.5 * length),
-                }
+                    FontMetricsQueryResult::NotAvailable => {
+                        reference_font_size.scale_by(0.5)
+                    },
+                };
+                (reference_size, length)
             },
             FontRelativeLength::Ch(length) => {
-                match query_font_metrics(context, reference_font_size) {
-                    FontMetricsQueryResult::Available(metrics) => metrics.zero_advance_measure.scale_by(length),
+                let reference_size = match query_font_metrics(context, reference_font_size) {
+                    FontMetricsQueryResult::Available(metrics) => {
+                        metrics.zero_advance_measure
+                    },
                     // https://drafts.csswg.org/css-values/#ch
                     //
                     //     In the cases where it is impossible or impractical to
                     //     determine the measure of the “0” glyph, it must be
                     //     assumed to be 0.5em wide by 1em tall. Thus, the ch
                     //     unit falls back to 0.5em in the general case, and to
                     //     1em when it would be typeset upright (i.e.
                     //     writing-mode is vertical-rl or vertical-lr and
                     //     text-orientation is upright).
                     //
                     FontMetricsQueryResult::NotAvailable => {
                         if context.style().writing_mode.is_vertical() {
-                            reference_font_size.scale_by(length)
+                            reference_font_size
                         } else {
-                            reference_font_size.scale_by(0.5 * length)
+                            reference_font_size.scale_by(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.
                 //
-                if context.is_root_element {
-                    reference_font_size.scale_by(length)
+                let reference_size = if context.is_root_element {
+                    reference_font_size
                 } else {
-                    context.device().root_font_size().scale_by(length)
-                }
+                    context.device().root_font_size()
+                };
+                (reference_size, length)
             }
         }
     }
 }
 
 #[derive(Clone, Copy, Debug, PartialEq)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 /// A viewport-relative length.
@@ -192,50 +217,52 @@ impl ToCss for ViewportPercentageLength 
             ViewportPercentageLength::Vmin(length) => serialize_dimension(length, "vmin", dest),
             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 {
+    pub fn to_computed_value(&self, viewport_size: Size2D<Au>) -> CSSPixelLength {
         let (factor, length) = match *self {
             ViewportPercentageLength::Vw(length) =>
                 (length, viewport_size.width),
             ViewportPercentageLength::Vh(length) =>
                 (length, viewport_size.height),
             ViewportPercentageLength::Vmin(length) =>
                 (length, cmp::min(viewport_size.width, viewport_size.height)),
             ViewportPercentageLength::Vmax(length) =>
                 (length, cmp::max(viewport_size.width, viewport_size.height)),
         };
 
+        // FIXME: Bug 1396535, we need to fix the extremely small viewport length for transform.
         // 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)
+        Au::from_f64_au(trunc_scaled).into()
     }
 }
 
 /// 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);
 
 impl CharacterWidth {
     /// Computes the given character width.
-    pub fn to_computed_value(&self, reference_font_size: Au) -> Au {
+    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.
         //
         // TODO(pcwalton): Find these from the font.
         let average_advance = reference_font_size.scale_by(0.5);
         let max_advance = reference_font_size;
-        average_advance.scale_by(self.0 as CSSFloat - 1.0) + max_advance
+        let au = average_advance.scale_by(self.0 as CSSFloat - 1.0) + max_advance;
+        au.into()
     }
 }
 
 /// Represents an absolute length with its unit
 #[derive(Clone, Copy, Debug, PartialEq)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 pub enum AbsoluteLength {
     /// An absolute length in pixels (px)
@@ -281,42 +308,24 @@ impl AbsoluteLength {
             AbsoluteLength::Pt(value) => value * (AU_PER_PT / AU_PER_PX),
             AbsoluteLength::Pc(value) => value * (AU_PER_PC / AU_PER_PX),
         };
         pixel.min(f32::MAX).max(f32::MIN)
     }
 }
 
 impl ToComputedValue for AbsoluteLength {
-    type ComputedValue = Au;
+    type ComputedValue = CSSPixelLength;
 
-    fn to_computed_value(&self, _: &Context) -> Au {
-        Au::from(*self)
+    fn to_computed_value(&self, _: &Context) -> Self::ComputedValue {
+        CSSPixelLength::new(self.to_px())
     }
 
-    fn from_computed_value(computed: &Au) -> AbsoluteLength {
-        AbsoluteLength::Px(computed.to_f32_px())
-    }
-}
-
-fn au_from_f32_round(x: f32) -> Au {
-    Au::from_f64_au((x as f64).round())
-}
-
-impl From<AbsoluteLength> for Au {
-    fn from(length: AbsoluteLength) -> Au {
-        match length {
-            AbsoluteLength::Px(value) => au_from_f32_round((value * AU_PER_PX)),
-            AbsoluteLength::In(value) => au_from_f32_round((value * AU_PER_IN)),
-            AbsoluteLength::Cm(value) => au_from_f32_round((value * AU_PER_CM)),
-            AbsoluteLength::Mm(value) => au_from_f32_round((value * AU_PER_MM)),
-            AbsoluteLength::Q(value) => au_from_f32_round((value * AU_PER_Q)),
-            AbsoluteLength::Pt(value) => au_from_f32_round((value * AU_PER_PT)),
-            AbsoluteLength::Pc(value) => au_from_f32_round((value * AU_PER_PC)),
-        }
+    fn from_computed_value(computed: &Self::ComputedValue) -> Self {
+        AbsoluteLength::Px(computed.px())
     }
 }
 
 impl ToCss for AbsoluteLength {
     fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
         match *self {
             AbsoluteLength::Px(length) => serialize_dimension(length, "px", dest),
             AbsoluteLength::In(length) => serialize_dimension(length, "in", dest),
@@ -371,28 +380,30 @@ pub struct PhysicalLength(pub CSSFloat);
 
 #[cfg(feature = "gecko")]
 impl PhysicalLength {
     fn is_zero(&self) -> bool {
         self.0 == 0.
     }
 
     /// Computes the given character width.
-    pub fn to_computed_value(&self, context: &Context) -> Au {
+    pub fn to_computed_value(&self, context: &Context) -> CSSPixelLength {
         use gecko_bindings::bindings;
+        use std::f32;
+
         // Same as Gecko
-        const MM_PER_INCH: f32 = 25.4;
+        const INCH_PER_MM: f32 = 1. / 25.4;
 
-        let physical_inch = unsafe {
-            bindings::Gecko_GetAppUnitsPerPhysicalInch(context.device().pres_context())
+        let au_per_physical_inch = unsafe {
+            bindings::Gecko_GetAppUnitsPerPhysicalInch(context.device().pres_context()) as f32
         };
 
-        let inch = self.0 / MM_PER_INCH;
-
-        au_from_f32_round(inch * physical_inch as f32)
+        let px_per_physical_inch = au_per_physical_inch / AU_PER_PX;
+        let pixel = self.0 * px_per_physical_inch * INCH_PER_MM;
+        CSSPixelLength::new(pixel.min(f32::MAX).max(f32::MIN))
     }
 }
 
 #[cfg(feature = "gecko")]
 impl ToCss for PhysicalLength {
     fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
         serialize_dimension(self.0, "mozmm", dest)
     }
@@ -626,17 +637,17 @@ impl Length {
     pub fn parse_dimension(context: &ParserContext, value: CSSFloat, unit: &str)
                            -> Result<Length, ()> {
         NoCalcLength::parse_dimension(context, value, unit).map(Length::NoCalc)
     }
 
     #[inline]
     fn parse_internal<'i, 't>(context: &ParserContext,
                               input: &mut Parser<'i, 't>,
-                              num_context: AllowedLengthType,
+                              num_context: AllowedNumericType,
                               allow_quirks: AllowQuirks)
                               -> Result<Length, ParseError<'i>> {
         // FIXME: remove early returns when lifetimes are non-lexical
         {
             let token = input.next()?;
             match *token {
                 Token::Dimension { value, ref unit, .. } if num_context.is_ok(context.parsing_mode, value) => {
                     return Length::parse_dimension(context, value, unit)
@@ -667,17 +678,17 @@ impl Length {
     }
 
     /// Parse a non-negative length, allowing quirks.
     #[inline]
     pub fn parse_non_negative_quirky<'i, 't>(context: &ParserContext,
                                              input: &mut Parser<'i, 't>,
                                              allow_quirks: AllowQuirks)
                                              -> Result<Length, ParseError<'i>> {
-        Self::parse_internal(context, input, AllowedLengthType::NonNegative, allow_quirks)
+        Self::parse_internal(context, input, AllowedNumericType::NonNegative, allow_quirks)
     }
 
     /// Get an absolute length from a px value.
     #[inline]
     pub fn from_px(px_value: CSSFloat) -> Length {
         Length::NoCalc(NoCalcLength::from_px(px_value))
     }
 
@@ -697,29 +708,29 @@ impl Parse for Length {
 }
 
 impl Length {
     /// Parses a length, with quirks.
     pub fn parse_quirky<'i, 't>(context: &ParserContext,
                                 input: &mut Parser<'i, 't>,
                                 allow_quirks: AllowQuirks)
                                 -> Result<Self, ParseError<'i>> {
-        Self::parse_internal(context, input, AllowedLengthType::All, allow_quirks)
+        Self::parse_internal(context, input, AllowedNumericType::All, allow_quirks)
     }
 }
 
 impl<T: Parse> Either<Length, T> {
     /// Parse a non-negative length
     #[inline]
     pub fn parse_non_negative_length<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
                                              -> Result<Self, ParseError<'i>> {
         if let Ok(v) = input.try(|input| T::parse(context, input)) {
             return Ok(Either::Second(v));
         }
-        Length::parse_internal(context, input, AllowedLengthType::NonNegative, AllowQuirks::No).map(Either::First)
+        Length::parse_internal(context, input, AllowedNumericType::NonNegative, AllowQuirks::No).map(Either::First)
     }
 }
 
 /// A wrapper of Length, whose value must be >= 0.
 pub type NonNegativeLength = NonNegative<Length>;
 
 impl From<NoCalcLength> for NonNegativeLength {
     #[inline]
@@ -736,17 +747,17 @@ impl From<Length> for NonNegativeLength 
 }
 
 impl<T: Parse> Parse for Either<NonNegativeLength, T> {
     #[inline]
     fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
         if let Ok(v) = input.try(|input| T::parse(context, input)) {
             return Ok(Either::Second(v));
         }
-        Length::parse_internal(context, input, AllowedLengthType::NonNegative, AllowQuirks::No)
+        Length::parse_internal(context, input, AllowedNumericType::NonNegative, AllowQuirks::No)
             .map(NonNegative::<Length>).map(Either::First)
     }
 }
 
 impl NonNegativeLength {
     /// Returns a `zero` length.
     #[inline]
     pub fn zero() -> Self {
@@ -820,17 +831,17 @@ impl LengthOrPercentage {
     #[inline]
     /// Returns a `zero` length.
     pub fn zero() -> LengthOrPercentage {
         LengthOrPercentage::Length(NoCalcLength::zero())
     }
 
     fn parse_internal<'i, 't>(context: &ParserContext,
                               input: &mut Parser<'i, 't>,
-                              num_context: AllowedLengthType,
+                              num_context: AllowedNumericType,
                               allow_quirks: AllowQuirks)
                               -> Result<LengthOrPercentage, ParseError<'i>>
     {
         // FIXME: remove early returns when lifetimes are non-lexical
         {
             let token = input.next()?;
             match *token {
                 Token::Dimension { value, ref unit, .. } if num_context.is_ok(context.parsing_mode, value) => {
@@ -869,17 +880,17 @@ impl LengthOrPercentage {
     }
 
     /// Parse a non-negative length, with quirks.
     #[inline]
     pub fn parse_non_negative_quirky<'i, 't>(context: &ParserContext,
                                              input: &mut Parser<'i, 't>,
                                              allow_quirks: AllowQuirks)
                                              -> Result<LengthOrPercentage, ParseError<'i>> {
-        Self::parse_internal(context, input, AllowedLengthType::NonNegative, allow_quirks)
+        Self::parse_internal(context, input, AllowedNumericType::NonNegative, allow_quirks)
     }
 
     /// Parse a length, treating dimensionless numbers as pixels
     ///
     /// https://www.w3.org/TR/SVG2/types.html#presentation-attribute-css-value
     pub fn parse_numbers_are_pixels<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
                                             -> Result<LengthOrPercentage, ParseError<'i>> {
         if let Ok(lop) = input.try(|i| Self::parse(context, i)) {
@@ -930,17 +941,17 @@ impl Parse for LengthOrPercentage {
 
 impl LengthOrPercentage {
     /// Parses a length or a percentage, allowing the unitless length quirk.
     /// https://quirks.spec.whatwg.org/#the-unitless-length-quirk
     #[inline]
     pub fn parse_quirky<'i, 't>(context: &ParserContext,
                                 input: &mut Parser<'i, 't>,
                                 allow_quirks: AllowQuirks) -> Result<Self, ParseError<'i>> {
-        Self::parse_internal(context, input, AllowedLengthType::All, allow_quirks)
+        Self::parse_internal(context, input, AllowedNumericType::All, allow_quirks)
     }
 }
 
 /// Either a `<length>`, a `<percentage>`, or the `auto` keyword.
 #[allow(missing_docs)]
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 #[derive(Clone, Debug, PartialEq, ToCss)]
 pub enum LengthOrPercentageOrAuto {
@@ -962,17 +973,17 @@ impl From<computed::Percentage> for Leng
     fn from(pc: computed::Percentage) -> Self {
         LengthOrPercentageOrAuto::Percentage(pc)
     }
 }
 
 impl LengthOrPercentageOrAuto {
     fn parse_internal<'i, 't>(context: &ParserContext,
                               input: &mut Parser<'i, 't>,
-                              num_context: AllowedLengthType,
+                              num_context: AllowedNumericType,
                               allow_quirks: AllowQuirks)
                               -> Result<Self, ParseError<'i>> {
         // FIXME: remove early returns when lifetimes are non-lexical
         {
             let token = input.next()?;
             match *token {
                 Token::Dimension { value, ref unit, .. } if num_context.is_ok(context.parsing_mode, value) => {
                     return NoCalcLength::parse_dimension(context, value, unit)
@@ -1014,17 +1025,17 @@ impl LengthOrPercentageOrAuto {
     }
 
     /// Parse a non-negative length, percentage, or auto.
     #[inline]
     pub fn parse_non_negative_quirky<'i, 't>(context: &ParserContext,
                                              input: &mut Parser<'i, 't>,
                                              allow_quirks: AllowQuirks)
                                              -> Result<Self, ParseError<'i>> {
-        Self::parse_internal(context, input, AllowedLengthType::NonNegative, allow_quirks)
+        Self::parse_internal(context, input, AllowedNumericType::NonNegative, allow_quirks)
     }
 
     /// Returns the `auto` value.
     pub fn auto() -> Self {
         LengthOrPercentageOrAuto::Auto
     }
 
     /// Returns a value representing a `0` length.
@@ -1047,17 +1058,17 @@ impl Parse for LengthOrPercentageOrAuto 
 
 impl LengthOrPercentageOrAuto {
     /// Parses, with quirks.
     #[inline]
     pub fn parse_quirky<'i, 't>(context: &ParserContext,
                                 input: &mut Parser<'i, 't>,
                                 allow_quirks: AllowQuirks)
                                 -> Result<Self, ParseError<'i>> {
-        Self::parse_internal(context, input, AllowedLengthType::All, allow_quirks)
+        Self::parse_internal(context, input, AllowedNumericType::All, allow_quirks)
     }
 }
 
 /// Either a `<length>`, a `<percentage>`, or the `none` keyword.
 #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
 #[derive(Clone, Debug, PartialEq, ToCss)]
 #[allow(missing_docs)]
 pub enum LengthOrPercentageOrNone {
@@ -1065,17 +1076,17 @@ pub enum LengthOrPercentageOrNone {
     Percentage(computed::Percentage),
     Calc(Box<CalcLengthOrPercentage>),
     None,
 }
 
 impl LengthOrPercentageOrNone {
     fn parse_internal<'i, 't>(context: &ParserContext,
                               input: &mut Parser<'i, 't>,
-                              num_context: AllowedLengthType,
+                              num_context: AllowedNumericType,
                               allow_quirks: AllowQuirks)
                               -> Result<LengthOrPercentageOrNone, ParseError<'i>>
     {
         // FIXME: remove early returns when lifetimes are non-lexical
         {
             let token = input.next()?;
             match *token {
                 Token::Dimension { value, ref unit, .. } if num_context.is_ok(context.parsing_mode, value) => {
@@ -1117,24 +1128,24 @@ impl LengthOrPercentageOrNone {
     }
 
     /// Parse a non-negative LengthOrPercentageOrNone, with quirks.
     #[inline]
     pub fn parse_non_negative_quirky<'i, 't>(context: &ParserContext,
                                              input: &mut Parser<'i, 't>,
                                              allow_quirks: AllowQuirks)
                                              -> Result<Self, ParseError<'i>> {
-        Self::parse_internal(context, input, AllowedLengthType::NonNegative, allow_quirks)
+        Self::parse_internal(context, input, AllowedNumericType::NonNegative, allow_quirks)
     }
 }
 
 impl Parse for LengthOrPercentageOrNone {
     #[inline]
     fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
-        Self::parse_internal(context, input, AllowedLengthType::All, AllowQuirks::No)
+        Self::parse_internal(context, input, AllowedNumericType::All, AllowQuirks::No)
     }
 }
 
 /// A wrapper of LengthOrPercentage, whose value must be >= 0.
 pub type NonNegativeLengthOrPercentage = NonNegative<LengthOrPercentage>;
 
 impl From<NoCalcLength> for NonNegativeLengthOrPercentage {
     #[inline]
--- a/servo/components/style/values/specified/position.rs
+++ b/servo/components/style/values/specified/position.rs
@@ -205,17 +205,18 @@ impl<S: Side> ToComputedValue for Positi
                         ComputedLengthOrPercentage::Calc(
                             CalcLengthOrPercentage::new(-length, Some(Percentage::hundred())))
                     },
                     ComputedLengthOrPercentage::Percentage(p) => {
                         ComputedLengthOrPercentage::Percentage(Percentage(1.0 - p.0))
                     },
                     ComputedLengthOrPercentage::Calc(calc) => {
                         let p = Percentage(1. - calc.percentage.map_or(0., |p| p.0));
-                        ComputedLengthOrPercentage::Calc(CalcLengthOrPercentage::new(-calc.unclamped_length(), Some(p)))
+                        let l = -calc.unclamped_length();
+                        ComputedLengthOrPercentage::Calc(CalcLengthOrPercentage::new(l, Some(p)))
                     },
                 }
             },
             PositionComponent::Side(_, Some(ref length)) |
             PositionComponent::Length(ref length) => {
                 length.to_computed_value(context)
             },
         }
--- a/servo/components/style/values/specified/text.rs
+++ b/servo/components/style/values/specified/text.rs
@@ -79,60 +79,62 @@ impl Parse for LineHeight {
     }
 }
 
 impl ToComputedValue for LineHeight {
     type ComputedValue = ComputedLineHeight;
 
     #[inline]
     fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
+        use values::computed::Length as ComputedLength;
         use 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))
             },
             GenericLineHeight::Length(ref non_negative_lop) => {
                 let result = match non_negative_lop.0 {
                     LengthOrPercentage::Length(NoCalcLength::Absolute(ref abs)) => {
-                        context.maybe_zoom_text(abs.to_computed_value(context).into())
+                        context.maybe_zoom_text(abs.to_computed_value(context))
                     }
                     LengthOrPercentage::Length(ref length) => {
-                        length.to_computed_value(context).into()
+                        length.to_computed_value(context)
                     },
                     LengthOrPercentage::Percentage(ref p) => {
                         FontRelativeLength::Em(p.0)
                             .to_computed_value(
                                 context,
                                 FontBaseSize::CurrentStyle,
-                            ).into()
+                            )
                     }
                     LengthOrPercentage::Calc(ref calc) => {
-                        let computed_calc = calc.to_computed_value_zoomed(context, FontBaseSize::CurrentStyle);
+                        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();
-                        computed_calc
+                        let absolute_length = computed_calc.unclamped_length().px();
+                        let pixel = computed_calc
                             .clamping_mode
-                            .clamp(absolute_length + font_relative_length)
-                            .into()
+                            .clamp(absolute_length + font_relative_length);
+                        ComputedLength::new(pixel)
                     }
                 };
-                GenericLineHeight::Length(result)
+                GenericLineHeight::Length(result.into())
             }
         }
     }
 
     #[inline]
     fn from_computed_value(computed: &Self::ComputedValue) -> Self {
         match *computed {
             GenericLineHeight::Normal => {
--- a/servo/components/style_traits/values.rs
+++ b/servo/components/style_traits/values.rs
@@ -464,73 +464,37 @@ macro_rules! __define_css_keyword_enum__
             }
         }
     }
 }
 
 /// Helper types for the handling of specified values.
 pub mod specified {
     use ParsingMode;
-    use app_units::Au;
-    use std::cmp;
-
-    /// Whether to allow negative lengths or not.
-    #[repr(u8)]
-    #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
-    #[derive(Clone, Copy, Debug, Eq, PartialEq)]
-    pub enum AllowedLengthType {
-        /// Allow all kind of lengths.
-        All,
-        /// Allow only non-negative lengths.
-        NonNegative
-    }
-
-    impl Default for AllowedLengthType {
-        #[inline]
-        fn default() -> Self {
-            AllowedLengthType::All
-        }
-    }
-
-    impl AllowedLengthType {
-        /// Whether value is valid for this allowed length type.
-        #[inline]
-        pub fn is_ok(&self, parsing_mode: ParsingMode, value: f32) -> bool {
-            if parsing_mode.allows_all_numeric_values() {
-                return true;
-            }
-            match *self {
-                AllowedLengthType::All => true,
-                AllowedLengthType::NonNegative => value >= 0.,
-            }
-        }
-
-        /// Clamp the value following the rules of this numeric type.
-        #[inline]
-        pub fn clamp(&self, val: Au) -> Au {
-            match *self {
-                AllowedLengthType::All => val,
-                AllowedLengthType::NonNegative => cmp::max(Au(0), val),
-            }
-        }
-    }
 
     /// Whether to allow negative lengths or not.
     #[repr(u8)]
     #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
     #[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd)]
     pub enum AllowedNumericType {
         /// Allow all kind of numeric values.
         All,
         /// Allow only non-negative numeric values.
         NonNegative,
         /// Allow only numeric values greater or equal to 1.0.
         AtLeastOne,
     }
 
+    impl Default for AllowedNumericType {
+        #[inline]
+        fn default() -> Self {
+            AllowedNumericType::All
+        }
+    }
+
     impl AllowedNumericType {
         /// Whether the value fits the rules of this numeric type.
         #[inline]
         pub fn is_ok(&self, parsing_mode: ParsingMode, val: f32) -> bool {
             if parsing_mode.allows_all_numeric_values() {
                 return true;
             }
             match *self {
--- a/servo/components/style_traits/viewport.rs
+++ b/servo/components/style_traits/viewport.rs
@@ -102,17 +102,17 @@ impl ToCss for Zoom {
 
 impl Zoom {
     /// Parse a zoom value per:
     ///
     /// https://drafts.csswg.org/css-device-adapt/#descdef-viewport-zoom
     pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Zoom, ParseError<'i>> {
         use PARSING_MODE_DEFAULT;
         use cssparser::Token;
-        use values::specified::AllowedLengthType::NonNegative;
+        use values::specified::AllowedNumericType::NonNegative;
 
         match *input.next()? {
             // TODO: This parse() method should take ParserContext as an
             // argument, and pass ParsingMode owned by the ParserContext to
             // is_ok() instead of using PARSING_MODE_DEFAULT directly.
             // In order to do so, we might want to move these stuff into style::stylesheets::viewport_rule.
             Token::Percentage { unit_value, .. } if NonNegative.is_ok(PARSING_MODE_DEFAULT, unit_value) => {
                 Ok(Zoom::Percentage(unit_value))
--- a/servo/tests/unit/style/animated_properties.rs
+++ b/servo/tests/unit/style/animated_properties.rs
@@ -1,13 +1,12 @@
 /* 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 app_units::Au;
 use cssparser::RGBA;
 use style::properties::longhands::transform::computed_value::ComputedOperation as TransformOperation;
 use style::properties::longhands::transform::computed_value::T as TransformList;
 use style::values::animated::{Animate, Procedure, ToAnimatedValue};
 use style::values::computed::Percentage;
 
 fn interpolate_rgba(from: RGBA, to: RGBA, progress: f64) -> RGBA {
     let from = from.to_animated_value();
@@ -60,52 +59,54 @@ fn test_rgba_color_interepolation_out_of
     assert_eq!(interpolate_rgba(RGBA::from_floats(1.0, 0.0, 0.0, 0.8),
                                 RGBA::from_floats(0.0, 1.0, 0.0, 0.2), 1.5),
                RGBA::from_floats(0.0, 0.0, 0.0, 0.0));
 }
 
 // Transform
 #[test]
 fn test_transform_interpolation_on_translate() {
-    use style::values::computed::{CalcLengthOrPercentage, LengthOrPercentage};
+    use style::values::computed::{CalcLengthOrPercentage, Length, LengthOrPercentage};
 
     let from = TransformList(Some(vec![
-        TransformOperation::Translate(LengthOrPercentage::Length(Au(0)),
-                                      LengthOrPercentage::Length(Au(100)),
-                                      Au(25))]));
+        TransformOperation::Translate(LengthOrPercentage::Length(Length::new(0.)),
+                                      LengthOrPercentage::Length(Length::new(100.)),
+                                      Length::new(25.))]));
     let to = TransformList(Some(vec![
-        TransformOperation::Translate(LengthOrPercentage::Length(Au(100)),
-                                      LengthOrPercentage::Length(Au(0)),
-                                      Au(75))]));
+        TransformOperation::Translate(LengthOrPercentage::Length(Length::new(100.)),
+                                      LengthOrPercentage::Length(Length::new(0.)),
+                                      Length::new(75.))]));
     assert_eq!(
         from.animate(&to, Procedure::Interpolate { progress: 0.5 }).unwrap(),
         TransformList(Some(vec![TransformOperation::Translate(
-            LengthOrPercentage::Length(Au(50)),
-            LengthOrPercentage::Length(Au(50)),
-            Au(50),
+            LengthOrPercentage::Length(Length::new(50.)),
+            LengthOrPercentage::Length(Length::new(50.)),
+            Length::new(50.),
         )]))
     );
 
     let from = TransformList(Some(vec![TransformOperation::Translate(
         LengthOrPercentage::Percentage(Percentage(0.5)),
         LengthOrPercentage::Percentage(Percentage(1.0)),
-        Au(25),
+        Length::new(25.),
     )]));
     let to = TransformList(Some(vec![
-        TransformOperation::Translate(LengthOrPercentage::Length(Au(100)),
-                                      LengthOrPercentage::Length(Au(50)),
-                                      Au(75))]));
+        TransformOperation::Translate(LengthOrPercentage::Length(Length::new(100.)),
+                                      LengthOrPercentage::Length(Length::new(50.)),
+                                      Length::new(75.))]));
     assert_eq!(
         from.animate(&to, Procedure::Interpolate { progress: 0.5 }).unwrap(),
         TransformList(Some(vec![TransformOperation::Translate(
             // calc(50px + 25%)
-            LengthOrPercentage::Calc(CalcLengthOrPercentage::new(Au(50), Some(Percentage(0.25)))),
+            LengthOrPercentage::Calc(CalcLengthOrPercentage::new(Length::new(50.),
+                                                                 Some(Percentage(0.25)))),
             // calc(25px + 50%)
-            LengthOrPercentage::Calc(CalcLengthOrPercentage::new(Au(25), Some(Percentage(0.5)))),
-            Au(50),
+            LengthOrPercentage::Calc(CalcLengthOrPercentage::new(Length::new(25.),
+                                                                 Some(Percentage(0.5)))),
+            Length::new(50.),
         )]))
     );
 }
 
 #[test]
 fn test_transform_interpolation_on_scale() {
     let from = TransformList(Some(vec![TransformOperation::Scale(1.0, 2.0, 1.0)]));
     let to = TransformList(Some(vec![TransformOperation::Scale(2.0, 4.0, 2.0)]));
@@ -145,24 +146,24 @@ fn test_transform_interpolation_on_skew(
             Angle::from_radians(50.0),
             Angle::from_radians(50.0),
         )]))
     );
 }
 
 #[test]
 fn test_transform_interpolation_on_mismatched_lists() {
-    use style::values::computed::{Angle, LengthOrPercentage, Percentage};
+    use style::values::computed::{Angle, Length, LengthOrPercentage};
 
     let from = TransformList(Some(vec![TransformOperation::Rotate(0.0, 0.0, 1.0,
                                                                   Angle::from_radians(100.0))]));
     let to = TransformList(Some(vec![
-        TransformOperation::Translate(LengthOrPercentage::Length(Au(100)),
-                                      LengthOrPercentage::Length(Au(0)),
-                                      Au(0))]));
+        TransformOperation::Translate(LengthOrPercentage::Length(Length::new(100.)),
+                                      LengthOrPercentage::Length(Length::new(0.)),
+                                      Length::new(0.))]));
     assert_eq!(
         from.animate(&to, Procedure::Interpolate { progress: 0.5 }).unwrap(),
         TransformList(Some(vec![TransformOperation::InterpolateMatrix {
             from_list: from.clone(),
             to_list: to.clone(),
             progress: Percentage(0.5),
         }]))
     );
--- a/servo/tests/unit/style/attr.rs
+++ b/servo/tests/unit/style/attr.rs
@@ -3,22 +3,22 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use app_units::Au;
 use style::attr::{AttrValue, LengthOrPercentageOrAuto, parse_length};
 use style::values::computed::{CalcLengthOrPercentage, Percentage};
 
 #[test]
 fn test_length_calc() {
-    let calc = CalcLengthOrPercentage::new(Au(10), Some(Percentage(0.2)));
+    let calc = CalcLengthOrPercentage::new(Au(10).into(), Some(Percentage(0.2)));
     assert_eq!(calc.to_used_value(Some(Au(10))), Some(Au(12)));
     assert_eq!(calc.to_used_value(Some(Au(0))), Some(Au(10)));
     assert_eq!(calc.to_used_value(None), None);
 
-    let calc = CalcLengthOrPercentage::new(Au(10), None);
+    let calc = CalcLengthOrPercentage::new(Au(10).into(), None);
     assert_eq!(calc.to_used_value(Some(Au(0))), Some(Au(10)));
     assert_eq!(calc.to_used_value(None), Some(Au(10)));
 }
 
 #[test]
 fn test_parse_double() {
     let value = String::from("432.5e2");
     match AttrValue::from_double(value, 0.0) {