diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2019-12-16 23:51:18 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-12-16 23:51:18 -0500 |
commit | a8b8f4647622dc88e2d19c04de3948795dcc594d (patch) | |
tree | 50ccc190c83684029855eeaf1b0b422b90da062e | |
parent | b274d59875522ad303e9b54c17414dd57dee325b (diff) | |
parent | 7513bc293e0e515dd4e9e56b8ede32b68b8c8186 (diff) | |
download | servo-a8b8f4647622dc88e2d19c04de3948795dcc594d.tar.gz servo-a8b8f4647622dc88e2d19c04de3948795dcc594d.zip |
Auto merge of #25299 - emilio:gecko-sync, r=emilio,nox
style: Sync changes from mozilla-central.
See individual commits for details.
80 files changed, 770 insertions, 450 deletions
diff --git a/Cargo.lock b/Cargo.lock index f8bcf052113..ac076d7dca6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -887,7 +887,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b" dependencies = [ "crossbeam-utils", - "smallvec", + "smallvec 0.6.10", ] [[package]] @@ -947,7 +947,7 @@ dependencies = [ "proc-macro2 1.0.1", "quote 1.0.2", "serde", - "smallvec", + "smallvec 0.6.10", "syn 1.0.3", ] @@ -1103,6 +1103,17 @@ dependencies = [ ] [[package]] +name = "derive_more" +version = "0.99.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2159be042979966de68315bce7034bb000c775f22e3e834e1c52ff78f041cae8" +dependencies = [ + "proc-macro2 1.0.1", + "quote 1.0.2", + "syn 1.0.3", +] + +[[package]] name = "device" version = "0.0.1" source = "git+https://github.com/servo/devices#cb28c4725ffbfece99dab842d17d3e8c50774778" @@ -1387,7 +1398,7 @@ name = "fallible" version = "0.0.1" dependencies = [ "hashglobe", - "smallvec", + "smallvec 1.0.0", ] [[package]] @@ -1609,7 +1620,7 @@ dependencies = [ "servo_arc", "servo_atoms", "servo_url", - "smallvec", + "smallvec 0.6.10", "style", "time", "truetype", @@ -1646,7 +1657,7 @@ dependencies = [ "parking_lot", "range-alloc", "raw-window-handle", - "smallvec", + "smallvec 0.6.10", "spirv_cross", "winapi", "wio", @@ -1665,7 +1676,7 @@ dependencies = [ "log", "range-alloc", "raw-window-handle", - "smallvec", + "smallvec 0.6.10", "spirv_cross", "winapi", ] @@ -1702,7 +1713,7 @@ dependencies = [ "parking_lot", "range-alloc", "raw-window-handle", - "smallvec", + "smallvec 0.6.10", "spirv_cross", "storage-map", ] @@ -1722,7 +1733,7 @@ dependencies = [ "log", "objc", "raw-window-handle", - "smallvec", + "smallvec 0.6.10", "winapi", "x11", ] @@ -1735,7 +1746,7 @@ checksum = "7c88981665c780447bb08eb099e1ded330754a7246719bab927ee4a949c0ba7f" dependencies = [ "bitflags", "raw-window-handle", - "smallvec", + "smallvec 0.6.10", ] [[package]] @@ -2706,7 +2717,7 @@ dependencies = [ "servo_geometry", "servo_url", "size_of_test", - "smallvec", + "smallvec 0.6.10", "style", "style_traits", "unicode-bidi", @@ -2938,7 +2949,7 @@ dependencies = [ "rust-webvr", "servo-egl", "simpleservo", - "smallvec", + "smallvec 0.6.10", "webxr", "webxr-api", ] @@ -3137,7 +3148,7 @@ dependencies = [ "serde_bytes", "servo_arc", "smallbitvec", - "smallvec", + "smallvec 1.0.0", "string_cache", "thin-slice", "time", @@ -3812,7 +3823,7 @@ dependencies = [ "libc", "redox_syscall", "rustc_version", - "smallvec", + "smallvec 0.6.10", "winapi", ] @@ -4307,7 +4318,7 @@ dependencies = [ "gfx-hal", "log", "relevant", - "smallvec", + "smallvec 0.6.10", ] [[package]] @@ -4322,7 +4333,7 @@ dependencies = [ "log", "relevant", "slab", - "smallvec", + "smallvec 0.6.10", ] [[package]] @@ -4514,7 +4525,7 @@ dependencies = [ "servo_geometry", "servo_rand", "servo_url", - "smallvec", + "smallvec 0.6.10", "sparkle", "style", "style_traits", @@ -4633,7 +4644,7 @@ version = "0.21.0" dependencies = [ "bitflags", "cssparser", - "derive_more", + "derive_more 0.99.2", "fxhash", "log", "matches", @@ -4641,7 +4652,7 @@ dependencies = [ "phf_codegen", "precomputed-hash", "servo_arc", - "smallvec", + "smallvec 1.0.0", "thin-slice", "to_shmem", "to_shmem_derive", @@ -4836,7 +4847,7 @@ dependencies = [ "servo-media-player", "servo-media-traits", "servo_media_derive", - "smallvec", + "smallvec 0.6.10", ] [[package]] @@ -5224,6 +5235,12 @@ dependencies = [ ] [[package]] +name = "smallvec" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ecf3b85f68e8abaa7555aa5abdb1153079387e60b718283d732f03897fcfc86" + +[[package]] name = "smithay-client-toolkit" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -5351,7 +5368,7 @@ dependencies = [ "byteorder", "crossbeam-channel", "cssparser", - "derive_more", + "derive_more 0.99.2", "encoding_rs", "euclid", "fallible", @@ -5384,7 +5401,7 @@ dependencies = [ "servo_config", "servo_url", "smallbitvec", - "smallvec", + "smallvec 1.0.0", "string_cache", "style_derive", "style_traits", @@ -5689,7 +5706,7 @@ dependencies = [ "cssparser", "servo_arc", "smallbitvec", - "smallvec", + "smallvec 1.0.0", "string_cache", "thin-slice", ] @@ -6279,7 +6296,7 @@ dependencies = [ "malloc_size_of", "serde", "servo_config", - "smallvec", + "smallvec 0.6.10", "wgpu-core", ] @@ -6314,7 +6331,7 @@ dependencies = [ "serde", "serde_json", "sha2", - "smallvec", + "smallvec 0.6.10", "svg_fmt", "thread_profiler", "time", @@ -6334,7 +6351,7 @@ dependencies = [ "byteorder", "core-foundation", "core-graphics", - "derive_more", + "derive_more 0.13.0", "euclid", "malloc_size_of_derive", "peek-poke", @@ -6443,7 +6460,7 @@ dependencies = [ "rendy-descriptor", "rendy-memory", "serde", - "smallvec", + "smallvec 0.6.10", "vec_map", ] diff --git a/components/fallible/Cargo.toml b/components/fallible/Cargo.toml index e8f5314693b..49064da33ea 100644 --- a/components/fallible/Cargo.toml +++ b/components/fallible/Cargo.toml @@ -10,7 +10,7 @@ name = "fallible" path = "lib.rs" [dependencies] -smallvec = "0.6" +smallvec = "1.0" hashglobe = { path = "../hashglobe" } # This crate effectively does nothing except if the `known_system_malloc` diff --git a/components/gfx/font.rs b/components/gfx/font.rs index 3dd5ac9f244..439784ba680 100644 --- a/components/gfx/font.rs +++ b/components/gfx/font.rs @@ -131,7 +131,7 @@ impl<'a> From<&'a FontStyleStruct> for FontDescriptor { FontDescriptor { template_descriptor: FontTemplateDescriptor::from(style), variant: style.font_variant_caps, - pt_size: style.font_size.size(), + pt_size: Au::from_f32_px(style.font_size.size().px()), } } } diff --git a/components/gfx/font_context.rs b/components/gfx/font_context.rs index 06755205935..113b384f84d 100644 --- a/components/gfx/font_context.rs +++ b/components/gfx/font_context.rs @@ -95,7 +95,7 @@ impl<S: FontSource> FontContext<S> { self.expire_font_caches_if_necessary(); let cache_key = FontGroupCacheKey { - size: style.font_size.size(), + size: Au::from_f32_px(style.font_size.size().px()), style, }; diff --git a/components/layout/block.rs b/components/layout/block.rs index 80c0fae2243..4b0999489ee 100644 --- a/components/layout/block.rs +++ b/components/layout/block.rs @@ -2029,7 +2029,7 @@ impl BlockFlow { // If `max-width` is set, then don't perform this speculation. We guess that the // page set `max-width` in order to avoid hitting floats. The search box on Google // SERPs falls into this category. - if self.fragment.style.max_inline_size() != MaxSize::None { + if !matches!(self.fragment.style.max_inline_size(), MaxSize::None) { return; } @@ -2548,8 +2548,16 @@ impl Flow for BlockFlow { .base .flags .contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) && - self.fragment.style().logical_position().inline_start == LengthPercentageOrAuto::Auto && - self.fragment.style().logical_position().inline_end == LengthPercentageOrAuto::Auto + self.fragment + .style() + .logical_position() + .inline_start + .is_auto() && + self.fragment + .style() + .logical_position() + .inline_end + .is_auto() { self.base.position.start.i = inline_position } @@ -2560,8 +2568,12 @@ impl Flow for BlockFlow { .base .flags .contains(FlowFlags::IS_ABSOLUTELY_POSITIONED) && - self.fragment.style().logical_position().block_start == LengthPercentageOrAuto::Auto && - self.fragment.style().logical_position().block_end == LengthPercentageOrAuto::Auto + self.fragment + .style() + .logical_position() + .block_start + .is_auto() && + self.fragment.style().logical_position().block_end.is_auto() { self.base.position.start.b = block_position } @@ -2848,16 +2860,15 @@ pub trait ISizeAndMarginsComputer { parent_flow_inline_size: Au, shared_context: &SharedStyleContext, ) -> MaybeAuto { + let inline_size = + self.containing_block_inline_size(block, parent_flow_inline_size, shared_context); + MaybeAuto::from_option( block .fragment() .style() .content_inline_size() - .to_used_value(self.containing_block_inline_size( - block, - parent_flow_inline_size, - shared_context, - )), + .to_used_value(inline_size), ) } diff --git a/components/layout/display_list/background.rs b/components/layout/display_list/background.rs index 9d05cef9054..c08dcfe8598 100644 --- a/components/layout/display_list/background.rs +++ b/components/layout/display_list/background.rs @@ -47,7 +47,7 @@ pub fn get_cyclic<T>(arr: &[T], index: usize) -> &T { /// For a given area and an image compute how big the /// image should be displayed on the background. fn compute_background_image_size( - bg_size: BackgroundSize, + bg_size: &BackgroundSize, bounds_size: Size2D<Au>, intrinsic_size: Option<Size2D<Au>>, ) -> Size2D<Au> { @@ -156,7 +156,7 @@ pub fn placement( let bg_position_x = get_cyclic(&bg.background_position_x.0, index); let bg_position_y = get_cyclic(&bg.background_position_y.0, index); let bg_repeat = get_cyclic(&bg.background_repeat.0, index); - let bg_size = *get_cyclic(&bg.background_size.0, index); + let bg_size = get_cyclic(&bg.background_size.0, index); let (clip_rect, clip_radii) = clip( bg_clip, diff --git a/components/layout/display_list/border.rs b/components/layout/display_list/border.rs index 4970b2a34de..14ca2abe84f 100644 --- a/components/layout/display_list/border.rs +++ b/components/layout/display_list/border.rs @@ -25,7 +25,7 @@ use webrender_api::{BorderRadius, BorderSide, BorderStyle, ColorF, NormalBorder} /// /// [1]: https://drafts.csswg.org/css-backgrounds-3/#border-radius fn corner_radius( - radius: BorderCornerRadius, + radius: &BorderCornerRadius, containing_size: UntypedSize2D<Au>, ) -> UntypedSize2D<Au> { let w = radius.0.width().to_used_value(containing_size.width); @@ -91,13 +91,13 @@ pub fn radii(abs_bounds: Rect<Au>, border_style: &Border) -> BorderRadius { overlapping_radii( abs_bounds.size.to_layout(), BorderRadius { - top_left: corner_radius(border_style.border_top_left_radius, abs_bounds.size) + top_left: corner_radius(&border_style.border_top_left_radius, abs_bounds.size) .to_layout(), - top_right: corner_radius(border_style.border_top_right_radius, abs_bounds.size) + top_right: corner_radius(&border_style.border_top_right_radius, abs_bounds.size) .to_layout(), - bottom_right: corner_radius(border_style.border_bottom_right_radius, abs_bounds.size) + bottom_right: corner_radius(&border_style.border_bottom_right_radius, abs_bounds.size) .to_layout(), - bottom_left: corner_radius(border_style.border_bottom_left_radius, abs_bounds.size) + bottom_left: corner_radius(&border_style.border_bottom_left_radius, abs_bounds.size) .to_layout(), }, ) @@ -161,7 +161,7 @@ pub fn image_outset( } fn side_image_width( - border_image_width: BorderImageSideWidth, + border_image_width: &BorderImageSideWidth, border_width: f32, total_length: Au, ) -> f32 { @@ -178,10 +178,10 @@ pub fn image_width( border_area: UntypedSize2D<Au>, ) -> LayoutSideOffsets { LayoutSideOffsets::new( - side_image_width(width.0, border.top, border_area.height), - side_image_width(width.1, border.right, border_area.width), - side_image_width(width.2, border.bottom, border_area.height), - side_image_width(width.3, border.left, border_area.width), + side_image_width(&width.0, border.top, border_area.height), + side_image_width(&width.1, border.right, border_area.width), + side_image_width(&width.2, border.bottom, border_area.height), + side_image_width(&width.3, border.left, border_area.width), ) } diff --git a/components/layout/display_list/builder.rs b/components/layout/display_list/builder.rs index 258c4f5490c..542ab95172a 100644 --- a/components/layout/display_list/builder.rs +++ b/components/layout/display_list/builder.rs @@ -995,7 +995,7 @@ impl Fragment { }; DisplayItem::Gradient(CommonDisplayItem::with_data(base, item, stops)) }, - GradientKind::Radial(shape, center) => { + GradientKind::Radial(ref shape, ref center) => { let (gradient, stops) = gradient::radial( style, placement.tile_size, @@ -1238,7 +1238,7 @@ impl Fragment { stops = linear_stops; NinePatchBorderSource::Gradient(wr_gradient) }, - GradientKind::Radial(shape, center) => { + GradientKind::Radial(ref shape, ref center) => { let (wr_gradient, radial_stops) = gradient::radial( style, border_image_area, diff --git a/components/layout/display_list/gradient.rs b/components/layout/display_list/gradient.rs index 3d7730e4fe6..e683bbb963c 100644 --- a/components/layout/display_list/gradient.rs +++ b/components/layout/display_list/gradient.rs @@ -91,9 +91,12 @@ fn convert_gradient_stops( color, position: None, }), - GradientItem::ComplexColorStop { color, position } => Some(ColorStop { + GradientItem::ComplexColorStop { color, - position: Some(position), + ref position, + } => Some(ColorStop { + color, + position: Some(position.clone()), }), _ => None, }) @@ -122,15 +125,24 @@ fn convert_gradient_stops( // Step 2: Move any stops placed before earlier stops to the // same position as the preceding stop. - let mut last_stop_position = stop_items.first().unwrap().position.unwrap(); + // + // FIXME(emilio): Once we know the offsets, it seems like converting the + // positions to absolute at once then process that would be cheaper. + let mut last_stop_position = stop_items + .first() + .unwrap() + .position + .as_ref() + .unwrap() + .clone(); for stop in stop_items.iter_mut().skip(1) { - if let Some(pos) = stop.position { - if position_to_offset(last_stop_position, total_length) > + if let Some(ref pos) = stop.position { + if position_to_offset(&last_stop_position, total_length) > position_to_offset(pos, total_length) { stop.position = Some(last_stop_position); } - last_stop_position = stop.position.unwrap(); + last_stop_position = stop.position.as_ref().unwrap().clone(); } } @@ -144,8 +156,10 @@ fn convert_gradient_stops( // Initialize a new stop run. // `unwrap()` here should never fail because this is the beginning of // a stop run, which is always bounded by a length or percentage. - let start_offset = - position_to_offset(stop_items[i - 1].position.unwrap(), total_length); + let start_offset = position_to_offset( + stop_items[i - 1].position.as_ref().unwrap(), + total_length, + ); // `unwrap()` here should never fail because this is the end of // a stop run, which is always bounded by a length or percentage. let (end_index, end_stop) = stop_items[(i + 1)..] @@ -153,7 +167,8 @@ fn convert_gradient_stops( .enumerate() .find(|&(_, ref stop)| stop.position.is_some()) .unwrap(); - let end_offset = position_to_offset(end_stop.position.unwrap(), total_length); + let end_offset = + position_to_offset(end_stop.position.as_ref().unwrap(), total_length); stop_run = Some(StopRun { start_offset, end_offset, @@ -168,7 +183,7 @@ fn convert_gradient_stops( stop_run_length * (i - stop_run.start_index) as f32 / ((2 + stop_run.stop_count) as f32) }, - Some(position) => { + Some(ref position) => { stop_run = None; position_to_offset(position, total_length) }, @@ -212,7 +227,7 @@ where Size2D::new(cmp(left_side, right_side), cmp(top_side, bottom_side)) } -fn position_to_offset(position: LengthPercentage, total_length: Au) -> f32 { +fn position_to_offset(position: &LengthPercentage, total_length: Au) -> f32 { if total_length == Au(0) { return 0.0; } @@ -289,8 +304,8 @@ pub fn radial( style: &ComputedValues, size: Size2D<Au>, stops: &[GradientItem], - shape: EndingShape, - center: Position, + shape: &EndingShape, + center: &Position, repeating: bool, ) -> (RadialGradient, Vec<GradientStop>) { let center = Point2D::new( @@ -299,15 +314,15 @@ pub fn radial( ); let radius = match shape { EndingShape::Circle(Circle::Radius(length)) => { - let length = Au::from(length); + let length = Au::from(*length); Size2D::new(length, length) }, - EndingShape::Circle(Circle::Extent(extent)) => circle_size_keyword(extent, &size, ¢er), + EndingShape::Circle(Circle::Extent(extent)) => circle_size_keyword(*extent, &size, ¢er), EndingShape::Ellipse(Ellipse::Radii(x, y)) => { Size2D::new(x.to_used_value(size.width), y.to_used_value(size.height)) }, EndingShape::Ellipse(Ellipse::Extent(extent)) => { - ellipse_size_keyword(extent, &size, ¢er) + ellipse_size_keyword(*extent, &size, ¢er) }, }; diff --git a/components/layout/flex.rs b/components/layout/flex.rs index 8d2f7b98fe1..204e87f23fc 100644 --- a/components/layout/flex.rs +++ b/components/layout/flex.rs @@ -43,7 +43,7 @@ enum AxisSize { impl AxisSize { /// Generate a new available cross or main axis size from the specified size of the container, /// containing block size, min constraint, and max constraint - pub fn new(size: Size, content_size: Option<Au>, min: Size, max: MaxSize) -> AxisSize { + pub fn new(size: &Size, content_size: Option<Au>, min: &Size, max: &MaxSize) -> AxisSize { match size { Size::Auto => AxisSize::MinMax(SizeConstraint::new(content_size, min, max, None)), Size::LengthPercentage(ref lp) => match lp.maybe_to_used_value(content_size) { @@ -58,10 +58,10 @@ impl AxisSize { /// and the container size, then return the used value of flex basis. it can be used to help /// determining the flex base size and to indicate whether the main size of the item /// is definite after flex size resolving. -fn from_flex_basis(flex_basis: FlexBasis, main_length: Size, containing_length: Au) -> MaybeAuto { +fn from_flex_basis(flex_basis: &FlexBasis, main_length: &Size, containing_length: Au) -> MaybeAuto { let width = match flex_basis { FlexBasis::Content => return MaybeAuto::Auto, - FlexBasis::Size(width) => width, + FlexBasis::Size(ref width) => width, }; let width = match width { @@ -135,7 +135,7 @@ impl FlexItem { // https://drafts.csswg.org/css-flexbox-1/#min-size-auto Direction::Inline => { let basis = from_flex_basis( - block.fragment.style.get_position().flex_basis, + &block.fragment.style.get_position().flex_basis, block.fragment.style.content_inline_size(), containing_length, ); @@ -170,7 +170,7 @@ impl FlexItem { }, Direction::Block => { let basis = from_flex_basis( - block.fragment.style.get_position().flex_basis, + &block.fragment.style.get_position().flex_basis, block.fragment.style.content_block_size(), containing_length, ); @@ -452,7 +452,7 @@ impl FlexFlow { fn inline_mode_bubble_inline_sizes(&mut self) { // FIXME(emilio): This doesn't handle at all writing-modes. let fixed_width = - !model::style_length(self.block_flow.fragment.style().get_position().width, None) + !model::style_length(&self.block_flow.fragment.style().get_position().width, None) .is_auto(); let mut computation = self.block_flow.fragment.compute_intrinsic_inline_sizes(); @@ -478,7 +478,7 @@ impl FlexFlow { // stripped out. fn block_mode_bubble_inline_sizes(&mut self) { let fixed_width = - !model::style_length(self.block_flow.fragment.style().get_position().width, None) + !model::style_length(&self.block_flow.fragment.style().get_position().width, None) .is_auto(); let mut computation = self.block_flow.fragment.compute_intrinsic_inline_sizes(); @@ -960,9 +960,9 @@ impl Flow for FlexFlow { let style = &self.block_flow.fragment.style; let (specified_block_size, specified_inline_size) = if style.writing_mode.is_vertical() { - (style.get_position().width, style.get_position().height) + (&style.get_position().width, &style.get_position().height) } else { - (style.get_position().height, style.get_position().width) + (&style.get_position().height, &style.get_position().width) }; let available_inline_size = AxisSize::new( diff --git a/components/layout/flow.rs b/components/layout/flow.rs index 2d6e449766e..c2d01b7f9f9 100644 --- a/components/layout/flow.rs +++ b/components/layout/flow.rs @@ -64,7 +64,6 @@ use style::logical_geometry::{LogicalRect, LogicalSize, WritingMode}; use style::properties::ComputedValues; use style::selector_parser::RestyleDamage; use style::servo::restyle_damage::ServoRestyleDamage; -use style::values::computed::LengthPercentageOrAuto; use webrender_api::units::LayoutTransform; /// This marker trait indicates that a type is a struct with `#[repr(C)]` whose first field @@ -1020,13 +1019,13 @@ impl BaseFlow { flags.insert(FlowFlags::IS_ABSOLUTELY_POSITIONED); let logical_position = style.logical_position(); - if logical_position.inline_start == LengthPercentageOrAuto::Auto && - logical_position.inline_end == LengthPercentageOrAuto::Auto + if logical_position.inline_start.is_auto() && + logical_position.inline_end.is_auto() { flags.insert(FlowFlags::INLINE_POSITION_IS_STATIC); } - if logical_position.block_start == LengthPercentageOrAuto::Auto && - logical_position.block_end == LengthPercentageOrAuto::Auto + if logical_position.block_start.is_auto() && + logical_position.block_end.is_auto() { flags.insert(FlowFlags::BLOCK_POSITION_IS_STATIC); } @@ -1113,13 +1112,12 @@ impl BaseFlow { let logical_position = style.logical_position(); self.flags.set( FlowFlags::INLINE_POSITION_IS_STATIC, - logical_position.inline_start == LengthPercentageOrAuto::Auto && - logical_position.inline_end == LengthPercentageOrAuto::Auto, + logical_position.inline_start.is_auto() && + logical_position.inline_end.is_auto(), ); self.flags.set( FlowFlags::BLOCK_POSITION_IS_STATIC, - logical_position.block_start == LengthPercentageOrAuto::Auto && - logical_position.block_end == LengthPercentageOrAuto::Auto, + logical_position.block_start.is_auto() && logical_position.block_end.is_auto(), ); } } diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs index f663dad744d..c0240f72071 100644 --- a/components/layout/fragment.rs +++ b/components/layout/fragment.rs @@ -61,10 +61,9 @@ use style::selector_parser::RestyleDamage; use style::servo::restyle_damage::ServoRestyleDamage; use style::str::char_is_whitespace; use style::values::computed::counters::ContentItem; -use style::values::computed::{LengthPercentage, LengthPercentageOrAuto, Size, VerticalAlign}; +use style::values::computed::{Size, VerticalAlign}; use style::values::generics::box_::{Perspective, VerticalAlignKeyword}; use style::values::generics::transform; -use style::Zero; use webrender_api; use webrender_api::units::LayoutTransform; @@ -1329,13 +1328,17 @@ impl Fragment { return; }, _ => { - let margin = self.style().logical_margin(); - self.margin.inline_start = - MaybeAuto::from_style(margin.inline_start, containing_block_inline_size) - .specified_or_zero(); - self.margin.inline_end = - MaybeAuto::from_style(margin.inline_end, containing_block_inline_size) - .specified_or_zero(); + let (inline_start, inline_end) = { + let margin = self.style().logical_margin(); + ( + MaybeAuto::from_style(margin.inline_start, containing_block_inline_size) + .specified_or_zero(), + MaybeAuto::from_style(margin.inline_end, containing_block_inline_size) + .specified_or_zero(), + ) + }; + self.margin.inline_start = inline_start; + self.margin.inline_end = inline_end; }, } @@ -1384,13 +1387,17 @@ impl Fragment { _ => { // NB: Percentages are relative to containing block inline-size (not block-size) // per CSS 2.1. - let margin = self.style().logical_margin(); - self.margin.block_start = - MaybeAuto::from_style(margin.block_start, containing_block_inline_size) - .specified_or_zero(); - self.margin.block_end = - MaybeAuto::from_style(margin.block_end, containing_block_inline_size) - .specified_or_zero(); + let (block_start, block_end) = { + let margin = self.style().logical_margin(); + ( + MaybeAuto::from_style(margin.block_start, containing_block_inline_size) + .specified_or_zero(), + MaybeAuto::from_style(margin.block_end, containing_block_inline_size) + .specified_or_zero(), + ) + }; + self.margin.block_start = block_start; + self.margin.block_end = block_end; }, } } @@ -1458,14 +1465,14 @@ impl Fragment { pub fn relative_position(&self, containing_block_size: &LogicalSize<Au>) -> LogicalSize<Au> { fn from_style(style: &ComputedValues, container_size: &LogicalSize<Au>) -> LogicalSize<Au> { let offsets = style.logical_position(); - let offset_i = if offsets.inline_start != LengthPercentageOrAuto::Auto { + let offset_i = if !offsets.inline_start.is_auto() { MaybeAuto::from_style(offsets.inline_start, container_size.inline) .specified_or_zero() } else { -MaybeAuto::from_style(offsets.inline_end, container_size.inline) .specified_or_zero() }; - let offset_b = if offsets.block_start != LengthPercentageOrAuto::Auto { + let offset_b = if !offsets.block_start.is_auto() { MaybeAuto::from_style(offsets.block_start, container_size.block).specified_or_zero() } else { -MaybeAuto::from_style(offsets.block_end, container_size.block).specified_or_zero() @@ -2520,13 +2527,19 @@ impl Fragment { { continue; } - if inline_context_node.style.logical_margin().inline_end != - LengthPercentageOrAuto::zero() + if !inline_context_node + .style + .logical_margin() + .inline_end + .is_definitely_zero() { return false; } - if inline_context_node.style.logical_padding().inline_end != - LengthPercentage::zero() + if !inline_context_node + .style + .logical_padding() + .inline_end + .is_definitely_zero() { return false; } @@ -2546,13 +2559,19 @@ impl Fragment { { continue; } - if inline_context_node.style.logical_margin().inline_start != - LengthPercentageOrAuto::zero() + if !inline_context_node + .style + .logical_margin() + .inline_start + .is_definitely_zero() { return false; } - if inline_context_node.style.logical_padding().inline_start != - LengthPercentage::zero() + if !inline_context_node + .style + .logical_padding() + .inline_start + .is_definitely_zero() { return false; } @@ -3193,7 +3212,7 @@ impl Fragment { ) -> Option<LayoutTransform> { match self.style().get_box().perspective { Perspective::Length(length) => { - let perspective_origin = self.style().get_box().perspective_origin; + let perspective_origin = &self.style().get_box().perspective_origin; let perspective_origin = Point2D::new( perspective_origin .horizontal diff --git a/components/layout/inline.rs b/components/layout/inline.rs index 5ba82c1c95b..dfdb20e309b 100644 --- a/components/layout/inline.rs +++ b/components/layout/inline.rs @@ -1275,7 +1275,7 @@ impl InlineFlow { &mut line_metrics, &inline_metrics, style.get_box().display, - VerticalAlign::baseline(), + &VerticalAlign::baseline(), &mut largest_block_size_for_top_fragments, &mut largest_block_size_for_bottom_fragments, ); @@ -1296,7 +1296,7 @@ impl InlineFlow { &mut line_metrics, &inline_metrics, node.style.get_box().display, - node.style.get_box().vertical_align, + &node.style.get_box().vertical_align, &mut largest_block_size_for_top_fragments, &mut largest_block_size_for_bottom_fragments, ); @@ -1318,7 +1318,7 @@ impl InlineFlow { line_metrics: &mut LineMetrics, inline_metrics: &InlineMetrics, display_value: Display, - vertical_align_value: VerticalAlign, + vertical_align_value: &VerticalAlign, largest_block_size_for_top_fragments: &mut Au, largest_block_size_for_bottom_fragments: &mut Au, ) { diff --git a/components/layout/lib.rs b/components/layout/lib.rs index fdf3971fc3f..582a3e284d5 100644 --- a/components/layout/lib.rs +++ b/components/layout/lib.rs @@ -3,6 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ #![deny(unsafe_code)] +#![feature(matches_macro)] #[macro_use] extern crate bitflags; diff --git a/components/layout/model.rs b/components/layout/model.rs index e6be75e45a4..08f916142e9 100644 --- a/components/layout/model.rs +++ b/components/layout/model.rs @@ -437,7 +437,7 @@ pub enum MaybeAuto { impl MaybeAuto { #[inline] - pub fn from_style(length: LengthPercentageOrAuto, containing_length: Au) -> MaybeAuto { + pub fn from_style(length: &LengthPercentageOrAuto, containing_length: Au) -> MaybeAuto { match length { LengthPercentageOrAuto::Auto => MaybeAuto::Auto, LengthPercentageOrAuto::LengthPercentage(ref lp) => { @@ -498,7 +498,7 @@ impl MaybeAuto { /// Receive an optional container size and return used value for width or height. /// /// `style_length`: content size as given in the CSS. -pub fn style_length(style_length: Size, container_size: Option<Au>) -> MaybeAuto { +pub fn style_length(style_length: &Size, container_size: Option<Au>) -> MaybeAuto { match style_length { Size::Auto => MaybeAuto::Auto, Size::LengthPercentage(ref lp) => { @@ -546,10 +546,10 @@ pub fn specified_margin_from_style( LogicalMargin::from_physical( writing_mode, SideOffsets2D::new( - MaybeAuto::from_style(margin_style.margin_top, Au(0)).specified_or_zero(), - MaybeAuto::from_style(margin_style.margin_right, Au(0)).specified_or_zero(), - MaybeAuto::from_style(margin_style.margin_bottom, Au(0)).specified_or_zero(), - MaybeAuto::from_style(margin_style.margin_left, Au(0)).specified_or_zero(), + MaybeAuto::from_style(&margin_style.margin_top, Au(0)).specified_or_zero(), + MaybeAuto::from_style(&margin_style.margin_right, Au(0)).specified_or_zero(), + MaybeAuto::from_style(&margin_style.margin_bottom, Au(0)).specified_or_zero(), + MaybeAuto::from_style(&margin_style.margin_left, Au(0)).specified_or_zero(), ), ) } @@ -568,8 +568,8 @@ impl SizeConstraint { /// Create a `SizeConstraint` for an axis. pub fn new( container_size: Option<Au>, - min_size: Size, - max_size: MaxSize, + min_size: &Size, + max_size: &MaxSize, border: Option<Au>, ) -> SizeConstraint { let mut min_size = match min_size { diff --git a/components/layout/multicol.rs b/components/layout/multicol.rs index 8890c08e189..4e1bfdf8d58 100644 --- a/components/layout/multicol.rs +++ b/components/layout/multicol.rs @@ -102,14 +102,14 @@ impl Flow for MulticolFlow { let column_width; { let style = &self.block_flow.fragment.style; - let column_gap = match style.get_position().column_gap { - NonNegativeLengthPercentageOrNormal::LengthPercentage(len) => { - len.0.to_pixel_length(content_inline_size).into() + let column_gap = Au::from(match style.get_position().column_gap { + NonNegativeLengthPercentageOrNormal::LengthPercentage(ref len) => { + len.0.to_pixel_length(content_inline_size) }, NonNegativeLengthPercentageOrNormal::Normal => { self.block_flow.fragment.style.get_font().font_size.size() }, - }; + }); let column_style = style.get_column(); let mut column_count; diff --git a/components/layout/table_colgroup.rs b/components/layout/table_colgroup.rs index b318dd95efd..ce097083f62 100644 --- a/components/layout/table_colgroup.rs +++ b/components/layout/table_colgroup.rs @@ -76,7 +76,7 @@ impl Flow for TableColGroupFlow { // Retrieve the specified value from the appropriate CSS property. let inline_size = fragment.style().content_inline_size(); for _ in 0..fragment.column_span() { - self.inline_sizes.push(inline_size) + self.inline_sizes.push(inline_size.clone()) } } } diff --git a/components/layout/table_row.rs b/components/layout/table_row.rs index ffaf720467b..58fb40bde3a 100644 --- a/components/layout/table_row.rs +++ b/components/layout/table_row.rs @@ -403,11 +403,6 @@ impl Flow for TableRowFlow { let child_row_span; { let child_table_cell = kid.as_mut_table_cell(); - child_specified_inline_size = child_table_cell - .block_flow - .fragment - .style - .content_inline_size(); child_column_span = child_table_cell.column_span; child_row_span = child_table_cell.row_span; @@ -422,6 +417,13 @@ impl Flow for TableRowFlow { &mut self.preliminary_collapsed_borders, ) } + + child_specified_inline_size = child_table_cell + .block_flow + .fragment + .style + .content_inline_size() + .clone(); } // Collect minimum and preferred inline-sizes of the cell for automatic table layout diff --git a/components/layout/text.rs b/components/layout/text.rs index 199bd7e07f2..ef9515b0726 100644 --- a/components/layout/text.rs +++ b/components/layout/text.rs @@ -519,7 +519,7 @@ pub fn line_height_from_style(style: &ComputedValues, metrics: &FontMetrics) -> let font_size = style.get_font().font_size.size(); match style.get_inherited_text().line_height { LineHeight::Normal => Au::from(metrics.line_gap), - LineHeight::Number(l) => font_size.scale_by(l.0), + LineHeight::Number(l) => Au::from(font_size * l.0), LineHeight::Length(l) => Au::from(l), } } diff --git a/components/layout_2020/geom.rs b/components/layout_2020/geom.rs index 562fad5c4f6..86e6faf45a7 100644 --- a/components/layout_2020/geom.rs +++ b/components/layout_2020/geom.rs @@ -175,13 +175,18 @@ impl flow_relative::Vec2<MaxSize<LengthPercentage>> { containing_block: &ContainingBlock, ) -> flow_relative::Vec2<Option<Length>> { flow_relative::Vec2 { - inline: self - .inline - .to_option() - .map(|lp| lp.percentage_relative_to(containing_block.inline_size)), - block: self.block.to_option().and_then(|olp| { - olp.maybe_percentage_relative_to(containing_block.block_size.non_auto()) - }), + inline: match self.inline { + MaxSize::None => None, + MaxSize::LengthPercentage(ref lp) => { + Some(lp.percentage_relative_to(containing_block.inline_size)) + }, + }, + block: match self.block { + MaxSize::None => None, + MaxSize::LengthPercentage(ref lp) => { + lp.maybe_percentage_relative_to(containing_block.block_size.non_auto()) + }, + }, } } } diff --git a/components/layout_2020/positioned.rs b/components/layout_2020/positioned.rs index c9ad2dd97c4..b10b489bc1d 100644 --- a/components/layout_2020/positioned.rs +++ b/components/layout_2020/positioned.rs @@ -40,7 +40,7 @@ pub(crate) struct HoistedAbsolutelyPositionedBox<'box_tree> { box_offsets: Vec2<AbsoluteBoxOffsets>, } -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Debug)] pub(crate) enum AbsoluteBoxOffsets { StaticStart { start: Length, @@ -113,13 +113,13 @@ impl AbsolutelyPositionedBox { box_offsets: Vec2 { inline: absolute_box_offsets( initial_start_corner.inline, - box_offsets.inline_start, - box_offsets.inline_end, + box_offsets.inline_start.clone(), + box_offsets.inline_end.clone(), ), block: absolute_box_offsets( initial_start_corner.block, - box_offsets.block_start, - box_offsets.block_end, + box_offsets.block_start.clone(), + box_offsets.block_end.clone(), ), }, } @@ -372,20 +372,20 @@ impl<'box_tree> HoistedAbsolutelyPositionedBox<'box_tree> { let inline_axis = solve_axis( cbis, pb.inline_sum(), - computed_margin.inline_start, - computed_margin.inline_end, + computed_margin.inline_start.clone(), + computed_margin.inline_end.clone(), /* avoid_negative_margin_start */ true, - self.box_offsets.inline, + self.box_offsets.inline.clone(), size.inline, ); let block_axis = solve_axis( cbis, pb.block_sum(), - computed_margin.block_start, - computed_margin.block_end, + computed_margin.block_start.clone(), + computed_margin.block_end.clone(), /* avoid_negative_margin_start */ false, - self.box_offsets.block, + self.box_offsets.block.clone(), size.block, ); diff --git a/components/layout_2020/sizing.rs b/components/layout_2020/sizing.rs index e3c74d3733f..dc7513a7859 100644 --- a/components/layout_2020/sizing.rs +++ b/components/layout_2020/sizing.rs @@ -7,6 +7,7 @@ use crate::style_ext::ComputedValuesExt; use style::properties::ComputedValues; use style::values::computed::{Length, LengthPercentage, Percentage}; +use style::values::generics::length::MaxSize; use style::Zero; /// Which min/max-content values should be computed during box construction @@ -114,11 +115,10 @@ impl BoxContentSizes { .inline .percentage_relative_to(Length::zero()) .auto_is(Length::zero); - let max_inline_size = style - .max_box_size() - .inline - .to_option() - .and_then(|lp| lp.as_length()); + let max_inline_size = match style.max_box_size().inline { + MaxSize::None => None, + MaxSize::LengthPercentage(ref lp) => lp.as_length(), + }; let clamp = |l: Length| l.clamp_between_extremums(min_inline_size, max_inline_size); // Percentages for 'width' are treated as 'auto' diff --git a/components/layout_2020/style_ext.rs b/components/layout_2020/style_ext.rs index 67d8bc78d7e..2d5af4da38e 100644 --- a/components/layout_2020/style_ext.rs +++ b/components/layout_2020/style_ext.rs @@ -55,9 +55,9 @@ impl ComputedValuesExt for ComputedValues { fn inline_size_is_length(&self) -> bool { let position = self.get_position(); let size = if self.writing_mode.is_horizontal() { - position.width + &position.width } else { - position.height + &position.height }; matches!(size, Size::LengthPercentage(lp) if lp.0.as_length().is_some()) } @@ -65,21 +65,21 @@ impl ComputedValuesExt for ComputedValues { fn inline_box_offsets_are_both_non_auto(&self) -> bool { let position = self.get_position(); let (a, b) = if self.writing_mode.is_horizontal() { - (position.left, position.right) + (&position.left, &position.right) } else { - (position.top, position.bottom) + (&position.top, &position.bottom) }; - a != LengthPercentageOrAuto::Auto && b != LengthPercentageOrAuto::Auto + !a.is_auto() && !b.is_auto() } #[inline] fn box_offsets(&self) -> flow_relative::Sides<LengthPercentageOrAuto> { let position = self.get_position(); physical::Sides { - top: position.top, - left: position.left, - bottom: position.bottom, - right: position.right, + top: position.top.clone(), + left: position.left.clone(), + bottom: position.bottom.clone(), + right: position.right.clone(), } .to_flow_relative(self.writing_mode) } @@ -88,8 +88,8 @@ impl ComputedValuesExt for ComputedValues { fn box_size(&self) -> flow_relative::Vec2<LengthPercentageOrAuto> { let position = self.get_position(); physical::Vec2 { - x: size_to_length(position.width), - y: size_to_length(position.height), + x: size_to_length(position.width.clone()), + y: size_to_length(position.height.clone()), } .size_to_flow_relative(self.writing_mode) } @@ -98,8 +98,8 @@ impl ComputedValuesExt for ComputedValues { fn min_box_size(&self) -> flow_relative::Vec2<LengthPercentageOrAuto> { let position = self.get_position(); physical::Vec2 { - x: size_to_length(position.min_width), - y: size_to_length(position.min_height), + x: size_to_length(position.min_width.clone()), + y: size_to_length(position.min_height.clone()), } .size_to_flow_relative(self.writing_mode) } @@ -112,8 +112,8 @@ impl ComputedValuesExt for ComputedValues { }; let position = self.get_position(); physical::Vec2 { - x: unwrap(position.max_width), - y: unwrap(position.max_height), + x: unwrap(position.max_width.clone()), + y: unwrap(position.max_height.clone()), } .size_to_flow_relative(self.writing_mode) } @@ -122,10 +122,10 @@ impl ComputedValuesExt for ComputedValues { fn padding(&self) -> flow_relative::Sides<LengthPercentage> { let padding = self.get_padding(); physical::Sides { - top: padding.padding_top.0, - left: padding.padding_left.0, - bottom: padding.padding_bottom.0, - right: padding.padding_right.0, + top: padding.padding_top.0.clone(), + left: padding.padding_left.0.clone(), + bottom: padding.padding_bottom.0.clone(), + right: padding.padding_right.0.clone(), } .to_flow_relative(self.writing_mode) } @@ -144,10 +144,10 @@ impl ComputedValuesExt for ComputedValues { fn margin(&self) -> flow_relative::Sides<LengthPercentageOrAuto> { let margin = self.get_margin(); physical::Sides { - top: margin.margin_top, - left: margin.margin_left, - bottom: margin.margin_bottom, - right: margin.margin_right, + top: margin.margin_top.clone(), + left: margin.margin_left.clone(), + bottom: margin.margin_bottom.clone(), + right: margin.margin_right.clone(), } .to_flow_relative(self.writing_mode) } @@ -180,7 +180,9 @@ impl From<stylo::Display> for Display { fn size_to_length(size: Size) -> LengthPercentageOrAuto { match size { - Size::LengthPercentage(length) => LengthPercentageOrAuto::LengthPercentage(length.0), + Size::LengthPercentage(length) => { + LengthPercentageOrAuto::LengthPercentage(length.0.clone()) + }, Size::Auto => LengthPercentageOrAuto::Auto, } } diff --git a/components/malloc_size_of/Cargo.toml b/components/malloc_size_of/Cargo.toml index d2068a30e9b..1b4872e67f1 100644 --- a/components/malloc_size_of/Cargo.toml +++ b/components/malloc_size_of/Cargo.toml @@ -40,7 +40,7 @@ serde = { version = "1.0.27", optional = true } serde_bytes = { version = "0.11", optional = true } servo_arc = { path = "../servo_arc" } smallbitvec = "2.3.0" -smallvec = "0.6" +smallvec = "1.0" string_cache = { version = "0.8", optional = true } thin-slice = "0.1.0" time = { version = "0.1.17", optional = true } diff --git a/components/selectors/Cargo.toml b/components/selectors/Cargo.toml index d32e82a2336..8bf0ba716cb 100644 --- a/components/selectors/Cargo.toml +++ b/components/selectors/Cargo.toml @@ -23,13 +23,13 @@ bench = [] bitflags = "1.0" matches = "0.1" cssparser = "0.27" -derive_more = "0.13" +derive_more = "0.99" log = "0.4" fxhash = "0.2" phf = "0.8" precomputed-hash = "0.1" servo_arc = { version = "0.1", path = "../servo_arc" } -smallvec = "0.6" +smallvec = "1.0" thin-slice = "0.1.0" to_shmem = { path = "../to_shmem" } to_shmem_derive = { path = "../to_shmem_derive" } diff --git a/components/selectors/builder.rs b/components/selectors/builder.rs index 41b83b0c40e..7a58e35d17f 100644 --- a/components/selectors/builder.rs +++ b/components/selectors/builder.rs @@ -17,7 +17,7 @@ //! is non-trivial. This module encapsulates those details and presents an //! easy-to-use API for the parser. -use crate::parser::{Combinator, Component, SelectorImpl}; +use crate::parser::{Combinator, Component, NonTSPseudoClass, SelectorImpl}; use crate::sink::Push; use servo_arc::{Arc, HeaderWithLength, ThinArc}; use smallvec::{self, SmallVec}; @@ -142,7 +142,7 @@ impl<Impl: SelectorImpl> SelectorBuilder<Impl> { let iter = SelectorBuilderIter { current_simple_selectors: current.iter(), rest_of_simple_selectors: rest, - combinators: self.combinators.drain().rev(), + combinators: self.combinators.drain(..).rev(), }; Arc::into_thin(Arc::from_header_and_iter(header, iter)) @@ -152,7 +152,7 @@ impl<Impl: SelectorImpl> SelectorBuilder<Impl> { struct SelectorBuilderIter<'a, Impl: SelectorImpl> { current_simple_selectors: slice::Iter<'a, Component<Impl>>, rest_of_simple_selectors: &'a [Component<Impl>], - combinators: iter::Rev<smallvec::Drain<'a, (Combinator, usize)>>, + combinators: iter::Rev<smallvec::Drain<'a, [(Combinator, usize); 16]>>, } impl<'a, Impl: SelectorImpl> ExactSizeIterator for SelectorBuilderIter<'a, Impl> { @@ -322,10 +322,14 @@ where Component::NthLastOfType(..) | Component::FirstOfType | Component::LastOfType | - Component::OnlyOfType | - Component::NonTSPseudoClass(..) => { + Component::OnlyOfType => { specificity.class_like_selectors += 1; }, + Component::NonTSPseudoClass(ref pseudo) => { + if !pseudo.has_zero_specificity() { + specificity.class_like_selectors += 1; + } + }, Component::ExplicitUniversalType | Component::ExplicitAnyNamespace | Component::ExplicitNoNamespace | diff --git a/components/selectors/parser.rs b/components/selectors/parser.rs index 507121bbf97..92a5b039b90 100644 --- a/components/selectors/parser.rs +++ b/components/selectors/parser.rs @@ -52,6 +52,9 @@ pub trait NonTSPseudoClass: Sized + ToCss { /// /// https://drafts.csswg.org/selectors-4/#useraction-pseudos fn is_user_action_state(&self) -> bool; + + /// Whether this pseudo-class has zero specificity. + fn has_zero_specificity(&self) -> bool; } /// Returns a Cow::Borrowed if `s` is already ASCII lowercase, and a @@ -2336,6 +2339,11 @@ pub mod tests { fn is_user_action_state(&self) -> bool { self.is_active_or_hover() } + + #[inline] + fn has_zero_specificity(&self) -> bool { + false + } } impl ToCss for PseudoClass { diff --git a/components/style/Cargo.toml b/components/style/Cargo.toml index 47a0d4392ef..6adb71e89d7 100644 --- a/components/style/Cargo.toml +++ b/components/style/Cargo.toml @@ -35,7 +35,7 @@ bitflags = "1.0" byteorder = "1.0" cssparser = "0.27" crossbeam-channel = { version = "0.3", optional = true } -derive_more = "0.13" +derive_more = "0.99" new_debug_unreachable = "1.0" encoding_rs = {version = "0.8", optional = true} euclid = "0.20" @@ -66,7 +66,7 @@ servo_arc = { path = "../servo_arc" } servo_atoms = {path = "../atoms", optional = true} servo_config = {path = "../config", optional = true} smallbitvec = "2.3.0" -smallvec = "0.6.6" +smallvec = "1.0" string_cache = { version = "0.8", optional = true } style_derive = {path = "../style_derive"} style_traits = {path = "../style_traits"} diff --git a/components/style/bloom.rs b/components/style/bloom.rs index a24dac42b2a..c17b31d1bee 100644 --- a/components/style/bloom.rs +++ b/components/style/bloom.rs @@ -216,7 +216,7 @@ impl<E: TElement> StyleBloom<E> { self.filter.clear(); self.pushed_hashes.clear(); } else { - for hash in self.pushed_hashes.drain() { + for hash in self.pushed_hashes.drain(..) { self.filter.remove_hash(hash); } debug_assert!(self.filter.is_zeroed()); @@ -233,7 +233,7 @@ impl<E: TElement> StyleBloom<E> { element = parent; } - for parent in parents_to_insert.drain().rev() { + for parent in parents_to_insert.drain(..).rev() { self.push(parent); } } @@ -374,7 +374,7 @@ impl<E: TElement> StyleBloom<E> { // Now the parents match, so insert the stack of elements we have been // collecting so far. - for parent in parents_to_insert.drain().rev() { + for parent in parents_to_insert.drain(..).rev() { self.push(parent); } diff --git a/components/style/dom.rs b/components/style/dom.rs index fbe35e2e49d..74067e225c8 100644 --- a/components/style/dom.rs +++ b/components/style/dom.rs @@ -807,6 +807,9 @@ pub trait TElement: /// data if it comes from Shadow DOM. /// /// Returns whether normal document author rules should apply. + /// + /// TODO(emilio): We could separate the invalidation data for elements + /// matching in other scopes to avoid over-invalidation. fn each_applicable_non_document_style_rule_data<'a, F>(&self, mut f: F) -> bool where Self: 'a, @@ -841,11 +844,42 @@ pub trait TElement: // Slots can only have assigned nodes when in a shadow tree. let shadow = slot.containing_shadow().unwrap(); if let Some(data) = shadow.style_data() { - f(data, shadow.host()); + if data.any_slotted_rule() { + f(data, shadow.host()); + } } current = slot.assigned_slot(); } + if target.has_part_attr() { + if let Some(mut inner_shadow) = target.containing_shadow() { + loop { + let inner_shadow_host = inner_shadow.host(); + match inner_shadow_host.containing_shadow() { + Some(shadow) => { + if let Some(data) = shadow.style_data() { + if data.any_part_rule() { + f(data, shadow.host()) + } + } + // TODO: Could be more granular. + if !shadow.host().exports_any_part() { + break; + } + inner_shadow = shadow; + }, + None => { + // TODO(emilio): Should probably distinguish with + // MatchesDocumentRules::{No,Yes,IfPart} or + // something so that we could skip some work. + doc_rules_apply = true; + break; + }, + } + } + } + } + doc_rules_apply } diff --git a/components/style/font_metrics.rs b/components/style/font_metrics.rs index 8e69118ade4..b521fdf76c9 100644 --- a/components/style/font_metrics.rs +++ b/components/style/font_metrics.rs @@ -7,17 +7,17 @@ #![deny(missing_docs)] use crate::context::SharedStyleContext; +use crate::values::computed::Length; use crate::Atom; -use app_units::Au; /// Represents the font metrics that style needs from a font to compute the /// value of certain CSS units like `ex`. #[derive(Clone, Debug, Default, PartialEq)] pub struct FontMetrics { /// The x-height of the font. - pub x_height: Option<Au>, + pub x_height: Option<Length>, /// The zero advance. This is usually writing mode dependent - pub zero_advance_measure: Option<Au>, + pub zero_advance_measure: Option<Length>, } /// Type of font metrics to retrieve. @@ -47,7 +47,7 @@ pub trait FontMetricsProvider { &self, font_name: &Atom, font_family: crate::values::computed::font::GenericFontFamily, - ) -> Au; + ) -> Length; /// Construct from a shared style context fn create_from(context: &SharedStyleContext) -> Self @@ -70,7 +70,7 @@ impl FontMetricsProvider for ServoMetricsProvider { ServoMetricsProvider } - fn get_size(&self, _: &Atom, _: crate::values::computed::font::GenericFontFamily) -> Au { + fn get_size(&self, _: &Atom, _: crate::values::computed::font::GenericFontFamily) -> Length { unreachable!("Dummy provider should never be used to compute font size") } } diff --git a/components/style/gecko/media_queries.rs b/components/style/gecko/media_queries.rs index 3463c1f95e9..3f82b832bce 100644 --- a/components/style/gecko/media_queries.rs +++ b/components/style/gecko/media_queries.rs @@ -11,10 +11,9 @@ use crate::gecko_bindings::structs; use crate::media_queries::MediaType; use crate::properties::ComputedValues; use crate::string_cache::Atom; -use crate::values::computed::font::FontSize; +use crate::values::specified::font::FONT_MEDIUM_PX; use crate::values::{CustomIdent, KeyframesName}; -use app_units::Au; -use app_units::AU_PER_PX; +use app_units::{Au, AU_PER_PX}; use cssparser::RGBA; use euclid::default::Size2D; use euclid::Scale; @@ -87,7 +86,7 @@ impl Device { document, default_values: ComputedValues::default_values(doc), // FIXME(bz): Seems dubious? - root_font_size: AtomicIsize::new(FontSize::medium().size().0 as isize), + root_font_size: AtomicIsize::new(Au::from_px(FONT_MEDIUM_PX as i32).0 as isize), body_text_color: AtomicUsize::new(prefs.mDefaultColor as usize), used_root_font_size: AtomicBool::new(false), used_viewport_size: AtomicBool::new(false), diff --git a/components/style/gecko/non_ts_pseudo_class_list.rs b/components/style/gecko/non_ts_pseudo_class_list.rs index f38757189d0..8d9fc3d2d85 100644 --- a/components/style/gecko/non_ts_pseudo_class_list.rs +++ b/components/style/gecko/non_ts_pseudo_class_list.rs @@ -48,8 +48,7 @@ macro_rules! apply_non_ts_list { ("indeterminate", Indeterminate, indeterminate, IN_INDETERMINATE_STATE, _), ("-moz-devtools-highlighted", MozDevtoolsHighlighted, mozDevtoolsHighlighted, IN_DEVTOOLS_HIGHLIGHTED_STATE, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS), ("-moz-styleeditor-transitioning", MozStyleeditorTransitioning, mozStyleeditorTransitioning, IN_STYLEEDITOR_TRANSITIONING_STATE, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS), - ("fullscreen", Fullscreen, fullscreen, IN_FULLSCREEN_STATE, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME), - ("-moz-full-screen", MozFullScreen, mozFullScreen, IN_FULLSCREEN_STATE, _), + ("fullscreen", Fullscreen, fullscreen, IN_FULLSCREEN_STATE, _), // TODO(emilio): This is inconsistently named (the capital R). ("-moz-focusring", MozFocusRing, mozFocusRing, IN_FOCUSRING_STATE, _), ("-moz-broken", MozBroken, mozBroken, IN_BROKEN_STATE, _), @@ -94,6 +93,7 @@ macro_rules! apply_non_ts_list { ("-moz-last-node", MozLastNode, lastNode, _, _), ("-moz-only-whitespace", MozOnlyWhitespace, mozOnlyWhitespace, _, _), ("-moz-native-anonymous", MozNativeAnonymous, mozNativeAnonymous, _, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS), + ("-moz-native-anonymous-no-specificity", MozNativeAnonymousNoSpecificity, mozNativeAnonymousNoSpecificity, _, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS), ("-moz-use-shadow-tree-root", MozUseShadowTreeRoot, mozUseShadowTreeRoot, _, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS), ("-moz-is-html", MozIsHTML, mozIsHTML, _, _), ("-moz-placeholder", MozPlaceholder, mozPlaceholder, _, _), diff --git a/components/style/gecko/pseudo_element_definition.mako.rs b/components/style/gecko/pseudo_element_definition.mako.rs index d8d80d60165..f4a6671bd39 100644 --- a/components/style/gecko/pseudo_element_definition.mako.rs +++ b/components/style/gecko/pseudo_element_definition.mako.rs @@ -193,18 +193,18 @@ impl PseudoElement { % for pseudo in SIMPLE_PSEUDOS: "${pseudo.value[1:]}" => { return Some(${pseudo_element_variant(pseudo)}) - } + }, % endfor // Alias some legacy prefixed pseudos to their standardized name at parse time: "-moz-selection" => { return Some(PseudoElement::Selection); - } + }, "-moz-placeholder" => { return Some(PseudoElement::Placeholder); - } + }, "-moz-list-bullet" | "-moz-list-number" => { return Some(PseudoElement::Marker); - } + }, _ => { if starts_with_ignore_ascii_case(name, "-moz-tree-") { return PseudoElement::tree_pseudo_element(name, Box::new([])) diff --git a/components/style/gecko/selector_parser.rs b/components/style/gecko/selector_parser.rs index 2aad41adc9c..9f5b49c5c13 100644 --- a/components/style/gecko/selector_parser.rs +++ b/components/style/gecko/selector_parser.rs @@ -137,6 +137,7 @@ impl NonTSPseudoClass { ([$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*]) => { match_ignore_ascii_case! { &name, $($css => Some(NonTSPseudoClass::$name),)* + "-moz-full-screen" => Some(NonTSPseudoClass::Fullscreen), _ => None, } } @@ -169,16 +170,9 @@ impl NonTSPseudoClass { } /// Returns whether the pseudo-class is enabled in content sheets. + #[inline] fn is_enabled_in_content(&self) -> bool { - match *self { - // For pseudo-classes with pref, the availability in content - // depends on the pref. - NonTSPseudoClass::Fullscreen => static_prefs::pref!("full-screen-api.unprefix.enabled"), - // Otherwise, a pseudo-class is enabled in content when it - // doesn't have any enabled flag. - _ => !self - .has_any_flag(NonTSPseudoClassFlag::PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME), - } + !self.has_any_flag(NonTSPseudoClassFlag::PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME) } /// Get the state flag associated with a pseudo-class, if any. @@ -233,6 +227,9 @@ impl NonTSPseudoClass { // across all the elements involved and the latter is already // checked for by our caching precondtions. NonTSPseudoClass::MozIsHTML | + // We prevent style sharing for NAC. + NonTSPseudoClass::MozNativeAnonymous | + NonTSPseudoClass::MozNativeAnonymousNoSpecificity | // :-moz-placeholder is parsed but never matches. NonTSPseudoClass::MozPlaceholder | // :-moz-locale-dir and :-moz-window-inactive depend only on @@ -275,6 +272,11 @@ impl ::selectors::parser::NonTSPseudoClass for NonTSPseudoClass { NonTSPseudoClass::Hover | NonTSPseudoClass::Active | NonTSPseudoClass::Focus ) } + + #[inline] + fn has_zero_specificity(&self) -> bool { + matches!(*self, NonTSPseudoClass::MozNativeAnonymousNoSpecificity) + } } /// The dummy struct we use to implement our selector parsing. @@ -394,7 +396,7 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> { parser, )?.into() ) - } + }, _ => return Err(parser.new_custom_error( SelectorParseErrorKind::UnsupportedPseudoClassOrElement(name.clone()) )) diff --git a/components/style/gecko/snapshot.rs b/components/style/gecko/snapshot.rs index 02707682b4d..fa9914f6222 100644 --- a/components/style/gecko/snapshot.rs +++ b/components/style/gecko/snapshot.rs @@ -71,7 +71,7 @@ impl GeckoElementSnapshot { } /// Returns true if the snapshot recorded an attribute change which isn't a - /// class or id change. + /// class / id #[inline] pub fn other_attr_changed(&self) -> bool { self.mOtherAttributeChanged() diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs index bf4da090646..e4b2d7f0be1 100644 --- a/components/style/gecko/wrapper.rs +++ b/components/style/gecko/wrapper.rs @@ -68,6 +68,7 @@ use crate::shared_lock::Locked; use crate::string_cache::{Atom, Namespace, WeakAtom, WeakNamespace}; use crate::stylist::CascadeData; use crate::values::computed::font::GenericFontFamily; +use crate::values::computed::Length; use crate::values::specified::length::FontBaseSize; use crate::CaseSensitivityExt; use app_units::Au; @@ -929,7 +930,7 @@ impl FontMetricsProvider for GeckoFontMetricsProvider { GeckoFontMetricsProvider::new() } - fn get_size(&self, font_name: &Atom, font_family: GenericFontFamily) -> Au { + fn get_size(&self, font_name: &Atom, font_family: GenericFontFamily) -> Length { let mut cache = self.font_size_cache.borrow_mut(); if let Some(sizes) = cache.iter().find(|el| el.0 == *font_name) { return sizes.1.size_for_generic(font_family); @@ -950,7 +951,7 @@ impl FontMetricsProvider for GeckoFontMetricsProvider { None => return Default::default(), }; - let size = base_size.resolve(context); + let size = Au::from(base_size.resolve(context)); let style = context.style(); let (wm, font) = match base_size { @@ -977,9 +978,9 @@ impl FontMetricsProvider for GeckoFontMetricsProvider { ) }; FontMetrics { - x_height: Some(Au(gecko_metrics.mXSize)), + x_height: Some(Au(gecko_metrics.mXSize).into()), zero_advance_measure: if gecko_metrics.mChSize >= 0 { - Some(Au(gecko_metrics.mChSize)) + Some(Au(gecko_metrics.mChSize).into()) } else { None }, @@ -988,7 +989,7 @@ impl FontMetricsProvider for GeckoFontMetricsProvider { } impl structs::FontSizePrefs { - fn size_for_generic(&self, font_family: GenericFontFamily) -> Au { + fn size_for_generic(&self, font_family: GenericFontFamily) -> Length { Au(match font_family { GenericFontFamily::None => self.mDefaultVariableSize, GenericFontFamily::Serif => self.mDefaultSerifSize, @@ -1000,6 +1001,7 @@ impl structs::FontSizePrefs { "Should never get here, since this doesn't (yet) appear on font family" ), }) + .into() } } @@ -2045,7 +2047,6 @@ impl<'le> ::selectors::Element for GeckoElement<'le> { NonTSPseudoClass::Disabled | NonTSPseudoClass::Checked | NonTSPseudoClass::Fullscreen | - NonTSPseudoClass::MozFullScreen | NonTSPseudoClass::Indeterminate | NonTSPseudoClass::PlaceholderShown | NonTSPseudoClass::Target | @@ -2130,7 +2131,10 @@ impl<'le> ::selectors::Element for GeckoElement<'le> { } true }, - NonTSPseudoClass::MozNativeAnonymous => self.is_in_native_anonymous_subtree(), + NonTSPseudoClass::MozNativeAnonymous | + NonTSPseudoClass::MozNativeAnonymousNoSpecificity => { + self.is_in_native_anonymous_subtree() + }, NonTSPseudoClass::MozUseShadowTreeRoot => self.is_root_of_use_element_shadow_tree(), NonTSPseudoClass::MozTableBorderNonzero => unsafe { bindings::Gecko_IsTableBorderNonzero(self.0) diff --git a/components/style/gecko_bindings/sugar/ns_t_array.rs b/components/style/gecko_bindings/sugar/ns_t_array.rs index 64ca9ffab78..e3d4e5b86bd 100644 --- a/components/style/gecko_bindings/sugar/ns_t_array.rs +++ b/components/style/gecko_bindings/sugar/ns_t_array.rs @@ -89,9 +89,11 @@ impl<T> nsTArray<T> { pub unsafe fn set_len(&mut self, len: u32) { // this can leak debug_assert!(len >= self.len() as u32); + if self.len() == len as usize { + return; + } self.ensure_capacity(len as usize); - let header = self.header_mut(); - header.mLength = len; + self.header_mut().mLength = len; } /// Resizes an array containing only POD elements @@ -103,6 +105,9 @@ impl<T> nsTArray<T> { where T: Copy, { + if self.len() == len as usize { + return; + } self.ensure_capacity(len as usize); let header = self.header_mut(); header.mLength = len; diff --git a/components/style/invalidation/element/invalidation_map.rs b/components/style/invalidation/element/invalidation_map.rs index e0b9cf8d747..6d9f6a8602d 100644 --- a/components/style/invalidation/element/invalidation_map.rs +++ b/components/style/invalidation/element/invalidation_map.rs @@ -142,6 +142,19 @@ pub struct DocumentStateDependency { pub state: DocumentState, } +bitflags! { + /// A set of flags that denote whether any invalidations have occurred + /// for a particular attribute selector. + #[derive(MallocSizeOf)] + #[repr(C)] + pub struct InvalidationMapFlags : u8 { + /// Whether [class] or such is used. + const HAS_CLASS_ATTR_SELECTOR = 1 << 0; + /// Whether [id] or such is used. + const HAS_ID_ATTR_SELECTOR = 1 << 1; + } +} + /// A map where we store invalidations. /// /// This is slightly different to a SelectorMap, in the sense of that the same @@ -164,16 +177,9 @@ pub struct InvalidationMap { pub document_state_selectors: Vec<DocumentStateDependency>, /// A map of other attribute affecting selectors. pub other_attribute_affecting_selectors: SelectorMap<Dependency>, - /// Whether there are attribute rules of the form `[class~="foo"]` that may - /// match. In that case, we need to look at - /// `other_attribute_affecting_selectors` too even if only the `class` has - /// changed. - pub has_class_attribute_selectors: bool, - /// Whether there are attribute rules of the form `[id|="foo"]` that may - /// match. In that case, we need to look at - /// `other_attribute_affecting_selectors` too even if only the `id` has - /// changed. - pub has_id_attribute_selectors: bool, + /// A set of flags that contain whether various special attributes are used + /// in this invalidation map. + pub flags: InvalidationMapFlags, } impl InvalidationMap { @@ -185,8 +191,7 @@ impl InvalidationMap { state_affecting_selectors: SelectorMap::new(), document_state_selectors: Vec::new(), other_attribute_affecting_selectors: SelectorMap::new(), - has_class_attribute_selectors: false, - has_id_attribute_selectors: false, + flags: InvalidationMapFlags::empty(), } } @@ -210,8 +215,7 @@ impl InvalidationMap { self.state_affecting_selectors.clear(); self.document_state_selectors.clear(); self.other_attribute_affecting_selectors.clear(); - self.has_id_attribute_selectors = false; - self.has_class_attribute_selectors = false; + self.flags = InvalidationMapFlags::empty(); } /// Adds a selector to this `InvalidationMap`. Returns Err(..) to @@ -238,8 +242,7 @@ impl InvalidationMap { state: ElementState::empty(), document_state: &mut document_state, other_attributes: false, - has_id_attribute_selectors: false, - has_class_attribute_selectors: false, + flags: &mut self.flags, }; // Visit all the simple selectors in this sequence. @@ -255,9 +258,6 @@ impl InvalidationMap { index += 1; // Account for the simple selector. } - self.has_id_attribute_selectors |= compound_visitor.has_id_attribute_selectors; - self.has_class_attribute_selectors |= compound_visitor.has_class_attribute_selectors; - for class in compound_visitor.classes { self.class_to_selector .try_entry(class, quirks_mode)? @@ -349,11 +349,8 @@ struct CompoundSelectorDependencyCollector<'a> { /// [id] attribute selectors). other_attributes: bool, - /// Whether there were attribute selectors with the id attribute. - has_id_attribute_selectors: bool, - - /// Whether there were attribute selectors with the class attribute. - has_class_attribute_selectors: bool, + /// The invalidation map flags, that we set when some attribute selectors are present. + flags: &'a mut InvalidationMapFlags, } impl<'a> SelectorVisitor for CompoundSelectorDependencyCollector<'a> { @@ -398,8 +395,13 @@ impl<'a> SelectorVisitor for CompoundSelectorDependencyCollector<'a> { }; if may_match_in_no_namespace { - self.has_id_attribute_selectors |= *local_name_lower == local_name!("id"); - self.has_class_attribute_selectors |= *local_name_lower == local_name!("class"); + if *local_name_lower == local_name!("id") { + self.flags + .insert(InvalidationMapFlags::HAS_ID_ATTR_SELECTOR) + } else if *local_name_lower == local_name!("class") { + self.flags + .insert(InvalidationMapFlags::HAS_CLASS_ATTR_SELECTOR) + } } true diff --git a/components/style/invalidation/element/invalidator.rs b/components/style/invalidation/element/invalidator.rs index e094be281b4..f0f55595dff 100644 --- a/components/style/invalidation/element/invalidator.rs +++ b/components/style/invalidation/element/invalidator.rs @@ -698,7 +698,7 @@ where } } - sibling_invalidations.extend(new_sibling_invalidations.drain()); + sibling_invalidations.extend(new_sibling_invalidations.drain(..)); invalidated_self } diff --git a/components/style/invalidation/element/state_and_attributes.rs b/components/style/invalidation/element/state_and_attributes.rs index e678413218c..628f174a3d7 100644 --- a/components/style/invalidation/element/state_and_attributes.rs +++ b/components/style/invalidation/element/state_and_attributes.rs @@ -42,6 +42,7 @@ where descendant_invalidations: &'a mut DescendantInvalidationLists<'selectors>, sibling_invalidations: &'a mut InvalidationVector<'selectors>, invalidates_self: bool, + attr_selector_flags: InvalidationMapFlags, } /// An invalidation processor for style changes due to state and attribute @@ -155,6 +156,8 @@ where return false; } + let mut attr_selector_flags = InvalidationMapFlags::empty(); + // If we the visited state changed, we force a restyle here. Matching // doesn't depend on the actual visited state at all, so we can't look // at matching results to decide what to do for this case. @@ -172,6 +175,7 @@ where let mut classes_removed = SmallVec::<[Atom; 8]>::new(); let mut classes_added = SmallVec::<[Atom; 8]>::new(); if snapshot.class_changed() { + attr_selector_flags.insert(InvalidationMapFlags::HAS_CLASS_ATTR_SELECTOR); // TODO(emilio): Do this more efficiently! snapshot.each_class(|c| { if !element.has_class(c, CaseSensitivity::CaseSensitive) { @@ -189,6 +193,7 @@ where let mut id_removed = None; let mut id_added = None; if snapshot.id_changed() { + attr_selector_flags.insert(InvalidationMapFlags::HAS_ID_ATTR_SELECTOR); let old_id = snapshot.id_attr(); let current_id = element.id(); @@ -199,7 +204,10 @@ where } if log_enabled!(::log::Level::Debug) { - debug!("Collecting changes for: {:?}", element); + debug!( + "Collecting changes for: {:?}, flags {:?}", + element, attr_selector_flags + ); if !state_changes.is_empty() { debug!(" > state: {:?}", state_changes); } @@ -247,6 +255,7 @@ where descendant_invalidations, sibling_invalidations, invalidates_self: false, + attr_selector_flags, }; let document_origins = if !matches_document_author_rules { @@ -356,9 +365,8 @@ where } } - let should_examine_attribute_selector_map = self.snapshot.other_attr_changed() || - (self.snapshot.class_changed() && map.has_class_attribute_selectors) || - (self.snapshot.id_changed() && map.has_id_attribute_selectors); + let should_examine_attribute_selector_map = + self.snapshot.other_attr_changed() || map.flags.intersects(self.attr_selector_flags); if should_examine_attribute_selector_map { self.collect_dependencies_in_map(&map.other_attribute_affecting_selectors) diff --git a/components/style/logical_geometry.rs b/components/style/logical_geometry.rs index cb45544146b..d4d058adc61 100644 --- a/components/style/logical_geometry.rs +++ b/components/style/logical_geometry.rs @@ -468,7 +468,7 @@ impl<T: Zero> LogicalSize<T> { } } -impl<T: Copy> LogicalSize<T> { +impl<T> LogicalSize<T> { #[inline] pub fn new(mode: WritingMode, inline: T, block: T) -> LogicalSize<T> { LogicalSize { @@ -486,7 +486,9 @@ impl<T: Copy> LogicalSize<T> { LogicalSize::new(mode, size.width, size.height) } } +} +impl<T: Copy> LogicalSize<T> { #[inline] pub fn width(&self, mode: WritingMode) -> T { self.debug_writing_mode.check(mode); @@ -860,7 +862,7 @@ impl<T: Zero> LogicalMargin<T> { } } -impl<T: Copy> LogicalMargin<T> { +impl<T> LogicalMargin<T> { #[inline] pub fn new( mode: WritingMode, @@ -879,11 +881,6 @@ impl<T: Copy> LogicalMargin<T> { } #[inline] - pub fn new_all_same(mode: WritingMode, value: T) -> LogicalMargin<T> { - LogicalMargin::new(mode, value, value, value, value) - } - - #[inline] pub fn from_physical(mode: WritingMode, offsets: SideOffsets2D<T>) -> LogicalMargin<T> { let block_start; let inline_end; @@ -917,6 +914,13 @@ impl<T: Copy> LogicalMargin<T> { } LogicalMargin::new(mode, block_start, inline_end, block_end, inline_start) } +} + +impl<T: Copy> LogicalMargin<T> { + #[inline] + pub fn new_all_same(mode: WritingMode, value: T) -> LogicalMargin<T> { + LogicalMargin::new(mode, value, value, value, value) + } #[inline] pub fn top(&self, mode: WritingMode) -> T { diff --git a/components/style/matching.rs b/components/style/matching.rs index 01246ed3878..7ec94d35346 100644 --- a/components/style/matching.rs +++ b/components/style/matching.rs @@ -715,7 +715,7 @@ pub trait MatchMethods: TElement { .map_or(true, |s| s.get_font().clone_font_size() != new_font_size) { debug_assert!(self.owner_doc_matches_for_testing(device)); - device.set_root_font_size(new_font_size.size()); + device.set_root_font_size(new_font_size.size().into()); // If the root font-size changed since last time, and something // in the document did use rem units, ensure we recascade the // entire tree. diff --git a/components/style/parallel.rs b/components/style/parallel.rs index d4aa0af6acf..9e578e9e9e6 100644 --- a/components/style/parallel.rs +++ b/components/style/parallel.rs @@ -180,7 +180,7 @@ fn top_down_dom<'a, 'scope, E, D>( let mut traversal_data_copy = traversal_data.clone(); traversal_data_copy.current_dom_depth += 1; traverse_nodes( - discovered_child_nodes.drain(), + discovered_child_nodes.drain(..), DispatchMode::NotTailCall, recursion_ok, root, @@ -210,7 +210,7 @@ fn top_down_dom<'a, 'scope, E, D>( if !discovered_child_nodes.is_empty() { traversal_data.current_dom_depth += 1; traverse_nodes( - discovered_child_nodes.drain(), + discovered_child_nodes.drain(..), DispatchMode::TailCall, recursion_ok, root, diff --git a/components/style/properties/cascade.rs b/components/style/properties/cascade.rs index a667cba09bc..dd87916cf7d 100644 --- a/components/style/properties/cascade.rs +++ b/components/style/properties/cascade.rs @@ -743,6 +743,7 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> { fn recompute_keyword_font_size_if_needed(&mut self) { use crate::values::computed::ToComputedValue; use crate::values::specified; + use app_units::Au; if !self.seen.contains(LonghandId::XLang) && !self.seen.contains(LonghandId::FontFamily) { @@ -759,7 +760,7 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> { None => return, }; - if font.gecko().mScriptUnconstrainedSize == new_size.size().0 { + if font.gecko().mScriptUnconstrainedSize == Au::from(new_size.size()).0 { return; } diff --git a/components/style/properties/counted_unknown_properties.py b/components/style/properties/counted_unknown_properties.py index de36199e77a..047d129a2ff 100644 --- a/components/style/properties/counted_unknown_properties.py +++ b/components/style/properties/counted_unknown_properties.py @@ -10,7 +10,8 @@ # "offset-distance", # "offset-path", # "offset-rotate", -# "offset" +# "offset", +# "text-underline-position", COUNTED_UNKNOWN_PROPERTIES = [ "-webkit-font-smoothing", "-webkit-tap-highlight-color", @@ -40,7 +41,6 @@ COUNTED_UNKNOWN_PROPERTIES = [ "baseline-shift", "-webkit-hyphenate-character", "page", - "text-underline-position", "-webkit-highlight", "background-repeat-x", "-webkit-padding-end", diff --git a/components/style/properties/data.py b/components/style/properties/data.py index 87ec87a7fa5..15ab380789b 100644 --- a/components/style/properties/data.py +++ b/components/style/properties/data.py @@ -385,6 +385,7 @@ class Longhand(object): "TextDecorationLine", "TextEmphasisPosition", "TextTransform", + "TextUnderlinePosition", "TouchAction", "TransformStyle", "UserSelect", diff --git a/components/style/properties/declaration_block.rs b/components/style/properties/declaration_block.rs index 930d4400d3d..90dec0a47d7 100644 --- a/components/style/properties/declaration_block.rs +++ b/components/style/properties/declaration_block.rs @@ -1433,7 +1433,7 @@ fn report_css_errors( selectors: Option<&SelectorList<SelectorImpl>>, errors: &mut SmallParseErrorVec, ) { - for (error, slice, property) in errors.drain() { + for (error, slice, property) in errors.drain(..) { report_one_css_error(context, Some(block), selectors, error, slice, property) } } diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index b6cd741038c..14262e7a074 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -426,7 +426,7 @@ def set_gecko_property(ffi_name, expr): pub fn copy_${ident}_from(&mut self, other: &Self) { use crate::gecko_bindings::structs::nsStyleSVG_${ident.upper()}_CONTEXT as CONTEXT_VALUE; - self.gecko.${gecko_ffi_name} = other.gecko.${gecko_ffi_name}; + self.gecko.${gecko_ffi_name} = other.gecko.${gecko_ffi_name}.clone(); self.gecko.mContextFlags = (self.gecko.mContextFlags & !CONTEXT_VALUE) | (other.gecko.mContextFlags & CONTEXT_VALUE); @@ -442,7 +442,7 @@ def set_gecko_property(ffi_name, expr): if (self.gecko.mContextFlags & CONTEXT_VALUE) != 0 { return SVGLength::ContextValue; } - SVGLength::LengthPercentage(self.gecko.${gecko_ffi_name}) + SVGLength::LengthPercentage(self.gecko.${gecko_ffi_name}.clone()) } </%def> @@ -563,7 +563,7 @@ def set_gecko_property(ffi_name, expr): #[allow(non_snake_case)] pub fn copy_${ident}_from(&mut self, other: &Self) { self.gecko.${gecko_ffi_name}.${index} = - other.gecko.${gecko_ffi_name}.${index}; + other.gecko.${gecko_ffi_name}.${index}.clone(); } #[allow(non_snake_case)] pub fn reset_${ident}(&mut self, other: &Self) { @@ -572,7 +572,7 @@ def set_gecko_property(ffi_name, expr): #[allow(non_snake_case)] pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T { - self.gecko.${gecko_ffi_name}.${index} + self.gecko.${gecko_ffi_name}.${index}.clone() } </%def> @@ -601,7 +601,7 @@ def set_gecko_property(ffi_name, expr): #[allow(non_snake_case)] pub fn copy_${ident}_from(&mut self, other: &Self) { self.gecko.${gecko_ffi_name}.${corner} = - other.gecko.${gecko_ffi_name}.${corner}; + other.gecko.${gecko_ffi_name}.${corner}.clone(); } #[allow(non_snake_case)] pub fn reset_${ident}(&mut self, other: &Self) { @@ -609,7 +609,7 @@ def set_gecko_property(ffi_name, expr): } #[allow(non_snake_case)] pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T { - self.gecko.${gecko_ffi_name}.${corner} + self.gecko.${gecko_ffi_name}.${corner}.clone() } </%def> @@ -1134,7 +1134,7 @@ fn static_assert() { pub fn set_font_size(&mut self, v: FontSize) { use crate::values::specified::font::KeywordSize; - let size = v.size(); + let size = Au::from(v.size()); self.gecko.mScriptUnconstrainedSize = size.0; // These two may be changed from Cascade::fixup_font_stuff. @@ -1852,7 +1852,7 @@ fn static_assert() { for (layer, other) in self.gecko.${layers_field_name}.mLayers.iter_mut() .zip(other.gecko.${layers_field_name}.mLayers.iter()) .take(count as usize) { - layer.${field_name} = other.${field_name}; + layer.${field_name} = other.${field_name}.clone(); } self.gecko.${layers_field_name}.${field_name}Count = count; } @@ -2006,7 +2006,7 @@ fn static_assert() { for (layer, other) in self.gecko.${image_layers_field}.mLayers.iter_mut() .zip(other.gecko.${image_layers_field}.mLayers.iter()) .take(count as usize) { - layer.mPosition.${keyword} = other.mPosition.${keyword}; + layer.mPosition.${keyword} = other.mPosition.${keyword}.clone(); } self.gecko.${image_layers_field}.mPosition${orientation.upper()}Count = count; } @@ -2020,7 +2020,7 @@ fn static_assert() { longhands::${shorthand}_position_${orientation}::computed_value::List( self.gecko.${image_layers_field}.mLayers.iter() .take(self.gecko.${image_layers_field}.mPosition${orientation.upper()}Count as usize) - .map(|position| position.mPosition.${keyword}) + .map(|position| position.mPosition.${keyword}.clone()) .collect() ) } @@ -2054,7 +2054,7 @@ fn static_assert() { pub fn clone_${shorthand}_size(&self) -> longhands::${shorthand}_size::computed_value::T { longhands::${shorthand}_size::computed_value::List( - self.gecko.${image_layers_field}.mLayers.iter().map(|layer| layer.mSize).collect() + self.gecko.${image_layers_field}.mLayers.iter().map(|layer| layer.mSize.clone()).collect() ) } diff --git a/components/style/properties/longhands/border.mako.rs b/components/style/properties/longhands/border.mako.rs index 4d68c8bfc93..09cbea19a7f 100644 --- a/components/style/properties/longhands/border.mako.rs +++ b/components/style/properties/longhands/border.mako.rs @@ -108,7 +108,6 @@ ${helpers.predefined_type( "border-image-source", "ImageLayer", engines="gecko servo-2013 servo-2020", - servo_2020_pref="layout.2020.unimplemented", initial_value="computed::ImageLayer::none()", initial_specified_value="specified::ImageLayer::none()", spec="https://drafts.csswg.org/css-backgrounds/#the-background-image", @@ -122,7 +121,6 @@ ${helpers.predefined_type( "border-image-outset", "NonNegativeLengthOrNumberRect", engines="gecko servo-2013 servo-2020", - servo_2020_pref="layout.2020.unimplemented", initial_value="generics::rect::Rect::all(computed::NonNegativeLengthOrNumber::zero())", initial_specified_value="generics::rect::Rect::all(specified::NonNegativeLengthOrNumber::zero())", spec="https://drafts.csswg.org/css-backgrounds/#border-image-outset", @@ -135,7 +133,6 @@ ${helpers.predefined_type( "BorderImageRepeat", "computed::BorderImageRepeat::stretch()", engines="gecko servo-2013 servo-2020", - servo_2020_pref="layout.2020.unimplemented", initial_specified_value="specified::BorderImageRepeat::stretch()", animation_value_type="discrete", spec="https://drafts.csswg.org/css-backgrounds/#the-border-image-repeat", @@ -145,7 +142,6 @@ ${helpers.predefined_type( "border-image-width", "BorderImageWidth", engines="gecko servo-2013 servo-2020", - servo_2020_pref="layout.2020.unimplemented", initial_value="computed::BorderImageWidth::all(computed::BorderImageSideWidth::one())", initial_specified_value="specified::BorderImageWidth::all(specified::BorderImageSideWidth::one())", spec="https://drafts.csswg.org/css-backgrounds/#border-image-width", @@ -157,7 +153,6 @@ ${helpers.predefined_type( "border-image-slice", "BorderImageSlice", engines="gecko servo-2013 servo-2020", - servo_2020_pref="layout.2020.unimplemented", initial_value="computed::BorderImageSlice::hundred_percent()", initial_specified_value="specified::BorderImageSlice::hundred_percent()", spec="https://drafts.csswg.org/css-backgrounds/#border-image-slice", diff --git a/components/style/properties/longhands/box.mako.rs b/components/style/properties/longhands/box.mako.rs index aa6118b8a8a..f5f09f32e6e 100644 --- a/components/style/properties/longhands/box.mako.rs +++ b/components/style/properties/longhands/box.mako.rs @@ -24,7 +24,7 @@ ${helpers.single_keyword( "-moz-top-layer", "none top", engines="gecko", - gecko_constant_prefix="NS_STYLE_TOP_LAYER", + gecko_enum_prefix="StyleTopLayer", gecko_ffi_name="mTopLayer", animation_value_type="none", enabled_in="ua", @@ -494,6 +494,7 @@ ${helpers.single_keyword( engines="gecko", spec="https://drafts.fxtf.org/compositing/#isolation", flags="CREATES_STACKING_CONTEXT", + gecko_enum_prefix="StyleIsolation", animation_value_type="discrete", )} diff --git a/components/style/properties/longhands/inherited_box.mako.rs b/components/style/properties/longhands/inherited_box.mako.rs index a92d638671b..78c2e6023ee 100644 --- a/components/style/properties/longhands/inherited_box.mako.rs +++ b/components/style/properties/longhands/inherited_box.mako.rs @@ -16,6 +16,7 @@ ${helpers.single_keyword( gecko_ffi_name="mVisible", animation_value_type="ComputedValue", spec="https://drafts.csswg.org/css-box/#propdef-visibility", + gecko_enum_prefix="StyleVisibility", )} // CSS Writing Modes Level 3 diff --git a/components/style/properties/longhands/inherited_text.mako.rs b/components/style/properties/longhands/inherited_text.mako.rs index e7cfbba377b..9784e2529e9 100644 --- a/components/style/properties/longhands/inherited_text.mako.rs +++ b/components/style/properties/longhands/inherited_text.mako.rs @@ -53,7 +53,7 @@ ${helpers.single_keyword( "-moz-text-size-adjust", "auto none", engines="gecko", - gecko_constant_prefix="NS_STYLE_TEXT_SIZE_ADJUST", + gecko_enum_prefix="StyleTextSizeAdjust", gecko_ffi_name="mTextSizeAdjust", animation_value_type="discrete", spec="https://drafts.csswg.org/css-size-adjust/#adjustment-control", @@ -332,6 +332,7 @@ ${helpers.single_keyword( "space-around start center space-between", engines="gecko", animation_value_type="discrete", + gecko_enum_prefix="StyleRubyAlign", spec="https://drafts.csswg.org/css-ruby/#ruby-align-property", )} @@ -341,6 +342,7 @@ ${helpers.single_keyword( engines="gecko", animation_value_type="discrete", spec="https://drafts.csswg.org/css-ruby/#ruby-position-property", + gecko_enum_prefix="StyleRubyPosition", )} // CSS Writing Modes Module Level 3 @@ -389,6 +391,18 @@ ${helpers.predefined_type( spec="https://drafts.csswg.org/css-text-decor-4/#underline-offset", )} +// text underline position +${helpers.predefined_type( + "text-underline-position", + "TextUnderlinePosition", + "computed::TextUnderlinePosition::AUTO", + engines="gecko", + animation_value_type="discrete", + gecko_pref="layout.css.text-underline-position.enabled", + has_effect_on_gecko_scrollbars=False, + spec="https://drafts.csswg.org/css-text-decor-3/#text-underline-position-property", +)} + // text decoration skip ink ${helpers.predefined_type( "text-decoration-skip-ink", diff --git a/components/style/properties/longhands/inherited_ui.mako.rs b/components/style/properties/longhands/inherited_ui.mako.rs index a7b83f0ea99..25b53190964 100644 --- a/components/style/properties/longhands/inherited_ui.mako.rs +++ b/components/style/properties/longhands/inherited_ui.mako.rs @@ -26,6 +26,7 @@ ${helpers.single_keyword( animation_value_type="discrete", extra_gecko_values="visiblepainted visiblefill visiblestroke visible painted fill stroke all", spec="https://www.w3.org/TR/SVG11/interact.html#PointerEventsProperty", + gecko_enum_prefix="StylePointerEvents", )} ${helpers.single_keyword( diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index 38243aa45e4..30a03f79290 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -3121,59 +3121,59 @@ impl ComputedValuesInner { /// Get the logical computed inline size. #[inline] - pub fn content_inline_size(&self) -> computed::Size { + pub fn content_inline_size(&self) -> &computed::Size { let position_style = self.get_position(); if self.writing_mode.is_vertical() { - position_style.height + &position_style.height } else { - position_style.width + &position_style.width } } /// Get the logical computed block size. #[inline] - pub fn content_block_size(&self) -> computed::Size { + pub fn content_block_size(&self) -> &computed::Size { let position_style = self.get_position(); - if self.writing_mode.is_vertical() { position_style.width } else { position_style.height } + if self.writing_mode.is_vertical() { &position_style.width } else { &position_style.height } } /// Get the logical computed min inline size. #[inline] - pub fn min_inline_size(&self) -> computed::Size { + pub fn min_inline_size(&self) -> &computed::Size { let position_style = self.get_position(); - if self.writing_mode.is_vertical() { position_style.min_height } else { position_style.min_width } + if self.writing_mode.is_vertical() { &position_style.min_height } else { &position_style.min_width } } /// Get the logical computed min block size. #[inline] - pub fn min_block_size(&self) -> computed::Size { + pub fn min_block_size(&self) -> &computed::Size { let position_style = self.get_position(); - if self.writing_mode.is_vertical() { position_style.min_width } else { position_style.min_height } + if self.writing_mode.is_vertical() { &position_style.min_width } else { &position_style.min_height } } /// Get the logical computed max inline size. #[inline] - pub fn max_inline_size(&self) -> computed::MaxSize { + pub fn max_inline_size(&self) -> &computed::MaxSize { let position_style = self.get_position(); - if self.writing_mode.is_vertical() { position_style.max_height } else { position_style.max_width } + if self.writing_mode.is_vertical() { &position_style.max_height } else { &position_style.max_width } } /// Get the logical computed max block size. #[inline] - pub fn max_block_size(&self) -> computed::MaxSize { + pub fn max_block_size(&self) -> &computed::MaxSize { let position_style = self.get_position(); - if self.writing_mode.is_vertical() { position_style.max_width } else { position_style.max_height } + if self.writing_mode.is_vertical() { &position_style.max_width } else { &position_style.max_height } } /// Get the logical computed padding for this writing mode. #[inline] - pub fn logical_padding(&self) -> LogicalMargin<computed::LengthPercentage> { + pub fn logical_padding(&self) -> LogicalMargin<<&computed::LengthPercentage> { let padding_style = self.get_padding(); LogicalMargin::from_physical(self.writing_mode, SideOffsets2D::new( - padding_style.padding_top.0, - padding_style.padding_right.0, - padding_style.padding_bottom.0, - padding_style.padding_left.0, + &padding_style.padding_top.0, + &padding_style.padding_right.0, + &padding_style.padding_bottom.0, + &padding_style.padding_left.0, )) } @@ -3197,26 +3197,26 @@ impl ComputedValuesInner { /// Gets the logical computed margin from this style. #[inline] - pub fn logical_margin(&self) -> LogicalMargin<computed::LengthPercentageOrAuto> { + pub fn logical_margin(&self) -> LogicalMargin<<&computed::LengthPercentageOrAuto> { let margin_style = self.get_margin(); LogicalMargin::from_physical(self.writing_mode, SideOffsets2D::new( - margin_style.margin_top, - margin_style.margin_right, - margin_style.margin_bottom, - margin_style.margin_left, + &margin_style.margin_top, + &margin_style.margin_right, + &margin_style.margin_bottom, + &margin_style.margin_left, )) } /// Gets the logical position from this style. #[inline] - pub fn logical_position(&self) -> LogicalMargin<computed::LengthPercentageOrAuto> { + pub fn logical_position(&self) -> LogicalMargin<<&computed::LengthPercentageOrAuto> { // FIXME(SimonSapin): should be the writing mode of the containing block, maybe? let position_style = self.get_position(); LogicalMargin::from_physical(self.writing_mode, SideOffsets2D::new( - position_style.top, - position_style.right, - position_style.bottom, - position_style.left, + &position_style.top, + &position_style.right, + &position_style.bottom, + &position_style.left, )) } diff --git a/components/style/properties/shorthands/border.mako.rs b/components/style/properties/shorthands/border.mako.rs index c1bf200fe45..d584e568aed 100644 --- a/components/style/properties/shorthands/border.mako.rs +++ b/components/style/properties/shorthands/border.mako.rs @@ -179,6 +179,16 @@ pub fn parse_border<'i, 't>( impl<'a> ToCss for LonghandsToSerialize<'a> { fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write { + use crate::properties::longhands; + + // If any of the border-image longhands differ from their initial specified values we should not + // invoke serialize_directional_border(), so there is no point in continuing on to compute all_equal. + % for name in "outset repeat slice source width".split(): + if *self.border_image_${name} != longhands::border_image_${name}::get_initial_specified_value() { + return Ok(()); + } + % endfor + let all_equal = { % for side in PHYSICAL_SIDES: let border_${side}_width = self.border_${side}_width; diff --git a/components/style/rule_collector.rs b/components/style/rule_collector.rs index ab1fb88d7f2..9841eb9e70f 100644 --- a/components/style/rule_collector.rs +++ b/components/style/rule_collector.rs @@ -348,7 +348,8 @@ where return; } - let outer_shadow = inner_shadow.host().containing_shadow(); + let inner_shadow_host = inner_shadow.host(); + let outer_shadow = inner_shadow_host.containing_shadow(); let part_rules = match outer_shadow { Some(shadow) => shadow .style_data() @@ -387,8 +388,6 @@ where shadow_cascade_order.inc(); } - let inner_shadow_host = inner_shadow.host(); - inner_shadow = match outer_shadow { Some(s) => s, None => break, // Nowhere to export to. diff --git a/components/style/rule_tree/mod.rs b/components/style/rule_tree/mod.rs index 7cb153de375..19e3accb851 100644 --- a/components/style/rule_tree/mod.rs +++ b/components/style/rule_tree/mod.rs @@ -345,7 +345,7 @@ impl RuleTree { important_author.sort_by_key(|&(_, order)| -order); } - for (source, shadow_cascade_order) in important_author.drain() { + for (source, shadow_cascade_order) in important_author.drain(..) { current = current.ensure_child( self.root.downgrade(), source, @@ -355,11 +355,11 @@ impl RuleTree { ); } - for source in important_user.drain() { + for source in important_user.drain(..) { current = current.ensure_child(self.root.downgrade(), source, UserImportant); } - for source in important_ua.drain() { + for source in important_ua.drain(..) { current = current.ensure_child(self.root.downgrade(), source, UAImportant); } @@ -378,7 +378,7 @@ impl RuleTree { guards: &StylesheetGuards, ) -> StrongRuleNode { self.insert_ordered_rules_with_important( - applicable_declarations.drain().map(|d| d.for_rule_tree()), + applicable_declarations.drain(..).map(|d| d.for_rule_tree()), guards, ) } @@ -556,7 +556,7 @@ impl RuleTree { // Now the rule is in the relevant place, push the children as // necessary. - let rule = self.insert_ordered_rules_from(current, children.drain().rev()); + let rule = self.insert_ordered_rules_from(current, children.drain(..).rev()); Some(rule) } @@ -592,8 +592,8 @@ impl RuleTree { last = node; } - let rule = - self.insert_ordered_rules_from(last.parent().unwrap().clone(), children.drain().rev()); + let rule = self + .insert_ordered_rules_from(last.parent().unwrap().clone(), children.drain(..).rev()); rule } diff --git a/components/style/servo/media_queries.rs b/components/style/servo/media_queries.rs index df7bf93b8ac..4cdfc80eef7 100644 --- a/components/style/servo/media_queries.rs +++ b/components/style/servo/media_queries.rs @@ -10,8 +10,8 @@ use crate::media_queries::media_feature::{Evaluator, MediaFeatureDescription}; use crate::media_queries::media_feature_expression::RangeOrOperator; use crate::media_queries::MediaType; use crate::properties::ComputedValues; -use crate::values::computed::font::FontSize; use crate::values::computed::CSSPixelLength; +use crate::values::specified::font::FONT_MEDIUM_PX; use crate::values::KeyframesName; use app_units::Au; use cssparser::RGBA; @@ -68,7 +68,7 @@ impl Device { viewport_size, device_pixel_ratio, // FIXME(bz): Seems dubious? - root_font_size: AtomicIsize::new(FontSize::medium().size().0 as isize), + root_font_size: AtomicIsize::new(Au::from_px(FONT_MEDIUM_PX).0 as isize), used_root_font_size: AtomicBool::new(false), used_viewport_units: AtomicBool::new(false), environment: CssEnvironment, diff --git a/components/style/servo/selector_parser.rs b/components/style/servo/selector_parser.rs index 977a6c59a85..942dcdba1bb 100644 --- a/components/style/servo/selector_parser.rs +++ b/components/style/servo/selector_parser.rs @@ -309,6 +309,11 @@ impl ::selectors::parser::NonTSPseudoClass for NonTSPseudoClass { NonTSPseudoClass::Active | NonTSPseudoClass::Hover | NonTSPseudoClass::Focus ) } + + #[inline] + fn has_zero_specificity(&self) -> bool { + false + } } impl ToCss for NonTSPseudoClass { diff --git a/components/style/stylesheets/mod.rs b/components/style/stylesheets/mod.rs index b74413866f5..c9697ead615 100644 --- a/components/style/stylesheets/mod.rs +++ b/components/style/stylesheets/mod.rs @@ -59,6 +59,7 @@ pub use self::rules_iterator::{AllRules, EffectiveRules}; pub use self::rules_iterator::{NestedRuleIterationCondition, RulesIterator}; pub use self::style_rule::StyleRule; pub use self::stylesheet::{DocumentStyleSheet, Namespaces, Stylesheet}; +pub use self::stylesheet::{SanitizationData, SanitizationKind}; pub use self::stylesheet::{StylesheetContents, StylesheetInDocument, UserAgentStylesheets}; pub use self::supports_rule::SupportsRule; pub use self::viewport_rule::ViewportRule; diff --git a/components/style/stylesheets/namespace_rule.rs b/components/style/stylesheets/namespace_rule.rs index 81a92f1c300..d76703e4f81 100644 --- a/components/style/stylesheets/namespace_rule.rs +++ b/components/style/stylesheets/namespace_rule.rs @@ -7,8 +7,9 @@ use crate::shared_lock::{SharedRwLockReadGuard, ToCssWithGuard}; use crate::str::CssStringWriter; use crate::{Namespace, Prefix}; -use cssparser::SourceLocation; +use cssparser::{self, SourceLocation}; use std::fmt::{self, Write}; +use style_traits::{CssWriter, ToCss}; /// A `@namespace` rule. #[derive(Clone, Debug, PartialEq, ToShmem)] @@ -27,13 +28,12 @@ impl ToCssWithGuard for NamespaceRule { fn to_css(&self, _guard: &SharedRwLockReadGuard, dest: &mut CssStringWriter) -> fmt::Result { dest.write_str("@namespace ")?; if let Some(ref prefix) = self.prefix { - dest.write_str(&*prefix.to_string())?; + let prefix = prefix.to_string(); + cssparser::serialize_identifier(&prefix, dest)?; dest.write_str(" ")?; } - - // FIXME(emilio): Pretty sure this needs some escaping, or something? - dest.write_str("url(\"")?; - dest.write_str(&*self.url.to_string())?; - dest.write_str("\");") + dest.write_str("url(")?; + self.url.to_string().to_css(&mut CssWriter::new(dest))?; + dest.write_str(");") } } diff --git a/components/style/stylesheets/stylesheet.rs b/components/style/stylesheets/stylesheet.rs index f5194d7d443..068bfb6502a 100644 --- a/components/style/stylesheets/stylesheet.rs +++ b/components/style/stylesheets/stylesheet.rs @@ -81,6 +81,7 @@ impl StylesheetContents { quirks_mode: QuirksMode, line_number_offset: u32, use_counters: Option<&UseCounters>, + sanitization_data: Option<&mut SanitizationData>, ) -> Self { let namespaces = RwLock::new(Namespaces::default()); let (rules, source_map_url, source_url) = Stylesheet::parse_rules( @@ -94,6 +95,7 @@ impl StylesheetContents { quirks_mode, line_number_offset, use_counters, + sanitization_data, ); Self { @@ -341,6 +343,69 @@ impl StylesheetInDocument for DocumentStyleSheet { } } +/// The kind of sanitization to use when parsing a stylesheet. +#[repr(u8)] +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum SanitizationKind { + /// Perform no sanitization. + None, + /// Allow only @font-face, style rules, and @namespace. + Standard, + /// Allow everything but conditional rules. + NoConditionalRules, +} + +impl SanitizationKind { + fn allows(self, rule: &CssRule) -> bool { + debug_assert_ne!(self, SanitizationKind::None); + // NOTE(emilio): If this becomes more complex (not filtering just by + // top-level rules), we should thread all the data through nested rules + // and such. But this doesn't seem necessary at the moment. + let is_standard = matches!(self, SanitizationKind::Standard); + match *rule { + CssRule::Document(..) | + CssRule::Media(..) | + CssRule::Supports(..) | + CssRule::Import(..) => false, + + CssRule::FontFace(..) | CssRule::Namespace(..) | CssRule::Style(..) => true, + + CssRule::Keyframes(..) | + CssRule::Page(..) | + CssRule::FontFeatureValues(..) | + CssRule::Viewport(..) | + CssRule::CounterStyle(..) => !is_standard, + } + } +} + +/// A struct to hold the data relevant to style sheet sanitization. +#[derive(Debug)] +pub struct SanitizationData { + kind: SanitizationKind, + output: String, +} + +impl SanitizationData { + /// Create a new input for sanitization. + #[inline] + pub fn new(kind: SanitizationKind) -> Option<Self> { + if matches!(kind, SanitizationKind::None) { + return None; + } + Some(Self { + kind, + output: String::new(), + }) + } + + /// Take the sanitized output. + #[inline] + pub fn take(self) -> String { + self.output + } +} + impl Stylesheet { /// Updates an empty stylesheet from a given string of text. pub fn update_from_str( @@ -365,6 +430,7 @@ impl Stylesheet { existing.contents.quirks_mode, line_number_offset, /* use_counters = */ None, + /* sanitization_data = */ None, ); *existing.contents.url_data.write() = url_data; @@ -391,6 +457,7 @@ impl Stylesheet { quirks_mode: QuirksMode, line_number_offset: u32, use_counters: Option<&UseCounters>, + mut sanitization_data: Option<&mut SanitizationData>, ) -> (Vec<CssRule>, Option<String>, Option<String>) { let mut rules = Vec::new(); let mut input = ParserInput::new_with_line_number_offset(css, line_number_offset); @@ -419,12 +486,24 @@ impl Stylesheet { { let mut iter = RuleListParser::new_for_stylesheet(&mut input, rule_parser); - while let Some(result) = iter.next() { + loop { + let rule_start = iter.input.position().byte_index(); + let result = match iter.next() { + Some(result) => result, + None => break, + }; match result { Ok(rule) => { - // Use a fallible push here, and if it fails, just - // fall out of the loop. This will cause the page to - // be shown incorrectly, but it's better than OOMing. + if let Some(ref mut data) = sanitization_data { + if !data.kind.allows(&rule) { + continue; + } + let end = iter.input.position().byte_index(); + data.output.push_str(&css[rule_start..end]); + } + // Use a fallible push here, and if it fails, just fall + // out of the loop. This will cause the page to be + // shown incorrectly, but it's better than OOMing. if rules.try_push(rule).is_err() { break; } @@ -470,6 +549,7 @@ impl Stylesheet { quirks_mode, line_number_offset, /* use_counters = */ None, + /* sanitized_output = */ None, ); Stylesheet { diff --git a/components/style/stylist.rs b/components/style/stylist.rs index 83db2ec4b17..9de1ec4e71b 100644 --- a/components/style/stylist.rs +++ b/components/style/stylist.rs @@ -1013,7 +1013,7 @@ impl Stylist { ); if !declarations.is_empty() { let rule_node = self.rule_tree.insert_ordered_rules_with_important( - declarations.drain().map(|a| a.for_rule_tree()), + declarations.drain(..).map(|a| a.for_rule_tree()), guards, ); if rule_node != *self.rule_tree.root() { @@ -1889,18 +1889,33 @@ impl CascadeData { self.host_rules.as_ref().and_then(|d| d.rules(pseudo)) } + /// Whether there's any host rule that could match in this scope. + pub fn any_host_rules(&self) -> bool { + self.host_rules.is_some() + } + /// Returns the slotted rule map for a given pseudo-element. #[inline] pub fn slotted_rules(&self, pseudo: Option<&PseudoElement>) -> Option<&SelectorMap<Rule>> { self.slotted_rules.as_ref().and_then(|d| d.rules(pseudo)) } + /// Whether there's any ::slotted rule that could match in this scope. + pub fn any_slotted_rule(&self) -> bool { + self.slotted_rules.is_some() + } + /// Returns the parts rule map for a given pseudo-element. #[inline] pub fn part_rules(&self, pseudo: Option<&PseudoElement>) -> Option<&PartMap> { self.part_rules.as_ref().and_then(|d| d.rules(pseudo)) } + /// Whether there's any ::part rule that could match in this scope. + pub fn any_part_rule(&self) -> bool { + self.part_rules.is_some() + } + /// Collects all the applicable media query results into `results`. /// /// This duplicates part of the logic in `add_stylesheet`, which is diff --git a/components/style/values/animated/transform.rs b/components/style/values/animated/transform.rs index aceb70f6766..3d93ae93f6d 100644 --- a/components/style/values/animated/transform.rs +++ b/components/style/values/animated/transform.rs @@ -1373,7 +1373,7 @@ impl ComputedTranslate { LengthPercentage::zero(), Length::zero(), ), - Translate::Translate(tx, ty, tz) => (tx, ty, tz), + Translate::Translate(ref tx, ref ty, ref tz) => (tx.clone(), ty.clone(), tz.clone()), } } } diff --git a/components/style/values/computed/font.rs b/components/style/values/computed/font.rs index a4fa6013277..658d3412475 100644 --- a/components/style/values/computed/font.rs +++ b/components/style/values/computed/font.rs @@ -21,7 +21,6 @@ use crate::values::specified::font::{ use crate::values::specified::length::{FontBaseSize, NoCalcLength}; use crate::values::CSSFloat; use crate::Atom; -use app_units::Au; use byteorder::{BigEndian, ByteOrder}; use cssparser::{serialize_identifier, CssStringWriter, Parser}; #[cfg(feature = "gecko")] @@ -148,15 +147,16 @@ impl FontWeight { impl FontSize { /// The actual computed font size. - pub fn size(self) -> Au { - self.size.into() + #[inline] + pub fn size(&self) -> Length { + self.size.0 } #[inline] /// Get default value of font size. pub fn medium() -> Self { Self { - size: Au::from_px(specified::FONT_MEDIUM_PX).into(), + size: NonNegative(Length::new(specified::FONT_MEDIUM_PX as CSSFloat)), keyword_info: Some(KeywordInfo::medium()), } } diff --git a/components/style/values/computed/length.rs b/components/style/values/computed/length.rs index 2423d447a6a..c9248f97c95 100644 --- a/components/style/values/computed/length.rs +++ b/components/style/values/computed/length.rs @@ -29,7 +29,7 @@ pub use crate::values::specified::url::UrlOrNone; pub use crate::values::specified::{Angle, BorderStyle, Time}; impl ToComputedValue for specified::NoCalcLength { - type ComputedValue = CSSPixelLength; + type ComputedValue = Length; #[inline] fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { @@ -75,9 +75,7 @@ impl ToComputedValue for specified::Length { /// /// https://drafts.csswg.org/css-values-4/#typedef-length-percentage #[allow(missing_docs)] -#[derive( - Clone, Copy, Debug, Deserialize, MallocSizeOf, Serialize, ToAnimatedZero, ToResolvedValue, -)] +#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize, ToAnimatedZero, ToResolvedValue)] #[repr(C)] pub struct LengthPercentage { length: Length, @@ -543,14 +541,14 @@ impl ToAnimatedValue for NonNegativeLengthPercentage { impl From<NonNegativeLength> for NonNegativeLengthPercentage { #[inline] fn from(length: NonNegativeLength) -> Self { - LengthPercentage::new(length.0, None).into() + NonNegative(LengthPercentage::new(length.0, None)) } } impl From<LengthPercentage> for NonNegativeLengthPercentage { #[inline] fn from(lp: LengthPercentage) -> Self { - NonNegative::<LengthPercentage>(lp) + NonNegative(lp) } } diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 6e6f20ad0fe..f5b3440f426 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -75,6 +75,7 @@ pub use self::resolution::Resolution; pub use self::svg::MozContextProperties; pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind}; pub use self::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth}; +pub use self::text::TextUnderlinePosition; pub use self::text::{InitialLetter, LetterSpacing, LineBreak, LineHeight}; pub use self::text::{OverflowWrap, TextOverflow, WordBreak, WordSpacing}; pub use self::text::{TextAlign, TextEmphasisPosition, TextEmphasisStyle}; diff --git a/components/style/values/computed/text.rs b/components/style/values/computed/text.rs index 4cccd248d1c..3f9ffb2ad0f 100644 --- a/components/style/values/computed/text.rs +++ b/components/style/values/computed/text.rs @@ -19,6 +19,7 @@ use std::fmt::{self, Write}; use style_traits::{CssWriter, ToCss}; pub use crate::values::specified::TextAlignKeyword as TextAlign; +pub use crate::values::specified::TextUnderlinePosition; pub use crate::values::specified::{LineBreak, OverflowWrap, WordBreak}; pub use crate::values::specified::{TextDecorationLine, TextEmphasisPosition}; pub use crate::values::specified::{TextDecorationSkipInk, TextTransform}; diff --git a/components/style/values/generics/length.rs b/components/style/values/generics/length.rs index b2f34058283..4183f40a942 100644 --- a/components/style/values/generics/length.rs +++ b/components/style/values/generics/length.rs @@ -207,15 +207,6 @@ impl<LengthPercentage> MaxSize<LengthPercentage> { pub fn none() -> Self { MaxSize::None } - - /// Convert - #[cfg(not(feature = "gecko"))] - pub fn to_option(self) -> Option<LengthPercentage> { - match self { - Self::LengthPercentage(lp) => Some(lp), - Self::None => None, - } - } } /// A generic `<length>` | `<number>` value for the `-moz-tab-size` property. diff --git a/components/style/values/specified/align.rs b/components/style/values/specified/align.rs index 7c2ecda19a4..0dc1e422515 100644 --- a/components/style/values/specified/align.rs +++ b/components/style/values/specified/align.rs @@ -691,11 +691,11 @@ fn parse_baseline<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, Pars "first" => { input.expect_ident_matching("baseline")?; Ok(AlignFlags::BASELINE) - } + }, "last" => { input.expect_ident_matching("baseline")?; Ok(AlignFlags::LAST_BASELINE) - } + }, } } @@ -794,7 +794,7 @@ fn parse_legacy<'i, 't>(input: &mut Parser<'i, 't>) -> Result<AlignFlags, ParseE .unwrap_or(AlignFlags::empty()); return Ok(AlignFlags::LEGACY | flags) - } + }, "left" => AlignFlags::LEFT, "right" => AlignFlags::RIGHT, "center" => AlignFlags::CENTER, diff --git a/components/style/values/specified/box.rs b/components/style/values/specified/box.rs index 1fea857d3e8..ad8602ac431 100644 --- a/components/style/values/specified/box.rs +++ b/components/style/values/specified/box.rs @@ -389,21 +389,10 @@ impl Display { }; Display::from3(DisplayOutside::Block, inside, self.is_list_item()) }, - // If this pref is true, then we'll blockify "-moz-inline-box" to - // "-moz-box", and blockify "-moz-box" to itself. Otherwise, we - // blockify both to "block". #[cfg(feature = "gecko")] - DisplayOutside::XUL => { - if static_prefs::pref!( - "layout.css.xul-box-display-values.survive-blockification.enabled" - ) { - match self.inside() { - DisplayInside::MozInlineBox | DisplayInside::MozBox => Display::MozBox, - _ => Display::Block, - } - } else { - Display::Block - } + DisplayOutside::XUL => match self.inside() { + DisplayInside::MozInlineBox | DisplayInside::MozBox => Display::MozBox, + _ => Display::Block, }, DisplayOutside::Block | DisplayOutside::None => *self, #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))] diff --git a/components/style/values/specified/font.rs b/components/style/values/specified/font.rs index c09d5a2c34c..05a29c94087 100644 --- a/components/style/values/specified/font.rs +++ b/components/style/values/specified/font.rs @@ -20,7 +20,6 @@ use crate::values::specified::{AllowQuirks, Angle, Integer, LengthPercentage}; use crate::values::specified::{NoCalcLength, NonNegativeNumber, Number, Percentage}; use crate::values::CustomIdent; use crate::Atom; -use app_units::Au; use byteorder::{BigEndian, ByteOrder}; use cssparser::{Parser, Token}; #[cfg(feature = "gecko")] @@ -773,18 +772,18 @@ impl ToComputedValue for KeywordSize { type ComputedValue = NonNegativeLength; #[inline] fn to_computed_value(&self, _: &Context) -> NonNegativeLength { + let medium = Length::new(FONT_MEDIUM_PX as f32); // https://drafts.csswg.org/css-fonts-3/#font-size-prop - match *self { - KeywordSize::XXSmall => Au::from_px(FONT_MEDIUM_PX) * 3 / 5, - KeywordSize::XSmall => Au::from_px(FONT_MEDIUM_PX) * 3 / 4, - KeywordSize::Small => Au::from_px(FONT_MEDIUM_PX) * 8 / 9, - KeywordSize::Medium => Au::from_px(FONT_MEDIUM_PX), - KeywordSize::Large => Au::from_px(FONT_MEDIUM_PX) * 6 / 5, - KeywordSize::XLarge => Au::from_px(FONT_MEDIUM_PX) * 3 / 2, - KeywordSize::XXLarge => Au::from_px(FONT_MEDIUM_PX) * 2, - KeywordSize::XXXLarge => Au::from_px(FONT_MEDIUM_PX) * 3, - } - .into() + NonNegative(match *self { + KeywordSize::XXSmall => medium * 3.0 / 5.0, + KeywordSize::XSmall => medium * 3.0 / 4.0, + KeywordSize::Small => medium * 8.0 / 9.0, + KeywordSize::Medium => medium, + KeywordSize::Large => medium * 6.0 / 5.0, + KeywordSize::XLarge => medium * 3.0 / 2.0, + KeywordSize::XXLarge => medium * 2.0, + KeywordSize::XXXLarge => medium * 3.0, + }) } #[inline] @@ -799,7 +798,6 @@ impl ToComputedValue for KeywordSize { #[inline] fn to_computed_value(&self, cx: &Context) -> NonNegativeLength { use crate::context::QuirksMode; - use crate::values::specified::length::au_to_int_px; // The tables in this function are originally from // nsRuleNode::CalcFontPointSize in Gecko: @@ -850,22 +848,21 @@ impl ToComputedValue for KeywordSize { Atom::with(gecko_font.mLanguage.mRawPtr, |atom| { cx.font_metrics_provider .get_size(atom, gecko_font.mGenericID) - .0 }) }; - let base_size_px = au_to_int_px(base_size as f32); + let base_size_px = base_size.px().round() as i32; let html_size = self.html_size() as usize; - if base_size_px >= 9 && base_size_px <= 16 { + NonNegative(if base_size_px >= 9 && base_size_px <= 16 { let mapping = if cx.quirks_mode == QuirksMode::Quirks { QUIRKS_FONT_SIZE_MAPPING } else { FONT_SIZE_MAPPING }; - Au::from_px(mapping[(base_size_px - 9) as usize][html_size]).into() + Length::new(mapping[(base_size_px - 9) as usize][html_size] as f32) } else { - Au(FONT_SIZE_FACTORS[html_size] * base_size / 100).into() - } + base_size * FONT_SIZE_FACTORS[html_size] as f32 / 100.0 + }) } #[inline] @@ -927,7 +924,7 @@ impl FontSize { // If the parent font was keyword-derived, this is too. // Tack the % onto the factor info = compose_keyword(pc.0); - base_size.resolve(context).scale_by(pc.0).into() + base_size.resolve(context) * pc.0 }, FontSize::Length(LengthPercentage::Calc(ref calc)) => { let parent = context.style().get_parent_font().clone_font_size(); @@ -964,7 +961,7 @@ impl FontSize { // others should reject negatives during parsing. But SMIL // allows parsing negatives, and relies on us _not_ doing that // clamping. That's so bonkers :( - CSSPixelLength::from(calc.to_used_value(base_size.resolve(context))) + calc.percentage_relative_to(base_size.resolve(context)) .clamp_to_non_negative() }, FontSize::Keyword(i) => { diff --git a/components/style/values/specified/gecko.rs b/components/style/values/specified/gecko.rs index 131c2a1a314..4c85d1df668 100644 --- a/components/style/values/specified/gecko.rs +++ b/components/style/values/specified/gecko.rs @@ -5,8 +5,7 @@ //! Specified types for legacy Gecko-only properties. use crate::parser::{Parse, ParserContext}; -use crate::values::computed::length::CSSPixelLength; -use crate::values::computed::{self, LengthPercentage}; +use crate::values::computed::{self, Length, LengthPercentage}; use crate::values::generics::rect::Rect; use cssparser::{Parser, Token}; use std::fmt; @@ -24,7 +23,7 @@ fn parse_pixel_or_percent<'i, 't>( value, ref unit, .. } => { match_ignore_ascii_case! { unit, - "px" => Ok(LengthPercentage::new(CSSPixelLength::new(value), None)), + "px" => Ok(LengthPercentage::new(Length::new(value), None)), _ => Err(()), } }, diff --git a/components/style/values/specified/length.rs b/components/style/values/specified/length.rs index ebf7746ee11..d9a51665ead 100644 --- a/components/style/values/specified/length.rs +++ b/components/style/values/specified/length.rs @@ -47,14 +47,6 @@ pub const AU_PER_PT: CSSFloat = AU_PER_IN / 72.; /// Number of app units per pica pub const AU_PER_PC: CSSFloat = AU_PER_PT * 12.; -/// Same as Gecko's AppUnitsToIntCSSPixels -/// -/// Converts app units to integer pixel values, -/// rounding during the conversion -pub fn au_to_int_px(au: f32) -> i32 { - (au / AU_PER_PX).round() as i32 -} - /// A font relative length. #[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss, ToShmem)] pub enum FontRelativeLength { @@ -87,7 +79,7 @@ pub enum FontBaseSize { impl FontBaseSize { /// Calculate the actual size for a given context - pub fn resolve(&self, context: &Context) -> Au { + pub fn resolve(&self, context: &Context) -> computed::Length { match *self { FontBaseSize::CurrentStyle => context.style().get_font().clone_font_size().size(), FontBaseSize::InheritedStyleButStripEmUnits | FontBaseSize::InheritedStyle => { @@ -109,13 +101,13 @@ impl FontRelativeLength { } /// Computes the font-relative length. - pub fn to_computed_value(&self, context: &Context, base_size: FontBaseSize) -> CSSPixelLength { - use std::f32; + pub fn to_computed_value( + &self, + context: &Context, + base_size: FontBaseSize, + ) -> computed::Length { let (reference_size, length) = self.reference_font_size_and_length(context, base_size); - let pixel = (length * reference_size.to_f32_px()) - .min(f32::MAX) - .max(f32::MIN); - CSSPixelLength::new(pixel) + reference_size * length } /// Return reference font size. @@ -129,7 +121,7 @@ impl FontRelativeLength { &self, context: &Context, base_size: FontBaseSize, - ) -> (Au, CSSFloat) { + ) -> (computed::Length, CSSFloat) { fn query_font_metrics( context: &Context, base_size: FontBaseSize, @@ -153,7 +145,7 @@ impl FontRelativeLength { } if base_size == FontBaseSize::InheritedStyleButStripEmUnits { - (Au(0), length) + (Zero::zero(), length) } else { (reference_font_size, length) } @@ -175,7 +167,7 @@ impl FontRelativeLength { // determine the x-height, a value of 0.5em must be // assumed. // - reference_font_size.scale_by(0.5) + reference_font_size * 0.5 }); (reference_size, length) }, @@ -210,7 +202,7 @@ impl FontRelativeLength { if wm.is_vertical() && wm.is_upright() { reference_font_size } else { - reference_font_size.scale_by(0.5) + reference_font_size * 0.5 } }); (reference_size, length) @@ -225,7 +217,7 @@ impl FontRelativeLength { let reference_size = if context.is_root_element || context.in_media_query { reference_font_size } else { - context.device().root_font_size() + computed::Length::new(context.device().root_font_size().to_f32_px()) }; (reference_size, length) }, @@ -290,15 +282,14 @@ pub struct CharacterWidth(pub i32); impl CharacterWidth { /// Computes the given character width. - pub fn to_computed_value(&self, reference_font_size: Au) -> CSSPixelLength { - // This applies the *converting a character width to pixels* algorithm as specified - // in HTML5 § 14.5.4. + pub fn to_computed_value(&self, reference_font_size: computed::Length) -> computed::Length { + // This applies the *converting a character width to pixels* algorithm + // as specified in HTML5 § 14.5.4. // // TODO(pcwalton): Find these from the font. - let average_advance = reference_font_size.scale_by(0.5); + let average_advance = reference_font_size * 0.5; let max_advance = reference_font_size; - let au = average_advance.scale_by(self.0 as CSSFloat - 1.0) + max_advance; - au.into() + average_advance * (self.0 as CSSFloat - 1.0) + max_advance } } diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index bc7a8203dee..7f3ecfb96b3 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -80,6 +80,7 @@ pub use self::svg::MozContextProperties; pub use self::svg::{SVGLength, SVGOpacity, SVGPaint}; pub use self::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth}; pub use self::svg_path::SVGPathData; +pub use self::text::TextUnderlinePosition; pub use self::text::{InitialLetter, LetterSpacing, LineBreak, LineHeight, TextAlign}; pub use self::text::{OverflowWrap, TextEmphasisPosition, TextEmphasisStyle, WordBreak}; pub use self::text::{TextAlignKeyword, TextDecorationLine, TextOverflow, WordSpacing}; diff --git a/components/style/values/specified/text.rs b/components/style/values/specified/text.rs index cc4bcee1a55..8c50a61ef94 100644 --- a/components/style/values/specified/text.rs +++ b/components/style/values/specified/text.rs @@ -77,7 +77,6 @@ impl ToComputedValue for LineHeight { #[inline] fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { - use crate::values::computed::Length as ComputedLength; use crate::values::specified::length::FontBaseSize; match *self { GenericLineHeight::Normal => GenericLineHeight::Normal, @@ -97,16 +96,8 @@ impl ToComputedValue for LineHeight { LengthPercentage::Calc(ref calc) => { let computed_calc = calc.to_computed_value_zoomed(context, FontBaseSize::CurrentStyle); - let font_relative_length = - FontRelativeLength::Em(computed_calc.percentage()) - .to_computed_value(context, FontBaseSize::CurrentStyle) - .px(); - - let absolute_length = computed_calc.unclamped_length().px(); - let pixel = computed_calc - .clamping_mode - .clamp(absolute_length + font_relative_length); - ComputedLength::new(pixel) + let base = context.style().get_font().clone_font_size().size(); + computed_calc.percentage_relative_to(base) }, }; GenericLineHeight::Length(result.into()) @@ -1054,3 +1045,98 @@ impl TextDecorationLength { matches!(*self, GenericTextDecorationLength::Auto) } } + +bitflags! { + #[derive(MallocSizeOf, SpecifiedValueInfo, ToComputedValue, ToResolvedValue, ToShmem)] + #[value_info(other_values = "auto,under,left,right")] + #[repr(C)] + /// Specified keyword values for the text-underline-position property. + /// (Non-exclusive, but not all combinations are allowed: only `under` may occur + /// together with either `left` or `right`.) + /// https://drafts.csswg.org/css-text-decor-3/#text-underline-position-property + pub struct TextUnderlinePosition: u8 { + /// Use automatic positioning below the alphabetic baseline. + const AUTO = 0; + /// Below the glyph box. + const UNDER = 1 << 0; + /// In vertical mode, place to the left of the text. + const LEFT = 1 << 1; + /// In vertical mode, place to the right of the text. + const RIGHT = 1 << 2; + } +} + +impl Parse for TextUnderlinePosition { + fn parse<'i, 't>( + _context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result<TextUnderlinePosition, ParseError<'i>> { + let mut result = TextUnderlinePosition::empty(); + + loop { + let location = input.current_source_location(); + let ident = match input.next() { + Ok(&Token::Ident(ref ident)) => ident, + Ok(other) => return Err(location.new_unexpected_token_error(other.clone())), + Err(..) => break, + }; + + match_ignore_ascii_case! { ident, + "auto" if result.is_empty() => { + return Ok(result); + }, + "under" if !result.intersects(TextUnderlinePosition::UNDER) => { + result.insert(TextUnderlinePosition::UNDER); + }, + "left" if !result.intersects(TextUnderlinePosition::LEFT | + TextUnderlinePosition::RIGHT) => { + result.insert(TextUnderlinePosition::LEFT); + }, + "right" if !result.intersects(TextUnderlinePosition::LEFT | + TextUnderlinePosition::RIGHT) => { + result.insert(TextUnderlinePosition::RIGHT); + }, + _ => return Err(location.new_custom_error( + SelectorParseErrorKind::UnexpectedIdent(ident.clone()) + )), + } + } + + if !result.is_empty() { + Ok(result) + } else { + Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)) + } + } +} + +impl ToCss for TextUnderlinePosition { + fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result + where + W: Write, + { + if self.is_empty() { + return dest.write_str("auto"); + } + + let mut writer = SequenceWriter::new(dest, " "); + let mut any = false; + + macro_rules! maybe_write { + ($ident:ident => $str:expr) => { + if self.contains(TextUnderlinePosition::$ident) { + any = true; + writer.raw_item($str)?; + } + }; + } + + maybe_write!(UNDER => "under"); + maybe_write!(LEFT => "left"); + maybe_write!(RIGHT => "right"); + + debug_assert!(any); + + Ok(()) + } +} diff --git a/components/to_shmem/Cargo.toml b/components/to_shmem/Cargo.toml index dd3614111e1..76be7671da3 100644 --- a/components/to_shmem/Cargo.toml +++ b/components/to_shmem/Cargo.toml @@ -17,6 +17,6 @@ gecko = [] cssparser = "0.27" servo_arc = { path = "../servo_arc" } smallbitvec = "2.1.1" -smallvec = "0.6.6" +smallvec = "1.0" string_cache = { version = "0.8", optional = true } thin-slice = "0.1.0" diff --git a/servo-tidy.toml b/servo-tidy.toml index c35e180c260..b0d2477edad 100644 --- a/servo-tidy.toml +++ b/servo-tidy.toml @@ -35,6 +35,12 @@ packages = [ # https://github.com/servo/servo/pull/23288#issuecomment-494687746 "gl_generator", + # Just needs a WR update. + "derive_more", + + # Lots of crates to update. + "smallvec", + # https://github.com/servo/servo/issues/24421 "proc-macro2", "quote", diff --git a/tests/wpt/metadata/css/cssom/border-shorthand-serialization.html.ini b/tests/wpt/metadata/css/cssom/border-shorthand-serialization.html.ini deleted file mode 100644 index 5e4163cc85d..00000000000 --- a/tests/wpt/metadata/css/cssom/border-shorthand-serialization.html.ini +++ /dev/null @@ -1,4 +0,0 @@ -[border-shorthand-serialization.html] - [Declaration with border longhands and border-image is not serialized to a border shorthand declaration.] - expected: FAIL - |