mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-17 07:15:46 +00:00
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:
parent
0a70fd0b47
commit
102da9013f
@ -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 {
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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(),
|
||||
}));
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
|
@ -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!(),
|
||||
}
|
||||
}
|
||||
|
@ -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; }
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {},
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
}))));
|
||||
}
|
||||
|
@ -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),
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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>)
|
||||
}
|
||||
}
|
||||
|
@ -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")}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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),
|
||||
|
@ -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",
|
||||
)}
|
||||
|
||||
|
@ -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!(),
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
|
||||
|
@ -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",
|
||||
|
@ -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"]:
|
||||
|
@ -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)")}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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)}
|
||||
|
@ -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(());
|
||||
}
|
||||
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
@ -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>;
|
||||
|
@ -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)]
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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]
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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>),
|
||||
|
@ -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,
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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_>;
|
||||
|
||||
|
@ -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))]
|
||||
|
@ -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")) {
|
||||
|
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user