diff options
Diffstat (limited to 'components/layout')
-rw-r--r-- | components/layout/construct_modern.rs | 1 | ||||
-rw-r--r-- | components/layout/display_list/conversions.rs | 8 | ||||
-rw-r--r-- | components/layout/display_list/mod.rs | 130 | ||||
-rw-r--r-- | components/layout/display_list/stacking_context.rs | 76 | ||||
-rw-r--r-- | components/layout/flexbox/layout.rs | 30 | ||||
-rw-r--r-- | components/layout/flexbox/mod.rs | 3 | ||||
-rw-r--r-- | components/layout/flow/construct.rs | 31 | ||||
-rw-r--r-- | components/layout/flow/float.rs | 3 | ||||
-rw-r--r-- | components/layout/flow/inline/construct.rs | 5 | ||||
-rw-r--r-- | components/layout/flow/inline/inline_box.rs | 8 | ||||
-rw-r--r-- | components/layout/flow/inline/line.rs | 3 | ||||
-rw-r--r-- | components/layout/flow/inline/mod.rs | 19 | ||||
-rw-r--r-- | components/layout/flow/root.rs | 2 | ||||
-rw-r--r-- | components/layout/fragment_tree/fragment.rs | 4 | ||||
-rw-r--r-- | components/layout/layout_impl.rs | 2 | ||||
-rw-r--r-- | components/layout/lib.rs | 20 | ||||
-rw-r--r-- | components/layout/table/construct.rs | 13 | ||||
-rw-r--r-- | components/layout/taffy/mod.rs | 3 | ||||
-rw-r--r-- | components/layout/traversal.rs | 12 |
19 files changed, 210 insertions, 163 deletions
diff --git a/components/layout/construct_modern.rs b/components/layout/construct_modern.rs index 8f1282ec9f6..d09744b2031 100644 --- a/components/layout/construct_modern.rs +++ b/components/layout/construct_modern.rs @@ -150,7 +150,6 @@ impl<'a, 'dom> ModernContainerBuilder<'a, 'dom> { let inline_formatting_context = inline_formatting_context_builder.finish( self.context, - self.propagated_data, true, /* has_first_formatted_line */ false, /* is_single_line_text_box */ self.info.style.writing_mode.to_bidi_level(), diff --git a/components/layout/display_list/conversions.rs b/components/layout/display_list/conversions.rs index 6d78a17e886..a2517c863f1 100644 --- a/components/layout/display_list/conversions.rs +++ b/components/layout/display_list/conversions.rs @@ -125,11 +125,15 @@ impl ToWebRender for ComputedTextDecorationStyle { type Type = LineStyle; fn to_webrender(&self) -> Self::Type { match *self { - ComputedTextDecorationStyle::Solid => LineStyle::Solid, + ComputedTextDecorationStyle::Solid | ComputedTextDecorationStyle::Double => { + LineStyle::Solid + }, ComputedTextDecorationStyle::Dotted => LineStyle::Dotted, ComputedTextDecorationStyle::Dashed => LineStyle::Dashed, ComputedTextDecorationStyle::Wavy => LineStyle::Wavy, - _ => LineStyle::Solid, + ComputedTextDecorationStyle::MozNone => { + unreachable!("Should never try to draw a moz-none text decoration") + }, } } } diff --git a/components/layout/display_list/mod.rs b/components/layout/display_list/mod.rs index 95689cf1186..3716ff35b2c 100644 --- a/components/layout/display_list/mod.rs +++ b/components/layout/display_list/mod.rs @@ -11,7 +11,7 @@ use base::id::ScrollTreeNodeId; use clip::{Clip, ClipId}; use compositing_traits::display_list::{CompositorDisplayListInfo, SpatialTreeNodeInfo}; use embedder_traits::Cursor; -use euclid::{Point2D, SideOffsets2D, Size2D, UnknownUnit}; +use euclid::{Point2D, SideOffsets2D, Size2D, UnknownUnit, Vector2D}; use fonts::GlyphStore; use gradient::WebRenderGradient; use range::Range as ServoRange; @@ -21,7 +21,9 @@ use servo_geometry::MaxRect; use style::Zero; use style::color::{AbsoluteColor, ColorSpace}; use style::computed_values::border_image_outset::T as BorderImageOutset; -use style::computed_values::text_decoration_style::T as ComputedTextDecorationStyle; +use style::computed_values::text_decoration_style::{ + T as ComputedTextDecorationStyle, T as TextDecorationStyle, +}; use style::dom::OpaqueNode; use style::properties::ComputedValues; use style::properties::longhands::visibility::computed_value::T as Visibility; @@ -572,6 +574,7 @@ impl Fragment { section: StackingContextSection, is_hit_test_for_scrollable_overflow: bool, is_collapsed_table_borders: bool, + text_decorations: &Arc<Vec<FragmentTextDecoration>>, ) { let spatial_id = builder.spatial_id(builder.current_scroll_node_id); let clip_chain_id = builder.clip_chain_id(builder.current_clip_id); @@ -683,9 +686,12 @@ impl Fragment { .get_inherited_box() .visibility { - Visibility::Visible => { - self.build_display_list_for_text_fragment(text, builder, containing_block) - }, + Visibility::Visible => self.build_display_list_for_text_fragment( + text, + builder, + containing_block, + text_decorations, + ), Visibility::Hidden => (), Visibility::Collapse => (), } @@ -723,6 +729,7 @@ impl Fragment { fragment: &TextFragment, builder: &mut DisplayListBuilder, containing_block: &PhysicalRect<Au>, + text_decorations: &Arc<Vec<FragmentTextDecoration>>, ) { // NB: The order of painting text components (CSS Text Decoration Module Level 3) is: // shadows, underline, overline, text, text-emphasis, and then line-through. @@ -732,6 +739,7 @@ impl Fragment { let rect = fragment.rect.translate(containing_block.origin.to_vector()); let mut baseline_origin = rect.origin; baseline_origin.y += fragment.font_metrics.ascent; + let glyphs = glyphs( &fragment.glyphs, baseline_origin, @@ -774,23 +782,36 @@ impl Fragment { ); } - if fragment - .text_decoration_line - .contains(TextDecorationLine::UNDERLINE) - { - let mut rect = rect; - rect.origin.y += font_metrics.ascent - font_metrics.underline_offset; - rect.size.height = Au::from_f32_px(font_metrics.underline_size.to_nearest_pixel(dppx)); - self.build_display_list_for_text_decoration(&parent_style, builder, &rect, &color); + for text_decoration in text_decorations.iter() { + if text_decoration.line.contains(TextDecorationLine::UNDERLINE) { + let mut rect = rect; + rect.origin.y += font_metrics.ascent - font_metrics.underline_offset; + rect.size.height = + Au::from_f32_px(font_metrics.underline_size.to_nearest_pixel(dppx)); + + self.build_display_list_for_text_decoration( + &parent_style, + builder, + &rect, + text_decoration, + TextDecorationLine::UNDERLINE, + ); + } } - if fragment - .text_decoration_line - .contains(TextDecorationLine::OVERLINE) - { - let mut rect = rect; - rect.size.height = Au::from_f32_px(font_metrics.underline_size.to_nearest_pixel(dppx)); - self.build_display_list_for_text_decoration(&parent_style, builder, &rect, &color); + for text_decoration in text_decorations.iter() { + if text_decoration.line.contains(TextDecorationLine::OVERLINE) { + let mut rect = rect; + rect.size.height = + Au::from_f32_px(font_metrics.underline_size.to_nearest_pixel(dppx)); + self.build_display_list_for_text_decoration( + &parent_style, + builder, + &rect, + text_decoration, + TextDecorationLine::OVERLINE, + ); + } } // TODO: This caret/text selection implementation currently does not account for vertical text @@ -867,14 +888,23 @@ impl Fragment { None, ); - if fragment - .text_decoration_line - .contains(TextDecorationLine::LINE_THROUGH) - { - let mut rect = rect; - rect.origin.y += font_metrics.ascent - font_metrics.strikeout_offset; - rect.size.height = Au::from_f32_px(font_metrics.strikeout_size.to_nearest_pixel(dppx)); - self.build_display_list_for_text_decoration(&parent_style, builder, &rect, &color); + for text_decoration in text_decorations.iter() { + if text_decoration + .line + .contains(TextDecorationLine::LINE_THROUGH) + { + let mut rect = rect; + rect.origin.y += font_metrics.ascent - font_metrics.strikeout_offset; + rect.size.height = + Au::from_f32_px(font_metrics.strikeout_size.to_nearest_pixel(dppx)); + self.build_display_list_for_text_decoration( + &parent_style, + builder, + &rect, + text_decoration, + TextDecorationLine::LINE_THROUGH, + ); + } } if !shadows.0.is_empty() { @@ -887,27 +917,47 @@ impl Fragment { parent_style: &ServoArc<ComputedValues>, builder: &mut DisplayListBuilder, rect: &PhysicalRect<Au>, - color: &AbsoluteColor, + text_decoration: &FragmentTextDecoration, + line: TextDecorationLine, ) { - let rect = rect.to_webrender(); - let wavy_line_thickness = (0.33 * rect.size().height).ceil(); - let text_decoration_color = parent_style - .clone_text_decoration_color() - .resolve_to_absolute(color); - let text_decoration_style = parent_style.clone_text_decoration_style(); - if text_decoration_style == ComputedTextDecorationStyle::MozNone { + if text_decoration.style == ComputedTextDecorationStyle::MozNone { return; } + + let mut rect = rect.to_webrender(); + let line_thickness = rect.height().ceil(); + + if text_decoration.style == ComputedTextDecorationStyle::Wavy { + rect = rect.inflate(0.0, line_thickness * 1.0); + } + let common_properties = builder.common_properties(rect, parent_style); builder.wr().push_line( &common_properties, &rect, - wavy_line_thickness, + line_thickness, wr::LineOrientation::Horizontal, - &rgba(text_decoration_color), - text_decoration_style.to_webrender(), + &rgba(text_decoration.color), + text_decoration.style.to_webrender(), ); - // XXX(ferjm) support text-decoration-style: double + + if text_decoration.style == TextDecorationStyle::Double { + let half_height = (rect.height() / 2.0).floor().max(1.0); + let y_offset = match line { + TextDecorationLine::OVERLINE => -rect.height() - half_height, + _ => rect.height() + half_height, + }; + let rect = rect.translate(Vector2D::new(0.0, y_offset)); + let common_properties = builder.common_properties(rect, parent_style); + builder.wr().push_line( + &common_properties, + &rect, + line_thickness, + wr::LineOrientation::Horizontal, + &rgba(text_decoration.color), + text_decoration.style.to_webrender(), + ); + } } } diff --git a/components/layout/display_list/stacking_context.rs b/components/layout/display_list/stacking_context.rs index bcd882e3fcc..d22a2b6656a 100644 --- a/components/layout/display_list/stacking_context.rs +++ b/components/layout/display_list/stacking_context.rs @@ -5,6 +5,7 @@ use core::f32; use std::cell::RefCell; use std::mem; +use std::sync::Arc; use app_units::Au; use base::id::ScrollTreeNodeId; @@ -18,13 +19,15 @@ use euclid::default::{Point2D, Rect, Size2D}; use log::warn; use servo_config::opts::DebugOptions; use style::Zero; +use style::color::AbsoluteColor; use style::computed_values::float::T as ComputedFloat; use style::computed_values::mix_blend_mode::T as ComputedMixBlendMode; use style::computed_values::overflow_x::T as ComputedOverflow; use style::computed_values::position::T as ComputedPosition; +use style::computed_values::text_decoration_style::T as TextDecorationStyle; use style::values::computed::angle::Angle; use style::values::computed::basic_shape::ClipPath; -use style::values::computed::{ClipRectOrAuto, Length}; +use style::values::computed::{ClipRectOrAuto, Length, TextDecorationLine}; use style::values::generics::box_::Perspective; use style::values::generics::transform::{self, GenericRotate, GenericScale, GenericTranslate}; use style::values::specified::box_::DisplayOutside; @@ -168,12 +171,14 @@ impl StackingContextTree { }; let mut root_stacking_context = StackingContext::create_root(root_scroll_node_id, debug); + let text_decorations = Default::default(); for fragment in &fragment_tree.root_fragments { fragment.build_stacking_context_tree( &mut stacking_context_tree, &containing_block_info, &mut root_stacking_context, StackingContextBuildMode::SkipHoisted, + &text_decorations, ); } root_stacking_context.sort(); @@ -246,6 +251,14 @@ impl StackingContextTree { } } +/// The text decorations for a Fragment, collecting during [`StackingContextTree`] construction. +#[derive(Clone, Debug)] +pub(crate) struct FragmentTextDecoration { + pub line: TextDecorationLine, + pub color: AbsoluteColor, + pub style: TextDecorationStyle, +} + /// A piece of content that directly belongs to a section of a stacking context. /// /// This is generally part of a fragment, like its borders or foreground, but it @@ -261,6 +274,7 @@ pub(crate) enum StackingContextContent { fragment: Fragment, is_hit_test_for_scrollable_overflow: bool, is_collapsed_table_borders: bool, + text_decorations: Arc<Vec<FragmentTextDecoration>>, }, /// An index into [StackingContext::atomic_inline_stacking_containers]. @@ -292,6 +306,7 @@ impl StackingContextContent { fragment, is_hit_test_for_scrollable_overflow, is_collapsed_table_borders, + text_decorations, } => { builder.current_scroll_node_id = *scroll_node_id; builder.current_reference_frame_scroll_node_id = *reference_frame_scroll_node_id; @@ -302,6 +317,7 @@ impl StackingContextContent { *section, *is_hit_test_for_scrollable_overflow, *is_collapsed_table_borders, + text_decorations, ); }, Self::AtomicInlineStackingContainer { index } => { @@ -800,6 +816,7 @@ impl Fragment { containing_block_info: &ContainingBlockInfo, stacking_context: &mut StackingContext, mode: StackingContextBuildMode, + text_decorations: &Arc<Vec<FragmentTextDecoration>>, ) { let containing_block = containing_block_info.get_containing_block_for_fragment(self); let fragment_clone = self.clone(); @@ -812,6 +829,11 @@ impl Fragment { return; } + let text_decorations = match self { + Fragment::Float(..) => &Default::default(), + _ => text_decorations, + }; + // If this fragment has a transform applied that makes it take up no space // then we don't need to create any stacking contexts for it. let has_non_invertible_transform = fragment @@ -828,6 +850,7 @@ impl Fragment { containing_block, containing_block_info, stacking_context, + text_decorations, ); }, Fragment::AbsoluteOrFixedPositioned(fragment) => { @@ -842,6 +865,7 @@ impl Fragment { containing_block_info, stacking_context, StackingContextBuildMode::IncludeHoisted, + &Default::default(), ); }, Fragment::Positioning(fragment) => { @@ -851,6 +875,7 @@ impl Fragment { containing_block, containing_block_info, stacking_context, + text_decorations, ); }, Fragment::Text(_) | Fragment::Image(_) | Fragment::IFrame(_) => { @@ -867,6 +892,7 @@ impl Fragment { fragment: fragment_clone, is_hit_test_for_scrollable_overflow: false, is_collapsed_table_borders: false, + text_decorations: text_decorations.clone(), }); }, } @@ -929,6 +955,7 @@ impl BoxFragment { containing_block: &ContainingBlock, containing_block_info: &ContainingBlockInfo, parent_stacking_context: &mut StackingContext, + text_decorations: &Arc<Vec<FragmentTextDecoration>>, ) { self.build_stacking_context_tree_maybe_creating_reference_frame( fragment, @@ -936,6 +963,7 @@ impl BoxFragment { containing_block, containing_block_info, parent_stacking_context, + text_decorations, ); } @@ -946,6 +974,7 @@ impl BoxFragment { containing_block: &ContainingBlock, containing_block_info: &ContainingBlockInfo, parent_stacking_context: &mut StackingContext, + text_decorations: &Arc<Vec<FragmentTextDecoration>>, ) { let reference_frame_data = match self.reference_frame_data_if_necessary(&containing_block.rect) { @@ -957,6 +986,7 @@ impl BoxFragment { containing_block, containing_block_info, parent_stacking_context, + text_decorations, ); }, }; @@ -999,6 +1029,7 @@ impl BoxFragment { &adjusted_containing_block, &new_containing_block_info, parent_stacking_context, + text_decorations, ); } @@ -1009,6 +1040,7 @@ impl BoxFragment { containing_block: &ContainingBlock, containing_block_info: &ContainingBlockInfo, parent_stacking_context: &mut StackingContext, + text_decorations: &Arc<Vec<FragmentTextDecoration>>, ) { let context_type = match self.get_stacking_context_type() { Some(context_type) => context_type, @@ -1019,6 +1051,7 @@ impl BoxFragment { containing_block, containing_block_info, parent_stacking_context, + text_decorations, ); return; }, @@ -1072,6 +1105,7 @@ impl BoxFragment { containing_block, containing_block_info, &mut child_stacking_context, + text_decorations, ); let mut stolen_children = vec![]; @@ -1097,6 +1131,7 @@ impl BoxFragment { containing_block: &ContainingBlock, containing_block_info: &ContainingBlockInfo, stacking_context: &mut StackingContext, + text_decorations: &Arc<Vec<FragmentTextDecoration>>, ) { let mut new_scroll_node_id = containing_block.scroll_node_id; let mut new_clip_id = containing_block.clip_id; @@ -1164,6 +1199,7 @@ impl BoxFragment { fragment: fragment.clone(), is_hit_test_for_scrollable_overflow: false, is_collapsed_table_borders: false, + text_decorations: text_decorations.clone(), }); }; @@ -1198,6 +1234,7 @@ impl BoxFragment { fragment: fragment.clone(), is_hit_test_for_scrollable_overflow: true, is_collapsed_table_borders: false, + text_decorations: text_decorations.clone(), }); } } @@ -1239,12 +1276,46 @@ impl BoxFragment { containing_block_info.new_for_non_absolute_descendants(&for_non_absolute_descendants) }; + // Text decorations are not propagated to atomic inline-level descendants. + // From https://drafts.csswg.org/css2/#lining-striking-props: + // > Note that text decorations are not propagated to floating and absolutely + // > positioned descendants, nor to the contents of atomic inline-level descendants + // > such as inline blocks and inline tables. + let text_decorations = match self.is_atomic_inline_level() || + self.base + .flags + .contains(FragmentFlags::IS_OUTSIDE_LIST_ITEM_MARKER) + { + true => &Default::default(), + false => text_decorations, + }; + + let new_text_decoration; + let text_decorations = match self.style.clone_text_decoration_line() { + TextDecorationLine::NONE => text_decorations, + line => { + let mut new_vector = (**text_decorations).clone(); + let color = &self.style.get_inherited_text().color; + new_vector.push(FragmentTextDecoration { + line, + color: self + .style + .clone_text_decoration_color() + .resolve_to_absolute(color), + style: self.style.clone_text_decoration_style(), + }); + new_text_decoration = Arc::new(new_vector); + &new_text_decoration + }, + }; + for child in &self.children { child.build_stacking_context_tree( stacking_context_tree, &new_containing_block_info, stacking_context, StackingContextBuildMode::SkipHoisted, + text_decorations, ); } @@ -1263,6 +1334,7 @@ impl BoxFragment { fragment: fragment.clone(), is_hit_test_for_scrollable_overflow: false, is_collapsed_table_borders: true, + text_decorations: text_decorations.clone(), }); } } @@ -1646,6 +1718,7 @@ impl PositioningFragment { containing_block: &ContainingBlock, containing_block_info: &ContainingBlockInfo, stacking_context: &mut StackingContext, + text_decorations: &Arc<Vec<FragmentTextDecoration>>, ) { let rect = self .rect @@ -1660,6 +1733,7 @@ impl PositioningFragment { &new_containing_block_info, stacking_context, StackingContextBuildMode::SkipHoisted, + text_decorations, ); } } diff --git a/components/layout/flexbox/layout.rs b/components/layout/flexbox/layout.rs index 8fc5aa0778b..985f5f3cf65 100644 --- a/components/layout/flexbox/layout.rs +++ b/components/layout/flexbox/layout.rs @@ -417,9 +417,8 @@ struct DesiredFlexFractionAndGrowOrShrinkFactor { #[derive(Default)] struct FlexItemBoxInlineContentSizesInfo { outer_flex_base_size: Au, - content_min_main_size: Au, - content_max_main_size: Option<Au>, - pbm_auto_is_zero: FlexRelativeVec2<Au>, + outer_min_main_size: Au, + outer_max_main_size: Option<Au>, min_flex_factors: DesiredFlexFractionAndGrowOrShrinkFactor, max_flex_factors: DesiredFlexFractionAndGrowOrShrinkFactor, min_content_main_size_for_multiline_container: Au, @@ -583,9 +582,8 @@ impl FlexContainer { for FlexItemBoxInlineContentSizesInfo { outer_flex_base_size, - content_min_main_size, - content_max_main_size, - pbm_auto_is_zero, + outer_min_main_size, + outer_max_main_size, min_flex_factors, max_flex_factors, min_content_main_size_for_multiline_container, @@ -595,16 +593,13 @@ impl FlexContainer { // > 4. Add each item’s flex base size to the product of its flex grow factor (scaled flex shrink // > factor, if shrinking) and the chosen flex fraction, then clamp that result by the max main size // > floored by the min main size. - let outer_min_main_size = *content_min_main_size + pbm_auto_is_zero.main; - let outer_max_main_size = content_max_main_size.map(|v| v + pbm_auto_is_zero.main); - // > 5. The flex container’s max-content size is the largest sum (among all the lines) of the // > afore-calculated sizes of all items within a single line. container_max_content_size += (*outer_flex_base_size + Au::from_f32_px( max_flex_factors.flex_grow_or_shrink_factor * chosen_max_flex_fraction, )) - .clamp_between_extremums(outer_min_main_size, outer_max_main_size); + .clamp_between_extremums(*outer_min_main_size, *outer_max_main_size); // > The min-content main size of a single-line flex container is calculated // > identically to the max-content main size, except that the flex items’ @@ -621,7 +616,7 @@ impl FlexContainer { Au::from_f32_px( min_flex_factors.flex_grow_or_shrink_factor * chosen_min_flex_fraction, )) - .clamp_between_extremums(outer_min_main_size, outer_max_main_size); + .clamp_between_extremums(*outer_min_main_size, *outer_max_main_size); } else { container_min_content_size .max_assign(*min_content_main_size_for_multiline_container); @@ -2458,6 +2453,8 @@ impl FlexItemBox { }; let outer_flex_base_size = flex_base_size + pbm_auto_is_zero.main; + let outer_min_main_size = content_min_main_size + pbm_auto_is_zero.main; + let outer_max_main_size = content_max_main_size.map(|v| v + pbm_auto_is_zero.main); let max_flex_factors = self.desired_flex_factors_for_preferred_width( content_contribution_sizes.max_content, flex_base_size, @@ -2483,20 +2480,19 @@ impl FlexItemBox { content_contribution_sizes.min_content; let style_position = &self.style().get_position(); if style_position.flex_grow.is_zero() { - min_content_main_size_for_multiline_container.min_assign(flex_base_size); + min_content_main_size_for_multiline_container.min_assign(outer_flex_base_size); } if style_position.flex_shrink.is_zero() { - min_content_main_size_for_multiline_container.max_assign(flex_base_size); + min_content_main_size_for_multiline_container.max_assign(outer_flex_base_size); } min_content_main_size_for_multiline_container = min_content_main_size_for_multiline_container - .clamp_between_extremums(content_min_main_size, content_max_main_size); + .clamp_between_extremums(outer_min_main_size, outer_max_main_size); FlexItemBoxInlineContentSizesInfo { outer_flex_base_size, - content_min_main_size, - content_max_main_size, - pbm_auto_is_zero, + outer_min_main_size, + outer_max_main_size, min_flex_factors, max_flex_factors, min_content_main_size_for_multiline_container, diff --git a/components/layout/flexbox/mod.rs b/components/layout/flexbox/mod.rs index 96a311ee2b5..7f4a869a944 100644 --- a/components/layout/flexbox/mod.rs +++ b/components/layout/flexbox/mod.rs @@ -105,8 +105,7 @@ impl FlexContainer { contents: NonReplacedContents, propagated_data: PropagatedBoxTreeData, ) -> Self { - let mut builder = - ModernContainerBuilder::new(context, info, propagated_data.union(&info.style)); + let mut builder = ModernContainerBuilder::new(context, info, propagated_data); contents.traverse(context, info, &mut builder); let items = builder.finish(); diff --git a/components/layout/flow/construct.rs b/components/layout/flow/construct.rs index 334da8ae2b0..cc3fe0e6f44 100644 --- a/components/layout/flow/construct.rs +++ b/components/layout/flow/construct.rs @@ -199,7 +199,7 @@ impl<'dom, 'style> BlockContainerBuilder<'dom, 'style> { context, info, block_level_boxes: Vec::new(), - propagated_data: propagated_data.union(&info.style), + propagated_data, have_already_seen_first_line_for_text_indent: false, anonymous_box_info: None, anonymous_table_content: Vec::new(), @@ -228,7 +228,6 @@ impl<'dom, 'style> BlockContainerBuilder<'dom, 'style> { fn finish_ongoing_inline_formatting_context(&mut self) -> Option<InlineFormattingContext> { self.inline_formatting_context_builder.take()?.finish( self.context, - self.propagated_data, !self.have_already_seen_first_line_for_text_indent, self.info.is_single_line_text_input(), self.info.style.writing_mode.to_bidi_level(), @@ -280,16 +279,6 @@ impl<'dom, 'style> BlockContainerBuilder<'dom, 'style> { // creation of an inline table. It requires the parent to be an inline box. let inline_table = self.currently_processing_inline_box(); - // Text decorations are not propagated to atomic inline-level descendants. - // From https://drafts.csswg.org/css2/#lining-striking-props: - // > Note that text decorations are not propagated to floating and absolutely - // > positioned descendants, nor to the contents of atomic inline-level descendants - // > such as inline blocks and inline tables. - let propagated_data = match inline_table { - true => self.propagated_data.without_text_decorations(), - false => self.propagated_data, - }; - let contents: Vec<AnonymousTableContent<'dom>> = self.anonymous_table_content.drain(..).collect(); let last_text = match contents.last() { @@ -298,7 +287,7 @@ impl<'dom, 'style> BlockContainerBuilder<'dom, 'style> { }; let (table_info, ifc) = - Table::construct_anonymous(self.context, self.info, contents, propagated_data); + Table::construct_anonymous(self.context, self.info, contents, self.propagated_data); if inline_table { self.ensure_inline_formatting_context_builder() @@ -315,7 +304,7 @@ impl<'dom, 'style> BlockContainerBuilder<'dom, 'style> { info: table_info, box_slot: BoxSlot::dummy(), kind: BlockLevelCreator::AnonymousTable { table_block }, - propagated_data, + propagated_data: self.propagated_data, }); } @@ -464,7 +453,7 @@ impl<'dom> BlockContainerBuilder<'dom, '_> { contents, list_item_style, }, - propagated_data: self.propagated_data.without_text_decorations(), + propagated_data: self.propagated_data, }); } @@ -480,15 +469,14 @@ impl<'dom> BlockContainerBuilder<'dom, '_> { else { // If this inline element is an atomic, handle it and return. let context = self.context; - let propagaged_data = self.propagated_data.without_text_decorations(); + let propagated_data = self.propagated_data; let atomic = self.ensure_inline_formatting_context_builder().push_atomic( IndependentFormattingContext::construct( context, info, display_inside, contents, - // Text decorations are not propagated to atomic inline-level descendants. - propagaged_data, + propagated_data, ), ); box_slot.set(LayoutBox::InlineLevel(vec![atomic])); @@ -550,7 +538,6 @@ impl<'dom> BlockContainerBuilder<'dom, '_> { .and_then(|builder| { builder.split_around_block_and_finish( self.context, - self.propagated_data, !self.have_already_seen_first_line_for_text_indent, self.info.style.writing_mode.to_bidi_level(), ) @@ -631,7 +618,7 @@ impl<'dom> BlockContainerBuilder<'dom, '_> { info: info.clone(), box_slot, kind, - propagated_data: self.propagated_data.without_text_decorations(), + propagated_data: self.propagated_data, }); } @@ -664,7 +651,7 @@ impl<'dom> BlockContainerBuilder<'dom, '_> { info: info.clone(), box_slot, kind, - propagated_data: self.propagated_data.without_text_decorations(), + propagated_data: self.propagated_data, }); } @@ -754,7 +741,7 @@ impl BlockLevelJob<'_> { context, info, contents, - self.propagated_data.without_text_decorations(), + self.propagated_data, false, /* is_list_item */ ); ArcRefCell::new(BlockLevelBox::OutsideMarker(OutsideMarker { diff --git a/components/layout/flow/float.rs b/components/layout/flow/float.rs index f1ae2b4459a..bb6c7ca8983 100644 --- a/components/layout/flow/float.rs +++ b/components/layout/flow/float.rs @@ -897,8 +897,7 @@ impl FloatBox { info, display_inside, contents, - // Text decorations are not propagated to any out-of-flow descendants - propagated_data.without_text_decorations(), + propagated_data, ), } } diff --git a/components/layout/flow/inline/construct.rs b/components/layout/flow/inline/construct.rs index 600da9b721a..07a2e914835 100644 --- a/components/layout/flow/inline/construct.rs +++ b/components/layout/flow/inline/construct.rs @@ -16,7 +16,6 @@ use super::{ InlineBox, InlineBoxIdentifier, InlineBoxes, InlineFormattingContext, InlineItem, SharedInlineStyles, }; -use crate::PropagatedBoxTreeData; use crate::cell::ArcRefCell; use crate::context::LayoutContext; use crate::dom_traversal::NodeAndStyleInfo; @@ -344,7 +343,6 @@ impl InlineFormattingContextBuilder { pub(crate) fn split_around_block_and_finish( &mut self, layout_context: &LayoutContext, - propagated_data: PropagatedBoxTreeData, has_first_formatted_line: bool, default_bidi_level: Level, ) -> Option<InlineFormattingContext> { @@ -386,7 +384,6 @@ impl InlineFormattingContextBuilder { inline_builder_from_before_split.finish( layout_context, - propagated_data, has_first_formatted_line, /* is_single_line_text_input = */ false, default_bidi_level, @@ -397,7 +394,6 @@ impl InlineFormattingContextBuilder { pub(crate) fn finish( self, layout_context: &LayoutContext, - propagated_data: PropagatedBoxTreeData, has_first_formatted_line: bool, is_single_line_text_input: bool, default_bidi_level: Level, @@ -410,7 +406,6 @@ impl InlineFormattingContextBuilder { Some(InlineFormattingContext::new_with_builder( self, layout_context, - propagated_data, has_first_formatted_line, is_single_line_text_input, default_bidi_level, diff --git a/components/layout/flow/inline/inline_box.rs b/components/layout/flow/inline/inline_box.rs index b547f3b5935..a9642d3b222 100644 --- a/components/layout/flow/inline/inline_box.rs +++ b/components/layout/flow/inline/inline_box.rs @@ -256,13 +256,7 @@ impl InlineBoxContainerState { } Self { - base: InlineContainerState::new( - style, - flags, - Some(parent_container), - parent_container.text_decoration_line, - font_metrics, - ), + base: InlineContainerState::new(style, flags, Some(parent_container), font_metrics), identifier: inline_box.identifier, base_fragment_info: inline_box.base.base_fragment_info, pbm, diff --git a/components/layout/flow/inline/line.rs b/components/layout/flow/inline/line.rs index 3b92078d67d..14a1531883f 100644 --- a/components/layout/flow/inline/line.rs +++ b/components/layout/flow/inline/line.rs @@ -15,7 +15,6 @@ use style::values::generics::box_::{GenericVerticalAlign, VerticalAlignKeyword}; use style::values::generics::font::LineHeight; use style::values::specified::align::AlignFlags; use style::values::specified::box_::DisplayOutside; -use style::values::specified::text::TextDecorationLine; use unicode_bidi::{BidiInfo, Level}; use webrender_api::FontInstanceKey; @@ -572,7 +571,6 @@ impl LineItemLayout<'_, '_> { font_metrics: text_item.font_metrics, font_key: text_item.font_key, glyphs: text_item.text, - text_decoration_line: text_item.text_decoration_line, justification_adjustment: self.justification_adjustment, selection_range: text_item.selection_range, })), @@ -765,7 +763,6 @@ pub(super) struct TextRunLineItem { pub text: Vec<std::sync::Arc<GlyphStore>>, pub font_metrics: FontMetrics, pub font_key: FontInstanceKey, - pub text_decoration_line: TextDecorationLine, /// The BiDi level of this [`TextRunLineItem`] to enable reordering. pub bidi_level: Level, pub selection_range: Option<Range<ByteIndex>>, diff --git a/components/layout/flow/inline/mod.rs b/components/layout/flow/inline/mod.rs index 74d42ca6fb4..6fd4a51a526 100644 --- a/components/layout/flow/inline/mod.rs +++ b/components/layout/flow/inline/mod.rs @@ -103,7 +103,7 @@ use style::properties::style_structs::InheritedText; use style::values::generics::box_::VerticalAlignKeyword; use style::values::generics::font::LineHeight; use style::values::specified::box_::BaselineSource; -use style::values::specified::text::{TextAlignKeyword, TextDecorationLine}; +use style::values::specified::text::TextAlignKeyword; use style::values::specified::{TextAlignLast, TextJustify}; use text_run::{ TextRun, XI_LINE_BREAKING_CLASS_GL, XI_LINE_BREAKING_CLASS_WJ, XI_LINE_BREAKING_CLASS_ZWJ, @@ -134,7 +134,7 @@ use crate::geom::{LogicalRect, LogicalVec2, ToLogical}; use crate::positioned::{AbsolutelyPositionedBox, PositioningContext}; use crate::sizing::{ComputeInlineContentSizes, ContentSizes, InlineContentSizesResult}; use crate::style_ext::{ComputedValuesExt, PaddingBorderMargin}; -use crate::{ConstraintSpace, ContainingBlock, PropagatedBoxTreeData, SharedStyle}; +use crate::{ConstraintSpace, ContainingBlock, SharedStyle}; // From gfxFontConstants.h in Firefox. static FONT_SUBSCRIPT_OFFSET_RATIO: f32 = 0.20; @@ -163,8 +163,6 @@ pub(crate) struct InlineFormattingContext { /// share styles with all [`TextRun`] children. pub(super) shared_inline_styles: SharedInlineStyles, - pub(super) text_decoration_line: TextDecorationLine, - /// Whether this IFC contains the 1st formatted line of an element: /// <https://www.w3.org/TR/css-pseudo-4/#first-formatted-line>. pub(super) has_first_formatted_line: bool, @@ -628,12 +626,6 @@ pub(super) struct InlineContainerState { /// this inline box on the current line OR any previous line. has_content: RefCell<bool>, - /// Indicates whether this nesting level have text decorations in effect. - /// From <https://drafts.csswg.org/css-text-decor/#line-decoration> - // "When specified on or propagated to a block container that establishes - // an IFC..." - text_decoration_line: TextDecorationLine, - /// The block size contribution of this container's default font ie the size of the /// "strut." Whether this is integrated into the [`Self::nested_strut_block_sizes`] /// depends on the line-height quirk described in @@ -1461,7 +1453,6 @@ impl InlineFormattingContextLayout<'_> { inline_styles: text_run.inline_styles.clone(), font_metrics, font_key: ifc_font_info.key, - text_decoration_line: self.current_inline_container_state().text_decoration_line, bidi_level, selection_range, }, @@ -1655,7 +1646,6 @@ impl InlineFormattingContext { pub(super) fn new_with_builder( builder: InlineFormattingContextBuilder, layout_context: &LayoutContext, - propagated_data: PropagatedBoxTreeData, has_first_formatted_line: bool, is_single_line_text_input: bool, starting_bidi_level: Level, @@ -1711,7 +1701,6 @@ impl InlineFormattingContext { .last() .expect("Should have at least one SharedInlineStyle for the root of an IFC") .clone(), - text_decoration_line: propagated_data.text_decoration, has_first_formatted_line, contains_floats: builder.contains_floats, is_single_line_text_input, @@ -1781,7 +1770,6 @@ impl InlineFormattingContext { style.to_arc(), inline_container_state_flags, None, /* parent_container */ - self.text_decoration_line, default_font_metrics.as_ref(), ), inline_box_state_stack: Vec::new(), @@ -1879,10 +1867,8 @@ impl InlineContainerState { style: Arc<ComputedValues>, flags: InlineContainerStateFlags, parent_container: Option<&InlineContainerState>, - parent_text_decoration_line: TextDecorationLine, font_metrics: Option<&FontMetrics>, ) -> Self { - let text_decoration_line = parent_text_decoration_line | style.clone_text_decoration_line(); let font_metrics = font_metrics.cloned().unwrap_or_else(FontMetrics::empty); let line_height = line_height( &style, @@ -1919,7 +1905,6 @@ impl InlineContainerState { style, flags, has_content: RefCell::new(false), - text_decoration_line, nested_strut_block_sizes: nested_block_sizes, strut_block_sizes, baseline_offset, diff --git a/components/layout/flow/root.rs b/components/layout/flow/root.rs index a37db54065d..8ad3671032e 100644 --- a/components/layout/flow/root.rs +++ b/components/layout/flow/root.rs @@ -314,7 +314,7 @@ fn construct_for_root_element( let contents = ReplacedContents::for_element(root_element, context) .map_or_else(|| NonReplacedContents::OfElement.into(), Contents::Replaced); - let propagated_data = PropagatedBoxTreeData::default().union(&info.style); + let propagated_data = PropagatedBoxTreeData::default(); let root_box = if box_style.position.is_absolutely_positioned() { BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(ArcRefCell::new( AbsolutelyPositionedBox::construct(context, &info, display_inside, contents), diff --git a/components/layout/fragment_tree/fragment.rs b/components/layout/fragment_tree/fragment.rs index 1ebc7b3c989..c81fd59e36b 100644 --- a/components/layout/fragment_tree/fragment.rs +++ b/components/layout/fragment_tree/fragment.rs @@ -14,7 +14,6 @@ use range::Range as ServoRange; use servo_arc::Arc as ServoArc; use style::Zero; use style::properties::ComputedValues; -use style::values::specified::text::TextDecorationLine; use webrender_api::{FontInstanceKey, ImageKey}; use super::{ @@ -72,9 +71,6 @@ pub(crate) struct TextFragment { #[conditional_malloc_size_of] pub glyphs: Vec<Arc<GlyphStore>>, - /// A flag that represents the _used_ value of the text-decoration property. - pub text_decoration_line: TextDecorationLine, - /// Extra space to add for each justification opportunity. pub justification_adjustment: Au, pub selection_range: Option<ServoRange<ByteIndex>>, diff --git a/components/layout/layout_impl.rs b/components/layout/layout_impl.rs index b490b4a0506..8162ed1dd0b 100644 --- a/components/layout/layout_impl.rs +++ b/components/layout/layout_impl.rs @@ -773,7 +773,7 @@ impl LayoutThread { let root_node = root_element.as_node(); let damage = compute_damage_and_repair_style(layout_context.shared_context(), root_node); - if damage == RestyleDamage::REPAINT { + if damage.is_empty() || damage == RestyleDamage::REPAINT { layout_context.style_context.stylist.rule_tree().maybe_gc(); return false; } diff --git a/components/layout/lib.rs b/components/layout/lib.rs index cd992387277..ea254723dcb 100644 --- a/components/layout/lib.rs +++ b/components/layout/lib.rs @@ -41,7 +41,6 @@ use malloc_size_of_derive::MallocSizeOf; use servo_arc::Arc as ServoArc; use style::logical_geometry::WritingMode; use style::properties::ComputedValues; -use style::values::computed::TextDecorationLine; use crate::geom::{LogicalVec2, SizeConstraint}; use crate::style_ext::AspectRatio; @@ -163,39 +162,20 @@ impl<'a> From<&'_ DefiniteContainingBlock<'a>> for ContainingBlock<'a> { /// propoagation, but only during `BoxTree` construction. #[derive(Clone, Copy, Debug)] struct PropagatedBoxTreeData { - text_decoration: TextDecorationLine, allow_percentage_column_in_tables: bool, } impl Default for PropagatedBoxTreeData { fn default() -> Self { Self { - text_decoration: Default::default(), allow_percentage_column_in_tables: true, } } } impl PropagatedBoxTreeData { - pub(crate) fn union(&self, style: &ComputedValues) -> Self { - Self { - // FIXME(#31736): This is only taking into account the line style and not the decoration - // color. This should collect information about both so that they can be rendered properly. - text_decoration: self.text_decoration | style.clone_text_decoration_line(), - allow_percentage_column_in_tables: self.allow_percentage_column_in_tables, - } - } - - pub(crate) fn without_text_decorations(&self) -> Self { - Self { - text_decoration: TextDecorationLine::NONE, - allow_percentage_column_in_tables: self.allow_percentage_column_in_tables, - } - } - fn disallowing_percentage_table_columns(&self) -> PropagatedBoxTreeData { Self { - text_decoration: self.text_decoration, allow_percentage_column_in_tables: false, } } diff --git a/components/layout/table/construct.rs b/components/layout/table/construct.rs index 0c238073df2..0b22ea1c13a 100644 --- a/components/layout/table/construct.rs +++ b/components/layout/table/construct.rs @@ -81,12 +81,7 @@ impl Table { contents: NonReplacedContents, propagated_data: PropagatedBoxTreeData, ) -> Self { - let mut traversal = TableBuilderTraversal::new( - context, - info, - grid_style, - propagated_data.union(&info.style), - ); + let mut traversal = TableBuilderTraversal::new(context, info, grid_style, propagated_data); contents.traverse(context, info, &mut traversal); traversal.finish() } @@ -771,9 +766,6 @@ impl<'dom> TraversalHandler<'dom> for TableBuilderTraversal<'_, 'dom> { }); self.builder.table.row_groups.push(row_group.clone()); - let previous_propagated_data = self.current_propagated_data; - self.current_propagated_data = self.current_propagated_data.union(&info.style); - let new_row_group_index = self.builder.table.row_groups.len() - 1; self.current_row_group_index = Some(new_row_group_index); @@ -785,7 +777,6 @@ impl<'dom> TraversalHandler<'dom> for TableBuilderTraversal<'_, 'dom> { self.finish_anonymous_row_if_needed(); self.current_row_group_index = None; - self.current_propagated_data = previous_propagated_data; self.builder.incoming_rowspans.clear(); box_slot.set(LayoutBox::TableLevelBox(TableLevelBox::TrackGroup( @@ -936,7 +927,7 @@ impl<'style, 'builder, 'dom, 'a> TableRowBuilder<'style, 'builder, 'dom, 'a> { table_traversal, info, current_anonymous_cell_content: Vec::new(), - propagated_data: propagated_data.union(&info.style), + propagated_data, } } diff --git a/components/layout/taffy/mod.rs b/components/layout/taffy/mod.rs index 2bc7a598d08..05fc09c5511 100644 --- a/components/layout/taffy/mod.rs +++ b/components/layout/taffy/mod.rs @@ -36,8 +36,7 @@ impl TaffyContainer { contents: NonReplacedContents, propagated_data: PropagatedBoxTreeData, ) -> Self { - let mut builder = - ModernContainerBuilder::new(context, info, propagated_data.union(&info.style)); + let mut builder = ModernContainerBuilder::new(context, info, propagated_data); contents.traverse(context, info, &mut builder); let items = builder.finish(); diff --git a/components/layout/traversal.rs b/components/layout/traversal.rs index d05deb24bfa..faf25dc170d 100644 --- a/components/layout/traversal.rs +++ b/components/layout/traversal.rs @@ -105,7 +105,9 @@ pub(crate) fn compute_damage_and_repair_style_inner( parent_restyle_damage: RestyleDamage, ) -> RestyleDamage { let original_damage; - let damage = { + let damage; + + { let mut element_data = node .style_data() .expect("Should not run `compute_damage` before styling.") @@ -113,14 +115,14 @@ pub(crate) fn compute_damage_and_repair_style_inner( .borrow_mut(); original_damage = std::mem::take(&mut element_data.damage); + damage = original_damage | parent_restyle_damage; + if let Some(ref style) = element_data.styles.primary { if style.get_box().display == Display::None { - return parent_restyle_damage; + return damage; } } - - original_damage | parent_restyle_damage - }; + } let mut propagated_damage = damage; for child in iter_child_nodes(node) { |