mirror of
https://github.com/servo/servo.git
synced 2025-08-02 20:20:14 +01:00
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:
parent
1677d479f6
commit
951c050690
8 changed files with 84 additions and 191 deletions
|
@ -51,7 +51,7 @@ use style::computed_values::content::ContentItem;
|
||||||
use style::computed_values::position;
|
use style::computed_values::position;
|
||||||
use style::context::SharedStyleContext;
|
use style::context::SharedStyleContext;
|
||||||
use style::logical_geometry::Direction;
|
use style::logical_geometry::Direction;
|
||||||
use style::properties::{self, ServoComputedValues};
|
use style::properties::ServoComputedValues;
|
||||||
use style::selector_parser::{PseudoElement, RestyleDamage};
|
use style::selector_parser::{PseudoElement, RestyleDamage};
|
||||||
use style::servo::restyle_damage::{BUBBLE_ISIZES, RECONSTRUCT_FLOW};
|
use style::servo::restyle_damage::{BUBBLE_ISIZES, RECONSTRUCT_FLOW};
|
||||||
use style::values::Either;
|
use style::values::Either;
|
||||||
|
@ -178,7 +178,7 @@ impl InlineBlockSplit {
|
||||||
predecessors: mem::replace(
|
predecessors: mem::replace(
|
||||||
fragment_accumulator,
|
fragment_accumulator,
|
||||||
InlineFragmentsAccumulator::from_inline_node(
|
InlineFragmentsAccumulator::from_inline_node(
|
||||||
node, style_context)).to_intermediate_inline_fragments(),
|
node, style_context)).to_intermediate_inline_fragments(style_context),
|
||||||
flow: flow,
|
flow: flow,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -273,7 +273,8 @@ impl InlineFragmentsAccumulator {
|
||||||
self.fragments.absolute_descendants.push_descendants(fragments.absolute_descendants);
|
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 {
|
let InlineFragmentsAccumulator {
|
||||||
mut fragments,
|
mut fragments,
|
||||||
enclosing_node,
|
enclosing_node,
|
||||||
|
@ -299,9 +300,9 @@ impl InlineFragmentsAccumulator {
|
||||||
|
|
||||||
if let Some((start, end)) = bidi_control_chars {
|
if let Some((start, end)) = bidi_control_chars {
|
||||||
fragments.fragments.push_front(
|
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(
|
fragments.fragments.push_back(
|
||||||
control_chars_to_fragment(&enclosing_node, end, restyle_damage));
|
control_chars_to_fragment(&enclosing_node, context, end, restyle_damage));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fragments
|
fragments
|
||||||
|
@ -340,7 +341,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds the fragment for the given block or subclass thereof.
|
/// 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() {
|
let specific_fragment_info = match node.type_id() {
|
||||||
Some(LayoutNodeType::Element(LayoutElementType::HTMLIFrameElement)) => {
|
Some(LayoutNodeType::Element(LayoutElementType::HTMLIFrameElement)) => {
|
||||||
SpecificFragmentInfo::Iframe(IframeFragmentInfo::new(node))
|
SpecificFragmentInfo::Iframe(IframeFragmentInfo::new(node))
|
||||||
|
@ -399,7 +400,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
||||||
absolute_descendants: &mut AbsoluteDescendants,
|
absolute_descendants: &mut AbsoluteDescendants,
|
||||||
legalizer: &mut Legalizer,
|
legalizer: &mut Legalizer,
|
||||||
node: &ConcreteThreadSafeLayoutNode) {
|
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() {
|
if fragments.is_empty() {
|
||||||
return
|
return
|
||||||
};
|
};
|
||||||
|
@ -546,14 +547,12 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
||||||
ConstructionResult::ConstructionItem(ConstructionItem::Whitespace(
|
ConstructionResult::ConstructionItem(ConstructionItem::Whitespace(
|
||||||
whitespace_node,
|
whitespace_node,
|
||||||
whitespace_pseudo,
|
whitespace_pseudo,
|
||||||
mut whitespace_style,
|
whitespace_style,
|
||||||
whitespace_damage)) => {
|
whitespace_damage)) => {
|
||||||
// Add whitespace results. They will be stripped out later on when
|
// Add whitespace results. They will be stripped out later on when
|
||||||
// between block elements, and retained when between inline elements.
|
// between block elements, and retained when between inline elements.
|
||||||
let fragment_info = SpecificFragmentInfo::UnscannedText(
|
let fragment_info = SpecificFragmentInfo::UnscannedText(
|
||||||
box UnscannedTextFragmentInfo::new(" ".to_owned(), None));
|
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,
|
let fragment = Fragment::from_opaque_node_and_style(whitespace_node,
|
||||||
whitespace_pseudo,
|
whitespace_pseudo,
|
||||||
whitespace_style,
|
whitespace_style,
|
||||||
|
@ -644,7 +643,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
||||||
/// `<textarea>`.
|
/// `<textarea>`.
|
||||||
fn build_flow_for_block_like(&mut self, flow: FlowRef, node: &ConcreteThreadSafeLayoutNode)
|
fn build_flow_for_block_like(&mut self, flow: FlowRef, node: &ConcreteThreadSafeLayoutNode)
|
||||||
-> ConstructionResult {
|
-> ConstructionResult {
|
||||||
let mut initial_fragments = IntermediateInlineFragments::new();
|
let mut fragments = IntermediateInlineFragments::new();
|
||||||
let node_is_input_or_text_area =
|
let node_is_input_or_text_area =
|
||||||
node.type_id() == Some(LayoutNodeType::Element(LayoutElementType::HTMLInputElement)) ||
|
node.type_id() == Some(LayoutNodeType::Element(LayoutElementType::HTMLInputElement)) ||
|
||||||
node.type_id() == Some(LayoutNodeType::Element(LayoutElementType::HTMLTextAreaElement));
|
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 {
|
if node_is_input_or_text_area {
|
||||||
let context = self.style_context();
|
style = context.stylist.style_for_anonymous(
|
||||||
style = context.stylist.style_for_anonymous_box(
|
|
||||||
&context.guards, &PseudoElement::ServoInputText, &style)
|
&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, fragments)
|
||||||
self.build_flow_for_block_starting_with_fragments(flow, node, initial_fragments)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pushes fragments appropriate for the content of the given node onto the given list.
|
/// Pushes fragments appropriate for the content of the given node onto the given list.
|
||||||
|
@ -682,13 +682,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut style = (*style).clone();
|
let style = (*style).clone();
|
||||||
match node.get_pseudo_element_type() {
|
|
||||||
PseudoElementType::Before(_) |
|
|
||||||
PseudoElementType::After(_) => {}
|
|
||||||
_ => properties::modify_style_for_text(&mut style)
|
|
||||||
}
|
|
||||||
|
|
||||||
let selected_style = node.selected_style();
|
let selected_style = node.selected_style();
|
||||||
|
|
||||||
match text_content {
|
match text_content {
|
||||||
|
@ -824,13 +818,11 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
||||||
ConstructionResult::ConstructionItem(ConstructionItem::Whitespace(
|
ConstructionResult::ConstructionItem(ConstructionItem::Whitespace(
|
||||||
whitespace_node,
|
whitespace_node,
|
||||||
whitespace_pseudo,
|
whitespace_pseudo,
|
||||||
mut whitespace_style,
|
whitespace_style,
|
||||||
whitespace_damage)) => {
|
whitespace_damage)) => {
|
||||||
// Instantiate the whitespace fragment.
|
// Instantiate the whitespace fragment.
|
||||||
let fragment_info = SpecificFragmentInfo::UnscannedText(
|
let fragment_info = SpecificFragmentInfo::UnscannedText(
|
||||||
box UnscannedTextFragmentInfo::new(" ".to_owned(), None));
|
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 =
|
let fragment =
|
||||||
Fragment::from_opaque_node_and_style(whitespace_node,
|
Fragment::from_opaque_node_and_style(whitespace_node,
|
||||||
whitespace_pseudo,
|
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.
|
// An empty inline box needs at least one fragment to draw its background and borders.
|
||||||
let info = SpecificFragmentInfo::UnscannedText(
|
let info = SpecificFragmentInfo::UnscannedText(
|
||||||
box UnscannedTextFragmentInfo::new(String::new(), None));
|
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(),
|
let fragment = Fragment::from_opaque_node_and_style(node.opaque(),
|
||||||
node.get_pseudo_element_type().strip(),
|
node.get_pseudo_element_type().strip(),
|
||||||
modified_style,
|
node_style.clone(),
|
||||||
node.selected_style(),
|
node.selected_style(),
|
||||||
node.restyle_damage(),
|
node.restyle_damage(),
|
||||||
info);
|
info);
|
||||||
|
@ -880,7 +869,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
||||||
let construction_item = ConstructionItem::InlineFragments(
|
let construction_item = ConstructionItem::InlineFragments(
|
||||||
InlineFragmentsConstructionResult {
|
InlineFragmentsConstructionResult {
|
||||||
splits: opt_inline_block_splits,
|
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)
|
ConstructionResult::ConstructionItem(construction_item)
|
||||||
} else {
|
} else {
|
||||||
|
@ -897,31 +886,27 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
||||||
self.set_flow_construction_result(&kid, ConstructionResult::None)
|
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 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(
|
return ConstructionResult::ConstructionItem(ConstructionItem::Whitespace(
|
||||||
node.opaque(),
|
node.opaque(),
|
||||||
node.get_pseudo_element_type().strip(),
|
node.get_pseudo_element_type().strip(),
|
||||||
node.style(self.style_context()),
|
context.stylist.style_for_anonymous(
|
||||||
|
&context.guards, &PseudoElement::ServoText, &style),
|
||||||
node.restyle_damage()))
|
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
|
// 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 corresponding to that content. Otherwise, just initialize with the ordinary
|
||||||
// fragment that needs to be generated for this inline node.
|
// fragment that needs to be generated for this inline node.
|
||||||
let mut fragments = IntermediateInlineFragments::new();
|
let mut fragments = IntermediateInlineFragments::new();
|
||||||
match (node.get_pseudo_element_type(), node.type_id()) {
|
match (node.get_pseudo_element_type(), node.type_id()) {
|
||||||
(_, Some(LayoutNodeType::Text)) => {
|
(_, 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, _) => {
|
(PseudoElementType::Normal, _) => {
|
||||||
fragments.fragments.push_back(self.build_fragment_for_block(node));
|
fragments.fragments.push_back(self.build_fragment_for_block(node));
|
||||||
|
@ -952,7 +937,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
||||||
|
|
||||||
let context = self.style_context();
|
let context = self.style_context();
|
||||||
let style = node.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);
|
&context.guards, &PseudoElement::ServoInlineBlockWrapper, &style);
|
||||||
let fragment_info = SpecificFragmentInfo::InlineBlock(InlineBlockFragmentInfo::new(
|
let fragment_info = SpecificFragmentInfo::InlineBlock(InlineBlockFragmentInfo::new(
|
||||||
block_flow));
|
block_flow));
|
||||||
|
@ -970,7 +955,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
||||||
let construction_item =
|
let construction_item =
|
||||||
ConstructionItem::InlineFragments(InlineFragmentsConstructionResult {
|
ConstructionItem::InlineFragments(InlineFragmentsConstructionResult {
|
||||||
splits: LinkedList::new(),
|
splits: LinkedList::new(),
|
||||||
fragments: fragment_accumulator.to_intermediate_inline_fragments(),
|
fragments: fragment_accumulator.to_intermediate_inline_fragments(context),
|
||||||
});
|
});
|
||||||
ConstructionResult::ConstructionItem(construction_item)
|
ConstructionResult::ConstructionItem(construction_item)
|
||||||
}
|
}
|
||||||
|
@ -990,7 +975,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
||||||
InlineAbsoluteHypotheticalFragmentInfo::new(block_flow));
|
InlineAbsoluteHypotheticalFragmentInfo::new(block_flow));
|
||||||
let style_context = self.style_context();
|
let style_context = self.style_context();
|
||||||
let style = node.style(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);
|
&style_context.guards, &PseudoElement::ServoInlineAbsolute, &style);
|
||||||
let fragment = Fragment::from_opaque_node_and_style(node.opaque(),
|
let fragment = Fragment::from_opaque_node_and_style(node.opaque(),
|
||||||
PseudoElementType::Normal,
|
PseudoElementType::Normal,
|
||||||
|
@ -1006,7 +991,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
||||||
let construction_item =
|
let construction_item =
|
||||||
ConstructionItem::InlineFragments(InlineFragmentsConstructionResult {
|
ConstructionItem::InlineFragments(InlineFragmentsConstructionResult {
|
||||||
splits: LinkedList::new(),
|
splits: LinkedList::new(),
|
||||||
fragments: fragment_accumulator.to_intermediate_inline_fragments(),
|
fragments: fragment_accumulator.to_intermediate_inline_fragments(style_context),
|
||||||
});
|
});
|
||||||
ConstructionResult::ConstructionItem(construction_item)
|
ConstructionResult::ConstructionItem(construction_item)
|
||||||
}
|
}
|
||||||
|
@ -1103,7 +1088,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
||||||
{
|
{
|
||||||
let context = self.style_context();
|
let context = self.style_context();
|
||||||
table_style = node.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);
|
&context.guards, &PseudoElement::ServoTableWrapper, &table_style);
|
||||||
}
|
}
|
||||||
let wrapper_fragment =
|
let wrapper_fragment =
|
||||||
|
@ -1370,7 +1355,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
||||||
|
|
||||||
let mut set_has_newly_constructed_flow_flag = false;
|
let mut set_has_newly_constructed_flow_flag = false;
|
||||||
let result = {
|
let result = {
|
||||||
let mut style = node.style(self.style_context());
|
let style = node.style(self.style_context());
|
||||||
let damage = node.restyle_damage();
|
let damage = node.restyle_damage();
|
||||||
let mut data = node.mutate_layout_data().unwrap();
|
let mut data = node.mutate_layout_data().unwrap();
|
||||||
|
|
||||||
|
@ -1441,9 +1426,6 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
if node.is_replaced_content() {
|
|
||||||
properties::modify_style_for_replaced_content(&mut style);
|
|
||||||
}
|
|
||||||
fragment.repair_style(&style);
|
fragment.repair_style(&style);
|
||||||
set_has_newly_constructed_flow_flag = true;
|
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,
|
fn control_chars_to_fragment(node: &InlineFragmentNodeInfo,
|
||||||
|
context: &SharedStyleContext,
|
||||||
text: &str,
|
text: &str,
|
||||||
restyle_damage: RestyleDamage)
|
restyle_damage: RestyleDamage)
|
||||||
-> Fragment {
|
-> Fragment {
|
||||||
let info = SpecificFragmentInfo::UnscannedText(
|
let info = SpecificFragmentInfo::UnscannedText(
|
||||||
box UnscannedTextFragmentInfo::new(String::from(text), None));
|
box UnscannedTextFragmentInfo::new(String::from(text), None));
|
||||||
let mut style = node.style.clone();
|
let text_style = context.stylist.style_for_anonymous(
|
||||||
properties::modify_style_for_replaced_content(&mut style);
|
&context.guards, &PseudoElement::ServoText, &node.style);
|
||||||
properties::modify_style_for_text(&mut style);
|
|
||||||
Fragment::from_opaque_node_and_style(node.address,
|
Fragment::from_opaque_node_and_style(node.address,
|
||||||
node.pseudo,
|
node.pseudo,
|
||||||
style.clone(),
|
text_style,
|
||||||
node.selected_style.clone(),
|
node.selected_style.clone(),
|
||||||
restyle_damage,
|
restyle_damage,
|
||||||
info)
|
info)
|
||||||
|
@ -2085,7 +2067,7 @@ impl Legalizer {
|
||||||
let reference_block = reference.as_block();
|
let reference_block = reference.as_block();
|
||||||
let mut new_style = reference_block.fragment.style.clone();
|
let mut new_style = reference_block.fragment.style.clone();
|
||||||
for pseudo in pseudos {
|
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
|
let fragment = reference_block.fragment
|
||||||
.create_similar_anonymous_fragment(new_style,
|
.create_similar_anonymous_fragment(new_style,
|
||||||
|
|
|
@ -1173,14 +1173,13 @@ impl Fragment {
|
||||||
_ => self.style().logical_border_width(),
|
_ => self.style().logical_border_width(),
|
||||||
};
|
};
|
||||||
|
|
||||||
match self.inline_context {
|
// NOTE: We can have nodes with different writing mode inside
|
||||||
None => style_border_width,
|
// the inline fragment context, so we need to overwrite the
|
||||||
|
// writing mode to compute the child logical sizes.
|
||||||
|
let writing_mode = self.style.writing_mode;
|
||||||
|
let context_border = match self.inline_context {
|
||||||
|
None => LogicalMargin::zero(writing_mode),
|
||||||
Some(ref inline_fragment_context) => {
|
Some(ref inline_fragment_context) => {
|
||||||
// NOTE: We can have nodes with different writing mode inside
|
|
||||||
// the inline fragment context, so we need to overwrite the
|
|
||||||
// writing mode to compute the child logical sizes.
|
|
||||||
let writing_mode = self.style.writing_mode;
|
|
||||||
|
|
||||||
inline_fragment_context.nodes.iter().fold(style_border_width, |accumulator, node| {
|
inline_fragment_context.nodes.iter().fold(style_border_width, |accumulator, node| {
|
||||||
let mut this_border_width =
|
let mut this_border_width =
|
||||||
node.style.border_width_for_writing_mode(writing_mode);
|
node.style.border_width_for_writing_mode(writing_mode);
|
||||||
|
@ -1193,7 +1192,8 @@ impl Fragment {
|
||||||
accumulator + this_border_width
|
accumulator + this_border_width
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
style_border_width + context_border
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the border width in given direction if this fragment has property
|
/// Returns the border width in given direction if this fragment has property
|
||||||
|
@ -1216,32 +1216,13 @@ impl Fragment {
|
||||||
/// Do not use this method if the inline direction margins are to be computed some other way
|
/// Do not use this method if the inline direction margins are to be computed some other way
|
||||||
/// (for example, via constraint solving for blocks).
|
/// (for example, via constraint solving for blocks).
|
||||||
pub fn compute_inline_direction_margins(&mut self, containing_block_inline_size: Au) {
|
pub fn compute_inline_direction_margins(&mut self, containing_block_inline_size: Au) {
|
||||||
match self.specific {
|
let margin = self.style().logical_margin();
|
||||||
SpecificFragmentInfo::Table |
|
self.margin.inline_start =
|
||||||
SpecificFragmentInfo::TableCell |
|
MaybeAuto::from_style(margin.inline_start,
|
||||||
SpecificFragmentInfo::TableRow |
|
containing_block_inline_size).specified_or_zero();
|
||||||
SpecificFragmentInfo::TableColumn(_) |
|
self.margin.inline_end =
|
||||||
SpecificFragmentInfo::InlineAbsoluteHypothetical(_) => {
|
MaybeAuto::from_style(margin.inline_end,
|
||||||
self.margin.inline_start = Au(0);
|
containing_block_inline_size).specified_or_zero();
|
||||||
self.margin.inline_end = Au(0);
|
|
||||||
return
|
|
||||||
}
|
|
||||||
SpecificFragmentInfo::InlineBlock(_) => {
|
|
||||||
// Inline-blocks do not take self margins into account but do account for margins
|
|
||||||
// from outer inline contexts.
|
|
||||||
self.margin.inline_start = Au(0);
|
|
||||||
self.margin.inline_end = Au(0);
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(ref inline_context) = self.inline_context {
|
if let Some(ref inline_context) = self.inline_context {
|
||||||
for node in &inline_context.nodes {
|
for node in &inline_context.nodes {
|
||||||
|
|
|
@ -780,16 +780,7 @@ impl<'ln> ThreadSafeLayoutNode for ServoThreadSafeLayoutNode<'ln> {
|
||||||
self.node.type_id()
|
self.node.type_id()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn style_for_text_node(&self) -> Arc<ComputedValues> {
|
fn parent_style(&self) -> Arc<ComputedValues> {
|
||||||
// Text nodes get a copy of the parent style. Inheriting all non-
|
|
||||||
// inherited properties into the text node is odd from a CSS
|
|
||||||
// perspective, but makes fragment construction easier (by making
|
|
||||||
// properties like vertical-align on fragments have values that
|
|
||||||
// match the parent element). This is an implementation detail of
|
|
||||||
// Servo layout that is not central to how fragment construction
|
|
||||||
// works, but would be difficult to change. (Text node style is
|
|
||||||
// also not visible to script.)
|
|
||||||
debug_assert!(self.is_text_node());
|
|
||||||
let parent = self.node.parent_node().unwrap().as_element().unwrap();
|
let parent = self.node.parent_node().unwrap().as_element().unwrap();
|
||||||
let parent_data = parent.get_data().unwrap().borrow();
|
let parent_data = parent.get_data().unwrap().borrow();
|
||||||
parent_data.styles().primary.values().clone()
|
parent_data.styles().primary.values().clone()
|
||||||
|
|
|
@ -176,7 +176,7 @@ pub trait ThreadSafeLayoutNode: Clone + Copy + Debug + GetLayoutData + NodeInfo
|
||||||
/// it can be used to reach siblings and cousins. A simple immutable borrow
|
/// it can be used to reach siblings and cousins. A simple immutable borrow
|
||||||
/// of the parent data is fine, since the bottom-up traversal will not process
|
/// of the parent data is fine, since the bottom-up traversal will not process
|
||||||
/// the parent until all the children have been processed.
|
/// the parent until all the children have been processed.
|
||||||
fn style_for_text_node(&self) -> Arc<ServoComputedValues>;
|
fn parent_style(&self) -> Arc<ServoComputedValues>;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn is_element_or_elements_pseudo(&self) -> bool {
|
fn is_element_or_elements_pseudo(&self) -> bool {
|
||||||
|
@ -222,8 +222,10 @@ pub trait ThreadSafeLayoutNode: Clone + Copy + Debug + GetLayoutData + NodeInfo
|
||||||
if let Some(el) = self.as_element() {
|
if let Some(el) = self.as_element() {
|
||||||
el.style(context)
|
el.style(context)
|
||||||
} else {
|
} else {
|
||||||
|
// Text nodes are not styled during traversal,instead we simply
|
||||||
|
// return parent style here and do cascading during layout.
|
||||||
debug_assert!(self.is_text_node());
|
debug_assert!(self.is_text_node());
|
||||||
self.style_for_text_node()
|
self.parent_style()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,7 +234,8 @@ pub trait ThreadSafeLayoutNode: Clone + Copy + Debug + GetLayoutData + NodeInfo
|
||||||
el.selected_style()
|
el.selected_style()
|
||||||
} else {
|
} else {
|
||||||
debug_assert!(self.is_text_node());
|
debug_assert!(self.is_text_node());
|
||||||
self.style_for_text_node()
|
// TODO(stshine): What should the selected style be for text?
|
||||||
|
self.parent_style()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2445,49 +2445,6 @@ pub fn modify_style_for_anonymous_flow(style: &mut Arc<ComputedValues>,
|
||||||
outline.outline_width = Au(0);
|
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.
|
|
||||||
#[cfg(feature = "servo")]
|
|
||||||
#[inline]
|
|
||||||
pub fn modify_style_for_replaced_content(style: &mut Arc<ComputedValues>) {
|
|
||||||
// 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
|
/// Adjusts borders as appropriate to account for a fragment's status as the
|
||||||
/// first or last fragment within the range of an element.
|
/// first or last fragment within the range of an element.
|
||||||
///
|
///
|
||||||
|
@ -2544,44 +2501,6 @@ pub fn modify_border_style_for_inline_sides(style: &mut Arc<ComputedValues>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adjusts the `position` and `padding` properties as necessary to account for
|
|
||||||
/// text.
|
|
||||||
///
|
|
||||||
/// Text is never directly relatively positioned; it's always contained within
|
|
||||||
/// an element that is itself relatively positioned.
|
|
||||||
#[cfg(feature = "servo")]
|
|
||||||
#[inline]
|
|
||||||
pub fn modify_style_for_text(style: &mut Arc<ComputedValues>) {
|
|
||||||
if style.box_.position == longhands::position::computed_value::T::relative {
|
|
||||||
// We leave the `position` property set to `relative` so that we'll still establish a
|
|
||||||
// containing block if needed. But we reset all position offsets to `auto`.
|
|
||||||
let mut style = Arc::make_mut(style);
|
|
||||||
let mut position = Arc::make_mut(&mut style.position);
|
|
||||||
position.top = computed::LengthOrPercentageOrAuto::Auto;
|
|
||||||
position.right = computed::LengthOrPercentageOrAuto::Auto;
|
|
||||||
position.bottom = computed::LengthOrPercentageOrAuto::Auto;
|
|
||||||
position.left = computed::LengthOrPercentageOrAuto::Auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
if style.padding.padding_top != computed::LengthOrPercentage::Length(Au(0)) ||
|
|
||||||
style.padding.padding_right != computed::LengthOrPercentage::Length(Au(0)) ||
|
|
||||||
style.padding.padding_bottom != computed::LengthOrPercentage::Length(Au(0)) ||
|
|
||||||
style.padding.padding_left != computed::LengthOrPercentage::Length(Au(0)) {
|
|
||||||
let mut style = Arc::make_mut(style);
|
|
||||||
let mut padding = Arc::make_mut(&mut style.padding);
|
|
||||||
padding.padding_top = computed::LengthOrPercentage::Length(Au(0));
|
|
||||||
padding.padding_right = computed::LengthOrPercentage::Length(Au(0));
|
|
||||||
padding.padding_bottom = computed::LengthOrPercentage::Length(Au(0));
|
|
||||||
padding.padding_left = computed::LengthOrPercentage::Length(Au(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
if style.effects.opacity != 1.0 {
|
|
||||||
let mut style = Arc::make_mut(style);
|
|
||||||
let mut effects = Arc::make_mut(&mut style.effects);
|
|
||||||
effects.opacity = 1.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! css_properties_accessors {
|
macro_rules! css_properties_accessors {
|
||||||
($macro_name: ident) => {
|
($macro_name: ident) => {
|
||||||
|
|
|
@ -32,6 +32,7 @@ pub enum PseudoElement {
|
||||||
Selection,
|
Selection,
|
||||||
DetailsSummary,
|
DetailsSummary,
|
||||||
DetailsContent,
|
DetailsContent,
|
||||||
|
ServoText,
|
||||||
ServoInputText,
|
ServoInputText,
|
||||||
ServoTableWrapper,
|
ServoTableWrapper,
|
||||||
ServoAnonymousTableWrapper,
|
ServoAnonymousTableWrapper,
|
||||||
|
@ -52,6 +53,7 @@ impl ToCss for PseudoElement {
|
||||||
Selection => "::selection",
|
Selection => "::selection",
|
||||||
DetailsSummary => "::-servo-details-summary",
|
DetailsSummary => "::-servo-details-summary",
|
||||||
DetailsContent => "::-servo-details-content",
|
DetailsContent => "::-servo-details-content",
|
||||||
|
ServoText => "::-servo-text",
|
||||||
ServoInputText => "::-servo-input-text",
|
ServoInputText => "::-servo-input-text",
|
||||||
ServoTableWrapper => "::-servo-table-wrapper",
|
ServoTableWrapper => "::-servo-table-wrapper",
|
||||||
ServoAnonymousTableWrapper => "::-servo-anonymous-table-wrapper",
|
ServoAnonymousTableWrapper => "::-servo-anonymous-table-wrapper",
|
||||||
|
@ -87,6 +89,7 @@ impl PseudoElement {
|
||||||
PseudoElement::Selection => PseudoElementCascadeType::Eager,
|
PseudoElement::Selection => PseudoElementCascadeType::Eager,
|
||||||
PseudoElement::DetailsSummary => PseudoElementCascadeType::Lazy,
|
PseudoElement::DetailsSummary => PseudoElementCascadeType::Lazy,
|
||||||
PseudoElement::DetailsContent |
|
PseudoElement::DetailsContent |
|
||||||
|
PseudoElement::ServoText |
|
||||||
PseudoElement::ServoInputText |
|
PseudoElement::ServoInputText |
|
||||||
PseudoElement::ServoTableWrapper |
|
PseudoElement::ServoTableWrapper |
|
||||||
PseudoElement::ServoAnonymousTableWrapper |
|
PseudoElement::ServoAnonymousTableWrapper |
|
||||||
|
@ -284,6 +287,12 @@ impl<'a> ::selectors::Parser for SelectorParser<'a> {
|
||||||
}
|
}
|
||||||
DetailsContent
|
DetailsContent
|
||||||
},
|
},
|
||||||
|
"-servo-text" => {
|
||||||
|
if !self.in_user_agent_stylesheet() {
|
||||||
|
return Err(())
|
||||||
|
}
|
||||||
|
ServoText
|
||||||
|
},
|
||||||
"-servo-input-text" => {
|
"-servo-input-text" => {
|
||||||
if !self.in_user_agent_stylesheet() {
|
if !self.in_user_agent_stylesheet() {
|
||||||
return Err(())
|
return Err(())
|
||||||
|
@ -370,6 +379,7 @@ impl SelectorImpl {
|
||||||
fun(PseudoElement::DetailsContent);
|
fun(PseudoElement::DetailsContent);
|
||||||
fun(PseudoElement::DetailsSummary);
|
fun(PseudoElement::DetailsSummary);
|
||||||
fun(PseudoElement::Selection);
|
fun(PseudoElement::Selection);
|
||||||
|
fun(PseudoElement::ServoText);
|
||||||
fun(PseudoElement::ServoInputText);
|
fun(PseudoElement::ServoInputText);
|
||||||
fun(PseudoElement::ServoTableWrapper);
|
fun(PseudoElement::ServoTableWrapper);
|
||||||
fun(PseudoElement::ServoAnonymousTableWrapper);
|
fun(PseudoElement::ServoAnonymousTableWrapper);
|
||||||
|
|
|
@ -385,13 +385,14 @@ impl Stylist {
|
||||||
|
|
||||||
/// Returns the style for an anonymous box of the given type.
|
/// Returns the style for an anonymous box of the given type.
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
pub fn style_for_anonymous_box(&self,
|
pub fn style_for_anonymous(&self,
|
||||||
guards: &StylesheetGuards,
|
guards: &StylesheetGuards,
|
||||||
pseudo: &PseudoElement,
|
pseudo: &PseudoElement,
|
||||||
parent_style: &Arc<ComputedValues>)
|
parent_style: &Arc<ComputedValues>)
|
||||||
-> Arc<ComputedValues> {
|
-> Arc<ComputedValues> {
|
||||||
// For most (but not all) pseudo-elements, we inherit all values from the parent.
|
// For most (but not all) pseudo-elements, we inherit all values from the parent.
|
||||||
let inherit_all = match *pseudo {
|
let inherit_all = match *pseudo {
|
||||||
|
PseudoElement::ServoText |
|
||||||
PseudoElement::ServoInputText => false,
|
PseudoElement::ServoInputText => false,
|
||||||
PseudoElement::ServoAnonymousBlock |
|
PseudoElement::ServoAnonymousBlock |
|
||||||
PseudoElement::ServoAnonymousTable |
|
PseudoElement::ServoAnonymousTable |
|
||||||
|
|
|
@ -168,6 +168,12 @@ svg > * {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* style for text node. */
|
||||||
|
*|*::-servo-text {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* style for text in input elements. */
|
||||||
*|*::-servo-input-text {
|
*|*::-servo-input-text {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue