Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[wip] layout: Use a magic pseudo-element for text styles. #12496

Closed
wants to merge 2 commits into from
Closed
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Prev

Introduce -servo-replaced-content.

  • Loading branch information
emilio committed Jul 19, 2016
commit 7aca1860196c13524c53a44cb6b0b513a62dee90
@@ -260,10 +260,12 @@ impl InlineFragmentsAccumulator {
// Control characters are later discarded in transform_text, so they don't affect the
// is_first/is_last styles above.
if let Some((start, end)) = bidi_control_chars {
let mut style = style_context.stylist
.precomputed_values_for_pseudo(&PseudoElement::ServoText,
Some(&enclosing_node.style)).unwrap();
properties::modify_style_for_replaced_content(&mut style);
let style = style_context.stylist
.precomputed_values_for_pseudo(&PseudoElement::ServoReplacedContent,
Some(&enclosing_node.style)).unwrap();
let style = style_context.stylist
.precomputed_values_for_pseudo(&PseudoElement::ServoText,
Some(&style)).unwrap();

fragments.fragments.push_front(
control_chars_to_fragment(&enclosing_node,
@@ -589,13 +591,12 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
ConstructionResult::ConstructionItem(ConstructionItem::Whitespace(
whitespace_node,
whitespace_pseudo,
mut whitespace_style,
whitespace_style,
whitespace_damage)) => {
// Add whitespace results. They will be stripped out later on when
// between block elements, and retained when between inline elements.
let fragment_info = SpecificFragmentInfo::UnscannedText(
box UnscannedTextFragmentInfo::new(" ".to_owned(), None));
properties::modify_style_for_replaced_content(&mut whitespace_style);
let style_context = self.style_context();
let fragment = Fragment::from_opaque_node_and_style(whitespace_node,
whitespace_pseudo,
@@ -877,12 +878,11 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
ConstructionResult::ConstructionItem(ConstructionItem::Whitespace(
whitespace_node,
whitespace_pseudo,
mut whitespace_style,
whitespace_style,
whitespace_damage)) => {
// Instantiate the whitespace fragment.
let fragment_info = SpecificFragmentInfo::UnscannedText(
box UnscannedTextFragmentInfo::new(" ".to_owned(), None));
properties::modify_style_for_replaced_content(&mut whitespace_style);
let fragment =
Fragment::from_opaque_node_and_style(whitespace_node,
whitespace_pseudo,
@@ -904,10 +904,12 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
// An empty inline box needs at least one fragment to draw its background and borders.
let info = SpecificFragmentInfo::UnscannedText(
box UnscannedTextFragmentInfo::new(String::new(), None));
let mut modified_style = self.style_context().stylist
.precomputed_values_for_pseudo(&PseudoElement::ServoText,
Some(&node_style)).unwrap();
properties::modify_style_for_replaced_content(&mut modified_style);
let modified_style = self.style_context().stylist
.precomputed_values_for_pseudo(&PseudoElement::ServoReplacedContent,
Some(&node_style)).unwrap();
let modified_style = self.style_context().stylist
.precomputed_values_for_pseudo(&PseudoElement::ServoText,
Some(&modified_style)).unwrap();
let fragment = Fragment::from_opaque_node_and_style(node.opaque(),
node.get_pseudo_element_type().strip(),
modified_style,
@@ -964,10 +966,10 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
node.restyle_damage()))
}

// Modify the style as necessary. (See the comment in
// `properties::modify_style_for_replaced_content()`.)
let mut style = node.style(self.style_context()).clone();
properties::modify_style_for_replaced_content(&mut style);
let style = node.style(self.style_context());
let style = self.style_context().stylist
.precomputed_values_for_pseudo(&PseudoElement::ServoText,
Some(&style)).unwrap();

// If this is generated content, then we need to initialize the accumulator with the
// fragment corresponding to that content. Otherwise, just initialize with the ordinary
@@ -1409,7 +1411,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
return false
}

let mut style = node.style(self.style_context()).clone();
let style = node.style(self.style_context()).clone();
let mut data = node.mutate_layout_data().unwrap();
let damage = data.restyle_damage;
match *node.construction_result_mut(&mut *data) {
@@ -1479,9 +1481,15 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
}
_ => {
if node.is_replaced_content() {
properties::modify_style_for_replaced_content(&mut style);
let style =
self.style_context()
.stylist
.precomputed_values_for_pseudo(&PseudoElement::ServoReplacedContent,
Some(&style)).unwrap();
fragment.repair_style(&style);
} else {
fragment.repair_style(&style);
}
fragment.repair_style(&style);
}
}
}
@@ -2027,43 +2027,6 @@ pub fn modify_style_for_anonymous_flow(style: &mut Arc<ServoComputedValues>,
outline.outline_width = Au(0);
}

/// Alters the given style to accommodate replaced content. This is called in flow construction. It
/// handles cases like `<div style="position: absolute">foo bar baz</div>` (in which `foo`, `bar`,
/// and `baz` must not be absolutely-positioned) and cases like `<sup>Foo</sup>` (in which the
/// `vertical-align: top` style of `sup` must not propagate down into `Foo`).
///
/// FIXME(#5625, pcwalton): It would probably be cleaner and faster to do this in the cascade.
#[inline]
pub fn modify_style_for_replaced_content(style: &mut Arc<ServoComputedValues>) {
// Reset `position` to handle cases like `<div style="position: absolute">foo bar baz</div>`.
if style.box_.display != longhands::display::computed_value::T::inline {
let mut style = Arc::make_mut(style);
Arc::make_mut(&mut style.box_).display = longhands::display::computed_value::T::inline;
Arc::make_mut(&mut style.box_).position =
longhands::position::computed_value::T::static_;
}

// Reset `vertical-align` to handle cases like `<sup>foo</sup>`.
if style.box_.vertical_align != longhands::vertical_align::computed_value::T::baseline {
let mut style = Arc::make_mut(style);
Arc::make_mut(&mut style.box_).vertical_align =
longhands::vertical_align::computed_value::T::baseline
}

// Reset margins.
if style.margin.margin_top != computed::LengthOrPercentageOrAuto::Length(Au(0)) ||
style.margin.margin_left != computed::LengthOrPercentageOrAuto::Length(Au(0)) ||
style.margin.margin_bottom != computed::LengthOrPercentageOrAuto::Length(Au(0)) ||
style.margin.margin_right != computed::LengthOrPercentageOrAuto::Length(Au(0)) {
let mut style = Arc::make_mut(style);
let margin = Arc::make_mut(&mut style.margin);
margin.margin_top = computed::LengthOrPercentageOrAuto::Length(Au(0));
margin.margin_left = computed::LengthOrPercentageOrAuto::Length(Au(0));
margin.margin_bottom = computed::LengthOrPercentageOrAuto::Length(Au(0));
margin.margin_right = computed::LengthOrPercentageOrAuto::Length(Au(0));
}
}

/// Adjusts borders as appropriate to account for a fragment's status as the first or last fragment
/// within the range of an element.
///
@@ -111,6 +111,7 @@ pub enum PseudoElement {
DetailsSummary,
DetailsContent,
ServoText,
ServoReplacedContent,
}

impl PseudoElement {
@@ -131,6 +132,7 @@ impl PseudoElement {
PseudoElement::Selection => PseudoElementCascadeType::Eager,
PseudoElement::DetailsSummary => PseudoElementCascadeType::Lazy,
PseudoElement::ServoText |
PseudoElement::ServoReplacedContent |
PseudoElement::DetailsContent => PseudoElementCascadeType::Precomputed,
}
}
@@ -241,6 +243,12 @@ impl SelectorImpl for ServoSelectorImpl {
}
ServoText
},
"-servo-replaced-content" => {
if !context.in_user_agent_stylesheet {
return Err(())
}
ServoReplacedContent
},
_ => return Err(())
};

@@ -287,6 +287,13 @@ video { object-fit: contain; }

textarea { white-space: pre-wrap; }

*|*::-servo-replaced-content {
position: static;
display: inline;
vertical-align: baseline;
margin: 0;
}

/**
* This is a special pseudo-element whose styles apply to text nodes.
*/
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.