diff --git a/components/gfx/font_context.rs b/components/gfx/font_context.rs index 289939ee9d5..67214cf5e40 100644 --- a/components/gfx/font_context.rs +++ b/components/gfx/font_context.rs @@ -116,7 +116,7 @@ impl FontContext { let layout_font_group_cache_key = LayoutFontGroupCacheKey { pointer: style.clone(), - size: style.font_size, + size: style.font_size.0, }; if let Some(ref cached_font_group) = self.layout_font_group_cache.get( &layout_font_group_cache_key) { @@ -146,7 +146,7 @@ impl FontContext { 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 && + cached_font.requested_pt_size == style.font_size.0 && cached_font.variant == style.font_variant_caps { fonts.push((*cached_font_ref).clone()); cache_hit = true; @@ -164,7 +164,7 @@ impl FontContext { Some(template_info) => { let layout_font = self.create_layout_font(template_info.font_template, desc.clone(), - style.font_size, + style.font_size.0, style.font_variant_caps, template_info.font_key .expect("No font key present!")); @@ -198,7 +198,7 @@ impl FontContext { 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 && + cached_font.requested_pt_size == style.font_size.0 && cached_font.variant == style.font_variant_caps { fonts.push(cached_font_entry.font.clone()); cache_hit = true; @@ -210,7 +210,7 @@ impl FontContext { 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, + style.font_size.0, style.font_variant_caps, template_info.font_key.expect("No font key present!")); match layout_font { diff --git a/components/layout/construct.rs b/components/layout/construct.rs index c863219941e..c1643c9f92c 100644 --- a/components/layout/construct.rs +++ b/components/layout/construct.rs @@ -1860,10 +1860,10 @@ impl ComputedValueUtils for ComputedValues { !padding.padding_right.is_definitely_zero() || !padding.padding_bottom.is_definitely_zero() || !padding.padding_left.is_definitely_zero() || - border.border_top_width != Au(0) || - border.border_right_width != Au(0) || - border.border_bottom_width != Au(0) || - border.border_left_width != Au(0) + 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) } } diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index 5e238a683fe..05dee791c93 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -1393,7 +1393,7 @@ impl FragmentDisplayListBuilding for Fragment { box_shadow.base.horizontal, box_shadow.base.vertical, )), - box_shadow.base.blur, + box_shadow.base.blur.0, box_shadow.spread, ); @@ -1408,7 +1408,7 @@ impl FragmentDisplayListBuilding for Fragment { box_bounds: *absolute_bounds, color: style.resolve_color(box_shadow.base.color).to_gfx_color(), offset: Vector2D::new(box_shadow.base.horizontal, box_shadow.base.vertical), - blur_radius: box_shadow.base.blur, + blur_radius: box_shadow.base.blur.0, spread_radius: box_shadow.spread, border_radius: model::specified_border_radius(style.get_border() .border_top_left_radius, @@ -1577,7 +1577,7 @@ impl FragmentDisplayListBuilding for Fragment { clip: &Rect) { use style::values::Either; - let width = style.get_outline().outline_width; + let width = style.get_outline().outline_width.0; if width == Au(0) { return } @@ -2054,7 +2054,7 @@ impl FragmentDisplayListBuilding for Fragment { let effects = self.style().get_effects(); let mut filters = effects.filter.0.clone(); if effects.opacity != 1.0 { - filters.push(Filter::Opacity(effects.opacity)) + filters.push(Filter::Opacity(effects.opacity.into())) } let context_type = match mode { @@ -2129,7 +2129,7 @@ impl FragmentDisplayListBuilding for Fragment { for shadow in text_shadows.iter().rev() { state.add_display_item(DisplayItem::PushTextShadow(box PushTextShadowDisplayItem { base: base.clone(), - blur_radius: shadow.blur, + blur_radius: shadow.blur.0, offset: Vector2D::new(shadow.horizontal, shadow.vertical), color: self.style().resolve_color(shadow.color).to_gfx_color(), })); diff --git a/components/layout/flex.rs b/components/layout/flex.rs index 353c939f58b..577e9a167de 100644 --- a/components/layout/flex.rs +++ b/components/layout/flex.rs @@ -137,8 +137,8 @@ impl FlexItem { min_size: Au(0), max_size: MAX_AU, index: index, - flex_grow: flex_grow, - flex_shrink: flex_shrink, + flex_grow: flex_grow.into(), + flex_shrink: flex_shrink.into(), order: order, is_frozen: false, is_strut: false diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs index bd7d06be627..fd2d5698efd 100644 --- a/components/layout/fragment.rs +++ b/components/layout/fragment.rs @@ -2570,13 +2570,13 @@ impl Fragment { // 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 * BLUR_INFLATION_FACTOR; + let inflation = box_shadow.spread + box_shadow.base.blur.0 * 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; + let outline_width = self.style.get_outline().outline_width.0; if outline_width != Au(0) { overflow.paint = overflow.paint.union(&border_box.inflate(outline_width, outline_width)) diff --git a/components/layout/multicol.rs b/components/layout/multicol.rs index 3321faae926..8a1b3bee6ee 100644 --- a/components/layout/multicol.rs +++ b/components/layout/multicol.rs @@ -98,20 +98,20 @@ impl Flow for MulticolFlow { let column_style = self.block_flow.fragment.style.get_column(); let column_gap = match column_style.column_gap { - Either::First(len) => len, - Either::Second(_normal) => self.block_flow.fragment.style.get_font().font_size, + Either::First(len) => len.0, + Either::Second(_normal) => self.block_flow.fragment.style.get_font().font_size.0, }; let mut column_count; if let Either::First(column_width) = column_style.column_width { column_count = - max(1, (content_inline_size + column_gap).0 / (column_width + column_gap).0); + max(1, (content_inline_size + column_gap).0 / (column_width.0 + column_gap).0); if let Either::First(specified_column_count) = column_style.column_count { - column_count = min(column_count, specified_column_count as i32); + column_count = min(column_count, specified_column_count.0 as i32); } } else { column_count = match column_style.column_count { - Either::First(n) => n, + Either::First(n) => n.0, _ => unreachable!(), } } diff --git a/components/layout/query.rs b/components/layout/query.rs index fd9a97f44cc..5803a247e19 100644 --- a/components/layout/query.rs +++ b/components/layout/query.rs @@ -450,10 +450,10 @@ impl FragmentBorderBoxIterator for FragmentLocatingFragmentIterator { border_left_width: left_width, .. } = *fragment.style.get_border(); - self.client_rect.origin.y = top_width.to_px(); - self.client_rect.origin.x = left_width.to_px(); - self.client_rect.size.width = (border_box.size.width - left_width - right_width).to_px(); - self.client_rect.size.height = (border_box.size.height - top_width - bottom_width).to_px(); + 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(); } fn should_process(&mut self, fragment: &Fragment) -> bool { @@ -476,10 +476,10 @@ impl FragmentBorderBoxIterator for UnioningFragmentScrollAreaIterator { border_left_width: left_border, .. } = *fragment.style.get_border(); - let right_padding = (border_box.size.width - right_border - left_border).to_px(); - let bottom_padding = (border_box.size.height - bottom_border - top_border).to_px(); - let top_padding = top_border.to_px(); - let left_padding = left_border.to_px(); + 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(); match self.level { Some(start_level) if level <= start_level => { self.is_child = false; } diff --git a/components/layout/table.rs b/components/layout/table.rs index 7010acf1b87..dea2b590b27 100644 --- a/components/layout/table.rs +++ b/components/layout/table.rs @@ -27,7 +27,7 @@ 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; +use style::values::computed::{LengthOrPercentageOrAuto, NonNegativeAu}; use table_row::{self, CellIntrinsicInlineSize, CollapsedBorder, CollapsedBorderProvenance}; use table_row::TableRowFlow; use table_wrapper::TableLayout; @@ -190,8 +190,8 @@ impl TableFlow { border_collapse::T::separate => style.get_inheritedtable().border_spacing, border_collapse::T::collapse => { border_spacing::T { - horizontal: Au(0), - vertical: Au(0), + horizontal: NonNegativeAu::zero(), + vertical: NonNegativeAu::zero(), } } } @@ -202,7 +202,7 @@ impl TableFlow { if num_columns == 0 { return Au(0); } - self.spacing().horizontal * (num_columns as i32 + 1) + self.spacing().horizontal.0 * (num_columns as i32 + 1) } } @@ -469,7 +469,7 @@ impl Flow for TableFlow { fn assign_block_size(&mut self, _: &LayoutContext) { debug!("assign_block_size: assigning block_size for table"); - let vertical_spacing = self.spacing().vertical; + let vertical_spacing = self.spacing().vertical.0; self.block_flow.assign_block_size_for_table_like_flow(vertical_spacing) } diff --git a/components/layout/table_row.rs b/components/layout/table_row.rs index e960290bdd2..06040446ddc 100644 --- a/components/layout/table_row.rs +++ b/components/layout/table_row.rs @@ -25,7 +25,7 @@ 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}; +use style::values::computed::{Color, LengthOrPercentageOrAuto, NonNegativeAu}; use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize, InternalTable, VecExt}; use table_cell::{CollapsedBordersForCell, TableCellFlow}; @@ -93,8 +93,8 @@ impl TableRowFlow { column_computed_inline_sizes: Vec::new(), incoming_rowspan: Vec::new(), spacing: border_spacing::T { - horizontal: Au(0), - vertical: Au(0), + horizontal: NonNegativeAu::zero(), + vertical: NonNegativeAu::zero(), }, table_writing_mode: writing_mode, preliminary_collapsed_borders: CollapsedBordersForRow::new(), @@ -395,7 +395,7 @@ impl Flow for TableRowFlow { None => break, }; column_computed_inline_size.size = column_computed_inline_size.size + - extra_column_computed_inline_size.size + self.spacing.horizontal; + extra_column_computed_inline_size.size + self.spacing.horizontal.0; col += 1; } @@ -616,7 +616,7 @@ impl CollapsedBorder { -> CollapsedBorder { CollapsedBorder { style: css_style.get_border().border_top_style, - width: css_style.get_border().border_top_width, + width: css_style.get_border().border_top_width.0, color: css_style.get_border().border_top_color, provenance: provenance, } @@ -628,7 +628,7 @@ impl CollapsedBorder { -> CollapsedBorder { CollapsedBorder { style: css_style.get_border().border_right_style, - width: css_style.get_border().border_right_width, + width: css_style.get_border().border_right_width.0, color: css_style.get_border().border_right_color, provenance: provenance, } @@ -640,7 +640,7 @@ impl CollapsedBorder { -> CollapsedBorder { CollapsedBorder { style: css_style.get_border().border_bottom_style, - width: css_style.get_border().border_bottom_width, + width: css_style.get_border().border_bottom_width.0, color: css_style.get_border().border_bottom_color, provenance: provenance, } @@ -652,7 +652,7 @@ impl CollapsedBorder { -> CollapsedBorder { CollapsedBorder { style: css_style.get_border().border_left_style, - width: css_style.get_border().border_left_width, + width: css_style.get_border().border_left_width.0, color: css_style.get_border().border_left_color, provenance: provenance, } @@ -818,7 +818,7 @@ fn set_inline_position_of_child_flow( 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, + None => border_spacing.horizontal.0, }; if reverse_column_order { *inline_end_margin_edge += column_inline_size + border_inline_size; @@ -873,9 +873,9 @@ fn set_inline_position_of_child_flow( None => { // Take spacing into account. if reverse_column_order { - *inline_end_margin_edge += border_spacing.horizontal; + *inline_end_margin_edge += border_spacing.horizontal.0; } else { - *inline_start_margin_edge += border_spacing.horizontal; + *inline_start_margin_edge += border_spacing.horizontal.0; } } } diff --git a/components/layout/table_rowgroup.rs b/components/layout/table_rowgroup.rs index b609276f7a2..02c1b49da2b 100644 --- a/components/layout/table_rowgroup.rs +++ b/components/layout/table_rowgroup.rs @@ -21,6 +21,7 @@ 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 table::{ColumnIntrinsicInlineSize, InternalTable, TableLikeFlow}; /// A table formatting context. @@ -55,8 +56,8 @@ impl TableRowGroupFlow { block_flow: BlockFlow::from_fragment(fragment), column_intrinsic_inline_sizes: Vec::new(), spacing: border_spacing::T { - horizontal: Au(0), - vertical: Au(0), + horizontal: NonNegativeAu::zero(), + vertical: NonNegativeAu::zero(), }, collapsed_inline_direction_border_widths_for_table: Vec::new(), collapsed_block_direction_border_widths_for_table: Vec::new(), @@ -161,7 +162,7 @@ impl Flow for TableRowGroupFlow { 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) + self.block_flow.assign_block_size_for_table_like_flow(self.spacing.vertical.0) } fn compute_absolute_position(&mut self, layout_context: &LayoutContext) { diff --git a/components/layout/text.rs b/components/layout/text.rs index 6e1c7b2a43a..f1c7d40515d 100644 --- a/components/layout/text.rs +++ b/components/layout/text.rs @@ -446,11 +446,11 @@ pub fn font_metrics_for_style(font_context: &mut FontContext, font_style: ::Serv /// 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; + let font_size = style.get_font().font_size.0; match style.get_inheritedtext().line_height { LineHeight::Normal => metrics.line_gap, - LineHeight::Number(l) => font_size.scale_by(l), - LineHeight::Length(l) => l + LineHeight::Number(l) => font_size.scale_by(l.0), + LineHeight::Length(l) => l.0 } } diff --git a/components/layout/webrender_helpers.rs b/components/layout/webrender_helpers.rs index 13bde487675..6b8b334d52d 100644 --- a/components/layout/webrender_helpers.rs +++ b/components/layout/webrender_helpers.rs @@ -190,15 +190,15 @@ impl ToFilterOps for Vec { 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.to_f32_px())), - GenericFilter::Brightness(amount) => result.push(webrender_api::FilterOp::Brightness(amount)), - GenericFilter::Contrast(amount) => result.push(webrender_api::FilterOp::Contrast(amount)), - GenericFilter::Grayscale(amount) => result.push(webrender_api::FilterOp::Grayscale(amount)), + GenericFilter::Blur(radius) => result.push(webrender_api::FilterOp::Blur(radius.0.to_f32_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)), - GenericFilter::Opacity(amount) => result.push(webrender_api::FilterOp::Opacity(amount.into())), - GenericFilter::Saturate(amount) => result.push(webrender_api::FilterOp::Saturate(amount)), - GenericFilter::Sepia(amount) => result.push(webrender_api::FilterOp::Sepia(amount)), + 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)), GenericFilter::DropShadow(ref shadow) => match *shadow {}, } } diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 59db577c4eb..328dd76e822 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -548,7 +548,7 @@ impl LayoutElementHelpers for LayoutJS { shared_lock, PropertyDeclaration::BorderSpacing( Box::new(border_spacing::SpecifiedValue { - horizontal: width_value, + horizontal: width_value.into(), vertical: None, })))); } diff --git a/components/style/gecko/media_queries.rs b/components/style/gecko/media_queries.rs index babefa95ebb..a7ba27d8414 100644 --- a/components/style/gecko/media_queries.rs +++ b/components/style/gecko/media_queries.rs @@ -69,7 +69,8 @@ impl Device { Device { pres_context: pres_context, default_values: ComputedValues::default_values(unsafe { &*pres_context }), - root_font_size: AtomicIsize::new(font_size::get_initial_value().0 as isize), // FIXME(bz): Seems dubious? + // FIXME(bz): Seems dubious? + root_font_size: AtomicIsize::new(font_size::get_initial_value().value() as isize), used_root_font_size: AtomicBool::new(false), used_viewport_size: AtomicBool::new(false), } diff --git a/components/style/gecko/values.rs b/components/style/gecko/values.rs index a4815222409..9d961ee18c3 100644 --- a/components/style/gecko/values.rs +++ b/components/style/gecko/values.rs @@ -19,8 +19,9 @@ use values::{Auto, Either, ExtremumLength, None_, Normal}; use values::computed::{Angle, LengthOrPercentage, LengthOrPercentageOrAuto}; use values::computed::{LengthOrPercentageOrNone, Number, NumberOrPercentage}; use values::computed::{MaxLength, MozLength, Percentage}; +use values::computed::{NonNegativeAu, NonNegativeLengthOrPercentage, NonNegativeNumber}; use values::computed::basic_shape::ShapeRadius as ComputedShapeRadius; -use values::generics::CounterStyleOrNone; +use values::generics::{CounterStyleOrNone, NonNegative}; use values::generics::basic_shape::ShapeRadius; use values::generics::gecko::ScrollSnapPoint; use values::generics::grid::{TrackBreadth, TrackKeyword}; @@ -121,6 +122,16 @@ impl GeckoStyleCoordConvertible for LengthOrPercentage { } } +impl GeckoStyleCoordConvertible for NonNegativeLengthOrPercentage { + fn to_gecko_style_coord(&self, coord: &mut T) { + self.0.to_gecko_style_coord(coord); + } + + fn from_gecko_style_coord(coord: &T) -> Option { + LengthOrPercentage::from_gecko_style_coord(coord).map(NonNegative::) + } +} + impl GeckoStyleCoordConvertible for Au { fn to_gecko_style_coord(&self, coord: &mut T) { coord.set_value(CoordDataValue::Coord(self.0)); @@ -134,6 +145,26 @@ impl GeckoStyleCoordConvertible for Au { } } +impl GeckoStyleCoordConvertible for NonNegativeAu { + fn to_gecko_style_coord(&self, coord: &mut T) { + self.0.to_gecko_style_coord(coord); + } + + fn from_gecko_style_coord(coord: &T) -> Option { + Au::from_gecko_style_coord(coord).map(NonNegative::) + } +} + +impl GeckoStyleCoordConvertible for NonNegativeNumber { + fn to_gecko_style_coord(&self, coord: &mut T) { + self.0.to_gecko_style_coord(coord); + } + + fn from_gecko_style_coord(coord: &T) -> Option { + Number::from_gecko_style_coord(coord).map(NonNegative::) + } +} + impl GeckoStyleCoordConvertible for LengthOrPercentageOrAuto { fn to_gecko_style_coord(&self, coord: &mut T) { let value = match *self { diff --git a/components/style/gecko_bindings/sugar/ns_css_shadow_item.rs b/components/style/gecko_bindings/sugar/ns_css_shadow_item.rs index 0efebc94c19..0111256d5d1 100644 --- a/components/style/gecko_bindings/sugar/ns_css_shadow_item.rs +++ b/components/style/gecko_bindings/sugar/ns_css_shadow_item.rs @@ -27,7 +27,7 @@ impl nsCSSShadowItem { color: Color::rgba(convert_nscolor_to_rgba(self.mColor)), horizontal: Au(self.mXOffset), vertical: Au(self.mYOffset), - blur: Au(self.mRadius), + blur: Au(self.mRadius).into(), }, spread: Au(self.mSpread), inset: self.mInset, @@ -39,7 +39,7 @@ impl nsCSSShadowItem { pub fn set_from_simple_shadow(&mut self, shadow: SimpleShadow) { self.mXOffset = shadow.horizontal.0; self.mYOffset = shadow.vertical.0; - self.mRadius = shadow.blur.0; + self.mRadius = shadow.blur.value(); self.mSpread = 0; self.mInset = false; if shadow.color.is_currentcolor() { @@ -62,7 +62,7 @@ impl nsCSSShadowItem { color: Color::rgba(convert_nscolor_to_rgba(self.mColor)), horizontal: Au(self.mXOffset), vertical: Au(self.mYOffset), - blur: Au(self.mRadius), + blur: Au(self.mRadius).into(), } } } diff --git a/components/style/matching.rs b/components/style/matching.rs index 72e110ce1a2..d16dee6f3a1 100644 --- a/components/style/matching.rs +++ b/components/style/matching.rs @@ -534,7 +534,7 @@ pub trait MatchMethods : TElement { 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); + device.set_root_font_size(new_font_size.0); // If the root font-size changed since last time, and something // in the document did use rem units, ensure we recascade the // entire tree. diff --git a/components/style/properties/data.py b/components/style/properties/data.py index d6aa4a016ad..7e08b079ad8 100644 --- a/components/style/properties/data.py +++ b/components/style/properties/data.py @@ -157,7 +157,7 @@ class Longhand(object): allowed_in_keyframe_block=True, cast_type='u8', has_uncacheable_values=False, logical=False, alias=None, extra_prefixes=None, boxed=False, flags=None, allowed_in_page_rule=False, allow_quirks=False, ignored_when_colors_disabled=False, - gecko_pref_ident=None, vector=False): + gecko_pref_ident=None, vector=False, need_animatable=False): self.name = name if not spec: raise TypeError("Spec should be specified for %s" % name) diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index de2359193dc..ce8861cc5a9 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -62,7 +62,7 @@ use std::mem::{forget, uninitialized, transmute, zeroed}; use std::{cmp, ops, ptr}; use stylesheets::{MallocSizeOfWithRepeats, SizeOfState}; use values::{self, Auto, CustomIdent, Either, KeyframesName}; -use values::computed::ToComputedValue; +use values::computed::{NonNegativeAu, ToComputedValue}; use values::computed::effects::{BoxShadow, Filter, SimpleShadow}; use values::computed::length::Percentage; use computed_values::border_style; @@ -397,14 +397,14 @@ impl ${style_struct.gecko_struct_name} { <%def name="impl_simple_setter(ident, gecko_ffi_name)"> #[allow(non_snake_case)] pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) { - ${set_gecko_property(gecko_ffi_name, "v")} + ${set_gecko_property(gecko_ffi_name, "From::from(v)")} } <%def name="impl_simple_clone(ident, gecko_ffi_name)"> #[allow(non_snake_case)] pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T { - self.gecko.${gecko_ffi_name} + From::from(self.gecko.${gecko_ffi_name}) } @@ -616,7 +616,7 @@ def set_gecko_property(ffi_name, expr): }; match length { Either::First(number) => - self.gecko.${gecko_ffi_name}.set_value(CoordDataValue::Factor(number)), + self.gecko.${gecko_ffi_name}.set_value(CoordDataValue::Factor(From::from(number))), Either::Second(lop) => self.gecko.${gecko_ffi_name}.set(lop), } } @@ -641,10 +641,10 @@ def set_gecko_property(ffi_name, expr): return SVGLength::ContextValue; } let length = match self.gecko.${gecko_ffi_name}.as_value() { - CoordDataValue::Factor(number) => Either::First(number), - CoordDataValue::Coord(coord) => Either::Second(LengthOrPercentage::Length(Au(coord))), - CoordDataValue::Percent(p) => Either::Second(LengthOrPercentage::Percentage(Percentage(p))), - CoordDataValue::Calc(calc) => Either::Second(LengthOrPercentage::Calc(calc.into())), + CoordDataValue::Factor(number) => Either::First(From::from(number)), + CoordDataValue::Coord(coord) => Either::Second(From::from(LengthOrPercentage::Length(Au(coord)))), + CoordDataValue::Percent(p) => Either::Second(From::from(LengthOrPercentage::Percentage(Percentage(p)))), + CoordDataValue::Calc(calc) => Either::Second(From::from(LengthOrPercentage::Calc(calc.into()))), _ => unreachable!("Unexpected coordinate {:?} in ${ident}", self.gecko.${gecko_ffi_name}.as_value()), }; @@ -803,15 +803,16 @@ def set_gecko_property(ffi_name, expr): } -<%def name="impl_app_units(ident, gecko_ffi_name, need_clone, inherit_from=None, round_to_pixels=False)"> +<%def name="impl_non_negative_app_units(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, au_per_device_px).0 + round_border_to_device_pixels(v.0, au_per_device_px).0 % else: - v.0 + v.value() % endif }; @@ -847,7 +848,7 @@ def set_gecko_property(ffi_name, expr): %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 @@ -1088,6 +1089,9 @@ impl Clone for ${style_struct.gecko_struct_name} { predefined_types = { "length::LengthOrAuto": impl_style_coord, "length::LengthOrNormal": impl_style_coord, + "length::NonNegativeLengthOrAuto": impl_style_coord, + "length::NonNegativeLengthOrNormal": impl_style_coord, + "GreaterThanOrEqualToOneNumber": impl_simple, "Length": impl_absolute_length, "Position": impl_position, "LengthOrPercentage": impl_style_coord, @@ -1097,6 +1101,8 @@ impl Clone for ${style_struct.gecko_struct_name} { "LengthOrNormal": impl_style_coord, "MaxLength": impl_style_coord, "MozLength": impl_style_coord, + "NonNegativeLengthOrPercentage": impl_style_coord, + "NonNegativeNumber": impl_simple, "Number": impl_simple, "Integer": impl_simple, "Opacity": impl_simple, @@ -1105,6 +1111,7 @@ impl Clone for ${style_struct.gecko_struct_name} { "SVGLength": impl_svg_length, "SVGOpacity": impl_svg_opacity, "SVGPaint": impl_svg_paint, + "SVGWidth": impl_svg_length, "UrlOrNone": impl_css_url, } @@ -1310,11 +1317,11 @@ fn static_assert() { <% impl_color("border_%s_color" % side.ident, "(mBorderColor)[%s]" % side.index, need_clone=True) %> - <% impl_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_app_units("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 @@ -2052,9 +2059,9 @@ fn static_assert() { } } - <% impl_app_units("outline_width", "mActualOutlineWidth", - inherit_from="mOutlineWidth", - need_clone=True, round_to_pixels=True) %> + <% impl_non_negative_app_units("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("_", ""), @@ -2263,15 +2270,15 @@ fn static_assert() { } pub fn set_font_size(&mut self, v: longhands::font_size::computed_value::T) { - self.gecko.mSize = v.0; - self.gecko.mScriptUnconstrainedSize = v.0; + self.gecko.mSize = v.value(); + self.gecko.mScriptUnconstrainedSize = v.value(); } /// 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 { + device: &Device) -> Option { let (adjusted_size, adjusted_unconstrained_size) = self.calculate_script_level_size(parent, device); // In this case, we have been unaffected by scriptminsize, ignore it @@ -2281,9 +2288,9 @@ fn static_assert() { self.fixup_font_min_size(device); None } else { - self.gecko.mSize = v.0; + self.gecko.mSize = v.value(); self.fixup_font_min_size(device); - Some(Au(parent.gecko.mScriptUnconstrainedSize)) + Some(Au(parent.gecko.mScriptUnconstrainedSize).into()) } } @@ -2291,8 +2298,8 @@ fn static_assert() { unsafe { bindings::Gecko_nsStyleFont_FixupMinFontSize(&mut self.gecko, device.pres_context()) } } - pub fn apply_unconstrained_font_size(&mut self, v: Au) { - self.gecko.mScriptUnconstrainedSize = v.0; + pub fn apply_unconstrained_font_size(&mut self, v: NonNegativeAu) { + self.gecko.mScriptUnconstrainedSize = v.value(); } /// Calculates the constrained and unconstrained font sizes to be inherited @@ -2402,7 +2409,7 @@ fn static_assert() { /// /// Returns true if the inherited keyword size was actually used pub fn inherit_font_size_from(&mut self, parent: &Self, - kw_inherited_size: Option, + kw_inherited_size: Option, device: &Device) -> bool { let (adjusted_size, adjusted_unconstrained_size) = self.calculate_script_level_size(parent, device); @@ -2428,9 +2435,9 @@ fn static_assert() { false } else if let Some(size) = kw_inherited_size { // Parent element was a keyword-derived size. - self.gecko.mSize = size.0; + self.gecko.mSize = size.value(); // MathML constraints didn't apply here, so we can ignore this. - self.gecko.mScriptUnconstrainedSize = size.0; + self.gecko.mScriptUnconstrainedSize = size.value(); self.fixup_font_min_size(device); true } else { @@ -2444,7 +2451,7 @@ fn static_assert() { } pub fn clone_font_size(&self) -> longhands::font_size::computed_value::T { - Au(self.gecko.mSize) + Au(self.gecko.mSize).into() } pub fn set_font_weight(&mut self, v: longhands::font_weight::computed_value::T) { @@ -4420,11 +4427,11 @@ fn static_assert() { match servo { % for func in FILTER_FUNCTIONS: ${func}(factor) => fill_filter(NS_STYLE_FILTER_${func.upper()}, - CoordDataValue::Factor(factor), + CoordDataValue::Factor(factor.0), gecko_filter), % endfor Blur(length) => fill_filter(NS_STYLE_FILTER_BLUR, - CoordDataValue::Coord(length.0), + CoordDataValue::Coord(length.value()), gecko_filter), HueRotate(angle) => fill_filter(NS_STYLE_FILTER_HUE_ROTATE, @@ -4492,7 +4499,7 @@ fn static_assert() { }, % endfor NS_STYLE_FILTER_BLUR => { - filters.push(Filter::Blur(Au::from_gecko_style_coord( + filters.push(Filter::Blur(NonNegativeAu::from_gecko_style_coord( &filter.mFilterParameter).unwrap())); }, NS_STYLE_FILTER_HUE_ROTATE => { @@ -4584,8 +4591,8 @@ fn static_assert() { skip_longhands="border-spacing"> pub fn set_border_spacing(&mut self, v: longhands::border_spacing::computed_value::T) { - self.gecko.mBorderSpacingCol = v.horizontal.0; - self.gecko.mBorderSpacingRow = v.vertical.0; + self.gecko.mBorderSpacingCol = v.horizontal.value(); + self.gecko.mBorderSpacingRow = v.vertical.value(); } pub fn copy_border_spacing_from(&mut self, other: &Self) { @@ -4599,8 +4606,8 @@ fn static_assert() { pub fn clone_border_spacing(&self) -> longhands::border_spacing::computed_value::T { longhands::border_spacing::computed_value::T { - horizontal: Au(self.gecko.mBorderSpacingCol), - vertical: Au(self.gecko.mBorderSpacingRow) + horizontal: Au(self.gecko.mBorderSpacingCol).into(), + vertical: Au(self.gecko.mBorderSpacingRow).into() } } @@ -4645,8 +4652,8 @@ fn static_assert() { // 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.0), - LineHeight::Number(val) => CoordDataValue::Factor(val), + LineHeight::Length(val) => CoordDataValue::Coord(val.value()), + LineHeight::Number(val) => CoordDataValue::Factor(val.0), LineHeight::MozBlockHeight => CoordDataValue::Enumerated(structs::NS_STYLE_LINE_HEIGHT_BLOCK_HEIGHT), }; @@ -4657,8 +4664,8 @@ fn static_assert() { use values::generics::text::LineHeight; return match self.gecko.mLineHeight.as_value() { CoordDataValue::Normal => LineHeight::Normal, - CoordDataValue::Coord(coord) => LineHeight::Length(Au(coord)), - CoordDataValue::Factor(n) => LineHeight::Number(n), + CoordDataValue::Coord(coord) => LineHeight::Length(Au(coord).into()), + CoordDataValue::Factor(n) => LineHeight::Number(n.into()), CoordDataValue::Enumerated(val) if val == structs::NS_STYLE_LINE_HEIGHT_BLOCK_HEIGHT => LineHeight::MozBlockHeight, _ => panic!("this should not happen"), @@ -4792,18 +4799,20 @@ fn static_assert() { }) } - <%call expr="impl_app_units('_webkit_text_stroke_width', 'mWebkitTextStrokeWidth', need_clone=True)"> + <%call expr="impl_non_negative_app_units('_webkit_text_stroke_width', + 'mWebkitTextStrokeWidth', + need_clone=True)"> #[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(number) => { - self.gecko.mTabSize.set_value(CoordDataValue::Factor(number)); + Either::Second(non_negative_number) => { + self.gecko.mTabSize.set_value(CoordDataValue::Factor(non_negative_number.0)); } - Either::First(au) => { - self.gecko.mTabSize.set(au); + Either::First(non_negative_au) => { + self.gecko.mTabSize.set(non_negative_au.0); } } } @@ -4813,8 +4822,8 @@ fn static_assert() { use values::Either; match self.gecko.mTabSize.as_value() { - CoordDataValue::Coord(coord) => Either::First(Au(coord)), - CoordDataValue::Factor(number) => Either::Second(number), + CoordDataValue::Coord(coord) => Either::First(Au(coord).into()), + CoordDataValue::Factor(number) => Either::Second(From::from(number)), _ => unreachable!(), } } @@ -5151,7 +5160,7 @@ clip-path } for (mut gecko, servo) in self.gecko.mStrokeDasharray.iter_mut().zip(v) { match servo { - Either::First(number) => gecko.set_value(CoordDataValue::Factor(number)), + Either::First(number) => gecko.set_value(CoordDataValue::Factor(number.into())), Either::Second(lop) => gecko.set(lop), } } @@ -5191,13 +5200,13 @@ clip-path let mut vec = vec![]; for gecko in self.gecko.mStrokeDasharray.iter() { match gecko.as_value() { - CoordDataValue::Factor(number) => vec.push(Either::First(number)), + CoordDataValue::Factor(number) => vec.push(Either::First(number.into())), CoordDataValue::Coord(coord) => - vec.push(Either::Second(LengthOrPercentage::Length(Au(coord)))), + vec.push(Either::Second(LengthOrPercentage::Length(Au(coord)).into())), CoordDataValue::Percent(p) => - vec.push(Either::Second(LengthOrPercentage::Percentage(Percentage(p)))), + vec.push(Either::Second(LengthOrPercentage::Percentage(Percentage(p)).into())), CoordDataValue::Calc(calc) => - vec.push(Either::Second(LengthOrPercentage::Calc(calc.into()))), + vec.push(Either::Second(LengthOrPercentage::Calc(calc.into()).into())), _ => unreachable!(), } } @@ -5423,8 +5432,8 @@ clip-path use gecko_bindings::structs::{NS_STYLE_COLUMN_COUNT_AUTO, nsStyleColumn_kMaxColumnCount}; self.gecko.mColumnCount = match v { - Either::First(number) => unsafe { - cmp::min(number as u32, nsStyleColumn_kMaxColumnCount) + Either::First(integer) => unsafe { + cmp::min(integer.0 as u32, nsStyleColumn_kMaxColumnCount) }, Either::Second(Auto) => NS_STYLE_COLUMN_COUNT_AUTO }; @@ -5437,14 +5446,14 @@ clip-path if self.gecko.mColumnCount != NS_STYLE_COLUMN_COUNT_AUTO { debug_assert!((self.gecko.mColumnCount as i32) >= 0 && (self.gecko.mColumnCount as i32) < i32::max_value()); - Either::First(self.gecko.mColumnCount as i32) + Either::First((self.gecko.mColumnCount as i32).into()) } else { Either::Second(Auto) } } - <% impl_app_units("column_rule_width", "mColumnRuleWidth", need_clone=True, - round_to_pixels=True) %> + <% impl_non_negative_app_units("column_rule_width", "mColumnRuleWidth", need_clone=True, + round_to_pixels=True) %> <%self:impl_trait style_struct_name="Counters" diff --git a/components/style/properties/helpers.mako.rs b/components/style/properties/helpers.mako.rs index 4e285bf3092..82eeb653e16 100644 --- a/components/style/properties/helpers.mako.rs +++ b/components/style/properties/helpers.mako.rs @@ -76,8 +76,10 @@ We assume that the default/initial value is an empty vector for these. `initial_value` need not be defined for these. -<%def name="vector_longhand(name, animation_value_type=None, allow_empty=False, separator='Comma', **kwargs)"> - <%call expr="longhand(name, animation_value_type=animation_value_type, vector=True, **kwargs)"> +<%def name="vector_longhand(name, animation_value_type=None, allow_empty=False, separator='Comma', + need_animatable=False, **kwargs)"> + <%call expr="longhand(name, animation_value_type=animation_value_type, vector=True, + need_animatable=need_animatable, **kwargs)"> #[allow(unused_imports)] use smallvec::SmallVec; use std::fmt; @@ -127,7 +129,7 @@ % endif ); - % if animation_value_type == "ComputedValue": + % if need_animatable or animation_value_type == "ComputedValue": use properties::animated_properties::Animatable; use values::animated::ToAnimatedZero; diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs index d6e20b26cce..19ca7e49e7a 100644 --- a/components/style/properties/helpers/animated_properties.mako.rs +++ b/components/style/properties/helpers/animated_properties.mako.rs @@ -16,8 +16,11 @@ use euclid::{Point2D, Size2D}; #[cfg(feature = "gecko")] use gecko_string_cache::Atom; use properties::{CSSWideKeyword, PropertyDeclaration}; use properties::longhands; +use properties::longhands::background_size::computed_value::T as BackgroundSizeList; +use properties::longhands::border_spacing::computed_value::T as BorderSpacing; use properties::longhands::font_weight::computed_value::T as FontWeight; use properties::longhands::font_stretch::computed_value::T as FontStretch; +use properties::longhands::line_height::computed_value::T as LineHeight; use properties::longhands::transform::computed_value::ComputedMatrix; use properties::longhands::transform::computed_value::ComputedOperation as TransformOperation; use properties::longhands::transform::computed_value::T as TransformList; @@ -43,6 +46,10 @@ use values::computed::{Angle, LengthOrPercentageOrAuto, LengthOrPercentageOrNone use values::computed::{BorderCornerRadius, ClipRect}; use values::computed::{CalcLengthOrPercentage, Color, Context, ComputedValueAsSpecified}; use values::computed::{LengthOrPercentage, MaxLength, MozLength, Percentage, ToComputedValue}; +use values::computed::{NonNegativeAu, NonNegativeNumber, PositiveIntegerOrAuto}; +use values::computed::length::{NonNegativeLengthOrAuto, NonNegativeLengthOrNormal}; +use values::computed::length::NonNegativeLengthOrPercentage; +use values::generics::{GreaterThanOrEqualToOne, NonNegative}; use values::generics::border::BorderCornerRadius as GenericBorderCornerRadius; use values::generics::effects::Filter; use values::generics::position as generic_position; @@ -777,6 +784,7 @@ impl ToAnimatedZero for AnimationValue { impl RepeatableListAnimatable for LengthOrPercentage {} impl RepeatableListAnimatable for Either {} +impl RepeatableListAnimatable for Either {} macro_rules! repeated_vec_impl { ($($ty:ty),*) => { @@ -3191,7 +3199,7 @@ fn add_weighted_filter_function_impl(from: &AnimatedFilter, &to_value, self_portion, other_portion, - &0.0, + &NonNegative::(0.0), )?)) }, % endfor @@ -3202,7 +3210,7 @@ fn add_weighted_filter_function_impl(from: &AnimatedFilter, &to_value, self_portion, other_portion, - &1.0, + &NonNegative::(1.0), )?)) }, % endfor @@ -3373,3 +3381,49 @@ sorted_shorthands = [(p, position) for position, p in enumerate(sorted_shorthand % endfor } } + +impl Animatable for NonNegative + where T: Animatable + Clone +{ + #[inline] + fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result { + self.0.add_weighted(&other.0, self_portion, other_portion).map(NonNegative::) + } + + #[inline] + fn compute_distance(&self, other: &Self) -> Result { + self.0.compute_distance(&other.0) + } +} + +impl ToAnimatedZero for NonNegative + where T: ToAnimatedZero +{ + #[inline] + fn to_animated_zero(&self) -> Result { + self.0.to_animated_zero().map(NonNegative::) + } +} + +impl Animatable for GreaterThanOrEqualToOne + where T: Animatable + Clone +{ + #[inline] + fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result { + self.0.add_weighted(&other.0, self_portion, other_portion).map(GreaterThanOrEqualToOne::) + } + + #[inline] + fn compute_distance(&self, other: &Self) -> Result { + self.0.compute_distance(&other.0) + } +} + +impl ToAnimatedZero for GreaterThanOrEqualToOne + where T: ToAnimatedZero +{ + #[inline] + fn to_animated_zero(&self) -> Result { + self.0.to_animated_zero().map(GreaterThanOrEqualToOne::) + } +} diff --git a/components/style/properties/longhand/background.mako.rs b/components/style/properties/longhand/background.mako.rs index 1fed8b37f40..b2de4e38fc6 100644 --- a/components/style/properties/longhand/background.mako.rs +++ b/components/style/properties/longhand/background.mako.rs @@ -167,7 +167,8 @@ ${helpers.predefined_type("background-size", "BackgroundSize", initial_specified_value="specified::LengthOrPercentageOrAuto::Auto.into()", spec="https://drafts.csswg.org/css-backgrounds/#the-background-size", vector=True, - animation_value_type="ComputedValue", + animation_value_type="BackgroundSizeList", + need_animatable=True, flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", extra_prefixes="webkit")} diff --git a/components/style/properties/longhand/border.mako.rs b/components/style/properties/longhand/border.mako.rs index c4f6aa888b1..db5fd47b2bd 100644 --- a/components/style/properties/longhand/border.mako.rs +++ b/components/style/properties/longhand/border.mako.rs @@ -40,11 +40,11 @@ ${helpers.predefined_type("border-%s-width" % side_name, "BorderSideWidth", - "Au::from_px(3)", - computed_type="::app_units::Au", + "::values::computed::NonNegativeAu::from_px(3)", + computed_type="::values::computed::NonNegativeAu", alias=maybe_moz_logical_alias(product, side, "-moz-border-%s-width"), spec=maybe_logical_spec(side, "width"), - animation_value_type="ComputedValue", + animation_value_type="NonNegativeAu", logical=is_logical, flags="APPLIES_TO_FIRST_LETTER", allow_quirks=not is_logical)} @@ -62,7 +62,7 @@ ${helpers.gecko_keyword_conversion(Keyword('border-style', spec="https://drafts.csswg.org/css-backgrounds/#border-%s-radius" % corner, boxed=True, flags="APPLIES_TO_FIRST_LETTER", - animation_value_type="ComputedValue")} + animation_value_type="BorderCornerRadius")} % endfor /// -moz-border-*-colors: color, string, enum, none, inherit/initial diff --git a/components/style/properties/longhand/column.mako.rs b/components/style/properties/longhand/column.mako.rs index 440e5d94d81..dda11ea696c 100644 --- a/components/style/properties/longhand/column.mako.rs +++ b/components/style/properties/longhand/column.mako.rs @@ -7,33 +7,30 @@ <% data.new_style_struct("Column", inherited=False) %> ${helpers.predefined_type("column-width", - "length::LengthOrAuto", + "length::NonNegativeLengthOrAuto", "Either::Second(Auto)", initial_specified_value="Either::Second(Auto)", - parse_method="parse_non_negative_length", extra_prefixes="moz", - animation_value_type="ComputedValue", + animation_value_type="NonNegativeLengthOrAuto", experimental=True, spec="https://drafts.csswg.org/css-multicol/#propdef-column-width")} ${helpers.predefined_type("column-count", - "IntegerOrAuto", + "PositiveIntegerOrAuto", "Either::Second(Auto)", - parse_method="parse_positive", initial_specified_value="Either::Second(Auto)", experimental="True", - animation_value_type="ComputedValue", + animation_value_type="PositiveIntegerOrAuto", extra_prefixes="moz", spec="https://drafts.csswg.org/css-multicol/#propdef-column-count")} ${helpers.predefined_type("column-gap", - "length::LengthOrNormal", + "length::NonNegativeLengthOrNormal", "Either::Second(Normal)", - parse_method='parse_non_negative_length', extra_prefixes="moz", experimental=True, - animation_value_type="ComputedValue", + animation_value_type="NonNegativeLengthOrNormal", spec="https://drafts.csswg.org/css-multicol/#propdef-column-gap")} ${helpers.single_keyword("column-fill", "balance auto", extra_prefixes="moz", @@ -42,12 +39,12 @@ ${helpers.single_keyword("column-fill", "balance auto", extra_prefixes="moz", ${helpers.predefined_type("column-rule-width", "BorderSideWidth", - "Au::from_px(3)", + "::values::computed::NonNegativeAu::from_px(3)", initial_specified_value="specified::BorderSideWidth::Medium", - computed_type="::app_units::Au", + computed_type="::values::computed::NonNegativeAu", products="gecko", spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-width", - animation_value_type="ComputedValue", + animation_value_type="NonNegativeAu", extra_prefixes="moz")} // https://drafts.csswg.org/css-multicol-1/#crc diff --git a/components/style/properties/longhand/font.mako.rs b/components/style/properties/longhand/font.mako.rs index 754e4b81ab8..e31d459cee2 100644 --- a/components/style/properties/longhand/font.mako.rs +++ b/components/style/properties/longhand/font.mako.rs @@ -591,7 +591,7 @@ ${helpers.single_keyword_system("font-variant-caps", } -<%helpers:longhand name="font-size" need_clone="True" animation_value_type="ComputedValue" +<%helpers:longhand name="font-size" need_clone="True" animation_value_type="NonNegativeAu" 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; @@ -599,6 +599,7 @@ ${helpers.single_keyword_system("font-variant-caps", use std::fmt; use style_traits::{HasViewportPercentage, ToCss}; use values::FONT_MEDIUM_PX; + use values::computed::NonNegativeAu; use values::specified::{AllowQuirks, FontRelativeLength, LengthOrPercentage, NoCalcLength}; use values::specified::length::FontBaseSize; @@ -646,8 +647,8 @@ ${helpers.single_keyword_system("font-variant-caps", } pub mod computed_value { - use app_units::Au; - pub type T = Au; + use values::computed::NonNegativeAu; + pub type T = NonNegativeAu; } /// CSS font keywords @@ -722,7 +723,7 @@ ${helpers.single_keyword_system("font-variant-caps", % if product == "servo": impl ToComputedValue for KeywordSize { - type ComputedValue = Au; + type ComputedValue = NonNegativeAu; #[inline] fn to_computed_value(&self, _: &Context) -> computed_value::T { // https://drafts.csswg.org/css-fonts-3/#font-size-prop @@ -736,7 +737,7 @@ ${helpers.single_keyword_system("font-variant-caps", XLarge => Au::from_px(FONT_MEDIUM_PX) * 3 / 2, XXLarge => Au::from_px(FONT_MEDIUM_PX) * 2, XXXLarge => Au::from_px(FONT_MEDIUM_PX) * 3, - } + }.into() } #[inline] @@ -746,7 +747,7 @@ ${helpers.single_keyword_system("font-variant-caps", } % else: impl ToComputedValue for KeywordSize { - type ComputedValue = Au; + type ComputedValue = NonNegativeAu; #[inline] fn to_computed_value(&self, cx: &Context) -> computed_value::T { use gecko_bindings::structs::nsIAtom; @@ -782,9 +783,9 @@ ${helpers.single_keyword_system("font-variant-caps", 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 { - Au::from_px(FONT_SIZE_MAPPING[(base_size_px - 9) as usize][html_size]) + NonNegativeAu::from_px(FONT_SIZE_MAPPING[(base_size_px - 9) as usize][html_size]) } else { - Au(FONT_SIZE_FACTORS[html_size] * base_size / 100) + Au(FONT_SIZE_FACTORS[html_size] * base_size / 100).into() } } @@ -843,37 +844,38 @@ ${helpers.single_keyword_system("font-variant-caps", } /// Compute it against a given base font size - pub fn to_computed_value_against(&self, context: &Context, base_size: FontBaseSize) -> Au { + pub fn to_computed_value_against(&self, context: &Context, base_size: FontBaseSize) + -> NonNegativeAu { use values::specified::length::FontRelativeLength; match *self { SpecifiedValue::Length(LengthOrPercentage::Length( NoCalcLength::FontRelative(value))) => { - value.to_computed_value(context, base_size) + value.to_computed_value(context, base_size).into() } SpecifiedValue::Length(LengthOrPercentage::Length( NoCalcLength::ServoCharacterWidth(value))) => { - value.to_computed_value(base_size.resolve(context)) + value.to_computed_value(base_size.resolve(context)).into() } SpecifiedValue::Length(LengthOrPercentage::Length(ref l)) => { - context.maybe_zoom_text(l.to_computed_value(context)) + context.maybe_zoom_text(l.to_computed_value(context).into()) } SpecifiedValue::Length(LengthOrPercentage::Percentage(pc)) => { - base_size.resolve(context).scale_by(pc.0) + base_size.resolve(context).scale_by(pc.0).into() } SpecifiedValue::Length(LengthOrPercentage::Calc(ref calc)) => { let calc = calc.to_computed_value_zoomed(context); - calc.to_used_value(Some(base_size.resolve(context))).unwrap() + calc.to_used_value(Some(base_size.resolve(context))).unwrap().into() } SpecifiedValue::Keyword(ref key, fraction) => { context.maybe_zoom_text(key.to_computed_value(context).scale_by(fraction)) } SpecifiedValue::Smaller => { FontRelativeLength::Em(1. / LARGER_FONT_SIZE_RATIO) - .to_computed_value(context, base_size) + .to_computed_value(context, base_size).into() } SpecifiedValue::Larger => { FontRelativeLength::Em(LARGER_FONT_SIZE_RATIO) - .to_computed_value(context, base_size) + .to_computed_value(context, base_size).into() } SpecifiedValue::System(_) => { @@ -888,7 +890,7 @@ ${helpers.single_keyword_system("font-variant-caps", #[inline] #[allow(missing_docs)] pub fn get_initial_value() -> computed_value::T { - Au::from_px(FONT_MEDIUM_PX) + NonNegativeAu::from_px(FONT_MEDIUM_PX) } #[inline] @@ -908,7 +910,7 @@ ${helpers.single_keyword_system("font-variant-caps", #[inline] fn from_computed_value(computed: &computed_value::T) -> Self { SpecifiedValue::Length(LengthOrPercentage::Length( - ToComputedValue::from_computed_value(computed) + ToComputedValue::from_computed_value(&computed.0) )) } } @@ -955,7 +957,7 @@ ${helpers.single_keyword_system("font-variant-caps", #[allow(unused_mut)] pub fn cascade_specified_font_size(context: &mut Context, specified_value: &SpecifiedValue, - mut computed: Au) { + mut computed: NonNegativeAu) { if let SpecifiedValue::Keyword(kw, fraction) = *specified_value { context.builder.font_size_keyword = Some((kw, fraction)); } else if let Some(ratio) = specified_value.as_font_ratio() { @@ -1001,7 +1003,7 @@ ${helpers.single_keyword_system("font-variant-caps", if let Some(parent) = parent_unconstrained { let new_unconstrained = specified_value - .to_computed_value_against(context, FontBaseSize::Custom(parent)); + .to_computed_value_against(context, FontBaseSize::Custom(parent.0)); context.builder .mutate_font() .apply_unconstrained_font_size(new_unconstrained); @@ -1053,7 +1055,8 @@ ${helpers.single_keyword_system("font-variant-caps", } -<%helpers:longhand products="gecko" name="font-size-adjust" animation_value_type="ComputedValue" +<%helpers:longhand products="gecko" name="font-size-adjust" + animation_value_type="longhands::font_size_adjust::computed_value::T" flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER" spec="https://drafts.csswg.org/css-fonts/#propdef-font-size-adjust"> use properties::longhands::system_font::SystemFont; @@ -1107,7 +1110,7 @@ ${helpers.single_keyword_system("font-variant-caps", pub mod computed_value { use properties::animated_properties::Animatable; use values::CSSFloat; - use values::animated::ToAnimatedZero; + use values::animated::{ToAnimatedValue, ToAnimatedZero}; #[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[derive(Copy, Clone, Debug, PartialEq, ToCss)] @@ -1150,6 +1153,23 @@ ${helpers.single_keyword_system("font-variant-caps", #[inline] fn to_animated_zero(&self) -> Result { Err(()) } } + + impl ToAnimatedValue for T { + type AnimatedValue = Self; + + #[inline] + fn to_animated_value(self) -> Self { + self + } + + #[inline] + fn from_animated_value(animated: Self::AnimatedValue) -> Self { + match animated { + T::Number(number) => T::Number(number.max(0.)), + _ => animated + } + } + } } #[inline] @@ -2539,7 +2559,7 @@ ${helpers.single_keyword("-moz-math-variant", let weight = longhands::font_weight::computed_value::T::from_gecko_weight(system.weight); let ret = ComputedSystemFont { font_family: longhands::font_family::computed_value::T(family), - font_size: Au(system.size), + font_size: Au(system.size).into(), font_weight: weight, font_size_adjust: longhands::font_size_adjust::computed_value ::T::from_gecko_adjust(system.sizeAdjust), diff --git a/components/style/properties/longhand/inherited_svg.mako.rs b/components/style/properties/longhand/inherited_svg.mako.rs index a5bd2fdb35e..533c2f62e68 100644 --- a/components/style/properties/longhand/inherited_svg.mako.rs +++ b/components/style/properties/longhand/inherited_svg.mako.rs @@ -64,12 +64,11 @@ ${helpers.predefined_type( spec="https://www.w3.org/TR/SVG2/painting.html#SpecifyingStrokePaint")} ${helpers.predefined_type( - "stroke-width", "SVGLength", - "Au::from_px(1).into()", - "parse_non_negative", + "stroke-width", "SVGWidth", + "::values::computed::NonNegativeAu::from_px(1).into()", products="gecko", boxed="True", - animation_value_type="ComputedValue", + animation_value_type="::values::computed::SVGWidth", spec="https://www.w3.org/TR/SVG2/painting.html#StrokeWidth")} ${helpers.single_keyword("stroke-linecap", "butt round square", @@ -80,9 +79,10 @@ ${helpers.single_keyword("stroke-linejoin", "miter round bevel", products="gecko", animation_value_type="discrete", spec="https://www.w3.org/TR/SVG11/painting.html#StrokeLinejoinProperty")} -${helpers.predefined_type("stroke-miterlimit", "Number", "4.0", - "parse_at_least_one", products="gecko", - animation_value_type="ComputedValue", +${helpers.predefined_type("stroke-miterlimit", "GreaterThanOrEqualToOneNumber", + "From::from(4.0)", + products="gecko", + animation_value_type="::values::computed::GreaterThanOrEqualToOneNumber", spec="https://www.w3.org/TR/SVG11/painting.html#StrokeMiterlimitProperty")} ${helpers.predefined_type("stroke-opacity", "SVGOpacity", "Default::default()", @@ -94,7 +94,7 @@ ${helpers.predefined_type( "SVGStrokeDashArray", "Default::default()", products="gecko", - animation_value_type="ComputedValue", + animation_value_type="::values::computed::SVGStrokeDashArray", spec="https://www.w3.org/TR/SVG2/painting.html#StrokeDashing", )} diff --git a/components/style/properties/longhand/inherited_table.mako.rs b/components/style/properties/longhand/inherited_table.mako.rs index d524833304c..1be9de01bd2 100644 --- a/components/style/properties/longhand/inherited_table.mako.rs +++ b/components/style/properties/longhand/inherited_table.mako.rs @@ -20,21 +20,21 @@ ${helpers.single_keyword("caption-side", "top bottom", animation_value_type="discrete", spec="https://drafts.csswg.org/css-tables/#propdef-caption-side")} -<%helpers:longhand name="border-spacing" animation_value_type="ComputedValue" boxed="True" +<%helpers:longhand name="border-spacing" animation_value_type="BorderSpacing" boxed="True" spec="https://drafts.csswg.org/css-tables/#propdef-border-spacing"> - use app_units::Au; use values::specified::{AllowQuirks, Length}; + use values::specified::length::NonNegativeLength; pub mod computed_value { - use app_units::Au; use properties::animated_properties::Animatable; - use values::animated::ToAnimatedZero; + use values::animated::{ToAnimatedValue, ToAnimatedZero}; + use values::computed::NonNegativeAu; #[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[derive(Clone, Copy, Debug, PartialEq, ToCss)] pub struct T { - pub horizontal: Au, - pub vertical: Au, + pub horizontal: NonNegativeAu, + pub vertical: NonNegativeAu, } /// https://drafts.csswg.org/css-transitions/#animtype-simple-list @@ -66,20 +66,38 @@ ${helpers.single_keyword("caption-side", "top bottom", #[inline] fn to_animated_zero(&self) -> Result { Err(()) } } + + impl ToAnimatedValue for T { + type AnimatedValue = Self; + + #[inline] + fn to_animated_value(self) -> Self { + self + } + + #[inline] + fn from_animated_value(animated: Self::AnimatedValue) -> Self { + T { + horizontal: ToAnimatedValue::from_animated_value(animated.horizontal), + vertical: ToAnimatedValue::from_animated_value(animated.vertical) + } + } + } } #[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[derive(Clone, Debug, HasViewportPercentage, PartialEq, ToCss)] pub struct SpecifiedValue { - pub horizontal: Length, - pub vertical: Option, + pub horizontal: NonNegativeLength, + pub vertical: Option, } #[inline] pub fn get_initial_value() -> computed_value::T { + use values::computed::NonNegativeAu; computed_value::T { - horizontal: Au(0), - vertical: Au(0), + horizontal: NonNegativeAu::zero(), + vertical: NonNegativeAu::zero(), } } @@ -121,14 +139,14 @@ ${helpers.single_keyword("caption-side", "top bottom", (None, None) => Err(StyleParseError::UnspecifiedError.into()), (Some(length), None) => { Ok(SpecifiedValue { - horizontal: length, + horizontal: length.into(), vertical: None, }) } (Some(horizontal), Some(vertical)) => { Ok(SpecifiedValue { - horizontal: horizontal, - vertical: Some(vertical), + horizontal: horizontal.into(), + vertical: Some(vertical.into()), }) } (None, Some(_)) => unreachable!(), diff --git a/components/style/properties/longhand/inherited_text.mako.rs b/components/style/properties/longhand/inherited_text.mako.rs index 50df62db72a..8384671de0e 100644 --- a/components/style/properties/longhand/inherited_text.mako.rs +++ b/components/style/properties/longhand/inherited_text.mako.rs @@ -9,7 +9,7 @@ ${helpers.predefined_type("line-height", "LineHeight", "computed::LineHeight::normal()", - animation_value_type="ComputedValue", + animation_value_type="LineHeight", flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", spec="https://drafts.csswg.org/css2/visudet.html#propdef-line-height")} @@ -714,10 +714,9 @@ ${helpers.predefined_type("text-emphasis-color", "Color", ${helpers.predefined_type( - "-moz-tab-size", "LengthOrNumber", - "::values::Either::Second(8.0)", - "parse_non_negative", - products="gecko", animation_value_type="ComputedValue", + "-moz-tab-size", "length::NonNegativeLengthOrNumber", + "::values::Either::Second(From::from(8.0))", + products="gecko", animation_value_type="::values::computed::length::NonNegativeLengthOrNumber", spec="https://drafts.csswg.org/css-text-3/#tab-size-property")} @@ -742,9 +741,9 @@ ${helpers.predefined_type( ${helpers.predefined_type("-webkit-text-stroke-width", "BorderSideWidth", - "Au::from_px(0)", + "::values::computed::NonNegativeAu::from_px(0)", initial_specified_value="specified::BorderSideWidth::Length(specified::Length::zero())", - computed_type="::app_units::Au", + computed_type="::values::computed::NonNegativeAu", 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", diff --git a/components/style/properties/longhand/outline.mako.rs b/components/style/properties/longhand/outline.mako.rs index d7b62dd3cfc..f08537f6545 100644 --- a/components/style/properties/longhand/outline.mako.rs +++ b/components/style/properties/longhand/outline.mako.rs @@ -64,10 +64,10 @@ ${helpers.predefined_type("outline-color", "Color", "computed_value::T::currentc ${helpers.predefined_type("outline-width", "BorderSideWidth", - "Au::from_px(3)", + "::values::computed::NonNegativeAu::from_px(3)", initial_specified_value="specified::BorderSideWidth::Medium", - computed_type="::app_units::Au", - animation_value_type="ComputedValue", + computed_type="::values::computed::NonNegativeAu", + animation_value_type="NonNegativeAu", spec="https://drafts.csswg.org/css-ui/#propdef-outline-width")} // The -moz-outline-radius-* properties are non-standard and not on a standards track. @@ -76,7 +76,7 @@ ${helpers.predefined_type("outline-width", "computed::LengthOrPercentage::zero().into()", products="gecko", boxed=True, - animation_value_type="ComputedValue", + animation_value_type="BorderCornerRadius", spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-outline-radius)")} % endfor diff --git a/components/style/properties/longhand/padding.mako.rs b/components/style/properties/longhand/padding.mako.rs index 53035c32efb..49d9b1bd722 100644 --- a/components/style/properties/longhand/padding.mako.rs +++ b/components/style/properties/longhand/padding.mako.rs @@ -14,11 +14,10 @@ if side[1]: spec = "https://drafts.csswg.org/css-logical-props/#propdef-padding-%s" % side[1] %> - ${helpers.predefined_type("padding-%s" % side[0], "LengthOrPercentage", - "computed::LengthOrPercentage::Length(Au(0))", - "parse_non_negative", + ${helpers.predefined_type("padding-%s" % side[0], "NonNegativeLengthOrPercentage", + "computed::NonNegativeLengthOrPercentage::zero()", alias=maybe_moz_logical_alias(product, side, "-moz-padding-%s"), - animation_value_type="ComputedValue", + animation_value_type="NonNegativeLengthOrPercentage", logical = side[1], spec = spec, flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_PLACEHOLDER", diff --git a/components/style/properties/longhand/position.mako.rs b/components/style/properties/longhand/position.mako.rs index dd1cb9d5724..2ea32e99845 100644 --- a/components/style/properties/longhand/position.mako.rs +++ b/components/style/properties/longhand/position.mako.rs @@ -117,17 +117,17 @@ ${helpers.single_keyword("flex-wrap", "nowrap wrap wrap-reverse", % endif // Flex item properties -${helpers.predefined_type("flex-grow", "Number", - "0.0", "parse_non_negative", +${helpers.predefined_type("flex-grow", "NonNegativeNumber", + "From::from(0.0)", spec="https://drafts.csswg.org/css-flexbox/#flex-grow-property", extra_prefixes="webkit", - animation_value_type="ComputedValue")} + animation_value_type="NonNegativeNumber")} -${helpers.predefined_type("flex-shrink", "Number", - "1.0", "parse_non_negative", +${helpers.predefined_type("flex-shrink", "NonNegativeNumber", + "From::from(1.0)", spec="https://drafts.csswg.org/css-flexbox/#flex-shrink-property", extra_prefixes="webkit", - animation_value_type="ComputedValue")} + animation_value_type="NonNegativeNumber")} // https://drafts.csswg.org/css-align/#align-self-property % if product == "servo": @@ -166,7 +166,7 @@ ${helpers.predefined_type("order", "Integer", "0", logical=False, spec="https://drafts.csswg.org/css-flexbox/#flex-basis-property", extra_prefixes="webkit", - animation_value_type="ComputedValue")} + animation_value_type="MozLength")} % else: // FIXME: This property should be animatable. ${helpers.predefined_type("flex-basis", @@ -187,17 +187,17 @@ ${helpers.predefined_type("order", "Integer", "0", ${helpers.gecko_size_type("%s" % size, "MozLength", "auto()", logical, spec=spec % size, - animation_value_type="ComputedValue")} + animation_value_type="MozLength")} // min-width, min-height, min-block-size, min-inline-size, // max-width, max-height, max-block-size, max-inline-size ${helpers.gecko_size_type("min-%s" % size, "MozLength", "auto()", logical, spec=spec % size, - animation_value_type="ComputedValue")} + animation_value_type="MozLength")} ${helpers.gecko_size_type("max-%s" % size, "MaxLength", "none()", logical, spec=spec % size, - animation_value_type="ComputedValue")} + animation_value_type="MaxLength")} % else: // servo versions (no keyword support) ${helpers.predefined_type("%s" % size, @@ -249,11 +249,10 @@ ${helpers.predefined_type("object-position", % for kind in ["row", "column"]: ${helpers.predefined_type("grid-%s-gap" % kind, - "LengthOrPercentage", - "computed::LengthOrPercentage::Length(Au(0))", - "parse_non_negative", + "NonNegativeLengthOrPercentage", + "computed::NonNegativeLengthOrPercentage::zero()", spec="https://drafts.csswg.org/css-grid/#propdef-grid-%s-gap" % kind, - animation_value_type="ComputedValue", + animation_value_type="NonNegativeLengthOrPercentage", products="gecko")} % for range in ["start", "end"]: diff --git a/components/style/properties/longhand/xul.mako.rs b/components/style/properties/longhand/xul.mako.rs index 5d9ec6623e2..6802f60460c 100644 --- a/components/style/properties/longhand/xul.mako.rs +++ b/components/style/properties/longhand/xul.mako.rs @@ -24,9 +24,9 @@ ${helpers.single_keyword("-moz-box-direction", "normal reverse", alias="-webkit-box-direction", spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/box-direction)")} -${helpers.predefined_type("-moz-box-flex", "Number", "0.0", "parse_non_negative", +${helpers.predefined_type("-moz-box-flex", "NonNegativeNumber", "From::from(0.)", products="gecko", gecko_ffi_name="mBoxFlex", - animation_value_type="ComputedValue", + animation_value_type="NonNegativeNumber", alias="-webkit-box-flex", spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/box-flex)")} diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index ab8fce24621..82b2f4cb73b 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -10,13 +10,13 @@ <%namespace name="helpers" file="/helpers.mako.rs" /> +#[cfg(feature = "servo")] use app_units::Au; use servo_arc::{Arc, UniqueArc}; use std::borrow::Cow; use std::collections::HashSet; use std::{fmt, mem, ops}; #[cfg(feature = "gecko")] use std::ptr; -use app_units::Au; #[cfg(feature = "servo")] use cssparser::RGBA; use cssparser::{Parser, TokenSerializationType, serialize_identifier}; use cssparser::ParserInput; @@ -43,6 +43,7 @@ use stylesheets::{CssRuleType, MallocSizeOf, MallocSizeOfFn, Origin, UrlExtraDat #[cfg(feature = "servo")] use values::Either; use values::generics::text::LineHeight; use values::computed; +use values::computed::NonNegativeAu; use cascade_info::CascadeInfo; use rule_tree::{CascadeLevel, StrongRuleNode}; use self::computed_value_flags::ComputedValueFlags; @@ -1646,12 +1647,12 @@ pub use gecko_properties::style_structs; /// The module where all the style structs are defined. #[cfg(feature = "servo")] pub mod style_structs { - use app_units::Au; use fnv::FnvHasher; use super::longhands; use std::hash::{Hash, Hasher}; use logical_geometry::WritingMode; use media_queries::Device; + use values::computed::NonNegativeAu; % for style_struct in data.active_style_structs(): % if style_struct.name == "Font": @@ -1751,7 +1752,7 @@ pub mod style_structs { /// 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 != ::app_units::Au(0) + self.border_${side}_width != NonNegativeAu::zero() } % endfor % elif style_struct.name == "Font": @@ -1769,7 +1770,8 @@ pub mod style_structs { /// (Servo does not handle MathML, so this just calls copy_font_size_from) pub fn inherit_font_size_from(&mut self, parent: &Self, - _: Option, _: &Device) -> bool { + _: Option, + _: &Device) -> bool { self.copy_font_size_from(parent); false } @@ -1777,19 +1779,19 @@ pub mod style_structs { pub fn apply_font_size(&mut self, v: longhands::font_size::computed_value::T, _: &Self, - _: &Device) -> Option { + _: &Device) -> Option { self.set_font_size(v); None } /// (Servo does not handle MathML, so this does nothing) - pub fn apply_unconstrained_font_size(&mut self, _: Au) { + pub fn apply_unconstrained_font_size(&mut self, _: NonNegativeAu) { } % 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 != ::app_units::Au(0) + self.outline_width != NonNegativeAu::zero() } % elif style_struct.name == "Text": /// Whether the text decoration has an underline. @@ -2189,10 +2191,10 @@ impl ComputedValuesInner { pub fn logical_padding(&self) -> LogicalMargin { let padding_style = self.get_padding(); LogicalMargin::from_physical(self.writing_mode, SideOffsets2D::new( - padding_style.padding_top, - padding_style.padding_right, - padding_style.padding_bottom, - padding_style.padding_left, + padding_style.padding_top.0, + padding_style.padding_right.0, + padding_style.padding_bottom.0, + padding_style.padding_left.0, )) } @@ -2201,10 +2203,10 @@ impl ComputedValuesInner { pub fn border_width_for_writing_mode(&self, writing_mode: WritingMode) -> LogicalMargin { let border_style = self.get_border(); LogicalMargin::from_physical(writing_mode, SideOffsets2D::new( - border_style.border_top_width, - border_style.border_right_width, - border_style.border_bottom_width, - border_style.border_left_width, + border_style.border_top_width.0, + border_style.border_right_width.0, + border_style.border_bottom_width.0, + border_style.border_left_width.0, )) } @@ -3359,7 +3361,7 @@ pub fn adjust_border_width(style: &mut StyleBuilder) { // 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(Au(0)); + style.set_border_${side}_width(NonNegativeAu::zero()); } % endfor } @@ -3383,7 +3385,7 @@ pub fn modify_border_style_for_inline_sides(style: &mut Arc, PhysicalSide::Top => (border.border_top_width, border.border_top_style), PhysicalSide::Bottom => (border.border_bottom_width, border.border_bottom_style), }; - if current_style == (Au(0), BorderStyle::none) { + if current_style == (NonNegativeAu::zero(), BorderStyle::none) { return; } } @@ -3391,19 +3393,19 @@ pub fn modify_border_style_for_inline_sides(style: &mut Arc, let border = Arc::make_mut(&mut style.border); match side { PhysicalSide::Left => { - border.border_left_width = Au(0); + border.border_left_width = NonNegativeAu::zero(); border.border_left_style = BorderStyle::none; } PhysicalSide::Right => { - border.border_right_width = Au(0); + border.border_right_width = NonNegativeAu::zero(); border.border_right_style = BorderStyle::none; } PhysicalSide::Bottom => { - border.border_bottom_width = Au(0); + border.border_bottom_width = NonNegativeAu::zero(); border.border_bottom_style = BorderStyle::none; } PhysicalSide::Top => { - border.border_top_width = Au(0); + border.border_top_width = NonNegativeAu::zero(); border.border_top_style = BorderStyle::none; } } diff --git a/components/style/properties/shorthand/padding.mako.rs b/components/style/properties/shorthand/padding.mako.rs index 2972fb45259..592048cf56f 100644 --- a/components/style/properties/shorthand/padding.mako.rs +++ b/components/style/properties/shorthand/padding.mako.rs @@ -4,6 +4,6 @@ <%namespace name="helpers" file="/helpers.mako.rs" /> -${helpers.four_sides_shorthand("padding", "padding-%s", "specified::LengthOrPercentage::parse_non_negative", +${helpers.four_sides_shorthand("padding", "padding-%s", "specified::NonNegativeLengthOrPercentage::parse", spec="https://drafts.csswg.org/css-box-3/#propdef-padding", allow_quirks=True)} diff --git a/components/style/properties/shorthand/position.mako.rs b/components/style/properties/shorthand/position.mako.rs index c7653a48e15..f4221eae312 100644 --- a/components/style/properties/shorthand/position.mako.rs +++ b/components/style/properties/shorthand/position.mako.rs @@ -46,12 +46,13 @@ extra_prefixes="webkit" derive_serialize="True" spec="https://drafts.csswg.org/css-flexbox/#flex-property"> - use values::specified::Number; + use parser::Parse; + use values::specified::NonNegativeNumber; fn parse_flexibility<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) - -> Result<(Number, Option),ParseError<'i>> { - let grow = Number::parse_non_negative(context, input)?; - let shrink = input.try(|i| Number::parse_non_negative(context, i)).ok(); + -> Result<(NonNegativeNumber, Option),ParseError<'i>> { + let grow = NonNegativeNumber::parse(context, input)?; + let shrink = input.try(|i| NonNegativeNumber::parse(context, i)).ok(); Ok((grow, shrink)) } @@ -63,8 +64,8 @@ if input.try(|input| input.expect_ident_matching("none")).is_ok() { return Ok(expanded! { - flex_grow: Number::new(0.0), - flex_shrink: Number::new(0.0), + flex_grow: NonNegativeNumber::new(0.0), + flex_shrink: NonNegativeNumber::new(0.0), flex_basis: longhands::flex_basis::SpecifiedValue::auto(), }) } @@ -89,8 +90,8 @@ return Err(StyleParseError::UnspecifiedError.into()) } Ok(expanded! { - flex_grow: grow.unwrap_or(Number::new(1.0)), - flex_shrink: shrink.unwrap_or(Number::new(1.0)), + flex_grow: grow.unwrap_or(NonNegativeNumber::new(1.0)), + flex_shrink: shrink.unwrap_or(NonNegativeNumber::new(1.0)), // Per spec, this should be SpecifiedValue::zero(), but all // browsers currently agree on using `0%`. This is a spec // change which hasn't been adopted by browsers: @@ -458,7 +459,7 @@ use properties::longhands::grid_auto_flow::computed_value::{AutoFlow, T as SpecifiedAutoFlow}; use values::{Either, None_}; use values::generics::grid::{GridTemplateComponent, TrackListType}; - use values::specified::{GenericGridTemplateComponent, LengthOrPercentage, TrackSize}; + use values::specified::{GenericGridTemplateComponent, NonNegativeLengthOrPercentage, TrackSize}; pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { @@ -519,8 +520,8 @@ grid_auto_columns: auto_cols, grid_auto_flow: flow, // This shorthand also resets grid gap - grid_row_gap: LengthOrPercentage::zero(), - grid_column_gap: LengthOrPercentage::zero(), + grid_row_gap: NonNegativeLengthOrPercentage::zero(), + grid_column_gap: NonNegativeLengthOrPercentage::zero(), }) } @@ -538,8 +539,8 @@ fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { // `grid` shorthand resets these properties. If they are not zero, that means they // are changed by longhands and in that case we should fail serializing `grid`. - if *self.grid_row_gap != LengthOrPercentage::zero() || - *self.grid_column_gap != LengthOrPercentage::zero() { + if *self.grid_row_gap != NonNegativeLengthOrPercentage::zero() || + *self.grid_column_gap != NonNegativeLengthOrPercentage::zero() { return Ok(()); } diff --git a/components/style/servo/media_queries.rs b/components/style/servo/media_queries.rs index 6904051af18..9b47d231c97 100644 --- a/components/style/servo/media_queries.rs +++ b/components/style/servo/media_queries.rs @@ -60,7 +60,8 @@ impl Device { media_type: media_type, viewport_size: viewport_size, device_pixel_ratio: device_pixel_ratio, - root_font_size: AtomicIsize::new(font_size::get_initial_value().0 as isize), // FIXME(bz): Seems dubious? + // FIXME(bz): Seems dubious? + root_font_size: AtomicIsize::new(font_size::get_initial_value().value() as isize), used_root_font_size: AtomicBool::new(false), } } diff --git a/components/style/style_adjuster.rs b/components/style/style_adjuster.rs index 1c93e6bae58..70d9880fb29 100644 --- a/components/style/style_adjuster.rs +++ b/components/style/style_adjuster.rs @@ -242,7 +242,7 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { fn adjust_for_outline(&mut self) { if self.style.get_outline().clone_outline_style().none_or_hidden() && self.style.get_outline().outline_has_nonzero_width() { - self.style.mutate_outline().set_outline_width(Au(0)); + self.style.mutate_outline().set_outline_width(Au(0).into()); } } diff --git a/components/style/values/animated/effects.rs b/components/style/values/animated/effects.rs index cb0fc8799d4..9bd3456d028 100644 --- a/components/style/values/animated/effects.rs +++ b/components/style/values/animated/effects.rs @@ -12,8 +12,8 @@ use std::cmp; #[cfg(not(feature = "gecko"))] use values::Impossible; use values::animated::{ToAnimatedValue, ToAnimatedZero}; -use values::computed::{Angle, Number}; -use values::computed::length::Length; +use values::computed::{Angle, NonNegativeNumber}; +use values::computed::length::{Length, NonNegativeLength}; use values::generics::effects::BoxShadow as GenericBoxShadow; use values::generics::effects::Filter as GenericFilter; use values::generics::effects::SimpleShadow as GenericSimpleShadow; @@ -32,7 +32,7 @@ pub type TextShadowList = ShadowList; pub struct ShadowList(Vec); /// An animated value for a single `box-shadow`. -pub type BoxShadow = GenericBoxShadow; +pub type BoxShadow = GenericBoxShadow; /// An animated value for the `filter` property. #[cfg_attr(feature = "servo", derive(HeapSizeOf))] @@ -41,14 +41,14 @@ pub struct FilterList(pub Vec); /// An animated value for a single `filter`. #[cfg(feature = "gecko")] -pub type Filter = GenericFilter; +pub type Filter = GenericFilter; /// An animated value for a single `filter`. #[cfg(not(feature = "gecko"))] -pub type Filter = GenericFilter; +pub type Filter = GenericFilter; /// An animated value for the `drop-shadow()` filter. -pub type SimpleShadow = GenericSimpleShadow; +pub type SimpleShadow = GenericSimpleShadow; impl ToAnimatedValue for ComputedBoxShadowList { type AnimatedValue = BoxShadowList; diff --git a/components/style/values/animated/mod.rs b/components/style/values/animated/mod.rs index 63d85254598..49a53938e1e 100644 --- a/components/style/values/animated/mod.rs +++ b/components/style/values/animated/mod.rs @@ -9,7 +9,17 @@ //! module's raison d'ĂȘtre is to ultimately contain all these types. use app_units::Au; +use smallvec::SmallVec; +use std::cmp::max; use values::computed::Angle as ComputedAngle; +use values::computed::BorderCornerRadius as ComputedBorderCornerRadius; +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::NonNegativeLengthOrPercentage as ComputedNonNegativeLengthOrPercentage; +use values::computed::NonNegativeNumber as ComputedNonNegativeNumber; +use values::computed::PositiveInteger as ComputedPositiveInteger; use values::specified::url::SpecifiedUrl; pub mod effects; @@ -62,6 +72,23 @@ where } } +impl ToAnimatedValue for SmallVec<[T; 1]> +where + T: ToAnimatedValue, +{ + type AnimatedValue = SmallVec<[T::AnimatedValue; 1]>; + + #[inline] + fn to_animated_value(self) -> Self::AnimatedValue { + self.into_iter().map(T::to_animated_value).collect() + } + + #[inline] + fn from_animated_value(animated: Self::AnimatedValue) -> Self { + animated.into_iter().map(T::from_animated_value).collect() + } +} + /// Marker trait for computed values with the same representation during animations. pub trait AnimatedValueAsComputed {} @@ -88,6 +115,149 @@ where } } +impl ToAnimatedValue for ComputedNonNegativeNumber { + type AnimatedValue = Self; + + #[inline] + fn to_animated_value(self) -> Self { + self + } + + #[inline] + fn from_animated_value(animated: Self::AnimatedValue) -> Self { + animated.0.max(0.).into() + } +} + +impl ToAnimatedValue for ComputedGreaterThanOrEqualToOneNumber { + type AnimatedValue = Self; + + #[inline] + fn to_animated_value(self) -> Self { + self + } + + #[inline] + fn from_animated_value(animated: Self::AnimatedValue) -> Self { + animated.0.max(1.).into() + } +} + +impl ToAnimatedValue for NonNegativeAu { + 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() + } +} + +impl ToAnimatedValue for ComputedPositiveInteger { + type AnimatedValue = Self; + + #[inline] + fn to_animated_value(self) -> Self { + self + } + + #[inline] + fn from_animated_value(animated: Self::AnimatedValue) -> Self { + max(animated.0, 0).into() + } +} + +impl ToAnimatedValue for ComputedNonNegativeLengthOrPercentage { + type AnimatedValue = Self; + + #[inline] + fn to_animated_value(self) -> Self { + self + } + + #[inline] + fn from_animated_value(animated: Self::AnimatedValue) -> Self { + animated.0.clamp_to_non_negative().into() + } +} + +impl ToAnimatedValue for ComputedBorderCornerRadius { + type AnimatedValue = Self; + + #[inline] + fn to_animated_value(self) -> Self { + self + } + + #[inline] + fn from_animated_value(animated: Self::AnimatedValue) -> Self { + ComputedBorderCornerRadius::new(animated.0.width.clamp_to_non_negative(), + animated.0.height.clamp_to_non_negative()) + } +} + +impl ToAnimatedValue for ComputedMaxLength { + type AnimatedValue = Self; + + #[inline] + fn to_animated_value(self) -> Self { + self + } + + #[inline] + fn from_animated_value(animated: Self::AnimatedValue) -> Self { + use values::computed::{LengthOrPercentageOrNone, Percentage}; + match animated { + ComputedMaxLength::LengthOrPercentageOrNone(lopn) => { + let result = match lopn { + LengthOrPercentageOrNone::Length(au) => { + LengthOrPercentageOrNone::Length(max(au, Au(0))) + }, + LengthOrPercentageOrNone::Percentage(percentage) => { + LengthOrPercentageOrNone::Percentage(Percentage(percentage.0.max(0.))) + } + _ => lopn + }; + ComputedMaxLength::LengthOrPercentageOrNone(result) + }, + _ => animated + } + } +} + +impl ToAnimatedValue for ComputedMozLength { + type AnimatedValue = Self; + + #[inline] + fn to_animated_value(self) -> Self { + self + } + + #[inline] + fn from_animated_value(animated: Self::AnimatedValue) -> Self { + use values::computed::{LengthOrPercentageOrAuto, Percentage}; + match animated { + ComputedMozLength::LengthOrPercentageOrAuto(lopa) => { + let result = match lopa { + LengthOrPercentageOrAuto::Length(au) => { + LengthOrPercentageOrAuto::Length(max(au, Au(0))) + }, + LengthOrPercentageOrAuto::Percentage(percentage) => { + LengthOrPercentageOrAuto::Percentage(Percentage(percentage.0.max(0.))) + } + _ => lopa + }; + ComputedMozLength::LengthOrPercentageOrAuto(result) + }, + _ => animated + } + } +} + /// Returns a value similar to `self` that represents zero. pub trait ToAnimatedZero: Sized { /// Returns a value that, when added with an underlying value, will produce the underlying diff --git a/components/style/values/computed/background.rs b/components/style/values/computed/background.rs index a1de43c5fe6..d2781ac1891 100644 --- a/components/style/values/computed/background.rs +++ b/components/style/values/computed/background.rs @@ -5,7 +5,8 @@ //! Computed types for CSS values related to backgrounds. use properties::animated_properties::{Animatable, RepeatableListAnimatable}; -use values::animated::ToAnimatedZero; +use properties::longhands::background_size::computed_value::T as BackgroundSizeList; +use values::animated::{ToAnimatedValue, ToAnimatedZero}; use values::computed::length::LengthOrPercentageOrAuto; use values::generics::background::BackgroundSize as GenericBackgroundSize; @@ -56,3 +57,52 @@ impl ToAnimatedZero for BackgroundSize { #[inline] fn to_animated_zero(&self) -> Result { Err(()) } } + +impl ToAnimatedValue for BackgroundSize { + type AnimatedValue = Self; + + #[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; + let clamp_animated_value = |value: LengthOrPercentageOrAuto| -> LengthOrPercentageOrAuto { + match value { + LengthOrPercentageOrAuto::Length(len) => { + LengthOrPercentageOrAuto::Length(Au(::std::cmp::max(len.0, 0))) + }, + LengthOrPercentageOrAuto::Percentage(percent) => { + LengthOrPercentageOrAuto::Percentage(Percentage(percent.0.max(0.))) + }, + _ => value + } + }; + match animated { + GenericBackgroundSize::Explicit { width, height } => { + GenericBackgroundSize::Explicit { + width: clamp_animated_value(width), + height: clamp_animated_value(height) + } + }, + _ => animated + } + } +} + +impl ToAnimatedValue for BackgroundSizeList { + type AnimatedValue = Self; + + #[inline] + fn to_animated_value(self) -> Self { + self + } + + #[inline] + fn from_animated_value(animated: Self::AnimatedValue) -> Self { + BackgroundSizeList(ToAnimatedValue::from_animated_value(animated.0)) + } +} diff --git a/components/style/values/computed/effects.rs b/components/style/values/computed/effects.rs index b718ea7f265..fb87c58bf6f 100644 --- a/components/style/values/computed/effects.rs +++ b/components/style/values/computed/effects.rs @@ -6,23 +6,23 @@ #[cfg(not(feature = "gecko"))] use values::Impossible; -use values::computed::{Angle, Number}; +use values::computed::{Angle, NonNegativeNumber}; use values::computed::color::Color; -use values::computed::length::Length; +use values::computed::length::{Length, NonNegativeLength}; use values::generics::effects::BoxShadow as GenericBoxShadow; use values::generics::effects::Filter as GenericFilter; use values::generics::effects::SimpleShadow as GenericSimpleShadow; /// A computed value for a single shadow of the `box-shadow` property. -pub type BoxShadow = GenericBoxShadow; +pub type BoxShadow = GenericBoxShadow; /// A computed value for a single `filter`. #[cfg(feature = "gecko")] -pub type Filter = GenericFilter; +pub type Filter = GenericFilter; /// A computed value for a single `filter`. #[cfg(not(feature = "gecko"))] -pub type Filter = GenericFilter; +pub type Filter = GenericFilter; /// A computed value for the `drop-shadow()` filter. -pub type SimpleShadow = GenericSimpleShadow; +pub type SimpleShadow = GenericSimpleShadow; diff --git a/components/style/values/computed/length.rs b/components/style/values/computed/length.rs index 4d9f0cd6fbc..b3b7af805fd 100644 --- a/components/style/values/computed/length.rs +++ b/components/style/values/computed/length.rs @@ -11,6 +11,8 @@ use style_traits::ToCss; use style_traits::values::specified::AllowedLengthType; use super::{Number, ToComputedValue, Context}; use values::{Auto, CSSFloat, Either, ExtremumLength, None_, Normal, specified}; +use values::computed::{NonNegativeAu, NonNegativeNumber}; +use values::generics::NonNegative; use values::specified::length::{AbsoluteLength, FontBaseSize, FontRelativeLength}; use values::specified::length::ViewportPercentageLength; @@ -71,7 +73,7 @@ impl ToComputedValue for specified::NoCalcLength { specified::NoCalcLength::ViewportPercentage(length) => length.to_computed_value(context.viewport_size()), specified::NoCalcLength::ServoCharacterWidth(length) => - length.to_computed_value(context.style().get_font().clone_font_size()), + length.to_computed_value(context.style().get_font().clone_font_size().0), #[cfg(feature = "gecko")] specified::NoCalcLength::Physical(length) => length.to_computed_value(context), @@ -265,7 +267,7 @@ impl specified::CalcLengthOrPercentage { /// Compute font-size or line-height taking into account text-zoom if necessary. pub fn to_computed_value_zoomed(&self, context: &Context) -> CalcLengthOrPercentage { - self.to_computed_value_with_zoom(context, |abs| context.maybe_zoom_text(abs)) + self.to_computed_value_with_zoom(context, |abs| context.maybe_zoom_text(abs.into()).0) } } @@ -349,6 +351,20 @@ impl LengthOrPercentage { }, } } + + /// 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::Percentage(percentage) => { + LengthOrPercentage::Percentage(Percentage(percentage.0.max(0.))) + }, + _ => self + } + } } impl fmt::Debug for LengthOrPercentage { @@ -550,6 +566,43 @@ impl ToComputedValue for specified::LengthOrPercentageOrNone { } } +/// A wrapper of LengthOrPercentage, whose value must be >= 0. +pub type NonNegativeLengthOrPercentage = NonNegative; + +impl From for NonNegativeLengthOrPercentage { + #[inline] + fn from(length: NonNegativeAu) -> Self { + LengthOrPercentage::Length(length.0).into() + } +} + +impl From for NonNegativeLengthOrPercentage { + #[inline] + fn from(lop: LengthOrPercentage) -> Self { + NonNegative::(lop) + } +} + +impl NonNegativeLengthOrPercentage { + /// Get zero value. + #[inline] + pub fn zero() -> Self { + NonNegative::(LengthOrPercentage::zero()) + } + + /// Returns true if the computed value is absolute 0 or 0%. + #[inline] + pub fn is_definitely_zero(&self) -> bool { + self.0.is_definitely_zero() + } + + /// Returns the used value. + #[inline] + pub fn to_used_value(&self, containing_length: Au) -> Au { + self.0.to_used_value(containing_length) + } +} + /// A computed `` value. pub type Length = Au; @@ -573,6 +626,18 @@ impl LengthOrNumber { /// Either a computed `` or the `normal` keyword. pub type LengthOrNormal = Either; +/// A wrapper of Length, whose value must be >= 0. +pub type NonNegativeLength = NonNegativeAu; + +/// Either a computed NonNegativeLength or the `auto` keyword. +pub type NonNegativeLengthOrAuto = Either; + +/// Either a computed NonNegativeLength or the `normal` keyword. +pub type NonNegativeLengthOrNormal = Either; + +/// Either a computed NonNegativeLength or a NonNegativeNumber value. +pub type NonNegativeLengthOrNumber = Either; + /// A value suitable for a `min-width`, `min-height`, `width` or `height` property. /// See values/specified/length.rs for more details. #[allow(missing_docs)] diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index d2b49ef5e22..8cbcbca7eea 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -18,6 +18,7 @@ use std::f64::consts::PI; use std::fmt; use style_traits::ToCss; use super::{CSSFloat, CSSInteger}; +use super::generics::{GreaterThanOrEqualToOne, NonNegative}; use super::generics::grid::{TrackBreadth as GenericTrackBreadth, TrackSize as GenericTrackSize}; use super::generics::grid::GridTemplateComponent as GenericGridTemplateComponent; use super::generics::grid::TrackList as GenericTrackList; @@ -43,8 +44,9 @@ pub use super::generics::grid::GridLine; pub use super::specified::url::SpecifiedUrl; pub use self::length::{CalcLengthOrPercentage, Length, LengthOrNone, LengthOrNumber, LengthOrPercentage}; pub use self::length::{LengthOrPercentageOrAuto, LengthOrPercentageOrNone, MaxLength, MozLength, Percentage}; +pub use self::length::NonNegativeLengthOrPercentage; pub use self::position::Position; -pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind, SVGStrokeDashArray}; +pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind, SVGStrokeDashArray, SVGWidth}; pub use self::text::{InitialLetter, LetterSpacing, LineHeight, WordSpacing}; pub use self::transform::{TimingFunction, TransformOrigin}; @@ -136,12 +138,12 @@ impl<'a> Context<'a> { /// Apply text-zoom if enabled #[cfg(feature = "gecko")] - pub fn maybe_zoom_text(&self, size: Au) -> Au { + pub fn maybe_zoom_text(&self, size: NonNegativeAu) -> NonNegativeAu { // We disable zoom for 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) + self.device().zoom_text(size.0).into() } else { size } @@ -149,7 +151,7 @@ impl<'a> Context<'a> { /// (Servo doesn't do text-zoom) #[cfg(feature = "servo")] - pub fn maybe_zoom_text(&self, size: Au) -> Au { + pub fn maybe_zoom_text(&self, size: NonNegativeAu) -> NonNegativeAu { size } } @@ -425,6 +427,40 @@ impl ComputedValueAsSpecified for specified::BorderStyle {} /// A `` value. pub type Number = CSSFloat; +/// A wrapper of Number, but the value >= 0. +pub type NonNegativeNumber = NonNegative; + +impl From for NonNegativeNumber { + #[inline] + fn from(number: CSSFloat) -> NonNegativeNumber { + NonNegative::(number) + } +} + +impl From for CSSFloat { + #[inline] + fn from(number: NonNegativeNumber) -> CSSFloat { + number.0 + } +} + +/// A wrapper of Number, but the value >= 1. +pub type GreaterThanOrEqualToOneNumber = GreaterThanOrEqualToOne; + +impl From for GreaterThanOrEqualToOneNumber { + #[inline] + fn from(number: CSSFloat) -> GreaterThanOrEqualToOneNumber { + GreaterThanOrEqualToOne::(number) + } +} + +impl From for CSSFloat { + #[inline] + fn from(number: GreaterThanOrEqualToOneNumber) -> CSSFloat { + number.0 + } +} + #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[derive(Clone, Copy, Debug, PartialEq, ToCss)] @@ -476,9 +512,25 @@ impl IntegerOrAuto { } } +/// A wrapper of Integer, but only accept a value >= 1. +pub type PositiveInteger = GreaterThanOrEqualToOne; + +impl From for PositiveInteger { + #[inline] + fn from(int: CSSInteger) -> PositiveInteger { + GreaterThanOrEqualToOne::(int) + } +} + +/// PositiveInteger | auto +pub type PositiveIntegerOrAuto = Either; + /// | | pub type LengthOrPercentageOrNumber = Either; +/// NonNegativeLengthOrPercentage | NonNegativeNumber +pub type NonNegativeLengthOrPercentageOrNumber = Either; + #[derive(Clone, PartialEq, Eq, Copy, Debug)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[allow(missing_docs)] @@ -556,3 +608,40 @@ impl ClipRectOrAuto { /// | auto pub type ColorOrAuto = Either; + +/// A wrapper of Au, but the value >= 0. +pub type NonNegativeAu = NonNegative; + +impl NonNegativeAu { + /// Return a zero value. + #[inline] + pub fn zero() -> Self { + NonNegative::(Au(0)) + } + + /// Return a NonNegativeAu from pixel. + #[inline] + pub fn from_px(px: i32) -> Self { + NonNegative::(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::(self.0.scale_by(factor.max(0.))) + } +} + +impl From for NonNegativeAu { + #[inline] + fn from(au: Au) -> NonNegativeAu { + NonNegative::(au) + } +} diff --git a/components/style/values/computed/svg.rs b/components/style/values/computed/svg.rs index 9edc7a36220..43613baa8c4 100644 --- a/components/style/values/computed/svg.rs +++ b/components/style/values/computed/svg.rs @@ -7,6 +7,7 @@ use app_units::Au; use values::{Either, RGBA}; use values::computed::{LengthOrPercentageOrNumber, Opacity}; +use values::computed::{NonNegativeAu, NonNegativeLengthOrPercentageOrNumber}; use values::generics::svg as generic; /// Computed SVG Paint value @@ -43,8 +44,17 @@ impl From for SVGLength { } } +/// An non-negative wrapper of SVGLength. +pub type SVGWidth = generic::SVGLength; + +impl From for SVGWidth { + fn from(length: NonNegativeAu) -> Self { + generic::SVGLength::Length(Either::Second(length.into())) + } +} + /// [ | | ]# | context-value -pub type SVGStrokeDashArray = generic::SVGStrokeDashArray; +pub type SVGStrokeDashArray = generic::SVGStrokeDashArray; impl Default for SVGStrokeDashArray { fn default() -> Self { diff --git a/components/style/values/computed/text.rs b/components/style/values/computed/text.rs index c6902515c2a..7376616ba5e 100644 --- a/components/style/values/computed/text.rs +++ b/components/style/values/computed/text.rs @@ -4,10 +4,10 @@ //! Computed types for text properties. -use app_units::Au; use properties::animated_properties::Animatable; use values::{CSSInteger, CSSFloat}; use values::animated::ToAnimatedZero; +use values::computed::{NonNegativeAu, NonNegativeNumber}; use values::computed::length::{Length, LengthOrPercentage}; use values::generics::text::InitialLetter as GenericInitialLetter; use values::generics::text::LineHeight as GenericLineHeight; @@ -23,7 +23,7 @@ pub type LetterSpacing = Spacing; pub type WordSpacing = Spacing; /// A computed value for the `line-height` property. -pub type LineHeight = GenericLineHeight; +pub type LineHeight = GenericLineHeight; impl Animatable for LineHeight { #[inline] diff --git a/components/style/values/generics/effects.rs b/components/style/values/generics/effects.rs index f0a6cbc0b8b..9105123f5ab 100644 --- a/components/style/values/generics/effects.rs +++ b/components/style/values/generics/effects.rs @@ -12,9 +12,9 @@ use values::specified::url::SpecifiedUrl; /// A generic value for a single `box-shadow`. #[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[derive(Clone, Debug, HasViewportPercentage, PartialEq, ToAnimatedValue)] -pub struct BoxShadow { +pub struct BoxShadow { /// The base shadow. - pub base: SimpleShadow, + pub base: SimpleShadow, /// The spread radius. pub spread: ShapeLength, /// Whether this is an inset box shadow. @@ -77,10 +77,14 @@ pub struct SimpleShadow { pub blur: ShapeLength, } -impl ToCss for BoxShadow +impl ToCss for BoxShadow where Color: ToCss, SizeLength: ToCss, + BlurShapeLength: ToCss, ShapeLength: ToCss, { fn to_css(&self, dest: &mut W) -> fmt::Result diff --git a/components/style/values/generics/mod.rs b/components/style/values/generics/mod.rs index 9456f0061c5..f87b7a88de5 100644 --- a/components/style/values/generics/mod.rs +++ b/components/style/values/generics/mod.rs @@ -252,3 +252,13 @@ impl ToCss for FontSettingTagFloat { self.0.to_css(dest) } } + +/// A wrapper of Non-negative values. +#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, PartialOrd, ToComputedValue, ToCss)] +#[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))] +pub struct NonNegative(pub T); + +/// A wrapper of greater-than-or-equal-to-one values. +#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, PartialOrd, ToComputedValue, ToCss)] +#[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))] +pub struct GreaterThanOrEqualToOne(pub T); diff --git a/components/style/values/generics/svg.rs b/components/style/values/generics/svg.rs index 0970cd9b4fd..557a63fd24c 100644 --- a/components/style/values/generics/svg.rs +++ b/components/style/values/generics/svg.rs @@ -98,7 +98,7 @@ impl Parse for SVGPaint { /// An SVG length value supports `context-value` in addition to length. #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[derive(Clone, Copy, Debug, PartialEq, HasViewportPercentage, ToComputedValue, ToCss)] +#[derive(Clone, Copy, Debug, PartialEq, HasViewportPercentage, ToAnimatedValue, ToComputedValue, ToCss)] pub enum SVGLength { /// ` | | ` Length(LengthType), @@ -108,7 +108,7 @@ pub enum SVGLength { /// Generic value for stroke-dasharray. #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[derive(Clone, Debug, PartialEq, HasViewportPercentage, ToComputedValue)] +#[derive(Clone, Debug, PartialEq, HasViewportPercentage, ToAnimatedValue, ToComputedValue)] pub enum SVGStrokeDashArray { /// `[ | | ]#` Values(Vec), diff --git a/components/style/values/generics/text.rs b/components/style/values/generics/text.rs index 995752ce70f..94be4a6db8c 100644 --- a/components/style/values/generics/text.rs +++ b/components/style/values/generics/text.rs @@ -104,7 +104,7 @@ where /// A generic value for the `line-height` property. #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToCss)] +#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, ToAnimatedValue, ToCss)] pub enum LineHeight { /// `normal` Normal, diff --git a/components/style/values/specified/border.rs b/components/style/values/specified/border.rs index 6a6da001db3..419074babe6 100644 --- a/components/style/values/specified/border.rs +++ b/components/style/values/specified/border.rs @@ -4,11 +4,10 @@ //! Specified types for CSS values related to borders. -use app_units::Au; use cssparser::Parser; use parser::{Parse, ParserContext}; use style_traits::ParseError; -use values::computed::{Context, ToComputedValue}; +use values::computed::{Context, NonNegativeAu, ToComputedValue}; use values::generics::border::BorderCornerRadius as GenericBorderCornerRadius; use values::generics::border::BorderImageSideWidth as GenericBorderImageSideWidth; use values::generics::border::BorderImageSlice as GenericBorderImageSlice; @@ -72,7 +71,7 @@ impl Parse for BorderSideWidth { } impl ToComputedValue for BorderSideWidth { - type ComputedValue = Au; + type ComputedValue = NonNegativeAu; #[inline] fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { @@ -84,12 +83,12 @@ impl ToComputedValue for BorderSideWidth { 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) - } + }.into() } #[inline] fn from_computed_value(computed: &Self::ComputedValue) -> Self { - BorderSideWidth::Length(ToComputedValue::from_computed_value(computed)) + BorderSideWidth::Length(ToComputedValue::from_computed_value(&computed.0)) } } diff --git a/components/style/values/specified/effects.rs b/components/style/values/specified/effects.rs index 134827e958e..27bf0f531aa 100644 --- a/components/style/values/specified/effects.rs +++ b/components/style/values/specified/effects.rs @@ -9,28 +9,29 @@ use parser::{Parse, ParserContext}; use style_traits::{ParseError, StyleParseError}; #[cfg(not(feature = "gecko"))] use values::Impossible; -use values::computed::{Context, Number as ComputedNumber, ToComputedValue}; +use values::computed::{Context, NonNegativeNumber as ComputedNonNegativeNumber, ToComputedValue}; use values::computed::effects::BoxShadow as ComputedBoxShadow; use values::computed::effects::SimpleShadow as ComputedSimpleShadow; +use values::generics::NonNegative; use values::generics::effects::BoxShadow as GenericBoxShadow; use values::generics::effects::Filter as GenericFilter; use values::generics::effects::SimpleShadow as GenericSimpleShadow; use values::specified::{Angle, NumberOrPercentage}; use values::specified::color::Color; -use values::specified::length::Length; +use values::specified::length::{Length, NonNegativeLength}; #[cfg(feature = "gecko")] use values::specified::url::SpecifiedUrl; /// A specified value for a single shadow of the `box-shadow` property. -pub type BoxShadow = GenericBoxShadow, Length, Option>; +pub type BoxShadow = GenericBoxShadow, Length, Option, Option>; /// A specified value for a single `filter`. #[cfg(feature = "gecko")] -pub type Filter = GenericFilter; +pub type Filter = GenericFilter; /// A specified value for a single `filter`. #[cfg(not(feature = "gecko"))] -pub type Filter = GenericFilter; +pub type Filter = GenericFilter; /// A value for the `` parts in `Filter`. #[derive(Clone, Debug, HasViewportPercentage, PartialEq, ToCss)] @@ -48,25 +49,25 @@ impl Parse for Factor { } impl ToComputedValue for Factor { - type ComputedValue = ComputedNumber; + type ComputedValue = ComputedNonNegativeNumber; #[inline] fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { use values::computed::NumberOrPercentage; match self.0.to_computed_value(context) { - NumberOrPercentage::Number(n) => n, - NumberOrPercentage::Percentage(p) => p.0, + NumberOrPercentage::Number(n) => n.into(), + NumberOrPercentage::Percentage(p) => p.0.into(), } } #[inline] fn from_computed_value(computed: &Self::ComputedValue) -> Self { - Factor(NumberOrPercentage::Number(ToComputedValue::from_computed_value(computed))) + Factor(NumberOrPercentage::Number(ToComputedValue::from_computed_value(&computed.0))) } } /// A specified value for the `drop-shadow()` filter. -pub type SimpleShadow = GenericSimpleShadow, Length, Option>; +pub type SimpleShadow = GenericSimpleShadow, Length, Option>; impl Parse for BoxShadow { fn parse<'i, 't>( @@ -91,7 +92,7 @@ impl Parse for BoxShadow { let (blur, spread) = match i.try::<_, _, ParseError>(|i| Length::parse_non_negative(context, i)) { Ok(blur) => { let spread = i.try(|i| Length::parse(context, i)).ok(); - (Some(blur), spread) + (Some(blur.into()), spread) }, Err(_) => (None, None), }; @@ -162,7 +163,7 @@ impl Parse for Filter { let function = input.expect_function()?.clone(); input.parse_nested_block(|i| { try_match_ident_ignore_ascii_case! { function, - "blur" => Ok(GenericFilter::Blur(Length::parse_non_negative(context, i)?)), + "blur" => Ok(GenericFilter::Blur((Length::parse_non_negative(context, i)?).into())), "brightness" => Ok(GenericFilter::Brightness(Factor::parse(context, i)?)), "contrast" => Ok(GenericFilter::Contrast(Factor::parse(context, i)?)), "grayscale" => Ok(GenericFilter::Grayscale(Factor::parse(context, i)?)), @@ -192,7 +193,7 @@ impl Parse for SimpleShadow { color: color, horizontal: horizontal, vertical: vertical, - blur: blur, + blur: blur.map(NonNegative::), }) } } @@ -208,7 +209,7 @@ impl ToComputedValue for SimpleShadow { horizontal: self.horizontal.to_computed_value(context), vertical: self.vertical.to_computed_value(context), blur: - self.blur.as_ref().unwrap_or(&Length::zero()).to_computed_value(context), + self.blur.as_ref().unwrap_or(&NonNegativeLength::zero()).to_computed_value(context), } } diff --git a/components/style/values/specified/length.rs b/components/style/values/specified/length.rs index bf4b83b5293..8959743655e 100644 --- a/components/style/values/specified/length.rs +++ b/components/style/values/specified/length.rs @@ -21,6 +21,8 @@ use super::{AllowQuirks, Number, ToComputedValue}; use values::{Auto, CSSFloat, Either, FONT_MEDIUM_PX, None_, Normal}; use values::ExtremumLength; use values::computed::{self, Context}; +use values::generics::NonNegative; +use values::specified::NonNegativeNumber; use values::specified::calc::CalcNode; pub use values::specified::calc::CalcLengthOrPercentage; @@ -92,8 +94,8 @@ impl FontBaseSize { pub fn resolve(&self, context: &Context) -> Au { match *self { FontBaseSize::Custom(size) => size, - FontBaseSize::CurrentStyle => context.style().get_font().clone_font_size(), - FontBaseSize::InheritedStyle => context.style().get_parent_font().clone_font_size(), + FontBaseSize::CurrentStyle => context.style().get_font().clone_font_size().0, + FontBaseSize::InheritedStyle => context.style().get_parent_font().clone_font_size().0, } } } @@ -703,6 +705,57 @@ impl Either { } } +/// A wrapper of Length, whose value must be >= 0. +pub type NonNegativeLength = NonNegative; + +impl From for NonNegativeLength { + #[inline] + fn from(len: NoCalcLength) -> Self { + NonNegative::(Length::NoCalc(len)) + } +} + +impl From for NonNegativeLength { + #[inline] + fn from(len: Length) -> Self { + NonNegative::(len) + } +} + +impl Parse for Either { + #[inline] + fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { + 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(NonNegative::).map(Either::First) + } +} + +impl NonNegativeLength { + /// Returns a `zero` length. + #[inline] + pub fn zero() -> Self { + Length::zero().into() + } + + /// Get an absolute length from a px value. + #[inline] + pub fn from_px(px_value: CSSFloat) -> Self { + Length::from_px(px_value.max(0.)).into() + } +} + +/// Either a NonNegativeLength or the `normal` keyword. +pub type NonNegativeLengthOrNormal = Either; + +/// Either a NonNegativeLength or the `auto` keyword. +pub type NonNegativeLengthOrAuto = Either; + +/// Either a NonNegativeLength or a NonNegativeNumber value. +pub type NonNegativeLengthOrNumber = Either; + /// A percentage value. #[derive(Clone, Copy, Debug, Default, PartialEq)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] @@ -1185,6 +1238,41 @@ impl Parse for LengthOrPercentageOrNone { } } +/// A wrapper of LengthOrPercentage, whose value must be >= 0. +pub type NonNegativeLengthOrPercentage = NonNegative; + +impl From for NonNegativeLengthOrPercentage { + #[inline] + fn from(len: NoCalcLength) -> Self { + NonNegative::(LengthOrPercentage::from(len)) + } +} + +impl Parse for NonNegativeLengthOrPercentage { + #[inline] + fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { + LengthOrPercentage::parse_non_negative(context, input).map(NonNegative::) + } +} + +impl NonNegativeLengthOrPercentage { + #[inline] + /// Returns a `zero` length. + pub fn zero() -> Self { + NonNegative::(LengthOrPercentage::zero()) + } + + /// 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> { + LengthOrPercentage::parse_non_negative_quirky(context, input, allow_quirks) + .map(NonNegative::) + } +} + /// Either a `` or the `none` keyword. pub type LengthOrNone = Either; diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index 02ad9ac32f0..9a2dd857efc 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -18,6 +18,7 @@ use style_traits::{ToCss, ParseError, StyleParseError}; use style_traits::values::specified::AllowedNumericType; use super::{Auto, CSSFloat, CSSInteger, Either, None_}; use super::computed::{self, Context, ToComputedValue}; +use super::generics::{GreaterThanOrEqualToOne, NonNegative}; use super::generics::grid::{TrackBreadth as GenericTrackBreadth, TrackSize as GenericTrackSize}; use super::generics::grid::TrackList as GenericTrackList; use values::computed::ComputedValueAsSpecified; @@ -41,9 +42,10 @@ pub use self::length::{FontRelativeLength, Length, LengthOrNone, LengthOrNumber} pub use self::length::{LengthOrPercentage, LengthOrPercentageOrAuto}; pub use self::length::{LengthOrPercentageOrNone, MaxLength, MozLength}; pub use self::length::{NoCalcLength, Percentage, ViewportPercentageLength}; +pub use self::length::NonNegativeLengthOrPercentage; pub use self::rect::LengthOrNumberRect; pub use self::position::{Position, PositionComponent}; -pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind, SVGStrokeDashArray}; +pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind, SVGStrokeDashArray, SVGWidth}; pub use self::text::{InitialLetter, LetterSpacing, LineHeight, WordSpacing}; pub use self::transform::{TimingFunction, TransformOrigin}; pub use super::generics::grid::GridLine; @@ -533,6 +535,33 @@ impl ToCss for Number { } } +/// A Number which is >= 0.0. +pub type NonNegativeNumber = NonNegative; + +impl Parse for NonNegativeNumber { + fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { + parse_number_with_clamping_mode(context, input, AllowedNumericType::NonNegative) + .map(NonNegative::) + } +} + +impl NonNegativeNumber { + /// Returns a new non-negative number with the value `val`. + pub fn new(val: CSSFloat) -> Self { + NonNegative::(Number::new(val.max(0.))) + } +} + +/// A Number which is >= 1.0. +pub type GreaterThanOrEqualToOneNumber = GreaterThanOrEqualToOne; + +impl Parse for GreaterThanOrEqualToOneNumber { + fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { + parse_number_with_clamping_mode(context, input, AllowedNumericType::AtLeastOne) + .map(GreaterThanOrEqualToOne::) + } +} + /// | /// /// Accepts only non-negative numbers. @@ -713,6 +742,19 @@ impl IntegerOrAuto { } } +/// A wrapper of Integer, with value >= 1. +pub type PositiveInteger = GreaterThanOrEqualToOne; + +impl Parse for PositiveInteger { + #[inline] + fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { + Integer::parse_positive(context, input).map(GreaterThanOrEqualToOne::) + } +} + +/// PositiveInteger | auto +pub type PositiveIntegerOrAuto = Either; + #[allow(missing_docs)] pub type UrlOrNone = Either; @@ -732,19 +774,8 @@ pub type GridTemplateComponent = GenericGridTemplateComponent | | pub type LengthOrPercentageOrNumber = Either; -impl LengthOrPercentageOrNumber { - /// parse a | enforcing that the contents aren't negative - pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) - -> Result> { - // NB: Parse numbers before Lengths so we are consistent about how to - // recognize and serialize "0". - if let Ok(num) = input.try(|i| Number::parse_non_negative(context, i)) { - return Ok(Either::First(num)) - } - - LengthOrPercentage::parse_non_negative(context, input).map(Either::Second) - } -} +/// NonNegativeLengthOrPercentage | NonNegativeNumber +pub type NonNegativeLengthOrPercentageOrNumber = Either; #[derive(Clone, Debug, HasViewportPercentage, PartialEq)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] diff --git a/components/style/values/specified/svg.rs b/components/style/values/specified/svg.rs index a89ba3ad15e..8ee5736bbd7 100644 --- a/components/style/values/specified/svg.rs +++ b/components/style/values/specified/svg.rs @@ -8,7 +8,7 @@ use cssparser::Parser; use parser::{Parse, ParserContext}; use style_traits::{CommaWithSpace, ParseError, Separator, StyleParseError}; use values::generics::svg as generic; -use values::specified::{LengthOrPercentageOrNumber, Opacity}; +use values::specified::{LengthOrPercentageOrNumber, NonNegativeLengthOrPercentageOrNumber, Opacity}; use values::specified::color::RGBAColor; /// Specified SVG Paint value @@ -54,30 +54,38 @@ impl Parse for SVGLength { } } -impl SVGLength { - /// parse a non-negative SVG length - pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) - -> Result> { - input.try(|i| LengthOrPercentageOrNumber::parse_non_negative(context, i)) - .map(Into::into) - .or_else(|_| parse_context_value(input, generic::SVGLength::ContextValue)) - } -} - impl From for SVGLength { fn from(length: LengthOrPercentageOrNumber) -> Self { generic::SVGLength::Length(length) } } +/// A non-negative version of SVGLength. +pub type SVGWidth = generic::SVGLength; + +impl Parse for SVGWidth { + fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) + -> Result> { + input.try(|i| NonNegativeLengthOrPercentageOrNumber::parse(context, i)) + .map(Into::into) + .or_else(|_| parse_context_value(input, generic::SVGLength::ContextValue)) + } +} + +impl From for SVGWidth { + fn from(length: NonNegativeLengthOrPercentageOrNumber) -> Self { + generic::SVGLength::Length(length) + } +} + /// [ | | ]# | context-value -pub type SVGStrokeDashArray = generic::SVGStrokeDashArray; +pub type SVGStrokeDashArray = generic::SVGStrokeDashArray; impl Parse for SVGStrokeDashArray { fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { if let Ok(values) = input.try(|i| CommaWithSpace::parse(i, |i| { - LengthOrPercentageOrNumber::parse_non_negative(context, i) + NonNegativeLengthOrPercentageOrNumber::parse(context, i) })) { Ok(generic::SVGStrokeDashArray::Values(values)) } else if let Ok(_) = input.try(|i| i.expect_ident_matching("none")) { diff --git a/components/style/values/specified/text.rs b/components/style/values/specified/text.rs index 495b3eebd33..8341d6236f1 100644 --- a/components/style/values/specified/text.rs +++ b/components/style/values/specified/text.rs @@ -14,8 +14,9 @@ use values::computed::text::LineHeight as ComputedLineHeight; use values::generics::text::InitialLetter as GenericInitialLetter; use values::generics::text::LineHeight as GenericLineHeight; use values::generics::text::Spacing; -use values::specified::{AllowQuirks, Integer, Number}; +use values::specified::{AllowQuirks, Integer, NonNegativeNumber, Number}; use values::specified::length::{FontRelativeLength, Length, LengthOrPercentage, NoCalcLength}; +use values::specified::length::NonNegativeLengthOrPercentage; /// A specified type for the `initial-letter` property. pub type InitialLetter = GenericInitialLetter; @@ -27,7 +28,7 @@ pub type LetterSpacing = Spacing; pub type WordSpacing = Spacing; /// A specified value for the `line-height` property. -pub type LineHeight = GenericLineHeight; +pub type LineHeight = GenericLineHeight; impl Parse for InitialLetter { fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { @@ -58,11 +59,11 @@ impl Parse for WordSpacing { impl Parse for LineHeight { fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { - if let Ok(number) = input.try(|i| Number::parse_non_negative(context, i)) { + if let Ok(number) = input.try(|i| NonNegativeNumber::parse(context, i)) { return Ok(GenericLineHeight::Number(number)) } - if let Ok(lop) = input.try(|i| LengthOrPercentage::parse_non_negative(context, i)) { - return Ok(GenericLineHeight::Length(lop)) + if let Ok(nlop) = input.try(|i| NonNegativeLengthOrPercentage::parse(context, i)) { + return Ok(GenericLineHeight::Length(nlop)) } let ident = input.expect_ident()?; match ident { @@ -94,24 +95,29 @@ impl ToComputedValue for LineHeight { GenericLineHeight::Number(number) => { GenericLineHeight::Number(number.to_computed_value(context)) }, - GenericLineHeight::Length(LengthOrPercentage::Length(ref length)) => { - GenericLineHeight::Length(context.maybe_zoom_text(length.to_computed_value(context))) - }, - GenericLineHeight::Length(LengthOrPercentage::Percentage(p)) => { - let font_relative_length = - Length::NoCalc(NoCalcLength::FontRelative(FontRelativeLength::Em(p.0))); - GenericLineHeight::Length(font_relative_length.to_computed_value(context)) - }, - GenericLineHeight::Length(LengthOrPercentage::Calc(ref calc)) => { - let computed_calc = calc.to_computed_value_zoomed(context); - let font_relative_length = - Length::NoCalc(NoCalcLength::FontRelative(FontRelativeLength::Em(computed_calc.percentage()))); - let absolute_length = computed_calc.unclamped_length(); - let computed_length = computed_calc.clamping_mode.clamp( - absolute_length + font_relative_length.to_computed_value(context) - ); - GenericLineHeight::Length(computed_length) - }, + GenericLineHeight::Length(ref non_negative_lop) => { + let result = match non_negative_lop.0 { + LengthOrPercentage::Length(ref length) => { + context.maybe_zoom_text(length.to_computed_value(context).into()) + }, + LengthOrPercentage::Percentage(ref p) => { + let font_relative_length = + Length::NoCalc(NoCalcLength::FontRelative(FontRelativeLength::Em(p.0))); + font_relative_length.to_computed_value(context).into() + } + LengthOrPercentage::Calc(ref calc) => { + let computed_calc = calc.to_computed_value_zoomed(context); + let font_relative_length = + Length::NoCalc(NoCalcLength::FontRelative( + FontRelativeLength::Em(computed_calc.percentage()))); + let absolute_length = computed_calc.unclamped_length(); + computed_calc.clamping_mode.clamp( + absolute_length + font_relative_length.to_computed_value(context) + ).into() + } + }; + GenericLineHeight::Length(result) + } } } @@ -126,12 +132,10 @@ impl ToComputedValue for LineHeight { GenericLineHeight::MozBlockHeight }, GenericLineHeight::Number(ref number) => { - GenericLineHeight::Number(Number::from_computed_value(number)) + GenericLineHeight::Number(NonNegativeNumber::from_computed_value(number)) }, GenericLineHeight::Length(ref length) => { - GenericLineHeight::Length(LengthOrPercentage::Length( - NoCalcLength::from_computed_value(length) - )) + GenericLineHeight::Length(NoCalcLength::from_computed_value(&length.0).into()) } } } diff --git a/tests/unit/style/properties/serialization.rs b/tests/unit/style/properties/serialization.rs index 59013d1a01e..3cf56a1dc7f 100644 --- a/tests/unit/style/properties/serialization.rs +++ b/tests/unit/style/properties/serialization.rs @@ -268,10 +268,12 @@ mod shorthand_serialization { #[test] fn padding_should_serialize_correctly() { + use style::values::specified::NonNegativeLengthOrPercentage; + let mut properties = Vec::new(); - let px_10 = LengthOrPercentage::Length(NoCalcLength::from_px(10f32)); - let px_15 = LengthOrPercentage::Length(NoCalcLength::from_px(15f32)); + let px_10: NonNegativeLengthOrPercentage = NoCalcLength::from_px(10f32).into(); + let px_15: NonNegativeLengthOrPercentage = NoCalcLength::from_px(15f32).into(); properties.push(PropertyDeclaration::PaddingTop(px_10.clone())); properties.push(PropertyDeclaration::PaddingRight(px_15.clone())); properties.push(PropertyDeclaration::PaddingBottom(px_10)); @@ -556,12 +558,12 @@ mod shorthand_serialization { #[test] fn flex_should_serialize_all_available_properties() { - use style::values::specified::{Number, Percentage}; + use style::values::specified::{NonNegativeNumber, Percentage}; let mut properties = Vec::new(); - let grow = Number::new(2f32); - let shrink = Number::new(3f32); + let grow = NonNegativeNumber::new(2f32); + let shrink = NonNegativeNumber::new(3f32); let basis = FlexBasis::Length(Percentage::new(0.5f32).into()); @@ -1239,13 +1241,15 @@ mod shorthand_serialization { #[test] fn box_shadow_should_serialize_correctly() { + use style::values::specified::length::NonNegativeLength; + let mut properties = Vec::new(); let shadow_val = BoxShadow { base: SimpleShadow { color: None, horizontal: Length::from_px(1f32), vertical: Length::from_px(2f32), - blur: Some(Length::from_px(3f32)), + blur: Some(NonNegativeLength::from_px(3f32)), }, spread: Some(Length::from_px(4f32)), inset: false,