servo: Merge #17783 - stylo: Bug 1374233 - Clamp interpolated values for properties which need to be restricted (from BorisChiou:stylo/animation/restrictions); r=nox

Some properties only accept non-negative values, or values greater than or equal to one. It is possible to produce an negative interpolated values while using negative timing functions, so we have to apply a restriction to these values to avoid getting invalid values.

For example, line-height must be non-negative, but the output progress of some timing functions (e,g. cubic-bezier(0.25, -2, 0.75, 1)) may be a negative value, so the interpolated result of line-height is also negative.

---
- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors
- [X] These changes fix Bug 1374233.
- [X] These changes do not require tests because we have tests in Gecko side already.

Source-Repo: https://github.com/servo/servo
Source-Revision: 016ea11cbaf7586db144be122581c5b110649aee

--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 3562be334610046cb0edaad2fc231dd169a4aa0d
This commit is contained in:
Boris Chiou 2017-08-07 11:05:17 -05:00
parent 0a70fd0b47
commit 102da9013f
56 changed files with 1039 additions and 371 deletions

View File

@ -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 {

View File

@ -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)
}
}

View File

@ -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<Au>) {
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(),
}));

View File

@ -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

View File

@ -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))

View File

@ -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!(),
}
}

View File

@ -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; }

View File

@ -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)
}

View File

@ -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;
}
}
}

View File

@ -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) {

View File

@ -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
}
}

View File

@ -190,15 +190,15 @@ impl ToFilterOps for Vec<Filter> {
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 {},
}
}

View File

@ -548,7 +548,7 @@ impl LayoutElementHelpers for LayoutJS<Element> {
shared_lock,
PropertyDeclaration::BorderSpacing(
Box::new(border_spacing::SpecifiedValue {
horizontal: width_value,
horizontal: width_value.into(),
vertical: None,
}))));
}

View File

@ -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),
}

View File

@ -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<T: CoordDataMut>(&self, coord: &mut T) {
self.0.to_gecko_style_coord(coord);
}
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
LengthOrPercentage::from_gecko_style_coord(coord).map(NonNegative::<LengthOrPercentage>)
}
}
impl GeckoStyleCoordConvertible for Au {
fn to_gecko_style_coord<T: CoordDataMut>(&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<T: CoordDataMut>(&self, coord: &mut T) {
self.0.to_gecko_style_coord(coord);
}
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
Au::from_gecko_style_coord(coord).map(NonNegative::<Au>)
}
}
impl GeckoStyleCoordConvertible for NonNegativeNumber {
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
self.0.to_gecko_style_coord(coord);
}
fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
Number::from_gecko_style_coord(coord).map(NonNegative::<Number>)
}
}
impl GeckoStyleCoordConvertible for LengthOrPercentageOrAuto {
fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
let value = match *self {

View File

@ -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(),
}
}
}

View File

@ -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.

View File

@ -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)

View File

@ -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>
<%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})
}
</%def>
@ -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>
<%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
</%def>
@ -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<Au> {
device: &Device) -> Option<NonNegativeAu> {
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<Au>,
kw_inherited_size: Option<NonNegativeAu>,
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()
}
}
</%self:impl_trait>
@ -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>
<%call expr="impl_non_negative_app_units('_webkit_text_stroke_width',
'mWebkitTextStrokeWidth',
need_clone=True)"></%call>
#[allow(non_snake_case)]
pub fn set__moz_tab_size(&mut self, v: longhands::_moz_tab_size::computed_value::T) {
use values::Either;
match v {
Either::Second(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>
<%self:impl_trait style_struct_name="Counters"

View File

@ -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.
</%doc>
<%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;

View File

@ -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<f32, LengthOrPercentage> {}
impl RepeatableListAnimatable for Either<NonNegativeNumber, NonNegativeLengthOrPercentage> {}
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::<CSSFloat>(0.0),
)?))
},
% endfor
@ -3202,7 +3210,7 @@ fn add_weighted_filter_function_impl(from: &AnimatedFilter,
&to_value,
self_portion,
other_portion,
&1.0,
&NonNegative::<CSSFloat>(1.0),
)?))
},
% endfor
@ -3373,3 +3381,49 @@ sorted_shorthands = [(p, position) for position, p in enumerate(sorted_shorthand
% endfor
}
}
impl<T> Animatable for NonNegative<T>
where T: Animatable + Clone
{
#[inline]
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
self.0.add_weighted(&other.0, self_portion, other_portion).map(NonNegative::<T>)
}
#[inline]
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
self.0.compute_distance(&other.0)
}
}
impl<T> ToAnimatedZero for NonNegative<T>
where T: ToAnimatedZero
{
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
self.0.to_animated_zero().map(NonNegative::<T>)
}
}
impl<T> Animatable for GreaterThanOrEqualToOne<T>
where T: Animatable + Clone
{
#[inline]
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
self.0.add_weighted(&other.0, self_portion, other_portion).map(GreaterThanOrEqualToOne::<T>)
}
#[inline]
fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
self.0.compute_distance(&other.0)
}
}
impl<T> ToAnimatedZero for GreaterThanOrEqualToOne<T>
where T: ToAnimatedZero
{
#[inline]
fn to_animated_zero(&self) -> Result<Self, ()> {
self.0.to_animated_zero().map(GreaterThanOrEqualToOne::<T>)
}
}

View File

@ -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")}

View File

@ -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

View File

@ -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

View File

@ -591,7 +591,7 @@ ${helpers.single_keyword_system("font-variant-caps",
}
</%helpers:longhand>
<%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>
<%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<Self, ()> { 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),

View File

@ -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",
)}

View File

@ -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<Self, ()> { 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<Length>,
pub horizontal: NonNegativeLength,
pub vertical: Option<NonNegativeLength>,
}
#[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!(),

View File

@ -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",

View File

@ -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

View File

@ -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",

View File

@ -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"]:

View File

@ -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)")}

View File

@ -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<Au>, _: &Device) -> bool {
_: Option<NonNegativeAu>,
_: &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<Au> {
_: &Device) -> Option<NonNegativeAu> {
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<computed::LengthOrPercentage> {
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<Au> {
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<ComputedValues>,
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<ComputedValues>,
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;
}
}

View File

@ -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)}

View File

@ -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<Number>),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<NonNegativeNumber>),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<Longhands, ParseError<'i>> {
@ -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<W>(&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(());
}

View File

@ -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),
}
}

View File

@ -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());
}
}

View File

@ -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<SimpleShadow>;
pub struct ShadowList<Shadow>(Vec<Shadow>);
/// An animated value for a single `box-shadow`.
pub type BoxShadow = GenericBoxShadow<IntermediateColor, Length, Length>;
pub type BoxShadow = GenericBoxShadow<IntermediateColor, Length, NonNegativeLength, Length>;
/// An animated value for the `filter` property.
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@ -41,14 +41,14 @@ pub struct FilterList(pub Vec<Filter>);
/// An animated value for a single `filter`.
#[cfg(feature = "gecko")]
pub type Filter = GenericFilter<Angle, Number, Length, SimpleShadow>;
pub type Filter = GenericFilter<Angle, NonNegativeNumber, NonNegativeLength, SimpleShadow>;
/// An animated value for a single `filter`.
#[cfg(not(feature = "gecko"))]
pub type Filter = GenericFilter<Angle, Number, Length, Impossible>;
pub type Filter = GenericFilter<Angle, NonNegativeNumber, NonNegativeLength, Impossible>;
/// An animated value for the `drop-shadow()` filter.
pub type SimpleShadow = GenericSimpleShadow<IntermediateColor, Length, Length>;
pub type SimpleShadow = GenericSimpleShadow<IntermediateColor, Length, NonNegativeLength>;
impl ToAnimatedValue for ComputedBoxShadowList {
type AnimatedValue = BoxShadowList;

View File

@ -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<T> 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

View File

@ -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<Self, ()> { 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))
}
}

