aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout/construct.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/layout/construct.rs')
-rw-r--r--components/layout/construct.rs101
1 files changed, 69 insertions, 32 deletions
diff --git a/components/layout/construct.rs b/components/layout/construct.rs
index 0b489459352..086b323e878 100644
--- a/components/layout/construct.rs
+++ b/components/layout/construct.rs
@@ -25,14 +25,16 @@ use flow::{MutableFlowUtils, MutableOwnedFlowUtils};
use flow_ref::FlowRef;
use fragment::{CanvasFragmentInfo, ImageFragmentInfo, InlineAbsoluteFragmentInfo, SvgFragmentInfo};
use fragment::{Fragment, GeneratedContentInfo, IframeFragmentInfo};
+use fragment::{IS_INLINE_FLEX_ITEM, IS_BLOCK_FLEX_ITEM};
use fragment::{InlineAbsoluteHypotheticalFragmentInfo, TableColumnFragmentInfo};
use fragment::{InlineBlockFragmentInfo, SpecificFragmentInfo, UnscannedTextFragmentInfo};
use fragment::WhitespaceStrippingResult;
use gfx::display_list::OpaqueNode;
-use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFlow, InlineFragmentNodeFlags};
+use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFlow};
use inline::{InlineFragmentNodeInfo, LAST_FRAGMENT_OF_ELEMENT};
use linked_list::prepend_from;
use list_item::{ListItemFlow, ListStyleTypeContent};
+use model::Direction;
use multicol::{MulticolColumnFlow, MulticolFlow};
use parallel;
use script_layout_interface::{LayoutElementType, LayoutNodeType, is_image_data};
@@ -159,6 +161,32 @@ pub struct InlineBlockSplit {
pub flow: FlowRef,
}
+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 {
+ fragment_accumulator.enclosing_node.as_mut().expect(
+ "enclosing_node is None; Are {ib} splits being generated outside of an inline node?"
+ ).flags.remove(LAST_FRAGMENT_OF_ELEMENT);
+
+ let split = InlineBlockSplit {
+ predecessors: mem::replace(
+ fragment_accumulator,
+ InlineFragmentsAccumulator::from_inline_node(
+ node, style_context)).to_intermediate_inline_fragments(),
+ flow: flow,
+ };
+
+ fragment_accumulator.enclosing_node.as_mut().unwrap().flags.remove(FIRST_FRAGMENT_OF_ELEMENT);
+
+ split
+ }
+}
+
/// Holds inline fragments and absolute descendants.
#[derive(Clone)]
pub struct IntermediateInlineFragments {
@@ -192,8 +220,14 @@ struct InlineFragmentsAccumulator {
/// The list of fragments.
fragments: IntermediateInlineFragments,
- /// Whether we've created a range to enclose all the fragments. This will be Some() if the
- /// outer node is an inline and None otherwise.
+ /// Information about the inline box directly enclosing the fragments being gathered, if any.
+ ///
+ /// `inline::InlineFragmentNodeInfo` also stores flags indicating whether a fragment is the
+ /// first and/or last of the corresponding inline box. This `InlineFragmentsAccumulator` may
+ /// represent only one side of an {ib} split, so we store these flags as if it represented only
+ /// one fragment. `to_intermediate_inline_fragments` later splits this hypothetical fragment
+ /// into pieces, leaving the `FIRST_FRAGMENT_OF_ELEMENT` and `LAST_FRAGMENT_OF_ELEMENT` flags,
+ /// if present, on the first and last fragments of the output.
enclosing_node: Option<InlineFragmentNodeInfo>,
/// Restyle damage to use for fragments created in this node.
@@ -222,7 +256,7 @@ impl InlineFragmentsAccumulator {
pseudo: node.get_pseudo_element_type().strip(),
style: node.style(style_context),
selected_style: node.selected_style(),
- flags: InlineFragmentNodeFlags::empty(),
+ flags: FIRST_FRAGMENT_OF_ELEMENT | LAST_FRAGMENT_OF_ELEMENT,
}),
bidi_control_chars: None,
restyle_damage: node.restyle_damage(),
@@ -245,21 +279,23 @@ impl InlineFragmentsAccumulator {
bidi_control_chars,
restyle_damage,
} = self;
- if let Some(enclosing_node) = enclosing_node {
+ if let Some(mut enclosing_node) = enclosing_node {
let fragment_count = fragments.fragments.len();
for (index, fragment) in fragments.fragments.iter_mut().enumerate() {
let mut enclosing_node = enclosing_node.clone();
- if index == 0 {
- enclosing_node.flags.insert(FIRST_FRAGMENT_OF_ELEMENT)
+ if index != 0 {
+ enclosing_node.flags.remove(FIRST_FRAGMENT_OF_ELEMENT)
}
- if index == fragment_count - 1 {
- enclosing_node.flags.insert(LAST_FRAGMENT_OF_ELEMENT)
+ if index != fragment_count - 1 {
+ enclosing_node.flags.remove(LAST_FRAGMENT_OF_ELEMENT)
}
fragment.add_inline_context_style(enclosing_node);
}
// Control characters are later discarded in transform_text, so they don't affect the
// is_first/is_last styles above.
+ enclosing_node.flags.remove(FIRST_FRAGMENT_OF_ELEMENT | LAST_FRAGMENT_OF_ELEMENT);
+
if let Some((start, end)) = bidi_control_chars {
fragments.fragments.push_front(
control_chars_to_fragment(&enclosing_node, start, restyle_damage));
@@ -715,14 +751,8 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
} = split;
fragment_accumulator.push_all(predecessors);
- let split = InlineBlockSplit {
- predecessors: mem::replace(
- fragment_accumulator,
- InlineFragmentsAccumulator::from_inline_node(
- node, self.style_context())).to_intermediate_inline_fragments(),
- flow: kid_flow,
- };
- opt_inline_block_splits.push_back(split)
+ opt_inline_block_splits.push_back(
+ InlineBlockSplit::new(fragment_accumulator, node, self.style_context(), kid_flow));
}
}
@@ -749,17 +779,8 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
ConstructionResult::None => {}
ConstructionResult::Flow(flow, kid_abs_descendants) => {
if !flow::base(&*flow).flags.contains(IS_ABSOLUTELY_POSITIONED) {
- // {ib} split. Flush the accumulator to our new split and make a new
- // accumulator to hold any subsequent fragments we come across.
- let split = InlineBlockSplit {
- predecessors:
- mem::replace(
- &mut fragment_accumulator,
- InlineFragmentsAccumulator::from_inline_node(
- node, self.style_context())).to_intermediate_inline_fragments(),
- flow: flow,
- };
- opt_inline_block_splits.push_back(split);
+ opt_inline_block_splits.push_back(InlineBlockSplit::new(
+ &mut fragment_accumulator, node, self.style_context(), flow));
abs_descendants.push_descendants(kid_abs_descendants);
} else {
// Push the absolutely-positioned kid as an inline containing block.
@@ -1928,9 +1949,16 @@ impl Legalizer {
&[PseudoElement::ServoAnonymousBlock],
SpecificFragmentInfo::Generic,
BlockFlow::from_fragment);
- flow::mut_base(FlowRef::deref_mut(&mut
- block_wrapper)).flags
- .insert(MARGINS_CANNOT_COLLAPSE);
+ {
+ let flag = if parent.as_flex().main_mode() == Direction::Inline {
+ IS_INLINE_FLEX_ITEM
+ } else {
+ IS_BLOCK_FLEX_ITEM
+ };
+ let mut block = FlowRef::deref_mut(&mut block_wrapper).as_mut_block();
+ block.base.flags.insert(MARGINS_CANNOT_COLLAPSE);
+ block.fragment.flags.insert(flag);
+ }
block_wrapper.add_new_child((*child).clone());
block_wrapper.finish();
parent.add_new_child(block_wrapper);
@@ -1938,7 +1966,16 @@ impl Legalizer {
}
(FlowClass::Flex, _) => {
- flow::mut_base(FlowRef::deref_mut(child)).flags.insert(MARGINS_CANNOT_COLLAPSE);
+ {
+ let flag = if parent.as_flex().main_mode() == Direction::Inline {
+ IS_INLINE_FLEX_ITEM
+ } else {
+ IS_BLOCK_FLEX_ITEM
+ };
+ let mut block = FlowRef::deref_mut(child).as_mut_block();
+ block.base.flags.insert(MARGINS_CANNOT_COLLAPSE);
+ block.fragment.flags.insert(flag);
+ }
parent.add_new_child((*child).clone());
true
}