Use empty pseudo to cascade only inheritable properties for text

Since for nested inline elements non-inheritable properties are
properly stored in the inline context of an inline fragment, so get
rid of them on the style.
This commit is contained in:
Pu Xingyu 2017-03-23 21:03:41 +08:00
parent 1677d479f6
commit 951c050690
8 changed files with 84 additions and 191 deletions

View file

@ -51,7 +51,7 @@ use style::computed_values::content::ContentItem;
use style::computed_values::position;
use style::context::SharedStyleContext;
use style::logical_geometry::Direction;
use style::properties::{self, ServoComputedValues};
use style::properties::ServoComputedValues;
use style::selector_parser::{PseudoElement, RestyleDamage};
use style::servo::restyle_damage::{BUBBLE_ISIZES, RECONSTRUCT_FLOW};
use style::values::Either;
@ -178,7 +178,7 @@ impl InlineBlockSplit {
predecessors: mem::replace(
fragment_accumulator,
InlineFragmentsAccumulator::from_inline_node(
node, style_context)).to_intermediate_inline_fragments(),
node, style_context)).to_intermediate_inline_fragments(style_context),
flow: flow,
};
@ -273,7 +273,8 @@ impl InlineFragmentsAccumulator {
self.fragments.absolute_descendants.push_descendants(fragments.absolute_descendants);
}
fn to_intermediate_inline_fragments(self) -> IntermediateInlineFragments {
fn to_intermediate_inline_fragments(self, context: &SharedStyleContext)
-> IntermediateInlineFragments {
let InlineFragmentsAccumulator {
mut fragments,
enclosing_node,
@ -299,9 +300,9 @@ impl InlineFragmentsAccumulator {
if let Some((start, end)) = bidi_control_chars {
fragments.fragments.push_front(
control_chars_to_fragment(&enclosing_node, start, restyle_damage));
control_chars_to_fragment(&enclosing_node, context, start, restyle_damage));
fragments.fragments.push_back(
control_chars_to_fragment(&enclosing_node, end, restyle_damage));
control_chars_to_fragment(&enclosing_node, context, end, restyle_damage));
}
}
fragments
@ -340,7 +341,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
}
/// Builds the fragment for the given block or subclass thereof.
fn build_fragment_for_block(&mut self, node: &ConcreteThreadSafeLayoutNode) -> Fragment {
fn build_fragment_for_block(&self, node: &ConcreteThreadSafeLayoutNode) -> Fragment {
let specific_fragment_info = match node.type_id() {
Some(LayoutNodeType::Element(LayoutElementType::HTMLIFrameElement)) => {
SpecificFragmentInfo::Iframe(IframeFragmentInfo::new(node))
@ -399,7 +400,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
absolute_descendants: &mut AbsoluteDescendants,
legalizer: &mut Legalizer,
node: &ConcreteThreadSafeLayoutNode) {
let mut fragments = fragment_accumulator.to_intermediate_inline_fragments();
let mut fragments = fragment_accumulator.to_intermediate_inline_fragments(self.style_context());
if fragments.is_empty() {
return
};
@ -546,14 +547,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);
properties::modify_style_for_text(&mut whitespace_style);
let fragment = Fragment::from_opaque_node_and_style(whitespace_node,
whitespace_pseudo,
whitespace_style,
@ -644,7 +643,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
/// `<textarea>`.
fn build_flow_for_block_like(&mut self, flow: FlowRef, node: &ConcreteThreadSafeLayoutNode)
-> ConstructionResult {
let mut initial_fragments = IntermediateInlineFragments::new();
let mut fragments = IntermediateInlineFragments::new();
let node_is_input_or_text_area =
node.type_id() == Some(LayoutNodeType::Element(LayoutElementType::HTMLInputElement)) ||
node.type_id() == Some(LayoutNodeType::Element(LayoutElementType::HTMLTextAreaElement));
@ -658,17 +657,18 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
}
}
let mut style = node.style(self.style_context());
let context = self.style_context();
let mut style = node.style(context);
style = context.stylist.style_for_anonymous(
&context.guards, &PseudoElement::ServoText, &style);
if node_is_input_or_text_area {
let context = self.style_context();
style = context.stylist.style_for_anonymous_box(
style = context.stylist.style_for_anonymous(
&context.guards, &PseudoElement::ServoInputText, &style)
}
self.create_fragments_for_node_text_content(&mut initial_fragments, node, &style)
self.create_fragments_for_node_text_content(&mut fragments, node, &style)
}
self.build_flow_for_block_starting_with_fragments(flow, node, initial_fragments)
self.build_flow_for_block_starting_with_fragments(flow, node, fragments)
}
/// Pushes fragments appropriate for the content of the given node onto the given list.
@ -682,13 +682,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
return
}
let mut style = (*style).clone();
match node.get_pseudo_element_type() {
PseudoElementType::Before(_) |
PseudoElementType::After(_) => {}
_ => properties::modify_style_for_text(&mut style)
}
let style = (*style).clone();
let selected_style = node.selected_style();
match text_content {
@ -824,13 +818,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);
properties::modify_style_for_text(&mut whitespace_style);
let fragment =
Fragment::from_opaque_node_and_style(whitespace_node,
whitespace_pseudo,
@ -852,12 +844,9 @@ 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 = node_style.clone();
properties::modify_style_for_replaced_content(&mut modified_style);
properties::modify_style_for_text(&mut modified_style);
let fragment = Fragment::from_opaque_node_and_style(node.opaque(),
node.get_pseudo_element_type().strip(),
modified_style,
node_style.clone(),
node.selected_style(),
node.restyle_damage(),
info);
@ -880,7 +869,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
let construction_item = ConstructionItem::InlineFragments(
InlineFragmentsConstructionResult {
splits: opt_inline_block_splits,
fragments: fragment_accumulator.to_intermediate_inline_fragments(),
fragments: fragment_accumulator.to_intermediate_inline_fragments(self.style_context()),
});
ConstructionResult::ConstructionItem(construction_item)
} else {
@ -897,31 +886,27 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
self.set_flow_construction_result(&kid, ConstructionResult::None)
}
let context = self.style_context();
let style = node.style(context);
// If this node is ignorable whitespace, bail out now.
if node.is_ignorable_whitespace(self.style_context()) {
if node.is_ignorable_whitespace(context) {
return ConstructionResult::ConstructionItem(ConstructionItem::Whitespace(
node.opaque(),
node.get_pseudo_element_type().strip(),
node.style(self.style_context()),
context.stylist.style_for_anonymous(
&context.guards, &PseudoElement::ServoText, &style),
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());
match node.get_pseudo_element_type() {
PseudoElementType::Before(_) |
PseudoElementType::After(_) => {}
_ => properties::modify_style_for_replaced_content(&mut style)
}
// 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
// fragment that needs to be generated for this inline node.
let mut fragments = IntermediateInlineFragments::new();
match (node.get_pseudo_element_type(), node.type_id()) {
(_, Some(LayoutNodeType::Text)) => {
self.create_fragments_for_node_text_content(&mut fragments, node, &style)
let text_style = context.stylist.style_for_anonymous(
&context.guards, &PseudoElement::ServoText, &style);
self.create_fragments_for_node_text_content(&mut fragments, node, &text_style)
}
(PseudoElementType::Normal, _) => {
fragments.fragments.push_back(self.build_fragment_for_block(node));
@ -952,7 +937,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
let context = self.style_context();
let style = node.style(context);
let style = context.stylist.style_for_anonymous_box(
let style = context.stylist.style_for_anonymous(
&context.guards, &PseudoElement::ServoInlineBlockWrapper, &style);
let fragment_info = SpecificFragmentInfo::InlineBlock(InlineBlockFragmentInfo::new(
block_flow));
@ -970,7 +955,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
let construction_item =
ConstructionItem::InlineFragments(InlineFragmentsConstructionResult {
splits: LinkedList::new(),
fragments: fragment_accumulator.to_intermediate_inline_fragments(),
fragments: fragment_accumulator.to_intermediate_inline_fragments(context),
});
ConstructionResult::ConstructionItem(construction_item)
}
@ -990,7 +975,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
InlineAbsoluteHypotheticalFragmentInfo::new(block_flow));
let style_context = self.style_context();
let style = node.style(style_context);
let style = style_context.stylist.style_for_anonymous_box(
let style = style_context.stylist.style_for_anonymous(
&style_context.guards, &PseudoElement::ServoInlineAbsolute, &style);
let fragment = Fragment::from_opaque_node_and_style(node.opaque(),
PseudoElementType::Normal,
@ -1006,7 +991,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
let construction_item =
ConstructionItem::InlineFragments(InlineFragmentsConstructionResult {
splits: LinkedList::new(),
fragments: fragment_accumulator.to_intermediate_inline_fragments(),
fragments: fragment_accumulator.to_intermediate_inline_fragments(style_context),
});
ConstructionResult::ConstructionItem(construction_item)
}
@ -1103,7 +1088,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
{
let context = self.style_context();
table_style = node.style(context);
wrapper_style = context.stylist.style_for_anonymous_box(
wrapper_style = context.stylist.style_for_anonymous(
&context.guards, &PseudoElement::ServoTableWrapper, &table_style);
}
let wrapper_fragment =
@ -1370,7 +1355,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
let mut set_has_newly_constructed_flow_flag = false;
let result = {
let mut style = node.style(self.style_context());
let style = node.style(self.style_context());
let damage = node.restyle_damage();
let mut data = node.mutate_layout_data().unwrap();
@ -1441,9 +1426,6 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
return false
}
_ => {
if node.is_replaced_content() {
properties::modify_style_for_replaced_content(&mut style);
}
fragment.repair_style(&style);
set_has_newly_constructed_flow_flag = true;
}
@ -1845,17 +1827,17 @@ fn bidi_control_chars(style: &Arc<ServoComputedValues>) -> Option<(&'static str,
}
fn control_chars_to_fragment(node: &InlineFragmentNodeInfo,
context: &SharedStyleContext,
text: &str,
restyle_damage: RestyleDamage)
-> Fragment {
let info = SpecificFragmentInfo::UnscannedText(
box UnscannedTextFragmentInfo::new(String::from(text), None));
let mut style = node.style.clone();
properties::modify_style_for_replaced_content(&mut style);
properties::modify_style_for_text(&mut style);
let text_style = context.stylist.style_for_anonymous(
&context.guards, &PseudoElement::ServoText, &node.style);
Fragment::from_opaque_node_and_style(node.address,
node.pseudo,
style.clone(),
text_style,
node.selected_style.clone(),
restyle_damage,
info)
@ -2085,7 +2067,7 @@ impl Legalizer {
let reference_block = reference.as_block();
let mut new_style = reference_block.fragment.style.clone();
for pseudo in pseudos {
new_style = context.stylist.style_for_anonymous_box(&context.guards, pseudo, &new_style)
new_style = context.stylist.style_for_anonymous(&context.guards, pseudo, &new_style)
}
let fragment = reference_block.fragment
.create_similar_anonymous_fragment(new_style,