View File

@ -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<Color, Length, Length>;
pub type BoxShadow = GenericBoxShadow<Color, Length, NonNegativeLength, Length>;
/// A computed value for a single `filter`.
#[cfg(feature = "gecko")]
pub type Filter = GenericFilter<Angle, Number, Length, SimpleShadow>;
pub type Filter = GenericFilter<Angle, NonNegativeNumber, NonNegativeLength, SimpleShadow>;
/// A computed value for a single `filter`.
#[cfg(not(feature = "gecko"))]
pub type Filter = GenericFilter<Angle, Number, Length, Impossible>;
pub type Filter = GenericFilter<Angle, NonNegativeNumber, NonNegativeLength, Impossible>;
/// A computed value for the `drop-shadow()` filter.
pub type SimpleShadow = GenericSimpleShadow<Color, Length, Length>;
pub type SimpleShadow = GenericSimpleShadow<Color, Length, NonNegativeLength>;

View File

@ -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<LengthOrPercentage>;
impl From<NonNegativeAu> for NonNegativeLengthOrPercentage {
#[inline]
fn from(length: NonNegativeAu) -> Self {
LengthOrPercentage::Length(length.0).into()
}
}
impl From<LengthOrPercentage> for NonNegativeLengthOrPercentage {
#[inline]
fn from(lop: LengthOrPercentage) -> Self {
NonNegative::<LengthOrPercentage>(lop)
}
}
impl NonNegativeLengthOrPercentage {
/// Get zero value.
#[inline]
pub fn zero() -> Self {
NonNegative::<LengthOrPercentage>(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 `<length>` value.
pub type Length = Au;
@ -573,6 +626,18 @@ impl LengthOrNumber {
/// Either a computed `<length>` or the `normal` keyword.
pub type LengthOrNormal = Either<Length, Normal>;
/// A wrapper of Length, whose value must be >= 0.
pub type NonNegativeLength = NonNegativeAu;
/// Either a computed NonNegativeLength or the `auto` keyword.
pub type NonNegativeLengthOrAuto = Either<NonNegativeLength, Auto>;
/// Either a computed NonNegativeLength or the `normal` keyword.
pub type NonNegativeLengthOrNormal = Either<NonNegativeLength, Normal>;
/// Either a computed NonNegativeLength or a NonNegativeNumber value.
pub type NonNegativeLengthOrNumber = Either<NonNegativeLength, NonNegativeNumber>;
/// A value suitable for a `min-width`, `min-height`, `width` or `height` property.
/// See values/specified/length.rs for more details.
#[allow(missing_docs)]

View File

@ -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 <svg:text> by unsetting the
// -x-text-zoom property, which leads to a false value
// in mAllowZoom
if self.style().get_font().gecko.mAllowZoom {
self.device().zoom_text(size)
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 `<number>` value.
pub type Number = CSSFloat;
/// A wrapper of Number, but the value >= 0.
pub type NonNegativeNumber = NonNegative<CSSFloat>;
impl From<CSSFloat> for NonNegativeNumber {
#[inline]
fn from(number: CSSFloat) -> NonNegativeNumber {
NonNegative::<CSSFloat>(number)
}
}
impl From<NonNegativeNumber> for CSSFloat {
#[inline]
fn from(number: NonNegativeNumber) -> CSSFloat {
number.0
}
}
/// A wrapper of Number, but the value >= 1.
pub type GreaterThanOrEqualToOneNumber = GreaterThanOrEqualToOne<CSSFloat>;
impl From<CSSFloat> for GreaterThanOrEqualToOneNumber {
#[inline]
fn from(number: CSSFloat) -> GreaterThanOrEqualToOneNumber {
GreaterThanOrEqualToOne::<CSSFloat>(number)
}
}
impl From<GreaterThanOrEqualToOneNumber> 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<CSSInteger>;
impl From<CSSInteger> for PositiveInteger {
#[inline]
fn from(int: CSSInteger) -> PositiveInteger {
GreaterThanOrEqualToOne::<CSSInteger>(int)
}
}
/// PositiveInteger | auto
pub type PositiveIntegerOrAuto = Either<PositiveInteger, Auto>;
/// <length> | <percentage> | <number>
pub type LengthOrPercentageOrNumber = Either<Number, LengthOrPercentage>;
/// NonNegativeLengthOrPercentage | NonNegativeNumber
pub type NonNegativeLengthOrPercentageOrNumber = Either<NonNegativeNumber, NonNegativeLengthOrPercentage>;
#[derive(Clone, PartialEq, Eq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)]
@ -556,3 +608,40 @@ impl ClipRectOrAuto {
/// <color> | auto
pub type ColorOrAuto = Either<Color, Auto>;
/// A wrapper of Au, but the value >= 0.
pub type NonNegativeAu = NonNegative<Au>;
impl NonNegativeAu {
/// Return a zero value.
#[inline]
pub fn zero() -> Self {
NonNegative::<Au>(Au(0))
}
/// Return a NonNegativeAu from pixel.
#[inline]
pub fn from_px(px: i32) -> Self {
NonNegative::<Au>(Au::from_px(::std::cmp::max(px, 0)))
}
/// Get the inner value of |NonNegativeAu.0|.
#[inline]
pub fn value(self) -> i32 {
(self.0).0
}
/// Scale this NonNegativeAu.
#[inline]
pub fn scale_by(self, factor: f32) -> Self {
// scale this by zero if factor is negative.
NonNegative::<Au>(self.0.scale_by(factor.max(0.)))
}
}
impl From<Au> for NonNegativeAu {
#[inline]
fn from(au: Au) -> NonNegativeAu {
NonNegative::<Au>(au)
}
}

View File

@ -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<Au> for SVGLength {
}
}
/// An non-negative wrapper of SVGLength.
pub type SVGWidth = generic::SVGLength<NonNegativeLengthOrPercentageOrNumber>;
impl From<NonNegativeAu> for SVGWidth {
fn from(length: NonNegativeAu) -> Self {
generic::SVGLength::Length(Either::Second(length.into()))
}
}
/// [ <length> | <percentage> | <number> ]# | context-value
pub type SVGStrokeDashArray = generic::SVGStrokeDashArray<LengthOrPercentageOrNumber>;
pub type SVGStrokeDashArray = generic::SVGStrokeDashArray<NonNegativeLengthOrPercentageOrNumber>;
impl Default for SVGStrokeDashArray {
fn default() -> Self {

View File

@ -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<Length>;
pub type WordSpacing = Spacing<LengthOrPercentage>;
/// A computed value for the `line-height` property.
pub type LineHeight = GenericLineHeight<CSSFloat, Au>;
pub type LineHeight = GenericLineHeight<NonNegativeNumber, NonNegativeAu>;
impl Animatable for LineHeight {
#[inline]

View File

@ -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<Color, SizeLength, ShapeLength> {
pub struct BoxShadow<Color, SizeLength, BlurShapeLength, ShapeLength> {
/// The base shadow.
pub base: SimpleShadow<Color, SizeLength, ShapeLength>,
pub base: SimpleShadow<Color, SizeLength, BlurShapeLength>,
/// The spread radius.
pub spread: ShapeLength,
/// Whether this is an inset box shadow.
@ -77,10 +77,14 @@ pub struct SimpleShadow<Color, SizeLength, ShapeLength> {
pub blur: ShapeLength,
}
impl<Color, SizeLength, ShapeLength> ToCss for BoxShadow<Color, SizeLength, ShapeLength>
impl<Color, SizeLength, BlurShapeLength, ShapeLength> ToCss for BoxShadow<Color,
SizeLength,
BlurShapeLength,
ShapeLength>
where
Color: ToCss,
SizeLength: ToCss,
BlurShapeLength: ToCss,
ShapeLength: ToCss,
{
fn to_css<W>(&self, dest: &mut W) -> fmt::Result

View File

@ -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<T>(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<T>(pub T);

View File

@ -98,7 +98,7 @@ impl<ColorType: Parse> Parse for SVGPaint<ColorType> {
/// 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<LengthType> {
/// `<length> | <percentage> | <number>`
Length(LengthType),
@ -108,7 +108,7 @@ pub enum SVGLength<LengthType> {
/// 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<LengthType> {
/// `[ <length> | <percentage> | <number> ]#`
Values(Vec<LengthType>),

View File

@ -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<Number, LengthOrPercentage> {
/// `normal`
Normal,

View File

@ -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))
}
}

View File

@ -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<Option<Color>, Length, Option<Length>>;
pub type BoxShadow = GenericBoxShadow<Option<Color>, Length, Option<NonNegativeLength>, Option<Length>>;
/// A specified value for a single `filter`.
#[cfg(feature = "gecko")]
pub type Filter = GenericFilter<Angle, Factor, Length, SimpleShadow>;
pub type Filter = GenericFilter<Angle, Factor, NonNegativeLength, SimpleShadow>;
/// A specified value for a single `filter`.
#[cfg(not(feature = "gecko"))]
pub type Filter = GenericFilter<Angle, Factor, Length, Impossible>;
pub type Filter = GenericFilter<Angle, Factor, NonNegativeLength, Impossible>;
/// A value for the `<factor>` 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<Option<Color>, Length, Option<Length>>;
pub type SimpleShadow = GenericSimpleShadow<Option<Color>, Length, Option<NonNegativeLength>>;
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::<Length>),
})
}
}
@ -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),
}
}

View File

@ -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<T: Parse> Either<Length, T> {
}
}
/// A wrapper of Length, whose value must be >= 0.
pub type NonNegativeLength = NonNegative<Length>;
impl From<NoCalcLength> for NonNegativeLength {
#[inline]
fn from(len: NoCalcLength) -> Self {
NonNegative::<Length>(Length::NoCalc(len))
}
}
impl From<Length> for NonNegativeLength {
#[inline]
fn from(len: Length) -> Self {
NonNegative::<Length>(len)
}
}
impl<T: Parse> Parse for Either<NonNegativeLength, T> {
#[inline]
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
if let Ok(v) = input.try(|input| T::parse(context, input)) {
return Ok(Either::Second(v));
}
Length::parse_internal(context, input, AllowedLengthType::NonNegative, AllowQuirks::No)
.map(NonNegative::<Length>).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<NonNegativeLength, Normal>;
/// Either a NonNegativeLength or the `auto` keyword.
pub type NonNegativeLengthOrAuto = Either<NonNegativeLength, Auto>;
/// Either a NonNegativeLength or a NonNegativeNumber value.
pub type NonNegativeLengthOrNumber = Either<NonNegativeLength, NonNegativeNumber>;
/// 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<LengthOrPercentage>;
impl From<NoCalcLength> for NonNegativeLengthOrPercentage {
#[inline]
fn from(len: NoCalcLength) -> Self {
NonNegative::<LengthOrPercentage>(LengthOrPercentage::from(len))
}
}
impl Parse for NonNegativeLengthOrPercentage {
#[inline]
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
LengthOrPercentage::parse_non_negative(context, input).map(NonNegative::<LengthOrPercentage>)
}
}
impl NonNegativeLengthOrPercentage {
#[inline]
/// Returns a `zero` length.
pub fn zero() -> Self {
NonNegative::<LengthOrPercentage>(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<Self, ParseError<'i>> {
LengthOrPercentage::parse_non_negative_quirky(context, input, allow_quirks)
.map(NonNegative::<LengthOrPercentage>)
}
}
/// Either a `<length>` or the `none` keyword.
pub type LengthOrNone = Either<Length, None_>;

View File

@ -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<Number>;
impl Parse for NonNegativeNumber {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
parse_number_with_clamping_mode(context, input, AllowedNumericType::NonNegative)
.map(NonNegative::<Number>)
}
}
impl NonNegativeNumber {
/// Returns a new non-negative number with the value `val`.
pub fn new(val: CSSFloat) -> Self {
NonNegative::<Number>(Number::new(val.max(0.)))
}
}
/// A Number which is >= 1.0.
pub type GreaterThanOrEqualToOneNumber = GreaterThanOrEqualToOne<Number>;
impl Parse for GreaterThanOrEqualToOneNumber {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
parse_number_with_clamping_mode(context, input, AllowedNumericType::AtLeastOne)
.map(GreaterThanOrEqualToOne::<Number>)
}
}
/// <number> | <percentage>
///
/// Accepts only non-negative numbers.
@ -713,6 +742,19 @@ impl IntegerOrAuto {
}
}
/// A wrapper of Integer, with value >= 1.
pub type PositiveInteger = GreaterThanOrEqualToOne<Integer>;
impl Parse for PositiveInteger {
#[inline]
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
Integer::parse_positive(context, input).map(GreaterThanOrEqualToOne::<Integer>)
}
}
/// PositiveInteger | auto
pub type PositiveIntegerOrAuto = Either<PositiveInteger, Auto>;
#[allow(missing_docs)]
pub type UrlOrNone = Either<SpecifiedUrl, None_>;
@ -732,19 +774,8 @@ pub type GridTemplateComponent = GenericGridTemplateComponent<LengthOrPercentage
/// <length> | <percentage> | <number>
pub type LengthOrPercentageOrNumber = Either<Number, LengthOrPercentage>;
impl LengthOrPercentageOrNumber {
/// parse a <length-percentage> | <number> enforcing that the contents aren't negative
pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
// 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<NonNegativeNumber, NonNegativeLengthOrPercentage>;
#[derive(Clone, Debug, HasViewportPercentage, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]

View File

@ -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<Self, ParseError<'i>> {
input.try(|i| LengthOrPercentageOrNumber::parse_non_negative(context, i))
.map(Into::into)
.or_else(|_| parse_context_value(input, generic::SVGLength::ContextValue))
}
}
impl From<LengthOrPercentageOrNumber> for SVGLength {
fn from(length: LengthOrPercentageOrNumber) -> Self {
generic::SVGLength::Length(length)
}
}
/// A non-negative version of SVGLength.
pub type SVGWidth = generic::SVGLength<NonNegativeLengthOrPercentageOrNumber>;
impl Parse for SVGWidth {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
input.try(|i| NonNegativeLengthOrPercentageOrNumber::parse(context, i))
.map(Into::into)
.or_else(|_| parse_context_value(input, generic::SVGLength::ContextValue))
}
}
impl From<NonNegativeLengthOrPercentageOrNumber> for SVGWidth {
fn from(length: NonNegativeLengthOrPercentageOrNumber) -> Self {
generic::SVGLength::Length(length)
}
}
/// [ <length> | <percentage> | <number> ]# | context-value
pub type SVGStrokeDashArray = generic::SVGStrokeDashArray<LengthOrPercentageOrNumber>;
pub type SVGStrokeDashArray = generic::SVGStrokeDashArray<NonNegativeLengthOrPercentageOrNumber>;
impl Parse for SVGStrokeDashArray {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<Self, ParseError<'i>> {
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")) {

View File

@ -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<Number, Integer>;
@ -27,7 +28,7 @@ pub type LetterSpacing = Spacing<Length>;
pub type WordSpacing = Spacing<LengthOrPercentage>;
/// A specified value for the `line-height` property.
pub type LineHeight = GenericLineHeight<Number, LengthOrPercentage>;
pub type LineHeight = GenericLineHeight<NonNegativeNumber, NonNegativeLengthOrPercentage>;
impl Parse for InitialLetter {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
@ -58,11 +59,11 @@ impl Parse for WordSpacing {
impl Parse for LineHeight {
fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
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())
}
}
}

View File

@ -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,