servo: Merge #19842 - style: Cleanup a bit the cascade (from emilio:cascade-cleanup); r=nox,jryans
This makes an element available in StyleAdjuster, and uses it to replace some of our CascadeFlags (the ones that don't represent restrictions on what's actually cascaded, actually). That fixes handwaviness in the handling of those flags from style reparenting, and code duplication to handle tricky stuff like :visited. There are a number of other changes that are worth noticing: * skip_root_and_item_based_display_fixup is renamed to skip_item_display_fixup: TElement::is_root() already implies being the document element, which by definition is not native anonymous and not a pseudo-element. Thus, you never get fixed-up if your NAC or a pseudo, which is what the code tried to avoid, so the only fixup with a point is the item one, which is necessary. * The pseudo-element probing code was refactored to return early a Option::<CascadeInputs>::None, which is nicer than what it was doing. * The visited_links_enabled check has moved to selector-matching time. The rest of the checks aren't based on whether the element is a link, or are properly guarded by parent_style.visited_style().is_some() or visited_rules.is_some(). Thus you can transitively infer that no element will end up with a :visited style, not even from style reparenting. Anyway, the underlying reason why I want the element in StyleAdjuster is because we're going to implement an adjustment in there depending on the tag of the element (converting display: contents to display: none depending on the tag), so computing that information eagerly, including a hash lookup, wouldn't be nice. See each commit for details. Source-Repo: https://github.com/servo/servo Source-Revision: 02331617b9bd7a379b05f7daa7ad09a44c27504c
This commit is contained in:
@@ -51,6 +51,7 @@ use style::computed_values::float::T as Float;
|
||||
use style::computed_values::list_style_position::T as ListStylePosition;
|
||||
use style::computed_values::position::T as Position;
|
||||
use style::context::SharedStyleContext;
|
||||
use style::dom::TElement;
|
||||
use style::logical_geometry::Direction;
|
||||
use style::properties::ComputedValues;
|
||||
use style::properties::longhands::list_style_image;
|
||||
@@ -170,11 +171,12 @@ pub struct InlineBlockSplit {
|
||||
impl InlineBlockSplit {
|
||||
/// Flushes the given accumulator to the new split and makes a new accumulator to hold any
|
||||
/// subsequent fragments.
|
||||
fn new<ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>(fragment_accumulator: &mut InlineFragmentsAccumulator,
|
||||
node: &ConcreteThreadSafeLayoutNode,
|
||||
style_context: &SharedStyleContext,
|
||||
flow: FlowRef)
|
||||
-> InlineBlockSplit {
|
||||
fn new<ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>(
|
||||
fragment_accumulator: &mut InlineFragmentsAccumulator,
|
||||
node: &ConcreteThreadSafeLayoutNode,
|
||||
style_context: &SharedStyleContext,
|
||||
flow: FlowRef,
|
||||
) -> InlineBlockSplit {
|
||||
fragment_accumulator.enclosing_node.as_mut().expect(
|
||||
"enclosing_node is None; Are {ib} splits being generated outside of an inline node?"
|
||||
).flags.remove(InlineFragmentNodeFlags::LAST_FRAGMENT_OF_ELEMENT);
|
||||
@@ -183,7 +185,9 @@ impl InlineBlockSplit {
|
||||
predecessors: mem::replace(
|
||||
fragment_accumulator,
|
||||
InlineFragmentsAccumulator::from_inline_node(
|
||||
node, style_context)).to_intermediate_inline_fragments(style_context),
|
||||
node,
|
||||
style_context,
|
||||
)).to_intermediate_inline_fragments::<ConcreteThreadSafeLayoutNode>(style_context),
|
||||
flow: flow,
|
||||
};
|
||||
|
||||
@@ -280,8 +284,13 @@ impl InlineFragmentsAccumulator {
|
||||
self.fragments.absolute_descendants.push_descendants(fragments.absolute_descendants);
|
||||
}
|
||||
|
||||
fn to_intermediate_inline_fragments(self, context: &SharedStyleContext)
|
||||
-> IntermediateInlineFragments {
|
||||
fn to_intermediate_inline_fragments<N>(
|
||||
self,
|
||||
context: &SharedStyleContext,
|
||||
) -> IntermediateInlineFragments
|
||||
where
|
||||
N: ThreadSafeLayoutNode,
|
||||
{
|
||||
let InlineFragmentsAccumulator {
|
||||
mut fragments,
|
||||
enclosing_node,
|
||||
@@ -308,9 +317,21 @@ impl InlineFragmentsAccumulator {
|
||||
|
||||
if let Some((start, end)) = bidi_control_chars {
|
||||
fragments.fragments.push_front(
|
||||
control_chars_to_fragment(&enclosing_node, context, start, restyle_damage));
|
||||
control_chars_to_fragment::<N::ConcreteElement>(
|
||||
&enclosing_node,
|
||||
context,
|
||||
start,
|
||||
restyle_damage,
|
||||
)
|
||||
);
|
||||
fragments.fragments.push_back(
|
||||
control_chars_to_fragment(&enclosing_node, context, end, restyle_damage));
|
||||
control_chars_to_fragment::<N::ConcreteElement>(
|
||||
&enclosing_node,
|
||||
context,
|
||||
end,
|
||||
restyle_damage,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
fragments
|
||||
@@ -402,13 +423,18 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
||||
/// `#[inline(always)]` because this is performance critical and LLVM will not inline it
|
||||
/// otherwise.
|
||||
#[inline(always)]
|
||||
fn flush_inline_fragments_to_flow(&mut self,
|
||||
fragment_accumulator: InlineFragmentsAccumulator,
|
||||
flow: &mut FlowRef,
|
||||
absolute_descendants: &mut AbsoluteDescendants,
|
||||
legalizer: &mut Legalizer,
|
||||
node: &ConcreteThreadSafeLayoutNode) {
|
||||
let mut fragments = fragment_accumulator.to_intermediate_inline_fragments(self.style_context());
|
||||
fn flush_inline_fragments_to_flow(
|
||||
&mut self,
|
||||
fragment_accumulator: InlineFragmentsAccumulator,
|
||||
flow: &mut FlowRef,
|
||||
absolute_descendants: &mut AbsoluteDescendants,
|
||||
legalizer: &mut Legalizer,
|
||||
node: &ConcreteThreadSafeLayoutNode,
|
||||
) {
|
||||
let mut fragments =
|
||||
fragment_accumulator.to_intermediate_inline_fragments::<ConcreteThreadSafeLayoutNode>(
|
||||
self.style_context(),
|
||||
);
|
||||
if fragments.is_empty() {
|
||||
return
|
||||
};
|
||||
@@ -479,7 +505,11 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
||||
}
|
||||
|
||||
inline_flow_ref.finish();
|
||||
legalizer.add_child(self.style_context(), flow, inline_flow_ref)
|
||||
legalizer.add_child::<ConcreteThreadSafeLayoutNode::ConcreteElement>(
|
||||
self.style_context(),
|
||||
flow,
|
||||
inline_flow_ref,
|
||||
)
|
||||
}
|
||||
|
||||
fn build_block_flow_using_construction_result_of_child(
|
||||
@@ -512,7 +542,11 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
||||
legalizer,
|
||||
node);
|
||||
}
|
||||
legalizer.add_child(self.style_context(), flow, kid_flow)
|
||||
legalizer.add_child::<ConcreteThreadSafeLayoutNode::ConcreteElement>(
|
||||
self.style_context(),
|
||||
flow,
|
||||
kid_flow,
|
||||
)
|
||||
}
|
||||
abs_descendants.push_descendants(kid_abs_descendants);
|
||||
}
|
||||
@@ -546,7 +580,11 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
||||
node);
|
||||
|
||||
// Push the flow generated by the {ib} split onto our list of flows.
|
||||
legalizer.add_child(self.style_context(), flow, kid_flow)
|
||||
legalizer.add_child::<ConcreteThreadSafeLayoutNode::ConcreteElement>(
|
||||
self.style_context(),
|
||||
flow,
|
||||
kid_flow,
|
||||
)
|
||||
}
|
||||
|
||||
// Add the fragments to the list we're maintaining.
|
||||
@@ -666,11 +704,17 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
||||
|
||||
let context = self.style_context();
|
||||
let mut style = node.style(context);
|
||||
style = context.stylist.style_for_anonymous(
|
||||
&context.guards, &PseudoElement::ServoText, &style);
|
||||
style = context.stylist.style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>(
|
||||
&context.guards,
|
||||
&PseudoElement::ServoText,
|
||||
&style,
|
||||
);
|
||||
if node_is_input_or_text_area {
|
||||
style = context.stylist.style_for_anonymous(
|
||||
&context.guards, &PseudoElement::ServoInputText, &style)
|
||||
style = context.stylist.style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>(
|
||||
&context.guards,
|
||||
&PseudoElement::ServoInputText,
|
||||
&style,
|
||||
)
|
||||
}
|
||||
|
||||
self.create_fragments_for_node_text_content(&mut fragments, node, &style)
|
||||
@@ -878,7 +922,9 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
||||
let construction_item = ConstructionItem::InlineFragments(
|
||||
InlineFragmentsConstructionResult {
|
||||
splits: opt_inline_block_splits,
|
||||
fragments: fragment_accumulator.to_intermediate_inline_fragments(self.style_context()),
|
||||
fragments: fragment_accumulator.to_intermediate_inline_fragments::<ConcreteThreadSafeLayoutNode>(
|
||||
self.style_context(),
|
||||
),
|
||||
});
|
||||
ConstructionResult::ConstructionItem(construction_item)
|
||||
} else {
|
||||
@@ -902,9 +948,13 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
||||
return ConstructionResult::ConstructionItem(ConstructionItem::Whitespace(
|
||||
node.opaque(),
|
||||
node.get_pseudo_element_type(),
|
||||
context.stylist.style_for_anonymous(
|
||||
&context.guards, &PseudoElement::ServoText, &style),
|
||||
node.restyle_damage()))
|
||||
context.stylist.style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>(
|
||||
&context.guards,
|
||||
&PseudoElement::ServoText,
|
||||
&style,
|
||||
),
|
||||
node.restyle_damage(),
|
||||
))
|
||||
}
|
||||
|
||||
// If this is generated content, then we need to initialize the accumulator with the
|
||||
@@ -913,8 +963,11 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
||||
let mut fragments = IntermediateInlineFragments::new();
|
||||
match (node.get_pseudo_element_type(), node.type_id()) {
|
||||
(_, Some(LayoutNodeType::Text)) => {
|
||||
let text_style = context.stylist.style_for_anonymous(
|
||||
&context.guards, &PseudoElement::ServoText, &style);
|
||||
let text_style = context.stylist.style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>(
|
||||
&context.guards,
|
||||
&PseudoElement::ServoText,
|
||||
&style,
|
||||
);
|
||||
self.create_fragments_for_node_text_content(&mut fragments, node, &text_style)
|
||||
}
|
||||
(PseudoElementType::Normal, _) => {
|
||||
@@ -949,8 +1002,11 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
||||
|
||||
let context = self.style_context();
|
||||
let style = node.style(context);
|
||||
let style = context.stylist.style_for_anonymous(
|
||||
&context.guards, &PseudoElement::ServoInlineBlockWrapper, &style);
|
||||
let style = context.stylist.style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>(
|
||||
&context.guards,
|
||||
&PseudoElement::ServoInlineBlockWrapper,
|
||||
&style,
|
||||
);
|
||||
let fragment_info = SpecificFragmentInfo::InlineBlock(InlineBlockFragmentInfo::new(
|
||||
block_flow));
|
||||
let fragment = Fragment::from_opaque_node_and_style(node.opaque(),
|
||||
@@ -967,7 +1023,8 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
||||
let construction_item =
|
||||
ConstructionItem::InlineFragments(InlineFragmentsConstructionResult {
|
||||
splits: LinkedList::new(),
|
||||
fragments: fragment_accumulator.to_intermediate_inline_fragments(context),
|
||||
fragments: fragment_accumulator
|
||||
.to_intermediate_inline_fragments::<ConcreteThreadSafeLayoutNode>(context),
|
||||
});
|
||||
ConstructionResult::ConstructionItem(construction_item)
|
||||
}
|
||||
@@ -987,8 +1044,11 @@ 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(
|
||||
&style_context.guards, &PseudoElement::ServoInlineAbsolute, &style);
|
||||
let style = style_context.stylist.style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>(
|
||||
&style_context.guards,
|
||||
&PseudoElement::ServoInlineAbsolute,
|
||||
&style,
|
||||
);
|
||||
let fragment = Fragment::from_opaque_node_and_style(node.opaque(),
|
||||
PseudoElementType::Normal,
|
||||
style,
|
||||
@@ -1003,7 +1063,8 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
||||
let construction_item =
|
||||
ConstructionItem::InlineFragments(InlineFragmentsConstructionResult {
|
||||
splits: LinkedList::new(),
|
||||
fragments: fragment_accumulator.to_intermediate_inline_fragments(style_context),
|
||||
fragments: fragment_accumulator
|
||||
.to_intermediate_inline_fragments::<ConcreteThreadSafeLayoutNode>(style_context),
|
||||
});
|
||||
ConstructionResult::ConstructionItem(construction_item)
|
||||
}
|
||||
@@ -1097,8 +1158,11 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
||||
{
|
||||
let context = self.style_context();
|
||||
table_style = node.style(context);
|
||||
wrapper_style = context.stylist.style_for_anonymous(
|
||||
&context.guards, &PseudoElement::ServoTableWrapper, &table_style);
|
||||
wrapper_style = context.stylist.style_for_anonymous::<ConcreteThreadSafeLayoutNode::ConcreteElement>(
|
||||
&context.guards,
|
||||
&PseudoElement::ServoTableWrapper,
|
||||
&table_style,
|
||||
);
|
||||
}
|
||||
let wrapper_fragment =
|
||||
Fragment::from_opaque_node_and_style(node.opaque(),
|
||||
@@ -1128,7 +1192,11 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
||||
CaptionSide::Top);
|
||||
|
||||
if let ConstructionResult::Flow(table_flow, table_abs_descendants) = construction_result {
|
||||
legalizer.add_child(self.style_context(), &mut wrapper_flow, table_flow);
|
||||
legalizer.add_child::<ConcreteThreadSafeLayoutNode::ConcreteElement>(
|
||||
self.style_context(),
|
||||
&mut wrapper_flow,
|
||||
table_flow,
|
||||
);
|
||||
abs_descendants.push_descendants(table_abs_descendants);
|
||||
}
|
||||
|
||||
@@ -1821,16 +1889,24 @@ fn bidi_control_chars(style: &ServoArc<ComputedValues>) -> Option<(&'static str,
|
||||
}
|
||||
}
|
||||
|
||||
fn control_chars_to_fragment(node: &InlineFragmentNodeInfo,
|
||||
context: &SharedStyleContext,
|
||||
text: &str,
|
||||
restyle_damage: RestyleDamage)
|
||||
-> Fragment {
|
||||
fn control_chars_to_fragment<E>(
|
||||
node: &InlineFragmentNodeInfo,
|
||||
context: &SharedStyleContext,
|
||||
text: &str,
|
||||
restyle_damage: RestyleDamage,
|
||||
) -> Fragment
|
||||
where
|
||||
E: TElement,
|
||||
{
|
||||
let info = SpecificFragmentInfo::UnscannedText(
|
||||
Box::new(UnscannedTextFragmentInfo::new(String::from(text), None))
|
||||
);
|
||||
let text_style = context.stylist.style_for_anonymous(
|
||||
&context.guards, &PseudoElement::ServoText, &node.style);
|
||||
let text_style = context.stylist.style_for_anonymous::<E>(
|
||||
&context.guards,
|
||||
&PseudoElement::ServoText,
|
||||
&node.style,
|
||||
);
|
||||
|
||||
Fragment::from_opaque_node_and_style(node.address,
|
||||
node.pseudo,
|
||||
text_style,
|
||||
@@ -1887,16 +1963,24 @@ impl Legalizer {
|
||||
|
||||
/// Makes the `child` flow a new child of `parent`. Anonymous flows are automatically inserted
|
||||
/// to keep the tree legal.
|
||||
fn add_child(&mut self, context: &SharedStyleContext, parent: &mut FlowRef, mut child: FlowRef) {
|
||||
fn add_child<E>(
|
||||
&mut self,
|
||||
context: &SharedStyleContext,
|
||||
parent: &mut FlowRef,
|
||||
mut child: FlowRef,
|
||||
)
|
||||
where
|
||||
E: TElement,
|
||||
{
|
||||
while !self.stack.is_empty() {
|
||||
if self.try_to_add_child(context, parent, &mut child) {
|
||||
if self.try_to_add_child::<E>(context, parent, &mut child) {
|
||||
return
|
||||
}
|
||||
self.flush_top_of_stack(parent)
|
||||
}
|
||||
|
||||
while !self.try_to_add_child(context, parent, &mut child) {
|
||||
self.push_next_anonymous_flow(context, parent)
|
||||
while !self.try_to_add_child::<E>(context, parent, &mut child) {
|
||||
self.push_next_anonymous_flow::<E>(context, parent)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1913,8 +1997,15 @@ impl Legalizer {
|
||||
/// This method attempts to create anonymous blocks in between `parent` and `child` if and only
|
||||
/// if those blocks will only ever have `child` as their sole child. At present, this is only
|
||||
/// true for anonymous block children of flex flows.
|
||||
fn try_to_add_child(&mut self, context: &SharedStyleContext, parent: &mut FlowRef, child: &mut FlowRef)
|
||||
-> bool {
|
||||
fn try_to_add_child<E>(
|
||||
&mut self,
|
||||
context: &SharedStyleContext,
|
||||
parent: &mut FlowRef,
|
||||
child: &mut FlowRef,
|
||||
) -> bool
|
||||
where
|
||||
E: TElement,
|
||||
{
|
||||
let parent = self.stack.last_mut().unwrap_or(parent);
|
||||
let (parent_class, child_class) = (parent.class(), child.class());
|
||||
match (parent_class, child_class) {
|
||||
@@ -1944,12 +2035,14 @@ impl Legalizer {
|
||||
|
||||
(FlowClass::Flex, FlowClass::Inline) => {
|
||||
FlowRef::deref_mut(child).mut_base().flags.insert(FlowFlags::MARGINS_CANNOT_COLLAPSE);
|
||||
let mut block_wrapper =
|
||||
Legalizer::create_anonymous_flow(context,
|
||||
parent,
|
||||
&[PseudoElement::ServoAnonymousBlock],
|
||||
SpecificFragmentInfo::Generic,
|
||||
BlockFlow::from_fragment);
|
||||
let mut block_wrapper = Legalizer::create_anonymous_flow::<E, _>(
|
||||
context,
|
||||
parent,
|
||||
&[PseudoElement::ServoAnonymousBlock],
|
||||
SpecificFragmentInfo::Generic,
|
||||
BlockFlow::from_fragment,
|
||||
);
|
||||
|
||||
{
|
||||
let flag = if parent.as_flex().main_mode() == Direction::Inline {
|
||||
FragmentFlags::IS_INLINE_FLEX_ITEM
|
||||
@@ -1997,54 +2090,76 @@ impl Legalizer {
|
||||
|
||||
/// Adds the anonymous flow that would be necessary to make an illegal child of `parent` legal
|
||||
/// to the stack.
|
||||
fn push_next_anonymous_flow(&mut self, context: &SharedStyleContext, parent: &FlowRef) {
|
||||
fn push_next_anonymous_flow<E>(
|
||||
&mut self,
|
||||
context: &SharedStyleContext,
|
||||
parent: &FlowRef,
|
||||
)
|
||||
where
|
||||
E: TElement,
|
||||
{
|
||||
let parent_class = self.stack.last().unwrap_or(parent).class();
|
||||
match parent_class {
|
||||
FlowClass::TableRow => {
|
||||
self.push_new_anonymous_flow(context,
|
||||
parent,
|
||||
&[PseudoElement::ServoAnonymousTableCell],
|
||||
SpecificFragmentInfo::TableCell,
|
||||
TableCellFlow::from_fragment)
|
||||
self.push_new_anonymous_flow::<E, _>(
|
||||
context,
|
||||
parent,
|
||||
&[PseudoElement::ServoAnonymousTableCell],
|
||||
SpecificFragmentInfo::TableCell,
|
||||
TableCellFlow::from_fragment,
|
||||
)
|
||||
}
|
||||
FlowClass::Table | FlowClass::TableRowGroup => {
|
||||
self.push_new_anonymous_flow(context,
|
||||
parent,
|
||||
&[PseudoElement::ServoAnonymousTableRow],
|
||||
SpecificFragmentInfo::TableRow,
|
||||
TableRowFlow::from_fragment)
|
||||
self.push_new_anonymous_flow::<E, _>(
|
||||
context,
|
||||
parent,
|
||||
&[PseudoElement::ServoAnonymousTableRow],
|
||||
SpecificFragmentInfo::TableRow,
|
||||
TableRowFlow::from_fragment,
|
||||
)
|
||||
}
|
||||
FlowClass::TableWrapper => {
|
||||
self.push_new_anonymous_flow(context,
|
||||
parent,
|
||||
&[PseudoElement::ServoAnonymousTable],
|
||||
SpecificFragmentInfo::Table,
|
||||
TableFlow::from_fragment)
|
||||
self.push_new_anonymous_flow::<E, _>(
|
||||
context,
|
||||
parent,
|
||||
&[PseudoElement::ServoAnonymousTable],
|
||||
SpecificFragmentInfo::Table,
|
||||
TableFlow::from_fragment,
|
||||
)
|
||||
}
|
||||
_ => {
|
||||
self.push_new_anonymous_flow(context,
|
||||
parent,
|
||||
&[PseudoElement::ServoTableWrapper,
|
||||
PseudoElement::ServoAnonymousTableWrapper],
|
||||
SpecificFragmentInfo::TableWrapper,
|
||||
TableWrapperFlow::from_fragment)
|
||||
self.push_new_anonymous_flow::<E, _>(
|
||||
context,
|
||||
parent,
|
||||
&[PseudoElement::ServoTableWrapper,
|
||||
PseudoElement::ServoAnonymousTableWrapper],
|
||||
SpecificFragmentInfo::TableWrapper,
|
||||
TableWrapperFlow::from_fragment,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates an anonymous flow and pushes it onto the stack.
|
||||
fn push_new_anonymous_flow<F>(&mut self,
|
||||
context: &SharedStyleContext,
|
||||
reference: &FlowRef,
|
||||
pseudos: &[PseudoElement],
|
||||
specific_fragment_info: SpecificFragmentInfo,
|
||||
constructor: extern "Rust" fn(Fragment) -> F)
|
||||
where F: Flow {
|
||||
let new_flow = Legalizer::create_anonymous_flow(context,
|
||||
reference,
|
||||
pseudos,
|
||||
specific_fragment_info,
|
||||
constructor);
|
||||
fn push_new_anonymous_flow<E, F>(
|
||||
&mut self,
|
||||
context: &SharedStyleContext,
|
||||
reference: &FlowRef,
|
||||
pseudos: &[PseudoElement],
|
||||
specific_fragment_info: SpecificFragmentInfo,
|
||||
constructor: extern "Rust" fn(Fragment) -> F,
|
||||
)
|
||||
where
|
||||
E: TElement,
|
||||
F: Flow,
|
||||
{
|
||||
let new_flow = Self::create_anonymous_flow::<E, _>(
|
||||
context,
|
||||
reference,
|
||||
pseudos,
|
||||
specific_fragment_info,
|
||||
constructor,
|
||||
);
|
||||
self.stack.push(new_flow)
|
||||
}
|
||||
|
||||
@@ -2053,21 +2168,31 @@ impl Legalizer {
|
||||
///
|
||||
/// This method invokes the supplied constructor function on the given specific fragment info
|
||||
/// in order to actually generate the flow.
|
||||
fn create_anonymous_flow<F>(context: &SharedStyleContext,
|
||||
reference: &FlowRef,
|
||||
pseudos: &[PseudoElement],
|
||||
specific_fragment_info: SpecificFragmentInfo,
|
||||
constructor: extern "Rust" fn(Fragment) -> F)
|
||||
-> FlowRef
|
||||
where F: Flow {
|
||||
fn create_anonymous_flow<E, F>(
|
||||
context: &SharedStyleContext,
|
||||
reference: &FlowRef,
|
||||
pseudos: &[PseudoElement],
|
||||
specific_fragment_info: SpecificFragmentInfo,
|
||||
constructor: extern "Rust" fn(Fragment) -> F,
|
||||
) -> FlowRef
|
||||
where
|
||||
E: TElement,
|
||||
F: Flow,
|
||||
{
|
||||
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(&context.guards, pseudo, &new_style)
|
||||
new_style = context.stylist.style_for_anonymous::<E>(
|
||||
&context.guards,
|
||||
pseudo,
|
||||
&new_style,
|
||||
);
|
||||
}
|
||||
let fragment = reference_block.fragment
|
||||
.create_similar_anonymous_fragment(new_style,
|
||||
specific_fragment_info);
|
||||
let fragment =
|
||||
reference_block.fragment.create_similar_anonymous_fragment(
|
||||
new_style,
|
||||
specific_fragment_info,
|
||||
);
|
||||
FlowRef::new(Arc::new(constructor(fragment)))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user