mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
layout: Move text decoration propagation to stacking context tree construction (#37069)
Text decorations have a special kind of propagation. Instead of propating these during box tree construction, move propagation to stacking context tree construction. This will allow for using a very easy type of incremental layout when text decorations change. For instance, when a link changes color during hovering over it, we can skip all of box and fragment tree construction. In addition, propagation works a bit better now and color and style properly move down from their originating `Fragment`s. This introduces three new failures, because now we are drawing the text-decoration with the correct color in more places, which exposes an issue we have with text-decorations not being drawn in relation to the baseline (taking into account `vertical-align`). Testing: There are tests for these changes. Fixes #31736. Signed-off-by: Martin Robinson <mrobinson@igalia.com> Co-authored-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
parent
cebb1619ae
commit
9781f1241a
23 changed files with 152 additions and 142 deletions
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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>>,
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue